GPBFile.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #include "GPBFile.h"
  2. namespace gameplay
  3. {
  4. GPBFile::GPBFile(void)
  5. : _file(NULL), _animationsAdded(false)
  6. {
  7. }
  8. GPBFile::~GPBFile(void)
  9. {
  10. }
  11. void GPBFile::saveBinary(const std::string& filepath)
  12. {
  13. _file = fopen(filepath.c_str(), "w+b");
  14. // identifier
  15. char identifier[] = { '«', 'G', 'P', 'B', '»', '\r', '\n', '\x1A', '\n' };
  16. fwrite(identifier, 1, sizeof(identifier), _file);
  17. // version
  18. fwrite(VERSION, 1, sizeof(VERSION), _file);
  19. // write refs
  20. _refTable.writeBinary(_file);
  21. // meshes
  22. write(_geometry.size(), _file);
  23. for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); ++i)
  24. {
  25. (*i)->writeBinary(_file);
  26. }
  27. // Objects
  28. write(_objects.size(), _file);
  29. for (std::list<Object*>::const_iterator i = _objects.begin(); i != _objects.end(); ++i)
  30. {
  31. (*i)->writeBinary(_file);
  32. }
  33. _refTable.updateOffsets(_file);
  34. fclose(_file);
  35. }
  36. void GPBFile::saveText(const std::string& filepath)
  37. {
  38. _file = fopen(filepath.c_str(), "w");
  39. fprintf(_file, "<root>\n");
  40. // write refs
  41. _refTable.writeText(_file);
  42. // meshes
  43. for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); ++i)
  44. {
  45. (*i)->writeText(_file);
  46. }
  47. // Objects
  48. for (std::list<Object*>::const_iterator i = _objects.begin(); i != _objects.end(); ++i)
  49. {
  50. (*i)->writeText(_file);
  51. }
  52. fprintf(_file, "</root>");
  53. fclose(_file);
  54. }
  55. void GPBFile::add(Object* obj)
  56. {
  57. _objects.push_back(obj);
  58. }
  59. void GPBFile::addScene(Scene* scene)
  60. {
  61. addToRefTable(scene);
  62. _objects.push_back(scene);
  63. }
  64. void GPBFile::addCamera(Camera* camera)
  65. {
  66. addToRefTable(camera);
  67. _cameras.push_back(camera);
  68. }
  69. void GPBFile::addLight(Light* light)
  70. {
  71. addToRefTable(light);
  72. _lights.push_back(light);
  73. }
  74. void GPBFile::addMesh(Mesh* mesh)
  75. {
  76. addToRefTable(mesh);
  77. _geometry.push_back(mesh);
  78. }
  79. void GPBFile::addNode(Node* node)
  80. {
  81. addToRefTable(node);
  82. _nodes.push_back(node);
  83. }
  84. void GPBFile::addAnimation(Animation* animation)
  85. {
  86. _animations.add(animation);
  87. if (!_animationsAdded)
  88. {
  89. // The animations container should only be added once and only if the file has at least one animation.
  90. _animationsAdded = true;
  91. addToRefTable(&_animations);
  92. add(&_animations);
  93. }
  94. }
  95. void GPBFile::addToRefTable(Object* obj)
  96. {
  97. if (obj)
  98. {
  99. const std::string& id = obj->getId();
  100. if (id.length() > 0)
  101. {
  102. if (_refTable.get(id) == NULL)
  103. {
  104. _refTable.add(id, obj);
  105. }
  106. }
  107. }
  108. }
  109. Object* GPBFile::getFromRefTable(const std::string& id)
  110. {
  111. return _refTable.get(id);
  112. }
  113. bool GPBFile::idExists(const std::string& id)
  114. {
  115. return _refTable.get(id) != NULL;
  116. }
  117. Camera* GPBFile::getCamera(const char* id)
  118. {
  119. if (!id)
  120. return NULL;
  121. // TODO: O(n) search is not ideal
  122. for (std::list<Camera*>::const_iterator i = _cameras.begin(); i != _cameras.end(); ++i)
  123. {
  124. const std::string& _id = (*i)->getId();
  125. if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
  126. {
  127. return *i;
  128. }
  129. }
  130. return NULL;
  131. }
  132. Light* GPBFile::getLight(const char* id)
  133. {
  134. if (!id)
  135. return NULL;
  136. // TODO: O(n) search is not ideal
  137. for (std::list<Light*>::const_iterator i = _lights.begin(); i != _lights.end(); ++i)
  138. {
  139. const std::string& _id = (*i)->getId();
  140. if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
  141. {
  142. return *i;
  143. }
  144. }
  145. return NULL;
  146. }
  147. Mesh* GPBFile::getMesh(const char* id)
  148. {
  149. if (!id)
  150. return NULL;
  151. // TODO: O(n) search is not ideal
  152. for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); ++i)
  153. {
  154. const std::string& _id = (*i)->getId();
  155. if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
  156. {
  157. return *i;
  158. }
  159. }
  160. return NULL;
  161. }
  162. Node* GPBFile::getNode(const char* id)
  163. {
  164. if (!id)
  165. return NULL;
  166. // TODO: O(n) search is not ideal
  167. for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
  168. {
  169. const std::string& _id = (*i)->getId();
  170. if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
  171. {
  172. return *i;
  173. }
  174. }
  175. return NULL;
  176. }
  177. void GPBFile::adjust()
  178. {
  179. // calculate the ambient color for each scene
  180. for (std::list<Object*>::iterator i = _objects.begin(); i != _objects.end(); ++i)
  181. {
  182. Object* obj = *i;
  183. if (obj->getTypeId() == Object::SCENE_ID)
  184. {
  185. Scene* scene = dynamic_cast<Scene*>(obj);
  186. scene->calcAmbientColor();
  187. }
  188. }
  189. // TODO:
  190. // remove ambient _lights
  191. // for each node
  192. // if node has ambient light
  193. // if node has no camera, mesh or children but 1 ambient light
  194. // delete node and remove from ref table
  195. // delete light and remove from ref table
  196. //
  197. // merge animations if possible
  198. // Search for animations that have the same target and key times and see if they can be merged.
  199. // Blender will output a simple translation animation to 3 separate animations with the same key times but targetting X, Y and Z.
  200. // This can be merged into one animation. Same for scale animations.
  201. }
  202. }