PageRenderTime 28ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/RayTrace/RayTrace/Scene.h

https://bitbucket.org/jibarra/cse470-assign5
C Header | 738 lines | 503 code | 89 blank | 146 comment | 88 complexity | 2f5a8f89bd9c86f82ebdd5d0052c806c MD5 | raw file
  1. /*
  2. NOTE: You do not need to edit this file for this assignment but may do so
  3. This file defines the following:
  4. SceneObjectType Enumeration
  5. SceneBackground Class
  6. SceneLight Class
  7. SceneMaterial Class
  8. SceneObject Class -> SceneSphere, SceneTriangle, SceneModel
  9. Scene Class
  10. Scene Usage: Several Functions
  11. Scene::Load (sceneFile) - load a scene descriptor file
  12. Scene::GetDescription () - get the scene description string
  13. Scene::GetAuthor () - get the scene author string
  14. Scene::GetBackground () - get the scene background information
  15. Scene::GetNumLights () - get the number of lights in the scene
  16. Scene::GetLight (lightIndex) - get one of the lights in the scene
  17. Scene::GetNumMaterials () - get the number of materials in the scene
  18. Scene::GetMaterial (materialIndex OR materialName) - get a material's description
  19. Scene::GetNumObjects () - get the number of objects in the scene
  20. Scene::GetObject (objectIndex) - get an object's description
  21. Scene::GetCamera - get the current camera description
  22. The trickiest one of these is the GetObject () function
  23. It is used like this:
  24. [The object is type-casted to its corresponding type]
  25. SceneObject tempObject = m_Scene.GetObject (0);
  26. if (tempObject.IsTriangle ())
  27. {
  28. Vector vertices[3];
  29. for (int n = 0; n < 3; n++)
  30. {
  31. vertices[n] = ((SceneTriangle)tempObject).vertex[n];
  32. }
  33. }
  34. */
  35. #ifndef SCENE_H
  36. #define SCENE_H
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string>
  40. #include <vector>
  41. #include <fstream>
  42. #include "Utils.h"
  43. // XML Parser by Frank Vanden Berghen
  44. // Available: http://iridia.ulb.ac.be/~fvandenb/tools/xmlParser.html
  45. #include "xmlParser.h"
  46. // 3DS File by bkenwright@xbdev.net
  47. // Updated by Raphael Mun
  48. #include "3ds.h"
  49. // Max Line Length for OBJ File Loading
  50. #define MAX_LINE_LEN 1000
  51. #define CHECK_ATTR(a) (a == NULL ? "" : a)
  52. #define CHECK_ATTR2(a,b) (a == NULL ? b : a)
  53. /*
  54. SceneObjectType Namespace - Holds the ObjectType Enumeration
  55. */
  56. namespace SceneObjectType
  57. {
  58. enum ObjectType
  59. {
  60. Sphere = 0,
  61. Triangle = 1,
  62. Model = 2,
  63. };
  64. };
  65. /*
  66. SceneBackground Class - The Background properties of a ray-trace scene
  67. This class defines the background in the Scene
  68. */
  69. class SceneBackground
  70. {
  71. public:
  72. Vector color;
  73. Vector ambientLight;
  74. };
  75. /*
  76. SceneLight Class - The light properties of a single light-source in a ray-trace scene
  77. The Scene class holds a list of these
  78. */
  79. class SceneLight
  80. {
  81. public:
  82. float attenuationConstant, attenuationLinear, attenuationQuadratic;
  83. Vector color;
  84. Vector position;
  85. };
  86. /*
  87. SceneMaterial Class - The material properties used in a ray-trace scene
  88. The Scene class holds a list of material
  89. */
  90. class SceneMaterial
  91. {
  92. public:
  93. std::string name;
  94. std::string texture;
  95. Vector diffuse;
  96. Vector specular;
  97. float shininess;
  98. Vector transparent;
  99. Vector reflective;
  100. Vector refraction_index;
  101. // -- Constructors & Destructors --
  102. SceneMaterial (void)
  103. {}
  104. ~SceneMaterial (void)
  105. {
  106. }
  107. };
  108. /*
  109. SceneObject Class - A base object class that defines the common features of all objects
  110. This is the base object class that the various scene object types derive from
  111. */
  112. class SceneObject
  113. {
  114. public:
  115. std::string name;
  116. SceneObjectType::ObjectType type;
  117. Vector scale, rotation, position;
  118. // -- Constructors & Destructors --
  119. SceneObject (void) { scale.x = 1.0f; scale.y = 1.0f; scale.z = 1.0f; }
  120. SceneObject (SceneObjectType::ObjectType tp) : type (tp) { scale.x = 1.0f; scale.y = 1.0f; scale.z = 1.0f; }
  121. SceneObject (std::string nm, SceneObjectType::ObjectType tp) : name(nm), type (tp) { scale.x = 1.0f; scale.y = 1.0f; scale.z = 1.0f; }
  122. // -- Object Type Checking Functions --
  123. bool IsSphere (void) { return (type == SceneObjectType::Sphere); }
  124. bool IsTriangle (void) { return (type == SceneObjectType::Triangle); }
  125. bool IsModel (void) { return (type == SceneObjectType::Model); }
  126. };
  127. /*
  128. SceneSphere Class - The sphere scene object
  129. Sphere object derived from the SceneObject
  130. */
  131. class SceneSphere : public SceneObject
  132. {
  133. public:
  134. std::string material;
  135. Vector center;
  136. float radius;
  137. // -- Constructors & Destructors --
  138. SceneSphere (void) : SceneObject ("Sphere", SceneObjectType::Sphere) {}
  139. SceneSphere (std::string nm) : SceneObject (nm, SceneObjectType::Sphere) {}
  140. };
  141. /*
  142. SceneTriangle Class - The triangle scene object
  143. Single triangle object derived from the SceneObject
  144. */
  145. class SceneTriangle : public SceneObject
  146. {
  147. public:
  148. std::string material[3];
  149. Vector vertex[3];
  150. Vector normal[3];
  151. float u[3], v[3];
  152. // -- Constructors & Destructors --
  153. SceneTriangle (void) : SceneObject ("Triangle", SceneObjectType::Triangle) {}
  154. SceneTriangle (std::string nm) : SceneObject (nm, SceneObjectType::Triangle) {}
  155. };
  156. /*
  157. SceneModel Class - The model scene object
  158. A model object consisting of a list of triangles derived from the SceneObject
  159. */
  160. class SceneModel : public SceneObject
  161. {
  162. public:
  163. std::string filename;
  164. std::vector<SceneTriangle> triangleList;
  165. // -- Constructors & Destructors --
  166. SceneModel (void) : SceneObject ("Model", SceneObjectType::Model) {}
  167. SceneModel (std::string file) : SceneObject ("Model", SceneObjectType::Model) { filename = file; }
  168. SceneModel (std::string file, std::string nm) : SceneObject (nm, SceneObjectType::Model) { filename = file; }
  169. // -- Accessor Functions --
  170. // - GetNumTriangles - Returns the number of triangles in the model
  171. unsigned int GetNumTriangles (void) { return (unsigned int)triangleList.size (); }
  172. // - GetTriangle - Gets the nth SceneTriangle
  173. SceneTriangle *GetTriangle (int triIndex) { return &triangleList[triIndex]; }
  174. };
  175. /*
  176. Scene Class - The main scene definition class with the scene information
  177. This is the base scene class
  178. */
  179. class Scene
  180. {
  181. std::string m_Desc, m_Author;
  182. SceneBackground m_Background;
  183. std::vector<SceneLight> m_LightList;
  184. std::vector<SceneMaterial> m_MaterialList;
  185. std::vector<SceneObject *> m_ObjectList;
  186. // - Private utility Functions used by Load () -
  187. Vector ParseColor (XMLNode node)
  188. {
  189. if (node.isEmpty ())
  190. return Vector (0.0f, 0.0f, 0.0f);
  191. return Vector (atof(node.getAttribute("red")),
  192. atof(node.getAttribute("green")),
  193. atof(node.getAttribute("blue")));
  194. }
  195. Vector ParseXYZ (XMLNode node)
  196. {
  197. if (node.isEmpty ())
  198. return Vector (0.0f, 0.0f, 0.0f);
  199. return Vector (atof(node.getAttribute("x")),
  200. atof(node.getAttribute("y")),
  201. atof(node.getAttribute("z")));
  202. }
  203. void ParseOBJCommand (char *line, int max, char *command, int &position);
  204. Vector ParseOBJVector (char *str);
  205. bool ParseOBJCoords (char *str, int &num, int v_index[3], int n_index[3]);
  206. public:
  207. Camera m_Camera;
  208. // -- Constructors & Destructors --
  209. Scene (void) {}
  210. ~Scene (void)
  211. {
  212. // Free the memory allocated from the objects
  213. unsigned int numObj = GetNumObjects ();
  214. for (unsigned int n = 0; n < numObj; n++)
  215. {
  216. SceneObject *sceneObj = m_ObjectList[n];
  217. if (sceneObj->IsSphere ())
  218. {
  219. delete ((SceneSphere *)sceneObj);
  220. }
  221. else if (sceneObj->IsTriangle ())
  222. {
  223. delete ((SceneTriangle *)sceneObj);
  224. }
  225. else if (sceneObj->IsModel ())
  226. {
  227. delete ((SceneModel *)sceneObj);
  228. }
  229. }
  230. m_ObjectList.clear ();
  231. }
  232. // -- Main Functions --
  233. // - Load - Loads the Scene XML file
  234. bool Load (char *filename);
  235. // -- Accessor Functions --
  236. // - GetDescription - Returns the Description String
  237. const char * GetDescription (void) { return m_Desc.c_str(); }
  238. // - GetAuthor - Return the Author String
  239. const char * GetAuthor (void) { return m_Author.c_str(); }
  240. // - GetBackground - Returns the SceneBackground
  241. SceneBackground GetBackground (void) { return m_Background; }
  242. // - GetNumLights - Returns the number of lights in the scene
  243. unsigned int GetNumLights (void) { return (unsigned int)m_LightList.size (); }
  244. // - GetLight - Returns the nth SceneLight
  245. SceneLight GetLight (int lightIndex) { return m_LightList[lightIndex]; }
  246. // - GetNumMaterials - Returns the number of materials in the scene
  247. unsigned int GetNumMaterials (void) { return (unsigned int)m_MaterialList.size (); }
  248. // - GetMaterial - Returns the nth SceneMaterial
  249. SceneMaterial GetMaterial (int matIndex) { return m_MaterialList[matIndex]; }
  250. SceneMaterial GetMaterial (std::string matName)
  251. {
  252. unsigned int numMats = (unsigned int)m_MaterialList.size ();
  253. for (unsigned int n = 0; n < numMats; n++)
  254. {
  255. if (matName == m_MaterialList[n].name)
  256. return m_MaterialList[n];
  257. }
  258. return SceneMaterial ();
  259. }
  260. // - GetNumObjects - Returns the number of objects in the scene
  261. unsigned int GetNumObjects (void) { return (unsigned int)m_ObjectList.size (); }
  262. // - GetObject - Returns the nth object [NOTE: The Object will need to be type-casted afterwards]
  263. SceneObject *GetObject (int objIndex) { return m_ObjectList[objIndex]; }
  264. // - GetCamera - Returns the camera class
  265. Camera GetCamera (void) { return m_Camera; }
  266. };
  267. bool Scene::Load (char *filename)
  268. {
  269. XMLNode tempNode;
  270. // Open the Scene XML File
  271. printf ("Loading Scenefile %s...\n", filename);
  272. XMLNode sceneXML = XMLNode::openFileHelper(filename, "scene");
  273. if (sceneXML.isEmpty ())
  274. return false;
  275. m_Desc = CHECK_ATTR(sceneXML.getAttribute("desc"));
  276. m_Author = CHECK_ATTR(sceneXML.getAttribute("author"));
  277. printf ("Description: \n\t%s\n", m_Desc.c_str ());
  278. printf ("Author: %s\n", m_Author.c_str ());
  279. // Load the Background
  280. printf ("Loading Background...\n");
  281. tempNode = sceneXML.getChildNode("background");
  282. if (tempNode.isEmpty ())
  283. return false;
  284. m_Background.color = ParseColor (tempNode.getChildNode("color"));
  285. m_Background.ambientLight = ParseColor (tempNode.getChildNode("ambientLight"));
  286. // Load the Lights
  287. printf ("Loading Lights...\n");
  288. tempNode = sceneXML.getChildNode("light_list");
  289. if (!tempNode.isEmpty ())
  290. {
  291. unsigned int numLights = tempNode.nChildNode ("light");
  292. for (unsigned int n = 0; n < numLights; n++)
  293. {
  294. XMLNode tempLightNode = tempNode.getChildNode("light", n);
  295. if (tempLightNode.isEmpty ())
  296. return false;
  297. SceneLight tempLight;
  298. tempLight.color = ParseColor (tempLightNode.getChildNode("color"));
  299. tempLight.attenuationConstant = atof(CHECK_ATTR(tempLightNode.getChildNode("attenuation").getAttribute ("constant")));
  300. tempLight.attenuationLinear = atof(CHECK_ATTR(tempLightNode.getChildNode("attenuation").getAttribute ("linear")));
  301. tempLight.attenuationQuadratic = atof(CHECK_ATTR(tempLightNode.getChildNode("attenuation").getAttribute ("quadratic")));
  302. tempLight.position = ParseXYZ (tempLightNode.getChildNode("position"));
  303. m_LightList.push_back (tempLight);
  304. }
  305. }
  306. // Load the Materials
  307. printf ("Loading Materials...\n");
  308. tempNode = sceneXML.getChildNode("material_list");
  309. if (!tempNode.isEmpty ())
  310. {
  311. unsigned int numMaterials = tempNode.nChildNode ("material");
  312. for (unsigned int n = 0; n < numMaterials; n++)
  313. {
  314. XMLNode tempMaterialNode = tempNode.getChildNode("material", n);
  315. if (tempMaterialNode.isEmpty ())
  316. return false;
  317. SceneMaterial tempMaterial;
  318. tempMaterial.name = CHECK_ATTR(tempMaterialNode.getAttribute("name"));
  319. tempMaterial.texture = CHECK_ATTR(tempMaterialNode.getChildNode("texture").getAttribute("filename"));
  320. tempMaterial.diffuse = ParseColor (tempMaterialNode.getChildNode("diffuse"));
  321. tempMaterial.specular = ParseColor (tempMaterialNode.getChildNode("specular"));
  322. tempMaterial.shininess = atof(CHECK_ATTR(tempMaterialNode.getChildNode("specular").getAttribute("shininess")));
  323. tempMaterial.transparent = ParseColor (tempMaterialNode.getChildNode("transparent"));
  324. tempMaterial.reflective = ParseColor (tempMaterialNode.getChildNode("reflective"));
  325. tempMaterial.refraction_index = ParseColor (tempMaterialNode.getChildNode("refraction_index"));
  326. m_MaterialList.push_back (tempMaterial);
  327. }
  328. }
  329. // Load the Objects
  330. printf ("Loading Objects...\n");
  331. tempNode = sceneXML.getChildNode("object_list");
  332. if (!tempNode.isEmpty ())
  333. {
  334. unsigned int numObjects = tempNode.nChildNode ();
  335. for (unsigned int n = 0; n < numObjects; n++)
  336. {
  337. XMLNode tempObjectNode = tempNode.getChildNode(n);
  338. if (tempObjectNode.isEmpty ())
  339. return false;
  340. if (!strcasecmp(tempObjectNode.getName (), "sphere"))
  341. {
  342. // Load a Sphere
  343. SceneSphere *tempSphere = new SceneSphere ();
  344. tempSphere->name = CHECK_ATTR(tempObjectNode.getAttribute("name"));
  345. tempSphere->material = CHECK_ATTR(tempObjectNode.getAttribute("material"));
  346. tempSphere->radius = atof(CHECK_ATTR(tempObjectNode.getAttribute("radius")));
  347. tempSphere->scale = ParseXYZ (tempObjectNode.getChildNode("scale"));
  348. tempSphere->rotation = ParseXYZ (tempObjectNode.getChildNode("rotation"));
  349. tempSphere->position = ParseXYZ (tempObjectNode.getChildNode("position"));
  350. tempSphere->center = ParseXYZ (tempObjectNode.getChildNode("center"));
  351. m_ObjectList.push_back (tempSphere);
  352. }
  353. else if (!strcasecmp(tempObjectNode.getName (), "triangle"))
  354. {
  355. // Load a Triangle
  356. XMLNode vertexNode;
  357. SceneTriangle *tempTriangle = new SceneTriangle ();
  358. tempTriangle->name = CHECK_ATTR(tempObjectNode.getAttribute("name"));
  359. tempTriangle->scale = ParseXYZ (tempObjectNode.getChildNode("scale"));
  360. tempTriangle->rotation = ParseXYZ (tempObjectNode.getChildNode("rotation"));
  361. tempTriangle->position = ParseXYZ (tempObjectNode.getChildNode("position"));
  362. // Load Vertex 0
  363. vertexNode = tempObjectNode.getChildNodeWithAttribute ("vertex", "index", "0");
  364. tempTriangle->material[0] = CHECK_ATTR(vertexNode.getAttribute("material"));
  365. tempTriangle->vertex[0] = ParseXYZ (vertexNode.getChildNode("position"));
  366. tempTriangle->normal[0] = ParseXYZ (vertexNode.getChildNode("normal"));
  367. tempTriangle->u[0] = atof (CHECK_ATTR(vertexNode.getChildNode("texture").getAttribute("u")));
  368. tempTriangle->v[0] = atof (CHECK_ATTR(vertexNode.getChildNode("texture").getAttribute("v")));
  369. // Load Vertex 1
  370. vertexNode = tempObjectNode.getChildNodeWithAttribute ("vertex", "index", "1");
  371. tempTriangle->material[1] = CHECK_ATTR(vertexNode.getAttribute("material"));
  372. tempTriangle->vertex[1] = ParseXYZ (vertexNode.getChildNode("position"));
  373. tempTriangle->normal[1] = ParseXYZ (vertexNode.getChildNode("normal"));
  374. tempTriangle->u[1] = atof (CHECK_ATTR(vertexNode.getChildNode("texture").getAttribute("u")));
  375. tempTriangle->v[1] = atof (CHECK_ATTR(vertexNode.getChildNode("texture").getAttribute("v")));
  376. // Load Vertex 2
  377. vertexNode = tempObjectNode.getChildNodeWithAttribute ("vertex", "index", "2");
  378. tempTriangle->material[2] = CHECK_ATTR(vertexNode.getAttribute("material"));
  379. tempTriangle->vertex[2] = ParseXYZ (vertexNode.getChildNode("position"));
  380. tempTriangle->normal[2] = ParseXYZ (vertexNode.getChildNode("normal"));
  381. tempTriangle->u[2] = atof (CHECK_ATTR(vertexNode.getChildNode("texture").getAttribute("u")));
  382. tempTriangle->v[2] = atof (CHECK_ATTR(vertexNode.getChildNode("texture").getAttribute("v")));
  383. m_ObjectList.push_back (tempTriangle);
  384. }
  385. else if (!strcasecmp(tempObjectNode.getName (), "model"))
  386. {
  387. // Load a Model
  388. SceneModel *tempModel = new SceneModel ();
  389. tempModel->filename = CHECK_ATTR(tempObjectNode.getAttribute("filename"));
  390. if (tempModel->filename == "")
  391. {
  392. printf ("No Specified Model filename\n");
  393. return false;
  394. }
  395. tempModel->name = CHECK_ATTR(tempObjectNode.getAttribute("name"));
  396. std::string material = CHECK_ATTR(tempObjectNode.getAttribute("material"));
  397. //tempModel->material = tempObjectNode.getAttribute("material");
  398. tempModel->scale = ParseXYZ (tempObjectNode.getChildNode("scale"));
  399. tempModel->rotation = ParseXYZ (tempObjectNode.getChildNode("rotation"));
  400. tempModel->position = ParseXYZ (tempObjectNode.getChildNode("position"));
  401. // Check the file format
  402. if (tempModel->filename.substr (tempModel->filename.length() - 4, 4) == ".3ds")
  403. {
  404. // Load the list of triangles from the .3ds
  405. C3DS sceneObj;
  406. if (!sceneObj.Create((char *)tempModel->filename.c_str()))
  407. {
  408. printf ("Error loading .3ds file\n");
  409. return false;
  410. }
  411. for (unsigned int obj = 0; obj < (unsigned int)sceneObj.m_iNumMeshs; obj++)
  412. {
  413. for (unsigned int n = 0; n < (unsigned int)sceneObj.m_pMeshs[obj].iNumFaces; n++)
  414. {
  415. SceneTriangle tempTriangle;
  416. Vector v1, v2, v3;
  417. // Vert 1
  418. v1.x = sceneObj.m_pMeshs[obj].pVerts[sceneObj.m_pMeshs[obj].pFaces[n].corner[0]].x;
  419. v1.y = sceneObj.m_pMeshs[obj].pVerts[sceneObj.m_pMeshs[obj].pFaces[n].corner[0]].y;
  420. v1.z = sceneObj.m_pMeshs[obj].pVerts[sceneObj.m_pMeshs[obj].pFaces[n].corner[0]].z;
  421. // Vert 2
  422. v2.x = sceneObj.m_pMeshs[obj].pVerts[sceneObj.m_pMeshs[obj].pFaces[n].corner[1]].x;
  423. v2.y = sceneObj.m_pMeshs[obj].pVerts[sceneObj.m_pMeshs[obj].pFaces[n].corner[1]].y;
  424. v2.z = sceneObj.m_pMeshs[obj].pVerts[sceneObj.m_pMeshs[obj].pFaces[n].corner[1]].z;
  425. // Vert 3
  426. v3.x = sceneObj.m_pMeshs[obj].pVerts[sceneObj.m_pMeshs[obj].pFaces[n].corner[2]].x;
  427. v3.y = sceneObj.m_pMeshs[obj].pVerts[sceneObj.m_pMeshs[obj].pFaces[n].corner[2]].y;
  428. v3.z = sceneObj.m_pMeshs[obj].pVerts[sceneObj.m_pMeshs[obj].pFaces[n].corner[2]].z;
  429. // Normal
  430. Vector normal = (v1 - v2).Cross(v3 - v2).Normalize();
  431. // Load Vertex 0
  432. tempTriangle.material[0] = material;
  433. tempTriangle.vertex[0] = v1;
  434. tempTriangle.normal[0] = normal;
  435. // Texture Coords
  436. if (sceneObj.m_pMeshs[obj].bTextCoords)
  437. {
  438. tempTriangle.u[0] = sceneObj.m_pMeshs[obj].pTexs[sceneObj.m_pMeshs[obj].pFaces[n].corner[0]].tu;
  439. tempTriangle.v[0] = sceneObj.m_pMeshs[obj].pTexs[sceneObj.m_pMeshs[obj].pFaces[n].corner[0]].tv;
  440. }
  441. else
  442. {
  443. tempTriangle.u[0] = 0.0f;
  444. tempTriangle.v[0] = 0.0f;
  445. }
  446. // Load Vertex 1
  447. tempTriangle.material[1] = material;
  448. tempTriangle.vertex[1] = v2;
  449. tempTriangle.normal[1] = normal;
  450. // Texture Coords
  451. if (sceneObj.m_pMeshs[obj].bTextCoords)
  452. {
  453. tempTriangle.u[1] = sceneObj.m_pMeshs[obj].pTexs[sceneObj.m_pMeshs[obj].pFaces[n].corner[1]].tu;
  454. tempTriangle.v[1] = sceneObj.m_pMeshs[obj].pTexs[sceneObj.m_pMeshs[obj].pFaces[n].corner[1]].tv;
  455. }
  456. else
  457. {
  458. tempTriangle.u[1] = 0.0f;
  459. tempTriangle.v[1] = 0.0f;
  460. }
  461. // Load Vertex 2
  462. tempTriangle.material[2] = material;
  463. tempTriangle.vertex[2] = v3;
  464. tempTriangle.normal[2] = normal;
  465. // Texture Coords
  466. if (sceneObj.m_pMeshs[obj].bTextCoords)
  467. {
  468. tempTriangle.u[2] = sceneObj.m_pMeshs[obj].pTexs[sceneObj.m_pMeshs[obj].pFaces[n].corner[2]].tu;
  469. tempTriangle.v[2] = sceneObj.m_pMeshs[obj].pTexs[sceneObj.m_pMeshs[obj].pFaces[n].corner[2]].tv;
  470. }
  471. else
  472. {
  473. tempTriangle.u[2] = 0.0f;
  474. tempTriangle.v[2] = 0.0f;
  475. }
  476. tempModel->triangleList.push_back (tempTriangle);
  477. }
  478. }
  479. sceneObj.Release();
  480. }
  481. else if (tempModel->filename.substr (tempModel->filename.length() - 4, 4) == ".obj")
  482. {
  483. // The following code is a modified version of code from the old RayTracer Code rt_trimesh.cpp
  484. char line[MAX_LINE_LEN];
  485. char command[MAX_LINE_LEN];
  486. int position;
  487. vector<Vector> vertices;
  488. vector<Vector> normals;
  489. std::ifstream infile (tempModel->filename.c_str());
  490. if (infile == NULL)
  491. {
  492. printf ("Error loading .obj file\n");
  493. return false;
  494. }
  495. while (infile.good ())
  496. {
  497. infile.getline (line, MAX_LINE_LEN);
  498. ParseOBJCommand (line, MAX_LINE_LEN, command, position);
  499. if (strcmp (command,"v")==0)
  500. {
  501. Vector pos = ParseOBJVector (&(line[position]));
  502. vertices.push_back (pos);
  503. }
  504. else if (strcmp (command,"vn")==0)
  505. {
  506. Vector norm = ParseOBJVector (&(line[position]));
  507. normals.push_back (norm);
  508. }
  509. else if (strcmp (command,"f")==0)
  510. {
  511. int num = 0; // number of edges
  512. int v_index[3]; // vertex index
  513. int n_index[3]; // normal index
  514. if (!ParseOBJCoords (&(line[position]), num, v_index, n_index))
  515. {
  516. printf ("Error parsing faces in .obj file\n");
  517. return false;
  518. }
  519. SceneTriangle tempTriangle;
  520. // Load Vertex 0
  521. tempTriangle.material[0] = material;
  522. tempTriangle.vertex[0] = vertices[v_index[0]];
  523. tempTriangle.normal[0] = normals[n_index[0]];
  524. // Texture Coords
  525. tempTriangle.u[0] = 0.0f;
  526. tempTriangle.v[0] = 0.0f;
  527. // Load Vertex 1
  528. tempTriangle.material[1] = material;
  529. tempTriangle.vertex[1] = vertices[v_index[1]];
  530. tempTriangle.normal[1] = normals[n_index[1]];
  531. // Texture Coords
  532. tempTriangle.u[1] = 0.0f;
  533. tempTriangle.v[1] = 0.0f;
  534. // Load Vertex 2
  535. tempTriangle.material[2] = material;
  536. tempTriangle.vertex[2] = vertices[v_index[2]];
  537. tempTriangle.normal[2] = normals[n_index[2]];
  538. // Texture Coords
  539. tempTriangle.u[2] = 0.0f;
  540. tempTriangle.v[2] = 0.0f;
  541. tempModel->triangleList.push_back (tempTriangle);
  542. }
  543. else
  544. {
  545. //printf ("Ignoring command <%s> in obj file\n", command);
  546. }
  547. }
  548. infile.close ();
  549. }
  550. else
  551. {
  552. printf ("Unsupported file format\n");
  553. return false;
  554. }
  555. m_ObjectList.push_back (tempModel);
  556. }
  557. else
  558. {
  559. printf ("Unrecognized Node <%s> in <object_list>\n", tempObjectNode.getName ());
  560. exit (255);
  561. }
  562. }
  563. }
  564. // Load the Camera
  565. printf ("Loading Camera...\n");
  566. tempNode = sceneXML.getChildNode("camera");
  567. if (tempNode.isEmpty ())
  568. return false;
  569. m_Camera.SetFOV (atof(CHECK_ATTR2(tempNode.getAttribute("fieldOfView"), "45.0")));
  570. m_Camera.SetNearClip (atof(CHECK_ATTR2(tempNode.getAttribute("nearClip"), "0.1")));
  571. m_Camera.SetFarClip (atof(CHECK_ATTR2(tempNode.getAttribute("farClip"), "100.0")));
  572. m_Camera.SetPosition (ParseXYZ (tempNode.getChildNode("position")));
  573. m_Camera.SetTarget (ParseXYZ (tempNode.getChildNode("target")));
  574. m_Camera.SetUp (ParseXYZ (tempNode.getChildNode("up")));
  575. printf ("Scene Loaded!\n");
  576. return true;
  577. }
  578. void Scene::ParseOBJCommand (char *line, int max, char *command, int &position)
  579. {
  580. int i = 0;
  581. int j = 0;
  582. while (i<max && line[i]==' ') i++;
  583. while (i<max && line[i]!='\0' && line[i]!=' ')
  584. {
  585. command[j] = line[i];
  586. j++; i++;
  587. }
  588. command[j] = '\0';
  589. position = i;
  590. }
  591. Vector Scene::ParseOBJVector (char *str)
  592. {
  593. int i = 0;
  594. float x,y,z;
  595. while (str[i]!='\0' && str[i]==' ') i++;
  596. x = atof (&(str[i]));
  597. while (str[i]!='\0' && str[i]!=' ') i++;
  598. y = atof (&(str[i]));
  599. while (str[i]!='\0' && str[i]==' ') i++;
  600. while (str[i]!='\0' && str[i]!=' ') i++;
  601. z = atof (&(str[i]));
  602. return Vector (x,y,z);
  603. }
  604. bool Scene::ParseOBJCoords (char *str, int &num, int v_index[3], int n_index[3])
  605. {
  606. int i = 0;
  607. num = 0;
  608. while (str[i]!='\0' && str[i]==' ') i++;
  609. while (str[i]!='\0')
  610. {
  611. while (str[i]!='\0' && str[i]!=' ') i++;
  612. while (str[i]!='\0' && str[i]==' ') i++;
  613. num++;
  614. }
  615. if (num != 3)
  616. return false;
  617. i = 0;
  618. for (int j=0; j<num; j++)
  619. {
  620. while (str[i]==' ') i++;
  621. v_index[j] = atoi (&(str[i])) - 1;
  622. while (str[i]!='/' && str[i]!=' ') i++;
  623. if (str[i] != '/')
  624. return false;
  625. i++;
  626. while (str[i]!='/' && str[i]!=' ') i++;
  627. if (str[i] != '/')
  628. return false;
  629. i++;
  630. n_index[j] = atoi (&(str[i])) - 1;
  631. while(str[i]!='\0' && str[i]!=' ') i++;
  632. }
  633. return true;
  634. }
  635. #endif // SCENE_H