mirror of https://github.com/AxioDL/metaforce.git
Implement CActorLights::BuildAreaLightList
This commit is contained in:
parent
9cd421888d
commit
84578e9909
|
@ -167,12 +167,15 @@ bool MREA::Extract(const SpecBase& dataSpec,
|
|||
rs.seek(secStart + head.secSizes[curSec++], athena::Begin);
|
||||
|
||||
/* Dump VISI entities */
|
||||
auto visiPos = rs.position();
|
||||
if (head.secSizes[curSec] && rs.readUint32Big() == 'VISI')
|
||||
{
|
||||
athena::io::YAMLDocWriter visiWriter("VISI");
|
||||
uint32_t unkCount = 0;
|
||||
if (auto __vec = visiWriter.enterSubVector("entities"))
|
||||
{
|
||||
rs.seek(18, athena::Current);
|
||||
rs.seek(14, athena::Current);
|
||||
unkCount = rs.readUint32Big();
|
||||
uint32_t entityCount = rs.readUint32Big();
|
||||
rs.seek(8, athena::Current);
|
||||
for (int i=0 ; i<entityCount ; ++i)
|
||||
|
@ -184,6 +187,14 @@ bool MREA::Extract(const SpecBase& dataSpec,
|
|||
hecl::ProjectPath visiMetadataPath(outPath.getParentPath(), _S("!visi.yaml"));
|
||||
athena::io::FileWriter visiMetadata(visiMetadataPath.getAbsolutePath());
|
||||
visiWriter.finish(&visiMetadata);
|
||||
|
||||
if (unkCount)
|
||||
{
|
||||
rs.seek(visiPos, athena::Begin);
|
||||
auto bytes = rs.readUBytes(head.secSizes[curSec]);
|
||||
athena::io::FileWriter fw(std::string("/Users/jacko/Desktop/") + pakRouter.getBestEntryName(entry, false).c_str() + ".visi");
|
||||
fw.writeUBytes(bytes.get(), head.secSizes[curSec]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Origins to center of mass */
|
||||
|
@ -398,15 +409,16 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
|
|||
}
|
||||
|
||||
/* Lights */
|
||||
std::vector<atVec3f> lightsVisi;
|
||||
std::vector<atVec3f> lightsVisi[2];
|
||||
{
|
||||
int actualCount = 0;
|
||||
int actualCounts[2] = {};
|
||||
for (const Light& l : lights)
|
||||
if (l.layer == 0 || l.layer == 1)
|
||||
++actualCount;
|
||||
lightsVisi.reserve(actualCount);
|
||||
++actualCounts[l.layer];
|
||||
lightsVisi[0].reserve(actualCounts[0]);
|
||||
lightsVisi[1].reserve(actualCounts[1]);
|
||||
|
||||
secs.emplace_back(12 + 65 * actualCount, 0);
|
||||
secs.emplace_back(12 + 65 * (actualCounts[0] + actualCounts[1]), 0);
|
||||
athena::io::MemoryWriter w(secs.back().data(), secs.back().size());
|
||||
w.writeUint32Big(0xBABEDEAD);
|
||||
|
||||
|
@ -426,7 +438,7 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
|
|||
BabeDeadLight light = {};
|
||||
WriteBabeDeadLightFromBlender(light, l);
|
||||
light.write(w);
|
||||
lightsVisi.push_back(light.position);
|
||||
lightsVisi[l.layer].push_back(light.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -495,8 +507,11 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
|
|||
w.writeVec3fBig(ent.second.max);
|
||||
}
|
||||
|
||||
w.writeUint32Big(lightsVisi.size());
|
||||
for (const auto& light : lightsVisi)
|
||||
w.writeUint32Big(lightsVisi[0].size() + lightsVisi[1].size());
|
||||
w.writeUint32Big(lightsVisi[1].size());
|
||||
for (const auto& light : lightsVisi[1])
|
||||
w.writeVec3fBig(light);
|
||||
for (const auto& light : lightsVisi[0])
|
||||
w.writeVec3fBig(light);
|
||||
|
||||
w.close();
|
||||
|
|
|
@ -237,15 +237,15 @@ struct LightParameters : BigYAML
|
|||
Value<atUint32> shadowTesselation;
|
||||
Value<float> unknown3;
|
||||
Value<float> unknown4;
|
||||
Value<atVec4f> unknown5; // CColor
|
||||
Value<bool> unknown6;
|
||||
Value<atVec4f> noLightsAmbient; // CColor
|
||||
Value<bool> makeLights;
|
||||
Value<atUint32> worldLightingOptions;
|
||||
Value<atUint32> lightRecalculationOptions;
|
||||
Value<atVec3f> unknown7;
|
||||
Value<atUint32> unknown8;
|
||||
Value<atUint32> unknown9;
|
||||
Value<bool> unknown10;
|
||||
Value<atUint32> unknown11;
|
||||
Value<atVec3f> actorPosBias;
|
||||
Value<atUint32> maxDynamicLights;
|
||||
Value<atUint32> maxAreaLights;
|
||||
Value<bool> ambientChannelOverflow;
|
||||
Value<atUint32> layerIndex;
|
||||
};
|
||||
|
||||
struct PatternedInfo : BigYAML
|
||||
|
|
|
@ -1071,8 +1071,8 @@ void CTweakPlayer::read(athena::io::YAMLDocReader& __dna_docin)
|
|||
x130_ = __dna_docin.readFloat("x130_");
|
||||
/* x134_ */
|
||||
x134_ = __dna_docin.readFloat("x134_");
|
||||
/* x138_ */
|
||||
x138_hudLagAmount = __dna_docin.readFloat("x138_");
|
||||
/* x138_hudLagAmount */
|
||||
x138_hudLagAmount = __dna_docin.readFloat("x138_hudLagAmount");
|
||||
/* x13c_ */
|
||||
x13c_ = __dna_docin.readFloat("x13c_");
|
||||
/* x140_ */
|
||||
|
@ -1580,8 +1580,8 @@ void CTweakPlayer::CTweakPlayer::write(athena::io::YAMLDocWriter& __dna_docout)
|
|||
__dna_docout.writeFloat("x130_", x130_);
|
||||
/* x134_ */
|
||||
__dna_docout.writeFloat("x134_", x134_);
|
||||
/* x138_ */
|
||||
__dna_docout.writeFloat("x138_", x138_hudLagAmount);
|
||||
/* x138_hudLagAmount */
|
||||
__dna_docout.writeFloat("x138_hudLagAmount", x138_hudLagAmount);
|
||||
/* x13c_ */
|
||||
__dna_docout.writeFloat("x13c_", x13c_);
|
||||
/* x140_ */
|
||||
|
|
|
@ -261,6 +261,7 @@ public:
|
|||
const std::weak_ptr<CWorldTransManager>&,
|
||||
const std::weak_ptr<CWorldLayerState>&);
|
||||
|
||||
u32 GetInputFrameIdx() const { return x8d4_inputFrameIdx; }
|
||||
bool RenderLast(TUniqueId);
|
||||
void AddDrawableActorPlane(const CActor& actor, const zeus::CPlane&, const zeus::CAABox& aabb) const;
|
||||
void AddDrawableActor(const CActor& actor, const zeus::CVector3f& vec, const zeus::CAABox& aabb) const;
|
||||
|
|
|
@ -1,21 +1,28 @@
|
|||
#include "CActorLights.hpp"
|
||||
#include "Graphics/CModel.hpp"
|
||||
#include "World/CGameArea.hpp"
|
||||
#include "CStateManager.hpp"
|
||||
#include "Collision/CGameCollision.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
s32 CActorLights::sFrameSchedulerCount = 0;
|
||||
CActorLights::CActorLights(u32 unk, const zeus::CVector3f& vec, int a, int b, bool c, int d, int e, float f1)
|
||||
: x2a8_(unk), x2ac_(vec), x2b8_b(b), x2bc_a(a), x2cc_(f1 * f1)
|
||||
CActorLights::CActorLights(u32 areaUpdateFramePeriod, const zeus::CVector3f& actorPosBias,
|
||||
int maxDynamicLights, int maxAreaLights, bool ambientChannelOverflow,
|
||||
bool layer2, bool disableWorldLights, float positionUpdateThreshold)
|
||||
: x2a8_areaUpdateFramePeriod(areaUpdateFramePeriod), x2ac_actorPosBias(actorPosBias),
|
||||
x2b8_maxAreaLights(maxAreaLights), x2bc_maxDynamicLights(maxDynamicLights),
|
||||
x2cc_actorPositionDeltaUpdateThreshold(positionUpdateThreshold * positionUpdateThreshold)
|
||||
{
|
||||
x298_24_ = true;
|
||||
x298_25_ = true;
|
||||
x298_24_dirty = true;
|
||||
x298_25_castShadows = true;
|
||||
|
||||
x298_28_inArea = (!e && b > 0) ? true : false;
|
||||
x298_29_ = c;
|
||||
x298_30_ = d;
|
||||
x298_31_ = e;
|
||||
x299_24_ = true;
|
||||
x298_28_inArea = (!disableWorldLights && maxAreaLights > 0) ? true : false;
|
||||
x298_29_ambientChannelOverflow = ambientChannelOverflow;
|
||||
x298_30_layer2 = layer2;
|
||||
x298_31_disableWorldLights = disableWorldLights;
|
||||
x299_24_inBrightLight = true;
|
||||
|
||||
sFrameSchedulerCount++;
|
||||
sFrameSchedulerCount &= 7;
|
||||
|
@ -24,9 +31,9 @@ CActorLights::CActorLights(u32 unk, const zeus::CVector3f& vec, int a, int b, bo
|
|||
void CActorLights::BuildConstantAmbientLighting()
|
||||
{
|
||||
x299_26_ = true;
|
||||
x298_24_ = true;
|
||||
x29c_ = -1;
|
||||
x2a0_ = -1;
|
||||
x298_24_dirty = true;
|
||||
x29c_shadowLightValIdx = -1;
|
||||
x2a0_shadowLightIdx = -1;
|
||||
}
|
||||
|
||||
void CActorLights::BuildConstantAmbientLighting(const zeus::CColor& color)
|
||||
|
@ -34,10 +41,10 @@ void CActorLights::BuildConstantAmbientLighting(const zeus::CColor& color)
|
|||
x299_26_ = false;
|
||||
x288_ambientColor = color;
|
||||
x294_aid = kInvalidAreaId;
|
||||
x298_24_ = true;
|
||||
x298_26_ = true;
|
||||
x29c_ = -1;
|
||||
x2a0_ = -1;
|
||||
x298_24_dirty = true;
|
||||
x298_26_hasAreaLights = true;
|
||||
x29c_shadowLightValIdx = -1;
|
||||
x2a0_shadowLightIdx = -1;
|
||||
}
|
||||
|
||||
void CActorLights::BuildFakeLightList(const std::vector<CLight>& lights, const zeus::CColor& color)
|
||||
|
@ -50,11 +57,299 @@ void CActorLights::BuildFaceLightList(CStateManager& mgr, const CGameArea& area,
|
|||
{
|
||||
}
|
||||
|
||||
void CActorLights::BuildDynamicLightList(CStateManager& mgr, const zeus::CAABox& aabb)
|
||||
struct SLightValue
|
||||
{
|
||||
u32 x0_areaLightIdx;
|
||||
zeus::CColor x4_color;
|
||||
float x10_colorMag;
|
||||
float x14_accumulatedMag = 0.f;
|
||||
EPVSVisSetState x18_visiblity;
|
||||
};
|
||||
|
||||
void CActorLights::MergeOverflowLight(CLight& out, zeus::CColor& color, const CLight& in, float colorMag)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CActorLights::MoveAmbienceToLights(const zeus::CVector3f& vec)
|
||||
void CActorLights::AddOverflowToLights(const CLight& light, const zeus::CColor& color, float mag)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CActorLights::MoveAmbienceToLights(const zeus::CColor& color)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CActorLights::MultiplyLightingLevels(float level)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool CActorLights::BuildAreaLightList(CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb)
|
||||
{
|
||||
const std::vector<CWorldLight>& lightList = x298_30_layer2 ? area.GetPostConstructed()->x80_lightsB :
|
||||
area.GetPostConstructed()->x60_lightsA;
|
||||
const std::vector<CLight>& gfxLightList = x298_30_layer2 ? area.GetPostConstructed()->x90_gfxLightsB :
|
||||
area.GetPostConstructed()->x70_gfxLightsA;
|
||||
float worldLightingLevel = area.GetPostConstructed()->x1128_worldLightingLevel;
|
||||
x298_26_hasAreaLights = lightList.size() != 0;
|
||||
if (!x298_26_hasAreaLights || !x298_28_inArea)
|
||||
{
|
||||
/* World lights disabled */
|
||||
if (x298_31_disableWorldLights)
|
||||
x2d4_worldLightingLevel = worldLightingLevel;
|
||||
x29c_shadowLightValIdx = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
zeus::CVector3f vec;
|
||||
if (!x298_24_dirty && x294_aid == area.GetAreaId())
|
||||
{
|
||||
/* Early return if not ready for update */
|
||||
if (mgr.GetInputFrameIdx() - x2a4_lastUpdateFrame < x2a8_areaUpdateFramePeriod)
|
||||
return false;
|
||||
vec = aabb.center() + x2ac_actorPosBias;
|
||||
if (x2d4_worldLightingLevel == worldLightingLevel)
|
||||
if ((x2c0_lastActorPos - vec).magSquared() < x2cc_actorPositionDeltaUpdateThreshold)
|
||||
return false;
|
||||
x2c0_lastActorPos = vec;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x294_aid != area.GetAreaId())
|
||||
x2d8_brightLightIdx = -1;
|
||||
x2a4_lastUpdateFrame = sFrameSchedulerCount + mgr.GetInputFrameIdx();
|
||||
vec = aabb.center() + x2ac_actorPosBias;
|
||||
x2c0_lastActorPos = vec;
|
||||
}
|
||||
|
||||
/* Reset lighting state */
|
||||
x2d4_worldLightingLevel = worldLightingLevel;
|
||||
x298_24_dirty = false;
|
||||
x294_aid = area.GetAreaId();
|
||||
x29c_shadowLightValIdx = -1;
|
||||
x288_ambientColor = zeus::CColor::skClear;
|
||||
|
||||
/* Find candidate lights via PVS */
|
||||
bool use2ndLayer;
|
||||
if (x298_30_layer2)
|
||||
{
|
||||
if (const CPVSAreaSet* pvs = area.GetAreaVisSet())
|
||||
use2ndLayer = pvs->Has2ndLayerLights();
|
||||
else
|
||||
use2ndLayer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
use2ndLayer = false;
|
||||
}
|
||||
|
||||
CPVSVisSet sets[3];
|
||||
sets[0].Reset(EPVSVisSetState::OutOfBounds);
|
||||
sets[1].Reset(EPVSVisSetState::OutOfBounds);
|
||||
sets[2].Reset(EPVSVisSetState::OutOfBounds);
|
||||
|
||||
if (const CPVSAreaSet* pvs = area.GetAreaVisSet())
|
||||
{
|
||||
zeus::CVector3f localVec = area.GetInverseTransform() * vec;
|
||||
sets[0].SetTestPoint(pvs->GetVisOctree(), localVec);
|
||||
localVec = area.GetInverseTransform() * aabb.max;
|
||||
sets[1].SetTestPoint(pvs->GetVisOctree(), localVec);
|
||||
localVec = area.GetInverseTransform() * aabb.min;
|
||||
sets[2].SetTestPoint(pvs->GetVisOctree(), localVec);
|
||||
}
|
||||
|
||||
std::vector<SLightValue> valList;
|
||||
valList.reserve(lightList.size());
|
||||
|
||||
auto lightIt = lightList.begin();
|
||||
int lightIdx = 0;
|
||||
for (const CLight& light : gfxLightList)
|
||||
{
|
||||
if (light.GetType() == ELightType::LocalAmbient)
|
||||
{
|
||||
/* Take ambient here */
|
||||
x288_ambientColor = light.GetNormalIndependentLightingAtPoint(vec);
|
||||
}
|
||||
else
|
||||
{
|
||||
EPVSVisSetState visible = EPVSVisSetState::OutOfBounds;
|
||||
if (area.GetAreaVisSet())
|
||||
{
|
||||
if (lightIt->DoesCastShadows())
|
||||
{
|
||||
u32 pvsIdx;
|
||||
if (use2ndLayer)
|
||||
pvsIdx = area.Get2ndPVSLightFeature(lightIdx);
|
||||
else
|
||||
pvsIdx = area.Get1stPVSLightFeature(lightIdx);
|
||||
visible = sets[0].GetVisible(pvsIdx);
|
||||
if (visible != EPVSVisSetState::OutOfBounds)
|
||||
visible = std::max(visible, sets[1].GetVisible(pvsIdx));
|
||||
if (visible != EPVSVisSetState::OutOfBounds)
|
||||
visible = std::max(visible, sets[2].GetVisible(pvsIdx));
|
||||
}
|
||||
}
|
||||
if (visible != EPVSVisSetState::EndOfTree)
|
||||
{
|
||||
zeus::CSphere sphere(light.GetPosition(), light.GetRadius() * 2.f);
|
||||
if (aabb.intersects(sphere))
|
||||
{
|
||||
/* Light passes as candidate */
|
||||
valList.emplace_back();
|
||||
SLightValue& value = valList.back();
|
||||
value.x0_areaLightIdx = lightIdx;
|
||||
value.x4_color = light.GetNormalIndependentLightingAtPoint(vec);
|
||||
value.x4_color.a = 0.f;
|
||||
value.x10_colorMag = value.x4_color.magnitude();
|
||||
value.x18_visiblity = visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
++lightIt;
|
||||
++lightIdx;
|
||||
}
|
||||
|
||||
/* Sort lights most intense to least intense */
|
||||
std::sort(valList.begin(), valList.end(),
|
||||
[](const SLightValue& a, const SLightValue& b)
|
||||
{
|
||||
return a.x10_colorMag >= b.x10_colorMag;
|
||||
});
|
||||
|
||||
if (x298_27_findShadowLight)
|
||||
{
|
||||
/* Accumulate magnitudes up to most intense for shadow dynamic range check */
|
||||
x288_ambientColor.a = 0.f;
|
||||
float mag = x288_ambientColor.magnitude();
|
||||
for (auto it = valList.rbegin() ; it != valList.rend() ; ++it)
|
||||
{
|
||||
mag += it->x10_colorMag;
|
||||
it->x14_accumulatedMag = mag;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ambient color for overflow area lights */
|
||||
zeus::CColor overflowAmbColor;
|
||||
|
||||
/* Averaged light for overflow area lights */
|
||||
CLight overflowLight = CLight::BuildCustom(zeus::CVector3f::skZero, zeus::CVector3f::skZero, zeus::CColor::skBlack,
|
||||
0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
|
||||
zeus::CColor overflowLightColor;
|
||||
float overflowMag = 0.f;
|
||||
|
||||
/* Max significant lights */
|
||||
int maxAreaLights = !x298_29_ambientChannelOverflow ? x2b8_maxAreaLights - 1 : x2b8_maxAreaLights;
|
||||
x0_areaLights.clear();
|
||||
|
||||
/* Filter for performing final light visibility test */
|
||||
CMaterialFilter filter =
|
||||
CMaterialFilter::MakeIncludeExclude(CMaterialList(EMaterialTypes::Solid),
|
||||
CMaterialList(EMaterialTypes::Projectile, EMaterialTypes::ProjectilePassthrough,
|
||||
EMaterialTypes::SeeThrough));
|
||||
u32 mostSigLightIdx = 0;
|
||||
|
||||
/* Narrowphase test candidates starting with most intense */
|
||||
for (int i=0 ; i<valList.size() ; ++i)
|
||||
{
|
||||
const SLightValue& value = valList[i];
|
||||
const CLight& light = gfxLightList[value.x0_areaLightIdx];
|
||||
if (x0_areaLights.size() < maxAreaLights)
|
||||
{
|
||||
/* Significant light */
|
||||
bool actorToLightContact = true;
|
||||
bool castShadows = lightList[value.x0_areaLightIdx].DoesCastShadows() && x298_25_castShadows;
|
||||
bool outOfBounds = area.GetAreaVisSet() && value.x18_visiblity == EPVSVisSetState::OutOfBounds;
|
||||
if (castShadows)
|
||||
{
|
||||
/* Process shadow cast */
|
||||
zeus::CVector3f delta = light.GetPosition() - vec;
|
||||
float deltaMag = delta.magnitude();
|
||||
bool useShadow = false;
|
||||
if (x298_27_findShadowLight && x29c_shadowLightValIdx == -1 && light.GetType() != ELightType::LocalAmbient &&
|
||||
deltaMag > 2.f && !aabb.pointInside(light.GetPosition()))
|
||||
{
|
||||
/* Perform shadow dynamic range check */
|
||||
if (!x0_areaLights.size() ||
|
||||
(x0_areaLights.size() == 1 && value.x10_colorMag / valList[mostSigLightIdx].x10_colorMag > 0.5f))
|
||||
{
|
||||
useShadow = value.x10_colorMag / value.x14_accumulatedMag >
|
||||
x2d0_shadowDynamicRangeThreshold / (1.f + x2d0_shadowDynamicRangeThreshold);
|
||||
}
|
||||
}
|
||||
if (useShadow)
|
||||
{
|
||||
/* Note shadow light */
|
||||
x29c_shadowLightValIdx = x0_areaLights.size();
|
||||
x2a0_shadowLightIdx = value.x0_areaLightIdx;
|
||||
}
|
||||
else if (!outOfBounds)
|
||||
{
|
||||
/* Note brightest light contact */
|
||||
delta = delta * 1.f / deltaMag;
|
||||
actorToLightContact = CGameCollision::TestLightRayIntersection(area, vec, delta, deltaMag, filter);
|
||||
if (i == 0)
|
||||
{
|
||||
x299_24_inBrightLight = actorToLightContact;
|
||||
if (x2d8_brightLightIdx != value.x0_areaLightIdx)
|
||||
{
|
||||
x2dc_overrideDist = actorToLightContact ? 0 : 15;
|
||||
x2d8_brightLightIdx = value.x0_areaLightIdx;
|
||||
}
|
||||
x299_25_overrideFirstDist = false;
|
||||
actorToLightContact = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (actorToLightContact)
|
||||
{
|
||||
/* Add to final list */
|
||||
if (x0_areaLights.size() == 0)
|
||||
mostSigLightIdx = i;
|
||||
x0_areaLights.push_back(light);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Overflow light */
|
||||
if (!x298_29_ambientChannelOverflow && value.x10_colorMag > 0.001f)
|
||||
{
|
||||
/* Average parameters into final light */
|
||||
MergeOverflowLight(overflowLight, overflowLightColor, light, value.x10_colorMag);
|
||||
overflowMag += value.x10_colorMag;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Average color into ambient channel */
|
||||
overflowAmbColor += value.x4_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finalize overflow lights */
|
||||
if (!x298_29_ambientChannelOverflow)
|
||||
AddOverflowToLights(overflowLight, overflowLightColor, overflowMag);
|
||||
else
|
||||
MoveAmbienceToLights(overflowAmbColor);
|
||||
|
||||
/* Clamp ambient color */
|
||||
if (x288_ambientColor.r > 1.f)
|
||||
x288_ambientColor.r = 1.f;
|
||||
if (x288_ambientColor.g > 1.f)
|
||||
x288_ambientColor.g = 1.f;
|
||||
if (x288_ambientColor.b > 1.f)
|
||||
x288_ambientColor.b = 1.f;
|
||||
x288_ambientColor.a = 1.f;
|
||||
|
||||
/* Multiply down lighting with world fader level */
|
||||
if (worldLightingLevel < 1.f)
|
||||
MultiplyLightingLevels(worldLightingLevel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CActorLights::BuildDynamicLightList(CStateManager& mgr, const zeus::CAABox& aabb)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -63,7 +358,7 @@ void CActorLights::ActivateLights(CBooModel& model) const
|
|||
std::vector<CLight> lights;
|
||||
if (x298_28_inArea)
|
||||
{
|
||||
if (!x298_26_ || !x299_26_)
|
||||
if (!x298_26_hasAreaLights || !x299_26_)
|
||||
{
|
||||
model.ActivateLights(lights);
|
||||
//return;
|
||||
|
|
|
@ -25,45 +25,53 @@ class CActorLights
|
|||
{
|
||||
struct
|
||||
{
|
||||
bool x298_24_ : 1;
|
||||
bool x298_25_ : 1;
|
||||
bool x298_26_ : 1;
|
||||
bool x298_27_ : 1;
|
||||
bool x298_24_dirty : 1;
|
||||
bool x298_25_castShadows : 1;
|
||||
bool x298_26_hasAreaLights : 1;
|
||||
bool x298_27_findShadowLight : 1;
|
||||
bool x298_28_inArea : 1;
|
||||
bool x298_29_ : 1;
|
||||
bool x298_30_ : 1;
|
||||
bool x298_31_ : 1;
|
||||
bool x299_24_ : 1;
|
||||
bool x298_29_ambientChannelOverflow : 1;
|
||||
bool x298_30_layer2 : 1;
|
||||
bool x298_31_disableWorldLights : 1;
|
||||
bool x299_24_inBrightLight : 1;
|
||||
bool x299_25_overrideFirstDist : 1;
|
||||
bool x299_26_ : 1;
|
||||
};
|
||||
u16 _dummy = 0;
|
||||
};
|
||||
bool x29a_ = false;
|
||||
u32 x29c_ = -1;
|
||||
u32 x2a0_ = -1;
|
||||
u32 x2a4_ = 0;
|
||||
u32 x2a8_;
|
||||
zeus::CVector3f x2ac_;
|
||||
int x2b8_b;
|
||||
int x2bc_a;
|
||||
zeus::CVector3f x2c0_;
|
||||
float x2cc_;
|
||||
float x2d0_ = 0.f;
|
||||
float x2d4_ = 1.f;
|
||||
u32 x2d8_ = -1;
|
||||
u32 x29c_shadowLightValIdx = -1;
|
||||
u32 x2a0_shadowLightIdx = -1;
|
||||
u32 x2a4_lastUpdateFrame = 0;
|
||||
u32 x2a8_areaUpdateFramePeriod;
|
||||
zeus::CVector3f x2ac_actorPosBias;
|
||||
int x2b8_maxAreaLights;
|
||||
int x2bc_maxDynamicLights;
|
||||
zeus::CVector3f x2c0_lastActorPos;
|
||||
float x2cc_actorPositionDeltaUpdateThreshold;
|
||||
float x2d0_shadowDynamicRangeThreshold = 0.f;
|
||||
float x2d4_worldLightingLevel = 1.f;
|
||||
u32 x2d8_brightLightIdx = -1;
|
||||
u32 x2dc_overrideDist = 0;
|
||||
|
||||
static void MergeOverflowLight(CLight& out, zeus::CColor& color, const CLight& in, float colorMag);
|
||||
void AddOverflowToLights(const CLight& light, const zeus::CColor& color, float mag);
|
||||
void MoveAmbienceToLights(const zeus::CColor& color);
|
||||
void MultiplyLightingLevels(float level);
|
||||
|
||||
public:
|
||||
CActorLights(u32, const zeus::CVector3f& vec, int, int, bool, int, int, float);
|
||||
CActorLights(u32 areaUpdateFramePeriod, const zeus::CVector3f& actorPosBias,
|
||||
int maxDynamicLights, int maxAreaLights, bool ambientChannelOverflow,
|
||||
bool layer2, bool disableWorldLights, float positionUpdateThreshold);
|
||||
|
||||
void BuildConstantAmbientLighting();
|
||||
void BuildConstantAmbientLighting(const zeus::CColor& color);
|
||||
void BuildFakeLightList(const std::vector<CLight>& lights, const zeus::CColor& color);
|
||||
void BuildFaceLightList(CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb);
|
||||
bool BuildAreaLightList(CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb);
|
||||
void BuildDynamicLightList(CStateManager& mgr, const zeus::CAABox& aabb);
|
||||
void MoveAmbienceToLights(const zeus::CVector3f& vec);
|
||||
void ActivateLights(CBooModel& model) const;
|
||||
void SetCastShadows(bool v) { x298_25_castShadows = v; }
|
||||
|
||||
void SetAmbientColor(const zeus::CColor& color) { x288_ambientColor = color; }
|
||||
const CLight& GetLight(u32 idx) const;
|
||||
|
|
|
@ -158,4 +158,14 @@ CGameCollision::RayWorldIntersection(const CStateManager& mgr, TUniqueId& idOut,
|
|||
else
|
||||
return staticRes;
|
||||
}
|
||||
|
||||
bool CGameCollision::TestLightRayIntersection(const CGameArea& area, const zeus::CVector3f& pos,
|
||||
const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter)
|
||||
{
|
||||
if (mag <= 0.f)
|
||||
mag = 100000.f;
|
||||
CAreaOctTree::Node node = area.GetPostConstructed()->x0_collision->GetRootNode();
|
||||
zeus::CLine line(pos, dir);
|
||||
return node.LineTest(line, filter, mag);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ class CMaterialList;
|
|||
class CStateManager;
|
||||
class CPhysicsActor;
|
||||
class CMaterialFilter;
|
||||
class CGameArea;
|
||||
|
||||
class CGameCollision
|
||||
{
|
||||
|
@ -44,6 +45,8 @@ public:
|
|||
static CRayCastResult RayWorldIntersection(const CStateManager& mgr, TUniqueId& idOut, const zeus::CVector3f& pos,
|
||||
const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList);
|
||||
static bool TestLightRayIntersection(const CGameArea& area, const zeus::CVector3f& pos,
|
||||
const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -86,6 +86,15 @@ CLight::CLight(ELightType type,
|
|||
}
|
||||
}
|
||||
|
||||
zeus::CColor CLight::GetNormalIndependentLightingAtPoint(const zeus::CVector3f& point) const
|
||||
{
|
||||
if (x1c_type == ELightType::LocalAmbient)
|
||||
return x18_color;
|
||||
|
||||
float dist = std::max((x0_pos - point).magnitude(), FLT_EPSILON);
|
||||
return x18_color * (1.f / (x2c_distQ * dist * dist + x28_distL * dist + x24_distC));
|
||||
}
|
||||
|
||||
CLight CLight::BuildDirectional(const zeus::CVector3f& dir, const zeus::CColor& color)
|
||||
{
|
||||
return CLight(ELightType::Directional, kDefaultPosition, dir, color, 180.f);
|
||||
|
|
|
@ -116,6 +116,7 @@ public:
|
|||
|
||||
float GetIntensity() const;
|
||||
const zeus::CColor& GetColor() const { return x18_color; }
|
||||
zeus::CColor GetNormalIndependentLightingAtPoint(const zeus::CVector3f& point) const;
|
||||
|
||||
static CLight BuildDirectional(const zeus::CVector3f& dir, const zeus::CColor& color);
|
||||
static CLight BuildSpot(const zeus::CVector3f& pos, const zeus::CVector3f& dir,
|
||||
|
|
|
@ -8,7 +8,7 @@ CPVSAreaSet::CPVSAreaSet(const u8* data, u32 len)
|
|||
CMemoryInStream r(data, len);
|
||||
x0_numFeatures = r.readUint32Big();
|
||||
x4_numLights = r.readUint32Big();
|
||||
x8_c = r.readUint32Big();
|
||||
x8_num2ndLights = r.readUint32Big();
|
||||
xc_numActors = r.readUint32Big();
|
||||
x10_leafSize = r.readUint32Big();
|
||||
x14_lightIndexCount = r.readUint32Big();
|
||||
|
|
|
@ -11,7 +11,7 @@ class CPVSAreaSet
|
|||
{
|
||||
u32 x0_numFeatures;
|
||||
u32 x4_numLights;
|
||||
u32 x8_c;
|
||||
u32 x8_num2ndLights;
|
||||
u32 xc_numActors;
|
||||
u32 x10_leafSize;
|
||||
u32 x14_lightIndexCount;
|
||||
|
@ -23,8 +23,11 @@ public:
|
|||
CPVSAreaSet(const u8* data, u32 len);
|
||||
u32 GetNumFeatures() const { return x0_numFeatures; }
|
||||
u32 GetNumActors() const { return xc_numActors; }
|
||||
u32 Get1stLightIndex(u32 lightIdx) const { return x0_numFeatures + x8_num2ndLights + lightIdx; }
|
||||
u32 Get2ndLightIndex(u32 lightIdx) const { return x0_numFeatures + lightIdx; }
|
||||
bool Has2ndLayerLights() const { return x8_num2ndLights != 0; }
|
||||
u32 GetEntityIdByIndex(int idx) const { return x18_entityIndex[idx]; }
|
||||
const CPVSVisOctree& GetVisOctree() { return x20_octree; }
|
||||
const CPVSVisOctree& GetVisOctree() const { return x20_octree; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -759,7 +759,10 @@ void CSamusHud::UpdateHudDynamicLights(float dt, const CStateManager& mgr)
|
|||
{
|
||||
if (TCastToConstPtr<CFirstPersonCamera> fpCam = mgr.GetCameraManager()->GetCurrentCamera(mgr))
|
||||
{
|
||||
|
||||
zeus::CAABox camAABB(fpCam->GetTranslation() - 0.125f, fpCam->GetTranslation() + 0.125f);
|
||||
if (mgr.GetPlayer().GetAreaIdAlways() == kInvalidAreaId)
|
||||
return;
|
||||
//x33c_lights->
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -340,6 +340,11 @@ public:
|
|||
MREAHeader VerifyHeader() const;
|
||||
TUniqueId LookupPVSUniqueID(TUniqueId id) const;
|
||||
s16 LookupPVSID(TUniqueId id) const;
|
||||
const CPVSAreaSet* GetAreaVisSet() const { return GetPostConstructed()->xa0_pvs.get(); }
|
||||
u32 Get1stPVSLightFeature(u32 lightIdx) const
|
||||
{ return GetAreaVisSet() ? GetAreaVisSet()->Get1stLightIndex(lightIdx) : -1; }
|
||||
u32 Get2ndPVSLightFeature(u32 lightIdx) const
|
||||
{ return GetAreaVisSet() ? GetAreaVisSet()->Get2ndLightIndex(lightIdx) : -1; }
|
||||
|
||||
const zeus::CTransform& GetTransform() const {return xc_transform;}
|
||||
const zeus::CTransform& GetInverseTransform() const {return x3c_invTransform;}
|
||||
|
|
|
@ -5,20 +5,6 @@
|
|||
#include "zeus/CColor.hpp"
|
||||
#include "Character/CActorLights.hpp"
|
||||
|
||||
static inline u32 count_1bits(u32 x)
|
||||
{
|
||||
x = x - ((x >> 1) & 0x55555555);
|
||||
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
|
||||
x = x + (x >> 8);
|
||||
x = x + (x >> 16);
|
||||
return x & 0x0000003F;
|
||||
}
|
||||
|
||||
static inline u32 count_0bits(u32 x)
|
||||
{
|
||||
return 32 - count_1bits(x);
|
||||
}
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
|
@ -34,16 +20,16 @@ public:
|
|||
{
|
||||
Zero,
|
||||
NormalWorld,
|
||||
Two,
|
||||
NoShadowCast,
|
||||
DisableWorld
|
||||
};
|
||||
|
||||
enum class ELightRecalculationOptions
|
||||
{
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
Three
|
||||
LargeFrameCount,
|
||||
EightFrames,
|
||||
FourFrames,
|
||||
OneFrame
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -52,54 +38,59 @@ private:
|
|||
EShadowTesselation xc_shadowTesselation = EShadowTesselation::Zero;
|
||||
float x10_d = 0.f;
|
||||
float x14_e = 0.f;
|
||||
zeus::CColor x18_f;
|
||||
bool x1c_noLights = false;
|
||||
bool x1d_h = false;
|
||||
zeus::CColor x18_noLightsAmbient;
|
||||
bool x1c_makeLights = false;
|
||||
bool x1d_ambientChannelOverflow = false;
|
||||
EWorldLightingOptions x20_worldLightingOptions = EWorldLightingOptions::Zero;
|
||||
ELightRecalculationOptions x24_lightRecalcOpts = ELightRecalculationOptions::One;
|
||||
s32 x28_k = 0;
|
||||
zeus::CVector3f x2c_l;
|
||||
s32 x38_m = 4;
|
||||
s32 x3c_n = 4;
|
||||
ELightRecalculationOptions x24_lightRecalcOpts = ELightRecalculationOptions::EightFrames;
|
||||
s32 x28_layerIdx = 0;
|
||||
zeus::CVector3f x2c_actorPosBias;
|
||||
s32 x38_maxDynamicLights = 4;
|
||||
s32 x3c_maxAreaLights = 4;
|
||||
public:
|
||||
CLightParameters() = default;
|
||||
CLightParameters(bool a, float b, EShadowTesselation shadowTess, float d, float e, const zeus::CColor& f,
|
||||
bool noLights, EWorldLightingOptions lightingOpts, ELightRecalculationOptions lightRecalcOpts,
|
||||
const zeus::CVector3f& l, s32 m, s32 n, bool h, s32 k)
|
||||
: x4_a(a), x8_b(b), xc_shadowTesselation(shadowTess), x10_d(d), x14_e(e), x18_f(f), x1c_noLights(noLights), x1d_h(h),
|
||||
x20_worldLightingOptions(lightingOpts), x24_lightRecalcOpts(lightRecalcOpts), x28_k(k), x2c_l(l), x38_m(m), x3c_n(n)
|
||||
CLightParameters(bool a, float b, EShadowTesselation shadowTess, float d, float e, const zeus::CColor& noLightsAmbient,
|
||||
bool makeLights, EWorldLightingOptions lightingOpts, ELightRecalculationOptions lightRecalcOpts,
|
||||
const zeus::CVector3f& actorPosBias, s32 maxDynamicLights, s32 maxAreaLights, bool ambChannelOverflow, s32 layerIdx)
|
||||
: x4_a(a), x8_b(b), xc_shadowTesselation(shadowTess), x10_d(d), x14_e(e), x18_noLightsAmbient(noLightsAmbient), x1c_makeLights(makeLights),
|
||||
x1d_ambientChannelOverflow(ambChannelOverflow), x20_worldLightingOptions(lightingOpts), x24_lightRecalcOpts(lightRecalcOpts),
|
||||
x28_layerIdx(layerIdx), x2c_actorPosBias(actorPosBias), x38_maxDynamicLights(maxDynamicLights), x3c_maxAreaLights(maxAreaLights)
|
||||
{
|
||||
if (x38_m > 4 || x38_m == -1)
|
||||
x38_m = 4;
|
||||
if (x3c_n > 4 || x3c_n == -1)
|
||||
x3c_n = 4;
|
||||
if (x38_maxDynamicLights > 4 || x38_maxDynamicLights == -1)
|
||||
x38_maxDynamicLights = 4;
|
||||
if (x3c_maxAreaLights > 4 || x3c_maxAreaLights == -1)
|
||||
x3c_maxAreaLights = 4;
|
||||
}
|
||||
static CLightParameters None() {return CLightParameters();}
|
||||
|
||||
static u32 GetFramesBetweenRecalculation(ELightRecalculationOptions opts)
|
||||
{
|
||||
if (opts == ELightRecalculationOptions::Zero)
|
||||
if (opts == ELightRecalculationOptions::LargeFrameCount)
|
||||
return 0x3FFFFFFF;
|
||||
else if (opts == ELightRecalculationOptions::One)
|
||||
else if (opts == ELightRecalculationOptions::EightFrames)
|
||||
return 8;
|
||||
else if (opts == ELightRecalculationOptions::Two)
|
||||
else if (opts == ELightRecalculationOptions::FourFrames)
|
||||
return 4;
|
||||
else if (opts == ELightRecalculationOptions::Three)
|
||||
else if (opts == ELightRecalculationOptions::OneFrame)
|
||||
return 1;
|
||||
return 8;
|
||||
}
|
||||
|
||||
std::unique_ptr<CActorLights> MakeActorLights() const
|
||||
{
|
||||
if (x1c_noLights == false)
|
||||
if (!x1c_makeLights)
|
||||
return {};
|
||||
|
||||
u32 updateFrames = GetFramesBetweenRecalculation(x24_lightRecalcOpts);
|
||||
CActorLights* lights = new CActorLights(updateFrames, x2c_l, x1d_h, x3c_n, x38_m,
|
||||
count_0bits(x28_k - 1) / 32,
|
||||
count_0bits(u32(x20_worldLightingOptions) - 3) / 32,
|
||||
CActorLights* lights = new CActorLights(updateFrames, x2c_actorPosBias, x38_maxDynamicLights,
|
||||
x3c_maxAreaLights, x1d_ambientChannelOverflow, x28_layerIdx == 1,
|
||||
x20_worldLightingOptions == EWorldLightingOptions::DisableWorld,
|
||||
0.1f);
|
||||
return std::unique_ptr<CActorLights>(std::move(lights));
|
||||
if (x20_worldLightingOptions == EWorldLightingOptions::NoShadowCast)
|
||||
lights->SetCastShadows(false);
|
||||
if (x3c_maxAreaLights == 0)
|
||||
lights->SetAmbientColor(x18_noLightsAmbient);
|
||||
return std::unique_ptr<CActorLights>(lights);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
ELightType GetLightType() const;
|
||||
const zeus::CVector3f& GetDirection() const;
|
||||
const zeus::CVector3f& GetPosition() const;
|
||||
bool DoesCastShadows() const;
|
||||
bool DoesCastShadows() const { return x34_castShadows; }
|
||||
|
||||
CLight GetAsCGraphicsLight() const;
|
||||
};
|
||||
|
|
|
@ -281,34 +281,35 @@ CLightParameters ScriptLoader::LoadLightParameters(CInputStream& in)
|
|||
float d = in.readFloatBig();
|
||||
float e = in.readFloatBig();
|
||||
|
||||
zeus::CColor col;
|
||||
col.readRGBABig(in);
|
||||
zeus::CColor noLightsAmbient;
|
||||
noLightsAmbient.readRGBABig(in);
|
||||
|
||||
bool f = in.readBool();
|
||||
bool makeLights = in.readBool();
|
||||
CLightParameters::EWorldLightingOptions lightOpts = CLightParameters::EWorldLightingOptions(in.readUint32Big());
|
||||
CLightParameters::ELightRecalculationOptions recalcOpts =
|
||||
CLightParameters::ELightRecalculationOptions(in.readUint32Big());
|
||||
|
||||
zeus::CVector3f vec;
|
||||
vec.readBig(in);
|
||||
zeus::CVector3f actorPosBias;
|
||||
actorPosBias.readBig(in);
|
||||
|
||||
s32 w1 = -1;
|
||||
s32 w2 = -1;
|
||||
s32 maxDynamicLights = -1;
|
||||
s32 maxAreaLights = -1;
|
||||
if (propCount >= 12)
|
||||
{
|
||||
w1 = in.readUint32Big();
|
||||
w2 = in.readUint32Big();
|
||||
maxDynamicLights = in.readUint32Big();
|
||||
maxAreaLights = in.readUint32Big();
|
||||
}
|
||||
|
||||
bool b1 = false;
|
||||
bool ambientChannelOverflow = false;
|
||||
if (propCount >= 13)
|
||||
b1 = in.readBool();
|
||||
ambientChannelOverflow = in.readBool();
|
||||
|
||||
s32 w3 = 0;
|
||||
s32 layerIdx = 0;
|
||||
if (propCount >= 14)
|
||||
w3 = in.readUint32Big();
|
||||
layerIdx = in.readUint32Big();
|
||||
|
||||
return CLightParameters(a, b, shadowTess, d, e, col, f, lightOpts, recalcOpts, vec, w1, w2, b1, w3);
|
||||
return CLightParameters(a, b, shadowTess, d, e, noLightsAmbient, makeLights, lightOpts, recalcOpts, actorPosBias,
|
||||
maxDynamicLights, maxAreaLights, ambientChannelOverflow, layerIdx);
|
||||
}
|
||||
return CLightParameters::None();
|
||||
}
|
||||
|
|
|
@ -306,6 +306,7 @@ std::vector<uint8_t> VISIBuilder::build(const zeus::CAABox& fullAabb,
|
|||
size_t modelCount,
|
||||
const std::vector<VISIRenderer::Entity>& entities,
|
||||
const std::vector<VISIRenderer::Light>& lights,
|
||||
size_t layer2LightCount,
|
||||
FPercent updatePercent)
|
||||
{
|
||||
Log.report(logvisor::Info, "Started!");
|
||||
|
@ -338,7 +339,7 @@ std::vector<uint8_t> VISIBuilder::build(const zeus::CAABox& fullAabb,
|
|||
w.writeBool(true);
|
||||
w.writeUint32Big(featureCount);
|
||||
w.writeUint32Big(lights.size());
|
||||
w.writeUint32Big(0);
|
||||
w.writeUint32Big(layer2LightCount);
|
||||
w.writeUint32Big(entities.size());
|
||||
w.writeUint32Big(leafBytesCount);
|
||||
w.writeUint32Big(lights.size());
|
||||
|
|
|
@ -122,6 +122,7 @@ struct VISIBuilder
|
|||
size_t modelCount,
|
||||
const std::vector<VISIRenderer::Entity>& entities,
|
||||
const std::vector<VISIRenderer::Light>& lights,
|
||||
size_t layer2LightCount,
|
||||
FPercent updatePercent);
|
||||
|
||||
VISIBuilder(VISIRenderer& renderer) : renderCache(renderer) {}
|
||||
|
|
|
@ -488,6 +488,7 @@ void VISIRenderer::Run(FPercent updatePercent)
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t layer2LightCount = 0;
|
||||
{
|
||||
athena::io::FileReader r(m_argv[1]);
|
||||
if (r.hasError())
|
||||
|
@ -545,6 +546,7 @@ void VISIRenderer::Run(FPercent updatePercent)
|
|||
}
|
||||
|
||||
uint32_t lightCount = r.readUint32Big();
|
||||
layer2LightCount = r.readUint32Big();
|
||||
m_lights.resize(lightCount);
|
||||
for (uint32_t i=0 ; i<lightCount ; ++i)
|
||||
{
|
||||
|
@ -561,7 +563,8 @@ void VISIRenderer::Run(FPercent updatePercent)
|
|||
|
||||
VISIBuilder builder(*this);
|
||||
std::vector<uint8_t> dataOut = builder.build(m_totalAABB, m_models.size(),
|
||||
m_entities, m_lights, m_updatePercent);
|
||||
m_entities, m_lights, layer2LightCount,
|
||||
m_updatePercent);
|
||||
if (dataOut.empty())
|
||||
{
|
||||
m_return = 1;
|
||||
|
|
Loading…
Reference in New Issue