openFrameworks
      3D
3D

 ofNode     ofMesh   of3dUtils




ofCamera




ofEasyCam
ofCamera


Camera movement and matrices

• Extends from ofNode
• Basic GLUT camera functions
• Coordinate conversions
ofCamera


Frustum setup
                        angle of field of view in y direction, in degrees
     setFov(float)
                                            (45-60)

   setNearClip(float)             near clipping plane distance

   setFarClip(float)             set far clipping plane distance
ofCamera

Perspective and modelview matrices

        getProjectionMatrix()        Ortho / Perspective


       getModelViewMatrix()          Position/Orientation

   getModelViewProjectionMatrix()   Modelview * Projection
ofCamera


Coordinate conversion
    worldToScreen()      Convert openGL world to screen

    screenToWorld()        Convert screen to GL world

   worldToCamera()          Convert world to camera

   cameraToWorld()          Convert camera to world
ofCamera
               testApp.h




class testApp : public ofBaseApp{

 public:

 
      ...

 
      ofCamera cam;

 
};
ofCamera
                           testApp.cpp




void testApp::setup(){

 ofBackground(33,33,33);

 cam.setNearClip(0.1);

 cam.setFarClip(100);

    // "1 meter" to the right, "5 meters" away from object
    cam.setPosition(ofVec3f(1,0,5));
}




void testApp::draw(){

 cam.begin();

 
      glPointSize(10);

 
      glBegin(GL_POINTS);

 
      
   glVertex3f(0,0,0);

 
      glEnd();

 cam.end();
}
ofNode
ofNode

3D object container

• Standard 3D scene item
• Manage position, scale and orientation
• Lots of fantastic helper functions
• ofCamera extends from this class
ofNode


Movement
       truck()             Move left to right (x-axis)

      boom()              Move up and down (y-axis)

       dolly()        Move forward and backward (z-axis)

    setPosition()             Set position directly
ofNode

Rotation
         tilt()             Rotate around x-axis

         pan()              Rotate around y-axis

        dolly()             Rotate around z-axis

     rotate(a,axis)      Rotate around arbitrary axis
ofNode

Testing movement/orientation
                             Apply ofNode transformation (does a
     transformGL()
                                glPushMatrix/glMultMatrixf())

                         Does a glPopMatrix, call after transformGL and
  restoreTransformGL()
                                           drawing.

    resetTransform()          Resets the orientation and position
ofNode
void setScale(float s)

void setScale(float x, float y, float z)

void setScale(const ofVec3f& p)


void setPosition(float x, float y, float z)

void setPosition(const ofVec3f& p)

void setGlobalPosition(float x, float y, float z)

void setGlobalPosition(const ofVec3f& p)


void setOrientation(const ofQuaternion& q)

void setOrientation(const ofVec3f& eulerAngles)

void setGlobalOrientation(const ofQuaternion& q)
ofNode

Custom 3D nodes

• Create custom class and inherit from ofNode
• Implement virtual customDraw(void) member
  function.

• To draw, just call draw(void) on instance
ofNode
                Extend ofNode




class MyCustom3DNode : public ofNode {
public:

 virtual void customDraw() {

 
   ofSphere(0,0,0,0.7);

 
   ofDrawAxis(2
 );

 }
};
ofEasyCam


Camera interaction made easy

     begin()/end()       Put your draw calls between these

   setTarget(ofNode)        Follow and look at a target
ofEasyCam
        Custom ofNode - example ofEasyCam




class MyCustom3DNode : public ofNode {
public:

 virtual void customDraw() {

 
     ofSphere(0,0,0,0.7);

 
     ofDrawAxis(2);

 }
};

class testApp : public ofBaseApp{


    public:

    
    ofEasyCam easy_cam;

    
    vector<MyCustom3DNode*> custom_nodes;

    
    MyCustom3DNode* mover;
};
ofEasyCam
           Custom ofNode - example ofEasyCam



