LLBC_Variant &LLBC_Variant::BecomeLong() { if (!IsLong()) { *this = AsLong(); } return *this; }
void ParticleLayer3D::PrepareRenderData(Camera* camera) { AABBox3 bbox; if (emitter->GetWorldTransformPtr()) { Vector3 emmiterPos = emitter->GetWorldTransformPtr()->GetTranslationVector(); bbox = AABBox3(emmiterPos, emmiterPos); } // Yuri Coder, 2013/06/07. Don't draw SuperEmitter layers - see pls DF-1251 for details. if (!sprite || type == TYPE_SUPEREMITTER_PARTICLES) { //build bounding box as sum of inner particle emitters bboxes if (type == TYPE_SUPEREMITTER_PARTICLES) { Particle *current = head; while (current) { bbox.AddAABBox(current->GetInnerEmitter()->GetBoundingBox()); current=current->next; } } renderBatch->SetLayerBoundingBox(bbox); renderBatch->SetTotalCount(0); return; } Matrix4 mv; Matrix3 rotation; bool worldAlign = particleOrientation&ParticleLayer::PARTICLE_ORIENTATION_WORLD_ALIGN; if (!worldAlign) { rotation = emitter->GetRotationMatrix(); } Vector<std::pair<Vector3, Vector3> > basises; if (particleOrientation&ParticleLayer::PARTICLE_ORIENTATION_CAMERA_FACING) { mv = camera->GetMatrix(); basises.push_back(std::pair<Vector3, Vector3>(Vector3(mv._01, mv._11, mv._21), Vector3(mv._00, mv._10, mv._20))); } if (particleOrientation&ParticleLayer::PARTICLE_ORIENTATION_X_FACING) { Vector3 up(0,1,0); Vector3 left(0,0,1); if (!worldAlign) { up = up*rotation; up.Normalize(); left = left*rotation; left.Normalize(); } basises.push_back(std::pair<Vector3, Vector3>(up, left)); } if (particleOrientation&ParticleLayer::PARTICLE_ORIENTATION_Y_FACING) { Vector3 up(0,0,1); Vector3 left(1,0,0); if (!worldAlign) { up = up*rotation; up.Normalize(); left = left*rotation; left.Normalize(); } basises.push_back(std::pair<Vector3, Vector3>(up, left)); } if (particleOrientation&ParticleLayer::PARTICLE_ORIENTATION_Z_FACING) { Vector3 up(0,1,0); Vector3 left(1,0,0); if (!worldAlign) { up = up*rotation; up.Normalize(); left = left*rotation; left.Normalize(); } basises.push_back(std::pair<Vector3, Vector3>(up, left)); } int32 planesCount = basises.size(); direction = camera->GetDirection(); verts.clear(); textures.clear(); colors.clear(); if (enableFrameBlend) { textures2.clear(); times.clear(); } int32 totalCount = 0; // Reserve the memory for vectors to avoid the resize operations. Actually there can be less than count // particles (for Single Particle or Superemitter one), but never more than count. static const int32 POINTS_PER_PARTICLE = 4; static const int32 INDICES_PER_PARTICLE = 6; verts.resize(count * POINTS_PER_PARTICLE * 3 * planesCount); // 4 vertices per each particle, 3 coords per vertex. textures.resize(count * POINTS_PER_PARTICLE * 2 * planesCount); // 4 texture coords per particle, 2 values per texture coord. colors.resize(count * POINTS_PER_PARTICLE*planesCount); //frame blending if (enableFrameBlend) { textures2.resize(count * POINTS_PER_PARTICLE * 2 * planesCount); times.resize(count * POINTS_PER_PARTICLE * planesCount); //single time value per vertex } Particle * current = head; if(current) { renderBatch->GetMaterial()->GetRenderState()->SetTexture(sprite->GetTexture(current->frame)); } int32 verticesCount = 0; int32 texturesCount = 0; int32 texturesCount2 = 0; int32 timesCount = 0; int32 colorsCount = 0; while(current != 0) { for (int32 i=0; i<planesCount; ++i) { _up = basises[i].first; _left = basises[i].second; Vector3 topRight; Vector3 topLeft; Vector3 botRight; Vector3 botLeft; if (IsLong()) { CalcLong(current, topLeft, topRight, botLeft, botRight); } else { CalcNonLong(current, topLeft, topRight, botLeft, botRight); } verts[verticesCount] = topLeft.x;//0 verticesCount ++; verts[verticesCount] = topLeft.y; verticesCount ++; verts[verticesCount] = topLeft.z; verticesCount ++; verts[verticesCount] = topRight.x;//1 verticesCount ++; verts[verticesCount] = topRight.y; verticesCount ++; verts[verticesCount] = topRight.z; verticesCount ++; verts[verticesCount] = botLeft.x;//2 verticesCount ++; verts[verticesCount] = botLeft.y; verticesCount ++; verts[verticesCount] = botLeft.z; verticesCount ++; verts[verticesCount] = botRight.x;//3 verticesCount ++; verts[verticesCount] = botRight.y; verticesCount ++; verts[verticesCount] = botRight.z; verticesCount ++; bbox.AddPoint(topLeft); bbox.AddPoint(topRight); bbox.AddPoint(botLeft); bbox.AddPoint(botRight); float32 *pT = sprite->GetTextureVerts(current->frame); textures[texturesCount] = pT[0]; texturesCount ++; textures[texturesCount] = pT[1]; texturesCount ++; textures[texturesCount] = pT[2]; texturesCount ++; textures[texturesCount] = pT[3]; texturesCount ++; textures[texturesCount] = pT[4]; texturesCount ++; textures[texturesCount] = pT[5]; texturesCount ++; textures[texturesCount] = pT[6]; texturesCount ++; textures[texturesCount] = pT[7]; texturesCount ++; //frame blending if (enableFrameBlend) { int32 nextFrame = current->frame+1; if (nextFrame >= sprite->GetFrameCount()) { if (loopSpriteAnimation) nextFrame = 0; else nextFrame = sprite->GetFrameCount()-1; } pT = sprite->GetTextureVerts(nextFrame); textures2[texturesCount2] = pT[0]; texturesCount2 ++; textures2[texturesCount2] = pT[1]; texturesCount2 ++; textures2[texturesCount2] = pT[2]; texturesCount2 ++; textures2[texturesCount2] = pT[3]; texturesCount2 ++; textures2[texturesCount2] = pT[4]; texturesCount2 ++; textures2[texturesCount2] = pT[5]; texturesCount2 ++; textures2[texturesCount2] = pT[6]; texturesCount2 ++; textures2[texturesCount2] = pT[7]; texturesCount2 ++; times[timesCount] = current->animTime; timesCount++; times[timesCount] = current->animTime; timesCount++; times[timesCount] = current->animTime; timesCount++; times[timesCount] = current->animTime; timesCount++; } // Yuri Coder, 2013/04/03. Need to use drawColor here instead of just colot // to take colorOverlife property into account. uint32 color = (((uint32)(current->drawColor.a*255.f))<<24) | (((uint32)(current->drawColor.b*255.f))<<16) | (((uint32)(current->drawColor.g*255.f))<<8) | ((uint32)(current->drawColor.r*255.f)); for(int32 i = 0; i < POINTS_PER_PARTICLE; ++i) { colors[i + colorsCount] = color; } colorsCount += POINTS_PER_PARTICLE; totalCount++; } current = TYPE_PARTICLES == type ? current->next : 0; } int indexCount = indices.size()/INDICES_PER_PARTICLE; if (totalCount>indexCount) { indices.resize(totalCount*INDICES_PER_PARTICLE); for (;indexCount<totalCount; ++indexCount) { indices[indexCount*INDICES_PER_PARTICLE+0] = indexCount*POINTS_PER_PARTICLE+0; indices[indexCount*INDICES_PER_PARTICLE+1] = indexCount*POINTS_PER_PARTICLE+1; indices[indexCount*INDICES_PER_PARTICLE+2] = indexCount*POINTS_PER_PARTICLE+2; indices[indexCount*INDICES_PER_PARTICLE+3] = indexCount*POINTS_PER_PARTICLE+2; indices[indexCount*INDICES_PER_PARTICLE+4] = indexCount*POINTS_PER_PARTICLE+1; indices[indexCount*INDICES_PER_PARTICLE+5] = indexCount*POINTS_PER_PARTICLE+3; //preserve order } } renderBatch->SetTotalCount(totalCount); renderBatch->SetLayerBoundingBox(bbox); if(totalCount > 0) { renderData->SetStream(EVF_VERTEX, TYPE_FLOAT, 3, 0, &verts.front()); renderData->SetStream(EVF_TEXCOORD0, TYPE_FLOAT, 2, 0, &textures.front()); renderData->SetStream(EVF_COLOR, TYPE_UNSIGNED_BYTE, 4, 0, &colors.front()); if (enableFrameBlend) { renderData->SetStream(EVF_TEXCOORD1, TYPE_FLOAT, 2, 0, &textures2.front()); renderData->SetStream(EVF_TIME, TYPE_FLOAT, 1, 0, ×.front()); } } }