Work on CMapWorld rendering

This commit is contained in:
Jack Andersen 2017-04-21 20:42:32 -10:00
parent 56e386088a
commit 337ffd1c16
23 changed files with 1406 additions and 132 deletions

View File

@ -45,6 +45,8 @@ struct ITweakAutoMapper : public ITweak
virtual float GetCamPanUnitsPerFrame() const=0;
virtual float GetCamVerticalOffset() const=0;
virtual const zeus::CColor& GetMiniMapSamusModColor() const=0;
virtual const zeus::CColor& GetDoorColor(int idx) const=0;
virtual const zeus::CColor& GetOpenDoorColor() const=0;
};
}

View File

@ -120,6 +120,8 @@ struct CTweakAutoMapper : public ITweakAutoMapper
float GetCamPanUnitsPerFrame() const { return xe0_camPanUnitsPerFrame; }
float GetCamVerticalOffset() const { return xec_camVerticalOffset; }
const zeus::CColor& GetMiniMapSamusModColor() const { return xf0_miniMapSamusModColor; }
const zeus::CColor& GetDoorColor(int idx) const { return x104_doorColors[idx]; }
const zeus::CColor& GetOpenDoorColor() const { return x11c_openDoorColor; }
};
}
}

View File

@ -29,10 +29,14 @@ void CMapArea::PostConstruct()
x38_moStart = x44_buf.get();
x3c_vertexStart = x38_moStart + (x28_mappableObjCount * 0x50);
x40_surfaceStart = x40_surfaceStart + (x2c_vertexCount * 12);
for (u32 i = 0, j=0 ; i<x28_mappableObjCount ; ++i, j += 0x50)
(reinterpret_cast<CMappableObject*>(x38_moStart + j))->PostConstruct(x44_buf.get());
#if __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__
m_mappableObjects.reserve(x28_mappableObjCount);
for (u32 i = 0, j=0 ; i<x28_mappableObjCount ; ++i, j += 0x50)
{
m_mappableObjects.emplace_back(x38_moStart + j);
m_mappableObjects.back().PostConstruct(x44_buf.get());
}
u8* tmp = x3c_vertexStart;
for (u32 i = 0 ; i<(x2c_vertexCount*3) ; ++i)
{
@ -40,11 +44,29 @@ void CMapArea::PostConstruct()
*fl = hecl::SBig(*fl);
tmp += 4;
}
#endif
std::vector<u32> index;
m_surfaces.reserve(x30_surfaceCount);
for (u32 i = 0, j = 0 ; i<x30_surfaceCount ; ++i, j += 32)
(reinterpret_cast<CMapAreaSurface*>(x40_surfaceStart + j))->PostConstruct(x44_buf.get());
{
m_surfaces.emplace_back(x40_surfaceStart + j);
m_surfaces.back().PostConstruct(x44_buf.get(), index);
}
m_gfxToken = CGraphics::CommitResources([this, &index](boo::IGraphicsDataFactory::Context& ctx)
{
m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, x3c_vertexStart, 12, x2c_vertexCount);
m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, index.data(), 4, index.size());
for (u32 i = 0 ; i<x30_surfaceCount ; ++i)
m_surfaces[i].m_surfacePrims.emplace(ctx, m_vbo, m_ibo);
for (u32 i = 0 ; i<x28_mappableObjCount ; ++i)
{
CMappableObject& mapObj = m_mappableObjects[i];
if (CMappableObject::IsDoorType(mapObj.GetType()))
mapObj.m_doorSurface.emplace(ctx);
}
return true;
});
}
bool CMapArea::GetIsVisibleToAutoMapper(bool worldVis, bool areaVis) const
@ -138,8 +160,151 @@ const zeus::CVector3f& CMapArea::GetAreaPostTranslate(const IWorld& world, TArea
return zeus::CVector3f::skZero;
}
void CMapArea::CMapAreaSurface::PostConstruct(const void *)
CMapArea::CMapAreaSurface::CMapAreaSurface(const void* surfBuf)
{
athena::io::MemoryReader r(surfBuf, 32);
x0_normal = r.readVec3fBig();
xc_centroid = r.readVec3fBig();
x18_surfOffset = reinterpret_cast<const u8*>(uintptr_t(r.readUint32Big()));
x1c_outlineOffset = reinterpret_cast<const u8*>(uintptr_t(r.readUint32Big()));
}
void CMapArea::CMapAreaSurface::PostConstruct(const u8* buf, std::vector<u32>& index)
{
x18_surfOffset = buf + reinterpret_cast<uintptr_t>(x18_surfOffset);
x1c_outlineOffset = buf + reinterpret_cast<uintptr_t>(x1c_outlineOffset);
m_primStart = index.size();
{
athena::io::MemoryReader r(x18_surfOffset, INT_MAX);
u32 primCount = r.readUint32Big();
for (u32 i=0 ; i<primCount ; ++i)
{
GX::Primitive prim = GX::Primitive(r.readUint32Big());
u32 count = r.readUint32Big();
switch (prim)
{
case GX::Primitive::TRIANGLES:
{
for (u32 v=0 ; v<count ; v+=3)
{
if (index.size())
{
index.push_back(index.back());
index.push_back(r.readUByte());
index.push_back(index.back());
}
else
{
index.push_back(r.readUByte());
}
index.push_back(r.readUByte());
index.push_back(r.readUByte());
index.push_back(index.back());
}
break;
}
case GX::Primitive::TRIANGLESTRIP:
{
if (index.size())
{
index.push_back(index.back());
index.push_back(r.readUByte());
index.push_back(index.back());
}
else
{
index.push_back(r.readUByte());
}
for (u32 v=1 ; v<count ; ++v)
index.push_back(r.readUByte());
if (count & 1)
index.push_back(index.back());
break;
}
case GX::Primitive::TRIANGLEFAN:
{
u8 firstVert = r.readUByte();
if (index.size())
{
index.push_back(index.back());
index.push_back(r.readUByte());
}
else
{
index.push_back(r.readUByte());
index.push_back(index.back());
}
for (u32 v=1 ; v<count ; ++v)
{
index.push_back(firstVert);
index.push_back(r.readUByte());
}
break;
}
default: break;
}
r.seekAlign4();
}
}
m_primCount = index.size() - m_primStart;
}
void CMapArea::CMapAreaSurface::Draw(const zeus::CVector3f* verts, const zeus::CColor& surfColor,
const zeus::CColor& lineColor, float lineWidth) const
{
if (surfColor.a)
const_cast<CMapSurfaceShader&>(*m_surfacePrims).draw(surfColor, m_primStart, m_primCount);
if (lineColor.a)
{
bool draw2 = lineWidth > 1.f;
int totalPrims = draw2 + 1;
athena::io::MemoryReader r(x1c_outlineOffset, INT_MAX);
u32 outlineCount = r.readUint32Big();
totalPrims *= outlineCount;
std::vector<CLineRenderer>& linePrims = const_cast<std::vector<CLineRenderer>&>(m_linePrims);
if (linePrims.size() < totalPrims)
{
linePrims.reserve(totalPrims);
for (u32 j=0 ; j<=draw2 ; ++j)
{
r.seek(4, athena::SeekOrigin::Begin);
for (u32 i=0 ; i<outlineCount ; ++i)
{
u32 count = r.readUint32Big();
r.seek(count);
r.seekAlign4();
linePrims.emplace_back(CLineRenderer::EPrimitiveMode::LineStrip, count, nullptr, false);
}
}
}
zeus::CColor color = lineColor;
if (draw2)
color.a *= 0.5f;
float width = lineWidth;
auto primIt = linePrims.begin();
for (u32 j=0 ; j<=draw2 ; ++j)
{
r.seek(4, athena::SeekOrigin::Begin);
for (u32 i=0 ; i<outlineCount ; ++i)
{
CLineRenderer& prim = *primIt++;
prim.Reset();
u32 count = r.readUint32Big();
for (u32 v=0 ; v<count ; ++v)
{
u8 idx = r.readUByte();
prim.AddVertex(verts[idx], color, width);
}
prim.Render();
}
width -= 1.f;
}
}
}
CFactoryFnReturn FMapAreaFactory(const SObjectTag& objTag, CInputStream& in, const CVParamTransfer&,

View File

@ -5,6 +5,10 @@
#include "CResFactory.hpp"
#include "zeus/CAABox.hpp"
#include "zeus/CVector3f.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
#include "Graphics/CLineRenderer.hpp"
#include "Graphics/Shaders/CMapSurfaceShader.hpp"
#include "CMappableObject.hpp"
namespace urde
{
@ -14,11 +18,23 @@ class CMapArea
public:
class CMapAreaSurface
{
friend class CMapArea;
zeus::CVector3f x0_normal;
zeus::CVector3f xc_centroid;
const u8* x18_surfOffset;
const u8* x1c_outlineOffset;
u32 m_primStart;
u32 m_primCount;
std::experimental::optional<CMapSurfaceShader> m_surfacePrims;
std::vector<CLineRenderer> m_linePrims;
public:
void PostConstruct(const void*);
void Draw(const zeus::CVector3f*, const zeus::CColor&, const zeus::CColor&, float) const;
const zeus::CVector3f& GetNormal() const;
const zeus::CVector3f& GetCenterPosition() const;
CMapAreaSurface(const void* surfBuf);
CMapAreaSurface(CMapAreaSurface&&) = default;
void PostConstruct(const u8* buf, std::vector<u32>& index);
void Draw(const zeus::CVector3f* verts, const zeus::CColor& surfColor,
const zeus::CColor& lineColor, float lineWidth) const;
const zeus::CVector3f& GetNormal() const { return x0_normal; }
const zeus::CVector3f& GetCenterPosition() const { return xc_centroid; }
};
enum class EVisMode
{
@ -39,20 +55,25 @@ private:
u32 x30_surfaceCount;
u32 x34_size;
u8* x38_moStart;
std::vector<CMappableObject> m_mappableObjects;
u8* x3c_vertexStart;
u8* x40_surfaceStart;
std::vector<CMapAreaSurface> m_surfaces;
std::unique_ptr<u8[]> x44_buf;
boo::GraphicsDataToken m_gfxToken;
boo::IGraphicsBufferS* m_vbo;
boo::IGraphicsBufferS* m_ibo;
public:
CMapArea(CInputStream&, u32);
CMapArea(CInputStream& in, u32 size);
void PostConstruct();
bool GetIsVisibleToAutoMapper(bool, bool) const;
bool GetIsVisibleToAutoMapper(bool worldVis, bool areaVis) const;
zeus::CVector3f GetAreaCenterPoint() const { return x10_box.center(); }
const zeus::CAABox& GetBoundingBox() const { return x10_box; }
const zeus::CVector3f& GetVertices() const;
void GetMappableObject(s32) const;
void GetSurface(s32) const;
u32 GetNumMappableObjects() const;
u32 GetNumSurfaces() const;
const CMappableObject& GetMappableObject(int idx) const { return m_mappableObjects[idx]; }
const CMapAreaSurface& GetSurface(int idx) const { return m_surfaces[idx]; }
u32 GetNumMappableObjects() const { return m_mappableObjects.size(); }
u32 GetNumSurfaces() const { return m_surfaces.size(); }
zeus::CTransform GetAreaPostTransform(const IWorld& world, TAreaId aid) const;
static const zeus::CVector3f& GetAreaPostTranslate(const IWorld& world, TAreaId aid);
};

View File

@ -1,31 +1,102 @@
#include "CMapWorld.hpp"
#include "CMapWorldInfo.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "World/CWorld.hpp"
namespace urde
{
CMapWorld::CMapAreaData::CMapAreaData(ResId areaRes, EMapAreaList list, CMapAreaData* next)
: x0_area(g_SimplePool->GetObj(SObjectTag{FOURCC('MAPA'), areaRes})), x10_list(list), x14_next(next)
{}
CMapWorld::CMapWorld(CInputStream& in)
{
x10_listHeads.resize(3);
in.readUint32Big();
in.readUint32Big();
u32 areaCount = in.readUint32Big();
x0_areas.reserve(areaCount);
x20_traversed.resize(areaCount);
for (u32 i=0 ; i<areaCount ; ++i)
{
ResId mapaId = in.readUint32Big();
x0_areas.emplace_back(mapaId, EMapAreaList::Unloaded, x0_areas.empty() ? nullptr : &x0_areas.back());
}
x10_listHeads[2] = &x0_areas.back();
}
void CMapWorld::IsMapAreaInBFSInfoVector(const CMapWorld::CMapAreaData*, const std::vector<CMapWorld::CMapAreaBFSInfo>&) const
bool CMapWorld::IsMapAreaInBFSInfoVector(const CMapWorld::CMapAreaData* area,
const std::vector<CMapWorld::CMapAreaBFSInfo>& vec) const
{
for (const CMapWorld::CMapAreaBFSInfo& bfs : vec)
{
if (&x0_areas[bfs.GetAreaIndex()] == area)
return true;
}
return false;
}
void CMapWorld::SetWhichMapAreasLoaded(const IWorld&, int start, int count)
void CMapWorld::SetWhichMapAreasLoaded(const IWorld& wld, int start, int count)
{
ClearTraversedFlags();
std::vector<CMapAreaBFSInfo> bfsInfos;
bfsInfos.reserve(x0_areas.size());
DoBFS(wld, start, count, 9999.f, 9999.f, false, bfsInfos);
for (int i=0 ; i<2 ; ++i)
{
for (CMapAreaData* data = x10_listHeads[i] ; data ; data = data->NextMapAreaData())
{
if (!IsMapAreaInBFSInfoVector(data, bfsInfos))
{
data->Unlock();
MoveMapAreaToList(data, EMapAreaList::Unloaded);
}
}
}
for (CMapAreaBFSInfo& bfs : bfsInfos)
{
CMapAreaData& data = x0_areas[bfs.GetAreaIndex()];
data.Lock();
if (data.GetContainingList() == EMapAreaList::Unloaded)
MoveMapAreaToList(&data, EMapAreaList::Loading);
}
}
bool CMapWorld::IsMapAreasStreaming() const
{
return false;
bool ret = false;
for (CMapAreaData* data = x10_listHeads[1] ; data ; data = data->NextMapAreaData())
{
if (data->IsLoaded())
const_cast<CMapWorld*>(this)->MoveMapAreaToList(data, EMapAreaList::Loaded);
else
ret = true;
}
return ret;
}
void CMapWorld::MoveMapAreaToList(CMapWorld::CMapAreaData*, CMapWorld::EMapAreaList)
void CMapWorld::MoveMapAreaToList(CMapWorld::CMapAreaData* data, CMapWorld::EMapAreaList list)
{
CMapAreaData* last = nullptr;
for (CMapAreaData* head = x10_listHeads[int(data->GetContainingList())] ;;
last = head, head = head->NextMapAreaData())
{
if (head != data)
continue;
if (!last)
x10_listHeads[int(data->GetContainingList())] = head->NextMapAreaData();
else
last->SetNextMapArea(head->NextMapAreaData());
break;
}
data->SetNextMapArea(x10_listHeads[int(list)]);
data->SetContainingList(list);
x10_listHeads[int(list)] = data;
}
s32 CMapWorld::GetCurrentMapAreaDepth(const IWorld& wld, TAreaId aid) const
@ -39,9 +110,9 @@ s32 CMapWorld::GetCurrentMapAreaDepth(const IWorld& wld, TAreaId aid) const
return info.back().GetDepth();
}
std::vector<TAreaId> CMapWorld::GetVisibleAreas(const IWorld& wld, const CMapWorldInfo& mwInfo) const
std::vector<int> CMapWorld::GetVisibleAreas(const IWorld& wld, const CMapWorldInfo& mwInfo) const
{
std::vector<TAreaId> ret;
std::vector<int> ret;
ret.reserve(x0_areas.size());
for (int i=0 ; i<x0_areas.size() ; ++i)
{
@ -56,29 +127,439 @@ std::vector<TAreaId> CMapWorld::GetVisibleAreas(const IWorld& wld, const CMapWor
return ret;
}
void CMapWorld::Draw(const CMapWorld::CMapWorldDrawParms&, int, int, float, float, bool) const
void CMapWorld::Draw(const CMapWorld::CMapWorldDrawParms& parms, int curArea, int otherArea,
float depth1, float depth2, bool inMapScreen) const
{
if (depth1 == 0.f && depth2 == 0.f)
return;
ClearTraversedFlags();
int areaDepth = std::ceil(std::max(depth1, depth2));
std::vector<CMapAreaBFSInfo> bfsInfos;
bfsInfos.reserve(x0_areas.size());
if (curArea != otherArea)
{
const_cast<CMapWorld*>(this)->x20_traversed[otherArea] = true;
DoBFS(parms.GetWorld(), curArea, areaDepth, depth1, depth2, true, bfsInfos);
float lowD1 = std::ceil(depth1 - 1.f);
float tmp;
if (depth1 == std::floor(depth1))
tmp = 0.f;
else
tmp = 1.f - std::fmod(depth1, 1.f);
float newD1 = lowD1 + tmp;
float lowD2 = std::ceil(depth2 - 1.f);
if (depth2 == std::floor(depth2))
tmp = 0.f;
else
tmp = 1.f - std::fmod(depth2, 1.f);
float newD2 = lowD2 + tmp;
int otherDepth = std::ceil(std::max(newD1, newD2));
if (parms.GetWorld().IGetAreaAlways(otherArea)->IIsActive())
{
const_cast<CMapWorld*>(this)->x20_traversed[otherArea] = false;
DoBFS(parms.GetWorld(), otherArea, otherDepth, newD1, newD2, true, bfsInfos);
}
}
else
{
DoBFS(parms.GetWorld(), curArea, areaDepth, depth1, depth2, true, bfsInfos);
}
DrawAreas(parms, curArea, bfsInfos, inMapScreen);
}
void CMapWorld::DoBFS(const IWorld& wld, int startArea, int areaCount, float surfDepth, float outlineDepth,
bool checkLoad, std::vector<CMapAreaBFSInfo>& bfsInfos) const
{
if (areaCount <= 0 || !IsMapAreaValid(wld, startArea, checkLoad))
return;
int size = bfsInfos.size();
bfsInfos.emplace_back(startArea, 1, surfDepth, outlineDepth);
const_cast<CMapWorld*>(this)->x20_traversed[startArea] = true;
for (; size != bfsInfos.size() ; ++size)
{
CMapAreaBFSInfo& testInfo = bfsInfos[size];
if (testInfo.GetDepth() == areaCount)
continue;
surfDepth = testInfo.GetSurfaceDrawDepth() - 1.f;
outlineDepth = testInfo.GetOutlineDrawDepth() - 1.f;
const IGameArea* area = wld.IGetAreaAlways(testInfo.GetAreaIndex());
for (int i=0 ; i<area->IGetNumAttachedAreas() ; ++i)
{
TAreaId attId = area->IGetAttachedAreaId(i);
if (IsMapAreaValid(wld, attId, checkLoad) && !x20_traversed[attId])
{
bfsInfos.emplace_back(attId, testInfo.GetDepth() + 1, surfDepth, outlineDepth);
const_cast<CMapWorld*>(this)->x20_traversed[attId] = true;
}
}
}
}
bool CMapWorld::IsMapAreaValid(const IWorld& wld, int areaIdx, bool checkLoad) const
{
if (!wld.IGetAreaAlways(areaIdx)->IIsActive())
return false;
const CMapArea* mapa = GetMapArea(areaIdx);
if (checkLoad)
return mapa != nullptr;
return true;
}
void CMapWorld::DrawAreas(const CMapWorld::CMapWorldDrawParms&, int,
const std::vector<CMapWorld::CMapAreaBFSInfo>&, bool) const
{
}
void CMapWorld::DoBFS(const IWorld&, TAreaId, int, float, float, bool, std::vector<CMapAreaBFSInfo>&) const
struct Support
{
int x0_;
int x4_[3];
};
struct Circle2
{
zeus::CVector2f x0_point;
float x8_radiusSq;
};
struct Circle
{
zeus::CVector2f x0_point;
float x8_radius;
Circle(const Circle2& circ2)
: x0_point(circ2.x0_point), x8_radius(std::sqrt(circ2.x8_radiusSq)) {}
};
static Circle2 ExactCircle1(const zeus::CVector2f* a)
{
return {*a, 0.f};
}
bool CMapWorld::IsMapAreaValid(const IWorld &, int, bool) const
static Circle2 ExactCircle2(const zeus::CVector2f* a, const zeus::CVector2f* b)
{
return false;
Circle2 ret = {};
ret.x0_point = 0.5f * (*a + *b);
ret.x8_radiusSq = (*b - *a).magSquared() * 0.25f;
return ret;
}
void CMapWorld::DrawAreas(const CMapWorld::CMapWorldDrawParms&, int, const std::vector<CMapWorld::CMapAreaBFSInfo>&, bool) const
static Circle2 ExactCircle3(const zeus::CVector2f* a, const zeus::CVector2f* b, const zeus::CVector2f* c)
{
Circle2 ret = {};
zeus::CVector2f d1 = *b - *a;
zeus::CVector2f d2 = *c - *a;
float cross = d1.cross(d2);
zeus::CVector2f magVec(d1.magSquared() * 0.5f, d2.magSquared() * 0.5f);
if (std::fabs(cross) > 0.01f)
{
zeus::CVector2f tmp((d2.y * magVec.x - d1.y * magVec.y) / cross,
(d1.x * magVec.y - d2.x * magVec.x) / cross);
ret.x0_point = *a + tmp;
ret.x8_radiusSq = tmp.magSquared();
}
else
{
ret.x8_radiusSq = FLT_MAX;
}
return ret;
}
void CMapWorld::RecalculateWorldSphere(const CMapWorldInfo&, const IWorld&) const
static bool PointInsideCircle(const zeus::CVector2f& point, const Circle2& circ, float& intersect)
{
intersect = (point - circ.x0_point).magSquared() - circ.x8_radiusSq;
return intersect <= 0.f;
}
static Circle2 UpdateSupport1(int idx, zeus::CVector2f** list, Support& support)
{
Circle2 ret = ExactCircle2(list[support.x4_[0]], list[idx]);
support.x0_ = 2;
support.x4_[1] = idx;
return ret;
}
static Circle2 UpdateSupport2(int idx, zeus::CVector2f** list, Support& support)
{
Circle2 circs[3] = {};
float intersect;
int circIdx = -1;
float minRad = FLT_MAX;
circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]);
if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect))
{
minRad = circs[0].x8_radiusSq;
circIdx = 0;
}
circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]);
if (circs[1].x8_radiusSq < minRad && PointInsideCircle(*list[support.x4_[1]], circs[1], intersect))
{
minRad = circs[1].x8_radiusSq;
circIdx = 1;
}
Circle2 ret = {};
if (circIdx != -1)
{
ret = circs[circIdx];
support.x4_[1 - circIdx] = idx;
}
else
{
ret = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]);
support.x0_ = 3;
support.x4_[2] = idx;
}
return ret;
}
static Circle2 UpdateSupport3(int idx, zeus::CVector2f** list, Support& support)
{
Circle2 circs[6] = {};
float intersect;
int circIdxA = -1;
int circIdxB = -1;
float minRadA = FLT_MAX;
float minRadB = FLT_MAX;
circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]);
if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect))
{
if (PointInsideCircle(*list[support.x4_[2]], circs[0], intersect))
{
minRadA = circs[0].x8_radiusSq;
circIdxA = 0;
}
else
{
minRadB = intersect;
circIdxB = 0;
}
}
else
{
minRadB = intersect;
circIdxB = 0;
}
circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]);
if (circs[1].x8_radiusSq < minRadA)
{
if (PointInsideCircle(*list[support.x4_[0]], circs[1], intersect))
{
if (PointInsideCircle(*list[support.x4_[2]], circs[1], intersect))
{
minRadA = circs[1].x8_radiusSq;
circIdxA = 1;
}
else if (intersect < minRadB)
{
minRadB = intersect;
circIdxB = 1;
}
}
else if (intersect < minRadB)
{
minRadB = intersect;
circIdxB = 1;
}
}
circs[2] = ExactCircle2(list[support.x4_[2]], list[idx]);
if (circs[2].x8_radiusSq < minRadA)
{
if (PointInsideCircle(*list[support.x4_[0]], circs[2], intersect))
{
if (PointInsideCircle(*list[support.x4_[1]], circs[2], intersect))
{
minRadA = circs[2].x8_radiusSq;
circIdxA = 2;
}
else if (intersect < minRadB)
{
minRadB = intersect;
circIdxB = 2;
}
}
else if (intersect < minRadB)
{
minRadB = intersect;
circIdxB = 2;
}
}
circs[3] = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]);
if (circs[3].x8_radiusSq < minRadA)
{
if (PointInsideCircle(*list[support.x4_[2]], circs[3], intersect))
{
minRadA = circs[3].x8_radiusSq;
circIdxA = 3;
}
else if (intersect < minRadB)
{
minRadB = intersect;
circIdxB = 3;
}
}
circs[4] = ExactCircle3(list[support.x4_[0]], list[support.x4_[2]], list[idx]);
if (circs[4].x8_radiusSq < minRadA)
{
if (PointInsideCircle(*list[support.x4_[1]], circs[4], intersect))
{
minRadA = circs[4].x8_radiusSq;
circIdxA = 4;
}
else if (intersect < minRadB)
{
minRadB = intersect;
circIdxB = 4;
}
}
circs[5] = ExactCircle3(list[support.x4_[1]], list[support.x4_[2]], list[idx]);
if (circs[5].x8_radiusSq < minRadA)
{
if (PointInsideCircle(*list[support.x4_[0]], circs[5], intersect))
{
circIdxA = 5;
}
else if (intersect < minRadB)
{
circIdxB = 5;
}
}
if (circIdxA == -1)
circIdxA = circIdxB;
switch (circIdxA)
{
case 0:
support.x0_ = 2;
support.x4_[1] = idx;
break;
case 1:
support.x0_ = 2;
support.x4_[0] = idx;
break;
case 2:
support.x0_ = 2;
support.x4_[0] = support.x4_[2];
support.x4_[1] = idx;
break;
case 3:
support.x4_[2] = idx;
break;
case 4:
support.x4_[1] = idx;
break;
case 5:
support.x4_[0] = idx;
break;
default: break;
}
return circs[circIdxA];
}
typedef Circle2(*FSupport)(int idx, zeus::CVector2f** list, Support& support);
static const FSupport SupportFuncs[] =
{
nullptr,
UpdateSupport1,
UpdateSupport2,
UpdateSupport3
};
static Circle MinCircle(const std::vector<zeus::CVector2f>& coords)
{
Circle2 ret = {};
if (coords.size() >= 1)
{
std::unique_ptr<zeus::CVector2f*[]> randArr(new zeus::CVector2f*[coords.size()]);
for (int i=0 ; i<coords.size() ; ++i)
randArr[i] = const_cast<zeus::CVector2f*>(&coords[i]);
for (int i=coords.size()-1 ; i>=0 ; --i)
{
int shuf = rand() % (i+1);
if (shuf != i)
std::swap(randArr[i], randArr[shuf]);
}
ret = ExactCircle1(randArr[0]);
Support support = {};
support.x0_ = 1;
for (int i=1 ; i<coords.size() ;)
{
bool broke = false;
for (int j=0 ; j<support.x0_ ; ++j)
{
if ((*randArr[i] - *randArr[support.x4_[j]]).magSquared() < 0.01f)
{
broke = true;
break;
}
}
float intersect;
if (!broke && !PointInsideCircle(*randArr[i], ret, intersect))
{
Circle2 circ = SupportFuncs[support.x0_](i, randArr.get(), support);
if (circ.x8_radiusSq > ret.x8_radiusSq)
{
i = 0;
ret = circ;
continue;
}
}
++i;
}
}
return ret;
}
void CMapWorld::RecalculateWorldSphere(const CMapWorldInfo& mwInfo, const IWorld& wld) const
{
std::vector<zeus::CVector2f> coords;
coords.reserve(x0_areas.size() * 8);
float zMin = FLT_MAX;
float zMax = FLT_MIN;
for (int i=0 ; i<x0_areas.size() ; ++i)
{
if (IsMapAreaValid(wld, i, true))
{
const CMapArea* mapa = GetMapArea(i);
if (mapa->GetIsVisibleToAutoMapper(mwInfo.IsWorldVisible(i), mwInfo.IsAreaVisible(i)))
{
zeus::CAABox aabb = mapa->GetBoundingBox().getTransformedAABox(mapa->GetAreaPostTransform(wld, i));
for (int j=0 ; j<8 ; ++j)
{
zeus::CVector3f point = aabb.getPoint(j);
coords.emplace_back(point.x, point.y);
zMin = std::min(point.z, zMin);
zMax = std::max(point.z, zMax);
}
}
}
}
Circle circle = MinCircle(coords);
const_cast<CMapWorld*>(this)->x3c_ = circle.x8_radius;
const_cast<CMapWorld*>(this)->x30_ = zeus::CVector3f(circle.x0_point.x, circle.x0_point.y, (zMin + zMax) * 0.5f);
const_cast<CMapWorld*>(this)->x40_ = (zMax - zMin) * 0.5f;
}
zeus::CVector3f CMapWorld::ConstrainToWorldVolume(const zeus::CVector3f&, const zeus::CVector3f&) const
@ -88,7 +569,9 @@ zeus::CVector3f CMapWorld::ConstrainToWorldVolume(const zeus::CVector3f&, const
void CMapWorld::ClearTraversedFlags() const
{
std::vector<bool>& flags = const_cast<CMapWorld*>(this)->x20_traversed;
for (int i=0 ; i<flags.size() ; ++i)
flags[i] = false;
}
CFactoryFnReturn FMapWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param,

View File

@ -19,54 +19,70 @@ public:
/* skDrawProfileItemNames; */
enum class EMapAreaList
{
Loaded,
Loading,
Unloaded
};
class CMapAreaBFSInfo
{
s32 x0_areaIdx;
s32 x4_depth;
float x8_;
float xc_;
int x0_areaIdx;
int x4_depth;
float x8_surfDrawDepth;
float xc_outlineDrawDepth;
public:
CMapAreaBFSInfo(s32 areaIdx, s32 depth, float a, float b)
: x0_areaIdx(areaIdx), x4_depth(depth), x8_(a), xc_(b) {}
s32 GetAreaIndex() const { return x0_areaIdx; }
s32 GetDepth() const { return x4_depth; }
float GetOutlineDrawDepth() const;
float GetSurfaceDrawDepth() const;
CMapAreaBFSInfo(int areaIdx, int depth, float a, float b)
: x0_areaIdx(areaIdx), x4_depth(depth), x8_surfDrawDepth(a), xc_outlineDrawDepth(b) {}
int GetAreaIndex() const { return x0_areaIdx; }
int GetDepth() const { return x4_depth; }
float GetOutlineDrawDepth() const { return x8_surfDrawDepth; }
float GetSurfaceDrawDepth() const { return xc_outlineDrawDepth; }
};
class CMapObjectSortInfo
{
float x0_zDist;
int x4_areaIdx;
int x8_typeAndIdx;
zeus::CColor xc_surfColor;
zeus::CColor x10_outlineColor;
public:
enum class EObjectCode
{
One = 1 << 16,
Door = 2 << 16,
Three = 3 << 16,
Four = 4 << 16
};
private:
public:
CMapObjectSortInfo(float, int, EObjectCode, int, const zeus::CColor&, const zeus::CColor& );
const zeus::CColor& GetOutlineColor() const;
const zeus::CColor& GetSurfaceColor() const;
u32 GetLocalObjectIndex();
EObjectCode GetObjectCode() const;
u32 GetAreaIndex() const;
float GetZDistance() const;
CMapObjectSortInfo(float zDist, int areaIdx, EObjectCode type, int idx,
const zeus::CColor& surfColor, const zeus::CColor& outlineColor)
: x0_zDist(zDist), x4_areaIdx(areaIdx), x8_typeAndIdx(int(type) | idx),
xc_surfColor(surfColor), x10_outlineColor(outlineColor) {}
const zeus::CColor& GetOutlineColor() const { return x10_outlineColor; }
const zeus::CColor& GetSurfaceColor() const { return xc_surfColor; }
u32 GetLocalObjectIndex() const { return x8_typeAndIdx & 0xffff; }
EObjectCode GetObjectCode() const { return EObjectCode(x8_typeAndIdx & 0xffff0000); }
u32 GetAreaIndex() const { return x4_areaIdx; }
float GetZDistance() const { return x0_zDist; }
};
class CMapAreaData
{
TCachedToken<CMapArea> x0_area;
EMapAreaList x10_list;
CMapAreaData* x14_next;
public:
CMapAreaData(u32, EMapAreaList, CMapAreaData*);
void Lock();
void Unlock();
bool IsLoaded() const;
CMapAreaData(ResId areaRes, EMapAreaList list, CMapAreaData* next);
void Lock() { x0_area.Lock(); }
void Unlock() { x0_area.Unlock(); }
bool IsLoaded() const { return x0_area.IsLoaded(); }
const CMapArea* GetMapArea() const { return x0_area.IsLoaded() ? x0_area.GetObj() : nullptr; }
void GetNextMapAreaData() const;
void GetContainingList() const;
void NextMapAreaData();
void SetContainingList(EMapAreaList);
void SetNextMapArea(CMapAreaData*);
const CMapAreaData* GetNextMapAreaData() const { return x14_next; }
EMapAreaList GetContainingList() const { return x10_list; }
CMapAreaData* NextMapAreaData() { return x14_next; }
void SetContainingList(EMapAreaList list) { x10_list = list; }
void SetNextMapArea(CMapAreaData* next) { x14_next = next; }
};
class CMapWorldDrawParms
@ -126,18 +142,23 @@ public:
private:
std::vector<CMapAreaData> x0_areas;
rstl::reserved_vector<CMapAreaData*, 3> x10_listHeads;
std::vector<bool> x20_traversed;
zeus::CVector3f x30_;
float x3c_ = 0.f;
float x40_ = 0.f;
public:
CMapWorld(CInputStream&);
u32 GetNumAreas() const { return x0_areas.size(); }
const CMapArea* GetMapArea(TAreaId aid) const { return x0_areas[aid].GetMapArea(); }
void IsMapAreaInBFSInfoVector(const CMapAreaData*, const std::vector<CMapAreaBFSInfo>&) const;
const CMapArea* GetMapArea(int aid) const { return x0_areas[aid].GetMapArea(); }
bool IsMapAreaInBFSInfoVector(const CMapAreaData*, const std::vector<CMapAreaBFSInfo>&) const;
void SetWhichMapAreasLoaded(const IWorld&, int start, int count);
bool IsMapAreasStreaming() const;
void MoveMapAreaToList(CMapAreaData*, EMapAreaList);
s32 GetCurrentMapAreaDepth(const IWorld&, TAreaId) const;
std::vector<TAreaId> GetVisibleAreas(const IWorld&, const CMapWorldInfo&) const;
s32 GetCurrentMapAreaDepth(const IWorld&, int areaIdx) const;
std::vector<int> GetVisibleAreas(const IWorld&, const CMapWorldInfo&) const;
void Draw(const CMapWorldDrawParms&, int, int, float, float, bool) const;
void DoBFS(const IWorld&, TAreaId, int, float, float, bool, std::vector<CMapAreaBFSInfo>&) const;
void DoBFS(const IWorld&, int, int, float, float, bool, std::vector<CMapAreaBFSInfo>&) const;
bool IsMapAreaValid(const IWorld&, int, bool) const;
void DrawAreas(const CMapWorldDrawParms&, int, const std::vector<CMapAreaBFSInfo>&, bool) const;
void RecalculateWorldSphere(const CMapWorldInfo&, const IWorld&) const;

View File

@ -1,10 +1,34 @@
#include "CMappableObject.hpp"
#include "GameGlobalObjects.hpp"
#include "CMapWorldInfo.hpp"
#include "CSimplePool.hpp"
#include "CToken.hpp"
#include "Graphics/CTexture.hpp"
namespace urde
{
const zeus::CVector3f CMappableObject::skDoorVerts[8] = {};
static const u32 DoorIndices[] =
{
6, 4, 2, 0,
3, 1, 7, 5,
1, 0, 5, 4,
7, 6, 3, 2,
3, 2, 1, 0,
5, 4, 7, 6
};
CMappableObject::CMappableObject(const void* buf)
{
athena::io::MemoryReader r(buf, 64);
x0_type = EMappableObjectType(r.readUint32Big());
x4_ = r.readUint32Big();
x8_objId = r.readUint32Big();
xc_ = r.readUint32Big();
x10_transform.read34RowMajor(r);
}
zeus::CTransform CMappableObject::AdjustTransformForType()
{
const float doorCenterX = g_tweakAutoMapper->GetDoorCenter().x;
@ -14,7 +38,7 @@ zeus::CTransform CMappableObject::AdjustTransformForType()
zeus::CTransform orientation;
orientation.origin = {-1.4f*doorCenterX, 0.0f, 0.0f};
orientation.rotateLocalZ(zeus::degToRad(90.0f));
return (x10_transform * orientation) * zeus::CTransform::Scale(zeus::CVector3f{1.5f});
return (x10_transform * orientation) * zeus::CTransform::Scale(zeus::CVector3f{1.5f});
}
else if (x0_type == EMappableObjectType::BigDoor2)
{
@ -40,14 +64,14 @@ zeus::CTransform CMappableObject::AdjustTransformForType()
return x10_transform * orientation;
}
else if ((u32(x0_type) - u32(EMappableObjectType::IceDoorFloor2)) <= u32(EMappableObjectType::ShieldDoor)
|| x0_type == EMappableObjectType::Fifteen)
|| x0_type == EMappableObjectType::PlasmaDoorFloor2)
{
zeus::CTransform orientation;
orientation.origin = {-0.49f * doorCenterX, 0.f, -1.f * doorCenterZ};
orientation.rotateLocalY(zeus::degToRad(90.f));
return x10_transform * orientation;
}
else if (x0_type >= EMappableObjectType::BlueDoor || x0_type <= EMappableObjectType::Fifteen)
else if (x0_type >= EMappableObjectType::BlueDoor || x0_type <= EMappableObjectType::PlasmaDoorFloor2)
{
zeus::CMatrix4f tmp = x10_transform.toMatrix4f().transposed();
return zeus::CTransform::Translate(tmp.m[1][0], tmp.m[2][1], tmp[3][2]);
@ -55,35 +79,189 @@ zeus::CTransform CMappableObject::AdjustTransformForType()
return x10_transform;
}
void CMappableObject::PostConstruct(const void *)
std::pair<zeus::CColor, zeus::CColor>
CMappableObject::GetDoorColors(int curAreaId, const CMapWorldInfo& mwInfo, float alpha) const
{
#if __BYTE_ORDER__!= __ORDER_BIG_ENDIAN__
x0_type = EMappableObjectType(hecl::SBig(u32(x0_type)));
x4_ = hecl::SBig(x4_);
x8_.id = hecl::SBig(x8_.id);
xc_ = hecl::SBig(xc_);
for (u32 i = 0 ; i<3 ; i++)
zeus::CColor color = {1.f, 0.f, 1.f, 1.f};
if (x8_objId.AreaNum() == curAreaId)
{
for (u32 j = 0 ; j<4 ; j++)
if (mwInfo.IsDoorVisited(x8_objId) && x0_type == EMappableObjectType::ShieldDoor)
{
u32* tmp = reinterpret_cast<u32*>(&x10_transform.basis.m[i][j]);
*tmp = hecl::SBig(*tmp);
color = g_tweakAutoMapper->GetDoorColor(0);
}
else
{
int colorIdx = 0;
switch (x0_type)
{
case EMappableObjectType::ShieldDoor:
colorIdx = 1;
break;
case EMappableObjectType::IceDoor:
case EMappableObjectType::IceDoorCeiling:
case EMappableObjectType::IceDoorFloor:
case EMappableObjectType::IceDoorFloor2:
colorIdx = 2;
break;
case EMappableObjectType::WaveDoor:
case EMappableObjectType::WaveDoorCeiling:
case EMappableObjectType::WaveDoorFloor:
case EMappableObjectType::WaveDoorFloor2:
colorIdx = 3;
break;
case EMappableObjectType::PlasmaDoor:
case EMappableObjectType::PlasmaDoorCeiling:
case EMappableObjectType::PlasmaDoorFloor:
case EMappableObjectType::PlasmaDoorFloor2:
colorIdx = 4;
default: break;
}
color = g_tweakAutoMapper->GetDoorColor(colorIdx);
}
}
else if (mwInfo.IsDoorVisited(x8_objId))
{
color = g_tweakAutoMapper->GetOpenDoorColor();
}
else
{
color = zeus::CColor::skClear;
}
#endif
x10_transform.origin.x = x10_transform.basis.m[0][3];
x10_transform.origin.y = x10_transform.basis.m[1][3];
x10_transform.origin.z = x10_transform.basis.m[2][3];
x10_transform.basis.transpose();
color.a *= alpha;
return {color, zeus::CColor(std::min(1.4f * color.r, 1.f),
std::min(1.4f * color.g, 1.f),
std::min(1.4f * color.b, 1.f),
std::min(1.4f * color.a, 1.f))};
}
void CMappableObject::PostConstruct(const void *)
{
x10_transform = AdjustTransformForType();
}
zeus::CVector3f CMappableObject::BuildSurfaceCenterPoint(s32) const
void CMappableObject::Draw(int curArea, const CMapWorldInfo& mwInfo,
float alpha, bool needsVtxLoad) const
{
if (IsDoorType(x0_type))
{
std::pair<zeus::CColor, zeus::CColor> colors = GetDoorColors(curArea, mwInfo, alpha);
for (int s=0 ; s<6 ; ++s)
{
DoorSurface& ds = const_cast<DoorSurface&>(*m_doorSurface);
ds.m_surface.draw(colors.first, s * 4, 4);
CLineRenderer& line = ds.m_outline;
const u32* baseIdx = &DoorIndices[s * 4];
line.Reset();
line.AddVertex(skDoorVerts[baseIdx[0]], colors.second, 1.f);
line.AddVertex(skDoorVerts[baseIdx[1]], colors.second, 1.f);
line.AddVertex(skDoorVerts[baseIdx[2]], colors.second, 1.f);
line.AddVertex(skDoorVerts[baseIdx[3]], colors.second, 1.f);
line.Render();
}
}
else
{
ResId iconRes;
zeus::CColor iconColor = zeus::CColor::skWhite;
switch (x0_type)
{
case EMappableObjectType::DownArrowYellow:
iconRes = g_tweakPlayerRes->x10_minesBreakFirstTopIcon;
iconColor = zeus::CColor{1.f, 1.f, 0.588f, 1.f};
break;
case EMappableObjectType::UpArrowYellow:
iconRes = g_tweakPlayerRes->x14_minesBreakFirstBottomIcon;
iconColor = zeus::CColor{1.f, 1.f, 0.588f, 1.f};
break;
case EMappableObjectType::DownArrowGreen:
iconRes = g_tweakPlayerRes->x10_minesBreakFirstTopIcon;
iconColor = zeus::CColor{0.392f, 1.f, 0.588f, 1.f};
break;
case EMappableObjectType::UpArrowGreen:
iconRes = g_tweakPlayerRes->x14_minesBreakFirstBottomIcon;
iconColor = zeus::CColor{0.392f, 1.f, 0.588f, 1.f};
break;
case EMappableObjectType::DownArrowRed:
iconRes = g_tweakPlayerRes->x10_minesBreakFirstTopIcon;
iconColor = zeus::CColor{1.f, 0.392f, 0.588f, 1.f};
break;
case EMappableObjectType::UpArrowRed:
iconRes = g_tweakPlayerRes->x14_minesBreakFirstBottomIcon;
iconColor = zeus::CColor{1.f, 0.392f, 0.588f, 1.f};
break;
case EMappableObjectType::SaveStation:
iconRes = g_tweakPlayerRes->x4_saveStationIcon;
break;
case EMappableObjectType::MissileStation:
iconRes = g_tweakPlayerRes->x8_missileStationIcon;
break;
default:
iconRes = g_tweakPlayerRes->xc_elevatorIcon;
break;
}
iconColor.a *= alpha;
TLockedToken<CTexture> tex = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), iconRes});
if (!m_texQuadFilter || m_texQuadFilter->GetTex().GetObj() != tex.GetObj())
const_cast<CMappableObject*>(this)->m_texQuadFilter.emplace(CCameraFilterPass::EFilterType::Blend, tex);
CTexturedQuadFilter::Vert verts[4] =
{
{{-2.6f, 0.f, 2.6f}, {0.f, 1.f}},
{{-2.6f, 0.f, -2.6f}, {0.f, 0.f}},
{{2.6f, 0.f, 2.6f}, {1.f, 1.f}},
{{2.6f, 0.f, -2.6f}, {1.f, 0.f}}
};
const_cast<CMappableObject*>(this)->m_texQuadFilter->drawVerts(iconColor, verts);
}
}
void CMappableObject::DrawDoorSurface(int curArea, const CMapWorldInfo& mwInfo,
float alpha, int surfIdx, bool needsVtxLoad) const
{
std::pair<zeus::CColor, zeus::CColor> colors = GetDoorColors(curArea, mwInfo, alpha);
DoorSurface& ds = const_cast<DoorSurface&>(*m_doorSurface);
ds.m_surface.draw(colors.first, surfIdx * 4, 4);
CLineRenderer& line = ds.m_outline;
const u32* baseIdx = &DoorIndices[surfIdx * 4];
line.Reset();
line.AddVertex(skDoorVerts[baseIdx[0]], colors.second, 1.f);
line.AddVertex(skDoorVerts[baseIdx[1]], colors.second, 1.f);
line.AddVertex(skDoorVerts[baseIdx[2]], colors.second, 1.f);
line.AddVertex(skDoorVerts[baseIdx[3]], colors.second, 1.f);
line.Render();
}
zeus::CVector3f CMappableObject::BuildSurfaceCenterPoint(int surfIdx) const
{
const zeus::CVector3f& doorCenter = g_tweakAutoMapper->GetDoorCenter();
switch (surfIdx)
{
case 0:
return x10_transform * zeus::CVector3f::skZero;
case 1:
return x10_transform * zeus::CVector3f{0.f, 0.f, 2.f * doorCenter.x};
case 2:
return x10_transform * zeus::CVector3f{0.f, -doorCenter.y, 0.f};
case 3:
return x10_transform * zeus::CVector3f{0.f, doorCenter.y, 0.f};
case 4:
return x10_transform * zeus::CVector3f{-doorCenter.x, 0.f, 0.f};
case 5:
return x10_transform * zeus::CVector3f{doorCenter.x, 0.f, 0.f};
default: break;
}
return {};
}
boo::GraphicsDataToken CMappableObject::g_gfxToken = {};
boo::IGraphicsBufferS* CMappableObject::g_doorVbo;
boo::IGraphicsBufferS* CMappableObject::g_doorIbo;
void CMappableObject::ReadAutoMapperTweaks(const ITweakAutoMapper& tweaks)
{
const zeus::CVector3f& center = tweaks.GetDoorCenter();
@ -97,5 +275,17 @@ void CMappableObject::ReadAutoMapperTweaks(const ITweakAutoMapper& tweaks)
doorVerts[5].assign(.2f * -center.z, -center.y, 2.f * center.x);
doorVerts[6].assign(.2f * -center.z, center.y, 0.f);
doorVerts[7].assign(.2f * -center.z, center.y, 2.f * center.x);
g_gfxToken = CGraphics::CommitResources([](boo::IGraphicsDataFactory::Context& ctx)
{
g_doorVbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, skDoorVerts, 16, 8);
g_doorIbo = ctx.newStaticBuffer(boo::BufferUse::Index, DoorIndices, 4, 24);
return true;
});
}
void CMappableObject::Shutdown()
{
g_gfxToken.doDestroy();
}
}