void testApp::setup(){

 ofBackground(33,33,33);


   // set distance of camera "5" meters away

   easy_cam.setDistance(5);


   // create a bunch of custom 3D nodes

   float r = 4;

   for(int i = 0; i < 10; ++i) {

   
     MyCustom3DNode* node = new MyCustom3DNode();

   
     node->setPosition(

   
     
    cos((float)i/10*TWO_PI) * r

   
     
    ,sin((float)i/10*TWO_PI) * r

   
     
    ,-5

   
     );

   
     custom_nodes.push_back(node);

   
     mover = node;

   }


   // set target for camera

   easy_cam.setTarget(*mover);
}
ofEasyCam
                   Custom ofNode - example ofEasyCam




void testApp::draw(){

 easy_cam.begin();

 
      // draw custom nodes.

 
      for(int i = 0; i < custom_nodes.size(); ++i) {

 
      
    custom_nodes[i]->draw();

 
      }

 

 
      // move over x-axis.

 
      float truck_amount = sin(ofGetElapsedTimef()*0.5) * 0.001;

 
      mover->truck(truck_amount);

 easy_cam.end();
}
ofMesh

Container for all vertex related data

•   Use this when working with 3D meshes. It creates a model that is used
    by openGL to draw 3D shapes.

•   Future proof (ready for modern openGL)

•   Clean API for most used data:
    add[Vertex,Color,TexCoord]()

•   Nice interface for writing 3D exports (OBJ, PLY)

•   Use this with Vertex Buffer Objects (VBO)
ofMesh
Adding vertices
          addVertex(ofVec3f)             Add one vertex

      addVertices(vector<ofVec3f>&)    Reference to ofVec3f
      addVertices(ofVec3f*, int num)    Pointer to vertices
          setVertex(int index)          Remove by index


Remove vertices
        removeVertex(int index)         Remove by index

            clearVertices()            Remove all vertices


Get vertex
             getVertex(int)              Get one vertex
ofMesh
Adding normals
         addNormal(ofVec3f&)             Add a normal

      addNormals(vector<ofVec3f>)    Add vector of normals
       addNormals(ofVec3f*, int)     Add array of normals
        setNormal(int, ofVec3f&)    Set one normal by index




Removing normals
         removeNormal(int)             Remove by index

           clearNormals()             Remove all normals



Retrieving normals
           getNormal(int)            Get normal by index
ofMesh
Adding indices
         addIndex(ofIndexType)              Add a index

     addIndices(const<ofIndextype>&)   Add a bunch of indices
       addIndices(ofIndexType*,int)    Add bunch of indices
        setIndex(int, ofIndexType)      Set a specific index




Removing indices
          removeIndex(int i)             Remove by index

            clearIndices()               Remove all indices



Retrieving indices
             getIndex(int)             Get index by index ;-)
ofMesh
Adding colors
         addColor(const ofFloatColor& c)                Add a index

      addColors(const<ofFloatColor>& cols)         Add a bunch of indices
    addColors(const ofFloatColor* cols, int amt)   Add bunch of indices
     setColor(int index, const ofFloatColor& c)     Set a specific index




Removing colors
            removeColor(int index)                   Remove by index

                 clearColors()                       Remove all indices



Retrieving colors
        ofFloatColor getColor(int i)               Get index by index ;-)
ofMesh
Useful for GL_ARRAY_BUFFER / VBO
            getNumVertices()               Total number of vertices

             getNumColors()                 Total number of colors

          getNumTexCoords()             Total number of texture coords

            getNumIndices()                Total number of indices



        float* getVerticesPointer()       Get a pointer to the vertices

        float* getColorsPointer()          Get a pointer to the colors

       float* getNormalsPointer()        Get pointer to stored normals

   ofIndexType* getTexCoordsPointer()      Get pointer to texcoords
ofMesh

Same API for the rest
• Same API for Colors, TexCoord

