Files
FC1/Cry3DEngine/partpolygon.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

436 lines
13 KiB
C++

////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: partpolygon.cpp
// Version: v1.00
// Created: 28/5/2001 by Vladimir Kajalin
// Compilers: Visual Studio.NET
// Description: sprite particles, big independent polygons
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "partman.h"
#include "objman.h"
#include "3dEngine.h"
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void CSprite::Render( const PartProcessParams &PPP,IShader *pShader )
{
float fCurTime = PPP.fCurTime;
uint nDynLightMask = 0;
if (m_pEmitter->m_pShader)
{
pShader = m_pEmitter->m_pShader;
}
else
{
if (m_pParams->pShader)
pShader = m_pParams->pShader;
else
{
if (m_pMaterial)
{
IShader *pShaderContainer = m_pMaterial->GetShaderItem().m_pShader;
if (pShaderContainer)
pShader = pShaderContainer->GetTemplate(-1);
}
}
}
// pRenderer->DrawLabel(m_vPos,2,"%d",nDynLightMask);
int dwCCObjFlags = 0;
if (m_pParams->nParticleFlags & PART_FLAG_DRAW_NEAR)
dwCCObjFlags = FOB_NEAREST;
// do not draw fire in the water
if(m_pParams->nParticleFlags & PART_FLAG_NO_DRAW_UNDERWATER && m_pEmitter->m_fWaterLevel>WATER_LEVEL_UNKNOWN)
if(m_vPos.z < m_pEmitter->m_fWaterLevel)
return;
// Render 3d object
if(m_pParams->pStatObj)
{
float fObjScale = m_fSize;
if (m_pParams->fObjectScale)
fObjScale *= m_pParams->fObjectScale;
nDynLightMask = PPP.p3DEngine->GetLightMaskFromPosition(m_vPos, fObjScale);
PPP.p3DEngine->CheckDistancesToLightSources(nDynLightMask,m_vPos,fObjScale,m_pSpawnerEntity,1);
//Matrix44 matPart2=GetTranslationMat(m_vPos);
Matrix44 matPart2=Matrix34::CreateTranslationMat(m_vPos);
matPart2=GetTransposed44(matPart2);
matPart2=Matrix33::CreateScale( Vec3d(fObjScale,fObjScale,fObjScale) )*matPart2;
if (m_pParams->nParticleFlags & PART_FLAG_SWAP_XY)
{
matPart2=Matrix33::CreateRotationAA( -m_vAngles.z*gf_DEGTORAD, Vec3d(0,0,1) )*matPart2; //NOTE: angles needs to be negated
matPart2=Matrix33::CreateRotationAA( -m_vAngles.x*gf_DEGTORAD, Vec3d(1,0,0) )*matPart2; //NOTE: angles needs to be negated
matPart2=Matrix33::CreateRotationAA( -m_vAngles.y*gf_DEGTORAD, Vec3d(0,1,0) )*matPart2; //NOTE: angles needs to be negated
}
else
matPart2=Matrix44::CreateRotationZYX(-gf_DEGTORAD*m_vAngles)*matPart2; //NOTE: angles in radians and negated
//-------------------------------------------------------------------
if(!(m_pParams->nParticleFlags & PART_FLAG_NO_OFFSET))
{
Vec3d vCenter = (m_pParams->pStatObj->GetBoxMax() + m_pParams->pStatObj->GetBoxMin())*0.5f;
//Matrix44 matOffSet=GetTranslationMat(-vCenter*fObjScale);
Matrix44 matOffSet=Matrix34::CreateTranslationMat(-vCenter*fObjScale);
matOffSet=GetTransposed44(matOffSet);
matPart2 = matOffSet * matPart2;
}
//-----------------------------------------------------------------------------------------------
SRendParams rParms;
rParms.pMatrix = &matPart2;
rParms.nDLightMask = nDynLightMask;
rParms.nStrongestDLightMask = nDynLightMask;
rParms.vAmbientColor = Color2Vec(m_cAmbientColor);
rParms.dwFObjFlags = FOB_IGNOREMATERIALAMBIENT | dwCCObjFlags;
// rParms.nFogVolumeID = m_nFogVolumeId;
rParms.pMaterial = m_pMaterial;
rParms.dwFObjFlags |= FOB_TRANS_MASK;
int nSortId = max(-4,min(4,m_pParams->nDrawLast));
nSortId = FtoI(PPP.pObjManager->GetSortOffset(m_vPos,PPP.vCamPos,m_pEmitter->m_fWaterLevel)) - nSortId;
rParms.fCustomSortOffset = (float)nSortId;
if(dwCCObjFlags & FOB_NEAREST)
rParms.nSortValue = EFSLIST_LAST;
float fAge = fCurTime-m_fSpawnTime;
float fAlpha = (1.f - (fAge - m_pParams->fFadeInTime)/(m_fLifeTime - m_pParams->fFadeInTime));//*2.f;
//if(fAlpha<0) fAlpha=0; else if(fAlpha>1) fAlpha=1;
// fadde in
if (fAge < m_pParams->fFadeInTime && fCurTime)
fAlpha *= fAge / m_pParams->fFadeInTime;
fAlpha*=1.5f;
if(fAlpha<0) fAlpha=0; else if(fAlpha>1) fAlpha=1;
rParms.fAlpha = fAlpha;
m_pParams->pStatObj->Render(rParms,Vec3(zero),0);
}
// render sprite
if (m_pParams->nTexId)
{
if (m_pParams->eBlendType != ParticleBlendType_Additive)
{
nDynLightMask = PPP.p3DEngine->GetLightMaskFromPosition(m_vPos, 0);
PPP.p3DEngine->CheckDistancesToLightSources(nDynLightMask,m_vPos,m_fSize,m_pSpawnerEntity,1);
}
// find vertex offsets from origin
Vec3d vFront, vRight, vUp;
Vec3d vParticlePos = m_vPos;
{
if(m_pParams->nParticleFlags & PART_FLAG_HORIZONTAL)
{
vRight = Vec3d(m_fSize,0,0);
vUp = Vec3d(0,m_fSize,0);
vFront = Vec3d(0,0,1);
}
else
{
vFront = PPP.vFront;
vRight = -PPP.vRight*m_fSize;
vUp = -PPP.vUp*m_fSize;
}
if(m_vAngles.z)
{
Matrix33 mat;
mat.SetRotationAA( DEG2RAD(m_vAngles.z), vFront ); //NOTE: angles needs to be negated
vRight = mat * vRight;
vUp = mat * vUp;
}
// Stretching to speed direction.
if (m_pParams->fStretch != 0)
{
float fSpeed = m_vDelta.GetLength();
if (fSpeed < 0.01f)
fSpeed = 0.01f;
vFront = PPP.pCamera->GetPos() - m_vPos;
vFront.Normalize();
Vec3d vVec1 = -vFront.Cross(m_vDelta/fSpeed);
Vec3d vVec2 = vVec1.Cross(vFront);
vRight = m_fSize * vVec1;
vUp = m_fSize * vVec2;
vUp = vUp + vUp*fSpeed*m_pParams->fStretch;
vParticlePos -= vUp; // Offset partcile.
}
}
int nSortId = max(-4,min(4,m_pParams->nDrawLast));
nSortId = FtoI(PPP.pObjManager->GetSortOffset(m_vPos,PPP.vCamPos,m_pEmitter->m_fWaterLevel)) - nSortId;
/*
if((vCamPos.z-pTerrain->Ge tWaterLevel())*(m_vPos.z-pTerrain->GetWaterLev el())>0)
nSortId += 10000;
else
nSortId -= 10000;
*/
////////////////////////////////////////////////////////////////////////////////////////////////
// Find color, texture and alpha
////////////////////////////////////////////////////////////////////////////////////////////////
int nTexBindId = m_pParams->nTexId;
float fAlpha = 1.f;
float t=0; // from 0 to 1
float fAge = fCurTime-m_fSpawnTime;
if ((m_nParticleFlags & PARTICLE_ANIMATED_TEXTURE) && m_pParams->pAnimTex)
{ // animated
t = fAge/m_fLifeTime;
if (t<0) t=0; else if(t>1) t=1;
float anim_time = t*(m_pParams->nTexAnimFramesCount-1);
AnimTexInfo *pAnimTexInfo = m_pParams->pAnimTex;
int cur_tid = 0;
cur_tid = ((int)anim_time) % pAnimTexInfo->nFramesCount;
nTexBindId = pAnimTexInfo->pBindIds[cur_tid];
//t = float(cur_tid)/(pAnimTexInfo->nFramesCount);
}
else if(m_pParams->nTexId>=0)
{ // one frame
nTexBindId = m_pParams->nTexId;
t = fAge/m_fLifeTime;
if (t<0) t=0; else if(t>1) t=1;
}
fAlpha = (1.f - (fAge - m_pParams->fFadeInTime)/(m_fLifeTime - m_pParams->fFadeInTime));//*2.f;
//if(fAlpha<0) fAlpha=0; else if(fAlpha>1) fAlpha=1;
if(!m_fLifeTime)
{
fAlpha = 1.f;
t = 0;
}
// fadde in
if (fAge < m_pParams->fFadeInTime && fCurTime)
fAlpha *= fAge / m_pParams->fFadeInTime;
fAlpha*=1.5f;
if(fAlpha<0) fAlpha=0; else if(fAlpha>1) fAlpha=1;
Vec3d vResColor;
vResColor = m_pParams->vColorStart*(1.f-t) + m_pParams->vColorEnd*t;
// find result color
if(nDynLightMask==0 && (!(m_nParticleFlags & CParticle::PARTICLE_ADDITIVE)))
{
vResColor.Set(0,0,0);
}
else
{
if (m_nParticleFlags & CParticle::PARTICLE_COLOR_BASED)
vResColor *= fAlpha*255.f;
else
vResColor *= 0.5f*255.f;
}
Vec3 vAmbientColor;
if (m_nParticleFlags & CParticle::PARTICLE_COLOR_BASED)
{
vAmbientColor.Set(0,0,0);
}
else
{
if(PPP.p3DEngine->GetFogEnd()>PPP.p3DEngine->GetFogStart())
{
float fDist = (L1Distance2D(m_vPos, PPP.vCamPos)-PPP.p3DEngine->GetFogStart())
/(PPP.p3DEngine->GetFogEnd()-PPP.p3DEngine->GetFogStart());
if(fDist>1.f)
fDist=1.f;
else if(fDist<0)
fDist=0;
fAlpha *= (1.f-fDist);
}
vAmbientColor = Color2Vec(m_cAmbientColor);
}
// fade if near the space bounds
float fAlphaSpaceLoopRatio = 1.f;
if(m_pParams->nParticleFlags & PART_FLAG_SPACELOOP && m_pEmitter)
{
float fDistFromCenterX = m_pParams->vSpaceLoopBoxSize.x - fabs(m_pEmitter->m_pos.x-m_vPos.x);
float fDistFromCenterY = m_pParams->vSpaceLoopBoxSize.y - fabs(m_pEmitter->m_pos.y-m_vPos.y);
float fDistFromCenterZ = m_pParams->vSpaceLoopBoxSize.z - fabs(m_pEmitter->m_pos.z-m_vPos.z);
float fMinDistToTheBorder = min(min(fDistFromCenterX,fDistFromCenterY),fDistFromCenterZ);
fAlphaSpaceLoopRatio = max(0,min(1.f,fMinDistToTheBorder*0.5f));
}
// make particle color
UCol ucResCol;
ucResCol.bcolor[0] = fastftol_positive(vResColor.x);
ucResCol.bcolor[1] = fastftol_positive(vResColor.y);
ucResCol.bcolor[2] = fastftol_positive(vResColor.z);
ucResCol.bcolor[3] = fastftol_positive(255.f*fAlpha*fAlphaSpaceLoopRatio);
if(m_pParams->nParticleFlags & PART_FLAG_LINEPARTICLE)
{ // line bullet trail
Vec3d vCamVec = PPP.pCamera->GetPos()-m_vPos;
vCamVec.Normalize();
Vec3d vSideStep = vCamVec.Cross(m_vDelta.normalized());
vSideStep.Normalize();
vSideStep.SetLen(m_fSize);
PPP.pObjManager->AddPolygonToRenderer( nTexBindId, pShader, nDynLightMask, vSideStep, m_vDelta*0.5f,
ucResCol,
m_pParams->eBlendType,
vAmbientColor,
vParticlePos+m_vDelta*0.5f, 0,0,0,0, (float)nSortId, dwCCObjFlags, m_pMaterial );
}
else if (m_pParams->fTailLenght)
{ // render with tail
SColorVert arrTailVerts[PART_MAX_HISTORY_ELEMENTS*2];
byte arrTailIndices[PART_MAX_HISTORY_ELEMENTS*6];
int nTailVertsNum=0, nTailIndsNum=0;
nTailVertsNum = FillTailVertBuffer( arrTailVerts, vFront, ucResCol );
if(nTailVertsNum>2)
{ // fill tail indices
nTailIndsNum = (nTailVertsNum/2-1)*6;
int nIdxId = 0;
for(int i=0; i<(nTailVertsNum/2-1); i++)
{
arrTailIndices[nIdxId++] = i*2+0;
arrTailIndices[nIdxId++] = i*2+1;
arrTailIndices[nIdxId++] = i*2+2;
arrTailIndices[nIdxId++] = i*2+1;
arrTailIndices[nIdxId++] = i*2+2;
arrTailIndices[nIdxId++] = i*2+3;
assert(i*2+3 < m_nTailSteps*2);
}
assert(nIdxId == nTailIndsNum);
}
// nTailIndsNum=0;
PPP.pObjManager->AddPolygonToRenderer( nTexBindId, pShader, nDynLightMask, vRight, vUp,
ucResCol,
m_pParams->eBlendType,
vAmbientColor,
vParticlePos, arrTailVerts, nTailVertsNum, arrTailIndices, nTailIndsNum, (float)nSortId, dwCCObjFlags, m_pMaterial);
if (m_pArrvPosHistory)
{
float fTailLength = (m_pParams->fTailLenght/m_nTailSteps) / m_fScale; // Here we must divide by scale because speed is scaled.
m_fTrailCurPos += min(1.f, PPP.fFrameTime/fTailLength);
m_pArrvPosHistory[FtoI(m_fTrailCurPos)%m_nTailSteps] = m_vPos;
}
}
else
{
list2<struct ShadowMapLightSourceInstance> * pShadowsList = NULL;
if(PPP.pObjManager->GetCVars()->e_particles_receive_shadows &&
m_pSpawnerEntity && m_pSpawnerEntity->GetEntityRS() && m_pSpawnerEntity->GetEntityRS()->pShadowMapInfo)
pShadowsList = m_pSpawnerEntity->GetEntityRS()->pShadowMapInfo->pShadowMapCasters;
// no tail
PPP.pObjManager->AddPolygonToRenderer( nTexBindId, pShader, nDynLightMask, vRight, vUp,
ucResCol,
m_pParams->eBlendType,
vAmbientColor,
vParticlePos, 0,0,0,0, (float)nSortId, dwCCObjFlags, m_pMaterial, NULL, pShadowsList );
}
}
}
int CSprite::FillTailVertBuffer( SColorVert * pTailVerts,
const Vec3d & vCamVec,
const UCol & ucColor )
{
int nVertCount=0;
if (m_pArrvPosHistory && m_pParams->fTailLenght && (m_vDelta!=Vec3(0.0f,0.0f,0.0f)) )
{
int nPos = FtoI(m_fTrailCurPos);
// if(nPos==1)
// return 0;
// Vec3d vCamVec = PPP.pCamera->GetPos()-m_vPos;
// vCamVec.Normalize();
Vec3d vSideStep,vSideStepPrev,vDelta,vSideStepReal;
//Vec3d vSideStepPrev,vSideStepReal;
//float fMaxItSteps = min( (float)(PART_HISTORY_ELEMENTS-1), m_fTrailCurPos-1);
float fInvMaxItHalfSteps = 0.5f/m_nTailSteps;
float fTC0=0.5f;
Vec3 vPrev = m_vPos;
// fill vert buffer
for(int it=0; it < m_nTailSteps && nPos >= 0; it++)
{
Vec3 vPos = m_pArrvPosHistory[ nPos % m_nTailSteps ];
vDelta = vPrev-vPos;
if (vDelta.IsZero())
vDelta = m_vDelta;
vSideStep = m_fSize*vCamVec.Cross(GetNormalized(vDelta));
//if (it > 0)
//vSideStepReal = (vSideStep + vSideStepPrev)*0.5f; // Average.
//else
//vSideStepReal = vSideStep;
//vSideStepPrev = vSideStep;
vPrev = vPos;
pTailVerts[nVertCount].vert = vPos + vSideStep;
pTailVerts[nVertCount].dTC[0] = fTC0;
pTailVerts[nVertCount].dTC[1] = 0;
pTailVerts[nVertCount].color = ucColor;
nVertCount++;
pTailVerts[nVertCount].vert = vPos - vSideStep;
pTailVerts[nVertCount].dTC[0] = fTC0;
pTailVerts[nVertCount].dTC[1] = 1;
pTailVerts[nVertCount].color = ucColor;
nVertCount++;
nPos--;
fTC0+=fInvMaxItHalfSteps;
}
}
return nVertCount;
}