View File

@ -5,12 +5,22 @@
#include "zeus/CAABox.hpp"
#include "zeus/CTransform.hpp"
#include "GameGlobalObjects.hpp"
#include "Graphics/Shaders/CMapSurfaceShader.hpp"
#include "Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Graphics/CLineRenderer.hpp"
namespace urde
{
class CStateManager;
class CMapWorldInfo;
class CMappableObject
{
friend class CMapArea;
static boo::GraphicsDataToken g_gfxToken;
static boo::IGraphicsBufferS* g_doorVbo;
static boo::IGraphicsBufferS* g_doorIbo;
public:
enum class EMappableObjectType
{
@ -29,7 +39,7 @@ public:
PlasmaDoorFloor = 12,
IceDoorFloor2 = 13,
WaveDoorFloor2 = 14,
Fifteen = 15,
PlasmaDoorFloor2 = 15,
DownArrowYellow = 27, /* Maintenance Tunnel */
UpArrowYellow = 28, /* Phazon Processing Center */
DownArrowGreen = 29, /* Elevator A */
@ -46,25 +56,44 @@ private:
EMappableObjectType x0_type;
u32 x4_;
TEditorId x8_;
TEditorId x8_objId;
u32 xc_;
zeus::CTransform x10_transform;
struct DoorSurface
{
CMapSurfaceShader m_surface;
CLineRenderer m_outline;
DoorSurface(boo::IGraphicsDataFactory::Context& ctx)
: m_surface(ctx, g_doorVbo, g_doorIbo),
m_outline(ctx, CLineRenderer::EPrimitiveMode::LineStrip, 5, nullptr, false)
{}
};
std::experimental::optional<DoorSurface> m_doorSurface;
std::experimental::optional<CTexturedQuadFilter> m_texQuadFilter;
zeus::CTransform AdjustTransformForType();
std::pair<zeus::CColor, zeus::CColor> GetDoorColors(int idx, const CMapWorldInfo& mwInfo, float alpha) const;
public:
CMappableObject(const void* buf);
CMappableObject(CMappableObject&&) = default;
void PostConstruct(const void*);
const zeus::CTransform& GetTransform() const;
EMappableObjectType GetType() const;
void Draw(int, const CStateManager&, float, bool) const;
void DrawDoorSurface(int, const CStateManager&, float, int, bool) const;
zeus::CVector3f BuildSurfaceCenterPoint(s32) const;
bool IsDoorConnectedToArea(s32, const CStateManager&) const;
const zeus::CTransform& GetTransform() const { return x10_transform; }
EMappableObjectType GetType() const { return x0_type; }
void Draw(int, const CMapWorldInfo&, float, bool) const;
void DrawDoorSurface(int curArea, const CMapWorldInfo& mwInfo, float alpha,
int surfIdx, bool needsVtxLoad) const;
zeus::CVector3f BuildSurfaceCenterPoint(int surfIdx) const;
bool IsDoorConnectedToArea(int idx, const CStateManager&) const;
bool IsDoorConnectedToVisitedArea(const CStateManager&) const;
bool GetIsVisibleToAutoMapper(bool) const;
bool GetIsSeen() const;
void ReadAutoMapperTweaks(const ITweakAutoMapper&);
static void ReadAutoMapperTweaks(const ITweakAutoMapper&);
static bool GetTweakIsMapVisibilityCheat();
static bool IsDoorType(EMappableObjectType);
static bool IsDoorType(EMappableObjectType type) { return type >= EMappableObjectType::BlueDoor &&
type <= EMappableObjectType::PlasmaDoorFloor2; }
static void Shutdown();
};
}
#endif // __URDE_CMAPPABLEOBJECT_HPP__

View File

@ -33,6 +33,38 @@ struct SDrawUniform
zeus::CColor moduColor;
};
CLineRenderer::CLineRenderer(boo::IGraphicsDataFactory::Context& ctx,
EPrimitiveMode mode, u32 maxVerts, boo::ITexture* texture, bool additive)
: m_mode(mode), m_maxVerts(maxVerts)
{
if (maxVerts < 2)
{
LineRendererLog.report(logvisor::Fatal, _S("maxVerts < 2, maxVerts = %i"), maxVerts);
return;
}
m_textured = texture != nullptr;
u32 maxTriVerts;
switch (mode)
{
case EPrimitiveMode::Lines:
maxTriVerts = maxVerts * 3;
break;
case EPrimitiveMode::LineStrip:
maxTriVerts = maxVerts * 2;
break;
case EPrimitiveMode::LineLoop:
maxTriVerts = maxVerts * 2 + 2;
break;
}
m_vertBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex,
texture ? sizeof(SDrawVertTex) : sizeof(SDrawVertNoTex),
maxTriVerts);
m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SDrawUniform), 1);
CLineRendererShaders::BuildShaderDataBinding(ctx, *this, texture, additive);
}
CLineRenderer::CLineRenderer(EPrimitiveMode mode, u32 maxVerts, boo::ITexture* texture, bool additive)
: m_mode(mode), m_maxVerts(maxVerts)
{

View File

@ -44,7 +44,10 @@ public:
boo::IGraphicsBufferD* m_uniformBuf;
boo::IShaderDataBinding* m_shaderBind = nullptr;
CLineRenderer(boo::IGraphicsDataFactory::Context& ctx,
EPrimitiveMode mode, u32 maxVerts, boo::ITexture* texture, bool additive);
CLineRenderer(EPrimitiveMode mode, u32 maxVerts, boo::ITexture* texture, bool additive);
CLineRenderer(CLineRenderer&&) = default;
void Reset();
void AddVertex(const zeus::CVector3f& position, const zeus::CColor& color, float width,

View File

@ -13,7 +13,8 @@ if(WIN32)
Shaders/CFogVolumePlaneShaderHLSL.cpp
Shaders/CFogVolumeFilterHLSL.cpp
Shaders/CEnergyBarShaderHLSL.cpp
Shaders/CRadarPaintShaderHLSL.cpp)
Shaders/CRadarPaintShaderHLSL.cpp
Shaders/CMapSurfaceShaderHLSL.cpp)
elseif(BOO_HAS_METAL)
set(PLAT_SRCS
Shaders/CLineRendererShadersMetal.cpp
@ -29,7 +30,8 @@ elseif(BOO_HAS_METAL)
Shaders/CFogVolumePlaneShaderMetal.cpp
Shaders/CFogVolumeFilterMetal.cpp
Shaders/CEnergyBarShaderMetal.cpp
Shaders/CRadarPaintShaderMetal.cpp)
Shaders/CRadarPaintShaderMetal.cpp
Shaders/CMapSurfaceShaderMetal.cpp)
endif()
set(GRAPHICS_SOURCES
@ -39,7 +41,7 @@ set(GRAPHICS_SOURCES
CDrawable.hpp CDrawable.cpp
CDrawablePlaneObject.hpp CDrawablePlaneObject.cpp
CLineRenderer.hpp CLineRenderer.cpp
CMetroidModelInstance.hpp CMetroidModelInstance.cpp
CMetroidModelInstance.hpp
CLight.hpp CLight.cpp
CTexture.hpp CTextureBoo.cpp
CModel.hpp CModelBoo.cpp
@ -67,6 +69,7 @@ set(GRAPHICS_SOURCES
Shaders/CFogVolumeFilter.hpp Shaders/CFogVolumeFilter.cpp Shaders/CFogVolumeFilterGLSL.cpp
Shaders/CEnergyBarShader.hpp Shaders/CEnergyBarShader.cpp Shaders/CEnergyBarShaderGLSL.cpp
Shaders/CRadarPaintShader.hpp Shaders/CRadarPaintShader.cpp Shaders/CRadarPaintShaderGLSL.cpp
Shaders/CMapSurfaceShader.hpp Shaders/CMapSurfaceShader.cpp Shaders/CMapSurfaceShaderGLSL.cpp
${PLAT_SRCS})
runtime_add_list(Graphics GRAPHICS_SOURCES)

View File

@ -1,26 +0,0 @@
#include "CMetroidModelInstance.hpp"
#include "CModel.hpp"
namespace urde
{
#if 0
CMetroidModelInstance::CMetroidModelInstance(CBooModel* inst)
: x0_visorFlags(0), m_instance(inst)
{
x34_aabb = inst->x20_aabb;
}
CMetroidModelInstance::CMetroidModelInstance
(const void* modelHeader, CBooModel* inst)
: x0_visorFlags(hecl::SBig(*static_cast<const u32*>(modelHeader))), m_instance(inst)
{
athena::io::MemoryReader r(static_cast<const u8*>(modelHeader) + 4, INT32_MAX);
x4_xf.read34RowMajor(r);
x34_aabb.readBoundingBoxBig(r);
}
CMetroidModelInstance::~CMetroidModelInstance() {}
#endif
}

View File

@ -22,9 +22,8 @@ class CMetroidModelInstance
std::vector<CBooSurface> m_surfaces;
std::unique_ptr<CBooModel> m_instance;
public:
//CMetroidModelInstance(CBooModel* inst);
//CMetroidModelInstance(const void* modelHeader, CBooModel* inst);
//~CMetroidModelInstance();
CMetroidModelInstance() = default;
CMetroidModelInstance(CMetroidModelInstance&&) = default;
};
}

