#pragma once #if !defined(MIJIN_GEO_TANGENT_GENERATION_HPP_INCLUDED) #define MIJIN_GEO_TANGENT_GENERATION_HPP_INCLUDED 1 #include #include "./geometry_traits.hpp" namespace mijin { namespace impl { template struct MikktData { Mesh3DTraits traits; Vector2Traits vec2Traits; Vector3Traits vec3Traits; Vector4Traits vec4Traits; TMesh* mesh; }; template int mikktGetNumFaces(const SMikkTSpaceContext* context) { const MikktData& data = *static_cast*>(context->m_pUserData); return static_cast(data.traits.getNumFaces(*data.mesh)); } template int mikktGetNumVerticesOfFace(const SMikkTSpaceContext* context, const int face) { const MikktData& data = *static_cast*>(context->m_pUserData); return static_cast(data.traits.getFaceNumVertices(*data.mesh, face)); } template void mikktGetPosition(const SMikkTSpaceContext* context, float posOut[], const int face, const int vert) // NOLINT { const MikktData& data = *static_cast*>(context->m_pUserData); const auto position = data.traits.getPosition(*data.mesh, face, vert); posOut[0] = data.vec3Traits.getX(position); posOut[1] = data.vec3Traits.getY(position); posOut[2] = data.vec3Traits.getZ(position); } template void mikktGetNormal(const SMikkTSpaceContext* context, float normOut[], const int face, const int vert) // NOLINT { const MikktData& data = *static_cast*>(context->m_pUserData); const auto normal = data.traits.getNormal(*data.mesh, face, vert); normOut[0] = data.vec3Traits.getX(normal); normOut[1] = data.vec3Traits.getY(normal); normOut[2] = data.vec3Traits.getZ(normal); } template void mikktGetTexCoord(const SMikkTSpaceContext* context, float texcOut[], const int face, const int vert) // NOLINT { const MikktData& data = *static_cast*>(context->m_pUserData); const auto texCoord = data.traits.getTexCoord(*data.mesh, face, vert); texcOut[0] = data.vec2Traits.getX(texCoord); texcOut[1] = data.vec2Traits.getY(texCoord); } template void mikktSetTSpaceBasic(const SMikkTSpaceContext* context, const float resultTangent[], const float sign, const int face, const int vert) // NOLINT { const MikktData& data = *static_cast*>(context->m_pUserData); typename Mesh3DTraits::vector4_t tangent; data.vec4Traits.setX(tangent, resultTangent[0]); data.vec4Traits.setY(tangent, resultTangent[1]); data.vec4Traits.setZ(tangent, resultTangent[2]); data.vec4Traits.setW(tangent, sign); data.traits.setTangent(*data.mesh, face, vert, tangent); } } template bool generateTangentsMikkt(TMesh& mesh) { SMikkTSpaceInterface mikktInterface = { .m_getNumFaces = &impl::mikktGetNumFaces, .m_getNumVerticesOfFace = &impl::mikktGetNumVerticesOfFace, .m_getPosition = &impl::mikktGetPosition, .m_getNormal = &impl::mikktGetNormal, .m_getTexCoord = &impl::mikktGetTexCoord, .m_setTSpaceBasic = &impl::mikktSetTSpaceBasic }; impl::MikktData data = { .mesh = &mesh }; const SMikkTSpaceContext context = { .m_pInterface = &mikktInterface, .m_pUserData = &data }; return genTangSpaceDefault(&context); } } #endif // MIJIN_GEO_TANGENT_GENERATION_HPP_INCLUDED