/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... 2005-07-06: (Patrick) added new function buildTriangleList() */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_IMPORTER #include "static_model.h" #include "stdlibincl.h" #include #include "vector.h" using namespace std; //////////////////// /// SUB-Elements /// //////////////////// /** * @brief creates a new ModelFaceElement */ ModelFaceElement::ModelFaceElement() { this->vertexNumber = -1; this->normalNumber = -1; this->texCoordNumber = -1; this->next = NULL; } /** * @brief destroys a ModelFaceElement */ ModelFaceElement::~ModelFaceElement() { if (this->next) delete this->next; } /** * @brief creates a new ModelFace */ ModelFace::ModelFace() { this->vertexCount = 0; this->firstElem = NULL; this->material = NULL; this->next = NULL; } /** * deletes a ModelFace */ ModelFace::~ModelFace() { PRINTF(5)("Cleaning up Face\n"); if (this->firstElem != NULL) delete this->firstElem; if (this->next != NULL) delete this->next; } /** * @brief Creates a new ModelGroup */ ModelGroup::ModelGroup() { PRINTF(4)("Adding new Group\n"); this->name = NULL; this->faceMode = -1; this->faceCount = 0; this->next = NULL; this->listNumber = 0; this->indices = NULL; this->firstFace = new ModelFace; this->currentFace = this->firstFace; } /** * @brief deletes a ModelGroup */ ModelGroup::~ModelGroup() { PRINTF(5)("Cleaning up group\n"); if (this->firstFace != NULL) delete this->firstFace; // deleting the glList if (this->listNumber != 0) glDeleteLists(this->listNumber, 1); if (this->name != NULL) delete[] this->name; if (this->next !=NULL) delete this->next; } /** * @brief cleans up a ModelGroup * * actually does the same as the delete Operator, but does not delete the predecessing group */ void ModelGroup::cleanup() { PRINTF(5)("Cleaning up group\n"); if (this->firstFace) delete this->firstFace; this->firstFace = NULL; if (this->next) this->next->cleanup(); } ///////////// /// MODEL /// ///////////// /** * @brief Creates a 3D-Model. * * assigns it a Name and a Type */ StaticModel::StaticModel(const char* modelName) { this->setClassID(CL_MODEL, "Model"); PRINTF(4)("new 3D-Model is being created\n"); this->setName(modelName); this->finalized = false; // setting the start group; this->currentGroup = this->firstGroup = new ModelGroup; this->groupCount = 0; this->faceCount = 0; this->scaleFactor = 1.0f; } /** * @brief deletes an Model. * * Looks if any from model allocated space is still in use, and if so deleted it. */ StaticModel::~StaticModel() { PRINTF(4)("Deleting Model "); if (this->getName()) { PRINT(4)("%s\n", this->getName()); } else { PRINT(4)("\n"); } this->cleanup(); PRINTF(5)("Deleting display Lists.\n"); delete this->firstGroup; // deleting the MaterialList PRINTF(5)("Deleting Materials.\n"); //! @todo do we really have to delete this material?? list::iterator modMat; for(modMat = this->materialList.begin(); modMat != this->materialList.end(); modMat++) { if (!(*modMat)->external) delete (*modMat)->material; delete (*modMat); } } /** * @brief Finalizes an Object. This can be done outside of the Class. */ void StaticModel::finalize() { // this creates the display List. this->importToDisplayList(); this->buildTriangleList(); this->pModelInfo.pVertices = this->vertices.getArray(); this->pModelInfo.pNormals = this->normals.getArray(); this->pModelInfo.pTexCoor = this->vTexture.getArray(); this->finalized = true; } /** * @brief rebuild the Model from the Information we got. */ void StaticModel::rebuild() { PRINTF(3)("Rebuilding Model '%s'\n", this->getName()); this->finalize(); } ////////// // DRAW // ////////// /** * @brief Draws the Models of all Groups. * * It does this by just calling the Lists that must have been created earlier. */ void StaticModel::draw () const { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); PRINTF(4)("drawing the 3D-Models\n"); ModelGroup* tmpGroup = this->firstGroup; while (tmpGroup != NULL) { PRINTF(5)("Drawing model %s\n", tmpGroup->name); glCallList (tmpGroup->listNumber); tmpGroup = tmpGroup->next; } } /** * @brief Draws the Model number groupNumber * @param groupNumber The number of the group that will be displayed. * * It does this by just calling the List that must have been created earlier. */ void StaticModel::draw (int groupNumber) const { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (unlikely(groupNumber >= this->groupCount)) { PRINTF(2)("You requested model number %i, but this File only contains of %i Models.\n", groupNumber-1, this->groupCount); return; } PRINTF(4)("drawing the requested 3D-Models if found.\n"); ModelGroup* tmpGroup = this->firstGroup; int counter = 0; while (tmpGroup != NULL) { if (counter == groupNumber) { PRINTF(4)("Drawing model number %i named %s\n", counter, tmpGroup->name); glCallList (tmpGroup->listNumber); return; } ++counter; tmpGroup = tmpGroup->next; } PRINTF(2)("Model number %i in %s not Found.\n", groupNumber, this->getName()); return; } /** * @brief Draws the Model with a specific groupName * @param groupName The name of the group that will be displayed. * * It does this by just calling the List that must have been created earlier. */ void StaticModel::draw (char* groupName) const { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (groupName == NULL) return; PRINTF(4)("drawing the requested 3D-Models if found.\n"); ModelGroup* tmpGroup = this->firstGroup; while (tmpGroup != NULL) { if (tmpGroup->name != NULL && !strcmp(tmpGroup->name, groupName)) { PRINTF(4)("Drawing model %s\n", tmpGroup->name); glCallList (tmpGroup->listNumber); return; } tmpGroup = tmpGroup->next; } PRINTF(2)("Model Named %s in %s not Found.\n", groupName, this->getName()); return; } ////////// // INIT // ////////// /** * @brief finalizes an Model. * * This funcion is needed, to delete all the Lists, and arrays that are no more * needed because they are already imported into openGL. * This will be applied at the end of the importing Process. */ bool StaticModel::cleanup() { PRINTF(4)("cleaning up the 3D-Model to save Memory.\n"); this->firstGroup->cleanup(); return true; } ////////// // MESH // ////////// /** * @brief adds a new Material to the Material List * @param material the Material to add * @returns the added material * * this also tells this Model, that all the Materials are handled externally * with this option set the Materials will not be deleted with the Model. */ Material* StaticModel::addMaterial(Material* material) { if (material == NULL) return NULL; ModelMaterial* modMat = new ModelMaterial; modMat->external = true; modMat->material = material; this->materialList.push_back(modMat); return modMat->material; } /** * @brief adds a new Material to the Material List * @param materialName the name of the Material to add * @returns the added material */ Material* StaticModel::addMaterial(const char* materialName) { ModelMaterial* modMat = new ModelMaterial; modMat->external = false; modMat->material = new Material(materialName); // adding material to the List of materials this->materialList.push_back(modMat); return modMat->material; } /** * @brief finds a Material by its name and returns it * @param materialName the Name of the material to search for. * @returns the Material if found, NULL otherwise */ Material* StaticModel::findMaterialByName(const char* materialName) { list::iterator modMat; for (modMat = this->materialList.begin(); modMat != this->materialList.end(); modMat++) if (!strcmp((*modMat)->material->getName(), materialName)) return (*modMat)->material; return NULL; } /** * @brief parses a group String * @param groupString the new Group to create * * This function initializes a new Group. * With it you should be able to create Models with more than one SubModel inside */ bool StaticModel::addGroup(const char* groupString) { PRINTF(5)("Read Group: %s.\n", groupString); if (this->groupCount != 0 && this->currentGroup->faceCount > 0) { // finalizeGroup(currentGroup); this->currentGroup = this->currentGroup->next = new ModelGroup; } // setting the group name if not default. if (strcmp(groupString, "default")) { this->currentGroup->name = new char [strlen(groupString)+1]; strcpy(this->currentGroup->name, groupString); } ++this->groupCount; } /** * @brief parses a vertex-String * @param vertexString The String that will be parsed. * * If a vertex line is found this function will inject it into the vertex-Array */ bool StaticModel::addVertex (const char* vertexString) { float subbuffer1; float subbuffer2; float subbuffer3; sscanf (vertexString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3); this->vertices.addEntry(subbuffer1*scaleFactor, subbuffer2*scaleFactor, subbuffer3*scaleFactor); this->pModelInfo.numVertices++; return true; } /** * @brief parses a vertex-String * @param x the X-coordinate of the Vertex to add. * @param y the Y-coordinate of the Vertex to add. * @param z the Z-coordinate of the Vertex to add. */ bool StaticModel::addVertex(float x, float y, float z) { PRINTF(5)("reading in a vertex: %f %f %f\n", x, y, z); this->vertices.addEntry(x*scaleFactor, y*scaleFactor, z*scaleFactor); this->pModelInfo.numVertices++; return true; } /** * @brief parses a vertexNormal-String * @param normalString The String that will be parsed. * * If a vertexNormal line is found this function will inject it into the vertexNormal-Array */ bool StaticModel::addVertexNormal (const char* normalString) { float subbuffer1; float subbuffer2; float subbuffer3; sscanf (normalString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3); this->normals.addEntry(subbuffer1, subbuffer2, subbuffer3); this->pModelInfo.numNormals++; return true; } /** * @brief adds a VertexNormal. * @param x The x coordinate of the Normal. * @param y The y coordinate of the Normal. * @param z The z coordinate of the Normal. * * If a vertexNormal line is found this function will inject it into the vertexNormal-Array */ bool StaticModel::addVertexNormal(float x, float y, float z) { PRINTF(5)("found vertex-Normal %f, %f, %f\n", x, y, z); this->normals.addEntry(x, y, z); this->pModelInfo.numNormals++; return true; } /** * @brief parses a vertexTextureCoordinate-String * @param vTextureString The String that will be parsed. * * If a vertexTextureCoordinate line is found, * this function will inject it into the vertexTexture-Array * * !! WARNING THIS IS DIFFERNT FROM addVervexTexture(float, float); because it changes the second entry to 1-v !! */ bool StaticModel::addVertexTexture (const char* vTextureString) { float subbuffer1; float subbuffer2; sscanf (vTextureString, "%f %f", &subbuffer1, &subbuffer2); this->vTexture.addEntry(subbuffer1); this->vTexture.addEntry(1 - subbuffer2); this->pModelInfo.numTexCoor++; return true; } /** * @brief adds a Texture Coordinate * @param u The u coordinate of the TextureCoordinate. * @param v The y coordinate of the TextureCoordinate. * * If a TextureCoordinate line is found this function will * inject it into the TextureCoordinate-Array */ bool StaticModel::addVertexTexture(float u, float v) { PRINTF(5)("found vertex-Texture %f, %f\n", u, v); this->vTexture.addEntry(u); this->vTexture.addEntry(v); this->pModelInfo.numTexCoor++; return true; } /** * @brief parses a face-string * @param faceString The String that will be parsed. * * If a face line is found this function will add it to the glList. * * String is different from the argument addFace, * in this, that the first Vertex/Normal/Texcoord is 1 instead of 0 */ bool StaticModel::addFace (const char* faceString) { if (this->currentGroup->faceCount >0) this->currentGroup->currentFace = this->currentGroup->currentFace->next = new ModelFace; ModelFaceElement* tmpElem = this->currentGroup->currentFace->firstElem = new ModelFaceElement; tmpElem->next = NULL; while(strcmp (faceString, "\0")) { if (this->currentGroup->currentFace->vertexCount>0) tmpElem = tmpElem->next = new ModelFaceElement; tmpElem->next = NULL; char tmpValue [50]; int tmpLen; char* vertex = NULL; char* texture = NULL; char* normal = NULL; sscanf (faceString, "%s", tmpValue); tmpLen = strlen(tmpValue); vertex = tmpValue; if ((texture = strstr (vertex, "/")) != NULL) { texture[0] = '\0'; texture ++; if ((normal = strstr (texture, "/")) !=NULL) { normal[0] = '\0'; normal ++; } } if (vertex) tmpElem->vertexNumber = atoi(vertex)-1; if (texture) tmpElem->texCoordNumber = atoi(texture)-1; if (normal) tmpElem->normalNumber = atoi(normal)-1; faceString += tmpLen; if (strcmp (faceString, "\0")) faceString++; this->currentGroup->currentFace->vertexCount++; } this->currentGroup->faceCount += this->currentGroup->currentFace->vertexCount -2; this->faceCount += this->currentGroup->currentFace->vertexCount -2; } /** * @brief adds a new Face * @param faceElemCount the number of Vertices to add to the Face. * @param type The information Passed with each Vertex */ bool StaticModel::addFace(int faceElemCount, VERTEX_FORMAT type, ...) { if (this->currentGroup->faceCount > 0) this->currentGroup->currentFace = this->currentGroup->currentFace->next = new ModelFace; ModelFaceElement* tmpElem = this->currentGroup->currentFace->firstElem = new ModelFaceElement; va_list itemlist; va_start (itemlist, type); for (int i = 0; i < faceElemCount; i++) { if (this->currentGroup->currentFace->vertexCount > 0) tmpElem = tmpElem->next = new ModelFaceElement; tmpElem->vertexNumber = va_arg (itemlist, int); if (type & TEXCOORD) tmpElem->texCoordNumber = va_arg (itemlist, int); if (type & NORMAL) tmpElem->normalNumber = va_arg(itemlist, int); this->currentGroup->currentFace->vertexCount++; } va_end(itemlist); this->currentGroup->faceCount += this->currentGroup->currentFace->vertexCount - 2; this->faceCount += this->currentGroup->currentFace->vertexCount -2; } /** * Function that selects a material, if changed in the obj file. * @param matString the Material that will be set. */ bool StaticModel::setMaterial(const char* matString) { if (this->currentGroup->faceCount > 0) this->currentGroup->currentFace = this->currentGroup->currentFace->next = new ModelFace; this->currentGroup->currentFace->material = this->findMaterialByName(matString); if (this->currentGroup->faceCount == 0) this->currentGroup->faceCount++; } /** * Function that selects a material, if changed in the obj file. * @param mtl the Material that will be set. */ bool StaticModel::setMaterial(Material* mtl) { if (this->currentGroup->faceCount > 0) this->currentGroup->currentFace = this->currentGroup->currentFace->next = new ModelFace; this->currentGroup->currentFace->material = mtl; if (this->currentGroup->faceCount == 0) this->currentGroup->faceCount++; } /** * @brief A routine that is able to create normals. * * The algorithm does the following: * 1. It calculates creates Vectors for each normale, and sets them to zero. * 2. It then Walks through a) all the Groups b) all the Faces c) all the FaceElements * 3. It searches for a points two neighbours per Face, takes Vecotrs to them calculates FaceNormals and adds it to the Points Normal. * 4. It goes through all the normale-Points and calculates the VertexNormale and includes it in the normals-Array. */ bool StaticModel::buildVertexNormals () { PRINTF(4)("Normals are being calculated.\n"); Vector* normArray = new Vector [vertices.getCount()/3]; for (int i=0; ifirstFace; while (tmpFace != NULL) { if (tmpFace->firstElem != NULL) { ModelFaceElement* firstElem = tmpFace->firstElem; ModelFaceElement* prevElem; ModelFaceElement* curElem = firstElem; ModelFaceElement* nextElem; ModelFaceElement* lastElem; // find last Element of the Chain. !! IMPORTANT:the last Element of the Chain must point to NULL, or it will resolv into an infinity-loop. while (curElem != NULL) { prevElem = curElem; curElem = curElem->next; } lastElem = prevElem; curElem = firstElem; for (int j=0; jvertexCount; j++) { if (!(nextElem = curElem->next)) nextElem = firstElem; curElem->normalNumber = curElem->vertexNumber; curV = Vector (this->vertices.getArray()[curElem->vertexNumber*3], this->vertices.getArray()[curElem->vertexNumber*3+1], this->vertices.getArray()[curElem->vertexNumber*3+2]); prevV = Vector (this->vertices.getArray()[prevElem->vertexNumber*3], this->vertices.getArray()[prevElem->vertexNumber*3+1], this->vertices.getArray()[prevElem->vertexNumber*3+2]) - curV; nextV = Vector (this->vertices.getArray()[nextElem->vertexNumber*3], this->vertices.getArray()[nextElem->vertexNumber*3+1], this->vertices.getArray()[nextElem->vertexNumber*3+2]) - curV; normArray[curElem->vertexNumber] = normArray[curElem->vertexNumber] + nextV.cross(prevV); prevElem = curElem; curElem = curElem->next; } } tmpFace = tmpFace->next; } tmpGroup = tmpGroup->next; } for (int i=0; i < this->vertices.getCount()/3;i++) { normArray[i].normalize(); PRINTF(5)("Found Normale number %d: (%f; %f, %f).\n", i, normArray[i].x, normArray[i].y, normArray[i].z); this->addVertexNormal(normArray[i].x, normArray[i].y, normArray[i].z); } delete[] normArray; } //////////// // openGL // //////////// /** * reads and includes the Faces/Materials into the openGL state Machine */ bool StaticModel::importToDisplayList() { // finalize the Arrays this->vertices.finalizeArray(); this->vTexture.finalizeArray(); if (normals.getCount() == 0) // vertices-Array must be built for this this->buildVertexNormals(); this->normals.finalizeArray(); this->currentGroup = this->firstGroup; while (this->currentGroup != NULL) { // creating a glList for the Group if ((this->currentGroup->listNumber = glGenLists(1)) == 0) { PRINTF(2)("glList could not be created for this Model\n"); return false; } glNewList (this->currentGroup->listNumber, GL_COMPILE); // Putting Faces to GL ModelFace* tmpFace = this->currentGroup->firstFace; while (tmpFace != NULL) { if (tmpFace->vertexCount == 0 && tmpFace->material != NULL) { if (this->currentGroup->faceMode != -1) glEnd(); this->currentGroup->faceMode = 0; Material* tmpMat; if (tmpFace->material != NULL) { tmpFace->material->select(); PRINTF(5)("using material %s for coming Faces.\n", tmpFace->material->getName()); } } else if (tmpFace->vertexCount == 3) { if (this->currentGroup->faceMode != 3) { if (this->currentGroup->faceMode != -1) glEnd(); glBegin(GL_TRIANGLES); } this->currentGroup->faceMode = 3; PRINTF(5)("found triag.\n"); } else if (tmpFace->vertexCount == 4) { if (this->currentGroup->faceMode != 4) { if (this->currentGroup->faceMode != -1) glEnd(); glBegin(GL_QUADS); } this->currentGroup->faceMode = 4; PRINTF(5)("found quad.\n"); } else if (tmpFace->vertexCount > 4) { if (this->currentGroup->faceMode != -1) glEnd(); glBegin(GL_POLYGON); PRINTF(5)("Polygon with %i faces found.", tmpFace->vertexCount); this->currentGroup->faceMode = tmpFace->vertexCount; } ModelFaceElement* tmpElem = tmpFace->firstElem; while (tmpElem != NULL) { // PRINTF(2)("%s\n", tmpElem->value); this->addGLElement(tmpElem); tmpElem = tmpElem->next; } tmpFace = tmpFace->next; } glEnd(); glEndList(); this->currentGroup = this->currentGroup->next; } } /** * builds an array of triangles, that can later on be used for obb separation and octree separation */ bool StaticModel::buildTriangleList() { if( unlikely(this->pModelInfo.pTriangles != NULL)) return true; /* make sure, that all the arrays are finalized */ if( unlikely(!this->vertices.isFinalized())) this->vertices.finalizeArray(); if( unlikely(!this->vTexture.isFinalized())) this->vTexture.finalizeArray(); if( normals.getCount() == 0) // vertices-Array must be built for this this->buildVertexNormals(); if( unlikely(!this->normals.isFinalized())) this->normals.finalizeArray(); int index = 0; //!< the counter for the triangle array ModelFaceElement* tmpElem; //!< the temporary faceelement reference ModelFace* tmpFace; //!< the temporary face referece /* count the number of triangles */ /* now iterate through all groups and build up the triangle list */ this->currentGroup = this->firstGroup; while( this->currentGroup != NULL) { tmpFace = this->currentGroup->firstFace; while( tmpFace != NULL) { /* if its a triangle just add it to the list */ if( tmpFace->vertexCount == 3) { ++this->pModelInfo.numTriangles; } /* if the polygon is a quad */ else if( tmpFace->vertexCount == 4) { this->pModelInfo.numTriangles += 2; } else if( tmpFace->vertexCount > 4) { PRINTF(1)("This model (%s) got over 4 vertices per face <=> conflicts in the CD engine!\n", this->getName()); //exit(0); } tmpFace = tmpFace->next; } this->currentGroup = this->currentGroup->next; } PRINTF(3)("got %i triangles, %i vertices\n", this->pModelInfo.numTriangles, this->pModelInfo.numVertices); /* write MODELINFO structure */ /* allocate memory for the new triangle structures */ if( (this->pModelInfo.pTriangles = new sTriangleExt[this->pModelInfo.numTriangles]) == NULL) { PRINTF(1)("Could not allocate memory for triangle list\n"); return false; } /* now iterate through all groups and build up the triangle list */ this->currentGroup = this->firstGroup; while( this->currentGroup != NULL) { // Putting Faces to GL tmpFace = this->currentGroup->firstFace; while( tmpFace != NULL) { tmpElem = tmpFace->firstElem; /* if its a triangle just add it to the list */ if( tmpFace->vertexCount == 3) { for( int j = 0; j < 3; ++j) { this->pModelInfo.pTriangles[index].indexToVertices[j] = (unsigned int)tmpElem->vertexNumber * 3; this->pModelInfo.pTriangles[index].indexToNormals[j] = (unsigned int)tmpElem->normalNumber * 3; this->pModelInfo.pTriangles[index].indexToTexCoor[j] = (unsigned int)tmpElem->texCoordNumber * 3; tmpElem = tmpElem->next; } ++index; } /* if the polygon is a quad */ else if( tmpFace->vertexCount == 4) { this->pModelInfo.pTriangles[index].indexToVertices[0] = (unsigned int)tmpElem->vertexNumber * 3; this->pModelInfo.pTriangles[index].indexToNormals[0] = (unsigned int)tmpElem->normalNumber * 3; this->pModelInfo.pTriangles[index].indexToTexCoor[0] = (unsigned int)tmpElem->texCoordNumber * 3; this->pModelInfo.pTriangles[index + 1].indexToVertices[0] = (unsigned int)tmpElem->vertexNumber * 3; this->pModelInfo.pTriangles[index + 1].indexToNormals[0] = (unsigned int)tmpElem->normalNumber * 3; this->pModelInfo.pTriangles[index + 1].indexToTexCoor[0] = (unsigned int)tmpElem->texCoordNumber * 3; tmpElem = tmpElem->next; this->pModelInfo.pTriangles[index].indexToVertices[1] = (unsigned int)tmpElem->vertexNumber * 3; this->pModelInfo.pTriangles[index].indexToNormals[1] = (unsigned int)tmpElem->normalNumber * 3; this->pModelInfo.pTriangles[index].indexToTexCoor[1] = (unsigned int)tmpElem->texCoordNumber * 3; tmpElem = tmpElem->next; this->pModelInfo.pTriangles[index].indexToVertices[2] = (unsigned int)tmpElem->vertexNumber * 3; this->pModelInfo.pTriangles[index].indexToNormals[2] = (unsigned int)tmpElem->normalNumber * 3; this->pModelInfo.pTriangles[index].indexToTexCoor[2] = (unsigned int)tmpElem->texCoordNumber * 3; this->pModelInfo.pTriangles[index + 1].indexToVertices[2] = (unsigned int)tmpElem->vertexNumber * 3; this->pModelInfo.pTriangles[index + 1].indexToNormals[2] = (unsigned int)tmpElem->normalNumber * 3; this->pModelInfo.pTriangles[index + 1].indexToTexCoor[2] = (unsigned int)tmpElem->texCoordNumber * 3; tmpElem = tmpElem->next; this->pModelInfo.pTriangles[index + 1].indexToVertices[1] = (unsigned int)tmpElem->vertexNumber * 3; this->pModelInfo.pTriangles[index + 1].indexToNormals[1] = (unsigned int)tmpElem->normalNumber * 3; this->pModelInfo.pTriangles[index + 1].indexToTexCoor[1] = (unsigned int)tmpElem->texCoordNumber * 3; index += 2; } tmpFace = tmpFace->next; } this->currentGroup = this->currentGroup->next; } return true; } /** * Adds a Face-element (one vertex of a face) with all its information. * @param elem The FaceElement to add to the OpenGL-environment. It does this by searching: 1. The Vertex itself 2. The VertexNormale 3. The VertexTextureCoordinate merging this information, the face will be drawn. */ bool StaticModel::addGLElement (ModelFaceElement* elem) { PRINTF(5)("importing grafical Element to openGL.\n"); if (elem->texCoordNumber != -1) { if (likely(elem->texCoordNumber < this->pModelInfo.numTexCoor)) glTexCoord2fv(this->vTexture.getArray() + elem->texCoordNumber * 2); else PRINTF(2)("TextureCoordinate %d is not in the List (max: %d)\nThe Model might be incomplete\n", elem->texCoordNumber, this->pModelInfo.numTexCoor); } if (elem->normalNumber != -1) { if (likely(elem->normalNumber < this->pModelInfo.numNormals)) glNormal3fv(this->normals.getArray() + elem->normalNumber * 3); else PRINTF(2)("Normal %d is not in the List (max: %d)\nThe Model might be incomplete", elem->normalNumber, this->pModelInfo.numNormals); } if (elem->vertexNumber != -1) { if (likely(elem->vertexNumber < this->pModelInfo.numVertices)) glVertex3fv(this->vertices.getArray() + elem->vertexNumber * 3); else PRINTF(2)("Vertex %d is not in the List (max: %d)\nThe Model might be incomplete", elem->vertexNumber, this->pModelInfo.numVertices); } } /** * Includes a default model This will inject a Cube, because this is the most basic model. */ void StaticModel::cubeModel() { this->addVertex (-0.5, -0.5, 0.5); this->addVertex (0.5, -0.5, 0.5); this->addVertex (-0.5, 0.5, 0.5); this->addVertex (0.5, 0.5, 0.5); this->addVertex (-0.5, 0.5, -0.5); this->addVertex (0.5, 0.5, -0.5); this->addVertex (-0.5, -0.5, -0.5); this->addVertex (0.5, -0.5, -0.5); this->addVertexTexture (0.0, 0.0); this->addVertexTexture (1.0, 0.0); this->addVertexTexture (0.0, 1.0); this->addVertexTexture (1.0, 1.0); this->addVertexTexture (0.0, 2.0); this->addVertexTexture (1.0, 2.0); this->addVertexTexture (0.0, 3.0); this->addVertexTexture (1.0, 3.0); this->addVertexTexture (0.0, 4.0); this->addVertexTexture (1.0, 4.0); this->addVertexTexture (2.0, 0.0); this->addVertexTexture (2.0, 1.0); this->addVertexTexture (-1.0, 0.0); this->addVertexTexture (-1.0, 1.0); this->addVertexNormal (0.0, 0.0, 1.0); this->addVertexNormal (0.0, 0.0, 1.0); this->addVertexNormal (0.0, 0.0, 1.0); this->addVertexNormal (0.0, 0.0, 1.0); this->addVertexNormal (0.0, 1.0, 0.0); this->addVertexNormal (0.0, 1.0, 0.0); this->addVertexNormal (0.0, 1.0, 0.0); this->addVertexNormal (0.0, 1.0, 0.0); this->addVertexNormal (0.0, 0.0, -1.0); this->addVertexNormal (0.0, 0.0, -1.0); this->addVertexNormal (0.0, 0.0, -1.0); this->addVertexNormal (0.0, 0.0, -1.0); this->addVertexNormal (0.0, -1.0, 0.0); this->addVertexNormal (0.0, -1.0, 0.0); this->addVertexNormal (0.0, -1.0, 0.0); this->addVertexNormal (0.0, -1.0, 0.0); this->addVertexNormal (1.0, 0.0, 0.0); this->addVertexNormal (1.0, 0.0, 0.0); this->addVertexNormal (1.0, 0.0, 0.0); this->addVertexNormal (1.0, 0.0, 0.0); this->addVertexNormal (-1.0, 0.0, 0.0); this->addVertexNormal (-1.0, 0.0, 0.0); this->addVertexNormal (-1.0, 0.0, 0.0); this->addVertexNormal (-1.0, 0.0, 0.0); this->addFace (4, VERTEX_TEXCOORD_NORMAL, 0,0,0, 1,1,1, 3,3,2, 2,2,3); this->addFace (4, VERTEX_TEXCOORD_NORMAL, 2,2,4, 3,3,5, 5,5,6, 4,4,7); this->addFace (4, VERTEX_TEXCOORD_NORMAL, 4,4,8, 5,5,9, 7,7,10, 6,6,11); this->addFace (4, VERTEX_TEXCOORD_NORMAL, 6,6,12, 7,7,13, 1,9,14, 0,8,15); this->addFace (4, VERTEX_TEXCOORD_NORMAL, 1,1,16, 7,10,17, 5,11,18, 3,3,19); this->addFace (4, VERTEX_TEXCOORD_NORMAL, 6,12,20, 0,0,21, 2,2,22, 4,13,23); }