CCPUMeshSurfaceEmitter.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. /****************************************************************************
  2. Copyright (C) 2013 Henry van Merode. All rights reserved.
  3. Copyright (c) 2015-2017 Chukong Technologies Inc.
  4. http://www.cocos2d-x.org
  5. Permission is hereby granted, free of charge, to any person obtaining a copy
  6. of this software and associated documentation files (the "Software"), to deal
  7. in the Software without restriction, including without limitation the rights
  8. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the Software is
  10. furnished to do so, subject to the following conditions:
  11. The above copyright notice and this permission notice shall be included in
  12. all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. THE SOFTWARE.
  20. ****************************************************************************/
  21. #include "CCPUMeshSurfaceEmitter.h"
  22. #include "extensions/Particle3D/PU/CCPUParticleSystem3D.h"
  23. #include "extensions/Particle3D/PU/CCPUUtil.h"
  24. NS_CC_BEGIN
  25. // Constants
  26. const Vec3 PUMeshSurfaceEmitter::DEFAULT_SCALE(1, 1, 1);
  27. const MeshInfo::MeshSurfaceDistribution PUMeshSurfaceEmitter::DEFAULT_DISTRIBUTION = MeshInfo::MSD_HOMOGENEOUS;
  28. //-----------------------------------------------------------------------
  29. inline void PUTriangle::calculateSquareSurface (void)
  30. {
  31. /* Calculating the surface of a triangle with the following algorithm:
  32. v1 = Vector3(x1, y1, z1)
  33. v2 = Vector3(x2, y2, z2)
  34. v3 = Vector3(x3, y3, z3)
  35. a = sqrt ((x1-x3)*(x1-x3) + (y1-y3)*(y1-y3) + (z1-z3)*(z1-z3))
  36. b = sqrt ((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1))
  37. c = sqrt ((x3-x2)*(x3-x2) + (y3-y2)*(y3-y2) + (z3-z2)*(z3-z2))
  38. p = 0.5 * (a + b + c)
  39. surface = sqrt (p * (p-a) * (p-b) * (p-c));
  40. */
  41. // a, b and c are the length of each triangle
  42. float a = sqrt ( (v1.x - v3.x) * (v1.x - v3.x) +
  43. (v1.y - v3.y) * (v1.y - v3.y) +
  44. (v1.z - v3.z) * (v1.z - v3.z));
  45. float b = sqrt ( (v2.x - v1.x) * (v2.x - v1.x) +
  46. (v2.y - v1.y) * (v2.y - v1.y) +
  47. (v2.z - v1.z) * (v2.z - v1.z));
  48. float c = sqrt ( (v3.x - v2.x) * (v3.x - v2.x) +
  49. (v3.y - v2.y) * (v3.y - v2.y) +
  50. (v3.z - v2.z) * (v3.z - v2.z));
  51. float p = 0.5f * (a + b + c);
  52. // Assign square surface of the triangle
  53. squareSurface = p * (p-a) * (p-b) * (p-c);
  54. }
  55. //-----------------------------------------------------------------------
  56. inline void PUTriangle::calculateSurfaceNormal (void)
  57. {
  58. /* Calculating the surface normal of a triangle with the following algorithm:
  59. v1 = Vector3(x1, y1, z1)
  60. v2 = Vector3(x2, y2, z2)
  61. v3 = Vector3(x3, y3, z3)
  62. n = (v2-v1)x(v3-v1), where the 'x' is the cross product
  63. */
  64. Vec3::cross(v2-v1, v3-v1, &surfaceNormal);
  65. surfaceNormal.normalize();
  66. }
  67. //-----------------------------------------------------------------------
  68. inline void PUTriangle::calculateEdgeNormals (void)
  69. {
  70. Vec3::cross(v1, v2, &en1);
  71. en1.normalize();
  72. Vec3::cross(v2, v3, &en2);
  73. en2.normalize();
  74. Vec3::cross(v3, v1, &en3);
  75. en3.normalize();
  76. }
  77. //-----------------------------------------------------------------------
  78. const Vec3 PUTriangle::getRandomTrianglePosition (void)
  79. {
  80. // Use barycentric coordinates. Let A, B, C be the three vertices of the triangle. Any point P inside can
  81. // be expressed uniquely as P = aA + bB + cC, where a+b+c=1 and a,b,c are each >= 0.
  82. // Knowing a and b permits you to calculate c=1-a-b.
  83. // So if you can generate two random numbers a and b, each in [0,1], such that their sum <=1, you've got a
  84. // random point in your triangle. Generate random a and b independently and uniformly in [0,1]
  85. // If a+b>1, replace a by 1-a, b by 1-b. Let c=1-a-b. Then aA + bB + cC is uniformly distributed
  86. // in triangle ABC: the reflection step a=1-a; b=1-b gives a point (a,b) uniformly distributed in the
  87. // triangle (0,0)(1,0)(0,1), which is then mapped affinely to ABC. Now you have barycentric coordinates
  88. // a,b,c. Compute your point P = aA + bB + cC.
  89. float a = CCRANDOM_0_1();
  90. float b = CCRANDOM_0_1();
  91. if (a + b > 1)
  92. {
  93. a = 1 - a;
  94. b = 1 - b;
  95. }
  96. float c = 1 - a - b;
  97. return a * v1 + b * v2 + c * v3;
  98. }
  99. //-----------------------------------------------------------------------
  100. const PUTriangle::PositionAndNormal PUTriangle::getRandomEdgePositionAndNormal (void)
  101. {
  102. float mult = CCRANDOM_0_1();
  103. float randomVal = CCRANDOM_0_1() * 3.0f;
  104. PositionAndNormal pAndN;
  105. pAndN.position.setZero();
  106. pAndN.normal.setZero();
  107. if (randomVal < 1)
  108. {
  109. pAndN.position.set(v2.x + mult*(v1.x - v2.x), v2.y + mult*(v1.y - v2.y), v2.z + mult*(v1.z - v2.z));
  110. pAndN.normal = en1;
  111. }
  112. else
  113. {
  114. if (randomVal < 2)
  115. {
  116. pAndN.position.set(v3.x + mult*(v2.x - v3.x), v3.y + mult*(v2.y - v3.y), v3.z + mult*(v2.z - v3.z));
  117. pAndN.normal = en2;
  118. }
  119. else
  120. {
  121. pAndN.position.set(v1.x + mult*(v3.x - v1.x), v1.y + mult*(v3.y - v1.y), v1.z + mult*(v3.z - v1.z));
  122. pAndN.normal = en3;
  123. }
  124. }
  125. return pAndN;
  126. }
  127. //-----------------------------------------------------------------------
  128. const PUTriangle::PositionAndNormal PUTriangle::getRandomVertexAndNormal (void)
  129. {
  130. float randomVal = CCRANDOM_0_1() * 3.0f;
  131. PositionAndNormal pAndN;
  132. pAndN.position.setZero();
  133. pAndN.normal.setZero();
  134. if (randomVal < 1)
  135. {
  136. pAndN.position = v1;
  137. pAndN.normal = vn1;
  138. }
  139. else
  140. {
  141. if (randomVal < 2)
  142. {
  143. pAndN.position = v2;
  144. pAndN.normal = vn2;
  145. }
  146. else
  147. {
  148. pAndN.position = v3;
  149. pAndN.normal = vn3;
  150. }
  151. }
  152. return pAndN;
  153. }
  154. //-----------------------------------------------------------------------
  155. //-----------------------------------------------------------------------
  156. //-----------------------------------------------------------------------
  157. MeshInfo::MeshInfo (const std::string& /*meshName*/,
  158. MeshSurfaceDistribution distribution,
  159. const Quaternion& /*orientation*/,
  160. const Vec3& /*scale*/) :
  161. mDistribution(distribution)
  162. {
  163. //Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().load(meshName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
  164. //getMeshInformation(mesh, Vec3::ZERO, orientation, scale);
  165. }
  166. //-----------------------------------------------------------------------
  167. MeshInfo::~MeshInfo (void)
  168. {
  169. _triangles.clear();
  170. }
  171. //-----------------------------------------------------------------------
  172. inline float MeshInfo::getGaussianRandom (float high, float cutoff)
  173. {
  174. float x1 = 0;
  175. float x2 = 0;
  176. float w = 0;
  177. float y1 = 0;
  178. unsigned int max = 0;
  179. do
  180. {
  181. x1 = CCRANDOM_0_1();
  182. x2 = CCRANDOM_0_1();
  183. w = x1 * x1 + x2 * x2;
  184. // Prevent infinite loop
  185. if (w >= 1.0f && max > 4 )
  186. w = x1;
  187. } while (w >= 1.0f);
  188. w = sqrt((-2.0f * ::log(w)) / w);
  189. y1 = std::abs(x1 * w);
  190. y1 = y1 > cutoff ? cutoff : y1;
  191. y1 *= high / cutoff;
  192. return y1;
  193. }
  194. //-----------------------------------------------------------------------
  195. const PUTriangle& MeshInfo::getTriangle (size_t triangleIndex)
  196. {
  197. return _triangles[triangleIndex];
  198. }
  199. //-----------------------------------------------------------------------
  200. size_t MeshInfo::getRandomTriangleIndex()
  201. {
  202. size_t index;
  203. if (mDistribution == MSD_HOMOGENEOUS || mDistribution == MSD_HETEROGENEOUS_1)
  204. {
  205. index = (size_t)getGaussianRandom((float)_triangles.size() - 1);
  206. }
  207. else
  208. index = (size_t)(CCRANDOM_0_1() * (float)(_triangles.size() - 1));
  209. return index;
  210. }
  211. //-----------------------------------------------------------------------
  212. const PUTriangle::PositionAndNormal MeshInfo::getRandomPositionAndNormal (const size_t triangleIndex)
  213. {
  214. PUTriangle triangle = getTriangle(triangleIndex);
  215. PUTriangle::PositionAndNormal pAndN;
  216. pAndN.position.setZero();
  217. pAndN.normal.setZero();
  218. if (mDistribution == MSD_HOMOGENEOUS || mDistribution == MSD_HETEROGENEOUS_1 || mDistribution == MSD_HETEROGENEOUS_2)
  219. {
  220. pAndN.position = triangle.getRandomTrianglePosition();
  221. pAndN.normal = triangle.surfaceNormal;
  222. }
  223. else
  224. {
  225. if (mDistribution == MSD_VERTEX)
  226. {
  227. pAndN = triangle.getRandomVertexAndNormal();
  228. }
  229. else
  230. {
  231. if (mDistribution == MSD_EDGE)
  232. {
  233. pAndN = triangle.getRandomEdgePositionAndNormal();
  234. }
  235. }
  236. }
  237. return pAndN;
  238. }
  239. //-----------------------------------------------------------------------
  240. //void MeshInfo::getMeshInformation( Ogre::MeshPtr mesh,
  241. // const Vec3 &position,
  242. // const Quaternion &orient,
  243. // const Vec3 &scale)
  244. //{
  245. // size_t vertexCount = 0;
  246. // size_t indexCount = 0;
  247. // Vec3* vertices = 0;
  248. // Vec3* normals;
  249. // unsigned long* indices = 0;
  250. //
  251. // bool added_shared = false;
  252. // size_t current_offset = 0;
  253. // size_t shared_offset = 0;
  254. // size_t next_offset = 0;
  255. // size_t index_offset = 0;
  256. //
  257. // // Calculate how many vertices and indices we're going to need
  258. // for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
  259. // {
  260. // Ogre::SubMesh* submesh = mesh->getSubMesh( i );
  261. //
  262. // // We only need to add the shared vertices once
  263. // if(submesh->useSharedVertices)
  264. // {
  265. // if( !added_shared )
  266. // {
  267. // vertexCount += mesh->sharedVertexData->vertexCount;
  268. // added_shared = true;
  269. // }
  270. // }
  271. // else
  272. // {
  273. // vertexCount += submesh->vertexData->vertexCount;
  274. // }
  275. //
  276. // // Add the indices
  277. // indexCount += submesh->indexData->indexCount;
  278. // }
  279. //
  280. // // Allocate space for the vertices and indices
  281. // vertices = new (std::nothrow) Vec3[vertexCount];
  282. // normals = new (std::nothrow) Vec3[vertexCount];
  283. // indices = new (std::nothrow) unsigned long[indexCount];
  284. // added_shared = false;
  285. //
  286. // // Run through the submeshes again, adding the data into the arrays
  287. // for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
  288. // {
  289. // Ogre::SubMesh* submesh = mesh->getSubMesh(i);
  290. // Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
  291. //
  292. // if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared))
  293. // {
  294. // if(submesh->useSharedVertices)
  295. // {
  296. // added_shared = true;
  297. // shared_offset = current_offset;
  298. // }
  299. //
  300. // const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
  301. // const Ogre::VertexElement* normalElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_NORMAL);
  302. // Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
  303. // unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
  304. // float* pReal;
  305. //
  306. // for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
  307. // {
  308. // posElem->baseVertexPointerToElement(vertex, &pReal);
  309. // Vec3 pt(pReal[0], pReal[1], pReal[2]);
  310. // vertices[current_offset + j] = (orient * (pt * scale)) + position;
  311. //
  312. // normalElem->baseVertexPointerToElement(vertex, &pReal);
  313. // Vec3 nt(pReal[0], pReal[1], pReal[2]);
  314. // normals[current_offset + j] = nt;
  315. // }
  316. //
  317. // vbuf->unlock();
  318. // next_offset += vertex_data->vertexCount;
  319. // }
  320. //
  321. // Ogre::IndexData* index_data = submesh->indexData;
  322. // size_t numTris = index_data->indexCount / 3;
  323. // Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
  324. // bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
  325. // unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
  326. // unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
  327. // size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
  328. //
  329. // size_t numTrisMultThree = numTris*3;
  330. // if ( use32bitindexes )
  331. // {
  332. // for ( size_t k = 0; k < numTrisMultThree; ++k)
  333. // {
  334. // indices[index_offset++] = pLong[k] + static_cast<unsigned long>(offset);
  335. // }
  336. // }
  337. // else
  338. // {
  339. // for ( size_t k = 0; k < numTrisMultThree; ++k)
  340. // {
  341. // indices[index_offset++] = static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset);
  342. // }
  343. // }
  344. //
  345. // ibuf->unlock();
  346. // current_offset = next_offset;
  347. // }
  348. //
  349. // // Create triangles from the retrieved data
  350. // for (size_t k = 0; k < indexCount-1; k+=3)
  351. // {
  352. // Triangle t;
  353. // t.v1 = vertices [indices[k]];
  354. // t.vn1 = normals [indices[k]];
  355. //
  356. // t.v2 = vertices [indices[k+1]];
  357. // t.vn2 = normals [indices[k+1]];
  358. //
  359. // t.v3 = vertices [indices[k+2]];
  360. // t.vn3 = normals [indices[k+2]];
  361. //
  362. // t.calculateSquareSurface();
  363. // t.calculateSurfaceNormal();
  364. // t.calculateEdgeNormals();
  365. // _triangles.push_back(t);
  366. // }
  367. //
  368. // // Delete intermediate arrays
  369. // delete [] indices;
  370. // delete [] normals;
  371. // delete [] vertices;
  372. //
  373. // // Sort the triangle on their size, if needed (only if a gaussian random number generator
  374. // // function is used to perform a random lookup of a triangle)
  375. // if (mDistribution == MSD_HOMOGENEOUS)
  376. // sort(_triangles.begin(), _triangles.end(), SortDescending());
  377. // else
  378. // if (mDistribution == MSD_HETEROGENEOUS_1)
  379. // sort(_triangles.begin(), _triangles.end(), SortAscending());
  380. //}
  381. //-----------------------------------------------------------------------
  382. //-----------------------------------------------------------------------
  383. //-----------------------------------------------------------------------
  384. PUMeshSurfaceEmitter::PUMeshSurfaceEmitter(void) :
  385. PUEmitter(),
  386. _meshName(),
  387. _orientation(),
  388. _scale(DEFAULT_SCALE),
  389. _distribution(DEFAULT_DISTRIBUTION),
  390. _meshInfo(0),
  391. _triangleIndex(0),
  392. _directionSet(false)
  393. {
  394. }
  395. //-----------------------------------------------------------------------
  396. PUMeshSurfaceEmitter::~PUMeshSurfaceEmitter(void)
  397. {
  398. if (_meshInfo)
  399. {
  400. CC_SAFE_DELETE(_meshInfo);
  401. }
  402. }
  403. //-----------------------------------------------------------------------
  404. void PUMeshSurfaceEmitter::prepare()
  405. {
  406. PUEmitter::prepare();
  407. // Build the data
  408. if (!_meshName.empty())
  409. {
  410. build();
  411. }
  412. }
  413. //-----------------------------------------------------------------------
  414. void PUMeshSurfaceEmitter::unPrepare()
  415. {
  416. // Todo
  417. PUEmitter::unPrepare();
  418. }
  419. //-----------------------------------------------------------------------
  420. void PUMeshSurfaceEmitter::initParticlePosition(PUParticle3D* particle)
  421. {
  422. PUTriangle::PositionAndNormal pAndN;
  423. pAndN.position.setZero();
  424. pAndN.normal.setZero();
  425. _directionSet = false;
  426. if (_meshInfo && _meshInfo->getTriangleCount())
  427. {
  428. getDerivedPosition();
  429. _triangleIndex = _meshInfo->getRandomTriangleIndex (); // Get a random triangle index
  430. pAndN = _meshInfo->getRandomPositionAndNormal(_triangleIndex); // Determine position and normal
  431. //ParticleSystem* sys = mParentTechnique->getParentSystem();
  432. if (_autoDirection)
  433. {
  434. if (pAndN.normal != Vec3::ZERO)
  435. {
  436. // Set position and direction of the particle
  437. //if (sys)
  438. {
  439. Mat4 rotMat;
  440. Mat4::createRotation(static_cast<PUParticleSystem3D *>(_particleSystem)->getDerivedOrientation(), &rotMat);
  441. particle->position = _derivedPosition + rotMat * Vec3(_emitterScale.x * pAndN.position.x, _emitterScale.y * pAndN.position.y, _emitterScale.z * pAndN.position.z);
  442. }
  443. //else
  444. //{
  445. // particle->position = _derivedPosition + _emitterScale * pAndN.position;
  446. //}
  447. // The value of the direction vector that has been set does not have a meaning
  448. float angle = (_dynamicAttributeHelper.calculate(_dynAngle, (static_cast<PUParticleSystem3D *>(_particleSystem))->getTimeElapsedSinceStart()));
  449. if (angle != 0.0f)
  450. {
  451. //particle->direction = (pAndN.normal).randomDeviant(angle, mUpVector);
  452. particle->direction = PUUtil::randomDeviant(pAndN.normal, angle, _upVector);
  453. }
  454. else
  455. {
  456. particle->direction = pAndN.normal;
  457. }
  458. particle->originalDirection = particle->direction;
  459. _directionSet = true;
  460. }
  461. }
  462. else
  463. {
  464. // Set position of the particle
  465. //if (sys)
  466. {
  467. Mat4 rotMat;
  468. Mat4::createRotation(static_cast<PUParticleSystem3D *>(_particleSystem)->getDerivedOrientation(), &rotMat);
  469. particle->position = _derivedPosition + rotMat * Vec3(_emitterScale.x * pAndN.position.x, _emitterScale.y * pAndN.position.y, _emitterScale.z * pAndN.position.z);
  470. }
  471. //else
  472. //{
  473. // particle->position = mDerivedPosition + _mEmitterScale * pAndN.position;
  474. //}
  475. }
  476. particle->originalPosition = particle->position;
  477. }
  478. }
  479. //-----------------------------------------------------------------------
  480. unsigned short PUMeshSurfaceEmitter::calculateRequestedParticles(float timeElapsed)
  481. {
  482. if (_meshInfo)
  483. {
  484. return PUEmitter::calculateRequestedParticles(timeElapsed);
  485. }
  486. return 0;
  487. }
  488. //-----------------------------------------------------------------------
  489. void PUMeshSurfaceEmitter::initParticleDirection(PUParticle3D* particle)
  490. {
  491. // Only determine direction if it hasn't been calculated yet
  492. if (!_directionSet)
  493. {
  494. PUEmitter::initParticleDirection(particle);
  495. }
  496. }
  497. //-----------------------------------------------------------------------
  498. const std::string& PUMeshSurfaceEmitter::getMeshName(void) const
  499. {
  500. return _meshName;
  501. }
  502. //-----------------------------------------------------------------------
  503. void PUMeshSurfaceEmitter::setMeshName(const std::string& meshName, bool doBuild)
  504. {
  505. _meshName = meshName;
  506. // If needed, build the data needed for emitting particles
  507. if (doBuild)
  508. {
  509. build();
  510. }
  511. }
  512. //-----------------------------------------------------------------------
  513. MeshInfo::MeshSurfaceDistribution PUMeshSurfaceEmitter::getDistribution() const
  514. {
  515. return _distribution;
  516. }
  517. //-----------------------------------------------------------------------
  518. void PUMeshSurfaceEmitter::setDistribution(MeshInfo::MeshSurfaceDistribution distribution)
  519. {
  520. _distribution = distribution;
  521. }
  522. //-----------------------------------------------------------------------
  523. const Vec3& PUMeshSurfaceEmitter::getScale (void) const
  524. {
  525. return _scale;
  526. }
  527. //-----------------------------------------------------------------------
  528. void PUMeshSurfaceEmitter::setScale (const Vec3& scale)
  529. {
  530. _scale = scale;
  531. }
  532. //-----------------------------------------------------------------------
  533. void PUMeshSurfaceEmitter::build(void)
  534. {
  535. // Delete the mesh info if already existing
  536. if (_meshInfo)
  537. {
  538. CC_SAFE_DELETE(_meshInfo);
  539. }
  540. // Generate meshinfo.
  541. _meshInfo = new (std::nothrow) MeshInfo(_meshName, _distribution, _orientation, _scale);
  542. }
  543. PUMeshSurfaceEmitter* PUMeshSurfaceEmitter::create()
  544. {
  545. auto pe = new (std::nothrow) PUMeshSurfaceEmitter();
  546. pe->autorelease();
  547. return pe;
  548. }
  549. void PUMeshSurfaceEmitter::copyAttributesTo( PUEmitter* emitter )
  550. {
  551. PUEmitter::copyAttributesTo(emitter);
  552. PUMeshSurfaceEmitter* meshSurfaceEmitter = static_cast<PUMeshSurfaceEmitter*>(emitter);
  553. meshSurfaceEmitter->_meshName = _meshName;
  554. meshSurfaceEmitter->_distribution = _distribution;
  555. meshSurfaceEmitter->_orientation = _orientation;
  556. meshSurfaceEmitter->_scale = _scale;
  557. }
  558. PUMeshSurfaceEmitter* PUMeshSurfaceEmitter::clone()
  559. {
  560. auto be = PUMeshSurfaceEmitter::create();
  561. copyAttributesTo(be);
  562. return be;
  563. }
  564. NS_CC_END