Advertisement
MachCUBED

Untitled

Mar 7th, 2011
163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #import <OpenGLES/ES2/glext.h>
  2.  
  3. //we can't muck around with the pvrt code without going into objective-c++ mode, thus the .mm extension on Model.
  4. #import "PVRTModelPOD.h"
  5. #import "PVRTResourceFile.h" //for CPVRTResourceFile::SetReadPath and model loading
  6. #import "PVRTTextureAPI.h" //for PVRTTextureLoadFromPVR
  7.  
  8. #include "PVRShell.h" //For debugging
  9.  
  10. #import "Model.h"
  11. #import "GLProgram.h"
  12.  
  13. // vertex attributes
  14. enum EVertexAttrib {
  15.     VERTEX_ARRAY,
  16.     NORMAL_ARRAY,
  17.     TEXCOORD_ARRAY,
  18.     TANGENT_ARRAY,
  19.     BINORMAL_ARRAY,
  20.     BONEWEIGHT_ARRAY,
  21.     BONEINDEX_ARRAY,
  22.     eNumAttribs
  23. };
  24.  
  25. // shader uniforms
  26. enum ESkinnnedUniform {
  27.     eViewProj,
  28.     eLightPos,
  29.     eBoneCount,
  30.     eBoneMatrices,
  31.     eBoneMatricesIT,
  32.     ebUseDot3,
  33.     eNumSkinnedUniforms
  34. };
  35.  
  36. // Default
  37.  
  38. // vertex attributes
  39. enum EDefaultVertexAttrib {
  40.     DEFAULT_VERTEX_ARRAY,
  41.     DEFAULT_TEXCOORD_ARRAY,
  42.     eNumDefaultAttribs
  43. };
  44.  
  45. // shader uniforms
  46. enum EDefaultUniform {
  47.     eDefaultMVPMatrix,
  48.     eDefaultUOffset,
  49.     eNumDefaultUniforms
  50. };
  51.  
  52. // Camera constants. Used for making the projection matrix
  53. const float g_fCameraNear = 4.0f;
  54. const float g_fCameraFar  = 5000.0f;
  55.  
  56. const float g_fDemoFrameRate = 1.0f / 30.0f;
  57.  
  58. // The camera to use from the pod file
  59. const int g_ui32Camera = 0;
  60.  
  61. /*
  62.  // Group shader programs and their uniform locations together
  63. struct m_SkinnedShaderProgram
  64. {
  65.     GLuint uiId;
  66.     GLuint auiLoc[eNumSkinnedUniforms];
  67. };
  68.  
  69. struct m_DefaultShaderProgram
  70. {
  71.     GLuint uiId;
  72.     GLuint auiLoc[eNumDefaultUniforms];
  73. };
  74. */
  75.  
  76. // Variables to handle the animation in a time-based manner
  77. unsigned long m_iTimePrev;
  78. float   m_fFrame;
  79.  
  80.  
  81. @implementation Model
  82.  
  83. @synthesize defaultProgram;
  84. @synthesize skinnedVertexProgram;
  85. @synthesize textureProgram;
  86. @synthesize lightProgram;
  87.  
  88.  
  89. #pragma mark -
  90. #pragma mark Helper Methods
  91.  
  92. -(void)setupShaders
  93. {
  94.     //Setup shaders
  95.    
  96.     self.defaultProgram = [[GLProgram alloc]initWithVertexShaderFilename:@"VertShader" fragmentShaderFilename:@"FragShader"];
  97.     [self.defaultProgram addAttribute:@"inVertex"];
  98.     [self.defaultProgram addAttribute:@"inNormal"];
  99.     [self.defaultProgram addAttribute:@"inTexCoord"];
  100.     [self.defaultProgram link];
  101.    
  102.     /*
  103.     self.defaultProgram = [[GLProgram alloc]initWithVertexShaderFilename:@"DefaultVertShader" fragmentShaderFilename:@"DefaultFragShader"];
  104.     [self.defaultProgram addAttribute:@"inVertex"];
  105.     [self.defaultProgram addAttribute:@"inTexCoord"];
  106.     [self.defaultProgram link];
  107.    
  108.     self.skinnedVertexProgram = [[GLProgram alloc]initWithVertexShaderFilename:@"SkinnedVertShader" fragmentShaderFilename:@"SkinnedFragShader"];
  109.     [self.skinnedVertexProgram addAttribute:@"inVertex"];
  110.     [self.skinnedVertexProgram addAttribute:@"inNormal"];
  111.     [self.skinnedVertexProgram addAttribute:@"inTangent"];
  112.     [self.skinnedVertexProgram addAttribute:@"inBiNormal"];
  113.     [self.skinnedVertexProgram addAttribute:@"inTexCoord"];
  114.     [self.skinnedVertexProgram addAttribute:@"inBoneIndex"];
  115.     [self.skinnedVertexProgram addAttribute:@"inBoneWeights"];
  116.    
  117.     [self.skinnedVertexProgram link];
  118.    
  119.     self.textureProgram = [[GLProgram alloc]initWithVertexShaderFilename:@"Print3DVertShader" fragmentShaderFilename:@"Print3DFragShader"];
  120.     [self.textureProgram addAttribute:@"myVertex"];
  121.     [self.textureProgram addAttribute:@"myUV"];
  122.     [self.textureProgram addAttribute:@"myColour"];
  123.     [self.textureProgram link];
  124.    
  125.     self.lightProgram = [[GLProgram alloc]initWithVertexShaderFilename:@"LightShader3D" fragmentShaderFilename:@"LightShader3D"];
  126.     [self.lightProgram addAttribute:@"myVertex"];
  127.     [self.lightProgram addAttribute:@"myNormal"];
  128.     [self.lightProgram link];
  129.      */
  130. }
  131.  
  132. #pragma mark Mesh Setup
  133.  
  134. -(void)loadVbosInScene:(CPVRTModelPOD*)scene
  135. {
  136.     if (!vbo)
  137.         vbo = new GLuint[scene->nNumMesh];
  138.     if (!indexvbo)
  139.         indexvbo = new GLuint[scene->nNumMesh];
  140.    
  141.     /*
  142.      Load vertex data of all meshes in the scene into VBOs
  143.      
  144.      The meshes have been exported with the "Interleave Vectors" option,
  145.      so all data is interleaved in the buffer at pMesh->pInterleaved.
  146.      Interleaving data improves the memory access pattern and cache efficiency,
  147.      thus it can be read faster by the hardware.
  148.      */
  149.    
  150.     glGenBuffers(scene->nNumMesh, vbo);
  151.    
  152.     for(unsigned int i=0; i < scene->nNumMesh;i++)
  153.     {
  154.         SPODMesh& mesh = scene->pMesh[i];
  155.         unsigned int size = mesh.nNumVertex * mesh.sVertex.nStride;
  156.        
  157.         assert(mesh.pInterleaved);
  158.         assert(mesh.sFaces.pData);
  159.         NSLog(@"size %d, interleaved 0x%x", size, mesh.pInterleaved);
  160.        
  161.         //shove vertex data into a vertex buffer object
  162.         glBindBuffer(GL_ARRAY_BUFFER, vbo[i]);
  163.         glBufferData(GL_ARRAY_BUFFER, size, mesh.pInterleaved, GL_STATIC_DRAW);
  164.        
  165.         //shove index data into a vertex buffer object
  166.         indexvbo[i] = 0;
  167.         if(mesh.sFaces.pData)
  168.         {
  169.             glGenBuffers(1, &indexvbo[i]);
  170.             size = PVRTModelPODCountIndices(mesh) * sizeof(GLshort);
  171.             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexvbo[i]);
  172.             glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, mesh.sFaces.pData, GL_STATIC_DRAW);
  173.         }
  174.     }
  175.    
  176.     glBindBuffer(GL_ARRAY_BUFFER, 0);
  177.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  178. }
  179.  
  180. -(void)setupTexturesInScene:(CPVRTModelPOD*)scene withErrorString:(CPVRTString*)error
  181. {
  182.    
  183.     //load any textures for the scene's materials.
  184.     //Initializes an array to lookup the textures
  185.     //for each material in the scene.
  186.     texture = new GLuint[scene->nNumMaterial];
  187.    
  188.     for(unsigned int i=0;i<scene->nNumMaterial;i++)
  189.     {
  190.         texture[i] = 0;
  191.         SPODMaterial* mat = &scene->pMaterial[i];
  192.         if(mat->nIdxTexDiffuse != -1)
  193.         {
  194.             //load the texture file.
  195.             CPVRTString filenamePVR = scene->pTexture[mat->nIdxTexDiffuse].pszName;
  196.             //todo: global buffer of textures  Bad access error at this point.
  197.             printf("%s", filenamePVR.c_str());
  198.            
  199.             if(PVRTTextureLoadFromPVR(filenamePVR.c_str(), &texture[i], NULL, true, 0) != PVR_SUCCESS)
  200.             {
  201.                 //NSLog(@"texture load failed for file %s", filenamePVR.c_str());
  202.                
  203.                 //More detailed error handling
  204.                 *error = "ERROR: Failed to load " + filenamePVR + ".";
  205.                
  206.                 // Check to see if we're trying to load .pvr or not
  207.                 CPVRTString sFileExtension = PVRTStringGetFileExtension(filenamePVR);
  208.                
  209.                 if(sFileExtension.toLower() != "pvr")
  210.                     *error += "Note: IntroducingPOD can only load pvr files.";
  211.             }
  212.         }
  213.     }
  214. }
  215.  
  216.  
  217. #pragma mark -
  218. #pragma mark Setup and Initialization Methods
  219.  
  220.  
  221. - (void) load:(NSString*)filename
  222. {  
  223.     const char* cpath = [[NSString stringWithFormat:@"%@/", [[NSBundle mainBundle] resourcePath]] cStringUsingEncoding: NSASCIIStringEncoding];
  224.    
  225.     printf("cpath %s\n", cpath);
  226.    
  227.     model = CPVRTModelPOD(); //todo: dealloc, also check if already alloc'd
  228.    
  229.     //CPVRTModelPOD* scene = (CPVRTModelPOD*)model;
  230.    
  231.     CPVRTResourceFile::SetReadPath(cpath);
  232.    
  233.     if(model.ReadFromFile([filename cStringUsingEncoding:NSASCIIStringEncoding]) != PVR_SUCCESS)
  234.     {
  235.         NSLog(@"ERROR: Couldn't load %@.", filename);
  236.         delete &model;
  237.         //model = NULL;
  238.         return;
  239.     }
  240.     else
  241.     {
  242.         NSLog(@"Loading %@...", filename);
  243.        
  244.         CPVRTString errorStr;
  245.        
  246.         [self loadVbosInScene:&model];
  247.         [self setupTexturesInScene:&model withErrorString:&errorStr];
  248.     }
  249. }
  250.  
  251. + (Model*) modelFromFile:(NSString*) filename
  252. {
  253.     //Allocate memory for model
  254.     Model* retval = [[Model alloc] init];
  255.    
  256.     //Load file for model
  257.     [retval load:filename];
  258.    
  259.     [retval setupShaders];
  260.    
  261.     //Return a model after all that setup...finally!
  262.     return [retval autorelease];
  263. }
  264.  
  265.  
  266. #pragma mark -
  267. #pragma mark Graphics Methods
  268.  
  269. -(void)drawMeshWithNodeIndex:(int)i32NodeIndex withModelView:(PVRTMat4)view
  270. {
  271.     int i32MeshIndex = model.pNode[i32NodeIndex].nIdx;
  272.     SPODMesh* pMesh = &model.pMesh[i32MeshIndex];
  273.    
  274.     // bind the VBO for the mesh
  275.     glBindBuffer(GL_ARRAY_BUFFER, vbo[i32MeshIndex]);
  276.     // bind the index buffer, won't hurt if the handle is 0
  277.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexvbo[i32MeshIndex]);
  278.    
  279.     // Enable the vertex attribute arrays
  280.     glEnableVertexAttribArray(VERTEX_ARRAY);
  281.     glEnableVertexAttribArray(NORMAL_ARRAY);
  282.     glEnableVertexAttribArray(TEXCOORD_ARRAY);
  283.    
  284.     // Set the vertex attribute offsets
  285.     glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sVertex.nStride, pMesh->sVertex.pData);
  286.     glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sNormals.nStride, pMesh->sNormals.pData);
  287.     glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, pMesh->psUVW[0].nStride, pMesh->psUVW[0].pData);
  288.    
  289.     /*
  290.      The geometry can be exported in 4 ways:
  291.      - Indexed Triangle list
  292.      - Non-Indexed Triangle list
  293.      - Indexed Triangle strips
  294.      - Non-Indexed Triangle strips
  295.      */
  296.    
  297.     if(pMesh->nNumStrips == 0)
  298.     {
  299.         if(indexvbo[i32MeshIndex])
  300.         {
  301.             // Indexed Triangle list
  302.             glDrawElements(GL_TRIANGLES, pMesh->nNumFaces*3, GL_UNSIGNED_SHORT, 0);
  303.         }
  304.         else
  305.         {
  306.             // Non-Indexed Triangle list
  307.             glDrawArrays(GL_TRIANGLES, 0, pMesh->nNumFaces*3);
  308.         }
  309.     }
  310.     else
  311.     {
  312.         int offset = 0;
  313.        
  314.         for(int i = 0; i < (int)pMesh->nNumStrips; ++i)
  315.         {
  316.             if(indexvbo[i32MeshIndex])
  317.             {
  318.                 // Indexed Triangle strips
  319.                 glDrawElements(GL_TRIANGLE_STRIP, pMesh->pnStripLength[i]+2, GL_UNSIGNED_SHORT, &((GLshort*)0)[offset]);
  320.             }
  321.             else
  322.             {
  323.                 // Non-Indexed Triangle strips
  324.                 glDrawArrays(GL_TRIANGLE_STRIP, offset, pMesh->pnStripLength[i]+2);
  325.             }
  326.             offset += pMesh->pnStripLength[i]+2;
  327.         }
  328.     }
  329.    
  330.     // Safely disable the vertex attribute arrays
  331.     glDisableVertexAttribArray(VERTEX_ARRAY);
  332.     glDisableVertexAttribArray(NORMAL_ARRAY);
  333.     glDisableVertexAttribArray(TEXCOORD_ARRAY);
  334.    
  335.     glBindBuffer(GL_ARRAY_BUFFER, 0);
  336.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  337. }
  338.  
  339. -(void)draw
  340. {
  341.     //CPVRTModelPOD *scene = (CPVRTModelPOD*)model;
  342.    
  343.     // Clear the color and depth buffer
  344.     //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  345.    
  346.     // Use shader program
  347.     [defaultProgram use];
  348.    
  349.     /*
  350.      //Calculates the frame number to animate in a time-based manner.
  351.      //Uses the shell function PVRShellGetTime() to get the time in milliseconds.
  352.  
  353.     int iTime = PVRShell::PVRShellGetTime();
  354.     int iDeltaTime = iTime - m_iTimePrev;
  355.     m_iTimePrev = iTime;
  356.     m_fFrame += (float)iDeltaTime * g_fDemoFrameRate;
  357.     if (m_fFrame > scene->nNumFrame - 1)
  358.         m_fFrame = 0;
  359.     */
  360.    
  361.     /*
  362.     //Modifying the above code to use an NSTimer instead.
  363.     int iTime = PVRShell::PVRShellGetTime();
  364.     int iDeltaTime = iTime - m_iTimePrev;
  365.     m_iTimePrev = iTime;
  366.     m_fFrame += (float)iDeltaTime * g_fDemoFrameRate;
  367.     if (m_fFrame > scene->nNumFrame - 1)
  368.         m_fFrame = 0;
  369.    
  370.     // Sets the scene animation to this frame
  371.     scene->SetFrame(m_fFrame);
  372.     */
  373.  
  374.      //Get the direction of the first light from the scene.
  375.    
  376.     PVRTVec4 vLightDirection;
  377.     vLightDirection = model.GetLightDirection(0);
  378.     // For direction vectors, w should be 0
  379.     vLightDirection.w = 0.0f;
  380.    
  381.      //Set up the view and projection matrices from the camera
  382.    
  383.     PVRTMat4 mView, mProjection;
  384.     PVRTVec3    vFrom, vTo(0.0f), vUp(0.0f, 1.0f, 0.0f);
  385.     float fFOV;
  386.    
  387.     // Setup the camera, this code may be unnecessary
  388.  
  389.     // Camera nodes are after the mesh and light nodes in the array
  390.     int i32CamID = model.pNode[model.nNumMeshNode + model.nNumLight + g_ui32Camera].nIdx;
  391.    
  392.     printf("132CamID: %d", i32CamID);
  393.    
  394.     //printf("Camera Index Target: %d", (int)indexTarget);
  395.    
  396.     // Get the camera position, target and field of view (fov)
  397.     if(model.pCamera[i32CamID].nIdxTarget != -1) // Does the camera have a target?
  398.         fFOV = model.GetCameraPos( vFrom, vTo, g_ui32Camera); // vTo is taken from the target node
  399.     else
  400.         fFOV = model.GetCamera( vFrom, vTo, vUp, g_ui32Camera); // vTo is calculated from the rotation
  401.    
  402.     // We can build the model view matrix from the camera position, target and an up vector.
  403.     // For this we usePVRTMat4LookAtRH()
  404.     mView = mView.LookAtRH(vFrom, vTo, vUp);
  405.    
  406.     // Calculate the projection matrix
  407.    
  408.     //bool bRotate = PVRShell::PVRShellGet(prefIsRotated) && PVRShell::PVRShellGet(prefFullScreen);
  409.     float aspectRatio = [UIScreen mainScreen].bounds.size.width/[UIScreen mainScreen].bounds.size.height;
  410.     mProjection = mProjection.PerspectiveFovRH(fFOV, aspectRatio, g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, false);
  411.    
  412.    
  413.     /*
  414.      A scene is composed of nodes. There are 3 types of nodes:
  415.      - MeshNodes :
  416.      references a mesh in the pMesh[].
  417.      These nodes are at the beginning of the pNode[] array.
  418.      And there are nNumMeshNode number of them.
  419.      This way the .pod format can instantiate several times the same mesh
  420.      with different attributes.
  421.      - lights
  422.      - cameras
  423.      To draw a scene, you must go through all the MeshNodes and draw the referenced meshes.
  424.      */
  425.    
  426.     for (unsigned int i = 0; i < model.nNumMeshNode; ++i)
  427.     {
  428.         SPODNode& Node = model.pNode[i];
  429.        
  430.         // Get the node model matrix
  431.         PVRTMat4 mWorld;
  432.         mWorld = model.GetWorldMatrix(Node);
  433.        
  434.         // Pass the model-view-projection matrix (MVP) to the shader to transform the vertices
  435.         PVRTMat4 mModelView, mMVP;
  436.         mModelView = mView * mWorld;
  437.         mMVP = mProjection * mModelView;
  438.         glUniformMatrix4fv([defaultProgram uniformIndex:@"MVPMatrix"], 1, GL_FALSE, mMVP.f);
  439.        
  440.         // Pass the light direction in model space to the shader
  441.         PVRTVec4 vLightDir;
  442.         vLightDir = mWorld.inverse() * vLightDirection;
  443.        
  444.         PVRTVec3 vLightDirModel = *(PVRTVec3*)&vLightDir;
  445.         vLightDirModel.normalize();
  446.        
  447.         glUniform3fv([defaultProgram uniformIndex:@"LightDirection"], 1, &vLightDirModel.x);
  448.        
  449.         // Load the correct texture using our texture lookup table
  450.         GLuint uiTex = 0;
  451.        
  452.         if(Node.nIdxMaterial != -1)
  453.             uiTex = texture[Node.nIdxMaterial];
  454.        
  455.         glBindTexture(GL_TEXTURE_2D, uiTex);
  456.        
  457.         // Now that the model-view matrix is set and the materials ready,
  458.         //call another function to actually draw the mesh.
  459.        
  460.         [self drawMeshWithNodeIndex:1 withModelView:mModelView];
  461.     }
  462. }
  463.  
  464. #pragma mark Animation Methods
  465.  
  466.  
  467. - (void) setFrame:(float) frame
  468. {
  469.     model.SetFrame(frame);
  470. }
  471.  
  472. - (int) numFrames
  473. {
  474.     return model.nNumFrame;
  475. }
  476.  
  477. #pragma mark Skeleton Methods
  478.  
  479. -(PVRTMat4)boneWorldMatrixForNode:(SPODNode)nodeMesh withBone:(SPODNode)nodeBone
  480. {
  481.     return model.GetBoneWorldMatrix(nodeMesh, nodeBone);
  482. }
  483.  
  484. -(void)boneWorldMatrixWithOutput:(PVRTMATRIX)output ForNode:(SPODNode)nodeMesh withBone:(SPODNode)nodeBone
  485. {
  486.     model.GetBoneWorldMatrix(output, nodeMesh, nodeBone);
  487. }
  488.  
  489.  
  490. #pragma mark -
  491. #pragma mark Memory Managements
  492.  
  493.  
  494. - (void) dealloc
  495. {
  496.         //CPVRTModelPOD* scene = (CPVRTModelPOD*)model;
  497.         //todo: global buffer of textures
  498.         glDeleteTextures(model.nNumMaterial, texture);
  499.         glDeleteBuffers(model.nNumMesh, vbo);
  500.         glDeleteBuffers(model.nNumMesh, indexvbo); //note that not all the indexvbos will be non-zero, but glDeleteBuffers silently ignores those, per http://www.opengl.org/sdk/docs/man/xhtml/glDeleteBuffers.xml
  501.         delete vbo;
  502.         delete indexvbo;
  503.         delete texture;
  504.         model.Destroy();
  505.    
  506.     [defaultProgram release];
  507.     [skinnedVertexProgram release];
  508.     [lightProgram release];
  509.     [textureProgram release];
  510.     [super dealloc];
  511. }
  512.  
  513. @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement