#include "ivreader.h" #include #include #include IVMeshListNode *IVReader::meshList = NULL; int IVReader::instanceCnt = 0; Ogre::Log *IVReader::IVLog = NULL; IVMeshListNode::IVMeshListNode(std::string name, IVManualMeshLoader *loader) { this->name = name; this->loader = loader; next = NULL; } IVMeshListNode::~IVMeshListNode() { if (loader != NULL) delete loader; } void IVMeshListNode::attachNewNode(std::string name, IVManualMeshLoader *loader) { IVMeshListNode *help = this; while (help->next != NULL) help = help->next; help->next = new IVMeshListNode(name, loader); } IVManualMeshLoader *IVMeshListNode::getManualMeshLoader(std::string name) { IVMeshListNode *help = this; if (help->name == name) return help->loader; while (help->next != NULL) { help = help->next; if (help->name == name) return help->loader; } return NULL; } IVDefListNode::IVDefListNode(std::string name, IVNode *node) { this->name = name; this->node = node; next = NULL; } IVDefListNode::~IVDefListNode() { } void IVDefListNode::attachNewNode(std::string name, IVNode *node) { IVDefListNode *help = this; while (help->next != NULL) help = help->next; help->next = new IVDefListNode(name, node); } IVNode *IVDefListNode::getDef(std::string name) { IVDefListNode *help = this; if (help->name == name) return help->node; while (help->next != NULL) { help = help->next; if (help->name == name) return help->node; } return NULL; } IVReader::IVReader() { root = NULL; meshList = NULL; defList = NULL; fileName = NULL; instanceCnt++; IVLog = NULL; } IVReader::~IVReader() { collapse(); instanceCnt--; if (instanceCnt == 0) if (meshList != NULL) { IVMeshListNode *help = meshList, *delme = NULL; while (help->next != NULL) { delme = help; help = help->next; delete delme; } delete help; } } void IVReader::collapse() { if (root != NULL) { delete root; root = NULL; } if (defList != NULL) { IVDefListNode *help = defList, *delme = NULL; while (help->next != NULL) { delme = help; help = help->next; delete delme; } delete help; defList = NULL; } if (this->fileName != NULL) { delete [] this->fileName; this->fileName = NULL; } } void IVReader::setLog(Ogre::Log *IVLog) { this->IVLog = IVLog; } std::string IVReader::intToStr(int num) { std::ostringstream myStream; myStream << num; myStream.flush(); return(myStream.str()); } std::string IVReader::realToStr(Ogre::Real num) { std::ostringstream myStream; myStream << num; myStream.flush(); return(myStream.str()); } bool IVReader::loadFile(const char* fileName) { std::string message = "trying to load "; message = message + fileName + "..."; if (IVLog != NULL) IVLog->logMessage(message); collapse(); this->fileName = new char[strlen(fileName)+1]; strcpy(this->fileName, fileName); treeCnt = 0; infile = fopen(fileName, "r"); root = NULL; if (infile == NULL) { message = "! Error loading File "; message = message + fileName + " !"; if (IVLog != NULL) IVLog->logMessage(message); return false; } if ((fgets(buf, BUFFERSIZE, infile) == NULL) && !feof(infile)) { message = "! Error loading File "; message = message + fileName + " !"; if (IVLog != NULL) IVLog->logMessage(message); fclose(infile); return false; } if (!checkHeader(buf)) { message = "! Invalid Header !"; if (IVLog != NULL) IVLog->logMessage(message); fclose(infile); return false; } IVTokenType tmptyp = IV_TOKEN_INVALID; eof = false; bufOffset = 0; char token[BUFFERSIZE] = "\0", oldtoken[BUFFERSIZE] = "\0", fieldtoken[BUFFERSIZE] = "\0"; int level = 0; while (getNextElement(token, &tmptyp)) { if (tmptyp == IV_TOKEN_BRACEOPEN) { root = new IVNode(oldtoken); level++; break; } strcpy(oldtoken, token); } IVNode *actualNode = root, *parent = root, *fieldNode = root, *newNode = NULL; IVTokenType oldtmptyp = tmptyp; bool textfield = false, realfield = false; IVType fieldtyp = IV_INVALID; bool def = false; std::string defLabel; Ogre::Real rblock[BLOCKSIZE]; float *rvalues; int cnt = 0; int blockcnt = 0; while (getNextElement(token, &tmptyp)) { if ((tmptyp == IV_TOKEN_BRACKETOPEN)) if (!getNextElement(token, &tmptyp)) break; if ((tmptyp == IV_TOKEN_INVALID)) if (!getNextElement(token, &tmptyp)) break; if (tmptyp == IV_TOKEN_BRACEOPEN) { actualNode = new IVNode(oldtoken); if (parent == NULL) { message = "Error loading file "; message = message + fileName + "! Invalid tree structure."; if (IVLog != NULL) IVLog->logMessage(message); fclose(infile); return false; } parent->attachNode(actualNode); parent = actualNode; level++; if (def) { addDefToList(defLabel, actualNode); def = false; } } else if (tmptyp == IV_TOKEN_BRACECLOSE) { if (realfield) { if (blockcnt == 0) rvalues = (Ogre::Real *)malloc((cnt)*sizeof(Ogre::Real)); else rvalues = (Ogre::Real *)realloc(rvalues, (BLOCKSIZE*(blockcnt) + cnt)*sizeof(Ogre::Real)); memcpy((void *)&rvalues[BLOCKSIZE*blockcnt], rblock, cnt*sizeof(Ogre::Real)); fieldNode->addField(fieldtoken, rvalues, BLOCKSIZE*blockcnt+cnt, fieldtyp); realfield = false; // free(rvalues); } if (level > 0) { actualNode = parent = actualNode->getParent(); level--; } } else { if (oldtmptyp == IV_TOKEN_DEF) { def = true; defLabel = ""; defLabel = defLabel + token; } else if (oldtmptyp == IV_TOKEN_USE) { newNode = new IVNode("USE"); if (parent == NULL) { message = "Error loading file "; message = message + fileName + "! Invalid tree structure."; if (IVLog != NULL) IVLog->logMessage(message); fclose(infile); return false; } char *s = (char *)malloc(sizeof(char)*(strlen(token)+1)); memcpy(s, token, strlen(token)); s[strlen(token)] = '\0'; newNode->addField("label", s); actualNode->attachNode(newNode); } else if (!def) if (oldtmptyp == IV_TOKEN_STRING) { if (!textfield) { if (tmptyp == IV_TOKEN_STRING) { /* char *s = new char[strlen(token)+1]; strcpy(s, token); */ char *s = (char *)malloc(sizeof(char)*(strlen(token)+1)); memcpy(s, token, strlen(token)); s[strlen(token)] = '\0'; actualNode->addField(oldtoken, s); // delete [] s; } } if (!realfield) { if ((tmptyp == IV_TOKEN_REAL) || (tmptyp == IV_TOKEN_INT)) { cnt = 0; blockcnt = 0; char *stopstring; rblock[0] = strtod(token, &stopstring); cnt++; strcpy(fieldtoken, oldtoken); fieldNode = actualNode; if (tmptyp == IV_TOKEN_REAL) fieldtyp = IV_REAL; if (tmptyp == IV_TOKEN_INT) fieldtyp = IV_INT; realfield = true; } } textfield = !textfield; } else { if (realfield) { if ((tmptyp == IV_TOKEN_REAL) || (tmptyp == IV_TOKEN_INT)) { char *stopstring; if (cnt >= BLOCKSIZE) { if (blockcnt == 0) rvalues = (Ogre::Real *)malloc((BLOCKSIZE)*sizeof(Ogre::Real)); else rvalues = (Ogre::Real *)realloc(rvalues, (BLOCKSIZE*(blockcnt+1))*sizeof(Ogre::Real)); memcpy((void *)&rvalues[BLOCKSIZE*blockcnt], rblock, BLOCKSIZE*sizeof(Ogre::Real)); cnt = 0; blockcnt++; } rblock[cnt] = strtod(token, &stopstring); cnt++; if (tmptyp == IV_TOKEN_REAL) fieldtyp = IV_REAL; } else { if (blockcnt == 0) rvalues = (Ogre::Real *)malloc((cnt)*sizeof(Ogre::Real)); else rvalues = (Ogre::Real *)realloc(rvalues, (BLOCKSIZE*(blockcnt) + cnt)*sizeof(Ogre::Real)); memcpy((void *)&rvalues[BLOCKSIZE*blockcnt], rblock, cnt*sizeof(Ogre::Real)); fieldNode->addField(fieldtoken, rvalues, BLOCKSIZE*blockcnt+cnt, fieldtyp); realfield = false; // free(rvalues); } } textfield = false; } } strcpy(oldtoken, token); oldtmptyp = tmptyp; } message = ""; ; message = message + fileName + " loaded."; if (IVLog != NULL) IVLog->logMessage(message); fclose(infile); return true; } void IVReader::print() { if (root != NULL) root->print(); } bool IVReader::checkHeader(const char *string) { for (int i=0; i < validIVHeaderCnt; i++) if (strcmp(validIVHeader[i], string) == 0) return true; return false; } bool IVReader::isSpace(char c) { if ((c==' ') || (c=='\t')) return true; return false; } bool IVReader::isNewline(char c) { if (c=='\n') return true; return false; } bool IVReader::isDigit(char c) { if ((c>=48) && (c<=57)) return true; return false; } bool IVReader::isHexDigit(char c) { if ( ((c>=48) && (c<=57)) || ((c>=65) && (c<=70)) || ((c>=97) && (c<=102)) ) return true; return false; } bool IVReader::getNextElement(char *token, IVTokenType *type) { if (eof) return false; bool quoted = false; while (isSpace(buf[bufOffset])) bufOffset++; int i=0; while ((!isSpace(buf[bufOffset])) || (quoted)) { if (!quoted) { if (isNewline(buf[bufOffset]) || (buf[bufOffset] == COMMENTCHAR)) { token[i] = '\0'; classify(token, type); bufOffset = 0; if (fgets(buf, BUFFERSIZE, infile) == NULL) { eof = true; } if (i==0) return getNextElement(token, type); return true; } if ((buf[bufOffset] == ',') || (buf[bufOffset] == ']')) { token[i] = '\0'; bufOffset++; classify(token, type); return true; } } else if (isNewline(buf[bufOffset])) { eof = true; } token[i] = buf[bufOffset]; i++; if (buf[bufOffset] == '"') { quoted = !quoted; i--; } bufOffset++; } token[i] = '\0'; classify(token, type); return true; } void IVReader::classify(char *token, IVTokenType *type) { bool isInt = true, isReal = true; if (!isDigit(token[0]) && (token[0] != '-') && (token[0] != '+')) { isInt = false; if (token[0] != '.') isReal = false; } int i = 1; while ((token[i] != '\0') && isReal) { if (isInt && (i!=2) && !isHexDigit(token[i])) { isInt = false; } if (isInt && (i==2) && !isHexDigit(token[i]) && (token[i] != 'x') && (token[i] != 'X')) isInt = false; if (isReal && (!isDigit(token[i])) && (token[i] != '.') && (token[i] != 'e') && (token[i] != 'E') && (token[i] != 'd') && (token[i] != 'D') && (token[i] != '-') && (token[i] != '+')) isReal = false; i++; } if (isInt) *type = IV_TOKEN_INT; else if (isReal) *type = IV_TOKEN_REAL; else *type = IV_TOKEN_STRING; if (strcmp(token, "DEF") == 0) *type = IV_TOKEN_DEF; if (strcmp(token, "USE") == 0) *type = IV_TOKEN_USE; if (token[1] == '\0') { if (token[0] == '{') *type = IV_TOKEN_BRACEOPEN; if (token[0] == '}') *type = IV_TOKEN_BRACECLOSE; if (token[0] == '[') *type = IV_TOKEN_BRACKETOPEN; if (token[0] == ']') *type = IV_TOKEN_BRACKETCLOSE; if (token[0] == '(') *type = IV_TOKEN_PARENTHESISOPEN; if (token[0] == ')') *type = IV_TOKEN_PARENTHESISCLOSE; } if (token[0] == '\0') { *type = IV_TOKEN_INVALID; } } /* IVNode *IVReader::getNode(const char* name) { return root->getNodeRecursive(name); } */ void IVReader::addMeshToList(std::string name, IVManualMeshLoader *loader) { if (meshList == NULL) { meshList = new IVMeshListNode(name, loader); } else { meshList->attachNewNode(name, loader); } } void IVReader::addDefToList(std::string name, IVNode *node) { if (defList == NULL) { defList = new IVDefListNode(name, node); } else { defList->attachNewNode(name, node); } } Ogre::Entity *IVReader::createEntity(Ogre::SceneManager* sceneMgr, std::string name, IVMeshData *mData, Ogre::Vector3 *translation) { using namespace Ogre; std::string meshName = name.substr(name.find('/',0), name.length()) + "/Mesh"; std::string entityName = name + "/Entity"; Mesh* pMesh = NULL; if ((pMesh = (Mesh *) MeshManager::getSingleton().getByName(meshName).getPointer()) == NULL) { IVMeshData *data = mData->expand(); IVManualMeshLoader *loader = new IVManualMeshLoader(data); if (translation != NULL) *translation = data->boundingBox->getCenter(); // data->collapse(); // delete data; addMeshToList(meshName, loader); Mesh* pMesh = MeshManager::getSingleton().createManual(meshName, "IVGroup", loader).getPointer(); pMesh->load(); pMesh->touch(); } else { if (translation != NULL) { *translation = meshList->getManualMeshLoader(meshName)->getBoundingBox()->getCenter(); } } Entity *pEntity = sceneMgr->createEntity(entityName, meshName); return pEntity; } void IVReader::buildTree(Ogre::SceneManager* sceneMgr, Ogre::SceneNode *sceneNodeRoot) { using namespace Ogre; if (root == NULL) return; std::string s = intToStr(treeCnt) + "/" + fileName + "/Root"; SceneNode *actualSceneNode = sceneNodeRoot->createChildSceneNode(s); s = "/"; s = s + fileName + "/RootMaterial"; Material* pMaterial = NULL; if ((pMaterial = (Material *) MaterialManager::getSingleton().getByName(s).getPointer()) == NULL) { pMaterial = (Material *)MaterialManager::getSingleton().create(s, "General").getPointer(); } pMaterial->load(); nodeCnt = 1; matCnt = 1; buildTree(sceneMgr, actualSceneNode, root, NULL, pMaterial); treeCnt++; std::string message = "Tree of "; message = message + fileName + " built (" + intToStr(nodeCnt) + " Nodes)"; if (IVLog != NULL) IVLog->logMessage(message); } void IVReader::buildTree(Ogre::SceneManager* sceneMgr, Ogre::SceneNode *sceneNodeRoot, IVNode *ivRoot, IVMeshData *mData, Ogre::Material *material) { using namespace Ogre; Material *newMaterial = NULL; bool meshDataCreated = false; if (mData == NULL) { mData = new IVMeshData(); meshDataCreated = true; } IVType t; int i; IVNode *help = ivRoot->getNextChildNode(true); while (help != NULL) { if (strcmp(help->getName(), "USE") == 0) { char *defLabel = (char *) help->getField("label", &t, &i); if (t == IV_STRING) { help = defList->getDef(defLabel); } } if ((strcmp(help->getName(), "Separator") == 0) || (strcmp(help->getName(), "TransformSeparator") == 0)) { /* std::string s = sceneNodeRoot->getName() + "/Sep" + intToStr(nodeCnt); nodeCnt++; SceneNode *actualSceneNode = sceneNodeRoot->createChildSceneNode(s); buildTree(sceneMgr, actualSceneNode, help, mData, actualMaterial); */ if (newMaterial == NULL) newMaterial = material; buildTree(sceneMgr, sceneNodeRoot, help, mData, newMaterial); } if (strcmp(help->getName(), "Texture2") == 0) { char *textureFileName = (char *) help->getField("filename", &t, &i); if (t == IV_STRING) { std::string s = sceneNodeRoot->getName().substr(sceneNodeRoot->getName().find('/',0), sceneNodeRoot->getName().length()) + "/Material" + intToStr(matCnt); matCnt++; if ((newMaterial = (Material *) MaterialManager::getSingleton().getByName(s).getPointer()) == NULL) { newMaterial = (Material *)MaterialManager::getSingleton().create(s, "General").getPointer(); newMaterial->getTechnique(0)->getPass(0)->createTextureUnitState(textureFileName); } newMaterial->load(); newMaterial->reload(); } } // can be included if (strcmp(help->getName(), "Material") == 0) { Real *ambientColor = (Real *) help->getField("ambientColor", &t, &i); if ((i != 3) || (t != IV_REAL)) ambientColor = NULL; Real *diffuseColor = (Real *) help->getField("diffuseColor", &t, &i); if ((i != 3) || (t != IV_REAL)) diffuseColor = NULL; Real *specularColor = (Real *) help->getField("specularColor", &t, &i); if ((i != 3) || (t != IV_REAL)) specularColor = NULL; Real *emissiveColor = (Real *) help->getField("emissiveColor", &t, &i); if ((i != 3) || (t != IV_REAL)) emissiveColor = NULL; Real *shininess = (Real *) help->getField("shininess", &t, &i); if ((i != 1) || (t != IV_REAL)) shininess = NULL; Real *transparency = (Real *) help->getField("transparency", &t, &i); if ((i != 1) || (t != IV_REAL)) transparency = NULL; if (newMaterial == NULL) { std::string s = sceneNodeRoot->getName().substr(sceneNodeRoot->getName().find('/',0), sceneNodeRoot->getName().length()) + "/Material" + intToStr(matCnt); matCnt++; if ((newMaterial = (Material *) MaterialManager::getSingleton().getByName(s).getPointer()) == NULL) { if (material == NULL) newMaterial = (Material *)MaterialManager::getSingleton().create(s, "General").getPointer(); else newMaterial = material->clone(s).getPointer(); Real alpha = 1.f; if (transparency != NULL) alpha = 1.f - transparency[0]; if (ambientColor != NULL) newMaterial->setAmbient(ambientColor[0], ambientColor[1], ambientColor[2]); if (diffuseColor != NULL) newMaterial->setDiffuse(diffuseColor[0], diffuseColor[1], diffuseColor[2], alpha); if (specularColor != NULL) newMaterial->setSpecular(specularColor[0], specularColor[1], specularColor[2], alpha); if (emissiveColor != NULL) newMaterial->setSelfIllumination(emissiveColor[0], emissiveColor[1], emissiveColor[2]); if (shininess != NULL) newMaterial->setShininess(shininess[0]); // if (material->getTechnique(0)->getPass(0)->getNumTextureUnitStates() > 0) // { // newMaterial->getTechnique(0)->getPass(0)->createTextureUnitState(material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureName()); // } } newMaterial->load(); newMaterial->reload(); } else { Real alpha = 1.f; if (transparency != NULL) alpha = 1.f - transparency[0]; if (ambientColor != NULL) newMaterial->setAmbient(ambientColor[0], ambientColor[1], ambientColor[2]); if (diffuseColor != NULL) newMaterial->setDiffuse(diffuseColor[0], diffuseColor[1], diffuseColor[2], alpha); if (specularColor != NULL) newMaterial->setSpecular(specularColor[0], specularColor[1], specularColor[2], alpha); if (emissiveColor != NULL) newMaterial->setSelfIllumination(emissiveColor[0], emissiveColor[1], emissiveColor[2]); if (shininess != NULL) newMaterial->setShininess(shininess[0]); newMaterial->load(); } } if (strcmp(help->getName(), "Coordinate3") == 0) { mData->vertices = (Real *) help->getField("point", &t, &mData->vcnt); if ((t != IV_REAL) && (t != IV_INT)) mData->vertices = NULL; } if (strcmp(help->getName(), "Normal") == 0) { mData->normals = (Real *) help->getField("vector", &t, &mData->ncnt); if ((t != IV_REAL) && (t != IV_INT)) mData->normals = NULL; } if (strcmp(help->getName(), "TextureCoordinate2") == 0) { mData->texCoords = (Real *) help->getField("point", &t, &mData->tcnt); if ((t != IV_REAL) && (t != IV_INT)) mData->texCoords = NULL; } if (strcmp(help->getName(), "IndexedFaceSet") == 0) { std::string s = sceneNodeRoot->getName() + "/IFS" + intToStr(nodeCnt); nodeCnt++; SceneNode *triangleStripSceneNode = sceneNodeRoot->createChildSceneNode(s); mData->indices = (Real *) help->getField("coordIndex", &t, &mData->icnt); if (t != IV_INT) mData->indices = NULL; mData->normalIndices = (Real *) help->getField("normalIndex", &t, &mData->nicnt); if (t != IV_INT) mData->normalIndices = NULL; mData->texCoordIndices = (Real *) help->getField("textureCoordIndex", &t, &mData->ticnt); if (t != IV_INT) mData->texCoordIndices = NULL; mData->roType = IV_ROT_FACE_SET; Vector3 translation = Vector3(0,0,0); Entity *pEntity = createEntity(sceneMgr, s, mData, &translation); if (newMaterial == NULL) newMaterial = material; if (newMaterial != NULL) pEntity->setMaterialName(newMaterial->getName()); triangleStripSceneNode->attachObject(pEntity); triangleStripSceneNode->translate(translation); } if (strcmp(help->getName(), "IndexedTriangleStripSet") == 0) { std::string s = sceneNodeRoot->getName() + "/ITS" + intToStr(nodeCnt); nodeCnt++; SceneNode *triangleStripSceneNode = sceneNodeRoot->createChildSceneNode(s); mData->indices = (Real *) help->getField("coordIndex", &t, &mData->icnt); if (t != IV_INT) mData->indices = NULL; mData->normalIndices = (Real *) help->getField("normalIndex", &t, &mData->nicnt); if (t != IV_INT) mData->normalIndices = NULL; mData->texCoordIndices = (Real *) help->getField("textureCoordIndex", &t, &mData->ticnt); if (t != IV_INT) mData->texCoordIndices = NULL; IVNode *n = help->getNextChildNode(true); while ((n != NULL) && (strcmp(help->getName(), "VertexProperty") == 0)) { n = help->getNextChildNode(); } if (n != NULL) { mData->vertices = (Real *) n->getField("vertex", &t, &mData->vcnt); if ((t != IV_REAL) && (t != IV_INT)) mData->vertices = NULL; mData->normals = (Real *) n->getField("normal", &t, &mData->ncnt); if ((t != IV_REAL) && (t != IV_INT)) mData->normals = NULL; mData->texCoords = (Real *) n->getField("texCoord", &t, &mData->tcnt); if ((t != IV_REAL) && (t != IV_INT)) mData->texCoords = NULL; } mData->roType = IV_ROT_TRIANGLE_STRIP; Vector3 translation = Vector3(0,0,0); Entity *pEntity = createEntity(sceneMgr, s, mData, &translation); if (newMaterial == NULL) newMaterial = material; if (newMaterial != NULL) pEntity->setMaterialName(newMaterial->getName()); triangleStripSceneNode->attachObject(pEntity); triangleStripSceneNode->translate(translation); } help = ivRoot->getNextChildNode(); } if (meshDataCreated) if (mData != NULL) delete mData; }