diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg
index d18a3d026b..97cd451d24 100644
--- a/binaries/data/config/default.cfg
+++ b/binaries/data/config/default.cfg
@@ -73,9 +73,12 @@ renderpath = default
; Prefer GLSL shaders over ARB shaders (not recommended). REQUIRES gentangents=true.
preferglsl = false
-; Generate tangents for normal and parallax mapping. REQUIRES preferglsl=true. Incompatible with gpuskinning.
+; Generate tangents for normal and parallax mapping. REQUIRES preferglsl=true.
gentangents = false
+; Experimental probably-non-working GPU skinning support; requires preferglsl; use at own risk
+gpuskinning = false
+
; Use smooth LOS interpolation; REQUIRES preferglsl=true.
smoothlos = false
@@ -96,9 +99,6 @@ materialmgr.PARALLAX_VHQ_DIST.max = 0
; Replace alpha-blending with alpha-testing, for performance experiments
forcealphatest = false
-; Experimental probably-non-working GPU skinning support; requires preferglsl; use at own risk
-gpuskinning = false
-
; Opt-in online user reporting system
userreport.url = "http://feedback.wildfiregames.com/report/upload/v1/"
diff --git a/binaries/data/mods/public/shaders/glsl/model_common.fs b/binaries/data/mods/public/shaders/glsl/model_common.fs
index d6bb9dd0a4..5ffe2a254c 100644
--- a/binaries/data/mods/public/shaders/glsl/model_common.fs
+++ b/binaries/data/mods/public/shaders/glsl/model_common.fs
@@ -38,7 +38,7 @@ varying vec4 v_lighting;
varying vec2 v_tex;
varying vec2 v_los;
-#if USE_INSTANCING && USE_AO
+#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO
varying vec2 v_tex2;
#endif
@@ -53,14 +53,14 @@ varying vec2 v_los;
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX_MAP
varying vec4 v_normal;
- #if USE_INSTANCING && (USE_NORMAL_MAP || USE_PARALLAX_MAP)
+ #if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_NORMAL_MAP || USE_PARALLAX_MAP)
varying vec4 v_tangent;
//varying vec3 v_bitangent;
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP
varying vec3 v_half;
#endif
- #if USE_INSTANCING && USE_PARALLAX_MAP
+ #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX_MAP
varying vec3 v_eyeVec;
#endif
#endif
@@ -112,12 +112,12 @@ void main()
{
vec2 coord = v_tex;
- #if USE_PARALLAX_MAP || USE_NORMAL_MAP
+ #if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_PARALLAX_MAP || USE_NORMAL_MAP)
vec3 bitangent = vec3(v_normal.w, v_tangent.w, v_lighting.w);
mat3 tbn = mat3(v_tangent.xyz, bitangent, v_normal.xyz);
#endif
- #if USE_PARALLAX_MAP
+ #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX_MAP
{
float h = texture2D(normTex, coord).a;
@@ -222,7 +222,7 @@ void main()
vec3 normal = v_normal.xyz;
#endif
- #if USE_INSTANCING && USE_NORMAL_MAP
+ #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_NORMAL_MAP
vec3 ntex = texture2D(normTex, coord).rgb * 2.0 - 1.0;
ntex.y = -ntex.y;
normal = normalize(tbn * ntex);
@@ -251,7 +251,7 @@ void main()
vec3 color = (texdiffuse * sundiffuse + specular.rgb) * get_shadow();
vec3 ambColor = texdiffuse * ambient;
- #if USE_INSTANCING && USE_AO
+ #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO
vec3 ao = texture2D(aoTex, v_tex2).rrr;
ao = mix(vec3(1.0), ao * 2.0, effectSettings.w);
ambColor *= ao;
diff --git a/binaries/data/mods/public/shaders/glsl/model_common.vs b/binaries/data/mods/public/shaders/glsl/model_common.vs
index f5cd2af6ee..1d4a324d22 100644
--- a/binaries/data/mods/public/shaders/glsl/model_common.vs
+++ b/binaries/data/mods/public/shaders/glsl/model_common.vs
@@ -30,27 +30,27 @@ varying vec2 v_los;
varying vec4 v_shadow;
#endif
-#if USE_INSTANCING && USE_AO
+#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO
varying vec2 v_tex2;
#endif
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX_MAP
varying vec4 v_normal;
- #if USE_INSTANCING && (USE_NORMAL_MAP || USE_PARALLAX_MAP)
+ #if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_NORMAL_MAP || USE_PARALLAX_MAP)
varying vec4 v_tangent;
//varying vec3 v_bitangent;
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP
varying vec3 v_half;
#endif
- #if USE_INSTANCING && USE_PARALLAX_MAP
+ #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX_MAP
varying vec3 v_eyeVec;
#endif
#endif
attribute vec3 a_vertex;
attribute vec3 a_normal;
-#if USE_INSTANCING
+#if (USE_INSTANCING || USE_GPU_SKINNING)
attribute vec4 a_tangent;
#endif
attribute vec2 a_uv0;
@@ -86,9 +86,13 @@ void main()
}
}
vec4 position = instancingTransform * vec4(p, 1.0);
- vec3 normal = mat3(instancingTransform) * normalize(n);
+ mat3 normalMatrix = mat3(instancingTransform[0].xyz, instancingTransform[1].xyz, instancingTransform[2].xyz);
+ vec3 normal = normalMatrix * normalize(n);
+ #if (USE_NORMAL_MAP || USE_PARALLAX_MAP)
+ vec3 tangent = normalMatrix * a_tangent.xyz;
+ #endif
#else
- #if USE_INSTANCING
+ #if (USE_INSTANCING)
vec4 position = instancingTransform * vec4(a_vertex, 1.0);
mat3 normalMatrix = mat3(instancingTransform[0].xyz, instancingTransform[1].xyz, instancingTransform[2].xyz);
vec3 normal = normalMatrix * a_normal;
@@ -140,7 +144,7 @@ void main()
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX_MAP
v_normal.xyz = normal;
- #if USE_INSTANCING && (USE_NORMAL_MAP || USE_PARALLAX_MAP)
+ #if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_NORMAL_MAP || USE_PARALLAX_MAP)
v_tangent.xyz = tangent;
vec3 bitangent = cross(v_normal.xyz, v_tangent.xyz) * a_tangent.w;
v_normal.w = bitangent.x;
@@ -154,7 +158,7 @@ void main()
vec3 sunVec = -sunDir;
v_half = normalize(sunVec + normalize(eyeVec));
#endif
- #if USE_INSTANCING && USE_PARALLAX_MAP
+ #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX_MAP
v_eyeVec = eyeVec;
#endif
#endif
@@ -164,7 +168,7 @@ void main()
v_tex = a_uv0;
- #if USE_INSTANCING && USE_AO
+ #if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO
v_tex2 = a_uv1;
#endif
diff --git a/binaries/data/mods/public/shaders/glsl/model_common.xml b/binaries/data/mods/public/shaders/glsl/model_common.xml
index 8b7c47ef7c..0eb6fef37c 100644
--- a/binaries/data/mods/public/shaders/glsl/model_common.xml
+++ b/binaries/data/mods/public/shaders/glsl/model_common.xml
@@ -12,7 +12,7 @@
-
+
diff --git a/source/renderer/InstancingModelRenderer.cpp b/source/renderer/InstancingModelRenderer.cpp
index d7c37faf3b..06e4b670eb 100644
--- a/source/renderer/InstancingModelRenderer.cpp
+++ b/source/renderer/InstancingModelRenderer.cpp
@@ -31,13 +31,14 @@
#include "graphics/LightEnv.h"
#include "graphics/Model.h"
#include "graphics/ModelDef.h"
-#include "graphics/weldmesh.h"
#include "renderer/InstancingModelRenderer.h"
#include "renderer/Renderer.h"
#include "renderer/RenderModifiers.h"
#include "renderer/VertexArray.h"
+#include "third_party/mikktspace/weldmesh.h"
+
///////////////////////////////////////////////////////////////////////////////////////////////
// InstancingModelRenderer implementation
@@ -85,6 +86,17 @@ IModelDef::IModelDef(const CModelDefPtr& mdef, bool gpuSkinning, bool calculateT
m_Array.AddAttribute(&m_UVs[i]);
}
+ if (gpuSkinning)
+ {
+ m_BlendJoints.type = GL_UNSIGNED_BYTE;
+ m_BlendJoints.elems = 4;
+ m_Array.AddAttribute(&m_BlendJoints);
+
+ m_BlendWeights.type = GL_UNSIGNED_BYTE;
+ m_BlendWeights.elems = 4;
+ m_Array.AddAttribute(&m_BlendWeights);
+ }
+
if (calculateTangents)
{
// Generate tangents for the geometry:-
@@ -93,8 +105,12 @@ IModelDef::IModelDef(const CModelDefPtr& mdef, bool gpuSkinning, bool calculateT
m_Tangent.elems = 4;
m_Array.AddAttribute(&m_Tangent);
- // floats per vertex; position + normal + tangent + UV*sets
+ // floats per vertex; position + normal + tangent + UV*sets [+ GPUskinning]
int numVertexAttrs = 3 + 3 + 4 + 2 * mdef->GetNumUVsPerVertex();
+ if (gpuSkinning)
+ {
+ numVertexAttrs += 8;
+ }
// the tangent generation can increase the number of vertices temporarily
// so reserve a bit more memory to avoid reallocations in GenTangents (in most cases)
@@ -102,7 +118,7 @@ IModelDef::IModelDef(const CModelDefPtr& mdef, bool gpuSkinning, bool calculateT
newVertices.reserve(numVertexAttrs * numVertices * 2);
// Generate the tangents
- ModelRenderer::GenTangents(mdef, newVertices);
+ ModelRenderer::GenTangents(mdef, newVertices, gpuSkinning);
// how many vertices do we have after generating tangents?
int newNumVert = newVertices.size() / numVertexAttrs;
@@ -123,23 +139,44 @@ IModelDef::IModelDef(const CModelDefPtr& mdef, bool gpuSkinning, bool calculateT
VertexArrayIterator Normal = m_Normal.GetIterator();
VertexArrayIterator Tangent = m_Tangent.GetIterator();
+ VertexArrayIterator BlendJoints;
+ VertexArrayIterator BlendWeights;
+ if (gpuSkinning)
+ {
+ BlendJoints = m_BlendJoints.GetIterator();
+ BlendWeights = m_BlendWeights.GetIterator();
+ }
+
// copy everything into the vertex array
for (int i = 0; i < numVertices2; i++)
{
int q = numVertexAttrs * i;
Position[i] = CVector3D(vertexDataOut[q + 0], vertexDataOut[q + 1], vertexDataOut[q + 2]);
+ q += 3;
- Normal[i] = CVector3D(vertexDataOut[q + 3], vertexDataOut[q + 4], vertexDataOut[q + 5]);
+ Normal[i] = CVector3D(vertexDataOut[q + 0], vertexDataOut[q + 1], vertexDataOut[q + 2]);
+ q += 3;
- Tangent[i] = CVector4D(vertexDataOut[q + 6], vertexDataOut[q + 7], vertexDataOut[q + 8],
- vertexDataOut[q + 9]);
+ Tangent[i] = CVector4D(vertexDataOut[q + 0], vertexDataOut[q + 1], vertexDataOut[q + 2],
+ vertexDataOut[q + 3]);
+ q += 4;
+
+ if (gpuSkinning)
+ {
+ for (size_t j = 0; j < 4; ++j)
+ {
+ BlendJoints[i][j] = (u8)vertexDataOut[q + 0 + 2 * j];
+ BlendWeights[i][j] = (u8)vertexDataOut[q + 1 + 2 * j];
+ }
+ q += 8;
+ }
for (size_t j = 0; j < mdef->GetNumUVsPerVertex(); j++)
{
VertexArrayIterator UVit = m_UVs[j].GetIterator();
- UVit[i][0] = vertexDataOut[q + 10 + 2 * j];
- UVit[i][1] = vertexDataOut[q + 11 + 2 * j];
+ UVit[i][0] = vertexDataOut[q + 0 + 2 * j];
+ UVit[i][1] = vertexDataOut[q + 1 + 2 * j];
}
}
@@ -169,17 +206,6 @@ IModelDef::IModelDef(const CModelDefPtr& mdef, bool gpuSkinning, bool calculateT
{
// Upload model without calculating tangents:-
- if (gpuSkinning)
- {
- m_BlendJoints.type = GL_UNSIGNED_BYTE;
- m_BlendJoints.elems = 4;
- m_Array.AddAttribute(&m_BlendJoints);
-
- m_BlendWeights.type = GL_UNSIGNED_BYTE;
- m_BlendWeights.elems = 4;
- m_Array.AddAttribute(&m_BlendWeights);
- }
-
m_Array.SetNumVertices(numVertices);
m_Array.Layout();
diff --git a/source/renderer/MikktspaceWrap.cpp b/source/renderer/MikktspaceWrap.cpp
index 8499050f9b..eb10368b6c 100644
--- a/source/renderer/MikktspaceWrap.cpp
+++ b/source/renderer/MikktspaceWrap.cpp
@@ -25,40 +25,42 @@
#include "graphics/ModelDef.h"
#include "graphics/ShaderManager.h"
#include "graphics/TextureManager.h"
-#include "graphics/mikktspace.h"
#include "renderer/MikktspaceWrap.h"
+#include "third_party/mikktspace/mikktspace.h"
-MikkTSpace::MikkTSpace(const CModelDefPtr& m, std::vector& v) : model(m), newVertices(v)
+
+MikkTSpace::MikkTSpace(const CModelDefPtr& m, std::vector& v, bool gpuSkinning) : m_Model(m),
+ m_NewVertices(v), m_GpuSkinning(gpuSkinning)
{
- // ensure that newVertices is empty
- newVertices.clear();
+ // ensure that m_NewVertices is empty
+ m_NewVertices.clear();
// set up SMikkTSpaceInterface struct
- interface.m_getNumFaces = getNumFaces;
- interface.m_getNumVerticesOfFace = getNumVerticesOfFace;
- interface.m_getPosition = getPosition;
- interface.m_getNormal = getNormal;
- interface.m_getTexCoord = getTexCoord;
- interface.m_setTSpaceBasic = NULL;
- 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 = NULL;
+ m_Interface.m_setTSpace = setTSpace;
// set up SMikkTSpaceContext struct
- context.m_pInterface = &interface;
- context.m_pUserData = (void*)this;
+ m_Context.m_pInterface = &m_Interface;
+ m_Context.m_pUserData = (void*)this;
}
void MikkTSpace::generate()
{
- genTangSpaceDefault(&context);
+ genTangSpaceDefault(&m_Context);
}
int MikkTSpace::getNumFaces(const SMikkTSpaceContext *pContext)
{
- return ((MikkTSpace*)pContext->m_pUserData)->model->GetNumFaces();
+ return ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetNumFaces();
}
@@ -71,9 +73,9 @@ int MikkTSpace::getNumVerticesOfFace(const SMikkTSpaceContext* UNUSED(pContext),
void MikkTSpace::getPosition(const SMikkTSpaceContext *pContext,
float fvPosOut[], const int iFace, const int iVert)
{
- SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->model->GetFaces()[iFace];
+ SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace];
long i = face.m_Verts[iVert];
- const CVector3D &p = ((MikkTSpace*)pContext->m_pUserData)->model->GetVertices()[i].m_Coords;
+ const CVector3D &p = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices()[i].m_Coords;
fvPosOut[0] = p.X;
fvPosOut[1] = p.Y;
@@ -84,9 +86,9 @@ void MikkTSpace::getPosition(const SMikkTSpaceContext *pContext,
void MikkTSpace::getNormal(const SMikkTSpaceContext *pContext,
float fvNormOut[], const int iFace, const int iVert)
{
- SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->model->GetFaces()[iFace];
+ SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace];
long i = face.m_Verts[iVert];
- const CVector3D &n = ((MikkTSpace*)pContext->m_pUserData)->model->GetVertices()[i].m_Norm;
+ const CVector3D &n = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices()[i].m_Norm;
fvNormOut[0] = n.X;
fvNormOut[1] = n.Y;
@@ -97,9 +99,9 @@ void MikkTSpace::getNormal(const SMikkTSpaceContext *pContext,
void MikkTSpace::getTexCoord(const SMikkTSpaceContext *pContext,
float fvTexcOut[], const int iFace, const int iVert)
{
- SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->model->GetFaces()[iFace];
+ SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace];
long i = face.m_Verts[iVert];
- SModelVertex &v = ((MikkTSpace*)pContext->m_pUserData)->model->GetVertices()[i];
+ SModelVertex &v = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices()[i];
// the tangents are calculated according to the 'default' UV set
fvTexcOut[0] = v.m_UVs[0];
@@ -111,33 +113,42 @@ void MikkTSpace::setTSpace(const SMikkTSpaceContext * pContext, const float fvTa
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)->model->GetFaces()[iFace];
+ SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace];
long i = face.m_Verts[iVert];
- SModelVertex* vertices = ((MikkTSpace*)pContext->m_pUserData)->model->GetVertices();
- size_t numUVsPerVertex = ((MikkTSpace*)pContext->m_pUserData)->model->GetNumUVsPerVertex();
- std::vector& newVertices = ((MikkTSpace*)pContext->m_pUserData)->newVertices;
+ 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 = vertices[i].m_Coords;
const CVector3D &n = vertices[i].m_Norm;
- newVertices.push_back(p.X);
- newVertices.push_back(p.Y);
- newVertices.push_back(p.Z);
+ m_NewVertices.push_back(p.X);
+ m_NewVertices.push_back(p.Y);
+ m_NewVertices.push_back(p.Z);
- newVertices.push_back(n.X);
- newVertices.push_back(n.Y);
- newVertices.push_back(n.Z);
+ m_NewVertices.push_back(n.X);
+ m_NewVertices.push_back(n.Y);
+ m_NewVertices.push_back(n.Z);
- newVertices.push_back(fvTangent[0]);
- newVertices.push_back(fvTangent[1]);
- newVertices.push_back(fvTangent[2]);
- newVertices.push_back(bIsOrientationPreserving > 0.5 ? 1.0f : (-1.0f));
+ 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)
+ {
+ for (size_t 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]);
+ }
+ }
for (size_t UVset = 0; UVset < numUVsPerVertex; ++UVset)
{
- newVertices.push_back(vertices[i].m_UVs[UVset * 2]);
- newVertices.push_back(1.0 - vertices[i].m_UVs[UVset * 2 + 1]);
+ m_NewVertices.push_back(vertices[i].m_UVs[UVset * 2]);
+ m_NewVertices.push_back(1.0 - vertices[i].m_UVs[UVset * 2 + 1]);
}
}
diff --git a/source/renderer/MikktspaceWrap.h b/source/renderer/MikktspaceWrap.h
index fc8e96a953..afcb59faa3 100644
--- a/source/renderer/MikktspaceWrap.h
+++ b/source/renderer/MikktspaceWrap.h
@@ -1,102 +1,86 @@
-/* Copyright (C) 2012 Wildfire Games.
- * This file is part of 0 A.D.
- *
- * 0 A.D. is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * 0 A.D. is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with 0 A.D. If not, see .
- */
-
-#ifndef INCLUDED_MIKKWRAP
-#define INCLUDED_MIKKWRAP
-
-
-#include "graphics/mikktspace.h"
-
-// Disable useless MSVC warning
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_MIKKWRAP
+#define INCLUDED_MIKKWRAP
+
+
+#include "third_party/mikktspace/mikktspace.h"
+
+// Disable useless MSVC warning
#if MSC_VERSION
# pragma warning(disable:4512) // "assignment operator could not be generated"
-#endif
-
-class MikkTSpace
-{
-
-public:
-
- MikkTSpace(const CModelDefPtr& m, std::vector& v);
-
- void generate();
-
-private:
-
- SMikkTSpaceInterface interface;
- SMikkTSpaceContext context;
-
- const CModelDefPtr& model;
-
- std::vector& newVertices;
-
-
- // 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);
-
-
- // either (or both) of the two setTSpace callbacks can be set.
- // The call-back m_setTSpaceBasic() is sufficient for basic normal mapping.
-
- // This function is used to return the tangent and fSign to the application.
- // fvTangent is a unit length vector.
- // For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level.
- // bitangent = fSign * cross(vN, tangent);
- // Note that the results are returned unindexed. It is possible to generate a new index list
- // But averaging/overwriting tangent spaces by using an already existing index list WILL produce INCRORRECT results.
- // DO NOT! use an already existing index list.
- //void setTSpaceBasic(const MikkTSpace *parent, const SMikkTSpaceContext *pContext,
- // const float fvTangent[], const float fSign, const int iFace, const int iVert);
-
-
- // 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);
- // Note that the results are returned unindexed. It is possible to generate a new index list
- // But averaging/overwriting tangent spaces by using an already existing index list WILL produce INCRORRECT results.
- // DO NOT! use an already existing index list.
- static void setTSpace(const SMikkTSpaceContext * pContext, const float fvTangent[],
- const float fvBiTangent[], const float fMagS, const float fMagT,
- const tbool bIsOrientationPreserving, const int iFace, const int iVert);
-
-
-};
-
-
+#endif
+
+class MikkTSpace
+{
+
+public:
+
+ MikkTSpace(const CModelDefPtr& m, std::vector& v, bool gpuSkinning);
+
+ 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);
+
+
+ // 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,
+ const tbool bIsOrientationPreserving, const int iFace, const int iVert);
+
+
+};
+
+
#endif // INCLUDED_MIKKWRAP
\ No newline at end of file
diff --git a/source/renderer/ModelRenderer.cpp b/source/renderer/ModelRenderer.cpp
index f57cf9d305..8741e1eb44 100644
--- a/source/renderer/ModelRenderer.cpp
+++ b/source/renderer/ModelRenderer.cpp
@@ -149,9 +149,9 @@ void ModelRenderer::BuildColor4ub(
}
-void ModelRenderer::GenTangents(const CModelDefPtr& mdef, std::vector& newVertices)
+void ModelRenderer::GenTangents(const CModelDefPtr& mdef, std::vector& newVertices, bool gpuSkinning)
{
- MikkTSpace ms(mdef, newVertices);
+ MikkTSpace ms(mdef, newVertices, gpuSkinning);
ms.generate();
}
diff --git a/source/renderer/ModelRenderer.h b/source/renderer/ModelRenderer.h
index dde9a359d2..3aed661515 100644
--- a/source/renderer/ModelRenderer.h
+++ b/source/renderer/ModelRenderer.h
@@ -262,7 +262,7 @@ public:
* @param newVertices An out vector of the unindexed vertices with tangents added.
* The new vertices cannot be used with existing face index and must be welded/reindexed.
*/
- static void GenTangents(const CModelDefPtr& mdef, std::vector& newVertices);
+ static void GenTangents(const CModelDefPtr& mdef, std::vector& newVertices, bool gpuSkinning);
};
diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp
index dc487fe3e9..daa9f66a01 100644
--- a/source/renderer/Renderer.cpp
+++ b/source/renderer/Renderer.cpp
@@ -584,7 +584,7 @@ void CRenderer::ReloadShaders()
if (GetRenderPath() == RP_SHADER && m_Options.m_GPUSkinning) // TODO: should check caps and GLSL etc too
{
- m->Model.VertexGPUSkinningShader = ModelVertexRendererPtr(new InstancingModelRenderer(true, false));
+ m->Model.VertexGPUSkinningShader = ModelVertexRendererPtr(new InstancingModelRenderer(true, m_Options.m_GenTangents));
m->Model.NormalSkinned = ModelRendererPtr(new ShaderModelRenderer(m->Model.VertexGPUSkinningShader));
m->Model.TranspSkinned = ModelRendererPtr(new ShaderModelRenderer(m->Model.VertexGPUSkinningShader));
}
diff --git a/source/graphics/mikktspace.cpp b/source/third_party/mikktspace/mikktspace.cpp
similarity index 100%
rename from source/graphics/mikktspace.cpp
rename to source/third_party/mikktspace/mikktspace.cpp
diff --git a/source/graphics/mikktspace.h b/source/third_party/mikktspace/mikktspace.h
similarity index 100%
rename from source/graphics/mikktspace.h
rename to source/third_party/mikktspace/mikktspace.h
diff --git a/source/graphics/weldmesh.cpp b/source/third_party/mikktspace/weldmesh.cpp
similarity index 100%
rename from source/graphics/weldmesh.cpp
rename to source/third_party/mikktspace/weldmesh.cpp
diff --git a/source/graphics/weldmesh.h b/source/third_party/mikktspace/weldmesh.h
similarity index 100%
rename from source/graphics/weldmesh.h
rename to source/third_party/mikktspace/weldmesh.h