Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/mesh_tangent.cc
| Show First 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | struct BKEMeshToTangent { | ||||
| uint GetNumVerticesOfFace(const uint face_num) | uint GetNumVerticesOfFace(const uint face_num) | ||||
| { | { | ||||
| return uint(mpolys[face_num].totloop); | return uint(mpolys[face_num].totloop); | ||||
| } | } | ||||
| mikk::float3 GetPosition(const uint face_num, const uint vert_num) | mikk::float3 GetPosition(const uint face_num, const uint vert_num) | ||||
| { | { | ||||
| const uint loop_idx = uint(mpolys[face_num].loopstart) + vert_num; | const uint loop_idx = uint(mpolys[face_num].loopstart) + vert_num; | ||||
| return mikk::float3(positions[mloops[loop_idx].v]); | return mikk::float3(positions[corner_verts[loop_idx]]); | ||||
| } | } | ||||
| mikk::float3 GetTexCoord(const uint face_num, const uint vert_num) | mikk::float3 GetTexCoord(const uint face_num, const uint vert_num) | ||||
| { | { | ||||
| const float *uv = luvs[uint(mpolys[face_num].loopstart) + vert_num]; | const float *uv = luvs[uint(mpolys[face_num].loopstart) + vert_num]; | ||||
| return mikk::float3(uv[0], uv[1], 1.0f); | return mikk::float3(uv[0], uv[1], 1.0f); | ||||
| } | } | ||||
| mikk::float3 GetNormal(const uint face_num, const uint vert_num) | mikk::float3 GetNormal(const uint face_num, const uint vert_num) | ||||
| { | { | ||||
| return mikk::float3(loop_normals[uint(mpolys[face_num].loopstart) + vert_num]); | return mikk::float3(loop_normals[uint(mpolys[face_num].loopstart) + vert_num]); | ||||
| } | } | ||||
| void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation) | void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation) | ||||
| { | { | ||||
| float *p_res = tangents[uint(mpolys[face_num].loopstart) + vert_num]; | float *p_res = tangents[uint(mpolys[face_num].loopstart) + vert_num]; | ||||
| copy_v4_fl4(p_res, T.x, T.y, T.z, orientation ? 1.0f : -1.0f); | copy_v4_fl4(p_res, T.x, T.y, T.z, orientation ? 1.0f : -1.0f); | ||||
| } | } | ||||
| const MPoly *mpolys; /* faces */ | const MPoly *mpolys; /* faces */ | ||||
| const MLoop *mloops; /* faces vertices */ | const int *corner_verts; /* faces vertices */ | ||||
| const float (*positions)[3]; /* vertices */ | const float (*positions)[3]; /* vertices */ | ||||
| const float (*luvs)[2]; /* texture coordinates */ | const float (*luvs)[2]; /* texture coordinates */ | ||||
| const float (*loop_normals)[3]; /* loops' normals */ | const float (*loop_normals)[3]; /* loops' normals */ | ||||
| float (*tangents)[4]; /* output tangents */ | float (*tangents)[4]; /* output tangents */ | ||||
| int num_polys; /* number of polygons */ | int num_polys; /* number of polygons */ | ||||
| }; | }; | ||||
| void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3], | void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3], | ||||
| const int /*numVerts*/, | const int /*numVerts*/, | ||||
| const MLoop *mloops, | const int *corner_verts, | ||||
| float (*r_looptangent)[4], | float (*r_looptangent)[4], | ||||
| const float (*loop_normals)[3], | const float (*loop_normals)[3], | ||||
| const float (*loop_uvs)[2], | const float (*loop_uvs)[2], | ||||
| const int /*numLoops*/, | const int /*numLoops*/, | ||||
| const MPoly *mpolys, | const MPoly *mpolys, | ||||
| const int numPolys, | const int numPolys, | ||||
| ReportList *reports) | ReportList *reports) | ||||
| { | { | ||||
| /* Compute Mikktspace's tangent normals. */ | /* Compute Mikktspace's tangent normals. */ | ||||
| BKEMeshToTangent mesh_to_tangent; | BKEMeshToTangent mesh_to_tangent; | ||||
| mesh_to_tangent.mpolys = mpolys; | mesh_to_tangent.mpolys = mpolys; | ||||
| mesh_to_tangent.mloops = mloops; | mesh_to_tangent.corner_verts = corner_verts; | ||||
| mesh_to_tangent.positions = vert_positions; | mesh_to_tangent.positions = vert_positions; | ||||
| mesh_to_tangent.luvs = loop_uvs; | mesh_to_tangent.luvs = loop_uvs; | ||||
| mesh_to_tangent.loop_normals = loop_normals; | mesh_to_tangent.loop_normals = loop_normals; | ||||
| mesh_to_tangent.tangents = r_looptangent; | mesh_to_tangent.tangents = r_looptangent; | ||||
| mesh_to_tangent.num_polys = numPolys; | mesh_to_tangent.num_polys = numPolys; | ||||
| mikk::Mikktspace<BKEMeshToTangent> mikk(mesh_to_tangent); | mikk::Mikktspace<BKEMeshToTangent> mikk(mesh_to_tangent); | ||||
| Show All 36 Lines | void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, | ||||
| if (!loop_normals) { | if (!loop_normals) { | ||||
| BKE_report( | BKE_report( | ||||
| reports, RPT_ERROR, "Tangent space computation needs loop normals, none found, aborting"); | reports, RPT_ERROR, "Tangent space computation needs loop normals, none found, aborting"); | ||||
| return; | return; | ||||
| } | } | ||||
| BKE_mesh_calc_loop_tangent_single_ex(BKE_mesh_vert_positions(mesh), | BKE_mesh_calc_loop_tangent_single_ex(BKE_mesh_vert_positions(mesh), | ||||
| mesh->totvert, | mesh->totvert, | ||||
| BKE_mesh_loops(mesh), | mesh->corner_verts().data(), | ||||
| r_looptangents, | r_looptangents, | ||||
| loop_normals, | loop_normals, | ||||
| reinterpret_cast<const float(*)[2]>(uv_map.data()), | reinterpret_cast<const float(*)[2]>(uv_map.data()), | ||||
| mesh->totloop, | mesh->totloop, | ||||
| BKE_mesh_polys(mesh), | BKE_mesh_polys(mesh), | ||||
| mesh->totpoly, | mesh->totpoly, | ||||
| reports); | reports); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
| #endif | #endif | ||||
| return lt->tri[vert_num]; | return lt->tri[vert_num]; | ||||
| } | } | ||||
| mikk::float3 GetPosition(const uint face_num, const uint vert_num) | mikk::float3 GetPosition(const uint face_num, const uint vert_num) | ||||
| { | { | ||||
| const MLoopTri *lt; | const MLoopTri *lt; | ||||
| uint loop_index = GetLoop(face_num, vert_num, lt); | uint loop_index = GetLoop(face_num, vert_num, lt); | ||||
| return mikk::float3(positions[mloop[loop_index].v]); | return mikk::float3(positions[corner_verts[loop_index]]); | ||||
| } | } | ||||
| mikk::float3 GetTexCoord(const uint face_num, const uint vert_num) | mikk::float3 GetTexCoord(const uint face_num, const uint vert_num) | ||||
| { | { | ||||
| const MLoopTri *lt; | const MLoopTri *lt; | ||||
| uint loop_index = GetLoop(face_num, vert_num, lt); | uint loop_index = GetLoop(face_num, vert_num, lt); | ||||
| if (mloopuv != nullptr) { | if (mloopuv != nullptr) { | ||||
| const float2 &uv = mloopuv[loop_index]; | const float2 &uv = mloopuv[loop_index]; | ||||
| return mikk::float3(uv[0], uv[1], 1.0f); | return mikk::float3(uv[0], uv[1], 1.0f); | ||||
| } | } | ||||
| const float *l_orco = orco[mloop[loop_index].v]; | const float *l_orco = orco[corner_verts[loop_index]]; | ||||
| float u, v; | float u, v; | ||||
| map_to_sphere(&u, &v, l_orco[0], l_orco[1], l_orco[2]); | map_to_sphere(&u, &v, l_orco[0], l_orco[1], l_orco[2]); | ||||
| return mikk::float3(u, v, 1.0f); | return mikk::float3(u, v, 1.0f); | ||||
| } | } | ||||
| mikk::float3 GetNormal(const uint face_num, const uint vert_num) | mikk::float3 GetNormal(const uint face_num, const uint vert_num) | ||||
| { | { | ||||
| const MLoopTri *lt; | const MLoopTri *lt; | ||||
| uint loop_index = GetLoop(face_num, vert_num, lt); | uint loop_index = GetLoop(face_num, vert_num, lt); | ||||
| if (precomputedLoopNormals) { | if (precomputedLoopNormals) { | ||||
| return mikk::float3(precomputedLoopNormals[loop_index]); | return mikk::float3(precomputedLoopNormals[loop_index]); | ||||
| } | } | ||||
| if ((mpoly[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */ | if ((mpoly[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */ | ||||
| if (precomputedFaceNormals) { | if (precomputedFaceNormals) { | ||||
| return mikk::float3(precomputedFaceNormals[lt->poly]); | return mikk::float3(precomputedFaceNormals[lt->poly]); | ||||
| } | } | ||||
| #ifdef USE_LOOPTRI_DETECT_QUADS | #ifdef USE_LOOPTRI_DETECT_QUADS | ||||
| const MPoly *mp = &mpoly[lt->poly]; | const MPoly *mp = &mpoly[lt->poly]; | ||||
| float normal[3]; | float normal[3]; | ||||
| if (mp->totloop == 4) { | if (mp->totloop == 4) { | ||||
| normal_quad_v3(normal, | normal_quad_v3(normal, | ||||
| positions[mloop[mp->loopstart + 0].v], | positions[corner_verts[mp->loopstart + 0]], | ||||
| positions[mloop[mp->loopstart + 1].v], | positions[corner_verts[mp->loopstart + 1]], | ||||
| positions[mloop[mp->loopstart + 2].v], | positions[corner_verts[mp->loopstart + 2]], | ||||
| positions[mloop[mp->loopstart + 3].v]); | positions[corner_verts[mp->loopstart + 3]]); | ||||
| } | } | ||||
| else | else | ||||
| #endif | #endif | ||||
| { | { | ||||
| normal_tri_v3(normal, | normal_tri_v3(normal, | ||||
| positions[mloop[lt->tri[0]].v], | positions[corner_verts[lt->tri[0]]], | ||||
| positions[mloop[lt->tri[1]].v], | positions[corner_verts[lt->tri[1]]], | ||||
| positions[mloop[lt->tri[2]].v]); | positions[corner_verts[lt->tri[2]]]); | ||||
| } | } | ||||
| return mikk::float3(normal); | return mikk::float3(normal); | ||||
| } | } | ||||
| return mikk::float3(vert_normals[mloop[loop_index].v]); | return mikk::float3(vert_normals[corner_verts[loop_index]]); | ||||
| } | } | ||||
| void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation) | void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation) | ||||
| { | { | ||||
| const MLoopTri *lt; | const MLoopTri *lt; | ||||
| uint loop_index = GetLoop(face_num, vert_num, lt); | uint loop_index = GetLoop(face_num, vert_num, lt); | ||||
| copy_v4_fl4(tangent[loop_index], T.x, T.y, T.z, orientation ? 1.0f : -1.0f); | copy_v4_fl4(tangent[loop_index], T.x, T.y, T.z, orientation ? 1.0f : -1.0f); | ||||
| } | } | ||||
| const float (*precomputedFaceNormals)[3]; | const float (*precomputedFaceNormals)[3]; | ||||
| const float (*precomputedLoopNormals)[3]; | const float (*precomputedLoopNormals)[3]; | ||||
| const MLoopTri *looptri; | const MLoopTri *looptri; | ||||
| const float2 *mloopuv; /* texture coordinates */ | const float2 *mloopuv; /* texture coordinates */ | ||||
| const MPoly *mpoly; /* indices */ | const MPoly *mpoly; /* indices */ | ||||
| const MLoop *mloop; /* indices */ | const int *corner_verts; /* indices */ | ||||
| const float (*positions)[3]; /* vertex coordinates */ | const float (*positions)[3]; /* vertex coordinates */ | ||||
| const float (*vert_normals)[3]; | const float (*vert_normals)[3]; | ||||
| const float (*orco)[3]; | const float (*orco)[3]; | ||||
| float (*tangent)[4]; /* destination */ | float (*tangent)[4]; /* destination */ | ||||
| int numTessFaces; | int numTessFaces; | ||||
| #ifdef USE_LOOPTRI_DETECT_QUADS | #ifdef USE_LOOPTRI_DETECT_QUADS | ||||
| /* map from 'fake' face index to looptri, | /* map from 'fake' face index to looptri, | ||||
| ▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData, | ||||
| if (uv_layer_num == 0) { | if (uv_layer_num == 0) { | ||||
| *rtangent_mask |= DM_TANGENT_MASK_ORCO; | *rtangent_mask |= DM_TANGENT_MASK_ORCO; | ||||
| } | } | ||||
| } | } | ||||
| void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3], | void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3], | ||||
| const MPoly *mpoly, | const MPoly *mpoly, | ||||
| const uint mpoly_len, | const uint mpoly_len, | ||||
| const MLoop *mloop, | const int *corner_verts, | ||||
| const MLoopTri *looptri, | const MLoopTri *looptri, | ||||
| const uint looptri_len, | const uint looptri_len, | ||||
| CustomData *loopdata, | CustomData *loopdata, | ||||
| bool calc_active_tangent, | bool calc_active_tangent, | ||||
| const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME], | const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME], | ||||
| int tangent_names_len, | int tangent_names_len, | ||||
| const float (*vert_normals)[3], | const float (*vert_normals)[3], | ||||
| ▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | if (looptri_len != 0) { | ||||
| mesh2tangent->numTessFaces = int(looptri_len); | mesh2tangent->numTessFaces = int(looptri_len); | ||||
| #ifdef USE_LOOPTRI_DETECT_QUADS | #ifdef USE_LOOPTRI_DETECT_QUADS | ||||
| mesh2tangent->face_as_quad_map = face_as_quad_map; | mesh2tangent->face_as_quad_map = face_as_quad_map; | ||||
| mesh2tangent->num_face_as_quad_map = num_face_as_quad_map; | mesh2tangent->num_face_as_quad_map = num_face_as_quad_map; | ||||
| #endif | #endif | ||||
| mesh2tangent->positions = vert_positions; | mesh2tangent->positions = vert_positions; | ||||
| mesh2tangent->vert_normals = vert_normals; | mesh2tangent->vert_normals = vert_normals; | ||||
| mesh2tangent->mpoly = mpoly; | mesh2tangent->mpoly = mpoly; | ||||
| mesh2tangent->mloop = mloop; | mesh2tangent->corner_verts = corner_verts; | ||||
| mesh2tangent->looptri = looptri; | mesh2tangent->looptri = looptri; | ||||
| /* NOTE: we assume we do have tessellated loop normals at this point | /* NOTE: we assume we do have tessellated loop normals at this point | ||||
| * (in case it is object-enabled), have to check this is valid. */ | * (in case it is object-enabled), have to check this is valid. */ | ||||
| mesh2tangent->precomputedLoopNormals = loop_normals; | mesh2tangent->precomputedLoopNormals = loop_normals; | ||||
| mesh2tangent->precomputedFaceNormals = poly_normals; | mesh2tangent->precomputedFaceNormals = poly_normals; | ||||
| mesh2tangent->orco = nullptr; | mesh2tangent->orco = nullptr; | ||||
| mesh2tangent->mloopuv = static_cast<const float2 *>(CustomData_get_layer_named( | mesh2tangent->mloopuv = static_cast<const float2 *>(CustomData_get_layer_named( | ||||
| ▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | void BKE_mesh_calc_loop_tangents(Mesh *me_eval, | ||||
| int tangent_names_len) | int tangent_names_len) | ||||
| { | { | ||||
| /* TODO(@campbellbarton): store in Mesh.runtime to avoid recalculation. */ | /* TODO(@campbellbarton): store in Mesh.runtime to avoid recalculation. */ | ||||
| short tangent_mask = 0; | short tangent_mask = 0; | ||||
| BKE_mesh_calc_loop_tangent_ex( | BKE_mesh_calc_loop_tangent_ex( | ||||
| BKE_mesh_vert_positions(me_eval), | BKE_mesh_vert_positions(me_eval), | ||||
| BKE_mesh_polys(me_eval), | BKE_mesh_polys(me_eval), | ||||
| uint(me_eval->totpoly), | uint(me_eval->totpoly), | ||||
| BKE_mesh_loops(me_eval), | me_eval->corner_verts().data(), | ||||
| BKE_mesh_runtime_looptri_ensure(me_eval), | BKE_mesh_runtime_looptri_ensure(me_eval), | ||||
| uint(BKE_mesh_runtime_looptri_len(me_eval)), | uint(BKE_mesh_runtime_looptri_len(me_eval)), | ||||
| &me_eval->ldata, | &me_eval->ldata, | ||||
| calc_active_tangent, | calc_active_tangent, | ||||
| tangent_names, | tangent_names, | ||||
| tangent_names_len, | tangent_names_len, | ||||
| BKE_mesh_vertex_normals_ensure(me_eval), | BKE_mesh_vertex_normals_ensure(me_eval), | ||||
| BKE_mesh_poly_normals_ensure(me_eval), | BKE_mesh_poly_normals_ensure(me_eval), | ||||
| Show All 10 Lines | |||||