Skip to content

Commit 4d074ea

Browse files
committed
Merge pull request #120829 from zeux/csg-tangents
Switch CSG tangent generation to meshopt_generateTangents
2 parents 6815eff + 14c934b commit 4d074ea

2 files changed

Lines changed: 37 additions & 73 deletions

File tree

modules/csg/csg_shape.cpp

Lines changed: 35 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "scene/main/scene_tree.h"
3838
#include "scene/resources/3d/navigation_mesh_source_geometry_data_3d.h"
3939
#include "scene/resources/navigation_mesh.h"
40+
#include "scene/resources/surface_tool.h"
4041
#include "servers/rendering/rendering_server.h"
4142

4243
#ifdef DEV_ENABLED
@@ -541,58 +542,42 @@ CSGBrush *CSGShape3D::_get_brush() {
541542
return brush;
542543
}
543544

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);
546548

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+
}
566552

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+
};
572558

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);
575563

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];
580566

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+
}
590576

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);
596581
}
597582

598583
void CSGShape3D::update_shape() {
@@ -624,21 +609,11 @@ void CSGShape3D::update_shape() {
624609

625610
for (int i = 0; i < surfaces.size(); i++) {
626611
// calculate tangents for this surface
627-
bool have_tangents = calculate_tangents;
612+
bool have_tangents = calculate_tangents && SurfaceTool::generate_tangents_func;
628613
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);
642617
}
643618

644619
if (surfaces[i].last_added == 0) {

modules/csg/csg_shape.h

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@
3939
#include "scene/resources/3d/concave_polygon_shape_3d.h"
4040
#endif // PHYSICS_3D_DISABLED
4141

42-
#include <thirdparty/misc/mikktspace.h>
43-
4442
class Mesh;
4543
class NavigationMesh;
4644
class NavigationMeshSourceGeometryData3D;
@@ -90,25 +88,16 @@ class CSGShape3D : public GeometryInstance3D {
9088
Vector<Vector3> vertices;
9189
Vector<Vector3> normals;
9290
Vector<Vector2> uvs;
93-
Vector<real_t> tans;
91+
Vector<float> tans;
9492
Ref<Material> material;
9593
int last_added = 0;
9694

9795
Vector3 *verticesw = nullptr;
9896
Vector3 *normalsw = nullptr;
9997
Vector2 *uvsw = nullptr;
100-
real_t *tansw = nullptr;
98+
float *tansw = nullptr;
10199
};
102100

103-
//mikktspace callbacks
104-
static int mikktGetNumFaces(const SMikkTSpaceContext *pContext);
105-
static int mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace);
106-
static void mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert);
107-
static void mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert);
108-
static void mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert);
109-
static void mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
110-
const tbool bIsOrientationPreserving, const int iFace, const int iVert);
111-
112101
#ifndef PHYSICS_3D_DISABLED
113102
void _update_collision_faces();
114103
bool _is_debug_collision_shape_visible();

0 commit comments

Comments
 (0)