/* 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 "model.h" #include #include #include "vector.h" #include "list.h" using namespace std; //////////////////// /// SUB-Elements /// //////////////////// /** * creates a new ModelFaceElement */ ModelFaceElement::ModelFaceElement() { this->vertexNumber = -1; this->normalNumber = -1; this->texCoordNumber = -1; this->next = NULL; } /** * destroys a ModelFaceElement */ ModelFaceElement::~ModelFaceElement() { if (this->next) delete this->next; } /** * 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; } /** * Creates a new ModelGroup */ ModelGroup::ModelGroup() { PRINTF(4)("Adding new Group\n"); this->name = ""; this->faceMode = -1; this->faceCount = 0; this->next = NULL; this->listNumber = 0; this->firstFace = new ModelFace; this->currentFace = this->firstFace; } /** * 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[0] != '\0') delete[] this->name; if (this->next !=NULL) delete this->next; } /** * 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 /// ///////////// /** * Creates a 3D-Model. assigns it a Name and a Type */ Model::Model(const char* modelName, MODEL_TYPE type) { PRINTF(4)("new 3D-Model is being created\n"); this->setName(modelName); this->type = type; this->finalized = false; // setting the start group; this->currentGroup = this->firstGroup = new ModelGroup; this->groupCount = 0; this->vertexCount = 0; this->normalCount = 0; this->texCoordCount = 0; this->faceCount = 0; this->triangleCount = 0; this->triangles = NULL; this->pModelInfo = NULL; this->scaleFactor = 1; this->vertices = new tArray(); this->vTexture = new tArray(); this->normals = new tArray(); this->materialList = new tList; if (this->type == MODEL_VERTEX_ARRAY) glEnableClientState(GL_VERTEX_ARRAY | GL_NORMAL_ARRAY | GL_TEXTURE_COORD_ARRAY); } /** * deletes an Model. Looks if any from model allocated space is still in use, and if so deleted it. */ Model::~Model() { PRINTF(4)("Deleting Model "); if (this->getName()) { PRINT(4)("%s\n", this->getName()); } else PRINT(4)("\n"); PRINTF(5)("Deleting display Lists.\n"); delete this->firstGroup; // deleting Arrays (if not allready done by finalize) this->deleteArrays(); // deleting the MaterialList PRINTF(5)("Deleting Materials.\n"); tIterator* tmpIt = this->materialList->getIterator(); ModelMaterial* modMat = tmpIt->firstElement(); //! @todo do we really have to delete this material?? while(modMat != NULL) { if (!modMat->external) delete modMat->material; delete modMat; modMat = tmpIt->nextElement(); } delete tmpIt; delete materialList; delete this->pModelInfo; } /** * Finalizes an Object. This can be done outside of the Class. */ void Model::finalize() { // this creates the display List. this->importToDisplayList(); this->buildTriangleList(); // deletes everything we allocated. //if (this->type == MODEL_DISPLAY_LIST) //this->deleteArrays(); this->cleanup(); /* load the ModelInfo */ this->pModelInfo = new modelInfo; this->pModelInfo->numVertices = this->vertexCount; this->pModelInfo->pVertices = this->vertices->getArray(); this->pModelInfo->numTriangles = this->triangleCount; this->pModelInfo->pTriangles = this->triangles; this->pModelInfo->numNormals = this->normalCount; this->pModelInfo->pNormals = this->normals->getArray(); this->pModelInfo->numTexCoor = this->vTexture->getCount(); this->pModelInfo->pTexCoor = this->vTexture->getArray(); this->finalized = true; } ////////// // DRAW // ////////// /** * Draws the Models of all Groups. It does this by just calling the Lists that must have been created earlier. */ void Model::draw () const { 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; } /* const GLfloat* pVertices = NULL; const GLfloat* pNorm = NULL; glBegin(GL_TRIANGLES); for( int i = 0; i < this->triangleCount; ++i) { //printf("int i = %i\n", i); pNorm = &this->normals->getArray()[this->triangles[i].indexToNormals[0]]; pVertices = &this->vertices->getArray()[this->triangles[i].indexToVertices[0]]; glNormal3f(pNorm[0], pNorm[1], pNorm[2]); glVertex3f(pVertices[0], pVertices[1], pVertices[2]); pNorm = &this->normals->getArray()[this->triangles[i].indexToNormals[1]]; pVertices = &this->vertices->getArray()[this->triangles[i].indexToVertices[1]]; glNormal3f(pNorm[0], pNorm[1], pNorm[2]); glVertex3f(pVertices[0], pVertices[1], pVertices[2]); pNorm = &this->normals->getArray()[this->triangles[i].indexToNormals[2]]; pVertices = &this->vertices->getArray()[this->triangles[i].indexToVertices[2]]; glNormal3f(pNorm[0], pNorm[1], pNorm[2]); glVertex3f(pVertices[0], pVertices[1], pVertices[2]); } glEnd();*/ } /** * 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 Model::draw (int groupNumber) const { if (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; } /** * 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 Model::draw (char* groupName) const { PRINTF(4)("drawing the requested 3D-Models if found.\n"); ModelGroup* tmpGroup = this->firstGroup; while (tmpGroup != NULL) { if (!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 // ////////// /** * deletes all the arrays */ bool Model::deleteArrays() { if (this->vertices) delete this->vertices; if (this->vTexture) delete this->vTexture; if (this->normals) delete this->normals; if (this->triangles) delete[] this->triangles; this->vertices = NULL; this->vTexture = NULL; this->normals = NULL; this->triangles = NULL; this->triangleCount = 0; } /** * 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 Model::cleanup() { PRINTF(4)("cleaning up the 3D-Model to save Memory.\n"); this->firstGroup->cleanup(); return true; } ////////// // MESH // ////////// /** * 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* Model::addMaterial(Material* material) { if (material == NULL) return NULL; ModelMaterial* modMat = new ModelMaterial; modMat->external = true; modMat->material = material; this->materialList->add(modMat); return modMat->material; } /** * adds a new Material to the Material List * @param materialName the name of the Material to add * @returns the added material */ Material* Model::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->add(modMat); return modMat->material; } /** * 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* Model::findMaterialByName(const char* materialName) { tIterator* tmpIt = this->materialList->getIterator(); ModelMaterial* modMat = tmpIt->firstElement(); while(modMat != NULL) { if (!strcmp(modMat->material->getName(), materialName)) { delete tmpIt; return modMat->material; } modMat = tmpIt->nextElement(); } delete tmpIt; return NULL; } /** * 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 Model::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; } /** * 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 Model::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->vertexCount++; return true; } /** * 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 Model::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->vertexCount++; return true; } /** * 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 Model::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->normalCount++; return true; } /** * 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 Model::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->normalCount++; return true; } /** * 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 Model::addVertexTexture (const char* vTextureString) { float subbuffer1; float subbuffer2; sscanf (vTextureString, "%f %f", &subbuffer1, &subbuffer2); this->vTexture->addEntry(subbuffer1); this->vTexture->addEntry(1 - subbuffer2); this->texCoordCount++; return true; } /** * 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 Model::addVertexTexture(float u, float v) { PRINTF(5)("found vertex-Texture %f, %f\n", u, v); this->vTexture->addEntry(u); this->vTexture->addEntry(v); this->texCoordCount++; return true; } /** * 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 Model::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; } /** * adds a new Face * @param faceElemCount the number of Vertices to add to the Face. * @param type The information Passed with each Vertex */ bool Model::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 Model::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 Model::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 ++; } /** * 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 Model::buildVertexNormals () { PRINTF(4)("Normals are being calculated.\n"); Vector* normArray = new Vector [vertices->getCount()/3]; for (int i=0; igetCount()/3;i++) normArray[i] = Vector(.0,.0,.0); int firstTouch; int secondTouch; Vector prevV; Vector nextV; Vector curV; ModelGroup* tmpGroup = firstGroup; while (tmpGroup) { ModelFace* tmpFace = tmpGroup->firstFace; while (tmpFace) { if (tmpFace->firstElem) { 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) { 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 (vertices->getArray()[curElem->vertexNumber*3], vertices->getArray()[curElem->vertexNumber*3+1], vertices->getArray()[curElem->vertexNumber*3+2]); prevV = Vector (vertices->getArray()[prevElem->vertexNumber*3], vertices->getArray()[prevElem->vertexNumber*3+1], vertices->getArray()[prevElem->vertexNumber*3+2]) - curV; nextV = Vector (vertices->getArray()[nextElem->vertexNumber*3], vertices->getArray()[nextElem->vertexNumber*3+1], 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 < 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 Model::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; } } /** * reads and includes the Faces/Materials into the openGL state Machine */ bool Model::importToVertexArray() { // 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; glVertexPointer(3, GL_FLOAT, 0, this->vertices->getArray()); glNormalPointer(3, 0, this->normals->getArray()); glTexCoordPointer(2, GL_FLOAT, 0, this->vTexture->getArray()); } /** * builds an array of triangles, that can later on be used for obb separation and octree separation */ bool Model::buildTriangleList() { if( unlikely(this->triangles != 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->triangleCount = 0; 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->triangleCount; } /* if the polygon is a quad */ else if( tmpFace->vertexCount == 4) { this->triangleCount += 2; } else if( tmpFace->vertexCount > 4) { PRINTF(1)("NASTY NASTY: More than 4 vertices for a face, there will be errors in the triangles information!\n"); //exit(0); } tmpFace = tmpFace->next; } this->currentGroup = this->currentGroup->next; } PRINTF(3)("got %i triangles, %i vertices\n", this->triangleCount, this->vertexCount); /* allocate memory for the new triangle structures */ if( (this->triangles = new sTriangleExt[this->triangleCount]) == 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->triangles[index].indexToVertices[j] = (unsigned int)tmpElem->vertexNumber * 3; this->triangles[index].indexToNormals[j] = (unsigned int)tmpElem->normalNumber * 3; this->triangles[index].indexToTexCoor[j] = (unsigned int)tmpElem->texCoordNumber * 3; tmpElem = tmpElem->next; } ++index; } /* if the polygon is a quad */ else if( tmpFace->vertexCount == 4) { this->triangles[index].indexToVertices[0] = (unsigned int)tmpElem->vertexNumber * 3; this->triangles[index].indexToNormals[0] = (unsigned int)tmpElem->normalNumber * 3; this->triangles[index].indexToTexCoor[0] = (unsigned int)tmpElem->texCoordNumber * 3; this->triangles[index + 1].indexToVertices[0] = (unsigned int)tmpElem->vertexNumber * 3; this->triangles[index + 1].indexToNormals[0] = (unsigned int)tmpElem->normalNumber * 3; this->triangles[index + 1].indexToTexCoor[0] = (unsigned int)tmpElem->texCoordNumber * 3; tmpElem = tmpElem->next; this->triangles[index].indexToVertices[1] = (unsigned int)tmpElem->vertexNumber * 3; this->triangles[index].indexToNormals[1] = (unsigned int)tmpElem->normalNumber * 3; this->triangles[index].indexToTexCoor[1] = (unsigned int)tmpElem->texCoordNumber * 3; tmpElem = tmpElem->next; this->triangles[index].indexToVertices[2] = (unsigned int)tmpElem->vertexNumber * 3; this->triangles[index].indexToNormals[2] = (unsigned int)tmpElem->normalNumber * 3; this->triangles[index].indexToTexCoor[2] = (unsigned int)tmpElem->texCoordNumber * 3; this->triangles[index + 1].indexToVertices[2] = (unsigned int)tmpElem->vertexNumber * 3; this->triangles[index + 1].indexToNormals[2] = (unsigned int)tmpElem->normalNumber * 3; this->triangles[index + 1].indexToTexCoor[2] = (unsigned int)tmpElem->texCoordNumber * 3; tmpElem = tmpElem->next; this->triangles[index + 1].indexToVertices[1] = (unsigned int)tmpElem->vertexNumber * 3; this->triangles[index + 1].indexToNormals[1] = (unsigned int)tmpElem->normalNumber * 3; this->triangles[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 Model::addGLElement (ModelFaceElement* elem) { PRINTF(5)("importing grafical Element to openGL.\n"); if (elem->texCoordNumber != -1) { if (likely(elem->texCoordNumber < this->texCoordCount)) 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->texCoordCount); } if (elem->normalNumber != -1) { if (likely(elem->normalNumber < this->normalCount)) 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->normalCount); } if (elem->vertexNumber != -1) { if (likely(elem->vertexNumber < this->vertexCount)) 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->vertexCount); } } /** * Includes a default model This will inject a Cube, because this is the most basic model. */ void Model::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); }