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

@ -38,11 +38,11 @@ public:
CPOINode(CInputStream& in); CPOINode(CInputStream& in);
virtual ~CPOINode() = default; virtual ~CPOINode() = default;
std::string_view GetString() const {return x8_name;} std::string_view GetString() const { return x8_name; }
const CCharAnimTime& GetTime() const {return x1c_time;} const CCharAnimTime& GetTime() const { return x1c_time; }
void SetTime(const CCharAnimTime& time) { x1c_time = time; } void SetTime(const CCharAnimTime& time) { x1c_time = time; }
EPOIType GetPoiType() const { return x18_type; } EPOIType GetPoiType() const { return x18_type; }
u32 GetIndex() const {return x24_index;} u32 GetIndex() const { return x24_index; }
float GetWeight() const { return x2c_weight; } float GetWeight() const { return x2c_weight; }
s32 GetCharacterIndex() const { return x30_charIdx; } s32 GetCharacterIndex() const { return x30_charIdx; }
s32 GetFlags() const { return x34_flags; } s32 GetFlags() const { return x34_flags; }

View File

@ -14,7 +14,7 @@ class CParticlePOINode : public CPOINode
public: public:
CParticlePOINode(); CParticlePOINode();
CParticlePOINode(CInputStream& in); CParticlePOINode(CInputStream& in);
const CParticleData& GetParticleData() const {return x38_data;} const CParticleData& GetParticleData() const { return x38_data; }
static CParticlePOINode CopyNodeMinusStartTime(const CParticlePOINode& node, static CParticlePOINode CopyNodeMinusStartTime(const CParticlePOINode& node,
const CCharAnimTime& startTime); const CCharAnimTime& startTime);

View File

@ -1321,7 +1321,10 @@ 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;
CGraphics::SetModelMatrix(systemViewPointMatrix); if (x26c_29_ORNT)
CGraphics::SetModelMatrix(systemViewPointMatrix * systemCameraMatrix);
else
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,99 +1442,203 @@ void CElementGen::RenderParticles()
Log.report(logvisor::Fatal, "unexpected particle shader class"); Log.report(logvisor::Fatal, "unexpected particle shader class");
break; break;
} }
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; if (!x26c_29_ORNT)
zeus::CVector3f viewPoint; {
if (desc->x44_28_x30_28_SORT) for (int i = 0; i < x30_particles.size(); ++i)
viewPoint = sortItems[i].x4_viewPoint; {
else int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : i;
viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * CParticle& particle = x30_particles[partIdx];
g_currentParticle = &particle;
int partFrame = x74_curFrame - particle.x28_startFrame - 1;
zeus::CVector3f viewPoint;
if (desc->x44_28_x30_28_SORT)
viewPoint = sortItems[i].x4_viewPoint;
else
viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) *
x80_timeDeltaScale + particle.x10_prevPos); x80_timeDeltaScale + particle.x10_prevPos);
if (!constUVs) if (!constUVs)
{ {
CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame); CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame);
CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame); CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame);
texr->GetValueUV(partFrame, uvs); texr->GetValueUV(partFrame, uvs);
} }
float size = 0.5f * particle.x2c_lineLengthOrSize; float size = 0.5f * particle.x2c_lineLengthOrSize;
if (0.f == particle.x30_lineWidthOrRota) if (0.f == particle.x30_lineWidthOrRota)
{
switch (m_shaderClass)
{ {
case CElementGenShaders::EShaderClass::Tex: switch (m_shaderClass)
{
case CElementGenShaders::EShaderClass::Tex:
{
g_instTexData.emplace_back();
SParticleInstanceTex& inst = g_instTexData.back();
inst.pos[0] = zeus::CVector4f{viewPoint.x + size, 0.f, viewPoint.z + size, 1.f};
inst.pos[1] = zeus::CVector4f{viewPoint.x - size, 0.f, viewPoint.z + size, 1.f};
inst.pos[2] = zeus::CVector4f{viewPoint.x + size, 0.f, viewPoint.z - size, 1.f};
inst.pos[3] = zeus::CVector4f{viewPoint.x - size, 0.f, viewPoint.z - size, 1.f};
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();
inst.pos[0] = zeus::CVector4f{viewPoint.x + size, 0.f, viewPoint.z + size, 1.f};
inst.pos[1] = zeus::CVector4f{viewPoint.x - size, 0.f, viewPoint.z + size, 1.f};
inst.pos[2] = zeus::CVector4f{viewPoint.x + size, 0.f, viewPoint.z - size, 1.f};
inst.pos[3] = zeus::CVector4f{viewPoint.x - size, 0.f, viewPoint.z - size, 1.f};
inst.color = particle.x34_color;
break;
}
default:
break;
}
}
else
{ {
g_instTexData.emplace_back(); float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
SParticleInstanceTex& inst = g_instTexData.back(); float sinT = std::sin(theta) * size;
inst.pos[0] = zeus::CVector4f{viewPoint.x + size, 0.f, viewPoint.z + size, 1.f}; float cosT = std::cos(theta) * size;
inst.pos[1] = zeus::CVector4f{viewPoint.x - size, 0.f, viewPoint.z + size, 1.f};
inst.pos[2] = zeus::CVector4f{viewPoint.x + size, 0.f, viewPoint.z - size, 1.f};
inst.pos[3] = zeus::CVector4f{viewPoint.x - size, 0.f, viewPoint.z - size, 1.f};
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();
inst.pos[0] = zeus::CVector4f{viewPoint.x + size, 0.f, viewPoint.z + size, 1.f};
inst.pos[1] = zeus::CVector4f{viewPoint.x - size, 0.f, viewPoint.z + size, 1.f};
inst.pos[2] = zeus::CVector4f{viewPoint.x + size, 0.f, viewPoint.z - size, 1.f};
inst.pos[3] = zeus::CVector4f{viewPoint.x - size, 0.f, viewPoint.z - size, 1.f};
inst.color = particle.x34_color;
break;
}
default: break;
}
}
else
{
float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
float sinT = std::sin(theta) * size;
float cosT = std::cos(theta) * size;
switch (m_shaderClass) switch (m_shaderClass)
{ {
case CElementGenShaders::EShaderClass::Tex: case CElementGenShaders::EShaderClass::Tex:
{ {
g_instTexData.emplace_back(); g_instTexData.emplace_back();
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.color = particle.x34_color; inst.pos[3] = zeus::CVector4f{viewPoint.x - (sinT + cosT), 0.f, viewPoint.z - (cosT - sinT),
inst.uvs[0] = {uvs.xMax, uvs.yMax}; 1.f};
inst.uvs[1] = {uvs.xMin, uvs.yMax}; inst.color = particle.x34_color;
inst.uvs[2] = {uvs.xMax, uvs.yMin}; inst.uvs[0] = {uvs.xMax, uvs.yMax};
inst.uvs[3] = {uvs.xMin, uvs.yMin}; inst.uvs[1] = {uvs.xMin, uvs.yMax};
break; inst.uvs[2] = {uvs.xMax, uvs.yMin};
} inst.uvs[3] = {uvs.xMin, uvs.yMin};
case CElementGenShaders::EShaderClass::NoTex: break;
{ }
g_instNoTexData.emplace_back(); case CElementGenShaders::EShaderClass::NoTex:
SParticleInstanceNoTex& inst = g_instNoTexData.back(); {
inst.pos[0] = zeus::CVector4f{viewPoint.x + sinT + cosT, 0.f, viewPoint.z + cosT - sinT, 1.f}; g_instNoTexData.emplace_back();
inst.pos[1] = zeus::CVector4f{viewPoint.x + sinT - cosT, 0.f, viewPoint.z + sinT + cosT, 1.f}; SParticleInstanceNoTex& inst = g_instNoTexData.back();
inst.pos[2] = zeus::CVector4f{viewPoint.x + (cosT - sinT), 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[3] = 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.color = particle.x34_color; inst.pos[2] = zeus::CVector4f{viewPoint.x + (cosT - sinT), 0.f, viewPoint.z + (-cosT - sinT),
break; 1.f};
} inst.pos[3] = zeus::CVector4f{viewPoint.x - (sinT + cosT), 0.f, viewPoint.z - (cosT - sinT),
default: break; 1.f};
inst.color = particle.x34_color;
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;