Line data Source code
1 : /* Copyright (C) 2021 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
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.
8 : *
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.
13 : *
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/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "renderer/MikktspaceWrap.h"
21 :
22 0 : MikkTSpace::MikkTSpace(const CModelDefPtr& m, std::vector<float>& v, bool gpuSkinning) : m_Model(m),
23 0 : m_NewVertices(v), m_GpuSkinning(gpuSkinning)
24 : {
25 : // ensure that m_NewVertices is empty
26 0 : m_NewVertices.clear();
27 :
28 : // set up SMikkTSpaceInterface struct
29 0 : m_Interface.m_getNumFaces = GetNumFaces;
30 0 : m_Interface.m_getNumVerticesOfFace = GetNumVerticesOfFace;
31 0 : m_Interface.m_getPosition = GetPosition;
32 0 : m_Interface.m_getNormal = GetNormal;
33 0 : m_Interface.m_getTexCoord = GetTexCoord;
34 0 : m_Interface.m_setTSpaceBasic = nullptr;
35 0 : m_Interface.m_setTSpace = SetTSpace;
36 :
37 : // set up SMikkTSpaceContext struct
38 0 : m_Context.m_pInterface = &m_Interface;
39 0 : m_Context.m_pUserData = static_cast<void*>(this);
40 0 : }
41 :
42 0 : void MikkTSpace::Generate()
43 : {
44 0 : genTangSpaceDefault(&m_Context);
45 0 : }
46 :
47 0 : int MikkTSpace::GetNumFaces(const SMikkTSpaceContext* pContext)
48 : {
49 0 : return GetUserDataFromContext(pContext)->m_Model->GetNumFaces();
50 : }
51 :
52 0 : int MikkTSpace::GetNumVerticesOfFace(const SMikkTSpaceContext* UNUSED(pContext), const int UNUSED(iFace))
53 : {
54 0 : return 3;
55 : }
56 :
57 0 : void MikkTSpace::GetPosition(const SMikkTSpaceContext* pContext,
58 : float* fvPosOut, const int iFace, const int iVert)
59 : {
60 0 : const CVector3D& position = GetVertex(pContext, iFace, iVert).m_Coords;
61 :
62 0 : fvPosOut[0] = position.X;
63 0 : fvPosOut[1] = position.Y;
64 0 : fvPosOut[2] = position.Z;
65 0 : }
66 :
67 :
68 0 : void MikkTSpace::GetNormal(const SMikkTSpaceContext* pContext,
69 : float* fvNormOut, const int iFace, const int iVert)
70 : {
71 0 : const CVector3D& normal = GetVertex(pContext, iFace, iVert).m_Norm;
72 :
73 0 : fvNormOut[0] = normal.X;
74 0 : fvNormOut[1] = normal.Y;
75 0 : fvNormOut[2] = normal.Z;
76 0 : }
77 :
78 :
79 0 : void MikkTSpace::GetTexCoord(const SMikkTSpaceContext* pContext,
80 : float* fvTexcOut, const int iFace, const int iVert)
81 : {
82 0 : const MikkTSpace* userData = GetUserDataFromContext(pContext);
83 0 : const SModelFace& face = userData->m_Model->GetFaces()[iFace];
84 0 : const size_t numberOfUVPerVertex = userData->m_Model->GetNumUVsPerVertex();
85 :
86 : // The tangents are calculated according to the 'default' UV set
87 0 : const CVector2D& uv = userData->m_Model->GetUVCoordinates()[face.m_Verts[iVert] * numberOfUVPerVertex];
88 0 : fvTexcOut[0] = uv.X;
89 0 : fvTexcOut[1] = 1.0 - uv.Y;
90 0 : }
91 :
92 :
93 0 : 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)
96 : {
97 0 : const MikkTSpace* userData = GetUserDataFromContext(pContext);
98 0 : const SModelFace& face = userData->m_Model->GetFaces()[iFace];
99 0 : const SModelVertex& vertex = userData->m_Model->GetVertices()[face.m_Verts[iVert]];
100 :
101 0 : const CVector3D& p = vertex.m_Coords;
102 0 : userData->m_NewVertices.push_back(p.X);
103 0 : userData->m_NewVertices.push_back(p.Y);
104 0 : userData->m_NewVertices.push_back(p.Z);
105 :
106 0 : const CVector3D& n = vertex.m_Norm;
107 0 : userData->m_NewVertices.push_back(n.X);
108 0 : userData->m_NewVertices.push_back(n.Y);
109 0 : userData->m_NewVertices.push_back(n.Z);
110 :
111 0 : userData->m_NewVertices.push_back(fvTangent[0]);
112 0 : userData->m_NewVertices.push_back(fvTangent[1]);
113 0 : userData->m_NewVertices.push_back(fvTangent[2]);
114 0 : userData->m_NewVertices.push_back(bIsOrientationPreserving != 0 ? 1.f : -1.f);
115 :
116 0 : if (userData->m_GpuSkinning)
117 : {
118 0 : for (u8 j = 0; j < 4; ++j)
119 : {
120 0 : userData->m_NewVertices.push_back(vertex.m_Blend.m_Bone[j]);
121 0 : userData->m_NewVertices.push_back(255.f * vertex.m_Blend.m_Weight[j]);
122 : }
123 : }
124 :
125 0 : const size_t numberOfUVPerVertex = userData->m_Model->GetNumUVsPerVertex();
126 0 : for (size_t UVset = 0; UVset < numberOfUVPerVertex; ++UVset)
127 : {
128 0 : const CVector2D& uv = userData->m_Model->GetUVCoordinates()[face.m_Verts[iVert] * numberOfUVPerVertex + UVset];
129 0 : userData->m_NewVertices.push_back(uv.X);
130 0 : userData->m_NewVertices.push_back(1.f - uv.Y);
131 : }
132 0 : }
133 :
134 0 : MikkTSpace* MikkTSpace::GetUserDataFromContext(const SMikkTSpaceContext* pContext)
135 : {
136 0 : return static_cast<MikkTSpace*>(pContext->m_pUserData);
137 : }
138 :
139 0 : SModelVertex MikkTSpace::GetVertex(const SMikkTSpaceContext* pContext, const int iFace, const int iVert)
140 : {
141 0 : const MikkTSpace* userData = GetUserDataFromContext(pContext);
142 0 : const SModelFace& f = userData->m_Model->GetFaces()[iFace];
143 0 : return userData->m_Model->GetVertices()[f.m_Verts[iVert]];
144 3 : }
|