123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682 |
- #pragma once
- #include <Mathematics/Logger.h>
- #include <Mathematics/Matrix.h>
- #include <Mathematics/IndexAttribute.h>
- #include <Mathematics/VertexAttribute.h>
- #include <Mathematics/Vector2.h>
- #include <Mathematics/Vector3.h>
- namespace WwiseGTE
- {
- enum class MeshTopology
- {
- ARBITRARY,
- RECTANGLE,
- CYLINDER,
- TORUS,
- DISK,
- SPHERE
- };
- class MeshDescription
- {
- public:
-
-
-
-
- MeshDescription(uint32_t inNumVertices, uint32_t inNumTriangles)
- :
- topology(MeshTopology::ARBITRARY),
- numVertices(inNumVertices),
- numTriangles(inNumTriangles),
- wantDynamicTangentSpaceUpdate(false),
- wantCCW(true),
- hasTangentSpaceVectors(false),
- allowUpdateFrame(false),
- numRows(0),
- numCols(0),
- rMax(0),
- cMax(0),
- rIncrement(0),
- constructed(false)
- {
- LogAssert(numVertices >= 3 && numTriangles >= 1, "Invalid input.");
- }
-
-
-
-
-
-
-
-
-
- MeshDescription(MeshTopology inTopology, uint32_t inNumRows, uint32_t inNumCols)
- :
- topology(inTopology),
- wantDynamicTangentSpaceUpdate(false),
- wantCCW(true),
- hasTangentSpaceVectors(false),
- allowUpdateFrame(false),
- constructed(false)
- {
- switch (topology)
- {
- case MeshTopology::ARBITRARY:
- numVertices = inNumRows;
- numTriangles = inNumCols;
- numRows = 0;
- numCols = 0;
- rMax = 0;
- cMax = 0;
- rIncrement = 0;
- break;
- case MeshTopology::RECTANGLE:
- numRows = std::max(inNumRows, 2u);
- numCols = std::max(inNumCols, 2u);
- rMax = numRows - 1;
- cMax = numCols - 1;
- rIncrement = numCols;
- numVertices = (rMax + 1) * (cMax + 1);
- numTriangles = 2 * rMax * cMax;
- break;
- case MeshTopology::CYLINDER:
- numRows = std::max(inNumRows, 2u);
- numCols = std::max(inNumCols, 3u);
- rMax = numRows - 1;
- cMax = numCols;
- rIncrement = numCols + 1;
- numVertices = (rMax + 1) * (cMax + 1);
- numTriangles = 2 * rMax * cMax;
- break;
- case MeshTopology::TORUS:
- numRows = std::max(inNumRows, 2u);
- numCols = std::max(inNumCols, 3u);
- rMax = numRows;
- cMax = numCols;
- rIncrement = numCols + 1;
- numVertices = (rMax + 1) * (cMax + 1);
- numTriangles = 2 * rMax * cMax;
- break;
- case MeshTopology::DISK:
- numRows = std::max(inNumRows, 1u);
- numCols = std::max(inNumCols, 3u);
- rMax = numRows - 1;
- cMax = numCols;
- rIncrement = numCols + 1;
- numVertices = (rMax + 1) * (cMax + 1) + 1;
- numTriangles = 2 * rMax * cMax + numCols;
- break;
- case MeshTopology::SPHERE:
- numRows = std::max(inNumRows, 1u);
- numCols = std::max(inNumCols, 3u);
- rMax = numRows - 1;
- cMax = numCols;
- rIncrement = numCols + 1;
- numVertices = (rMax + 1) * (cMax + 1) + 2;
- numTriangles = 2 * rMax * cMax + 2 * numCols;
- break;
- }
- }
- MeshTopology topology;
- uint32_t numVertices;
- uint32_t numTriangles;
- std::vector<VertexAttribute> vertexAttributes;
- IndexAttribute indexAttribute;
- bool wantDynamicTangentSpaceUpdate;
- bool wantCCW;
-
- bool hasTangentSpaceVectors;
- bool allowUpdateFrame;
- uint32_t numRows, numCols;
- uint32_t rMax, cMax, rIncrement;
-
-
-
- bool constructed;
- };
- template <typename Real>
- class Mesh
- {
- public:
-
-
-
-
-
- Mesh(MeshDescription const& description, std::vector<MeshTopology> const& validTopologies)
- :
- mDescription(description),
- mPositions(nullptr),
- mNormals(nullptr),
- mTangents(nullptr),
- mBitangents(nullptr),
- mDPDUs(nullptr),
- mDPDVs(nullptr),
- mTCoords(nullptr),
- mPositionStride(0),
- mNormalStride(0),
- mTangentStride(0),
- mBitangentStride(0),
- mDPDUStride(0),
- mDPDVStride(0),
- mTCoordStride(0)
- {
- mDescription.constructed = false;
- for (auto const& topology : validTopologies)
- {
- if (mDescription.topology == topology)
- {
- mDescription.constructed = true;
- break;
- }
- }
- LogAssert(mDescription.indexAttribute.source != nullptr,
- "The mesh needs triangles/indices in Mesh constructor.");
-
- mDescription.hasTangentSpaceVectors = false;
- mDescription.allowUpdateFrame = mDescription.wantDynamicTangentSpaceUpdate;
- for (auto const& attribute : mDescription.vertexAttributes)
- {
- if (attribute.source != nullptr && attribute.stride > 0)
- {
- if (attribute.semantic == "position")
- {
- mPositions = reinterpret_cast<Vector3<Real>*>(attribute.source);
- mPositionStride = attribute.stride;
- continue;
- }
- if (attribute.semantic == "normal")
- {
- mNormals = reinterpret_cast<Vector3<Real>*>(attribute.source);
- mNormalStride = attribute.stride;
- continue;
- }
- if (attribute.semantic == "tangent")
- {
- mTangents = reinterpret_cast<Vector3<Real>*>(attribute.source);
- mTangentStride = attribute.stride;
- mDescription.hasTangentSpaceVectors = true;
- continue;
- }
- if (attribute.semantic == "bitangent")
- {
- mBitangents = reinterpret_cast<Vector3<Real>*>(attribute.source);
- mBitangentStride = attribute.stride;
- mDescription.hasTangentSpaceVectors = true;
- continue;
- }
- if (attribute.semantic == "dpdu")
- {
- mDPDUs = reinterpret_cast<Vector3<Real>*>(attribute.source);
- mDPDUStride = attribute.stride;
- mDescription.hasTangentSpaceVectors = true;
- continue;
- }
- if (attribute.semantic == "dpdv")
- {
- mDPDVs = reinterpret_cast<Vector3<Real>*>(attribute.source);
- mDPDVStride = attribute.stride;
- mDescription.hasTangentSpaceVectors = true;
- continue;
- }
- if (attribute.semantic == "tcoord")
- {
- mTCoords = reinterpret_cast<Vector2<Real>*>(attribute.source);
- mTCoordStride = attribute.stride;
- continue;
- }
- }
- }
- LogAssert(mPositions != nullptr, "The mesh needs positions in Mesh constructor.");
-
-
-
-
-
-
-
- if (mDescription.allowUpdateFrame)
- {
- if (!mDescription.hasTangentSpaceVectors)
- {
- mDescription.allowUpdateFrame = false;
- }
- if (!mTCoords && !mNormals)
- {
- mDescription.allowUpdateFrame = false;
- }
- }
- if (mDescription.allowUpdateFrame)
- {
- mUTU.resize(mDescription.numVertices);
- mDTU.resize(mDescription.numVertices);
- }
- }
- virtual ~Mesh()
- {
- }
-
- Mesh(Mesh const&) = delete;
- Mesh& operator=(Mesh const&) = delete;
-
- inline MeshDescription const& GetDescription() const
- {
- return mDescription;
- }
-
-
-
- void Update()
- {
- LogAssert(mDescription.constructed, "The Mesh object failed the construction.");
- UpdatePositions();
- if (mDescription.allowUpdateFrame)
- {
- UpdateFrame();
- }
- else if (mNormals)
- {
- UpdateNormals();
- }
-
- }
- protected:
-
- inline Vector3<Real>& Position(uint32_t i)
- {
- char* positions = reinterpret_cast<char*>(mPositions);
- return *reinterpret_cast<Vector3<Real>*>(positions + i * mPositionStride);
- }
- inline Vector3<Real>& Normal(uint32_t i)
- {
- char* normals = reinterpret_cast<char*>(mNormals);
- return *reinterpret_cast<Vector3<Real>*>(normals + i * mNormalStride);
- }
- inline Vector3<Real>& Tangent(uint32_t i)
- {
- char* tangents = reinterpret_cast<char*>(mTangents);
- return *reinterpret_cast<Vector3<Real>*>(tangents + i * mTangentStride);
- }
- inline Vector3<Real>& Bitangent(uint32_t i)
- {
- char* bitangents = reinterpret_cast<char*>(mBitangents);
- return *reinterpret_cast<Vector3<Real>*>(bitangents + i * mBitangentStride);
- }
- inline Vector3<Real>& DPDU(uint32_t i)
- {
- char* dpdus = reinterpret_cast<char*>(mDPDUs);
- return *reinterpret_cast<Vector3<Real>*>(dpdus + i * mDPDUStride);
- }
- inline Vector3<Real>& DPDV(uint32_t i)
- {
- char* dpdvs = reinterpret_cast<char*>(mDPDVs);
- return *reinterpret_cast<Vector3<Real>*>(dpdvs + i * mDPDVStride);
- }
- inline Vector2<Real>& TCoord(uint32_t i)
- {
- char* tcoords = reinterpret_cast<char*>(mTCoords);
- return *reinterpret_cast<Vector2<Real>*>(tcoords + i * mTCoordStride);
- }
-
-
- void ComputeIndices()
- {
- uint32_t t = 0;
- for (uint32_t r = 0, i = 0; r < mDescription.rMax; ++r)
- {
- uint32_t v0 = i, v1 = v0 + 1;
- i += mDescription.rIncrement;
- uint32_t v2 = i, v3 = v2 + 1;
- for (uint32_t c = 0; c < mDescription.cMax; ++c, ++v0, ++v1, ++v2, ++v3)
- {
- if (mDescription.wantCCW)
- {
- mDescription.indexAttribute.SetTriangle(t++, v0, v1, v2);
- mDescription.indexAttribute.SetTriangle(t++, v1, v3, v2);
- }
- else
- {
- mDescription.indexAttribute.SetTriangle(t++, v0, v2, v1);
- mDescription.indexAttribute.SetTriangle(t++, v1, v2, v3);
- }
- }
- }
- if (mDescription.topology == MeshTopology::DISK)
- {
- uint32_t v0 = 0, v1 = 1, v2 = mDescription.numVertices - 1;
- for (unsigned int c = 0; c < mDescription.numCols; ++c, ++v0, ++v1)
- {
- if (mDescription.wantCCW)
- {
- mDescription.indexAttribute.SetTriangle(t++, v0, v2, v1);
- }
- else
- {
- mDescription.indexAttribute.SetTriangle(t++, v0, v1, v2);
- }
- }
- }
- else if (mDescription.topology == MeshTopology::SPHERE)
- {
- uint32_t v0 = 0, v1 = 1, v2 = mDescription.numVertices - 2;
- for (uint32_t c = 0; c < mDescription.numCols; ++c, ++v0, ++v1)
- {
- if (mDescription.wantCCW)
- {
- mDescription.indexAttribute.SetTriangle(t++, v0, v2, v1);
- }
- else
- {
- mDescription.indexAttribute.SetTriangle(t++, v0, v1, v2);
- }
- }
- v0 = (mDescription.numRows - 1) * mDescription.numCols;
- v1 = v0 + 1;
- v2 = mDescription.numVertices - 1;
- for (uint32_t c = 0; c < mDescription.numCols; ++c, ++v0, ++v1)
- {
- if (mDescription.wantCCW)
- {
- mDescription.indexAttribute.SetTriangle(t++, v0, v2, v1);
- }
- else
- {
- mDescription.indexAttribute.SetTriangle(t++, v0, v1, v2);
- }
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
-
- virtual void UpdatePositions()
- {
- }
- virtual void UpdateNormals()
- {
-
-
-
- Vector3<Real> zero{ (Real)0, (Real)0, (Real)0 };
- for (uint32_t i = 0; i < mDescription.numVertices; ++i)
- {
- Normal(i) = zero;
- }
-
- for (uint32_t t = 0; t < mDescription.numTriangles; ++t)
- {
-
- uint32_t v0, v1, v2;
- mDescription.indexAttribute.GetTriangle(t, v0, v1, v2);
- Vector3<Real> P0 = Position(v0);
- Vector3<Real> P1 = Position(v1);
- Vector3<Real> P2 = Position(v2);
-
- Vector3<Real> E1 = P1 - P0;
- Vector3<Real> E2 = P2 - P0;
-
-
- Vector3<Real> triangleNormal = Cross(E1, E2);
-
- Normal(v0) += triangleNormal;
- Normal(v1) += triangleNormal;
- Normal(v2) += triangleNormal;
- }
-
- for (uint32_t i = 0; i < mDescription.numVertices; ++i)
- {
- Normalize(Normal(i), true);
- }
- }
- virtual void UpdateFrame()
- {
- if (!mTCoords)
- {
-
-
-
- UpdateNormals();
- }
-
-
- Matrix<2, 2, Real> zero2x2;
- Matrix<3, 2, Real> zero3x2;
- std::fill(mUTU.begin(), mUTU.end(), zero2x2);
- std::fill(mDTU.begin(), mDTU.end(), zero3x2);
- for (uint32_t t = 0; t < mDescription.numTriangles; ++t)
- {
-
- uint32_t v0, v1, v2;
- mDescription.indexAttribute.GetTriangle(t, v0, v1, v2);
- Vector3<Real> P0 = Position(v0);
- Vector3<Real> P1 = Position(v1);
- Vector3<Real> P2 = Position(v2);
- Vector3<Real> D10 = P1 - P0;
- Vector3<Real> D20 = P2 - P0;
- Vector3<Real> D21 = P2 - P1;
- if (mTCoords)
- {
-
- Vector2<Real> C0 = TCoord(v0);
- Vector2<Real> C1 = TCoord(v1);
- Vector2<Real> C2 = TCoord(v2);
- Vector2<Real> U10 = C1 - C0;
- Vector2<Real> U20 = C2 - C0;
- Vector2<Real> U21 = C2 - C1;
-
- Matrix<2, 2, Real> outerU10 = OuterProduct(U10, U10);
- Matrix<2, 2, Real> outerU20 = OuterProduct(U20, U20);
- Matrix<2, 2, Real> outerU21 = OuterProduct(U21, U21);
- Matrix<3, 2, Real> outerD10 = OuterProduct(D10, U10);
- Matrix<3, 2, Real> outerD20 = OuterProduct(D20, U20);
- Matrix<3, 2, Real> outerD21 = OuterProduct(D21, U21);
-
- mUTU[v0] += outerU10 + outerU20;
- mUTU[v1] += outerU10 + outerU21;
- mUTU[v2] += outerU20 + outerU21;
- mDTU[v0] += outerD10 + outerD20;
- mDTU[v1] += outerD10 + outerD21;
- mDTU[v2] += outerD20 + outerD21;
- }
- else
- {
-
- Vector3<Real> basis[3];
- basis[0] = Normal(v0);
- ComputeOrthogonalComplement(1, basis, true);
- Vector2<Real> U10{ Dot(basis[1], D10), Dot(basis[2], D10) };
- Vector2<Real> U20{ Dot(basis[1], D20), Dot(basis[2], D20) };
- mUTU[v0] += OuterProduct(U10, U10) + OuterProduct(U20, U20);
- mDTU[v0] += OuterProduct(D10, U10) + OuterProduct(D20, U20);
- basis[0] = Normal(v1);
- ComputeOrthogonalComplement(1, basis, true);
- Vector2<Real> U01{ Dot(basis[1], D10), Dot(basis[2], D10) };
- Vector2<Real> U21{ Dot(basis[1], D21), Dot(basis[2], D21) };
- mUTU[v1] += OuterProduct(U01, U01) + OuterProduct(U21, U21);
- mDTU[v1] += OuterProduct(D10, U01) + OuterProduct(D21, U21);
- basis[0] = Normal(v2);
- ComputeOrthogonalComplement(1, basis, true);
- Vector2<Real> U02{ Dot(basis[1], D20), Dot(basis[2], D20) };
- Vector2<Real> U12{ Dot(basis[1], D21), Dot(basis[2], D21) };
- mUTU[v2] += OuterProduct(U02, U02) + OuterProduct(U12, U12);
- mDTU[v2] += OuterProduct(D20, U02) + OuterProduct(D21, U12);
- }
- }
- for (uint32_t i = 0; i < mDescription.numVertices; ++i)
- {
- Matrix<3, 2, Real> jacobian = mDTU[i] * Inverse(mUTU[i]);
- Vector3<Real> basis[3];
- basis[0] = { jacobian(0, 0), jacobian(1, 0), jacobian(2, 0) };
- basis[1] = { jacobian(0, 1), jacobian(1, 1), jacobian(2, 1) };
- if (mDPDUs)
- {
- DPDU(i) = basis[0];
- }
- if (mDPDVs)
- {
- DPDV(i) = basis[1];
- }
- ComputeOrthogonalComplement(2, basis, true);
- if (mNormals)
- {
- Normal(i) = basis[2];
- }
- if (mTangents)
- {
- Tangent(i) = basis[0];
- }
- if (mBitangents)
- {
- Bitangent(i) = basis[1];
- }
- }
- }
-
-
-
-
-
- MeshDescription mDescription;
-
- Vector3<Real>* mPositions;
- Vector3<Real>* mNormals;
- Vector3<Real>* mTangents;
- Vector3<Real>* mBitangents;
- Vector3<Real>* mDPDUs;
- Vector3<Real>* mDPDVs;
- Vector2<Real>* mTCoords;
- size_t mPositionStride;
- size_t mNormalStride;
- size_t mTangentStride;
- size_t mBitangentStride;
- size_t mDPDUStride;
- size_t mDPDVStride;
- size_t mTCoordStride;
-
-
-
-
-
-
-
-
- std::vector<Matrix<2, 2, Real>> mUTU;
- std::vector<Matrix<3, 2, Real>> mDTU;
- };
- }
|