View File

@ -132,7 +132,7 @@ CLineRendererShaders::IDataBindingFactory* CLineRendererShaders::Initialize(boo:
m_texAlpha = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, 1, TexNames, 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::None,
true, true, false, boo::CullMode::None);
false, true, false, boo::CullMode::None);
m_texAdditive = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, 1, TexNames, 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
boo::Primitive::TriStrips, boo::ZTest::None,
@ -140,7 +140,7 @@ CLineRendererShaders::IDataBindingFactory* CLineRendererShaders::Initialize(boo:
m_noTexAlpha = ctx.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, 1, nullptr, 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::None,
true, true, false, boo::CullMode::None);
false, true, false, boo::CullMode::None);
m_noTexAdditive = ctx.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, 1, nullptr, 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
boo::Primitive::TriStrips, boo::ZTest::None,

View File

@ -0,0 +1,28 @@
#include "CMapSurfaceShader.hpp"
namespace urde
{
CMapSurfaceShader::CMapSurfaceShader(boo::IGraphicsDataFactory::Context& ctx,
boo::IGraphicsBufferS* vbo,
boo::IGraphicsBufferS* ibo)
: m_vbo(vbo), m_ibo(ibo)
{
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1);
m_dataBind = TShader<CMapSurfaceShader>::BuildShaderDataBinding(ctx, *this);
}
void CMapSurfaceShader::draw(const zeus::CColor& color, u32 start, u32 count)
{
m_uniform.mtx = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f();
m_uniform.color = color;
m_uniBuf->load(&m_uniform, sizeof(m_uniform));
CGraphics::SetShaderDataBinding(m_dataBind);
CGraphics::DrawArrayIndexed(start, count);
}
URDE_SPECIALIZE_SHADER(CMapSurfaceShader)
void CMapSurfaceShader::Shutdown() {}
}