•   Helper function addTriangle(int,int,int)
Create two planes                   testApp.cpp
                                    void testApp::setup(){

                                    
   // bottom
                                    
   cube.addVertex(ofVec3f(-1,0,1));
                                    
   cube.addVertex(ofVec3f(1,0,1));
                                    
   cube.addVertex(ofVec3f(1,0,-1));
                                    
   cube.addVertex(ofVec3f(-1,0,-1));
                                    
                                    
   // top
                                    
   cube.addVertex(ofVec3f(-1,1,1));
                                    
   cube.addVertex(ofVec3f(1,1,1));
                                    
   cube.addVertex(ofVec3f(1,1,-1));
                                    
   cube.addVertex(ofVec3f(-1,1,-1));

                                    
                                    
   // triangles bottom
                                    
   cube.addIndex(0);
                                    
   cube.addIndex(1);
                                    
   cube.addIndex(2);
                                    
   cube.addIndex(2);
                                    
   cube.addIndex(3);
testApp.h                           
   cube.addIndex(0);
                                    
class testApp : public ofBaseApp{
                                    
   // triangles top
                                    
   cube.addIndex(4);

 public:
                                    
   cube.addIndex(5);

 
    ofMesh cube;
                                    
   cube.addIndex(6);
};
                                    
   cube.addIndex(6);
                                    
   cube.addIndex(7);
                                    
   cube.addIndex(4);
                                    
                                    }
Create a cube                       testApp.cpp

                                     void testApp::setup(){
                                     
 // bottom vertices
                                     
 cube.addVertex(ofVec3f(-1,0,1));
                                     
 cube.addVertex(ofVec3f(1,0,1));
                                     
 cube.addVertex(ofVec3f(1,0,-1));
                                     
 cube.addVertex(ofVec3f(-1,0,-1));
                                     
                                     
 // top vertices
                                     
 cube.addVertex(ofVec3f(-1,1,1));
                                     
 cube.addVertex(ofVec3f(1,1,1));
                                     
 cube.addVertex(ofVec3f(1,1,-1));
                                     
 cube.addVertex(ofVec3f(-1,1,-1));

                                     
   // indices
                                     
   cube.addTriangle(0,1,2);   // bottom
                                     
   cube.addTriangle(2,3,0);
                                     
   cube.addTriangle(4,5,6);   // top
                                     
   cube.addTriangle(6,7,4);
                                     
   cube.addTriangle(0,4,5);   // front
                                     
   cube.addTriangle(0,1,5);
testApp.h                            
   cube.addTriangle(1,2,6);   // right
                                     
   cube.addTriangle(6,5,1);
class testApp : public ofBaseApp{    
   cube.addTriangle(2,6,3);   // back
                                     
   cube.addTriangle(3,7,6);

 public:                            
   cube.addTriangle(0,3,7);   // left

 
    ofMesh cube;                  
   cube.addTriangle(7,4,0);
};                                   }
roxlu
www.roxlu.com

