Mass code cleanup

This commit is contained in:
parax0
2016-03-27 13:09:38 -06:00
parent 6b79ef2f3f
commit 82ad4fb5c8
279 changed files with 5702 additions and 7227 deletions

View File

@@ -1,30 +0,0 @@
#include "CAnimSet.h"
CAnimSet::CAnimSet() : CResource()
{
}
CAnimSet::~CAnimSet()
{
}
u32 CAnimSet::getNodeCount()
{
return nodes.size();
}
TString CAnimSet::getNodeName(u32 node)
{
if (node >= nodes.size())
return nodes[0].name;
else
return nodes[node].name;
}
CModel* CAnimSet::getNodeModel(u32 node)
{
if (node >= nodes.size())
return nodes[0].model;
else
return nodes[node].model;
}

View File

@@ -16,22 +16,21 @@ class CAnimSet : public CResource
struct SNode
{
TString name;
TResPtr<CModel> model;
u32 skinID;
u32 skelID;
TString Name;
TResPtr<CModel> pModel;
u32 SkinID;
u32 SkelID;
SNode() { model = nullptr; }
SNode() { pModel = nullptr; }
};
std::vector<SNode> nodes;
std::vector<SNode> mNodes;
public:
CAnimSet();
~CAnimSet();
CAnimSet() : CResource() {}
u32 getNodeCount();
TString getNodeName(u32 node);
CModel* getNodeModel(u32 node);
u32 NumNodes() const { return mNodes.size(); }
TString NodeName(u32 Index) { if (Index >= mNodes.size()) Index = 0; return mNodes[Index].Name; }
CModel* NodeModel(u32 Index) { if (Index >= mNodes.size()) Index = 0; return mNodes[Index].pModel; }
};
#endif // CCHARACTERSET_H

View File

@@ -6,47 +6,46 @@
#include <iostream>
CAnimationParameters::CAnimationParameters()
: mGame(ePrime)
, mNodeIndex(0)
, mUnknown1(0)
, mUnknown2(0)
, mUnknown3(0)
{
mGame = ePrime;
mNodeIndex = 0;
mUnknown1 = 0;
mUnknown2 = 0;
mUnknown3 = 0;
}
CAnimationParameters::CAnimationParameters(EGame Game)
: mGame(Game)
, mNodeIndex(0)
, mUnknown1(0)
, mUnknown2(0)
, mUnknown3(0)
{
mGame = Game;
mNodeIndex = 0;
mUnknown1 = 0;
mUnknown2 = 0;
mUnknown3 = 0;
}
CAnimationParameters::CAnimationParameters(IInputStream& SCLY, EGame Game)
CAnimationParameters::CAnimationParameters(IInputStream& rSCLY, EGame Game)
: mGame(Game)
, mNodeIndex(0)
, mUnknown1(0)
, mUnknown2(0)
, mUnknown3(0)
{
mGame = Game;
mNodeIndex = 0;
mUnknown1 = 0;
mUnknown2 = 0;
mUnknown3 = 0;
if (Game <= eEchoes)
{
mCharacter = CResourceInfo(SCLY.ReadLong(), "ANCS");
mNodeIndex = SCLY.ReadLong();
mUnknown1 = SCLY.ReadLong();
mCharacter = CResourceInfo(rSCLY.ReadLong(), "ANCS");
mNodeIndex = rSCLY.ReadLong();
mUnknown1 = rSCLY.ReadLong();
}
else if (Game <= eCorruption)
{
mCharacter = CResourceInfo(SCLY.ReadLongLong(), "CHAR");
mUnknown1 = SCLY.ReadLong();
mCharacter = CResourceInfo(rSCLY.ReadLongLong(), "CHAR");
mUnknown1 = rSCLY.ReadLong();
}
else if (Game == eReturns)
{
u8 Flags = SCLY.ReadByte();
u8 Flags = rSCLY.ReadByte();
// 0x80 - CharacterAnimationSet is empty.
if (Flags & 0x80)
@@ -57,19 +56,19 @@ CAnimationParameters::CAnimationParameters(IInputStream& SCLY, EGame Game)
return;
}
mCharacter = CResourceInfo(SCLY.ReadLongLong(), "CHAR");
mCharacter = CResourceInfo(rSCLY.ReadLongLong(), "CHAR");
// 0x20 - Default Anim is present
if (Flags & 0x20)
mUnknown1 = SCLY.ReadLong();
mUnknown1 = rSCLY.ReadLong();
else
mUnknown1 = -1;
// 0x40 - Two-value struct is present
if (Flags & 0x40)
{
mUnknown2 = SCLY.ReadLong();
mUnknown3 = SCLY.ReadLong();
mUnknown2 = rSCLY.ReadLong();
mUnknown3 = rSCLY.ReadLong();
}
else
{
@@ -147,8 +146,8 @@ CModel* CAnimationParameters::GetCurrentModel(s32 NodeIndex /*= -1*/)
if (pSet->Type() != eAnimSet) return nullptr;
if (NodeIndex == -1) NodeIndex = mNodeIndex;
if (pSet->getNodeCount() <= (u32) NodeIndex) return nullptr;
return pSet->getNodeModel(NodeIndex);
if (pSet->NumNodes() <= (u32) NodeIndex) return nullptr;
return pSet->NodeModel(NodeIndex);
}
TString CAnimationParameters::GetCurrentCharacterName(s32 NodeIndex /*= -1*/)
@@ -160,26 +159,11 @@ TString CAnimationParameters::GetCurrentCharacterName(s32 NodeIndex /*= -1*/)
if (pSet->Type() != eAnimSet) return "";
if (NodeIndex == -1) NodeIndex = mNodeIndex;
if (pSet->getNodeCount() <= (u32) NodeIndex) return "";
return pSet->getNodeName((u32) NodeIndex);
}
// ************ GETTERS ************
EGame CAnimationParameters::Version()
{
return mGame;
}
CAnimSet* CAnimationParameters::AnimSet()
{
return (CAnimSet*) mCharacter.Load();
}
u32 CAnimationParameters::CharacterIndex()
{
return mNodeIndex;
if (pSet->NumNodes() <= (u32) NodeIndex) return "";
return pSet->NodeName((u32) NodeIndex);
}
// ************ ACCESSORS ************
u32 CAnimationParameters::Unknown(u32 Index)
{
switch (Index)
@@ -191,7 +175,6 @@ u32 CAnimationParameters::Unknown(u32 Index)
}
}
// ************ SETTERS ************
void CAnimationParameters::SetResource(CResourceInfo Res)
{
if (Res.Type() == "ANCS" || Res.Type() == "CHAR")
@@ -203,11 +186,6 @@ void CAnimationParameters::SetResource(CResourceInfo Res)
Log::Error("Resource with invalid type passed to CAnimationParameters: " + Res.ToString());
}
void CAnimationParameters::SetNodeIndex(u32 Index)
{
mNodeIndex = Index;
}
void CAnimationParameters::SetUnknown(u32 Index, u32 Value)
{
switch (Index)

View File

@@ -20,21 +20,20 @@ class CAnimationParameters
public:
CAnimationParameters();
CAnimationParameters(EGame Game);
CAnimationParameters(IInputStream& SCLY, EGame Game);
CAnimationParameters(IInputStream& rSCLY, EGame Game);
void Write(IOutputStream& rSCLY);
CModel* GetCurrentModel(s32 NodeIndex = -1);
TString GetCurrentCharacterName(s32 NodeIndex = -1);
// Getters
EGame Version();
CAnimSet* AnimSet();
u32 CharacterIndex();
u32 Unknown(u32 index);
// Accessors
inline EGame Version() const { return mGame; }
inline CAnimSet* AnimSet() const { return (CAnimSet*) mCharacter.Load(); }
inline u32 CharacterIndex() { return mNodeIndex; }
inline void SetNodeIndex(u32 Index) { mNodeIndex = Index; }
// Setters
u32 Unknown(u32 Index);
void SetResource(CResourceInfo Res);
void SetNodeIndex(u32 Index);
void SetUnknown(u32 Index, u32 Value);
// Operators

View File

@@ -33,32 +33,34 @@ void CCollisionMesh::BufferGL()
// Add all the verts to our VBO, first...
mVBO.Reserve(mCollisionVertices.size());
for (u16 v = 0; v < mCollisionVertices.size(); v++)
mVBO.AddVertex(CVertex(mCollisionVertices[v].Pos));
for (u16 iVtx = 0; iVtx < mCollisionVertices.size(); iVtx++)
mVBO.AddVertex(CVertex(mCollisionVertices[iVtx].Pos));
// Then add all the relevant indices to the IBO
mIBO.Reserve(mCollisionFaces.size() * 3);
for (u32 v = 0; v < mCollisionFaces.size(); v++)
for (u32 iVtx = 0; iVtx < mCollisionFaces.size(); iVtx++)
{
u16 Verts[3];
CCollisionFace *Face = &mCollisionFaces[v];
CCollisionLine *LineA = GetLine(Face->Lines[0]);
CCollisionLine *LineB = GetLine(Face->Lines[1]);
Verts[0] = LineA->Vertices[0];
Verts[1] = LineA->Vertices[1];
CCollisionFace *pFace = &mCollisionFaces[iVtx];
CCollisionLine *pLineA = GetLine(pFace->Lines[0]);
CCollisionLine *pLineB = GetLine(pFace->Lines[1]);
Verts[0] = pLineA->Vertices[0];
Verts[1] = pLineA->Vertices[1];
// We have two vertex indices; the last one is one of the ones on line B, but we're not sure which one
if ((LineB->Vertices[0] != Verts[0]) &&
(LineB->Vertices[0] != Verts[1]))
Verts[2] = LineB->Vertices[0];
if ((pLineB->Vertices[0] != Verts[0]) &&
(pLineB->Vertices[0] != Verts[1]))
Verts[2] = pLineB->Vertices[0];
else
Verts[2] = LineB->Vertices[1];
Verts[2] = pLineB->Vertices[1];
// Some faces have a property that indicates they need to be inverted
if (!Face->Properties.Invert)
if (!pFace->Properties.Invert)
mIBO.AddIndices(&Verts[0], 3);
else {
else
{
mIBO.AddIndex(Verts[2]);
mIBO.AddIndex(Verts[1]);
mIBO.AddIndex(Verts[0]);
@@ -88,17 +90,17 @@ void CCollisionMesh::DrawWireframe()
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
CCollisionMesh::CCollisionVertex* CCollisionMesh::GetVertex(u16 index)
CCollisionMesh::CCollisionVertex* CCollisionMesh::GetVertex(u16 Index)
{
return &mCollisionVertices[index];
return &mCollisionVertices[Index];
}
CCollisionMesh::CCollisionLine* CCollisionMesh::GetLine(u16 index)
CCollisionMesh::CCollisionLine* CCollisionMesh::GetLine(u16 Index)
{
return &mCollisionLines[index];
return &mCollisionLines[Index];
}
CCollisionMesh::CCollisionFace* CCollisionMesh::GetFace(u16 index)
CCollisionMesh::CCollisionFace* CCollisionMesh::GetFace(u16 Index)
{
return &mCollisionFaces[index];
return &mCollisionFaces[Index];
}

View File

@@ -27,7 +27,7 @@ class CCollisionMesh
SOctreeNode *pChildren[8];
};
SOctreeNode* Root;
SOctreeNode* mpRoot;
};
struct SCollisionProperties
@@ -65,16 +65,16 @@ class CCollisionMesh
bool mBuffered;
CAABox mAABox;
CCollisionOctree *mOctree;
CCollisionOctree *mpOctree;
std::vector<u32> mFlags;
std::vector<CCollisionVertex> mCollisionVertices;
std::vector<CCollisionLine> mCollisionLines;
std::vector<CCollisionFace> mCollisionFaces;
bool mOctreeLoaded;
CCollisionVertex *GetVertex(u16 index);
CCollisionLine *GetLine(u16 index);
CCollisionFace *GetFace(u16 index);
CCollisionVertex *GetVertex(u16 Index);
CCollisionLine *GetLine(u16 Index);
CCollisionFace *GetFace(u16 Index);
public:
CCollisionMesh();

View File

@@ -1,38 +0,0 @@
#include "CCollisionMeshGroup.h"
CCollisionMeshGroup::CCollisionMeshGroup()
{
}
CCollisionMeshGroup::~CCollisionMeshGroup()
{
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
delete *it;
}
u32 CCollisionMeshGroup::NumMeshes()
{
return mMeshes.size();
}
CCollisionMesh* CCollisionMeshGroup::MeshByIndex(u32 index)
{
return mMeshes[index];
}
void CCollisionMeshGroup::AddMesh(CCollisionMesh *pMesh)
{
mMeshes.push_back(pMesh);
}
void CCollisionMeshGroup::Draw()
{
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
(*it)->Draw();
}
void CCollisionMeshGroup::DrawWireframe()
{
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
(*it)->DrawWireframe();
}

View File

@@ -12,14 +12,29 @@ class CCollisionMeshGroup : public CResource
std::vector<CCollisionMesh*> mMeshes;
public:
CCollisionMeshGroup();
~CCollisionMeshGroup();
CCollisionMeshGroup() {}
u32 NumMeshes();
CCollisionMesh* MeshByIndex(u32 index);
void AddMesh(CCollisionMesh *pMesh);
void Draw();
void DrawWireframe();
~CCollisionMeshGroup()
{
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
delete *it;
}
inline u32 NumMeshes() const { return mMeshes.size(); }
inline CCollisionMesh* MeshByIndex(u32 Index) const { return mMeshes[Index]; }
inline void AddMesh(CCollisionMesh *pMesh) { mMeshes.push_back(pMesh); }
inline void Draw()
{
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
(*it)->Draw();
}
inline void DrawWireframe()
{
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
(*it)->DrawWireframe();
}
};
#endif // CCOLLISIONMESHGROUP_H

View File

@@ -2,7 +2,6 @@
#include "CResCache.h"
#include "Core/Render/CDrawUtil.h"
#include "Core/Render/CRenderer.h"
#include <Common/AnimUtil.h>
CDynamicVertexBuffer CFont::smGlyphVertices;
CIndexBuffer CFont::smGlyphIndices;
@@ -16,14 +15,14 @@ CFont::~CFont()
{
}
inline float PtsToFloat(s32 pt)
inline float PtsToFloat(s32 Pt)
{
// This is a bit of an arbitrary number but it works
// 1 / (1280 / 1.333333f / 2)
return 0.00208333f * pt;
return 0.00208333f * Pt;
}
CVector2f CFont::RenderString(const TString& String, CRenderer* /*pRenderer*/, float /*AspectRatio*/,
CVector2f CFont::RenderString(const TString& rkString, CRenderer* /*pRenderer*/, float /*AspectRatio*/,
CVector2f /*Position*/, CColor FillColor, CColor StrokeColor, u32 FontSize)
{
// WIP
@@ -49,16 +48,16 @@ CVector2f CFont::RenderString(const TString& String, CRenderer* /*pRenderer*/, f
if (FontSize == CFONT_DEFAULT_SIZE) Scale = 1.f;
else Scale = (float) FontSize / (mDefaultSize != 0 ? mDefaultSize : 18);
for (u32 iChar = 0; iChar < String.Length(); iChar++)
for (u32 iChar = 0; iChar < rkString.Length(); iChar++)
{
// Get character, check for newline
char Char = String[iChar];
char Char = rkString[iChar];
if (Char == '\n')
{
pPrevGlyph = nullptr;
PrintHead.x = -1;
PrintHead.y -= (PtsToFloat(mLineHeight) + PtsToFloat(mLineMargin) + PtsToFloat(mUnknown)) * Scale;
PrintHead.X = -1;
PrintHead.Y -= (PtsToFloat(mLineHeight) + PtsToFloat(mLineMargin) + PtsToFloat(mUnknown)) * Scale;
continue;
}
@@ -68,7 +67,7 @@ CVector2f CFont::RenderString(const TString& String, CRenderer* /*pRenderer*/, f
SGlyph *pGlyph = &iGlyph->second;
// Apply left padding and kerning
PrintHead.x += PtsToFloat(pGlyph->LeftPadding) * Scale;
PrintHead.X += PtsToFloat(pGlyph->LeftPadding) * Scale;
if (pPrevGlyph)
{
@@ -77,9 +76,9 @@ CVector2f CFont::RenderString(const TString& String, CRenderer* /*pRenderer*/, f
for (u32 iKern = pPrevGlyph->KerningIndex; iKern < mKerningTable.size(); iKern++)
{
if (mKerningTable[iKern].CharacterA != pPrevGlyph->Character) break;
if (mKerningTable[iKern].CharacterB == String[iChar])
if (mKerningTable[iKern].CharacterB == rkString[iChar])
{
PrintHead.x += PtsToFloat(mKerningTable[iKern].Adjust) * Scale;
PrintHead.X += PtsToFloat(mKerningTable[iKern].Adjust) * Scale;
break;
}
}
@@ -87,16 +86,16 @@ CVector2f CFont::RenderString(const TString& String, CRenderer* /*pRenderer*/, f
}
// Add a newline if this character goes over the right edge of the screen
if (PrintHead.x + ((PtsToFloat(pGlyph->PrintAdvance) + PtsToFloat(pGlyph->RightPadding)) * Scale) > 1)
if (PrintHead.X + ((PtsToFloat(pGlyph->PrintAdvance) + PtsToFloat(pGlyph->RightPadding)) * Scale) > 1)
{
PrintHead.x = -1;
PrintHead.y -= (PtsToFloat(mLineHeight) + PtsToFloat(mLineMargin) + PtsToFloat(mUnknown)) * Scale;
PrintHead.X = -1;
PrintHead.Y -= (PtsToFloat(mLineHeight) + PtsToFloat(mLineMargin) + PtsToFloat(mUnknown)) * Scale;
if (Char == ' ') continue;
}
float XTrans = PrintHead.x;
float YTrans = PrintHead.y + ((PtsToFloat(pGlyph->BaseOffset * 2) - PtsToFloat(mVerticalOffset * 2)) * Scale);
float XTrans = PrintHead.X;
float YTrans = PrintHead.Y + ((PtsToFloat(pGlyph->BaseOffset * 2) - PtsToFloat(mVerticalOffset * 2)) * Scale);
CTransform4f GlyphTransform = PtScale;
GlyphTransform.Scale(CVector3f((float) pGlyph->Width / 2, (float) pGlyph->Height, 1.f));
@@ -115,7 +114,7 @@ CVector2f CFont::RenderString(const TString& String, CRenderer* /*pRenderer*/, f
// Draw fill
glUniform1i(LayerLoc, GlyphLayer);
glUniform4fv(ColorLoc, 1, &FillColor.r);
glUniform4fv(ColorLoc, 1, &FillColor.R);
smGlyphIndices.DrawElements();
// Draw stroke
@@ -127,13 +126,13 @@ CVector2f CFont::RenderString(const TString& String, CRenderer* /*pRenderer*/, f
else if (mTextureFormat == 8) StrokeLayer = GlyphLayer - 2;
glUniform1i(LayerLoc, StrokeLayer);
glUniform4fv(ColorLoc, 1, &StrokeColor.r);
glUniform4fv(ColorLoc, 1, &StrokeColor.R);
smGlyphIndices.DrawElements();
}
// Update print head
PrintHead.x += PtsToFloat(pGlyph->PrintAdvance) * Scale;
PrintHead.x += PtsToFloat(pGlyph->RightPadding) * Scale;
PrintHead.X += PtsToFloat(pGlyph->PrintAdvance) * Scale;
PrintHead.X += PtsToFloat(pGlyph->RightPadding) * Scale;
pPrevGlyph = pGlyph;
}

View File

@@ -61,7 +61,7 @@ public:
CFont();
~CFont();
CResource* MakeCopy(CResCache *pCopyCache);
CVector2f RenderString(const TString& String, CRenderer *pRenderer, float AspectRatio,
CVector2f RenderString(const TString& rkString, CRenderer *pRenderer, float AspectRatio,
CVector2f Position = CVector2f(0,0),
CColor FillColor = CColor::skWhite, CColor StrokeColor = CColor::skBlack,
u32 FontSize = CFONT_DEFAULT_SIZE);

View File

@@ -26,17 +26,17 @@ CGameArea::~CGameArea()
for (u32 iSCLY = 0; iSCLY < mScriptLayers.size(); iSCLY++)
delete mScriptLayers[iSCLY];
for (u32 lyr = 0; lyr < mLightLayers.size(); lyr++)
for (u32 lit = 0; lit < mLightLayers[lyr].size(); lit++)
delete mLightLayers[lyr][lit];
for (u32 iLyr = 0; iLyr < mLightLayers.size(); iLyr++)
for (u32 iLight = 0; iLight < mLightLayers[iLyr].size(); iLight++)
delete mLightLayers[iLyr][iLight];
}
void CGameArea::AddWorldModel(CModel *mdl)
void CGameArea::AddWorldModel(CModel *pModel)
{
mTerrainModels.push_back(mdl);
mVertexCount += mdl->GetVertexCount();
mTriangleCount += mdl->GetTriangleCount();
mAABox.ExpandBounds(mdl->AABox());
mWorldModels.push_back(pModel);
mVertexCount += pModel->GetVertexCount();
mTriangleCount += pModel->GetTriangleCount();
mAABox.ExpandBounds(pModel->AABox());
}
void CGameArea::MergeTerrain()
@@ -44,9 +44,9 @@ void CGameArea::MergeTerrain()
if (mTerrainMerged) return;
// Nothing really complicated here - iterate through every terrain submesh, add each to a static model
for (u32 iMdl = 0; iMdl < mTerrainModels.size(); iMdl++)
for (u32 iMdl = 0; iMdl < mWorldModels.size(); iMdl++)
{
CModel *pMdl = mTerrainModels[iMdl];
CModel *pMdl = mWorldModels[iMdl];
u32 SubmeshCount = pMdl->GetSurfaceCount();
for (u32 iSurf = 0; iSurf < SubmeshCount; iSurf++)
@@ -54,8 +54,8 @@ void CGameArea::MergeTerrain()
SSurface *pSurf = pMdl->GetSurface(iSurf);
CMaterial *pMat = mMaterialSet->MaterialByIndex(pSurf->MaterialID);
bool newMat = true;
for (std::vector<CStaticModel*>::iterator it = mStaticTerrainModels.begin(); it != mStaticTerrainModels.end(); it++)
bool NewMat = true;
for (std::vector<CStaticModel*>::iterator it = mStaticWorldModels.begin(); it != mStaticWorldModels.end(); it++)
{
if ((*it)->GetMaterial() == pMat)
{
@@ -66,18 +66,18 @@ void CGameArea::MergeTerrain()
// This is maybe not the most efficient way to do this, but it works.
CStaticModel *pStatic = *it;
pStatic->AddSurface(pSurf);
mStaticTerrainModels.erase(it);
mStaticTerrainModels.push_back(pStatic);
newMat = false;
mStaticWorldModels.erase(it);
mStaticWorldModels.push_back(pStatic);
NewMat = false;
break;
}
}
if (newMat)
if (NewMat)
{
CStaticModel *pStatic = new CStaticModel(pMat);
pStatic->AddSurface(pSurf);
mStaticTerrainModels.push_back(pStatic);
mStaticWorldModels.push_back(pStatic);
}
}
}
@@ -85,13 +85,13 @@ void CGameArea::MergeTerrain()
void CGameArea::ClearTerrain()
{
for (u32 t = 0; t < mTerrainModels.size(); t++)
delete mTerrainModels[t];
mTerrainModels.clear();
for (u32 iModel = 0; iModel < mWorldModels.size(); iModel++)
delete mWorldModels[iModel];
mWorldModels.clear();
for (u32 s = 0; s < mStaticTerrainModels.size(); s++)
delete mStaticTerrainModels[s];
mStaticTerrainModels.clear();
for (u32 iStatic = 0; iStatic < mStaticWorldModels.size(); iStatic++)
delete mStaticWorldModels[iStatic];
mStaticWorldModels.clear();
if (mMaterialSet) delete mMaterialSet;

View File

@@ -46,8 +46,8 @@ class CGameArea : public CResource
// Geometry
CMaterialSet *mMaterialSet;
std::vector<CModel*> mTerrainModels; // TerrainModels is the original version of each model; this is currently mainly used in the POI map editor
std::vector<CStaticModel*> mStaticTerrainModels; // StaticTerrainModels is the merged terrain for faster rendering in the world editor
std::vector<CModel*> mWorldModels; // TerrainModels is the original version of each model; this is currently mainly used in the POI map editor
std::vector<CStaticModel*> mStaticWorldModels; // StaticTerrainModels is the merged terrain for faster rendering in the world editor
// Script
std::vector<CScriptLayer*> mScriptLayers;
CScriptLayer *mpGeneratorLayer;
@@ -63,7 +63,7 @@ public:
CGameArea();
~CGameArea();
void AddWorldModel(CModel *mdl);
void AddWorldModel(CModel *pModel);
void MergeTerrain();
void ClearTerrain();
void ClearScriptLayers();
@@ -79,24 +79,24 @@ public:
void DeleteInstance(CScriptObject *pInstance);
// Inline Accessors
inline EGame Version() const { return mVersion; }
inline u32 WorldIndex() const { return mWorldIndex; }
inline CTransform4f GetTransform() const { return mTransform; }
inline u32 GetTerrainModelCount() const { return mTerrainModels.size(); }
inline u32 GetStaticModelCount() const { return mStaticTerrainModels.size(); }
inline CModel* GetTerrainModel(u32 iMdl) const { return mTerrainModels[iMdl]; }
inline CStaticModel* GetStaticModel(u32 iMdl) const { return mStaticTerrainModels[iMdl]; }
inline CCollisionMeshGroup* GetCollision() const { return mpCollision; }
inline u32 GetScriptLayerCount() const { return mScriptLayers.size(); }
inline CScriptLayer* GetScriptLayer(u32 Index) const { return mScriptLayers[Index]; }
inline CScriptLayer* GetGeneratorLayer() const { return mpGeneratorLayer; }
inline u32 GetLightLayerCount() const { return mLightLayers.size(); }
inline u32 GetLightCount(u32 LayerIndex) const { return (LayerIndex < mLightLayers.size() ? mLightLayers[LayerIndex].size() : 0); }
inline CLight* GetLight(u32 LayerIndex, u32 LightIndex) const { return mLightLayers[LayerIndex][LightIndex]; }
inline CPoiToWorld* GetPoiToWorldMap() const { return mpPoiToWorldMap; }
inline CAABox AABox() const { return mAABox; }
inline EGame Version() const { return mVersion; }
inline u32 WorldIndex() const { return mWorldIndex; }
inline CTransform4f Transform() const { return mTransform; }
inline u32 NumWorldModels() const { return mWorldModels.size(); }
inline u32 NumStaticModels() const { return mStaticWorldModels.size(); }
inline CModel* TerrainModel(u32 iMdl) const { return mWorldModels[iMdl]; }
inline CStaticModel* StaticModel(u32 iMdl) const { return mStaticWorldModels[iMdl]; }
inline CCollisionMeshGroup* Collision() const { return mpCollision; }
inline u32 NumScriptLayers() const { return mScriptLayers.size(); }
inline CScriptLayer* ScriptLayer(u32 Index) const { return mScriptLayers[Index]; }
inline CScriptLayer* GeneratedObjectsLayer() const { return mpGeneratorLayer; }
inline u32 NumLightLayers() const { return mLightLayers.size(); }
inline u32 NumLights(u32 LayerIndex) const { return (LayerIndex < mLightLayers.size() ? mLightLayers[LayerIndex].size() : 0); }
inline CLight* Light(u32 LayerIndex, u32 LightIndex) const { return mLightLayers[LayerIndex][LightIndex]; }
inline CPoiToWorld* PoiToWorldMap() const { return mpPoiToWorldMap; }
inline CAABox AABox() const { return mAABox; }
inline void SetWorldIndex(u32 NewWorldIndex) { mWorldIndex = NewWorldIndex; }
inline void SetWorldIndex(u32 NewWorldIndex) { mWorldIndex = NewWorldIndex; }
};
#endif // CGAMEAREA_H

View File

@@ -7,14 +7,14 @@
#define CLIGHT_NO_INTENSITY 0x80
CLight::CLight()
: mPosition(skDefaultLightPos)
, mDirection(skDefaultLightDir)
, mDistAttenCoefficients(0.f, 1.f, 0.f)
, mAngleAttenCoefficients(0.f, 1.f, 0.f)
, mCachedRadius(0.f)
, mCachedIntensity(0.f)
, mDirtyFlags(CLIGHT_NO_RADIUS | CLIGHT_NO_INTENSITY)
{
mPosition = skDefaultLightPos;
mDirection = skDefaultLightDir;
mDistAttenCoefficients = CVector3f(0.f, 1.f, 0.f);
mAngleAttenCoefficients = CVector3f(0.f, 1.f, 0.f);
mCachedRadius = 0.f;
mCachedIntensity = 0.f;
mDirtyFlags = CLIGHT_NO_RADIUS | CLIGHT_NO_INTENSITY;
}
// ************ DATA MANIPULATION ************
@@ -22,30 +22,30 @@ CLight::CLight()
// This function is reverse engineered from the kiosk demo's code
float CLight::CalculateRadius() const
{
if ((mDistAttenCoefficients.y >= FLT_EPSILON) ||
(mDistAttenCoefficients.z >= FLT_EPSILON))
if ((mDistAttenCoefficients.Y >= FLT_EPSILON) ||
(mDistAttenCoefficients.Z >= FLT_EPSILON))
{
float Intensity = GetIntensity();
if (mDistAttenCoefficients.z > FLT_EPSILON)
if (mDistAttenCoefficients.Z > FLT_EPSILON)
{
if (Intensity <= FLT_EPSILON)
return 0.f;
float IntensityMod = (Intensity * 5.f / 255.f * mDistAttenCoefficients.z);
return sqrt(Intensity / IntensityMod);
float IntensityMod = (Intensity * 5.f / 255.f * mDistAttenCoefficients.Z);
return sqrtf(Intensity / IntensityMod);
}
else
{
if (mDistAttenCoefficients.y <= FLT_EPSILON)
if (mDistAttenCoefficients.Y <= FLT_EPSILON)
return 0.f;
float IntensityMod = (Intensity * 5.f) / 255.f;
if (IntensityMod < 0.2f)
IntensityMod = 0.2f;
return Intensity / (IntensityMod * mDistAttenCoefficients.y);
return Intensity / (IntensityMod * mDistAttenCoefficients.Y);
}
}
@@ -56,10 +56,10 @@ float CLight::CalculateRadius() const
float CLight::CalculateIntensity() const
{
// Get the color component with the greatest numeric value
float Greatest = (mColor.g >= mColor.b) ? mColor.g : mColor.b;
Greatest = (mColor.r >= Greatest) ? mColor.r : Greatest;
float Greatest = (mColor.G >= mColor.B) ? mColor.G : mColor.B;
Greatest = (mColor.R >= Greatest) ? mColor.R : Greatest;
float Multiplier = (mType == eCustom) ? mAngleAttenCoefficients.x : 1.0f;
float Multiplier = (mType == eCustom) ? mAngleAttenCoefficients.X : 1.0f;
return Greatest * Multiplier;
}
@@ -78,42 +78,7 @@ CVector3f CLight::CalculateSpotAngleAtten()
return CVector3f(0.f, -RadianCosine / InvCosine, 1.f / InvCosine);
}
// ************ GETTERS ************
ELightType CLight::GetType() const
{
return mType;
}
u32 CLight::GetLayerIndex() const
{
return mLayerIndex;
}
CVector3f CLight::GetPosition() const
{
return mPosition;
}
CVector3f CLight::GetDirection() const
{
return mDirection;
}
CColor CLight::GetColor() const
{
return mColor;
}
CVector3f CLight::GetDistAttenuation() const
{
return mDistAttenCoefficients;
}
CVector3f CLight::GetAngleAttenuation() const
{
return mAngleAttenCoefficients;
}
// ************ ACCESSORS ************
float CLight::GetRadius() const
{
if (mDirtyFlags & CLIGHT_NO_RADIUS)
@@ -136,25 +101,9 @@ float CLight::GetIntensity() const
return mCachedIntensity;
}
// ************ SETTERS ************
void CLight::SetLayer(u32 index)
void CLight::SetColor(const CColor& rkColor)
{
mLayerIndex = index;
}
void CLight::SetPosition(const CVector3f& Position)
{
mPosition = Position;
}
void CLight::SetDirection(const CVector3f& Direction)
{
mDirection = Direction;
}
void CLight::SetColor(const CColor& Color)
{
mColor = Color;
mColor = rkColor;
mDirtyFlags = CLIGHT_NO_RADIUS | CLIGHT_NO_INTENSITY;
}
@@ -166,16 +115,16 @@ void CLight::SetSpotCutoff(float Cutoff)
void CLight::SetDistAtten(float DistCoefA, float DistCoefB, float DistCoefC)
{
mDistAttenCoefficients.x = DistCoefA;
mDistAttenCoefficients.y = DistCoefB;
mDistAttenCoefficients.z = DistCoefC;
mDistAttenCoefficients.X = DistCoefA;
mDistAttenCoefficients.Y = DistCoefB;
mDistAttenCoefficients.Z = DistCoefC;
}
void CLight::SetAngleAtten(float AngleCoefA, float AngleCoefB, float AngleCoefC)
{
mAngleAttenCoefficients.x = AngleCoefA;
mAngleAttenCoefficients.y = AngleCoefB;
mAngleAttenCoefficients.z = AngleCoefC;
mAngleAttenCoefficients.X = AngleCoefA;
mAngleAttenCoefficients.Y = AngleCoefB;
mAngleAttenCoefficients.Z = AngleCoefC;
}
// ************ OTHER ************
@@ -184,9 +133,7 @@ void CLight::Load() const
u8 Index = (u8) CGraphics::sNumLights;
if (Index >= 8) return;
CGraphics::SLightBlock::SGXLight *Light = &CGraphics::sLightBlock.Lights[Index];
CVector3f PosView = CGraphics::sMVPBlock.ViewMatrix * mPosition;
CVector3f DirView = CGraphics::sMVPBlock.ViewMatrix * mDirection;
CGraphics::SLightBlock::SGXLight *pLight = &CGraphics::sLightBlock.Lights[Index];
switch (mType)
{
@@ -194,25 +141,25 @@ void CLight::Load() const
// LocalAmbient is already accounted for in CGraphics::sAreaAmbientColor
return;
case eDirectional:
Light->Position = CVector4f(-mDirection * 1048576.f, 1.f);
Light->Direction = CVector4f(mDirection, 0.f);
Light->Color = mColor * CGraphics::sWorldLightMultiplier;
Light->DistAtten = CVector4f(1.f, 0.f, 0.f, 0.f);
Light->AngleAtten = CVector4f(1.f, 0.f, 0.f, 0.f);
pLight->Position = CVector4f(-mDirection * 1048576.f, 1.f);
pLight->Direction = CVector4f(mDirection, 0.f);
pLight->Color = mColor * CGraphics::sWorldLightMultiplier;
pLight->DistAtten = CVector4f(1.f, 0.f, 0.f, 0.f);
pLight->AngleAtten = CVector4f(1.f, 0.f, 0.f, 0.f);
break;
case eSpot:
Light->Position = CVector4f(mPosition, 1.f);
Light->Direction = CVector4f(mDirection, 0.f);
Light->Color = mColor * CGraphics::sWorldLightMultiplier;
Light->DistAtten = mDistAttenCoefficients;
Light->AngleAtten = mAngleAttenCoefficients;
pLight->Position = CVector4f(mPosition, 1.f);
pLight->Direction = CVector4f(mDirection, 0.f);
pLight->Color = mColor * CGraphics::sWorldLightMultiplier;
pLight->DistAtten = mDistAttenCoefficients;
pLight->AngleAtten = mAngleAttenCoefficients;
break;
case eCustom:
Light->Position = CVector4f(mPosition, 1.f);
Light->Direction = CVector4f(mDirection, 0.f);
Light->Color = mColor * CGraphics::sWorldLightMultiplier;
Light->DistAtten = mDistAttenCoefficients;
Light->AngleAtten = mAngleAttenCoefficients;
pLight->Position = CVector4f(mPosition, 1.f);
pLight->Direction = CVector4f(mDirection, 0.f);
pLight->Color = mColor * CGraphics::sWorldLightMultiplier;
pLight->DistAtten = mDistAttenCoefficients;
pLight->AngleAtten = mAngleAttenCoefficients;
break;
default:
return;
@@ -221,57 +168,57 @@ void CLight::Load() const
}
// ************ STATIC ************
CLight* CLight::BuildLocalAmbient(const CVector3f& Position, const CColor& Color)
CLight* CLight::BuildLocalAmbient(const CVector3f& rkPosition, const CColor& rkColor)
{
CLight *Light = new CLight;
Light->mType = eLocalAmbient;
Light->mPosition = Position;
Light->mDirection = skDefaultLightDir;
Light->mColor = Color;
Light->mSpotCutoff = 0.f;
return Light;
CLight *pLight = new CLight;
pLight->mType = eLocalAmbient;
pLight->mPosition = rkPosition;
pLight->mDirection = skDefaultLightDir;
pLight->mColor = rkColor;
pLight->mSpotCutoff = 0.f;
return pLight;
}
CLight* CLight::BuildDirectional(const CVector3f& Position, const CVector3f& Direction, const CColor& Color)
CLight* CLight::BuildDirectional(const CVector3f& rkPosition, const CVector3f& rkDirection, const CColor& rkColor)
{
CLight *Light = new CLight;
Light->mType = eDirectional;
Light->mPosition = Position;
Light->mDirection = Direction;
Light->mColor = Color;
Light->mSpotCutoff = 0.f;
return Light;
CLight *pLight = new CLight;
pLight->mType = eDirectional;
pLight->mPosition = rkPosition;
pLight->mDirection = rkDirection;
pLight->mColor = rkColor;
pLight->mSpotCutoff = 0.f;
return pLight;
}
CLight* CLight::BuildSpot(const CVector3f& Position, const CVector3f& Direction, const CColor& Color, float Cutoff)
CLight* CLight::BuildSpot(const CVector3f& rkPosition, const CVector3f& rkDirection, const CColor& rkColor, float Cutoff)
{
CLight *Light = new CLight;
Light->mType = eSpot;
Light->mPosition = Position;
Light->mDirection = -Direction.Normalized();
Light->mColor = Color;
Light->mSpotCutoff = Cutoff * 0.5f;
Light->mAngleAttenCoefficients = Light->CalculateSpotAngleAtten();
return Light;
CLight *pLight = new CLight;
pLight->mType = eSpot;
pLight->mPosition = rkPosition;
pLight->mDirection = -rkDirection.Normalized();
pLight->mColor = rkColor;
pLight->mSpotCutoff = Cutoff * 0.5f;
pLight->mAngleAttenCoefficients = pLight->CalculateSpotAngleAtten();
return pLight;
}
CLight* CLight::BuildCustom(const CVector3f& Position, const CVector3f& Direction, const CColor& Color,
CLight* CLight::BuildCustom(const CVector3f& rkPosition, const CVector3f& rkDirection, const CColor& rkColor,
float DistAttenA, float DistAttenB, float DistAttenC,
float AngleAttenA, float AngleAttenB, float AngleAttenC)
{
CLight *Light = new CLight;
Light->mType = eCustom;
Light->mPosition = Position;
Light->mDirection = Direction;
Light->mColor = Color;
Light->mSpotCutoff = 0.f;
Light->mDistAttenCoefficients.x = DistAttenA;
Light->mDistAttenCoefficients.y = DistAttenB;
Light->mDistAttenCoefficients.z = DistAttenC;
Light->mAngleAttenCoefficients.x = AngleAttenA;
Light->mAngleAttenCoefficients.y = AngleAttenB;
Light->mAngleAttenCoefficients.z = AngleAttenC * AngleAttenC;
return Light;
CLight *pLight = new CLight;
pLight->mType = eCustom;
pLight->mPosition = rkPosition;
pLight->mDirection = rkDirection;
pLight->mColor = rkColor;
pLight->mSpotCutoff = 0.f;
pLight->mDistAttenCoefficients.X = DistAttenA;
pLight->mDistAttenCoefficients.Y = DistAttenB;
pLight->mDistAttenCoefficients.Z = DistAttenC;
pLight->mAngleAttenCoefficients.X = AngleAttenA;
pLight->mAngleAttenCoefficients.Y = AngleAttenB;
pLight->mAngleAttenCoefficients.Z = AngleAttenC * AngleAttenC;
return pLight;
}
// ************ CONSTANTS ************

View File

@@ -41,22 +41,23 @@ private:
CVector3f CalculateSpotAngleAtten();
public:
// Getters
ELightType GetType() const;
u32 GetLayerIndex() const;
CVector3f GetPosition() const;
CVector3f GetDirection() const;
CColor GetColor() const;
CVector3f GetDistAttenuation() const;
CVector3f GetAngleAttenuation() const;
// Accessors
inline ELightType Type() const { return mType; }
inline u32 LayerIndex() const { return mLayerIndex; }
inline CVector3f Position() const { return mPosition; }
inline CVector3f Direction() const { return mDirection; }
inline CColor Color() const { return mColor; }
inline CVector3f DistAttenuation() const { return mDistAttenCoefficients; }
inline CVector3f AngleAttenuation() const { return mAngleAttenCoefficients; }
inline void SetLayer(u32 Index) { mLayerIndex = Index; }
inline void SetPosition(const CVector3f& rkPosition) { mPosition = rkPosition; }
inline void SetDirection(const CVector3f& rkDirection) { mDirection = rkDirection; }
float GetRadius() const;
float GetIntensity() const;
// Setters
void SetLayer(u32 index);
void SetPosition(const CVector3f& Position);
void SetDirection(const CVector3f& Direction);
void SetColor(const CColor& Color);
void SetColor(const CColor& rkColor);
void SetSpotCutoff(float Cutoff);
void SetDistAtten(float DistCoefA, float DistCoefB, float DistCoefC);
void SetAngleAtten(float AngleCoefA, float AngleCoefB, float AngleCoefC);
@@ -65,10 +66,10 @@ public:
void Load() const;
// Static
static CLight* BuildLocalAmbient(const CVector3f& Position, const CColor& Color);
static CLight* BuildDirectional(const CVector3f& Position, const CVector3f& Direction, const CColor& Color);
static CLight* BuildSpot(const CVector3f& Position, const CVector3f& Direction, const CColor& Color, float Cutoff);
static CLight* BuildCustom(const CVector3f& Position, const CVector3f& Direction, const CColor& Color,
static CLight* BuildLocalAmbient(const CVector3f& rkPosition, const CColor& rkColor);
static CLight* BuildDirectional(const CVector3f& rkPosition, const CVector3f& rkDirection, const CColor& rkColor);
static CLight* BuildSpot(const CVector3f& rkPosition, const CVector3f& rkDirection, const CColor& rkColor, float Cutoff);
static CLight* BuildCustom(const CVector3f& rkPosition, const CVector3f& rkDirection, const CColor& rkColor,
float DistAttenA, float DistAttenB, float DistAttenC,
float AngleAttenA, float AngleAttenB, float AngleAttenC);

View File

@@ -13,31 +13,44 @@ u64 CMaterial::sCurrentMaterial = 0;
CColor CMaterial::sCurrentTint = CColor::skWhite;
CMaterial::CMaterial()
: mpShader(nullptr)
, mShaderStatus(eNoShader)
, mRecalcHash(true)
, mEnableBloom(false)
, mVersion(eUnknownVersion)
, mOptions(eNoSettings)
, mVtxDesc(eNoAttributes)
, mBlendSrcFac(GL_ONE)
, mBlendDstFac(GL_ZERO)
, mLightingEnabled(true)
, mEchoesUnknownA(0)
, mEchoesUnknownB(0)
, mpIndirectTexture(nullptr)
{
mpShader = nullptr;
mShaderStatus = eNoShader;
mRecalcHash = true;
mEnableBloom = false;
mVersion = eUnknownVersion;
mOptions = eNoSettings;
mVtxDesc = eNoAttributes;
mBlendSrcFac = GL_ONE;
mBlendDstFac = GL_ZERO;
mLightingEnabled = true;
mEchoesUnknownA = 0;
mEchoesUnknownB = 0;
mpIndirectTexture = nullptr;
}
CMaterial::CMaterial(EGame version, FVertexDescription vtxDesc)
CMaterial::CMaterial(EGame Version, FVertexDescription VtxDesc)
: mpShader(nullptr)
, mShaderStatus(eNoShader)
, mRecalcHash(true)
, mEnableBloom(Version == eCorruption)
, mVersion(Version)
, mOptions(eDepthWrite)
, mVtxDesc(VtxDesc)
, mBlendSrcFac(GL_ONE)
, mBlendDstFac(GL_ZERO)
, mLightingEnabled(true)
, mEchoesUnknownA(0)
, mEchoesUnknownB(0)
, mpIndirectTexture(nullptr)
{
mpShader = nullptr;
mShaderStatus = eNoShader;
mRecalcHash = true;
mEnableBloom = (version == eCorruption);
mVersion = version;
mEnableBloom = (Version == eCorruption);
mVersion = Version;
mOptions = eDepthWrite;
mVtxDesc = vtxDesc;
mVtxDesc = VtxDesc;
mBlendSrcFac = GL_ONE;
mBlendDstFac = GL_ZERO;
mLightingEnabled = true;
@@ -218,114 +231,6 @@ void CMaterial::Update()
mShaderStatus = eNoShader;
}
// ************ GETTERS ************
TString CMaterial::Name() const
{
return mName;
}
EGame CMaterial::Version() const
{
return mVersion;
}
CMaterial::FMaterialOptions CMaterial::Options() const
{
return mOptions;
}
FVertexDescription CMaterial::VtxDesc() const
{
return mVtxDesc;
}
GLenum CMaterial::BlendSrcFac() const {
return mBlendSrcFac;
}
GLenum CMaterial::BlendDstFac() const {
return mBlendDstFac;
}
CColor CMaterial::Konst(u32 KIndex) const
{
if (KIndex > 3) return CColor::skTransparentBlack;
else return mKonstColors[KIndex];
}
CTexture* CMaterial::IndTexture() const
{
return mpIndirectTexture;
}
bool CMaterial::IsLightingEnabled() const
{
return mLightingEnabled;
}
u32 CMaterial::EchoesUnknownA() const
{
return mEchoesUnknownA;
}
u32 CMaterial::EchoesUnknownB() const
{
return mEchoesUnknownB;
}
u32 CMaterial::PassCount() const
{
return mPasses.size();
}
CMaterialPass* CMaterial::Pass(u32 PassIndex) const
{
return mPasses[PassIndex];
}
// ************ SETTERS ************
void CMaterial::SetName(const TString& name)
{
mName = name;
}
void CMaterial::SetOptions(FMaterialOptions Options)
{
mOptions = Options;
mRecalcHash = true;
}
void CMaterial::SetVertexDescription(FVertexDescription desc)
{
mVtxDesc = desc;
mRecalcHash = true;
}
void CMaterial::SetBlendMode(GLenum SrcFac, GLenum DstFac)
{
mBlendSrcFac = SrcFac;
mBlendDstFac = DstFac;
mRecalcHash = true;
}
void CMaterial::SetKonst(CColor& Konst, u32 KIndex)
{
mKonstColors[KIndex] = Konst;
mRecalcHash = true;
}
void CMaterial::SetIndTexture(CTexture *pTex)
{
mpIndirectTexture = pTex;
}
void CMaterial::SetLightingEnabled(bool Enabled)
{
mLightingEnabled = Enabled;
mRecalcHash = true;
}
void CMaterial::SetNumPasses(u32 NumPasses)
{
if (NumPasses < mPasses.size())
@@ -345,9 +250,3 @@ void CMaterial::SetNumPasses(u32 NumPasses)
mRecalcHash = true;
}
// ************ STATIC ************
void CMaterial::KillCachedMaterial()
{
sCurrentMaterial = 0;
}

View File

@@ -74,41 +74,41 @@ private:
public:
CMaterial();
CMaterial(EGame version, FVertexDescription vtxDesc);
CMaterial(EGame Version, FVertexDescription VtxDesc);
~CMaterial();
CMaterial* Clone();
void GenerateShader(bool AllowRegen = true);
bool SetCurrent(FRenderOptions Options);
u64 HashParameters();
void Update();
// Getters
TString Name() const;
EGame Version() const;
FMaterialOptions Options() const;
FVertexDescription VtxDesc() const;
GLenum BlendSrcFac() const;
GLenum BlendDstFac() const;
CColor Konst(u32 KIndex) const;
CTexture* IndTexture() const;
bool IsLightingEnabled() const;
u32 EchoesUnknownA() const;
u32 EchoesUnknownB() const;
u32 PassCount() const;
CMaterialPass* Pass(u32 PassIndex) const;
// Setters
void SetName(const TString& name);
void SetOptions(FMaterialOptions Options);
void SetVertexDescription(FVertexDescription desc);
void SetBlendMode(GLenum SrcFac, GLenum DstFac);
void SetKonst(CColor& Konst, u32 KIndex);
void SetIndTexture(CTexture *pTex);
void SetLightingEnabled(bool Enabled);
void SetNumPasses(u32 NumPasses);
// Accessors
inline TString Name() const { return mName; }
inline EGame Version() const { return mVersion; }
inline FMaterialOptions Options() const { return mOptions; }
inline FVertexDescription VtxDesc() const { return mVtxDesc; }
inline GLenum BlendSrcFac() const { return mBlendSrcFac; }
inline GLenum BlendDstFac() const { return mBlendDstFac; }
inline CColor Konst(u32 KIndex) const { return mKonstColors[KIndex]; }
inline CTexture* IndTexture() const { return mpIndirectTexture; }
inline bool IsLightingEnabled() const { return mLightingEnabled; }
inline u32 EchoesUnknownA() const { return mEchoesUnknownA; }
inline u32 EchoesUnknownB() const { return mEchoesUnknownB; }
inline u32 PassCount() const { return mPasses.size(); }
inline CMaterialPass* Pass(u32 PassIndex) const { return mPasses[PassIndex]; }
inline void SetName(const TString& rkName) { mName = rkName; }
inline void SetOptions(FMaterialOptions Options) { mOptions = Options; mRecalcHash = true; }
inline void SetVertexDescription(FVertexDescription Desc) { mVtxDesc = Desc; mRecalcHash = true; }
inline void SetBlendMode(GLenum SrcFac, GLenum DstFac) { mBlendSrcFac = SrcFac; mBlendDstFac = DstFac; mRecalcHash = true; }
inline void SetKonst(CColor& Konst, u32 KIndex) { mKonstColors[KIndex] = Konst; mRecalcHash = true; }
inline void SetIndTexture(CTexture *pTex) { mpIndirectTexture = pTex; }
inline void SetLightingEnabled(bool Enabled) { mLightingEnabled = Enabled; mRecalcHash = true; }
// Static
static void KillCachedMaterial();
inline static void KillCachedMaterial() { sCurrentMaterial = 0; }
};
#endif // MATERIAL_H

View File

@@ -1,24 +1,22 @@
#include "CMaterialPass.h"
#include "CMaterial.h"
#include "Core/Render/CGraphics.h"
#include <Common/AnimUtil.h>
#include <Common/CTimer.h>
CMaterialPass::CMaterialPass(CMaterial *pParent)
: mPassType("CUST")
, mSettings(eNoPassSettings)
, mpTexture(nullptr)
, mEnabled(true)
, mpParentMat(pParent)
, mColorOutput(ePrevReg)
, mAlphaOutput(ePrevReg)
, mKColorSel(eKonstOne)
, mKAlphaSel(eKonstOne)
, mRasSel(eRasColorNull)
, mTexCoordSource(0xFF)
, mAnimMode(eNoUVAnim)
{
mPassType = "CUST";
mSettings = eNoPassSettings;
mpTexture = nullptr;
mEnabled = true;
mpParentMat = pParent;
mColorOutput = ePrevReg;
mAlphaOutput = ePrevReg;
mKColorSel = eKonstOne;
mKAlphaSel = eKonstOne;
mRasSel = eRasColorNull;
mTexCoordSource = 0xFF;
mAnimMode = eNoUVAnim;
for (u32 iParam = 0; iParam < 4; iParam++)
{
mColorInputs[iParam] = eZeroRGB;
@@ -36,10 +34,13 @@ CMaterialPass* CMaterialPass::Clone(CMaterial *pParent)
CMaterialPass *pOut = new CMaterialPass(pParent);
pOut->mPassType = mPassType;
pOut->mSettings = mSettings;
for (u32 iIn = 0; iIn < 4; iIn++) {
for (u32 iIn = 0; iIn < 4; iIn++)
{
pOut->mColorInputs[iIn] = mColorInputs[iIn];
pOut->mAlphaInputs[iIn] = mAlphaInputs[iIn];
}
pOut->mColorOutput = mColorOutput;
pOut->mAlphaOutput = mAlphaOutput;
pOut->mKColorSel = mKColorSel;
@@ -48,30 +49,32 @@ CMaterialPass* CMaterialPass::Clone(CMaterial *pParent)
pOut->mTexCoordSource = mTexCoordSource;
pOut->mpTexture = mpTexture;
pOut->mAnimMode = mAnimMode;
for (u32 iParam = 0; iParam < 4; iParam++)
pOut->mAnimParams[iParam] = mAnimParams[iParam];
pOut->mEnabled = mEnabled;
return pOut;
}
void CMaterialPass::HashParameters(CHashFNV1A &Hash)
void CMaterialPass::HashParameters(CHashFNV1A& rHash)
{
if (mEnabled)
{
Hash.HashLong(mPassType.ToLong());
Hash.HashLong(mSettings);
Hash.HashData(&mColorInputs[0], sizeof(ETevColorInput) * 4);
Hash.HashData(&mAlphaInputs[0], sizeof(ETevAlphaInput) * 4);
Hash.HashLong(mColorOutput);
Hash.HashLong(mAlphaOutput);
Hash.HashLong(mKColorSel);
Hash.HashLong(mKAlphaSel);
Hash.HashLong(mRasSel);
Hash.HashLong(mTexCoordSource);
Hash.HashLong(mAnimMode);
Hash.HashData(mAnimParams, sizeof(float) * 4);
Hash.HashByte(mEnabled);
rHash.HashLong(mPassType.ToLong());
rHash.HashLong(mSettings);
rHash.HashData(&mColorInputs[0], sizeof(ETevColorInput) * 4);
rHash.HashData(&mAlphaInputs[0], sizeof(ETevAlphaInput) * 4);
rHash.HashLong(mColorOutput);
rHash.HashLong(mAlphaOutput);
rHash.HashLong(mKColorSel);
rHash.HashLong(mKAlphaSel);
rHash.HashLong(mRasSel);
rHash.HashLong(mTexCoordSource);
rHash.HashLong(mAnimMode);
rHash.HashData(mAnimParams, sizeof(float) * 4);
rHash.HashByte(mEnabled);
}
}
@@ -85,7 +88,7 @@ void CMaterialPass::SetAnimCurrent(FRenderOptions Options, u32 PassIndex)
{
if (mAnimMode == eNoUVAnim) return;
float s = AnimUtil::SecondsMod900();
float Seconds = CTimer::SecondsMod900();
const CMatrix4f& ModelMtx = CGraphics::sMVPBlock.ModelMatrix;
const CMatrix4f& ViewMtx = CGraphics::sMVPBlock.ViewMatrix;
@@ -98,9 +101,9 @@ void CMaterialPass::SetAnimCurrent(FRenderOptions Options, u32 PassIndex)
case eInverseMV: // Mode 0
case eSimpleMode: // Mode 10 - maybe not correct?
{
glm::mat4 mtx = glm::inverse(glm::transpose(ViewMtx.ToGlmMat4()) * glm::transpose(ModelMtx.ToGlmMat4()));
mtx[0][3] = mtx[1][3] = mtx[2][3] = 0.f;
TexMtx = CMatrix4f::FromGlmMat4(mtx);
glm::mat4 InvMV = glm::inverse(glm::transpose(ViewMtx.ToGlmMat4()) * glm::transpose(ModelMtx.ToGlmMat4()));
InvMV[0][3] = InvMV[1][3] = InvMV[2][3] = 0.f;
TexMtx = CMatrix4f::FromGlmMat4(InvMV);
PostMtx = CMatrix4f(0.5f, 0.0f, 0.0f, 0.5f,
0.0f, 0.5f, 0.0f, 0.5f,
0.0f, 0.0f, 0.0f, 1.0f,
@@ -110,8 +113,8 @@ void CMaterialPass::SetAnimCurrent(FRenderOptions Options, u32 PassIndex)
case eInverseMVTranslated: // Mode 1
{
glm::mat4 mtx = glm::inverse(glm::transpose(ViewMtx.ToGlmMat4()) * glm::transpose(ModelMtx.ToGlmMat4()));
TexMtx = CMatrix4f::FromGlmMat4(mtx);
glm::mat4 InvMV = glm::inverse(glm::transpose(ViewMtx.ToGlmMat4()) * glm::transpose(ModelMtx.ToGlmMat4()));
TexMtx = CMatrix4f::FromGlmMat4(InvMV);
PostMtx = CMatrix4f(0.5f, 0.0f, 0.0f, 0.5f,
0.0f, 0.5f, 0.0f, 0.5f,
0.0f, 0.0f, 0.0f, 1.0f,
@@ -122,8 +125,8 @@ void CMaterialPass::SetAnimCurrent(FRenderOptions Options, u32 PassIndex)
{
if (Options & eEnableUVScroll)
{
TexMtx[0][3] = (s * mAnimParams[2]) + mAnimParams[0];
TexMtx[1][3] = (s * mAnimParams[3]) + mAnimParams[1];
TexMtx[0][3] = (Seconds * mAnimParams[2]) + mAnimParams[0];
TexMtx[1][3] = (Seconds * mAnimParams[3]) + mAnimParams[1];
}
break;
}
@@ -132,7 +135,7 @@ void CMaterialPass::SetAnimCurrent(FRenderOptions Options, u32 PassIndex)
{
if (Options & eEnableUVScroll)
{
float Angle = (s * mAnimParams[1]) + mAnimParams[0];
float Angle = (Seconds * mAnimParams[1]) + mAnimParams[0];
float ACos = cos(Angle);
float ASin = sin(Angle);
@@ -152,7 +155,7 @@ void CMaterialPass::SetAnimCurrent(FRenderOptions Options, u32 PassIndex)
{
if (Options & eEnableUVScroll)
{
float Offset = mAnimParams[2] * mAnimParams[0] * (mAnimParams[3] + s);
float Offset = mAnimParams[2] * mAnimParams[0] * (mAnimParams[3] + Seconds);
Offset = (float)(short)(float)(mAnimParams[1] * fmod(Offset, 1.0f)) * mAnimParams[2];
if (mAnimMode == eHFilmstrip) TexMtx[0][3] = Offset;
if (mAnimMode == eVFilmstrip) TexMtx[1][3] = Offset;
@@ -175,23 +178,22 @@ void CMaterialPass::SetAnimCurrent(FRenderOptions Options, u32 PassIndex)
case eConvolutedModeA: // Mode 7
{
CMatrix4f view = CGraphics::sMVPBlock.ViewMatrix;
CMatrix4f View = CGraphics::sMVPBlock.ViewMatrix;
// Oh god I seriously need a CMatrix4f inverse function.
glm::mat4 mtx = glm::inverse(glm::transpose(ViewMtx.ToGlmMat4()) * glm::transpose(ModelMtx.ToGlmMat4()));
mtx[0][3] = mtx[1][3] = mtx[2][3] = 0.f;
TexMtx = CMatrix4f::FromGlmMat4(mtx);
glm::mat4 Mtx = glm::inverse(glm::transpose(ViewMtx.ToGlmMat4()) * glm::transpose(ModelMtx.ToGlmMat4()));
Mtx[0][3] = Mtx[1][3] = Mtx[2][3] = 0.f;
TexMtx = CMatrix4f::FromGlmMat4(Mtx);
float xy = (view[3][0] + view[3][1]) * 0.025f * mAnimParams[1];
xy = (xy - (int) xy);
float XY = (View[3][0] + View[3][1]) * 0.025f * mAnimParams[1];
XY = (XY - (int) XY);
float z = view[3][2] * 0.05f * mAnimParams[1];
z = (z - (int) z);
float Z = View[3][2] * 0.05f * mAnimParams[1];
Z = (Z - (int) Z);
float halfA = mAnimParams[0] * 0.5f;
float HalfA = mAnimParams[0] * 0.5f;
PostMtx = CMatrix4f(halfA, 0.0f, 0.0f, xy,
0.0f, 0.0f, halfA, z,
PostMtx = CMatrix4f(HalfA, 0.0f, 0.0f, XY,
0.0f, 0.0f, HalfA, Z,
0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f);
break;

View File

@@ -45,7 +45,7 @@ public:
CMaterialPass(CMaterial *pParent);
~CMaterialPass();
CMaterialPass* Clone(CMaterial *pParent);
void HashParameters(CHashFNV1A& Hash);
void HashParameters(CHashFNV1A& rHash);
void LoadTexture(u32 PassIndex);
void SetAnimCurrent(FRenderOptions Options, u32 PassIndex);
@@ -65,61 +65,20 @@ public:
void SetEnabled(bool Enabled);
// Getters
inline CFourCC Type() const {
return mPassType;
}
inline TString NamedType() const {
return PassTypeName(mPassType);
}
inline ETevColorInput ColorInput(u32 Input) const {
return mColorInputs[Input];
}
inline ETevAlphaInput AlphaInput(u32 Input) const {
return mAlphaInputs[Input];
}
inline ETevOutput ColorOutput() const {
return mColorOutput;
}
inline ETevOutput AlphaOutput() const {
return mAlphaOutput;
}
inline ETevKSel KColorSel() const {
return mKColorSel;
}
inline ETevKSel KAlphaSel() const {
return mKAlphaSel;
}
inline ETevRasSel RasSel() const {
return mRasSel;
}
inline u32 TexCoordSource() const {
return mTexCoordSource;
}
inline CTexture* Texture() const {
return mpTexture;
}
inline EUVAnimMode AnimMode() const {
return mAnimMode;
}
inline float AnimParam(u32 ParamIndex) const {
return mAnimParams[ParamIndex];
}
inline bool IsEnabled() const {
return mEnabled;
}
inline CFourCC Type() const { return mPassType; }
inline TString NamedType() const { return PassTypeName(mPassType); }
inline ETevColorInput ColorInput(u32 Input) const { return mColorInputs[Input]; }
inline ETevAlphaInput AlphaInput(u32 Input) const { return mAlphaInputs[Input]; }
inline ETevOutput ColorOutput() const { return mColorOutput; }
inline ETevOutput AlphaOutput() const { return mAlphaOutput; }
inline ETevKSel KColorSel() const { return mKColorSel; }
inline ETevKSel KAlphaSel() const { return mKAlphaSel; }
inline ETevRasSel RasSel() const { return mRasSel; }
inline u32 TexCoordSource() const { return mTexCoordSource; }
inline CTexture* Texture() const { return mpTexture; }
inline EUVAnimMode AnimMode() const { return mAnimMode; }
inline float AnimParam(u32 ParamIndex) const { return mAnimParams[ParamIndex]; }
inline bool IsEnabled() const { return mEnabled; }
// Static
static TString PassTypeName(CFourCC Type);

View File

@@ -1,49 +0,0 @@
#include "CMaterialSet.h"
#include "CResCache.h"
#include <iostream>
CMaterialSet::CMaterialSet()
{
}
CMaterialSet::~CMaterialSet()
{
for (u32 iMat = 0; iMat < mMaterials.size(); iMat++)
delete mMaterials[iMat];
}
CMaterialSet* CMaterialSet::Clone()
{
CMaterialSet *pOut = new CMaterialSet();
pOut->mMaterials.resize(mMaterials.size());
for (u32 iMat = 0; iMat < mMaterials.size(); iMat++)
pOut->mMaterials[iMat] = mMaterials[iMat]->Clone();
return pOut;
}
u32 CMaterialSet::NumMaterials()
{
return mMaterials.size();
}
CMaterial* CMaterialSet::MaterialByIndex(u32 index)
{
if (index >= NumMaterials()) return nullptr;
return mMaterials[index];
}
CMaterial* CMaterialSet::MaterialByName(const TString& name)
{
for (auto it = mMaterials.begin(); it != mMaterials.end(); it++)
if ((*it)->Name() == name) return *it;
return nullptr;
}
u32 CMaterialSet::MaterialIndexByName(const TString& name)
{
for (u32 iMat = 0; iMat < mMaterials.size(); iMat++)
if (mMaterials[iMat]->Name() == name) return iMat;
return -1;
}

View File

@@ -14,13 +14,51 @@ class CMaterialSet
std::vector<CMaterial*> mMaterials;
public:
CMaterialSet();
~CMaterialSet();
CMaterialSet* Clone();
u32 NumMaterials();
CMaterial* MaterialByIndex(u32 index);
CMaterial* MaterialByName(const TString& name);
u32 MaterialIndexByName(const TString& name);
CMaterialSet() {}
~CMaterialSet()
{
for (u32 iMat = 0; iMat < mMaterials.size(); iMat++)
delete mMaterials[iMat];
}
CMaterialSet* Clone()
{
CMaterialSet *pOut = new CMaterialSet();
pOut->mMaterials.resize(mMaterials.size());
for (u32 iMat = 0; iMat < mMaterials.size(); iMat++)
pOut->mMaterials[iMat] = mMaterials[iMat]->Clone();
return pOut;
}
u32 NumMaterials()
{
return mMaterials.size();
}
CMaterial* MaterialByIndex(u32 Index)
{
if (Index >= NumMaterials()) return nullptr;
return mMaterials[Index];
}
CMaterial* MaterialByName(const TString& rkName)
{
for (auto it = mMaterials.begin(); it != mMaterials.end(); it++)
if ((*it)->Name() == rkName) return *it;
return nullptr;
}
u32 MaterialIndexByName(const TString& rkName)
{
for (u32 iMat = 0; iMat < mMaterials.size(); iMat++)
if (mMaterials[iMat]->Name() == rkName) return iMat;
return -1;
}
};
#endif // CMATERIALSET_H

View File

@@ -10,161 +10,166 @@
#include <iomanip>
CPakFile::CPakFile()
: mpPak(nullptr)
{
pak = nullptr;
}
CPakFile::CPakFile(IInputStream* pakfile)
CPakFile::CPakFile(IInputStream* pPakFile)
{
pak = pakfile;
if (!pak->IsValid()) return;
mpPak = pPakFile;
if (!mpPak->IsValid()) return;
version = pak->ReadLong();
pak->Seek(0x4, SEEK_CUR);
mVersion = mpPak->ReadLong();
mpPak->Seek(0x4, SEEK_CUR);
u32 namedResCount = pak->ReadLong();
NamedResTable.resize(namedResCount);
u32 NamedResCount = mpPak->ReadLong();
mNamedResTable.resize(NamedResCount);
for (u32 n = 0; n < namedResCount; n++)
for (u32 iName = 0; iName < NamedResCount; iName++)
{
SNamedResource *res = &NamedResTable[n];
res->resType = CFourCC(*pak);
res->resID = (u64) pak->ReadLong();
u32 resNameLength = pak->ReadLong();
res->resName = pak->ReadString(resNameLength);
SNamedResource *pRes = &mNamedResTable[iName];
pRes->Type = CFourCC(*mpPak);
pRes->ID = (u64) mpPak->ReadLong();
u32 resNameLength = mpPak->ReadLong();
pRes->Name = mpPak->ReadString(resNameLength);
}
u32 resCount = pak->ReadLong();
ResInfoTable.resize(resCount);
u32 ResCount = mpPak->ReadLong();
mResInfoTable.resize(ResCount);
for (u32 r = 0; r < resCount; r++)
for (u32 iRes = 0; iRes < ResCount; iRes++)
{
SResInfo *res = &ResInfoTable[r];
res->compressed = (pak->ReadLong() != 0);
res->resType = CFourCC(*pak);
res->resID = (u64) pak->ReadLong();
res->size = pak->ReadLong();
res->offset = pak->ReadLong();
SResInfo *pRes = &mResInfoTable[iRes];
pRes->Compressed = (mpPak->ReadLong() != 0);
pRes->Type = CFourCC(*mpPak);
pRes->ID = (u64) mpPak->ReadLong();
pRes->Size = mpPak->ReadLong();
pRes->Offset = mpPak->ReadLong();
}
}
CPakFile::~CPakFile()
{
if (pak) delete pak;
if (mpPak) delete mpPak;
}
std::vector<SNamedResource> CPakFile::getNamedResources()
std::vector<SNamedResource> CPakFile::NamedResources()
{
return NamedResTable;
return mNamedResTable;
}
SResInfo CPakFile::getResourceInfo(u64 assetID, CFourCC assetType)
SResInfo CPakFile::ResourceInfo(u64 AssetID, CFourCC AssetType)
{
// TODO: figure out how the game finds assets in paks, implement similar system to speed things up
if (ResInfoTable.empty())
if (mResInfoTable.empty())
return SResInfo();
for (u32 r = 0; r < ResInfoTable.size(); r++)
for (u32 iRes = 0; iRes < mResInfoTable.size(); iRes++)
{
if (((u64) (ResInfoTable[r].resID & 0xFFFFFFFF) == (u64) (assetID & 0xFFFFFFFF)) && (ResInfoTable[r].resType == assetType))
return ResInfoTable[r];
if (((u64) (mResInfoTable[iRes].ID & 0xFFFFFFFF) == (u64) (AssetID & 0xFFFFFFFF)) && (mResInfoTable[iRes].Type == AssetType))
return mResInfoTable[iRes];
}
return SResInfo();
}
std::vector<u8>* CPakFile::getResource(u64 assetID, CFourCC assetType)
std::vector<u8>* CPakFile::Resource(u64 AssetID, CFourCC AssetType)
{
SResInfo info = getResourceInfo(assetID, assetType);
SResInfo Info = ResourceInfo(AssetID, AssetType);
// make sure SResInfo is valid
if ((u64) (info.resID & 0xFFFFFFFF) != (u64) (assetID & 0xFFFFFFFF)) return nullptr;
else return getResource(info);
if ((u64) (Info.ID & 0xFFFFFFFF) != (u64) (AssetID & 0xFFFFFFFF)) return nullptr;
else return Resource(Info);
}
std::vector<u8>* CPakFile::getResource(SResInfo& info)
std::vector<u8>* CPakFile::Resource(SResInfo& rInfo)
{
pak->Seek(info.offset, SEEK_SET);
std::vector<u8> *res_buf = new std::vector<u8>;
mpPak->Seek(rInfo.Offset, SEEK_SET);
std::vector<u8> *pResBuf = new std::vector<u8>;
if (info.compressed)
if (rInfo.Compressed)
{
u32 decmp_size = pak->ReadLong();
res_buf->resize(decmp_size);
u32 DecmpSize = mpPak->ReadLong();
pResBuf->resize(DecmpSize);
std::vector<u8> cmp_buf(info.size - 4);
pak->ReadBytes(&cmp_buf[0], info.size - 4);
std::vector<u8> CmpBuf(rInfo.Size - 4);
mpPak->ReadBytes(&CmpBuf[0], rInfo.Size - 4);
bool dcmp = decompress(cmp_buf.data(), cmp_buf.size(), res_buf->data(), res_buf->size());
bool Success = Decompress(CmpBuf.data(), CmpBuf.size(), pResBuf->data(), pResBuf->size());
if (!dcmp) {
delete res_buf;
if (!Success)
{
delete pResBuf;
return nullptr;
}
}
else {
res_buf->resize(info.size);
pak->ReadBytes(res_buf->data(), info.size);
else
{
pResBuf->resize(rInfo.Size);
mpPak->ReadBytes(pResBuf->data(), rInfo.Size);
}
return res_buf;
return pResBuf;
}
bool CPakFile::decompress(u8 *src, u32 src_len, u8 *dst, u32 dst_len)
bool CPakFile::Decompress(u8 *pSrc, u32 SrcLen, u8 *pDst, u32 DstLen)
{
if ((src[0] == 0x78) && (src[1] == 0xda))
if ((pSrc[0] == 0x78) && (pSrc[1] == 0xda))
{
// zlib
z_stream z;
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;
z.avail_in = src_len;
z.next_in = src;
z.avail_out = dst_len;
z.next_out = dst;
z.avail_in = SrcLen;
z.next_in = pSrc;
z.avail_out = DstLen;
z.next_out = pDst;
s32 ret = inflateInit(&z);
s32 Ret = inflateInit(&z);
if (ret == Z_OK)
if (Ret == Z_OK)
{
ret = inflate(&z, Z_NO_FLUSH);
Ret = inflate(&z, Z_NO_FLUSH);
if ((ret == Z_OK) || (ret == Z_STREAM_END))
ret = inflateEnd(&z);
if ((Ret == Z_OK) || (Ret == Z_STREAM_END))
Ret = inflateEnd(&z);
}
if ((ret != Z_OK) && (ret != Z_STREAM_END)) {
Log::Error("zlib error: " + TString::FromInt32(ret, 0, 10));
if ((Ret != Z_OK) && (Ret != Z_STREAM_END)) {
Log::Error("zlib error: " + TString::FromInt32(Ret, 0, 10));
return false;
}
else return true;
}
else {
else
{
// LZO
lzo_uint decmp;
s32 ret;
u8 *src_end = src + src_len;
u8 *dst_end = dst + dst_len;
lzo_uint Decmp;
s32 Ret;
u8 *pSrcEnd = pSrc + SrcLen;
u8 *pDstEnd = pDst + DstLen;
lzo_init();
while ((src < src_end) && (dst < dst_end)) {
short block_size;
memcpy(&block_size, src, 2);
if (IOUtil::kSystemEndianness == IOUtil::eLittleEndian) IOUtil::SwapBytes(block_size);
src += 2;
while ((pSrc < pSrcEnd) && (pDst < pDstEnd))
{
short BlockSize;
memcpy(&BlockSize, pSrc, 2);
if (IOUtil::kSystemEndianness == IOUtil::eLittleEndian) IOUtil::SwapBytes(BlockSize);
pSrc += 2;
ret = lzo1x_decompress(src, block_size, dst, &decmp, LZO1X_MEM_DECOMPRESS);
if (ret != LZO_E_OK) break;
src += block_size;
dst += decmp;
Ret = lzo1x_decompress(pSrc, BlockSize, pDst, &Decmp, LZO1X_MEM_DECOMPRESS);
if (Ret != LZO_E_OK) break;
pSrc += BlockSize;
pDst += Decmp;
}
if (ret != LZO_E_OK) {
Log::Error("LZO error: " + TString::FromInt32(ret, 0, 10));
if (Ret != LZO_E_OK)
{
Log::Error("LZO error: " + TString::FromInt32(Ret, 0, 10));
return false;
}

View File

@@ -10,22 +10,22 @@
class CPakFile
{
private:
u32 version;
std::vector<SNamedResource> NamedResTable;
std::vector<SResInfo> ResInfoTable;
IInputStream* pak;
u32 mVersion;
std::vector<SNamedResource> mNamedResTable;
std::vector<SResInfo> mResInfoTable;
IInputStream* mpPak;
bool decompress(u8 *src, u32 src_len, u8 *dst, u32 dst_len);
bool Decompress(u8 *pSrc, u32 SrcLen, u8 *pDst, u32 DstLen);
public:
CPakFile();
CPakFile(IInputStream* pakfile);
CPakFile(IInputStream* pPakFile);
~CPakFile();
std::vector<SNamedResource> getNamedResources();
SResInfo getResourceInfo(u64 assetID, CFourCC assetType);
std::vector<u8>* getResource(u64 assetID, CFourCC assetType);
std::vector<u8>* getResource(SResInfo& info);
std::vector<SNamedResource> NamedResources();
SResInfo ResourceInfo(u64 AssetID, CFourCC AssetType);
std::vector<u8>* Resource(u64 AssetID, CFourCC AssetType);
std::vector<u8>* Resource(SResInfo& rInfo);
};
#endif // CPAKFILE_H

View File

@@ -17,8 +17,8 @@
#include <boost/filesystem.hpp>
CResCache::CResCache()
: mpPak(nullptr)
{
mpPak = nullptr;
}
CResCache::~CResCache()
@@ -34,11 +34,11 @@ void CResCache::Clean()
// I couldn't get this to work properly using reverse iterators, lol.
// Resources get cached after their dependencies, which is why I go backwards
// while loop is to ensure -all- unused resources are cleaned. Not sure of a better way to do it.
int numResourcesCleaned = 1;
int NumResourcesCleaned = 1;
while (numResourcesCleaned)
while (NumResourcesCleaned)
{
numResourcesCleaned = 0;
NumResourcesCleaned = 0;
for (auto it = mResourceCache.end(); it != mResourceCache.begin();)
{
@@ -47,41 +47,42 @@ void CResCache::Clean()
{
delete it->second;
it = mResourceCache.erase(it);
numResourcesCleaned++;
NumResourcesCleaned++;
}
}
}
Log::Write(std::to_string(mResourceCache.size()) + " resources loaded");
}
void CResCache::SetFolder(TString path)
void CResCache::SetFolder(TString Path)
{
path.EnsureEndsWith("/");
mResSource.Path = path;
mResSource.Source = SResSource::Folder;
Log::Write("Set resource folder: " + path);
Path.EnsureEndsWith("/");
mResSource.Path = Path;
mResSource.Source = SResSource::eFolder;
Log::Write("Set resource folder: " + Path);
}
void CResCache::SetPak(const TString& path)
void CResCache::SetPak(const TString& rkPath)
{
CFileInStream *pakfile = new CFileInStream(path.ToStdString(), IOUtil::eBigEndian);
if (!pakfile->IsValid())
CFileInStream *pPakFile = new CFileInStream(rkPath.ToStdString(), IOUtil::eBigEndian);
if (!pPakFile->IsValid())
{
Log::Error("Couldn't load pak file: " + path);
delete pakfile;
Log::Error("Couldn't load pak file: " + rkPath);
delete pPakFile;
return;
}
if (mpPak) delete mpPak;
mpPak = new CPakFile(pakfile);
mResSource.Path = path;
mResSource.Source = SResSource::PakFile;
Log::Write("Loaded pak file: " + path);
mpPak = new CPakFile(pPakFile);
mResSource.Path = rkPath;
mResSource.Source = SResSource::ePakFile;
Log::Write("Loaded pak file: " + rkPath);
}
void CResCache::SetResSource(SResSource& ResSource)
void CResCache::SetResSource(SResSource& rResSource)
{
mResSource = ResSource;
mResSource = rResSource;
}
SResSource CResCache::GetResSource()
@@ -94,7 +95,7 @@ TString CResCache::GetSourcePath()
return mResSource.Path;
}
CResource* CResCache::GetResource(CUniqueID ResID, CFourCC type)
CResource* CResCache::GetResource(CUniqueID ResID, CFourCC Type)
{
if (!ResID.IsValid()) return nullptr;
@@ -107,110 +108,111 @@ CResource* CResCache::GetResource(CUniqueID ResID, CFourCC type)
TString Source;
// Load from pak
if (mResSource.Source == SResSource::PakFile)
if (mResSource.Source == SResSource::ePakFile)
{
pBuffer = mpPak->getResource(ResID.ToLongLong(), type);
Source = ResID.ToString() + "." + type.ToString();
pBuffer = mpPak->Resource(ResID.ToLongLong(), Type);
Source = ResID.ToString() + "." + Type.ToString();
}
// Load from folder
else
{
Source = mResSource.Path + ResID.ToString() + "." + type.ToString();
CFileInStream file(Source.ToStdString(), IOUtil::eBigEndian);
if (!file.IsValid())
Source = mResSource.Path + ResID.ToString() + "." + Type.ToString();
CFileInStream File(Source.ToStdString(), IOUtil::eBigEndian);
if (!File.IsValid())
{
Log::Error("Couldn't open resource: " + ResID.ToString() + "." + type.ToString());
Log::Error("Couldn't open resource: " + ResID.ToString() + "." + Type.ToString());
return nullptr;
}
pBuffer = new std::vector<u8>;
pBuffer->resize(file.Size());
file.ReadBytes(pBuffer->data(), pBuffer->size());
pBuffer->resize(File.Size());
File.ReadBytes(pBuffer->data(), pBuffer->size());
}
if (!pBuffer) return nullptr;
// Load resource
CMemoryInStream mem(pBuffer->data(), pBuffer->size(), IOUtil::eBigEndian);
mem.SetSourceString(*Source.GetFileName());
CResource *Res = nullptr;
CMemoryInStream Mem(pBuffer->data(), pBuffer->size(), IOUtil::eBigEndian);
Mem.SetSourceString(*Source.GetFileName());
CResource *pRes = nullptr;
bool SupportedFormat = true;
if (type == "CMDL") Res = CModelLoader::LoadCMDL(mem);
else if (type == "TXTR") Res = CTextureDecoder::LoadTXTR(mem);
else if (type == "ANCS") Res = CAnimSetLoader::LoadANCS(mem);
else if (type == "CHAR") Res = CAnimSetLoader::LoadCHAR(mem);
else if (type == "MREA") Res = CAreaLoader::LoadMREA(mem);
else if (type == "MLVL") Res = CWorldLoader::LoadMLVL(mem);
else if (type == "STRG") Res = CStringLoader::LoadSTRG(mem);
else if (type == "FONT") Res = CFontLoader::LoadFONT(mem);
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(mem);
else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(mem);
else if (type == "EGMC") Res = CPoiToWorldLoader::LoadEGMC(mem);
if (Type == "CMDL") pRes = CModelLoader::LoadCMDL(Mem);
else if (Type == "TXTR") pRes = CTextureDecoder::LoadTXTR(Mem);
else if (Type == "ANCS") pRes = CAnimSetLoader::LoadANCS(Mem);
else if (Type == "CHAR") pRes = CAnimSetLoader::LoadCHAR(Mem);
else if (Type == "MREA") pRes = CAreaLoader::LoadMREA(Mem);
else if (Type == "MLVL") pRes = CWorldLoader::LoadMLVL(Mem);
else if (Type == "STRG") pRes = CStringLoader::LoadSTRG(Mem);
else if (Type == "FONT") pRes = CFontLoader::LoadFONT(Mem);
else if (Type == "SCAN") pRes = CScanLoader::LoadSCAN(Mem);
else if (Type == "DCLN") pRes = CCollisionLoader::LoadDCLN(Mem);
else if (Type == "EGMC") pRes = CPoiToWorldLoader::LoadEGMC(Mem);
else SupportedFormat = false;
// Log errors
if (!SupportedFormat)
Log::Write("Unsupported format; unable to load " + type.ToString() + " " + ResID.ToString());
Log::Write("Unsupported format; unable to load " + Type.ToString() + " " + ResID.ToString());
if (!Res) Res = new CResource(); // Default for invalid resource or unsupported format
if (!pRes) pRes = new CResource(); // Default for invalid resource or unsupported format
// Add to cache and cleanup
Res->mID = ResID;
Res->mResSource = Source;
mResourceCache[ResID.ToLongLong()] = Res;
pRes->mID = ResID;
pRes->mResSource = Source;
mResourceCache[ResID.ToLongLong()] = pRes;
delete pBuffer;
return Res;
return pRes;
}
CResource* CResCache::GetResource(const TString& ResPath)
CResource* CResCache::GetResource(const TString& rkResPath)
{
// Since this function takes a string argument it always loads directly from a file - no pak
CUniqueID ResID = ResPath.Hash64();
CUniqueID ResID = rkResPath.Hash64();
auto got = mResourceCache.find(ResID.ToLongLong());
auto Got = mResourceCache.find(ResID.ToLongLong());
if (got != mResourceCache.end())
return got->second;
if (Got != mResourceCache.end())
return Got->second;
CFileInStream file(ResPath.ToStdString(), IOUtil::eBigEndian);
if (!file.IsValid())
CFileInStream File(rkResPath.ToStdString(), IOUtil::eBigEndian);
if (!File.IsValid())
{
Log::Error("Couldn't open resource: " + ResPath);
Log::Error("Couldn't open resource: " + rkResPath);
return nullptr;
}
// Save old ResSource to restore later
const SResSource OldSource = mResSource;
mResSource.Source = SResSource::Folder;
mResSource.Path = ResPath.GetFileDirectory();
mResSource.Source = SResSource::eFolder;
mResSource.Path = rkResPath.GetFileDirectory();
// Load resource
CResource *Res = nullptr;
CFourCC type = ResPath.GetFileExtension().ToUpper();
CResource *pRes = nullptr;
CFourCC Type = rkResPath.GetFileExtension().ToUpper();
bool SupportedFormat = true;
if (type == "CMDL") Res = CModelLoader::LoadCMDL(file);
else if (type == "TXTR") Res = CTextureDecoder::LoadTXTR(file);
else if (type == "ANCS") Res = CAnimSetLoader::LoadANCS(file);
else if (type == "CHAR") Res = CAnimSetLoader::LoadCHAR(file);
else if (type == "MREA") Res = CAreaLoader::LoadMREA(file);
else if (type == "MLVL") Res = CWorldLoader::LoadMLVL(file);
else if (type == "STRG") Res = CStringLoader::LoadSTRG(file);
else if (type == "FONT") Res = CFontLoader::LoadFONT(file);
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(file);
else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(file);
else if (type == "EGMC") Res = CPoiToWorldLoader::LoadEGMC(file);
if (Type == "CMDL") pRes = CModelLoader::LoadCMDL(File);
else if (Type == "TXTR") pRes = CTextureDecoder::LoadTXTR(File);
else if (Type == "ANCS") pRes = CAnimSetLoader::LoadANCS(File);
else if (Type == "CHAR") pRes = CAnimSetLoader::LoadCHAR(File);
else if (Type == "MREA") pRes = CAreaLoader::LoadMREA(File);
else if (Type == "MLVL") pRes = CWorldLoader::LoadMLVL(File);
else if (Type == "STRG") pRes = CStringLoader::LoadSTRG(File);
else if (Type == "FONT") pRes = CFontLoader::LoadFONT(File);
else if (Type == "SCAN") pRes = CScanLoader::LoadSCAN(File);
else if (Type == "DCLN") pRes = CCollisionLoader::LoadDCLN(File);
else if (Type == "EGMC") pRes = CPoiToWorldLoader::LoadEGMC(File);
else SupportedFormat = false;
if (!Res) Res = new CResource(); // Default for unsupported formats
if (!pRes) pRes = new CResource(); // Default for unsupported formats
// Add to cache and cleanup
Res->mID = *ResPath;
Res->mResSource = ResPath;
mResourceCache[ResID.ToLongLong()] = Res;
pRes->mID = *rkResPath;
pRes->mResSource = rkResPath;
mResourceCache[ResID.ToLongLong()] = pRes;
mResSource = OldSource;
return Res;
return pRes;
}
CFourCC CResCache::FindResourceType(CUniqueID ResID, const TStringList& rkPossibleTypes)
@@ -220,13 +222,13 @@ CFourCC CResCache::FindResourceType(CUniqueID ResID, const TStringList& rkPossib
return CFourCC(rkPossibleTypes.front());
// Determine extension from pak
if (mResSource.Source == SResSource::PakFile)
if (mResSource.Source == SResSource::ePakFile)
{
for (auto it = rkPossibleTypes.begin(); it != rkPossibleTypes.end(); it++)
{
SResInfo ResInfo = mpPak->getResourceInfo(ResID.ToLongLong(), CFourCC(*it));
SResInfo ResInfo = mpPak->ResourceInfo(ResID.ToLongLong(), CFourCC(*it));
if (ResInfo.resType != "NULL")
if (ResInfo.Type != "NULL")
return CFourCC(*it);
}
}
@@ -251,20 +253,20 @@ CFourCC CResCache::FindResourceType(CUniqueID ResID, const TStringList& rkPossib
void CResCache::CacheResource(CResource *pRes)
{
u64 ID = pRes->ResID().ToLongLong();
auto got = mResourceCache.find(ID);
auto Got = mResourceCache.find(ID);
if (got != mResourceCache.end())
if (Got != mResourceCache.end())
mResourceCache[ID] = pRes;
}
void CResCache::DeleteResource(CUniqueID ResID)
{
auto got = mResourceCache.find(ResID.ToLongLong());
auto Got = mResourceCache.find(ResID.ToLongLong());
if (got != mResourceCache.end())
if (Got != mResourceCache.end())
{
delete got->second;
mResourceCache.erase(got, got);
delete Got->second;
mResourceCache.erase(Got, Got);
}
}

View File

@@ -11,7 +11,7 @@ struct SResSource
{
TString Path;
enum {
Folder, PakFile
eFolder, ePakFile
} Source;
};
@@ -25,13 +25,13 @@ public:
CResCache();
~CResCache();
void Clean();
void SetFolder(TString path);
void SetPak(const TString& path);
void SetResSource(SResSource& ResSource);
void SetFolder(TString Path);
void SetPak(const TString& rkPath);
void SetResSource(SResSource& rResSource);
SResSource GetResSource();
TString GetSourcePath();
CResource* GetResource(CUniqueID ResID, CFourCC type);
CResource* GetResource(const TString& ResPath);
CResource* GetResource(CUniqueID ResID, CFourCC Type);
CResource* GetResource(const TString& rkResPath);
CFourCC FindResourceType(CUniqueID ResID, const TStringList& rkPossibleTypes);
void CacheResource(CResource *pRes);
void DeleteResource(CUniqueID ResID);

View File

@@ -1,45 +1,4 @@
#include "CResource.h"
#include "CResCache.h"
#include <iostream>
CResource::CResource()
{
mRefCount = 0;
}
CResource::~CResource()
{
}
TString CResource::Source()
{
return mResSource.GetFileName();
}
TString CResource::FullSource()
{
return mResSource;
}
CUniqueID CResource::ResID()
{
return mID;
}
void CResource::Lock()
{
mRefCount++;
}
void CResource::Release()
{
mRefCount--;
}
bool CResource::IsValidResource()
{
return (Type() != eResource);
}
// ************ STATIC ************
EResType CResource::ResTypeForExtension(CFourCC Extension)

View File

@@ -35,14 +35,16 @@ class CResource
int mRefCount;
public:
CResource();
virtual ~CResource();
TString Source();
TString FullSource();
CUniqueID ResID();
void Lock();
void Release();
bool IsValidResource();
CResource() : mRefCount(0) {}
virtual ~CResource() {}
inline TString Source() const { return mResSource.GetFileName(); }
inline TString FullSource() const { return mResSource; }
inline CUniqueID ResID() const { return mID; }
inline void Lock() { mRefCount++; }
inline void Release() { mRefCount--; }
inline bool IsValidResource() { return (Type() != eResource); }
static EResType ResTypeForExtension(CFourCC Extension);
};

View File

@@ -1,39 +0,0 @@
#include "CScan.h"
CScan::CScan()
{
mpFrame = nullptr;
mpStringTable = nullptr;
mIsSlow = false;
mIsImportant = false;
mCategory = eNone;
}
CScan::~CScan()
{
}
EGame CScan::Version()
{
return mVersion;
}
CStringTable* CScan::ScanText()
{
return mpStringTable;
}
bool CScan::IsImportant()
{
return mIsImportant;
}
bool CScan::IsSlow()
{
return mIsSlow;
}
CScan::ELogbookCategory CScan::LogbookCategory()
{
return mCategory;
}

View File

@@ -31,13 +31,20 @@ private:
ELogbookCategory mCategory;
public:
CScan();
~CScan();
EGame Version();
CStringTable* ScanText();
bool IsImportant();
bool IsSlow();
ELogbookCategory LogbookCategory();
CScan()
: CResource()
, mpFrame(nullptr)
, mpStringTable(nullptr)
, mIsSlow(false)
, mIsImportant(false)
, mCategory(eNone)
{}
EGame Version() const { return mVersion; }
CStringTable* ScanText() const { return mpStringTable; }
bool IsImportant() const { return mIsImportant; }
bool IsSlow() const { return mIsSlow; }
ELogbookCategory LogbookCategory() const { return mCategory; }
};
#endif // CSCAN_H

View File

@@ -1,52 +0,0 @@
#include "CStringTable.h"
CStringTable::CStringTable() : CResource()
{
}
CStringTable::~CStringTable()
{
}
CResource* CStringTable::MakeCopy(CResCache*)
{
// Not using parameter 1 (CResCache* - pResCache)
return new CStringTable(*this);
}
// ************ SETTERS ************
u32 CStringTable::GetStringCount()
{
return mNumStrings;
}
u32 CStringTable::GetLangCount()
{
return mLangTables.size();
}
CFourCC CStringTable::GetLangTag(u32 Index)
{
return mLangTables[Index].Language;
}
TWideString CStringTable::GetString(CFourCC Lang, u32 StringIndex)
{
for (u32 iLang = 0; iLang < GetLangCount(); iLang++)
{
if (GetLangTag(iLang) == Lang)
return GetString(iLang, StringIndex);
}
return std::wstring();
}
TWideString CStringTable::GetString(u32 LangIndex, u32 StringIndex)
{
return mLangTables[LangIndex].Strings[StringIndex];
}
TString CStringTable::GetStringName(u32 StringIndex)
{
return mStringNames[StringIndex];
}

View File

@@ -23,17 +23,24 @@ class CStringTable : public CResource
std::vector<SLangTable> mLangTables;
public:
CStringTable();
~CStringTable();
CResource* MakeCopy(CResCache *pCopyCache);
CStringTable() {}
// Getters
u32 GetStringCount();
u32 GetLangCount();
CFourCC GetLangTag(u32 Index);
TWideString GetString(CFourCC Lang, u32 StringIndex);
TWideString GetString(u32 LangIndex, u32 StringIndex);
TString GetStringName(u32 StringIndex);
inline u32 NumStrings() const { return mLangTables.size(); }
inline u32 NumLanguages() const { return mLangTables.size(); }
inline CFourCC LanguageTag(u32 Index) const { return mLangTables[Index].Language; }
inline TWideString String(u32 LangIndex, u32 StringIndex) const { return mLangTables[LangIndex].Strings[StringIndex]; }
inline TString StringName(u32 StringIndex) const { return mStringNames[StringIndex]; }
TWideString String(CFourCC Lang, u32 StringIndex) const
{
for (u32 iLang = 0; iLang < NumLanguages(); iLang++)
{
if (LanguageTag(iLang) == Lang)
return String(iLang, StringIndex);
}
return TWideString();
}
};
#endif // CSTRINGTABLE_H

View File

@@ -1,51 +1,32 @@
#include "CTexture.h"
CTexture::CTexture() : CResource()
CTexture::CTexture()
: CResource()
, mTexelFormat(eRGBA8)
, mSourceTexelFormat(eRGBA8)
, mWidth(0)
, mHeight(0)
, mNumMipMaps(0)
, mLinearSize(0)
, mBufferExists(false)
, mpImgDataBuffer(nullptr)
, mImgDataSize(0)
, mGLBufferExists(false)
{
mTexelFormat = eRGBA8;
mSourceTexelFormat = eRGBA8;
mWidth = 0;
mHeight = 0;
mNumMipMaps = 0;
mLinearSize = 0;
mBufferExists = false;
mImgDataBuffer = nullptr;
mImgDataSize = 0;
mGLBufferExists = false;
}
CTexture::CTexture(const CTexture& Source)
{
mTexelFormat = Source.mTexelFormat;
mSourceTexelFormat = Source.mSourceTexelFormat;
mWidth = Source.mWidth;
mHeight = Source.mHeight;
mLinearSize = Source.mLinearSize;
mBufferExists = Source.mBufferExists;
mImgDataSize = Source.mImgDataSize;
mImgDataBuffer = new u8[mImgDataSize];
memcpy(mImgDataBuffer, Source.mImgDataBuffer, mImgDataSize);
mGLBufferExists = false;
}
CTexture::CTexture(u32 Width, u32 Height)
: mTexelFormat(eRGBA8)
, mSourceTexelFormat(eRGBA8)
, mWidth((u16) Width)
, mHeight((u16) Height)
, mNumMipMaps(1)
, mLinearSize(Width * Height * 4)
, mBufferExists(false)
, mpImgDataBuffer(nullptr)
, mImgDataSize(0)
, mGLBufferExists(false)
{
mTexelFormat = eRGBA8;
mSourceTexelFormat = eRGBA8;
mWidth = (u16) Width;
mHeight = (u16) Height;
mNumMipMaps = 1;
mLinearSize = Width * Height * 4;
mBufferExists = false;
mImgDataBuffer = nullptr;
mImgDataSize = 0;
mGLBufferExists = false;
}
CTexture::~CTexture()
@@ -61,8 +42,8 @@ bool CTexture::BufferGL()
GLenum GLFormat, GLType;
bool IsCompressed = false;
switch (mTexelFormat) {
switch (mTexelFormat)
{
case eLuminance:
GLFormat = GL_LUMINANCE;
GLType = GL_UNSIGNED_BYTE;
@@ -97,7 +78,7 @@ bool CTexture::BufferGL()
for (u32 iMip = 0; iMip < mNumMipMaps; iMip++)
{
GLvoid *pData = (mBufferExists) ? (mImgDataBuffer + MipOffset) : NULL;
GLvoid *pData = (mBufferExists) ? (mpImgDataBuffer + MipOffset) : NULL;
if (!IsCompressed)
glTexImage2D(GL_TEXTURE_2D, iMip, GLFormat, MipW, MipH, 0, GLFormat, GLType, pData);
@@ -147,16 +128,16 @@ void CTexture::Resize(u32 Width, u32 Height)
}
}
float CTexture::ReadTexelAlpha(const CVector2f& TexCoord)
float CTexture::ReadTexelAlpha(const CVector2f& rkTexCoord)
{
// todo: support texel formats other than DXT1
// DXT1 is definitely the most complicated one anyway; try reusing CTextureDecoder functions for other formats
u32 TexelX = (u32) ((mWidth - 1) * TexCoord.x);
u32 TexelY = (u32) ((mHeight - 1) * (1.f - fmodf(TexCoord.y, 1.f)));
u32 TexelX = (u32) ((mWidth - 1) * rkTexCoord.X);
u32 TexelY = (u32) ((mHeight - 1) * (1.f - fmodf(rkTexCoord.Y, 1.f)));
if (mTexelFormat == eDXT1 && mBufferExists)
{
CMemoryInStream Buffer(mImgDataBuffer, mImgDataSize, IOUtil::kSystemEndianness);
CMemoryInStream Buffer(mpImgDataBuffer, mImgDataSize, IOUtil::kSystemEndianness);
// 8 bytes per 4x4 16-pixel block, left-to-right top-to-bottom
u32 BlockIdxX = TexelX / 4;
@@ -190,83 +171,84 @@ float CTexture::ReadTexelAlpha(const CVector2f& TexCoord)
return 1.f;
}
bool CTexture::WriteDDS(IOutputStream& out)
bool CTexture::WriteDDS(IOutputStream& rOut)
{
if (!out.IsValid()) return false;
if (!rOut.IsValid()) return false;
CopyGLBuffer();
out.WriteString("DDS ", 4); // "DDS " fourCC
out.WriteLong(0x7C); // dwSize
out.WriteLong(0x21007); // dwFlags
out.WriteLong(mHeight); // dwHeight
out.WriteLong(mWidth); // dwWidth
out.WriteLong(mLinearSize); // dwPitchOrLinearSize
out.WriteLong(0); // dwDepth
out.WriteLong(mNumMipMaps - 1); // dwMipMapCount
rOut.WriteString("DDS ", 4); // "DDS " fourCC
rOut.WriteLong(0x7C); // dwSize
rOut.WriteLong(0x21007); // dwFlags
rOut.WriteLong(mHeight); // dwHeight
rOut.WriteLong(mWidth); // dwWidth
rOut.WriteLong(mLinearSize); // dwPitchOrLinearSize
rOut.WriteLong(0); // dwDepth
rOut.WriteLong(mNumMipMaps - 1); // dwMipMapCount
for (u32 i = 0; i < 11; i++)
out.WriteLong(0); // dwReserved1[11]
for (u32 iRes = 0; iRes < 11; iRes++)
rOut.WriteLong(0); // dwReserved1[11]
// DDS_PIXELFORMAT
out.WriteLong(32); // DDS_PIXELFORMAT.dwSize
rOut.WriteLong(32); // DDS_PIXELFORMAT.dwSize
u32 PFFlags = 0, PFBpp = 0, PFRBitMask = 0, PFGBitMask = 0, PFBBitMask = 0, PFABitMask = 0;
u32 pfFlags = 0, pfBpp = 0, pfRBitMask = 0, pfGBitMask = 0, pfBBitMask = 0, pfABitMask = 0;
switch (mTexelFormat) {
switch (mTexelFormat)
{
case eLuminance:
pfFlags = 0x20000;
pfBpp = 0x8;
pfRBitMask = 0xFF;
PFFlags = 0x20000;
PFBpp = 0x8;
PFRBitMask = 0xFF;
break;
case eLuminanceAlpha:
pfFlags = 0x20001;
pfBpp = 0x10;
pfRBitMask = 0x00FF;
pfABitMask = 0xFF00;
PFFlags = 0x20001;
PFBpp = 0x10;
PFRBitMask = 0x00FF;
PFABitMask = 0xFF00;
break;
case eRGBA4:
pfFlags = 0x41;
pfBpp = 0x10;
pfRBitMask = 0x0F00;
pfGBitMask = 0x00F0;
pfBBitMask = 0x000F;
pfABitMask = 0xF000;
PFFlags = 0x41;
PFBpp = 0x10;
PFRBitMask = 0x0F00;
PFGBitMask = 0x00F0;
PFBBitMask = 0x000F;
PFABitMask = 0xF000;
break;
case eRGB565:
pfFlags = 0x40;
pfBpp = 0x10;
pfRBitMask = 0xF800;
pfGBitMask = 0x7E0;
pfBBitMask = 0x1F;
PFFlags = 0x40;
PFBpp = 0x10;
PFRBitMask = 0xF800;
PFGBitMask = 0x7E0;
PFBBitMask = 0x1F;
break;
case eRGBA8:
pfFlags = 0x41;
pfBpp = 0x20;
pfRBitMask = 0x00FF0000;
pfGBitMask = 0x0000FF00;
pfBBitMask = 0x000000FF;
pfABitMask = 0xFF000000;
PFFlags = 0x41;
PFBpp = 0x20;
PFRBitMask = 0x00FF0000;
PFGBitMask = 0x0000FF00;
PFBBitMask = 0x000000FF;
PFABitMask = 0xFF000000;
break;
case eDXT1:
pfFlags = 0x4;
PFFlags = 0x4;
break;
}
out.WriteLong(pfFlags); // DDS_PIXELFORMAT.dwFlags
(mTexelFormat == eDXT1) ? out.WriteString("DXT1", 4) : out.WriteLong(0); // DDS_PIXELFORMAT.dwFourCC
out.WriteLong(pfBpp); // DDS_PIXELFORMAT.dwRGBBitCount
out.WriteLong(pfRBitMask); // DDS_PIXELFORMAT.dwRBitMask
out.WriteLong(pfGBitMask); // DDS_PIXELFORMAT.dwGBitMask
out.WriteLong(pfBBitMask); // DDS_PIXELFORMAT.dwBBitMask
out.WriteLong(pfABitMask); // DDS_PIXELFORMAT.dwABitMask
rOut.WriteLong(PFFlags); // DDS_PIXELFORMAT.dwFlags
(mTexelFormat == eDXT1) ? rOut.WriteString("DXT1", 4) : rOut.WriteLong(0); // DDS_PIXELFORMAT.dwFourCC
rOut.WriteLong(PFBpp); // DDS_PIXELFORMAT.dwRGBBitCount
rOut.WriteLong(PFRBitMask); // DDS_PIXELFORMAT.dwRBitMask
rOut.WriteLong(PFGBitMask); // DDS_PIXELFORMAT.dwGBitMask
rOut.WriteLong(PFBBitMask); // DDS_PIXELFORMAT.dwBBitMask
rOut.WriteLong(PFABitMask); // DDS_PIXELFORMAT.dwABitMask
out.WriteLong(0x401000); // dwCaps
out.WriteLong(0); // dwCaps2
out.WriteLong(0); // dwCaps3
out.WriteLong(0); // dwCaps4
out.WriteLong(0); // dwReserved2
rOut.WriteLong(0x401000); // dwCaps
rOut.WriteLong(0); // dwCaps2
rOut.WriteLong(0); // dwCaps3
rOut.WriteLong(0); // dwCaps4
rOut.WriteLong(0); // dwReserved2
out.WriteBytes(mImgDataBuffer, mImgDataSize); // Image data
rOut.WriteBytes(mpImgDataBuffer, mImgDataSize); // Image data
return true;
}
@@ -325,15 +307,15 @@ void CTexture::CopyGLBuffer()
// Clear existing buffer
if (mBufferExists)
{
delete[] mImgDataBuffer;
delete[] mpImgDataBuffer;
mBufferExists = false;
mImgDataBuffer = nullptr;
mpImgDataBuffer = nullptr;
mImgDataSize = 0;
}
// Calculate buffer size
mImgDataSize = CalcTotalSize();
mImgDataBuffer = new u8[mImgDataSize];
mpImgDataBuffer = new u8[mImgDataSize];
mBufferExists = true;
// Get texture
@@ -344,7 +326,7 @@ void CTexture::CopyGLBuffer()
for (u32 iMip = 0; iMip < mNumMipMaps; iMip++)
{
void *pData = mImgDataBuffer + MipOffset;
void *pData = mpImgDataBuffer + MipOffset;
glGetTexImage(GL_TEXTURE_2D, iMip, GL_RGBA, GL_UNSIGNED_BYTE, pData);
@@ -361,9 +343,9 @@ void CTexture::DeleteBuffers()
{
if (mBufferExists)
{
delete[] mImgDataBuffer;
delete[] mpImgDataBuffer;
mBufferExists = false;
mImgDataBuffer = nullptr;
mpImgDataBuffer = nullptr;
mImgDataSize = 0;
}

View File

@@ -21,32 +21,31 @@ class CTexture : public CResource
u32 mNumMipMaps; // The number of mipmaps this texture has
u32 mLinearSize; // The size of the top level mipmap, in bytes
bool mBufferExists; // Boolean that indicates whether image data buffer has valid data
u8 *mImgDataBuffer; // Pointer to image data buffer
u32 mImgDataSize; // Size of image data buffer
bool mBufferExists; // Indicates whether image data buffer has valid data
u8 *mpImgDataBuffer; // Pointer to image data buffer
u32 mImgDataSize; // Size of image data buffer
bool mGLBufferExists; // Boolean that indicates whether GL buffer has valid data
bool mGLBufferExists; // Indicates whether GL buffer has valid data
GLuint mTextureID; // ID for texture GL buffer
public:
CTexture();
CTexture(const CTexture& Source);
CTexture(u32 Width, u32 Height);
~CTexture();
bool BufferGL();
void Bind(u32 GLTextureUnit);
void Resize(u32 Width, u32 Height);
float ReadTexelAlpha(const CVector2f& TexCoord);
bool WriteDDS(IOutputStream& out);
float ReadTexelAlpha(const CVector2f& rkTexCoord);
bool WriteDDS(IOutputStream& rOut);
// Getters
ETexelFormat TexelFormat();
ETexelFormat SourceTexelFormat();
u32 Width();
u32 Height();
u32 NumMipMaps();
GLuint TextureID();
ETexelFormat TexelFormat() const { return mTexelFormat; }
ETexelFormat SourceTexelFormat() const { return mSourceTexelFormat; }
u32 Width() const { return (u32) mWidth; }
u32 Height() const { return (u32) mHeight; }
u32 NumMipMaps() const { return mNumMipMaps; }
GLuint TextureID() const { return mTextureID; }
// Static
static u32 FormatBPP(ETexelFormat Format);
@@ -59,28 +58,4 @@ private:
void DeleteBuffers();
};
inline ETexelFormat CTexture::TexelFormat() {
return mTexelFormat;
}
inline ETexelFormat CTexture::SourceTexelFormat() {
return mSourceTexelFormat;
}
inline u32 CTexture::Width() {
return (u32) mWidth;
}
inline u32 CTexture::Height() {
return (u32) mHeight;
}
inline u32 CTexture::NumMipMaps() {
return mNumMipMaps;
}
inline GLuint CTexture::TextureID() {
return mTextureID;
}
#endif // CTEXTURE_H

View File

@@ -2,14 +2,15 @@
#include "CResCache.h"
#include "Core/Resource/Script/CScriptLayer.h"
CWorld::CWorld() : CResource()
CWorld::CWorld()
: CResource()
, mWorldVersion(eUnknownVersion)
, mpWorldName(nullptr)
, mpDarkWorldName(nullptr)
, mpSaveWorld(nullptr)
, mpDefaultSkybox(nullptr)
, mpMapWorld(nullptr)
{
mWorldVersion = eUnknownVersion;
mpWorldName = nullptr;
mpDarkWorldName = nullptr;
mpSaveWorld = nullptr;
mpDefaultSkybox = nullptr;
mpMapWorld = nullptr;
}
CWorld::~CWorld()
@@ -23,76 +24,13 @@ void CWorld::SetAreaLayerInfo(CGameArea *pArea)
// the start window and the start window already knows the area index.
SArea& AreaInfo = mAreas[pArea->WorldIndex()];
for (u32 iLyr = 0; iLyr < pArea->GetScriptLayerCount(); iLyr++)
for (u32 iLyr = 0; iLyr < pArea->NumScriptLayers(); iLyr++)
{
if (AreaInfo.Layers.size() <= iLyr) break;
CScriptLayer *pLayer = pArea->GetScriptLayer(iLyr);
SArea::SLayer& LayerInfo = AreaInfo.Layers[iLyr];
CScriptLayer *pLayer = pArea->ScriptLayer(iLyr);
SArea::SLayer& rLayerInfo = AreaInfo.Layers[iLyr];
pLayer->SetName(LayerInfo.LayerName);
pLayer->SetActive(LayerInfo.EnabledByDefault);
pLayer->SetName(rLayerInfo.LayerName);
pLayer->SetActive(rLayerInfo.EnabledByDefault);
}
}
// ************ GETTERS ************
// World
EGame CWorld::Version()
{
return mWorldVersion;
}
CStringTable* CWorld::GetWorldName()
{
return mpWorldName;
}
CStringTable* CWorld::GetDarkWorldName()
{
return mpDarkWorldName;
}
CResource* CWorld::GetSaveWorld()
{
return mpSaveWorld;
}
CModel* CWorld::GetDefaultSkybox()
{
return mpDefaultSkybox;
}
CResource* CWorld::GetMapWorld()
{
return mpMapWorld;
}
// Area
u32 CWorld::GetNumAreas()
{
return mAreas.size();
}
u64 CWorld::GetAreaResourceID(u32 AreaIndex)
{
return mAreas[AreaIndex].FileID;
}
u32 CWorld::GetAreaAttachedCount(u32 AreaIndex)
{
return mAreas[AreaIndex].AttachedAreaIDs.size();
}
u32 CWorld::GetAreaAttachedID(u32 AreaIndex, u32 AttachedIndex)
{
return (u32) mAreas[AreaIndex].AttachedAreaIDs[AttachedIndex];
}
TString CWorld::GetAreaInternalName(u32 AreaIndex)
{
return mAreas[AreaIndex].InternalName;
}
CStringTable* CWorld::GetAreaName(u32 AreaIndex)
{
return mAreas[AreaIndex].pAreaName;
}

View File

@@ -86,20 +86,20 @@ public:
void SetAreaLayerInfo(CGameArea *pArea);
// Setters
EGame Version();
CStringTable* GetWorldName();
CStringTable* GetDarkWorldName();
CResource* GetSaveWorld();
CModel* GetDefaultSkybox();
CResource* GetMapWorld();
// Accessors
inline EGame Version() const { return mWorldVersion; }
inline CStringTable* WorldName() const { return mpWorldName; }
inline CStringTable* DarkWorldName() const { return mpDarkWorldName; }
inline CResource* SaveWorld() const { return mpSaveWorld; }
inline CModel* DefaultSkybox() const { return mpDefaultSkybox; }
inline CResource* MapWorld() const { return mpMapWorld; }
u32 GetNumAreas();
u64 GetAreaResourceID(u32 AreaIndex);
u32 GetAreaAttachedCount(u32 AreaIndex);
u32 GetAreaAttachedID(u32 AreaIndex, u32 AttachedIndex);
TString GetAreaInternalName(u32 AreaIndex);
CStringTable* GetAreaName(u32 AreaIndex);
inline u32 NumAreas() const { return mAreas.size(); }
inline u64 AreaResourceID(u32 AreaIndex) const { return mAreas[AreaIndex].FileID; }
inline u32 AreaAttachedCount(u32 AreaIndex) const { return mAreas[AreaIndex].AttachedAreaIDs.size(); }
inline u32 AreaAttachedID(u32 AreaIndex, u32 AttachedIndex) const { return mAreas[AreaIndex].AttachedAreaIDs[AttachedIndex]; }
inline TString AreaInternalName(u32 AreaIndex) const { return mAreas[AreaIndex].InternalName; }
inline CStringTable* AreaName(u32 AreaIndex) const { return mAreas[AreaIndex].pAreaName; }
};
#endif // CWORLD_H

View File

@@ -32,8 +32,8 @@ void CAreaCooker::DetermineSectionNumbersPrime()
break;
}
for (u32 iMesh = 0; iMesh < mpArea->mTerrainModels.size(); iMesh++)
GeometrySections += mpArea->mTerrainModels[iMesh]->GetSurfaceCount();
for (u32 iMesh = 0; iMesh < mpArea->mWorldModels.size(); iMesh++)
GeometrySections += mpArea->mWorldModels[iMesh]->GetSurfaceCount();
// Set section numbers
u32 SecNum = GeometrySections;
@@ -349,9 +349,9 @@ void CAreaCooker::WriteCookedArea(CGameArea *pArea, IOutputStream& rOut)
Cooker.WriteAreaData(rOut);
}
u32 CAreaCooker::GetMREAVersion(EGame version)
u32 CAreaCooker::GetMREAVersion(EGame Version)
{
switch (version)
switch (Version)
{
case ePrimeDemo: return 0xC;
case ePrime: return 0xF;

View File

@@ -64,7 +64,7 @@ class CAreaCooker
public:
static void WriteCookedArea(CGameArea *pArea, IOutputStream& rOut);
static u32 GetMREAVersion(EGame version);
static u32 GetMREAVersion(EGame Version);
};
#endif // CAREACOOKER_H

View File

@@ -2,11 +2,11 @@
#include <algorithm>
CMaterialCooker::CMaterialCooker()
: mpMat(nullptr)
{
mpMat = nullptr;
}
void CMaterialCooker::WriteMatSetPrime(IOutputStream& Out)
void CMaterialCooker::WriteMatSetPrime(IOutputStream& rOut)
{
// Gather texture list from the materials before starting
mTextureIDs.clear();
@@ -30,47 +30,46 @@ void CMaterialCooker::WriteMatSetPrime(IOutputStream& Out)
mTextureIDs.erase(std::unique(mTextureIDs.begin(), mTextureIDs.end()), mTextureIDs.end());
// Write texture IDs
Out.WriteLong(mTextureIDs.size());
rOut.WriteLong(mTextureIDs.size());
for (u32 iTex = 0; iTex < mTextureIDs.size(); iTex++)
Out.WriteLong(mTextureIDs[iTex]);
rOut.WriteLong(mTextureIDs[iTex]);
// Write material offset filler
Out.WriteLong(NumMats);
u32 MatOffsetsStart = Out.Tell();
rOut.WriteLong(NumMats);
u32 MatOffsetsStart = rOut.Tell();
for (u32 iMat = 0; iMat < NumMats; iMat++)
Out.WriteLong(0);
rOut.WriteLong(0);
// Write materials
u32 MatsStart = Out.Tell();
u32 MatsStart = rOut.Tell();
std::vector<u32> MatEndOffsets(NumMats);
for (u32 iMat = 0; iMat < NumMats; iMat++)
{
mpMat = mpSet->mMaterials[iMat];
WriteMaterialPrime(Out);
MatEndOffsets[iMat] = Out.Tell() - MatsStart;
WriteMaterialPrime(rOut);
MatEndOffsets[iMat] = rOut.Tell() - MatsStart;
}
// Write material offsets
u32 MatsEnd = Out.Tell();
Out.Seek(MatOffsetsStart, SEEK_SET);
u32 MatsEnd = rOut.Tell();
rOut.Seek(MatOffsetsStart, SEEK_SET);
for (u32 iMat = 0; iMat < NumMats; iMat++)
Out.WriteLong(MatEndOffsets[iMat]);
rOut.WriteLong(MatEndOffsets[iMat]);
// Done!
Out.Seek(MatsEnd, SEEK_SET);
rOut.Seek(MatsEnd, SEEK_SET);
}
void CMaterialCooker::WriteMatSetCorruption(IOutputStream&)
void CMaterialCooker::WriteMatSetCorruption(IOutputStream& /*rOut*/)
{
// Not using parameter 1 (IOutputStream& - Out)
// todo
}
void CMaterialCooker::WriteMaterialPrime(IOutputStream& Out)
void CMaterialCooker::WriteMaterialPrime(IOutputStream& rOut)
{
// Gather data from the passes before we start writing
u32 TexFlags = 0;
@@ -143,12 +142,12 @@ void CMaterialCooker::WriteMaterialPrime(IOutputStream& Out)
Flags |= (HasKonst ? 0x8 : 0x0) | (mpMat->Options() & ~0x8) | (TexFlags << 16);
Out.WriteLong(Flags);
rOut.WriteLong(Flags);
// Texture indices
Out.WriteLong(TexIndices.size());
rOut.WriteLong(TexIndices.size());
for (u32 iTex = 0; iTex < TexIndices.size(); iTex++)
Out.WriteLong(TexIndices[iTex]);
rOut.WriteLong(TexIndices[iTex]);
// Vertex description
FVertexDescription Desc = mpMat->VtxDesc();
@@ -156,24 +155,24 @@ void CMaterialCooker::WriteMaterialPrime(IOutputStream& Out)
if (mVersion < eEchoes)
Desc &= 0x00FFFFFF;
Out.WriteLong(Desc);
rOut.WriteLong(Desc);
// Echoes unknowns
if (mVersion == eEchoes)
{
Out.WriteLong(mpMat->EchoesUnknownA());
Out.WriteLong(mpMat->EchoesUnknownB());
rOut.WriteLong(mpMat->EchoesUnknownA());
rOut.WriteLong(mpMat->EchoesUnknownB());
}
// Group index
Out.WriteLong(GroupIndex);
rOut.WriteLong(GroupIndex);
// Konst
if (HasKonst)
{
Out.WriteLong(NumKonst);
rOut.WriteLong(NumKonst);
for (u32 iKonst = 0; iKonst < NumKonst; iKonst++)
Out.WriteLong( mpMat->Konst(iKonst).ToLongRGBA() );
rOut.WriteLong( mpMat->Konst(iKonst).ToLongRGBA() );
}
// Blend Mode
@@ -182,16 +181,16 @@ void CMaterialCooker::WriteMaterialPrime(IOutputStream& Out)
u16 BlendDstFac = (u16) mpMat->BlendDstFac();
if (BlendSrcFac >= 0x300) BlendSrcFac -= 0x2FE;
if (BlendDstFac >= 0x300) BlendDstFac -= 0x2FE;
Out.WriteShort(BlendDstFac);
Out.WriteShort(BlendSrcFac);
rOut.WriteShort(BlendDstFac);
rOut.WriteShort(BlendSrcFac);
// Color Channels
Out.WriteLong(1);
Out.WriteLong(0x3000 | (mpMat->IsLightingEnabled() ? 1 : 0));
rOut.WriteLong(1);
rOut.WriteLong(0x3000 | (mpMat->IsLightingEnabled() ? 1 : 0));
// TEV
u32 NumPasses = mpMat->PassCount();
Out.WriteLong(NumPasses);
rOut.WriteLong(NumPasses);
for (u32 iPass = 0; iPass < NumPasses; iPass++)
{
@@ -209,14 +208,14 @@ void CMaterialCooker::WriteMaterialPrime(IOutputStream& Out)
u32 ColorOpFlags = 0x100 | (pPass->ColorOutput() << 9);
u32 AlphaOpFlags = 0x100 | (pPass->AlphaOutput() << 9);
Out.WriteLong(ColorInputFlags);
Out.WriteLong(AlphaInputFlags);
Out.WriteLong(ColorOpFlags);
Out.WriteLong(AlphaOpFlags);
Out.WriteByte(0); // Padding
Out.WriteByte(pPass->KAlphaSel());
Out.WriteByte(pPass->KColorSel());
Out.WriteByte(pPass->RasSel());
rOut.WriteLong(ColorInputFlags);
rOut.WriteLong(AlphaInputFlags);
rOut.WriteLong(ColorOpFlags);
rOut.WriteLong(AlphaOpFlags);
rOut.WriteByte(0); // Padding
rOut.WriteByte(pPass->KAlphaSel());
rOut.WriteByte(pPass->KColorSel());
rOut.WriteByte(pPass->RasSel());
}
// TEV Tex/UV input selection
@@ -224,22 +223,22 @@ void CMaterialCooker::WriteMaterialPrime(IOutputStream& Out)
for (u32 iPass = 0; iPass < NumPasses; iPass++)
{
Out.WriteShort(0); // Padding
rOut.WriteShort(0); // Padding
if (mpMat->Pass(iPass)->Texture())
{
Out.WriteByte((u8) CurTexIdx);
Out.WriteByte((u8) CurTexIdx);
rOut.WriteByte((u8) CurTexIdx);
rOut.WriteByte((u8) CurTexIdx);
CurTexIdx++;
}
else
Out.WriteShort((u16) 0xFFFF);
rOut.WriteShort((u16) 0xFFFF);
}
// TexGen
u32 NumTexCoords = CurTexIdx; // TexIdx is currently equal to the tex coord count
Out.WriteLong(NumTexCoords);
rOut.WriteLong(NumTexCoords);
u32 CurTexMtx = 0;
for (u32 iPass = 0; iPass < NumPasses; iPass++)
@@ -280,15 +279,15 @@ void CMaterialCooker::WriteMaterialPrime(IOutputStream& Out)
}
u32 TexGenFlags = (CoordSource << 4) | (TexMtxIdx << 9) | (Normalize << 14) | (PostMtxIdx << 15);
Out.WriteLong(TexGenFlags);
rOut.WriteLong(TexGenFlags);
}
// Animations
u32 AnimSizeOffset = Out.Tell();
u32 AnimSizeOffset = rOut.Tell();
u32 NumAnims = CurTexMtx; // CurTexMtx is currently equal to the anim count
Out.WriteLong(0); // Anim size filler
u32 AnimsStart = Out.Tell();
Out.WriteLong(NumAnims);
rOut.WriteLong(0); // Anim size filler
u32 AnimsStart = rOut.Tell();
rOut.WriteLong(NumAnims);
for (u32 iPass = 0; iPass < NumPasses; iPass++)
{
@@ -296,38 +295,37 @@ void CMaterialCooker::WriteMaterialPrime(IOutputStream& Out)
u32 AnimMode = pPass->AnimMode();
if (AnimMode == eNoUVAnim) continue;
Out.WriteLong(AnimMode);
rOut.WriteLong(AnimMode);
if ((AnimMode > 1) && (AnimMode != 6))
{
Out.WriteFloat(pPass->AnimParam(0));
Out.WriteFloat(pPass->AnimParam(1));
rOut.WriteFloat(pPass->AnimParam(0));
rOut.WriteFloat(pPass->AnimParam(1));
if ((AnimMode == 2) || (AnimMode == 4) || (AnimMode == 5))
{
Out.WriteFloat(pPass->AnimParam(2));
Out.WriteFloat(pPass->AnimParam(3));
rOut.WriteFloat(pPass->AnimParam(2));
rOut.WriteFloat(pPass->AnimParam(3));
}
}
}
u32 AnimsEnd = Out.Tell();
u32 AnimsEnd = rOut.Tell();
u32 AnimsSize = AnimsEnd - AnimsStart;
Out.Seek(AnimSizeOffset, SEEK_SET);
Out.WriteLong(AnimsSize);
Out.Seek(AnimsEnd, SEEK_SET);
rOut.Seek(AnimSizeOffset, SEEK_SET);
rOut.WriteLong(AnimsSize);
rOut.Seek(AnimsEnd, SEEK_SET);
// Done!
}
void CMaterialCooker::WriteMaterialCorruption(IOutputStream&)
void CMaterialCooker::WriteMaterialCorruption(IOutputStream& /*rOut*/)
{
// Not using parameter 1 (IOutputStream& - Out)
// todo
}
// ************ STATIC ************
void CMaterialCooker::WriteCookedMatSet(CMaterialSet *pSet, EGame Version, IOutputStream &Out)
void CMaterialCooker::WriteCookedMatSet(CMaterialSet *pSet, EGame Version, IOutputStream& rOut)
{
CMaterialCooker Cooker;
Cooker.mpSet = pSet;
@@ -339,12 +337,12 @@ void CMaterialCooker::WriteCookedMatSet(CMaterialSet *pSet, EGame Version, IOutp
case ePrime:
case eEchoesDemo:
case eEchoes:
Cooker.WriteMatSetPrime(Out);
Cooker.WriteMatSetPrime(rOut);
break;
}
}
void CMaterialCooker::WriteCookedMaterial(CMaterial *pMat, EGame Version, IOutputStream &Out)
void CMaterialCooker::WriteCookedMaterial(CMaterial *pMat, EGame Version, IOutputStream& rOut)
{
CMaterialCooker Cooker;
Cooker.mpMat = pMat;
@@ -356,7 +354,7 @@ void CMaterialCooker::WriteCookedMaterial(CMaterial *pMat, EGame Version, IOutpu
case ePrime:
case eEchoesDemo:
case eEchoes:
Cooker.WriteMaterialPrime(Out);
Cooker.WriteMaterialPrime(rOut);
break;
// TODO: Corruption/Uncooked
}

View File

@@ -14,14 +14,14 @@ class CMaterialCooker
std::vector<u64> mMaterialHashes;
CMaterialCooker();
void WriteMatSetPrime(IOutputStream& Out);
void WriteMatSetCorruption(IOutputStream& Out);
void WriteMaterialPrime(IOutputStream& Out);
void WriteMaterialCorruption(IOutputStream& Out);
void WriteMatSetPrime(IOutputStream& rOut);
void WriteMatSetCorruption(IOutputStream& rOut);
void WriteMaterialPrime(IOutputStream& rOut);
void WriteMaterialCorruption(IOutputStream& rOut);
public:
static void WriteCookedMatSet(CMaterialSet *pSet, EGame Version, IOutputStream& Out);
static void WriteCookedMaterial(CMaterial *pMat, EGame Version, IOutputStream& Out);
static void WriteCookedMatSet(CMaterialSet *pSet, EGame Version, IOutputStream& rOut);
static void WriteCookedMaterial(CMaterial *pMat, EGame Version, IOutputStream& rOut);
};
#endif // CMATERIALCOOKER_H

View File

@@ -9,14 +9,6 @@ CModelCooker::CModelCooker()
{
}
bool SortVertsByArrayPos(const CVertex& A, const CVertex& B) {
return (A.ArrayPosition < B.ArrayPosition);
}
bool CheckDuplicateVertsByArrayPos(const CVertex& A, const CVertex& B) {
return (A.ArrayPosition == B.ArrayPosition);
}
void CModelCooker::GenerateSurfaceData()
{
// Need to gather metadata from the model before we can start
@@ -60,65 +52,65 @@ void CModelCooker::GenerateSurfaceData()
mNumVertices = mVertices.size();
}
void CModelCooker::WriteEditorModel(IOutputStream& /*Out*/)
void CModelCooker::WriteEditorModel(IOutputStream& /*rOut*/)
{
}
void CModelCooker::WriteModelPrime(IOutputStream& Out)
void CModelCooker::WriteModelPrime(IOutputStream& rOut)
{
GenerateSurfaceData();
// Header
Out.WriteLong(0xDEADBABE);
Out.WriteLong(GetCMDLVersion(mVersion));
Out.WriteLong(5);
mpModel->mAABox.Write(Out);
rOut.WriteLong(0xDEADBABE);
rOut.WriteLong(GetCMDLVersion(mVersion));
rOut.WriteLong(5);
mpModel->mAABox.Write(rOut);
u32 NumSections = mNumMatSets + mNumSurfaces + 6;
Out.WriteLong(NumSections);
Out.WriteLong(mNumMatSets);
rOut.WriteLong(NumSections);
rOut.WriteLong(mNumMatSets);
u32 SectionSizesOffset = Out.Tell();
u32 SectionSizesOffset = rOut.Tell();
for (u32 iSec = 0; iSec < NumSections; iSec++)
Out.WriteLong(0);
rOut.WriteLong(0);
Out.WriteToBoundary(32, 0);
rOut.WriteToBoundary(32, 0);
std::vector<u32> SectionSizes;
SectionSizes.reserve(NumSections);
CSectionMgrOut SectionMgr;
SectionMgr.SetSectionCount(NumSections);
SectionMgr.Init(Out);
SectionMgr.Init(rOut);
// Materials
for (u32 iSet = 0; iSet < mNumMatSets; iSet++)
{
CMaterialCooker::WriteCookedMatSet(mpModel->mMaterialSets[iSet], mVersion, Out);
Out.WriteToBoundary(32, 0);
SectionMgr.AddSize(Out);
CMaterialCooker::WriteCookedMatSet(mpModel->mMaterialSets[iSet], mVersion, rOut);
rOut.WriteToBoundary(32, 0);
SectionMgr.AddSize(rOut);
}
// Vertices
for (u32 iPos = 0; iPos < mNumVertices; iPos++)
mVertices[iPos].Position.Write(Out);
mVertices[iPos].Position.Write(rOut);
Out.WriteToBoundary(32, 0);
SectionMgr.AddSize(Out);
rOut.WriteToBoundary(32, 0);
SectionMgr.AddSize(rOut);
// Normals
for (u32 iNrm = 0; iNrm < mNumVertices; iNrm++)
mVertices[iNrm].Normal.Write(Out);
mVertices[iNrm].Normal.Write(rOut);
Out.WriteToBoundary(32, 0);
SectionMgr.AddSize(Out);
rOut.WriteToBoundary(32, 0);
SectionMgr.AddSize(rOut);
// Colors
for (u32 iColor = 0; iColor < mNumVertices; iColor++)
mVertices[iColor].Color[0].Write(Out);
mVertices[iColor].Color[0].Write(rOut);
Out.WriteToBoundary(32, 0);
SectionMgr.AddSize(Out);
rOut.WriteToBoundary(32, 0);
SectionMgr.AddSize(rOut);
// Float UV coordinates
for (u32 iTexSlot = 0; iTexSlot < 8; iTexSlot++)
@@ -127,50 +119,50 @@ void CModelCooker::WriteModelPrime(IOutputStream& Out)
if (HasTexSlot)
{
for (u32 iTex = 0; iTex < mNumVertices; iTex++)
mVertices[iTex].Tex[iTexSlot].Write(Out);
mVertices[iTex].Tex[iTexSlot].Write(rOut);
}
}
Out.WriteToBoundary(32, 0);
SectionMgr.AddSize(Out);
SectionMgr.AddSize(Out); // Skipping short UV coordinates
rOut.WriteToBoundary(32, 0);
SectionMgr.AddSize(rOut);
SectionMgr.AddSize(rOut); // Skipping short UV coordinates
// Surface offsets
Out.WriteLong(mNumSurfaces);
u32 SurfaceOffsetsStart = Out.Tell();
rOut.WriteLong(mNumSurfaces);
u32 SurfaceOffsetsStart = rOut.Tell();
for (u32 iSurf = 0; iSurf < mNumSurfaces; iSurf++)
Out.WriteLong(0);
rOut.WriteLong(0);
Out.WriteToBoundary(32, 0);
SectionMgr.AddSize(Out);
rOut.WriteToBoundary(32, 0);
SectionMgr.AddSize(rOut);
// Surfaces
u32 SurfacesStart = Out.Tell();
u32 SurfacesStart = rOut.Tell();
std::vector<u32> SurfaceEndOffsets(mNumSurfaces);
for (u32 iSurf = 0; iSurf < mNumSurfaces; iSurf++)
{
SSurface *pSurface = mpModel->GetSurface(iSurf);
pSurface->CenterPoint.Write(Out);
Out.WriteLong(pSurface->MaterialID);
Out.WriteShort((u16) 0x8000);
u32 PrimTableSizeOffset = Out.Tell();
Out.WriteShort(0);
Out.WriteLongLong(0);
Out.WriteLong(0);
pSurface->ReflectionDirection.Write(Out);
Out.WriteToBoundary(32, 0);
pSurface->CenterPoint.Write(rOut);
rOut.WriteLong(pSurface->MaterialID);
rOut.WriteShort((u16) 0x8000);
u32 PrimTableSizeOffset = rOut.Tell();
rOut.WriteShort(0);
rOut.WriteLongLong(0);
rOut.WriteLong(0);
pSurface->ReflectionDirection.Write(rOut);
rOut.WriteToBoundary(32, 0);
u32 PrimTableStart = Out.Tell();
u32 PrimTableStart = rOut.Tell();
FVertexDescription MatAttribs = mpModel->GetMaterialBySurface(0, iSurf)->VtxDesc();
for (u32 iPrim = 0; iPrim < pSurface->Primitives.size(); iPrim++)
{
SSurface::SPrimitive *pPrimitive = &pSurface->Primitives[iPrim];
Out.WriteByte((u8) pPrimitive->Type);
Out.WriteShort((u16) pPrimitive->Vertices.size());
rOut.WriteByte((u8) pPrimitive->Type);
rOut.WriteShort((u16) pPrimitive->Vertices.size());
for (u32 iVert = 0; iVert < pPrimitive->Vertices.size(); iVert++)
{
@@ -180,59 +172,59 @@ void CModelCooker::WriteModelPrime(IOutputStream& Out)
{
for (u32 iMtxAttribs = 0; iMtxAttribs < 8; iMtxAttribs++)
if (MatAttribs & (ePosMtx << iMtxAttribs))
Out.WriteByte(pVert->MatrixIndices[iMtxAttribs]);
rOut.WriteByte(pVert->MatrixIndices[iMtxAttribs]);
}
u16 VertexIndex = (u16) pVert->ArrayPosition;
if (MatAttribs & ePosition)
Out.WriteShort(VertexIndex);
rOut.WriteShort(VertexIndex);
if (MatAttribs & eNormal)
Out.WriteShort(VertexIndex);
rOut.WriteShort(VertexIndex);
if (MatAttribs & eColor0)
Out.WriteShort(VertexIndex);
rOut.WriteShort(VertexIndex);
if (MatAttribs & eColor1)
Out.WriteShort(VertexIndex);
rOut.WriteShort(VertexIndex);
u16 TexOffset = 0;
for (u32 iTex = 0; iTex < 8; iTex++)
{
if (MatAttribs & (eTex0 << (iTex * 2)))
{
Out.WriteShort(VertexIndex + TexOffset);
rOut.WriteShort(VertexIndex + TexOffset);
TexOffset += (u16) mNumVertices;
}
}
}
}
Out.WriteToBoundary(32, 0);
u32 PrimTableEnd = Out.Tell();
rOut.WriteToBoundary(32, 0);
u32 PrimTableEnd = rOut.Tell();
u32 PrimTableSize = PrimTableEnd - PrimTableStart;
Out.Seek(PrimTableSizeOffset, SEEK_SET);
Out.WriteShort((u16) PrimTableSize);
Out.Seek(PrimTableEnd, SEEK_SET);
rOut.Seek(PrimTableSizeOffset, SEEK_SET);
rOut.WriteShort((u16) PrimTableSize);
rOut.Seek(PrimTableEnd, SEEK_SET);
SectionMgr.AddSize(Out);
SurfaceEndOffsets[iSurf] = Out.Tell() - SurfacesStart;
SectionMgr.AddSize(rOut);
SurfaceEndOffsets[iSurf] = rOut.Tell() - SurfacesStart;
}
// Done writing the file - now we go back to fill in surface offsets + section sizes
Out.Seek(SurfaceOffsetsStart, SEEK_SET);
rOut.Seek(SurfaceOffsetsStart, SEEK_SET);
for (u32 iSurf = 0; iSurf < mNumSurfaces; iSurf++)
Out.WriteLong(SurfaceEndOffsets[iSurf]);
rOut.WriteLong(SurfaceEndOffsets[iSurf]);
Out.Seek(SectionSizesOffset, SEEK_SET);
SectionMgr.WriteSizes(Out);
rOut.Seek(SectionSizesOffset, SEEK_SET);
SectionMgr.WriteSizes(rOut);
// Done!
}
void CModelCooker::WriteCookedModel(CModel *pModel, EGame Version, IOutputStream& CMDL)
void CModelCooker::WriteCookedModel(CModel *pModel, EGame Version, IOutputStream& rOut)
{
CModelCooker Cooker;
Cooker.mpModel = pModel;
@@ -244,12 +236,12 @@ void CModelCooker::WriteCookedModel(CModel *pModel, EGame Version, IOutputStream
case ePrime:
case eEchoesDemo:
case eEchoes:
Cooker.WriteModelPrime(CMDL);
Cooker.WriteModelPrime(rOut);
break;
}
}
void CModelCooker::WriteUncookedModel(CModel* /*pModel*/, IOutputStream& /*EMDL*/)
void CModelCooker::WriteUncookedModel(CModel* /*pModel*/, IOutputStream& /*rOut*/)
{
}

View File

@@ -18,12 +18,12 @@ class CModelCooker
CModelCooker();
void GenerateSurfaceData();
void WriteEditorModel(IOutputStream& Out);
void WriteModelPrime(IOutputStream& Out);
void WriteEditorModel(IOutputStream& rOut);
void WriteModelPrime(IOutputStream& rOut);
public:
static void WriteCookedModel(CModel *pModel, EGame Version, IOutputStream& Out);
static void WriteUncookedModel(CModel *pModel, IOutputStream& Out);
static void WriteCookedModel(CModel *pModel, EGame Version, IOutputStream& rOut);
static void WriteUncookedModel(CModel *pModel, IOutputStream& rOut);
static u32 GetCMDLVersion(EGame Version);
};

View File

@@ -12,13 +12,13 @@ void CPoiToWorldCooker::WriteEGMC(CPoiToWorld *pPoiToWorld, IOutputStream& rOut)
for (u32 iPoi = 0; iPoi < pPoiToWorld->NumMappedPOIs(); iPoi++)
{
const CPoiToWorld::SPoiMap *kpMap = pPoiToWorld->MapByIndex(iPoi);
const CPoiToWorld::SPoiMap *pkMap = pPoiToWorld->MapByIndex(iPoi);
for (auto it = kpMap->ModelIDs.begin(); it != kpMap->ModelIDs.end(); it++)
for (auto it = pkMap->ModelIDs.begin(); it != pkMap->ModelIDs.end(); it++)
{
SPoiMapping Mapping;
Mapping.MeshID = *it;
Mapping.PoiID = kpMap->PoiID;
Mapping.PoiID = pkMap->PoiID;
Mappings.push_back(Mapping);
}
}

View File

@@ -1,33 +0,0 @@
#include "CSectionMgrOut.h"
CSectionMgrOut::CSectionMgrOut()
{
mSectionCount = 0;
mCurSectionStart = 0;
mCurSectionIndex = 0;
}
void CSectionMgrOut::SetSectionCount(u32 Count)
{
mSectionCount = Count;
mSectionSizes.resize(Count);
}
void CSectionMgrOut::Init(const IOutputStream& OutputStream)
{
mCurSectionStart = OutputStream.Tell();
mCurSectionIndex = 0;
}
void CSectionMgrOut::AddSize(IOutputStream& OutputStream)
{
mSectionSizes[mCurSectionIndex] = OutputStream.Tell() - mCurSectionStart;
mCurSectionIndex++;
mCurSectionStart = OutputStream.Tell();
}
void CSectionMgrOut::WriteSizes(IOutputStream& OutputStream)
{
for (u32 iSec = 0; iSec < mSectionCount; iSec++)
OutputStream.WriteLong(mSectionSizes[iSec]);
}

View File

@@ -14,11 +14,36 @@ class CSectionMgrOut
std::vector<u32> mSectionSizes;
public:
CSectionMgrOut();
void SetSectionCount(u32 Count);
void Init(const IOutputStream& OutputStream);
void AddSize(IOutputStream& OutputStream);
void WriteSizes(IOutputStream& OutputStream);
CSectionMgrOut()
: mSectionCount(0)
, mCurSectionStart(0)
, mCurSectionIndex(0)
{}
void SetSectionCount(u32 Count)
{
mSectionCount = Count;
mSectionSizes.resize(Count);
}
void Init(const IOutputStream& rOut)
{
mCurSectionStart = rOut.Tell();
mCurSectionIndex = 0;
}
void AddSize(IOutputStream& rOut)
{
mSectionSizes[mCurSectionIndex] = rOut.Tell() - mCurSectionStart;
mCurSectionIndex++;
mCurSectionStart = rOut.Tell();
}
void WriteSizes(IOutputStream& rOut)
{
for (u32 iSec = 0; iSec < mSectionCount; iSec++)
rOut.WriteLong(mSectionSizes[iSec]);
}
};
#endif // CBLOCKMGROUT_H

View File

@@ -41,7 +41,7 @@ void CTemplateWriter::SavePropertyTemplate(IPropertyTemplate *pTemp)
void CTemplateWriter::SaveAllTemplates()
{
// Create directory
std::list<CMasterTemplate*> MasterList = CMasterTemplate::GetMasterList();
std::list<CMasterTemplate*> MasterList = CMasterTemplate::MasterList();
boost::filesystem::create_directory(smTemplatesDir.ToStdString());
// Resave property list
@@ -77,8 +77,8 @@ void CTemplateWriter::SaveAllTemplates()
pGame->LinkEndChild(pGameName);
XMLElement *pAreaVersion = GameList.NewElement("mrea");
u32 VersionNumber = CAreaCooker::GetMREAVersion(pMaster->GetGame());
pAreaVersion->SetText(*TString::HexString(VersionNumber, true, true, 2));
u32 VersionNumber = CAreaCooker::GetMREAVersion(pMaster->Game());
pAreaVersion->SetText(*TString::HexString(VersionNumber, 2));
pGame->LinkEndChild(pAreaVersion);
XMLElement *pTempPath = GameList.NewElement("master");
@@ -139,7 +139,7 @@ void CTemplateWriter::SaveGameTemplates(CMasterTemplate *pMaster)
TString StrID;
if (ObjID <= 0xFF)
StrID = TString::HexString(ObjID, true, true, 2);
StrID = TString::HexString(ObjID, 2);
else
StrID = CFourCC(ObjID).ToString();
@@ -177,7 +177,7 @@ void CTemplateWriter::SaveGameTemplates(CMasterTemplate *pMaster)
}
TString StrID;
if (ID <= 0xFF) StrID = TString::HexString(ID, true, true, 2);
if (ID <= 0xFF) StrID = TString::HexString(ID, 2);
else StrID = CFourCC(ID).ToString();
XMLElement *pSubElem = Master.NewElement(*Type);
@@ -210,7 +210,7 @@ void CTemplateWriter::SavePropertyList()
TString Name = it->second;
XMLElement *pElem = List.NewElement("property");
pElem->SetAttribute("ID", *TString::HexString(ID, true, true, 8));
pElem->SetAttribute("ID", *TString::HexString(ID));
pElem->SetAttribute("name", *Name);
pBase->LinkEndChild(pElem);
}
@@ -262,7 +262,7 @@ void CTemplateWriter::SaveScriptTemplate(CScriptTemplate *pTemp)
XMLElement *pEditorProperties = ScriptXML.NewElement("properties");
pEditor->LinkEndChild(pEditorProperties);
TString propNames[6] = {
TString PropNames[6] = {
"InstanceName", "Position", "Rotation",
"Scale", "Active", "LightParameters"
};
@@ -277,7 +277,7 @@ void CTemplateWriter::SaveScriptTemplate(CScriptTemplate *pTemp)
if (!pPropStrings[iProp]->IsEmpty())
{
XMLElement *pProperty = ScriptXML.NewElement("property");
pProperty->SetAttribute("name", *propNames[iProp]);
pProperty->SetAttribute("name", *PropNames[iProp]);
pProperty->SetAttribute("ID", **pPropStrings[iProp]);
pEditorProperties->LinkEndChild(pProperty);
}
@@ -373,7 +373,7 @@ void CTemplateWriter::SaveScriptTemplate(CScriptTemplate *pTemp)
if (pProp->Type() == eBoolProperty)
StrVal = (it->Value == 1 ? "true" : "false");
else
StrVal = TString::HexString((u32) it->Value, true, true, (it->Value > 0xFF ? 8 : 2));
StrVal = TString::HexString((u32) it->Value, (it->Value > 0xFF ? 8 : 2));
XMLElement *pCondition = ScriptXML.NewElement("condition");
pCondition->SetAttribute("value", *StrVal);
@@ -469,7 +469,7 @@ void CTemplateWriter::SaveProperties(XMLDocument *pDoc, XMLElement *pParent, CSt
// Get ID
IPropertyTemplate *pProp = pTemp->PropertyByIndex(iProp);
u32 ID = pProp->PropertyID();
TString StrID = TString::HexString(ID, true, true, (ID > 0xFF ? 8 : 2));
TString StrID = TString::HexString(ID, (ID > 0xFF ? 8 : 2));
// Create element
XMLElement *pElem;
@@ -495,7 +495,7 @@ void CTemplateWriter::SaveProperties(XMLDocument *pDoc, XMLElement *pParent, CSt
if (pProp->Game() >= eEchoesDemo && ID > 0xFF)
{
TString MasterName = CMasterTemplate::GetPropertyName(ID);
TString MasterName = CMasterTemplate::PropertyName(ID);
if (Name != MasterName)
pElem->SetAttribute("name", *Name);
@@ -652,7 +652,7 @@ void CTemplateWriter::SaveProperties(XMLDocument *pDoc, XMLElement *pParent, CSt
else
{
CStructTemplate *pOriginal = pMaster->GetStructAtSource(pStruct->mSourceFile);
CStructTemplate *pOriginal = pMaster->StructAtSource(pStruct->mSourceFile);
if (pOriginal)
SavePropertyOverrides(pDoc, pElem, pStruct, pOriginal);
@@ -696,7 +696,7 @@ void CTemplateWriter::SavePropertyOverrides(XMLDocument *pDoc, XMLElement *pPare
// ID
u32 ID = pProp->PropertyID();
pElem->SetAttribute("ID", *TString::HexString(pProp->PropertyID(), true, true, (ID > 0xFF ? 8 : 2)));
pElem->SetAttribute("ID", *TString::HexString(pProp->PropertyID(), (ID > 0xFF ? 8 : 2)));
// Name
if (pProp->Name() != pSource->Name())
@@ -793,7 +793,7 @@ void CTemplateWriter::SaveEnumerators(XMLDocument *pDoc, XMLElement *pParent, CE
{
XMLElement *pElem = pDoc->NewElement("enumerator");
u32 EnumerID = pTemp->EnumeratorID(iEnum);
pElem->SetAttribute("ID", *TString::HexString(EnumerID, true, true, (EnumerID > 0xFF ? 8 : 2)));
pElem->SetAttribute("ID", *TString::HexString(EnumerID, (EnumerID > 0xFF ? 8 : 2)));
pElem->SetAttribute("name", *pTemp->EnumeratorName(iEnum));
pEnumerators->LinkEndChild(pElem);
}
@@ -807,7 +807,7 @@ void CTemplateWriter::SaveBitFlags(XMLDocument *pDoc, XMLElement *pParent, CBitf
for (u32 iFlag = 0; iFlag < pTemp->NumFlags(); iFlag++)
{
XMLElement *pElem = pDoc->NewElement("flag");
pElem->SetAttribute("mask", *TString::HexString(pTemp->FlagMask(iFlag), true, true, 8));
pElem->SetAttribute("mask", *TString::HexString(pTemp->FlagMask(iFlag)));
pElem->SetAttribute("name", *pTemp->FlagName(iFlag));
pFlags->LinkEndChild(pElem);
}

View File

@@ -2,34 +2,34 @@
#include <Common/Log.h>
CTextureEncoder::CTextureEncoder()
: mpTexture(nullptr)
{
mpTexture = nullptr;
}
void CTextureEncoder::WriteTXTR(IOutputStream& TXTR)
void CTextureEncoder::WriteTXTR(IOutputStream& rTXTR)
{
// Only DXT1->CMPR supported at the moment
TXTR.WriteLong(mOutputFormat);
TXTR.WriteShort(mpTexture->mWidth);
TXTR.WriteShort(mpTexture->mHeight);
TXTR.WriteLong(mpTexture->mNumMipMaps);
rTXTR.WriteLong(mOutputFormat);
rTXTR.WriteShort(mpTexture->mWidth);
rTXTR.WriteShort(mpTexture->mHeight);
rTXTR.WriteLong(mpTexture->mNumMipMaps);
u32 MipW = mpTexture->Width() / 4;
u32 MipH = mpTexture->Height() / 4;
CMemoryInStream Image(mpTexture->mImgDataBuffer, mpTexture->mImgDataSize, IOUtil::eLittleEndian);
CMemoryInStream Image(mpTexture->mpImgDataBuffer, mpTexture->mImgDataSize, IOUtil::eLittleEndian);
u32 MipOffset = Image.Tell();
for (u32 iMip = 0; iMip < mpTexture->mNumMipMaps; iMip++)
{
for (u32 BlockY = 0; BlockY < MipH; BlockY += 2)
for (u32 BlockX = 0; BlockX < MipW; BlockX += 2)
for (u32 ImgY = BlockY; ImgY < BlockY + 2; ImgY++)
for (u32 ImgX = BlockX; ImgX < BlockX + 2; ImgX++)
for (u32 iBlockY = 0; iBlockY < MipH; iBlockY += 2)
for (u32 iBlockX = 0; iBlockX < MipW; iBlockX += 2)
for (u32 iImgY = iBlockY; iImgY < iBlockY + 2; iImgY++)
for (u32 iImgX = iBlockX; iImgX < iBlockX + 2; iImgX++)
{
u32 SrcPos = ((ImgY * MipW) + ImgX) * 8;
u32 SrcPos = ((iImgY * MipW) + iImgX) * 8;
Image.Seek(MipOffset + SrcPos, SEEK_SET);
ReadSubBlockCMPR(Image, TXTR);
ReadSubBlockCMPR(Image, rTXTR);
}
MipOffset += MipW * MipH * 8;
@@ -45,20 +45,21 @@ void CTextureEncoder::DetermineBestOutputFormat()
// todo
}
void CTextureEncoder::ReadSubBlockCMPR(IInputStream& Source, IOutputStream& Dest)
void CTextureEncoder::ReadSubBlockCMPR(IInputStream& rSource, IOutputStream& rDest)
{
Dest.WriteShort(Source.ReadShort());
Dest.WriteShort(Source.ReadShort());
rDest.WriteShort(rSource.ReadShort());
rDest.WriteShort(rSource.ReadShort());
for (u32 byte = 0; byte < 4; byte++) {
u8 b = Source.ReadByte();
b = ((b & 0x3) << 6) | ((b & 0xC) << 2) | ((b & 0x30) >> 2) | ((b & 0xC0) >> 6);
Dest.WriteByte(b);
for (u32 iByte = 0; iByte < 4; iByte++)
{
u8 Byte = rSource.ReadByte();
Byte = ((Byte & 0x3) << 6) | ((Byte & 0xC) << 2) | ((Byte & 0x30) >> 2) | ((Byte & 0xC0) >> 6);
rDest.WriteByte(Byte);
}
}
// ************ STATIC ************
void CTextureEncoder::EncodeTXTR(IOutputStream& TXTR, CTexture *pTex)
void CTextureEncoder::EncodeTXTR(IOutputStream& rTXTR, CTexture *pTex)
{
if (pTex->mTexelFormat != eDXT1)
{
@@ -70,13 +71,13 @@ void CTextureEncoder::EncodeTXTR(IOutputStream& TXTR, CTexture *pTex)
Encoder.mpTexture = pTex;
Encoder.mSourceFormat = eDXT1;
Encoder.mOutputFormat = eGX_CMPR;
Encoder.WriteTXTR(TXTR);
Encoder.WriteTXTR(rTXTR);
}
void CTextureEncoder::EncodeTXTR(IOutputStream& TXTR, CTexture *pTex, ETexelFormat /*OutputFormat*/)
void CTextureEncoder::EncodeTXTR(IOutputStream& rTXTR, CTexture *pTex, ETexelFormat /*OutputFormat*/)
{
// todo: support for encoding a specific format
EncodeTXTR(TXTR, pTex);
EncodeTXTR(rTXTR, pTex);
}
ETexelFormat CTextureEncoder::GetGXFormat(ETexelFormat Format)

View File

@@ -13,13 +13,13 @@ class CTextureEncoder
ETexelFormat mOutputFormat;
CTextureEncoder();
void WriteTXTR(IOutputStream& TXTR);
void WriteTXTR(IOutputStream& rTXTR);
void DetermineBestOutputFormat();
void ReadSubBlockCMPR(IInputStream& Source, IOutputStream& Dest);
void ReadSubBlockCMPR(IInputStream& rSource, IOutputStream& rDest);
public:
static void EncodeTXTR(IOutputStream& TXTR, CTexture *pTex);
static void EncodeTXTR(IOutputStream& TXTR, CTexture *pTex, ETexelFormat OutputFormat);
static void EncodeTXTR(IOutputStream& rTXTR, CTexture *pTex);
static void EncodeTXTR(IOutputStream& rTXTR, CTexture *pTex, ETexelFormat OutputFormat);
static ETexelFormat GetGXFormat(ETexelFormat Format);
static ETexelFormat GetFormat(ETexelFormat Format);
};

View File

@@ -4,9 +4,9 @@ CWorldCooker::CWorldCooker()
{
}
u32 CWorldCooker::GetMLVLVersion(EGame version)
u32 CWorldCooker::GetMLVLVersion(EGame Version)
{
switch (version)
switch (Version)
{
case ePrimeDemo: return 0xD;
case ePrime: return 0x11;

View File

@@ -8,7 +8,7 @@ class CWorldCooker
{
CWorldCooker();
public:
static u32 GetMLVLVersion(EGame version);
static u32 GetMLVLVersion(EGame Version);
};
#endif // CWORLDCOOKER_H

View File

@@ -4,14 +4,14 @@
// Global version enum that can be easily shared between loaders
enum EGame
{
ePrimeDemo = 0,
ePrime = 1,
eEchoesDemo = 2,
eEchoes = 3,
eCorruptionProto = 4,
eCorruption = 5,
eReturns = 6,
eUnknownVersion = -1
ePrimeDemo = 0,
ePrime = 1,
eEchoesDemo = 2,
eEchoes = 3,
eCorruptionProto = 4,
eCorruption = 5,
eReturns = 6,
eUnknownVersion = -1
};
#endif // EGAME_H

View File

@@ -6,189 +6,192 @@ CAnimSetLoader::CAnimSetLoader()
{
}
CAnimSet* CAnimSetLoader::LoadCorruptionCHAR(IInputStream& CHAR)
CAnimSet* CAnimSetLoader::LoadCorruptionCHAR(IInputStream& rCHAR)
{
// For now, we only read enough to fetch the model
CHAR.Seek(0x1, SEEK_CUR);
set->nodes.resize(1);
CAnimSet::SNode& node = set->nodes[0];
rCHAR.Seek(0x1, SEEK_CUR);
pSet->mNodes.resize(1);
CAnimSet::SNode& node = pSet->mNodes[0];
node.name = CHAR.ReadString();
node.model = gResCache.GetResource(CHAR.ReadLongLong(), "CMDL");
return set;
node.Name = rCHAR.ReadString();
node.pModel = gResCache.GetResource(rCHAR.ReadLongLong(), "CMDL");
return pSet;
}
CAnimSet* CAnimSetLoader::LoadReturnsCHAR(IInputStream& CHAR)
CAnimSet* CAnimSetLoader::LoadReturnsCHAR(IInputStream& rCHAR)
{
// For now, we only read enough to fetch the model
CHAR.Seek(0x16, SEEK_CUR);
set->nodes.resize(1);
CAnimSet::SNode& node = set->nodes[0];
rCHAR.Seek(0x16, SEEK_CUR);
pSet->mNodes.resize(1);
CAnimSet::SNode& rNode = pSet->mNodes[0];
node.name = CHAR.ReadString();
CHAR.Seek(0x14, SEEK_CUR);
CHAR.ReadString();
node.model = gResCache.GetResource(CHAR.ReadLongLong(), "CMDL");
return set;
rNode.Name = rCHAR.ReadString();
rCHAR.Seek(0x14, SEEK_CUR);
rCHAR.ReadString();
rNode.pModel = gResCache.GetResource(rCHAR.ReadLongLong(), "CMDL");
return pSet;
}
void CAnimSetLoader::LoadPASDatabase(IInputStream& PAS4)
void CAnimSetLoader::LoadPASDatabase(IInputStream& rPAS4)
{
// For now, just parse the data; don't store it
PAS4.Seek(0x4, SEEK_CUR); // Skipping PAS4 FourCC
u32 anim_state_count = PAS4.ReadLong();
PAS4.Seek(0x4, SEEK_CUR); // Skipping default anim state
rPAS4.Seek(0x4, SEEK_CUR); // Skipping PAS4 FourCC
u32 AnimStateCount = rPAS4.ReadLong();
rPAS4.Seek(0x4, SEEK_CUR); // Skipping default anim state
for (u32 s = 0; s < anim_state_count; s++)
for (u32 iState = 0; iState < AnimStateCount; iState++)
{
PAS4.Seek(0x4, SEEK_CUR); // Skipping unknown value
u32 parm_info_count = PAS4.ReadLong();
u32 anim_info_count = PAS4.ReadLong();
rPAS4.Seek(0x4, SEEK_CUR); // Skipping unknown value
u32 ParmInfoCount = rPAS4.ReadLong();
u32 AnimInfoCount = rPAS4.ReadLong();
u32 skip = 0;
for (u32 p = 0; p < parm_info_count; p++)
u32 Skip = 0;
for (u32 iParm = 0; iParm < ParmInfoCount; iParm++)
{
u32 type = PAS4.ReadLong();
PAS4.Seek(0x8, SEEK_CUR);
u32 Type = rPAS4.ReadLong();
rPAS4.Seek(0x8, SEEK_CUR);
switch (type) {
switch (Type) {
case 0: // Int32
case 1: // Uint32
case 2: // Real32
case 4: // Enum
PAS4.Seek(0x8, SEEK_CUR);
skip += 4;
rPAS4.Seek(0x8, SEEK_CUR);
Skip += 4;
break;
case 3: // Bool
PAS4.Seek(0x2, SEEK_CUR);
skip++;
rPAS4.Seek(0x2, SEEK_CUR);
Skip++;
break;
}
}
for (u32 a = 0; a < anim_info_count; a++)
PAS4.Seek(0x4 + skip, SEEK_CUR);
for (u32 iInfo = 0; iInfo < AnimInfoCount; iInfo++)
rPAS4.Seek(0x4 + Skip, SEEK_CUR);
}
}
// ************ STATIC ************
CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& ANCS)
CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS)
{
if (!ANCS.IsValid()) return nullptr;
if (!rANCS.IsValid()) return nullptr;
u32 magic = ANCS.ReadLong();
if (magic != 0x00010001)
u32 Magic = rANCS.ReadLong();
if (Magic != 0x00010001)
{
Log::FileError(ANCS.GetSourceString(), "Invalid ANCS magic: " + TString::HexString(magic));
Log::FileError(rANCS.GetSourceString(), "Invalid ANCS magic: " + TString::HexString(Magic));
return nullptr;
}
CAnimSetLoader loader;
loader.set = new CAnimSet;
CAnimSetLoader Loader;
Loader.pSet = new CAnimSet;
u32 node_count = ANCS.ReadLong();
loader.set->nodes.resize(node_count);
u32 NodeCount = rANCS.ReadLong();
Loader.pSet->mNodes.resize(NodeCount);
for (u32 n = 0; n < node_count; n++)
for (u32 iNode = 0; iNode < NodeCount; iNode++)
{
CAnimSet::SNode *node = &loader.set->nodes[n];
CAnimSet::SNode *pNode = &Loader.pSet->mNodes[iNode];
ANCS.Seek(0x4, SEEK_CUR); // Skipping node self-index
u16 unknown1 = ANCS.ReadShort();
if (n == 0) loader.mVersion = (unknown1 == 0xA) ? eEchoes : ePrime; // Best version indicator we know of unfortunately
node->name = ANCS.ReadString();
node->model = gResCache.GetResource(ANCS.ReadLong(), "CMDL");
node->skinID = ANCS.ReadLong();
node->skelID = ANCS.ReadLong();
rANCS.Seek(0x4, SEEK_CUR); // Skipping node self-index
u16 Unknown1 = rANCS.ReadShort();
if (iNode == 0) Loader.mVersion = (Unknown1 == 0xA) ? eEchoes : ePrime; // Best version indicator we know of unfortunately
pNode->Name = rANCS.ReadString();
pNode->pModel = gResCache.GetResource(rANCS.ReadLong(), "CMDL");
pNode->SkinID = rANCS.ReadLong();
pNode->SkelID = rANCS.ReadLong();
// Unfortunately that's all that's actually supported at the moment. Hope to expand later.
// Since there's no size value I have to actually read the rest of the node to reach the next one
u32 anim_count = ANCS.ReadLong();
for (u32 a = 0; a < anim_count; a++)
u32 AnimCount = rANCS.ReadLong();
for (u32 iAnim = 0; iAnim < AnimCount; iAnim++)
{
ANCS.Seek(0x4, SEEK_CUR);
if (loader.mVersion == ePrime) ANCS.Seek(0x1, SEEK_CUR);
ANCS.ReadString();
rANCS.Seek(0x4, SEEK_CUR);
if (Loader.mVersion == ePrime) rANCS.Seek(0x1, SEEK_CUR);
rANCS.ReadString();
}
// PAS Database
loader.LoadPASDatabase(ANCS);
Loader.LoadPASDatabase(rANCS);
// Particles
u32 particle_count = ANCS.ReadLong();
ANCS.Seek(particle_count * 4, SEEK_CUR);
u32 swoosh_count = ANCS.ReadLong();
ANCS.Seek(swoosh_count * 4, SEEK_CUR);
if (unknown1 != 5) ANCS.Seek(0x4, SEEK_CUR);
u32 electric_count = ANCS.ReadLong();
ANCS.Seek(electric_count * 4, SEEK_CUR);
if (loader.mVersion == eEchoes) {
u32 spsc_count = ANCS.ReadLong();
ANCS.Seek(spsc_count * 4, SEEK_CUR);
}
ANCS.Seek(0x4, SEEK_CUR);
if (loader.mVersion == eEchoes) ANCS.Seek(0x4, SEEK_CUR);
u32 ParticleCount = rANCS.ReadLong();
rANCS.Seek(ParticleCount * 4, SEEK_CUR);
u32 SwooshCount = rANCS.ReadLong();
rANCS.Seek(SwooshCount * 4, SEEK_CUR);
if (Unknown1 != 5) rANCS.Seek(0x4, SEEK_CUR);
u32 ElectricCount = rANCS.ReadLong();
rANCS.Seek(ElectricCount * 4, SEEK_CUR);
u32 anim_count2 = ANCS.ReadLong();
for (u32 a = 0; a < anim_count2; a++)
if (Loader.mVersion == eEchoes)
{
ANCS.ReadString();
ANCS.Seek(0x18, SEEK_CUR);
u32 SPSCCount = rANCS.ReadLong();
rANCS.Seek(SPSCCount * 4, SEEK_CUR);
}
u32 EffectGroupCount = ANCS.ReadLong();
for (u32 g = 0; g < EffectGroupCount; g++)
{
ANCS.ReadString();
u32 EffectCount = ANCS.ReadLong();
rANCS.Seek(0x4, SEEK_CUR);
if (Loader.mVersion == eEchoes) rANCS.Seek(0x4, SEEK_CUR);
for (u32 e = 0; e < EffectCount; e++)
u32 AnimCount2 = rANCS.ReadLong();
for (u32 iAnim = 0; iAnim < AnimCount2; iAnim++)
{
rANCS.ReadString();
rANCS.Seek(0x18, SEEK_CUR);
}
u32 EffectGroupCount = rANCS.ReadLong();
for (u32 iGrp = 0; iGrp < EffectGroupCount; iGrp++)
{
rANCS.ReadString();
u32 EffectCount = rANCS.ReadLong();
for (u32 iEffect = 0; iEffect < EffectCount; iEffect++)
{
ANCS.ReadString();
ANCS.Seek(0x8, SEEK_CUR);
if (loader.mVersion == ePrime) ANCS.ReadString();
if (loader.mVersion == eEchoes) ANCS.Seek(0x4, SEEK_CUR);
ANCS.Seek(0xC, SEEK_CUR);
rANCS.ReadString();
rANCS.Seek(0x8, SEEK_CUR);
if (Loader.mVersion == ePrime) rANCS.ReadString();
if (Loader.mVersion == eEchoes) rANCS.Seek(0x4, SEEK_CUR);
rANCS.Seek(0xC, SEEK_CUR);
}
}
ANCS.Seek(0x8, SEEK_CUR);
rANCS.Seek(0x8, SEEK_CUR);
u32 unknown_count = ANCS.ReadLong();
ANCS.Seek(unknown_count * 4, SEEK_CUR);
u32 UnknownCount = rANCS.ReadLong();
rANCS.Seek(UnknownCount * 4, SEEK_CUR);
if (loader.mVersion == eEchoes)
if (Loader.mVersion == eEchoes)
{
ANCS.Seek(0x5, SEEK_CUR);
u32 unknown_count2 = ANCS.ReadLong();
ANCS.Seek(unknown_count2 * 0x1C, SEEK_CUR);
rANCS.Seek(0x5, SEEK_CUR);
u32 UnknownCount2 = rANCS.ReadLong();
rANCS.Seek(UnknownCount2 * 0x1C, SEEK_CUR);
}
// Lots of work for data I'm not even using x.x
}
return loader.set;
return Loader.pSet;
}
CAnimSet* CAnimSetLoader::LoadCHAR(IInputStream &CHAR)
CAnimSet* CAnimSetLoader::LoadCHAR(IInputStream& rCHAR)
{
if (!CHAR.IsValid()) return nullptr;
if (!rCHAR.IsValid()) return nullptr;
CAnimSetLoader loader;
u8 check = CHAR.ReadByte();
CAnimSetLoader Loader;
u8 Check = rCHAR.ReadByte();
if (check == 0x5 || check == 0x3)
if (Check == 0x5 || Check == 0x3)
{
loader.mVersion = eCorruption;
loader.set = new CAnimSet();
return loader.LoadCorruptionCHAR(CHAR);
Loader.mVersion = eCorruption;
Loader.pSet = new CAnimSet();
return Loader.LoadCorruptionCHAR(rCHAR);
}
if (check == 0x59)
if (Check == 0x59)
{
loader.mVersion = eReturns;
loader.set = new CAnimSet();
return loader.LoadReturnsCHAR(CHAR);
Loader.mVersion = eReturns;
Loader.pSet = new CAnimSet();
return Loader.LoadReturnsCHAR(rCHAR);
}
Log::FileError(CHAR.GetSourceString(), "CHAR has invalid first byte: " + TString::HexString(check));
Log::FileError(rCHAR.GetSourceString(), "CHAR has invalid first byte: " + TString::HexString(Check, 2));
return nullptr;
}

View File

@@ -7,18 +7,18 @@
class CAnimSetLoader
{
TResPtr<CAnimSet> set;
TResPtr<CAnimSet> pSet;
CResCache *mpResCache;
EGame mVersion;
CAnimSetLoader();
CAnimSet* LoadCorruptionCHAR(IInputStream& CHAR);
CAnimSet* LoadReturnsCHAR(IInputStream& CHAR);
void LoadPASDatabase(IInputStream& PAS4);
CAnimSet* LoadCorruptionCHAR(IInputStream& rCHAR);
CAnimSet* LoadReturnsCHAR(IInputStream& rCHAR);
void LoadPASDatabase(IInputStream& rPAS4);
public:
static CAnimSet* LoadANCS(IInputStream& ANCS);
static CAnimSet* LoadCHAR(IInputStream& CHAR);
static CAnimSet* LoadANCS(IInputStream& rANCS);
static CAnimSet* LoadCHAR(IInputStream& rCHAR);
};
#endif // CCHARACTERLOADER_H

View File

@@ -11,26 +11,26 @@
#include <iostream>
CAreaLoader::CAreaLoader()
: mpMREA(nullptr)
, mHasDecompressedBuffer(false)
, mGeometryBlockNum(-1)
, mScriptLayerBlockNum(-1)
, mCollisionBlockNum(-1)
, mUnknownBlockNum(-1)
, mLightsBlockNum(-1)
, mEmptyBlockNum(-1)
, mPathBlockNum(-1)
, mOctreeBlockNum(-1)
, mScriptGeneratorBlockNum(-1)
, mFFFFBlockNum(-1)
, mUnknown2BlockNum(-1)
, mEGMCBlockNum(-1)
, mBoundingBoxesBlockNum(-1)
, mDependenciesBlockNum(-1)
, mGPUBlockNum(-1)
, mPVSBlockNum(-1)
, mRSOBlockNum(-1)
{
mpMREA = nullptr;
mHasDecompressedBuffer = false;
mGeometryBlockNum = -1;
mScriptLayerBlockNum = -1;
mCollisionBlockNum = -1;
mUnknownBlockNum = -1;
mLightsBlockNum = -1;
mEmptyBlockNum = -1;
mPathBlockNum = -1;
mOctreeBlockNum = -1;
mScriptGeneratorBlockNum = -1;
mFFFFBlockNum = -1;
mUnknown2BlockNum = -1;
mEGMCBlockNum = -1;
mBoundingBoxesBlockNum = -1;
mDependenciesBlockNum = -1;
mGPUBlockNum = -1;
mPVSBlockNum = -1;
mRSOBlockNum = -1;
}
CAreaLoader::~CAreaLoader()
@@ -38,7 +38,7 @@ CAreaLoader::~CAreaLoader()
if (mHasDecompressedBuffer)
{
delete mpMREA;
delete[] mDecmpBuffer;
delete[] mpDecmpBuffer;
}
}
@@ -177,17 +177,17 @@ void CAreaLoader::ReadLightsPrime()
Log::FileWrite(mpMREA->GetSourceString(), "Reading MREA dynamic lights (MP1/MP2)");
mpSectionMgr->ToSection(mLightsBlockNum);
u32 babedead = mpMREA->ReadLong();
if (babedead != 0xbabedead) return;
u32 BabeDead = mpMREA->ReadLong();
if (BabeDead != 0xbabedead) return;
mpArea->mLightLayers.resize(2);
for (u32 ly = 0; ly < 2; ly++)
for (u32 iLyr = 0; iLyr < 2; iLyr++)
{
u32 NumLights = mpMREA->ReadLong();
mpArea->mLightLayers[ly].resize(NumLights);
mpArea->mLightLayers[iLyr].resize(NumLights);
for (u32 l = 0; l < NumLights; l++)
for (u32 iLight = 0; iLight < NumLights; iLight++)
{
ELightType Type = ELightType(mpMREA->ReadLong());
CVector3f Color(*mpMREA);
@@ -200,9 +200,9 @@ void CAreaLoader::ReadLightsPrime()
mpMREA->Seek(0x4, SEEK_CUR);
// Relevant data is read - now we process and form a CLight out of it
CLight *Light;
CLight *pLight;
CColor LightColor = CColor(Color.x, Color.y, Color.z, 0.f);
CColor LightColor = CColor(Color.X, Color.Y, Color.Z, 0.f);
if (Multiplier < FLT_EPSILON)
Multiplier = FLT_EPSILON;
@@ -212,29 +212,29 @@ void CAreaLoader::ReadLightsPrime()
Color *= Multiplier;
// Clamp
if (Color.x > 1.f) Color.x = 1.f;
if (Color.y > 1.f) Color.y = 1.f;
if (Color.z > 1.f) Color.z = 1.f;
CColor MultColor(Color.x, Color.y, Color.z, 1.f);
if (Color.X > 1.f) Color.X = 1.f;
if (Color.Y > 1.f) Color.Y = 1.f;
if (Color.Z > 1.f) Color.Z = 1.f;
CColor MultColor(Color.X, Color.Y, Color.Z, 1.f);
Light = CLight::BuildLocalAmbient(Position, MultColor);
pLight = CLight::BuildLocalAmbient(Position, MultColor);
}
// Directional
else if (Type == eDirectional)
{
Light = CLight::BuildDirectional(Position, Direction, LightColor);
pLight = CLight::BuildDirectional(Position, Direction, LightColor);
}
// Spot
else if (Type == eSpot)
{
Light = CLight::BuildSpot(Position, Direction.Normalized(), LightColor, SpotCutoff);
pLight = CLight::BuildSpot(Position, Direction.Normalized(), LightColor, SpotCutoff);
float DistAttenA = (FalloffType == 0) ? (2.f / Multiplier) : 0.f;
float DistAttenB = (FalloffType == 1) ? (250.f / Multiplier) : 0.f;
float DistAttenC = (FalloffType == 2) ? (25000.f / Multiplier) : 0.f;
Light->SetDistAtten(DistAttenA, DistAttenB, DistAttenC);
pLight->SetDistAtten(DistAttenA, DistAttenB, DistAttenC);
}
// Custom
@@ -244,13 +244,13 @@ void CAreaLoader::ReadLightsPrime()
float DistAttenB = (FalloffType == 1) ? (249.9998f / Multiplier) : 0.f;
float DistAttenC = (FalloffType == 2) ? (25000.f / Multiplier) : 0.f;
Light = CLight::BuildCustom(Position, Direction, LightColor,
pLight = CLight::BuildCustom(Position, Direction, LightColor,
DistAttenA, DistAttenB, DistAttenC,
1.f, 0.f, 0.f);
}
Light->SetLayer(ly);
mpArea->mLightLayers[ly][l] = Light;
pLight->SetLayer(iLyr);
mpArea->mLightLayers[iLyr][iLight] = pLight;
}
}
}
@@ -435,8 +435,8 @@ void CAreaLoader::ReadLightsCorruption()
Log::FileWrite(mpMREA->GetSourceString(), "Reading MREA dynamic lights (MP3)");
mpSectionMgr->ToSection(mLightsBlockNum);
u32 babedead = mpMREA->ReadLong();
if (babedead != 0xbabedead) return;
u32 BabeDead = mpMREA->ReadLong();
if (BabeDead != 0xbabedead) return;
mpArea->mLightLayers.resize(4);
@@ -449,11 +449,11 @@ void CAreaLoader::ReadLightsCorruption()
{
ELightType Type = (ELightType) mpMREA->ReadLong();
float r = mpMREA->ReadFloat();
float g = mpMREA->ReadFloat();
float b = mpMREA->ReadFloat();
float a = mpMREA->ReadFloat();
CColor LightColor(r, g, b, a);
float R = mpMREA->ReadFloat();
float G = mpMREA->ReadFloat();
float B = mpMREA->ReadFloat();
float A = mpMREA->ReadFloat();
CColor LightColor(R, G, B, A);
CVector3f Position(*mpMREA);
CVector3f Direction(*mpMREA);
@@ -466,7 +466,7 @@ void CAreaLoader::ReadLightsCorruption()
mpMREA->Seek(0x18, SEEK_CUR);
// Relevant data is read - now we process and form a CLight out of it
CLight *Light;
CLight *pLight;
if (Multiplier < FLT_EPSILON)
Multiplier = FLT_EPSILON;
@@ -474,24 +474,24 @@ void CAreaLoader::ReadLightsCorruption()
// Local Ambient
if (Type == eLocalAmbient)
{
Light = CLight::BuildLocalAmbient(Position, LightColor * Multiplier);
pLight = CLight::BuildLocalAmbient(Position, LightColor * Multiplier);
}
// Directional
else if (Type == eDirectional)
{
Light = CLight::BuildDirectional(Position, Direction, LightColor);
pLight = CLight::BuildDirectional(Position, Direction, LightColor);
}
// Spot
else if (Type == eSpot)
{
Light = CLight::BuildSpot(Position, Direction.Normalized(), LightColor, SpotCutoff);
pLight = CLight::BuildSpot(Position, Direction.Normalized(), LightColor, SpotCutoff);
float DistAttenA = (FalloffType == 0) ? (2.f / Multiplier) : 0.f;
float DistAttenB = (FalloffType == 1) ? (250.f / Multiplier) : 0.f;
float DistAttenC = (FalloffType == 2) ? (25000.f / Multiplier) : 0.f;
Light->SetDistAtten(DistAttenA, DistAttenB, DistAttenC);
pLight->SetDistAtten(DistAttenA, DistAttenB, DistAttenC);
}
// Custom
@@ -501,13 +501,13 @@ void CAreaLoader::ReadLightsCorruption()
float DistAttenB = (FalloffType == 1) ? (249.9998f / Multiplier) : 0.f;
float DistAttenC = (FalloffType == 2) ? (25000.f / Multiplier) : 0.f;
Light = CLight::BuildCustom(Position, Direction, LightColor,
pLight = CLight::BuildCustom(Position, Direction, LightColor,
DistAttenA, DistAttenB, DistAttenC,
1.f, 0.f, 0.f);
}
Light->SetLayer(iLayer);
mpArea->mLightLayers[iLayer][iLight] = Light;
pLight->SetLayer(iLayer);
mpArea->mLightLayers[iLayer][iLight] = pLight;
}
}
}
@@ -517,15 +517,15 @@ void CAreaLoader::ReadCompressedBlocks()
{
mTotalDecmpSize = 0;
for (u32 c = 0; c < mClusters.size(); c++)
for (u32 iClust = 0; iClust < mClusters.size(); iClust++)
{
mClusters[c].BufferSize = mpMREA->ReadLong();
mClusters[c].DecompressedSize = mpMREA->ReadLong();
mClusters[c].CompressedSize = mpMREA->ReadLong();
mClusters[c].NumSections = mpMREA->ReadLong();
mTotalDecmpSize += mClusters[c].DecompressedSize;
mClusters[iClust].BufferSize = mpMREA->ReadLong();
mClusters[iClust].DecompressedSize = mpMREA->ReadLong();
mClusters[iClust].CompressedSize = mpMREA->ReadLong();
mClusters[iClust].NumSections = mpMREA->ReadLong();
mTotalDecmpSize += mClusters[iClust].DecompressedSize;
if (mClusters[c].CompressedSize != 0) mpArea->mUsesCompression = true;
if (mClusters[iClust].CompressedSize != 0) mpArea->mUsesCompression = true;
}
mpMREA->SeekToBoundary(32);
@@ -539,39 +539,39 @@ void CAreaLoader::Decompress()
if (mVersion < eEchoes) return;
// Decompress clusters
mDecmpBuffer = new u8[mTotalDecmpSize];
mpDecmpBuffer = new u8[mTotalDecmpSize];
u32 Offset = 0;
for (u32 c = 0; c < mClusters.size(); c++)
for (u32 iClust = 0; iClust < mClusters.size(); iClust++)
{
SCompressedCluster *cc = &mClusters[c];
SCompressedCluster *pClust = &mClusters[iClust];
// Is it decompressed already?
if (mClusters[c].CompressedSize == 0)
if (mClusters[iClust].CompressedSize == 0)
{
mpMREA->ReadBytes(mDecmpBuffer + Offset, cc->DecompressedSize);
Offset += cc->DecompressedSize;
mpMREA->ReadBytes(mpDecmpBuffer + Offset, pClust->DecompressedSize);
Offset += pClust->DecompressedSize;
}
else
{
u32 StartOffset = 32 - (mClusters[c].CompressedSize % 32); // For some reason they pad the beginning instead of the end
u32 StartOffset = 32 - (mClusters[iClust].CompressedSize % 32); // For some reason they pad the beginning instead of the end
if (StartOffset != 32)
mpMREA->Seek(StartOffset, SEEK_CUR);
std::vector<u8> cmp(mClusters[c].CompressedSize);
mpMREA->ReadBytes(cmp.data(), cmp.size());
std::vector<u8> CompressedBuf(mClusters[iClust].CompressedSize);
mpMREA->ReadBytes(CompressedBuf.data(), CompressedBuf.size());
bool Success = CompressionUtil::DecompressSegmentedData(cmp.data(), cmp.size(), mDecmpBuffer + Offset, cc->DecompressedSize);
bool Success = CompressionUtil::DecompressSegmentedData(CompressedBuf.data(), CompressedBuf.size(), mpDecmpBuffer + Offset, pClust->DecompressedSize);
if (!Success)
throw "Failed to decompress MREA!";
Offset += cc->DecompressedSize;
Offset += pClust->DecompressedSize;
}
}
TString Source = mpMREA->GetSourceString();
mpMREA = new CMemoryInStream(mDecmpBuffer, mTotalDecmpSize, IOUtil::eBigEndian);
mpMREA = new CMemoryInStream(mpDecmpBuffer, mTotalDecmpSize, IOUtil::eBigEndian);
mpMREA->SetSourceString(Source.ToStdString());
mpSectionMgr->SetInputStream(mpMREA);
mHasDecompressedBuffer = true;
@@ -609,14 +609,14 @@ void CAreaLoader::ReadEGMC()
void CAreaLoader::SetUpObjects()
{
// Iterate over all objects
for (u32 iLyr = 0; iLyr < mpArea->GetScriptLayerCount() + 1; iLyr++)
for (u32 iLyr = 0; iLyr < mpArea->NumScriptLayers() + 1; iLyr++)
{
CScriptLayer *pLayer;
if (iLyr < mpArea->GetScriptLayerCount()) pLayer = mpArea->mScriptLayers[iLyr];
if (iLyr < mpArea->NumScriptLayers()) pLayer = mpArea->mScriptLayers[iLyr];
else
{
pLayer = mpArea->GetGeneratorLayer();
pLayer = mpArea->GeneratedObjectsLayer();
if (!pLayer) break;
}
@@ -657,17 +657,17 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA)
// Validation
if (!MREA.IsValid()) return nullptr;
u32 deadbeef = MREA.ReadLong();
if (deadbeef != 0xdeadbeef)
u32 DeadBeef = MREA.ReadLong();
if (DeadBeef != 0xdeadbeef)
{
Log::FileError(MREA.GetSourceString(), "Invalid MREA magic: " + TString::HexString(deadbeef));
Log::FileError(MREA.GetSourceString(), "Invalid MREA magic: " + TString::HexString(DeadBeef));
return nullptr;
}
// Header
Loader.mpArea = new CGameArea;
u32 version = MREA.ReadLong();
Loader.mVersion = GetFormatVersion(version);
u32 Version = MREA.ReadLong();
Loader.mVersion = GetFormatVersion(Version);
Loader.mpArea->mVersion = Loader.mVersion;
Loader.mpMREA = &MREA;
@@ -718,7 +718,7 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA)
}
break;
default:
Log::FileError(MREA.GetSourceString(), "Unsupported MREA version: " + TString::HexString(version));
Log::FileError(MREA.GetSourceString(), "Unsupported MREA version: " + TString::HexString(Version, 0));
Loader.mpArea.Delete();
return nullptr;
}
@@ -728,9 +728,9 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA)
return Loader.mpArea;
}
EGame CAreaLoader::GetFormatVersion(u32 version)
EGame CAreaLoader::GetFormatVersion(u32 Version)
{
switch (version)
switch (Version)
{
case 0xC: return ePrimeDemo;
case 0xF: return ePrime;

View File

@@ -25,7 +25,7 @@ class CAreaLoader
std::unordered_map<u32, std::vector<CLink*>> mConnectionMap;
// Compression
u8 *mDecmpBuffer;
u8 *mpDecmpBuffer;
bool mHasDecompressedBuffer;
std::vector<SCompressedCluster> mClusters;
u32 mTotalDecmpSize;
@@ -80,8 +80,8 @@ class CAreaLoader
void SetUpObjects();
public:
static CGameArea* LoadMREA(IInputStream& MREA);
static EGame GetFormatVersion(u32 version);
static CGameArea* LoadMREA(IInputStream& rMREA);
static EGame GetFormatVersion(u32 Version);
};
#endif // CAREALOADER_H

View File

@@ -6,201 +6,201 @@ CCollisionLoader::CCollisionLoader()
{
}
CCollisionMesh::CCollisionOctree* CCollisionLoader::ParseOctree(IInputStream& /*src*/)
CCollisionMesh::CCollisionOctree* CCollisionLoader::ParseOctree(IInputStream& /*rSrc*/)
{
return nullptr;
}
CCollisionMesh::CCollisionOctree::SBranch* CCollisionLoader::ParseOctreeBranch(IInputStream& /*src*/)
CCollisionMesh::CCollisionOctree::SBranch* CCollisionLoader::ParseOctreeBranch(IInputStream& /*rSrc*/)
{
return nullptr;
}
CCollisionMesh::CCollisionOctree::SLeaf* CCollisionLoader::ParseOctreeLeaf(IInputStream& /*src*/)
CCollisionMesh::CCollisionOctree::SLeaf* CCollisionLoader::ParseOctreeLeaf(IInputStream& /*rSrc*/)
{
return nullptr;
}
void CCollisionLoader::ParseOBBNode(IInputStream& DCLN)
void CCollisionLoader::ParseOBBNode(IInputStream& rDCLN)
{
bool b = false;
while (b == false)
{
DCLN.Seek(0x3C, SEEK_CUR);
b = (DCLN.ReadByte() == 1);
if (!b) ParseOBBNode(DCLN);
rDCLN.Seek(0x3C, SEEK_CUR);
b = (rDCLN.ReadByte() == 1);
if (!b) ParseOBBNode(rDCLN);
}
u32 numFaces = DCLN.ReadLong();
DCLN.Seek(numFaces * 2, SEEK_CUR);
u32 NumFaces = rDCLN.ReadLong();
rDCLN.Seek(NumFaces * 2, SEEK_CUR);
}
void CCollisionLoader::ReadPropertyFlags(IInputStream& src)
void CCollisionLoader::ReadPropertyFlags(IInputStream& rSrc)
{
CCollisionMesh::SCollisionProperties property;
CCollisionMesh::SCollisionProperties Property;
if (mVersion == ePrime)
{
u32 flag = src.ReadLong();
property.Invert = (flag >> 25) & 0x1;
u32 Flag = rSrc.ReadLong();
Property.Invert = (Flag >> 25) & 0x1;
}
else if (mVersion == eEchoes)
{
u64 flag = src.ReadLongLong();
property.Invert = (flag >> 24) & 0x1;
u64 Flag = rSrc.ReadLongLong();
Property.Invert = (Flag >> 24) & 0x1;
}
else if (mVersion == eReturns)
{
u64 flag = src.ReadLongLong();
property.Invert = (flag >> 28) & 0x1;
u64 Flag = rSrc.ReadLongLong();
Property.Invert = (Flag >> 28) & 0x1;
}
mProperties.push_back(property);
mProperties.push_back(Property);
}
void CCollisionLoader::LoadCollisionIndices(IInputStream &file, bool buildAABox)
void CCollisionLoader::LoadCollisionIndices(IInputStream &rFile, bool BuildAABox)
{
// Properties
u32 propSetCount = file.ReadLong();
for (u32 iProp = 0; iProp < propSetCount; iProp++)
ReadPropertyFlags(file);
u32 PropSetCount = rFile.ReadLong();
for (u32 iProp = 0; iProp < PropSetCount; iProp++)
ReadPropertyFlags(rFile);
// Property indices for vertices/lines/faces
u32 vtxIndexCount = file.ReadLong();
std::vector<u8> vtxIndices(vtxIndexCount);
file.ReadBytes(vtxIndices.data(), vtxIndices.size());
u32 VtxIndexCount = rFile.ReadLong();
std::vector<u8> VtxIndices(VtxIndexCount);
rFile.ReadBytes(VtxIndices.data(), VtxIndices.size());
u32 lineIndexCount = file.ReadLong();
std::vector<u8> lineIndices(lineIndexCount);
file.ReadBytes(lineIndices.data(), lineIndices.size());
u32 LineIndexCount = rFile.ReadLong();
std::vector<u8> LineIndices(LineIndexCount);
rFile.ReadBytes(LineIndices.data(), LineIndices.size());
u32 faceIndexCount = file.ReadLong();
std::vector<u8> faceIndices(faceIndexCount);
file.ReadBytes(faceIndices.data(), faceIndices.size());
u32 FaceIndexCount = rFile.ReadLong();
std::vector<u8> FaceIndices(FaceIndexCount);
rFile.ReadBytes(FaceIndices.data(), FaceIndices.size());
// Lines
mpMesh->mLineCount = file.ReadLong();
mpMesh->mLineCount = rFile.ReadLong();
mpMesh->mCollisionLines.resize(mpMesh->mLineCount);
for (u32 iLine = 0; iLine < mpMesh->mLineCount; iLine++)
{
CCollisionMesh::CCollisionLine *pLine = &mpMesh->mCollisionLines[iLine];
pLine->Vertices[0] = file.ReadShort();
pLine->Vertices[1] = file.ReadShort();
pLine->Properties = mProperties[lineIndices[iLine]];
pLine->Vertices[0] = rFile.ReadShort();
pLine->Vertices[1] = rFile.ReadShort();
pLine->Properties = mProperties[LineIndices[iLine]];
}
// Faces
mpMesh->mFaceCount = file.ReadLong() / 3; // Not sure why they store it this way. It's inconsistent.
mpMesh->mFaceCount = rFile.ReadLong() / 3; // Not sure why they store it this way. It's inconsistent.
mpMesh->mCollisionFaces.resize(mpMesh->mFaceCount);
for (u32 iFace = 0; iFace < mpMesh->mFaceCount; iFace++)
{
CCollisionMesh::CCollisionFace *pFace = &mpMesh->mCollisionFaces[iFace];
pFace->Lines[0] = file.ReadShort();
pFace->Lines[1] = file.ReadShort();
pFace->Lines[2] = file.ReadShort();
pFace->Properties = mProperties[faceIndices[iFace]];
pFace->Lines[0] = rFile.ReadShort();
pFace->Lines[1] = rFile.ReadShort();
pFace->Lines[2] = rFile.ReadShort();
pFace->Properties = mProperties[FaceIndices[iFace]];
}
// Echoes introduces a new data chunk; don't know what it is yet, skipping for now
if (mVersion >= eEchoes)
{
u32 unknownCount = file.ReadLong();
file.Seek(unknownCount * 2, SEEK_CUR);
u32 UnknownCount = rFile.ReadLong();
rFile.Seek(UnknownCount * 2, SEEK_CUR);
}
// Vertices
mpMesh->mVertexCount = file.ReadLong();
mpMesh->mVertexCount = rFile.ReadLong();
mpMesh->mCollisionVertices.resize(mpMesh->mVertexCount);
CAABox bounds;
CAABox Bounds;
for (u32 iVtx = 0; iVtx < mpMesh->mVertexCount; iVtx++)
{
CCollisionMesh::CCollisionVertex *pVtx = &mpMesh->mCollisionVertices[iVtx];
pVtx->Pos = CVector3f(file);
pVtx->Properties = mProperties[vtxIndices[iVtx]];
if (buildAABox) bounds.ExpandBounds(pVtx->Pos);
pVtx->Pos = CVector3f(rFile);
pVtx->Properties = mProperties[VtxIndices[iVtx]];
if (BuildAABox) Bounds.ExpandBounds(pVtx->Pos);
}
if (buildAABox) mpMesh->mAABox = bounds;
if (BuildAABox) mpMesh->mAABox = Bounds;
}
// ************ STATIC ************
CCollisionMeshGroup* CCollisionLoader::LoadAreaCollision(IInputStream& MREA)
CCollisionMeshGroup* CCollisionLoader::LoadAreaCollision(IInputStream& rMREA)
{
if (!MREA.IsValid()) return nullptr;
if (!rMREA.IsValid()) return nullptr;
CCollisionLoader loader;
MREA.Seek(0x8, SEEK_CUR);
u32 deafbabe = MREA.ReadLong();
if (deafbabe != 0xDEAFBABE)
rMREA.Seek(0x8, SEEK_CUR);
u32 DeafBabe = rMREA.ReadLong();
if (DeafBabe != 0xDEAFBABE)
{
Log::FileError(MREA.GetSourceString(), MREA.Tell() - 4, "Invalid collision magic: " + TString::HexString(deafbabe));
Log::FileError(rMREA.GetSourceString(), rMREA.Tell() - 4, "Invalid collision magic: " + TString::HexString(DeafBabe));
return nullptr;
}
loader.mVersion = GetFormatVersion(MREA.ReadLong());
loader.mVersion = GetFormatVersion(rMREA.ReadLong());
loader.mpGroup = new CCollisionMeshGroup;
loader.mpMesh = new CCollisionMesh;
// Octree - structure is known, but not coding this right now
loader.mpMesh->mAABox = CAABox(MREA);
MREA.Seek(0x4, SEEK_CUR);
u32 octreeSize = MREA.ReadLong();
MREA.Seek(octreeSize, SEEK_CUR); // Skipping the octree for now
loader.mpMesh->mAABox = CAABox(rMREA);
rMREA.Seek(0x4, SEEK_CUR);
u32 OctreeSize = rMREA.ReadLong();
rMREA.Seek(OctreeSize, SEEK_CUR); // Skipping the octree for now
loader.mpMesh->mOctreeLoaded = false;
// Read collision indices and return
loader.LoadCollisionIndices(MREA, false);
loader.LoadCollisionIndices(rMREA, false);
loader.mpGroup->AddMesh(loader.mpMesh);
return loader.mpGroup;
}
CCollisionMeshGroup* CCollisionLoader::LoadDCLN(IInputStream &DCLN)
CCollisionMeshGroup* CCollisionLoader::LoadDCLN(IInputStream& rDCLN)
{
if (!DCLN.IsValid()) return nullptr;
if (!rDCLN.IsValid()) return nullptr;
CCollisionLoader loader;
loader.mpGroup = new CCollisionMeshGroup;
CCollisionLoader Loader;
Loader.mpGroup = new CCollisionMeshGroup;
u32 numMeshes = DCLN.ReadLong();
u32 NumMeshes = rDCLN.ReadLong();
for (u32 iMesh = 0; iMesh < numMeshes; iMesh++)
for (u32 iMesh = 0; iMesh < NumMeshes; iMesh++)
{
u32 deafbabe = DCLN.ReadLong();
u32 DeafBabe = rDCLN.ReadLong();
if (deafbabe != 0xDEAFBABE)
if (DeafBabe != 0xDEAFBABE)
{
Log::FileError(DCLN.GetSourceString(), DCLN.Tell() - 4, "Invalid collision magic: " + TString::HexString(deafbabe));
loader.mpGroup.Delete();
Log::FileError(rDCLN.GetSourceString(), rDCLN.Tell() - 4, "Invalid collision magic: " + TString::HexString(DeafBabe));
Loader.mpGroup.Delete();
return nullptr;
}
loader.mVersion = GetFormatVersion(DCLN.ReadLong());
Loader.mVersion = GetFormatVersion(rDCLN.ReadLong());
loader.mpMesh = new CCollisionMesh;
loader.mpMesh->mOctreeLoaded = false;
Loader.mpMesh = new CCollisionMesh;
Loader.mpMesh->mOctreeLoaded = false;
if (loader.mVersion == eReturns)
loader.mpMesh->mAABox = CAABox(DCLN);
if (Loader.mVersion == eReturns)
Loader.mpMesh->mAABox = CAABox(rDCLN);
// Read indices and return
DCLN.Seek(0x4, SEEK_CUR);
loader.LoadCollisionIndices(DCLN, loader.mVersion != eReturns);
loader.mpGroup->AddMesh(loader.mpMesh);
rDCLN.Seek(0x4, SEEK_CUR);
Loader.LoadCollisionIndices(rDCLN, Loader.mVersion != eReturns);
Loader.mpGroup->AddMesh(Loader.mpMesh);
// Parse OBB tree
loader.ParseOBBNode(DCLN);
Loader.ParseOBBNode(rDCLN);
}
return loader.mpGroup;
return Loader.mpGroup;
}
EGame CCollisionLoader::GetFormatVersion(u32 version)
EGame CCollisionLoader::GetFormatVersion(u32 Version)
{
switch (version)
switch (Version)
{
case 0x2: return ePrime;
case 0x3: return ePrime;

View File

@@ -13,17 +13,17 @@ class CCollisionLoader
std::vector<CCollisionMesh::SCollisionProperties> mProperties;
CCollisionLoader();
CCollisionMesh::CCollisionOctree* ParseOctree(IInputStream& src);
CCollisionMesh::CCollisionOctree::SBranch* ParseOctreeBranch(IInputStream& src);
CCollisionMesh::CCollisionOctree::SLeaf* ParseOctreeLeaf(IInputStream& src);
void ParseOBBNode(IInputStream& DCLN);
void ReadPropertyFlags(IInputStream& src);
void LoadCollisionIndices(IInputStream& file, bool buildAABox);
CCollisionMesh::CCollisionOctree* ParseOctree(IInputStream& rSrc);
CCollisionMesh::CCollisionOctree::SBranch* ParseOctreeBranch(IInputStream& rSrc);
CCollisionMesh::CCollisionOctree::SLeaf* ParseOctreeLeaf(IInputStream& rSrc);
void ParseOBBNode(IInputStream& rDCLN);
void ReadPropertyFlags(IInputStream& rSrc);
void LoadCollisionIndices(IInputStream& rFile, bool BuildAABox);
public:
static CCollisionMeshGroup* LoadAreaCollision(IInputStream& MREA);
static CCollisionMeshGroup* LoadDCLN(IInputStream& DCLN);
static EGame GetFormatVersion(u32 version);
static CCollisionMeshGroup* LoadAreaCollision(IInputStream& rMREA);
static CCollisionMeshGroup* LoadDCLN(IInputStream& rDCLN);
static EGame GetFormatVersion(u32 Version);
};
#endif // CCOLLISIONLOADER_H

View File

@@ -6,34 +6,34 @@ CFontLoader::CFontLoader()
{
}
CFont* CFontLoader::LoadFont(IInputStream& FONT)
CFont* CFontLoader::LoadFont(IInputStream& rFONT)
{
// If I seek past a value without reading it, then it's because I don't know what it is
mpFont->mUnknown = FONT.ReadLong();
mpFont->mLineHeight = FONT.ReadLong();
mpFont->mVerticalOffset = FONT.ReadLong();
mpFont->mLineMargin = FONT.ReadLong();
if (mVersion > ePrimeDemo) FONT.Seek(0x4, SEEK_CUR);
FONT.Seek(0x2, SEEK_CUR);
mpFont->mDefaultSize = FONT.ReadLong();
mpFont->mFontName = FONT.ReadString();
mpFont->mUnknown = rFONT.ReadLong();
mpFont->mLineHeight = rFONT.ReadLong();
mpFont->mVerticalOffset = rFONT.ReadLong();
mpFont->mLineMargin = rFONT.ReadLong();
if (mVersion > ePrimeDemo) rFONT.Seek(0x4, SEEK_CUR);
rFONT.Seek(0x2, SEEK_CUR);
mpFont->mDefaultSize = rFONT.ReadLong();
mpFont->mFontName = rFONT.ReadString();
if (mVersion <= eEchoes) mpFont->mpFontTexture = gResCache.GetResource(FONT.ReadLong(), "TXTR");
else mpFont->mpFontTexture = gResCache.GetResource(FONT.ReadLongLong(), "TXTR");
if (mVersion <= eEchoes) mpFont->mpFontTexture = gResCache.GetResource(rFONT.ReadLong(), "TXTR");
else mpFont->mpFontTexture = gResCache.GetResource(rFONT.ReadLongLong(), "TXTR");
mpFont->mTextureFormat = FONT.ReadLong();
u32 NumGlyphs = FONT.ReadLong();
mpFont->mTextureFormat = rFONT.ReadLong();
u32 NumGlyphs = rFONT.ReadLong();
mpFont->mGlyphs.reserve(NumGlyphs);
for (u32 iGlyph = 0; iGlyph < NumGlyphs; iGlyph++)
{
CFont::SGlyph Glyph;
Glyph.Character = FONT.ReadShort();
Glyph.Character = rFONT.ReadShort();
float TexCoordL = FONT.ReadFloat();
float TexCoordU = FONT.ReadFloat();
float TexCoordR = FONT.ReadFloat();
float TexCoordD = FONT.ReadFloat();
float TexCoordL = rFONT.ReadFloat();
float TexCoordU = rFONT.ReadFloat();
float TexCoordR = rFONT.ReadFloat();
float TexCoordD = rFONT.ReadFloat();
Glyph.TexCoords[0] = CVector2f(TexCoordL, TexCoordU); // Upper-left
Glyph.TexCoords[1] = CVector2f(TexCoordR, TexCoordU); // Upper-right
Glyph.TexCoords[2] = CVector2f(TexCoordL, TexCoordD); // Lower-left
@@ -42,66 +42,66 @@ CFont* CFontLoader::LoadFont(IInputStream& FONT)
if (mVersion <= ePrime)
{
Glyph.RGBAChannel = 0;
Glyph.LeftPadding = FONT.ReadLong();
Glyph.PrintAdvance = FONT.ReadLong();
Glyph.RightPadding = FONT.ReadLong();
Glyph.Width = FONT.ReadLong();
Glyph.Height = FONT.ReadLong();
Glyph.BaseOffset = FONT.ReadLong();
Glyph.KerningIndex = FONT.ReadLong();
Glyph.LeftPadding = rFONT.ReadLong();
Glyph.PrintAdvance = rFONT.ReadLong();
Glyph.RightPadding = rFONT.ReadLong();
Glyph.Width = rFONT.ReadLong();
Glyph.Height = rFONT.ReadLong();
Glyph.BaseOffset = rFONT.ReadLong();
Glyph.KerningIndex = rFONT.ReadLong();
}
else if (mVersion >= eEchoes)
{
Glyph.RGBAChannel = FONT.ReadByte();
Glyph.LeftPadding = FONT.ReadByte();
Glyph.PrintAdvance = FONT.ReadByte();
Glyph.RightPadding = FONT.ReadByte();
Glyph.Width = FONT.ReadByte();
Glyph.Height = FONT.ReadByte();
Glyph.BaseOffset = FONT.ReadByte();
Glyph.KerningIndex = FONT.ReadShort();
Glyph.RGBAChannel = rFONT.ReadByte();
Glyph.LeftPadding = rFONT.ReadByte();
Glyph.PrintAdvance = rFONT.ReadByte();
Glyph.RightPadding = rFONT.ReadByte();
Glyph.Width = rFONT.ReadByte();
Glyph.Height = rFONT.ReadByte();
Glyph.BaseOffset = rFONT.ReadByte();
Glyph.KerningIndex = rFONT.ReadShort();
}
mpFont->mGlyphs[Glyph.Character] = Glyph;
}
u32 NumKerningPairs = FONT.ReadLong();
u32 NumKerningPairs = rFONT.ReadLong();
mpFont->mKerningTable.reserve(NumKerningPairs);
for (u32 iKern = 0; iKern < NumKerningPairs; iKern++)
{
CFont::SKerningPair Pair;
Pair.CharacterA = FONT.ReadShort();
Pair.CharacterB = FONT.ReadShort();
Pair.Adjust = FONT.ReadLong();
Pair.CharacterA = rFONT.ReadShort();
Pair.CharacterB = rFONT.ReadShort();
Pair.Adjust = rFONT.ReadLong();
mpFont->mKerningTable.push_back(Pair);
}
return mpFont;
}
CFont* CFontLoader::LoadFONT(IInputStream& FONT)
CFont* CFontLoader::LoadFONT(IInputStream& rFONT)
{
if (!FONT.IsValid()) return nullptr;
if (!rFONT.IsValid()) return nullptr;
CFourCC Magic(FONT);
CFourCC Magic(rFONT);
if (Magic != "FONT")
{
Log::FileError(FONT.GetSourceString(), "Invalid FONT magic: " + TString::HexString((u32) Magic.ToLong()));
Log::FileError(rFONT.GetSourceString(), "Invalid FONT magic: " + TString::HexString(Magic.ToLong()));
return nullptr;
}
u32 FileVersion = FONT.ReadLong();
u32 FileVersion = rFONT.ReadLong();
EGame Version = GetFormatVersion(FileVersion);
if (Version == eUnknownVersion)
{
Log::FileError(FONT.GetSourceString(), "Unsupported FONT version: " + TString::HexString(FileVersion));
Log::FileError(rFONT.GetSourceString(), "Unsupported FONT version: " + TString::HexString(FileVersion, 0));
return nullptr;
}
CFontLoader Loader;
Loader.mpFont = new CFont();
Loader.mVersion = Version;
return Loader.LoadFont(FONT);
return Loader.LoadFont(rFONT);
}
EGame CFontLoader::GetFormatVersion(u32 Version)

View File

@@ -11,10 +11,10 @@ class CFontLoader
EGame mVersion;
CFontLoader();
CFont* LoadFont(IInputStream& FONT);
CFont* LoadFont(IInputStream& rFONT);
public:
static CFont* LoadFONT(IInputStream& FONT);
static CFont* LoadFONT(IInputStream& rFONT);
static EGame GetFormatVersion(u32 Version);
};

View File

@@ -6,9 +6,9 @@
#include <iomanip>
CMaterialLoader::CMaterialLoader()
: mCorruptionFlags(0)
, mHasOPAC(false)
{
mCorruptionFlags = 0;
mHasOPAC = false;
}
CMaterialLoader::~CMaterialLoader()
@@ -18,29 +18,29 @@ CMaterialLoader::~CMaterialLoader()
void CMaterialLoader::ReadPrimeMatSet()
{
// Textures
u32 numTextures = mpFile->ReadLong();
mTextures.resize(numTextures);
u32 NumTextures = mpFile->ReadLong();
mTextures.resize(NumTextures);
for (u32 iTex = 0; iTex < numTextures; iTex++)
for (u32 iTex = 0; iTex < NumTextures; iTex++)
{
u32 TextureID = mpFile->ReadLong();
mTextures[iTex] = gResCache.GetResource(TextureID, "TXTR");
}
// Materials
u32 numMats = mpFile->ReadLong();
std::vector<u32> offsets(numMats);
for (u32 iMat = 0; iMat < numMats; iMat++)
offsets[iMat] = mpFile->ReadLong();
u32 NumMats = mpFile->ReadLong();
std::vector<u32> Offsets(NumMats);
for (u32 iMat = 0; iMat < NumMats; iMat++)
Offsets[iMat] = mpFile->ReadLong();
u32 matsStart = mpFile->Tell();
mpSet->mMaterials.resize(numMats);
for (u32 iMat = 0; iMat < numMats; iMat++)
u32 MatsStart = mpFile->Tell();
mpSet->mMaterials.resize(NumMats);
for (u32 iMat = 0; iMat < NumMats; iMat++)
{
mpSet->mMaterials[iMat] = ReadPrimeMaterial();
mpSet->mMaterials[iMat]->mVersion = mVersion;
mpSet->mMaterials[iMat]->mName = TString("Material #") + std::to_string(iMat + 1);
mpFile->Seek(matsStart + offsets[iMat], SEEK_SET);
mpFile->Seek(MatsStart + Offsets[iMat], SEEK_SET);
}
}
@@ -87,8 +87,8 @@ CMaterial* CMaterialLoader::ReadPrimeMaterial()
}
// Blend mode
pMat->mBlendDstFac = glBlendFactor[mpFile->ReadShort()];
pMat->mBlendSrcFac = glBlendFactor[mpFile->ReadShort()];
pMat->mBlendDstFac = gBlendFactor[mpFile->ReadShort()];
pMat->mBlendSrcFac = gBlendFactor[mpFile->ReadShort()];
// Indirect texture
if (pMat->mOptions & CMaterial::eIndStage)
@@ -308,7 +308,7 @@ CMaterial* CMaterialLoader::ReadCorruptionMaterial()
if (ClrType == "DIFB")
{
ClrVal.a = 0xFF;
ClrVal.A = 0xFF;
pMat->mKonstColors[1] = ClrVal;
}
@@ -584,9 +584,9 @@ CMaterial* CMaterialLoader::LoadAssimpMaterial(const aiMaterial *pAiMat)
// todo: generate new material using import values.
CMaterial *pMat = new CMaterial(mVersion, eNoAttributes);
aiString name;
pAiMat->Get(AI_MATKEY_NAME, name);
pMat->SetName(name.C_Str());
aiString Name;
pAiMat->Get(AI_MATKEY_NAME, Name);
pMat->SetName(Name.C_Str());
// Create generic custom pass that uses Konst color
CMaterialPass *pPass = new CMaterialPass(pMat);
@@ -602,11 +602,11 @@ CMaterial* CMaterialLoader::LoadAssimpMaterial(const aiMaterial *pAiMat)
}
// ************ STATIC ************
CMaterialSet* CMaterialLoader::LoadMaterialSet(IInputStream& Mat, EGame Version)
CMaterialSet* CMaterialLoader::LoadMaterialSet(IInputStream& rMat, EGame Version)
{
CMaterialLoader Loader;
Loader.mpSet = new CMaterialSet();
Loader.mpFile = &Mat;
Loader.mpFile = &rMat;
Loader.mVersion = Version;
if ((Version >= ePrimeDemo) && (Version <= eEchoes))
@@ -617,17 +617,17 @@ CMaterialSet* CMaterialLoader::LoadMaterialSet(IInputStream& Mat, EGame Version)
return Loader.mpSet;
}
CMaterialSet* CMaterialLoader::ImportAssimpMaterials(const aiScene *pScene, EGame targetVersion)
CMaterialSet* CMaterialLoader::ImportAssimpMaterials(const aiScene *pScene, EGame TargetVersion)
{
CMaterialLoader loader;
loader.mVersion = targetVersion;
CMaterialLoader Loader;
Loader.mVersion = TargetVersion;
CMaterialSet *pOut = new CMaterialSet();
pOut->mMaterials.reserve(pScene->mNumMaterials);
for (u32 iMat = 0; iMat < pScene->mNumMaterials; iMat++)
{
CMaterial *pMat = loader.LoadAssimpMaterial(pScene->mMaterials[iMat]);
CMaterial *pMat = Loader.LoadAssimpMaterial(pScene->mMaterials[iMat]);
pOut->mMaterials.push_back(pMat);
}

View File

@@ -38,8 +38,8 @@ class CMaterialLoader
// Static
public:
static CMaterialSet* LoadMaterialSet(IInputStream& Mat, EGame Version);
static CMaterialSet* ImportAssimpMaterials(const aiScene *pScene, EGame targetVersion);
static CMaterialSet* LoadMaterialSet(IInputStream& rMat, EGame Version);
static CMaterialSet* ImportAssimpMaterials(const aiScene *pScene, EGame TargetVersion);
};
#endif // CMATERIALLOADER_H

View File

@@ -4,24 +4,24 @@
#include <map>
CModelLoader::CModelLoader()
: mFlags(eNoFlags)
, mNumVertices(0)
{
mFlags = eNoFlags;
mNumVertices = 0;
}
CModelLoader::~CModelLoader()
{
}
void CModelLoader::LoadWorldMeshHeader(IInputStream &Model)
void CModelLoader::LoadWorldMeshHeader(IInputStream& rModel)
{
// I don't really have any need for most of this data, so
Model.Seek(0x34, SEEK_CUR);
mAABox = CAABox(Model);
rModel.Seek(0x34, SEEK_CUR);
mAABox = CAABox(rModel);
mpSectionMgr->ToNextSection();
}
void CModelLoader::LoadAttribArrays(IInputStream& Model)
void CModelLoader::LoadAttribArrays(IInputStream& rModel)
{
// Positions
if (mFlags & eShortPositions) // Shorts (DKCR only)
@@ -31,10 +31,10 @@ void CModelLoader::LoadAttribArrays(IInputStream& Model)
for (u32 iVtx = 0; iVtx < mPositions.size(); iVtx++)
{
float x = Model.ReadShort() / Divisor;
float y = Model.ReadShort() / Divisor;
float z = Model.ReadShort() / Divisor;
mPositions[iVtx] = CVector3f(x, y, z);
float X = rModel.ReadShort() / Divisor;
float Y = rModel.ReadShort() / Divisor;
float Z = rModel.ReadShort() / Divisor;
mPositions[iVtx] = CVector3f(X, Y, Z);
}
}
@@ -43,7 +43,7 @@ void CModelLoader::LoadAttribArrays(IInputStream& Model)
mPositions.resize(mpSectionMgr->CurrentSectionSize() / 0xC);
for (u32 iVtx = 0; iVtx < mPositions.size(); iVtx++)
mPositions[iVtx] = CVector3f(Model);
mPositions[iVtx] = CVector3f(rModel);
}
mpSectionMgr->ToNextSection();
@@ -56,10 +56,10 @@ void CModelLoader::LoadAttribArrays(IInputStream& Model)
for (u32 iVtx = 0; iVtx < mNormals.size(); iVtx++)
{
float x = Model.ReadShort() / Divisor;
float y = Model.ReadShort() / Divisor;
float z = Model.ReadShort() / Divisor;
mNormals[iVtx] = CVector3f(x, y, z);
float X = rModel.ReadShort() / Divisor;
float Y = rModel.ReadShort() / Divisor;
float Z = rModel.ReadShort() / Divisor;
mNormals[iVtx] = CVector3f(X, Y, Z);
}
}
else // Floats
@@ -67,7 +67,7 @@ void CModelLoader::LoadAttribArrays(IInputStream& Model)
mNormals.resize(mpSectionMgr->CurrentSectionSize() / 0xC);
for (u32 iVtx = 0; iVtx < mNormals.size(); iVtx++)
mNormals[iVtx] = CVector3f(Model);
mNormals[iVtx] = CVector3f(rModel);
}
mpSectionMgr->ToNextSection();
@@ -76,7 +76,7 @@ void CModelLoader::LoadAttribArrays(IInputStream& Model)
mColors.resize(mpSectionMgr->CurrentSectionSize() / 4);
for (u32 iVtx = 0; iVtx < mColors.size(); iVtx++)
mColors[iVtx] = CColor(Model);
mColors[iVtx] = CColor(rModel);
mpSectionMgr->ToNextSection();
@@ -85,7 +85,7 @@ void CModelLoader::LoadAttribArrays(IInputStream& Model)
mTex0.resize(mpSectionMgr->CurrentSectionSize() / 0x8);
for (u32 iVtx = 0; iVtx < mTex0.size(); iVtx++)
mTex0[iVtx] = CVector2f(Model);
mTex0[iVtx] = CVector2f(rModel);
mpSectionMgr->ToNextSection();
@@ -97,48 +97,48 @@ void CModelLoader::LoadAttribArrays(IInputStream& Model)
for (u32 iVtx = 0; iVtx < mTex1.size(); iVtx++)
{
float x = Model.ReadShort() / Divisor;
float y = Model.ReadShort() / Divisor;
mTex1[iVtx] = CVector2f(x, y);
float X = rModel.ReadShort() / Divisor;
float Y = rModel.ReadShort() / Divisor;
mTex1[iVtx] = CVector2f(X, Y);
}
mpSectionMgr->ToNextSection();
}
}
void CModelLoader::LoadSurfaceOffsets(IInputStream& Model)
void CModelLoader::LoadSurfaceOffsets(IInputStream& rModel)
{
mSurfaceCount = Model.ReadLong();
mSurfaceCount = rModel.ReadLong();
mSurfaceOffsets.resize(mSurfaceCount);
for (u32 iSurf = 0; iSurf < mSurfaceCount; iSurf++)
mSurfaceOffsets[iSurf] = Model.ReadLong();
mSurfaceOffsets[iSurf] = rModel.ReadLong();
mpSectionMgr->ToNextSection();
}
SSurface* CModelLoader::LoadSurface(IInputStream& Model)
SSurface* CModelLoader::LoadSurface(IInputStream& rModel)
{
SSurface *pSurf = new SSurface;
// Surface header
if (mVersion < eReturns)
LoadSurfaceHeaderPrime(Model, pSurf);
LoadSurfaceHeaderPrime(rModel, pSurf);
else
LoadSurfaceHeaderDKCR(Model, pSurf);
LoadSurfaceHeaderDKCR(rModel, pSurf);
bool HasAABB = (pSurf->AABox != CAABox::skInfinite);
CMaterial *pMat = mMaterials[0]->MaterialByIndex(pSurf->MaterialID);
// Primitive table
u8 Flag = Model.ReadByte();
u8 Flag = rModel.ReadByte();
u32 NextSurface = mpSectionMgr->NextOffset();
while ((Flag != 0) && ((u32) Model.Tell() < NextSurface))
while ((Flag != 0) && ((u32) rModel.Tell() < NextSurface))
{
SSurface::SPrimitive Prim;
Prim.Type = EGXPrimitiveType(Flag & 0xF8);
u16 VertexCount = Model.ReadShort();
u16 VertexCount = rModel.ReadShort();
for (u16 iVtx = 0; iVtx < VertexCount; iVtx++)
{
@@ -146,7 +146,7 @@ SSurface* CModelLoader::LoadSurface(IInputStream& Model)
FVertexDescription VtxDesc = pMat->VtxDesc();
for (u32 iMtxAttr = 0; iMtxAttr < 8; iMtxAttr++)
if (VtxDesc & (ePosMtx << iMtxAttr)) Model.Seek(0x1, SEEK_CUR);
if (VtxDesc & (ePosMtx << iMtxAttr)) rModel.Seek(0x1, SEEK_CUR);
// Only thing to do here is check whether each attribute is present, and if so, read it.
// A couple attributes have special considerations; normals can be floats or shorts, as can tex0, depending on vtxfmt.
@@ -155,7 +155,7 @@ SSurface* CModelLoader::LoadSurface(IInputStream& Model)
// Position
if (VtxDesc & ePosition)
{
u16 PosIndex = Model.ReadShort() & 0xFFFF;
u16 PosIndex = rModel.ReadShort() & 0xFFFF;
Vtx.Position = mPositions[PosIndex];
Vtx.ArrayPosition = PosIndex;
@@ -164,12 +164,12 @@ SSurface* CModelLoader::LoadSurface(IInputStream& Model)
// Normal
if (VtxDesc & eNormal)
Vtx.Normal = mNormals[Model.ReadShort() & 0xFFFF];
Vtx.Normal = mNormals[rModel.ReadShort() & 0xFFFF];
// Color
for (u32 c = 0; c < 2; c++)
if (VtxDesc & (eColor0 << (c * 2)))
Vtx.Color[c] = mColors[Model.ReadShort() & 0xFFFF];
for (u32 iClr = 0; iClr < 2; iClr++)
if (VtxDesc & (eColor0 << (iClr * 2)))
Vtx.Color[iClr] = mColors[rModel.ReadShort() & 0xFFFF];
// Tex Coords - these are done a bit differently in DKCR than in the Prime series
if (mVersion < eReturns)
@@ -178,15 +178,15 @@ SSurface* CModelLoader::LoadSurface(IInputStream& Model)
if (VtxDesc & eTex0)
{
if ((mFlags & eHasTex1) && (pMat->Options() & CMaterial::eShortTexCoord))
Vtx.Tex[0] = mTex1[Model.ReadShort() & 0xFFFF];
Vtx.Tex[0] = mTex1[rModel.ReadShort() & 0xFFFF];
else
Vtx.Tex[0] = mTex0[Model.ReadShort() & 0xFFFF];
Vtx.Tex[0] = mTex0[rModel.ReadShort() & 0xFFFF];
}
// Tex1-7
for (u32 iTex = 1; iTex < 7; iTex++)
if (VtxDesc & (eTex0 << (iTex * 2)))
Vtx.Tex[iTex] = mTex0[Model.ReadShort() & 0xFFFF];
Vtx.Tex[iTex] = mTex0[rModel.ReadShort() & 0xFFFF];
}
else
@@ -197,9 +197,9 @@ SSurface* CModelLoader::LoadSurface(IInputStream& Model)
if (VtxDesc & (eTex0 << iTex * 2))
{
if (!mSurfaceUsingTex1)
Vtx.Tex[iTex] = mTex0[Model.ReadShort() & 0xFFFF];
Vtx.Tex[iTex] = mTex0[rModel.ReadShort() & 0xFFFF];
else
Vtx.Tex[iTex] = mTex1[Model.ReadShort() & 0xFFFF];
Vtx.Tex[iTex] = mTex1[rModel.ReadShort() & 0xFFFF];
}
}
}
@@ -222,24 +222,24 @@ SSurface* CModelLoader::LoadSurface(IInputStream& Model)
}
pSurf->Primitives.push_back(Prim);
Flag = Model.ReadByte();
Flag = rModel.ReadByte();
} // Primitive table end
mpSectionMgr->ToNextSection();
return pSurf;
}
void CModelLoader::LoadSurfaceHeaderPrime(IInputStream& Model, SSurface *pSurf)
void CModelLoader::LoadSurfaceHeaderPrime(IInputStream& rModel, SSurface *pSurf)
{
pSurf->CenterPoint = CVector3f(Model);
pSurf->MaterialID = Model.ReadLong();
pSurf->CenterPoint = CVector3f(rModel);
pSurf->MaterialID = rModel.ReadLong();
Model.Seek(0xC, SEEK_CUR);
u32 ExtraSize = Model.ReadLong();
pSurf->ReflectionDirection = CVector3f(Model);
rModel.Seek(0xC, SEEK_CUR);
u32 ExtraSize = rModel.ReadLong();
pSurf->ReflectionDirection = CVector3f(rModel);
if (mVersion >= eEchoesDemo)
Model.Seek(0x4, SEEK_CUR); // Skipping unknown values
rModel.Seek(0x4, SEEK_CUR); // Skipping unknown values
bool HasAABox = (ExtraSize >= 0x18); // MREAs have a set of bounding box coordinates here.
@@ -247,54 +247,54 @@ void CModelLoader::LoadSurfaceHeaderPrime(IInputStream& Model, SSurface *pSurf)
if (HasAABox)
{
ExtraSize -= 0x18;
pSurf->AABox = CAABox(Model);
pSurf->AABox = CAABox(rModel);
}
else
pSurf->AABox = CAABox::skInfinite;
Model.Seek(ExtraSize, SEEK_CUR);
Model.SeekToBoundary(32);
rModel.Seek(ExtraSize, SEEK_CUR);
rModel.SeekToBoundary(32);
}
void CModelLoader::LoadSurfaceHeaderDKCR(IInputStream& Model, SSurface *pSurf)
void CModelLoader::LoadSurfaceHeaderDKCR(IInputStream& rModel, SSurface *pSurf)
{
pSurf->CenterPoint = CVector3f(Model);
Model.Seek(0xE, SEEK_CUR);
pSurf->MaterialID = (u32) Model.ReadShort();
Model.Seek(0x2, SEEK_CUR);
mSurfaceUsingTex1 = (Model.ReadByte() == 1);
u32 ExtraSize = Model.ReadByte();
pSurf->CenterPoint = CVector3f(rModel);
rModel.Seek(0xE, SEEK_CUR);
pSurf->MaterialID = (u32) rModel.ReadShort();
rModel.Seek(0x2, SEEK_CUR);
mSurfaceUsingTex1 = (rModel.ReadByte() == 1);
u32 ExtraSize = rModel.ReadByte();
if (ExtraSize > 0)
{
ExtraSize -= 0x18;
pSurf->AABox = CAABox(Model);
pSurf->AABox = CAABox(rModel);
}
else
pSurf->AABox = CAABox::skInfinite;
Model.Seek(ExtraSize, SEEK_CUR);
Model.SeekToBoundary(32);
rModel.Seek(ExtraSize, SEEK_CUR);
rModel.SeekToBoundary(32);
}
SSurface* CModelLoader::LoadAssimpMesh(const aiMesh *pMesh, CMaterialSet *pSet)
SSurface* CModelLoader::LoadAssimpMesh(const aiMesh *pkMesh, CMaterialSet *pSet)
{
// Create vertex description and assign it to material
CMaterial *pMat = pSet->MaterialByIndex(pMesh->mMaterialIndex);
FVertexDescription desc = pMat->VtxDesc();
CMaterial *pMat = pSet->MaterialByIndex(pkMesh->mMaterialIndex);
FVertexDescription Desc = pMat->VtxDesc();
if (desc == eNoAttributes)
if (Desc == eNoAttributes)
{
if (pMesh->HasPositions()) desc |= ePosition;
if (pMesh->HasNormals()) desc |= eNormal;
if (pkMesh->HasPositions()) Desc |= ePosition;
if (pkMesh->HasNormals()) Desc |= eNormal;
for (u32 iUV = 0; iUV < pMesh->GetNumUVChannels(); iUV++)
desc |= (eTex0 << (iUV * 2));
for (u32 iUV = 0; iUV < pkMesh->GetNumUVChannels(); iUV++)
Desc |= (eTex0 << (iUV * 2));
pMat->SetVertexDescription(desc);
pMat->SetVertexDescription(Desc);
// TEMP - disable dynamic lighting on geometry with no normals
if (!pMesh->HasNormals())
if (!pkMesh->HasNormals())
{
pMat->SetLightingEnabled(false);
pMat->Pass(0)->SetColorInputs(eZeroRGB, eOneRGB, eKonstRGB, eZeroRGB);
@@ -304,87 +304,90 @@ SSurface* CModelLoader::LoadAssimpMesh(const aiMesh *pMesh, CMaterialSet *pSet)
// Create surface
SSurface *pSurf = new SSurface();
pSurf->MaterialID = pMesh->mMaterialIndex;
pSurf->MaterialID = pkMesh->mMaterialIndex;
if (pMesh->mNumFaces > 0)
if (pkMesh->mNumFaces > 0)
{
pSurf->Primitives.resize(1);
SSurface::SPrimitive& prim = pSurf->Primitives[0];
SSurface::SPrimitive& rPrim = pSurf->Primitives[0];
// Check primitive type on first face
u32 numIndices = pMesh->mFaces[0].mNumIndices;
if (numIndices == 1) prim.Type = eGX_Points;
else if (numIndices == 2) prim.Type = eGX_Lines;
else if (numIndices == 3) prim.Type = eGX_Triangles;
u32 NumIndices = pkMesh->mFaces[0].mNumIndices;
if (NumIndices == 1) rPrim.Type = eGX_Points;
else if (NumIndices == 2) rPrim.Type = eGX_Lines;
else if (NumIndices == 3) rPrim.Type = eGX_Triangles;
// Generate bounding box, center point, and reflection projection
pSurf->CenterPoint = CVector3f::skZero;
pSurf->ReflectionDirection = CVector3f::skZero;
for (u32 iVtx = 0; iVtx < pMesh->mNumVertices; iVtx++)
for (u32 iVtx = 0; iVtx < pkMesh->mNumVertices; iVtx++)
{
aiVector3D aiPos = pMesh->mVertices[iVtx];
pSurf->AABox.ExpandBounds(CVector3f(aiPos.x, aiPos.y, aiPos.z));
aiVector3D AiPos = pkMesh->mVertices[iVtx];
pSurf->AABox.ExpandBounds(CVector3f(AiPos.x, AiPos.y, AiPos.z));
if (pMesh->HasNormals()) {
aiVector3D aiNrm = pMesh->mNormals[iVtx];
if (pkMesh->HasNormals()) {
aiVector3D aiNrm = pkMesh->mNormals[iVtx];
pSurf->ReflectionDirection += CVector3f(aiNrm.x, aiNrm.y, aiNrm.z);
}
}
pSurf->CenterPoint = pSurf->AABox.Center();
if (pMesh->HasNormals())
pSurf->ReflectionDirection /= (float) pMesh->mNumVertices;
if (pkMesh->HasNormals())
pSurf->ReflectionDirection /= (float) pkMesh->mNumVertices;
else
pSurf->ReflectionDirection = CVector3f(1.f, 0.f, 0.f);
// Set vertex/triangle count
pSurf->VertexCount = pMesh->mNumVertices;
pSurf->TriangleCount = (prim.Type == eGX_Triangles ? pMesh->mNumFaces : 0);
pSurf->VertexCount = pkMesh->mNumVertices;
pSurf->TriangleCount = (rPrim.Type == eGX_Triangles ? pkMesh->mNumFaces : 0);
// Create primitive
for (u32 iFace = 0; iFace < pMesh->mNumFaces; iFace++)
for (u32 iFace = 0; iFace < pkMesh->mNumFaces; iFace++)
{
for (u32 iIndex = 0; iIndex < numIndices; iIndex++)
for (u32 iIndex = 0; iIndex < NumIndices; iIndex++)
{
u32 index = pMesh->mFaces[iFace].mIndices[iIndex];
u32 Index = pkMesh->mFaces[iFace].mIndices[iIndex];
// Create vertex and add it to the primitive
CVertex vert;
vert.ArrayPosition = index + mNumVertices;
CVertex Vert;
Vert.ArrayPosition = Index + mNumVertices;
if (pMesh->HasPositions()) {
aiVector3D aiPos = pMesh->mVertices[index];
vert.Position = CVector3f(aiPos.x, aiPos.y, aiPos.z);
if (pkMesh->HasPositions())
{
aiVector3D AiPos = pkMesh->mVertices[Index];
Vert.Position = CVector3f(AiPos.x, AiPos.y, AiPos.z);
}
if (pMesh->HasNormals()) {
aiVector3D aiNrm = pMesh->mNormals[index];
vert.Normal = CVector3f(aiNrm.x, aiNrm.y, aiNrm.z);
if (pkMesh->HasNormals())
{
aiVector3D AiNrm = pkMesh->mNormals[Index];
Vert.Normal = CVector3f(AiNrm.x, AiNrm.y, AiNrm.z);
}
for (u32 iTex = 0; iTex < pMesh->GetNumUVChannels(); iTex++) {
aiVector3D aiTex = pMesh->mTextureCoords[iTex][index];
vert.Tex[iTex] = CVector2f(aiTex.x, aiTex.y);
for (u32 iTex = 0; iTex < pkMesh->GetNumUVChannels(); iTex++)
{
aiVector3D AiTex = pkMesh->mTextureCoords[iTex][Index];
Vert.Tex[iTex] = CVector2f(AiTex.x, AiTex.y);
}
prim.Vertices.push_back(vert);
rPrim.Vertices.push_back(Vert);
}
}
mNumVertices += pMesh->mNumVertices;
mNumVertices += pkMesh->mNumVertices;
}
return pSurf;
}
// ************ STATIC ************
CModel* CModelLoader::LoadCMDL(IInputStream& CMDL)
CModel* CModelLoader::LoadCMDL(IInputStream& rCMDL)
{
CModelLoader Loader;
// CMDL header - same across the three Primes, but different structure in DKCR
u32 Magic = CMDL.ReadLong();
u32 Magic = rCMDL.ReadLong();
u32 Version, BlockCount, MatSetCount;
CAABox AABox;
@@ -392,11 +395,11 @@ CModel* CModelLoader::LoadCMDL(IInputStream& CMDL)
// 0xDEADBABE - Metroid Prime seres
if (Magic == 0xDEADBABE)
{
Version = CMDL.ReadLong();
u32 Flags = CMDL.ReadLong();
AABox = CAABox(CMDL);
BlockCount = CMDL.ReadLong();
MatSetCount = CMDL.ReadLong();
Version = rCMDL.ReadLong();
u32 Flags = rCMDL.ReadLong();
AABox = CAABox(rCMDL);
BlockCount = rCMDL.ReadLong();
MatSetCount = rCMDL.ReadLong();
if (Flags & 0x2) Loader.mFlags |= eShortNormals;
if (Flags & 0x4) Loader.mFlags |= eHasTex1;
@@ -406,10 +409,10 @@ CModel* CModelLoader::LoadCMDL(IInputStream& CMDL)
else if (Magic == 0x9381000A)
{
Version = Magic & 0xFFFF;
u32 Flags = CMDL.ReadLong();
AABox = CAABox(CMDL);
BlockCount = CMDL.ReadLong();
MatSetCount = CMDL.ReadLong();
u32 Flags = rCMDL.ReadLong();
AABox = CAABox(rCMDL);
BlockCount = rCMDL.ReadLong();
MatSetCount = rCMDL.ReadLong();
// todo: unknown flags
Loader.mFlags = eShortNormals | eHasTex1;
@@ -420,22 +423,22 @@ CModel* CModelLoader::LoadCMDL(IInputStream& CMDL)
// Skipping for now - should read in eventually
if (Flags & 0x10)
{
CMDL.Seek(0x4, SEEK_CUR);
u32 VisGroupCount = CMDL.ReadLong();
rCMDL.Seek(0x4, SEEK_CUR);
u32 VisGroupCount = rCMDL.ReadLong();
for (u32 iVis = 0; iVis < VisGroupCount; iVis++)
{
u32 NameLength = CMDL.ReadLong();
CMDL.Seek(NameLength, SEEK_CUR);
u32 NameLength = rCMDL.ReadLong();
rCMDL.Seek(NameLength, SEEK_CUR);
}
CMDL.Seek(0x14, SEEK_CUR); // no clue what any of this is!
rCMDL.Seek(0x14, SEEK_CUR); // no clue what any of this is!
}
}
else
{
Log::FileError(CMDL.GetSourceString(), "Invalid CMDL magic: " + TString::HexString(Magic));
Log::FileError(rCMDL.GetSourceString(), "Invalid CMDL magic: " + TString::HexString(Magic));
return nullptr;
}
@@ -444,21 +447,21 @@ CModel* CModelLoader::LoadCMDL(IInputStream& CMDL)
if (Loader.mVersion == eUnknownVersion)
{
Log::FileError(CMDL.GetSourceString(), "Unsupported CMDL version: " + TString::HexString(Magic));
Log::FileError(rCMDL.GetSourceString(), "Unsupported CMDL version: " + TString::HexString(Magic, 0));
return nullptr;
}
CModel *pModel = new CModel();
Loader.mpModel = pModel;
Loader.mpSectionMgr = new CSectionMgrIn(BlockCount, &CMDL);
CMDL.SeekToBoundary(32);
Loader.mpSectionMgr = new CSectionMgrIn(BlockCount, &rCMDL);
rCMDL.SeekToBoundary(32);
Loader.mpSectionMgr->Init();
// Materials
Loader.mMaterials.resize(MatSetCount);
for (u32 iMat = 0; iMat < MatSetCount; iMat++)
{
Loader.mMaterials[iMat] = CMaterialLoader::LoadMaterialSet(CMDL, Loader.mVersion);
Loader.mMaterials[iMat] = CMaterialLoader::LoadMaterialSet(rCMDL, Loader.mVersion);
if (Loader.mVersion < eCorruptionProto)
Loader.mpSectionMgr->ToNextSection();
@@ -469,13 +472,13 @@ CModel* CModelLoader::LoadCMDL(IInputStream& CMDL)
if (Loader.mVersion >= eCorruptionProto) Loader.mpSectionMgr->ToNextSection();
// Mesh
Loader.LoadAttribArrays(CMDL);
Loader.LoadSurfaceOffsets(CMDL);
Loader.LoadAttribArrays(rCMDL);
Loader.LoadSurfaceOffsets(rCMDL);
pModel->mSurfaces.reserve(Loader.mSurfaceCount);
for (u32 iSurf = 0; iSurf < Loader.mSurfaceCount; iSurf++)
{
SSurface *pSurf = Loader.LoadSurface(CMDL);
SSurface *pSurf = Loader.LoadSurface(rCMDL);
pModel->mSurfaces.push_back(pSurf);
pModel->mVertexCount += pSurf->VertexCount;
pModel->mTriangleCount += pSurf->TriangleCount;
@@ -489,30 +492,30 @@ CModel* CModelLoader::LoadCMDL(IInputStream& CMDL)
return pModel;
}
CModel* CModelLoader::LoadWorldModel(IInputStream& MREA, CSectionMgrIn& BlockMgr, CMaterialSet& MatSet, EGame Version)
CModel* CModelLoader::LoadWorldModel(IInputStream& rMREA, CSectionMgrIn& rBlockMgr, CMaterialSet& rMatSet, EGame Version)
{
CModelLoader Loader;
Loader.mpSectionMgr = &BlockMgr;
Loader.mpSectionMgr = &rBlockMgr;
Loader.mVersion = Version;
Loader.mFlags = eShortNormals;
if (Version != eCorruptionProto) Loader.mFlags |= eHasTex1;
Loader.mMaterials.resize(1);
Loader.mMaterials[0] = &MatSet;
Loader.mMaterials[0] = &rMatSet;
Loader.LoadWorldMeshHeader(MREA);
Loader.LoadAttribArrays(MREA);
Loader.LoadSurfaceOffsets(MREA);
Loader.LoadWorldMeshHeader(rMREA);
Loader.LoadAttribArrays(rMREA);
Loader.LoadSurfaceOffsets(rMREA);
CModel *pModel = new CModel();
pModel->mMaterialSets.resize(1);
pModel->mMaterialSets[0] = &MatSet;
pModel->mMaterialSets[0] = &rMatSet;
pModel->mHasOwnMaterials = false;
pModel->mSurfaces.reserve(Loader.mSurfaceCount);
pModel->mHasOwnSurfaces = true;
for (u32 iSurf = 0; iSurf < Loader.mSurfaceCount; iSurf++)
{
SSurface *pSurf = Loader.LoadSurface(MREA);
SSurface *pSurf = Loader.LoadSurface(rMREA);
pModel->mSurfaces.push_back(pSurf);
pModel->mVertexCount += pSurf->VertexCount;
pModel->mTriangleCount += pSurf->TriangleCount;
@@ -522,33 +525,33 @@ CModel* CModelLoader::LoadWorldModel(IInputStream& MREA, CSectionMgrIn& BlockMgr
return pModel;
}
CModel* CModelLoader::LoadCorruptionWorldModel(IInputStream &MREA, CSectionMgrIn &BlockMgr, CMaterialSet &MatSet, u32 HeaderSecNum, u32 GPUSecNum, EGame Version)
CModel* CModelLoader::LoadCorruptionWorldModel(IInputStream& rMREA, CSectionMgrIn& rBlockMgr, CMaterialSet& rMatSet, u32 HeaderSecNum, u32 GPUSecNum, EGame Version)
{
CModelLoader Loader;
Loader.mpSectionMgr = &BlockMgr;
Loader.mpSectionMgr = &rBlockMgr;
Loader.mVersion = Version;
Loader.mFlags = eShortNormals;
Loader.mMaterials.resize(1);
Loader.mMaterials[0] = &MatSet;
Loader.mMaterials[0] = &rMatSet;
if (Version == eReturns) Loader.mFlags |= eHasTex1;
// Corruption/DKCR MREAs split the mesh header and surface offsets away from the actual geometry data so I need two section numbers to read it
BlockMgr.ToSection(HeaderSecNum);
Loader.LoadWorldMeshHeader(MREA);
Loader.LoadSurfaceOffsets(MREA);
BlockMgr.ToSection(GPUSecNum);
Loader.LoadAttribArrays(MREA);
rBlockMgr.ToSection(HeaderSecNum);
Loader.LoadWorldMeshHeader(rMREA);
Loader.LoadSurfaceOffsets(rMREA);
rBlockMgr.ToSection(GPUSecNum);
Loader.LoadAttribArrays(rMREA);
CModel *pModel = new CModel();
pModel->mMaterialSets.resize(1);
pModel->mMaterialSets[0] = &MatSet;
pModel->mMaterialSets[0] = &rMatSet;
pModel->mHasOwnMaterials = false;
pModel->mSurfaces.reserve(Loader.mSurfaceCount);
pModel->mHasOwnSurfaces = true;
for (u32 iSurf = 0; iSurf < Loader.mSurfaceCount; iSurf++)
{
SSurface *pSurf = Loader.LoadSurface(MREA);
SSurface *pSurf = Loader.LoadSurface(rMREA);
pModel->mSurfaces.push_back(pSurf);
pModel->mVertexCount += pSurf->VertexCount;
pModel->mTriangleCount += pSurf->TriangleCount;
@@ -609,25 +612,25 @@ void CModelLoader::BuildWorldMeshes(const std::vector<CModel*>& rkIn, std::vecto
}
}
CModel* CModelLoader::ImportAssimpNode(const aiNode *pNode, const aiScene *pScene, CMaterialSet& matSet)
CModel* CModelLoader::ImportAssimpNode(const aiNode *pkNode, const aiScene *pkScene, CMaterialSet& rMatSet)
{
CModelLoader loader;
loader.mpModel = new CModel(&matSet, true);
loader.mpModel->mSurfaces.reserve(pNode->mNumMeshes);
CModelLoader Loader;
Loader.mpModel = new CModel(&rMatSet, true);
Loader.mpModel->mSurfaces.reserve(pkNode->mNumMeshes);
for (u32 iMesh = 0; iMesh < pNode->mNumMeshes; iMesh++)
for (u32 iMesh = 0; iMesh < pkNode->mNumMeshes; iMesh++)
{
u32 meshIndex = pNode->mMeshes[iMesh];
const aiMesh *pMesh = pScene->mMeshes[meshIndex];
SSurface *pSurf = loader.LoadAssimpMesh(pMesh, &matSet);
u32 MeshIndex = pkNode->mMeshes[iMesh];
const aiMesh *pkMesh = pkScene->mMeshes[MeshIndex];
SSurface *pSurf = Loader.LoadAssimpMesh(pkMesh, &rMatSet);
loader.mpModel->mSurfaces.push_back(pSurf);
loader.mpModel->mAABox.ExpandBounds(pSurf->AABox);
loader.mpModel->mVertexCount += pSurf->VertexCount;
loader.mpModel->mTriangleCount += pSurf->TriangleCount;
Loader.mpModel->mSurfaces.push_back(pSurf);
Loader.mpModel->mAABox.ExpandBounds(pSurf->AABox);
Loader.mpModel->mVertexCount += pSurf->VertexCount;
Loader.mpModel->mTriangleCount += pSurf->TriangleCount;
}
return loader.mpModel;
return Loader.mpModel;
}
EGame CModelLoader::GetFormatVersion(u32 Version)

View File

@@ -46,21 +46,21 @@ private:
CModelLoader();
~CModelLoader();
void LoadWorldMeshHeader(IInputStream& Model);
void LoadAttribArrays(IInputStream& Model);
void LoadAttribArraysDKCR(IInputStream& Model);
void LoadSurfaceOffsets(IInputStream& Model);
SSurface* LoadSurface(IInputStream& Model);
void LoadSurfaceHeaderPrime(IInputStream& Model, SSurface *pSurf);
void LoadSurfaceHeaderDKCR(IInputStream& Model, SSurface *pSurf);
SSurface* LoadAssimpMesh(const aiMesh *pMesh, CMaterialSet *pSet);
void LoadWorldMeshHeader(IInputStream& rModel);
void LoadAttribArrays(IInputStream& rModel);
void LoadAttribArraysDKCR(IInputStream& rModel);
void LoadSurfaceOffsets(IInputStream& rModel);
SSurface* LoadSurface(IInputStream& rModel);
void LoadSurfaceHeaderPrime(IInputStream& rModel, SSurface *pSurf);
void LoadSurfaceHeaderDKCR(IInputStream& rModel, SSurface *pSurf);
SSurface* LoadAssimpMesh(const aiMesh *pkMesh, CMaterialSet *pSet);
public:
static CModel* LoadCMDL(IInputStream& CMDL);
static CModel* LoadWorldModel(IInputStream& MREA, CSectionMgrIn& BlockMgr, CMaterialSet& MatSet, EGame Version);
static CModel* LoadCorruptionWorldModel(IInputStream& MREA, CSectionMgrIn& BlockMgr, CMaterialSet& MatSet, u32 HeaderSecNum, u32 GPUSecNum, EGame Version);
static CModel* LoadCMDL(IInputStream& rCMDL);
static CModel* LoadWorldModel(IInputStream& rMREA, CSectionMgrIn& rBlockMgr, CMaterialSet& rMatSet, EGame Version);
static CModel* LoadCorruptionWorldModel(IInputStream& rMREA, CSectionMgrIn& rBlockMgr, CMaterialSet& rMatSet, u32 HeaderSecNum, u32 GPUSecNum, EGame Version);
static void BuildWorldMeshes(const std::vector<CModel*>& rkIn, std::vector<CModel*>& rOut, bool DeleteInputModels);
static CModel* ImportAssimpNode(const aiNode *pNode, const aiScene *pScene, CMaterialSet& matSet);
static CModel* ImportAssimpNode(const aiNode *pkNode, const aiScene *pkScene, CMaterialSet& rMatSet);
static EGame GetFormatVersion(u32 Version);
};

View File

@@ -6,132 +6,132 @@ CScanLoader::CScanLoader()
{
}
CScan* CScanLoader::LoadScanMP1(IInputStream &SCAN)
CScan* CScanLoader::LoadScanMP1(IInputStream& rSCAN)
{
// Basic support at the moment - don't read animation/scan image data
SCAN.Seek(0x4, SEEK_CUR); // Skip FRME ID
mpScan->mpStringTable = gResCache.GetResource(SCAN.ReadLong(), "STRG");
mpScan->mIsSlow = (SCAN.ReadLong() != 0);
mpScan->mCategory = (CScan::ELogbookCategory) SCAN.ReadLong();
mpScan->mIsImportant = (SCAN.ReadByte() == 1);
rSCAN.Seek(0x4, SEEK_CUR); // Skip FRME ID
mpScan->mpStringTable = gResCache.GetResource(rSCAN.ReadLong(), "STRG");
mpScan->mIsSlow = (rSCAN.ReadLong() != 0);
mpScan->mCategory = (CScan::ELogbookCategory) rSCAN.ReadLong();
mpScan->mIsImportant = (rSCAN.ReadByte() == 1);
mpScan->mVersion = ePrime;
return mpScan;
}
CScan* CScanLoader::LoadScanMP2(IInputStream& SCAN)
CScan* CScanLoader::LoadScanMP2(IInputStream& rSCAN)
{
// The SCAN format in MP2 embeds a SNFO object using the same format as SCLY
// However since the contents of the file are consistent there's no need to delegate to CScriptLoader
SCAN.Seek(0x1, SEEK_CUR);
u32 NumInstances = SCAN.ReadLong();
rSCAN.Seek(0x1, SEEK_CUR);
u32 NumInstances = rSCAN.ReadLong();
if (NumInstances != 1) {
Log::FileError(SCAN.GetSourceString(), "SCAN has multiple instances");
Log::FileError(rSCAN.GetSourceString(), "SCAN has multiple instances");
return nullptr;
}
u32 ScanInfoStart = SCAN.Tell();
u32 ScanInfoStart = rSCAN.Tell();
CFourCC SNFO(SCAN);
CFourCC SNFO(rSCAN);
if (SNFO != "SNFO") {
Log::FileError(SCAN.GetSourceString(), ScanInfoStart, "Unrecognized SCAN object type: " + SNFO.ToString());
Log::FileError(rSCAN.GetSourceString(), ScanInfoStart, "Unrecognized SCAN object type: " + SNFO.ToString());
return nullptr;
}
SCAN.Seek(0x6, SEEK_CUR);
u16 NumConnections = SCAN.ReadShort();
rSCAN.Seek(0x6, SEEK_CUR);
u16 NumConnections = rSCAN.ReadShort();
if (NumConnections > 0) {
Log::FileWarning(SCAN.GetSourceString(), ScanInfoStart, "SNFO object in SCAN has connections");
SCAN.Seek(NumConnections * 0xC, SEEK_CUR);
Log::FileWarning(rSCAN.GetSourceString(), ScanInfoStart, "SNFO object in SCAN has connections");
rSCAN.Seek(NumConnections * 0xC, SEEK_CUR);
}
u32 BasePropID = SCAN.ReadLong();
u32 BasePropID = rSCAN.ReadLong();
if (BasePropID != 0xFFFFFFFF) {
Log::FileError(SCAN.GetSourceString(), SCAN.Tell() - 4, "Invalid base proprty ID: " + TString::HexString(BasePropID));
Log::FileError(rSCAN.GetSourceString(), rSCAN.Tell() - 4, "Invalid base property ID: " + TString::HexString(BasePropID));
return nullptr;
}
SCAN.Seek(0x2, SEEK_CUR);
u16 NumProperties = SCAN.ReadShort();
rSCAN.Seek(0x2, SEEK_CUR);
u16 NumProperties = rSCAN.ReadShort();
switch (NumProperties)
{
case 0x14:
case 0xB:
mpScan = new CScan();
LoadParamsMP2(SCAN);
LoadParamsMP2(rSCAN);
break;
case 0x12:
case 0x16:
mpScan = new CScan();
LoadParamsMP3(SCAN);
LoadParamsMP3(rSCAN);
break;
default:
Log::FileError(SCAN.GetSourceString(), SCAN.Tell() - 2, "Invalid SNFO property count: " + TString::HexString(NumProperties));
Log::FileError(rSCAN.GetSourceString(), rSCAN.Tell() - 2, "Invalid SNFO property count: " + TString::HexString(NumProperties));
return nullptr;
}
return mpScan;
}
void CScanLoader::LoadParamsMP2(IInputStream& SCAN)
void CScanLoader::LoadParamsMP2(IInputStream& rSCAN)
{
// Function begins after the SNFO property count
for (u32 iProp = 0; iProp < 20; iProp++)
{
u32 PropertyID = SCAN.ReadLong();
u16 PropertySize = SCAN.ReadShort();
u32 Next = SCAN.Tell() + PropertySize;
u32 PropertyID = rSCAN.ReadLong();
u16 PropertySize = rSCAN.ReadShort();
u32 Next = rSCAN.Tell() + PropertySize;
switch (PropertyID)
{
case 0x2F5B6423:
mpScan->mpStringTable = gResCache.GetResource(SCAN.ReadLong(), "STRG");
mpScan->mpStringTable = gResCache.GetResource(rSCAN.ReadLong(), "STRG");
break;
case 0xC308A322:
mpScan->mIsSlow = (SCAN.ReadLong() != 0);
mpScan->mIsSlow = (rSCAN.ReadLong() != 0);
break;
case 0x7B714814:
mpScan->mIsImportant = (SCAN.ReadByte() != 0);
mpScan->mIsImportant = (rSCAN.ReadByte() != 0);
break;
}
SCAN.Seek(Next, SEEK_SET);
rSCAN.Seek(Next, SEEK_SET);
}
mpScan->mCategory = CScan::eNone;
mpScan->mVersion = eEchoes;
}
void CScanLoader::LoadParamsMP3(IInputStream& SCAN)
void CScanLoader::LoadParamsMP3(IInputStream& rSCAN)
{
// Function begins after the SNFO property count
// Function is near-identical to the MP2 one, but when I add support
// for the other params, there will be more differences
for (u32 iProp = 0; iProp < 20; iProp++)
{
u32 PropertyID = SCAN.ReadLong();
u16 PropertySize = SCAN.ReadShort();
u32 Next = SCAN.Tell() + PropertySize;
u32 PropertyID = rSCAN.ReadLong();
u16 PropertySize = rSCAN.ReadShort();
u32 Next = rSCAN.Tell() + PropertySize;
switch (PropertyID)
{
case 0x2F5B6423:
mpScan->mpStringTable = gResCache.GetResource(SCAN.ReadLongLong(), "STRG");
mpScan->mpStringTable = gResCache.GetResource(rSCAN.ReadLongLong(), "STRG");
break;
case 0xC308A322:
mpScan->mIsSlow = (SCAN.ReadLong() != 0);
mpScan->mIsSlow = (rSCAN.ReadLong() != 0);
break;
case 0x7B714814:
mpScan->mIsImportant = (SCAN.ReadByte() != 0);
mpScan->mIsImportant = (rSCAN.ReadByte() != 0);
break;
}
SCAN.Seek(Next, SEEK_SET);
rSCAN.Seek(Next, SEEK_SET);
}
mpScan->mCategory = CScan::eNone;
@@ -139,43 +139,43 @@ void CScanLoader::LoadParamsMP3(IInputStream& SCAN)
}
// ************ STATIC/PUBLIC ************
CScan* CScanLoader::LoadSCAN(IInputStream &SCAN)
CScan* CScanLoader::LoadSCAN(IInputStream& rSCAN)
{
if (!SCAN.IsValid()) return nullptr;
if (!rSCAN.IsValid()) return nullptr;
/* Switching to EGame enum here isn't really useful unfortunately
* because the MP1 demo can be 1, 2, or 3, while MP1 is 5 and MP2+ is 2
* MP1 is the only one that starts with 5 so that is a consistent check for now
* Better version checks will be implemented when the other versions are
* better-understood. */
u32 fileVersion = SCAN.ReadLong();
u32 magic = SCAN.ReadLong();
u32 FileVersion = rSCAN.ReadLong();
u32 Magic = rSCAN.ReadLong();
// Echoes+
if (CFourCC(fileVersion) == "SCAN")
if (CFourCC(FileVersion) == "SCAN")
{
// The MP2 load function will check for MP3
CScanLoader loader;
loader.mVersion = eEchoes;
if (magic == 0x01000000) SCAN.Seek(-4, SEEK_CUR); // The version number isn't present in the Echoes demo
return loader.LoadScanMP2(SCAN);
CScanLoader Loader;
Loader.mVersion = eEchoes;
if (Magic == 0x01000000) rSCAN.Seek(-4, SEEK_CUR); // The version number isn't present in the Echoes demo
return Loader.LoadScanMP2(rSCAN);
}
if (magic != 0x0BADBEEF)
if (Magic != 0x0BADBEEF)
{
Log::FileError(SCAN.GetSourceString(), "Invalid SCAN magic: " + TString::HexString(magic));
Log::FileError(rSCAN.GetSourceString(), "Invalid SCAN magic: " + TString::HexString(Magic));
return nullptr;
}
if (fileVersion != 5)
if (FileVersion != 5)
{
Log::FileError(SCAN.GetSourceString(), "Unsupported SCAN version: " + TString::HexString(fileVersion));
Log::FileError(rSCAN.GetSourceString(), "Unsupported SCAN version: " + TString::HexString(FileVersion, 0));
return nullptr;
}
// MP1 SCAN - read the file!
CScanLoader loader;
loader.mVersion = ePrime;
loader.mpScan = new CScan();
return loader.LoadScanMP1(SCAN);
CScanLoader Loader;
Loader.mVersion = ePrime;
Loader.mpScan = new CScan();
return Loader.LoadScanMP1(rSCAN);
}

View File

@@ -10,13 +10,13 @@ class CScanLoader
EGame mVersion;
CScanLoader();
CScan* LoadScanMP1(IInputStream& SCAN);
CScan* LoadScanMP2(IInputStream& SCAN);
void LoadParamsMP2(IInputStream& SCAN);
void LoadParamsMP3(IInputStream& SCAN);
CScan* LoadScanMP1(IInputStream& rSCAN);
CScan* LoadScanMP2(IInputStream& rSCAN);
void LoadParamsMP2(IInputStream& rSCAN);
void LoadParamsMP3(IInputStream& rSCAN);
public:
static CScan* LoadSCAN(IInputStream& SCAN);
static CScan* LoadSCAN(IInputStream& rSCAN);
};
#endif // CSCANLOADER_H

View File

@@ -7,8 +7,8 @@
#include <sstream>
CScriptLoader::CScriptLoader()
: mpObj(nullptr)
{
mpObj = nullptr;
}
void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY)
@@ -18,85 +18,96 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY
switch (pTemp->Type())
{
case eBoolProperty: {
case eBoolProperty:
{
TBoolProperty *pBoolCast = static_cast<TBoolProperty*>(pProp);
pBoolCast->Set( (rSCLY.ReadByte() != 0) );
break;
}
case eByteProperty: {
case eByteProperty:
{
TByteProperty *pByteCast = static_cast<TByteProperty*>(pProp);
pByteCast->Set(rSCLY.ReadByte());
break;
}
case eShortProperty: {
case eShortProperty:
{
TShortProperty *pShortCast = static_cast<TShortProperty*>(pProp);
pShortCast->Set(rSCLY.ReadShort());
break;
}
case eLongProperty: {
case eLongProperty:
{
TLongProperty *pLongCast = static_cast<TLongProperty*>(pProp);
pLongCast->Set(rSCLY.ReadLong());
break;
}
case eBitfieldProperty: {
case eBitfieldProperty:
{
TBitfieldProperty *pBitfieldCast = static_cast<TBitfieldProperty*>(pProp);
pBitfieldCast->Set(rSCLY.ReadLong());
// Validate
u32 mask = 0;
u32 Mask = 0;
CBitfieldTemplate *pBitfieldTemp = static_cast<CBitfieldTemplate*>(pTemp);
for (u32 iMask = 0; iMask < pBitfieldTemp->NumFlags(); iMask++)
mask |= pBitfieldTemp->FlagMask(iMask);
Mask |= pBitfieldTemp->FlagMask(iMask);
u32 check = pBitfieldCast->Get() & ~mask;
if (check != 0)
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Bitfield property \"" + pBitfieldTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has flags set that aren't in the template: " + TString::HexString(check, true, true, 8));
u32 Check = pBitfieldCast->Get() & ~Mask;
if (Check != 0)
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Bitfield property \"" + pBitfieldTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has flags set that aren't in the template: " + TString::HexString(Check));
break;
}
case eEnumProperty: {
case eEnumProperty:
{
TEnumProperty *pEnumCast = static_cast<TEnumProperty*>(pProp);
CEnumTemplate *pEnumTemp = static_cast<CEnumTemplate*>(pTemp);
u32 ID = rSCLY.ReadLong();
// Validate
u32 Index = pEnumTemp->EnumeratorIndex(ID);
if (Index == -1) Log::FileError(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Enum property \"" + pEnumTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has invalid enumerator value: " + TString::HexString(ID, true, true, 8));
if (Index == -1) Log::FileError(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Enum property \"" + pEnumTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has invalid enumerator value: " + TString::HexString(ID));
pEnumCast->Set(ID);
break;
}
case eFloatProperty: {
case eFloatProperty:
{
TFloatProperty *pFloatCast = static_cast<TFloatProperty*>(pProp);
pFloatCast->Set(rSCLY.ReadFloat());
break;
}
case eStringProperty: {
case eStringProperty:
{
TStringProperty *pStringCast = static_cast<TStringProperty*>(pProp);
pStringCast->Set(rSCLY.ReadString());
break;
}
case eVector3Property: {
case eVector3Property:
{
TVector3Property *pVector3Cast = static_cast<TVector3Property*>(pProp);
pVector3Cast->Set(CVector3f(rSCLY));
break;
}
case eColorProperty: {
case eColorProperty:
{
TColorProperty *pColorCast = static_cast<TColorProperty*>(pProp);
pColorCast->Set(CColor(rSCLY));
break;
}
case eFileProperty: {
case eFileProperty:
{
TFileProperty *pFileCast = static_cast<TFileProperty*>(pProp);
CUniqueID ResID = (mVersion < eCorruptionProto ? rSCLY.ReadLong() : rSCLY.ReadLongLong());
@@ -114,7 +125,8 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY
break;
}
case eStructProperty: {
case eStructProperty:
{
CPropertyStruct *pStructCast = static_cast<CPropertyStruct*>(pProp);
if (mVersion < eEchoesDemo)
@@ -124,7 +136,8 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY
break;
}
case eArrayProperty: {
case eArrayProperty:
{
CArrayProperty *pArrayCast = static_cast<CArrayProperty*>(pProp);
int Count = rSCLY.ReadLong();
@@ -140,13 +153,15 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY
break;
}
case eCharacterProperty: {
case eCharacterProperty:
{
TCharacterProperty *pAnimCast = static_cast<TCharacterProperty*>(pProp);
pAnimCast->Set(CAnimationParameters(rSCLY, mpMaster->GetGame()));
pAnimCast->Set(CAnimationParameters(rSCLY, mpMaster->Game()));
break;
}
case eMayaSplineProperty: {
case eMayaSplineProperty:
{
TMayaSplineProperty *pSplineCast = static_cast<TMayaSplineProperty*>(pProp);
std::vector<u8> Buffer(Size);
rSCLY.ReadBytes(Buffer.data(), Buffer.size());
@@ -154,7 +169,8 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY
break;
}
case eUnknownProperty: {
case eUnknownProperty:
{
TUnknownProperty *pUnknownCast = static_cast<TUnknownProperty*>(pProp);
std::vector<u8> Buffer(Size);
rSCLY.ReadBytes(Buffer.data(), Buffer.size());
@@ -182,7 +198,7 @@ void CScriptLoader::LoadStructMP1(IInputStream& rSCLY, CPropertyStruct *pStruct,
TIDString IDString = pTemp->IDString(true);
if (!IDString.IsEmpty()) IDString = " (" + IDString + ")";
Log::FileWarning(rSCLY.GetSourceString(), StructStart, "Struct \"" + pTemp->Name() + "\"" + IDString + " template prop count doesn't match file; template is " + TString::HexString(PropCount, true, true, 2) + ", file is " + TString::HexString(FilePropCount, true, true, 2));
Log::FileWarning(rSCLY.GetSourceString(), StructStart, "Struct \"" + pTemp->Name() + "\"" + IDString + " template prop count doesn't match file; template is " + TString::HexString(PropCount, 2) + ", file is " + TString::HexString(FilePropCount, 2));
Version = 0;
}
}
@@ -209,7 +225,7 @@ CScriptObject* CScriptLoader::LoadObjectMP1(IInputStream& rSCLY)
if (!pTemp)
{
// No valid template for this object; can't load
Log::FileError(rSCLY.GetSourceString(), ObjStart, "Unknown object ID encountered: " + TString::HexString(Type));
Log::FileError(rSCLY.GetSourceString(), ObjStart, "Unknown object ID encountered: " + TString::HexString(Type, 2));
rSCLY.Seek(End, SEEK_SET);
return nullptr;
}
@@ -381,7 +397,7 @@ CScriptLayer* CScriptLoader::LoadLayer(IInputStream& rSCLY, CGameArea *pArea, EG
CScriptLoader Loader;
Loader.mVersion = Version;
Loader.mpMaster = CMasterTemplate::GetMasterForGame(Version);
Loader.mpMaster = CMasterTemplate::MasterForGame(Version);
Loader.mpArea = pArea;
if (!Loader.mpMaster)
@@ -405,7 +421,7 @@ CScriptObject* CScriptLoader::LoadInstance(IInputStream& rSCLY, CGameArea *pArea
CScriptLoader Loader;
Loader.mVersion = (ForceReturnsFormat ? eReturns : Version);
Loader.mpMaster = CMasterTemplate::GetMasterForGame(Version);
Loader.mpMaster = CMasterTemplate::MasterForGame(Version);
Loader.mpArea = pArea;
Loader.mpLayer = pLayer;

View File

@@ -28,7 +28,7 @@ class CScriptLoader
public:
static CScriptLayer* LoadLayer(IInputStream& rSCLY, CGameArea *pArea, EGame Version);
static CScriptObject* LoadInstance(IInputStream& rSCLY, CGameArea *pArea, CScriptLayer *pLayer,EGame Version, bool ForceReturnsFormat);
static CScriptObject* LoadInstance(IInputStream& rSCLY, CGameArea *pArea, CScriptLayer *pLayer, EGame Version, bool ForceReturnsFormat);
};
#endif // CSCRIPTLOADER_H

View File

@@ -50,11 +50,11 @@ public:
mCurSec++;
}
inline u32 NextOffset() { return mCurSecStart + mSectionSizes[mCurSec]; }
inline u32 CurrentSection() { return mCurSec; }
inline u32 CurrentSectionSize() { return mSectionSizes[mCurSec]; }
inline u32 NumSections() { return mSectionSizes.size(); }
inline void SetInputStream(IInputStream *pIn) { mpInputStream = pIn; }
inline u32 NextOffset() { return mCurSecStart + mSectionSizes[mCurSec]; }
inline u32 CurrentSection() { return mCurSec; }
inline u32 CurrentSectionSize() { return mSectionSizes[mCurSec]; }
inline u32 NumSections() { return mSectionSizes.size(); }
inline void SetInputStream(IInputStream *pIn) { mpInputStream = pIn; }
};
#endif // CSECTIONMGRIN_H

View File

@@ -5,39 +5,39 @@ CStringLoader::CStringLoader()
{
}
void CStringLoader::LoadPrimeDemoSTRG(IInputStream& STRG)
void CStringLoader::LoadPrimeDemoSTRG(IInputStream& rSTRG)
{
// This function starts at 0x4 in the file - right after the size
// This STRG version only supports one language per file
mpStringTable->mLangTables.resize(1);
CStringTable::SLangTable* Lang = &mpStringTable->mLangTables[1];
Lang->Language = "ENGL";
u32 TableStart = STRG.Tell();
u32 TableStart = rSTRG.Tell();
// Header
u32 NumStrings = STRG.ReadLong();
u32 NumStrings = rSTRG.ReadLong();
Lang->Strings.resize(NumStrings);
mpStringTable->mNumStrings = NumStrings;
// String offsets (yeah, that wasn't much of a header)
std::vector<u32> StringOffsets(NumStrings);
for (u32 iOff = 0; iOff < StringOffsets.size(); iOff++)
StringOffsets[iOff] = STRG.ReadLong();
StringOffsets[iOff] = rSTRG.ReadLong();
// Strings
for (u32 iStr = 0; iStr < NumStrings; iStr++)
{
STRG.Seek(TableStart + StringOffsets[iStr], SEEK_SET);
Lang->Strings[iStr] = STRG.ReadWString();
rSTRG.Seek(TableStart + StringOffsets[iStr], SEEK_SET);
Lang->Strings[iStr] = rSTRG.ReadWString();
}
}
void CStringLoader::LoadPrimeSTRG(IInputStream& STRG)
void CStringLoader::LoadPrimeSTRG(IInputStream& rSTRG)
{
// This function starts at 0x8 in the file, after magic/version
// Header
u32 NumLanguages = STRG.ReadLong();
u32 NumStrings = STRG.ReadLong();
u32 NumLanguages = rSTRG.ReadLong();
u32 NumStrings = rSTRG.ReadLong();
mpStringTable->mNumStrings = NumStrings;
// Language definitions
@@ -46,70 +46,70 @@ void CStringLoader::LoadPrimeSTRG(IInputStream& STRG)
for (u32 iLang = 0; iLang < NumLanguages; iLang++)
{
mpStringTable->mLangTables[iLang].Language = CFourCC(STRG);
LangOffsets[iLang] = STRG.ReadLong();
if (mVersion == eEchoes) STRG.Seek(0x4, SEEK_CUR); // Skipping strings size
mpStringTable->mLangTables[iLang].Language = CFourCC(rSTRG);
LangOffsets[iLang] = rSTRG.ReadLong();
if (mVersion == eEchoes) rSTRG.Seek(0x4, SEEK_CUR); // Skipping strings size
}
// String names
if (mVersion == eEchoes)
LoadNameTable(STRG);
LoadNameTable(rSTRG);
// Strings
u32 StringsStart = STRG.Tell();
u32 StringsStart = rSTRG.Tell();
for (u32 iLang = 0; iLang < NumLanguages; iLang++)
{
STRG.Seek(StringsStart + LangOffsets[iLang], SEEK_SET);
if (mVersion == ePrime) STRG.Seek(0x4, SEEK_CUR); // Skipping strings size
rSTRG.Seek(StringsStart + LangOffsets[iLang], SEEK_SET);
if (mVersion == ePrime) rSTRG.Seek(0x4, SEEK_CUR); // Skipping strings size
u32 LangStart = STRG.Tell();
u32 LangStart = rSTRG.Tell();
CStringTable::SLangTable* pLang = &mpStringTable->mLangTables[iLang];
pLang->Strings.resize(NumStrings);
// Offsets
std::vector<u32> StringOffsets(NumStrings);
for (u32 iOff = 0; iOff < NumStrings; iOff++)
StringOffsets[iOff] = STRG.ReadLong();
StringOffsets[iOff] = rSTRG.ReadLong();
// The actual strings
for (u32 iStr = 0; iStr < NumStrings; iStr++)
{
STRG.Seek(LangStart + StringOffsets[iStr], SEEK_SET);
pLang->Strings[iStr] = STRG.ReadWString();
rSTRG.Seek(LangStart + StringOffsets[iStr], SEEK_SET);
pLang->Strings[iStr] = rSTRG.ReadWString();
}
}
}
void CStringLoader::LoadCorruptionSTRG(IInputStream& STRG)
void CStringLoader::LoadCorruptionSTRG(IInputStream& rSTRG)
{
// This function starts at 0x8 in the file, after magic/version
// Header
u32 NumLanguages = STRG.ReadLong();
u32 NumStrings = STRG.ReadLong();
u32 NumLanguages = rSTRG.ReadLong();
u32 NumStrings = rSTRG.ReadLong();
mpStringTable->mNumStrings = NumStrings;
// String names
LoadNameTable(STRG);
LoadNameTable(rSTRG);
// Language definitions
mpStringTable->mLangTables.resize(NumLanguages);
std::vector<std::vector<u32>> LangOffsets(NumLanguages);
for (u32 iLang = 0; iLang < NumLanguages; iLang++)
mpStringTable->mLangTables[iLang].Language = CFourCC(STRG);
mpStringTable->mLangTables[iLang].Language = CFourCC(rSTRG);
for (u32 iLang = 0; iLang < NumLanguages; iLang++)
{
LangOffsets[iLang].resize(NumStrings);
STRG.Seek(0x4, SEEK_CUR); // Skipping total string size
rSTRG.Seek(0x4, SEEK_CUR); // Skipping total string size
for (u32 iStr = 0; iStr < NumStrings; iStr++)
LangOffsets[iLang][iStr] = STRG.ReadLong();
LangOffsets[iLang][iStr] = rSTRG.ReadLong();
}
// Strings
u32 StringsStart = STRG.Tell();
u32 StringsStart = rSTRG.Tell();
for (u32 iLang = 0; iLang < NumLanguages; iLang++)
{
@@ -118,20 +118,20 @@ void CStringLoader::LoadCorruptionSTRG(IInputStream& STRG)
for (u32 iStr = 0; iStr < NumStrings; iStr++)
{
STRG.Seek(StringsStart + LangOffsets[iLang][iStr], SEEK_SET);
STRG.Seek(0x4, SEEK_CUR); // Skipping string size
rSTRG.Seek(StringsStart + LangOffsets[iLang][iStr], SEEK_SET);
rSTRG.Seek(0x4, SEEK_CUR); // Skipping string size
pLang->Strings[iStr] = STRG.ReadString();
pLang->Strings[iStr] = rSTRG.ReadString();
}
}
}
void CStringLoader::LoadNameTable(IInputStream& STRG)
void CStringLoader::LoadNameTable(IInputStream& rSTRG)
{
// Name table header
u32 NameCount = STRG.ReadLong();
u32 NameTableSize = STRG.ReadLong();
u32 NameTableStart = STRG.Tell();
u32 NameCount = rSTRG.ReadLong();
u32 NameTableSize = rSTRG.ReadLong();
u32 NameTableStart = rSTRG.Tell();
u32 NameTableEnd = NameTableStart + NameTableSize;
// Name definitions
@@ -142,8 +142,8 @@ void CStringLoader::LoadNameTable(IInputStream& STRG)
for (u32 iName = 0; iName < NameCount; iName++)
{
NameDefs[iName].NameOffset = STRG.ReadLong() + NameTableStart;
NameDefs[iName].StringIndex = STRG.ReadLong();
NameDefs[iName].NameOffset = rSTRG.ReadLong() + NameTableStart;
NameDefs[iName].StringIndex = rSTRG.ReadLong();
}
// Name strings
@@ -151,47 +151,47 @@ void CStringLoader::LoadNameTable(IInputStream& STRG)
for (u32 iName = 0; iName < NameCount; iName++)
{
SNameDef *pDef = &NameDefs[iName];
STRG.Seek(pDef->NameOffset, SEEK_SET);
mpStringTable->mStringNames[pDef->StringIndex] = STRG.ReadString();
rSTRG.Seek(pDef->NameOffset, SEEK_SET);
mpStringTable->mStringNames[pDef->StringIndex] = rSTRG.ReadString();
}
STRG.Seek(NameTableEnd, SEEK_SET);
rSTRG.Seek(NameTableEnd, SEEK_SET);
}
// ************ STATIC ************
CStringTable* CStringLoader::LoadSTRG(IInputStream& STRG)
CStringTable* CStringLoader::LoadSTRG(IInputStream& rSTRG)
{
// Verify that this is a valid STRG
if (!STRG.IsValid()) return nullptr;
if (!rSTRG.IsValid()) return nullptr;
u32 Magic = STRG.ReadLong();
u32 Magic = rSTRG.ReadLong();
EGame Version = eUnknownVersion;
if (Magic != 0x87654321)
{
// Check for MP1 Demo STRG format - no magic/version; the first value is actually the filesize
// so the best I can do is verify the first value actually points to the end of the file
if (Magic <= (u32) STRG.Size())
if (Magic <= (u32) rSTRG.Size())
{
STRG.Seek(Magic, SEEK_SET);
if ((STRG.EoF()) || (STRG.ReadShort() == 0xFFFF))
rSTRG.Seek(Magic, SEEK_SET);
if ((rSTRG.EoF()) || (rSTRG.ReadShort() == 0xFFFF))
Version = ePrimeDemo;
}
if (Version != ePrimeDemo)
{
Log::FileError(STRG.GetSourceString(), "Invalid STRG magic: " + TString::HexString(Magic));
Log::FileError(rSTRG.GetSourceString(), "Invalid STRG magic: " + TString::HexString(Magic));
return nullptr;
}
}
else
{
u32 FileVersion = STRG.ReadLong();
u32 FileVersion = rSTRG.ReadLong();
Version = GetFormatVersion(FileVersion);
if (FileVersion == eUnknownVersion)
{
Log::FileError(STRG.GetSourceString(), "Unsupported STRG version: " + TString::HexString(FileVersion));
Log::FileError(rSTRG.GetSourceString(), "Unsupported STRG version: " + TString::HexString(FileVersion, 0));
return nullptr;
}
}
@@ -201,9 +201,9 @@ CStringTable* CStringLoader::LoadSTRG(IInputStream& STRG)
Loader.mpStringTable = new CStringTable();
Loader.mVersion = Version;
if (Version == ePrimeDemo) Loader.LoadPrimeDemoSTRG(STRG);
else if (Version < eCorruption) Loader.LoadPrimeSTRG(STRG);
else Loader.LoadCorruptionSTRG(STRG);
if (Version == ePrimeDemo) Loader.LoadPrimeDemoSTRG(rSTRG);
else if (Version < eCorruption) Loader.LoadPrimeSTRG(rSTRG);
else Loader.LoadCorruptionSTRG(rSTRG);
return Loader.mpStringTable;
}

View File

@@ -12,13 +12,13 @@ class CStringLoader
EGame mVersion;
CStringLoader();
void LoadPrimeDemoSTRG(IInputStream& STRG);
void LoadPrimeSTRG(IInputStream& STRG);
void LoadCorruptionSTRG(IInputStream& STRG);
void LoadNameTable(IInputStream& STRG);
void LoadPrimeDemoSTRG(IInputStream& rSTRG);
void LoadPrimeSTRG(IInputStream& rSTRG);
void LoadCorruptionSTRG(IInputStream& rSTRG);
void LoadNameTable(IInputStream& rSTRG);
public:
static CStringTable* LoadSTRG(IInputStream& STRG);
static CStringTable* LoadSTRG(IInputStream& rSTRG);
static EGame GetFormatVersion(u32 Version);
};

View File

@@ -30,10 +30,10 @@ IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CScriptTempl
if (!NameAttr.IsEmpty())
Name = NameAttr;
else if (mGame >= eEchoesDemo)
Name = CMasterTemplate::GetPropertyName(ID);
Name = CMasterTemplate::PropertyName(ID);
else
{
Log::Error(rkTemplateName + ": Property " + TString::HexString(ID, true, true, 8) + " doesn't have a name either in the template itself nor in the master list");
Log::Error(rkTemplateName + ": Property " + TString::HexString(ID) + " doesn't have a name either in the template itself nor in the master list");
return nullptr;
}
@@ -53,9 +53,9 @@ IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CScriptTempl
if (Type == eInvalidProperty)
{
if (TypeStr.IsEmpty())
Log::Error(rkTemplateName + ": Property " + TString::HexString(ID, true, true, 8) + " doesn't have a type set");
Log::Error(rkTemplateName + ": Property " + TString::HexString(ID) + " doesn't have a type set");
else
Log::Error(rkTemplateName + ": Property " + TString::HexString(ID, true, true, 8) + " has an invalid type set: " + TypeStr);
Log::Error(rkTemplateName + ": Property " + TString::HexString(ID) + " has an invalid type set: " + TypeStr);
return nullptr;
}
@@ -64,7 +64,7 @@ IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CScriptTempl
if (!pProp)
{
Log::Error(rkTemplateName + ": Property " + TString::HexString(ID, true, true, 8) + " seems to be using a valid but unsupported property type? (" + TypeStr + ")");
Log::Error(rkTemplateName + ": Property " + TString::HexString(ID) + " seems to be using a valid but unsupported property type? (" + TypeStr + ")");
return nullptr;
}
}
@@ -87,10 +87,10 @@ IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CScriptTempl
while (pVersion)
{
TString VerName = pVersion->GetText();
u32 VerIdx = mpMaster->GetGameVersion(VerName);
u32 VerIdx = mpMaster->GameVersion(VerName);
if (VerIdx == -1)
Log::Error(rkTemplateName + ": Property " + TString::HexString(ID, true, true, 8) + " has invalid version \"" + VerName + "\"");
Log::Error(rkTemplateName + ": Property " + TString::HexString(ID) + " has invalid version \"" + VerName + "\"");
else
pProp->mAllowedVersions.push_back(VerIdx);
@@ -886,13 +886,13 @@ void CTemplateLoader::LoadGameList()
void CTemplateLoader::LoadGameTemplates(EGame Game)
{
std::list<CMasterTemplate*> MasterList = CMasterTemplate::GetMasterList();
std::list<CMasterTemplate*> MasterList = CMasterTemplate::MasterList();
for (auto it = MasterList.begin(); it != MasterList.end(); it++)
{
CMasterTemplate *pMaster = *it;
if (pMaster->GetGame() == Game && !pMaster->IsLoadedSuccessfully())
if (pMaster->Game() == Game && !pMaster->IsLoadedSuccessfully())
{
XMLDocument MasterXML;
OpenXML(mskTemplatesDir + pMaster->mSourceFile, MasterXML);
@@ -911,7 +911,7 @@ void CTemplateLoader::LoadGameTemplates(EGame Game)
void CTemplateLoader::LoadAllGames()
{
std::list<CMasterTemplate*> MasterList = CMasterTemplate::GetMasterList();
std::list<CMasterTemplate*> MasterList = CMasterTemplate::MasterList();
for (auto it = MasterList.begin(); it != MasterList.end(); it++)
{
@@ -925,7 +925,7 @@ void CTemplateLoader::LoadAllGames()
if (!MasterXML.Error())
{
CTemplateLoader Loader(mskTemplatesDir);
Loader.mGame = pMaster->GetGame();
Loader.mGame = pMaster->Game();
Loader.LoadMasterTemplate(&MasterXML, pMaster);
}
}

View File

@@ -50,11 +50,12 @@ CTexture* CTextureDecoder::CreateTexture()
pTex->mHeight = mHeight;
pTex->mNumMipMaps = mNumMipMaps;
pTex->mLinearSize = (u32) (mWidth * mHeight * gskPixelsToBytes[mTexelFormat]);
pTex->mImgDataBuffer = mpDataBuffer;
pTex->mpImgDataBuffer = mpDataBuffer;
pTex->mImgDataSize = mDataBufferSize;
pTex->mBufferExists = true;
switch (mTexelFormat) {
switch (mTexelFormat)
{
case eGX_I4:
case eGX_I8:
case eGX_IA4:
@@ -90,86 +91,85 @@ CTexture* CTextureDecoder::CreateTexture()
}
// ************ STATIC ************
CTexture* CTextureDecoder::LoadTXTR(IInputStream& TXTR)
CTexture* CTextureDecoder::LoadTXTR(IInputStream& rTXTR)
{
CTextureDecoder Decoder;
Decoder.ReadTXTR(TXTR);
Decoder.PartialDecodeGXTexture(TXTR);
Decoder.ReadTXTR(rTXTR);
Decoder.PartialDecodeGXTexture(rTXTR);
return Decoder.CreateTexture();
}
CTexture* CTextureDecoder::DoFullDecode(IInputStream &TXTR)
CTexture* CTextureDecoder::DoFullDecode(IInputStream& rTXTR)
{
CTextureDecoder Decoder;
Decoder.ReadTXTR(TXTR);
Decoder.FullDecodeGXTexture(TXTR);
Decoder.ReadTXTR(rTXTR);
Decoder.FullDecodeGXTexture(rTXTR);
CTexture *pTexture = Decoder.CreateTexture();
pTexture->mTexelFormat = eRGBA8;
return pTexture;
}
CTexture* CTextureDecoder::LoadDDS(IInputStream &DDS)
CTexture* CTextureDecoder::LoadDDS(IInputStream& rDDS)
{
CTextureDecoder Decoder;
Decoder.ReadDDS(DDS);
Decoder.DecodeDDS(DDS);
Decoder.ReadDDS(rDDS);
Decoder.DecodeDDS(rDDS);
return Decoder.CreateTexture();
}
CTexture* CTextureDecoder::DoFullDecode(CTexture*)
CTexture* CTextureDecoder::DoFullDecode(CTexture* /*pTexture*/)
{
// Not using parameter 1 (CTexture* - pTexture)
return nullptr;
}
// ************ READ ************
void CTextureDecoder::ReadTXTR(IInputStream& TXTR)
void CTextureDecoder::ReadTXTR(IInputStream& rTXTR)
{
// Read TXTR header
mTexelFormat = ETexelFormat(TXTR.ReadLong());
mWidth = TXTR.ReadShort();
mHeight = TXTR.ReadShort();
mNumMipMaps = TXTR.ReadLong();
mTexelFormat = ETexelFormat(rTXTR.ReadLong());
mWidth = rTXTR.ReadShort();
mHeight = rTXTR.ReadShort();
mNumMipMaps = rTXTR.ReadLong();
// For C4 and C8 images, read palette
if ((mTexelFormat == eGX_C4) || (mTexelFormat == eGX_C8))
{
mHasPalettes = true;
mPaletteFormat = EGXPaletteFormat(TXTR.ReadLong());
TXTR.Seek(0x4, SEEK_CUR);
mPaletteFormat = EGXPaletteFormat(rTXTR.ReadLong());
rTXTR.Seek(0x4, SEEK_CUR);
u32 PaletteEntryCount = (mTexelFormat == eGX_C4) ? 16 : 256;
mPalettes.resize(PaletteEntryCount * 2);
TXTR.ReadBytes(mPalettes.data(), mPalettes.size());
rTXTR.ReadBytes(mPalettes.data(), mPalettes.size());
mPaletteInput.SetData(mPalettes.data(), mPalettes.size(), IOUtil::eBigEndian);
}
else mHasPalettes = false;
}
void CTextureDecoder::ReadDDS(IInputStream& DDS)
void CTextureDecoder::ReadDDS(IInputStream& rDDS)
{
// Header
CFourCC Magic(DDS);
CFourCC Magic(rDDS);
if (Magic != "DDS ")
{
Log::FileError(DDS.GetSourceString(), "Invalid DDS magic: " + TString::HexString((u32) Magic.ToLong()));
Log::FileError(rDDS.GetSourceString(), "Invalid DDS magic: " + TString::HexString(Magic.ToLong()));
return;
}
u32 ImageDataStart = DDS.Tell() + DDS.ReadLong();
DDS.Seek(0x4, SEEK_CUR); // Skipping flags
mHeight = (u16) DDS.ReadLong();
mWidth = (u16) DDS.ReadLong();
DDS.Seek(0x8, SEEK_CUR); // Skipping linear size + depth
mNumMipMaps = DDS.ReadLong() + 1; // DDS doesn't seem to count the first mipmap
DDS.Seek(0x2C, SEEK_CUR); // Skipping reserved
u32 ImageDataStart = rDDS.Tell() + rDDS.ReadLong();
rDDS.Seek(0x4, SEEK_CUR); // Skipping flags
mHeight = (u16) rDDS.ReadLong();
mWidth = (u16) rDDS.ReadLong();
rDDS.Seek(0x8, SEEK_CUR); // Skipping linear size + depth
mNumMipMaps = rDDS.ReadLong() + 1; // DDS doesn't seem to count the first mipmap
rDDS.Seek(0x2C, SEEK_CUR); // Skipping reserved
// Pixel Format
DDS.Seek(0x4, SEEK_CUR); // Skipping size
mDDSInfo.Flags = DDS.ReadLong();
CFourCC Format(DDS);
rDDS.Seek(0x4, SEEK_CUR); // Skipping size
mDDSInfo.Flags = rDDS.ReadLong();
CFourCC Format(rDDS);
if (Format == "DXT1") mDDSInfo.Format = SDDSInfo::DXT1;
else if (Format == "DXT2") mDDSInfo.Format = SDDSInfo::DXT2;
@@ -179,11 +179,11 @@ void CTextureDecoder::ReadDDS(IInputStream& DDS)
else
{
mDDSInfo.Format = SDDSInfo::RGBA;
mDDSInfo.BitCount = DDS.ReadLong();
mDDSInfo.RBitMask = DDS.ReadLong();
mDDSInfo.GBitMask = DDS.ReadLong();
mDDSInfo.BBitMask = DDS.ReadLong();
mDDSInfo.ABitMask = DDS.ReadLong();
mDDSInfo.BitCount = rDDS.ReadLong();
mDDSInfo.RBitMask = rDDS.ReadLong();
mDDSInfo.GBitMask = rDDS.ReadLong();
mDDSInfo.BBitMask = rDDS.ReadLong();
mDDSInfo.ABitMask = rDDS.ReadLong();
mDDSInfo.RShift = CalculateShiftForMask(mDDSInfo.RBitMask);
mDDSInfo.GShift = CalculateShiftForMask(mDDSInfo.GBitMask);
mDDSInfo.BShift = CalculateShiftForMask(mDDSInfo.BBitMask);
@@ -195,7 +195,7 @@ void CTextureDecoder::ReadDDS(IInputStream& DDS)
}
// Skip the rest
DDS.Seek(ImageDataStart, SEEK_SET);
rDDS.Seek(ImageDataStart, SEEK_SET);
}
// ************ DECODE ************
@@ -235,12 +235,12 @@ void CTextureDecoder::PartialDecodeGXTexture(IInputStream& TXTR)
for (u32 iMip = 0; iMip < mNumMipMaps; iMip++)
{
for (u32 BlockY = 0; BlockY < MipH; BlockY += BHeight)
for (u32 BlockX = 0; BlockX < MipW; BlockX += BWidth) {
for (u32 ImgY = BlockY; ImgY < BlockY + BHeight; ImgY++) {
for (u32 ImgX = BlockX; ImgX < BlockX + BWidth; ImgX++)
for (u32 iBlockY = 0; iBlockY < MipH; iBlockY += BHeight)
for (u32 iBlockX = 0; iBlockX < MipW; iBlockX += BWidth) {
for (u32 iImgY = iBlockY; iImgY < iBlockY + BHeight; iImgY++) {
for (u32 iImgX = iBlockX; iImgX < iBlockX + BWidth; iImgX++)
{
u32 DstPos = ((ImgY * MipW) + ImgX) * PixelStride;
u32 DstPos = ((iImgY * MipW) + iImgX) * PixelStride;
Out.Seek(MipOffset + DstPos, SEEK_SET);
if (mTexelFormat == eGX_I4) ReadPixelsI4(TXTR, Out);
@@ -255,7 +255,7 @@ void CTextureDecoder::PartialDecodeGXTexture(IInputStream& TXTR)
else if (mTexelFormat == eGX_CMPR) ReadSubBlockCMPR(TXTR, Out);
// I4 and C4 have 4bpp images, so I'm forced to read two pixels at a time.
if ((mTexelFormat == eGX_I4) || (mTexelFormat == eGX_C4)) ImgX++;
if ((mTexelFormat == eGX_I4) || (mTexelFormat == eGX_C4)) iImgX++;
}
}
if (mTexelFormat == eGX_RGBA8) TXTR.Seek(0x20, SEEK_CUR);
@@ -272,13 +272,13 @@ void CTextureDecoder::PartialDecodeGXTexture(IInputStream& TXTR)
}
}
void CTextureDecoder::FullDecodeGXTexture(IInputStream& TXTR)
void CTextureDecoder::FullDecodeGXTexture(IInputStream& rTXTR)
{
// Get image data size, create output buffer
u32 ImageStart = TXTR.Tell();
TXTR.Seek(0x0, SEEK_END);
u32 ImageSize = TXTR.Tell() - ImageStart;
TXTR.Seek(ImageStart, SEEK_SET);
u32 ImageStart = rTXTR.Tell();
rTXTR.Seek(0x0, SEEK_END);
u32 ImageSize = rTXTR.Tell() - ImageStart;
rTXTR.Seek(ImageStart, SEEK_SET);
mDataBufferSize = ImageSize * (32 / gskSourceBpp[mTexelFormat]);
mpDataBuffer = new u8[mDataBufferSize];
@@ -296,53 +296,54 @@ void CTextureDecoder::FullDecodeGXTexture(IInputStream& TXTR)
// CMPR stores pixels in 8x8 blocks, with four 4x4 subblocks.
// An easy way to convert it is to pretend each block is 2x2 and each subblock is one pixel.
// So to do that we need to calculate the "new" dimensions of the image, 1/4 the size of the original.
if (mTexelFormat == eGX_CMPR) {
if (mTexelFormat == eGX_CMPR)
{
MipW /= 4;
MipH /= 4;
}
for (u32 iMip = 0; iMip < mNumMipMaps; iMip++)
{
for (u32 BlockY = 0; BlockY < MipH; BlockY += BHeight)
for (u32 BlockX = 0; BlockX < MipW; BlockX += BWidth) {
for (u32 ImgY = BlockY; ImgY < BlockY + BHeight; ImgY++) {
for (u32 ImgX = BlockX; ImgX < BlockX + BWidth; ImgX++)
for (u32 iBlockY = 0; iBlockY < MipH; iBlockY += BHeight)
for (u32 iBlockX = 0; iBlockX < MipW; iBlockX += BWidth) {
for (u32 iImgY = iBlockY; iImgY < iBlockY + BHeight; iImgY++) {
for (u32 iImgX = iBlockX; iImgX < iBlockX + BWidth; iImgX++)
{
u32 DstPos = (mTexelFormat == eGX_CMPR) ? ((ImgY * (MipW * 4)) + ImgX) * 16 : ((ImgY * MipW) + ImgX) * 4;
u32 DstPos = (mTexelFormat == eGX_CMPR) ? ((iImgY * (MipW * 4)) + iImgX) * 16 : ((iImgY * MipW) + iImgX) * 4;
Out.Seek(MipOffset + DstPos, SEEK_SET);
// I4/C4/CMPR require reading more than one pixel at a time
if (mTexelFormat == eGX_I4)
{
u8 Byte = TXTR.ReadByte();
u8 Byte = rTXTR.ReadByte();
Out.WriteLong( DecodePixelI4(Byte, 0).ToLongARGB() );
Out.WriteLong( DecodePixelI4(Byte, 1).ToLongARGB() );
}
else if (mTexelFormat == eGX_C4)
{
u8 Byte = TXTR.ReadByte();
u8 Byte = rTXTR.ReadByte();
Out.WriteLong( DecodePixelC4(Byte, 0, mPaletteInput).ToLongARGB() );
Out.WriteLong( DecodePixelC4(Byte, 1, mPaletteInput).ToLongARGB() );
}
else if (mTexelFormat == eGX_CMPR) DecodeSubBlockCMPR(TXTR, Out, (u16) (MipW * 4));
else if (mTexelFormat == eGX_CMPR) DecodeSubBlockCMPR(rTXTR, Out, (u16) (MipW * 4));
else
{
CColor Pixel;
if (mTexelFormat == eGX_I8) Pixel = DecodePixelI8(TXTR.ReadByte());
else if (mTexelFormat == eGX_IA4) Pixel = DecodePixelIA4(TXTR.ReadByte());
else if (mTexelFormat == eGX_IA8) Pixel = DecodePixelIA8(TXTR.ReadShort());
else if (mTexelFormat == eGX_C8) Pixel = DecodePixelC8(TXTR.ReadByte(), mPaletteInput);
else if (mTexelFormat == eGX_RGB565) Pixel = DecodePixelRGB565(TXTR.ReadShort());
else if (mTexelFormat == eGX_RGB5A3) Pixel = DecodePixelRGB5A3(TXTR.ReadShort());
else if (mTexelFormat == eGX_RGBA8) Pixel = CColor(TXTR, true);
if (mTexelFormat == eGX_I8) Pixel = DecodePixelI8(rTXTR.ReadByte());
else if (mTexelFormat == eGX_IA4) Pixel = DecodePixelIA4(rTXTR.ReadByte());
else if (mTexelFormat == eGX_IA8) Pixel = DecodePixelIA8(rTXTR.ReadShort());
else if (mTexelFormat == eGX_C8) Pixel = DecodePixelC8(rTXTR.ReadByte(), mPaletteInput);
else if (mTexelFormat == eGX_RGB565) Pixel = DecodePixelRGB565(rTXTR.ReadShort());
else if (mTexelFormat == eGX_RGB5A3) Pixel = DecodePixelRGB5A3(rTXTR.ReadShort());
else if (mTexelFormat == eGX_RGBA8) Pixel = CColor(rTXTR, true);
Out.WriteLong(Pixel.ToLongARGB());
}
}
}
if (mTexelFormat == eGX_RGBA8) TXTR.Seek(0x20, SEEK_CUR);
if (mTexelFormat == eGX_RGBA8) rTXTR.Seek(0x20, SEEK_CUR);
}
u32 MipSize = MipW * MipH * 4;
@@ -356,13 +357,13 @@ void CTextureDecoder::FullDecodeGXTexture(IInputStream& TXTR)
}
}
void CTextureDecoder::DecodeDDS(IInputStream &DDS)
void CTextureDecoder::DecodeDDS(IInputStream& rDDS)
{
// Get image data size, create output buffer
u32 ImageStart = DDS.Tell();
DDS.Seek(0x0, SEEK_END);
u32 ImageSize = DDS.Tell() - ImageStart;
DDS.Seek(ImageStart, SEEK_SET);
u32 ImageStart = rDDS.Tell();
rDDS.Seek(0x0, SEEK_END);
u32 ImageSize = rDDS.Tell() - ImageStart;
rDDS.Seek(ImageStart, SEEK_SET);
mDataBufferSize = ImageSize;
if (mDDSInfo.Format == SDDSInfo::DXT1) mDataBufferSize *= 8;
@@ -408,7 +409,7 @@ void CTextureDecoder::DecodeDDS(IInputStream &DDS)
Out.Seek(MipOffset, SEEK_SET);
u32 MipSize = MipW * MipH / 2;
std::vector<u8> MipBuffer(MipSize);
DDS.ReadBytes(MipBuffer.data(), MipBuffer.size());
rDDS.ReadBytes(MipBuffer.data(), MipBuffer.size());
Out.WriteBytes(MipBuffer.data(), MipBuffer.size());
MipOffset += MipSize;
@@ -421,32 +422,32 @@ void CTextureDecoder::DecodeDDS(IInputStream &DDS)
// Otherwise we do a full decode to RGBA8
else
{
for (u32 y = 0; y < MipH; y++)
for (u32 Y = 0; Y < MipH; Y++)
{
for (u32 x = 0; x < MipW; x++)
for (u32 X = 0; X < MipW; X++)
{
u32 OutPos = MipOffset;
if (mDDSInfo.Format == SDDSInfo::RGBA)
{
OutPos += ((y * MipW) + x) * 4;
OutPos += ((Y * MipW) + X) * 4;
Out.Seek(OutPos, SEEK_SET);
CColor Pixel = DecodeDDSPixel(DDS);
CColor Pixel = DecodeDDSPixel(rDDS);
Out.WriteLong(Pixel.ToLongARGB());
}
else
{
OutPos += ((y * (MipW * 4)) + x) * 16;
OutPos += ((Y * (MipW * 4)) + X) * 16;
Out.Seek(OutPos, SEEK_SET);
if (mDDSInfo.Format == SDDSInfo::DXT1)
DecodeBlockBC1(DDS, Out, MipW * 4);
DecodeBlockBC1(rDDS, Out, MipW * 4);
else if ((mDDSInfo.Format == SDDSInfo::DXT2) || (mDDSInfo.Format == SDDSInfo::DXT3))
DecodeBlockBC2(DDS, Out, MipW * 4);
DecodeBlockBC2(rDDS, Out, MipW * 4);
else if ((mDDSInfo.Format == SDDSInfo::DXT4) || (mDDSInfo.Format == SDDSInfo::DXT5))
DecodeBlockBC3(DDS, Out, MipW * 4);
DecodeBlockBC3(rDDS, Out, MipW * 4);
}
}
}
@@ -467,135 +468,136 @@ void CTextureDecoder::DecodeDDS(IInputStream &DDS)
}
// ************ READ PIXELS (PARTIAL DECODE) ************
void CTextureDecoder::ReadPixelsI4(IInputStream& src, IOutputStream& dst)
void CTextureDecoder::ReadPixelsI4(IInputStream& rSrc, IOutputStream& rDst)
{
u8 px = src.ReadByte();
dst.WriteByte(Extend4to8(px >> 4));
dst.WriteByte(Extend4to8(px >> 4));
dst.WriteByte(Extend4to8(px));
dst.WriteByte(Extend4to8(px));
u8 Pixels = rSrc.ReadByte();
rDst.WriteByte(Extend4to8(Pixels >> 4));
rDst.WriteByte(Extend4to8(Pixels >> 4));
rDst.WriteByte(Extend4to8(Pixels));
rDst.WriteByte(Extend4to8(Pixels));
}
void CTextureDecoder::ReadPixelI8(IInputStream& src, IOutputStream& dst)
void CTextureDecoder::ReadPixelI8(IInputStream& rSrc, IOutputStream& rDst)
{
u8 px = src.ReadByte();
dst.WriteByte(px);
dst.WriteByte(px);
u8 Pixel = rSrc.ReadByte();
rDst.WriteByte(Pixel);
rDst.WriteByte(Pixel);
}
void CTextureDecoder::ReadPixelIA4(IInputStream& src, IOutputStream& dst)
void CTextureDecoder::ReadPixelIA4(IInputStream& rSrc, IOutputStream& rDst)
{
// this can be left as-is for DDS conversion, but opengl doesn't support two components in one byte...
u8 byte = src.ReadByte();
u8 a = Extend4to8(byte >> 4);
u8 l = Extend4to8(byte);
dst.WriteShort((l << 8) | a);
u8 Byte = rSrc.ReadByte();
u8 Alpha = Extend4to8(Byte >> 4);
u8 Lum = Extend4to8(Byte);
rDst.WriteShort((Lum << 8) | Alpha);
}
void CTextureDecoder::ReadPixelIA8(IInputStream& src, IOutputStream& dst)
void CTextureDecoder::ReadPixelIA8(IInputStream& rSrc, IOutputStream& rDst)
{
dst.WriteShort(src.ReadShort());
rDst.WriteShort(rSrc.ReadShort());
}
void CTextureDecoder::ReadPixelsC4(IInputStream& src, IOutputStream& dst)
void CTextureDecoder::ReadPixelsC4(IInputStream& rSrc, IOutputStream& rDst)
{
// This isn't how C4 works, but due to the way Retro packed font textures (which use C4)
// this is the only way to get them to decode correctly for now.
// Commented-out code is proper C4 decoding. Dedicated font texture-decoding function
// is probably going to be necessary in the future.
u8 byte = src.ReadByte();
u8 indices[2];
indices[0] = (byte >> 4) & 0xF;
indices[1] = byte & 0xF;
u8 Byte = rSrc.ReadByte();
u8 Indices[2];
Indices[0] = (Byte >> 4) & 0xF;
Indices[1] = Byte & 0xF;
for (u32 i = 0; i < 2; i++)
for (u32 iIdx = 0; iIdx < 2; iIdx++)
{
u8 r, g, b, a;
((indices[i] >> 3) & 0x1) ? r = 0xFF : r = 0x0;
((indices[i] >> 2) & 0x1) ? g = 0xFF : g = 0x0;
((indices[i] >> 1) & 0x1) ? b = 0xFF : b = 0x0;
((indices[i] >> 0) & 0x1) ? a = 0xFF : a = 0x0;
u32 rgba = (r << 24) | (g << 16) | (b << 8) | (a);
dst.WriteLong(rgba);
u8 R, G, B, A;
((Indices[iIdx] >> 3) & 0x1) ? R = 0xFF : R = 0x0;
((Indices[iIdx] >> 2) & 0x1) ? G = 0xFF : G = 0x0;
((Indices[iIdx] >> 1) & 0x1) ? B = 0xFF : B = 0x0;
((Indices[iIdx] >> 0) & 0x1) ? A = 0xFF : A = 0x0;
u32 RGBA = (R << 24) | (G << 16) | (B << 8) | (A);
rDst.WriteLong(RGBA);
/*paletteInput->Seek(indices[i] * 2, SEEK_SET);
/*mPaletteInput.Seek(indices[i] * 2, SEEK_SET);
if (paletteFormat == PaletteIA8) readPixelIA8(*paletteInput, dst);
else if (paletteFormat == PaletteRGB565) readPixelRGB565(*paletteInput, dst);
else if (paletteFormat == PaletteRGB5A3) readPixelRGB5A3(*paletteInput, dst);*/
if (mPaletteFormat == ePalette_IA8) readPixelIA8(mPaletteInput, rDst);
else if (mPaletteFormat == ePalette_RGB565) readPixelRGB565(mPaletteInput, rDst);
else if (mPaletteFormat == ePalette_RGB5A3) readPixelRGB5A3(mPaletteInput, rDst);*/
}
}
void CTextureDecoder::ReadPixelC8(IInputStream& src, IOutputStream& dst)
void CTextureDecoder::ReadPixelC8(IInputStream& rSrc, IOutputStream& rDst)
{
// DKCR fonts use C8 :|
u8 index = src.ReadByte();
u8 Index = rSrc.ReadByte();
/*u8 r, g, b, a;
((index >> 3) & 0x1) ? r = 0xFF : r = 0x0;
((index >> 2) & 0x1) ? g = 0xFF : g = 0x0;
((index >> 1) & 0x1) ? b = 0xFF : b = 0x0;
((index >> 0) & 0x1) ? a = 0xFF : a = 0x0;
u32 rgba = (r << 24) | (g << 16) | (b << 8) | (a);
dst.WriteLong(rgba);*/
/*u8 R, G, B, A;
((Index >> 3) & 0x1) ? R = 0xFF : R = 0x0;
((Index >> 2) & 0x1) ? G = 0xFF : G = 0x0;
((Index >> 1) & 0x1) ? B = 0xFF : B = 0x0;
((Index >> 0) & 0x1) ? A = 0xFF : A = 0x0;
u32 RGBA = (R << 24) | (G << 16) | (B << 8) | (A);
dst.WriteLong(RGBA);*/
mPaletteInput.Seek(index * 2, SEEK_SET);
mPaletteInput.Seek(Index * 2, SEEK_SET);
if (mPaletteFormat == ePalette_IA8) ReadPixelIA8(mPaletteInput, dst);
else if (mPaletteFormat == ePalette_RGB565) ReadPixelRGB565(mPaletteInput, dst);
else if (mPaletteFormat == ePalette_RGB5A3) ReadPixelRGB5A3(mPaletteInput, dst);
if (mPaletteFormat == ePalette_IA8) ReadPixelIA8(mPaletteInput, rDst);
else if (mPaletteFormat == ePalette_RGB565) ReadPixelRGB565(mPaletteInput, rDst);
else if (mPaletteFormat == ePalette_RGB5A3) ReadPixelRGB5A3(mPaletteInput, rDst);
}
void CTextureDecoder::ReadPixelRGB565(IInputStream& src, IOutputStream& dst)
void CTextureDecoder::ReadPixelRGB565(IInputStream& rSrc, IOutputStream& rDst)
{
// RGB565 can be used as-is.
dst.WriteShort(src.ReadShort());
rDst.WriteShort(rSrc.ReadShort());
}
void CTextureDecoder::ReadPixelRGB5A3(IInputStream& src, IOutputStream& dst)
void CTextureDecoder::ReadPixelRGB5A3(IInputStream& rSrc, IOutputStream& rDst)
{
u16 px = src.ReadShort();
u8 r, g, b, a;
u16 Pixel = rSrc.ReadShort();
u8 R, G, B, A;
if (px & 0x8000) // RGB5
if (Pixel & 0x8000) // RGB5
{
b = Extend5to8(px >> 10);
g = Extend5to8(px >> 5);
r = Extend5to8(px >> 0);
a = 255;
B = Extend5to8(Pixel >> 10);
G = Extend5to8(Pixel >> 5);
R = Extend5to8(Pixel >> 0);
A = 255;
}
else // RGB4A3
{
a = Extend3to8(px >> 12);
b = Extend4to8(px >> 8);
g = Extend4to8(px >> 4);
r = Extend4to8(px >> 0);
A = Extend3to8(Pixel >> 12);
B = Extend4to8(Pixel >> 8);
G = Extend4to8(Pixel >> 4);
R = Extend4to8(Pixel >> 0);
}
u32 c = (a << 24) | (r << 16) | (g << 8) | b;
dst.WriteLong(c);
u32 Color = (A << 24) | (R << 16) | (G << 8) | B;
rDst.WriteLong(Color);
}
void CTextureDecoder::ReadPixelRGBA8(IInputStream& src, IOutputStream& dst)
void CTextureDecoder::ReadPixelRGBA8(IInputStream& rSrc, IOutputStream& rDst)
{
u16 ar = src.ReadShort();
src.Seek(0x1E, SEEK_CUR);
u16 gb = src.ReadShort();
src.Seek(-0x20, SEEK_CUR);
u32 px = (ar << 16) | gb;
dst.WriteLong(px);
u16 AR = rSrc.ReadShort();
rSrc.Seek(0x1E, SEEK_CUR);
u16 GB = rSrc.ReadShort();
rSrc.Seek(-0x20, SEEK_CUR);
u32 Pixel = (AR << 16) | GB;
rDst.WriteLong(Pixel);
}
void CTextureDecoder::ReadSubBlockCMPR(IInputStream& src, IOutputStream& dst)
void CTextureDecoder::ReadSubBlockCMPR(IInputStream& rSrc, IOutputStream& rDst)
{
dst.WriteShort(src.ReadShort());
dst.WriteShort(src.ReadShort());
rDst.WriteShort(rSrc.ReadShort());
rDst.WriteShort(rSrc.ReadShort());
for (u32 byte = 0; byte < 4; byte++) {
u8 b = src.ReadByte();
b = ((b & 0x3) << 6) | ((b & 0xC) << 2) | ((b & 0x30) >> 2) | ((b & 0xC0) >> 6);
dst.WriteByte(b);
for (u32 iByte = 0; iByte < 4; iByte++)
{
u8 Byte = rSrc.ReadByte();
Byte = ((Byte & 0x3) << 6) | ((Byte & 0xC) << 2) | ((Byte & 0x30) >> 2) | ((Byte & 0xC0) >> 6);
rDst.WriteByte(Byte);
}
}
@@ -603,8 +605,8 @@ void CTextureDecoder::ReadSubBlockCMPR(IInputStream& src, IOutputStream& dst)
CColor CTextureDecoder::DecodePixelI4(u8 Byte, u8 WhichPixel)
{
if (WhichPixel == 1) Byte >>= 4;
u8 px = Extend4to8(Byte);
return CColor::Integral(px, px, px);
u8 Pixel = Extend4to8(Byte);
return CColor::Integral(Pixel, Pixel, Pixel);
}
CColor CTextureDecoder::DecodePixelI8(u8 Byte)
@@ -626,60 +628,60 @@ CColor CTextureDecoder::DecodePixelIA8(u16 Short)
return CColor::Integral(Lum, Lum, Lum, Alpha);
}
CColor CTextureDecoder::DecodePixelC4(u8 Byte, u8 WhichPixel, IInputStream& PaletteStream)
CColor CTextureDecoder::DecodePixelC4(u8 Byte, u8 WhichPixel, IInputStream& rPaletteStream)
{
if (WhichPixel == 1) Byte >>= 4;
Byte &= 0xF;
PaletteStream.Seek(Byte * 2, SEEK_SET);
if (mPaletteFormat == ePalette_IA8) return DecodePixelIA8(PaletteStream.ReadShort());
else if (mPaletteFormat == ePalette_RGB565) return DecodePixelIA8(PaletteStream.ReadShort());
else if (mPaletteFormat == ePalette_RGB5A3) return DecodePixelIA8(PaletteStream.ReadShort());
rPaletteStream.Seek(Byte * 2, SEEK_SET);
if (mPaletteFormat == ePalette_IA8) return DecodePixelIA8(rPaletteStream.ReadShort());
else if (mPaletteFormat == ePalette_RGB565) return DecodePixelIA8(rPaletteStream.ReadShort());
else if (mPaletteFormat == ePalette_RGB5A3) return DecodePixelIA8(rPaletteStream.ReadShort());
else return CColor::skTransparentBlack;
}
CColor CTextureDecoder::DecodePixelC8(u8 Byte, IInputStream& PaletteStream)
CColor CTextureDecoder::DecodePixelC8(u8 Byte, IInputStream& rPaletteStream)
{
PaletteStream.Seek(Byte * 2, SEEK_SET);
if (mPaletteFormat == ePalette_IA8) return DecodePixelIA8(PaletteStream.ReadShort());
else if (mPaletteFormat == ePalette_RGB565) return DecodePixelIA8(PaletteStream.ReadShort());
else if (mPaletteFormat == ePalette_RGB5A3) return DecodePixelIA8(PaletteStream.ReadShort());
rPaletteStream.Seek(Byte * 2, SEEK_SET);
if (mPaletteFormat == ePalette_IA8) return DecodePixelIA8(rPaletteStream.ReadShort());
else if (mPaletteFormat == ePalette_RGB565) return DecodePixelIA8(rPaletteStream.ReadShort());
else if (mPaletteFormat == ePalette_RGB5A3) return DecodePixelIA8(rPaletteStream.ReadShort());
else return CColor::skTransparentBlack;
}
CColor CTextureDecoder::DecodePixelRGB565(u16 Short)
{
u8 b = Extend5to8( (u8) (Short >> 11) );
u8 g = Extend6to8( (u8) (Short >> 5) );
u8 r = Extend5to8( (u8) (Short) );
return CColor::Integral(r, g, b, 0xFF);
u8 B = Extend5to8( (u8) (Short >> 11) );
u8 G = Extend6to8( (u8) (Short >> 5) );
u8 R = Extend5to8( (u8) (Short) );
return CColor::Integral(R, G, B, 0xFF);
}
CColor CTextureDecoder::DecodePixelRGB5A3(u16 Short)
{
if (Short & 0x8000) // RGB5
{
u8 b = Extend5to8( (u8) (Short >> 10));
u8 g = Extend5to8( (u8) (Short >> 5));
u8 r = Extend5to8( (u8) (Short) );
return CColor::Integral(r, g, b, 0xFF);
u8 B = Extend5to8( (u8) (Short >> 10));
u8 G = Extend5to8( (u8) (Short >> 5));
u8 R = Extend5to8( (u8) (Short) );
return CColor::Integral(R, G, B, 0xFF);
}
else // RGB4A3
{
u8 a = Extend3to8( (u8) (Short >> 12) );
u8 b = Extend4to8( (u8) (Short >> 8) );
u8 g = Extend4to8( (u8) (Short >> 4) );
u8 r = Extend4to8( (u8) (Short) );
return CColor::Integral(r, g, b, a);
u8 A = Extend3to8( (u8) (Short >> 12) );
u8 B = Extend4to8( (u8) (Short >> 8) );
u8 G = Extend4to8( (u8) (Short >> 4) );
u8 R = Extend4to8( (u8) (Short) );
return CColor::Integral(R, G, B, A);
}
}
void CTextureDecoder::DecodeSubBlockCMPR(IInputStream& src, IOutputStream& dst, u16 Width)
void CTextureDecoder::DecodeSubBlockCMPR(IInputStream& rSrc, IOutputStream& rDst, u16 Width)
{
CColor Palettes[4];
u16 PaletteA = src.ReadShort();
u16 PaletteB = src.ReadShort();
u16 PaletteA = rSrc.ReadShort();
u16 PaletteB = rSrc.ReadShort();
Palettes[0] = DecodePixelRGB565(PaletteA);
Palettes[1] = DecodePixelRGB565(PaletteB);
@@ -694,29 +696,29 @@ void CTextureDecoder::DecodeSubBlockCMPR(IInputStream& src, IOutputStream& dst,
Palettes[3] = CColor::skTransparentBlack;
}
for (u32 y = 0; y < 4; y++)
for (u32 iBlockY = 0; iBlockY < 4; iBlockY++)
{
u8 Byte = src.ReadByte();
u8 Byte = rSrc.ReadByte();
for (u32 x = 0; x < 4; x++)
for (u32 iBlockX = 0; iBlockX < 4; iBlockX++)
{
u8 Shift = (u8) (6 - (x * 2));
u8 Shift = (u8) (6 - (iBlockX * 2));
u8 PaletteIndex = (Byte >> Shift) & 0x3;
CColor Pixel = Palettes[PaletteIndex];
dst.WriteLong(Pixel.ToLongARGB());
rDst.WriteLong(Pixel.ToLongARGB());
}
dst.Seek((Width - 4) * 4, SEEK_CUR);
rDst.Seek((Width - 4) * 4, SEEK_CUR);
}
}
void CTextureDecoder::DecodeBlockBC1(IInputStream& src, IOutputStream& dst, u32 Width)
void CTextureDecoder::DecodeBlockBC1(IInputStream& rSrc, IOutputStream& rDst, u32 Width)
{
// Very similar to the CMPR subblock function, but unfortunately a slight
// difference in the order the pixel indices are read requires a separate function
CColor Palettes[4];
u16 PaletteA = src.ReadShort();
u16 PaletteB = src.ReadShort();
u16 PaletteA = rSrc.ReadShort();
u16 PaletteB = rSrc.ReadShort();
Palettes[0] = DecodePixelRGB565(PaletteA);
Palettes[1] = DecodePixelRGB565(PaletteB);
@@ -731,27 +733,27 @@ void CTextureDecoder::DecodeBlockBC1(IInputStream& src, IOutputStream& dst, u32
Palettes[3] = CColor::skTransparentBlack;
}
for (u32 y = 0; y < 4; y++)
for (u32 iBlockY = 0; iBlockY < 4; iBlockY++)
{
u8 Byte = src.ReadByte();
u8 Byte = rSrc.ReadByte();
for (u32 x = 0; x < 4; x++)
for (u32 iBlockX = 0; iBlockX < 4; iBlockX++)
{
u8 Shift = (u8) (x * 2);
u8 Shift = (u8) (iBlockX * 2);
u8 PaletteIndex = (Byte >> Shift) & 0x3;
CColor Pixel = Palettes[PaletteIndex];
dst.WriteLong(Pixel.ToLongARGB());
rDst.WriteLong(Pixel.ToLongARGB());
}
dst.Seek((Width - 4) * 4, SEEK_CUR);
rDst.Seek((Width - 4) * 4, SEEK_CUR);
}
}
void CTextureDecoder::DecodeBlockBC2(IInputStream& src, IOutputStream& dst, u32 Width)
void CTextureDecoder::DecodeBlockBC2(IInputStream& rSrc, IOutputStream& rDst, u32 Width)
{
CColor CPalettes[4];
u16 PaletteA = src.ReadShort();
u16 PaletteB = src.ReadShort();
u16 PaletteA = rSrc.ReadShort();
u16 PaletteB = rSrc.ReadShort();
CPalettes[0] = DecodePixelRGB565(PaletteA);
CPalettes[1] = DecodePixelRGB565(PaletteB);
@@ -766,27 +768,27 @@ void CTextureDecoder::DecodeBlockBC2(IInputStream& src, IOutputStream& dst, u32
CPalettes[3] = CColor::skTransparentBlack;
}
for (u32 y = 0; y < 4; y++)
for (u32 iBlockY = 0; iBlockY < 4; iBlockY++)
{
u8 Byte = src.ReadByte();
u8 Byte = rSrc.ReadByte();
for (u32 x = 0; x < 4; x++)
for (u32 iBlockX = 0; iBlockX < 4; iBlockX++)
{
u8 Shift = (u8) (x * 2);
u8 Shift = (u8) (iBlockX * 2);
u8 PaletteIndex = (Byte >> Shift) & 0x3;
CColor Pixel = CPalettes[PaletteIndex];
dst.WriteLong(Pixel.ToLongARGB());
rDst.WriteLong(Pixel.ToLongARGB());
}
dst.Seek((Width - 4) * 4, SEEK_CUR);
rDst.Seek((Width - 4) * 4, SEEK_CUR);
}
}
void CTextureDecoder::DecodeBlockBC3(IInputStream& src, IOutputStream& dst, u32 Width)
void CTextureDecoder::DecodeBlockBC3(IInputStream& rSrc, IOutputStream& rDst, u32 Width)
{
CColor Palettes[4];
u16 PaletteA = src.ReadShort();
u16 PaletteB = src.ReadShort();
u16 PaletteA = rSrc.ReadShort();
u16 PaletteB = rSrc.ReadShort();
Palettes[0] = DecodePixelRGB565(PaletteA);
Palettes[1] = DecodePixelRGB565(PaletteB);
@@ -801,50 +803,50 @@ void CTextureDecoder::DecodeBlockBC3(IInputStream& src, IOutputStream& dst, u32
Palettes[3] = CColor::skTransparentBlack;
}
for (u32 y = 0; y < 4; y++)
for (u32 iBlockY = 0; iBlockY < 4; iBlockY++)
{
u8 Byte = src.ReadByte();
u8 Byte = rSrc.ReadByte();
for (u32 x = 0; x < 4; x++)
for (u32 iBlockX = 0; iBlockX < 4; iBlockX++)
{
u8 Shift = (u8) (x * 2);
u8 Shift = (u8) (iBlockX * 2);
u8 PaletteIndex = (Byte >> Shift) & 0x3;
CColor Pixel = Palettes[PaletteIndex];
dst.WriteLong(Pixel.ToLongARGB());
rDst.WriteLong(Pixel.ToLongARGB());
}
dst.Seek((Width - 4) * 4, SEEK_CUR);
rDst.Seek((Width - 4) * 4, SEEK_CUR);
}
}
CColor CTextureDecoder::DecodeDDSPixel(IInputStream& /*DDS*/)
CColor CTextureDecoder::DecodeDDSPixel(IInputStream& /*rDDS*/)
{
return CColor::skWhite;
}
// ************ UTILITY ************
u8 CTextureDecoder::Extend3to8(u8 in)
u8 CTextureDecoder::Extend3to8(u8 In)
{
in &= 0x7;
return (in << 5) | (in << 2) | (in >> 1);
In &= 0x7;
return (In << 5) | (In << 2) | (In >> 1);
}
u8 CTextureDecoder::Extend4to8(u8 in)
u8 CTextureDecoder::Extend4to8(u8 In)
{
in &= 0xF;
return (in << 4) | in;
In &= 0xF;
return (In << 4) | In;
}
u8 CTextureDecoder::Extend5to8(u8 in)
u8 CTextureDecoder::Extend5to8(u8 In)
{
in &= 0x1F;
return (in << 3) | (in >> 2);
In &= 0x1F;
return (In << 3) | (In >> 2);
}
u8 CTextureDecoder::Extend6to8(u8 in)
u8 CTextureDecoder::Extend6to8(u8 In)
{
in &= 0x3F;
return (in << 2) | (in >> 4);
In &= 0x3F;
return (In << 2) | (In >> 4);
}
u32 CTextureDecoder::CalculateShiftForMask(u32 BitMask)

View File

@@ -38,55 +38,55 @@ class CTextureDecoder
CTexture* CreateTexture();
// Read
void ReadTXTR(IInputStream& TXTR);
void ReadDDS(IInputStream& DDS);
void ReadTXTR(IInputStream& rTXTR);
void ReadDDS(IInputStream& rDDS);
// Decode
void PartialDecodeGXTexture(IInputStream& TXTR);
void FullDecodeGXTexture(IInputStream& TXTR);
void DecodeDDS(IInputStream& DDS);
void PartialDecodeGXTexture(IInputStream& rTXTR);
void FullDecodeGXTexture(IInputStream& rTXTR);
void DecodeDDS(IInputStream& rDDS);
// Decode Pixels (preserve compression)
void ReadPixelsI4(IInputStream& src, IOutputStream& dst);
void ReadPixelI8(IInputStream& src, IOutputStream& dst);
void ReadPixelIA4(IInputStream& src, IOutputStream& dst);
void ReadPixelIA8(IInputStream& src, IOutputStream& dst);
void ReadPixelsC4(IInputStream& src, IOutputStream& dst);
void ReadPixelC8(IInputStream& src, IOutputStream& dst);
void ReadPixelRGB565(IInputStream& src, IOutputStream& dst);
void ReadPixelRGB5A3(IInputStream& src, IOutputStream& dst);
void ReadPixelRGBA8(IInputStream& src, IOutputStream& dst);
void ReadSubBlockCMPR(IInputStream& src, IOutputStream& dst);
void ReadPixelsI4(IInputStream& rSrc, IOutputStream& rDst);
void ReadPixelI8(IInputStream& rSrc, IOutputStream& rDst);
void ReadPixelIA4(IInputStream& rSrc, IOutputStream& rDst);
void ReadPixelIA8(IInputStream& rSrc, IOutputStream& rDst);
void ReadPixelsC4(IInputStream& rSrc, IOutputStream& rDst);
void ReadPixelC8(IInputStream& rSrc, IOutputStream& rDst);
void ReadPixelRGB565(IInputStream& rSrc, IOutputStream& rDst);
void ReadPixelRGB5A3(IInputStream& rSrc, IOutputStream& rDst);
void ReadPixelRGBA8(IInputStream& rSrc, IOutputStream& rDst);
void ReadSubBlockCMPR(IInputStream& rSrc, IOutputStream& rDst);
// Decode Pixels (convert to RGBA8)
CColor DecodePixelI4(u8 Byte, u8 WhichPixel);
CColor DecodePixelI8(u8 Byte);
CColor DecodePixelIA4(u8 Byte);
CColor DecodePixelIA8(u16 Short);
CColor DecodePixelC4(u8 Byte, u8 WhichPixel, IInputStream& PaletteStream);
CColor DecodePixelC8(u8 Byte, IInputStream& PaletteStream);
CColor DecodePixelC4(u8 Byte, u8 WhichPixel, IInputStream& rPaletteStream);
CColor DecodePixelC8(u8 Byte, IInputStream& rPaletteStream);
CColor DecodePixelRGB565(u16 Short);
CColor DecodePixelRGB5A3(u16 Short);
CColor DecodePixelRGBA8(IInputStream& src, IOutputStream& dst);
void DecodeSubBlockCMPR(IInputStream& src, IOutputStream& dst, u16 Width);
CColor DecodePixelRGBA8(IInputStream& rSrc, IOutputStream& rDst);
void DecodeSubBlockCMPR(IInputStream& rSrc, IOutputStream& rDst, u16 Width);
void DecodeBlockBC1(IInputStream& src, IOutputStream& dst, u32 Width);
void DecodeBlockBC2(IInputStream& src, IOutputStream& dst, u32 Width);
void DecodeBlockBC3(IInputStream& src, IOutputStream& dst, u32 Width);
CColor DecodeDDSPixel(IInputStream& DDS);
void DecodeBlockBC1(IInputStream& rSrc, IOutputStream& rDst, u32 Width);
void DecodeBlockBC2(IInputStream& rSrc, IOutputStream& rDst, u32 Width);
void DecodeBlockBC3(IInputStream& rSrc, IOutputStream& rDst, u32 Width);
CColor DecodeDDSPixel(IInputStream& rDDS);
// Static
public:
static CTexture* LoadTXTR(IInputStream& TXTR);
static CTexture* LoadDDS(IInputStream& DDS);
static CTexture* DoFullDecode(IInputStream& TXTR);
static CTexture* LoadTXTR(IInputStream& rTXTR);
static CTexture* LoadDDS(IInputStream& rDDS);
static CTexture* DoFullDecode(IInputStream& rTXTR);
static CTexture* DoFullDecode(CTexture *pTexture);
// Utility
static u8 Extend3to8(u8 in);
static u8 Extend4to8(u8 in);
static u8 Extend5to8(u8 in);
static u8 Extend6to8(u8 in);
static u8 Extend3to8(u8 In);
static u8 Extend4to8(u8 In);
static u8 Extend5to8(u8 In);
static u8 Extend6to8(u8 In);
static u32 CalculateShiftForMask(u32 BitMask);
static u32 CalculateMaskBitCount(u32 BitMask);
};

View File

@@ -1,13 +1,12 @@
#include "CWorldLoader.h"
#include "Core/Resource/CResCache.h"
#include <Common/Log.h>
#include <iostream>
CWorldLoader::CWorldLoader()
{
}
void CWorldLoader::LoadPrimeMLVL(IInputStream& MLVL)
void CWorldLoader::LoadPrimeMLVL(IInputStream& rMLVL)
{
/*
* This function loads MLVL files from Prime 1/2
@@ -16,41 +15,41 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& MLVL)
// Header
if (mVersion < eCorruptionProto)
{
mpWorld->mpWorldName = gResCache.GetResource(MLVL.ReadLong(), "STRG");
if (mVersion == eEchoes) mpWorld->mpDarkWorldName = gResCache.GetResource(MLVL.ReadLong(), "STRG");
if (mVersion >= eEchoes) mpWorld->mUnknown1 = MLVL.ReadLong();
if (mVersion >= ePrime) mpWorld->mpSaveWorld = gResCache.GetResource(MLVL.ReadLong(), "SAVW");
mpWorld->mpDefaultSkybox = gResCache.GetResource(MLVL.ReadLong(), "CMDL");
mpWorld->mpWorldName = gResCache.GetResource(rMLVL.ReadLong(), "STRG");
if (mVersion == eEchoes) mpWorld->mpDarkWorldName = gResCache.GetResource(rMLVL.ReadLong(), "STRG");
if (mVersion >= eEchoes) mpWorld->mUnknown1 = rMLVL.ReadLong();
if (mVersion >= ePrime) mpWorld->mpSaveWorld = gResCache.GetResource(rMLVL.ReadLong(), "SAVW");
mpWorld->mpDefaultSkybox = gResCache.GetResource(rMLVL.ReadLong(), "CMDL");
}
else
{
mpWorld->mpWorldName = gResCache.GetResource(MLVL.ReadLongLong(), "STRG");
MLVL.Seek(0x4, SEEK_CUR); // Skipping unknown value
mpWorld->mpSaveWorld = gResCache.GetResource(MLVL.ReadLongLong(), "SAVW");
mpWorld->mpDefaultSkybox = gResCache.GetResource(MLVL.ReadLongLong(), "CMDL");
mpWorld->mpWorldName = gResCache.GetResource(rMLVL.ReadLongLong(), "STRG");
rMLVL.Seek(0x4, SEEK_CUR); // Skipping unknown value
mpWorld->mpSaveWorld = gResCache.GetResource(rMLVL.ReadLongLong(), "SAVW");
mpWorld->mpDefaultSkybox = gResCache.GetResource(rMLVL.ReadLongLong(), "CMDL");
}
// Memory relays - only in MP1
if (mVersion == ePrime)
{
u32 NumMemoryRelays = MLVL.ReadLong();
u32 NumMemoryRelays = rMLVL.ReadLong();
mpWorld->mMemoryRelays.reserve(NumMemoryRelays);
for (u32 iMem = 0; iMem < NumMemoryRelays; iMem++)
{
CWorld::SMemoryRelay MemRelay;
MemRelay.InstanceID = MLVL.ReadLong();
MemRelay.TargetID = MLVL.ReadLong();
MemRelay.Message = MLVL.ReadShort();
MemRelay.Unknown = MLVL.ReadByte();
MemRelay.InstanceID = rMLVL.ReadLong();
MemRelay.TargetID = rMLVL.ReadLong();
MemRelay.Message = rMLVL.ReadShort();
MemRelay.Unknown = rMLVL.ReadByte();
mpWorld->mMemoryRelays.push_back(MemRelay);
}
}
// Areas - here's the real meat of the file
u32 NumAreas = MLVL.ReadLong();
if (mVersion == ePrime) mpWorld->mUnknownAreas = MLVL.ReadLong();
u32 NumAreas = rMLVL.ReadLong();
if (mVersion == ePrime) mpWorld->mUnknownAreas = rMLVL.ReadLong();
mpWorld->mAreas.resize(NumAreas);
for (u32 iArea = 0; iArea < NumAreas; iArea++)
@@ -59,45 +58,45 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& MLVL)
CWorld::SArea *pArea = &mpWorld->mAreas[iArea];
if (mVersion < eCorruptionProto)
pArea->pAreaName = gResCache.GetResource(MLVL.ReadLong(), "STRG");
pArea->pAreaName = gResCache.GetResource(rMLVL.ReadLong(), "STRG");
else
pArea->pAreaName = gResCache.GetResource(MLVL.ReadLongLong(), "STRG");
pArea->pAreaName = gResCache.GetResource(rMLVL.ReadLongLong(), "STRG");
pArea->Transform = CTransform4f(MLVL);
pArea->AetherBox = CAABox(MLVL);
pArea->Transform = CTransform4f(rMLVL);
pArea->AetherBox = CAABox(rMLVL);
if (mVersion < eCorruptionProto)
{
pArea->FileID = MLVL.ReadLong() & 0xFFFFFFFF; // This is the MREA ID; not actually loading it for obvious reasons
pArea->AreaID = MLVL.ReadLong() & 0xFFFFFFFF;
pArea->FileID = rMLVL.ReadLong() & 0xFFFFFFFF; // This is the MREA ID; not actually loading it for obvious reasons
pArea->AreaID = rMLVL.ReadLong() & 0xFFFFFFFF;
}
else
{
pArea->FileID = MLVL.ReadLongLong();
pArea->AreaID = MLVL.ReadLongLong();
pArea->FileID = rMLVL.ReadLongLong();
pArea->AreaID = rMLVL.ReadLongLong();
}
// Attached areas
u32 NumAttachedAreas = MLVL.ReadLong();
u32 NumAttachedAreas = rMLVL.ReadLong();
pArea->AttachedAreaIDs.reserve(NumAttachedAreas);
for (u32 iAttached = 0; iAttached < NumAttachedAreas; iAttached++)
pArea->AttachedAreaIDs.push_back( MLVL.ReadShort() );
pArea->AttachedAreaIDs.push_back( rMLVL.ReadShort() );
if (mVersion < eCorruptionProto)
MLVL.Seek(0x4, SEEK_CUR); // Skipping unknown value (always 0)
rMLVL.Seek(0x4, SEEK_CUR); // Skipping unknown value (always 0)
// Depedencies
if (mVersion < eCorruptionProto)
{
u32 NumDependencies = MLVL.ReadLong();
u32 NumDependencies = rMLVL.ReadLong();
pArea->Dependencies.reserve(NumDependencies);
for (u32 iDep = 0; iDep < NumDependencies; iDep++)
{
SDependency Dependency;
Dependency.ResID = MLVL.ReadLong() & 0xFFFFFFFF;
Dependency.ResType = MLVL.ReadLong();
Dependency.ResID = rMLVL.ReadLong() & 0xFFFFFFFF;
Dependency.ResType = rMLVL.ReadLong();
pArea->Dependencies.push_back(Dependency);
}
@@ -105,26 +104,26 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& MLVL)
* Dependency offsets - indicates an offset into the dependency list where each layer's dependencies start
* The count is the layer count + 1 because the last offset is for common dependencies, like terrain textures
*/
u32 NumDependencyOffsets = MLVL.ReadLong();
u32 NumDependencyOffsets = rMLVL.ReadLong();
pArea->Layers.resize(NumDependencyOffsets - 1);
for (u32 iOff = 0; iOff < NumDependencyOffsets; iOff++)
{
u32 *Target;
if (iOff == NumDependencyOffsets - 1) Target = &pArea->CommonDependenciesStart;
else Target = &pArea->Layers[iOff].LayerDependenciesStart;
u32 *pTarget;
if (iOff == NumDependencyOffsets - 1) pTarget = &pArea->CommonDependenciesStart;
else pTarget = &pArea->Layers[iOff].LayerDependenciesStart;
*Target = MLVL.ReadLong();
*pTarget = rMLVL.ReadLong();
}
}
// Docks
u32 NumDocks = MLVL.ReadLong();
u32 NumDocks = rMLVL.ReadLong();
pArea->Docks.resize(NumDocks);
for (u32 iDock = 0; iDock < NumDocks; iDock++)
{
u32 NumConnectingDocks = MLVL.ReadLong();
u32 NumConnectingDocks = rMLVL.ReadLong();
CWorld::SArea::SDock* pDock = &pArea->Docks[iDock];
pDock->ConnectingDocks.reserve(NumConnectingDocks);
@@ -132,110 +131,110 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& MLVL)
for (u32 iConnect = 0; iConnect < NumConnectingDocks; iConnect++)
{
CWorld::SArea::SDock::SConnectingDock ConnectingDock;
ConnectingDock.AreaIndex = MLVL.ReadLong();
ConnectingDock.DockIndex = MLVL.ReadLong();
ConnectingDock.AreaIndex = rMLVL.ReadLong();
ConnectingDock.DockIndex = rMLVL.ReadLong();
pDock->ConnectingDocks.push_back(ConnectingDock);
}
u32 NumCoordinates = MLVL.ReadLong();
u32 NumCoordinates = rMLVL.ReadLong();
if (NumCoordinates != 4) Log::Error("Dock coordinate count not 4");
for (u32 iCoord = 0; iCoord < NumCoordinates; iCoord++)
pDock->DockCoordinates[iCoord] = CVector3f(MLVL);
pDock->DockCoordinates[iCoord] = CVector3f(rMLVL);
}
// Rels
if ( (mVersion == eEchoesDemo) || (mVersion == eEchoes) )
{
u32 NumRels = MLVL.ReadLong();
u32 NumRels = rMLVL.ReadLong();
pArea->RelFilenames.resize(NumRels);
for (u32 iRel = 0; iRel < NumRels; iRel++)
pArea->RelFilenames[iRel] = MLVL.ReadString();
pArea->RelFilenames[iRel] = rMLVL.ReadString();
if (mVersion == eEchoes)
{
u32 NumRelOffsets = MLVL.ReadLong(); // Don't know what these offsets correspond to
u32 NumRelOffsets = rMLVL.ReadLong(); // Don't know what these offsets correspond to
pArea->RelOffsets.resize(NumRelOffsets);
for (u32 iOff = 0; iOff < NumRelOffsets; iOff++)
pArea->RelOffsets[iOff] = MLVL.ReadLong();
pArea->RelOffsets[iOff] = rMLVL.ReadLong();
}
}
// Footer
if (mVersion >= eEchoesDemo)
pArea->InternalName = MLVL.ReadString();
pArea->InternalName = rMLVL.ReadString();
}
// MapWorld
if (mVersion < eCorruptionProto)
mpWorld->mpMapWorld = gResCache.GetResource(MLVL.ReadLong(), "MAPW");
mpWorld->mpMapWorld = gResCache.GetResource(rMLVL.ReadLong(), "MAPW");
else
mpWorld->mpMapWorld = gResCache.GetResource(MLVL.ReadLongLong(), "MAPW");
MLVL.Seek(0x5, SEEK_CUR); // Unknown values which are always 0
mpWorld->mpMapWorld = gResCache.GetResource(rMLVL.ReadLongLong(), "MAPW");
rMLVL.Seek(0x5, SEEK_CUR); // Unknown values which are always 0
// AudioGrps
if (mVersion == ePrime)
{
u32 NumAudioGrps = MLVL.ReadLong();
u32 NumAudioGrps = rMLVL.ReadLong();
mpWorld->mAudioGrps.reserve(NumAudioGrps);
for (u32 iGrp = 0; iGrp < NumAudioGrps; iGrp++)
{
CWorld::SAudioGrp AudioGrp;
AudioGrp.Unknown = MLVL.ReadLong();
AudioGrp.ResID = MLVL.ReadLong() & 0xFFFFFFFF;
AudioGrp.Unknown = rMLVL.ReadLong();
AudioGrp.ResID = rMLVL.ReadLong() & 0xFFFFFFFF;
mpWorld->mAudioGrps.push_back(AudioGrp);
}
MLVL.Seek(0x1, SEEK_CUR); // Unknown values which are always 0
rMLVL.Seek(0x1, SEEK_CUR); // Unknown values which are always 0
}
// Layer flags
MLVL.Seek(0x4, SEEK_CUR); // Skipping redundant area count
rMLVL.Seek(0x4, SEEK_CUR); // Skipping redundant area count
for (u32 iArea = 0; iArea < NumAreas; iArea++)
{
CWorld::SArea* pArea = &mpWorld->mAreas[iArea];
u32 NumLayers = MLVL.ReadLong();
u32 NumLayers = rMLVL.ReadLong();
if (NumLayers != pArea->Layers.size()) pArea->Layers.resize(NumLayers);
u64 LayerFlags = MLVL.ReadLongLong();
u64 LayerFlags = rMLVL.ReadLongLong();
for (u32 iLayer = 0; iLayer < NumLayers; iLayer++)
pArea->Layers[iLayer].EnabledByDefault = (((LayerFlags >> iLayer) & 0x1) == 1);
}
// Layer names
MLVL.Seek(0x4, SEEK_CUR); // Skipping redundant layer count
rMLVL.Seek(0x4, SEEK_CUR); // Skipping redundant layer count
for (u32 iArea = 0; iArea < NumAreas; iArea++)
{
CWorld::SArea* pArea = &mpWorld->mAreas[iArea];
u32 NumLayers = pArea->Layers.size();
for (u32 iLayer = 0; iLayer < NumLayers; iLayer++)
pArea->Layers[iLayer].LayerName = MLVL.ReadString();
pArea->Layers[iLayer].LayerName = rMLVL.ReadString();
}
// Last part of the file is layer name offsets, but we don't need it
// todo: Layer ID support for MP3
}
void CWorldLoader::LoadReturnsMLVL(IInputStream& MLVL)
void CWorldLoader::LoadReturnsMLVL(IInputStream& rMLVL)
{
mpWorld->mpWorldName = gResCache.GetResource(MLVL.ReadLongLong(), "STRG");
mpWorld->mpWorldName = gResCache.GetResource(rMLVL.ReadLongLong(), "STRG");
bool Check = (MLVL.ReadByte() != 0);
bool Check = (rMLVL.ReadByte() != 0);
if (Check)
{
MLVL.ReadString();
MLVL.Seek(0x10, SEEK_CUR);
rMLVL.ReadString();
rMLVL.Seek(0x10, SEEK_CUR);
}
mpWorld->mpSaveWorld = gResCache.GetResource(MLVL.ReadLongLong(), "SAVW");
mpWorld->mpDefaultSkybox = gResCache.GetResource(MLVL.ReadLongLong(), "CMDL");
mpWorld->mpSaveWorld = gResCache.GetResource(rMLVL.ReadLongLong(), "SAVW");
mpWorld->mpDefaultSkybox = gResCache.GetResource(rMLVL.ReadLongLong(), "CMDL");
// Areas
u32 NumAreas = MLVL.ReadLong();
u32 NumAreas = rMLVL.ReadLong();
mpWorld->mAreas.resize(NumAreas);
for (u32 iArea = 0; iArea < NumAreas; iArea++)
@@ -243,61 +242,61 @@ void CWorldLoader::LoadReturnsMLVL(IInputStream& MLVL)
// Area header
CWorld::SArea *pArea = &mpWorld->mAreas[iArea];
pArea->pAreaName = gResCache.GetResource(MLVL.ReadLongLong(), "STRG");
pArea->Transform = CTransform4f(MLVL);
pArea->AetherBox = CAABox(MLVL);
pArea->FileID = MLVL.ReadLongLong();
pArea->AreaID = MLVL.ReadLongLong();
pArea->pAreaName = gResCache.GetResource(rMLVL.ReadLongLong(), "STRG");
pArea->Transform = CTransform4f(rMLVL);
pArea->AetherBox = CAABox(rMLVL);
pArea->FileID = rMLVL.ReadLongLong();
pArea->AreaID = rMLVL.ReadLongLong();
MLVL.Seek(0x4, SEEK_CUR);
pArea->InternalName = MLVL.ReadString();
rMLVL.Seek(0x4, SEEK_CUR);
pArea->InternalName = rMLVL.ReadString();
}
// Layer flags
MLVL.Seek(0x4, SEEK_CUR); // Skipping redundant area count
rMLVL.Seek(0x4, SEEK_CUR); // Skipping redundant area count
for (u32 iArea = 0; iArea < NumAreas; iArea++)
{
CWorld::SArea* pArea = &mpWorld->mAreas[iArea];
u32 NumLayers = MLVL.ReadLong();
u32 NumLayers = rMLVL.ReadLong();
pArea->Layers.resize(NumLayers);
u64 LayerFlags = MLVL.ReadLongLong();
u64 LayerFlags = rMLVL.ReadLongLong();
for (u32 iLayer = 0; iLayer < NumLayers; iLayer++)
pArea->Layers[iLayer].EnabledByDefault = (((LayerFlags >> iLayer) & 0x1) == 1);
}
// Layer names
MLVL.Seek(0x4, SEEK_CUR); // Skipping redundant layer count
rMLVL.Seek(0x4, SEEK_CUR); // Skipping redundant layer count
for (u32 iArea = 0; iArea < NumAreas; iArea++)
{
CWorld::SArea* pArea = &mpWorld->mAreas[iArea];
u32 NumLayers = pArea->Layers.size();
for (u32 iLayer = 0; iLayer < NumLayers; iLayer++)
pArea->Layers[iLayer].LayerName = MLVL.ReadString();
pArea->Layers[iLayer].LayerName = rMLVL.ReadString();
}
// Last part of the file is layer name offsets, but we don't need it
// todo: Layer ID support
}
CWorld* CWorldLoader::LoadMLVL(IInputStream& MLVL)
CWorld* CWorldLoader::LoadMLVL(IInputStream& rMLVL)
{
if (!MLVL.IsValid()) return nullptr;
if (!rMLVL.IsValid()) return nullptr;
u32 Magic = MLVL.ReadLong();
u32 Magic = rMLVL.ReadLong();
if (Magic != 0xDEAFBABE)
{
Log::FileError(MLVL.GetSourceString(), "Invalid MLVL magic: " + TString::HexString(Magic));
Log::FileError(rMLVL.GetSourceString(), "Invalid MLVL magic: " + TString::HexString(Magic));
return nullptr;
}
u32 FileVersion = MLVL.ReadLong();
u32 FileVersion = rMLVL.ReadLong();
EGame Version = GetFormatVersion(FileVersion);
if (Version == eUnknownVersion)
{
Log::FileError(MLVL.GetSourceString(), "Unsupported MLVL version: " + TString::HexString(FileVersion));
Log::FileError(rMLVL.GetSourceString(), "Unsupported MLVL version: " + TString::HexString(FileVersion, 2));
return nullptr;
}
@@ -308,9 +307,9 @@ CWorld* CWorldLoader::LoadMLVL(IInputStream& MLVL)
Loader.mVersion = Version;
if (Version != eReturns)
Loader.LoadPrimeMLVL(MLVL);
Loader.LoadPrimeMLVL(rMLVL);
else
Loader.LoadReturnsMLVL(MLVL);
Loader.LoadReturnsMLVL(rMLVL);
return Loader.mpWorld;
}

View File

@@ -13,11 +13,11 @@ class CWorldLoader
EGame mVersion;
CWorldLoader();
void LoadPrimeMLVL(IInputStream& MLVL);
void LoadReturnsMLVL(IInputStream& MLVL);
void LoadPrimeMLVL(IInputStream& rMLVL);
void LoadReturnsMLVL(IInputStream& rMLVL);
public:
static CWorld* LoadMLVL(IInputStream& MLVL);
static CWorld* LoadMLVL(IInputStream& rMLVL);
static EGame GetFormatVersion(u32 Version);
};

View File

@@ -2,11 +2,14 @@
#include <iostream>
#include <list>
CBasicModel::CBasicModel() : CResource()
CBasicModel::CBasicModel()
: CResource()
, mVertexCount(0)
, mTriangleCount(0)
, mBuffered(false)
, mHasOwnMaterials(false)
, mHasOwnSurfaces(false)
{
mVertexCount = 0;
mTriangleCount = 0;
mBuffered = false;
}
CBasicModel::~CBasicModel()

View File

@@ -3,20 +3,18 @@
#include "Core/Render/CRenderer.h"
#include "Core/OpenGL/GLCommon.h"
CModel::CModel() : CBasicModel()
CModel::CModel()
: CBasicModel()
{
mHasOwnMaterials = true;
mHasOwnSurfaces = true;
mVertexCount = 0;
mTriangleCount = 0;
}
CModel::CModel(CMaterialSet *pSet, bool ownsMatSet)
CModel::CModel(CMaterialSet *pSet, bool OwnsMatSet)
: CBasicModel()
{
mHasOwnMaterials = ownsMatSet;
mHasOwnMaterials = OwnsMatSet;
mHasOwnSurfaces = true;
mVertexCount = 0;
mTriangleCount = 0;
mMaterialSets.resize(1);
mMaterialSets[0] = pSet;
@@ -25,8 +23,8 @@ CModel::CModel(CMaterialSet *pSet, bool ownsMatSet)
CModel::~CModel()
{
if (mHasOwnMaterials)
for (u32 m = 0; m < mMaterialSets.size(); m++)
delete mMaterialSets[m];
for (u32 iMat = 0; iMat < mMaterialSets.size(); iMat++)
delete mMaterialSets[iMat];
}
void CModel::BufferGL()
@@ -56,7 +54,8 @@ void CModel::BufferGL()
Indices[iVert] = mVBO.AddIfUnique(pPrim->Vertices[iVert], VBOStartOffset);
// then add the indices to the IBO. We convert some primitives to strips to minimize draw calls.
switch (pPrim->Type) {
switch (pPrim->Type)
{
case eGX_Triangles:
pIBO->TrianglesToStrips(Indices.data(), Indices.size());
break;
@@ -147,7 +146,7 @@ void CModel::DrawWireframe(FRenderOptions Options, CColor WireColor /*= CColor::
if (!mBuffered) BufferGL();
// Set up wireframe
WireColor.a = 0;
WireColor.A = 0;
CDrawUtil::UseColorShader(WireColor);
Options |= eNoMaterialSetup;
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

View File

@@ -19,7 +19,7 @@ class CModel : public CBasicModel
public:
CModel();
CModel(CMaterialSet *pSet, bool ownsMatSet);
CModel(CMaterialSet *pSet, bool OwnsMatSet);
~CModel();
void BufferGL();

View File

@@ -3,20 +3,18 @@
#include "Core/Render/CRenderer.h"
#include "Core/OpenGL/GLCommon.h"
CStaticModel::CStaticModel() : CBasicModel()
CStaticModel::CStaticModel()
: CBasicModel()
, mpMaterial(nullptr)
, mTransparent(false)
{
mpMaterial = nullptr;
mTransparent = false;
mHasOwnSurfaces = false;
mHasOwnMaterials = false;
}
CStaticModel::CStaticModel(CMaterial *pMat) : CBasicModel()
CStaticModel::CStaticModel(CMaterial *pMat)
: CBasicModel()
, mpMaterial(pMat)
, mTransparent((pMat->Options() & CMaterial::eTransparent) != 0)
{
mpMaterial = pMat;
mTransparent = ((pMat->Options() & CMaterial::eTransparent) != 0);
mHasOwnSurfaces = false;
mHasOwnMaterials = false;
}
CStaticModel::~CStaticModel()
@@ -58,7 +56,8 @@ void CStaticModel::BufferGL()
Indices[iVert] = mVBO.AddIfUnique(pPrim->Vertices[iVert], VBOStartOffset);
// then add the indices to the IBO. We convert some primitives to strips to minimize draw calls.
switch (pPrim->Type) {
switch (pPrim->Type)
{
case eGX_Triangles:
pIBO->TrianglesToStrips(Indices.data(), Indices.size());
break;
@@ -158,7 +157,7 @@ void CStaticModel::DrawWireframe(FRenderOptions Options, CColor WireColor /*= CC
if (!mBuffered) BufferGL();
// Set up wireframe
WireColor.a = 0;
WireColor.A = 0;
CDrawUtil::UseColorShader(WireColor);
Options |= eNoMaterialSetup;
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

View File

@@ -18,24 +18,24 @@ public:
CVertex() {}
CVertex(CVector3f& Pos)
CVertex(CVector3f& rPos)
{
Position = Pos;
Position = rPos;
}
bool operator==(const CVertex& other) {
return ((Position == other.Position) &&
(Normal == other.Normal) &&
(Color[0] == other.Color[0]) &&
(Color[1] == other.Color[1]) &&
(Tex[0] == other.Tex[0]) &&
(Tex[1] == other.Tex[1]) &&
(Tex[2] == other.Tex[2]) &&
(Tex[3] == other.Tex[3]) &&
(Tex[4] == other.Tex[4]) &&
(Tex[5] == other.Tex[5]) &&
(Tex[6] == other.Tex[6]) &&
(Tex[7] == other.Tex[7]));
bool operator==(const CVertex& rkOther) {
return ((Position == rkOther.Position) &&
(Normal == rkOther.Normal) &&
(Color[0] == rkOther.Color[0]) &&
(Color[1] == rkOther.Color[1]) &&
(Tex[0] == rkOther.Tex[0]) &&
(Tex[1] == rkOther.Tex[1]) &&
(Tex[2] == rkOther.Tex[2]) &&
(Tex[3] == rkOther.Tex[3]) &&
(Tex[4] == rkOther.Tex[4]) &&
(Tex[5] == rkOther.Tex[5]) &&
(Tex[6] == rkOther.Tex[6]) &&
(Tex[7] == rkOther.Tex[7]));
}
};

View File

@@ -5,27 +5,27 @@
enum EVertexAttribute
{
eNoAttributes = 0x0,
ePosition = 0x3,
eNormal = 0xC,
eColor0 = 0x30,
eColor1 = 0xC0,
eTex0 = 0x300,
eTex1 = 0xC00,
eTex2 = 0x3000,
eTex3 = 0xC000,
eTex4 = 0x30000,
eTex5 = 0xC0000,
eTex6 = 0x300000,
eTex7 = 0xC00000,
ePosMtx = 0x1000000,
eTex0Mtx = 0x2000000,
eTex1Mtx = 0x4000000,
eTex2Mtx = 0x8000000,
eTex3Mtx = 0x10000000,
eTex4Mtx = 0x20000000,
eTex5Mtx = 0x40000000,
eTex6Mtx = 0x80000000
eNoAttributes = 0x0,
ePosition = 0x3,
eNormal = 0xC,
eColor0 = 0x30,
eColor1 = 0xC0,
eTex0 = 0x300,
eTex1 = 0xC00,
eTex2 = 0x3000,
eTex3 = 0xC000,
eTex4 = 0x30000,
eTex5 = 0xC0000,
eTex6 = 0x300000,
eTex7 = 0xC00000,
ePosMtx = 0x1000000,
eTex0Mtx = 0x2000000,
eTex1Mtx = 0x4000000,
eTex2Mtx = 0x8000000,
eTex3Mtx = 0x10000000,
eTex4Mtx = 0x20000000,
eTex5Mtx = 0x40000000,
eTex6Mtx = 0x80000000
};
DECLARE_FLAGS(EVertexAttribute, FVertexDescription)

View File

@@ -3,7 +3,7 @@
#include "Core/CRayCollisionTester.h"
#include <Math/MathUtil.h>
std::pair<bool,float> SSurface::IntersectsRay(const CRay& Ray, bool allowBackfaces, float LineThreshold)
std::pair<bool,float> SSurface::IntersectsRay(const CRay& rkRay, bool AllowBackfaces, float LineThreshold)
{
bool Hit = false;
float HitDist;
@@ -25,43 +25,43 @@ std::pair<bool,float> SSurface::IntersectsRay(const CRay& Ray, bool allowBackfac
for (u32 iTri = 0; iTri < NumTris; iTri++)
{
CVector3f vtxA, vtxB, vtxC;
CVector3f VtxA, VtxB, VtxC;
// Get the three vertices that make up the current tri
if (pPrim->Type == eGX_Triangles)
{
u32 VertIndex = iTri * 3;
vtxA = pPrim->Vertices[VertIndex].Position;
vtxB = pPrim->Vertices[VertIndex+1].Position;
vtxC = pPrim->Vertices[VertIndex+2].Position;
VtxA = pPrim->Vertices[VertIndex].Position;
VtxB = pPrim->Vertices[VertIndex+1].Position;
VtxC = pPrim->Vertices[VertIndex+2].Position;
}
else if (pPrim->Type == eGX_TriangleFan)
{
vtxA = pPrim->Vertices[0].Position;
vtxB = pPrim->Vertices[iTri+1].Position;
vtxC = pPrim->Vertices[iTri+2].Position;
VtxA = pPrim->Vertices[0].Position;
VtxB = pPrim->Vertices[iTri+1].Position;
VtxC = pPrim->Vertices[iTri+2].Position;
}
else if (pPrim->Type = eGX_TriangleStrip)
{
if (iTri & 0x1)
{
vtxA = pPrim->Vertices[iTri+2].Position;
vtxB = pPrim->Vertices[iTri+1].Position;
vtxC = pPrim->Vertices[iTri].Position;
VtxA = pPrim->Vertices[iTri+2].Position;
VtxB = pPrim->Vertices[iTri+1].Position;
VtxC = pPrim->Vertices[iTri].Position;
}
else
{
vtxA = pPrim->Vertices[iTri].Position;
vtxB = pPrim->Vertices[iTri+1].Position;
vtxC = pPrim->Vertices[iTri+2].Position;
VtxA = pPrim->Vertices[iTri].Position;
VtxB = pPrim->Vertices[iTri+1].Position;
VtxC = pPrim->Vertices[iTri+2].Position;
}
}
// Intersection test
std::pair<bool,float> TriResult = Math::RayTriangleIntersection(Ray, vtxA, vtxB, vtxC, allowBackfaces);
std::pair<bool,float> TriResult = Math::RayTriangleIntersection(rkRay, VtxA, VtxB, VtxC, AllowBackfaces);
if (TriResult.first)
{
@@ -86,22 +86,22 @@ std::pair<bool,float> SSurface::IntersectsRay(const CRay& Ray, bool allowBackfac
for (u32 iLine = 0; iLine < NumLines; iLine++)
{
CVector3f vtxA, vtxB;
CVector3f VtxA, VtxB;
// Get the two vertices that make up the current line
u32 index = (pPrim->Type == eGX_Lines ? iLine * 2 : iLine);
vtxA = pPrim->Vertices[index].Position;
vtxB = pPrim->Vertices[index+1].Position;
u32 Index = (pPrim->Type == eGX_Lines ? iLine * 2 : iLine);
VtxA = pPrim->Vertices[Index].Position;
VtxB = pPrim->Vertices[Index+1].Position;
// Intersection test
std::pair<bool,float> result = Math::RayLineIntersection(Ray, vtxA, vtxB, LineThreshold);
std::pair<bool,float> Result = Math::RayLineIntersection(rkRay, VtxA, VtxB, LineThreshold);
if (result.first)
if (Result.first)
{
if ((!Hit) || (result.second < HitDist))
if ((!Hit) || (Result.second < HitDist))
{
Hit = true;
HitDist = result.second;
HitDist = Result.second;
}
}
}

View File

@@ -30,12 +30,13 @@ struct SSurface
};
std::vector<SPrimitive> Primitives;
SSurface() {
SSurface()
{
VertexCount = 0;
TriangleCount = 0;
}
std::pair<bool,float> IntersectsRay(const CRay& Ray, bool allowBackfaces = false, float LineThreshold = 0.02f);
std::pair<bool,float> IntersectsRay(const CRay& rkRay, bool AllowBackfaces = false, float LineThreshold = 0.02f);
};
#endif // SSURFACE_H

View File

@@ -6,9 +6,9 @@
struct SNamedResource
{
CFourCC resType;
TString resName;
u64 resID;
CFourCC Type;
TString Name;
u64 ID;
};
#endif // SNAMEDRESOURCE_H

View File

@@ -6,14 +6,14 @@
struct SResInfo
{
bool compressed;
CFourCC resType;
u64 resID;
u32 offset;
u32 size;
bool Compressed;
CFourCC Type;
u64 ID;
u32 Offset;
u32 Size;
SResInfo()
: compressed(false), resType("NULL"), resID(0), offset(0), size(0) {}
: Compressed(false), Type("NULL"), ID(0), Offset(0), Size(0) {}
};
#endif // SRESINFO_H

View File

@@ -3,9 +3,9 @@
#include <Common/Log.h>
CMasterTemplate::CMasterTemplate()
: mVersion(0)
, mFullyLoaded(false)
{
mVersion = 0;
mFullyLoaded = false;
}
CMasterTemplate::~CMasterTemplate()
@@ -14,18 +14,7 @@ CMasterTemplate::~CMasterTemplate()
delete it->second;
}
EGame CMasterTemplate::GetGame()
{
return mGame;
}
u32 CMasterTemplate::NumGameVersions()
{
if (mGameVersions.empty()) return 1;
else return mGameVersions.size();
}
u32 CMasterTemplate::GetGameVersion(TString VersionName)
u32 CMasterTemplate::GameVersion(TString VersionName)
{
VersionName = VersionName.ToLower();
@@ -99,12 +88,7 @@ SMessage CMasterTemplate::MessageByIndex(u32 Index)
return (std::next(it, Index))->second;
}
TString CMasterTemplate::GetDirectory() const
{
return mSourceFile.GetFileDirectory();
}
CStructTemplate* CMasterTemplate::GetStructAtSource(const TString& rkSource)
CStructTemplate* CMasterTemplate::StructAtSource(const TString& rkSource)
{
auto InfoIt = mStructTemplates.find(rkSource);
@@ -114,13 +98,8 @@ CStructTemplate* CMasterTemplate::GetStructAtSource(const TString& rkSource)
else return nullptr;
}
bool CMasterTemplate::IsLoadedSuccessfully()
{
return mFullyLoaded;
}
// ************ STATIC ************
CMasterTemplate* CMasterTemplate::GetMasterForGame(EGame Game)
CMasterTemplate* CMasterTemplate::MasterForGame(EGame Game)
{
auto it = smMasterMap.find(Game);
@@ -130,7 +109,7 @@ CMasterTemplate* CMasterTemplate::GetMasterForGame(EGame Game)
return nullptr;
}
std::list<CMasterTemplate*> CMasterTemplate::GetMasterList()
std::list<CMasterTemplate*> CMasterTemplate::MasterList()
{
std::list<CMasterTemplate*> list;
@@ -140,7 +119,7 @@ std::list<CMasterTemplate*> CMasterTemplate::GetMasterList()
return list;
}
TString CMasterTemplate::GetPropertyName(u32 PropertyID)
TString CMasterTemplate::PropertyName(u32 PropertyID)
{
auto it = smPropertyNames.find(PropertyID);
@@ -250,7 +229,7 @@ void CMasterTemplate::RenameProperty(IPropertyTemplate *pTemp, const TString& rk
}
}
std::vector<TString> CMasterTemplate::GetXMLsUsingID(u32 ID)
std::vector<TString> CMasterTemplate::XMLsUsingID(u32 ID)
{
auto InfoIt = smIDMap.find(ID);
@@ -263,7 +242,7 @@ std::vector<TString> CMasterTemplate::GetXMLsUsingID(u32 ID)
return std::vector<TString>();
}
const std::vector<IPropertyTemplate*>* CMasterTemplate::GetTemplatesWithMatchingID(IPropertyTemplate *pTemp)
const std::vector<IPropertyTemplate*>* CMasterTemplate::TemplatesWithMatchingID(IPropertyTemplate *pTemp)
{
u32 ID = pTemp->PropertyID();
if (ID <= 0xFF) ID = CreatePropertyID(pTemp);

View File

@@ -1,8 +1,8 @@
#ifndef CMASTERTEMPLATE_H
#define CMASTERTEMPLATE_H
#include "CScriptTemplate.h"
#include "CLink.h"
#include "CScriptTemplate.h"
#include "Core/Resource/EGame.h"
#include <Common/types.h>
#include <map>
@@ -38,12 +38,7 @@ class CMasterTemplate
public:
CMasterTemplate();
~CMasterTemplate();
EGame GetGame();
u32 NumGameVersions();
u32 GetGameVersion(TString VersionName);
u32 NumScriptTemplates();
u32 NumStates();
u32 NumMessages();
u32 GameVersion(TString VersionName);
CScriptTemplate* TemplateByID(u32 ObjectID);
CScriptTemplate* TemplateByID(const CFourCC& ObjectID);
CScriptTemplate* TemplateByIndex(u32 Index);
@@ -53,31 +48,26 @@ public:
SMessage MessageByID(u32 MessageID);
SMessage MessageByID(const CFourCC& MessageID);
SMessage MessageByIndex(u32 Index);
TString GetDirectory() const;
CStructTemplate* GetStructAtSource(const TString& rkSource);
bool IsLoadedSuccessfully();
CStructTemplate* StructAtSource(const TString& rkSource);
static CMasterTemplate* GetMasterForGame(EGame Game);
static std::list<CMasterTemplate*> GetMasterList();
static TString GetPropertyName(u32 PropertyID);
// Inline Accessors
EGame Game() const { return mGame; }
u32 NumGameVersions() const { return mGameVersions.empty() ? 1 : mGameVersions.size(); }
u32 NumScriptTemplates() const { return mTemplates.size(); }
u32 NumStates() const { return mStates.size(); }
u32 NumMessages() const { return mMessages.size(); }
bool IsLoadedSuccessfully() { return mFullyLoaded; }
TString GetDirectory() const { return mSourceFile.GetFileDirectory(); }
// Static
static CMasterTemplate* MasterForGame(EGame Game);
static std::list<CMasterTemplate*> MasterList();
static TString PropertyName(u32 PropertyID);
static u32 CreatePropertyID(IPropertyTemplate *pTemp);
static void AddProperty(IPropertyTemplate *pTemp, const TString& rkTemplateName = "");
static void RenameProperty(IPropertyTemplate *pTemp, const TString& rkNewName);
static std::vector<TString> GetXMLsUsingID(u32 ID);
static const std::vector<IPropertyTemplate*>* GetTemplatesWithMatchingID(IPropertyTemplate *pTemp);
static std::vector<TString> XMLsUsingID(u32 ID);
static const std::vector<IPropertyTemplate*>* TemplatesWithMatchingID(IPropertyTemplate *pTemp);
};
// ************ INLINE ************
inline u32 CMasterTemplate::NumScriptTemplates() {
return mTemplates.size();
}
inline u32 CMasterTemplate::NumStates() {
return mStates.size();
}
inline u32 CMasterTemplate::NumMessages() {
return mMessages.size();
}
#endif // CMASTERTEMPLATE_H

View File

@@ -101,14 +101,14 @@ public:
inline u32 AreaIndex() const
{
for (u32 iLyr = 0; iLyr < mpArea->GetScriptLayerCount(); iLyr++)
for (u32 iLyr = 0; iLyr < mpArea->NumScriptLayers(); iLyr++)
{
if (mpArea->GetScriptLayer(iLyr) == this)
if (mpArea->ScriptLayer(iLyr) == this)
return iLyr;
}
if (mpArea->GetGeneratorLayer() == this)
return mpArea->GetScriptLayerCount();
if (mpArea->GeneratedObjectsLayer() == this)
return mpArea->NumScriptLayers();
return -1;
}

View File

@@ -160,72 +160,6 @@ bool CScriptObject::HasNearVisibleActivation() const
return false;
}
// ************ GETTERS ************
IProperty* CScriptObject::PropertyByIndex(u32 index) const
{
return mpProperties->PropertyByIndex(index);
}
IProperty* CScriptObject::PropertyByIDString(const TString& str) const
{
return mpProperties->PropertyByIDString(str);
}
CScriptTemplate* CScriptObject::Template() const
{
return mpTemplate;
}
CMasterTemplate* CScriptObject::MasterTemplate() const
{
return mpTemplate->MasterTemplate();
}
CGameArea* CScriptObject::Area() const
{
return mpArea;
}
CScriptLayer* CScriptObject::Layer() const
{
return mpLayer;
}
u32 CScriptObject::Version() const
{
return mVersion;
}
CPropertyStruct* CScriptObject::Properties() const
{
return mpProperties;
}
u32 CScriptObject::NumProperties() const
{
return mpProperties->Count();
}
u32 CScriptObject::ObjectTypeID() const
{
return mpTemplate->ObjectID();
}
u32 CScriptObject::InstanceID() const
{
return mInstanceID;
}
u32 CScriptObject::NumLinks(ELinkType Type) const
{
return (Type == eIncoming ? mInLinks.size() : mOutLinks.size());
}
CLink* CScriptObject::Link(ELinkType Type, u32 Index) const
{
return (Type == eIncoming ? mInLinks[Index] : mOutLinks[Index]);
}
void CScriptObject::AddLink(ELinkType Type, CLink *pLink, u32 Index /*= -1*/)
{
std::vector<CLink*> *pLinkVec = (Type == eIncoming ? &mInLinks : &mOutLinks);
@@ -273,103 +207,3 @@ void CScriptObject::BreakAllLinks()
mInLinks.clear();
mOutLinks.clear();
}
TString CScriptObject::InstanceName() const
{
if (mpInstanceName)
return mpInstanceName->Get();
else
return "";
}
CVector3f CScriptObject::Position() const
{
if (mpPosition)
return mpPosition->Get();
else
return CVector3f::skZero;
}
CVector3f CScriptObject::Rotation() const
{
if (mpRotation)
return mpRotation->Get();
else
return CVector3f::skZero;
}
CVector3f CScriptObject::Scale() const
{
if (mpScale)
return mpScale->Get();
else
return CVector3f::skOne;
}
bool CScriptObject::IsActive() const
{
if (mpActive)
return mpActive->Get();
else
return false;
}
bool CScriptObject::HasInGameModel() const
{
return mHasInGameModel;
}
void CScriptObject::SetPosition(const CVector3f& newPos)
{
if (mpPosition) mpPosition->Set(newPos);
}
void CScriptObject::SetRotation(const CVector3f& newRot)
{
if (mpRotation) mpRotation->Set(newRot);
}
void CScriptObject::SetScale(const CVector3f& newScale)
{
if (mpScale) mpScale->Set(newScale);
}
void CScriptObject::SetName(const TString& newName)
{
if (mpInstanceName) mpInstanceName->Set(newName);
}
void CScriptObject::SetActive(bool isActive)
{
if (mpActive) mpActive->Set(isActive);
}
CPropertyStruct* CScriptObject::LightParameters() const
{
return mpLightParameters;
}
CModel* CScriptObject::GetDisplayModel() const
{
return mpDisplayModel;
}
CTexture* CScriptObject::GetBillboard() const
{
return mpBillboard;
}
CCollisionMeshGroup* CScriptObject::GetCollision() const
{
return mpCollision;
}
EVolumeShape CScriptObject::VolumeShape() const
{
return mVolumeShape;
}
float CScriptObject::VolumeScale() const
{
return mVolumeScale;
}

View File

@@ -63,41 +63,42 @@ public:
u32 LayerIndex() const;
bool HasNearVisibleActivation() const;
CScriptTemplate* Template() const;
CMasterTemplate* MasterTemplate() const;
CGameArea* Area() const;
CScriptLayer* Layer() const;
u32 Version() const;
CPropertyStruct* Properties() const;
u32 NumProperties() const;
IProperty* PropertyByIndex(u32 index) const;
IProperty* PropertyByIDString(const TIDString& str) const;
u32 ObjectTypeID() const;
u32 InstanceID() const;
u32 NumLinks(ELinkType Type) const;
CLink* Link(ELinkType Type, u32 Index) const;
void AddLink(ELinkType Type, CLink *pLink, u32 Index = -1);
void RemoveLink(ELinkType Type, CLink *pLink);
void BreakAllLinks();
CVector3f Position() const;
CVector3f Rotation() const;
CVector3f Scale() const;
TString InstanceName() const;
bool IsActive() const;
bool HasInGameModel() const;
void SetPosition(const CVector3f& newPos);
void SetRotation(const CVector3f& newRot);
void SetScale(const CVector3f& newScale);
void SetName(const TString& newName);
void SetActive(bool isActive);
CPropertyStruct* LightParameters() const;
CModel* GetDisplayModel() const;
CTexture* GetBillboard() const;
CCollisionMeshGroup* GetCollision() const;
EVolumeShape VolumeShape() const;
float VolumeScale() const;
// Accessors
CScriptTemplate* Template() const { return mpTemplate; }
CMasterTemplate* MasterTemplate() const { return mpTemplate->MasterTemplate(); }
CGameArea* Area() const { return mpArea; }
CScriptLayer* Layer() const { return mpLayer; }
u32 Version() const { return mVersion; }
CPropertyStruct* Properties() const { return mpProperties; }
u32 NumProperties() const { return mpProperties->Count(); }
IProperty* PropertyByIndex(u32 Index) const { return mpProperties->PropertyByIndex(Index); }
IProperty* PropertyByIDString(const TIDString& rkStr) const { return mpProperties->PropertyByIDString(rkStr); }
u32 ObjectTypeID() const { return mpTemplate->ObjectID(); }
u32 InstanceID() const { return mInstanceID; }
u32 NumLinks(ELinkType Type) const { return (Type == eIncoming ? mInLinks.size() : mOutLinks.size()); }
CLink* Link(ELinkType Type, u32 Index) const { return (Type == eIncoming ? mInLinks[Index] : mOutLinks[Index]); }
CVector3f Position() const { return mpPosition ? mpPosition->Get() : CVector3f::skZero; }
CVector3f Rotation() const { return mpRotation ? mpRotation->Get() : CVector3f::skZero; }
CVector3f Scale() const { return mpScale ? mpScale->Get() : CVector3f::skZero; }
TString InstanceName() const { return mpInstanceName ? mpInstanceName->Get() : ""; }
bool IsActive() const { return mpActive ? mpActive->Get() : false; }
bool HasInGameModel() const { return mHasInGameModel; }
void SetPosition(const CVector3f& rkNewPos) { if (mpPosition) mpPosition->Set(rkNewPos); }
void SetRotation(const CVector3f& rkNewRot) { if (mpRotation) mpRotation->Set(rkNewRot); }
void SetScale(const CVector3f& rkNewScale) { if (mpScale) mpScale->Set(rkNewScale); }
void SetName(const TString& rkNewName) { if (mpInstanceName) mpInstanceName->Set(rkNewName); }
void SetActive(bool Active) { if (mpActive) mpActive->Set(Active); }
CPropertyStruct* LightParameters() const { return mpLightParameters; }
CModel* GetDisplayModel() const { return mpDisplayModel; }
CTexture* GetBillboard() const { return mpBillboard; }
CCollisionMeshGroup* GetCollision() const { return mpCollision; }
EVolumeShape VolumeShape() const { return mVolumeShape; }
float VolumeScale() const { return mVolumeScale; }
TStringProperty* InstanceNameProperty() const { return mpInstanceName; }
TVector3Property* PositionProperty() const { return mpPosition; }

View File

@@ -23,74 +23,24 @@ CScriptTemplate::~CScriptTemplate()
delete mpBaseStruct;
}
CMasterTemplate* CScriptTemplate::MasterTemplate()
EGame CScriptTemplate::Game() const
{
return mpMaster;
}
EGame CScriptTemplate::Game()
{
return mpMaster->GetGame();
}
TString CScriptTemplate::Name() const
{
return mTemplateName;
}
CScriptTemplate::ERotationType CScriptTemplate::RotationType() const
{
return mRotationType;
}
CScriptTemplate::EScaleType CScriptTemplate::ScaleType() const
{
return mScaleType;
}
float CScriptTemplate::PreviewScale() const
{
return mPreviewScale;
}
u32 CScriptTemplate::ObjectID() const
{
return mObjectID;
}
void CScriptTemplate::SetVisible(bool visible)
{
mVisible = visible;
}
bool CScriptTemplate::IsVisible() const
{
return mVisible;
}
void CScriptTemplate::DebugPrintProperties()
{
mpBaseStruct->DebugPrintProperties("");
return mpMaster->Game();
}
// ************ PROPERTY FETCHING ************
template<typename t, EPropertyType propType>
t TFetchProperty(CPropertyStruct *pProperties, const TIDString& ID)
template<typename PropType, EPropertyType PropEnum>
PropType TFetchProperty(CPropertyStruct *pProperties, const TIDString& rkID)
{
if (ID.IsEmpty()) return nullptr;
IProperty *pProp = pProperties->PropertyByIDString(ID);
if (rkID.IsEmpty()) return nullptr;
IProperty *pProp = pProperties->PropertyByIDString(rkID);
if (pProp && (pProp->Type() == propType))
return static_cast<t>(pProp);
if (pProp && (pProp->Type() == PropEnum))
return static_cast<PropType>(pProp);
else
return nullptr;
}
CStructTemplate* CScriptTemplate::BaseStruct()
{
return mpBaseStruct;
}
EVolumeShape CScriptTemplate::VolumeShape(CScriptObject *pObj)
{
if (pObj->Template() != this)
@@ -101,9 +51,9 @@ EVolumeShape CScriptTemplate::VolumeShape(CScriptObject *pObj)
if (mVolumeShape == eConditionalShape)
{
s32 index = CheckVolumeConditions(pObj, true);
if (index == -1) return eInvalidShape;
else return mVolumeConditions[index].Shape;
s32 Index = CheckVolumeConditions(pObj, true);
if (Index == -1) return eInvalidShape;
else return mVolumeConditions[Index].Shape;
}
else return mVolumeShape;
}
@@ -118,9 +68,9 @@ float CScriptTemplate::VolumeScale(CScriptObject *pObj)
if (mVolumeShape == eConditionalShape)
{
s32 index = CheckVolumeConditions(pObj, false);
if (index == -1) return mVolumeScale;
else return mVolumeConditions[index].Scale;
s32 Index = CheckVolumeConditions(pObj, false);
if (Index == -1) return mVolumeScale;
else return mVolumeConditions[Index].Scale;
}
else return mVolumeScale;
}
@@ -133,40 +83,40 @@ s32 CScriptTemplate::CheckVolumeConditions(CScriptObject *pObj, bool LogErrors)
IProperty *pProp = pObj->Properties()->PropertyByIDString(mVolumeConditionIDString);
// Get value of the condition test property (only boolean, integral, and enum types supported)
int v;
int Val;
switch (pProp->Type())
{
case eBoolProperty:
v = (static_cast<TBoolProperty*>(pProp)->Get() ? 1 : 0);
Val = (static_cast<TBoolProperty*>(pProp)->Get() ? 1 : 0);
break;
case eByteProperty:
v = (int) static_cast<TByteProperty*>(pProp)->Get();
Val = (int) static_cast<TByteProperty*>(pProp)->Get();
break;
case eShortProperty:
v = (int) static_cast<TShortProperty*>(pProp)->Get();
Val = (int) static_cast<TShortProperty*>(pProp)->Get();
break;
case eLongProperty:
v = (int) static_cast<TLongProperty*>(pProp)->Get();
Val = (int) static_cast<TLongProperty*>(pProp)->Get();
break;
case eEnumProperty: {
v = (int) static_cast<TEnumProperty*>(pProp)->Get();
case eEnumProperty:
Val = (int) static_cast<TEnumProperty*>(pProp)->Get();
break;
}
}
// Test and check whether any of the conditions are true
for (u32 iCon = 0; iCon < mVolumeConditions.size(); iCon++)
{
if (mVolumeConditions[iCon].Value == v)
if (mVolumeConditions[iCon].Value == Val)
return iCon;
}
if (LogErrors)
Log::Error(pObj->Template()->Name() + " instance " + TString::HexString(pObj->InstanceID(), true, true, 8) + " has unexpected volume shape value of " + TString::HexString((u32) v, true, true));
Log::Error(pObj->Template()->Name() + " instance " + TString::HexString(pObj->InstanceID()) + " has unexpected volume shape value of " + TString::HexString((u32) Val, 0));
}
return -1;
@@ -213,8 +163,8 @@ CModel* CScriptTemplate::FindDisplayModel(CPropertyStruct *pProperties)
// File
if (it->AssetSource == SEditorAsset::eFile)
{
TString path = "../resources/" + it->AssetLocation;
pRes = gResCache.GetResource(path);
TString Path = "../resources/" + it->AssetLocation;
pRes = gResCache.GetResource(Path);
}
// Property

View File

@@ -12,7 +12,6 @@
#include <list>
#include <vector>
class CMasterTemplate;
class CScriptObject;
typedef TString TIDString;
@@ -89,21 +88,9 @@ private:
public:
CScriptTemplate(CMasterTemplate *pMaster);
~CScriptTemplate();
CMasterTemplate* MasterTemplate();
EGame Game();
TString Name() const;
u32 NumPropertySets() const;
ERotationType RotationType() const;
EScaleType ScaleType() const;
float PreviewScale() const;
u32 ObjectID() const;
void SetVisible(bool visible);
bool IsVisible() const;
void DebugPrintProperties();
EGame Game() const;
// Property Fetching
CStructTemplate* BaseStruct();
EVolumeShape VolumeShape(CScriptObject *pObj);
float VolumeScale(CScriptObject *pObj);
TStringProperty* FindInstanceName(CPropertyStruct *pProperties);
@@ -117,12 +104,26 @@ public:
CCollisionMeshGroup* FindCollision(CPropertyStruct *pProperties);
bool HasInGameModel(CPropertyStruct *pProperties);
inline TString SourceFile() const { return mSourceFile; }
inline bool HasName() const { return !mNameIDString.IsEmpty(); }
inline bool HasPosition() const { return !mPositionIDString.IsEmpty(); }
inline bool HasRotation() const { return !mRotationIDString.IsEmpty(); }
inline bool HasScale() const { return !mScaleIDString.IsEmpty(); }
inline bool HasActive() const { return !mActiveIDString.IsEmpty(); }
// Accessors
inline CMasterTemplate* MasterTemplate() const { return mpMaster; }
inline TString Name() const { return mTemplateName; }
inline ERotationType RotationType() const { return mRotationType; }
inline EScaleType ScaleType() const { return mScaleType; }
inline float PreviewScale() const { return mPreviewScale; }
inline u32 ObjectID() const { return mObjectID; }
inline bool IsVisible() const { return mVisible; }
inline TString SourceFile() const { return mSourceFile; }
inline CStructTemplate* BaseStruct() const { return mpBaseStruct; }
inline bool HasName() const { return !mNameIDString.IsEmpty(); }
inline bool HasPosition() const { return !mPositionIDString.IsEmpty(); }
inline bool HasRotation() const { return !mRotationIDString.IsEmpty(); }
inline bool HasScale() const { return !mScaleIDString.IsEmpty(); }
inline bool HasActive() const { return !mActiveIDString.IsEmpty(); }
inline void SetVisible(bool Visible) { mVisible = Visible; }
inline void DebugPrintProperties() { mpBaseStruct->DebugPrintProperties(""); }
// Object Tracking
u32 NumObjects() const;

View File

@@ -50,7 +50,7 @@ TIDString IProperty::IDString(bool FullPath) const
if (!Out.IsEmpty()) Out += ":";
}
Out += TString::HexString(ID(), true, true, 8);
Out += TString::HexString(ID());
}
return Out;

View File

@@ -5,7 +5,7 @@
// ************ IPropertyTemplate ************
EGame IPropertyTemplate::Game() const
{
return (mpMasterTemplate ? mpMasterTemplate->GetGame() : eUnknownVersion);
return (mpMasterTemplate ? mpMasterTemplate->Game() : eUnknownVersion);
}
bool IPropertyTemplate::IsInVersion(u32 Version) const
@@ -32,7 +32,7 @@ TIDString IPropertyTemplate::IDString(bool FullPath) const
if (!out.IsEmpty()) out += ":";
}
out += TIDString::HexString(mID, true, true, 8);
out += TIDString::HexString(mID);
return out;
}
else return "";

View File

@@ -168,13 +168,13 @@ public:
TString ToString() const
{
return TString::HexString(mValue, true, true, mValue > 0xFF ? 8 : 2);
return TString::HexString(mValue, 8);
}
void FromString(const TString& rkString)
{
u32 base = (rkString.StartsWith("0x") ? 16 : 10);
mValue = (s32) rkString.ToInt32(base);
u32 Base = (rkString.StartsWith("0x") ? 16 : 10);
mValue = (s32) rkString.ToInt32(Base);
}
IPropertyValue* Clone() const
@@ -237,10 +237,10 @@ public:
TString ToString() const
{
TString out;
out += TString::FromFloat(mValue.r) + ", ";
out += TString::FromFloat(mValue.g) + ", ";
out += TString::FromFloat(mValue.b) + ", ";
out += TString::FromFloat(mValue.a);
out += TString::FromFloat(mValue.R) + ", ";
out += TString::FromFloat(mValue.G) + ", ";
out += TString::FromFloat(mValue.B) + ", ";
out += TString::FromFloat(mValue.A);
return out;
}
@@ -255,8 +255,8 @@ public:
return;
}
float *pPtr = &mValue.r;
mValue.a = 1.0f;
float *pPtr = &mValue.R;
mValue.A = 1.0f;
for (auto it = Components.begin(); it != Components.end(); it++)
{
@@ -280,9 +280,9 @@ public:
TString ToString() const
{
TString out;
out += TString::FromFloat(mValue.x) + ", ";
out += TString::FromFloat(mValue.y) + ", ";
out += TString::FromFloat(mValue.z);
out += TString::FromFloat(mValue.X) + ", ";
out += TString::FromFloat(mValue.Y) + ", ";
out += TString::FromFloat(mValue.Z);
return out;
}
@@ -297,7 +297,7 @@ public:
return;
}
float *pPtr = &mValue.x;
float *pPtr = &mValue.X;
for (auto it = Components.begin(); it != Components.end(); it++)
{