View File

@ -0,0 +1,39 @@
#ifndef __URDE_CMAPSURFACESHADER_HPP__
#define __URDE_CMAPSURFACESHADER_HPP__
#include "TShader.hpp"
namespace urde
{
class CMapSurfaceShader
{
friend struct CMapSurfaceShaderGLDataBindingFactory;
friend struct CMapSurfaceShaderVulkanDataBindingFactory;
friend struct CMapSurfaceShaderMetalDataBindingFactory;
friend struct CMapSurfaceShaderD3DDataBindingFactory;
struct Uniform
{
zeus::CMatrix4f mtx;
zeus::CColor color;
};
Uniform m_uniform;
boo::IGraphicsBufferD* m_uniBuf;
boo::IGraphicsBufferS* m_vbo;
boo::IGraphicsBufferS* m_ibo;
boo::IShaderDataBinding* m_dataBind;
public:
CMapSurfaceShader(boo::IGraphicsDataFactory::Context& ctx, boo::IGraphicsBufferS* vbo,
boo::IGraphicsBufferS* ibo);
void draw(const zeus::CColor& color, u32 start, u32 count);
using _CLS = CMapSurfaceShader;
#include "TShaderDecl.hpp"
};
}
#endif // __URDE_CMAPSURFACESHADER_HPP__

