CCPUBillboardChain.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. /****************************************************************************
  2. Copyright (C) 2013 Henry van Merode. All rights reserved.
  3. Copyright (c) 2015-2016 Chukong Technologies Inc.
  4. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
  5. http://www.cocos2d-x.org
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12. The above copyright notice and this permission notice shall be included in
  13. all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. THE SOFTWARE.
  21. ****************************************************************************/
  22. #include "extensions/Particle3D/PU/CCPUBillboardChain.h"
  23. #include "extensions/Particle3D/PU/CCPUParticleSystem3D.h"
  24. #include "base/CCDirector.h"
  25. #include "renderer/CCMeshCommand.h"
  26. #include "renderer/CCRenderer.h"
  27. #include "renderer/CCTextureCache.h"
  28. #include "renderer/CCGLProgramState.h"
  29. #include "renderer/CCGLProgramCache.h"
  30. #include "renderer/CCVertexIndexBuffer.h"
  31. #include "renderer/CCVertexAttribBinding.h"
  32. #include "2d/CCCamera.h"
  33. #include "3d/CCSprite3D.h"
  34. NS_CC_BEGIN
  35. const size_t PUBillboardChain::SEGMENT_EMPTY = std::numeric_limits<size_t>::max();
  36. //-----------------------------------------------------------------------
  37. PUBillboardChain::Element::Element()
  38. {
  39. }
  40. //-----------------------------------------------------------------------
  41. PUBillboardChain::Element::Element(const Vec3 &pos,
  42. float w,
  43. float tex,
  44. const Vec4 &col,
  45. const Quaternion &ori) :
  46. position(pos),
  47. width(w),
  48. texCoord(tex),
  49. color(col),
  50. orientation(ori)
  51. {
  52. }
  53. //-----------------------------------------------------------------------
  54. PUBillboardChain::PUBillboardChain(const std::string& /*name*/, const std::string &texFile, size_t maxElements,
  55. size_t numberOfChains, bool useTextureCoords, bool useColours, bool dynamic)
  56. :_maxElementsPerChain(maxElements),
  57. _chainCount(numberOfChains),
  58. _useTexCoords(useTextureCoords),
  59. _useVertexColour(useColours),
  60. _dynamic(dynamic),
  61. _vertexDeclDirty(true),
  62. _buffersNeedRecreating(true),
  63. _boundsDirty(true),
  64. _indexContentDirty(true),
  65. _vertexContentDirty(true),
  66. _texCoordDir(TCD_U),
  67. _faceCamera(true),
  68. _normalBase(Vec3::UNIT_X),
  69. _meshCommand(nullptr),
  70. _texture(nullptr),
  71. _glProgramState(nullptr),
  72. _indexBuffer(nullptr),
  73. _vertexBuffer(nullptr),
  74. _texFile(texFile)
  75. {
  76. _stateBlock = RenderState::StateBlock::create();
  77. CC_SAFE_RETAIN(_stateBlock);
  78. _stateBlock->setCullFace(false);
  79. _stateBlock->setCullFaceSide(RenderState::CULL_FACE_SIDE_BACK);
  80. _stateBlock->setDepthTest(false);
  81. _stateBlock->setDepthWrite(false);
  82. _stateBlock->setBlend(true);
  83. _otherTexCoordRange[0] = 0.0f;
  84. _otherTexCoordRange[1] = 1.0f;
  85. setupChainContainers();
  86. init(texFile);
  87. }
  88. //-----------------------------------------------------------------------
  89. PUBillboardChain::~PUBillboardChain()
  90. {
  91. CC_SAFE_DELETE(_meshCommand);
  92. CC_SAFE_RELEASE(_stateBlock);
  93. //CC_SAFE_RELEASE(_texture);
  94. CC_SAFE_RELEASE(_glProgramState);
  95. CC_SAFE_RELEASE(_vertexBuffer);
  96. CC_SAFE_RELEASE(_indexBuffer);
  97. }
  98. //-----------------------------------------------------------------------
  99. void PUBillboardChain::setupChainContainers(void)
  100. {
  101. // Allocate enough space for everything
  102. _chainElementList.resize(_chainCount * _maxElementsPerChain);
  103. //_vertexData->vertexCount = _chainElementList.size() * 2;
  104. // Configure chains
  105. _chainSegmentList.resize(_chainCount);
  106. for (size_t i = 0; i < _chainCount; ++i)
  107. {
  108. ChainSegment& seg = _chainSegmentList[i];
  109. seg.start = i * _maxElementsPerChain;
  110. seg.tail = seg.head = SEGMENT_EMPTY;
  111. }
  112. }
  113. //-----------------------------------------------------------------------
  114. void PUBillboardChain::setupVertexDeclaration(void)
  115. {
  116. //if (_vertexDeclDirty)
  117. //{
  118. // VertexDeclaration* decl = _vertexData->vertexDeclaration;
  119. // decl->removeAllElements();
  120. // size_t offset = 0;
  121. // // Add a description for the buffer of the positions of the vertices
  122. // decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
  123. // offset += VertexElement::getTypeSize(VET_FLOAT3);
  124. // if (_useVertexColour)
  125. // {
  126. // decl->addElement(0, offset, VET_COLOUR, VES_DIFFUSE);
  127. // offset += VertexElement::getTypeSize(VET_COLOUR);
  128. // }
  129. // if (_useTexCoords)
  130. // {
  131. // decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES);
  132. // }
  133. // if (!_useTexCoords && !_useVertexColour)
  134. // {
  135. // LogManager::getSingleton().logMessage(
  136. // "Error - BillboardChain '" + mName + "' is using neither "
  137. // "texture coordinates or vertex colours; it will not be "
  138. // "visible on some rendering APIs so you should change this "
  139. // "so you use one or the other.");
  140. // }
  141. // _vertexDeclDirty = false;
  142. //}
  143. }
  144. //-----------------------------------------------------------------------
  145. void PUBillboardChain::setupBuffers(void)
  146. {
  147. //setupVertexDeclaration();
  148. if (_buffersNeedRecreating)
  149. {
  150. CC_SAFE_RELEASE(_vertexBuffer);
  151. CC_SAFE_RELEASE(_indexBuffer);
  152. GLsizei stride = sizeof(VertexInfo);
  153. _vertexBuffer = VertexBuffer::create(stride, (int)_chainElementList.size() * 2);
  154. _vertexBuffer->retain();
  155. VertexInfo vi = {Vec3(0.0f, 0.0f, 0.0f), Vec2(0.0f, 0.0f), Vec4::ONE};
  156. _vertices.resize(_chainElementList.size() * 2, vi);
  157. _indexBuffer = IndexBuffer::create(IndexBuffer::IndexType::INDEX_TYPE_SHORT_16, (int)(_chainCount * _maxElementsPerChain * 6));
  158. _indexBuffer->retain();
  159. _indices.resize(_chainCount * _maxElementsPerChain * 6, 0);
  160. //// Create the vertex buffer (always dynamic due to the camera adjust)
  161. //HardwareVertexBufferSharedPtr pBuffer =
  162. // HardwareBufferManager::getSingleton().createVertexBuffer(
  163. // _vertexData->vertexDeclaration->getVertexSize(0),
  164. // _vertexData->vertexCount,
  165. // HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
  166. //// (re)Bind the buffer
  167. //// Any existing buffer will lose its reference count and be destroyed
  168. //_vertexData->vertexBufferBinding->setBinding(0, pBuffer);
  169. //_indexData->indexBuffer =
  170. // HardwareBufferManager::getSingleton().createIndexBuffer(
  171. // HardwareIndexBuffer::IT_16BIT,
  172. // _chainCount * _maxElementsPerChain * 6, // max we can use
  173. // _dynamic? HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY : HardwareBuffer::HBU_STATIC_WRITE_ONLY);
  174. //// NB we don't set the indexCount on IndexData here since we will
  175. //// probably use less than the maximum number of indices
  176. _buffersNeedRecreating = false;
  177. }
  178. }
  179. //-----------------------------------------------------------------------
  180. void PUBillboardChain::setMaxChainElements(size_t maxElements)
  181. {
  182. _maxElementsPerChain = maxElements;
  183. setupChainContainers();
  184. _buffersNeedRecreating = _indexContentDirty = _vertexContentDirty = true;
  185. }
  186. //-----------------------------------------------------------------------
  187. void PUBillboardChain::setNumberOfChains(size_t numChains)
  188. {
  189. _chainCount = numChains;
  190. setupChainContainers();
  191. _buffersNeedRecreating = _indexContentDirty = _vertexContentDirty = true;
  192. }
  193. //-----------------------------------------------------------------------
  194. void PUBillboardChain::setUseTextureCoords(bool use)
  195. {
  196. _useTexCoords = use;
  197. _vertexDeclDirty = _buffersNeedRecreating = true;
  198. _indexContentDirty = _vertexContentDirty = true;
  199. }
  200. //-----------------------------------------------------------------------
  201. void PUBillboardChain::setTextureCoordDirection(PUBillboardChain::TexCoordDirection dir)
  202. {
  203. _texCoordDir = dir;
  204. _vertexContentDirty = true;
  205. }
  206. //-----------------------------------------------------------------------
  207. void PUBillboardChain::setOtherTextureCoordRange(float start, float end)
  208. {
  209. _otherTexCoordRange[0] = start;
  210. _otherTexCoordRange[1] = end;
  211. _vertexContentDirty = true;
  212. }
  213. //-----------------------------------------------------------------------
  214. void PUBillboardChain::setUseVertexColours(bool use)
  215. {
  216. _useVertexColour = use;
  217. _vertexDeclDirty = _buffersNeedRecreating = true;
  218. _indexContentDirty = _vertexContentDirty = true;
  219. }
  220. //-----------------------------------------------------------------------
  221. void PUBillboardChain::setDynamic(bool dyn)
  222. {
  223. _dynamic = dyn;
  224. _buffersNeedRecreating = _indexContentDirty = _vertexContentDirty = true;
  225. }
  226. //-----------------------------------------------------------------------
  227. void PUBillboardChain::addChainElement(size_t chainIndex,
  228. const PUBillboardChain::Element& dtls)
  229. {
  230. CCASSERT(chainIndex < _chainCount, "chainIndex out of bounds");
  231. ChainSegment& seg = _chainSegmentList[chainIndex];
  232. if (seg.head == SEGMENT_EMPTY)
  233. {
  234. // Tail starts at end, head grows backwards
  235. seg.tail = _maxElementsPerChain - 1;
  236. seg.head = seg.tail;
  237. }
  238. else
  239. {
  240. if (seg.head == 0)
  241. {
  242. // Wrap backwards
  243. seg.head = _maxElementsPerChain - 1;
  244. }
  245. else
  246. {
  247. // Just step backward
  248. --seg.head;
  249. }
  250. // Run out of elements?
  251. if (seg.head == seg.tail)
  252. {
  253. // Move tail backwards too, losing the end of the segment and re-using
  254. // it in the head
  255. if (seg.tail == 0)
  256. seg.tail = _maxElementsPerChain - 1;
  257. else
  258. --seg.tail;
  259. }
  260. }
  261. // Set the details
  262. _chainElementList[seg.start + seg.head] = dtls;
  263. _vertexContentDirty = true;
  264. _indexContentDirty = true;
  265. _boundsDirty = true;
  266. //// tell parent node to update bounds
  267. //if (mParentNode)
  268. // mParentNode->needUpdate();
  269. }
  270. //-----------------------------------------------------------------------
  271. void PUBillboardChain::removeChainElement(size_t chainIndex)
  272. {
  273. CCASSERT(chainIndex < _chainCount, "chainIndex out of bounds");
  274. ChainSegment& seg = _chainSegmentList[chainIndex];
  275. if (seg.head == SEGMENT_EMPTY)
  276. return; // do nothing, nothing to remove
  277. if (seg.tail == seg.head)
  278. {
  279. // last item
  280. seg.head = seg.tail = SEGMENT_EMPTY;
  281. }
  282. else if (seg.tail == 0)
  283. {
  284. seg.tail = _maxElementsPerChain - 1;
  285. }
  286. else
  287. {
  288. --seg.tail;
  289. }
  290. // we removed an entry so indexes need updating
  291. _vertexContentDirty = true;
  292. _indexContentDirty = true;
  293. _boundsDirty = true;
  294. //// tell parent node to update bounds
  295. //if (mParentNode)
  296. // mParentNode->needUpdate();
  297. }
  298. //-----------------------------------------------------------------------
  299. void PUBillboardChain::clearChain(size_t chainIndex)
  300. {
  301. CCASSERT(chainIndex < _chainCount, "chainIndex out of bounds");
  302. ChainSegment& seg = _chainSegmentList[chainIndex];
  303. // Just reset head & tail
  304. seg.tail = seg.head = SEGMENT_EMPTY;
  305. // we removed an entry so indexes need updating
  306. _vertexContentDirty = true;
  307. _indexContentDirty = true;
  308. _boundsDirty = true;
  309. //// tell parent node to update bounds
  310. //if (mParentNode)
  311. // mParentNode->needUpdate();
  312. }
  313. //-----------------------------------------------------------------------
  314. void PUBillboardChain::clearAllChains(void)
  315. {
  316. for (size_t i = 0; i < _chainCount; ++i)
  317. {
  318. clearChain(i);
  319. }
  320. }
  321. //-----------------------------------------------------------------------
  322. void PUBillboardChain::setFaceCamera( bool faceCamera, const Vec3 &normalVector )
  323. {
  324. _faceCamera = faceCamera;
  325. _normalBase = normalVector;
  326. _normalBase.normalize();
  327. _vertexContentDirty = true;
  328. }
  329. //-----------------------------------------------------------------------
  330. void PUBillboardChain::updateChainElement(size_t chainIndex, size_t elementIndex,
  331. const PUBillboardChain::Element& dtls)
  332. {
  333. CCASSERT(chainIndex < _chainCount, "chainIndex out of bounds");
  334. ChainSegment& seg = _chainSegmentList[chainIndex];
  335. CCASSERT(seg.head != SEGMENT_EMPTY, "Chain segment is empty");
  336. size_t idx = seg.head + elementIndex;
  337. // adjust for the edge and start
  338. idx = (idx % _maxElementsPerChain) + seg.start;
  339. _chainElementList[idx] = dtls;
  340. _vertexContentDirty = true;
  341. _boundsDirty = true;
  342. //// tell parent node to update bounds
  343. //if (mParentNode)
  344. // mParentNode->needUpdate();
  345. }
  346. //-----------------------------------------------------------------------
  347. const PUBillboardChain::Element&
  348. PUBillboardChain::getChainElement(size_t chainIndex, size_t elementIndex) const
  349. {
  350. CCASSERT(chainIndex < _chainCount, "chainIndex out of bounds");
  351. const ChainSegment& seg = _chainSegmentList[chainIndex];
  352. size_t idx = seg.head + elementIndex;
  353. // adjust for the edge and start
  354. idx = (idx % _maxElementsPerChain) + seg.start;
  355. return _chainElementList[idx];
  356. }
  357. //-----------------------------------------------------------------------
  358. size_t PUBillboardChain::getNumChainElements(size_t chainIndex) const
  359. {
  360. CCASSERT(chainIndex < _chainCount, "chainIndex out of bounds");
  361. const ChainSegment& seg = _chainSegmentList[chainIndex];
  362. if( seg.tail < seg.head )
  363. {
  364. return seg.tail - seg.head + _maxElementsPerChain + 1;
  365. }
  366. else
  367. {
  368. return seg.tail - seg.head + 1;
  369. }
  370. }
  371. //-----------------------------------------------------------------------
  372. void PUBillboardChain::updateVertexBuffer(const Mat4 &camMat)
  373. {
  374. setupBuffers();
  375. // The contents of the vertex buffer are correct if they are not dirty
  376. // and the camera used to build the vertex buffer is still the current
  377. // camera.
  378. if (!_vertexContentDirty)
  379. return;
  380. VertexInfo vi = {Vec3(0.0f, 0.0f, 0.0f), Vec2(0.0f, 0.0f), Vec4::ONE};
  381. _vertices.assign(_vertices.size(), vi);
  382. //HardwareVertexBufferSharedPtr pBuffer =
  383. // _vertexData->vertexBufferBinding->getBuffer(0);
  384. //void* pBufferStart = pBuffer->lock(HardwareBuffer::HBL_DISCARD);
  385. //const Vector3& camPos = cam->getDerivedPosition();
  386. //Vector3 eyePos = mParentNode->_getDerivedOrientation().Inverse() *
  387. // (camPos - mParentNode->_getDerivedPosition()) / mParentNode->_getDerivedScale();
  388. Vec3 eyePos(camMat.m[12], camMat.m[13], camMat.m[14]);
  389. Vec3 chainTangent;
  390. for (ChainSegmentList::iterator segi = _chainSegmentList.begin();
  391. segi != _chainSegmentList.end(); ++segi)
  392. {
  393. ChainSegment& seg = *segi;
  394. // Skip 0 or 1 element segment counts
  395. if (seg.head != SEGMENT_EMPTY && seg.head != seg.tail)
  396. {
  397. size_t laste = seg.head;
  398. for (size_t e = seg.head; ; ++e) // until break
  399. {
  400. // Wrap forwards
  401. if (e == _maxElementsPerChain)
  402. e = 0;
  403. Element& elem = _chainElementList[e + seg.start];
  404. CCASSERT (((e + seg.start) * 2) < 65536, "Too many elements!");
  405. unsigned short vertexIndex = static_cast<unsigned short>((e + seg.start) * 2);
  406. //// Determine base pointer to vertex #1
  407. //void* pBase = static_cast<void*>(
  408. // static_cast<char*>(pBufferStart) +
  409. // pBuffer->getVertexSize() * baseIdx);
  410. // Get index of next item
  411. size_t nexte = e + 1;
  412. if (nexte == _maxElementsPerChain)
  413. nexte = 0;
  414. if (e == seg.head)
  415. {
  416. // No laste, use next item
  417. chainTangent = _chainElementList[nexte + seg.start].position - elem.position;
  418. }
  419. else if (e == seg.tail)
  420. {
  421. // No nexte, use only last item
  422. chainTangent = elem.position - _chainElementList[laste + seg.start].position;
  423. }
  424. else
  425. {
  426. // A mid position, use tangent across both prev and next
  427. chainTangent = _chainElementList[nexte + seg.start].position - _chainElementList[laste + seg.start].position;
  428. }
  429. Vec3 vP1ToEye;
  430. //if( _faceCamera )
  431. vP1ToEye = eyePos - elem.position;
  432. //else
  433. // vP1ToEye = elem.orientation * _normalBase;
  434. Vec3 vPerpendicular;
  435. Vec3::cross(chainTangent, vP1ToEye, &vPerpendicular);
  436. vPerpendicular.normalize();
  437. vPerpendicular *= (elem.width * 0.5f);
  438. Vec3 pos0 = elem.position - vPerpendicular;
  439. Vec3 pos1 = elem.position + vPerpendicular;
  440. //float* pFloat = static_cast<float*>(pBase);
  441. //// pos1
  442. //*pFloat++ = pos0.x;
  443. //*pFloat++ = pos0.y;
  444. //*pFloat++ = pos0.z;
  445. _vertices[vertexIndex + 0].position = pos0;
  446. //pBase = static_cast<void*>(pFloat);
  447. if (_useVertexColour)
  448. {
  449. //RGBA* pCol = static_cast<RGBA*>(pBase);
  450. //Root::getSingleton().convertColourValue(elem.colour, pCol);
  451. //pCol++;
  452. //pBase = static_cast<void*>(pCol);
  453. _vertices[vertexIndex + 0].color = elem.color;
  454. }
  455. if (_useTexCoords)
  456. {
  457. //pFloat = static_cast<float*>(pBase);
  458. if (_texCoordDir == TCD_U)
  459. {
  460. //*pFloat++ = elem.texCoord;
  461. //*pFloat++ = _otherTexCoordRange[0];
  462. _vertices[vertexIndex + 0].uv.x = elem.texCoord;
  463. _vertices[vertexIndex + 0].uv.y = _otherTexCoordRange[0];
  464. }
  465. else
  466. {
  467. //*pFloat++ = _otherTexCoordRange[0];
  468. //*pFloat++ = elem.texCoord;
  469. _vertices[vertexIndex + 0].uv.x = _otherTexCoordRange[0];
  470. _vertices[vertexIndex + 0].uv.y = elem.texCoord;
  471. }
  472. //pBase = static_cast<void*>(pFloat);
  473. }
  474. // pos2
  475. //pFloat = static_cast<float*>(pBase);
  476. //*pFloat++ = pos1.x;
  477. //*pFloat++ = pos1.y;
  478. //*pFloat++ = pos1.z;
  479. //pBase = static_cast<void*>(pFloat);
  480. _vertices[vertexIndex + 1].position = pos1;
  481. if (_useVertexColour)
  482. {
  483. //RGBA* pCol = static_cast<RGBA*>(pBase);
  484. //Root::getSingleton().convertColourValue(elem.colour, pCol);
  485. //pCol++;
  486. //pBase = static_cast<void*>(pCol);
  487. _vertices[vertexIndex + 1].color = elem.color;
  488. }
  489. if (_useTexCoords)
  490. {
  491. //pFloat = static_cast<float*>(pBase);
  492. if (_texCoordDir == TCD_U)
  493. {
  494. //*pFloat++ = elem.texCoord;
  495. //*pFloat++ = _otherTexCoordRange[1];
  496. _vertices[vertexIndex + 1].uv.x = elem.texCoord;
  497. _vertices[vertexIndex + 1].uv.y = _otherTexCoordRange[1];
  498. }
  499. else
  500. {
  501. //*pFloat++ = _otherTexCoordRange[1];
  502. //*pFloat++ = elem.texCoord;
  503. _vertices[vertexIndex + 1].uv.x = _otherTexCoordRange[1];
  504. _vertices[vertexIndex + 1].uv.y = elem.texCoord;
  505. }
  506. }
  507. if (e == seg.tail)
  508. break; // last one
  509. laste = e;
  510. //vertexIndex += 2;
  511. } // element
  512. } // segment valid?
  513. } // each segment
  514. _vertexBuffer->updateVertices(&_vertices[0], (int)_vertices.size(), 0);
  515. //pBuffer->unlock();
  516. //_vertexCameraUsed = cam;
  517. _vertexContentDirty = false;
  518. }
  519. //-----------------------------------------------------------------------
  520. void PUBillboardChain::updateIndexBuffer(void)
  521. {
  522. setupBuffers();
  523. if (_indexContentDirty)
  524. {
  525. //uint16* pShort = static_cast<uint16*>(
  526. // _indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD));
  527. //_indexData->indexCount = 0;
  528. // indexes
  529. unsigned short index = 0;
  530. for (ChainSegmentList::iterator segi = _chainSegmentList.begin();
  531. segi != _chainSegmentList.end(); ++segi)
  532. {
  533. ChainSegment& seg = *segi;
  534. // Skip 0 or 1 element segment counts
  535. if (seg.head != SEGMENT_EMPTY && seg.head != seg.tail)
  536. {
  537. // Start from head + 1 since it's only useful in pairs
  538. size_t laste = seg.head;
  539. while(1) // until break
  540. {
  541. size_t e = laste + 1;
  542. // Wrap forwards
  543. if (e == _maxElementsPerChain)
  544. e = 0;
  545. // indexes of this element are (e * 2) and (e * 2) + 1
  546. // indexes of the last element are the same, -2
  547. CCASSERT (((e + seg.start) * 2) < 65536, "Too many elements!");
  548. unsigned short baseIdx = static_cast<unsigned short>((e + seg.start) * 2);
  549. unsigned short lastBaseIdx = static_cast<unsigned short>((laste + seg.start) * 2);
  550. //*pShort++ = lastBaseIdx;
  551. //*pShort++ = lastBaseIdx + 1;
  552. //*pShort++ = baseIdx;
  553. //*pShort++ = lastBaseIdx + 1;
  554. //*pShort++ = baseIdx + 1;
  555. //*pShort++ = baseIdx;
  556. //_indexData->indexCount += 6;
  557. _indices[index++] = lastBaseIdx;
  558. _indices[index++] = lastBaseIdx + 1;
  559. _indices[index++] = baseIdx;
  560. _indices[index++] = lastBaseIdx + 1;
  561. _indices[index++] = baseIdx + 1;
  562. _indices[index++] = baseIdx;
  563. if (e == seg.tail)
  564. break; // last one
  565. laste = e;
  566. }
  567. }
  568. }
  569. _indexBuffer->updateIndices(&_indices[0], (int)_indices.size(), 0);
  570. //_indexData->indexBuffer->unlock();
  571. _indexContentDirty = false;
  572. }
  573. }
  574. //-----------------------------------------------------------------------
  575. void PUBillboardChain::init( const std::string &texFile )
  576. {
  577. GLProgram* glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_PARTICLE_COLOR);
  578. if (!texFile.empty())
  579. {
  580. auto tex = Director::getInstance()->getTextureCache()->addImage(texFile);
  581. if (tex)
  582. {
  583. _texture = tex;
  584. glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_PARTICLE_TEXTURE);
  585. }
  586. }
  587. auto glProgramState = GLProgramState::create(glProgram);
  588. glProgramState->retain();
  589. GLsizei stride = sizeof(VertexInfo);
  590. glProgramState->setVertexAttribPointer(s_attributeNames[GLProgram::VERTEX_ATTRIB_POSITION], 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)offsetof(VertexInfo, position));
  591. glProgramState->setVertexAttribPointer(s_attributeNames[GLProgram::VERTEX_ATTRIB_TEX_COORD], 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)offsetof(VertexInfo, uv));
  592. glProgramState->setVertexAttribPointer(s_attributeNames[GLProgram::VERTEX_ATTRIB_COLOR], 4, GL_FLOAT, GL_FALSE, stride, (GLvoid*)offsetof(VertexInfo, color));
  593. _glProgramState = glProgramState;
  594. _meshCommand = new (std::nothrow) MeshCommand();
  595. _meshCommand->setSkipBatching(true);
  596. _meshCommand->setTransparent(true);
  597. _stateBlock->setDepthTest(true);
  598. _stateBlock->setDepthWrite(false);
  599. _stateBlock->setCullFaceSide(RenderState::CULL_FACE_SIDE_BACK);
  600. _stateBlock->setCullFace(true);
  601. }
  602. void PUBillboardChain::render( Renderer* renderer, const Mat4 &transform, ParticleSystem3D* particleSystem )
  603. {
  604. auto camera = Camera::getVisitingCamera();
  605. auto cameraMat = camera->getNodeToWorldTransform();
  606. if (!_chainSegmentList.empty())
  607. {
  608. updateVertexBuffer(cameraMat);
  609. updateIndexBuffer();
  610. if (!_vertices.empty() && !_indices.empty())
  611. {
  612. GLuint texId = this->getTextureName();
  613. _stateBlock->setBlendFunc(particleSystem->getBlendFunc());
  614. _meshCommand->init(0,
  615. texId,
  616. _glProgramState,
  617. _stateBlock,
  618. _vertexBuffer->getVBO(),
  619. _indexBuffer->getVBO(),
  620. GL_TRIANGLES,
  621. GL_UNSIGNED_SHORT,
  622. _indices.size(),
  623. transform,
  624. Node::FLAGS_RENDER_AS_3D);
  625. _meshCommand->setSkipBatching(true);
  626. _meshCommand->setTransparent(true);
  627. _glProgramState->setUniformVec4("u_color", Vec4(1,1,1,1));
  628. renderer->addCommand(_meshCommand);
  629. }
  630. }
  631. }
  632. void PUBillboardChain::setDepthTest( bool isDepthTest )
  633. {
  634. _stateBlock->setDepthTest(isDepthTest);
  635. }
  636. void PUBillboardChain::setDepthWrite( bool isDepthWrite )
  637. {
  638. _stateBlock->setDepthWrite(isDepthWrite);
  639. }
  640. void PUBillboardChain::setBlendFunc(const BlendFunc& blendFunc)
  641. {
  642. _stateBlock->setBlendFunc(blendFunc);
  643. }
  644. GLuint PUBillboardChain::getTextureName()
  645. {
  646. if (Director::getInstance()->getTextureCache()->getTextureForKey(_texFile) == nullptr)
  647. {
  648. _texture = nullptr;
  649. this->init("");
  650. }
  651. else if (_texture == nullptr)
  652. {
  653. this->init(_texFile);
  654. }
  655. if (_texture == nullptr)
  656. return 0;
  657. return _texture->getName();
  658. }
  659. //-----------------------------------------------------------------------
  660. //void PUBillboardChain::_updateRenderQueue(RenderQueue* queue)
  661. //{
  662. // updateIndexBuffer();
  663. //
  664. // if (mIndexData->indexCount > 0)
  665. // {
  666. // if (mRenderQueuePrioritySet)
  667. // queue->addRenderable(this, mRenderQueueID, mRenderQueuePriority);
  668. // else if (mRenderQueueIDSet)
  669. // queue->addRenderable(this, mRenderQueueID);
  670. // else
  671. // queue->addRenderable(this);
  672. // }
  673. //
  674. //}
  675. //-----------------------------------------------------------------------
  676. //void PUBillboardChain::getRenderOperation(RenderOperation& op)
  677. //{
  678. // op.indexData = mIndexData;
  679. // op.operationType = RenderOperation::OT_TRIANGLE_LIST;
  680. // op.srcRenderable = this;
  681. // op.useIndexes = true;
  682. // op.vertexData = mVertexData;
  683. //}
  684. //-----------------------------------------------------------------------
  685. //bool PUBillboardChain::preRender(SceneManager* sm, RenderSystem* rsys)
  686. //{
  687. // // Retrieve the current viewport from the scene manager.
  688. // // The viewport is only valid during a viewport update.
  689. // Viewport *currentViewport = sm->getCurrentViewport();
  690. // if( !currentViewport )
  691. // return false;
  692. //
  693. // updateVertexBuffer(currentViewport->getCamera());
  694. // return true;
  695. //}
  696. //-----------------------------------------------------------------------
  697. //void PUBillboardChain::getWorldTransforms(Matrix4* xform) const
  698. //{
  699. // *xform = _getParentNodeFullTransform();
  700. //}
  701. //---------------------------------------------------------------------
  702. NS_CC_END