2015-02-11 18:14:22 +08:00
|
|
|
/****************************************************************************
|
2015-02-25 18:05:41 +08:00
|
|
|
Copyright (C) 2013 Henry van Merode. All rights reserved.
|
2015-02-12 16:09:08 +08:00
|
|
|
Copyright (c) 2015 Chukong Technologies Inc.
|
2015-02-11 18:14:22 +08:00
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "CCPUParticle3DMeshSurfaceEmitter.h"
|
2015-02-13 16:57:00 +08:00
|
|
|
#include "extensions/Particle3D/ParticleUniverse/CCPUParticleSystem3D.h"
|
|
|
|
#include "extensions/Particle3D/ParticleUniverse/CCPUParticle3DUtil.h"
|
2015-02-11 18:14:22 +08:00
|
|
|
|
|
|
|
NS_CC_BEGIN
|
|
|
|
// Constants
|
|
|
|
const Vec3 PUParticle3DMeshSurfaceEmitter::DEFAULT_SCALE(1, 1, 1);
|
|
|
|
const MeshInfo::MeshSurfaceDistribution PUParticle3DMeshSurfaceEmitter::DEFAULT_DISTRIBUTION = MeshInfo::MSD_HOMOGENEOUS;
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
inline void PUTriangle::calculateSquareSurface (void)
|
|
|
|
{
|
|
|
|
/* Calculating the surface of a triangle with the following algorithm:
|
|
|
|
v1 = Vector3(x1, y1, z1)
|
|
|
|
v2 = Vector3(x2, y2, z2)
|
|
|
|
v3 = Vector3(x3, y3, z3)
|
|
|
|
a = sqrt ((x1-x3)*(x1-x3) + (y1-y3)*(y1-y3) + (z1-z3)*(z1-z3))
|
|
|
|
b = sqrt ((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1))
|
|
|
|
c = sqrt ((x3-x2)*(x3-x2) + (y3-y2)*(y3-y2) + (z3-z2)*(z3-z2))
|
|
|
|
p = 0.5 * (a + b + c)
|
|
|
|
surface = sqrt (p * (p-a) * (p-b) * (p-c));
|
|
|
|
*/
|
|
|
|
|
|
|
|
// a, b and c are the length of each triangle
|
|
|
|
float a = sqrt ( (v1.x - v3.x) * (v1.x - v3.x) +
|
|
|
|
(v1.y - v3.y) * (v1.y - v3.y) +
|
|
|
|
(v1.z - v3.z) * (v1.z - v3.z));
|
|
|
|
float b = sqrt ( (v2.x - v1.x) * (v2.x - v1.x) +
|
|
|
|
(v2.y - v1.y) * (v2.y - v1.y) +
|
|
|
|
(v2.z - v1.z) * (v2.z - v1.z));
|
|
|
|
float c = sqrt ( (v3.x - v2.x) * (v3.x - v2.x) +
|
|
|
|
(v3.y - v2.y) * (v3.y - v2.y) +
|
|
|
|
(v3.z - v2.z) * (v3.z - v2.z));
|
|
|
|
float p = 0.5f * (a + b + c);
|
|
|
|
|
|
|
|
// Assign square surface of the triangle
|
|
|
|
squareSurface = p * (p-a) * (p-b) * (p-c);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
inline void PUTriangle::calculateSurfaceNormal (void)
|
|
|
|
{
|
|
|
|
/* Calculating the surface normal of a triangle with the following algorithm:
|
|
|
|
v1 = Vector3(x1, y1, z1)
|
|
|
|
v2 = Vector3(x2, y2, z2)
|
|
|
|
v3 = Vector3(x3, y3, z3)
|
|
|
|
n = (v2-v1)x(v3-v1), where the 'x' is the cross product
|
|
|
|
*/
|
|
|
|
Vec3::cross(v2-v1, v3-v1, &surfaceNormal);
|
|
|
|
surfaceNormal.normalize();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
inline void PUTriangle::calculateEdgeNormals (void)
|
|
|
|
{
|
|
|
|
Vec3::cross(v1, v2, &en1);
|
|
|
|
en1.normalize();
|
|
|
|
Vec3::cross(v2, v3, &en2);
|
|
|
|
en2.normalize();
|
|
|
|
Vec3::cross(v3, v1, &en3);
|
|
|
|
en3.normalize();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
const Vec3 PUTriangle::getRandomTrianglePosition (void)
|
|
|
|
{
|
|
|
|
// Use barycentric coordinates. Let A, B, C be the three vertices of the triangle. Any point P inside can
|
|
|
|
// be expressed uniquely as P = aA + bB + cC, where a+b+c=1 and a,b,c are each >= 0.
|
|
|
|
// Knowing a and b permits you to calculate c=1-a-b.
|
|
|
|
// So if you can generate two random numbers a and b, each in [0,1], such that their sum <=1, you've got a
|
|
|
|
// random point in your triangle. Generate random a and b independently and uniformly in [0,1]
|
|
|
|
// 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
|
|
|
|
// in triangle ABC: the reflection step a=1-a; b=1-b gives a point (a,b) uniformly distributed in the
|
|
|
|
// triangle (0,0)(1,0)(0,1), which is then mapped affinely to ABC. Now you have barycentric coordinates
|
|
|
|
// a,b,c. Compute your point P = aA + bB + cC.
|
|
|
|
float a = CCRANDOM_0_1();
|
|
|
|
float b = CCRANDOM_0_1();
|
|
|
|
if (a + b > 1)
|
|
|
|
{
|
|
|
|
a = 1 - a;
|
|
|
|
b = 1 - b;
|
|
|
|
}
|
|
|
|
float c = 1 - a - b;
|
|
|
|
return a * v1 + b * v2 + c * v3;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
const PUTriangle::PositionAndNormal PUTriangle::getRandomEdgePositionAndNormal (void)
|
|
|
|
{
|
|
|
|
float mult = CCRANDOM_0_1();
|
|
|
|
float randomVal = CCRANDOM_0_1() * 3.0f;
|
|
|
|
PositionAndNormal pAndN;
|
|
|
|
pAndN.position = Vec3::ZERO;
|
|
|
|
pAndN.normal = Vec3::ZERO;
|
|
|
|
if (randomVal < 1)
|
|
|
|
{
|
|
|
|
pAndN.position = Vec3( v2.x + mult*(v1.x - v2.x),
|
|
|
|
v2.y + mult*(v1.y - v2.y),
|
|
|
|
v2.z + mult*(v1.z - v2.z));
|
|
|
|
pAndN.normal = en1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (randomVal < 2)
|
|
|
|
{
|
|
|
|
pAndN.position = Vec3( v3.x + mult*(v2.x - v3.x),
|
|
|
|
v3.y + mult*(v2.y - v3.y),
|
|
|
|
v3.z + mult*(v2.z - v3.z));
|
|
|
|
pAndN.normal = en2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
pAndN.position = Vec3( v1.x + mult*(v3.x - v1.x),
|
|
|
|
v1.y + mult*(v3.y - v1.y),
|
|
|
|
v1.z + mult*(v3.z - v1.z));
|
|
|
|
pAndN.normal = en3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pAndN;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
const PUTriangle::PositionAndNormal PUTriangle::getRandomVertexAndNormal (void)
|
|
|
|
{
|
|
|
|
float randomVal = CCRANDOM_0_1() * 3.0f;
|
|
|
|
PositionAndNormal pAndN;
|
|
|
|
pAndN.position = Vec3::ZERO;
|
|
|
|
pAndN.normal = Vec3::ZERO;
|
|
|
|
|
|
|
|
if (randomVal < 1)
|
|
|
|
{
|
|
|
|
pAndN.position = v1;
|
|
|
|
pAndN.normal = vn1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (randomVal < 2)
|
|
|
|
{
|
|
|
|
pAndN.position = v2;
|
|
|
|
pAndN.normal = vn2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pAndN.position = v3;
|
|
|
|
pAndN.normal = vn3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pAndN;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
MeshInfo::MeshInfo (const std::string& meshName,
|
|
|
|
MeshSurfaceDistribution distribution,
|
|
|
|
const Quaternion& orientation,
|
|
|
|
const Vec3& scale) :
|
|
|
|
mDistribution(distribution)
|
|
|
|
{
|
|
|
|
//Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().load(meshName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
|
|
|
//getMeshInformation(mesh, Vec3::ZERO, orientation, scale);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
MeshInfo::~MeshInfo (void)
|
|
|
|
{
|
|
|
|
_triangles.clear();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
inline float MeshInfo::getGaussianRandom (float high, float cutoff)
|
|
|
|
{
|
|
|
|
float x1 = 0;
|
|
|
|
float x2 = 0;
|
|
|
|
float w = 0;
|
|
|
|
float y1 = 0;
|
|
|
|
|
|
|
|
unsigned int max = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
x1 = CCRANDOM_0_1();
|
|
|
|
x2 = CCRANDOM_0_1();
|
|
|
|
w = x1 * x1 + x2 * x2;
|
|
|
|
|
|
|
|
// Prevent infinite loop
|
|
|
|
if (w >= 1.0f && max > 4 )
|
|
|
|
w = x1;
|
|
|
|
|
|
|
|
} while (w >= 1.0f);
|
|
|
|
|
|
|
|
w = sqrt((-2.0f * ::log(w)) / w);
|
|
|
|
y1 = abs(x1 * w);
|
|
|
|
y1 = y1 > cutoff ? cutoff : y1;
|
|
|
|
y1 *= high / cutoff;
|
|
|
|
return y1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
const PUTriangle& MeshInfo::getTriangle (size_t triangleIndex)
|
|
|
|
{
|
|
|
|
return _triangles[triangleIndex];
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
const size_t MeshInfo::getRandomTriangleIndex (void)
|
|
|
|
{
|
|
|
|
size_t index;
|
|
|
|
if (mDistribution == MSD_HOMOGENEOUS || mDistribution == MSD_HETEROGENEOUS_1)
|
|
|
|
{
|
|
|
|
index = (size_t)getGaussianRandom((float)_triangles.size() - 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
index = (size_t)(CCRANDOM_0_1() * (float)(_triangles.size() - 1));
|
|
|
|
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
const PUTriangle::PositionAndNormal MeshInfo::getRandomPositionAndNormal (const size_t triangleIndex)
|
|
|
|
{
|
|
|
|
PUTriangle triangle = getTriangle(triangleIndex);
|
|
|
|
PUTriangle::PositionAndNormal pAndN;
|
|
|
|
pAndN.position = Vec3::ZERO;
|
|
|
|
pAndN.normal = Vec3::ZERO;
|
|
|
|
if (mDistribution == MSD_HOMOGENEOUS || mDistribution == MSD_HETEROGENEOUS_1 || mDistribution == MSD_HETEROGENEOUS_2)
|
|
|
|
{
|
|
|
|
pAndN.position = triangle.getRandomTrianglePosition();
|
|
|
|
pAndN.normal = triangle.surfaceNormal;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (mDistribution == MSD_VERTEX)
|
|
|
|
{
|
|
|
|
pAndN = triangle.getRandomVertexAndNormal();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (mDistribution == MSD_EDGE)
|
|
|
|
{
|
|
|
|
pAndN = triangle.getRandomEdgePositionAndNormal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return pAndN;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
//void MeshInfo::getMeshInformation( Ogre::MeshPtr mesh,
|
|
|
|
// const Vec3 &position,
|
|
|
|
// const Quaternion &orient,
|
|
|
|
// const Vec3 &scale)
|
|
|
|
//{
|
|
|
|
// size_t vertexCount = 0;
|
|
|
|
// size_t indexCount = 0;
|
|
|
|
// Vec3* vertices = 0;
|
|
|
|
// Vec3* normals;
|
|
|
|
// unsigned long* indices = 0;
|
|
|
|
//
|
|
|
|
// bool added_shared = false;
|
|
|
|
// size_t current_offset = 0;
|
|
|
|
// size_t shared_offset = 0;
|
|
|
|
// size_t next_offset = 0;
|
|
|
|
// size_t index_offset = 0;
|
|
|
|
//
|
|
|
|
// // Calculate how many vertices and indices we're going to need
|
|
|
|
// for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
|
|
|
|
// {
|
|
|
|
// Ogre::SubMesh* submesh = mesh->getSubMesh( i );
|
|
|
|
//
|
|
|
|
// // We only need to add the shared vertices once
|
|
|
|
// if(submesh->useSharedVertices)
|
|
|
|
// {
|
|
|
|
// if( !added_shared )
|
|
|
|
// {
|
|
|
|
// vertexCount += mesh->sharedVertexData->vertexCount;
|
|
|
|
// added_shared = true;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// vertexCount += submesh->vertexData->vertexCount;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// // Add the indices
|
|
|
|
// indexCount += submesh->indexData->indexCount;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// // Allocate space for the vertices and indices
|
2015-02-12 16:09:08 +08:00
|
|
|
// vertices = new (std::nothrow) Vec3[vertexCount];
|
|
|
|
// normals = new (std::nothrow) Vec3[vertexCount];
|
|
|
|
// indices = new (std::nothrow) unsigned long[indexCount];
|
2015-02-11 18:14:22 +08:00
|
|
|
// added_shared = false;
|
|
|
|
//
|
|
|
|
// // Run through the submeshes again, adding the data into the arrays
|
|
|
|
// for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
|
|
|
|
// {
|
|
|
|
// Ogre::SubMesh* submesh = mesh->getSubMesh(i);
|
|
|
|
// Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
|
|
|
|
//
|
|
|
|
// if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared))
|
|
|
|
// {
|
|
|
|
// if(submesh->useSharedVertices)
|
|
|
|
// {
|
|
|
|
// added_shared = true;
|
|
|
|
// shared_offset = current_offset;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
|
|
|
|
// const Ogre::VertexElement* normalElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_NORMAL);
|
|
|
|
// Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
|
|
|
|
// unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
|
|
|
|
// float* pReal;
|
|
|
|
//
|
|
|
|
// for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
|
|
|
|
// {
|
|
|
|
// posElem->baseVertexPointerToElement(vertex, &pReal);
|
|
|
|
// Vec3 pt(pReal[0], pReal[1], pReal[2]);
|
|
|
|
// vertices[current_offset + j] = (orient * (pt * scale)) + position;
|
|
|
|
//
|
|
|
|
// normalElem->baseVertexPointerToElement(vertex, &pReal);
|
|
|
|
// Vec3 nt(pReal[0], pReal[1], pReal[2]);
|
|
|
|
// normals[current_offset + j] = nt;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// vbuf->unlock();
|
|
|
|
// next_offset += vertex_data->vertexCount;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// Ogre::IndexData* index_data = submesh->indexData;
|
|
|
|
// size_t numTris = index_data->indexCount / 3;
|
|
|
|
// Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
|
|
|
|
// bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
|
|
|
|
// unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
|
|
|
|
// unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
|
|
|
|
// size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
|
|
|
|
//
|
|
|
|
// size_t numTrisMultThree = numTris*3;
|
|
|
|
// if ( use32bitindexes )
|
|
|
|
// {
|
|
|
|
// for ( size_t k = 0; k < numTrisMultThree; ++k)
|
|
|
|
// {
|
|
|
|
// indices[index_offset++] = pLong[k] + static_cast<unsigned long>(offset);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// for ( size_t k = 0; k < numTrisMultThree; ++k)
|
|
|
|
// {
|
|
|
|
// indices[index_offset++] = static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// ibuf->unlock();
|
|
|
|
// current_offset = next_offset;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// // Create triangles from the retrieved data
|
|
|
|
// for (size_t k = 0; k < indexCount-1; k+=3)
|
|
|
|
// {
|
|
|
|
// Triangle t;
|
|
|
|
// t.v1 = vertices [indices[k]];
|
|
|
|
// t.vn1 = normals [indices[k]];
|
|
|
|
//
|
|
|
|
// t.v2 = vertices [indices[k+1]];
|
|
|
|
// t.vn2 = normals [indices[k+1]];
|
|
|
|
//
|
|
|
|
// t.v3 = vertices [indices[k+2]];
|
|
|
|
// t.vn3 = normals [indices[k+2]];
|
|
|
|
//
|
|
|
|
// t.calculateSquareSurface();
|
|
|
|
// t.calculateSurfaceNormal();
|
|
|
|
// t.calculateEdgeNormals();
|
|
|
|
// _triangles.push_back(t);
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// // Delete intermediate arrays
|
|
|
|
// delete [] indices;
|
|
|
|
// delete [] normals;
|
|
|
|
// delete [] vertices;
|
|
|
|
//
|
|
|
|
// // Sort the triangle on their size, if needed (only if a gaussian random number generator
|
|
|
|
// // function is used to perform a random lookup of a triangle)
|
|
|
|
// if (mDistribution == MSD_HOMOGENEOUS)
|
|
|
|
// sort(_triangles.begin(), _triangles.end(), SortDescending());
|
|
|
|
// else
|
|
|
|
// if (mDistribution == MSD_HETEROGENEOUS_1)
|
|
|
|
// sort(_triangles.begin(), _triangles.end(), SortAscending());
|
|
|
|
//}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
PUParticle3DMeshSurfaceEmitter::PUParticle3DMeshSurfaceEmitter(void) :
|
|
|
|
PUParticle3DEmitter(),
|
|
|
|
_meshName(),
|
|
|
|
_orientation(),
|
|
|
|
_scale(DEFAULT_SCALE),
|
|
|
|
_distribution(DEFAULT_DISTRIBUTION),
|
|
|
|
_meshInfo(0),
|
|
|
|
_triangleIndex(0),
|
|
|
|
_directionSet(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
PUParticle3DMeshSurfaceEmitter::~PUParticle3DMeshSurfaceEmitter(void)
|
|
|
|
{
|
|
|
|
if (_meshInfo)
|
|
|
|
{
|
|
|
|
CC_SAFE_DELETE(_meshInfo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void PUParticle3DMeshSurfaceEmitter::prepare()
|
|
|
|
{
|
|
|
|
// Build the data
|
|
|
|
if (!_meshName.empty())
|
|
|
|
{
|
|
|
|
build();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void PUParticle3DMeshSurfaceEmitter::unPrepare()
|
|
|
|
{
|
|
|
|
// Todo
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void PUParticle3DMeshSurfaceEmitter::initParticlePosition(PUParticle3D* particle)
|
|
|
|
{
|
|
|
|
PUTriangle::PositionAndNormal pAndN;
|
|
|
|
pAndN.position = Vec3::ZERO;
|
|
|
|
pAndN.normal = Vec3::ZERO;
|
|
|
|
_directionSet = false;
|
|
|
|
|
|
|
|
if (_meshInfo)
|
|
|
|
{
|
|
|
|
getDerivedPosition();
|
|
|
|
_triangleIndex = _meshInfo->getRandomTriangleIndex (); // Get a random triangle index
|
|
|
|
pAndN = _meshInfo->getRandomPositionAndNormal(_triangleIndex); // Determine position and normal
|
|
|
|
//ParticleSystem* sys = mParentTechnique->getParentSystem();
|
|
|
|
if (_autoDirection)
|
|
|
|
{
|
|
|
|
if (pAndN.normal != Vec3::ZERO)
|
|
|
|
{
|
|
|
|
// Set position and direction of the particle
|
|
|
|
//if (sys)
|
|
|
|
{
|
|
|
|
Mat4 rotMat;
|
|
|
|
Mat4::createRotation(static_cast<PUParticleSystem3D *>(_particleSystem)->getDerivedOrientation(), &rotMat);
|
|
|
|
particle->position = _derivedPosition + rotMat * Vec3(_emitterScale.x * pAndN.position.x, _emitterScale.y * pAndN.position.y, _emitterScale.z * pAndN.position.z);
|
|
|
|
}
|
|
|
|
//else
|
|
|
|
//{
|
|
|
|
// particle->position = _derivedPosition + _emitterScale * pAndN.position;
|
|
|
|
//}
|
|
|
|
|
|
|
|
// The value of the direction vector that has been set does not have a meaning
|
|
|
|
float angle = (_dynamicAttributeHelper.calculate(_dynAngle, (static_cast<PUParticleSystem3D *>(_particleSystem))->getTimeElapsedSinceStart()));
|
|
|
|
if (angle != 0.0f)
|
|
|
|
{
|
|
|
|
//particle->direction = (pAndN.normal).randomDeviant(angle, mUpVector);
|
|
|
|
particle->direction = PUParticle3DUtil::randomDeviant(pAndN.normal, angle, _upVector);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
particle->direction = pAndN.normal;
|
|
|
|
}
|
|
|
|
|
|
|
|
particle->originalDirection = particle->direction;
|
|
|
|
_directionSet = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Set position of the particle
|
|
|
|
//if (sys)
|
|
|
|
{
|
|
|
|
Mat4 rotMat;
|
|
|
|
Mat4::createRotation(static_cast<PUParticleSystem3D *>(_particleSystem)->getDerivedOrientation(), &rotMat);
|
|
|
|
particle->position = _derivedPosition + rotMat * Vec3(_emitterScale.x * pAndN.position.x, _emitterScale.y * pAndN.position.y, _emitterScale.z * pAndN.position.z);
|
|
|
|
}
|
|
|
|
//else
|
|
|
|
//{
|
|
|
|
// particle->position = mDerivedPosition + _mEmitterScale * pAndN.position;
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
|
|
|
|
particle->originalPosition = particle->position;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
unsigned short PUParticle3DMeshSurfaceEmitter::calculateRequestedParticles(float timeElapsed)
|
|
|
|
{
|
|
|
|
if (_meshInfo)
|
|
|
|
{
|
|
|
|
return PUParticle3DEmitter::calculateRequestedParticles(timeElapsed);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void PUParticle3DMeshSurfaceEmitter::initParticleDirection(PUParticle3D* particle)
|
|
|
|
{
|
|
|
|
// Only determine direction if it hasn't been calculated yet
|
|
|
|
if (!_directionSet)
|
|
|
|
{
|
|
|
|
PUParticle3DEmitter::initParticleDirection(particle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
const std::string& PUParticle3DMeshSurfaceEmitter::getMeshName(void) const
|
|
|
|
{
|
|
|
|
return _meshName;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void PUParticle3DMeshSurfaceEmitter::setMeshName(const std::string& meshName, bool doBuild)
|
|
|
|
{
|
|
|
|
_meshName = meshName;
|
|
|
|
|
|
|
|
// If needed, build the data needed for emitting particles
|
|
|
|
if (doBuild)
|
|
|
|
{
|
|
|
|
build();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
const MeshInfo::MeshSurfaceDistribution PUParticle3DMeshSurfaceEmitter::getDistribution (void) const
|
|
|
|
{
|
|
|
|
return _distribution;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void PUParticle3DMeshSurfaceEmitter::setDistribution(MeshInfo::MeshSurfaceDistribution distribution)
|
|
|
|
{
|
|
|
|
_distribution = distribution;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
const Vec3& PUParticle3DMeshSurfaceEmitter::getScale (void) const
|
|
|
|
{
|
|
|
|
return _scale;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void PUParticle3DMeshSurfaceEmitter::setScale (const Vec3& scale)
|
|
|
|
{
|
|
|
|
_scale = scale;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void PUParticle3DMeshSurfaceEmitter::build(void)
|
|
|
|
{
|
|
|
|
// Delete the mesh info if already existing
|
|
|
|
if (_meshInfo)
|
|
|
|
{
|
|
|
|
CC_SAFE_DELETE(_meshInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate meshinfo.
|
2015-02-12 16:09:08 +08:00
|
|
|
_meshInfo = new (std::nothrow) MeshInfo(_meshName, _distribution, _orientation, _scale);
|
2015-02-11 18:14:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PUParticle3DMeshSurfaceEmitter* PUParticle3DMeshSurfaceEmitter::create()
|
|
|
|
{
|
2015-02-12 16:09:08 +08:00
|
|
|
auto pe = new (std::nothrow) PUParticle3DMeshSurfaceEmitter();
|
2015-02-11 18:14:22 +08:00
|
|
|
pe->autorelease();
|
|
|
|
return pe;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_CC_END
|