/* 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 . */ #include "precompiled.h" #include #include "graphics/Color.h" #include "graphics/LightEnv.h" #include "graphics/Model.h" #include "graphics/ModelDef.h" #include "graphics/ShaderManager.h" #include "graphics/TextureManager.h" #include "renderer/MikktspaceWrap.h" #include "third_party/mikktspace/mikktspace.h" MikkTSpace::MikkTSpace(const CModelDefPtr& m, std::vector& v, bool gpuSkinning) : m_Model(m), m_NewVertices(v), m_GpuSkinning(gpuSkinning) { // ensure that m_NewVertices is empty m_NewVertices.clear(); // set up SMikkTSpaceInterface struct 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 m_Context.m_pInterface = &m_Interface; m_Context.m_pUserData = (void*)this; } void MikkTSpace::generate() { genTangSpaceDefault(&m_Context); } int MikkTSpace::getNumFaces(const SMikkTSpaceContext *pContext) { return ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetNumFaces(); } int MikkTSpace::getNumVerticesOfFace(const SMikkTSpaceContext* UNUSED(pContext), const int UNUSED(iFace)) { return 3; } void MikkTSpace::getPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) { SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace]; long i = face.m_Verts[iVert]; const CVector3D &p = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices()[i].m_Coords; fvPosOut[0] = p.X; fvPosOut[1] = p.Y; fvPosOut[2] = p.Z; } void MikkTSpace::getNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) { SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace]; long i = face.m_Verts[iVert]; const CVector3D &n = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetVertices()[i].m_Norm; fvNormOut[0] = n.X; fvNormOut[1] = n.Y; fvNormOut[2] = n.Z; } void MikkTSpace::getTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) { SModelFace &face = ((MikkTSpace*)pContext->m_pUserData)->m_Model->GetFaces()[iFace]; long i = face.m_Verts[iVert]; 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]; fvTexcOut[1] = 1.0-v.m_UVs[1]; } void MikkTSpace::setTSpace(const SMikkTSpaceContext * pContext, const float fvTangent[], 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)->m_Model->GetFaces()[iFace]; long i = face.m_Verts[iVert]; 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; m_NewVertices.push_back(p.X); m_NewVertices.push_back(p.Y); m_NewVertices.push_back(p.Z); m_NewVertices.push_back(n.X); m_NewVertices.push_back(n.Y); m_NewVertices.push_back(n.Z); 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) { m_NewVertices.push_back(vertices[i].m_UVs[UVset * 2]); m_NewVertices.push_back(1.0 - vertices[i].m_UVs[UVset * 2 + 1]); } }