103 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #if !defined(MIJIN_GEO_TANGENT_GENERATION_HPP_INCLUDED)
 | |
| #define MIJIN_GEO_TANGENT_GENERATION_HPP_INCLUDED 1
 | |
| 
 | |
| #include <mikktspace.h>
 | |
| #include "./geometry_traits.hpp"
 | |
| 
 | |
| namespace mijin
 | |
| {
 | |
| namespace impl
 | |
| {
 | |
| template<FullMesh3D TMesh>
 | |
| struct MikktData
 | |
| {
 | |
|     Mesh3DTraits<TMesh> traits;
 | |
|     Vector2Traits<typename TMesh::vector2_t> vec2Traits;
 | |
|     Vector3Traits<typename TMesh::vector3_t> vec3Traits;
 | |
|     Vector4Traits<typename TMesh::vector4_t> vec4Traits;
 | |
|     TMesh* mesh;
 | |
| };
 | |
| 
 | |
| template<FullMesh3D TMesh>
 | |
| int mikktGetNumFaces(const SMikkTSpaceContext* context)
 | |
| {
 | |
|     const MikktData<TMesh>& data = *static_cast<MikktData<TMesh>*>(context->m_pUserData);
 | |
|     return static_cast<int>(data.traits.getNumFaces(*data.mesh));
 | |
| }
 | |
| 
 | |
| template<FullMesh3D TMesh>
 | |
| int mikktGetNumVerticesOfFace(const SMikkTSpaceContext* context, const int face)
 | |
| {
 | |
|     const MikktData<TMesh>& data = *static_cast<MikktData<TMesh>*>(context->m_pUserData);
 | |
|     return static_cast<int>(data.traits.getFaceNumVertices(*data.mesh, face));
 | |
| }
 | |
| 
 | |
| template<FullMesh3D TMesh>
 | |
| void mikktGetPosition(const SMikkTSpaceContext* context, float posOut[], const int face, const int vert) // NOLINT
 | |
| {
 | |
|     const MikktData<TMesh>& data = *static_cast<MikktData<TMesh>*>(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<FullMesh3D TMesh>
 | |
| void mikktGetNormal(const SMikkTSpaceContext* context, float normOut[], const int face, const int vert) // NOLINT
 | |
| {
 | |
|     const MikktData<TMesh>& data = *static_cast<MikktData<TMesh>*>(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<FullMesh3D TMesh>
 | |
| void mikktGetTexCoord(const SMikkTSpaceContext* context, float texcOut[], const int face, const int vert) // NOLINT
 | |
| {
 | |
|     const MikktData<TMesh>& data = *static_cast<MikktData<TMesh>*>(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<FullMesh3D TMesh>
 | |
| void mikktSetTSpaceBasic(const SMikkTSpaceContext* context, const float resultTangent[], const float sign, const int face, const int vert) // NOLINT
 | |
| {
 | |
|     const MikktData<TMesh>& data = *static_cast<MikktData<TMesh>*>(context->m_pUserData);
 | |
|     typename Mesh3DTraits<TMesh>::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<FullMesh3D TMesh>
 | |
| bool generateTangentsMikkt(TMesh& mesh)
 | |
| {
 | |
|     SMikkTSpaceInterface mikktInterface = {
 | |
|         .m_getNumFaces = &impl::mikktGetNumFaces<TMesh>,
 | |
|         .m_getNumVerticesOfFace = &impl::mikktGetNumVerticesOfFace<TMesh>,
 | |
|         .m_getPosition = &impl::mikktGetPosition<TMesh>,
 | |
|         .m_getNormal = &impl::mikktGetNormal<TMesh>,
 | |
|         .m_getTexCoord = &impl::mikktGetTexCoord<TMesh>,
 | |
|         .m_setTSpaceBasic = &impl::mikktSetTSpaceBasic<TMesh>
 | |
|     };
 | |
|     impl::MikktData<TMesh> data = {
 | |
|         .mesh = &mesh
 | |
|     };
 | |
|     const SMikkTSpaceContext context = {
 | |
|         .m_pInterface = &mikktInterface,
 | |
|         .m_pUserData = &data
 | |
|     };
 | |
|     return genTangSpaceDefault(&context);
 | |
| }
 | |
| }
 | |
| 
 | |
| #endif // MIJIN_GEO_TANGENT_GENERATION_HPP_INCLUDED
 |