View File

@ -0,0 +1,115 @@
#include "CMapSurfaceShader.hpp"
#include "TShader.hpp"
namespace urde
{
static const char* VS =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
"layout(location=0) in vec4 posIn;\n"
"\n"
"UBINDING0 uniform MapSurfaceUniform\n"
"{\n"
" mat4 xf;\n"
" vec4 color;\n"
"};\n"
"\n"
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
"};\n"
"\n"
"SBINDING(0) out VertToFrag vtf;\n"
"void main()\n"
"{\n"
" vtf.color = color;\n"
" gl_Position = xf * vec4(posIn.xyz, 1.0);\n"
"}\n";
static const char* FS =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
"};\n"
"\n"
"SBINDING(0) in VertToFrag vtf;\n"
"layout(location=0) out vec4 colorOut;\n"
"void main()\n"
"{\n"
" colorOut = vtf.color;\n"
"}\n";
URDE_DECL_SPECIALIZE_SHADER(CMapSurfaceShader)
static boo::IVertexFormat* s_VtxFmt = nullptr;
static boo::IShaderPipeline* s_Pipeline = nullptr;
struct CMapSurfaceShaderGLDataBindingFactory : TShader<CMapSurfaceShader>::IDataBindingFactory
{
boo::IShaderDataBinding* BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx,
CMapSurfaceShader& filter)
{
boo::GLDataFactory::Context& cctx = static_cast<boo::GLDataFactory::Context&>(ctx);
const boo::VertexElementDescriptor VtxVmt[] =
{
{filter.m_vbo, filter.m_ibo, boo::VertexSemantic::Position4}
};
boo::IVertexFormat* vtxFmt = ctx.newVertexFormat(1, VtxVmt);
boo::IGraphicsBuffer* bufs[] = {filter.m_uniBuf};
boo::PipelineStage stages[] = {boo::PipelineStage::Vertex};
filter.m_dataBind = cctx.newShaderDataBinding(s_Pipeline,
vtxFmt, filter.m_vbo, nullptr, filter.m_ibo,
1, bufs, stages, nullptr, nullptr, 0, nullptr, nullptr, nullptr);
return filter.m_dataBind;
}
};
#if BOO_HAS_VULKAN
struct CMapSurfaceShaderVulkanDataBindingFactory : TShader<CMapSurfaceShader>::IDataBindingFactory
{
boo::IShaderDataBinding* BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx,
CMapSurfaceShader& filter)
{
boo::VulkanDataFactory::Context& cctx = static_cast<boo::VulkanDataFactory::Context&>(ctx);
boo::IGraphicsBuffer* bufs[] = {filter.m_uniBuf};
filter.m_dataBind = cctx.newShaderDataBinding(s_Pipeline, s_VtxFmt,
filter.m_vbo, nullptr, filter.m_ibo, 1, bufs,
nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr);
return filter.m_dataBind;
}
};
#endif
TShader<CMapSurfaceShader>::IDataBindingFactory*
CMapSurfaceShader::Initialize(boo::GLDataFactory::Context& ctx)
{
const char* uniNames[] = {"MapSurfaceUniform"};
s_Pipeline = ctx.newShaderPipeline(VS, FS, 0, nullptr, 1, uniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true,
false, boo::CullMode::Backface);
return new CMapSurfaceShaderGLDataBindingFactory;
}
#if BOO_HAS_VULKAN
TShader<CMapSurfaceShader>::IDataBindingFactory*
CMapSurfaceShader::Initialize(boo::VulkanDataFactory::Context& ctx)
{
const boo::VertexElementDescriptor VtxVmt[] =
{
{nullptr, nullptr, boo::VertexSemantic::Position4}
};
s_VtxFmt = ctx.newVertexFormat(1, VtxVmt);
s_Pipeline = ctx.newShaderPipeline(VS, FS, s_VtxFmt, boo::BlendFactor::SrcAlpha,
boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips,
boo::ZTest::LEqual, false, true, false, boo::CullMode::Backface);
return new CMapSurfaceShaderVulkanDataBindingFactory;
}
#endif
}

