Index: ps/trunk/source/renderer/MikktspaceWrap.h =================================================================== --- ps/trunk/source/renderer/MikktspaceWrap.h +++ ps/trunk/source/renderer/MikktspaceWrap.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -18,9 +18,13 @@ #ifndef INCLUDED_MIKKWRAP #define INCLUDED_MIKKWRAP - +#include "graphics/Model.h" +#include "graphics/ModelDef.h" #include "third_party/mikktspace/mikktspace.h" +#include + +class CVector3D; class MikkTSpace { @@ -28,53 +32,92 @@ MikkTSpace(const CModelDefPtr& m, std::vector& v, bool gpuSkinning); - void generate(); + void Generate(); private: SMikkTSpaceInterface m_Interface; + SMikkTSpaceContext m_Context; const CModelDefPtr& m_Model; std::vector& m_NewVertices; - bool m_GpuSkinning; - - - // Returns the number of faces (triangles/quads) on the mesh to be processed. - static int getNumFaces(const SMikkTSpaceContext *pContext); - - - // Returns the number of vertices on face number iFace - // iFace is a number in the range {0, 1, ..., getNumFaces()-1} - static int getNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace); - - - // returns the position/normal/texcoord of the referenced face of vertex number iVert. - // iVert is in the range {0,1,2} for triangles and {0,1,2,3} for quads. - static void getPosition(const SMikkTSpaceContext *pContext, - float fvPosOut[], const int iFace, const int iVert); - - static void getNormal(const SMikkTSpaceContext *pContext, - float fvNormOut[], const int iFace, const int iVert); - - static void getTexCoord(const SMikkTSpaceContext *pContext, - float fvTexcOut[], const int iFace, const int iVert); + bool m_GpuSkinning; - // This function is used to return tangent space results to the application. - // fvTangent and fvBiTangent are unit length vectors and fMagS and fMagT are their - // true magnitudes which can be used for relief mapping effects. - // fvBiTangent is the "real" bitangent and thus may not be perpendicular to fvTangent. - // However, both are perpendicular to the vertex normal. - // For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level. - // fSign = bIsOrientationPreserving ? 1.0f : (-1.0f); - // bitangent = fSign * cross(vN, tangent); - static void setTSpace(const SMikkTSpaceContext * pContext, const float fvTangent[], - const float fvBiTangent[], const float fMagS, const float fMagT, + /** + * @param[in] pContext - Pointer to the MikkTSpace context. + * @returns - the number of faces (triangles/quads) on the mesh to be processed. + */ + static int GetNumFaces(const SMikkTSpaceContext *pContext); + + /** + * @param[in] pContext - Pointer to the MikkTSpace context. + * @param[in] iFace - Number in the range { 0, 1, ..., getNumFaces() - 1 }. + * @returns - the number of faces (triangles/quads) on the mesh to be processed. + */ + static int GetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace); + + /** + * @param[in] pContext - Pointer to the MikkTSpace context. + * @returns - The MikkTSpace. + */ + static MikkTSpace* GetUserDataFromContext(const SMikkTSpaceContext *pContext); + + /** + * @param[in] pContext - Pointer to the MikkTSpace context. + * @param[in] iFace - Number in the range { 0, 1, ..., getNumFaces() - 1 }. + * @param[in] iVert - Number in the range { 0, 1, 2 } for triangles and { 0, 1, 2, 3 } for quads. + * @returns - The MikkTSpace. + */ + static SModelVertex GetVertex(const SMikkTSpaceContext *pContext, const int iFace, const int iVert); + + /** + * @param[in] pContext - Pointer to the MikkTSpace context. + * @param[out] fvPosOut - The array containing the face. + * @param[in] iFace - Number in the range { 0, 1, ..., getNumFaces() - 1 }. + * @param[in] iVert - Number in the range { 0, 1, 2 } for triangles and { 0, 1, 2, 3 } for quads. + */ + static void GetPosition(const SMikkTSpaceContext *pContext, + float fvPosOut[3], const int iFace, const int iVert); + + /** + * @param[in] pContext - Pointer to the MikkTSpace context. + * @param[out] fvNormOut iVert - The array containing the normal. + * @param[in] iFace - Number in the range { 0, 1, ..., getNumFaces() - 1 }. + * @param[in] iVert - Number in the range { 0, 1, 2 } for triangles and { 0, 1, 2, 3 } for quads. + */ + static void GetNormal(const SMikkTSpaceContext *pContext, + float fvNormOut[3], const int iFace, const int iVert); + + /** + * @param[in] pContext - Pointer to the MikkTSpace context. + * @param[out] fvTexcOut iVert - Array containing the UV. + * @param[in] iFace - Number in the range { 0, 1, ..., getNumFaces() - 1 }. + * @param[in] iVert - Number in the range { 0, 1, 2 } for triangles and { 0, 1, 2, 3 } for quads. + */ + static void GetTexCoord(const SMikkTSpaceContext *pContext, + float fvTexcOut[2], const int iFace, const int iVert); + + /** + * @brief This function is used to return tangent space results to the application. + * For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level. + * fSign = bIsOrientationPreserving ? 1.0f : (-1.0f); + * bitangent = fSign * cross(vN, tangent); + * @param[in] pContext - Pointer to the MikkTSpace context. + * @param[in] fvTangent - fvTangent - The tangent vector. + * @param[in] fvBiTangent - The "real" bitangent vector. Not be perpendicular to fvTangent. However, both are perpendicular to the vertex normal. + * @param[in] fMagS - magniture of the fvTangent vector. + * @param[in] fMagT - magniture of the fvBiTangent vector. + * @param[in] bIsOrientationPreserving - Whether the orientation should be preserved. + * @param[in] iFace - Number in the range {0,1,2} for triangles and {0,1,2,3} for quads. + * @param[in] iVert - Array containing the position vector of the face. + */ + static void SetTSpace(const SMikkTSpaceContext * pContext, const float fvTangent[], + const float UNUSED(fvBiTangent)[], const float UNUSED(fMagS), const float UNUSED(fMagT), const tbool bIsOrientationPreserving, const int iFace, const int iVert); - }; Index: ps/trunk/source/renderer/MikktspaceWrap.cpp =================================================================== --- ps/trunk/source/renderer/MikktspaceWrap.cpp +++ ps/trunk/source/renderer/MikktspaceWrap.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -17,21 +17,8 @@ #include "precompiled.h" -#include - -#include "graphics/Color.h" -#include "graphics/LightEnv.h" -#include "graphics/Model.h" -#include "graphics/ModelDef.h" -#include "graphics/ShaderManager.h" -#include "graphics/TextureManager.h" - #include "renderer/MikktspaceWrap.h" -#include "third_party/mikktspace/mikktspace.h" - - - MikkTSpace::MikkTSpace(const CModelDefPtr& m, std::vector& v, bool gpuSkinning) : m_Model(m), m_NewVertices(v), m_GpuSkinning(gpuSkinning) { @@ -39,118 +26,117 @@ m_NewVertices.clear(); // set up SMikkTSpaceInterface struct - m_Interface.m_getNumFaces = getNumFaces; - m_Interface.m_getNumVerticesOfFace = getNumVerticesOfFace; - m_Interface.m_getPosition = getPosition; - m_Interface.m_getNormal = getNormal; - m_Interface.m_getTexCoord = getTexCoord; - m_Interface.m_setTSpaceBasic = NULL; - m_Interface.m_setTSpace = setTSpace; + m_Interface.m_getNumFaces = GetNumFaces; + m_Interface.m_getNumVerticesOfFace = GetNumVerticesOfFace; + m_Interface.m_getPosition = GetPosition; + m_Interface.m_getNormal = GetNormal; + m_Interface.m_getTexCoord = GetTexCoord; + m_Interface.m_setTSpaceBasic = nullptr; + m_Interface.m_setTSpace = SetTSpace; // set up SMikkTSpaceContext struct m_Context.m_pInterface = &m_Interface; - m_Context.m_pUserData = (void*)this; + m_Context.m_pUserData = static_cast(this); } -void MikkTSpace::generate() +void MikkTSpace::Generate() { genTangSpaceDefault(&m_Context); } - -int MikkTSpace::getNumFaces(const SMikkTSpaceContext *pContext) +int MikkTSpace::GetNumFaces(const SMikkTSpaceContext *pContext) { - return ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetNumFaces(); + return GetUserDataFromContext(pContext)->m_Model->GetNumFaces(); } - -int MikkTSpace::getNumVerticesOfFace(const SMikkTSpaceContext* UNUSED(pContext), const int UNUSED(iFace)) +int MikkTSpace::GetNumVerticesOfFace(const SMikkTSpaceContext* UNUSED(pContext), const int UNUSED(iFace)) { return 3; } - -void MikkTSpace::getPosition(const SMikkTSpaceContext *pContext, - float fvPosOut[], const int iFace, const int iVert) +void MikkTSpace::GetPosition(const SMikkTSpaceContext *pContext, + float fvPosOut[3], const int iFace, const int iVert) { - SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace]; - long i = face.m_Verts[iVert]; - const CVector3D &p = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices()[i].m_Coords; + const CVector3D& position = GetVertex(pContext, iFace, iVert).m_Coords; - fvPosOut[0] = p.X; - fvPosOut[1] = p.Y; - fvPosOut[2] = p.Z; + fvPosOut[0] = position.X; + fvPosOut[1] = position.Y; + fvPosOut[2] = position.Z; } -void MikkTSpace::getNormal(const SMikkTSpaceContext *pContext, - float fvNormOut[], const int iFace, const int iVert) +void MikkTSpace::GetNormal(const SMikkTSpaceContext *pContext, + float fvNormOut[3], const int iFace, const int iVert) { - SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace]; - long i = face.m_Verts[iVert]; - const CVector3D &n = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices()[i].m_Norm; + const CVector3D& normal = GetVertex(pContext, iFace, iVert).m_Norm; - fvNormOut[0] = n.X; - fvNormOut[1] = n.Y; - fvNormOut[2] = n.Z; + fvNormOut[0] = normal.X; + fvNormOut[1] = normal.Y; + fvNormOut[2] = normal.Z; } -void MikkTSpace::getTexCoord(const SMikkTSpaceContext *pContext, - float fvTexcOut[], const int iFace, const int iVert) +void MikkTSpace::GetTexCoord(const SMikkTSpaceContext *pContext, + float fvTexcOut[2], const int iFace, const int iVert) { - SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace]; - long i = face.m_Verts[iVert]; - SModelVertex &v = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices()[i]; + const MikkTSpace* userData = GetUserDataFromContext(pContext); + const SModelFace& face = userData->m_Model->GetFaces()[iFace]; + const SModelVertex& v = userData->m_Model->GetVertices()[face.m_Verts[iVert]]; - // the tangents are calculated according to the 'default' UV set + // The tangents are calculated according to the 'default' UV set fvTexcOut[0] = v.m_UVs[0]; - fvTexcOut[1] = 1.0-v.m_UVs[1]; + fvTexcOut[1] = 1.0 - v.m_UVs[1]; } -void MikkTSpace::setTSpace(const SMikkTSpaceContext * pContext, const float fvTangent[], - const float UNUSED(fvBiTangent)[], const float UNUSED(fMagS), const float UNUSED(fMagT), - const tbool bIsOrientationPreserving, const int iFace, const int iVert) +void MikkTSpace::SetTSpace(const SMikkTSpaceContext* pContext, const float fvTangent[], + const float UNUSED(fvBiTangent)[], const float UNUSED(fMagS), const float UNUSED(fMagT), + const tbool bIsOrientationPreserving, const int iFace, const int iVert) { - SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace]; - long i = face.m_Verts[iVert]; + const MikkTSpace* userData = GetUserDataFromContext(pContext); + const SModelFace& face = userData->m_Model->GetFaces()[iFace]; + const SModelVertex& vertex = userData->m_Model->GetVertices()[face.m_Verts[iVert]]; - SModelVertex* vertices = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices(); - size_t numUVsPerVertex = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetNumUVsPerVertex(); - std::vector& m_NewVertices = ((MikkTSpace*)pContext->m_pUserData)->m_NewVertices; + const CVector3D &p = vertex.m_Coords; + userData->m_NewVertices.push_back(p.X); + userData->m_NewVertices.push_back(p.Y); + userData->m_NewVertices.push_back(p.Z); - const CVector3D &p = vertices[i].m_Coords; - const CVector3D &n = vertices[i].m_Norm; + const CVector3D& n = vertex.m_Norm; + userData->m_NewVertices.push_back(n.X); + userData->m_NewVertices.push_back(n.Y); + userData->m_NewVertices.push_back(n.Z); - m_NewVertices.push_back(p.X); - m_NewVertices.push_back(p.Y); - m_NewVertices.push_back(p.Z); + userData->m_NewVertices.push_back(fvTangent[0]); + userData->m_NewVertices.push_back(fvTangent[1]); + userData->m_NewVertices.push_back(fvTangent[2]); + userData->m_NewVertices.push_back(bIsOrientationPreserving != 0 ? 1.f : -1.f); - m_NewVertices.push_back(n.X); - m_NewVertices.push_back(n.Y); - m_NewVertices.push_back(n.Z); - - m_NewVertices.push_back(fvTangent[0]); - m_NewVertices.push_back(fvTangent[1]); - m_NewVertices.push_back(fvTangent[2]); - m_NewVertices.push_back(bIsOrientationPreserving > 0.5 ? 1.0f : (-1.0f)); - - if (((MikkTSpace*)pContext->m_pUserData)->m_GpuSkinning) + if (userData->m_GpuSkinning) { - for (size_t j = 0; j < 4; ++j) + for (u8 j = 0; j < 4; ++j) { - m_NewVertices.push_back(vertices[i].m_Blend.m_Bone[j]); - m_NewVertices.push_back(255.f * vertices[i].m_Blend.m_Weight[j]); + userData->m_NewVertices.push_back(vertex.m_Blend.m_Bone[j]); + userData->m_NewVertices.push_back(255.f * vertex.m_Blend.m_Weight[j]); } } + size_t numUVsPerVertex = userData->m_Model->GetNumUVsPerVertex(); for (size_t UVset = 0; UVset < numUVsPerVertex; ++UVset) { - m_NewVertices.push_back(vertices[i].m_UVs[UVset * 2]); - m_NewVertices.push_back(1.0 - vertices[i].m_UVs[UVset * 2 + 1]); + userData->m_NewVertices.push_back(vertex.m_UVs[UVset * 2]); + userData->m_NewVertices.push_back(1.f - vertex.m_UVs[UVset * 2 + 1]); } } +MikkTSpace* MikkTSpace::GetUserDataFromContext(const SMikkTSpaceContext *pContext) +{ + return static_cast(pContext->m_pUserData); +} - +SModelVertex MikkTSpace::GetVertex(const SMikkTSpaceContext *pContext, const int iFace, const int iVert) +{ + const MikkTSpace* userData = GetUserDataFromContext(pContext); + const SModelFace& f = userData->m_Model->GetFaces()[iFace]; + return userData->m_Model->GetVertices()[f.m_Verts[iVert]]; +} Index: ps/trunk/source/renderer/ModelRenderer.cpp =================================================================== --- ps/trunk/source/renderer/ModelRenderer.cpp +++ ps/trunk/source/renderer/ModelRenderer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -117,7 +117,7 @@ // just copy regular positions, transform normals to world space const CMatrix3D& transform = model->GetTransform(); const CMatrix3D& invtransform = model->GetInvTransform(); - for (size_t j=0; jGetShadingColor(); - for (size_t j=0; j& newVertices, bool gpuSkinning) { MikkTSpace ms(mdef, newVertices, gpuSkinning); - - ms.generate(); + ms.Generate(); } @@ -727,7 +726,7 @@ const CShaderRenderQueries& renderQueries = model->GetMaterial().GetRenderQueries(); - for (size_t q = 0; q < renderQueries.GetSize(); q++) + for (size_t q = 0; q < renderQueries.GetSize(); ++q) { CShaderRenderQueries::RenderQuery rq = renderQueries.GetItem(q); if (rq.first == RQUERY_TIME)