void ParticleEmitter3D::PrepareEmitterParametersShockwave(Particle * particle, float32 velocity, int32 emitIndex, const Vector3& tempPosition, const Matrix3& rotationMatrix) { // Emit ponts from the circle in the XY plane. float32 curRadius = 1.0f; if (radius) { curRadius = radius->GetValue(time); } float32 curAngle = PI_2 * (float32)Random::Instance()->RandFloat(); float sinAngle = 0.0f; float cosAngle = 0.0f; SinCosFast(curAngle, sinAngle, cosAngle); Vector3 directionVector(curRadius * cosAngle, curRadius * sinAngle, 0.0f); particle->position = tempPosition + TransformPerserveLength(directionVector, rotationMatrix); // Calculate Z value. const float32 TANGENT_EPSILON = (float32)(1E-4); if (this->emissionRange) { float32 emissionRangeValue = DegToRad(emissionRange->GetValue(time)); SinCosFast(emissionRangeValue, sinAngle, cosAngle); if (fabs(cosAngle) < TANGENT_EPSILON) { // Reset the direction vector. directionVector.x = 0; directionVector.y = 0; directionVector.z = -curRadius / 2 + (float32)Random::Instance()->RandFloat() * curRadius; } else { float32 zValue = (curRadius * sinAngle / cosAngle); directionVector.z = -zValue / 2 + (float32)Random::Instance()->RandFloat() * zValue; } } float32 dvl = directionVector.Length(); if (dvl>EPSILON) { directionVector*=velocity/dvl; } particle->speed = directionVector; }
void ParticleLayer3D::CalcNonLong(Particle* current, Vector3& topLeft, Vector3& topRight, Vector3& botLeft, Vector3& botRight) { Vector3 dx(_left); Vector3 dy(_up); float32 sine; float32 cosine; SinCosFast(current->angle, sine, cosine); // Draw pivot point is Sprite center + layer pivot point. Vector2 drawPivotPoint = GetDrawPivotPoint(); float32 pivotRight = ((sprite->GetWidth()-drawPivotPoint.x)*current->size.x*current->sizeOverLife.x)/2.f; float32 pivotLeft = (drawPivotPoint.x*current->size.x*current->sizeOverLife.x)/2.f; float32 pivotUp = (drawPivotPoint.y*current->size.y*current->sizeOverLife.y)/2.f; float32 pivotDown = ((sprite->GetHeight()-drawPivotPoint.y)*current->size.y*current->sizeOverLife.y)/2.f; Vector3 dxc = dx*cosine; Vector3 dxs = dx*sine; Vector3 dyc = dy*cosine; Vector3 dys = dy*sine; // Apply offset to the current position according to the emitter position. UpdateCurrentParticlePosition(current); topLeft = currentParticlePosition+(dxs+dyc)*pivotLeft + (dxc-dys)*pivotDown; topRight = currentParticlePosition+(-dxc+dys)*pivotUp + (dxs+dyc)*pivotLeft; botLeft = currentParticlePosition+(dxc-dys)*pivotDown + (-dxs-dyc)*pivotRight; botRight = currentParticlePosition+(-dxs-dyc)*pivotRight + (-dxc+dys)*pivotUp; }
void RenderHelper::DrawCircle3D(const Vector3 & center, const Vector3 &emissionVector, float32 radius, bool useFilling) { Polygon3 pts; float32 angle = SEGMENT_LENGTH / radius; int ptsCount = (int)(PI_2 / (DegToRad(angle))) + 1; for (int k = 0; k < ptsCount; ++k) { float32 angleA = ((float)k / (ptsCount - 1)) * PI_2; float sinAngle = 0.0f; float cosAngle = 0.0f; SinCosFast(angleA, sinAngle, cosAngle); Vector3 directionVector(radius * cosAngle, radius * sinAngle, 0.0f); // Rotate the direction vector according to the current emission vector value. Vector3 zNormalVector(0.0f, 0.0f, 1.0f); Vector3 curEmissionVector = emissionVector; curEmissionVector.Normalize(); // This code rotates the (XY) plane with the particles to the direction vector. // Taking into account that a normal vector to the (XY) plane is (0,0,1) this // code is very simplified version of the generic "plane rotation" code. float32 length = curEmissionVector.Length(); if (FLOAT_EQUAL(length, 0.0f) == false) { float32 cosAngleRot = curEmissionVector.z / length; float32 angleRot = acos(cosAngleRot); Vector3 axisRot(curEmissionVector.y, -curEmissionVector.x, 0); Matrix3 planeRotMatrix; planeRotMatrix.CreateRotation(axisRot, angleRot); Vector3 rotatedVector = directionVector * planeRotMatrix; directionVector = rotatedVector; } Vector3 pos = center - directionVector; pts.AddPoint(pos); } if (useFilling) { FillPolygon(pts); } else { DrawPolygon(pts, false); } }
void ParticleEmitter3D::CalculateParticlePositionForCircle(Particle* particle, const Vector3& tempPosition, const Matrix3& rotationMatrix) { float32 curRadius = 1.0f; if (radius) { curRadius = radius->GetValue(time); } float32 curAngle = PI_2 * (float32)Random::Instance()->RandFloat(); if (emitterType == EMITTER_ONCIRCLE_VOLUME) { // "Volume" means we have to emit particles from the whole circle. curRadius *= (float32)Random::Instance()->RandFloat(); } float sinAngle = 0.0f; float cosAngle = 0.0f; SinCosFast(curAngle, sinAngle, cosAngle); Vector3 directionVector(curRadius * cosAngle, curRadius * sinAngle, 0.0f); // Rotate the direction vector according to the current emission vector value. Vector3 zNormalVector(0.0f, 0.0f, 1.0f); Vector3 curEmissionVector; if (emissionVector) { curEmissionVector = emissionVector->GetValue(time); curEmissionVector.Normalize(); } // This code rotates the (XY) plane with the particles to the direction vector. // Taking into account that a normal vector to the (XY) plane is (0,0,1) this // code is very simplified version of the generic "plane rotation" code. float32 length = curEmissionVector.Length(); if (FLOAT_EQUAL(length, 0.0f) == false) { float32 cosAngleRot = curEmissionVector.z / length; float32 angleRot = acos(cosAngleRot); Vector3 axisRot(curEmissionVector.y, -curEmissionVector.x, 0); Matrix3 planeRotMatrix; planeRotMatrix.CreateRotation(axisRot, angleRot); Vector3 rotatedVector = directionVector * planeRotMatrix; directionVector = rotatedVector; } particle->position = tempPosition + TransformPerserveLength(directionVector, rotationMatrix); }
void ParticleLayer3D::Draw(Camera * camera) { if(!sprite) return; Matrix4 rotationMatrix = Matrix4::IDENTITY; switch(RenderManager::Instance()->GetRenderOrientation()) { case Core::SCREEN_ORIENTATION_LANDSCAPE_LEFT: //glRotatef(90.0f, 0.0f, 0.0f, 1.0f); rotationMatrix.CreateRotation(Vector3(0.0f, 0.0f, 1.0f), DegToRad(90.0f)); break; case Core::SCREEN_ORIENTATION_LANDSCAPE_RIGHT: //glRotatef(-90.0f, 0.0f, 0.0f, 1.0f); rotationMatrix.CreateRotation(Vector3(0.0f, 0.0f, 1.0f), DegToRad(-90.0f)); break; } Matrix4 mv = RenderManager::Instance()->GetMatrix(RenderManager::MATRIX_MODELVIEW)*rotationMatrix; Vector3 _up(mv._01, mv._11, mv._21); Vector3 _left(mv._00, mv._10, mv._20); verts.clear(); textures.clear(); colors.clear(); int32 totalCount = 0; Particle * current = head; if(current) { renderBatch->GetMaterial()->GetRenderState()->SetTexture(sprite->GetTexture(current->frame)); } while(current != 0) { Vector3 dx(_left); Vector3 dy(_up); //dx *= sqrt(2.f); //dy *= sqrt(2.f); float32 sine; float32 cosine; SinCosFast(current->angle, sine, cosine); float32 pivotRight = ((sprite->GetWidth()-pivotPoint.x)*current->size.x*current->sizeOverLife)/2.f; float32 pivotLeft = (pivotPoint.x*current->size.x*current->sizeOverLife)/2.f; float32 pivotUp = (pivotPoint.y*current->size.y*current->sizeOverLife)/2.f; float32 pivotDown = ((sprite->GetHeight()-pivotPoint.y)*current->size.y*current->sizeOverLife)/2.f; Vector3 dxc = dx*cosine; Vector3 dxs = dx*sine; Vector3 dyc = dy*cosine; Vector3 dys = dy*sine; Vector3 topLeft = current->position+(-dxc+dys)*pivotUp + (dxs+dyc)*pivotLeft; Vector3 topRight = current->position+(-dxs-dyc)*pivotRight + (-dxc+dys)*pivotUp; Vector3 botLeft = current->position+(dxs+dyc)*pivotLeft + (dxc-dys)*pivotDown; Vector3 botRight = current->position+(dxc-dys)*pivotDown + (-dxs-dyc)*pivotRight; verts.push_back(topLeft.x);//0 verts.push_back(topLeft.y); verts.push_back(topLeft.z); verts.push_back(topRight.x);//1 verts.push_back(topRight.y); verts.push_back(topRight.z); verts.push_back(botLeft.x);//2 verts.push_back(botLeft.y); verts.push_back(botLeft.z); verts.push_back(botLeft.x);//2 verts.push_back(botLeft.y); verts.push_back(botLeft.z); verts.push_back(topRight.x);//1 verts.push_back(topRight.y); verts.push_back(topRight.z); verts.push_back(botRight.x);//3 verts.push_back(botRight.y); verts.push_back(botRight.z); float32 *pT = sprite->GetTextureVerts(current->frame); textures.push_back(pT[0]); textures.push_back(pT[1]); textures.push_back(pT[2]); textures.push_back(pT[3]); textures.push_back(pT[4]); textures.push_back(pT[5]); textures.push_back(pT[4]); textures.push_back(pT[5]); textures.push_back(pT[2]); textures.push_back(pT[3]); textures.push_back(pT[6]); textures.push_back(pT[7]); // 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 < 6; ++i) { colors.push_back(color); } totalCount++; current = TYPE_PARTICLES == type ? current->next : 0; } renderBatch->SetTotalCount(totalCount); 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()); renderBatch->SetRenderDataObject(renderData); } }
void ParticleLayer3D::Draw(const Vector3 & _up, const Vector3 & _left) { verts.clear(); textures.clear(); colors.clear(); int32 totalCount = 0; Particle * current = head; if(current) { RenderManager::Instance()->SetTexture(sprite->GetTexture(current->frame)); } while(current != 0) { Vector3 dx(_left); Vector3 dy(_up); //dx *= sqrt(2.f); //dy *= sqrt(2.f); float32 sine; float32 cosine; SinCosFast(current->angle, sine, cosine); float32 pivotRight = ((sprite->GetWidth()-pivotPoint.x)*current->size.x*current->sizeOverLife)/2.f; float32 pivotLeft = (pivotPoint.x*current->size.x*current->sizeOverLife)/2.f; float32 pivotUp = (pivotPoint.y*current->size.y*current->sizeOverLife)/2.f; float32 pivotDown = ((sprite->GetHeight()-pivotPoint.y)*current->size.y*current->sizeOverLife)/2.f; Vector3 dxc = dx*cosine; Vector3 dxs = dx*sine; Vector3 dyc = dy*cosine; Vector3 dys = dy*sine; Vector3 topLeft = current->position+(-dxc+dys)*pivotUp + (dxs+dyc)*pivotLeft; Vector3 topRight = current->position+(-dxs-dyc)*pivotRight + (-dxc+dys)*pivotUp; Vector3 botLeft = current->position+(dxs+dyc)*pivotLeft + (dxc-dys)*pivotDown; Vector3 botRight = current->position+(dxc-dys)*pivotDown + (-dxs-dyc)*pivotRight; verts.push_back(topLeft.x);//0 verts.push_back(topLeft.y); verts.push_back(topLeft.z); verts.push_back(topRight.x);//1 verts.push_back(topRight.y); verts.push_back(topRight.z); verts.push_back(botLeft.x);//2 verts.push_back(botLeft.y); verts.push_back(botLeft.z); verts.push_back(botLeft.x);//2 verts.push_back(botLeft.y); verts.push_back(botLeft.z); verts.push_back(topRight.x);//1 verts.push_back(topRight.y); verts.push_back(topRight.z); verts.push_back(botRight.x);//3 verts.push_back(botRight.y); verts.push_back(botRight.z); float32 *pT = sprite->GetTextureVerts(current->frame); textures.push_back(pT[0]); textures.push_back(pT[1]); textures.push_back(pT[2]); textures.push_back(pT[3]); textures.push_back(pT[4]); textures.push_back(pT[5]); textures.push_back(pT[4]); textures.push_back(pT[5]); textures.push_back(pT[2]); textures.push_back(pT[3]); textures.push_back(pT[6]); textures.push_back(pT[7]); uint32 color = (((uint32)(current->color.a*255.f))<<24) | (((uint32)(current->color.b*255.f))<<16) | (((uint32)(current->color.g*255.f))<<8) | ((uint32)(current->color.r*255.f)); for(int32 i = 0; i < 6; ++i) { colors.push_back(color); } totalCount++; current = TYPE_PARTICLES == type ? current->next : 0; } 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()); RenderManager::Instance()->SetRenderData(renderData); material->PrepareRenderState(); RenderManager::Instance()->HWDrawArrays(PRIMITIVETYPE_TRIANGLELIST, 0, 6*totalCount); } }