CmVertexDeclaration.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. #include "CmVertexDeclaration.h"
  2. #include "CmVertexDeclarationRTTI.h"
  3. #include "CmHardwareBufferManager.h"
  4. #include "CmRenderSystem.h"
  5. #include "CmUtil.h"
  6. namespace CamelotFramework
  7. {
  8. VertexElement::VertexElement(unsigned short source, UINT32 offset,
  9. VertexElementType theType, VertexElementSemantic semantic, unsigned short index)
  10. : mSource(source), mOffset(offset), mType(theType),
  11. mSemantic(semantic), mIndex(index)
  12. {
  13. }
  14. //-----------------------------------------------------------------------------
  15. UINT32 VertexElement::getSize(void) const
  16. {
  17. return getTypeSize(mType);
  18. }
  19. //-----------------------------------------------------------------------------
  20. UINT32 VertexElement::getTypeSize(VertexElementType etype)
  21. {
  22. switch(etype)
  23. {
  24. case VET_COLOR:
  25. case VET_COLOR_ABGR:
  26. case VET_COLOR_ARGB:
  27. return sizeof(RGBA);
  28. case VET_FLOAT1:
  29. return sizeof(float);
  30. case VET_FLOAT2:
  31. return sizeof(float)*2;
  32. case VET_FLOAT3:
  33. return sizeof(float)*3;
  34. case VET_FLOAT4:
  35. return sizeof(float)*4;
  36. case VET_SHORT1:
  37. return sizeof(short);
  38. case VET_SHORT2:
  39. return sizeof(short)*2;
  40. case VET_SHORT3:
  41. return sizeof(short)*3;
  42. case VET_SHORT4:
  43. return sizeof(short)*4;
  44. case VET_UBYTE4:
  45. return sizeof(unsigned char)*4;
  46. }
  47. return 0;
  48. }
  49. //-----------------------------------------------------------------------------
  50. unsigned short VertexElement::getTypeCount(VertexElementType etype)
  51. {
  52. switch (etype)
  53. {
  54. case VET_COLOR:
  55. case VET_COLOR_ABGR:
  56. case VET_COLOR_ARGB:
  57. return 4;
  58. case VET_FLOAT1:
  59. return 1;
  60. case VET_FLOAT2:
  61. return 2;
  62. case VET_FLOAT3:
  63. return 3;
  64. case VET_FLOAT4:
  65. return 4;
  66. case VET_SHORT1:
  67. return 1;
  68. case VET_SHORT2:
  69. return 2;
  70. case VET_SHORT3:
  71. return 3;
  72. case VET_SHORT4:
  73. return 4;
  74. case VET_UBYTE4:
  75. return 4;
  76. }
  77. CM_EXCEPT(InvalidParametersException, "Invalid type");
  78. }
  79. //-----------------------------------------------------------------------------
  80. VertexElementType VertexElement::multiplyTypeCount(VertexElementType baseType,
  81. unsigned short count)
  82. {
  83. switch (baseType)
  84. {
  85. case VET_FLOAT1:
  86. switch(count)
  87. {
  88. case 1:
  89. return VET_FLOAT1;
  90. case 2:
  91. return VET_FLOAT2;
  92. case 3:
  93. return VET_FLOAT3;
  94. case 4:
  95. return VET_FLOAT4;
  96. default:
  97. break;
  98. }
  99. break;
  100. case VET_SHORT1:
  101. switch(count)
  102. {
  103. case 1:
  104. return VET_SHORT1;
  105. case 2:
  106. return VET_SHORT2;
  107. case 3:
  108. return VET_SHORT3;
  109. case 4:
  110. return VET_SHORT4;
  111. default:
  112. break;
  113. }
  114. break;
  115. default:
  116. break;
  117. }
  118. CM_EXCEPT(InvalidParametersException, "Invalid base type");
  119. }
  120. //--------------------------------------------------------------------------
  121. VertexElementType VertexElement::getBestColourVertexElementType(void)
  122. {
  123. // Use the current render system to determine if possible
  124. if (CamelotFramework::RenderSystem::instancePtr())
  125. {
  126. return CamelotFramework::RenderSystem::instancePtr()->getColorVertexElementType();
  127. }
  128. else
  129. {
  130. // We can't know the specific type right now, so pick a type
  131. // based on platform
  132. #if CM_PLATFORM == CM_PLATFORM_WIN32
  133. return VET_COLOR_ARGB; // prefer D3D format on windows
  134. #else
  135. return VET_COLOR_ABGR; // prefer GL format on everything else
  136. #endif
  137. }
  138. }
  139. //--------------------------------------------------------------------------
  140. void VertexElement::convertColourValue(VertexElementType srcType,
  141. VertexElementType dstType, UINT32* ptr)
  142. {
  143. if (srcType == dstType)
  144. return;
  145. // Conversion between ARGB and ABGR is always a case of flipping R/B
  146. *ptr =
  147. ((*ptr&0x00FF0000)>>16)|((*ptr&0x000000FF)<<16)|(*ptr&0xFF00FF00);
  148. }
  149. //--------------------------------------------------------------------------
  150. UINT32 VertexElement::convertColourValue(const Color& src,
  151. VertexElementType dst)
  152. {
  153. switch(dst)
  154. {
  155. #if CM_PLATFORM == CM_PLATFORM_WIN32
  156. default:
  157. #endif
  158. case VET_COLOR_ARGB:
  159. return src.getAsARGB();
  160. #if CM_PLATFORM != CM_PLATFORM_WIN32
  161. default:
  162. #endif
  163. case VET_COLOR_ABGR:
  164. return src.getAsABGR();
  165. };
  166. }
  167. //-----------------------------------------------------------------------------
  168. VertexElementType VertexElement::getBaseType(VertexElementType multiType)
  169. {
  170. switch (multiType)
  171. {
  172. case VET_FLOAT1:
  173. case VET_FLOAT2:
  174. case VET_FLOAT3:
  175. case VET_FLOAT4:
  176. return VET_FLOAT1;
  177. case VET_COLOR:
  178. return VET_COLOR;
  179. case VET_COLOR_ABGR:
  180. return VET_COLOR_ABGR;
  181. case VET_COLOR_ARGB:
  182. return VET_COLOR_ARGB;
  183. case VET_SHORT1:
  184. case VET_SHORT2:
  185. case VET_SHORT3:
  186. case VET_SHORT4:
  187. return VET_SHORT1;
  188. case VET_UBYTE4:
  189. return VET_UBYTE4;
  190. };
  191. // To keep compiler happy
  192. return VET_FLOAT1;
  193. }
  194. //-----------------------------------------------------------------------------
  195. size_t VertexElement::calculateHash() const
  196. {
  197. size_t hash = 0;
  198. hash_combine(hash, mSource);
  199. hash_combine(hash, mOffset);
  200. hash_combine(hash, mType);
  201. hash_combine(hash, mSemantic);
  202. hash_combine(hash, mIndex);
  203. return hash;
  204. }
  205. //-----------------------------------------------------------------------------
  206. VertexDeclaration::VertexDeclaration()
  207. :mHash(0)
  208. {
  209. }
  210. //-----------------------------------------------------------------------------
  211. VertexDeclaration::~VertexDeclaration()
  212. {
  213. }
  214. //-----------------------------------------------------------------------------
  215. const VertexDeclaration::VertexElementList& VertexDeclaration::getElements(void) const
  216. {
  217. return mElementList;
  218. }
  219. //-----------------------------------------------------------------------------
  220. const VertexElement& VertexDeclaration::addElement(unsigned short source,
  221. UINT32 offset, VertexElementType theType,
  222. VertexElementSemantic semantic, unsigned short index)
  223. {
  224. // Refine colour type to a specific type
  225. if (theType == VET_COLOR)
  226. {
  227. theType = VertexElement::getBestColourVertexElementType();
  228. }
  229. mElementList.push_back(
  230. VertexElement(source, offset, theType, semantic, index)
  231. );
  232. recalculateHash();
  233. return mElementList.back();
  234. }
  235. //-----------------------------------------------------------------------------
  236. const VertexElement& VertexDeclaration::insertElement(unsigned short atPosition,
  237. unsigned short source, UINT32 offset, VertexElementType theType,
  238. VertexElementSemantic semantic, unsigned short index)
  239. {
  240. if (atPosition >= mElementList.size())
  241. {
  242. return addElement(source, offset, theType, semantic, index);
  243. }
  244. VertexElementList::iterator i = mElementList.begin();
  245. for (unsigned short n = 0; n < atPosition; ++n)
  246. ++i;
  247. i = mElementList.insert(i,
  248. VertexElement(source, offset, theType, semantic, index));
  249. recalculateHash();
  250. return *i;
  251. }
  252. //-----------------------------------------------------------------------------
  253. const VertexElement* VertexDeclaration::getElement(unsigned short index)
  254. {
  255. assert(index < mElementList.size() && "Index out of bounds");
  256. VertexElementList::iterator i = mElementList.begin();
  257. for (unsigned short n = 0; n < index; ++n)
  258. ++i;
  259. return &(*i);
  260. }
  261. //-----------------------------------------------------------------------------
  262. void VertexDeclaration::removeElement(unsigned short elem_index)
  263. {
  264. assert(elem_index < mElementList.size() && "Index out of bounds");
  265. VertexElementList::iterator i = mElementList.begin();
  266. for (unsigned short n = 0; n < elem_index; ++n)
  267. ++i;
  268. mElementList.erase(i);
  269. recalculateHash();
  270. }
  271. //-----------------------------------------------------------------------------
  272. void VertexDeclaration::removeElement(VertexElementSemantic semantic, unsigned short index)
  273. {
  274. VertexElementList::iterator ei, eiend;
  275. eiend = mElementList.end();
  276. for (ei = mElementList.begin(); ei != eiend; ++ei)
  277. {
  278. if (ei->getSemantic() == semantic && ei->getSemanticIdx() == index)
  279. {
  280. mElementList.erase(ei);
  281. break;
  282. }
  283. }
  284. recalculateHash();
  285. }
  286. //-----------------------------------------------------------------------------
  287. void VertexDeclaration::removeAllElements(void)
  288. {
  289. mElementList.clear();
  290. recalculateHash();
  291. }
  292. //-----------------------------------------------------------------------------
  293. void VertexDeclaration::modifyElement(unsigned short elem_index,
  294. unsigned short source, UINT32 offset, VertexElementType theType,
  295. VertexElementSemantic semantic, unsigned short index)
  296. {
  297. assert(elem_index < mElementList.size() && "Index out of bounds");
  298. VertexElementList::iterator i = mElementList.begin();
  299. std::advance(i, elem_index);
  300. (*i) = VertexElement(source, offset, theType, semantic, index);
  301. recalculateHash();
  302. }
  303. //-----------------------------------------------------------------------------
  304. const VertexElement* VertexDeclaration::findElementBySemantic(
  305. VertexElementSemantic sem, unsigned short index)
  306. {
  307. VertexElementList::const_iterator ei, eiend;
  308. eiend = mElementList.end();
  309. for (ei = mElementList.begin(); ei != eiend; ++ei)
  310. {
  311. if (ei->getSemantic() == sem && ei->getSemanticIdx() == index)
  312. {
  313. return &(*ei);
  314. }
  315. }
  316. return NULL;
  317. }
  318. //-----------------------------------------------------------------------------
  319. VertexDeclaration::VertexElementList VertexDeclaration::findElementsBySource(
  320. unsigned short source)
  321. {
  322. VertexElementList retList;
  323. VertexElementList::const_iterator ei, eiend;
  324. eiend = mElementList.end();
  325. for (ei = mElementList.begin(); ei != eiend; ++ei)
  326. {
  327. if (ei->getStreamIdx() == source)
  328. {
  329. retList.push_back(*ei);
  330. }
  331. }
  332. return retList;
  333. }
  334. //-----------------------------------------------------------------------------
  335. UINT32 VertexDeclaration::getVertexSize(unsigned short source)
  336. {
  337. VertexElementList::const_iterator i, iend;
  338. iend = mElementList.end();
  339. UINT32 sz = 0;
  340. for (i = mElementList.begin(); i != iend; ++i)
  341. {
  342. if (i->getStreamIdx() == source)
  343. {
  344. sz += i->getSize();
  345. }
  346. }
  347. return sz;
  348. }
  349. //-----------------------------------------------------------------------------
  350. VertexDeclarationPtr VertexDeclaration::clone(HardwareBufferManager* mgr)
  351. {
  352. HardwareBufferManager* pManager = mgr ? mgr : HardwareBufferManager::instancePtr();
  353. VertexDeclarationPtr ret = pManager->createVertexDeclaration();
  354. VertexElementList::const_iterator i, iend;
  355. iend = mElementList.end();
  356. for (i = mElementList.begin(); i != iend; ++i)
  357. {
  358. ret->addElement(i->getStreamIdx(), i->getOffset(), i->getType(), i->getSemantic(), i->getSemanticIdx());
  359. }
  360. ret->mHash = mHash;
  361. return ret;
  362. }
  363. //-----------------------------------------------------------------------------
  364. // Sort routine for VertexElement
  365. bool VertexDeclaration::vertexElementLess(const VertexElement& e1, const VertexElement& e2)
  366. {
  367. // Sort by source first
  368. if (e1.getStreamIdx() < e2.getStreamIdx())
  369. {
  370. return true;
  371. }
  372. else if (e1.getStreamIdx() == e2.getStreamIdx())
  373. {
  374. // Use ordering of semantics to sort
  375. if (e1.getSemantic() < e2.getSemantic())
  376. {
  377. return true;
  378. }
  379. else if (e1.getSemantic() == e2.getSemantic())
  380. {
  381. // Use index to sort
  382. if (e1.getSemanticIdx() < e2.getSemanticIdx())
  383. {
  384. return true;
  385. }
  386. }
  387. }
  388. return false;
  389. }
  390. void VertexDeclaration::sort(void)
  391. {
  392. mElementList.sort(VertexDeclaration::vertexElementLess);
  393. }
  394. //-----------------------------------------------------------------------------
  395. void VertexDeclaration::closeGapsInSource(void)
  396. {
  397. if (mElementList.empty())
  398. return;
  399. // Sort first
  400. sort();
  401. VertexElementList::iterator i, iend;
  402. iend = mElementList.end();
  403. unsigned short targetIdx = 0;
  404. unsigned short lastIdx = getElement(0)->getStreamIdx();
  405. unsigned short c = 0;
  406. for (i = mElementList.begin(); i != iend; ++i, ++c)
  407. {
  408. VertexElement& elem = *i;
  409. if (lastIdx != elem.getStreamIdx())
  410. {
  411. targetIdx++;
  412. lastIdx = elem.getStreamIdx();
  413. }
  414. if (targetIdx != elem.getStreamIdx())
  415. {
  416. modifyElement(c, targetIdx, elem.getOffset(), elem.getType(),
  417. elem.getSemantic(), elem.getSemanticIdx());
  418. }
  419. }
  420. }
  421. //-----------------------------------------------------------------------------
  422. unsigned short VertexDeclaration::getMaxSource(void) const
  423. {
  424. VertexElementList::const_iterator i, iend;
  425. iend = mElementList.end();
  426. unsigned short ret = 0;
  427. for (i = mElementList.begin(); i != iend; ++i)
  428. {
  429. if (i->getStreamIdx() > ret)
  430. {
  431. ret = i->getStreamIdx();
  432. }
  433. }
  434. return ret;
  435. }
  436. //----------------------------------------------------------------------------
  437. void VertexDeclaration::recalculateHash()
  438. {
  439. mHash = 0;
  440. for(auto iter = mElementList.begin(); iter != mElementList.end(); ++iter)
  441. {
  442. hash_combine(mHash, iter->calculateHash());
  443. }
  444. }
  445. /************************************************************************/
  446. /* SERIALIZATION */
  447. /************************************************************************/
  448. RTTITypeBase* VertexDeclaration::getRTTIStatic()
  449. {
  450. return VertexDeclarationRTTI::instance();
  451. }
  452. RTTITypeBase* VertexDeclaration::getRTTI() const
  453. {
  454. return getRTTIStatic();
  455. }
  456. }