Particle POI fix, implement ORNT mode for particles

This commit is contained in:
Jack Andersen 2018-05-12 18:09:11 -10:00
parent 41034fefda
commit faf0ac7d27
7 changed files with 250 additions and 108 deletions

View File

@ -38,8 +38,8 @@ struct EVNT : BigDNA
Value<atUint32> idx; Value<atUint32> idx;
Value<bool> unk2; Value<bool> unk2;
Value<float> weight; Value<float> weight;
Value<atUint32> unk4; Value<atUint32> charIdx;
Value<atUint32> unk5; Value<atUint32> flags;
}; };
struct BoolPOINode : POINode struct BoolPOINode : POINode

View File

@ -647,7 +647,7 @@ void CAnimData::RecalcPoseBuilder(const CCharAnimTime* time)
void CAnimData::RenderAuxiliary(const zeus::CFrustum& frustum) const void CAnimData::RenderAuxiliary(const zeus::CFrustum& frustum) const
{ {
const_cast<CParticleDatabase&>(x120_particleDB).AddToRendererClipped(frustum); x120_particleDB.AddToRendererClipped(frustum);
} }
void CAnimData::Render(CSkinnedModel& model, const CModelFlags& drawFlags, void CAnimData::Render(CSkinnedModel& model, const CModelFlags& drawFlags,

View File

@ -126,37 +126,36 @@ void CAnimSourceReaderBase::UpdatePOIStates()
const std::vector<CParticlePOINode>& particleNodes = x4_sourceInfo->GetParticlePOIStream(); const std::vector<CParticlePOINode>& particleNodes = x4_sourceInfo->GetParticlePOIStream();
const std::vector<CSoundPOINode>& soundNodes = x4_sourceInfo->GetSoundPOIStream(); const std::vector<CSoundPOINode>& soundNodes = x4_sourceInfo->GetSoundPOIStream();
for (const CBoolPOINode& node : boolNodes) while (x14_passedBoolCount < boolNodes.size() &&
boolNodes[x14_passedBoolCount].GetTime() <= xc_curTime)
{ {
if (node.GetTime() > xc_curTime) auto& node = boolNodes[x14_passedBoolCount];
break; if (node.GetIndex() >= 0)
if (node.GetIndex() != -1)
x24_boolStates[node.GetIndex()].second = node.GetValue(); x24_boolStates[node.GetIndex()].second = node.GetValue();
++x14_passedBoolCount; ++x14_passedBoolCount;
} }
for (const CInt32POINode& node : int32Nodes) while (x18_passedIntCount < int32Nodes.size() &&
int32Nodes[x18_passedIntCount].GetTime() <= xc_curTime)
{ {
if (node.GetTime() > xc_curTime) auto& node = int32Nodes[x18_passedIntCount];
break; if (node.GetIndex() >= 0)
if (node.GetIndex() != -1)
x34_int32States[node.GetIndex()].second = node.GetValue(); x34_int32States[node.GetIndex()].second = node.GetValue();
++x18_passedIntCount; ++x18_passedIntCount;
} }
for (const CParticlePOINode& node : particleNodes) while (x1c_passedParticleCount < particleNodes.size() &&
particleNodes[x1c_passedParticleCount].GetTime() <= xc_curTime)
{ {
if (node.GetTime() > xc_curTime) auto& node = particleNodes[x1c_passedParticleCount];
break; if (node.GetIndex() >= 0)
if (node.GetIndex() != -1)
x44_particleStates[node.GetIndex()].second = node.GetParticleData().GetParentedMode(); x44_particleStates[node.GetIndex()].second = node.GetParticleData().GetParentedMode();
++x1c_passedParticleCount; ++x1c_passedParticleCount;
} }
for (const CSoundPOINode& node : soundNodes) while (x20_passedSoundCount < soundNodes.size() &&
soundNodes[x20_passedSoundCount].GetTime() <= xc_curTime)
{ {
if (node.GetTime() > xc_curTime)
break;
++x20_passedSoundCount; ++x20_passedSoundCount;
} }
} }

View File