View File

@ -0,0 +1,79 @@
#include "CMapSurfaceShader.hpp"
#include "TShader.hpp"
namespace urde
{
static const char* VS =
"struct VertData\n"
"{\n"
" float4 posIn : POSITION;\n"
"};\n"
"\n"
"cbuffer MapSurfaceUniform : register(b0)\n"
"{\n"
" float4x4 xf;\n"
" float4 color;\n"
"};\n"
"\n"
"struct VertToFrag\n"
"{\n"
" float4 position : SV_Position;\n"
" float4 color : COLOR;\n"
"};\n"
"\n"
"VertToFrag main(in VertData v)\n"
"{\n"
" VertToFrag vtf;\n"
" vtf.color = color;\n"
" vtf.position = mul(xf * float4(v.posIn.xyz, 1.0));\n"
" return vtf;\n"
"}\n";
static const char* FS =
"struct VertToFrag\n"
"{\n"
" float4 position : SV_Position;\n"
" float4 color : COLOR;\n"
"};\n"
"\n"
"float4 main(in VertToFrag vtf) : SV_Target0\n"
"{\n"
" return vtf.color;\n"
"}\n";
URDE_DECL_SPECIALIZE_SHADER(CMapSurfaceShader)
static boo::IVertexFormat* s_VtxFmt = nullptr;
static boo::IShaderPipeline* s_Pipeline = nullptr;
struct CMapSurfaceShaderD3DDataBindingFactory : TShader<CMapSurfaceShader>::IDataBindingFactory
{
boo::IShaderDataBinding* BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx,
CMapSurfaceShader& filter)
{
boo::ID3DDataFactory::Context& cctx = static_cast<boo::ID3DDataFactory::Context&>(ctx);
boo::IGraphicsBuffer* bufs[] = {filter.m_uniBuf};
filter.m_dataBind = cctx.newShaderDataBinding(s_Pipeline, s_VtxFmt,
filter.m_vbo, nullptr, filter.m_ibo, 1, bufs,
nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr);
return filter.m_dataBind;
}
};
TShader<CMapSurfaceShader>::IDataBindingFactory*
CMapSurfaceShader::Initialize(boo::ID3DDataFactory::Context& ctx)
{
const boo::VertexElementDescriptor VtxVmt[] =
{
{nullptr, nullptr, boo::VertexSemantic::Position4}
};
s_VtxFmt = ctx.newVertexFormat(1, VtxVmt);
s_Pipeline = ctx.newShaderPipeline(VS, FS, nullptr, nullptr, nullptr, s_VtxFmt,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips,
boo::ZTest::LEqual, false, true, false, boo::CullMode::Backface);
return new CMapSurfaceShaderD3DDataBindingFactory;
}
}

