From e60aac615a74721737679fbf663f18fb17ea38c5 Mon Sep 17 00:00:00 2001 From: kearwood Date: Thu, 15 Mar 2012 19:19:23 +0000 Subject: [PATCH] Refactored in preparation for FBX file format support --HG-- extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%409 --- KREngine/KREngine.xcodeproj/project.pbxproj | 6 + KREngine/KREngine/Classes/KRInstance.cpp | 3 +- KREngine/KREngine/Classes/KRMaterial.cpp | 9 +- KREngine/KREngine/Classes/KRMaterial.h | 5 +- .../KREngine/Classes/KRMaterialManager.cpp | 2 +- KREngine/KREngine/Classes/KRMesh.cpp | 163 +++++ KREngine/KREngine/Classes/KRMesh.h | 100 +++ KREngine/KREngine/Classes/KRModel.cpp | 573 +----------------- KREngine/KREngine/Classes/KRModel.h | 65 +- objview/Classes/KRObjViewGLView.mm | 3 +- 10 files changed, 302 insertions(+), 627 deletions(-) create mode 100644 KREngine/KREngine/Classes/KRMesh.cpp create mode 100644 KREngine/KREngine/Classes/KRMesh.h diff --git a/KREngine/KREngine.xcodeproj/project.pbxproj b/KREngine/KREngine.xcodeproj/project.pbxproj index ab28fdf..722c258 100644 --- a/KREngine/KREngine.xcodeproj/project.pbxproj +++ b/KREngine/KREngine.xcodeproj/project.pbxproj @@ -39,6 +39,7 @@ E491019D13C99BDC0098455B /* KRTextureManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E491018513C99BDC0098455B /* KRTextureManager.h */; settings = {ATTRIBUTES = (Private, ); }; }; E491019E13C99BDC0098455B /* KRTexture.h in Headers */ = {isa = PBXBuildFile; fileRef = E491018613C99BDC0098455B /* KRTexture.h */; settings = {ATTRIBUTES = (Private, ); }; }; E49101A013C99BF50098455B /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E491019F13C99BF50098455B /* OpenGLES.framework */; }; + E49E79FF1512615F009CF99C /* KRMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E49E79FE1512615F009CF99C /* KRMesh.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ @@ -94,6 +95,8 @@ E491018513C99BDC0098455B /* KRTextureManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KRTextureManager.h; path = Classes/KRTextureManager.h; sourceTree = ""; }; E491018613C99BDC0098455B /* KRTexture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KRTexture.h; path = Classes/KRTexture.h; sourceTree = ""; }; E491019F13C99BF50098455B /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; + E49E79FC15126146009CF99C /* KRMesh.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = KRMesh.h; path = Classes/KRMesh.h; sourceTree = ""; }; + E49E79FE1512615F009CF99C /* KRMesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KRMesh.cpp; path = Classes/KRMesh.cpp; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -199,6 +202,8 @@ E414BAEC14355EFF00A668C4 /* KRBoundingVolume.cpp */, E48B3CBC14393DF5000C50E2 /* KRCamera.h */, E48B3CBF14393E2F000C50E2 /* KRCamera.cpp */, + E49E79FC15126146009CF99C /* KRMesh.h */, + E49E79FE1512615F009CF99C /* KRMesh.cpp */, ); name = Classes; sourceTree = ""; @@ -294,6 +299,7 @@ E414BAE91435585A00A668C4 /* KRScene.cpp in Sources */, E414BAED14355EFF00A668C4 /* KRBoundingVolume.cpp in Sources */, E48B3CC014393E30000C50E2 /* KRCamera.cpp in Sources */, + E49E79FF1512615F009CF99C /* KRMesh.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/KREngine/KREngine/Classes/KRInstance.cpp b/KREngine/KREngine/Classes/KRInstance.cpp index eeb03a3..e313910 100644 --- a/KREngine/KREngine/Classes/KRInstance.cpp +++ b/KREngine/KREngine/Classes/KRInstance.cpp @@ -67,5 +67,6 @@ void KRInstance::render(KRCamera *pCamera, KRMaterialManager *pMaterialManager, } KRBoundingVolume KRInstance::getExtents() { - return KRBoundingVolume(Vector3(m_pModel->getMinX(), m_pModel->getMinY(), m_pModel->getMinZ()), Vector3(m_pModel->getMaxX(), m_pModel->getMaxY(), m_pModel->getMaxZ()), m_modelMatrix); + KRMesh *pMesh = m_pModel->getMesh(); + return KRBoundingVolume(Vector3(pMesh->getMinX(), pMesh->getMinY(), pMesh->getMinZ()), Vector3(pMesh->getMaxX(), pMesh->getMaxY(), pMesh->getMaxZ()), m_modelMatrix); } \ No newline at end of file diff --git a/KREngine/KREngine/Classes/KRMaterial.cpp b/KREngine/KREngine/Classes/KRMaterial.cpp index 359800e..d54b359 100644 --- a/KREngine/KREngine/Classes/KRMaterial.cpp +++ b/KREngine/KREngine/Classes/KRMaterial.cpp @@ -31,7 +31,8 @@ #include "KRMaterial.h" -KRMaterial::KRMaterial(KRShaderManager *pShaderManager) { +KRMaterial::KRMaterial(char *szName, KRShaderManager *pShaderManager) { + strcpy(m_szName, szName); m_pAmbientMap = NULL; m_pDiffuseMap = NULL; m_pSpecularMap = NULL; @@ -164,4 +165,8 @@ void KRMaterial::bind(KRCamera *pCamera, KRMat4 &mvpMatrix, Vector3 &cameraPosit glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } -} \ No newline at end of file +} + +char *KRMaterial::getName() { + return m_szName; +} diff --git a/KREngine/KREngine/Classes/KRMaterial.h b/KREngine/KREngine/Classes/KRMaterial.h index 7ca01ab..c8cfb94 100644 --- a/KREngine/KREngine/Classes/KRMaterial.h +++ b/KREngine/KREngine/Classes/KRMaterial.h @@ -47,7 +47,7 @@ using std::list; class KRMaterial { public: - KRMaterial(KRShaderManager *pShaderManager); + KRMaterial(char *szName, KRShaderManager *pShaderManager); ~KRMaterial(); void setAmbientMap(KRTexture *pTexture); @@ -62,8 +62,11 @@ public: void bind(KRCamera *pCamera, KRMat4 &mvpMatrix, Vector3 &cameraPosition, Vector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers); bool isTransparent(); + char *getName(); private: + char m_szName[64]; + KRTexture *m_pAmbientMap; // mtl map_Ka value KRTexture *m_pDiffuseMap; // mtl map_Kd value KRTexture *m_pSpecularMap; // mtl map_Ks value diff --git a/KREngine/KREngine/Classes/KRMaterialManager.cpp b/KREngine/KREngine/Classes/KRMaterialManager.cpp index d7302e2..0c1aa9b 100644 --- a/KREngine/KREngine/Classes/KRMaterialManager.cpp +++ b/KREngine/KREngine/Classes/KRMaterialManager.cpp @@ -110,7 +110,7 @@ bool KRMaterialManager::loadFile(const char *szPath) { if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) { - pMaterial = new KRMaterial(m_pShaderManager); + pMaterial = new KRMaterial(szSymbol[1], m_pShaderManager); m_materials[szSymbol[1]] = pMaterial; } if(pMaterial != NULL) { if(strcmp(szSymbol[0], "Ka") == 0) { diff --git a/KREngine/KREngine/Classes/KRMesh.cpp b/KREngine/KREngine/Classes/KRMesh.cpp new file mode 100644 index 0000000..843472d --- /dev/null +++ b/KREngine/KREngine/Classes/KRMesh.cpp @@ -0,0 +1,163 @@ +// +// KRMesh.cpp +// KREngine +// +// Created by Kearwood Gilbert on 12-03-15. +// Copyright (c) 2012 Kearwood Software. All rights reserved. +// + +#include "KRMesh.h" +#import "KRShader.h" +#import +#include +#include +#include +#include +#include +#include +#include + +KRMesh::KRMesh() { + m_fdPackFile = 0; + m_pPackData = NULL; + m_iPackFileSize = 0; + m_cBuffers = 0; + m_pBuffers = NULL; +} + +KRMesh::~KRMesh() { + if(m_fdPackFile) { + if(m_pPackData != NULL) { + munmap(m_pPackData, m_iPackFileSize); + m_pPackData = NULL; + } + close(m_fdPackFile); + } else { + // If we didn't load a packed file, then the data was calculated at run time and malloc'ed + if(m_pPackData != NULL) { + free(m_pPackData); + m_pPackData = NULL; + } + } + + if(m_pBuffers != NULL) { + glDeleteBuffers(m_cBuffers, m_pBuffers); + delete m_pBuffers; + m_pBuffers = NULL; + } +} + +void KRMesh::loadPack(std::string path) { + struct stat statbuf; + m_fdPackFile = open(path.c_str(), O_RDONLY); + if(m_fdPackFile >= 0) { + if(fstat(m_fdPackFile, &statbuf) >= 0) { + if ((m_pPackData = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, m_fdPackFile, 0)) == (caddr_t) -1) { + } else { + m_iPackFileSize = statbuf.st_size; + + + pack_header *pHeader = (pack_header *)m_pPackData; + + m_minx = pHeader->minx; + m_miny = pHeader->miny; + m_minz = pHeader->minz; + m_maxx = pHeader->maxx; + m_maxy = pHeader->maxy; + m_maxz = pHeader->maxz; + + pack_material *pPackMaterials = (pack_material *)(pHeader+1); + + for(int iMaterial=0; iMaterial < pHeader->submesh_count; iMaterial++) { + pack_material *pPackMaterial = pPackMaterials + iMaterial; + + Submesh *pSubmesh = new Submesh(); + pSubmesh->start_vertex = pPackMaterial->start_vertex; + pSubmesh->vertex_count = pPackMaterial->vertex_count; + strcpy(pSubmesh->szMaterialName, pPackMaterial->szName); + m_submeshes.push_back(pSubmesh); + } + + m_pVertexData = (VertexData *)(pPackMaterials + pHeader->submesh_count); + + + m_cBuffers = (pHeader->vertex_count + MAX_VBO_SIZE - 1) / MAX_VBO_SIZE; + m_pBuffers = new GLuint[m_cBuffers]; + glGenBuffers(m_cBuffers, m_pBuffers); + for(GLsizei iBuffer=0; iBuffer < m_cBuffers; iBuffer++) { + GLsizei cVertexes = iBuffer < m_cBuffers - 1 ? MAX_VBO_SIZE : pHeader->vertex_count % MAX_VBO_SIZE; + glBindBuffer(GL_ARRAY_BUFFER, m_pBuffers[iBuffer]); + glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData) * cVertexes, m_pVertexData + iBuffer * MAX_VBO_SIZE, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + } + } + } + } +} + +GLfloat KRMesh::getMaxDimension() { + GLfloat m = 0.0; + if(m_maxx - m_minx > m) m = m_maxx - m_minx; + if(m_maxy - m_miny > m) m = m_maxy - m_miny; + if(m_maxz - m_minz > m) m = m_maxz - m_minz; + return m; +} + +GLfloat KRMesh::getMinX() { + return m_minx; +} +GLfloat KRMesh::getMaxX() { + return m_maxx; +} +GLfloat KRMesh::getMinY() { + return m_miny; +} +GLfloat KRMesh::getMaxY() { + return m_maxy; +} +GLfloat KRMesh::getMinZ() { + return m_minz; +} +GLfloat KRMesh::getMaxZ() { + return m_maxz; +} + +vector KRMesh::getSubmeshes() { + return m_submeshes; +} + +void KRMesh::renderSubmesh(int iSubmesh) { + Submesh *pSubmesh = m_submeshes[iSubmesh]; + + + int iVertex = pSubmesh->start_vertex; + int iBuffer = iVertex / MAX_VBO_SIZE; + iVertex = iVertex % MAX_VBO_SIZE; + int cVertexes = pSubmesh->vertex_count; + while(cVertexes > 0) { + glBindBuffer(GL_ARRAY_BUFFER, m_pBuffers[iBuffer]); + + glVertexAttribPointer(KRShader::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, sizeof(VertexData), BUFFER_OFFSET(0)); + glEnableVertexAttribArray(KRShader::KRENGINE_ATTRIB_VERTEX); + + glVertexAttribPointer(KRShader::KRENGINE_ATTRIB_NORMAL, 3, GL_FLOAT, 0, sizeof(VertexData), BUFFER_OFFSET(sizeof(Vertex3D))); + glEnableVertexAttribArray(KRShader::KRENGINE_ATTRIB_NORMAL); + + glVertexAttribPointer(KRShader::KRENGINE_ATTRIB_TANGENT, 3, GL_FLOAT, 0, sizeof(VertexData), BUFFER_OFFSET(sizeof(Vertex3D) + sizeof(Vector3D))); + glEnableVertexAttribArray(KRShader::KRENGINE_ATTRIB_TANGENT); + + glVertexAttribPointer(KRShader::KRENGINE_ATTRIB_TEXUV, 2, GL_FLOAT, 0, sizeof(VertexData), BUFFER_OFFSET(sizeof(Vertex3D) + sizeof(Vector3D) * 2)); + glEnableVertexAttribArray(KRShader::KRENGINE_ATTRIB_TEXUV); + + if(iVertex + cVertexes >= MAX_VBO_SIZE) { + glDrawArrays(GL_TRIANGLES, iVertex, (MAX_VBO_SIZE - iVertex)); + cVertexes -= (MAX_VBO_SIZE - iVertex); + iVertex = 0; + iBuffer++; + } else { + glDrawArrays(GL_TRIANGLES, iVertex, cVertexes); + cVertexes = 0; + } + } +} diff --git a/KREngine/KREngine/Classes/KRMesh.h b/KREngine/KREngine/Classes/KRMesh.h new file mode 100644 index 0000000..882de70 --- /dev/null +++ b/KREngine/KREngine/Classes/KRMesh.h @@ -0,0 +1,100 @@ +// +// KRMesh.h +// KREngine +// +// Created by Kearwood Gilbert on 12-03-15. +// Copyright (c) 2012 Kearwood Software. All rights reserved. +// + +#import +#import +#import +#import +#import + +#define MAX_VBO_SIZE 65535 +// MAX_VBO_SIZE must be divisible by 3 so triangles aren't split across VBO objects... + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#ifndef KREngine_KRMesh_h +#define KREngine_KRMesh_h + + + +using std::vector; + +class KRMesh { +public: + KRMesh(); + ~KRMesh(); + + void loadPack(std::string path); + void renderSubmesh(int iSubmesh); + + GLfloat getMaxDimension(); + GLfloat getMinX(); + GLfloat getMaxX(); + GLfloat getMinY(); + GLfloat getMaxY(); + GLfloat getMinZ(); + GLfloat getMaxZ(); + + typedef struct { + GLint start_vertex; + GLsizei vertex_count; + char szMaterialName[64]; + } Submesh; + + vector getSubmeshes(); + +protected: + GLfloat m_minx, m_miny, m_minz, m_maxx, m_maxy, m_maxz; + + int m_fdPackFile; + void *m_pPackData; + int m_iPackFileSize; + + typedef struct { + char szTag[16]; + float minx, miny, minz, maxx, maxy, maxz; + int32_t vertex_count; + int32_t submesh_count; + } pack_header; + + typedef struct { + int32_t start_vertex; + int32_t vertex_count; + char szName[64]; + } pack_material; + + typedef struct { + GLfloat x; + GLfloat y; + GLfloat z; + } Vertex3D, Vector3D; + + typedef struct { + GLfloat u; + GLfloat v; + } TexCoord; + + typedef struct { + Vertex3D vertex; + Vector3D normal; + Vector3D tangent; + TexCoord texcoord; + } VertexData; + + VertexData *m_pVertexData; + + + + GLsizei m_cBuffers; + GLuint *m_pBuffers; + + vector m_submeshes; +}; + + +#endif diff --git a/KREngine/KREngine/Classes/KRModel.cpp b/KREngine/KREngine/Classes/KRModel.cpp index 89969e0..c9d5269 100644 --- a/KREngine/KREngine/Classes/KRModel.cpp +++ b/KREngine/KREngine/Classes/KRModel.cpp @@ -44,523 +44,29 @@ #include "KRVector3.h" #import "KRShader.h" -#define MAX_VBO_SIZE 65535 -// MAX_VBO_SIZE must be divisible by 3 so triangles aren't split across VBO objects... - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) KRModel::KRModel(std::string path, KRMaterialManager *pMaterialManager) { - - m_fdPackFile = 0; - m_pPackFile = NULL; - m_iPackFileSize = 0; - m_cBuffers = 0; - m_pBuffers = NULL; - - // loadWavefront(path, pMaterialManager); loadPack(path, pMaterialManager); } -void KRModel::loadPack(std::string path, KRMaterialManager *pMaterialManager) { - struct stat statbuf; - m_fdPackFile = open(path.c_str(), O_RDONLY); - if(m_fdPackFile >= 0) { - if(fstat(m_fdPackFile, &statbuf) >= 0) { - if ((m_pPackFile = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, m_fdPackFile, 0)) == (caddr_t) -1) { - } else { - m_iPackFileSize = statbuf.st_size; - - - pack_header *pHeader = (pack_header *)m_pPackFile; - - m_minx = pHeader->minx; - m_miny = pHeader->miny; - m_minz = pHeader->minz; - m_maxx = pHeader->maxx; - m_maxy = pHeader->maxy; - m_maxz = pHeader->maxz; - - pack_material *pPackMaterials = (pack_material *)(pHeader+1); - - for(int iMaterial=0; iMaterial < pHeader->material_count; iMaterial++) { - pack_material *pPackMaterial = pPackMaterials + iMaterial; - - Material *pMaterial = new Material(); - pMaterial->start_vertex = pPackMaterial->start_vertex; - pMaterial->vertex_count = pPackMaterial->vertex_count; - pMaterial->pMaterial = pMaterialManager->getMaterial(pPackMaterial->szName); - m_materials.push_back(pMaterial); - } - - m_pVertexData = (VertexData *)(pPackMaterials + pHeader->material_count); - - - m_cBuffers = (pHeader->vertex_count + MAX_VBO_SIZE - 1) / MAX_VBO_SIZE; - m_pBuffers = new GLuint[m_cBuffers]; - glGenBuffers(m_cBuffers, m_pBuffers); - for(GLsizei iBuffer=0; iBuffer < m_cBuffers; iBuffer++) { - GLsizei cVertexes = iBuffer < m_cBuffers - 1 ? MAX_VBO_SIZE : pHeader->vertex_count % MAX_VBO_SIZE; - glBindBuffer(GL_ARRAY_BUFFER, m_pBuffers[iBuffer]); - glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData) * cVertexes, m_pVertexData + iBuffer * MAX_VBO_SIZE, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - } - } - } - } -} - -void KRModel::loadWavefront(std::string path, KRMaterialManager *pMaterialManager) { - const char *szPath = path.c_str(); +void KRModel::loadPack(std::string path, KRMaterialManager *pMaterialManager) { + m_mesh.loadPack(path); - int fdFile = 0; - int fileSize = 0; - void *pFile = NULL; - char szSymbol[16][64]; + vector submeshes = m_mesh.getSubmeshes(); - std::vector materials; - - - Vertex3D *pVertices = NULL; - Vector3D *pNormals = NULL; - TexCoord *pTexCoords = NULL; - int *pFaces = NULL; - - struct stat statbuf; - fdFile = open(szPath, O_RDONLY); - if(fdFile >= 0) { - if(fstat(fdFile, &statbuf) >= 0) { - if ((pFile = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, fdFile, 0)) == (caddr_t) -1) { - } else { - fileSize = statbuf.st_size; - - - - // Pass 1 - Get counts - - int cVertices = 0; - int cNormals = 0; - int cTexCoords = 0; - int cVertexData = 0; - - - cVertices = 0; - int cFaces = 1; - GLint cMaterialFaceStart = 1; - - - - // --------- - - - char *pScan = (char *)pFile; - char *pEnd = (char *)pFile + fileSize; - while(pScan < pEnd) { - - // Scan through whitespace - while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) { - pScan++; - } - - if(*pScan == '#') { - // Line is a comment line - - // Scan to the end of the line - while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') { - pScan++; - } - } else { - int cSymbols = 0; - while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') { - - char *pDest = szSymbol[cSymbols++]; - while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') { - *pDest++ = *pScan++; - } - *pDest = '\0'; - - // Scan through whitespace, but don't advance to next line - while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) { - pScan++; - } - } - - if(strcmp(szSymbol[0], "v") == 0) { - // Vertex (v) - cVertices++; - } else if(strcmp(szSymbol[0], "vt") == 0) { - // Vertex Texture UV Coordinate (vt) - cTexCoords++; - } else if(strcmp(szSymbol[0], "vn") == 0) { - // Vertex Normal (vn) - cNormals++; - } else if(strcmp(szSymbol[0], "f") == 0) { - // Face (f) - int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles. - cVertexData += cFaceVertexes; - cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index - - } else if(strcmp(szSymbol[0], "usemtl") == 0) { - // Use Material (usemtl) - if(cMaterialFaceStart - cFaces > 0) { - cFaces++; - - } - materials.push_back(pMaterialManager->getMaterial(szSymbol[1])); - } - - } - } - - - // Pass 2 - Populate vertexes and faces - Vertex3D *pVertices = (Vertex3D *)malloc(sizeof(Vertex3D) * cVertices); - Vector3D *pNormals = (Vector3D *)malloc(sizeof(Vector3D) *cNormals); - TexCoord *pTexCoords = (TexCoord *)malloc(sizeof(TexCoord) * cTexCoords); - int *pFaces = (int *)malloc(sizeof(int *) * (cFaces + 1)); - - - Vertex3D *pVertice = pVertices; - Vector3D *pNormal = pNormals; - TexCoord *pTexCoord = pTexCoords; - int *pFace = pFaces; - int *pMaterialFaces = pFace++; - *pMaterialFaces = 0; - - - std::vector::iterator material_itr = materials.begin(); - - // -------- - - pScan = (char *)pFile; - while(pScan < pEnd) { - - // Scan through whitespace - while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) { - pScan++; - } - - if(*pScan == '#') { - // Line is a comment line - - // Scan to the end of the line - while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') { - pScan++; - } - } else { - int cSymbols = 0; - while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') { - - char *pDest = szSymbol[cSymbols++]; - while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') { - *pDest++ = *pScan++; - } - *pDest = '\0'; - - // Scan through whitespace, but don't advance to next line - while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) { - pScan++; - } - } - - if(strcmp(szSymbol[0], "v") == 0) { - // Vertex (v) - char *pChar = szSymbol[1]; - pVertice -> x = strtof(pChar, &pChar); - pChar = szSymbol[2]; - pVertice -> y = strtof(pChar, &pChar); - pChar = szSymbol[3]; - pVertice -> z = strtof(pChar, &pChar); - pVertice++; - } else if(strcmp(szSymbol[0], "vt") == 0) { - // Vertex Texture UV Coordinate (vt) - char *pChar = szSymbol[1]; - pTexCoord -> u = strtof(pChar, &pChar); - pChar = szSymbol[2]; - pTexCoord -> v = strtof(pChar, &pChar); - pTexCoord++; - } else if(strcmp(szSymbol[0], "vn") == 0) { - // Vertex Normal (vn) - char *pChar = szSymbol[1]; - pNormal -> x = strtof(pChar, &pChar); - pChar = szSymbol[2]; - pNormal -> y = strtof(pChar, &pChar); - pChar = szSymbol[3]; - pNormal -> z = strtof(pChar, &pChar); - pNormal++; - } else if(strcmp(szSymbol[0], "f") == 0) { - // Face (f) - GLint cFaceVertices = cSymbols - 1; - - *pFace++ = cFaceVertices; - for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) { - char *pChar = szSymbol[iSymbol]; - if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) { - *pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index - - if(*pChar == '/') { - pChar++; - if(*pChar == '/') { - *pFace++ = -1; - } else { - *pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index - } - } else { - *pFace++ = -1; - } - - if(*pChar == '/') { - pChar++; - if(*pChar == '/') { - *pFace++ = -1; - } else { - *pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index - } - } else { - *pFace++ = -1; - } - while(*pChar == '/') { - pChar++; - strtol(pChar, &pChar, 10); - } - } - } - - - } else if(strcmp(szSymbol[0], "usemtl") == 0) { - // Use Material (usemtl) - if(pFace - pMaterialFaces > 1) { - *pMaterialFaces = pFace - pMaterialFaces - 1; - pMaterialFaces = pFace++; - } - } - } - } - - - *pMaterialFaces = pFace - pMaterialFaces - 1; - *pFace++ = 0; - - - m_pVertexData = (VertexData *)malloc(sizeof(VertexData) * cVertexData); - - VertexData *pData = m_pVertexData; - - int iVertex = 0; - Material *pMaterial = new Material(); - pMaterial->start_vertex = iVertex; - pMaterial->vertex_count = 0; - if(material_itr < materials.end()) { - pMaterial->pMaterial = *material_itr++; - } else { - pMaterial->pMaterial = NULL; - } - m_materials.push_back(pMaterial); - - - pFace = pFaces; - while(*pFace != 0 && iVertex < cVertexData) { - pMaterial->start_vertex = iVertex; - - int *pMaterialEndFace = pFace + *pFace++; - while(pFace < pMaterialEndFace) { - int cFaceVertexes = *pFace; - VertexData *pFirstFaceVertex = NULL; - VertexData *pPrevFaceVertex = NULL; - for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) { - if(iFaceVertex > 2) { - // There have already been 3 vertices. Now we need to split the quad into a second triangle composed of the 1st, 3rd, and 4th vertices - memcpy(pData++, pFirstFaceVertex, sizeof(VertexData)); - memcpy(pData++, pPrevFaceVertex, sizeof(VertexData)); - iVertex+=2; - } - Vertex3D *pVertex = pVertices + pFace[iFaceVertex*3+1]; - if(iFaceVertex==0) { - pFirstFaceVertex = pData; - } - pPrevFaceVertex = pData; - pData->vertex.x = pVertex -> x; - pData->vertex.y = pVertex -> y; - pData->vertex.z = pVertex -> z; - - if(pFace[iFaceVertex*3+2] >= 0) { - TexCoord *pTexCoord = pTexCoords + pFace[iFaceVertex*3+2]; - pData->texcoord.u = pTexCoord -> u; - pData->texcoord.v = pTexCoord -> v; - } else { - pData->texcoord.u = 0; - pData->texcoord.v = 0; - } - - if(pFace[iFaceVertex*3+3] >= 0){ - Vector3D *pNormal = pNormals + pFace[iFaceVertex*3+3]; - pData->normal.x = pNormal -> x; - pData->normal.y = pNormal -> y; - pData->normal.z = pNormal -> z; - } else { - pData->normal.x = 0; - pData->normal.y = 0; - pData->normal.z = 0; - } - - pData++; - iVertex++; - } - pFace += cFaceVertexes * 3 + 1; - } - pMaterial->vertex_count = iVertex - pMaterial->start_vertex; - if(*pFace != 0) { - pMaterial = new Material(); - pMaterial->start_vertex = iVertex; - pMaterial->vertex_count = 0; - if(material_itr < materials.end()) { - pMaterial->pMaterial = *material_itr++; - } else { - pMaterial->pMaterial = NULL; - } - m_materials.push_back(pMaterial); - } - } - } - } - } - - - m_minx = 0.0; - m_miny = 0.0; - m_minz = 0.0; - m_maxx = 0.0; - m_maxy = 0.0; - m_maxz = 0.0; - - - - // Calculate surface normals and tangents - - for(std::vector::iterator itr = m_materials.begin(); itr != m_materials.end(); itr++) { - VertexData *pStart = m_pVertexData + (*itr)->start_vertex; - VertexData *pEnd = pStart + (*itr)->vertex_count; - for(VertexData *pVertex = pStart; pVertex < pEnd; pVertex+=3) { - if(pVertex->vertex.x < m_minx) m_minx = pVertex->vertex.x; - if(pVertex->vertex.x > m_maxx) m_maxx = pVertex->vertex.x; - if(pVertex->vertex.y < m_miny) m_miny = pVertex->vertex.y; - if(pVertex->vertex.y > m_maxy) m_maxy = pVertex->vertex.y; - if(pVertex->vertex.z < m_minz) m_minz = pVertex->vertex.z; - if(pVertex->vertex.z > m_maxz) m_maxz = pVertex->vertex.z; - } - - - for(VertexData *pVertex = pStart; pVertex < pEnd; pVertex+=3) { - Vector3 p1(pVertex[0].vertex.x, pVertex[0].vertex.y, pVertex[0].vertex.z); - Vector3 p2(pVertex[1].vertex.x, pVertex[1].vertex.y, pVertex[1].vertex.z); - Vector3 p3(pVertex[2].vertex.x, pVertex[2].vertex.y, pVertex[2].vertex.z); - Vector3 v1 = p2 - p1; - Vector3 v2 = p3 - p1; - - // -- Calculate normal -- - if(pVertex->normal.x == 0 && pVertex->normal.y == 0 && pVertex->normal.z == 0) { - - - Vector3 normal = v1.cross( v2 ); - - normal.normalize(); - - pVertex[0].normal.x = normal.x; - pVertex[0].normal.y = normal.y; - pVertex[0].normal.z = normal.z; - - pVertex[1].normal.x = normal.x; - pVertex[1].normal.y = normal.y; - pVertex[1].normal.z = normal.z; - - pVertex[2].normal.x = normal.x; - pVertex[2].normal.y = normal.y; - pVertex[2].normal.z = normal.z; - } - - // -- Calculate tangent -- - TexCoord st1; // = pVertex[2].texcoord; - TexCoord st2; // = pVertex[1].texcoord; - st1.u = pVertex[1].texcoord.u - pVertex[0].texcoord.u; - st1.v = pVertex[1].texcoord.v - pVertex[0].texcoord.v; - st2.u = pVertex[2].texcoord.u - pVertex[0].texcoord.u; - st2.v = pVertex[2].texcoord.v - pVertex[0].texcoord.v; - double coef = 1/ (st1.u * st2.v - st2.u * st1.v); - - pVertex[0].tangent.x = coef * ((v1.x * st2.v) + (v2.x * -st1.v)); - pVertex[0].tangent.y = coef * ((v1.y * st2.v) + (v2.y * -st1.v)); - pVertex[0].tangent.z = coef * ((v1.z * st2.v) + (v2.z * -st1.v)); - - Vector3 tangent( - coef * ((v1.x * st2.v) + (v2.x * -st1.v)), - coef * ((v1.y * st2.v) + (v2.y * -st1.v)), - coef * ((v1.z * st2.v) + (v2.z * -st1.v)) - ); - - tangent.normalize(); - - pVertex[0].tangent.x = tangent.x; - pVertex[0].tangent.y = tangent.y; - pVertex[0].tangent.z = tangent.z; - pVertex[1].tangent.x = tangent.x; - pVertex[1].tangent.y = tangent.y; - pVertex[1].tangent.z = tangent.z; - pVertex[2].tangent.x = tangent.x; - pVertex[2].tangent.y = tangent.y; - pVertex[2].tangent.z = tangent.z; - - - } - - } - - - if(pFile != NULL) { - munmap(pFile, fileSize); - } - - if(fdFile != 0) { - close(fdFile); - } - - if(pVertices) { - free(pVertices); - } - if(pNormals) { - free(pNormals); - } - if(pTexCoords) { - free(pTexCoords); - } - if(pFaces) { - free(pFaces); + for(std::vector::iterator itr = submeshes.begin(); itr != submeshes.end(); itr++) { + m_materials.push_back(pMaterialManager->getMaterial((*itr)->szMaterialName)); } } KRModel::~KRModel() { - - if(m_pPackFile != NULL) { - munmap(m_pPackFile, m_iPackFileSize); - } - if(m_fdPackFile) { - close(m_fdPackFile); - } else { - // If we didn't load a packed file, then the data was calculated at run time and malloc'ed - if(m_pVertexData != NULL) { - free(m_pVertexData); - } - } - - if(m_pBuffers != NULL) { - glDeleteBuffers(m_cBuffers, m_pBuffers); - delete m_pBuffers; - } + } void KRModel::render(KRCamera *pCamera, KRMaterialManager *pMaterialManager, bool bRenderShadowMap, KRMat4 &mvpMatrix, Vector3 &cameraPosition, Vector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers) { - for(std::vector::iterator itr = m_materials.begin(); itr != m_materials.end(); itr++) { - - KRMaterial *pMaterial = (*itr)->pMaterial; + int cSubmeshes = m_mesh.getSubmeshes().size(); + for(int iSubmesh=0; iSubmeshisTransparent()) { // Exclude transparent and semi-transparent meshes from shadow maps - - int iVertex = (*itr)->start_vertex; - int iBuffer = iVertex / MAX_VBO_SIZE; - iVertex = iVertex % MAX_VBO_SIZE; - int cVertexes = (*itr)->vertex_count; - while(cVertexes > 0) { - glBindBuffer(GL_ARRAY_BUFFER, m_pBuffers[iBuffer]); - - glVertexAttribPointer(KRShader::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, sizeof(VertexData), BUFFER_OFFSET(0)); - glEnableVertexAttribArray(KRShader::KRENGINE_ATTRIB_VERTEX); - - glVertexAttribPointer(KRShader::KRENGINE_ATTRIB_NORMAL, 3, GL_FLOAT, 0, sizeof(VertexData), BUFFER_OFFSET(sizeof(Vertex3D))); - glEnableVertexAttribArray(KRShader::KRENGINE_ATTRIB_NORMAL); - - glVertexAttribPointer(KRShader::KRENGINE_ATTRIB_TANGENT, 3, GL_FLOAT, 0, sizeof(VertexData), BUFFER_OFFSET(sizeof(Vertex3D) + sizeof(Vector3D))); - glEnableVertexAttribArray(KRShader::KRENGINE_ATTRIB_TANGENT); - - glVertexAttribPointer(KRShader::KRENGINE_ATTRIB_TEXUV, 2, GL_FLOAT, 0, sizeof(VertexData), BUFFER_OFFSET(sizeof(Vertex3D) + sizeof(Vector3D) * 2)); - glEnableVertexAttribArray(KRShader::KRENGINE_ATTRIB_TEXUV); - - if(iVertex + cVertexes >= MAX_VBO_SIZE) { - glDrawArrays(GL_TRIANGLES, iVertex, (MAX_VBO_SIZE - iVertex)); - cVertexes -= (MAX_VBO_SIZE - iVertex); - iVertex = 0; - iBuffer++; - } else { - glDrawArrays(GL_TRIANGLES, iVertex, cVertexes); - cVertexes = 0; - } - } + m_mesh.renderSubmesh(iSubmesh); } } glBindBuffer(GL_ARRAY_BUFFER, 0); - } - } - -GLfloat KRModel::getMaxDimension() { - GLfloat m = 0.0; - if(m_maxx - m_minx > m) m = m_maxx - m_minx; - if(m_maxy - m_miny > m) m = m_maxy - m_miny; - if(m_maxz - m_minz > m) m = m_maxz - m_minz; - return m; -} - -GLfloat KRModel::getMinX() { - return m_minx; -} -GLfloat KRModel::getMaxX() { - return m_maxx; -} -GLfloat KRModel::getMinY() { - return m_miny; -} -GLfloat KRModel::getMaxY() { - return m_maxy; -} -GLfloat KRModel::getMinZ() { - return m_minz; -} -GLfloat KRModel::getMaxZ() { - return m_maxz; +KRMesh *KRModel::getMesh() { + return &m_mesh; } diff --git a/KREngine/KREngine/Classes/KRModel.h b/KREngine/KREngine/Classes/KRModel.h index e5d2935..da4ab00 100644 --- a/KREngine/KREngine/Classes/KRModel.h +++ b/KREngine/KREngine/Classes/KRModel.h @@ -34,6 +34,7 @@ #import #import #import +#import "KRMesh.h" using std::vector; @@ -43,7 +44,6 @@ using std::vector; #import "KRMaterialManager.h" #import "KRCamera.h" - class KRModel { public: @@ -51,69 +51,14 @@ public: ~KRModel(); void render(KRCamera *pCamera, KRMaterialManager *pMaterialManager, bool bRenderShadowMap, KRMat4 &mvpMatrix, Vector3 &cameraPosition, Vector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers); + + KRMesh *getMesh(); - GLfloat getMaxDimension(); - GLfloat getMinX(); - GLfloat getMaxX(); - GLfloat getMinY(); - GLfloat getMaxY(); - GLfloat getMinZ(); - GLfloat getMaxZ(); - private: - - void loadWavefront(std::string path, KRMaterialManager *pMaterialManager); void loadPack(std::string path, KRMaterialManager *pMaterialManager); - int m_fdPackFile; - void *m_pPackFile; - int m_iPackFileSize; - - typedef struct { - char szTag[16]; - float minx, miny, minz, maxx, maxy, maxz; - int32_t vertex_count; - int32_t material_count; - } pack_header; - - typedef struct { - int32_t start_vertex; - int32_t vertex_count; - char szName[64]; - } pack_material; - - typedef struct { - GLfloat x; - GLfloat y; - GLfloat z; - } Vertex3D, Vector3D; - - typedef struct { - GLfloat u; - GLfloat v; - } TexCoord; - - typedef struct { - Vertex3D vertex; - Vector3D normal; - Vector3D tangent; - TexCoord texcoord; - } VertexData; - - VertexData *m_pVertexData; - - typedef struct { - GLint start_vertex; - GLsizei vertex_count; - KRMaterial *pMaterial; - } Material; - - GLsizei m_cBuffers; - GLuint *m_pBuffers; - - vector m_materials; - - GLfloat m_minx, m_miny, m_minz, m_maxx, m_maxy, m_maxz; + vector m_materials; + KRMesh m_mesh; }; diff --git a/objview/Classes/KRObjViewGLView.mm b/objview/Classes/KRObjViewGLView.mm index 486b86b..c395d0f 100644 --- a/objview/Classes/KRObjViewGLView.mm +++ b/objview/Classes/KRObjViewGLView.mm @@ -124,7 +124,8 @@ } KRModelManager *pModelManager = [renderEngine getModelManager]; - m_scene.addInstance(pModelManager->getModel("fachwerkhaus12"), KRMat4()); + //m_scene.addInstance(pModelManager->getModel("fachwerkhaus12"), KRMat4()); + m_scene.addInstance(pModelManager->getModel("ballroom"), KRMat4()); [renderEngine setNearZ: 25.0]; [renderEngine setFarZ: 5000.0];