Code Snippets

From Horde3D Wiki
Jump to: navigation, search

What is this page?

This page of the wiki is a sharing zone for rough Horde example code.



Using Custom GL Code After Horde3D

Horde3D has a bad habbit of messing with the OpenGL states after it is finished, so it is necessary with a few third party libraries to make sure that the OpenGL state is at its default settings before rendering. Here is an example using CEGUI. It is assumed you can logically piece together what the main loop would look like.

Custom OpenGL after Horde3D.
  1. void Engine::InitializeRenderer()
    
  2. {
    
  3.     glPushAttrib(GL_ALL_ATTRIB_BITS); // save default attributes
    
  4.  
    
  5.     LOG("Initializing rendering engine...",INFO);
    
  6.     if(!h3dInit())
    
  7.     {
    
  8.         LOG("Error initializing Horde3D. Aborting.",FATAL);
    
  9.         Kill();
    
  10.     }
    
  11.     LOG("Running the game.",INFO);
    
  12.  
    
  13.     glClearDepth(1.f);
    
  14.     glClearColor(0.f, 0.f, 0.5f, 0.f);
    
  15.     glEnable(GL_DEPTH_TEST);
    
  16. }
    
  17.  
    
  18. void Engine::FinalizeRenderer()
    
  19. {
    
  20.     if(stage)
    
  21.     {
    
  22.         h3dRender(active_camera);
    
  23.     }
    
  24.     h3dFinalizeFrame();
    
  25.     // attributes here are now messed up
    
  26. }
    
  27.  
    
  28. void Engine::FinalizeGUI()
    
  29. {
    
  30.     glPopAttrib(); // pop back to default state since horde3d messed with the states.
    
  31.  
    
  32.     CEGUI::System::getSingleton().renderGUI();
    
  33.  
    
  34.     glPushAttrib(GL_ALL_ATTRIB_BITS); // save the default state again before going back to Horde3D
    
  35. }
    


More procedurally generated content code

The following is similar but different to the Procedurally generated geometry tutorial

