Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/mesh_tangent.cc
| Show All 12 Lines | |||||
| #include "DNA_mesh_types.h" | #include "DNA_mesh_types.h" | ||||
| #include "DNA_meshdata_types.h" | #include "DNA_meshdata_types.h" | ||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "BLI_task.h" | #include "BLI_task.h" | ||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "BKE_attribute.hh" | |||||
| #include "BKE_customdata.h" | #include "BKE_customdata.h" | ||||
| #include "BKE_mesh.h" | #include "BKE_mesh.h" | ||||
| #include "BKE_mesh_runtime.h" | #include "BKE_mesh_runtime.h" | ||||
| #include "BKE_mesh_tangent.h" | #include "BKE_mesh_tangent.h" | ||||
| #include "BKE_report.h" | #include "BKE_report.h" | ||||
| #include "BLI_strict_flags.h" | #include "BLI_strict_flags.h" | ||||
| #include "atomic_ops.h" | #include "atomic_ops.h" | ||||
| #include "mikktspace.hh" | #include "mikktspace.hh" | ||||
| using blender::float2; | |||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Mesh Tangent Calculations (Single Layer) | /** \name Mesh Tangent Calculations (Single Layer) | ||||
| * \{ */ | * \{ */ | ||||
| struct BKEMeshToTangent { | struct BKEMeshToTangent { | ||||
| uint GetNumFaces() | uint GetNumFaces() | ||||
| { | { | ||||
| return uint(num_polys); | return uint(num_polys); | ||||
| } | } | ||||
| 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[mloops[loop_idx].v]); | ||||
| } | } | ||||
| 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].uv; | 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 MLoop *mloops; /* faces vertices */ | ||||
| const float (*positions)[3]; /* vertices */ | const float (*positions)[3]; /* vertices */ | ||||
| const MLoopUV *luvs; /* 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 MLoop *mloops, | ||||
| float (*r_looptangent)[4], | float (*r_looptangent)[4], | ||||
| const float (*loop_normals)[3], | const float (*loop_normals)[3], | ||||
| const MLoopUV *loopuvs, | 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.mloops = mloops; | ||||
| mesh_to_tangent.positions = vert_positions; | mesh_to_tangent.positions = vert_positions; | ||||
| mesh_to_tangent.luvs = loopuvs; | 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); | ||||
| /* First check we do have a tris/quads only mesh. */ | /* First check we do have a tris/quads only mesh. */ | ||||
| for (int i = 0; i < numPolys; i++) { | for (int i = 0; i < numPolys; i++) { | ||||
| if (mpolys[i].totloop > 4) { | if (mpolys[i].totloop > 4) { | ||||
| BKE_report( | BKE_report( | ||||
| reports, RPT_ERROR, "Tangent space can only be computed for tris/quads, aborting"); | reports, RPT_ERROR, "Tangent space can only be computed for tris/quads, aborting"); | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| mikk.genTangSpace(); | mikk.genTangSpace(); | ||||
| } | } | ||||
| void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, | void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, | ||||
| const char *uvmap, | const char *uvmap, | ||||
| float (*r_looptangents)[4], | float (*r_looptangents)[4], | ||||
| ReportList *reports) | ReportList *reports) | ||||
| { | { | ||||
| const MLoopUV *loopuvs; | using namespace blender; | ||||
| using namespace blender::bke; | |||||
| /* Check we have valid texture coordinates first! */ | if (!uvmap) { | ||||
| if (uvmap) { | uvmap = CustomData_get_active_layer_name(&mesh->ldata, CD_PROP_FLOAT2); | ||||
| loopuvs = static_cast<MLoopUV *>(CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvmap)); | |||||
| } | |||||
| else { | |||||
| loopuvs = static_cast<MLoopUV *>(CustomData_get_layer(&mesh->ldata, CD_MLOOPUV)); | |||||
| } | } | ||||
| if (!loopuvs) { | |||||
| const AttributeAccessor attributes = mesh->attributes(); | |||||
| const VArraySpan<float2> uv_map = attributes.lookup<float2>(uvmap, ATTR_DOMAIN_CORNER); | |||||
| if (uv_map.is_empty()) { | |||||
| BKE_reportf(reports, | BKE_reportf(reports, | ||||
| RPT_ERROR, | RPT_ERROR, | ||||
| "Tangent space computation needs a UV Map, \"%s\" not found, aborting", | "Tangent space computation needs a UV Map, \"%s\" not found, aborting", | ||||
| uvmap); | uvmap); | ||||
| return; | return; | ||||
| } | } | ||||
| const float(*loop_normals)[3] = static_cast<const float(*)[3]>( | const float(*loop_normals)[3] = static_cast<const float(*)[3]>( | ||||
| CustomData_get_layer(&mesh->ldata, CD_NORMAL)); | CustomData_get_layer(&mesh->ldata, CD_NORMAL)); | ||||
| 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), | BKE_mesh_loops(mesh), | ||||
| r_looptangents, | r_looptangents, | ||||
| loop_normals, | loop_normals, | ||||
| loopuvs, | 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 58 Lines • ▼ Show 20 Lines | mikk::float3 GetPosition(const uint face_num, const uint vert_num) | ||||
| return mikk::float3(positions[mloop[loop_index].v]); | return mikk::float3(positions[mloop[loop_index].v]); | ||||
| } | } | ||||
| 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 float *uv = mloopuv[loop_index].uv; | 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[mloop[loop_index].v]; | ||||
| 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); | ||||
| } | } | ||||
| Show All 37 Lines | void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation) | ||||
| 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 MLoopUV *mloopuv; /* texture coordinates */ | const float2 *mloopuv; /* texture coordinates */ | ||||
| const MPoly *mpoly; /* indices */ | const MPoly *mpoly; /* indices */ | ||||
| const MLoop *mloop; /* indices */ | const MLoop *mloop; /* 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; | ||||
| Show All 14 Lines | |||||
| } | } | ||||
| void BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData *uv_data, | void BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData *uv_data, | ||||
| CustomData *tan_data, | CustomData *tan_data, | ||||
| int numLoopData, | int numLoopData, | ||||
| const char *layer_name) | const char *layer_name) | ||||
| { | { | ||||
| if (CustomData_get_named_layer_index(tan_data, CD_TANGENT, layer_name) == -1 && | if (CustomData_get_named_layer_index(tan_data, CD_TANGENT, layer_name) == -1 && | ||||
| CustomData_get_named_layer_index(uv_data, CD_MLOOPUV, layer_name) != -1) { | CustomData_get_named_layer_index(uv_data, CD_PROP_FLOAT2, layer_name) != -1) { | ||||
| CustomData_add_layer_named( | CustomData_add_layer_named( | ||||
| tan_data, CD_TANGENT, CD_SET_DEFAULT, nullptr, numLoopData, layer_name); | tan_data, CD_TANGENT, CD_SET_DEFAULT, nullptr, numLoopData, layer_name); | ||||
| } | } | ||||
| } | } | ||||
| void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData, | void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData, | ||||
| bool calc_active_tangent, | bool calc_active_tangent, | ||||
| const char (*tangent_names)[MAX_NAME], | const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME], | ||||
| int tangent_names_count, | int tangent_names_count, | ||||
| bool *rcalc_act, | bool *rcalc_act, | ||||
| bool *rcalc_ren, | bool *rcalc_ren, | ||||
| int *ract_uv_n, | int *ract_uv_n, | ||||
| int *rren_uv_n, | int *rren_uv_n, | ||||
| char *ract_uv_name, | char *ract_uv_name, | ||||
| char *rren_uv_name, | char *rren_uv_name, | ||||
| short *rtangent_mask) | short *rtangent_mask) | ||||
| { | { | ||||
| /* Active uv in viewport */ | /* Active uv in viewport */ | ||||
| int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV); | int layer_index = CustomData_get_layer_index(loopData, CD_PROP_FLOAT2); | ||||
| *ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV); | *ract_uv_n = CustomData_get_active_layer(loopData, CD_PROP_FLOAT2); | ||||
| ract_uv_name[0] = 0; | ract_uv_name[0] = 0; | ||||
| if (*ract_uv_n != -1) { | if (*ract_uv_n != -1) { | ||||
| strcpy(ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name); | strcpy(ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name); | ||||
| } | } | ||||
| /* Active tangent in render */ | /* Active tangent in render */ | ||||
| *rren_uv_n = CustomData_get_render_layer(loopData, CD_MLOOPUV); | *rren_uv_n = CustomData_get_render_layer(loopData, CD_PROP_FLOAT2); | ||||
| rren_uv_name[0] = 0; | rren_uv_name[0] = 0; | ||||
| if (*rren_uv_n != -1) { | if (*rren_uv_n != -1) { | ||||
| strcpy(rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name); | strcpy(rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name); | ||||
| } | } | ||||
| /* If active tangent not in tangent_names we take it into account */ | /* If active tangent not in tangent_names we take it into account */ | ||||
| *rcalc_act = false; | *rcalc_act = false; | ||||
| *rcalc_ren = false; | *rcalc_ren = false; | ||||
| Show All 11 Lines | for (int i = 0; i < tangent_names_count; i++) { | ||||
| } | } | ||||
| if (STREQ(rren_uv_name, tangent_names[i])) { | if (STREQ(rren_uv_name, tangent_names[i])) { | ||||
| *rcalc_ren = false; | *rcalc_ren = false; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| *rtangent_mask = 0; | *rtangent_mask = 0; | ||||
| const int uv_layer_num = CustomData_number_of_layers(loopData, CD_MLOOPUV); | const int uv_layer_num = CustomData_number_of_layers(loopData, CD_PROP_FLOAT2); | ||||
| for (int n = 0; n < uv_layer_num; n++) { | for (int n = 0; n < uv_layer_num; n++) { | ||||
| const char *name = CustomData_get_layer_name(loopData, CD_MLOOPUV, n); | const char *name = CustomData_get_layer_name(loopData, CD_PROP_FLOAT2, n); | ||||
| bool add = false; | bool add = false; | ||||
| for (int i = 0; i < tangent_names_count; i++) { | for (int i = 0; i < tangent_names_count; i++) { | ||||
| if (tangent_names[i][0] && STREQ(tangent_names[i], name)) { | if (tangent_names[i][0] && STREQ(tangent_names[i], name)) { | ||||
| add = true; | add = true; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (!add && ((*rcalc_act && ract_uv_name[0] && STREQ(ract_uv_name, name)) || | if (!add && ((*rcalc_act && ract_uv_name[0] && STREQ(ract_uv_name, name)) || | ||||
| Show All 14 Lines | 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 MLoop *mloop, | ||||
| 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_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], | ||||
| const float (*poly_normals)[3], | const float (*poly_normals)[3], | ||||
| const float (*loop_normals)[3], | const float (*loop_normals)[3], | ||||
| const float (*vert_orco)[3], | const float (*vert_orco)[3], | ||||
| /* result */ | /* result */ | ||||
| CustomData *loopdata_out, | CustomData *loopdata_out, | ||||
| const uint loopdata_out_len, | const uint loopdata_out_len, | ||||
| short *tangent_mask_curr_p) | short *tangent_mask_curr_p) | ||||
| { | { | ||||
| int act_uv_n = -1; | int act_uv_n = -1; | ||||
| int ren_uv_n = -1; | int ren_uv_n = -1; | ||||
| bool calc_act = false; | bool calc_act = false; | ||||
| bool calc_ren = false; | bool calc_ren = false; | ||||
| char act_uv_name[MAX_NAME]; | char act_uv_name[MAX_CUSTOMDATA_LAYER_NAME]; | ||||
| char ren_uv_name[MAX_NAME]; | char ren_uv_name[MAX_CUSTOMDATA_LAYER_NAME]; | ||||
| short tangent_mask = 0; | short tangent_mask = 0; | ||||
| short tangent_mask_curr = *tangent_mask_curr_p; | short tangent_mask_curr = *tangent_mask_curr_p; | ||||
| BKE_mesh_calc_loop_tangent_step_0(loopdata, | BKE_mesh_calc_loop_tangent_step_0(loopdata, | ||||
| calc_active_tangent, | calc_active_tangent, | ||||
| tangent_names, | tangent_names, | ||||
| tangent_names_len, | tangent_names_len, | ||||
| &calc_act, | &calc_act, | ||||
| ▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | #endif | ||||
| mesh2tangent->mloop = mloop; | mesh2tangent->mloop = mloop; | ||||
| 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 MLoopUV *>( | mesh2tangent->mloopuv = static_cast<const float2 *>(CustomData_get_layer_named( | ||||
| CustomData_get_layer_named(loopdata, CD_MLOOPUV, loopdata_out->layers[index].name)); | loopdata, CD_PROP_FLOAT2, loopdata_out->layers[index].name)); | ||||
| /* Fill the resulting tangent_mask */ | /* Fill the resulting tangent_mask */ | ||||
| if (!mesh2tangent->mloopuv) { | if (!mesh2tangent->mloopuv) { | ||||
| mesh2tangent->orco = vert_orco; | mesh2tangent->orco = vert_orco; | ||||
| if (!mesh2tangent->orco) { | if (!mesh2tangent->orco) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| tangent_mask_curr |= DM_TANGENT_MASK_ORCO; | tangent_mask_curr |= DM_TANGENT_MASK_ORCO; | ||||
| } | } | ||||
| else { | else { | ||||
| int uv_ind = CustomData_get_named_layer_index( | int uv_ind = CustomData_get_named_layer_index( | ||||
| loopdata, CD_MLOOPUV, loopdata_out->layers[index].name); | loopdata, CD_PROP_FLOAT2, loopdata_out->layers[index].name); | ||||
| int uv_start = CustomData_get_layer_index(loopdata, CD_MLOOPUV); | int uv_start = CustomData_get_layer_index(loopdata, CD_PROP_FLOAT2); | ||||
| BLI_assert(uv_ind != -1 && uv_start != -1); | BLI_assert(uv_ind != -1 && uv_start != -1); | ||||
| BLI_assert(uv_ind - uv_start < MAX_MTFACE); | BLI_assert(uv_ind - uv_start < MAX_MTFACE); | ||||
| tangent_mask_curr |= short(1 << (uv_ind - uv_start)); | tangent_mask_curr |= short(1 << (uv_ind - uv_start)); | ||||
| } | } | ||||
| mesh2tangent->tangent = static_cast<float(*)[4]>(loopdata_out->layers[index].data); | mesh2tangent->tangent = static_cast<float(*)[4]>(loopdata_out->layers[index].data); | ||||
| BLI_task_pool_push(task_pool, DM_calc_loop_tangents_thread, mesh2tangent, false, nullptr); | BLI_task_pool_push(task_pool, DM_calc_loop_tangents_thread, mesh2tangent, false, nullptr); | ||||
| } | } | ||||
| Show All 12 Lines | |||||
| # undef USE_LOOPTRI_DETECT_QUADS | # undef USE_LOOPTRI_DETECT_QUADS | ||||
| #endif | #endif | ||||
| *tangent_mask_curr_p = tangent_mask_curr; | *tangent_mask_curr_p = tangent_mask_curr; | ||||
| /* Update active layer index */ | /* Update active layer index */ | ||||
| int act_uv_index = (act_uv_n != -1) ? | int act_uv_index = (act_uv_n != -1) ? | ||||
| CustomData_get_layer_index_n(loopdata, CD_MLOOPUV, act_uv_n) : | CustomData_get_layer_index_n(loopdata, CD_PROP_FLOAT2, act_uv_n) : | ||||
| -1; | -1; | ||||
| if (act_uv_index != -1) { | if (act_uv_index != -1) { | ||||
| int tan_index = CustomData_get_named_layer_index( | int tan_index = CustomData_get_named_layer_index( | ||||
| loopdata, CD_TANGENT, loopdata->layers[act_uv_index].name); | loopdata, CD_TANGENT, loopdata->layers[act_uv_index].name); | ||||
| CustomData_set_layer_active_index(loopdata, CD_TANGENT, tan_index); | CustomData_set_layer_active_index(loopdata, CD_TANGENT, tan_index); | ||||
| } /* else tangent has been built from orco */ | } /* else tangent has been built from orco */ | ||||
| /* Update render layer index */ | /* Update render layer index */ | ||||
| int ren_uv_index = (ren_uv_n != -1) ? | int ren_uv_index = (ren_uv_n != -1) ? | ||||
| CustomData_get_layer_index_n(loopdata, CD_MLOOPUV, ren_uv_n) : | CustomData_get_layer_index_n(loopdata, CD_PROP_FLOAT2, ren_uv_n) : | ||||
| -1; | -1; | ||||
| if (ren_uv_index != -1) { | if (ren_uv_index != -1) { | ||||
| int tan_index = CustomData_get_named_layer_index( | int tan_index = CustomData_get_named_layer_index( | ||||
| loopdata, CD_TANGENT, loopdata->layers[ren_uv_index].name); | loopdata, CD_TANGENT, loopdata->layers[ren_uv_index].name); | ||||
| CustomData_set_layer_render_index(loopdata, CD_TANGENT, tan_index); | CustomData_set_layer_render_index(loopdata, CD_TANGENT, tan_index); | ||||
| } /* else tangent has been built from orco */ | } /* else tangent has been built from orco */ | ||||
| } | } | ||||
| } | } | ||||
| void BKE_mesh_calc_loop_tangents(Mesh *me_eval, | void BKE_mesh_calc_loop_tangents(Mesh *me_eval, | ||||
| bool calc_active_tangent, | bool calc_active_tangent, | ||||
| const char (*tangent_names)[MAX_NAME], | const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME], | ||||
| 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), | ||||
| Show All 19 Lines | |||||