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<bool> unk2;
Value<float> weight;
Value<atUint32> unk4;
Value<atUint32> unk5;
Value<atUint32> charIdx;
Value<atUint32> flags;
};
struct BoolPOINode : POINode

View File

@ -647,7 +647,7 @@ void CAnimData::RecalcPoseBuilder(const CCharAnimTime* time)
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,

View File

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

View File

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

View File

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

View File

@ -1321,7 +1321,10 @@ void CElementGen::RenderParticles()
zeus::CTransform systemCameraMatrix = systemViewPointMatrix.inverse() * x22c_globalOrientation;
systemViewPointMatrix = ((zeus::CTransform::Translate(xe8_globalTranslation) * x10c_globalScaleTransform) *
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);
@ -1397,6 +1400,34 @@ void CElementGen::RenderParticles()
CParticleGlobals::SetEmitterTime(x74_curFrame);
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)
{
case CElementGenShaders::EShaderClass::Tex:
@ -1411,99 +1442,203 @@ void CElementGen::RenderParticles()
Log.report(logvisor::Fatal, "unexpected particle shader class");
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;
zeus::CVector3f viewPoint;
if (desc->x44_28_x30_28_SORT)
viewPoint = sortItems[i].x4_viewPoint;
else
viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) *
if (!x26c_29_ORNT)
{
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;
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);
if (!constUVs)
{
CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame);
CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame);
texr->GetValueUV(partFrame, uvs);
}
if (!constUVs)
{
CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame);
CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame);
texr->GetValueUV(partFrame, uvs);
}
float size = 0.5f * particle.x2c_lineLengthOrSize;
if (0.f == particle.x30_lineWidthOrRota)
{
switch (m_shaderClass)
float size = 0.5f * particle.x2c_lineLengthOrSize;
if (0.f == particle.x30_lineWidthOrRota)
{
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();
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
{
float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
float sinT = std::sin(theta) * size;
float cosT = std::cos(theta) * size;
float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
float sinT = std::sin(theta) * size;
float cosT = std::cos(theta) * size;
switch (m_shaderClass)
{
case CElementGenShaders::EShaderClass::Tex:
{
g_instTexData.emplace_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[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[3] = zeus::CVector4f{viewPoint.x - (sinT + cosT), 0.f, viewPoint.z - (cosT - sinT), 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 + 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[2] = zeus::CVector4f{viewPoint.x + (cosT - sinT), 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.color = particle.x34_color;
break;
}
default: break;
switch (m_shaderClass)
{
case CElementGenShaders::EShaderClass::Tex:
{
g_instTexData.emplace_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[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[3] = zeus::CVector4f{viewPoint.x - (sinT + cosT), 0.f, viewPoint.z - (cosT - sinT),
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 + 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[2] = zeus::CVector4f{viewPoint.x + (cosT - sinT), 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.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)
{
case CElementGenShaders::EShaderClass::Tex:

View File

@ -1036,14 +1036,22 @@ bool CParticleDataFactory::CreateGPSM(CGenDescription* fillDesc, CInputStream& i
fillDesc->xe8_xd4_SSPO.reset(GetVectorElement(in));
break;
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;
}
case SBIG('SSWH'):
fillDesc->xd4_xc0_SSWH = GetSwooshGeneratorDesc(in, resPool);
break;
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;
}
case SBIG('VMD4'):
fillDesc->x45_29_x31_31_VMD4 = GetBool(in);
break;