Building a 2D grid of quads
  1. void ScreenGridMesh( char*& data, int& fileSize, int& batchStart, int& batchCount, int& vertRStart, int& vertREnd )
    
  2. {
    
  3.         extern int appWidth;
    
  4.         extern int appHeight;
    
  5.  
    
  6.         //This example splits the screen up into groups of 16 pixels, and create a quad for each group.
    
  7.         int quadSize = 16;
    
  8.         int quadsH = (appWidth +quadSize-1) / quadSize;//divide by 16, rounding up
    
  9.         int quadsV = (appHeight+quadSize-1) / quadSize;
    
  10.         int quads = quadsH*quadsV;
    
  11.  
    
  12.  
    
  13.         int version = 5;//This is the current version of the GEO format (at the time of writing).
    
  14.  
    
  15.         int numJoints = 0;//I don't have code below for writing joints...
    
  16.         int numMorphTargets = 0;//...or morph targets
    
  17.  
    
  18. //The lines that begin with //! or /*! could be used if you want a more complete vertex format (i.e. normal/binormal/tangent/joints/etc)
    
  19. //!     int numVertexStreams = 8;
    
  20.         int numVertexStreams = 2;//I'm just using position + tex-coord
    
  21.  
    
  22.         int numVertices = quads * 4;// I'm making 4 verts per quad
    
  23.         int numTriangleIndices = quads * 6;//Each quad is 2 triangles. Each triangle is made up of 3 verts, so I need 6 indices to describe each quad.
    
  24.  
    
  25.         //These are all "magic numbers" that horde uses to interpret the data streams
    
  26.         int vertPositionID = 0;
    
  27.         int vertNormalID = 1;
    
  28.         int vertTangentID = 2;
    
  29.         int vertBiTangentID = 3;
    
  30.         int vertJointIndexID = 4;
    
  31.         int vertJointWeightID = 5;
    
  32.         int vertTexCoordID = 6;
    
  33.         int vertTexCoord2ID = 7;
    
  34.         int positionElementSize = sizeof(float)*3;
    
  35.         int normalElementSize   = sizeof(short)*3;
    
  36.         int tangentElementSize  = sizeof(short)*3;
    
  37.         int biTangentElementSize= sizeof(short)*3;
    
  38.         int jointIndexElementSize = sizeof(char)*4;
    
  39.         int jointWeightElementSize = sizeof(char)*4;
    
  40.         int texCoordElementSize = sizeof(float)*2;
    
  41.         int texCoord2ElementSize = sizeof(float)*2;
    
  42.  
    
  43.         batchStart = 0;
    
  44.         batchCount = numTriangleIndices;
    
  45.         vertRStart = 0;
    
  46.         vertREnd = numVertices-1;
    
  47.  
    
  48. //!     int vertDataSize = positionElementSize+normalElementSize+
    
  49. //!                        tangentElementSize+biTangentElementSize+
    
  50. //!                        jointIndexElementSize+jointWeightElementSize+
    
  51. //!                        texCoordElementSize+texCoord2ElementSize;
    
  52.         int vertDataSize = positionElementSize+texCoordElementSize;
    
  53.  
    
  54.         int quadDataSize = vertDataSize*4 + sizeof(int)*6;
    
  55. //!     fileSize = sizeof(char)*4 + sizeof(int)*22 + quadDataSize*quads;
    
  56.         fileSize = sizeof(char)*4 + sizeof(int)*10 + quadDataSize*quads;
    
  57.  
    
  58.         data = new char[fileSize];
    
  59.         int written = 0;
    
  60.  
    
  61. #define ASSERT( c )     \
    
  62.         if( !(c) ) { printf( "ASSERTION FAILED: %s\n", #c ); breakPlz(); }
    
  63. #define WRITE_DATA( d, size )   \
    
  64.         memcpy( &data[written], d, size ); written += size; ASSERT( written <= fileSize );
    
  65.  
    
  66.         //First write the header
    
  67.         WRITE_DATA( "H3DG", sizeof(char)*4 );
    
  68.         WRITE_DATA( &version, sizeof(int) );
    
  69.  
    
  70.         //Joint data would go here, if I had any
    
  71.         WRITE_DATA( &numJoints, sizeof(int) );
    
  72.  
    
  73.         //Then write the vertex-stream header
    
  74.         WRITE_DATA( &numVertexStreams, sizeof(int) );
    
  75.         WRITE_DATA( &numVertices, sizeof(int) );
    
  76.  
    
  77.         //I'm making quads in this example, so all my loops are going to create 4 pieces of each data.
    
  78.  
    
  79.         //To begin with I write the positions:
    
  80.         WRITE_DATA( &vertPositionID, sizeof(int) );
    
  81.         WRITE_DATA( &positionElementSize, sizeof(int) );
    
  82.         for( int y=0; y<quadsV; ++y )
    
  83.         {
    
  84.                 for( int x=0; x<quadsH; ++x )
    
  85.                 {
    
  86.                         float positionA[3] = { ((x+0.0f)/(float)quadsH)*2.0f-1.0f, ((y+0.0f)/(float)quadsV)*2.0f-1.0f, 0.0f };
    
  87.                         float positionB[3] = { ((x+1.0f)/(float)quadsH)*2.0f-1.0f, ((y+0.0f)/(float)quadsV)*2.0f-1.0f, 0.0f };
    
  88.                         float positionC[3] = { ((x+1.0f)/(float)quadsH)*2.0f-1.0f, ((y+1.0f)/(float)quadsV)*2.0f-1.0f, 0.0f };
    
  89.                         float positionD[3] = { ((x+0.0f)/(float)quadsH)*2.0f-1.0f, ((y+1.0f)/(float)quadsV)*2.0f-1.0f, 0.0f };
    
  90.                         WRITE_DATA( positionA, sizeof(float)*3 );
    
  91.                         WRITE_DATA( positionB, sizeof(float)*3 );
    
  92.                         WRITE_DATA( positionC, sizeof(float)*3 );
    
  93.                         WRITE_DATA( positionD, sizeof(float)*3 );
    
  94.                 }
    
  95.         }
    
  96.         /*!
    
  97.         //Normals/binormals/tangents should be floats in the 0-1 range, and then multiplied by 32767 and cast to 'short'. This is a form of compression.
    
  98.         WRITE_DATA( &vertNormalID, sizeof(int) );
    
  99.         WRITE_DATA( &normalElementSize, sizeof(int) );
    
  100.         for( int i=0; i!=quads; ++i )
    
  101.         {
    
  102.                 short n[] = { 0, 0, 32767 };
    
  103.                 WRITE_DATA( n, sizeof(short)*3 );
    
  104.                 WRITE_DATA( n, sizeof(short)*3 );
    
  105.                 WRITE_DATA( n, sizeof(short)*3 );
    
  106.                 WRITE_DATA( n, sizeof(short)*3 );
    
  107.         }
    
  108.         WRITE_DATA( &vertTangentID, sizeof(int) );
    
  109.         WRITE_DATA( &tangentElementSize, sizeof(int) );
    
  110.         for( int i=0; i!=quads; ++i )
    
  111.         {
    
  112.                 short n[] = { 0, 32767, 0 };
    
  113.                 WRITE_DATA( n, sizeof(short)*3 );
    
  114.                 WRITE_DATA( n, sizeof(short)*3 );
    
  115.                 WRITE_DATA( n, sizeof(short)*3 );
    
  116.                 WRITE_DATA( n, sizeof(short)*3 );
    
  117.         }
    
  118.         WRITE_DATA( &vertBiTangentID, sizeof(int) );
    
  119.         WRITE_DATA( &biTangentElementSize, sizeof(int) );
    
  120.         for( int i=0; i!=quads; ++i )
    
  121.         {
    
  122.                 short n[] = { 32767, 0, 0 };
    
  123.                 WRITE_DATA( n, sizeof(short)*3 );
    
  124.                 WRITE_DATA( n, sizeof(short)*3 );
    
  125.                 WRITE_DATA( n, sizeof(short)*3 );
    
  126.                 WRITE_DATA( n, sizeof(short)*3 );
    
  127.         }
    
  128.  
    
  129.         //Each vertex can be influenced by 4 joints - the joint IDs are written here
    
  130.         WRITE_DATA( &vertJointIndexID, sizeof(int) );
    
  131.         WRITE_DATA( &jointIndexElementSize, sizeof(int) );
    
  132.         for( int i=0; i!=quads; ++i )
    
  133.         {
    
  134.                 char j[] = { 0, 0, 0, 0 };
    
  135.                 WRITE_DATA( j, sizeof(char)*4 );
    
  136.                 WRITE_DATA( j, sizeof(char)*4 );
    
  137.                 WRITE_DATA( j, sizeof(char)*4 );
    
  138.                 WRITE_DATA( j, sizeof(char)*4 );
    
  139.         }
    
  140.  
    
  141.         //The 'percent' (out of 255, not out of 100) that each of the above joints influences the vertex:
    
  142.         WRITE_DATA( &vertJointWeightID, sizeof(int) );
    
  143.         WRITE_DATA( &jointWeightElementSize, sizeof(int) );
    
  144.         for( int i=0; i!=quads; ++i )
    
  145.         {
    
  146.                 ASSERT( sizeof(char) == 1 )
    
  147.                 char j[] = { 255, 0, 0, 0 };
    
  148.                 WRITE_DATA( j, sizeof(char)*4 );
    
  149.                 WRITE_DATA( j, sizeof(char)*4 );
    
  150.                 WRITE_DATA( j, sizeof(char)*4 );
    
  151.                 WRITE_DATA( j, sizeof(char)*4 );
    
  152.         }
    
  153.         */
    
  154.         //Tex-coords are pairs of floats
    
  155.         WRITE_DATA( &vertTexCoordID, sizeof(int) );
    
  156.         WRITE_DATA( &texCoordElementSize, sizeof(int) );
    
  157.         for( int i=0; i!=quads; ++i )
    
  158.         {
    
  159.                 float uvTl[] = { 0.0f, 1.0f };
    
  160.                 float uvBl[] = { 0.0f, 0.0f };
    
  161.                 float uvBr[] = { 1.0f, 0.0f };
    
  162.                 float uvTr[] = { 1.0f, 1.0f };
    
  163.                 WRITE_DATA( uvTl, sizeof(float)*2 );
    
  164.                 WRITE_DATA( uvBl, sizeof(float)*2 );
    
  165.                 WRITE_DATA( uvBr, sizeof(float)*2 );
    
  166.                 WRITE_DATA( uvTr, sizeof(float)*2 );
    
  167.         }
    
  168.         /*!
    
  169.         //You can have a second set of tex-coords if you want
    
  170.         WRITE_DATA( &vertTexCoord2ID, sizeof(int) );
    
  171.         WRITE_DATA( &texCoord2ElementSize, sizeof(int) );
    
  172.         for( int i=0; i!=quads; ++i )
    
  173.         {
    
  174.                 float uvTl[] = { 0.0f, 1.0f };
    
  175.                 float uvBl[] = { 0.0f, 0.0f };
    
  176.                 float uvBr[] = { 1.0f, 0.0f };
    
  177.                 float uvTr[] = { 1.0f, 1.0f };
    
  178.                 WRITE_DATA( uvTl, sizeof(float)*2 );
    
  179.                 WRITE_DATA( uvBl, sizeof(float)*2 );
    
  180.                 WRITE_DATA( uvBr, sizeof(float)*2 );
    
  181.                 WRITE_DATA( uvTr, sizeof(float)*2 );
    
  182.         }*/
    
  183.  
    
  184.         //Finally, time for the index buffer
    
  185.         WRITE_DATA( &numTriangleIndices, sizeof(int) );
    
  186.         for( int i=0; i!=quads; ++i )
    
  187.         {
    
  188.                 int base = i * 4;
    
  189.                 int a = base, b = base+1, c = base+2, d=base+2, e=base+3, f=base;
    
  190.                 WRITE_DATA( &a, sizeof(int) );
    
  191.                 WRITE_DATA( &b, sizeof(int) );
    
  192.                 WRITE_DATA( &c, sizeof(int) );
    
  193.                 WRITE_DATA( &d, sizeof(int) );
    
  194.                 WRITE_DATA( &e, sizeof(int) );
    
  195.                 WRITE_DATA( &f, sizeof(int) );
    
  196.         }
    
  197.  
    
  198.         //Morph targets would go here, if I had any
    
  199.         WRITE_DATA( &numMorphTargets, sizeof(int) );
    
  200.  
    
  201.         ASSERT( written == fileSize );//ensure we didn't over/under-use the buffer
    
  202. }
    
Example Usage
  1.         // Build a geo
    
  2.         H3DRes gridGeo = h3dAddResource( H3DResTypes::Geometry, "runtime/blahBlah.geo", H3DResFlags::NoQuery );
    
  3.         int batchStart = 0, batchCount = 0, vertRStart = 0, vertREnd = 0;
    
  4.         {
    
  5.                 int dataSize = 0;
    
  6.                 char* data = 0;
    
  7.                 ScreenGridMesh( data, dataSize, batchStart, batchCount, vertRStart, vertREnd );
    
  8.                 bool loadedData = h3dLoadResource( gridGeo, data, dataSize );
    
  9.                 delete [] lensBlurData;
    
  10.         }
    
  11.  
    
  12.         // Load a material
    
  13.         H3DRes material = h3dAddResource( H3DResTypes::Material, "materials/grid.material.xml", 0 );
    
  14.         h3dutLoadResourcesFromDisk( _contentDir.c_str() );
    
  15.  
    
  16.         // Create a model/mesh from the procedural geo
    
  17.         H3DNode model = h3dAddModelNode( H3DRootNode, "MyModel", gridGeo );
    
  18.         H3DNode mesh = h3dAddMeshNode( model, "MyMesh", material, batchStart, batchCount, vertRStart, vertREnd );
    
Personal tools