You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Tools/RC/ResourceCompilerPC/RenderMeshBuilder.h

258 lines
9.0 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// This is the class that makes a renderable (stripified) vertex/index buffers
// and tangent bases out of a CGF mesh
#ifndef CRYINCLUDE_TOOLS_RC_RESOURCECOMPILERPC_RENDERMESHBUILDER_H
#define CRYINCLUDE_TOOLS_RC_RESOURCECOMPILERPC_RENDERMESHBUILDER_H
#pragma once
#include "CryChunkedFile.h"
#include "TangentSpaceCalculation.h"
#include "CryCompiledFile.h"
// Calculates tangent spaces
// Builds index buffer (stripifies), material group array, ext-to-int map.
class CRenderMeshBuilder
{
public:
// constructs everything for the render mesh out of the given mesh
void build (const CryChunkedFile::MeshDesc* pMeshDesc);
// increases all indices of materials by the given offset
void addMaterialOffset (unsigned nOffset);
// cleans up the object
void clear();
// this error class is thrown from the constructor when the object can't be constructed
class Error
{
public:
Error(const char* szDesc)
: m_szDesc(szDesc){}
const char* c_str() const{return m_szDesc; }
protected:
const char* m_szDesc;
};
// returns the number of vertices in the resulting vertex buffer
unsigned numVertices() const;
// face/vertex index type
typedef unsigned short ushort;
// this is the index buffer (external indexation)
std::vector<ushort> m_arrIndices;
// this array represents the groups of indices in the index buffer:
// each group has its own material id and number of elements (indices, i.e. number of faces * 3 in case of strip stripification)
typedef CCFMaterialGroup MaterialGroup;
typedef std::vector<MaterialGroup> MaterialGroupArray;
MaterialGroupArray m_arrPrimGroups;
// this is the mapping from new indices to original
std::vector<ushort> m_arrExtTangMap;
// this is the mapping from new indices to original UV indices
// in the original CGF, texture and geometric mesh (faces/tex faces) are
// different (tex face indices are not necessarily the same as face indices),
// this is why the ExtToInt map doesn't coincide with this ExtUVMap
std::vector<ushort> m_arrExtUVMap;
// these are the tangent bases (external indexation)
std::vector<TangData> m_arrExtTangents;
#pragma pack(push,2)
// this is a group of faces, as they will be inside a group (material)
struct Face
{
ushort v[3];
Face(){}
Face(ushort v0, ushort v1, ushort v2)
{
v[0] = v0;
v[1] = v1;
v[2] = v2;
}
Face (const CryFace& rFace)
{
v[0] = rFace.v0;
v[1] = rFace.v1;
v[2] = rFace.v2;
}
Face (DWORD src[3])
{
v[0] = (ushort)src[0];
v[1] = (ushort)src[1];
v[2] = (ushort)src[2];
}
bool isDegenerate() const
{
return v[0] == v[1] || v[1] == v[2] || v[2] == v[0];
}
};
#pragma pack(pop)
// WARNING: this array must be binary-compatible with the array of unsigned shorts
// passed to Nvidia Stripifier. external indexation
typedef std::vector<Face> FaceArray;
// this is the array of faces for each material
std::vector<FaceArray> m_arrMtlFaces;
// this is the actual array of faces, but in the final external indexation
std::vector<CryFace> m_arrExtFaces;
protected:
// adjusts the base - converts from Martin's algorithm's requirements to the engine requirements
static void AdjustBase(TangData& rBase);
// creates the mapping from the external to internal indices
void buildExtToIntMaps();
// create m_arrMtlFaces; the degenerated faces are not included
void buildMtlFaces();
// create the indices and the array m_arrMaterials out of m_arrMtlFaces
void buildIndexBuffer();
// remaps (transposes, permutates) the indices to improve spatial locality of the vertex buffer
void remapIndicesForVBCache();
// remaps external indices according to the given permutation old->new
void remapExtIndices (unsigned* pPermutation, unsigned numNewTargets);
// prepares the m_arrExtTangents, m_arrExtToTBBMap, m_arrExtTangMap and m_arrExtUVMap
void prepareExtToIntMapping();
// adds an entry to all required maps - m_arrExtTangents, m_arrExtToTBBMap, m_arrExtTangMap and m_arrExtUVMap
bool addExtToIntMapEntry (DWORD FaceExt[3], const CryFace&FaceInt, const CryTexFace &TexFaceInt);
protected:
// add the primitive group(s) and indices (m_arrPrimGroups and m_arrIndices)
// from the given primitives generated by Nvidia Stripifier
void appendNvidiaStrip (const struct PrimitiveGroup& Group, unsigned nMaterial);
void selfValidate();
protected:
const CryChunkedFile::MeshDesc* m_pMeshDesc;
struct VertexUVPair
{
VertexUVPair(){}
VertexUVPair(ushort _nVertex, ushort _nTexVertex, ushort _nExtTangent)
: nVertex(_nVertex)
, nTexVertex (_nTexVertex)
, nExtTangent(_nExtTangent){}
bool operator < (const VertexUVPair& right) const
{
return
nVertex < right.nVertex ? true:
nVertex > right.nVertex ? false :
nTexVertex < right.nTexVertex? true:
nTexVertex > right.nTexVertex ? false :
nExtTangent < right.nExtTangent;
}
ushort nVertex; // vertex in internal indexation
ushort nTexVertex; // texture vertex (UV) in internal indexation
ushort nExtTangent; // vertex in TBB indexation, or tangent in the array of tangents generated by TBB
};
// this is the map from the vertex-uv pair to the index of the
// temporary vertex mapping in this->arrVertMap;
typedef std::map <VertexUVPair, ushort> VertexUVPairMap;
//////////////////////////////////////////////////////////////////////////
// a proxy structure that gets passed to the tangent space calculation algorithm
struct MeshProxy
{
public:
MeshProxy ()
{
m_pMeshDesc = NULL;
}
// creates temporary mapping for splitting the vertices
// with different UVs
void init (const CryChunkedFile::MeshDesc* pMeshDesc)
{
m_pMeshDesc = pMeshDesc;
Matrix34 tm;
const float* pMat = &m_pMeshDesc->pNode->pDesc->tm[0][0];
tm.SetFromVectors(
Vec3(pMat[ 0], pMat[ 1], pMat[ 2]),
Vec3(pMat[ 4], pMat[ 5], pMat[ 6]),
Vec3(pMat[ 8], pMat[ 9], pMat[10]),
Vec3(pMat[12], pMat[13], pMat[14]));
m_tm = tm;
}
DWORD GetTriangleCount(void) const
{
return m_pMeshDesc->numFaces();
}
void GetTriangleIndices(const DWORD indwTriNo, DWORD outdwPos[3], DWORD outdwNorm[3], DWORD outdwUV[3]) const
{
const CryFace& rFace = m_pMeshDesc->pFaces[indwTriNo];
outdwNorm[0] = outdwPos[0] = rFace.v0;
outdwNorm[1] = outdwPos[1] = rFace.v1;
outdwNorm[2] = outdwPos[2] = rFace.v2;
if (m_pMeshDesc->numTexFaces())
{
const CryTexFace& rTexFace = m_pMeshDesc->pTexFaces[indwTriNo];
outdwUV[0] = rTexFace.t0;
outdwUV[1] = rTexFace.t1;
outdwUV[2] = rTexFace.t2;
}
else
{
outdwUV[0] = outdwUV[1] = outdwUV[2] = 0;
}
}
void GetPos(const DWORD indwPos, float outfPos[3]) const;
void GetUV (const DWORD indwPos, float outfUV[2]) const
{
const CryUV& uv = m_pMeshDesc->pUVs[indwPos];
outfUV[0] = uv.u;
outfUV[1] = uv.v;
}
std::vector<VertexUVPair> arrVertMap;
protected:
const CryChunkedFile::MeshDesc* m_pMeshDesc;
Matrix34 m_tm;
};
CTangentSpaceCalculation<MeshProxy> m_TangBaseBuilder;
// this mapping gives the ext->tang ext mapping, i.e.
// maps from the final external indexation (that's found in
// m_arrExtTangMap, m_arrExtUVMap, m_arrExtTangents)
// to the tangent base indexation in m_TangBaseBuilder
// (GetBaseCount, GetTriangleBaseIndices, GetBase)
std::vector<ushort> m_arrExtToTBBMap;
// this is used during construction of the external maps to quickly find
// corresponding vertex-uv pairs and avoid collisions
// the vertex-uv indices are in internal indexations of vertices and UVs
VertexUVPairMap m_mapVUVP;
};
#endif // CRYINCLUDE_TOOLS_RC_RESOURCECOMPILERPC_RENDERMESHBUILDER_H