openFrameworks 007 - 3D

  • 1.
  • 2.
    3D ofNode ofMesh of3dUtils ofCamera ofEasyCam
  • 3.
    ofCamera Camera movement andmatrices • Extends from ofNode • Basic GLUT camera functions • Coordinate conversions
  • 4.
    ofCamera Frustum setup angle of field of view in y direction, in degrees setFov(float) (45-60) setNearClip(float) near clipping plane distance setFarClip(float) set far clipping plane distance
  • 5.
    ofCamera Perspective and modelviewmatrices getProjectionMatrix() Ortho / Perspective getModelViewMatrix() Position/Orientation getModelViewProjectionMatrix() Modelview * Projection
  • 6.
    ofCamera Coordinate conversion worldToScreen() Convert openGL world to screen screenToWorld() Convert screen to GL world worldToCamera() Convert world to camera cameraToWorld() Convert camera to world
  • 7.
    ofCamera testApp.h class testApp : public ofBaseApp{ public: ... ofCamera cam; };
  • 8.
    ofCamera testApp.cpp void testApp::setup(){ ofBackground(33,33,33); cam.setNearClip(0.1); cam.setFarClip(100); // "1 meter" to the right, "5 meters" away from object cam.setPosition(ofVec3f(1,0,5)); } void testApp::draw(){ cam.begin(); glPointSize(10); glBegin(GL_POINTS); glVertex3f(0,0,0); glEnd(); cam.end(); }
  • 9.
  • 10.
    ofNode 3D object container •Standard 3D scene item • Manage position, scale and orientation • Lots of fantastic helper functions • ofCamera extends from this class
  • 11.
    ofNode Movement truck() Move left to right (x-axis) boom() Move up and down (y-axis) dolly() Move forward and backward (z-axis) setPosition() Set position directly
  • 12.
    ofNode Rotation tilt() Rotate around x-axis pan() Rotate around y-axis dolly() Rotate around z-axis rotate(a,axis) Rotate around arbitrary axis
  • 13.
    ofNode Testing movement/orientation Apply ofNode transformation (does a transformGL() glPushMatrix/glMultMatrixf()) Does a glPopMatrix, call after transformGL and restoreTransformGL() drawing. resetTransform() Resets the orientation and position
  • 14.
    ofNode void setScale(float s) voidsetScale(float x, float y, float z) void setScale(const ofVec3f& p) void setPosition(float x, float y, float z) void setPosition(const ofVec3f& p) void setGlobalPosition(float x, float y, float z) void setGlobalPosition(const ofVec3f& p) void setOrientation(const ofQuaternion& q) void setOrientation(const ofVec3f& eulerAngles) void setGlobalOrientation(const ofQuaternion& q)
  • 15.
    ofNode Custom 3D nodes •Create custom class and inherit from ofNode • Implement virtual customDraw(void) member function. • To draw, just call draw(void) on instance
  • 16.
    ofNode Extend ofNode class MyCustom3DNode : public ofNode { public: virtual void customDraw() { ofSphere(0,0,0,0.7); ofDrawAxis(2 ); } };
  • 17.
    ofEasyCam Camera interaction madeeasy begin()/end() Put your draw calls between these setTarget(ofNode) Follow and look at a target
  • 18.
    ofEasyCam Custom ofNode - example ofEasyCam class MyCustom3DNode : public ofNode { public: virtual void customDraw() { ofSphere(0,0,0,0.7); ofDrawAxis(2); } }; class testApp : public ofBaseApp{ public: ofEasyCam easy_cam; vector<MyCustom3DNode*> custom_nodes; MyCustom3DNode* mover; };
  • 19.
    ofEasyCam Custom ofNode - example ofEasyCam void testApp::setup(){ ofBackground(33,33,33); // set distance of camera "5" meters away easy_cam.setDistance(5); // create a bunch of custom 3D nodes float r = 4; for(int i = 0; i < 10; ++i) { MyCustom3DNode* node = new MyCustom3DNode(); node->setPosition( cos((float)i/10*TWO_PI) * r ,sin((float)i/10*TWO_PI) * r ,-5 ); custom_nodes.push_back(node); mover = node; } // set target for camera easy_cam.setTarget(*mover); }
  • 20.
    ofEasyCam Custom ofNode - example ofEasyCam void testApp::draw(){ easy_cam.begin(); // draw custom nodes. for(int i = 0; i < custom_nodes.size(); ++i) { custom_nodes[i]->draw(); } // move over x-axis. float truck_amount = sin(ofGetElapsedTimef()*0.5) * 0.001; mover->truck(truck_amount); easy_cam.end(); }
  • 21.
    ofMesh Container for allvertex related data • Use this when working with 3D meshes. It creates a model that is used by openGL to draw 3D shapes. • Future proof (ready for modern openGL) • Clean API for most used data: add[Vertex,Color,TexCoord]() • Nice interface for writing 3D exports (OBJ, PLY) • Use this with Vertex Buffer Objects (VBO)
  • 22.
    ofMesh Adding vertices addVertex(ofVec3f) Add one vertex addVertices(vector<ofVec3f>&) Reference to ofVec3f addVertices(ofVec3f*, int num) Pointer to vertices setVertex(int index) Remove by index Remove vertices removeVertex(int index) Remove by index clearVertices() Remove all vertices Get vertex getVertex(int) Get one vertex
  • 23.
    ofMesh Adding normals addNormal(ofVec3f&) Add a normal addNormals(vector<ofVec3f>) Add vector of normals addNormals(ofVec3f*, int) Add array of normals setNormal(int, ofVec3f&) Set one normal by index Removing normals removeNormal(int) Remove by index clearNormals() Remove all normals Retrieving normals getNormal(int) Get normal by index
  • 24.
    ofMesh Adding indices addIndex(ofIndexType) Add a index addIndices(const<ofIndextype>&) Add a bunch of indices addIndices(ofIndexType*,int) Add bunch of indices setIndex(int, ofIndexType) Set a specific index Removing indices removeIndex(int i) Remove by index clearIndices() Remove all indices Retrieving indices getIndex(int) Get index by index ;-)
  • 25.
    ofMesh Adding colors addColor(const ofFloatColor& c) Add a index addColors(const<ofFloatColor>& cols) Add a bunch of indices addColors(const ofFloatColor* cols, int amt) Add bunch of indices setColor(int index, const ofFloatColor& c) Set a specific index Removing colors removeColor(int index) Remove by index clearColors() Remove all indices Retrieving colors ofFloatColor getColor(int i) Get index by index ;-)
  • 26.
    ofMesh Useful for GL_ARRAY_BUFFER/ VBO getNumVertices() Total number of vertices getNumColors() Total number of colors getNumTexCoords() Total number of texture coords getNumIndices() Total number of indices float* getVerticesPointer() Get a pointer to the vertices float* getColorsPointer() Get a pointer to the colors float* getNormalsPointer() Get pointer to stored normals ofIndexType* getTexCoordsPointer() Get pointer to texcoords
  • 27.
    ofMesh Same API forthe rest • Same API for Colors, TexCoord • Helper function addTriangle(int,int,int)
  • 28.
    Create two planes testApp.cpp void testApp::setup(){ // bottom cube.addVertex(ofVec3f(-1,0,1)); cube.addVertex(ofVec3f(1,0,1)); cube.addVertex(ofVec3f(1,0,-1)); cube.addVertex(ofVec3f(-1,0,-1)); // top cube.addVertex(ofVec3f(-1,1,1)); cube.addVertex(ofVec3f(1,1,1)); cube.addVertex(ofVec3f(1,1,-1)); cube.addVertex(ofVec3f(-1,1,-1)); // triangles bottom cube.addIndex(0); cube.addIndex(1); cube.addIndex(2); cube.addIndex(2); cube.addIndex(3); testApp.h cube.addIndex(0); class testApp : public ofBaseApp{ // triangles top cube.addIndex(4); public: cube.addIndex(5); ofMesh cube; cube.addIndex(6); }; cube.addIndex(6); cube.addIndex(7); cube.addIndex(4); }
  • 29.
    Create a cube testApp.cpp void testApp::setup(){ // bottom vertices cube.addVertex(ofVec3f(-1,0,1)); cube.addVertex(ofVec3f(1,0,1)); cube.addVertex(ofVec3f(1,0,-1)); cube.addVertex(ofVec3f(-1,0,-1)); // top vertices cube.addVertex(ofVec3f(-1,1,1)); cube.addVertex(ofVec3f(1,1,1)); cube.addVertex(ofVec3f(1,1,-1)); cube.addVertex(ofVec3f(-1,1,-1)); // indices cube.addTriangle(0,1,2); // bottom cube.addTriangle(2,3,0); cube.addTriangle(4,5,6); // top cube.addTriangle(6,7,4); cube.addTriangle(0,4,5); // front cube.addTriangle(0,1,5); testApp.h cube.addTriangle(1,2,6); // right cube.addTriangle(6,5,1); class testApp : public ofBaseApp{ cube.addTriangle(2,6,3); // back cube.addTriangle(3,7,6); public: cube.addTriangle(0,3,7); // left ofMesh cube; cube.addTriangle(7,4,0); }; }
  • 30.