git mv Code\Sandbox\Editor Code/Editor
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "OCMExporter.h"
|
||||
|
||||
|
||||
class CFileEndianWriter
|
||||
{
|
||||
std::vector<uint8> m_Data;
|
||||
size_t m_Offset;
|
||||
public:
|
||||
CFileEndianWriter()
|
||||
: m_Offset(0){}
|
||||
void Seek(size_t Offset){m_Offset = Offset; }
|
||||
void Write(const void* pData, size_t Size)
|
||||
{
|
||||
if (m_Offset + Size > m_Data.size())
|
||||
{
|
||||
m_Data.resize(m_Offset + Size);
|
||||
}
|
||||
memcpy(&m_Data[m_Offset], pData, Size);
|
||||
m_Offset += Size;
|
||||
}
|
||||
size_t Pos() const{return m_Offset; }
|
||||
template<size_t Padding>
|
||||
void Align(){m_Offset = (m_Offset + (Padding - 1)) & ~(Padding - 1); }
|
||||
template<class T>
|
||||
void Write(T D){Write(&D, sizeof(T)); }
|
||||
|
||||
|
||||
const std::vector<uint8>& Data() const{return m_Data; }
|
||||
};
|
||||
|
||||
const char* COCMExporter::GetExtension() const
|
||||
{
|
||||
return "ocm";
|
||||
}
|
||||
|
||||
const char* COCMExporter::GetShortDescription() const
|
||||
{
|
||||
return "occlusion culler mesh";
|
||||
}
|
||||
|
||||
Matrix44 MatRotate(f32 a, f32 b, f32 g)
|
||||
{
|
||||
const f32 CosR = cosf(a);
|
||||
const f32 SinR = sinf(a);
|
||||
const f32 CosP = cosf(b);
|
||||
const f32 SinP = sinf(b);
|
||||
const f32 CosY = cosf(g);
|
||||
const f32 SinY = sinf(g);
|
||||
const f32 SRSP = SinR * SinP;
|
||||
const f32 CRSP = CosR * SinP;
|
||||
|
||||
Matrix44 Mat;
|
||||
Mat.m00 = CosP * CosY;
|
||||
Mat.m01 = CosP * SinY;
|
||||
Mat.m02 = -SinP;
|
||||
Mat.m03 = 0.f;
|
||||
Mat.m10 = SRSP * CosY - CosR * SinY;
|
||||
Mat.m11 = SRSP * SinY + CosR * CosY;
|
||||
Mat.m12 = SinR * CosP;
|
||||
Mat.m13 = 0.f;
|
||||
Mat.m20 = CRSP * CosY + SinR * SinY;
|
||||
Mat.m21 = CRSP * SinY - SinR * CosY;
|
||||
Mat.m22 = CosR * CosP;
|
||||
Mat.m23 = 0.f;
|
||||
Mat.m30 = 0.f;
|
||||
Mat.m31 = 0.f;
|
||||
Mat.m32 = 0.f;
|
||||
Mat.m33 = 1.f;
|
||||
return Mat;
|
||||
};
|
||||
|
||||
void COCMExporter::Extends(const Matrix44& rTransform, const Export::Object* pMesh, f32& rMinX, f32& rMaxX, f32& rMinY, f32& rMaxY, f32& rMinZ, f32& rMaxZ) const
|
||||
{
|
||||
rMinX = rMinY = rMinZ = FLT_MAX;
|
||||
rMaxX = rMaxY = rMaxZ = -FLT_MAX;
|
||||
const uint32 TriCount = pMesh->GetVertexCount();
|
||||
const Export::Vector3D* pVerts = pMesh->GetVertexBuffer();
|
||||
for (size_t a = 0; a < TriCount; a++)
|
||||
{
|
||||
const Export::Vector3D& rV = pVerts[a];
|
||||
const Vec3 VO(rV.x, rV.y, rV.z);
|
||||
const Vec3 V = rTransform.TransformPoint(VO);
|
||||
rMinX = std::min(rMinX, V.x);
|
||||
rMinY = std::min(rMinY, V.y);
|
||||
rMinZ = std::min(rMinZ, V.z);
|
||||
rMaxX = std::max(rMaxX, V.x);
|
||||
rMaxY = std::max(rMaxY, V.y);
|
||||
rMaxZ = std::max(rMaxZ, V.z);
|
||||
}
|
||||
}
|
||||
|
||||
Matrix44 COCMExporter::CalcOBB(const Export::Object* pMesh)
|
||||
{
|
||||
Matrix44 OBBMat(IDENTITY);
|
||||
f32 MinX, MaxX, MinY, MaxY, MinZ, MaxZ;
|
||||
Extends(OBBMat, pMesh, MinX, MaxX, MinY, MaxY, MinZ, MaxZ);
|
||||
|
||||
OBBMat.m03 = -(MaxX + MinX) * 0.5f;
|
||||
OBBMat.m13 = -(MaxY + MinY) * 0.5f;
|
||||
OBBMat.m23 = -(MaxZ + MinZ) * 0.5f;
|
||||
|
||||
return OBBMat;
|
||||
}
|
||||
|
||||
size_t COCMExporter::SaveMesh(CFileEndianWriter& rWriter, const Export::Object* pMesh, Matrix44& rOBBMat)
|
||||
{
|
||||
const size_t PosStart = rWriter.Pos();
|
||||
rOBBMat = CalcOBB(pMesh);
|
||||
const Export::Vector3D* pVerts = pMesh->GetVertexBuffer();
|
||||
std::vector<float> Pos;
|
||||
const uint32 SubMeshCount = pMesh->GetMeshCount();
|
||||
for (uint32 b = 0; b < SubMeshCount; b++)
|
||||
{
|
||||
const Export::Mesh* pSubMesh = pMesh->GetMesh(b);
|
||||
const uint32 FaceCount = pSubMesh->GetFaceCount();
|
||||
const Export::Face* pFaces = pSubMesh->GetFaceBuffer();
|
||||
Pos.reserve(Pos.size() + FaceCount * 9);
|
||||
for (size_t a = 0; a < FaceCount; a++)
|
||||
{
|
||||
const Export::Vector3D& rV0 = pVerts[pFaces[a].idx[0]];
|
||||
const Export::Vector3D& rV1 = pVerts[pFaces[a].idx[1]];
|
||||
const Export::Vector3D& rV2 = pVerts[pFaces[a].idx[2]];
|
||||
const Vec3 VO0(rV0.x, rV0.y, rV0.z);
|
||||
const Vec3 VO1(rV1.x, rV1.y, rV1.z);
|
||||
const Vec3 VO2(rV2.x, rV2.y, rV2.z);
|
||||
const Vec3 V0 = rOBBMat.TransformPoint(VO0);
|
||||
const Vec3 V1 = rOBBMat.TransformPoint(VO1);
|
||||
const Vec3 V2 = rOBBMat.TransformPoint(VO2);
|
||||
const Vec3 N = (V2 - V0).cross(V1 - V0);
|
||||
if (fabsf(N.dot(N)) <= FLT_EPSILON)//degenerated?
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Pos.push_back(V0.x);
|
||||
Pos.push_back(V0.y);
|
||||
Pos.push_back(V0.z);
|
||||
Pos.push_back(1.f);
|
||||
Pos.push_back(V1.x);
|
||||
Pos.push_back(V1.y);
|
||||
Pos.push_back(V1.z);
|
||||
Pos.push_back(1.f);
|
||||
Pos.push_back(V2.x);
|
||||
Pos.push_back(V2.y);
|
||||
Pos.push_back(V2.z);
|
||||
Pos.push_back(1.f);
|
||||
}
|
||||
}
|
||||
const uint32 TriCount = static_cast<uint16>(std::min<size_t>(65535, Pos.size() / 4));//vertex count at 4float/vertex
|
||||
rWriter.Write(TriCount);
|
||||
rWriter.Align<16>();
|
||||
rWriter.Write(&Pos[0], 4 * TriCount * sizeof(float));
|
||||
rWriter.Align<4>();
|
||||
const size_t PosEnd = rWriter.Pos();
|
||||
return PosEnd - PosStart;//sizeof(TriCount)+sizeof(Pos[0])*Pos.size();
|
||||
}
|
||||
|
||||
void COCMExporter::SaveInstance(CFileEndianWriter& rWriter, const Export::Object* pInstance, const SOCMeshInfo& rMeshInfo)
|
||||
{
|
||||
Vec3 pos(pInstance->pos.x, pInstance->pos.y, pInstance->pos.z);
|
||||
Quat rot(pInstance->rot.w, pInstance->rot.v.x, pInstance->rot.v.y, pInstance->rot.v.z);
|
||||
Vec3 scale(pInstance->scale.x, pInstance->scale.y, pInstance->scale.z);
|
||||
|
||||
Matrix44 tm = Matrix33::CreateScale(scale) * Matrix34(rot);
|
||||
tm.SetTranslation(pos);
|
||||
|
||||
tm = tm * rMeshInfo.m_OBBMat.GetInverted();
|
||||
|
||||
//const uint32 MeshID = pInstance->MeshToUse()->ID();
|
||||
rWriter.Write(rMeshInfo.m_Offset);
|
||||
for (size_t a = 0; a < 12; a++)//just savin the 3x4 matrix
|
||||
{
|
||||
rWriter.Write(*(reinterpret_cast<float*>(&tm) + a));
|
||||
}
|
||||
}
|
||||
|
||||
bool COCMExporter::ExportToFile(const char* filename, const Export::IData* pExportData)
|
||||
{
|
||||
CLogFile::FormatLine("Exporting OCM file to '%s'", filename);
|
||||
|
||||
FILE* pFile = nullptr;
|
||||
azfopen(&pFile, filename, "wb");
|
||||
if (!pFile)
|
||||
{
|
||||
CLogFile::FormatLine("Error while opening file '%s'!", filename);
|
||||
assert(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
CFileEndianWriter Writer;
|
||||
// Write header
|
||||
const uint32 Version = ~(4u << 24);
|
||||
const uint32 MeshCount = pExportData->GetObjectCount();
|
||||
const uint32 InstCount = pExportData->GetObjectCount();
|
||||
uint32 OffsetInstances = 0;
|
||||
Writer.Write(Version);
|
||||
Writer.Write(MeshCount);
|
||||
Writer.Write(InstCount);
|
||||
Writer.Write(OffsetInstances);//keep header end aligned to 16byte
|
||||
|
||||
tdMeshOffset MeshOffsets;
|
||||
MeshOffsets.reserve(MeshCount);
|
||||
size_t Offset = 16;
|
||||
//std::map<void*,size_t> MeshO
|
||||
for (size_t a = 0; a < MeshCount; a++)
|
||||
{
|
||||
SOCMeshInfo MeshInfo;
|
||||
MeshInfo.m_MeshHash = pExportData->GetObject(a)->MeshHash();
|
||||
const tdMeshOffset::iterator it = std::find(MeshOffsets.begin(), MeshOffsets.end(), MeshInfo);
|
||||
if (it != MeshOffsets.end())
|
||||
{
|
||||
MeshInfo = *it;
|
||||
}
|
||||
else
|
||||
{
|
||||
MeshInfo.m_Offset = Offset;
|
||||
Offset += SaveMesh(Writer, pExportData->GetObject(a), MeshInfo.m_OBBMat);
|
||||
}
|
||||
MeshOffsets.push_back(MeshInfo);
|
||||
}
|
||||
OffsetInstances = Offset;
|
||||
for (size_t a = 0; a < InstCount; a++)
|
||||
{
|
||||
SaveInstance(Writer, pExportData->GetObject(a), MeshOffsets[a]);
|
||||
}
|
||||
Writer.Seek(4);
|
||||
Writer.Write(static_cast<uint32>(MeshOffsets.size()));
|
||||
Writer.Seek(12);
|
||||
Writer.Write(OffsetInstances);
|
||||
|
||||
fwrite(&Writer.Data()[0], 1, Writer.Data().size(), pFile);
|
||||
|
||||
fclose(pFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* COCMExporter::TrimFloat(float fValue) const
|
||||
{
|
||||
// Convert a float into a string representation and remove all
|
||||
// unnecessary zeros and the decimal dot if it is not needed
|
||||
const int nMaxAccessInTime = 4;
|
||||
|
||||
static char ppBufs[nMaxAccessInTime][16];
|
||||
static int nCurBuf = 0;
|
||||
|
||||
if (nCurBuf >= nMaxAccessInTime)
|
||||
{
|
||||
nCurBuf = 0;
|
||||
}
|
||||
|
||||
char* pBuf = ppBufs[nCurBuf];
|
||||
size_t bufSize = sizeof(ppBufs[nCurBuf]);
|
||||
++nCurBuf;
|
||||
sprintf_s(pBuf, bufSize, "%f", fValue);
|
||||
|
||||
for (int i = strlen(pBuf) - 1; i > 0; --i)
|
||||
{
|
||||
if (pBuf[i] == '0')
|
||||
{
|
||||
pBuf[i] = 0;
|
||||
}
|
||||
else if (pBuf[i] == '.')
|
||||
{
|
||||
pBuf[i] = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pBuf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void COCMExporter::Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
Reference in New Issue
Block a user