@ -1321,6 +1321,9 @@ void CElementGen::RenderParticles()
zeus::CTransform systemCameraMatrix = systemViewPointMatrix.inverse() * x22c_globalOrientation; zeus::CTransform systemCameraMatrix = systemViewPointMatrix.inverse() * x22c_globalOrientation;
systemViewPointMatrix = ((zeus::CTransform::Translate(xe8_globalTranslation) * x10c_globalScaleTransform) * systemViewPointMatrix = ((zeus::CTransform::Translate(xe8_globalTranslation) * x10c_globalScaleTransform) *
systemViewPointMatrix) * x178_localScaleTransform; systemViewPointMatrix) * x178_localScaleTransform;
if (x26c_29_ORNT)
CGraphics::SetModelMatrix(systemViewPointMatrix * systemCameraMatrix);
else
CGraphics::SetModelMatrix(systemViewPointMatrix); CGraphics::SetModelMatrix(systemViewPointMatrix);
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
@ -1397,6 +1400,34 @@ void CElementGen::RenderParticles()
CParticleGlobals::SetEmitterTime(x74_curFrame); CParticleGlobals::SetEmitterTime(x74_curFrame);
if (!x26c_30_MBLR) if (!x26c_30_MBLR)
{ {
#if 0
if (!desc->x44_28_x30_28_SORT && constUVs && !x26c_29_ORNT)
{
if (!desc->x50_x3c_ROTA)
{
if (!zeus::close_enough(x80_timeDeltaScale, 1.f))
{
RenderBasicParticlesNoRotNoTS(systemCameraMatrix);
}
else
{
RenderBasicParticlesNoRotTS(systemCameraMatrix);
}
}
else
{
if (!zeus::close_enough(x80_timeDeltaScale, 1.f))
{
RenderBasicParticlesRotNoTS(systemCameraMatrix);
}
else
{
RenderBasicParticlesRotTS(systemCameraMatrix);
}
}
}
#endif
switch (m_shaderClass) switch (m_shaderClass)
{ {
case CElementGenShaders::EShaderClass::Tex: case CElementGenShaders::EShaderClass::Tex:
@ -1411,6 +1442,9 @@ void CElementGen::RenderParticles()
Log.report(logvisor::Fatal, "unexpected particle shader class"); Log.report(logvisor::Fatal, "unexpected particle shader class");
break; break;
} }
if (!x26c_29_ORNT)
{
for (int i = 0; i < x30_particles.size(); ++i) for (int i = 0; i < x30_particles.size(); ++i)
{ {
int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : i; int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : i;
@ -1463,7 +1497,8 @@ void CElementGen::RenderParticles()
inst.color = particle.x34_color; inst.color = particle.x34_color;
break; break;
} }
default: break; default:
break;
} }
} }
else else
@ -1480,8 +1515,10 @@ void CElementGen::RenderParticles()
SParticleInstanceTex& inst = g_instTexData.back(); SParticleInstanceTex& inst = g_instTexData.back();
inst.pos[0] = zeus::CVector4f{viewPoint.x + sinT + cosT, 0.f, viewPoint.z + cosT - sinT, 1.f}; inst.pos[0] = zeus::CVector4f{viewPoint.x + sinT + cosT, 0.f, viewPoint.z + cosT - sinT, 1.f};
inst.pos[1] = zeus::CVector4f{viewPoint.x + sinT - cosT, 0.f, viewPoint.z + sinT + cosT, 1.f}; inst.pos[1] = zeus::CVector4f{viewPoint.x + sinT - cosT, 0.f, viewPoint.z + sinT + cosT, 1.f};
inst.pos[2] = zeus::CVector4f{viewPoint.x + (cosT - sinT), 0.f, viewPoint.z + (-cosT - sinT), 1.f}; inst.pos[2] = zeus::CVector4f{viewPoint.x + (cosT - sinT), 0.f, viewPoint.z + (-cosT - sinT),
inst.pos[3] = zeus::CVector4f{viewPoint.x - (sinT + cosT), 0.f, viewPoint.z - (cosT - sinT), 1.f}; 1.f};
inst.pos[3] = zeus::CVector4f{viewPoint.x - (sinT + cosT), 0.f, viewPoint.z - (cosT - sinT),
1.f};
inst.color = particle.x34_color; inst.color = particle.x34_color;
inst.uvs[0] = {uvs.xMax, uvs.yMax}; inst.uvs[0] = {uvs.xMax, uvs.yMax};
inst.uvs[1] = {uvs.xMin, uvs.yMax}; inst.uvs[1] = {uvs.xMin, uvs.yMax};
@ -1495,15 +1532,113 @@ void CElementGen::RenderParticles()
SParticleInstanceNoTex& inst = g_instNoTexData.back(); SParticleInstanceNoTex& inst = g_instNoTexData.back();
inst.pos[0] = zeus::CVector4f{viewPoint.x + sinT + cosT, 0.f, viewPoint.z + cosT - sinT, 1.f}; inst.pos[0] = zeus::CVector4f{viewPoint.x + sinT + cosT, 0.f, viewPoint.z + cosT - sinT, 1.f};
inst.pos[1] = zeus::CVector4f{viewPoint.x + sinT - cosT, 0.f, viewPoint.z + sinT + cosT, 1.f}; inst.pos[1] = zeus::CVector4f{viewPoint.x + sinT - cosT, 0.f, viewPoint.z + sinT + cosT, 1.f};
inst.pos[2] = zeus::CVector4f{viewPoint.x + (cosT - sinT), 0.f, viewPoint.z + (-cosT - sinT), 1.f}; inst.pos[2] = zeus::CVector4f{viewPoint.x + (cosT - sinT), 0.f, viewPoint.z + (-cosT - sinT),
inst.pos[3] = zeus::CVector4f{viewPoint.x - (sinT + cosT), 0.f, viewPoint.z - (cosT - sinT), 1.f}; 1.f};
inst.pos[3] = zeus::CVector4f{viewPoint.x - (sinT + cosT), 0.f, viewPoint.z - (cosT - sinT),
1.f};
inst.color = particle.x34_color; inst.color = particle.x34_color;
break; break;
} }
default: break; default:
break;
} }
} }
} }
}
else
{
for (int i = 0; i < x30_particles.size(); ++i)
{
int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : i;
CParticle& particle = x30_particles[partIdx];
g_currentParticle = &particle;
int partFrame = x74_curFrame - particle.x28_startFrame - 1;
zeus::CVector3f viewPoint = ((particle.x4_pos - particle.x10_prevPos) *
x80_timeDeltaScale + particle.x10_prevPos);
float width = !desc->x50_x3c_ROTA ? 1.f : particle.x30_lineWidthOrRota;
zeus::CVector3f dir;
if (particle.x1c_vel.canBeNormalized())
{
dir = particle.x1c_vel.normalized();
}
else
{
zeus::CVector3f delta = particle.x4_pos - particle.x10_prevPos;
if (delta.canBeNormalized())
dir = delta.normalized();
else
dir = zeus::CVector3f::skUp;
}
zeus::CVector3f foreVec = particle.x2c_lineLengthOrSize * dir;
zeus::CVector3f rightVec;
if (desc->x30_31_RSOP)
{
rightVec = dir.cross(CGraphics::g_ViewMatrix.basis[1]);
if (rightVec.canBeNormalized())
{
rightVec = rightVec.normalized() * (particle.x2c_lineLengthOrSize * width);
}
else
{
rightVec = dir.cross((CGraphics::g_ViewMatrix.origin - particle.x4_pos).normalized());
if (rightVec.canBeNormalized())
{
rightVec = rightVec.normalized() * (particle.x2c_lineLengthOrSize * width);
}
}
}
else
{
rightVec = foreVec.cross(CGraphics::g_ViewMatrix.basis[1]) * width;
}
if (!constUVs)
{
CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame);
CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame);
texr->GetValueUV(partFrame, uvs);
}
switch (m_shaderClass)
{
case CElementGenShaders::EShaderClass::Tex:
{
g_instTexData.emplace_back();
SParticleInstanceTex& inst = g_instTexData.back();
viewPoint += rightVec * 0.5f;
inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
viewPoint -= rightVec;
inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
inst.color = particle.x34_color;
inst.uvs[0] = {uvs.xMax, uvs.yMax};
inst.uvs[1] = {uvs.xMin, uvs.yMax};
inst.uvs[2] = {uvs.xMax, uvs.yMin};
inst.uvs[3] = {uvs.xMin, uvs.yMin};
break;
}
case CElementGenShaders::EShaderClass::NoTex:
{
g_instNoTexData.emplace_back();
SParticleInstanceNoTex& inst = g_instNoTexData.back();
viewPoint += rightVec * 0.5f;
inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
viewPoint -= rightVec;
inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec};
inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec};
inst.color = particle.x34_color;
break;
}
default:
break;
}
}
}
switch (m_shaderClass) switch (m_shaderClass)
{ {
case CElementGenShaders::EShaderClass::Tex: case CElementGenShaders::EShaderClass::Tex:

View File

@ -1036,14 +1036,22 @@ bool CParticleDataFactory::CreateGPSM(CGenDescription* fillDesc, CInputStream& i
fillDesc->xe8_xd4_SSPO.reset(GetVectorElement(in)); fillDesc->xe8_xd4_SSPO.reset(GetVectorElement(in));
break; break;
case SBIG('TEXR'): case SBIG('TEXR'):
fillDesc->x54_x40_TEXR.reset(GetTextureElement(in, resPool)); {
std::unique_ptr<CUVElement> tex(GetTextureElement(in, resPool));
if (tex->GetValueTexture(0))
fillDesc->x54_x40_TEXR = std::move(tex);
break; break;
}
case SBIG('SSWH'): case SBIG('SSWH'):
fillDesc->xd4_xc0_SSWH = GetSwooshGeneratorDesc(in, resPool); fillDesc->xd4_xc0_SSWH = GetSwooshGeneratorDesc(in, resPool);
break; break;
case SBIG('TIND'): case SBIG('TIND'):
fillDesc->x58_x44_TIND.reset(GetTextureElement(in, resPool)); {
std::unique_ptr<CUVElement> tex(GetTextureElement(in, resPool));
if (tex->GetValueTexture(0))
fillDesc->x58_x44_TIND = std::move(tex);
break; break;
}
case SBIG('VMD4'): case SBIG('VMD4'):
fillDesc->x45_29_x31_31_VMD4 = GetBool(in); fillDesc->x45_29_x31_31_VMD4 = GetBool(in);
break; break;