Thursday, February 28, 2013

[opengl] glutMainLoop(), glutDisplayFunc(), glutPostRedisplay()



http://stackoverflow.com/a/1862505

glutMainLoop only calls the display callback when a glut event triggers the display callback, such as resizing the window, uncovering the window, or calling glutPostRedisplay. You have to put code in your program to trigger glut into calling your display callback at a proper frame rate to produce animation in your program. For example, you can put a call to glutPostResdisplay into your idle callback function, so when GLUT is idle your display callback will get called.



http://www.gamedev.net/topic/379278-what-exactly-does-glutmainloop-do/

glutMainLoop() is a function that loops within itself, processing events and triggering your callback functions when necessary (glutDisplayFunc, etc). After a call to glutMainLoop(), you have no control over the execution of your program besides the callback functions you initialized before the call.

And another thing, the glutDisplayFunc() callback only gets triggered when your app's window receives a refresh event, unless you explicity post a redisplay. If you want your display function to be called repeatedly (i.e. for a game), you need to set your glutIdleFunc to post a redisplay.

Something like this:

int main()
{
    /* ... */
    glutIdleFunc(updateGame);
    /* ... */
   
    glutMainLoop();
}

void updateGame()
{
    glutPostRedisplay();
}


http://www.lighthouse3d.com/tutorials/glut-tutorial/glutpostredisplay-vs-idle-func/

Wednesday, February 27, 2013

Sunday, February 24, 2013

Saturday, February 23, 2013

[c/c++] error: CrtIsValidHeapPointer(pUserData) - free memory not on the heap

That's right, when you try to 'free()' memo - that is already freed or - that is not on the heap (e.g. a local varible to the function) CrtIsValidHeapPointer(pUserData) error occurs (VC++)

[c/c++] For who think they don't need to use dynamic allocation (malloc, calloc) for data structures

Look at the following code to add a node to a queue


void Queue1::add(int p_data)
{
Node newNode;
newNode.data = p_data;
newNode.next = 0;

// if tail exists
if(tail)
{
tail->next = &newNode;
tail = tail->next;
}
// otherwise
else
{
head = &newNode;
tail = &newNode;
}
}

This will not work as the 'newNode' created is only sitting on the stack not on the heap, therefore, every time this method is called, head and tail will be pointing at some junk from the get go.

We want the head to stay where it is and move the tail, hence need to put every Node created onto the heap.


void Queue1::add(int p_data)
{
Node* newNodePtr = (Node*) calloc(1, sizeof(Node));
newNodePtr->data = p_data;
newNodePtr->next = 0;

// if tail exists
if(tail)
{
tail->next = newNodePtr;
tail = tail->next;
}
// otherwise
else
{
head = newNodePtr;
tail = newNodePtr;
}
}

The full version of the main code file:




#include "Queue1.h"


Queue1::Queue1(void)
{
    head = 0;
    tail = 0; 
}


Queue1::~Queue1(void)
{
}


void Queue1::add(int p_data)
{
    Node* newNodePtr = (Node*) calloc(1, sizeof(Node)); 
    newNodePtr->data = p_data;
    newNodePtr->next = 0; 

    // if tail exists
    if(tail)
    {        
        tail->next = newNodePtr;
        tail = tail->next;
    }
    // otherwise
    else
    {
        head = newNodePtr;
        tail = newNodePtr;
    }
}

int Queue1::remove()
{
    int data = -1;
    if (head)
    {
        data = head->data;
        if (head == tail)
            tail = tail->next; 
        Node* temp = head;
        head = head->next;

        // so how to free the previous header occupied block?
        free(temp);
    }
    return data; 
}

int main(int argc, char* argv[]) 
{
    Queue1 q1; 
    q1.add(1); 
    q1.add(2);

    q1.remove();
    q1.remove(); 
}

Tuesday, February 19, 2013

[c/c++] Open GL display list example

Notice that:

- The drawParticle() method is static
- That's why this method can be put onto the GL 'display list', it will be loaded once but run many times, if you put 'cout', for example, in drawParticle() method, it will only show output once
- The position of drawing the points are actually specified by assigning value to the member variable x, at the end of the caller to the drawParticle() method.


--Particle.h--

#pragma once

#include <GL\glut.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include <limits.h>
#include <iostream>
#include "Vector3D.h"
#include "Constants.h"
using namespace std;


class Particle {

public: 
    /** Display list index. */
    static int PARTICLE_DISPLAY_LIST;

    /** Highlighted appearance if true, otherwise white. */
    bool highlight;

    /** If true, then particle is pinned in space. */
    bool pin;

    /** mass. */
    float m;

    /** Deformed Position. */
    Point3D x;

    /** Undeformed/material Position. */
    Point3D x0;

    /** Velocity. */
    Vector3D v;

    /** Force accumulator. */
    Vector3D f;

    /**
    * Draws a canonical circular particle.
    */
    static void drawParticle(Point3D p); 

public: 

    /**
    * Constructor: 
    */
    Particle() {
        setDefaultMemebers();
    }

    /**
    * Constructor: Constructs particle with the specified material/undeformed coordinate,
    * p0.
    */
    Particle(Point3D p_x0) {
        setDefaultMemebers();
        x0.Set(p_x0.x, p_x0.y, p_x0.z);
        x.Set(p_x0.x, p_x0.y, p_x0.z);
    }

