|
37 | 37 | #include "scene/main/scene_tree.h" |
38 | 38 | #include "scene/resources/3d/navigation_mesh_source_geometry_data_3d.h" |
39 | 39 | #include "scene/resources/navigation_mesh.h" |
| 40 | +#include "scene/resources/surface_tool.h" |
40 | 41 | #include "servers/rendering/rendering_server.h" |
41 | 42 |
|
42 | 43 | #ifdef DEV_ENABLED |
@@ -541,58 +542,42 @@ CSGBrush *CSGShape3D::_get_brush() { |
541 | 542 | return brush; |
542 | 543 | } |
543 | 544 |
|
544 | | -int CSGShape3D::mikktGetNumFaces(const SMikkTSpaceContext *pContext) { |
545 | | - ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); |
| 545 | +static void _generate_tangents_unindexed(float *p_tangents, size_t p_count, const Vector3 *p_positions, const Vector3 *p_normals, const Vector2 *p_uvs) { |
| 546 | + ERR_FAIL_COND_MSG(!SurfaceTool::generate_tangents_func, "Meshoptimizer library is not initialized."); |
| 547 | + ERR_FAIL_COND(p_count % 3 != 0); |
546 | 548 |
|
547 | | - return surface.vertices.size() / 3; |
548 | | -} |
549 | | - |
550 | | -int CSGShape3D::mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace) { |
551 | | - // always 3 |
552 | | - return 3; |
553 | | -} |
554 | | - |
555 | | -void CSGShape3D::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) { |
556 | | - ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); |
557 | | - |
558 | | - Vector3 v = surface.verticesw[iFace * 3 + iVert]; |
559 | | - fvPosOut[0] = v.x; |
560 | | - fvPosOut[1] = v.y; |
561 | | - fvPosOut[2] = v.z; |
562 | | -} |
563 | | - |
564 | | -void CSGShape3D::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) { |
565 | | - ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); |
| 549 | + if (p_count == 0) { |
| 550 | + return; |
| 551 | + } |
566 | 552 |
|
567 | | - Vector3 n = surface.normalsw[iFace * 3 + iVert]; |
568 | | - fvNormOut[0] = n.x; |
569 | | - fvNormOut[1] = n.y; |
570 | | - fvNormOut[2] = n.z; |
571 | | -} |
| 553 | + struct TangentVertex { |
| 554 | + float position[3]; |
| 555 | + float normal[3]; |
| 556 | + float uv[2]; |
| 557 | + }; |
572 | 558 |
|
573 | | -void CSGShape3D::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) { |
574 | | - ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); |
| 559 | + // We can't operate on input arrays directly because in double-precision builds, vectors use double components |
| 560 | + // So we convert the inputs to single precision floats before generating tangents. |
| 561 | + LocalVector<TangentVertex> tangent_vertices; |
| 562 | + tangent_vertices.resize(p_count); |
575 | 563 |
|
576 | | - Vector2 t = surface.uvsw[iFace * 3 + iVert]; |
577 | | - fvTexcOut[0] = t.x; |
578 | | - fvTexcOut[1] = t.y; |
579 | | -} |
| 564 | + for (size_t i = 0; i < p_count; i++) { |
| 565 | + TangentVertex &tangent_vertex = tangent_vertices[i]; |
580 | 566 |
|
581 | | -void CSGShape3D::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, |
582 | | - const tbool bIsOrientationPreserving, const int iFace, const int iVert) { |
583 | | - ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); |
584 | | - |
585 | | - int i = iFace * 3 + iVert; |
586 | | - Vector3 normal = surface.normalsw[i]; |
587 | | - Vector3 tangent = Vector3(fvTangent[0], fvTangent[1], fvTangent[2]); |
588 | | - Vector3 bitangent = Vector3(-fvBiTangent[0], -fvBiTangent[1], -fvBiTangent[2]); // for some reason these are reversed, something with the coordinate system in Godot |
589 | | - float d = bitangent.dot(normal.cross(tangent)); |
| 567 | + tangent_vertex.position[0] = p_positions[i].x; |
| 568 | + tangent_vertex.position[1] = p_positions[i].y; |
| 569 | + tangent_vertex.position[2] = p_positions[i].z; |
| 570 | + tangent_vertex.normal[0] = p_normals[i].x; |
| 571 | + tangent_vertex.normal[1] = p_normals[i].y; |
| 572 | + tangent_vertex.normal[2] = p_normals[i].z; |
| 573 | + tangent_vertex.uv[0] = p_uvs[i].x; |
| 574 | + tangent_vertex.uv[1] = p_uvs[i].y; |
| 575 | + } |
590 | 576 |
|
591 | | - i *= 4; |
592 | | - surface.tansw[i++] = tangent.x; |
593 | | - surface.tansw[i++] = tangent.y; |
594 | | - surface.tansw[i++] = tangent.z; |
595 | | - surface.tansw[i++] = d < 0 ? -1 : 1; |
| 577 | + SurfaceTool::generate_tangents_func(p_tangents, nullptr, p_count, |
| 578 | + tangent_vertices.ptr()->position, p_count, sizeof(TangentVertex), |
| 579 | + tangent_vertices.ptr()->normal, sizeof(TangentVertex), |
| 580 | + tangent_vertices.ptr()->uv, sizeof(TangentVertex), 0); |
596 | 581 | } |
597 | 582 |
|
598 | 583 | void CSGShape3D::update_shape() { |
@@ -624,21 +609,11 @@ void CSGShape3D::update_shape() { |
624 | 609 |
|
625 | 610 | for (int i = 0; i < surfaces.size(); i++) { |
626 | 611 | // calculate tangents for this surface |
627 | | - bool have_tangents = calculate_tangents; |
| 612 | + bool have_tangents = calculate_tangents && SurfaceTool::generate_tangents_func; |
628 | 613 | if (have_tangents) { |
629 | | - SMikkTSpaceInterface mkif; |
630 | | - mkif.m_getNormal = mikktGetNormal; |
631 | | - mkif.m_getNumFaces = mikktGetNumFaces; |
632 | | - mkif.m_getNumVerticesOfFace = mikktGetNumVerticesOfFace; |
633 | | - mkif.m_getPosition = mikktGetPosition; |
634 | | - mkif.m_getTexCoord = mikktGetTexCoord; |
635 | | - mkif.m_setTSpace = mikktSetTSpaceDefault; |
636 | | - mkif.m_setTSpaceBasic = nullptr; |
637 | | - |
638 | | - SMikkTSpaceContext msc; |
639 | | - msc.m_pInterface = &mkif; |
640 | | - msc.m_pUserData = &surfaces.write[i]; |
641 | | - have_tangents = genTangSpaceDefault(&msc); |
| 614 | + ShapeUpdateSurface &surface = surfaces.write[i]; |
| 615 | + |
| 616 | + _generate_tangents_unindexed(surface.tansw, surface.vertices.size(), surface.verticesw, surface.normalsw, surface.uvsw); |
642 | 617 | } |
643 | 618 |
|
644 | 619 | if (surfaces[i].last_added == 0) { |
|
0 commit comments