Handout 3 CS 116A Fall 2003

//SAMPLE Mesh code has NOT been compiled or tested. 


#include "vectormatrix.h"

#include <vector>

using namespace std


//################ Face ##################

class cFace



        vector<int> _vertexid; // the list of vertex indices

        vector<int> _normalid; // the list of normal indices

        cFace(){} // constructor

        ~cFace(){}// destructor


//###################### Mesh #######################

class cMesh



        vector<cVector> _vertex;       // array of 3D vertices

        vector<cVector> _normal;    // array of normals

        vector<cFace> _face;      // array of face data


        cMesh();               // constructor

        ~cMesh();          // destructor

        int facecount(){return _face.size();}

        int vertcount(int faceindex){return _face[faceindex].size();}

        cVector vertex(int faceindex, int i)

               {return _vertex[_face[faceindex]._vertexid[i]];|

        cVector normal(int faceindex, int i)

               {return _normal[_face[faceindex]._normalid[i]];|

        void draw(int drawflags);



//Simple method.

void cMesh:: draw(int drawflags)


        static int displayid = 0;

        if (!displayid) //Only do this the first time


                displayid = glGenLists(1);

                glNewList(displayid, GL_COMPILE);

               for(int j = 0; j < facecount(); j++) // draw each face



                        for(int i = 0; i < face[j].vertcount(); i++) // for each one..


                               glNormal3d(normal(j, i).x(), normal(j, i).y(),

                                       normal(j, i).z());

                               glVertex3d(vertex(j, i).x(), vertex(j, i).y(),

                                       vertex(j, i).z());





        } //End of the part you onlythe first time.

        glCallList(displaylistid); //Always do this.



//Faster, more complicated Vector Array method

void cMesh:: draw(int drawflags)


/* Don't have time to write it.  Uses calls to


        allocate Real *vertices = new Real[...]

        fill with lines like this: vertices[3+3*i] = ppolygon->getVertex(i).x();

        allocate GLushort *quadindices = new GLushort[4*size];

        fill with lines like this: quadindices[4*i] = 1 + i;

        Use with lines like








        You can do something similar for the normals.



==================================ASSEMBLY.H CODE from MOLECULES1, has been tested.

class cAssembly



        static cAssembly* cAssembly::makeRandomAssembly(int maxdepth = MAXDEPTH);

               /* makeRandomAssembly is a static (think "global") method that creates

               random assembliess. Methods of this kind are called factory methods,

               in that they create new objects for you.  The meaning of the maxdepth

                argument is that we guarantee not to return a nested cAssemblyComposite

               with more than maxdepth levels.  You use this method in your main program

               by picking some value of MAXDEPTH maybe between 2 and 5 and writing a

               line like

                cAssembly *pnew = cAssembly::makeRandomAssembly(MAXDEPTH);              */



        Real _actualradius; /* Make this be the actual radius of the most

               distant point form the origin. */


        cVector _scale;

        Real _spinangle;

        cVector _spinaxis;

        cVector _position;


        Real _spinrate;


//Construtor, Destructor, Copy




        virtual void randomize(); //Randomizes spinaxis and spinangle


//Essential methods

        virtual void animate(Real dt);

        virtual void draw(int drawflags = 0){} //If drawflags is 1, we draw wireframe.



class cAssemblyComposite : public cAssembly



        vector <cAssembly*> _pchild;


//Constructor, etc.

        cAssemblyComposite(){} //Default constructor makes empty _pchild array

//Special methods

        void add(cAssembly *pa);

        void addRandomChildren(int maxdepth = cAssembly::MAXDEPTH);


        virtual void fixActualRadius(); /* Try to adjust

                _actualradius to include all the pieces. */

        virtual int depth(); //Return 1 + max depth of children.

        virtual void animate(Real dt);

        virtual void draw(int drawflags = 0);



class cPolyhedron : public cAssembly

{ //as before



//========Good Stuff for cAssembly====================

void cAssembly::randomize()


        _spinaxis = cVector::randomUnitVector();

        _spinrate = cRandomizer::pinst()->randomReal(3.0*(2*PI), 20.0*(2*PI));



cAssembly* cAssembly::makeRandomAssembly(int depth)


        cAssembly *pnewassembly;

        if (depth >= 1)


                pnewassembly = new cAssemblyComposite();

                ((cAssemblyComposite*)pnewassembly)-> //Have to cast so I can use method

                       addRandomChildren(depth); //Allow  maxdepth more levels.



                pnewassembly = new cPolyhedron();

        pnewassembly->randomize(); /* Randomizes the spinaxis and spinrate, also,

               if it's a polyhedron, randomizes the color and shape. */


        return pnewassembly;



void cAssembly::animate(Real dt)


        _position += dt*_velocity;

        _spinangle += dt*_spinrate;


//===========Good cAssemblyComposite Stuff===============


void cAssemblyComposite::addRandomChildren(int maxdepth)


        cAssembly *pnew;

        int childcount = cRandomizer::pinst()->random(2, 3);

        for (int i=0; i<childcount; i++)


               pnew = cAssembly::makeRandomAssembly(maxdepth - 1);


               if (i>0)

        // I'll move the later guys out to be on periphery of the first guy.


                       cAssembly* pboss = _pchild[0];

                       cVector displacedir = cVector::randomUnitVector();

                       Real howfar = cRandomizer::pinst()->randomReal(0.5, 1.3);

                       pnew->setPosition(howfar * pboss->radius() * displacedir);


                       // I'll scale the later guys to be smaller.

                       Real shrinkfactor = cRandomizer::pinst()->randomReal(0.5, 0.8);




#endif //PLANETARY





void cAssemblyComposite::animate(Real dt)



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





int cAssemblyComposite::depth()


        int maxdepth = 0;

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

               if (maxdepth < _pchild[i]->depth())

                       maxdepth = _pchild[i]->depth();

        return maxdepth + 1;


//===============new drawFlurry in DONUTS.CPP

void drawFlurry() //Uses the global dt param.


        while (assemblyarray.size() < maxassemblycount)


                cAssembly *pnewpoly;

                pnewpoly = cAssembly::makeRandomAssembly(maxassemblycomplexity);


                       randomReal(-0.5* xradius, 0.5 * xradius),

                       cRandomizer::pinst()->randomReal(-0.5* yradius, 0.5* yradius),

                       cRandomizer::pinst()->randomReal(0.0, zradius)));


                //push_back adds the pointer to the array.


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



               if (fallflag)

                       assemblyarray[i]->translate(-FALLSPEED * dt * cVector::ZAXIS);

                assemblyarray[i]->draw(wireflag | showconnectorflag | showradiusflag);

               if (assemblyarray[i]->position().z() <

                       -zradius + assemblyarray[i]->radius())


                       delete assemblyarray[i]; //Delete it before removing from the deque.

                       assemblyarray.erase(assemblyarray.begin()+i); //Erase when you hit bottom.




==========MOLECULE 1 CONTROLS===========

' ': Space singlesteps if animation flag is turned off.

        'a': Toggles the running animation.

'b': Toggles wireframe balls around the assemblies.  The colors of

        the balls indicate the "depth" of the assmbly, that is, how many

        levels of subassemblies it has.

'c': Toggles wireframe lines connecting the first member of an assembly

        to the other.  Color = depth as in 'b'.

'd': Decrements maximum depth or complexity of assemblies. The minumum

        depth of 0 is a polyhedron.

D': Increments depth.

'f': Toggles the falling-towards-the-viwer motion.

'n': Decrements the number of assemblies on screen.

'N': Increments the number of assemblies on screen.

'q': Quit

'r': Randomize the assemblies on screen.

'w': Toggle a wireframe view.

'z': Zoom in.

'Z': Zoom out.

'2': Use a 2d orthogonal projection.

'3': Use a 3d perspective projection.