Render_XmlSceneLoader.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 Filename    :   Render_XmlSceneLoader.cpp
00004 Content     :   Imports and exports XML files - implementation
00005 Created     :   January 21, 2013
00006 Authors     :   Robotic Arm Software - Peter Hoff, Dan Goodman, Bryan Croteau
00007 
00008 Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
00009 
00010 Licensed under the Apache License, Version 2.0 (the "License");
00011 you may not use this file except in compliance with the License.
00012 You may obtain a copy of the License at
00013 
00014 http://www.apache.org/licenses/LICENSE-2.0
00015 
00016 Unless required by applicable law or agreed to in writing, software
00017 distributed under the License is distributed on an "AS IS" BASIS,
00018 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00019 See the License for the specific language governing permissions and
00020 limitations under the License.
00021 
00022 ************************************************************************************/
00023 
00024 #include "Render_XmlSceneLoader.h"
00025 #include <Kernel/OVR_Log.h>
00026 
00027 #ifdef OVR_DEFINE_NEW
00028 #undef new
00029 #endif
00030 
00031 namespace OVR { namespace Render {
00032 
00033 XmlHandler::XmlHandler() : pXmlDocument(NULL)
00034 {
00035     pXmlDocument = new tinyxml2::XMLDocument();
00036 }
00037 
00038 XmlHandler::~XmlHandler()
00039 {
00040     delete pXmlDocument;
00041 }
00042 
00043 bool XmlHandler::ReadFile(const char* fileName, OVR::Render::RenderDevice* pRender,
00044                               OVR::Render::Scene* pScene,
00045                           OVR::Array<Ptr<CollisionModel> >* pCollisions,
00046                               OVR::Array<Ptr<CollisionModel> >* pGroundCollisions)
00047 {
00048     if(pXmlDocument->LoadFile(fileName) != 0)
00049     {
00050         return false;
00051     }
00052 
00053     // Extract the relative path to our working directory for loading textures
00054     filePath[0] = 0;
00055     SPInt pos = 0;
00056         SPInt len = strlen(fileName);
00057     for(SPInt i = len; i > 0; i--)
00058     {
00059         if (fileName[i-1]=='\\' || fileName[i-1]=='/')
00060         {
00061             memcpy(filePath, fileName, i);
00062             filePath[i] = 0;
00063             break;
00064         }        
00065     }    
00066 
00067     // Load the textures
00068         OVR_DEBUG_LOG_TEXT(("Loading textures..."));
00069     XMLElement* pXmlTexture = pXmlDocument->FirstChildElement("scene")->FirstChildElement("textures");
00070     if (pXmlTexture)
00071     {
00072         pXmlTexture->QueryIntAttribute("count", &textureCount);
00073         pXmlTexture = pXmlTexture->FirstChildElement("texture");
00074     }
00075 
00076     for(int i = 0; i < textureCount; ++i)
00077     {
00078         const char* textureName = pXmlTexture->Attribute("fileName");
00079                 SPInt       dotpos = strcspn(textureName, ".");
00080         char        fname[300];
00081 
00082                 if (pos == len)
00083                 {            
00084                         OVR_sprintf(fname, 300, "%s", textureName);
00085                 }
00086                 else
00087                 {
00088                         OVR_sprintf(fname, 300, "%s%s", filePath, textureName);
00089                 }
00090 
00091         SysFile* pFile = new SysFile(fname);
00092                 Ptr<Texture> texture;
00093                 if (textureName[dotpos + 1] == 'd' || textureName[dotpos + 1] == 'D')
00094                 {
00095                         // DDS file
00096                         texture.SetPtr(*LoadTextureDDS(pRender, pFile));
00097                 }
00098                 else
00099                 {
00100                         texture.SetPtr(*LoadTextureTga(pRender, pFile));
00101                 }
00102 
00103         Textures.PushBack(texture);
00104                 pFile->Close();
00105                 pFile->Release();
00106         pXmlTexture = pXmlTexture->NextSiblingElement("texture");
00107     }
00108         OVR_DEBUG_LOG_TEXT(("Done.\n"));
00109 
00110     // Load the models
00111         pXmlDocument->FirstChildElement("scene")->FirstChildElement("models")->
00112                           QueryIntAttribute("count", &modelCount);
00113         
00114                 OVR_DEBUG_LOG(("Loading models... %i models to load...", modelCount));
00115     XMLElement* pXmlModel = pXmlDocument->FirstChildElement("scene")->
00116                                                   FirstChildElement("models")->FirstChildElement("model");
00117     for(int i = 0; i < modelCount; ++i)
00118     {
00119                 if (i % 15 == 0)
00120                 {
00121                         OVR_DEBUG_LOG_TEXT(("%i models remaining...", modelCount - i));
00122                 }
00123                 Models.PushBack(*new Model(Prim_Triangles));
00124         bool isCollisionModel = false;
00125         pXmlModel->QueryBoolAttribute("isCollisionModel", &isCollisionModel);
00126         Models[i]->IsCollisionModel = isCollisionModel;
00127                 if (isCollisionModel)
00128                 {
00129                         Models[i]->Visible = false;
00130                 }
00131 
00132         //read the vertices
00133         OVR::Array<Vector3f> *vertices = new OVR::Array<Vector3f>();
00134         ParseVectorString(pXmlModel->FirstChildElement("vertices")->FirstChild()->
00135                                       ToText()->Value(), vertices);
00136 
00137                 for (unsigned int vertexIndex = 0; vertexIndex < vertices->GetSize(); ++vertexIndex)
00138                 {
00139                         vertices->At(vertexIndex).x *= -1.0f;
00140                 }
00141 
00142         //read the normals
00143         OVR::Array<Vector3f> *normals = new OVR::Array<Vector3f>();
00144         ParseVectorString(pXmlModel->FirstChildElement("normals")->FirstChild()->
00145                                       ToText()->Value(), normals);
00146 
00147                 for (unsigned int normalIndex = 0; normalIndex < normals->GetSize(); ++normalIndex)
00148                 {
00149                         normals->At(normalIndex).z *= -1.0f;
00150                 }
00151 
00152         //read the textures
00153         OVR::Array<Vector3f> *diffuseUVs = new OVR::Array<Vector3f>();
00154         OVR::Array<Vector3f> *lightmapUVs = new OVR::Array<Vector3f>();
00155         int         diffuseTextureIndex = -1;
00156         int         lightmapTextureIndex = -1;
00157         XMLElement* pXmlCurMaterial = pXmlModel->FirstChildElement("material");
00158 
00159         while(pXmlCurMaterial != NULL)
00160         {
00161             if(pXmlCurMaterial->Attribute("name", "diffuse"))
00162             {
00163                 pXmlCurMaterial->FirstChildElement("texture")->
00164                                                      QueryIntAttribute("index", &diffuseTextureIndex);
00165                 if(diffuseTextureIndex > -1)
00166                 {
00167                     ParseVectorString(pXmlCurMaterial->FirstChildElement("texture")->
00168                                                               FirstChild()->ToText()->Value(), diffuseUVs, true);
00169                 }
00170             }
00171             else if(pXmlCurMaterial->Attribute("name", "lightmap"))
00172             {
00173                 pXmlCurMaterial->FirstChildElement("texture")->
00174                                                                        QueryIntAttribute("index", &lightmapTextureIndex);
00175                 if(lightmapTextureIndex > -1)
00176                 {
00177                     XMLElement* firstChildElement = pXmlCurMaterial->FirstChildElement("texture");
00178                     XMLNode* firstChild = firstChildElement->FirstChild();
00179                     XMLText* text = firstChild->ToText();
00180                     const char* value = text->Value();
00181                     ParseVectorString(value, lightmapUVs, true);
00182                 }
00183             }
00184 
00185             pXmlCurMaterial = pXmlCurMaterial->NextSiblingElement("material");
00186         }
00187 
00188         //set up the shader
00189         Ptr<ShaderFill> shader = *new ShaderFill(*pRender->CreateShaderSet());
00190         shader->GetShaders()->SetShader(pRender->LoadBuiltinShader(Shader_Vertex, VShader_MVP));
00191         if(diffuseTextureIndex > -1)
00192         {
00193             shader->SetTexture(0, Textures[diffuseTextureIndex]);
00194             if(lightmapTextureIndex > -1)
00195             {
00196                 shader->GetShaders()->SetShader(pRender->LoadBuiltinShader(Shader_Fragment, FShader_MultiTexture));
00197                 shader->SetTexture(1, Textures[lightmapTextureIndex]);
00198             }
00199             else
00200             {
00201                 shader->GetShaders()->SetShader(pRender->LoadBuiltinShader(Shader_Fragment, FShader_Texture));
00202             }
00203         }
00204         else
00205         {
00206             shader->GetShaders()->SetShader(pRender->LoadBuiltinShader(Shader_Fragment, FShader_LitGouraud));
00207         }
00208         Models[i]->Fill = shader;
00209 
00210         //add all the vertices to the model
00211         const UPInt numVerts = vertices->GetSize();
00212         for(UPInt v = 0; v < numVerts; ++v)
00213         {
00214             if(diffuseTextureIndex > -1)
00215             {
00216                 if(lightmapTextureIndex > -1)
00217                 {
00218                     Models[i]->AddVertex(vertices->At(v).z, vertices->At(v).y, vertices->At(v).x, Color(255, 255, 255),
00219                                           diffuseUVs->At(v).x, diffuseUVs->At(v).y, lightmapUVs->At(v).x, lightmapUVs->At(v).y,
00220                                           normals->At(v).x, normals->At(v).y, normals->At(v).z);
00221                 }
00222                 else
00223                 {
00224                     Models[i]->AddVertex(vertices->At(v).z, vertices->At(v).y, vertices->At(v).x, Color(255, 255, 255),
00225                                           diffuseUVs->At(v).x, diffuseUVs->At(v).y, 0, 0,
00226                                           normals->At(v).x, normals->At(v).y, normals->At(v).z);
00227                 }
00228             }
00229             else
00230             {
00231                 Models[i]->AddVertex(vertices->At(v).z, vertices->At(v).y, vertices->At(v).x, Color(255, 0, 0, 128),
00232                                       0, 0, 0, 0,
00233                                       normals->At(v).x, normals->At(v).y, normals->At(v).z);
00234             }
00235         }
00236 
00237         // Read the vertex indices for the triangles
00238         const char* indexStr = pXmlModel->FirstChildElement("indices")->
00239                                           FirstChild()->ToText()->Value();
00240         UPInt stringLength = strlen(indexStr);
00241 
00242         for(UPInt j = 0; j < stringLength;)
00243         {
00244             UPInt k = j + 1;
00245             for(; k < stringLength; ++k)
00246             {
00247                 if(indexStr[k] == ' ')
00248                 {
00249                     break;
00250                 }
00251             }
00252             char text[20];
00253             for(UPInt l = 0; l < k - j; ++l)
00254             {
00255                 text[l] = indexStr[j + l];
00256             }
00257             text[k - j] = '\0';
00258             Models[i]->Indices.InsertAt(0, (unsigned short)atoi(text));
00259             j = k + 1;
00260         }
00261 
00262         delete vertices;
00263         delete normals;
00264         delete diffuseUVs;
00265         delete lightmapUVs;
00266 
00267         pScene->World.Add(Models[i]);
00268         pScene->Models.PushBack(Models[i]);
00269         pXmlModel = pXmlModel->NextSiblingElement("model");
00270     }
00271         OVR_DEBUG_LOG(("Done."));
00272 
00273     //load the collision models
00274         OVR_DEBUG_LOG(("Loading collision models... "));
00275     XMLElement* pXmlCollisionModel = pXmlDocument->FirstChildElement("scene")->FirstChildElement("collisionModels");
00276     if (pXmlCollisionModel)
00277     {
00278                 pXmlCollisionModel->QueryIntAttribute("count", &collisionModelCount);
00279         pXmlCollisionModel = pXmlCollisionModel->FirstChildElement("collisionModel");
00280     }
00281 
00282     XMLElement* pXmlPlane = NULL;
00283     for(int i = 0; i < collisionModelCount; ++i)
00284     {
00285         Ptr<CollisionModel> cm = *new CollisionModel();
00286         int planeCount = 0;
00287         pXmlCollisionModel->QueryIntAttribute("planeCount", &planeCount);
00288 
00289         pXmlPlane = pXmlCollisionModel->FirstChildElement("plane");
00290         for(int j = 0; j < planeCount; ++j)
00291         {
00292             Vector3f norm;
00293             pXmlPlane->QueryFloatAttribute("nx", &norm.x);
00294             pXmlPlane->QueryFloatAttribute("ny", &norm.y);
00295             pXmlPlane->QueryFloatAttribute("nz", &norm.z);
00296             float D;
00297             pXmlPlane->QueryFloatAttribute("d", &D);
00298             D -= 0.5f;
00299             Planef p(norm.z, norm.y, norm.x * -1.0f, D);
00300             cm->Add(p);
00301             pXmlPlane = pXmlPlane->NextSiblingElement("plane");
00302         }
00303 
00304         pCollisions->PushBack(cm);
00305         pXmlCollisionModel = pXmlCollisionModel->NextSiblingElement("collisionModel");
00306     }
00307         OVR_DEBUG_LOG(("done."));
00308 
00309     //load the ground collision models
00310         OVR_DEBUG_LOG(("Loading ground collision models..."));
00311     pXmlCollisionModel = pXmlDocument->FirstChildElement("scene")->FirstChildElement("groundCollisionModels");
00312     if (pXmlCollisionModel)
00313     {
00314                 pXmlCollisionModel->QueryIntAttribute("count", &groundCollisionModelCount);
00315         pXmlCollisionModel = pXmlCollisionModel->FirstChildElement("collisionModel");
00316     }
00317     pXmlPlane = NULL;
00318     for(int i = 0; i < groundCollisionModelCount; ++i)
00319     {
00320         Ptr<CollisionModel> cm = *new CollisionModel();
00321         int planeCount = 0;
00322         pXmlCollisionModel->QueryIntAttribute("planeCount", &planeCount);
00323 
00324         pXmlPlane = pXmlCollisionModel->FirstChildElement("plane");
00325         for(int j = 0; j < planeCount; ++j)
00326         {
00327             Vector3f norm;
00328             pXmlPlane->QueryFloatAttribute("nx", &norm.x);
00329             pXmlPlane->QueryFloatAttribute("ny", &norm.y);
00330             pXmlPlane->QueryFloatAttribute("nz", &norm.z);
00331             float D;
00332             pXmlPlane->QueryFloatAttribute("d", &D);
00333             Planef p(norm.z, norm.y, norm.x * -1.0f, D);
00334             cm->Add(p);
00335             pXmlPlane = pXmlPlane->NextSiblingElement("plane");
00336         }
00337 
00338         pGroundCollisions->PushBack(cm);
00339         pXmlCollisionModel = pXmlCollisionModel->NextSiblingElement("collisionModel");
00340     }
00341         OVR_DEBUG_LOG(("done."));
00342         return true;
00343 }
00344 
00345 void XmlHandler::ParseVectorString(const char* str, OVR::Array<OVR::Vector3f> *array,
00346                                        bool is2element)
00347 {
00348     UPInt stride = is2element ? 2 : 3;
00349     UPInt stringLength = strlen(str);
00350     UPInt element = 0;
00351     float v[3];
00352 
00353     for(UPInt j = 0; j < stringLength;)
00354     {
00355         UPInt k = j + 1;
00356         for(; k < stringLength; ++k)
00357         {
00358             if(str[k] == ' ')
00359             {
00360                 break;
00361             }
00362         }
00363         char text[20];
00364         for(UPInt l = 0; l < k - j; ++l)
00365         {
00366             text[l] = str[j + l];
00367         }
00368         text[k - j] = '\0';
00369         v[element] = (float)atof(text);
00370 
00371         if(element == (stride - 1))
00372         {
00373             //we've got all the elements of our vertex, so store them
00374             OVR::Vector3f vect;
00375             vect.x = v[0];
00376             vect.y = v[1];
00377             vect.z = is2element ? 0.0f : v[2];
00378             array->PushBack(vect);
00379         }
00380 
00381         j = k + 1;
00382         element = (element + 1) % stride;
00383     }
00384 }
00385 
00386 }} // OVR::Render
00387 
00388 #ifdef OVR_DEFINE_NEW
00389 #define new OVR_DEFINE_NEW
00390 #endif


oculus_sdk
Author(s):
autogenerated on Mon Oct 6 2014 03:01:19