    /** Set default values to some of the members */
    void setDefaultMemebers(){
        highlight = false;
        pin = false;
        m = PARTICLE_MASS; 
        PARTICLE_DISPLAY_LIST = -1;
    }

    // Setters

    /** Specifies whether particle should be drawn highlighted. */
    void setHighlight(bool p_highlight) {
        highlight = p_highlight;
    }
    /**
    * Specifies whether or not this particle is fixed in space via a pin
    * constraint. (Should probably be elsewhere in a generic constraint list).
    */
    void setPin(bool fix) { 
        pin = fix; 
    }

    // Getters 

    /** True if particle should be drawn highlighted. */
    bool getHighlight() { 
        return highlight; 
    }
    /** Returns true if currently pinned. */
    bool isPinned() {
        return pin;
    }

    /** Draws circular particle using a display list. */
    void display();
};


----Particle.cpp----

#include "Particle.h"

/**
* Simple particle implementation, with miscellaneous adornments.
* 
* @author James Wang, Feb, 2013
* based on code orginally developed by Doug James in Java with JOGL 1.x
*/

int Particle::PARTICLE_DISPLAY_LIST = -1;

/** Draws circular particle using a display list. */
void Particle::display() {
    //cout << "NEW PARTICLE FOR DISPLAY LIST " << PARTICLE_DISPLAY_LIST << "\n";
    if (PARTICLE_DISPLAY_LIST < 0) {// MAKE DISPLAY LIST:
        int displayListIndex = glGenLists(1);
        glNewList(displayListIndex, GL_COMPILE);
        drawParticle(Point3D(0.0f, 0.0f, 0.0f));// /particle at origin
        glEndList();
        std::cout<<"MADE LIST" << displayListIndex << " : "
            << glIsList(displayListIndex);
        PARTICLE_DISPLAY_LIST = displayListIndex;
    }

    // COLOR: DEFAULT WHITE; GREEN IF HIGHLIGHTED; ADD RED IF PINNED
    Point3D c (1.0f, 1.0f, 1.0f);// default: white
    if (pin) {
        c.x = 1.0f;// add red
        c.y *= 0.2f;
        c.z = 0;
    }
    if (highlight) {
        c.y = 1;
        c.z = 0;
    }

    glColor3f(c.x, c.y, c.z);

    // / DRAW ORIGIN-CIRCLE TRANSLATED TO "p":
    glPushMatrix();
    glTranslated(x.x, x.y, x.z);
    glCallList(PARTICLE_DISPLAY_LIST);
    glPopMatrix();
}

/**
* Draws a canonical circular particle.
*/
void Particle::drawParticle(Point3D p) {
    double radius = PARTICLE_RADIUS;

    double vectorX1 = p.x;
    double vectorY1 = p.y;
    double vectorZ1 = p.z;

    cout << "\n" << "MAKING COORDINATE SPOT AT " << p.x << " " << p.y << " "<< p.z << "\n";

    // Draw the particle as 3D spheres 
    glColor4f(1, 0, 0, 0); 
    glutSolidSphere(radius, 10, 10);

    glEnd();
}

Sunday, February 17, 2013

[c/c++] LNK2019: unresolved external symbol

1.  if you have static variable, check if it is both declared and defined

http://stackoverflow.com/questions/195207/unresolved-external-symbol-on-static-class-members

in header file:


unsigned char test::X;
unsigned char test::Y;

in the cpp file: 
unsigned char test::X;

Then in the caller function, you can do
test::X = 3; 


2. Check if you copy, pasted and renamed to generate a .h file. 
- you can 'toggle' the 'Show All File' button in the Solution Explorer of Visual Studio to show the structure where Header Files and Source Files are shown in separate folders and check if that header file is there in the Header Files folder.
- if not, exclude it from and then include it into the project

[c/c++] c++ Vector of Abstract Class type



http://www.cplusplus.com/forum/general/17754/


#include <iostream>
#include <vector>
using namespace std;

// abstract base class
class Animal
{
public:
    // pure virtual method
    virtual void speak() = 0;
    // virtual destructor
    virtual ~Animal() {}
};

// derived class
class Dog : public Animal
{
public:
    // polymorphic implementation of speak
    virtual void speak() { cout << "Ruff!"; }
};

int main( int argc, char* args[] )

    // container of base class pointers
    vector<Animal*> barn;

    // dynamically allocate an Animal instance and add it to the container. Note: new returns a pointer
    barn.push_back( new Dog() ); 

    // invoke the speak method of the first Animal in the container
    barn.front()->speak();

    // free the allocated memory
    for( vector<Animal*>::iterator i = barn.begin(); i != barn.end(); ++i )
    {
        delete *i;
    }
    // empty the container
    barn.clear();

    return 0;
}

[c/c++] initialization and instantiation... prototyped function not called (was a variable definition intended?)




// Correct initialization with default Constructor of A
ClassA a;

// Incorrect initialization
ClassA a();

// Correct initialization, returning a pointer to an object (http://www.cplusplus.com/reference/new/operator%20new/)


  MyClass * p1 = new MyClass;
      // allocates memory by calling: operator new (sizeof(MyClass))
      // and then constructs an object at the newly allocated space

[c/c++] problem with fatal error LNK1561: entry point must be defined

Simply that you are missing a main() function or its alike. This is so even if you started in Visual Studio with an empty c++ project.