CmVertexIndexData.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. /*
  2. -----------------------------------------------------------------------------
  3. This source file is part of OGRE
  4. (Object-oriented Graphics Rendering Engine)
  5. For the latest info, see http://www.ogre3d.org/
  6. Copyright (c) 2000-2011 Torus Knot Software Ltd
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. -----------------------------------------------------------------------------
  23. */
  24. #include "CmVertexIndexData.h"
  25. #include "CmHardwareBufferManager.h"
  26. #include "CmHardwareVertexBuffer.h"
  27. #include "CmHardwareIndexBuffer.h"
  28. #include "CmVector3.h"
  29. #include "CmAxisAlignedBox.h"
  30. #include "CmException.h"
  31. #include "CmRenderSystem.h"
  32. #include "CmRenderSystemManager.h"
  33. namespace CamelotEngine {
  34. //-----------------------------------------------------------------------
  35. VertexData::VertexData(HardwareBufferManagerBase* mgr)
  36. {
  37. mMgr = mgr ? mgr : HardwareBufferManager::instancePtr();
  38. vertexBufferBinding = mMgr->createVertexBufferBinding();
  39. vertexDeclaration = mMgr->createVertexDeclaration();
  40. mDeleteDclBinding = true;
  41. vertexCount = 0;
  42. vertexStart = 0;
  43. }
  44. //---------------------------------------------------------------------
  45. VertexData::VertexData(VertexDeclarationPtr dcl, VertexBufferBinding* bind)
  46. {
  47. // this is a fallback rather than actively used
  48. mMgr = HardwareBufferManager::instancePtr();
  49. vertexDeclaration = dcl;
  50. vertexBufferBinding = bind;
  51. mDeleteDclBinding = false;
  52. vertexCount = 0;
  53. vertexStart = 0;
  54. }
  55. //-----------------------------------------------------------------------
  56. VertexData::~VertexData()
  57. {
  58. if (mDeleteDclBinding)
  59. {
  60. mMgr->destroyVertexBufferBinding(vertexBufferBinding);
  61. }
  62. }
  63. //-----------------------------------------------------------------------
  64. VertexData* VertexData::clone(bool copyData, HardwareBufferManagerBase* mgr) const
  65. {
  66. HardwareBufferManagerBase* pManager = mgr ? mgr : mMgr;
  67. VertexData* dest = new VertexData(mgr);
  68. // Copy vertex buffers in turn
  69. const VertexBufferBinding::VertexBufferBindingMap& bindings =
  70. this->vertexBufferBinding->getBindings();
  71. VertexBufferBinding::VertexBufferBindingMap::const_iterator vbi, vbend;
  72. vbend = bindings.end();
  73. for (vbi = bindings.begin(); vbi != vbend; ++vbi)
  74. {
  75. HardwareVertexBufferPtr srcbuf = vbi->second;
  76. HardwareVertexBufferPtr dstBuf;
  77. if (copyData)
  78. {
  79. // create new buffer with the same settings
  80. dstBuf = pManager->createVertexBuffer(
  81. srcbuf->getVertexSize(), srcbuf->getNumVertices(), srcbuf->getUsage());
  82. // copy data
  83. dstBuf->copyData(*srcbuf, 0, 0, srcbuf->getSizeInBytes(), true);
  84. }
  85. else
  86. {
  87. // don't copy, point at existing buffer
  88. dstBuf = srcbuf;
  89. }
  90. // Copy binding
  91. dest->vertexBufferBinding->setBinding(vbi->first, dstBuf);
  92. }
  93. // Basic vertex info
  94. dest->vertexStart = this->vertexStart;
  95. dest->vertexCount = this->vertexCount;
  96. // Copy elements
  97. const VertexDeclaration::VertexElementList elems =
  98. this->vertexDeclaration->getElements();
  99. VertexDeclaration::VertexElementList::const_iterator ei, eiend;
  100. eiend = elems.end();
  101. for (ei = elems.begin(); ei != eiend; ++ei)
  102. {
  103. dest->vertexDeclaration->addElement(
  104. ei->getSource(),
  105. ei->getOffset(),
  106. ei->getType(),
  107. ei->getSemantic(),
  108. ei->getIndex() );
  109. }
  110. // Copy reference to hardware shadow buffer, no matter whether copy data or not
  111. dest->hardwareShadowVolWBuffer = hardwareShadowVolWBuffer;
  112. return dest;
  113. }
  114. //-----------------------------------------------------------------------
  115. void VertexData::reorganiseBuffers(VertexDeclarationPtr newDeclaration,
  116. const BufferUsageList& bufferUsages, HardwareBufferManagerBase* mgr)
  117. {
  118. HardwareBufferManagerBase* pManager = mgr ? mgr : mMgr;
  119. // Firstly, close up any gaps in the buffer sources which might have arisen
  120. newDeclaration->closeGapsInSource();
  121. // Build up a list of both old and new elements in each buffer
  122. unsigned short buf = 0;
  123. vector<void*>::type oldBufferLocks;
  124. vector<UINT32>::type oldBufferVertexSizes;
  125. vector<void*>::type newBufferLocks;
  126. vector<UINT32>::type newBufferVertexSizes;
  127. VertexBufferBinding* newBinding = pManager->createVertexBufferBinding();
  128. const VertexBufferBinding::VertexBufferBindingMap& oldBindingMap = vertexBufferBinding->getBindings();
  129. VertexBufferBinding::VertexBufferBindingMap::const_iterator itBinding;
  130. // Pre-allocate old buffer locks
  131. if (!oldBindingMap.empty())
  132. {
  133. UINT32 count = oldBindingMap.rbegin()->first + 1;
  134. oldBufferLocks.resize(count);
  135. oldBufferVertexSizes.resize(count);
  136. }
  137. // Lock all the old buffers for reading
  138. for (itBinding = oldBindingMap.begin(); itBinding != oldBindingMap.end(); ++itBinding)
  139. {
  140. assert(itBinding->second->getNumVertices() >= vertexCount);
  141. oldBufferVertexSizes[itBinding->first] =
  142. itBinding->second->getVertexSize();
  143. oldBufferLocks[itBinding->first] =
  144. itBinding->second->lock(
  145. HardwareBuffer::HBL_READ_ONLY);
  146. }
  147. // Create new buffers and lock all for writing
  148. buf = 0;
  149. while (!newDeclaration->findElementsBySource(buf).empty())
  150. {
  151. UINT32 vertexSize = newDeclaration->getVertexSize(buf);
  152. HardwareVertexBufferPtr vbuf =
  153. pManager->createVertexBuffer(
  154. vertexSize,
  155. vertexCount,
  156. bufferUsages[buf]);
  157. newBinding->setBinding(buf, vbuf);
  158. newBufferVertexSizes.push_back(vertexSize);
  159. newBufferLocks.push_back(
  160. vbuf->lock(HardwareBuffer::HBL_DISCARD));
  161. buf++;
  162. }
  163. // Map from new to old elements
  164. typedef map<const VertexElement*, const VertexElement*>::type NewToOldElementMap;
  165. NewToOldElementMap newToOldElementMap;
  166. const VertexDeclaration::VertexElementList& newElemList = newDeclaration->getElements();
  167. VertexDeclaration::VertexElementList::const_iterator ei, eiend;
  168. eiend = newElemList.end();
  169. for (ei = newElemList.begin(); ei != eiend; ++ei)
  170. {
  171. // Find corresponding old element
  172. const VertexElement* oldElem =
  173. vertexDeclaration->findElementBySemantic(
  174. (*ei).getSemantic(), (*ei).getIndex());
  175. if (!oldElem)
  176. {
  177. // Error, cannot create new elements with this method
  178. CM_EXCEPT(ItemIdentityException,
  179. "Element not found in old vertex declaration");
  180. }
  181. newToOldElementMap[&(*ei)] = oldElem;
  182. }
  183. // Now iterate over the new buffers, pulling data out of the old ones
  184. // For each vertex
  185. for (UINT32 v = 0; v < vertexCount; ++v)
  186. {
  187. // For each (new) element
  188. for (ei = newElemList.begin(); ei != eiend; ++ei)
  189. {
  190. const VertexElement* newElem = &(*ei);
  191. NewToOldElementMap::iterator noi = newToOldElementMap.find(newElem);
  192. const VertexElement* oldElem = noi->second;
  193. unsigned short oldBufferNo = oldElem->getSource();
  194. unsigned short newBufferNo = newElem->getSource();
  195. void* pSrcBase = static_cast<void*>(
  196. static_cast<unsigned char*>(oldBufferLocks[oldBufferNo])
  197. + v * oldBufferVertexSizes[oldBufferNo]);
  198. void* pDstBase = static_cast<void*>(
  199. static_cast<unsigned char*>(newBufferLocks[newBufferNo])
  200. + v * newBufferVertexSizes[newBufferNo]);
  201. void *pSrc, *pDst;
  202. oldElem->baseVertexPointerToElement(pSrcBase, &pSrc);
  203. newElem->baseVertexPointerToElement(pDstBase, &pDst);
  204. memcpy(pDst, pSrc, newElem->getSize());
  205. }
  206. }
  207. // Unlock all buffers
  208. for (itBinding = oldBindingMap.begin(); itBinding != oldBindingMap.end(); ++itBinding)
  209. {
  210. itBinding->second->unlock();
  211. }
  212. for (buf = 0; buf < newBinding->getBufferCount(); ++buf)
  213. {
  214. newBinding->getBuffer(buf)->unlock();
  215. }
  216. // Delete old binding & declaration
  217. if (mDeleteDclBinding)
  218. {
  219. pManager->destroyVertexBufferBinding(vertexBufferBinding);
  220. }
  221. // Assign new binding and declaration
  222. vertexDeclaration = newDeclaration;
  223. vertexBufferBinding = newBinding;
  224. // after this is complete, new manager should be used
  225. mMgr = pManager;
  226. mDeleteDclBinding = true; // because we created these through a manager
  227. }
  228. //-----------------------------------------------------------------------
  229. void VertexData::reorganiseBuffers(VertexDeclarationPtr newDeclaration, HardwareBufferManagerBase* mgr)
  230. {
  231. // Derive the buffer usages from looking at where the source has come
  232. // from
  233. BufferUsageList usages;
  234. for (unsigned short b = 0; b <= newDeclaration->getMaxSource(); ++b)
  235. {
  236. VertexDeclaration::VertexElementList destElems = newDeclaration->findElementsBySource(b);
  237. // Initialise with most restrictive version
  238. // (not really a usable option, but these flags will be removed)
  239. HardwareBuffer::Usage final = static_cast<HardwareBuffer::Usage>(
  240. HardwareBuffer::HBU_STATIC_WRITE_ONLY | HardwareBuffer::HBU_DISCARDABLE);
  241. VertexDeclaration::VertexElementList::iterator v;
  242. for (v = destElems.begin(); v != destElems.end(); ++v)
  243. {
  244. VertexElement& destelem = *v;
  245. // get source
  246. const VertexElement* srcelem =
  247. vertexDeclaration->findElementBySemantic(
  248. destelem.getSemantic(), destelem.getIndex());
  249. // get buffer
  250. HardwareVertexBufferPtr srcbuf =
  251. vertexBufferBinding->getBuffer(srcelem->getSource());
  252. // improve flexibility only
  253. if (srcbuf->getUsage() & HardwareBuffer::HBU_DYNAMIC)
  254. {
  255. // remove static
  256. final = static_cast<HardwareBuffer::Usage>(
  257. final & ~HardwareBuffer::HBU_STATIC);
  258. // add dynamic
  259. final = static_cast<HardwareBuffer::Usage>(
  260. final | HardwareBuffer::HBU_DYNAMIC);
  261. }
  262. if (!(srcbuf->getUsage() & HardwareBuffer::HBU_WRITE_ONLY))
  263. {
  264. // remove write only
  265. final = static_cast<HardwareBuffer::Usage>(
  266. final & ~HardwareBuffer::HBU_WRITE_ONLY);
  267. }
  268. if (!(srcbuf->getUsage() & HardwareBuffer::HBU_DISCARDABLE))
  269. {
  270. // remove discardable
  271. final = static_cast<HardwareBuffer::Usage>(
  272. final & ~HardwareBuffer::HBU_DISCARDABLE);
  273. }
  274. }
  275. usages.push_back(final);
  276. }
  277. // Call specific method
  278. reorganiseBuffers(newDeclaration, usages, mgr);
  279. }
  280. //-----------------------------------------------------------------------
  281. void VertexData::closeGapsInBindings(void)
  282. {
  283. if (!vertexBufferBinding->hasGaps())
  284. return;
  285. // Check for error first
  286. const VertexDeclaration::VertexElementList& allelems =
  287. vertexDeclaration->getElements();
  288. VertexDeclaration::VertexElementList::const_iterator ai;
  289. for (ai = allelems.begin(); ai != allelems.end(); ++ai)
  290. {
  291. const VertexElement& elem = *ai;
  292. if (!vertexBufferBinding->isBufferBound(elem.getSource()))
  293. {
  294. CM_EXCEPT(ItemIdentityException,
  295. "No buffer is bound to that element source.");
  296. }
  297. }
  298. // Close gaps in the vertex buffer bindings
  299. VertexBufferBinding::BindingIndexMap bindingIndexMap;
  300. vertexBufferBinding->closeGaps(bindingIndexMap);
  301. // Modify vertex elements to reference to new buffer index
  302. unsigned short elemIndex = 0;
  303. for (ai = allelems.begin(); ai != allelems.end(); ++ai, ++elemIndex)
  304. {
  305. const VertexElement& elem = *ai;
  306. VertexBufferBinding::BindingIndexMap::const_iterator it =
  307. bindingIndexMap.find(elem.getSource());
  308. assert(it != bindingIndexMap.end());
  309. UINT16 targetSource = it->second;
  310. if (elem.getSource() != targetSource)
  311. {
  312. vertexDeclaration->modifyElement(elemIndex,
  313. targetSource, elem.getOffset(), elem.getType(),
  314. elem.getSemantic(), elem.getIndex());
  315. }
  316. }
  317. }
  318. //-----------------------------------------------------------------------
  319. void VertexData::removeUnusedBuffers(void)
  320. {
  321. set<UINT16>::type usedBuffers;
  322. // Collect used buffers
  323. const VertexDeclaration::VertexElementList& allelems =
  324. vertexDeclaration->getElements();
  325. VertexDeclaration::VertexElementList::const_iterator ai;
  326. for (ai = allelems.begin(); ai != allelems.end(); ++ai)
  327. {
  328. const VertexElement& elem = *ai;
  329. usedBuffers.insert(elem.getSource());
  330. }
  331. // Unset unused buffer bindings
  332. UINT16 count = vertexBufferBinding->getLastBoundIndex();
  333. for (UINT16 index = 0; index < count; ++index)
  334. {
  335. if (usedBuffers.find(index) == usedBuffers.end() &&
  336. vertexBufferBinding->isBufferBound(index))
  337. {
  338. vertexBufferBinding->unsetBinding(index);
  339. }
  340. }
  341. // Close gaps
  342. closeGapsInBindings();
  343. }
  344. //-----------------------------------------------------------------------
  345. void VertexData::convertPackedColour(
  346. VertexElementType srcType, VertexElementType destType)
  347. {
  348. if (destType != VET_COLOUR_ABGR && destType != VET_COLOUR_ARGB)
  349. {
  350. CM_EXCEPT(InvalidParametersException,
  351. "Invalid destType parameter");
  352. }
  353. if (srcType != VET_COLOUR_ABGR && srcType != VET_COLOUR_ARGB)
  354. {
  355. CM_EXCEPT(InvalidParametersException,
  356. "Invalid srcType parameter");
  357. }
  358. const VertexBufferBinding::VertexBufferBindingMap& bindMap =
  359. vertexBufferBinding->getBindings();
  360. VertexBufferBinding::VertexBufferBindingMap::const_iterator bindi;
  361. for (bindi = bindMap.begin(); bindi != bindMap.end(); ++bindi)
  362. {
  363. VertexDeclaration::VertexElementList elems =
  364. vertexDeclaration->findElementsBySource(bindi->first);
  365. bool conversionNeeded = false;
  366. VertexDeclaration::VertexElementList::iterator elemi;
  367. for (elemi = elems.begin(); elemi != elems.end(); ++elemi)
  368. {
  369. VertexElement& elem = *elemi;
  370. if (elem.getType() == VET_COLOUR ||
  371. ((elem.getType() == VET_COLOUR_ABGR || elem.getType() == VET_COLOUR_ARGB)
  372. && elem.getType() != destType))
  373. {
  374. conversionNeeded = true;
  375. }
  376. }
  377. if (conversionNeeded)
  378. {
  379. void* pBase = bindi->second->lock(HardwareBuffer::HBL_NORMAL);
  380. for (UINT32 v = 0; v < bindi->second->getNumVertices(); ++v)
  381. {
  382. for (elemi = elems.begin(); elemi != elems.end(); ++elemi)
  383. {
  384. VertexElement& elem = *elemi;
  385. VertexElementType currType = (elem.getType() == VET_COLOUR) ?
  386. srcType : elem.getType();
  387. if (elem.getType() == VET_COLOUR ||
  388. ((elem.getType() == VET_COLOUR_ABGR || elem.getType() == VET_COLOUR_ARGB)
  389. && elem.getType() != destType))
  390. {
  391. UINT32* pRGBA;
  392. elem.baseVertexPointerToElement(pBase, &pRGBA);
  393. VertexElement::convertColourValue(currType, destType, pRGBA);
  394. }
  395. }
  396. pBase = static_cast<void*>(
  397. static_cast<char*>(pBase) + bindi->second->getVertexSize());
  398. }
  399. bindi->second->unlock();
  400. // Modify the elements to reflect the changed type
  401. const VertexDeclaration::VertexElementList& allelems =
  402. vertexDeclaration->getElements();
  403. VertexDeclaration::VertexElementList::const_iterator ai;
  404. unsigned short elemIndex = 0;
  405. for (ai = allelems.begin(); ai != allelems.end(); ++ai, ++elemIndex)
  406. {
  407. const VertexElement& elem = *ai;
  408. if (elem.getType() == VET_COLOUR ||
  409. ((elem.getType() == VET_COLOUR_ABGR || elem.getType() == VET_COLOUR_ARGB)
  410. && elem.getType() != destType))
  411. {
  412. vertexDeclaration->modifyElement(elemIndex,
  413. elem.getSource(), elem.getOffset(), destType,
  414. elem.getSemantic(), elem.getIndex());
  415. }
  416. }
  417. }
  418. } // each buffer
  419. }
  420. //-----------------------------------------------------------------------
  421. //-----------------------------------------------------------------------
  422. IndexData::IndexData()
  423. {
  424. indexCount = 0;
  425. indexStart = 0;
  426. }
  427. //-----------------------------------------------------------------------
  428. IndexData::~IndexData()
  429. {
  430. }
  431. //-----------------------------------------------------------------------
  432. IndexData* IndexData::clone(bool copyData, HardwareBufferManagerBase* mgr) const
  433. {
  434. HardwareBufferManagerBase* pManager = mgr ? mgr : HardwareBufferManager::instancePtr();
  435. IndexData* dest = new IndexData();
  436. if (indexBuffer.get())
  437. {
  438. if (copyData)
  439. {
  440. dest->indexBuffer = pManager->createIndexBuffer(indexBuffer->getType(), indexBuffer->getNumIndexes(),
  441. indexBuffer->getUsage());
  442. dest->indexBuffer->copyData(*indexBuffer, 0, 0, indexBuffer->getSizeInBytes(), true);
  443. }
  444. else
  445. {
  446. dest->indexBuffer = indexBuffer;
  447. }
  448. }
  449. dest->indexCount = indexCount;
  450. dest->indexStart = indexStart;
  451. return dest;
  452. }
  453. //-----------------------------------------------------------------------
  454. //-----------------------------------------------------------------------
  455. // Local Utility class for vertex cache optimizer
  456. class Triangle
  457. {
  458. public:
  459. enum EdgeMatchType {
  460. AB, BC, CA, ANY, NONE
  461. };
  462. UINT32 a, b, c;
  463. inline Triangle()
  464. {
  465. }
  466. inline Triangle( UINT32 ta, UINT32 tb, UINT32 tc )
  467. : a( ta ), b( tb ), c( tc )
  468. {
  469. }
  470. inline Triangle( UINT32 t[3] )
  471. : a( t[0] ), b( t[1] ), c( t[2] )
  472. {
  473. }
  474. inline Triangle( const Triangle& t )
  475. : a( t.a ), b( t.b ), c( t.c )
  476. {
  477. }
  478. inline bool sharesEdge(const Triangle& t) const
  479. {
  480. return( a == t.a && b == t.c ||
  481. a == t.b && b == t.a ||
  482. a == t.c && b == t.b ||
  483. b == t.a && c == t.c ||
  484. b == t.b && c == t.a ||
  485. b == t.c && c == t.b ||
  486. c == t.a && a == t.c ||
  487. c == t.b && a == t.a ||
  488. c == t.c && a == t.b );
  489. }
  490. inline bool sharesEdge(const UINT32 ea, const UINT32 eb, const Triangle& t) const
  491. {
  492. return( ea == t.a && eb == t.c ||
  493. ea == t.b && eb == t.a ||
  494. ea == t.c && eb == t.b );
  495. }
  496. inline bool sharesEdge(const EdgeMatchType edge, const Triangle& t) const
  497. {
  498. if (edge == AB)
  499. return sharesEdge(a, b, t);
  500. else if (edge == BC)
  501. return sharesEdge(b, c, t);
  502. else if (edge == CA)
  503. return sharesEdge(c, a, t);
  504. else
  505. return (edge == ANY) == sharesEdge(t);
  506. }
  507. inline EdgeMatchType endoSharedEdge(const Triangle& t) const
  508. {
  509. if (sharesEdge(a, b, t)) return AB;
  510. if (sharesEdge(b, c, t)) return BC;
  511. if (sharesEdge(c, a, t)) return CA;
  512. return NONE;
  513. }
  514. inline EdgeMatchType exoSharedEdge(const Triangle& t) const
  515. {
  516. return t.endoSharedEdge(*this);
  517. }
  518. inline void shiftClockwise()
  519. {
  520. UINT32 t = a;
  521. a = c;
  522. c = b;
  523. b = t;
  524. }
  525. inline void shiftCounterClockwise()
  526. {
  527. UINT32 t = a;
  528. a = b;
  529. b = c;
  530. c = t;
  531. }
  532. };
  533. //-----------------------------------------------------------------------
  534. //-----------------------------------------------------------------------
  535. void IndexData::optimiseVertexCacheTriList(void)
  536. {
  537. if (indexBuffer->isLocked()) return;
  538. void *buffer = indexBuffer->lock(HardwareBuffer::HBL_NORMAL);
  539. Triangle* triangles;
  540. UINT32 *dest;
  541. UINT32 nIndexes = indexCount;
  542. UINT32 nTriangles = nIndexes / 3;
  543. UINT32 i, j;
  544. UINT16 *source = 0;
  545. if (indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT)
  546. {
  547. triangles = (Triangle*) malloc(sizeof(Triangle) * nTriangles);
  548. source = (UINT16 *)buffer;
  549. dest = (UINT32 *)triangles;
  550. for (i = 0; i < nIndexes; ++i) dest[i] = source[i];
  551. }
  552. else
  553. triangles = (Triangle*)buffer;
  554. // sort triangles based on shared edges
  555. UINT32 *destlist = (UINT32*)malloc(sizeof(UINT32) * nTriangles);
  556. unsigned char *visited = (unsigned char*)malloc(sizeof(unsigned char) * nTriangles);
  557. for (i = 0; i < nTriangles; ++i) visited[i] = 0;
  558. UINT32 start = 0, ti = 0, destcount = 0;
  559. bool found = false;
  560. for (i = 0; i < nTriangles; ++i)
  561. {
  562. if (found)
  563. found = false;
  564. else
  565. {
  566. while (visited[start++]);
  567. ti = start - 1;
  568. }
  569. destlist[destcount++] = ti;
  570. visited[ti] = 1;
  571. for (j = start; j < nTriangles; ++j)
  572. {
  573. if (visited[j]) continue;
  574. if (triangles[ti].sharesEdge(triangles[j]))
  575. {
  576. found = true;
  577. ti = static_cast<UINT32>(j);
  578. break;
  579. }
  580. }
  581. }
  582. if (indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT)
  583. {
  584. // reorder the indexbuffer
  585. j = 0;
  586. for (i = 0; i < nTriangles; ++i)
  587. {
  588. Triangle *t = &triangles[destlist[i]];
  589. source[j++] = (UINT16)t->a;
  590. source[j++] = (UINT16)t->b;
  591. source[j++] = (UINT16)t->c;
  592. }
  593. free(triangles);
  594. }
  595. else
  596. {
  597. UINT32 *reflist = (UINT32*)malloc(sizeof(UINT32) * nTriangles);
  598. // fill the referencebuffer
  599. for (i = 0; i < nTriangles; ++i)
  600. reflist[destlist[i]] = static_cast<UINT32>(i);
  601. // reorder the indexbuffer
  602. for (i = 0; i < nTriangles; ++i)
  603. {
  604. j = destlist[i];
  605. if (i == j) continue; // do not move triangle
  606. // swap triangles
  607. Triangle t = triangles[i];
  608. triangles[i] = triangles[j];
  609. triangles[j] = t;
  610. // change reference
  611. destlist[reflist[i]] = static_cast<UINT32>(j);
  612. // destlist[i] = i; // not needed, it will not be used
  613. }
  614. free(reflist);
  615. }
  616. free(destlist);
  617. free(visited);
  618. indexBuffer->unlock();
  619. }
  620. //-----------------------------------------------------------------------
  621. //-----------------------------------------------------------------------
  622. void VertexCacheProfiler::profile(const HardwareIndexBufferPtr& indexBuffer)
  623. {
  624. if (indexBuffer->isLocked()) return;
  625. UINT16 *shortbuffer = (UINT16 *)indexBuffer->lock(HardwareBuffer::HBL_READ_ONLY);
  626. if (indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT)
  627. for (unsigned int i = 0; i < indexBuffer->getNumIndexes(); ++i)
  628. inCache(shortbuffer[i]);
  629. else
  630. {
  631. UINT32 *buffer = (UINT32 *)shortbuffer;
  632. for (unsigned int i = 0; i < indexBuffer->getNumIndexes(); ++i)
  633. inCache(buffer[i]);
  634. }
  635. indexBuffer->unlock();
  636. }
  637. //-----------------------------------------------------------------------
  638. bool VertexCacheProfiler::inCache(unsigned int index)
  639. {
  640. for (unsigned int i = 0; i < buffersize; ++i)
  641. {
  642. if (index == cache[i])
  643. {
  644. hit++;
  645. return true;
  646. }
  647. }
  648. miss++;
  649. cache[tail++] = index;
  650. tail %= size;
  651. if (buffersize < size) buffersize++;
  652. return false;
  653. }
  654. }