View File

@ -0,0 +1,83 @@
#include "CMapSurfaceShader.hpp"
#include "TShader.hpp"
namespace urde
{
static const char* VS =
"#include <metal_stdlib>\n"
"using namespace metal;\n"
"struct VertData\n"
"{\n"
" float4 posIn [[ attribute(0) ]];\n"
"};\n"
"\n"
"struct MapSurfaceUniform\n"
"{\n"
" float4x4 xf;\n"
" float4 color;\n"
"};\n"
"\n"
"struct VertToFrag\n"
"{\n"
" float4 position [[ position ]];\n"
" float4 color;\n"
"};\n"
"\n"
"vertex VertToFrag vmain(VertData v [[ stage_in ]], constant MapSurfaceUniform& msu [[ buffer(2) ]])\n"
"{\n"
" VertToFrag vtf;\n"
" vtf.color = msu.color;\n"
" vtf.position = msu.xf * float4(v.posIn.xyz, 1.0);\n"
" return vtf;\n"
"}\n";
static const char* FS =
"#include <metal_stdlib>\n"
"using namespace metal;\n"
"struct VertToFrag\n"
"{\n"
" float4 position [[ position ]];\n"
" float4 color;\n"
"};\n"
"\n"
"fragment float4 fmain(VertToFrag vtf [[ stage_in ]])\n"
"{\n"
" return vtf.color;\n"
"}\n";
URDE_DECL_SPECIALIZE_SHADER(CMapSurfaceShader)
static boo::IVertexFormat* s_VtxFmt = nullptr;
static boo::IShaderPipeline* s_Pipeline = nullptr;
struct CMapSurfaceShaderMetalDataBindingFactory : TShader<CMapSurfaceShader>::IDataBindingFactory
{
boo::IShaderDataBinding* BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx,
CMapSurfaceShader& filter)
{
boo::MetalDataFactory::Context& cctx = static_cast<boo::MetalDataFactory::Context&>(ctx);
boo::IGraphicsBuffer* bufs[] = {filter.m_uniBuf};
filter.m_dataBind = cctx.newShaderDataBinding(s_Pipeline, s_VtxFmt,
filter.m_vbo, nullptr, filter.m_ibo, 1, bufs,
nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr);
return filter.m_dataBind;
}
};
TShader<CMapSurfaceShader>::IDataBindingFactory*
CMapSurfaceShader::Initialize(boo::MetalDataFactory::Context& ctx)
{
const boo::VertexElementDescriptor VtxVmt[] =
{
{nullptr, nullptr, boo::VertexSemantic::Position4}
};
s_VtxFmt = ctx.newVertexFormat(1, VtxVmt);
s_Pipeline = ctx.newShaderPipeline(VS, FS, s_VtxFmt, CGraphics::g_ViewportSamples,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips,
boo::ZTest::LEqual, false, true, false, boo::CullMode::Backface);
return new CMapSurfaceShaderMetalDataBindingFactory;
}
}

