Merge 'remotes/trunk'
[0ad.git] / source / renderer / MikktspaceWrap.cpp
blob57c31403ed3c1c32f9f89e0b7f90f43b42f0cb85
1 /* Copyright (C) 2021 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
18 #include "precompiled.h"
20 #include "renderer/MikktspaceWrap.h"
22 MikkTSpace::MikkTSpace(const CModelDefPtr& m, std::vector<float>& v, bool gpuSkinning) : m_Model(m),
23 m_NewVertices(v), m_GpuSkinning(gpuSkinning)
25 // ensure that m_NewVertices is empty
26 m_NewVertices.clear();
28 // set up SMikkTSpaceInterface struct
29 m_Interface.m_getNumFaces = GetNumFaces;
30 m_Interface.m_getNumVerticesOfFace = GetNumVerticesOfFace;
31 m_Interface.m_getPosition = GetPosition;
32 m_Interface.m_getNormal = GetNormal;
33 m_Interface.m_getTexCoord = GetTexCoord;
34 m_Interface.m_setTSpaceBasic = nullptr;
35 m_Interface.m_setTSpace = SetTSpace;
37 // set up SMikkTSpaceContext struct
38 m_Context.m_pInterface = &m_Interface;
39 m_Context.m_pUserData = static_cast<void*>(this);
42 void MikkTSpace::Generate()
44 genTangSpaceDefault(&m_Context);
47 int MikkTSpace::GetNumFaces(const SMikkTSpaceContext* pContext)
49 return GetUserDataFromContext(pContext)->m_Model->GetNumFaces();
52 int MikkTSpace::GetNumVerticesOfFace(const SMikkTSpaceContext* UNUSED(pContext), const int UNUSED(iFace))
54 return 3;
57 void MikkTSpace::GetPosition(const SMikkTSpaceContext* pContext,
58 float* fvPosOut, const int iFace, const int iVert)
60 const CVector3D& position = GetVertex(pContext, iFace, iVert).m_Coords;
62 fvPosOut[0] = position.X;
63 fvPosOut[1] = position.Y;
64 fvPosOut[2] = position.Z;
68 void MikkTSpace::GetNormal(const SMikkTSpaceContext* pContext,
69 float* fvNormOut, const int iFace, const int iVert)
71 const CVector3D& normal = GetVertex(pContext, iFace, iVert).m_Norm;
73 fvNormOut[0] = normal.X;
74 fvNormOut[1] = normal.Y;
75 fvNormOut[2] = normal.Z;
79 void MikkTSpace::GetTexCoord(const SMikkTSpaceContext* pContext,
80 float* fvTexcOut, const int iFace, const int iVert)
82 const MikkTSpace* userData = GetUserDataFromContext(pContext);
83 const SModelFace& face = userData->m_Model->GetFaces()[iFace];
84 const size_t numberOfUVPerVertex = userData->m_Model->GetNumUVsPerVertex();
86 // The tangents are calculated according to the 'default' UV set
87 const CVector2D& uv = userData->m_Model->GetUVCoordinates()[face.m_Verts[iVert] * numberOfUVPerVertex];
88 fvTexcOut[0] = uv.X;
89 fvTexcOut[1] = 1.0 - uv.Y;
93 void MikkTSpace::SetTSpace(const SMikkTSpaceContext* pContext, const float* fvTangent,
94 const float* UNUSED(fvBiTangent), const float UNUSED(fMagS), const float UNUSED(fMagT),
95 const tbool bIsOrientationPreserving, const int iFace, const int iVert)
97 const MikkTSpace* userData = GetUserDataFromContext(pContext);
98 const SModelFace& face = userData->m_Model->GetFaces()[iFace];
99 const SModelVertex& vertex = userData->m_Model->GetVertices()[face.m_Verts[iVert]];
101 const CVector3D& p = vertex.m_Coords;
102 userData->m_NewVertices.push_back(p.X);
103 userData->m_NewVertices.push_back(p.Y);
104 userData->m_NewVertices.push_back(p.Z);
106 const CVector3D& n = vertex.m_Norm;
107 userData->m_NewVertices.push_back(n.X);
108 userData->m_NewVertices.push_back(n.Y);
109 userData->m_NewVertices.push_back(n.Z);
111 userData->m_NewVertices.push_back(fvTangent[0]);
112 userData->m_NewVertices.push_back(fvTangent[1]);
113 userData->m_NewVertices.push_back(fvTangent[2]);
114 userData->m_NewVertices.push_back(bIsOrientationPreserving != 0 ? 1.f : -1.f);
116 if (userData->m_GpuSkinning)
118 for (u8 j = 0; j < 4; ++j)
120 userData->m_NewVertices.push_back(vertex.m_Blend.m_Bone[j]);
121 userData->m_NewVertices.push_back(255.f * vertex.m_Blend.m_Weight[j]);
125 const size_t numberOfUVPerVertex = userData->m_Model->GetNumUVsPerVertex();
126 for (size_t UVset = 0; UVset < numberOfUVPerVertex; ++UVset)
128 const CVector2D& uv = userData->m_Model->GetUVCoordinates()[face.m_Verts[iVert] * numberOfUVPerVertex + UVset];
129 userData->m_NewVertices.push_back(uv.X);
130 userData->m_NewVertices.push_back(1.f - uv.Y);
134 MikkTSpace* MikkTSpace::GetUserDataFromContext(const SMikkTSpaceContext* pContext)
136 return static_cast<MikkTSpace*>(pContext->m_pUserData);
139 SModelVertex MikkTSpace::GetVertex(const SMikkTSpaceContext* pContext, const int iFace, const int iVert)
141 const MikkTSpace* userData = GetUserDataFromContext(pContext);
142 const SModelFace& f = userData->m_Model->GetFaces()[iFace];
143 return userData->m_Model->GetVertices()[f.m_Verts[iVert]];