Gizmo3D

tree.cpp

Tree example application. This example illustrates how recursive structure can be used.
The source code can also be found in the examples directory of the Gizmo3D distribution.

00001 // *****************************************************************************
00002 // File         : tree.cpp
00003 // Module       : 
00004 // Description  : Test app for recursive tree sample
00005 // Author       : Anders Modén          
00006 // Product      : Gizmo3D 2.1.1
00007 //              
00008 // Copyright © 2003- Saab Training Systems AB, Sweden   
00009 //                      
00010 // NOTE:    Gizmo3D is a high performance 3D Scene Graph and effect visualisation 
00011 //          C++ toolkit for Linux, Mac OS X, Windows (Win32) and IRIX® for  
00012 //          usage in Game or VisSim development.
00013 //
00014 //
00015 // Revision History...                                                  
00016 //                                                                      
00017 // Who  Date    Description                                             
00018 //                                                                      
00019 // AMO  020901  Created file    
00020 //
00021 // ******************************************************************************
00022 
00023 //#define GZ_MEM_DEBUG  //to enable mem debug
00024 
00025 #define USE_STATS
00026 
00027 //#define USE_COMPILED_TREE
00028 
00029 // The general includes
00030 #include "gzGizmo3DLibrary.h"
00031 
00032 
00033 gzRealXY xyfunk1(gzReal in)
00034 {
00035     return gzRealXY(in*(1-in)*sin(in*GZ_PI*3)*5,in*(1-in)*sin(3*in*GZ_PI)*5);
00036 }
00037 
00038 gzRealXY xyfunk2(gzReal in)
00039 {
00040     return gzRealXY(in*(1-in)*sin(2*in*GZ_PI)*5,in*(1-in)*sin(5*in*GZ_PI));
00041 }
00042 
00043 
00044 gzGeometry *leaf()
00045 {
00046     gzGeometry *leaf=new gzGeometry;
00047 
00048     gzArray<gzVec3> &coordinates=leaf->getCoordinateArray();
00049     gzArray<gzVec2> &tex=leaf->getTexCoordinateArray();
00050     gzArray<gzVec3> &norm=leaf->getNormalArray();
00051 
00052 
00053     coordinates+=   gzVec3(-80,0,0);
00054     coordinates+=   gzVec3(80,0,0);
00055     coordinates+=   gzVec3(80,160,0);
00056     coordinates+=   gzVec3(-80,160,0);
00057 
00058     tex+=   gzVec2(0,0);
00059     tex+=   gzVec2(1,0);
00060     tex+=   gzVec2(1,1);
00061     tex+=   gzVec2(0,1);
00062 
00063     norm+=gzVec3(0,0,1);
00064 
00065     leaf->setTexBind(GZ_BIND_ON);
00066     leaf->setNormalBind(GZ_BIND_PER_PRIM);
00067     leaf->setGeoPrimType(GZ_PRIM_QUADS);
00068 
00069 
00070     // Fix state on leaf
00071 
00072     gzMaterial *material=new gzMaterial;
00073     gzState *state=new gzState;
00074 
00075     state->setMaterial(material);
00076     //state->setBackMaterial(material);
00077     state->setMode(GZ_STATE_MATERIAL,GZ_STATE_ON);
00078 
00079     gzTexture *texture=new gzTexture;
00080 
00081     texture->setImage(gzImageManager::loadImage("leaf.png"));
00082     texture->setComponents(4);
00083     texture->setWrapS(GZ_TEXTURE_WRAP_REPEAT);
00084     texture->setWrapT(GZ_TEXTURE_WRAP_REPEAT);
00085     texture->useMipMaps(TRUE);
00086     texture->setMagFilter(GZ_TEXTURE_MAG_LINEAR);
00087     texture->setMinFilter(GZ_TEXTURE_MIN_LINEAR_MIPMAP_LINEAR);
00088 
00089     state->setMode(GZ_STATE_ALPHA_FUNC,GZ_STATE_ON);
00090     state->setAlphaFunc(GZ_ALPHA_FUNC_GREATER,0.5f);
00091 
00092 
00093 
00094     state->setTexture(texture);
00095     state->setMode(GZ_STATE_TEXTURE,GZ_STATE_ON);
00096 
00097     state->setMode(GZ_STATE_POLYGON_MODE,GZ_STATE_ON);
00098     state->setBackPolygonMode(GZ_POLYGON_MODE_FILL);
00099     state->setFrontPolygonMode(GZ_POLYGON_MODE_FILL);
00100 
00101     leaf->setState(state);
00102 
00103     return leaf;
00104 }
00105 // A test sample of a geometry
00106 gzNode *buildTree()
00107 {
00108 
00109     
00110     gzGeometry *base_1=new gzGeometryTube(50,5,11,6,GZ_TUBE_CONE,xyfunk1,5,5);
00111 
00112     //base_1->useDisplayList(TRUE);
00113 
00114     gzGeometry *base_2=new gzGeometryTube(50,5,11,6,GZ_TUBE_CONE,xyfunk2,5,5);
00115 
00116     //gzGeometry *branch_base=new gzGeometryTube(20,0.2,10,3,0,xyfunk2,10,10);
00117 
00118 
00119     //base_2->useDisplayList(TRUE);
00120 
00121     // Base branch
00122 
00123     gzSeedSwitch *base=new gzSeedSwitch;
00124 
00125     base->addNode(base_1);
00126     base->addNode(base_2);
00127 
00128 
00129     gzULong depth=13;
00130 
00131     // Build tree
00132 
00133     gzRecursive *tree=new gzRecursive;
00134 
00135     tree->setMaxDepth(depth);
00136 
00137     //tree->useDistanceDepth(TRUE);
00138     //tree->setDistanceDepthEquation(1000,1);
00139 
00140     // tree=(base+T1*R1*S1*tree+T2*R2*S2*tree+SW*(T3*R3*S3*tree.....))
00141 
00142     // tree=base
00143     tree->addNode(base);
00144 
00145     tree->setMaxDepthNode(leaf());
00146 
00147     gzFloat rotation=180;
00148 
00149     gzFloat balance=0.6f;
00150 
00151     gzFloat spread=50;
00152 
00153     gzFloat offset=0;
00154 
00155     gzFloat add_rotation=108;
00156 
00157     // TRS1 - top striving high
00158     gzSeedTransform *pSeedTransform_1=new gzSeedTransform();
00159     pSeedTransform_1->setTranslation(0,48.5,0);
00160     pSeedTransform_1->setScale(0.85f,balance*1.5f,0.85f);
00161     pSeedTransform_1->setHPRSeedValue(TRUE,gzVec3(rotation+add_rotation,(1-balance)*spread,0),gzVec3(rotation+add_rotation,(1-balance)*spread,0));
00162     
00163     pSeedTransform_1->setStriveDirection(gzVec3(1,0,0));
00164     pSeedTransform_1->setStriveFactors(0.1f,0.1f,2.0f);
00165     
00166     pSeedTransform_1->addNode(tree);
00167     pSeedTransform_1->setRecursiveDepthScaleFactor(1);
00168 
00169     //pSeedTransform_1->setCacheSize(1000);
00170 
00171     // tree=base+T1*R1*S1*tree
00172     tree->addNode(pSeedTransform_1);
00173 
00174     
00175     // TRS2 - side winder
00176     gzSeedTransform *pSeedTransform_2=new gzSeedTransform();
00177     pSeedTransform_2->setTranslation(0,48,0);
00178     pSeedTransform_2->setScale((1-balance)*1.7,(1-balance)*1.7,(1-balance)*1.7);
00179     pSeedTransform_2->setHPRSeedValue(TRUE,gzVec3(rotation+add_rotation,-(offset+balance*spread),0),gzVec3(rotation+add_rotation,-(offset+balance*spread),0));
00180     
00181     pSeedTransform_2->setStriveDirection(gzVec3(1,-1,0));
00182     pSeedTransform_2->setStriveFactors(0.5);
00183     
00184     pSeedTransform_2->addNode(tree);
00185     pSeedTransform_2->setRecursiveDepthScaleFactor(1.1f);
00186 
00187     //pSeedTransform_2->setCacheSize(1000);
00188 
00189     
00190 
00191     tree->addNode(pSeedTransform_2);
00192 
00193 
00194     // Fix state on overall tree
00195 
00196     gzMaterial *material=new gzMaterial;
00197     gzState *state=new gzState;
00198 
00199     state->setMaterial(material);
00200     state->setMode(GZ_STATE_MATERIAL,GZ_STATE_ON);
00201 
00202     gzTexture *tex=new gzTexture;
00203 
00204     tex->setImage(gzImageManager::loadImage("bark.png"));
00205     tex->setWrapS(GZ_TEXTURE_WRAP_REPEAT);
00206     tex->setWrapT(GZ_TEXTURE_WRAP_REPEAT);
00207     tex->useMipMaps(TRUE);
00208     tex->setMagFilter(GZ_TEXTURE_MAG_LINEAR);
00209     tex->setMinFilter(GZ_TEXTURE_MIN_LINEAR_MIPMAP_LINEAR);
00210 
00211 
00212     state->setTexture(tex);
00213     state->setMode(GZ_STATE_TEXTURE,GZ_STATE_ON);
00214 
00215     // Seed starter
00216     gzSeedControl *topNode=new gzSeedControl;
00217     //topNode->setSeedControlType(GZ_SEED_FROM_TIME);
00218 
00219     topNode->setState(state);
00220 
00221     // Add recursive tree 
00222 
00223     topNode->addNode(tree);
00224 
00225     return topNode;
00226 }
00227 
00228 
00229 // And here comes the Java look alike app. It is a matter of taste.
00230 
00231 class MyWindow : public gzWindow
00232 {
00233 public:
00234     MyWindow():gzWindow(gzString("Gizmo3D : ")+gzTime::now(TRUE).asString())
00235     {
00236             // Create a scene to render -------------------------------------
00237             // We must have a scene that the camera can "look at"
00238             m_scene=new gzScene("Database Loader Example Scene");
00239             
00240             // Create some light environment group. This way we get lighting into the model
00241             // All stuff under this is lit with material s etc.
00242             gzEnvironment *group=new gzEnvironment;
00243 
00244             // Create a backface culling state
00245             // We don't want to render backfaces. this way we can "force" the geoms to be rendered without 
00246             // backfaces
00247             m_state=new gzState;
00248 
00249             m_state->setMode(GZ_STATE_POLYGON_MODE,GZ_STATE_ON);
00250             m_state->setBackPolygonMode(GZ_POLYGON_MODE_CULL);
00251             m_state->setFrontPolygonMode(GZ_POLYGON_MODE_FILL);
00252 
00253 #ifdef USE_STATS            
00254             m_state->setMode(GZ_STATE_GENERATE_DEBUG_INFO,GZ_STATE_ON);
00255             m_state->setDebugMode((gzStateDebugMode)(GZ_STATE_DEBUG_COLLECT_STATS /*|GZ_STATE_DEBUG_SHOW_NORMALS*/));
00256 #endif
00257             
00258             
00259 
00260             m_state->disableAllNonEnabledModes();   // We need this for the top global state
00261 
00262             gzState::setGlobalState(getContext(),m_state);
00263             
00264 
00265             // -------------------- lights --------------------------------
00266 
00267             // Add some dynamic light
00268             m_spin=new gzLight;                     // This is the lamp that we move around
00269             m_spin->setSpecularColor(0.2f,0.2f,0.2f);
00270             m_spin->setDiffuseColor(0.5f,0.5f,0.5f);
00271             m_spin->setAmbientColor(0.3f,0.3f,0.3f);
00272             m_spin->setPosition(26,10,90);
00273 
00274             // m_spin->invertShadowLight(TRUE); // Funny to invert shadow to be a spot instead..
00275 
00276             group->addLight(m_spin);
00277 
00278             // ------------------------ some global settings --------------
00279 
00280             gzEnvironment::setTwoSideLighting(getContext(),TRUE);
00281 
00282 
00283             // Add a sample recursive geometry
00284 
00285             
00286             gzNode *pTree=buildTree();
00287 
00288             gzTransform *trx=new gzTransform;
00289             gzCompileGroup *cg=new gzCompileGroup;
00290 
00291 #ifdef USE_COMPILED_TREE
00292             cg->addNode(pTree);
00293             trx->addNode(cg);
00294 #else
00295             trx->addNode(pTree);
00296 #endif
00297 
00298             trx->scale(0.2f);
00299             
00300             group->addNode(trx);
00301 
00302             
00303             // Add a lamp to show position of light
00304 
00305             m_lamp=new gzTransform;
00306 
00307             gzGeometry *sphere=new gzGeometrySphere(1 , 20 ,gzVec4(1.0,1.0,1.0,1.0) );
00308 
00309             //sphere->useDisplayList(TRUE);
00310 
00311             //sphere->convertToIndexed();
00312 
00313             m_lamp->addNode( sphere );
00314 
00315             // Set mouse press state
00316             m_inMousePress=FALSE;
00317 
00318 
00319             // And add the group to the scene as well
00320             m_scene->addNode(group);
00321 
00322             // And add the lamp
00323             m_scene->addNode(m_lamp);
00324 
00325                         
00326             // Add some textual info about frame rates
00327             m_text=new gzText("Screen Text");
00328 
00329             m_text->setColor(gzVec4(1,1,0,0.5));
00330             m_text->use2DPosition(TRUE);
00331             m_text->set2DPosition(10, -10);
00332             
00333             m_scene->addNode(m_text);
00334 
00335             // Now we want to look at the scene. Grab the default perspective camera from the window and set the scen as the
00336             // active one.
00337             getCamera()->setScene(m_scene);
00338             getCamera()->setNearClipPlane(1);
00339             getCamera()->setFarClipPlane(2000);
00340 
00341             // Lets add some movement to the scene
00342 
00343             m_input=new gzSimpleMouseViewControl(getCamera());
00344 
00345             addInputInterface(m_input);
00346 
00347             // Hmm. trivial
00348             setBackground(0.5f,0.5f,0.5f,1.0f);
00349 
00350             // and show us ...
00351             show();
00352 
00353             // hm. wonder why I put this one here ?
00354             angle=2.22f;
00355 
00356     };
00357 
00358 
00359     /*
00360         The following code snippet is a virtual function to catch the window messages
00361         for pressed, repeated and released keys
00362     */
00363 
00364     gzBool onKey(gzKeyValue key , gzKeyState keystate , gzLong mouse_x , gzLong mouse_y)
00365     {
00366         switch(key)
00367         {
00368             case ' ':   // Space pressed
00369 
00370                 if(keystate == GZ_KEY_STATE_PRESSED)
00371                 {
00372                     gzState *state=new gzState;
00373 
00374                     state->setFrontPolygonMode(GZ_POLYGON_MODE_LINE);
00375                     state->setBackPolygonMode(GZ_POLYGON_MODE_CULL);
00376                     state->setMode(GZ_STATE_POLYGON_MODE,GZ_STATE_ON);
00377                     state->setOverride(GZ_STATE_POLYGON_MODE,GZ_STATE_ON);
00378                     state->setOverride(GZ_STATE_TEXTURE,GZ_STATE_ON);
00379 
00380                     state->setMode(GZ_STATE_GENERATE_DEBUG_INFO,GZ_STATE_ON);
00381                     state->setDebugMode((gzStateDebugMode)(GZ_STATE_DEBUG_COLLECT_STATS));
00382             
00383 
00384                     state->disableAllNonEnabledModes();
00385 
00386                     gzState::setGlobalState(getContext(),state);
00387                 }
00388                 if(keystate == GZ_KEY_STATE_RELEASED)
00389                 {
00390                     gzState::setGlobalState(getContext(),m_state);
00391                 }
00392                 break;
00393 
00394             case GZ_KEY_LBUTTON :
00395 
00396                 if((keystate == GZ_KEY_STATE_PRESSED) && !m_inMousePress)
00397                 {
00398                     setCaptureMouse(TRUE);
00399                     setHideMouse(TRUE);
00400                     m_inMousePress=TRUE;
00401                 }
00402                 else if((keystate == GZ_KEY_STATE_RELEASED) && m_inMousePress)
00403                 {
00404                     setHideMouse(FALSE);
00405                     setCaptureMouse(FALSE);
00406                     m_inMousePress=FALSE;
00407                 }
00408                 break;
00409 
00410             case 'd' :
00411                 if(keystate == GZ_KEY_STATE_PRESSED)
00412                 {
00413                     getCamera()->getScene()->debug(GZ_DEBUG_SHOW_ALL);
00414                 }
00415                 break;
00416 
00417 
00418         }
00419 
00420         return gzWindow::onKey((gzKeyValue)key,(gzKeyState)keystate,mouse_x,mouse_y);
00421     }
00422 
00423 
00424     gzVoid onIdle()
00425     {
00426         // Hmm. Now i remember. The spinning lamp..
00427 
00428         angle+=0.003f;
00429 
00430         if(angle>2*GZ_PI)
00431             angle-=(gzReal)(2*GZ_PI);
00432 
00433         m_spin->setPosition((gzReal)(50*cos(5*angle)),5.0f,(gzReal)(50*sin(angle/2)+20));
00434 
00435         m_lamp->setTranslation((gzReal)(50*cos(5*angle)),5.0f,(gzReal)(50*sin(angle/2)+20));
00436 
00437         gzSeedTransform::setGlobalStriveStrength((1+(0.3*cos(7*angle)*sin(3*angle)+0.4*cos(5*angle)+0.2*sin(8*angle)+0.1*sin(21*angle) ))*0.5);
00438 
00439         //gzSleep(10);
00440     }
00441 
00442     virtual ~MyWindow()
00443     {
00444         if(m_input)
00445             delete m_input;
00446     }
00447 
00448     gzRefPointer<gzState> m_state;
00449 
00450     gzLight *           m_spin;
00451 
00452     gzText *            m_text;
00453 
00454     gzReal              angle;
00455 
00456     gzTransform *       m_lamp;
00457     
00458     gzBool              m_inMousePress;
00459 
00460     gzScene             *m_scene;
00461 
00462     gzSwitch            *m_switch;
00463 
00464     gzSimpleMouseViewControl    *m_input;
00465 
00466 };
00467 
00468 
00469 class WindowApp : public gzApplication
00470 {
00471 public:
00472         
00473     WindowApp():m_win(NULL),m_format(NULL),m_heading(0),m_pitch(0),m_position(30,30,500)
00474     {
00475     };
00476 
00477     ~WindowApp()
00478     {
00479         if(m_win)
00480         {
00481             delete m_win;
00482         }
00483 
00484     }
00485 
00486     void Create()
00487     {
00488         m_win = new MyWindow;
00489 
00490         gzPerspCamera *camera=gzDynamic_Cast<gzPerspCamera>(m_win->getCamera());
00491 
00492         camera->setHPR(m_heading,m_pitch,0);
00493         camera->setPosition(m_position.v1,m_position.v2,m_position.v3);
00494         camera->lookAt(0,25,0);
00495         camera->useInfiniteFarPlane(TRUE);
00496 
00497     }
00498 
00499     void onIdle()
00500     {
00501         if(m_win)
00502         {
00503             m_win->onIdle();
00504 
00505             m_win->triggerKeyEvaluation();
00506 
00507             if(!m_win->refreshWindow()) // Yield some time if no rendering
00508                 gzSleep(30);
00509 
00510             gzDouble delay=gzDynamicLoader::getWorkDelay();
00511 
00512             gzULong pending=gzDynamicLoader::getPendingWork();
00513 
00514             gzString outputString;
00515 
00516             if(!gzDynamicLoader::isWorking())
00517             {
00518                 outputString=gzString("FrameRate:")+gzString(m_win->getFrameRate());
00519                 delay=0;
00520             }
00521             else
00522                 outputString=gzString("FrameRate:")+gzString(m_win->getFrameRate())+"\n\nDynamic Loading -- Delay("+gzString(delay,"%.2f")+gzString("s) Pending(") + gzString((gzLongLong)gzDynamicLoader::getPendingWork())+ gzString(")");
00523 
00524 #ifdef USE_STATS
00525             outputString+=(gzString("\n\n\n")+gzGraphicsStats(m_win->getContext()));
00526 #endif
00527 
00528             
00529             
00530             if((delay>0.8) || (pending>100))
00531             {
00532                 gzDynamicLoader::boostLoaderWork();
00533                 outputString+="\n\n BOOSTED LOADING !!";
00534             }
00535             else
00536                 gzDynamicLoader::unBoostLoaderWork();
00537 
00538             
00539 
00540             m_win->m_text->setText(outputString);
00541 
00542         }
00543 
00544     }
00545 
00546 private:
00547 
00548     friend class MyWindow;
00549     
00550     MyWindow                *m_win;
00551     gzGraphicsFormat        *m_format;
00552 
00553     gzFloat             m_heading;
00554     gzFloat             m_pitch;
00555     gzVec3              m_position;
00556 
00557 };
00558 
00559 int main(int argc, char *argv[])
00560 {
00561     gzStartUpGizmo();   // Needed for some systems to install external graphics engines
00562     
00563     gzMessage::setMessageLevel(GZ_MESSAGE_MEM_DEBUG);
00564 
00565     try
00566     { 
00567         gzLicense::notifyDefaultLicense();
00568     
00569         gzGraphicsEngine::useEngine(GZ_ENGINE_OPENGL);
00570     
00571         gzInitializeDbManagers();
00572 
00573         // Make the application
00574         WindowApp app;
00575           
00576         // Create the scene and the window
00577         app.Create();
00578         
00579         // run the application
00580         app.run();
00581 
00582     }
00583     catch(gzBaseError &error)       // In case of exceptions thrown we want to print the message
00584     {
00585         error.reportError();
00586     }
00587     
00588     gzShutDownGizmo();
00589 
00590     return 0;
00591 }

Documentation for Gizmo3D generated at Wed Feb 20 11:54:02 2008 by   Saab Training Systems AB, ¸ (c) 2003-and beyond