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
))
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
];
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
]];