mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-10 05:57:48 +00:00
Initial commit of current work on Prime World Editor
This commit is contained in:
57
Resource/model/CBasicModel.cpp
Normal file
57
Resource/model/CBasicModel.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "CBasicModel.h"
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
CBasicModel::CBasicModel() : CResource()
|
||||
{
|
||||
mVertexCount = 0;
|
||||
mTriangleCount = 0;
|
||||
mBuffered = false;
|
||||
}
|
||||
|
||||
CBasicModel::~CBasicModel()
|
||||
{
|
||||
if (mHasOwnSurfaces)
|
||||
for (u32 iSurf = 0; iSurf < mSurfaces.size(); iSurf++)
|
||||
delete mSurfaces[iSurf];
|
||||
}
|
||||
|
||||
EResType CBasicModel::Type()
|
||||
{
|
||||
return eModel;
|
||||
}
|
||||
|
||||
u32 CBasicModel::GetVertexCount()
|
||||
{
|
||||
return mVertexCount;
|
||||
}
|
||||
|
||||
u32 CBasicModel::GetTriangleCount()
|
||||
{
|
||||
return mTriangleCount;
|
||||
}
|
||||
|
||||
CAABox CBasicModel::AABox()
|
||||
{
|
||||
return mAABox;
|
||||
}
|
||||
|
||||
bool CBasicModel::IsBuffered()
|
||||
{
|
||||
return mBuffered;
|
||||
}
|
||||
|
||||
u32 CBasicModel::GetSurfaceCount()
|
||||
{
|
||||
return mSurfaces.size();
|
||||
}
|
||||
|
||||
CAABox CBasicModel::GetSurfaceAABox(u32 Surface)
|
||||
{
|
||||
return mSurfaces[Surface]->AABox;
|
||||
}
|
||||
|
||||
SSurface* CBasicModel::GetSurface(u32 Surface)
|
||||
{
|
||||
return mSurfaces[Surface];
|
||||
}
|
||||
37
Resource/model/CBasicModel.h
Normal file
37
Resource/model/CBasicModel.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef CBASICMODEL_H
|
||||
#define CBASICMODEL_H
|
||||
|
||||
#include "../CResource.h"
|
||||
#include "SSurface.h"
|
||||
#include <Common/CAABox.h>
|
||||
#include <OpenGL/CVertexBuffer.h>
|
||||
|
||||
class CBasicModel : public CResource
|
||||
{
|
||||
protected:
|
||||
CAABox mAABox;
|
||||
u32 mVertexCount;
|
||||
u32 mTriangleCount;
|
||||
bool mBuffered;
|
||||
bool mHasOwnMaterials;
|
||||
bool mHasOwnSurfaces;
|
||||
|
||||
CVertexBuffer mVBO;
|
||||
std::vector<SSurface*> mSurfaces;
|
||||
|
||||
public:
|
||||
CBasicModel();
|
||||
~CBasicModel();
|
||||
EResType Type();
|
||||
|
||||
u32 GetVertexCount();
|
||||
u32 GetTriangleCount();
|
||||
CAABox AABox();
|
||||
bool IsBuffered();
|
||||
u32 GetSurfaceCount();
|
||||
CAABox GetSurfaceAABox(u32 Surface);
|
||||
SSurface* GetSurface(u32 Surface);
|
||||
virtual void ClearGLBuffer() = 0;
|
||||
};
|
||||
|
||||
#endif // CBASICMODEL_H
|
||||
207
Resource/model/CModel.cpp
Normal file
207
Resource/model/CModel.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
#include "CModel.h"
|
||||
#include <Core/CRenderer.h>
|
||||
#include <OpenGL/GLCommon.h>
|
||||
|
||||
CModel::CModel() : CBasicModel()
|
||||
{
|
||||
mHasOwnMaterials = true;
|
||||
mHasOwnSurfaces = true;
|
||||
}
|
||||
|
||||
CModel::CModel(SModelData *pModelData) : CBasicModel()
|
||||
{
|
||||
SetData(pModelData);
|
||||
mHasOwnMaterials = false;
|
||||
mHasOwnSurfaces = true;
|
||||
}
|
||||
|
||||
CModel::CModel(SModelData *data, CMaterialSet *pMatSet) : CBasicModel()
|
||||
{
|
||||
SetData(data);
|
||||
mMaterialSets.resize(1);
|
||||
mMaterialSets[0] = pMatSet;
|
||||
mHasOwnMaterials = false;
|
||||
mHasOwnSurfaces = true;
|
||||
}
|
||||
|
||||
CModel::~CModel()
|
||||
{
|
||||
if (mHasOwnMaterials)
|
||||
for (u32 m = 0; m < mMaterialSets.size(); m++)
|
||||
delete mMaterialSets[m];
|
||||
}
|
||||
|
||||
void CModel::SetData(SModelData *pModelData)
|
||||
{
|
||||
mAABox = pModelData->mAABox;
|
||||
mSurfaces = pModelData->mSurfaces;
|
||||
|
||||
mVertexCount = 0;
|
||||
mTriangleCount = 0;
|
||||
|
||||
for (u32 iSurf = 0; iSurf < mSurfaces.size(); iSurf++)
|
||||
{
|
||||
SSurface *pSurf = mSurfaces[iSurf];
|
||||
mVertexCount += pSurf->VertexCount;
|
||||
mTriangleCount += pSurf->TriangleCount;
|
||||
}
|
||||
}
|
||||
|
||||
void CModel::BufferGL()
|
||||
{
|
||||
mVBO.Clear();
|
||||
mSubmeshIndexBuffers.clear();
|
||||
|
||||
mSubmeshIndexBuffers.resize(mSurfaces.size());
|
||||
|
||||
for (u32 iSurf = 0; iSurf < mSurfaces.size(); iSurf++)
|
||||
{
|
||||
SSurface *pSurf = mSurfaces[iSurf];
|
||||
|
||||
u16 VBOStartOffset = (u16) mVBO.Size();
|
||||
mVBO.Reserve((u16) pSurf->VertexCount);
|
||||
|
||||
for (u32 iPrim = 0; iPrim < pSurf->Primitives.size(); iPrim++)
|
||||
{
|
||||
SSurface::SPrimitive *pPrim = &pSurf->Primitives[iPrim];
|
||||
CIndexBuffer *pIBO = InternalGetIBO(iSurf, pPrim->Type);
|
||||
pIBO->Reserve(pPrim->Vertices.size() + 1); // Allocate enough space for this primitive, plus the restart index
|
||||
|
||||
std::vector<u16> Indices(pPrim->Vertices.size());
|
||||
for (u32 iVert = 0; iVert < pPrim->Vertices.size(); iVert++)
|
||||
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) {
|
||||
case eGX_Triangles:
|
||||
pIBO->TrianglesToStrips(Indices.data(), Indices.size());
|
||||
break;
|
||||
case eGX_TriangleFan:
|
||||
pIBO->FansToStrips(Indices.data(), Indices.size());
|
||||
break;
|
||||
case eGX_Quads:
|
||||
pIBO->QuadsToStrips(Indices.data(), Indices.size());
|
||||
break;
|
||||
default:
|
||||
pIBO->AddIndices(Indices.data(), Indices.size());
|
||||
pIBO->AddIndex(0xFFFF); // primitive restart
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mBuffered = true;
|
||||
}
|
||||
|
||||
void CModel::ClearGLBuffer()
|
||||
{
|
||||
mVBO.Clear();
|
||||
mSubmeshIndexBuffers.clear();
|
||||
mBuffered = false;
|
||||
}
|
||||
|
||||
void CModel::Draw(ERenderOptions Options, u32 MatSet)
|
||||
{
|
||||
if (!mBuffered) BufferGL();
|
||||
for (u32 iSurf = 0; iSurf < mSurfaces.size(); iSurf++)
|
||||
DrawSurface(Options, iSurf, MatSet);
|
||||
}
|
||||
|
||||
void CModel::DrawSurface(ERenderOptions Options, u32 Surface, u32 MatSet)
|
||||
{
|
||||
if (!mBuffered) BufferGL();
|
||||
|
||||
// Check that mat set index is valid
|
||||
if (MatSet >= mMaterialSets.size())
|
||||
MatSet = mMaterialSets.size() - 1;
|
||||
|
||||
// Bind material
|
||||
SSurface *pSurf = mSurfaces[Surface];
|
||||
CMaterial *pMat = mMaterialSets[MatSet]->materials[pSurf->MaterialID];
|
||||
|
||||
if ((Options & eNoMaterialSetup) == 0)
|
||||
{
|
||||
if ((!(Options & eEnableOccluders)) && (pMat->Options() & CMaterial::eOccluder))
|
||||
return;
|
||||
|
||||
pMat->SetCurrent(Options);
|
||||
}
|
||||
|
||||
// Draw IBOs
|
||||
mVBO.Bind();
|
||||
|
||||
for (u32 iIBO = 0; iIBO < mSubmeshIndexBuffers[Surface].size(); iIBO++)
|
||||
{
|
||||
CIndexBuffer *pIBO = &mSubmeshIndexBuffers[Surface][iIBO];
|
||||
pIBO->DrawElements();
|
||||
}
|
||||
|
||||
mVBO.Unbind();
|
||||
}
|
||||
|
||||
u32 CModel::GetMatSetCount()
|
||||
{
|
||||
return mMaterialSets.size();
|
||||
}
|
||||
|
||||
u32 CModel::GetMatCount()
|
||||
{
|
||||
if (mMaterialSets.empty()) return 0;
|
||||
else return mMaterialSets[0]->materials.size();
|
||||
}
|
||||
|
||||
CMaterialSet* CModel::GetMatSet(u32 MatSet)
|
||||
{
|
||||
return mMaterialSets[MatSet];
|
||||
}
|
||||
|
||||
CMaterial* CModel::GetMaterialByIndex(u32 MatSet, u32 Index)
|
||||
{
|
||||
if (MatSet >= mMaterialSets.size())
|
||||
MatSet = mMaterialSets.size() - 1;
|
||||
|
||||
if (GetMatCount() == 0)
|
||||
return nullptr;
|
||||
|
||||
return mMaterialSets[MatSet]->materials[Index];
|
||||
}
|
||||
|
||||
CMaterial* CModel::GetMaterialBySurface(u32 MatSet, u32 Surface)
|
||||
{
|
||||
return GetMaterialByIndex(MatSet, mSurfaces[Surface]->MaterialID);
|
||||
}
|
||||
|
||||
bool CModel::HasTransparency(u32 MatSet)
|
||||
{
|
||||
if (MatSet >= mMaterialSets.size())
|
||||
MatSet = mMaterialSets.size() - 1;
|
||||
|
||||
for (u32 iMat = 0; iMat < mMaterialSets[MatSet]->materials.size(); iMat++)
|
||||
if (mMaterialSets[MatSet]->materials[iMat]->Options() & CMaterial::eTransparent ) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CModel::IsSurfaceTransparent(u32 Surface, u32 MatSet)
|
||||
{
|
||||
if (MatSet >= mMaterialSets.size())
|
||||
MatSet = mMaterialSets.size() - 1;
|
||||
|
||||
u32 matID = mSurfaces[Surface]->MaterialID;
|
||||
return (mMaterialSets[MatSet]->materials[matID]->Options() & CMaterial::eTransparent) != 0;
|
||||
}
|
||||
|
||||
CIndexBuffer* CModel::InternalGetIBO(u32 Surface, EGXPrimitiveType Primitive)
|
||||
{
|
||||
std::vector<CIndexBuffer> *pIBOs = &mSubmeshIndexBuffers[Surface];
|
||||
GLenum Type = GXPrimToGLPrim(Primitive);
|
||||
|
||||
for (u32 iIBO = 0; iIBO < pIBOs->size(); iIBO++)
|
||||
{
|
||||
if ((*pIBOs)[iIBO].GetPrimitiveType() == Type)
|
||||
return &(*pIBOs)[iIBO];
|
||||
}
|
||||
|
||||
pIBOs->emplace_back(CIndexBuffer(Type));
|
||||
return &pIBOs->back();
|
||||
}
|
||||
46
Resource/model/CModel.h
Normal file
46
Resource/model/CModel.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef CMODEL_H
|
||||
#define CMODEL_H
|
||||
|
||||
#include "CBasicModel.h"
|
||||
#include "SModelData.h"
|
||||
#include "SSurface.h"
|
||||
#include "../CMaterialSet.h"
|
||||
|
||||
#include <Core/ERenderOptions.h>
|
||||
#include <OpenGL/CIndexBuffer.h>
|
||||
#include <OpenGL/GLCommon.h>
|
||||
|
||||
class CModel : public CBasicModel
|
||||
{
|
||||
friend class CModelLoader;
|
||||
friend class CModelCooker;
|
||||
|
||||
std::vector<CMaterialSet*> mMaterialSets;
|
||||
std::vector<std::vector<CIndexBuffer>> mSubmeshIndexBuffers;
|
||||
bool mHasOwnMaterials;
|
||||
|
||||
public:
|
||||
CModel();
|
||||
CModel(SModelData *pModelData);
|
||||
CModel(SModelData *pModelData, CMaterialSet *pMatSet);
|
||||
~CModel();
|
||||
void SetData(SModelData *pModelData);
|
||||
|
||||
void BufferGL();
|
||||
void ClearGLBuffer();
|
||||
void Draw(ERenderOptions Options, u32 MatSet);
|
||||
void DrawSurface(ERenderOptions Options, u32 Surface, u32 MatSet);
|
||||
|
||||
u32 GetMatSetCount();
|
||||
u32 GetMatCount();
|
||||
CMaterialSet* GetMatSet(u32 MatSet);
|
||||
CMaterial* GetMaterialByIndex(u32 MatSet, u32 Index);
|
||||
CMaterial* GetMaterialBySurface(u32 MatSet, u32 Surface);
|
||||
bool HasTransparency(u32 MatSet);
|
||||
bool IsSurfaceTransparent(u32 Surface, u32 MatSet);
|
||||
|
||||
private:
|
||||
CIndexBuffer* InternalGetIBO(u32 Surface, EGXPrimitiveType Primitive);
|
||||
};
|
||||
|
||||
#endif // MODEL_H
|
||||
177
Resource/model/CStaticModel.cpp
Normal file
177
Resource/model/CStaticModel.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
#include "CStaticModel.h"
|
||||
#include <Core/CRenderer.h>
|
||||
#include <OpenGL/GLCommon.h>
|
||||
|
||||
CStaticModel::CStaticModel() : CBasicModel()
|
||||
{
|
||||
mpMaterial = nullptr;
|
||||
mTransparent = false;
|
||||
mHasOwnSurfaces = false;
|
||||
mHasOwnMaterials = false;
|
||||
}
|
||||
|
||||
CStaticModel::CStaticModel(CMaterial *pMat) : CBasicModel()
|
||||
{
|
||||
mpMaterial = pMat;
|
||||
mTransparent = ((pMat->Options() & CMaterial::eTransparent) != 0);
|
||||
mHasOwnSurfaces = false;
|
||||
mHasOwnMaterials = false;
|
||||
}
|
||||
|
||||
CStaticModel::~CStaticModel()
|
||||
{
|
||||
}
|
||||
|
||||
void CStaticModel::AddSurface(SSurface *pSurface)
|
||||
{
|
||||
mSurfaces.push_back(pSurface);
|
||||
mAABox.ExpandBounds(pSurface->AABox);
|
||||
|
||||
mVertexCount += pSurface->VertexCount;
|
||||
mTriangleCount += pSurface->TriangleCount;
|
||||
}
|
||||
|
||||
void CStaticModel::BufferGL()
|
||||
{
|
||||
mVBO.Clear();
|
||||
mIBOs.clear();
|
||||
|
||||
for (u32 iSurf = 0; iSurf < mSurfaces.size(); iSurf++)
|
||||
{
|
||||
SSurface *pSurf = mSurfaces[iSurf];
|
||||
|
||||
u16 VBOStartOffset = (u16) mVBO.Size();
|
||||
mVBO.Reserve((u16) pSurf->VertexCount);
|
||||
|
||||
for (u32 iPrim = 0; iPrim < pSurf->Primitives.size(); iPrim++)
|
||||
{
|
||||
SSurface::SPrimitive *pPrim = &pSurf->Primitives[iPrim];
|
||||
CIndexBuffer *pIBO = InternalGetIBO(pPrim->Type);
|
||||
pIBO->Reserve(pPrim->Vertices.size() + 1); // Allocate enough space for this primitive, plus the restart index
|
||||
|
||||
// Next step: add new vertices to the VBO and create a small index buffer for the current primitive
|
||||
std::vector<u16> Indices(pPrim->Vertices.size());
|
||||
for (u32 iVert = 0; iVert < pPrim->Vertices.size(); iVert++)
|
||||
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) {
|
||||
case eGX_Triangles:
|
||||
pIBO->TrianglesToStrips(Indices.data(), Indices.size());
|
||||
break;
|
||||
case eGX_TriangleFan:
|
||||
pIBO->FansToStrips(Indices.data(), Indices.size());
|
||||
break;
|
||||
case eGX_Quads:
|
||||
pIBO->QuadsToStrips(Indices.data(), Indices.size());
|
||||
break;
|
||||
default:
|
||||
pIBO->AddIndices(Indices.data(), Indices.size());
|
||||
pIBO->AddIndex(0xFFFF); // primitive restart
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the number of submesh offset vectors matches the number of IBOs, then add the offsets
|
||||
while (mIBOs.size() > mSubmeshEndOffsets.size())
|
||||
mSubmeshEndOffsets.emplace_back(std::vector<u32>(mSurfaces.size()));
|
||||
|
||||
for (u32 iIBO = 0; iIBO < mIBOs.size(); iIBO++)
|
||||
mSubmeshEndOffsets[iIBO][iSurf] = mIBOs[iIBO].GetSize();
|
||||
}
|
||||
|
||||
mVBO.Buffer();
|
||||
|
||||
for (u32 iIBO = 0; iIBO < mIBOs.size(); iIBO++)
|
||||
mIBOs[iIBO].Buffer();
|
||||
|
||||
mBuffered = true;
|
||||
}
|
||||
|
||||
void CStaticModel::ClearGLBuffer()
|
||||
{
|
||||
mVBO.Clear();
|
||||
mIBOs.clear();
|
||||
mSubmeshEndOffsets.clear();
|
||||
mBuffered = false;
|
||||
}
|
||||
|
||||
void CStaticModel::Draw(ERenderOptions Options)
|
||||
{
|
||||
if (!mBuffered) BufferGL();
|
||||
|
||||
if ((Options & eNoMaterialSetup) == 0) mpMaterial->SetCurrent(Options);
|
||||
|
||||
// Draw IBOs
|
||||
mVBO.Bind();
|
||||
|
||||
for (u32 iIBO = 0; iIBO < mIBOs.size(); iIBO++)
|
||||
{
|
||||
CIndexBuffer *pIBO = &mIBOs[iIBO];
|
||||
pIBO->Bind();
|
||||
glDrawElements(pIBO->GetPrimitiveType(), pIBO->GetSize(), GL_UNSIGNED_SHORT, (void*) 0);
|
||||
pIBO->Unbind();
|
||||
gDrawCount++;
|
||||
}
|
||||
|
||||
mVBO.Unbind();
|
||||
}
|
||||
|
||||
void CStaticModel::DrawSurface(ERenderOptions Options, u32 Surface)
|
||||
{
|
||||
if (!mBuffered) BufferGL();
|
||||
|
||||
mVBO.Bind();
|
||||
if ((Options & eNoMaterialSetup) == 0) mpMaterial->SetCurrent(Options);
|
||||
|
||||
for (u32 iIBO = 0; iIBO < mIBOs.size(); iIBO++)
|
||||
{
|
||||
// Since there is a shared IBO for every mesh, we need two things to draw a single one: an offset and a size
|
||||
u32 Offset = 0;
|
||||
if (Surface > 0) Offset = mSubmeshEndOffsets[iIBO][Surface - 1];
|
||||
u32 Size = mSubmeshEndOffsets[iIBO][Surface] - Offset;
|
||||
|
||||
if (!Size) continue; // The chosen submesh doesn't use this IBO
|
||||
|
||||
// Now we have both, so we can draw
|
||||
mIBOs[iIBO].DrawElements(Offset, Size);
|
||||
gDrawCount++;
|
||||
}
|
||||
|
||||
mVBO.Unbind();
|
||||
}
|
||||
|
||||
CMaterial* CStaticModel::GetMaterial()
|
||||
{
|
||||
return mpMaterial;
|
||||
}
|
||||
|
||||
void CStaticModel::SetMaterial(CMaterial *pMat)
|
||||
{
|
||||
mpMaterial = pMat;
|
||||
mTransparent = ((pMat->Options() & CMaterial::eTransparent) != 0);
|
||||
}
|
||||
|
||||
bool CStaticModel::IsTransparent()
|
||||
{
|
||||
return mTransparent;
|
||||
}
|
||||
|
||||
bool CStaticModel::IsOccluder()
|
||||
{
|
||||
return ((mpMaterial->Options() & CMaterial::eOccluder) != 0);
|
||||
}
|
||||
|
||||
CIndexBuffer* CStaticModel::InternalGetIBO(EGXPrimitiveType Primitive)
|
||||
{
|
||||
GLenum type = GXPrimToGLPrim(Primitive);
|
||||
|
||||
for (u32 iIBO = 0; iIBO < mIBOs.size(); iIBO++)
|
||||
{
|
||||
if (mIBOs[iIBO].GetPrimitiveType() == type)
|
||||
return &mIBOs[iIBO];
|
||||
}
|
||||
|
||||
mIBOs.emplace_back(CIndexBuffer(type));
|
||||
return &mIBOs.back();
|
||||
}
|
||||
39
Resource/model/CStaticModel.h
Normal file
39
Resource/model/CStaticModel.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef CSTATICMODEL_H
|
||||
#define CSTATICMODEL_H
|
||||
|
||||
#include "CBasicModel.h"
|
||||
#include <Core/ERenderOptions.h>
|
||||
#include <OpenGL/CIndexBuffer.h>
|
||||
|
||||
// A CStaticModel is meant for meshes that don't move. It's built specifically with terrain in mind.
|
||||
// It only links to one material, and what it does best is combining submeshes from different models
|
||||
// into shared VBOs and IBOs. This allows for a significantly reduced number of draw calls.
|
||||
|
||||
class CStaticModel : public CBasicModel
|
||||
{
|
||||
CMaterial *mpMaterial;
|
||||
std::vector<CIndexBuffer> mIBOs;
|
||||
std::vector<std::vector<u32>> mSubmeshEndOffsets;
|
||||
bool mTransparent;
|
||||
|
||||
public:
|
||||
CStaticModel();
|
||||
CStaticModel(CMaterial *pMat);
|
||||
~CStaticModel();
|
||||
void AddSurface(SSurface *pSurface);
|
||||
|
||||
void BufferGL();
|
||||
void ClearGLBuffer();
|
||||
void Draw(ERenderOptions Options);
|
||||
void DrawSurface(ERenderOptions Options, u32 Surface);
|
||||
|
||||
CMaterial* GetMaterial();
|
||||
void SetMaterial(CMaterial *pMat);
|
||||
bool IsTransparent();
|
||||
bool IsOccluder();
|
||||
|
||||
private:
|
||||
CIndexBuffer* InternalGetIBO(EGXPrimitiveType Primitive);
|
||||
};
|
||||
|
||||
#endif // CSTATICMODEL_H
|
||||
42
Resource/model/CVertex.h
Normal file
42
Resource/model/CVertex.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef CVERTEX_H
|
||||
#define CVERTEX_H
|
||||
|
||||
#include <Common/CVector2f.h>
|
||||
#include <Common/CVector3f.h>
|
||||
#include <Common/CColor.h>
|
||||
|
||||
class CVertex
|
||||
{
|
||||
public:
|
||||
u32 ArrayPosition; // Position of this vertex in the input model file.
|
||||
// This is needed to resave without breaking rigging.
|
||||
CVector3f Position;
|
||||
CVector3f Normal;
|
||||
CColor Color[2];
|
||||
CVector2f Tex[8];
|
||||
u8 MatrixIndices[8];
|
||||
|
||||
CVertex() {}
|
||||
|
||||
CVertex(CVector3f& Pos)
|
||||
{
|
||||
Position = Pos;
|
||||
}
|
||||
|
||||
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]));
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CVERTEX_H
|
||||
33
Resource/model/EVertexDescription.h
Normal file
33
Resource/model/EVertexDescription.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef EVERTEXDESCRIPTION
|
||||
#define EVERTEXDESCRIPTION
|
||||
|
||||
#include <Common/EnumUtil.h>
|
||||
|
||||
enum EVertexDescription
|
||||
{
|
||||
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
|
||||
};
|
||||
DEFINE_ENUM_FLAGS(EVertexDescription)
|
||||
|
||||
#endif // EVERTEXDESCRIPTION
|
||||
|
||||
13
Resource/model/SModelData.h
Normal file
13
Resource/model/SModelData.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef SMODELDATA_H
|
||||
#define SMODELDATA_H
|
||||
|
||||
#include "SSurface.h"
|
||||
#include <Common/CAABox.h>
|
||||
|
||||
struct SModelData
|
||||
{
|
||||
CAABox mAABox;
|
||||
std::vector<SSurface*> mSurfaces;
|
||||
};
|
||||
|
||||
#endif // SMODELDATA_H
|
||||
89
Resource/model/SSurface.cpp
Normal file
89
Resource/model/SSurface.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "SSurface.h"
|
||||
#include <Common/CRayCollisionTester.h>
|
||||
#include <Common/Math.h>
|
||||
#include <Core/CDrawUtil.h>
|
||||
|
||||
std::pair<bool,float> SSurface::IntersectsRay(const CRay& Ray, const CTransform4f& Transform)
|
||||
{
|
||||
//CDrawUtil::DrawWireCube(AABox.Transformed(Transform), CColor::skRed);
|
||||
bool Hit = false;
|
||||
float HitDist;
|
||||
|
||||
for (u32 iPrim = 0; iPrim < Primitives.size(); iPrim++)
|
||||
{
|
||||
SPrimitive *pPrim = &Primitives[iPrim];
|
||||
u32 NumVerts = pPrim->Vertices.size();
|
||||
|
||||
if ((pPrim->Type == eGX_Triangles) || (pPrim->Type == eGX_TriangleFan) || (pPrim->Type == eGX_TriangleStrip))
|
||||
{
|
||||
u32 NumTris;
|
||||
|
||||
if (pPrim->Type == eGX_Triangles)
|
||||
NumTris = NumVerts / 3;
|
||||
else
|
||||
NumTris = NumVerts - 2;
|
||||
|
||||
CColor LineColor;
|
||||
if (pPrim->Type == eGX_Triangles)
|
||||
LineColor = CColor::skRed;
|
||||
else if (pPrim->Type == eGX_TriangleStrip)
|
||||
LineColor = CColor::skYellow;
|
||||
else if (pPrim->Type == eGX_TriangleFan)
|
||||
LineColor = CColor::skGreen;
|
||||
|
||||
for (u32 iTri = 0; iTri < NumTris; iTri++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
else if (pPrim->Type == eGX_TriangleFan)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
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);
|
||||
|
||||
if (TriResult.first)
|
||||
{
|
||||
if ((!Hit) || (TriResult.second < HitDist))
|
||||
{
|
||||
Hit = true;
|
||||
HitDist = TriResult.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo: Intersection tests for line primitives
|
||||
}
|
||||
|
||||
return std::pair<bool,float>(Hit, HitDist);
|
||||
}
|
||||
39
Resource/model/SSurface.h
Normal file
39
Resource/model/SSurface.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef SSURFACE_H
|
||||
#define SSURFACE_H
|
||||
|
||||
#include "../CMaterialSet.h"
|
||||
#include "CVertex.h"
|
||||
#include <Common/types.h>
|
||||
#include <Common/CAABox.h>
|
||||
#include <Common/CRay.h>
|
||||
#include <Common/CTransform4f.h>
|
||||
#include <Common/CVector3f.h>
|
||||
#include <Common/SRayIntersection.h>
|
||||
#include <OpenGL/GLCommon.h>
|
||||
#include <vector>
|
||||
|
||||
struct SSurface
|
||||
{
|
||||
u32 VertexCount;
|
||||
u32 TriangleCount;
|
||||
CAABox AABox;
|
||||
CVector3f CenterPoint;
|
||||
u32 MaterialID;
|
||||
CVector3f ReflectionDirection;
|
||||
|
||||
struct SPrimitive
|
||||
{
|
||||
EGXPrimitiveType Type;
|
||||
std::vector<CVertex> Vertices;
|
||||
};
|
||||
std::vector<SPrimitive> Primitives;
|
||||
|
||||
SSurface() {
|
||||
VertexCount = 0;
|
||||
TriangleCount = 0;
|
||||
}
|
||||
|
||||
std::pair<bool,float> IntersectsRay(const CRay& Ray, const CTransform4f& Transform = CTransform4f::skIdentity);
|
||||
};
|
||||
|
||||
#endif // SSURFACE_H
|
||||
Reference in New Issue
Block a user