ShapeModule.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. //
  2. // ShapeModule.cpp
  3. // cocos2d_libs
  4. //
  5. // Created by 徐俊杰 on 2020/4/24.
  6. //
  7. #include "rparticle/Modules/ShapeModule.h"
  8. //#include "UnityPrefix.h"
  9. //#include "rparticle/Modules/ShapeModule.h"
  10. #include "rparticle/ParticleSystemUtils.h"
  11. #include "rparticle/RParticleSystem.h"
  12. //#include "Runtime/Graphics/TriStripper.h"
  13. //#include "Runtime/Math/Vector2.h"
  14. #include "rparticle/Math/Random/Random.h"
  15. //#include "Runtime/Geometry/ComputionalGeometry.h"
  16. //#include "Runtime/BaseClasses/IsPlaying.h"
  17. //#include "Runtime/Utilities/StrideIterator.h"
  18. //#include "Runtime/Filters/Mesh/LodMesh.h"
  19. #include "rparticle/Serialize/TransferFunctions/SerializeTransfer.h"
  20. #define zero ZERO
  21. #define one ONE
  22. #define yAxis UNIT_Y
  23. #define zAxis UNIT_Z
  24. // MinMaxAABB
  25. #define m_Max _max
  26. #define m_Min _min
  27. NS_RRP_BEGIN
  28. static const float kMinRadius = 0.001f;
  29. enum MeshDistributionMode
  30. {
  31. kDistributionVertex,
  32. kDistributionTriangle,
  33. };
  34. /// This gives a random barycentric coord (on the edge of triangle)
  35. // @TODO: Stupid: Make this in a faster way
  36. inline Vector3f RandomBarycentricCoordEdge (Rand& rand)
  37. {
  38. float u = rand.GetFloat ();
  39. float v = rand.GetFloat ();
  40. if (u + v > 1.0F)
  41. {
  42. u = 1.0F - u;
  43. v = 1.0F - v;
  44. }
  45. float w = 1.0F - u - v;
  46. int edge = RangedRandom(rand, 0, 2);
  47. if(0 == edge)
  48. {
  49. v += 0.5f * u;
  50. w += 0.5f * u;
  51. u = 0.0f;
  52. }
  53. else if(1 == edge)
  54. {
  55. u += 0.5f * v;
  56. w += 0.5f * v;
  57. v = 0.0f;
  58. }
  59. else
  60. {
  61. u += 0.5f * w;
  62. v += 0.5f * w;
  63. w = 0.0f;
  64. }
  65. return Vector3f (u, v, w);
  66. }
  67. // TODO: It could make sense to initialize in separated loops. i.e. separate position and velcoity vectors
  68. inline void EmitterStoreData(const Matrix4x4f& localToWorld, const Vector3f& scale, ParticleSystemParticles& ps, size_t q, Vector3f& pos, Vector3f& n, Rand& random, bool randomDirection)
  69. {
  70. if(randomDirection)
  71. n = RandomUnitVector (random);
  72. n = NormalizeSafe(n);
  73. pos = ScaleVec3(pos, scale);
  74. Vector3f vel = Magnitude (ps.velocity[q]) * n;
  75. vel = localToWorld.MultiplyVector3 (vel);
  76. // @TODO: Sooo... why multiply point and then undo the result of it? Why not just MultiplyVector?
  77. pos = localToWorld.MultiplyPoint3 (pos) - localToWorld.GetPosition();
  78. ps.position[q] += pos;
  79. ps.velocity[q] = vel;
  80. #if 0 // WIP code for converting to spherical
  81. Vector3f sp = ps.position[q];
  82. ps.position[q].x = Sqrt(sp.x*sp.x + sp.y*sp.y + sp.z*sp.z);
  83. ps.position[q].y = acosf(sp.z/ps.position[q].x);
  84. ps.position[q].z = acosf(sp.y/ps.position[q].x);
  85. #endif
  86. if(ps.usesAxisOfRotation)
  87. {
  88. Vector3f tan = Cross (-n, Vector3f::zAxis);
  89. if (SqrMagnitude (tan) <= 0.01)
  90. tan = Cross (-pos, Vector3f::zAxis);
  91. if (SqrMagnitude (tan) <= 0.01)
  92. tan = Vector3f::yAxis;
  93. ps.axisOfRotation[q] = Normalize (tan);
  94. }
  95. }
  96. inline void EmitterStoreData(const Matrix4x4f& localToWorld, const Vector3f& scale, ParticleSystemParticles& ps, size_t q, Vector3f& pos, Vector3f& n, ColorRGBA32& color, Rand& random, bool randomDirection)
  97. {
  98. EmitterStoreData(localToWorld, scale, ps, q, pos, n, random, randomDirection);
  99. ps.color[q] *= color;
  100. }
  101. //TODO: Mesh stuff
  102. /*
  103. template<MeshDistributionMode distributionMode>
  104. void GetPositionMesh (Vector3f& pos,
  105. Vector3f& n,
  106. ColorRGBA32& color,
  107. const ParticleSystemEmitterMeshVertex* vertexData,
  108. const int vertexCount,
  109. const MeshTriangleData* triangleData,
  110. const UInt32 numPrimitives,
  111. float totalTriangleArea,
  112. Rand& random,
  113. bool edge)
  114. {
  115. // position/normal of particle is vertex/vertex normal from mesh
  116. if(kDistributionVertex == distributionMode)
  117. {
  118. int vertexIndex = RangedRandom (random, 0, vertexCount);
  119. pos = vertexData[vertexIndex].position;
  120. n = vertexData[vertexIndex].normal;
  121. color = vertexData[vertexIndex].color;
  122. }
  123. else if(kDistributionTriangle == distributionMode)
  124. {
  125. float randomArea = RangedRandom(random, 0.0f, totalTriangleArea);
  126. float accArea = 0.0f;
  127. UInt32 triangleIndex = 0;
  128. for(UInt32 i = 0; i < numPrimitives; i++)
  129. {
  130. const MeshTriangleData& data = triangleData[i];
  131. accArea += data.area;
  132. if(accArea >= randomArea)
  133. {
  134. triangleIndex = i;
  135. break;
  136. }
  137. }
  138. const MeshTriangleData& data = triangleData[triangleIndex];
  139. UInt16 a = data.indices[0];
  140. UInt16 b = data.indices[1];
  141. UInt16 c = data.indices[2];
  142. Vector3f barycenter;
  143. if(edge)
  144. barycenter = RandomBarycentricCoordEdge (random);
  145. else
  146. barycenter = RandomBarycentricCoord (random);
  147. // Interpolate vertex with barycentric coordinate
  148. pos = barycenter.x * vertexData[a].position + barycenter.y * vertexData[b].position + barycenter.z * vertexData[c].position;
  149. n = barycenter.x * vertexData[a].normal + barycenter.y * vertexData[b].normal + barycenter.z * vertexData[c].normal;
  150. // TODO: Don't convert to floats!!!
  151. ColorRGBAf color1(vertexData[a].color);
  152. ColorRGBAf color2(vertexData[b].color);
  153. ColorRGBAf color3(vertexData[c].color);
  154. color = barycenter.x * color1 + barycenter.y * color2 + barycenter.z * color3;
  155. }
  156. }
  157. static bool CompareMeshTriangleData (const MeshTriangleData& a, const MeshTriangleData& b)
  158. {
  159. return (a.area > b.area);
  160. }
  161. static float BuildMeshAreaTable(MeshTriangleData* triData, const StrideIterator<Vector3f> vertices, const UInt16* indices, int numTriangles)
  162. {
  163. float result = 0.0f;
  164. for(int i = 0; i < numTriangles; i++)
  165. {
  166. const UInt16 a = indices[i * 3 + 0];
  167. const UInt16 b = indices[i * 3 + 1];
  168. const UInt16 c = indices[i * 3 + 2];
  169. float area = TriangleArea3D (vertices[a], vertices[b], vertices[c]);
  170. result += area;
  171. triData[i].indices[0] = a;
  172. triData[i].indices[1] = b;
  173. triData[i].indices[2] = c;
  174. triData[i].area = area;
  175. }
  176. return result;
  177. }
  178. */
  179. // ------------------------------------------------------------------------------------------
  180. ShapeModule::ShapeModule () : ParticleSystemModule(true)
  181. , m_Type (kCone)
  182. , m_RandomDirection (false)
  183. , m_Angle(25.0f)
  184. , m_Radius(1.0f)
  185. , m_RadiusThickness(1.0f)
  186. , m_BurstSpread(false)
  187. , m_SpreadSpaceThickness(1.0f)
  188. , m_Length(5.0f)
  189. , m_Arc(360.0f)
  190. , m_BoxX(1.0f)
  191. , m_BoxY(1.0f)
  192. , m_BoxZ(1.0f)
  193. //TODO: Mesh stuff
  194. /*
  195. , m_PlacementMode(kVertex)
  196. , m_CachedMesh(NULL)
  197. , m_MeshNode (NULL)
  198. */
  199. {
  200. }
  201. void ShapeModule::Start (const ParticleSystemReadOnlyState& roState, const ParticleSystemState& state, ParticleSystemParticles& ps, const Matrix4x4f& matrix, size_t fromIndex, float t)
  202. {
  203. DebugAssert(roState.lengthInSec > 0.0001f);
  204. const float normalizedT = t / roState.lengthInSec;
  205. DebugAssert (normalizedT >= 0.0f);
  206. DebugAssert (normalizedT <= 1.0f);
  207. Rand& random = GetRandom();
  208. //TODO: Mesh stuff
  209. /*
  210. if (m_Type == kMesh)
  211. {
  212. if(!m_CachedMesh)
  213. return;
  214. if(!m_CachedVertexData.size())
  215. return;
  216. if(!m_CachedTriangleData.size())
  217. return;
  218. const ParticleSystemEmitterMeshVertex* vertexData = &m_CachedVertexData[0];
  219. const int vertexCount = m_CachedVertexData.size();
  220. size_t count = ps.array_size ();
  221. switch(m_PlacementMode)
  222. {
  223. case kVertex:
  224. {
  225. for (int q = fromIndex; q < count; ++q)
  226. {
  227. Vector3f pos;
  228. Vector3f n;
  229. ColorRGBA32 color;
  230. GetPositionMesh<kDistributionVertex>(pos, n, color, vertexData, vertexCount, NULL, 0, m_CachedTotalTriangleArea, random, false);
  231. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, color, random, m_RandomDirection);
  232. }
  233. break;
  234. }
  235. case kEdge:
  236. {
  237. for (int q = fromIndex; q < count; ++q)
  238. {
  239. Vector3f pos;
  240. Vector3f n;
  241. ColorRGBA32 color;
  242. GetPositionMesh<kDistributionTriangle>(pos, n, color, vertexData, vertexCount, m_CachedTriangleData.begin(), m_CachedTriangleData.size(), m_CachedTotalTriangleArea, random, true);
  243. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, color, random, m_RandomDirection);
  244. }
  245. break;
  246. }
  247. case kTriangle:
  248. {
  249. for (int q = fromIndex; q < count; ++q)
  250. {
  251. Vector3f pos;
  252. Vector3f n;
  253. ColorRGBA32 color;
  254. GetPositionMesh<kDistributionTriangle>(pos, n, color, vertexData, vertexCount, m_CachedTriangleData.begin(), m_CachedTriangleData.size(), m_CachedTotalTriangleArea, random, false);
  255. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, color, random, m_RandomDirection);
  256. }
  257. break;
  258. }
  259. default:
  260. {
  261. DebugAssert(0 && "PlacementMode Not Supported");
  262. }
  263. }
  264. }
  265. else
  266. */
  267. {
  268. const float r = m_Radius;
  269. float a = Deg2Rad (m_Angle);
  270. float sinA = Sin (a);
  271. float cosA = Cos (a);
  272. float length = m_Length;
  273. const size_t count = ps.array_size ();
  274. switch(m_Type)
  275. {
  276. case kSphere:
  277. {
  278. float innerRadiusThickness = std::pow(1.0f - m_RadiusThickness, 3.0f);
  279. for (int q = fromIndex; q < count; ++q)
  280. {
  281. float rr = std::pow(RangedRandom(m_Random, innerRadiusThickness, 1.0f), 1.0f / 3.0f);
  282. Vector3f pos = RandomUnitVector (random) * (r * rr);
  283. Vector3f n = pos;
  284. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, random, m_RandomDirection);
  285. }
  286. break;
  287. }
  288. case kSphereShell:
  289. {
  290. for (int q = fromIndex; q < count; ++q)
  291. {
  292. Vector3f pos = RandomUnitVector(random) * r;
  293. Vector3f n = pos;
  294. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, random, m_RandomDirection);
  295. }
  296. break;
  297. }
  298. case kHemiSphere:
  299. {
  300. float innerRadiusThickness = std::pow(1.0f - m_RadiusThickness, 3.0f);
  301. for (int q = fromIndex; q < count; ++q)
  302. {
  303. float rr = std::pow(RangedRandom(m_Random, innerRadiusThickness, 1.0f), 1.0f / 3.0f);
  304. Vector3f pos = RandomUnitVector (random) * (r * rr);
  305. if (pos.z < 0.0f)
  306. pos.z *= -1.0f;
  307. Vector3f n = pos;
  308. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, random, m_RandomDirection);
  309. }
  310. break;
  311. }
  312. case kHemiSphereShell:
  313. {
  314. for (int q = fromIndex; q < count; ++q)
  315. {
  316. Vector3f pos = RandomUnitVector (random) * r;
  317. if (pos.z < 0.0f)
  318. pos.z *= -1.0f;
  319. Vector3f n = pos;
  320. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, random, m_RandomDirection);
  321. }
  322. break;
  323. }
  324. case kCone:
  325. {
  326. const float innerRadiusThickness = std::max(kMinRadius, 1.0f - m_RadiusThickness);
  327. for (int q = fromIndex; q < count; ++q)
  328. {
  329. float rr = RangedRandom(m_Random, innerRadiusThickness, 1.0f);
  330. Vector2f posXY = NormalizeSafe(RandomUnitVector2 (random)) * rr;
  331. Vector2f nXY;
  332. if(m_RandomDirection)
  333. nXY = RandomPointInsideUnitCircle (random) * sinA;
  334. else
  335. nXY = Vector2f(posXY.x, posXY.y)* sinA;
  336. Vector3f n (nXY.x, nXY.y, cosA);
  337. Vector3f pos (posXY.x * r, posXY.y * r, 0.0f);
  338. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, random, false);
  339. }
  340. break;
  341. }
  342. case kConeShell:
  343. {
  344. for (int q = fromIndex; q < count; ++q)
  345. {
  346. Vector2f posXY = NormalizeSafe(RandomUnitVector2 (random));
  347. Vector2f nXY;
  348. if(m_RandomDirection)
  349. nXY = RandomPointInsideUnitCircle (random) * sinA;
  350. else
  351. nXY = Vector2f(posXY.x, posXY.y)* sinA;
  352. Vector3f n (nXY.x, nXY.y, cosA);
  353. Vector3f pos (posXY.x * r, posXY.y * r, 0.0f);
  354. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, random, false);
  355. }
  356. break;
  357. }
  358. case kConeVolume:
  359. {
  360. const float innerRadiusThickness = std::max(kMinRadius, 1.0f - m_RadiusThickness);
  361. for (int q = fromIndex; q < count; ++q)
  362. {
  363. float rr = RangedRandom(m_Random, innerRadiusThickness, 1.0f);
  364. Vector2f posXY = NormalizeSafe(RandomUnitVector2 (random)) * rr;
  365. Vector2f nXY = Vector2f(posXY.x, posXY.y)* sinA;
  366. Vector3f n (nXY.x, nXY.y, cosA);
  367. Vector3f pos (posXY.x * r, posXY.y * r, 0.0f);
  368. pos += length * Random01(random) * NormalizeSafe(n);
  369. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, random, m_RandomDirection);
  370. }
  371. break;
  372. }
  373. case kConeVolumeShell:
  374. {
  375. for (int q = fromIndex; q < count; ++q)
  376. {
  377. Vector2f posXY = NormalizeSafe(RandomUnitVector2 (random));
  378. Vector2f nXY = Vector2f(posXY.x, posXY.y)* sinA;
  379. Vector3f n (nXY.x, nXY.y, cosA);
  380. Vector3f pos = Vector3f(posXY.x * r, posXY.y * r, 0.0f);
  381. pos += length * Random01(random) * NormalizeSafe(n);
  382. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, random, m_RandomDirection);
  383. }
  384. break;
  385. }
  386. case kCircle:
  387. {
  388. float arc = CC_DEGREES_TO_RADIANS(m_Arc);
  389. float innerRadiusThicknessSqr = std::sqrt(1.0f - m_RadiusThickness);
  390. auto burstCount = count - fromIndex;
  391. float randomAngle = m_BurstSpread ? Random01(m_Random) * (1 - m_SpreadSpaceThickness) : 0;
  392. for (int q = fromIndex; q < count; ++q)
  393. {
  394. // angle
  395. float ra = 0.0f;
  396. if (m_BurstSpread) {
  397. ra = (Random01(m_Random) * m_SpreadSpaceThickness + randomAngle + q - fromIndex) * (arc / burstCount);
  398. } else {
  399. ra = Random01(m_Random) * arc;
  400. }
  401. // distance from center
  402. float radiusRandom = std::sqrt(Lerp(innerRadiusThicknessSqr, 1.0f, m_Random.GetFloat()));
  403. float rr = (radiusRandom * r);
  404. // generate
  405. float sra = sin(ra);
  406. float cra = cos(ra);
  407. Vector3f pos(cra * rr, sra * rr, 0);
  408. Vector3f n(cra, sra, 0);
  409. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, random, m_RandomDirection);
  410. }
  411. break;
  412. }
  413. case kBox:
  414. {
  415. const Vector3f extents (0.5f * m_BoxX, 0.5f * m_BoxY, 0.5f * m_BoxZ);
  416. for (int q = fromIndex; q < count; ++q)
  417. {
  418. Vector3f pos = RandomPointInsideCube (random, extents);
  419. Vector3f n = Vector3f::zAxis;
  420. EmitterStoreData(matrix, state.emitterScale, ps, q, pos, n, random, m_RandomDirection);
  421. }
  422. }
  423. break;
  424. default:
  425. {
  426. DebugAssert(0 && "Shape not supported");
  427. }
  428. }
  429. }
  430. }
  431. void ShapeModule::CalculateProceduralBounds(MinMaxAABB& bounds, const Vector3f& emitterScale, Vector2f minMaxBounds) const
  432. {
  433. DebugAssert(minMaxBounds.x <= minMaxBounds.y);
  434. switch(m_Type)
  435. {
  436. case kSphere:
  437. case kSphereShell:
  438. bounds.m_Max = Vector3f(m_Radius, m_Radius, m_Radius);
  439. bounds.m_Min = -bounds.m_Max;
  440. break;
  441. case kHemiSphere:
  442. case kHemiSphereShell:
  443. bounds.m_Max = Vector3f(m_Radius, m_Radius, m_Radius);
  444. bounds.m_Min = Vector3f(-m_Radius, -m_Radius, 0.0f);
  445. break;
  446. case kCone:
  447. case kConeShell:
  448. bounds.m_Max = Vector3f(m_Radius, m_Radius, 0.0f);
  449. bounds.m_Min = -bounds.m_Max;
  450. break;
  451. case kConeVolume:
  452. case kConeVolumeShell:
  453. {
  454. const float a = Deg2Rad (m_Angle);
  455. const float coneRadius2 = m_Radius + m_Length * Sin (a);
  456. const float coneLength = m_Length * Cos (a);
  457. bounds.m_Max = Vector3f(coneRadius2, coneRadius2, coneLength);
  458. bounds.m_Min = -Vector3f(coneRadius2, coneRadius2, 0.0f);
  459. break;
  460. }
  461. case kBox:
  462. bounds.m_Max = Vector3f(m_BoxX, m_BoxY, m_BoxZ) * 0.5f;
  463. bounds.m_Min = -bounds.m_Max;
  464. break;
  465. case kMesh:
  466. {
  467. //TODO: Mesh stuff
  468. /*
  469. if(m_CachedMesh)
  470. bounds = m_CachedMesh->GetBounds(0);
  471. else
  472. bounds = MinMaxAABB(Vector3f::zero, Vector3f::zero);
  473. */
  474. break;
  475. }
  476. default:
  477. {
  478. AssertBreak(!"Shape not implemented.");
  479. }
  480. }
  481. bounds.m_Min = ScaleVec3(bounds.m_Min, emitterScale);
  482. bounds.m_Max = ScaleVec3(bounds.m_Max, emitterScale);
  483. MinMaxAABB speedBounds;
  484. // Cone and cone shell random direction only deviate inside the bound
  485. if(m_RandomDirection && (m_Type != kCone) && (m_Type != kConeShell))
  486. {
  487. speedBounds.m_Max = Vector3f::one;
  488. speedBounds.m_Min = -Vector3f::one;
  489. minMaxBounds = Abs(minMaxBounds);
  490. }
  491. else
  492. {
  493. switch(m_Type)
  494. {
  495. case kSphere:
  496. case kSphereShell:
  497. case kMesh:
  498. speedBounds.m_Max = Vector3f::one;
  499. speedBounds.m_Min = -Vector3f::one;
  500. break;
  501. case kHemiSphere:
  502. case kHemiSphereShell:
  503. speedBounds.m_Max = Vector3f::one;
  504. speedBounds.m_Min = Vector3f(-1.0f, -1.0f, 0.0f);
  505. break;
  506. case kCone:
  507. case kConeShell:
  508. case kConeVolume:
  509. case kConeVolumeShell:
  510. {
  511. const float a = Deg2Rad (m_Angle);
  512. const float sinA = Sin (a);
  513. speedBounds.m_Max = Vector3f(sinA, sinA, 1.0f);
  514. speedBounds.m_Min = Vector3f(-sinA, -sinA, 0.0f);
  515. break;
  516. }
  517. case kBox:
  518. speedBounds.m_Max = Vector3f::zAxis;
  519. speedBounds.m_Min = Vector3f::zero;
  520. break;
  521. default:
  522. {
  523. AssertBreak(!"Shape not implemented.");
  524. }
  525. }
  526. }
  527. MinMaxAABB speedBound;
  528. speedBound.m_Min = bounds.m_Min + speedBounds.m_Min * minMaxBounds.y;
  529. speedBound.m_Max = bounds.m_Max + speedBounds.m_Max * minMaxBounds.y;
  530. bounds.Encapsulate(speedBound);
  531. MinMaxAABB negSpeedBound;
  532. negSpeedBound.m_Min = speedBounds.m_Min * minMaxBounds.x;
  533. negSpeedBound.m_Max = speedBounds.m_Max * minMaxBounds.x;
  534. speedBound.m_Min = MIN(negSpeedBound.m_Min, negSpeedBound.m_Max);
  535. speedBound.m_Max = MAX(negSpeedBound.m_Min, negSpeedBound.m_Max);
  536. bounds.Encapsulate(speedBound);
  537. }
  538. void ShapeModule::CheckConsistency ()
  539. {
  540. m_Type = clamp<int> (m_Type, kSphere, kMax-1);
  541. //TODO: Mesh stuff
  542. // m_PlacementMode = clamp<int> (m_PlacementMode, kVertex, kModeMax-1);
  543. m_Angle = clamp(m_Angle, 0.0f, 90.0f);
  544. m_Radius = MAX(0.01f, m_Radius);
  545. m_Length = MAX(0.0f, m_Length);
  546. m_BoxX = MAX(0.0f, m_BoxX);
  547. m_BoxY = MAX(0.0f, m_BoxY);
  548. m_BoxZ = MAX(0.0f, m_BoxZ);
  549. }
  550. void ShapeModule::AwakeFromLoad (RParticleSystem* system, const ParticleSystemReadOnlyState& roState)
  551. {
  552. //TODO: Mesh stuff
  553. /*
  554. m_MeshNode.RemoveFromList();
  555. m_MeshNode.SetData(system);
  556. m_CachedMesh = m_Mesh;
  557. if (m_CachedMesh != NULL)
  558. m_CachedMesh->AddObjectUser( m_MeshNode );
  559. DidModifyMeshData();
  560. */
  561. ResetSeed(roState);
  562. }
  563. void ShapeModule::ResetSeed(const ParticleSystemReadOnlyState& roState)
  564. {
  565. if(roState.randomSeed == 0)
  566. m_Random.SetSeed(GetGlobalRandomSeed ());
  567. else
  568. m_Random.SetSeed(roState.randomSeed);
  569. }
  570. void ShapeModule::DidDeleteMesh (RParticleSystem* system)
  571. {
  572. //TODO: Mesh stuff
  573. // m_CachedMesh = NULL;
  574. }
  575. void ShapeModule::DidModifyMeshData ()
  576. {
  577. //TODO: Mesh stuff
  578. /*
  579. if (m_CachedMesh == NULL)
  580. {
  581. m_CachedTriangleData.resize_uninitialized(0);
  582. m_CachedVertexData.resize_uninitialized(0);
  583. m_CachedTotalTriangleArea = 0;
  584. return;
  585. }
  586. const StrideIterator<Vector3f> vertexBuffer = m_CachedMesh->GetVertexBegin();
  587. const UInt16* indexBuffer = m_CachedMesh->GetSubMeshBuffer16(0);
  588. const SubMesh& submesh = m_CachedMesh->GetSubMeshFast (0);
  589. if (submesh.topology == kPrimitiveTriangleStripDeprecated)
  590. {
  591. const int numTriangles = CountTrianglesInStrip(indexBuffer, submesh.indexCount);
  592. const int capacity = numTriangles * 3;
  593. UNITY_TEMP_VECTOR(UInt16) tempIndices(capacity);
  594. Destripify(indexBuffer, submesh.indexCount, &tempIndices[0], capacity);
  595. m_CachedTriangleData.resize_uninitialized(numTriangles);
  596. m_CachedTotalTriangleArea = BuildMeshAreaTable(m_CachedTriangleData.begin(), vertexBuffer, &tempIndices[0], numTriangles);
  597. }
  598. else if (submesh.topology == kPrimitiveTriangles)
  599. {
  600. const int numTriangles = submesh.indexCount/3;
  601. m_CachedTriangleData.resize_uninitialized(numTriangles);
  602. m_CachedTotalTriangleArea = BuildMeshAreaTable(m_CachedTriangleData.begin(), vertexBuffer, indexBuffer, numTriangles);
  603. }
  604. else
  605. {
  606. m_CachedMesh = NULL;
  607. }
  608. // Optimization: This sorts so big triangles comes before small, which means finding the right triangle is faster
  609. std::sort(m_CachedTriangleData.begin(), m_CachedTriangleData.begin() + m_CachedTriangleData.size(), CompareMeshTriangleData);
  610. // Cache vertices
  611. const int vertexCount = m_CachedMesh->GetVertexCount();
  612. const StrideIterator<Vector3f> vertices = m_CachedMesh->GetVertexBegin();
  613. const StrideIterator<Vector3f> normals = m_CachedMesh->GetNormalBegin();
  614. const StrideIterator<ColorRGBA32> colors = m_CachedMesh->GetColorBegin();
  615. m_CachedVertexData.resize_uninitialized(vertexCount);
  616. for(int i = 0; i < vertexCount; i++)
  617. {
  618. m_CachedVertexData[i].position = vertices[i];
  619. if(!normals.IsNull())
  620. m_CachedVertexData[i].normal = normals[i];
  621. else
  622. m_CachedVertexData[i].normal = Vector3f::zero;
  623. if(!colors.IsNull())
  624. m_CachedVertexData[i].color = colors[i];
  625. else
  626. m_CachedVertexData[i].color = ColorRGBA32(0xffffffff);
  627. }
  628. */
  629. }
  630. Rand& ShapeModule::GetRandom()
  631. {
  632. #if UNITY_EDITOR
  633. if(!IsWorldPlaying())
  634. return m_EditorRandom;
  635. else
  636. #endif
  637. return m_Random;
  638. }
  639. template<class TransferFunction>
  640. void ShapeModule::Transfer (TransferFunction& transfer)
  641. {
  642. transfer.SetVersion(2);
  643. ParticleSystemModule::Transfer (transfer);
  644. transfer.Transfer (m_Type, "type");
  645. // Primitive
  646. transfer.Transfer(m_Radius, "radius");
  647. transfer.Transfer(m_RadiusThickness, "radiusThickness");
  648. transfer.Transfer(m_Angle, "angle");
  649. transfer.Transfer(m_Length, "length");
  650. transfer.Transfer(m_BoxX, "boxX");
  651. transfer.Transfer(m_BoxY, "boxY");
  652. transfer.Transfer(m_BoxZ, "boxZ");
  653. //TODO: Mesh stuff
  654. /*(
  655. // Mesh
  656. transfer.Transfer (m_PlacementMode, "placementMode");
  657. TRANSFER (m_Mesh);
  658. */
  659. transfer.Transfer (m_RandomDirection, "randomDirection"); transfer.Align();
  660. // In Unity 3.5 all cone emitters had random direction set to false, but behaved as if it was true
  661. if(transfer.IsOldVersion(1))
  662. if(kCone == m_Type)
  663. m_RandomDirection = true;
  664. }
  665. INSTANTIATE_TEMPLATE_TRANSFER(ShapeModule)
  666. NS_RRP_END