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);
    }
}
Example #6
0
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);
	}
}