View File

@ -86,6 +86,7 @@ void CTweaks::RegisterTweaks()
tag = factory.GetResourceIdByName("AutoMapper");
strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag));
g_tweakAutoMapper = new DataSpec::DNAMP1::CTweakAutoMapper(*strm);
CMappableObject::ReadAutoMapperTweaks(*g_tweakAutoMapper);
/* Gui */
tag = factory.GetResourceIdByName("Gui");

View File

@ -10,6 +10,7 @@
#include "Graphics/Shaders/CTextSupportShader.hpp"
#include "Graphics/Shaders/CEnergyBarShader.hpp"
#include "Graphics/Shaders/CRadarPaintShader.hpp"
#include "Graphics/Shaders/CMapSurfaceShader.hpp"
#include "Character/CCharLayoutInfo.hpp"
#include "Audio/CStreamAudioManager.hpp"
#include "CGBASupport.hpp"
@ -27,6 +28,7 @@ URDE_DECL_SPECIALIZE_SHADER(CFogVolumePlaneShader)
URDE_DECL_SPECIALIZE_SHADER(CFogVolumeFilter)
URDE_DECL_SPECIALIZE_SHADER(CEnergyBarShader)
URDE_DECL_SPECIALIZE_SHADER(CRadarPaintShader)
URDE_DECL_SPECIALIZE_SHADER(CMapSurfaceShader)
URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CColoredQuadFilter)
URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CTexturedQuadFilter)
URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CTexturedQuadFilterAlpha)
@ -219,6 +221,7 @@ CMain::BooSetter::BooSetter(boo::IGraphicsDataFactory* factory,
TShader<CFogVolumeFilter>::Initialize();
TShader<CEnergyBarShader>::Initialize();
TShader<CRadarPaintShader>::Initialize();
TShader<CMapSurfaceShader>::Initialize();
TMultiBlendShader<CColoredQuadFilter>::Initialize();
TMultiBlendShader<CTexturedQuadFilter>::Initialize();
TMultiBlendShader<CTexturedQuadFilterAlpha>::Initialize();
@ -334,6 +337,7 @@ void CMain::ShutdownSubsystems()
CAnimData::FreeCache();
CMemoryCardSys::Shutdown();
CModelShaders::Shutdown();
CMappableObject::Shutdown();
}
void CMain::Shutdown()
@ -349,6 +353,7 @@ void CMain::Shutdown()
TShader<CFogVolumeFilter>::Shutdown();
TShader<CEnergyBarShader>::Shutdown();
TShader<CRadarPaintShader>::Shutdown();
TShader<CMapSurfaceShader>::Shutdown();
TMultiBlendShader<CColoredQuadFilter>::Shutdown();
TMultiBlendShader<CTexturedQuadFilter>::Shutdown();
TMultiBlendShader<CTexturedQuadFilterAlpha>::Shutdown();

View File

@ -25,7 +25,7 @@ public:
virtual ResId IGetSaveWorldAssetId() const=0;
virtual const CMapWorld* IGetMapWorld() const=0;
virtual CMapWorld* IMapWorld()=0;
virtual const IGameArea* IGetAreaAlways(TAreaId id) const=0;
virtual const IGameArea* IGetAreaAlways(TAreaId id) const=0;
virtual TAreaId IGetCurrentAreaId() const=0;
virtual TAreaId IGetAreaId(ResId id) const=0;
virtual bool ICheckWorldComplete()=0;

2
hecl

@ -1 +1 @@
Subproject commit eca3f3fdfad2f2558a98b0e193a63011cb76d02d
Subproject commit 2066835a7c597ec5fb022713edbb5a598941dce7