1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357 |
- //
- // ParticleSystemRenderer.cpp
- // cocos2d_libs
- //
- // Created by 徐俊杰 on 2020/4/24.
- //
- #include "rparticle/ParticleSystemRenderer.h"
- #include "rparticle/ParticleSystemParticle.h"
- #include "rparticle/Utilities/StrideIterator.h"
- #include "rparticle/Macros/RParticleGlobalStuff.h"
- #include "rparticle/Utilities/Transform.h"
- #include "2d/CCCamera.h"
- #include "base/ccMacros.h"
- #include "renderer/ccGLStateCache.h"
- #include "renderer/CCGLProgram.h"
- #include "renderer/CCRenderer.h"
- #include <algorithm>
- #include "rparticle/Serialize/TransferFunctions/SerializeTransfer.h"
- using namespace cocos2d;
- NS_RRP_BEGIN
- //PROFILER_INFORMATION(gParticlesSort, "ParticleSystem.Sort", kProfilerParticles)
- //PROFILER_INFORMATION(gParticlesSingleProfile, "ParticleSystem.RenderSingle", kProfilerParticles)
- //PROFILER_INFORMATION(gParticlesBatchProfile, "ParticleSystem.RenderBatch", kProfilerParticles)
- //PROFILER_INFORMATION(gSubmitVBOParticleProfile, "Mesh.SubmitVBO", kProfilerRender)
- enum { kMaxQuads = 65536/4 - 4 }; // so we fit into 16 bit indices, minus some more just in case
- #define DEBUG_PARTICLE_SORTING (0)
- #if UNITY_WII
- #define kMaxNumParticlesPerBatch (65536/6)
- #else
- #define kMaxNumParticlesPerBatch (std::min<int>(kDynamicBatchingIndicesThreshold/6, kMaxQuads))
- #endif
- //struct ParticleSystemVertex
- //{
- // Vector3f vert;
- // Vector3f normal;
- // ColorRGBAf color;
- // Vector2f uv;
- // Vector4f tangent; // Here, we put 2nd uv + blend factor
- //};
- struct ParticleSystemGeomConstInputData
- {
- Matrix4x4f m_ViewMatrix;
- Vector3f m_CameraVelocity;
- //Object* m_Renderer;
- UInt16 const* m_MeshIndexBuffer[ParticleSystemRendererData::kMaxNumParticleMeshes];
- int m_MeshIndexCount[ParticleSystemRendererData::kMaxNumParticleMeshes];
- int m_NumTilesX;
- int m_NumTilesY;
- float maxPlaneScale;
- float maxOrthoSize;
- float numUVFrame;
- float animUScale;
- float animVScale;
- Vector3f xSpan;
- Vector3f ySpan;
- bool usesSheetIndex;
- int uvModuleMode;
- float bentNormalFactor;
- Vector3f bentNormalVector;
- bool isSpriteFrame;
- RRP_PARTICLEQUAD_VERTEX_INFO* vertexInfo;
- Vector3f globalScale;
- };
- inline void ScaleMatrix(Matrix4x4f& matrix, float scale)
- {
- matrix.m[0] *= scale;
- matrix.m[1] *= scale;
- matrix.m[2] *= scale;
- matrix.m[4] *= scale;
- matrix.m[5] *= scale;
- matrix.m[6] *= scale;
- matrix.m[8] *= scale;
- matrix.m[9] *= scale;
- matrix.m[10] *= scale;
- }
- static ParticleSystemVertex* _vbPtr = nullptr;
- struct ParticleSort
- {
- inline static void SetValues(ParticleSort& sort, UInt32 inIndex, int inIntValue)
- {
- sort.index = inIndex;
- sort.intValue = inIntValue;
- }
- inline static bool CompareValue (const ParticleSort& left, const ParticleSort& right)
- {
- return (left.intValue < right.intValue);
- }
- inline static void Swap(ParticleSort* oneOfThem, ParticleSort* theOtherOne)
- {
- ParticleSort temp = *oneOfThem;
- *oneOfThem = *theOtherOne;
- *theOtherOne = temp;
- }
- UInt32 index;
- int intValue;
- };
- //bool ParticleSystemRenderer::init(){
- // //if(!Node::init()){
- // // return false;
- // //}
- // //this->setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR));
- // return true;
- //}
- //ParticleSystemRenderer* ParticleSystemRenderer::create() {
- // ParticleSystemRenderer * ret = new (std::nothrow) ParticleSystemRenderer();
- // if (ret && ret->init()) {
- // //ret->autorelease();
- // } else {
- // CC_SAFE_DELETE(ret);
- // }
- // return ret;
- //}
- void GenerateSortIndices(ParticleSort* indices, const Vector3f& distFactor, const ParticleSystemParticles& ps, ParticleSystemSortMode sortMode)
- {
- const size_t particleCount = ps.array_size();
- if(sortMode == kSSMByDistance)
- for(int i = 0; i < particleCount; i++)
- ParticleSort::SetValues(indices[i], i, (int)(Dot (distFactor, ps.position[i]) * 40000.0f));
- else if(sortMode == kSSMOldestFirst)
- for(int i = 0; i < particleCount; i++)
- ParticleSort::SetValues(indices[i], i, (int)((ps.startLifetime[i]- ps.lifetime[i]) * -40000.0f));
- else if(sortMode == kSSMYoungestFirst)
- for(int i = 0; i < particleCount; i++)
- ParticleSort::SetValues(indices[i], i, (int)((ps.startLifetime[i]- ps.lifetime[i]) * 40000.0f));
- }
- template<bool sortTempData>
- void ApplySortRemap(ParticleSort* particleSortIndexBuffer, ParticleSystemParticlesTempData* tempData, ParticleSystemParticles& ps)
- {
- const size_t count = ps.array_size();
- for(int i = 0; i < count; i++)
- {
- int dst = particleSortIndexBuffer[i].intValue;
- while(i != dst)
- {
- ParticleSort::Swap(&particleSortIndexBuffer[i], &particleSortIndexBuffer[dst]);
- ps.element_swap(i, dst);
- if(sortTempData)
- tempData->element_swap(i, dst);
- dst = particleSortIndexBuffer[i].intValue;
- }
- }
- }
- void Sort (const Matrix4x4f& matrix, ParticleSystemParticles& ps, ParticleSystemSortMode mode, ParticleSystemParticlesTempData* tempData, bool sortTempData)
- {
- //PROFILER_AUTO_GFX(gParticlesSort, 0);
- DebugAssert(mode != kSSMNone);
- const Vector3f distFactor = Vector3f (matrix.Get (2, 0), matrix.Get (2, 1), + matrix.Get (2, 2));
- const size_t count = ps.array_size();
- ParticleSort* particleSortIndexBuffer;
- //ALLOC_TEMP(particleSortIndexBuffer, ParticleSort, count);
- particleSortIndexBuffer = (ParticleSort*)malloc(sizeof(ParticleSort) * count);
- GenerateSortIndices(&particleSortIndexBuffer[0], distFactor, ps, mode);
- // Sort
- std::sort(&particleSortIndexBuffer[0], &particleSortIndexBuffer[0] + count, ParticleSort::CompareValue);
- // Create inverse mapping
- for(int i = 0; i < count; i++)
- particleSortIndexBuffer[particleSortIndexBuffer[i].index].intValue = i;
- if(sortTempData)
- ApplySortRemap<true>(particleSortIndexBuffer, tempData, ps);
- else
- ApplySortRemap<false>(particleSortIndexBuffer, tempData, ps);
- free(particleSortIndexBuffer);
- }
- struct ParticleMeshData
- {
- int vertexCount;
- StrideIterator<Vector3f> positions;
- StrideIterator<Vector3f> normals;
- StrideIterator<Vector4f> tangents;
- StrideIterator<ColorRGBA32> colors;
- StrideIterator<Vector2f> texCoords;
- int indexCount;
- const UInt16* indexBuffer;
- };
- template<bool hasNormals, bool hasTangents>
- void TransformParticleMesh(const ParticleMeshData& src, ColorRGBA32 particleColor,
- const Matrix4x4f& xform, const Matrix4x4f& xformNoScale, UInt8** dest)
- {
- for(int vertex = 0; vertex < src.vertexCount; vertex++)
- {
- // Vertex format is position, color, uv, and optional normals and tangents
- xform.MultiplyPoint3(src.positions[vertex], *reinterpret_cast<Vector3f*>(*dest));
- *dest += sizeof(Vector3f);
- if (hasNormals)
- {
- xformNoScale.MultiplyVector3(src.normals[vertex], *reinterpret_cast<Vector3f*>(*dest));
- *dest += sizeof(Vector3f);
- }
- auto tempColor = particleColor;
- tempColor *= src.colors[vertex];
- *reinterpret_cast<ColorRGBA32*>(*dest) = tempColor;
- *dest += sizeof(ColorRGBA32);
- *reinterpret_cast<Vector2f*>(*dest) = src.texCoords[vertex];
- *dest += sizeof(Vector2f);
- // Tangent is last in vertex format
- if (hasTangents)
- {
- Vector3f newTangent = xformNoScale.MultiplyVector3((const Vector3f&)src.tangents[vertex]);
- //*reinterpret_cast<Vector4f*>(*dest) = Vector4f(newTangent, src.tangents[vertex].w);
- *reinterpret_cast<Vector4f*>(*dest) = Vector4f(newTangent.x, newTangent.y, newTangent.z, src.tangents[vertex].w);
- *dest += sizeof(Vector4f);
- }
- }
- }
- ParticleSystemRenderer::ParticleSystemRenderer (/*MemLabelId label, ObjectCreationMode mode*/)
- //: Super(kRendererParticleSystem, label, mode)
- : m_LocalSpaceAABB (Vector3f::ZERO, Vector3f::ZERO)
- {
- //setName(COMPONENT_PS_RENDERER);
- //SetVisible (false);
- //for (int i = 0; i < ParticleSystemRendererData::kMaxNumParticleMeshes; ++i)
- // m_Data.cachedMeshUserNode[i].SetData (this);
- #if UNITY_EDITOR
- m_EditorEnabled = true;
- #endif
- }
- ParticleSystemRenderer::~ParticleSystemRenderer ()
- {
-
- }
- //void ParticleSystemRenderer::InitializeClass ()
- //{
- // REGISTER_MESSAGE_PTR (ParticleSystemRenderer, kDidDeleteMesh, OnDidDeleteMesh, Mesh);
- //}
- //void ParticleSystemRenderer::AwakeFromLoad (AwakeFromLoadMode awakeMode)
- //{
- // Super::AwakeFromLoad (awakeMode);
- // UpdateCachedMesh ();
- //}
- //void ParticleSystemRenderer::UpdateCachedMesh ()
- //{
- // int dst = 0;
- // for(int src = 0; src < ParticleSystemRendererData::kMaxNumParticleMeshes; src++)
- // {
- // m_Data.cachedMesh[src] = NULL;
- // m_Data.cachedMeshUserNode[src].RemoveFromList ();
- //
- // Mesh* mesh = m_Mesh[src];
- // if (mesh)
- // {
- // if (mesh->GetSubMeshCount() == 1)
- // {
- // m_Data.cachedMesh[dst] = mesh;
- // const SubMesh& sm = mesh->GetSubMeshFast(0);
- // const UInt16* buffer = mesh->GetSubMeshBuffer16(0);
- //
- // if (sm.topology == kPrimitiveTriangleStripDeprecated)
- // {
- // const int capacity = CountTrianglesInStrip(buffer, sm.indexCount) * 3;
- // m_CachedIndexBuffer[dst].resize_uninitialized(capacity);
- // Destripify(buffer, sm.indexCount, m_CachedIndexBuffer[dst].begin(), capacity);
- // }
- // else if (sm.topology == kPrimitiveTriangles)
- // {
- // const int capacity = sm.indexCount;
- // m_CachedIndexBuffer[dst].resize_uninitialized(capacity);
- // memcpy(m_CachedIndexBuffer[dst].begin(), buffer, capacity*kVBOIndexSize);
- // }
- // else
- // {
- // m_CachedIndexBuffer[dst].resize_uninitialized(0);
- // }
- //
- // // Hook into mesh's user notifications.
- // mesh->AddObjectUser (m_Data.cachedMeshUserNode[dst]);
- //
- // dst++;
- // }
- // else
- // {
- // m_Data.cachedMesh[src] = NULL;
- // m_CachedIndexBuffer[src].resize_uninitialized(0);
- // AssertString ("Particle system meshes will only work with exactly one (1) sub mesh");
- // }
- // }
- // }
- //}
- //void ParticleSystemRenderer::OnDidDeleteMesh (Mesh* mesh)
- //{
- // // Clear out cached pointer to mesh.
- // for (int i = 0; i < ParticleSystemRendererData::kMaxNumParticleMeshes; ++i)
- // {
- // if (m_Data.cachedMesh[i] != mesh)
- // continue;
- //
- // m_Data.cachedMesh[i] = NULL;
- // m_Data.cachedMeshUserNode[i].RemoveFromList ();
- // }
- //}
- //void ParticleSystemRenderer::GetLocalAABB (AABB& result)
- //{
- // result = m_LocalSpaceAABB;
- //}
- //void ParticleSystemRenderer::GetWorldAABB (AABB& result)
- //{
- // TransformAABB (m_LocalSpaceAABB, GetTransform ().GetPosition (), GetTransform ().GetRotation (), result);
- //}
- float ParticleSystemRenderer::GetSortingFudge () const
- {
- return m_Data.sortingFudge;
- }
- //void ParticleSystemRenderer::CheckConsistency ()
- //{
- // Super::CheckConsistency ();
- // m_Data.maxParticleSize = std::max (0.0F, m_Data.maxParticleSize);
- // m_Data.normalDirection = clamp<float>(m_Data.normalDirection, 0.0f, 1.0f);
- //}
- void ParticleSystemRenderer::Reset ()
- {
- //Super::Reset ();
- m_Data.orthographic = false;
- m_Data.scale = 1.0F;
- m_Data.renderMode = kSRMBillboard;
- m_Data.lengthScale = 2.0F;
- m_Data.velocityScale = 0.0F;
- m_Data.cameraVelocityScale = 0.0F;
- m_Data.maxParticleSize = 0.5F;
- m_Data.sortingFudge = 0.0F;
- m_Data.sortMode = kSSMNone;
- m_Data.normalDirection = 1.0f;
- //for(int i = 0; i < ParticleSystemRendererData::kMaxNumParticleMeshes; i++)
- // m_Mesh[i] = NULL;
- //m_LocalSpaceAABB.SetCenterAndExtent (Vector3f::ZERO, Vector3f::ZERO);
- m_LocalSpaceAABB.set(Vector3f::ZERO, Vector3f::ZERO);
- #if UNITY_EDITOR
- m_EditorEnabled = true;
- #endif
- }
- //void ParticleSystemRenderer::UpdateRenderer ()
- //{
- // ParticleSystem* system = QueryComponent(ParticleSystem);
- // if (system)
- // {
- // SetVisible (true);
- // BoundsChanged();
- // }
- // else
- // {
- // UpdateManagerState (false);
- // }
- //
- // Super::UpdateRenderer ();
- //}
- //void ParticleSystemRenderer::Update (const AABB& aabb)
- //{
- // m_LocalSpaceAABB = aabb;
- // UpdateManagerState (true);
- //}
- void ParticleSystemRenderer::RendererBecameVisible()
- {
- //Super::RendererBecameVisible();
- //ParticleSystem* system = QueryComponent(ParticleSystem);
- //if(system)
- // system->RendererBecameVisible();
- }
- void ParticleSystemRenderer::RendererBecameInvisible()
- {
- //Super::RendererBecameInvisible();
- //ParticleSystem* system = QueryComponent(ParticleSystem);
- //if(system)
- // system->RendererBecameInvisible();
- }
- //void ParticleSystemRenderer::UpdateLocalAABB()
- //{
- // AABB aabb;
- // GetLocalAABB(aabb);
- // m_TransformInfo.localAABB = aabb;
- //}
- template<ParticleSystemRenderMode renderMode>
- void GenerateParticleGeometry (ParticleSystemVertex* vbPtr,
- const ParticleSystemGeomConstInputData& constData,
- const ParticleSystemRendererData& rendererData,
- const ParticleSystemParticles& ps,
- const ParticleSystemParticlesTempData& psTemp,
- size_t startIndex,
- size_t endIndex,
- const Matrix4x4f& worldViewMatrix,
- const Matrix4x4f& viewToWorldMatrix)
- {
- float maxPlaneScale = constData.maxPlaneScale;
- float maxOrthoSize = constData.maxOrthoSize;
- float numUVFrame = constData.numUVFrame;
- Vector3f xSpan = constData.xSpan;
- Vector3f ySpan = constData.ySpan;
- Vector3f cameraVelocity = constData.m_CameraVelocity * rendererData.cameraVelocityScale;
- int numTilesX = constData.m_NumTilesX;
- float animUScale = constData.animUScale;
- float animVScale = constData.animVScale;
- bool usesSheetIndex = constData.usesSheetIndex;
- int uvModuleMode = constData.uvModuleMode;
- float lengthScale = rendererData.lengthScale;
- float velocityScale = rendererData.velocityScale;
- float bentNormalFactor = constData.bentNormalFactor;
- Vector3f bentNormalVector = constData.bentNormalVector;
- bool isSpriteFrame = constData.isSpriteFrame;
- const RRP_PARTICLEQUAD_VERTEX_INFO* vertexInfo = constData.vertexInfo;
- auto frameCount = rendererData.cachedVertexInfos.size();
- Matrix3x3f scaleMatrix;
- scaleMatrix.SetScale(constData.globalScale);
- // Vector2f uv[4] = { Vector2f(0.0f, 1.0f),
- // Vector2f(1.0f, 1.0f),
- // Vector2f(1.0f, 0.0f),
- // Vector2f(0.0f, 0.0f)};
- // Vector4f uv2[4] = { Vector4f(0.0f, 1.0f, 0.0f, 0.0f),
- // Vector4f(1.0f, 1.0f, 0.0f, 0.0f),
- // Vector4f(1.0f, 0.0f, 0.0f, 0.0f),
- // Vector4f(0.0f, 0.0f, 0.0f, 0.0f)};
- Tex2F uv[4] = {
- vertexInfo->tl,
- vertexInfo->tr,
- vertexInfo->br,
- vertexInfo->bl
- };
- float invAnimVScale = 1.0f - animVScale;
- #if REDREAM_EDITOR
- auto stageContentToWorldMatrix = Transform::GetContentToWorldMatrix();
- #endif
- for( size_t i = startIndex; i < endIndex; ++i )
- {
- if (usesSheetIndex && uvModuleMode == 1 && frameCount > 0) {
- auto sheetIndex = psTemp.sheetIndex[i] * frameCount;
- const int index0 = FloorfToIntPos (sheetIndex);
- vertexInfo = &rendererData.cachedVertexInfos[index0];
- uv[0] = vertexInfo->tl,
- uv[1] = vertexInfo->tr;
- uv[2] = vertexInfo->br;
- uv[3] = vertexInfo->bl;
- }
- Vector3f vert[4];
- Vector3f n0, n1;
- Vector3f position;
- worldViewMatrix.MultiplyPoint3 (ps.position[i], position);
- // Constrain the size to be a fraction of the viewport size.
- // v[0].z * / farPlaneZ * farPlaneWorldSpaceLength * maxLength[0...1]
- // Also all valid z's are negative so we just negate the whole equation
- // float maxWorldSpaceLength = position.z * maxPlaneScale + maxOrthoSize;
- // float hsize = std::min (psTemp.size[i], maxWorldSpaceLength) * 0.5f;
- float hsize = psTemp.size[i] * 0.5f;
- if (renderMode == kSRMBillboard)
- {
- float r = ps.rotation[i] * kDeg2Rad;
- float s = Sin (r);
- float c = Cos (r);
- if (isSpriteFrame) {
- GLfloat x1 = -hsize * vertexInfo->centerPercentage.left;
- GLfloat y1 = -hsize * vertexInfo->centerPercentage.bottom;
- GLfloat x2 = hsize * vertexInfo->centerPercentage.right;
- GLfloat y2 = hsize * vertexInfo->centerPercentage.top;
- vert[0] = position + scaleMatrix.MultiplyVector3(Vec3(x1 * c + y2 * s, y2 * c - x1 * s, 0.0f));
- vert[1] = position + scaleMatrix.MultiplyVector3(Vec3(x2 * c + y2 * s, y2 * c - x2 * s, 0.0f));
- vert[2] = position + scaleMatrix.MultiplyVector3(Vec3(x2 * c + y1 * s, y1 * c - x2 * s, 0.0f));
- vert[3] = position + scaleMatrix.MultiplyVector3(Vec3(x1 * c + y1 * s, y1 * c - x1 * s, 0.0f));
- } else {
- n0 = scaleMatrix.MultiplyVector3(Vector3f(-c+s, s+c, 0.0f) * hsize);
- n1 = scaleMatrix.MultiplyVector3(Vector3f( c+s, -s+c, 0.0f) * hsize);
- vert[0] = position + n0;
- vert[1] = position + n1;
- vert[2] = position - n0;
- vert[3] = position - n1;
- }
- }
- else if (renderMode == kSRMBillboardFixedHorizontal || renderMode == kSRMBillboardFixedVertical)
- {
- float s = Sin ((ps.rotation[i]+0.78539816339744830961566084581988f) * kDeg2Rad);
- float c = Cos ((ps.rotation[i]+0.78539816339744830961566084581988f) * kDeg2Rad);
- n0 = scaleMatrix.MultiplyVector3((xSpan*c + ySpan*s) * hsize);
- n1 = scaleMatrix.MultiplyVector3((ySpan*c - xSpan*s) * hsize);
- vert[0] = position + n0;
- vert[1] = position + n1;
- vert[2] = position - n0;
- vert[3] = position - n1;
- }
- else if (renderMode == kSRMStretch3D)
- {
- //RH BUG FOR LATER: Here we see the stretching bug as described by case no 434115...this is a Flash VM error, where a writeFloat (or readFloat) fails.
- Vector3f velocity;
- worldViewMatrix.MultiplyVector3(ps.velocity[i] + ps.animatedVelocity[i], velocity);
- velocity -= cameraVelocity;
- float sqrVelocity = SqrMagnitude (velocity);
- auto camPos = Camera::getDefaultCamera()->getPosition3D();
- position -= camPos;
- Vector2f delta;
- Vector3f endProj;
- bool nonZeroVelocity = sqrVelocity > Vector3f::epsilon;
- if (nonZeroVelocity)
- {
- endProj = position - velocity * (velocityScale + FastInvSqrt (sqrVelocity) * (lengthScale * psTemp.size[i]));
- delta.x = position.z*endProj.y - position.y*endProj.z;
- delta.y = position.x*endProj.z - position.z*endProj.x;
- delta = NormalizeFast(delta);
- }
- else
- {
- endProj = position;
- delta = Vector2f::UNIT_X;
- }
- n0 = n1 = scaleMatrix.MultiplyVector3(Vector3f(delta.x, delta.y, 0.0f) * hsize);
- if (isSpriteFrame) {
- n0 *= vertexInfo->centerPercentage.top;
- n1 *= vertexInfo->centerPercentage.bottom;
-
- auto posTemp = position;
- position = endProj.lerp(position, vertexInfo->centerPercentage.left * 0.5f + 0.5f);
- endProj = posTemp.lerp(endProj, vertexInfo->centerPercentage.right * 0.5f + 0.5f);
- }
- position += camPos;
- endProj += camPos;
- vert[0] = position + n0;
- vert[1] = endProj + n0;
- vert[2] = endProj - n1;
- vert[3] = position - n1;
- }
- // UV animation
- float sheetIndex;
- if(usesSheetIndex && uvModuleMode == 0 && !isSpriteFrame)
- {
- // TODO: Pretty much the perfect candidate for SIMD
- sheetIndex = psTemp.sheetIndex[i] * numUVFrame;
- Assert (psTemp.sheetIndex[i] >= 0.0f && psTemp.sheetIndex[i] <= 1.0f);
- const int index0 = FloorfToIntPos (sheetIndex);
- const int index1 = index0 + 1;
- Vector2f offset0, offset1;
- const float blend = sheetIndex - (float)index0;
- int vIdx = index0 / numTilesX;
- int uIdx = index0 - vIdx * numTilesX;
- offset0.x = (float)uIdx * animUScale;
- // offset0.y = invAnimVScale - (float)vIdx * animVScale;
- offset0.y = (float)vIdx * animVScale;
- vIdx = index1 / numTilesX;
- uIdx = index1 - vIdx * numTilesX;
- offset1.x = (float)uIdx * animUScale;
- // offset1.y = invAnimVScale - (float)vIdx * animVScale;
- offset1.y = (float)vIdx * animVScale;
- // uv[0].set(offset0.x, offset0.y + animVScale );
- // uv[1].set(offset0.x + animUScale, offset0.y + animVScale );
- // uv[2].set(offset0.x + animUScale, offset0.y );
- // uv[3].set(offset0.x, offset0.y );
- uv[0].u = offset0.x; uv[0].v = offset0.y; // invers v, top-left
- uv[1].u = offset0.x + animUScale; uv[1].v = offset0.y; // invers v, top-right
- uv[2].u = offset0.x + animUScale; uv[2].v = offset0.y + animVScale; // invers v, bottom-right
- uv[3].u = offset0.x; uv[3].v = offset0.y + animVScale; // invers v, bottom-left
- // uv2[0].set(offset1.x, offset1.y + animVScale, blend, 0.0f );
- // uv2[1].set(offset1.x + animUScale, offset1.y + animVScale, blend, 0.0f );
- // uv2[2].set(offset1.x + animUScale, offset1.y, blend, 0.0f );
- // uv2[3].set(offset1.x, offset1.y, blend, 0.0f );
- }
- n0 = viewToWorldMatrix.MultiplyVector3(n0 * bentNormalFactor);
- n1 = viewToWorldMatrix.MultiplyVector3(n1 * bentNormalFactor);
-
- // ColorRGBAf color = ColorRGBAf(psTemp.color[i]);
- auto& color = psTemp.color[i];
-
- #if REDREAM_EDITOR
- for (int i = 0; i < 4; i++) {
- vert[i] = stageContentToWorldMatrix.MultiplyPoint3(vert[i]);
- }
- #endif
- vbPtr->tl.vertices = vert[0];
- // vbPtr[0].normal = bentNormalVector + n0;
- vbPtr->tl.colors = color;
- vbPtr->tl.texCoords = Tex2F(uv[0]);
- // vbPtr[0].tangent = uv2[0];
- vbPtr->tr.vertices = vert[1];
- // vbPtr[1].normal = bentNormalVector + n1;
- vbPtr->tr.colors = color;
- vbPtr->tr.texCoords = Tex2F(uv[1]);
- // vbPtr[1].tangent = uv2[1];
- vbPtr->br.vertices = vert[2];
- // vbPtr[2].normal = bentNormalVector - n0;
- vbPtr->br.colors = color;
- vbPtr->br.texCoords = Tex2F(uv[2]);
- // vbPtr[2].tangent = uv2[2];
- vbPtr->bl.vertices = vert[3];
- // vbPtr[3].normal = bentNormalVector - n1;
- vbPtr->bl.colors = color;
- vbPtr->bl.texCoords = Tex2F(uv[3]);
- // vbPtr[3].tangent = uv2[3];
- // Next four vertices
- // vbPtr += 4;
- vbPtr++;
- }
- }
- //static void DrawMeshParticles (const ParticleSystemGeomConstInputData& constInput, const ParticleSystemRendererData& rendererData, const Matrix4x4f& worldMatrix, const ParticleSystemParticles& ps, const ParticleSystemParticlesTempData& psTemp, const ChannelAssigns& channels)
- //{
- // int numMeshes = 0;
- // ParticleMeshData particleMeshes[ParticleSystemRendererData::kMaxNumParticleMeshes];
- // Vector3f defaultNormal(0, 0, 0);
- // Vector4f defaultTangent(0, 0, 0, 0);
- // ColorRGBA32 defaultColor(255, 255, 255, 255);
- // Vector2f defaultTexCoords(0, 0);
- // for(int i = 0; i < ParticleSystemRendererData::kMaxNumParticleMeshes; i++)
- // {
- // if(constInput.m_MeshIndexCount[i] == 0)
- // break;
- // const Mesh* mesh = rendererData.cachedMesh[i];
- // if(mesh == NULL || !mesh->HasVertexData())
- // break;
- // ParticleMeshData& dest = particleMeshes[i];
- // dest.vertexCount = mesh->GetVertexCount();
- // dest.positions = mesh->GetVertexBegin();
- // dest.normals = mesh->GetNormalBegin();
- // if (dest.normals.IsNull())
- // dest.normals = StrideIterator<Vector3f>(&defaultNormal, 0);
- // dest.tangents = mesh->GetTangentBegin();
- // if (dest.tangents.IsNull())
- // dest.tangents = StrideIterator<Vector4f>(&defaultTangent, 0);
- // dest.texCoords = mesh->GetUvBegin();
- // if (dest.texCoords.IsNull())
- // dest.texCoords = StrideIterator<Vector2f>(&defaultTexCoords, 0);
- // dest.colors = mesh->GetColorBegin();
- // if (dest.colors.IsNull())
- // dest.colors = StrideIterator<ColorRGBA32>(&defaultColor, 0);
- // dest.indexCount = constInput.m_MeshIndexCount[i];
- // dest.indexBuffer = constInput.m_MeshIndexBuffer[i];
- // numMeshes++;
- // }
- //
- // if(0 == numMeshes)
- // return;
- //
- // GfxDevice& device = GetGfxDevice();
- //
- // Matrix4x4f viewMatrix;
- // CopyMatrix (device.GetViewMatrix (), viewMatrix.GetPtr ());
- //
- // const size_t particleCount = ps.array_size ();
- //
- // float probability = 1.0f / (float)numMeshes;
- //
- // // @TODO: We should move all these platform dependent numbers into Gfx specific code and get it from there.
- // const int kMaxVertices = 65536;
- //
- //#if UNITY_WII
- // const int kMaxIndices = 65536;
- //#else
- // const int kMaxIndices = kDynamicBatchingIndicesThreshold;
- //#endif
- //
- // int particleOffset = 0;
- // while (particleOffset < particleCount)
- // {
- // int numVertices = 0;
- // int numIndices = 0;
- // int particleCountBatch = 0;
- //
- // // Figure out batch size
- // for(int i = particleOffset; i < particleCount; i++)
- // {
- // const float randomValue = GenerateRandom(ps.randomSeed[i] + kParticleSystemMeshSelectionId);
- // int lastNumVertices = 0;
- // int lastNumIndices = 0;
- // for(int j = 0; j < numMeshes; j++)
- // {
- // const float lower = probability * j;
- // const float upper = probability * (j + 1);
- // if((randomValue >= lower) && (randomValue <= upper))
- // {
- // lastNumVertices = particleMeshes[j].vertexCount;
- // lastNumIndices = particleMeshes[j].indexCount;
- // break;
- // }
- // }
- // if((numVertices >= kMaxVertices) || (numIndices >= kMaxIndices))
- // {
- // break;
- // }
- // else
- // {
- // numVertices += lastNumVertices;
- // numIndices += lastNumIndices;
- // particleCountBatch++;
- // }
- // }
- //
- // const int vertexCount = numVertices;
- // const int indexCount = numIndices;
- //
- // // Figure out if normals and tangents are needed by shader
- // UInt32 normalTangentMask = channels.GetSourceMap() & VERTEX_FORMAT2(Normal, Tangent);
- //
- // // Tangents requires normals
- // if( normalTangentMask & VERTEX_FORMAT1(Tangent) )
- // normalTangentMask |= VERTEX_FORMAT1(Normal);
- //
- // // Get VBO chunk
- // DynamicVBO& vbo = device.GetDynamicVBO();
- // UInt8* vbPtr = NULL;
- // UInt16* ibPtr = NULL;
- // const UInt32 mandatoryChannels = VERTEX_FORMAT3(Vertex, Color, TexCoord0);
- // if( !vbo.GetChunk( mandatoryChannels | normalTangentMask,
- // vertexCount, indexCount,
- // DynamicVBO::kDrawIndexedTriangles,
- // (void**)&vbPtr, (void**)&ibPtr ) )
- // {
- // return;
- // }
- //
- // int vertexOffset = 0;
- // int indexOffset = 0;
- // const int startIndex = particleOffset;
- // const int endIndex = particleOffset + particleCountBatch;
- // for( int i = startIndex; i < endIndex; ++i )
- // {
- // const Vector3f position = ps.position[i];
- // const float rotation = ps.rotation[i];
- // const float size = psTemp.size[i];
- // const Vector3f axisOfRotation = NormalizeSafe (ps.axisOfRotation[i], Vector3f::yAxis);
- // const ColorRGBA32 particleColor = psTemp.color[i];
- //
- // // Only shared part is actually rotation. xformNoScale doesn't need a translation, so no need to copy that data
- // Matrix4x4f xformNoScale;
- // xformNoScale.SetTR (position, AxisAngleToQuaternion (axisOfRotation, rotation));
- //
- // Matrix4x4f xform = xformNoScale;
- // ScaleMatrix(xform, size);
- //
- // // Figure out which mesh to use
- // const float randomValue = GenerateRandom(ps.randomSeed[i] + kParticleSystemMeshSelectionId);
- // int meshIndex = 0;
- // for(int j = 0; j < numMeshes; j++)
- // {
- // const float lower = probability * j;
- // const float upper = probability * (j + 1);
- // if((randomValue >= lower) && (randomValue <= upper))
- // {
- // meshIndex = j;
- // break;
- // }
- // }
- //
- // const ParticleMeshData& mesh = particleMeshes[meshIndex];
- //
- // // Fill up vbo here
- // if( normalTangentMask == VERTEX_FORMAT2(Normal, Tangent) )
- // TransformParticleMesh<true, true>(mesh, particleColor, xform, xformNoScale, &vbPtr);
- // else if( normalTangentMask == VERTEX_FORMAT1(Normal) )
- // TransformParticleMesh<true, false>(mesh, particleColor, xform, xformNoScale, &vbPtr);
- // else if( normalTangentMask == 0 )
- // TransformParticleMesh<false, false>(mesh, particleColor, xform, xformNoScale, &vbPtr);
- // else
- // ErrorString("Invalid normalTangentMask");
- //
- // const int meshIndexMax = mesh.indexCount - 2;
- // for(int index = 0; index < meshIndexMax; index+=3)
- // {
- // ibPtr[index+0] = mesh.indexBuffer[index+0] + vertexOffset;
- // ibPtr[index+1] = mesh.indexBuffer[index+1] + vertexOffset;
- // ibPtr[index+2] = mesh.indexBuffer[index+2] + vertexOffset;
- // }
- // ibPtr += mesh.indexCount;
- //
- // vertexOffset += mesh.vertexCount;
- // indexOffset += mesh.indexCount;
- // }
- //
- // vbo.ReleaseChunk (vertexCount, indexCount);
- // device.SetViewMatrix(viewMatrix.GetPtr());
- // device.SetWorldMatrix(worldMatrix.GetPtr());
- // vbo.DrawChunk (channels);
- // GPU_TIMESTAMP();
- //
- // particleOffset += particleCountBatch;
- // }
- //}
- static void DrawParticlesInternal(const ParticleSystemGeomConstInputData& constData, const ParticleSystemRendererData& rendererData, const Matrix4x4f& worldViewMatrix, const Matrix4x4f& viewToWorldMatrix, const ParticleSystemParticles& ps, const ParticleSystemParticlesTempData& psTemp, ParticleSystemVertex* vbPtr, const size_t particleOffset, const size_t numParticles, int renderMode)
- {
- const size_t endIndex = particleOffset + numParticles;
- //renderMode = kSRMStretch3D;
-
- if (renderMode == kSRMBillboard)
- GenerateParticleGeometry<kSRMBillboard> (vbPtr, constData, rendererData, ps, psTemp, particleOffset, endIndex, worldViewMatrix, viewToWorldMatrix);
- if (renderMode == kSRMStretch3D)
- GenerateParticleGeometry<kSRMStretch3D> (vbPtr, constData, rendererData, ps, psTemp, particleOffset, endIndex, worldViewMatrix, viewToWorldMatrix);
- if (renderMode == kSRMBillboardFixedHorizontal)
- GenerateParticleGeometry<kSRMBillboardFixedHorizontal> (vbPtr, constData, rendererData, ps, psTemp, particleOffset, endIndex, worldViewMatrix, viewToWorldMatrix);
- if (renderMode == kSRMBillboardFixedVertical)
- GenerateParticleGeometry<kSRMBillboardFixedVertical> (vbPtr, constData, rendererData, ps, psTemp, particleOffset, endIndex, worldViewMatrix, viewToWorldMatrix);
- }
- static void DrawParticles(const ParticleSystemGeomConstInputData& constData, const ParticleSystemRendererData& rendererData, const Matrix4x4f& worldViewMatrix, const Matrix4x4f& viewToWorldMatrix, const ParticleSystemParticles& ps, const ParticleSystemParticlesTempData& psTemp, ParticleSystemVertex* vbPtr)
- {
-
- //GfxDevice& device = GetGfxDevice();
- const size_t particleCount = ps.array_size();
- if(vbPtr)
- {
- DrawParticlesInternal(constData, rendererData, worldViewMatrix, viewToWorldMatrix, ps, psTemp, vbPtr, 0, particleCount, rendererData.renderMode);
- }
- else
- {
- int particleOffset = 0;
- while (particleOffset < particleCount)
- {
- const int particleCountBatch = std::min(kMaxNumParticlesPerBatch, (int)particleCount - particleOffset);
- unsigned int vertexCnount = sizeof(V3F_C4B_T2F);
- vbPtr = (ParticleSystemVertex*)malloc(vertexCnount * particleCountBatch * 4);
- DrawParticlesInternal(constData, rendererData, worldViewMatrix, viewToWorldMatrix, ps, psTemp, vbPtr, particleOffset, particleCountBatch, rendererData.renderMode);
- particleOffset += particleCountBatch;
- GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION |
- GL::VERTEX_ATTRIB_FLAG_COLOR |
- GL::VERTEX_ATTRIB_FLAG_TEX_COORD);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- if (rendererData.orthographic)
- {
- glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, vertexCnount, &(vbPtr->tl.vertices));
- }
- else
- {
- glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, vertexCnount, &(vbPtr->tl.vertices));
- }
- glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, vertexCnount, &(vbPtr->tl.texCoords));
- glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexCnount, &(vbPtr->tl.colors));
- GLuint* vertexIndexBuff = new GLuint[particleCountBatch * 6];
- for(int particleIdx = 0; particleIdx < particleCountBatch; particleIdx++){
- int idx0 = particleIdx * 4 + 0;
- int idx1 = particleIdx * 4 + 1;
- int idx2 = particleIdx * 4 + 2;
- int idx3 = particleIdx * 4 + 3;
- vertexIndexBuff[particleIdx * 6 + 0] = idx0;
- vertexIndexBuff[particleIdx * 6 + 1] = idx1;
- vertexIndexBuff[particleIdx * 6 + 2] = idx2;
- vertexIndexBuff[particleIdx * 6 + 3] = idx3;
- vertexIndexBuff[particleIdx * 6 + 4] = idx2;
- vertexIndexBuff[particleIdx * 6 + 5] = idx1;
- }
- glDrawElements(GL_TRIANGLES, particleCountBatch * 6, GL_UNSIGNED_INT, vertexIndexBuff);
- delete[] vertexIndexBuff;
- free(vbPtr);
- CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, vertexCnount);
- CHECK_GL_ERROR_DEBUG();
- }
- }
- }
- void ParticleSystemRenderer::CalculateTotalParticleCount(UInt32& totalNumberOfParticles, RParticleSystem& system, bool first)
- {
- //ParticleSystemRenderer* renderer = system.QueryComponent(RParticleSystemRenderer);
- //if(!renderer || first)
- //{
- // totalNumberOfParticles += system.GetParticleCount();
- // Transform* t = system.QueryComponent (Transform);
- // if (t == NULL)
- // return;
- // for (Transform::iterator i=t->begin ();i != t->end ();i++)
- // {
- // ParticleSystem* child = (**i).QueryComponent(ParticleSystem);
- // if (child)
- // CalculateTotalParticleCount(totalNumberOfParticles, *child, false);
- // }
- //}
-
- totalNumberOfParticles += system.GetParticleCount();
- }
- void ParticleSystemRenderer::CombineParticleBuffersRec(int& offset, ParticleSystemParticles& ps, ParticleSystemParticlesTempData& psTemp, RParticleSystem& system, bool first, bool needsAxisOfRotation)
- {
- if(first)
- {
- int particleCount = system.GetParticleCount();
- ps.array_merge_preallocated(system.GetParticles(), offset, needsAxisOfRotation, false);
- if(system.m_ReadOnlyState->useLocalSpace)
- {
- Matrix4x4f localToWorld = system.getNodeToWorldTransform();
- int endIndex = offset + particleCount;
- for(int i = offset; i < endIndex; i++)
- ps.position[i] = localToWorld.MultiplyPoint3(ps.position[i]);
- for(int i = offset; i < endIndex; i++)
- ps.velocity[i] = localToWorld.MultiplyVector3(ps.velocity[i]);
- for(int i = offset; i < endIndex; i++)
- ps.animatedVelocity[i] = localToWorld.MultiplyVector3(ps.animatedVelocity[i]);
- if(ps.usesAxisOfRotation)
- for(int i = offset; i < endIndex; i++)
- ps.axisOfRotation[i] = localToWorld.MultiplyVector3(ps.axisOfRotation[i]);
- }
- RParticleSystem::UpdateModulesNonIncremental(system, ps, psTemp, offset, offset + particleCount);
- offset += particleCount;
- }
- }
- void ParticleSystemRenderer::SetUsesAxisOfRotationRec(RParticleSystem& shuriken, bool first)
- {
- if(first)
- {
- shuriken.SetUsesAxisOfRotation();
- }
- }
- //void ParticleSystemRenderer::CombineBoundsRec(RParticleSystem& shuriken, MinMaxAABB& aabb, bool first)
- //{
- // ParticleSystemRenderer* renderer = shuriken.QueryComponent(ParticleSystemRenderer);
- // if(!renderer || first)
- // {
- // AABB result = shuriken.m_State->minMaxAABB;
- // if(!shuriken.m_ReadOnlyState->useLocalSpace)
- // InverseTransformAABB (result, renderer->GetTransform().GetPosition (), renderer->GetTransform().GetRotation (), result);
- //
- // if(first)
- // aabb = result;
- // else
- // aabb.Encapsulate(result);
- //
- // Transform* t = shuriken.QueryComponent (Transform);
- // if (t == NULL)
- // return;
- // for (Transform::iterator i=t->begin ();i != t->end ();i++)
- // {
- // ParticleSystem* shuriken = (**i).QueryComponent(ParticleSystem);
- // if (shuriken)
- // CombineBoundsRec(*shuriken, aabb, false);
- // }
- // }
- //}
- void ParticleSystemRenderer::Render (RParticleSystem* system, ParticleSystemVertex* vbPtr/* int materialIndex, const ChannelAssigns& channels*/, const Matrix4x4f &transform)
- {
- //ParticleSystem::SyncJobs();
- //ParticleSystem* system = QueryComponent(ParticleSystem);
- //if(!system)
- // return;
- //// Can't render without an active camera (case 568930)
- //// Can remove check when we finally kill Renderer.Render()
- //if (!GetCurrentCameraPtr())
- // return;
- //PROFILER_AUTO_GFX(gParticlesSingleProfile, this);
- RParticleSystem::SyncJobs();
- UInt32 numParticles = 0;
- CalculateTotalParticleCount(numParticles, *system, true);
- if(numParticles)
- RenderInternal(*system, *this, vbPtr, numParticles, transform);
- }
- //void ParticleSystemRenderer::RenderMultiple (const BatchInstanceData* instances, size_t count, const ChannelAssigns& channels)
- //{
- // ParticleSystem::SyncJobs();
- //
- // size_t numParticlesBatch = 0;
- //
- // BatchInstanceData const* instancesEnd = instances + count;
- // BatchInstanceData const* iBatchBegin = instances;
- // BatchInstanceData const* iBatchEnd = instances;
- // while(iBatchEnd != instancesEnd)
- // {
- // Assert(iBatchEnd->renderer->GetRendererType() == kRendererParticleSystem);
- // ParticleSystemRenderer* psRenderer = (ParticleSystemRenderer*)iBatchEnd->renderer;
- // Assert(psRenderer->GetRenderMode() != kSRMMesh);
- // ParticleSystem* system = psRenderer->QueryComponent(ParticleSystem);
- // if (!system )
- // {
- // iBatchEnd++;
- // continue;
- // }
- // UInt32 numParticles = 0;
- // psRenderer->CalculateTotalParticleCount(numParticles, *system, true);
- //
- // if((numParticlesBatch + numParticles) <= kMaxNumParticlesPerBatch)
- // {
- // numParticlesBatch += numParticles;
- // iBatchEnd++;
- // }
- // else
- // {
- // if(numParticlesBatch)
- // {
- // RenderBatch(iBatchBegin, iBatchEnd - iBatchBegin, numParticlesBatch, channels);
- // numParticlesBatch = 0;
- // iBatchBegin = iBatchEnd;
- // }
- // else // Can't fit in one draw call
- // {
- // RenderBatch(iBatchEnd, 1, numParticles, channels);
- // iBatchEnd++;
- // iBatchBegin = iBatchEnd;
- // }
- // }
- // }
- //
- // if((iBatchBegin != iBatchEnd) && numParticlesBatch)
- // RenderBatch(iBatchBegin, iBatchEnd - iBatchBegin, numParticlesBatch, channels);
- //}
- //void ParticleSystemRenderer::RenderBatch (const BatchInstanceData* instances, size_t count, size_t numParticles, const ChannelAssigns& channels)
- //{
- // DebugAssert(numParticles);
- //
- // GfxDevice& device = GetGfxDevice();
- //
- // const MaterialPropertyBlock* customProps = count > 0 ? instances[0].renderer->GetCustomProperties() : NULL;
- // if (customProps)
- // device.SetMaterialProperties (*customProps);
- //
- // Matrix4x4f viewMatrix;
- // CopyMatrix (device.GetViewMatrix (), viewMatrix.GetPtr ());
- //
- // ParticleSystemVertex* vbPtr = 0;
- // DynamicVBO& vbo = device.GetDynamicVBO();
- // if(numParticles <= kMaxNumParticlesPerBatch)
- // {
- // if( !vbo.GetChunk( (1<<kShaderChannelVertex) | (1<<kShaderChannelNormal) | (1<<kShaderChannelTexCoord0) | (1<<kShaderChannelColor) | (1<<kShaderChannelTangent),
- // numParticles * 4, 0,
- // DynamicVBO::kDrawQuads,
- // (void**)&vbPtr, NULL ) )
- // {
- // return;
- // }
- // }
- //
- // PROFILER_AUTO_GFX(gParticlesBatchProfile, 0);
- //
- // // Allocate VBO if count is not above threshold. Else just pass null down
- // BatchInstanceData const* iBatchBegin = instances;
- // BatchInstanceData const* instancesEnd = instances + count;
- // size_t particleOffset = 0;
- // while (iBatchBegin != instancesEnd)
- // {
- // Assert(iBatchBegin->renderer->GetRendererType() == kRendererParticleSystem);
- // ParticleSystemRenderer* psRenderer = (ParticleSystemRenderer*)iBatchBegin->renderer;
- // Assert(psRenderer->GetRenderMode() != kSRMMesh);
- // ParticleSystem* system = psRenderer->QueryComponent(ParticleSystem);
- // UInt32 particleCountTotal = 0;
- // if (system)
- // {
- // // It would be nice to filter out NULL particle systems earlier, but we don't (case 504744)
- // CalculateTotalParticleCount(particleCountTotal, *system, true);
- // if(particleCountTotal)
- // RenderInternal(*system, *psRenderer, channels, vbPtr + particleOffset * 4, particleCountTotal);
- // }
- // iBatchBegin++;
- // particleOffset += particleCountTotal;
- // }
- //
- // if(vbPtr)
- // {
- // vbo.ReleaseChunk (numParticles * 4, 0);
- //
- // // Draw
- // device.SetViewMatrix (Matrix4x4f::identity.GetPtr()); // implicitly sets world to identity
- //
- // PROFILER_BEGIN(gSubmitVBOParticleProfile, 0)
- // vbo.DrawChunk (channels);
- // GPU_TIMESTAMP();
- // PROFILER_END
- //
- // if (count > 1)
- // device.AddBatchingStats(numParticles * 2, numParticles * 4, count);
- //
- // device.SetViewMatrix(viewMatrix.GetPtr());
- // }
- //}
- void ParticleSystemRenderer::RenderInternal (RParticleSystem& system, const ParticleSystemRenderer& renderer, ParticleSystemVertex* vbPtr, UInt32 particleCountTotal, const Matrix4x4f &transform)
- {
- Assert(particleCountTotal);
- #if UNITY_EDITOR
- if (!renderer.m_EditorEnabled)
- return;
- #endif
- //c-edit GfxDevice& device = GetGfxDevice();
- // Render matrix
- Matrix4x4f viewMatrix;
- viewMatrix = Matrix4x4f::IDENTITY;
- //c-edit CopyMatrix (device.GetViewMatrix (), viewMatrix.GetPtr ());
- ParticleSystemParticles* ps = &system.GetParticles ();
- size_t particleCount = ps->array_size ();
- AssertBreak(particleCountTotal >= particleCount);
- UInt8* combineBuffer = 0;
- ParticleSystemParticles combineParticles;
- if(particleCountTotal > particleCount)
- {
- particleCount = particleCountTotal;
- combineBuffer = ALLOC_TEMP_MANUAL(UInt8, particleCountTotal * ParticleSystemParticles::GetParticleSize());
- combineParticles.array_assign_external((void*)&combineBuffer[0], particleCountTotal);
- ps = &combineParticles;
- }
- if(!particleCount)
- return;
- const bool needsAxisOfRotation = !renderer.GetScreenSpaceRotation();
- if(needsAxisOfRotation)
- {
- SetUsesAxisOfRotationRec (system, true);
- }
- ParticleSystemSortMode sortMode = (ParticleSystemSortMode)renderer.m_Data.sortMode;
- bool isInLocalSpace = system.m_ReadOnlyState->useLocalSpace && !combineBuffer;
- Matrix4x4f worldMatrix = Matrix4x4f::IDENTITY;
- #if REDREAM_EDITOR
- if(isInLocalSpace){
- //worldMatrix = system.GetComponent (Transform).GetLocalToWorldMatrixNoScale ();
- worldMatrix = Transform::GetLocalToWorldMatrixNoScale(&system);
- }
- #else
- if(isInLocalSpace){
- //worldMatrix = system.GetComponent (Transform).GetLocalToWorldMatrixNoScale ();
- worldMatrix = transform;
- } else {
- worldMatrix = Director::getInstance()->getRunningScene()->getNodeToParentTransform();
- }
- #endif
- ParticleSystemParticlesTempData psTemp;
- psTemp.color = ALLOC_TEMP_MANUAL(ColorRGBA32, particleCount);
- psTemp.size = ALLOC_TEMP_MANUAL(float, particleCount);
- psTemp.sheetIndex = 0;
- psTemp.particleCount = particleCount;
- psTemp.particleSysytemWorldPos = ALLOC_TEMP_MANUAL(Vec3, particleCount);
- if(combineBuffer)
- {
- int offset = 0;
- CombineParticleBuffersRec(offset, *ps, psTemp, system, true, needsAxisOfRotation);
- if (kSSMNone != sortMode)
- Sort(viewMatrix, *ps, sortMode, &psTemp, true);
- }
- else
- {
- if(system.m_UVModule->GetEnabled())
- psTemp.sheetIndex = ALLOC_TEMP_MANUAL(float, particleCount);
- if (kSSMNone != sortMode)
- {
- Matrix4x4f objectToViewMatrix;
- MultiplyMatrices3x4(viewMatrix, worldMatrix, objectToViewMatrix);
- Sort(objectToViewMatrix, *ps, sortMode, 0, false);
- }
- RParticleSystem::UpdateModulesNonIncremental(system, *ps, psTemp, 0, particleCount);
- }
- if (system._opacityModifyRGB) {
- for (int i = 0; i < particleCount; i++) {
- auto& color = psTemp.color[i];
- color.r *= color.a / 255.0f;
- color.g *= color.a / 255.0f;
- color.b *= color.a / 255.0f;
- }
- }
- // Constrain the size to be a fraction of the viewport size.
- // In perspective case, max size is (z*factorA). In ortho case, max size is just factorB. To have both
- // without branches, we do (z*factorA+factorB) and set one of factors to zero.
- float maxPlaneScale = 0.0f;
- float maxOrthoSize = 0.0f;
- // Getting the camera isn't totally free, so do it once.
-
- Camera* camera = Camera::getDefaultCamera();
-
- //if (!camera.GetOrthographic())
- // maxPlaneScale = -camera.CalculateFarPlaneWorldSpaceLength() * renderer.m_Data.maxParticleSize / camera.GetFar();
- //else
- // maxOrthoSize = camera.CalculateFarPlaneWorldSpaceLength() * renderer.m_Data.maxParticleSize;
-
- //maxOrthoSize = camera->getFarPlane() * renderer.m_Data.maxParticleSize;
-
-
- if (true){
- Size fSize = Director::getInstance()->getOpenGLView()->getFrameSize();
- float len = Vec2(fSize.width, fSize.height).getLength();
- maxPlaneScale = - len * renderer.m_Data.maxParticleSize / camera->getFarPlane();
- //maxPlaneScale = -camera.CalculateFarPlaneWorldSpaceLength() * renderer.m_Data.maxParticleSize / camera.GetFar();
- //maxPlaneScale =
- }
- else{
- //maxOrthoSize = camera.CalculateFarPlaneWorldSpaceLength() * renderer.m_Data.maxParticleSize;
- Size fSize = Director::getInstance()->getOpenGLView()->getFrameSize();
- float len = Vec2(fSize.width, fSize.height).getLength();
- maxOrthoSize = len * renderer.m_Data.maxParticleSize;
- }
-
- int numMeshes = 0;
- for(int i = 0; i < ParticleSystemRendererData::kMaxNumParticleMeshes; i++)
- if(renderer.m_Data.cachedMesh[i])
- numMeshes++;
- ParticleSystemGeomConstInputData constData;
- constData.m_ViewMatrix = viewMatrix;
- //constData.m_CameraVelocity = viewMatrix.MultiplyVector3(camera.GetVelocity ());
- constData.m_CameraVelocity = viewMatrix.MultiplyVector3(Vec3::ZERO);
-
- //TODO
- //constData.m_Renderer = (Object*)&renderer;
- //for(int i = 0; i < numMeshes; i++)
- //{
- // constData.m_MeshIndexBuffer[i] = renderer.m_CachedIndexBuffer[i].begin();
- // constData.m_MeshIndexCount[i] = renderer.m_CachedIndexBuffer[i].size();
- // AssertBreak((constData.m_MeshIndexCount[i] % 3) == 0);
- //}
- system.GetNumTiles(constData.m_NumTilesX, constData.m_NumTilesY);
-
- constData.maxPlaneScale = maxPlaneScale;
- constData.maxOrthoSize = maxOrthoSize;
- constData.numUVFrame = constData.m_NumTilesX * constData.m_NumTilesY;
- constData.animUScale = 1.0f / (float)constData.m_NumTilesX;
- constData.animVScale = 1.0f / (float)constData.m_NumTilesY;
- constData.xSpan = Vector3f(-1.0f,0.0f,0.0f);
- constData.ySpan = Vector3f(0.0f,0.0f,1.0f);
- if (renderer.m_Data.renderMode == kSRMBillboardFixedVertical)
- {
- constData.ySpan = Vector3f(0.0f,1.0f,0.0f);
- const Vector3f zSpan = viewMatrix.MultiplyVector3 (Vector3f::UNIT_Z);// (RotateVectorByQuat (cameraRotation, Vector3f(0.0f,0.0f,1.0f));
- constData.xSpan = NormalizeSafe (Cross (constData.ySpan, zSpan));
- }
- constData.xSpan = viewMatrix.MultiplyVector3(constData.xSpan);
- constData.ySpan = viewMatrix.MultiplyVector3(constData.ySpan);
- constData.usesSheetIndex = psTemp.sheetIndex != NULL;
- constData.uvModuleMode = system.getUVModuleMode();
- constData.isSpriteFrame = system._isSpriteFrame;
- constData.vertexInfo = &system._vertexInfo;
- const float bentNormalAngle = renderer.m_Data.normalDirection * 90.0f * kDeg2Rad;
- const float scale = (renderer.m_Data.renderMode == kSRMBillboard) ? 0.707106781f : 1.0f;
- Matrix4x4f viewToWorldMatrix;
- Matrix4x4f::Invert_General3D(viewMatrix, viewToWorldMatrix);
- Matrix4x4f worldViewMatrix;
- //MultiplyMatrices4x4(&viewMatrix, &worldMatrix, &worldViewMatrix);
- Matrix4x4f::multiply(viewMatrix, worldMatrix, &worldViewMatrix);
- Vector3f billboardNormal = Vector3f::UNIT_Z;
- if((renderer.m_Data.renderMode == kSRMBillboardFixedHorizontal) || (renderer.m_Data.renderMode == kSRMBillboardFixedVertical))
- billboardNormal = viewMatrix.MultiplyVector3 (NormalizeSafe (Cross (constData.xSpan, constData.ySpan)));
- constData.bentNormalVector = viewToWorldMatrix.MultiplyVector3(Sin(bentNormalAngle) * billboardNormal);
- constData.bentNormalFactor = Cos(bentNormalAngle) * scale;
- switch (system.getScalingMode()) {
- case kParticleSystemScalingModeHierarchy:
- transform.decompose(&constData.globalScale, nullptr, nullptr);
- break;
- case kParticleSystemScalingModeLocal:
- system.getNodeToParentTransform().decompose(&constData.globalScale, nullptr, nullptr);
- break;
- case kParticleSystemScalingModeShape:
- constData.globalScale.set(1, 1, 1);
- break;
- }
- if (renderer.m_Data.renderMode == kSRMMesh){
- //DrawMeshParticles (constData, renderer.m_Data, worldMatrix, *ps, psTemp);
- }else{
- DrawParticles(constData, renderer.m_Data, worldViewMatrix, viewToWorldMatrix, *ps, psTemp, vbPtr);
- //const size_t particleCount = ps->array_size();
- //DrawParticlesInternal(constData, renderer.m_Data, worldViewMatrix, viewToWorldMatrix, *ps, psTemp, vbPtr, 0, particleCount, renderer.m_Data.renderMode);
- }
- FREE_TEMP_MANUAL(psTemp.color);
- FREE_TEMP_MANUAL(psTemp.size);
- FREE_TEMP_MANUAL(psTemp.particleSysytemWorldPos);
- if(psTemp.sheetIndex)
- FREE_TEMP_MANUAL(psTemp.sheetIndex);
- if(combineBuffer)
- FREE_TEMP_MANUAL(combineBuffer);
- }
- template<class TransferFunction>
- void ParticleSystemRenderer::Transfer (TransferFunction& transfer)
- {
- // Super::Transfer (transfer);
- transfer.Transfer (m_Data.scale, "m_Scale");
- transfer.Transfer (m_Data.renderMode, "m_RenderMode");
- transfer.Transfer (m_Data.maxParticleSize, "m_MaxParticleSize");
- transfer.Transfer (m_Data.cameraVelocityScale, "m_CameraVelocityScale");
- transfer.Transfer (m_Data.velocityScale, "m_VelocityScale");
- transfer.Transfer (m_Data.lengthScale, "m_LengthScale");
- transfer.Transfer (m_Data.sortingFudge, "m_SortingFudge");
- transfer.Transfer (m_Data.normalDirection, "m_NormalDirection");
- transfer.Transfer (m_Data.sortMode, "m_SortMode");
- //TODO: Mesh
- //transfer.Transfer (m_Mesh[0], "m_Mesh");
- //transfer.Transfer (m_Mesh[1], "m_Mesh1");
- //transfer.Transfer (m_Mesh[2], "m_Mesh2");
- //transfer.Transfer (m_Mesh[3], "m_Mesh3");
- }
- INSTANTIATE_TEMPLATE_TRANSFER(ParticleSystemRenderer)
- NS_RRP_END
|