Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to pre-calculate the model's tangent #81

Closed
xkyl-yhw opened this issue Sep 26, 2023 · 4 comments
Closed

how to pre-calculate the model's tangent #81

xkyl-yhw opened this issue Sep 26, 2023 · 4 comments

Comments

@xkyl-yhw
Copy link

In the structure, there has the varible called "vertex_tangent". I use it without consideration, but unfortunate it didn't exist. I wonder how to open the option to calculate the tangent?

@xkyl-yhw
Copy link
Author

Never Mind. I figure it out. I use blender to calculate the tangent vector which contain in the fbx file. I recommod to add a new option to calculate the tangent vector.

@bqqbarbhg
Copy link
Collaborator

bqqbarbhg commented Sep 29, 2023

Yeah I considered adding tangent calculation but it's actually very complicated to get right, and in practice most people will want to use mikktspace to stay compatible with other software.

@xkyl-yhw xkyl-yhw reopened this Oct 9, 2023
@xkyl-yhw
Copy link
Author

xkyl-yhw commented Oct 9, 2023

I highly recommend to add the method of tangent calculate. I try to use the mikktspace. Refer to https://www.turais.de/using-mikktspace-in-your-project/, I build the conection between mikktspace and ufbx_mesh. Here is my code.

`
#include "calc_mikktspace_tangent.h"
#include
#include <fmt/format.h>

CalcMikkTSpaceTangent::CalcMikkTSpaceTangent()
{
iface.m_getNumFaces = get_num_faces;
iface.m_getNumVerticesOfFace = get_num_vertices_of_face;

iface.m_getNormal = get_normal;
iface.m_getPosition = get_position;
iface.m_getTexCoord = get_tex_coords;
iface.m_setTSpaceBasic = set_tspace_basic;

context.m_pInterface = &iface;

}

void CalcMikkTSpaceTangent::calc(ufbx_mesh* mesh)
{
context.m_pUserData = mesh;

genTangSpaceDefault(&this->context);

}

int CalcMikkTSpaceTangent::get_vertex_index (const SMikkTSpaceContext* context, int iFace, int iVert)
{
ufbx_mesh* _mesh = static_cast<ufbx_mesh*> (context->m_pUserData);

auto face_size = get_num_vertices_of_face(context, iFace);

auto indices_index = (iFace * face_size) + iVert;

int index = _mesh->vertex_indices[indices_index];

return index;

}

int CalcMikkTSpaceTangent::get_num_faces (const SMikkTSpaceContext* context)
{
ufbx_mesh* _mesh = static_cast<ufbx_mesh*> (context->m_pUserData);
float f_size = (float)_mesh->num_indices / 3.f;
int i_size = (int)_mesh->num_indices / 3;

//assert((f_size - (float)i_size) == 0.f);

return i_size;

}

int CalcMikkTSpaceTangent::get_num_vertices_of_face (const SMikkTSpaceContext* context, int iFace)
{
return 3;
}

void CalcMikkTSpaceTangent::get_position (const SMikkTSpaceContext* context, float outpos[], int iFace, int iVert)
{
ufbx_mesh* _mesh = static_cast<ufbx_mesh*> (context->m_pUserData);

auto index = get_vertex_index(context, iFace, iVert);
auto vertex = _mesh->vertex_position[index];

outpos[0] = vertex.x;
outpos[1] = vertex.y;
outpos[2] = vertex.z;

}

void CalcMikkTSpaceTangent::get_normal (const SMikkTSpaceContext* context, float outnormal[], int iFace, int iVert)
{
ufbx_mesh* _mesh = static_cast<ufbx_mesh*> (context->m_pUserData);

auto index = get_vertex_index(context, iFace, iVert);
auto normal = _mesh->vertex_normal[index];

outnormal[0] = normal.x;
outnormal[1] = normal.y;
outnormal[2] = normal.z;

}

void CalcMikkTSpaceTangent::get_tex_coords (const SMikkTSpaceContext* context, float outuv[], int iFace, int iVert)
{
ufbx_mesh* _mesh = static_cast<ufbx_mesh*> (context->m_pUserData);

auto index = get_vertex_index(context, iFace, iVert);
auto uv = _mesh->vertex_uv[index];

outuv[0] = uv.x;
outuv[1] = uv.y;

}

void CalcMikkTSpaceTangent::set_tspace_basic (const SMikkTSpaceContext* context, const float tangentu[], float fSign, int iFace, int iVert)
{
ufbx_mesh* _mesh = static_cast<ufbx_mesh*> (context->m_pUserData);

auto index = get_vertex_index(context, iFace, iVert);
auto* tangent = &_mesh->vertex_tangent[index];

tangent->x = tangentu[0];
tangent->y = tangentu[1];
tangent->z = tangentu[2];

}
`

Here are two problem.

  1. The result didn't go well, the normal is total wrong.
  2. Only the fbx which had calculate the tangent in blender can override tangent. That why I think should add the support between the ufbx and mikktspace.

@bqqbarbhg
Copy link
Collaborator

Hmm, adding callbacks to external mikktspace would be an option for sure.

It looks like it doesn't support N-gons:

static int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
{
	int iTSpacesOffs = 0, f=0, t=0;
	int iDstTriIndex = 0;
	for (f=0; f<pContext->m_pInterface->m_getNumFaces(pContext); f++)
	{
		const int verts = pContext->m_pInterface->m_getNumVerticesOfFace(pContext, f);
		if (verts!=3 && verts!=4) continue;

This will make integrating it a lot harder as ufbx would need to create some sort of temporary face mapping with triangulated N-gons.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants