Model.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*
  2. * Model.cpp
  3. */
  4. #include "Base.h"
  5. #include "Model.h"
  6. #include "MeshPart.h"
  7. #include "Scene.h"
  8. #include "Technique.h"
  9. #include "Pass.h"
  10. namespace gameplay
  11. {
  12. Model::Model(Mesh* mesh) :
  13. _mesh(mesh), _material(NULL), _partCount(0), _partMaterials(NULL), _node(NULL), _skin(NULL)
  14. {
  15. _partCount = mesh->getPartCount();
  16. }
  17. Model::~Model()
  18. {
  19. SAFE_RELEASE(_material);
  20. if (_partMaterials)
  21. {
  22. for (unsigned int i = 0; i < _partCount; ++i)
  23. {
  24. SAFE_RELEASE(_partMaterials[i]);
  25. }
  26. SAFE_DELETE_ARRAY(_partMaterials);
  27. }
  28. SAFE_RELEASE(_mesh);
  29. SAFE_DELETE(_skin);
  30. }
  31. Model* Model::create(Mesh* mesh)
  32. {
  33. mesh->addRef();
  34. return new Model(mesh);
  35. }
  36. Mesh* Model::getMesh()
  37. {
  38. return _mesh;
  39. }
  40. unsigned int Model::getMeshPartCount() const
  41. {
  42. return _mesh->getPartCount();
  43. }
  44. Material* Model::getMaterial(int partIndex)
  45. {
  46. assert(partIndex == -1 || (partIndex >= 0 && partIndex < (int)getMeshPartCount()));
  47. Material* m = NULL;
  48. if (partIndex >= 0 && partIndex < (int)_partCount)
  49. {
  50. // Look up explicitly specified part material.
  51. if (_partMaterials)
  52. {
  53. m = _partMaterials[partIndex];
  54. }
  55. }
  56. if (m == NULL)
  57. {
  58. // Return the shared material.
  59. m = _material;
  60. }
  61. return m;
  62. }
  63. void Model::setMaterial(Material* material, int partIndex)
  64. {
  65. assert(partIndex == -1 || (partIndex >= 0 && partIndex < (int)getMeshPartCount()));
  66. if (partIndex == -1)
  67. {
  68. // Release existing shared material and binding.
  69. if (_material)
  70. {
  71. _material->setMeshBinding(NULL);
  72. SAFE_RELEASE(_material);
  73. }
  74. // Set new shared material.
  75. if (material)
  76. {
  77. _material = material;
  78. _material->addRef();
  79. _material->setMeshBinding(_mesh);
  80. }
  81. }
  82. else if (partIndex >= 0 && partIndex < (int)getMeshPartCount())
  83. {
  84. // Ensure mesh part count is up-to-date.
  85. validatePartCount();
  86. // Release existing part material and part binding.
  87. if (_partMaterials)
  88. {
  89. if (_partMaterials[partIndex])
  90. {
  91. _partMaterials[partIndex]->setMeshBinding(NULL);
  92. SAFE_RELEASE(_partMaterials[partIndex]);
  93. }
  94. }
  95. else
  96. {
  97. // Allocate part arrays for the first time.
  98. if (_partMaterials == NULL)
  99. {
  100. _partMaterials = new Material*[_partCount];
  101. memset(_partMaterials, 0, sizeof(Material*) * _partCount);
  102. }
  103. }
  104. // Set new part material.
  105. if (material)
  106. {
  107. _partMaterials[partIndex] = material;
  108. material->addRef();
  109. material->setMeshBinding(_mesh);
  110. }
  111. }
  112. // Apply node binding for the new material.
  113. if (material && _node)
  114. {
  115. setMaterialNodeBinding(material);
  116. }
  117. }
  118. Material* Model::setMaterial(const char* vshPath, const char* fshPath, const char* defines, int partIndex)
  119. {
  120. // Try to create a Material with the given parameters.
  121. Material* material = Material::create(vshPath, fshPath, defines);
  122. if (material == NULL)
  123. {
  124. return NULL;
  125. }
  126. // Assign the material to us.
  127. setMaterial(material, partIndex);
  128. // Release the material since we now have a reference to it.
  129. material->release();
  130. return material;
  131. }
  132. Material* Model::setMaterial(const char* materialPath, int partIndex)
  133. {
  134. // Try to create a Material from the specified material file.
  135. Material* material = Material::create(materialPath);
  136. if (material == NULL)
  137. {
  138. return NULL;
  139. }
  140. // Assign the material to us
  141. setMaterial(material, partIndex);
  142. // Release the material since we now have a reference to it
  143. material->release();
  144. return material;
  145. }
  146. MeshSkin* Model::getSkin()
  147. {
  148. return _skin;
  149. }
  150. void Model::setSkin(MeshSkin* skin)
  151. {
  152. if (_skin != skin)
  153. {
  154. // Free the old skin
  155. SAFE_DELETE(_skin);
  156. // Assign the new skin
  157. _skin = skin;
  158. _skin->_model = this;
  159. }
  160. }
  161. Node* Model::getNode() const
  162. {
  163. return _node;
  164. }
  165. void Model::setNode(Node* node)
  166. {
  167. if (_node != node)
  168. {
  169. SAFE_RELEASE(_node);
  170. _node = node;
  171. if (_node)
  172. {
  173. node->addRef();
  174. }
  175. }
  176. // Re-bind node related material parameters
  177. if (node)
  178. {
  179. if (_material)
  180. {
  181. setMaterialNodeBinding(_material);
  182. }
  183. if (_partMaterials)
  184. {
  185. for (unsigned int i = 0; i < _partCount; ++i)
  186. {
  187. if (_partMaterials[i])
  188. {
  189. setMaterialNodeBinding(_partMaterials[i]);
  190. }
  191. }
  192. }
  193. }
  194. }
  195. void Model::draw(bool wireframe)
  196. {
  197. unsigned int count = _mesh->getPartCount();
  198. if (count == 0)
  199. {
  200. // No mesh parts (index buffers).
  201. if (_material)
  202. {
  203. Technique* technique = _material->getTechnique();
  204. for (unsigned int i = 0, count = technique->getPassCount(); i < count; ++i)
  205. {
  206. Pass* pass = technique->getPass(i);
  207. pass->bind();
  208. if (wireframe)
  209. {
  210. for (unsigned int i = 0, count = _mesh->getVertexCount(); i < count; i += 3)
  211. {
  212. GL_ASSERT( glDrawArrays(GL_LINE_LOOP, i, 3) );
  213. }
  214. }
  215. else
  216. {
  217. GL_ASSERT( glDrawArrays(_mesh->getPrimitiveType(), 0, _mesh->getVertexCount()) );
  218. }
  219. pass->unbind();
  220. }
  221. }
  222. }
  223. else
  224. {
  225. for (unsigned int i = 0; i < count; ++i)
  226. {
  227. MeshPart* part = _mesh->getPart(i);
  228. // Get the material for this mesh part.
  229. Material* material;
  230. if (_partMaterials && i < _partCount && _partMaterials[i])
  231. {
  232. material = _partMaterials[i]; // Use part material
  233. }
  234. else
  235. {
  236. material = _material; // Use shared material
  237. }
  238. if (material)
  239. {
  240. Technique* technique = material->getTechnique();
  241. for (unsigned int i = 0, count = technique->getPassCount(); i < count; ++i)
  242. {
  243. Pass* pass = technique->getPass(i);
  244. pass->bind();
  245. GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, part->_indexBuffer) );
  246. if (wireframe)
  247. {
  248. for (unsigned int i = 0, count = part->getIndexCount(); i < count; i += 3)
  249. {
  250. GL_ASSERT( glDrawElements(GL_LINE_LOOP, 3, part->getIndexFormat(), (const GLvoid*)i) );
  251. }
  252. }
  253. else
  254. {
  255. GL_ASSERT( glDrawElements(part->getPrimitiveType(), part->getIndexCount(), part->getIndexFormat(), 0) );
  256. }
  257. pass->unbind();
  258. }
  259. }
  260. }
  261. }
  262. }
  263. void Model::validatePartCount()
  264. {
  265. unsigned int partCount = _mesh->getPartCount();
  266. if (_partCount != partCount)
  267. {
  268. // Allocate new arrays and copy old items to them.
  269. if (_partMaterials)
  270. {
  271. Material** oldArray = _partMaterials;
  272. _partMaterials = new Material*[partCount];
  273. memset(_partMaterials, 0, sizeof(Material*) * partCount);
  274. for (unsigned int i = 0; i < _partCount; ++i)
  275. {
  276. _partMaterials[i] = oldArray[i];
  277. }
  278. SAFE_DELETE_ARRAY(oldArray);
  279. }
  280. // Update local part count.
  281. _partCount = _mesh->getPartCount();
  282. }
  283. }
  284. void Model::setMaterialNodeBinding(Material *material)
  285. {
  286. if (_node)
  287. {
  288. material->setNodeBinding(_node);
  289. unsigned int techniqueCount = material->getTechniqueCount();
  290. for (unsigned int i = 0; i < techniqueCount; ++i)
  291. {
  292. Technique* technique = material->getTechnique(i);
  293. technique->setNodeBinding(_node);
  294. unsigned int passCount = technique->getPassCount();
  295. for (unsigned int j = 0; j < passCount; ++j)
  296. {
  297. Pass* pass = technique->getPass(j);
  298. pass->setNodeBinding(_node);
  299. }
  300. }
  301. }
  302. }
  303. }