Merge 'remotes/trunk'
[0ad.git] / source / renderer / MikktspaceWrap.cpp
blob428ba722c73782c4d47f60368e4febb658253a89
1 /* Copyright (C) 2012 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 <boost/bind.hpp>
22 #include "graphics/Color.h"
23 #include "graphics/LightEnv.h"
24 #include "graphics/Model.h"
25 #include "graphics/ModelDef.h"
26 #include "graphics/ShaderManager.h"
27 #include "graphics/TextureManager.h"
29 #include "renderer/MikktspaceWrap.h"
31 #include "third_party/mikktspace/mikktspace.h"
35 MikkTSpace::MikkTSpace(const CModelDefPtr& m, std::vector<float>& v, bool gpuSkinning) : m_Model(m),
36 m_NewVertices(v), m_GpuSkinning(gpuSkinning)
38 // ensure that m_NewVertices is empty
39 m_NewVertices.clear();
41 // set up SMikkTSpaceInterface struct
42 m_Interface.m_getNumFaces = getNumFaces;
43 m_Interface.m_getNumVerticesOfFace = getNumVerticesOfFace;
44 m_Interface.m_getPosition = getPosition;
45 m_Interface.m_getNormal = getNormal;
46 m_Interface.m_getTexCoord = getTexCoord;
47 m_Interface.m_setTSpaceBasic = NULL;
48 m_Interface.m_setTSpace = setTSpace;
50 // set up SMikkTSpaceContext struct
51 m_Context.m_pInterface = &m_Interface;
52 m_Context.m_pUserData = (void*)this;
55 void MikkTSpace::generate()
57 genTangSpaceDefault(&m_Context);
61 int MikkTSpace::getNumFaces(const SMikkTSpaceContext *pContext)
63 return ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetNumFaces();
67 int MikkTSpace::getNumVerticesOfFace(const SMikkTSpaceContext* UNUSED(pContext), const int UNUSED(iFace))
69 return 3;
73 void MikkTSpace::getPosition(const SMikkTSpaceContext *pContext,
74 float fvPosOut[], const int iFace, const int iVert)
76 SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace];
77 long i = face.m_Verts[iVert];
78 const CVector3D &p = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices()[i].m_Coords;
80 fvPosOut[0] = p.X;
81 fvPosOut[1] = p.Y;
82 fvPosOut[2] = p.Z;
86 void MikkTSpace::getNormal(const SMikkTSpaceContext *pContext,
87 float fvNormOut[], const int iFace, const int iVert)
89 SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace];
90 long i = face.m_Verts[iVert];
91 const CVector3D &n = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices()[i].m_Norm;
93 fvNormOut[0] = n.X;
94 fvNormOut[1] = n.Y;
95 fvNormOut[2] = n.Z;
99 void MikkTSpace::getTexCoord(const SMikkTSpaceContext *pContext,
100 float fvTexcOut[], const int iFace, const int iVert)
102 SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace];
103 long i = face.m_Verts[iVert];
104 SModelVertex &v = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices()[i];
106 // the tangents are calculated according to the 'default' UV set
107 fvTexcOut[0] = v.m_UVs[0];
108 fvTexcOut[1] = 1.0-v.m_UVs[1];
112 void MikkTSpace::setTSpace(const SMikkTSpaceContext * pContext, const float fvTangent[],
113 const float UNUSED(fvBiTangent)[], const float UNUSED(fMagS), const float UNUSED(fMagT),
114 const tbool bIsOrientationPreserving, const int iFace, const int iVert)
116 SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace];
117 long i = face.m_Verts[iVert];
119 SModelVertex* vertices = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices();
120 size_t numUVsPerVertex = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetNumUVsPerVertex();
121 std::vector<float>& m_NewVertices = ((MikkTSpace*)pContext->m_pUserData)->m_NewVertices;
123 const CVector3D &p = vertices[i].m_Coords;
124 const CVector3D &n = vertices[i].m_Norm;
126 m_NewVertices.push_back(p.X);
127 m_NewVertices.push_back(p.Y);
128 m_NewVertices.push_back(p.Z);
130 m_NewVertices.push_back(n.X);
131 m_NewVertices.push_back(n.Y);
132 m_NewVertices.push_back(n.Z);
134 m_NewVertices.push_back(fvTangent[0]);
135 m_NewVertices.push_back(fvTangent[1]);
136 m_NewVertices.push_back(fvTangent[2]);
137 m_NewVertices.push_back(bIsOrientationPreserving > 0.5 ? 1.0f : (-1.0f));
139 if (((MikkTSpace*)pContext->m_pUserData)->m_GpuSkinning)
141 for (size_t j = 0; j < 4; ++j)
143 m_NewVertices.push_back(vertices[i].m_Blend.m_Bone[j]);
144 m_NewVertices.push_back(255.f * vertices[i].m_Blend.m_Weight[j]);
148 for (size_t UVset = 0; UVset < numUVsPerVertex; ++UVset)
150 m_NewVertices.push_back(vertices[i].m_UVs[UVset * 2]);
151 m_NewVertices.push_back(1.0 - vertices[i].m_UVs[UVset * 2 + 1]);