Skip to content

Commit a51d334

Browse files
committed
Merge branch 'master' of https://github.com/raysan5/raylib
2 parents 9d4c315 + 15a0cf8 commit a51d334

File tree

7 files changed

+110
-54
lines changed

7 files changed

+110
-54
lines changed

build.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
256256
raylib.root_module.linkSystemLibrary("GLESv2", .{});
257257
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES2", "");
258258
}
259+
raylib.root_module.linkSystemLibrary("EGL", .{});
259260

260261
setDesktopPlatform(raylib, .android);
261262
} else {

parser/output/raylib_api.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3139,7 +3139,7 @@
31393139
"name": "fileName"
31403140
},
31413141
{
3142-
"type": "char *",
3142+
"type": "const char *",
31433143
"name": "text"
31443144
}
31453145
]
@@ -4409,7 +4409,7 @@
44094409
"name": "fileName"
44104410
},
44114411
{
4412-
"type": "char *",
4412+
"type": "const char *",
44134413
"name": "text"
44144414
}
44154415
]
@@ -4707,7 +4707,7 @@
47074707
"returnType": "unsigned char *",
47084708
"params": [
47094709
{
4710-
"type": "const unsigned char *",
4710+
"type": "const char *",
47114711
"name": "data"
47124712
},
47134713
{

parser/output/raylib_api.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3108,7 +3108,7 @@ return {
31083108
returnType = "bool",
31093109
params = {
31103110
{type = "const char *", name = "fileName"},
3111-
{type = "char *", name = "text"}
3111+
{type = "const char *", name = "text"}
31123112
}
31133113
},
31143114
{
@@ -4006,7 +4006,7 @@ return {
40064006
returnType = "bool",
40074007
params = {
40084008
{type = "const char *", name = "fileName"},
4009-
{type = "char *", name = "text"}
4009+
{type = "const char *", name = "text"}
40104010
}
40114011
},
40124012
{
@@ -4211,7 +4211,7 @@ return {
42114211
description = "Decode Base64 string data, memory must be MemFree()",
42124212
returnType = "unsigned char *",
42134213
params = {
4214-
{type = "const unsigned char *", name = "data"},
4214+
{type = "const char *", name = "data"},
42154215
{type = "int *", name = "outputSize"}
42164216
}
42174217
},

parser/output/raylib_api.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ Callback 005: SaveFileTextCallback() (2 input parameters)
985985
Return type: bool
986986
Description: FileIO: Save text data
987987
Param[1]: fileName (type: const char *)
988-
Param[2]: text (type: char *)
988+
Param[2]: text (type: const char *)
989989
Callback 006: AudioCallback() (2 input parameters)
990990
Name: AudioCallback
991991
Return type: void
@@ -1656,7 +1656,7 @@ Function 123: SaveFileText() (2 input parameters)
16561656
Return type: bool
16571657
Description: Save text data to file (write), string must be '\0' terminated, returns true on success
16581658
Param[1]: fileName (type: const char *)
1659-
Param[2]: text (type: char *)
1659+
Param[2]: text (type: const char *)
16601660
Function 124: FileExists() (1 input parameters)
16611661
Name: FileExists
16621662
Return type: bool
@@ -1795,7 +1795,7 @@ Function 149: DecodeDataBase64() (2 input parameters)
17951795
Name: DecodeDataBase64
17961796
Return type: unsigned char *
17971797
Description: Decode Base64 string data, memory must be MemFree()
1798-
Param[1]: data (type: const unsigned char *)
1798+
Param[1]: data (type: const char *)
17991799
Param[2]: outputSize (type: int *)
18001800
Function 150: ComputeCRC32() (2 input parameters)
18011801
Name: ComputeCRC32

parser/output/raylib_api.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@
672672
</Callback>
673673
<Callback name="SaveFileTextCallback" retType="bool" paramCount="2" desc="FileIO: Save text data">
674674
<Param type="const char *" name="fileName" desc="" />
675-
<Param type="char *" name="text" desc="" />
675+
<Param type="const char *" name="text" desc="" />
676676
</Callback>
677677
<Callback name="AudioCallback" retType="void" paramCount="2" desc="">
678678
<Param type="void *" name="bufferData" desc="" />
@@ -1046,7 +1046,7 @@
10461046
</Function>
10471047
<Function name="SaveFileText" retType="bool" paramCount="2" desc="Save text data to file (write), string must be '\0' terminated, returns true on success">
10481048
<Param type="const char *" name="fileName" desc="" />
1049-
<Param type="char *" name="text" desc="" />
1049+
<Param type="const char *" name="text" desc="" />
10501050
</Function>
10511051
<Function name="FileExists" retType="bool" paramCount="1" desc="Check if file exists">
10521052
<Param type="const char *" name="fileName" desc="" />
@@ -1129,7 +1129,7 @@
11291129
<Param type="int *" name="outputSize" desc="" />
11301130
</Function>
11311131
<Function name="DecodeDataBase64" retType="unsigned char *" paramCount="2" desc="Decode Base64 string data, memory must be MemFree()">
1132-
<Param type="const unsigned char *" name="data" desc="" />
1132+
<Param type="const char *" name="data" desc="" />
11331133
<Param type="int *" name="outputSize" desc="" />
11341134
</Function>
11351135
<Function name="ComputeCRC32" retType="unsigned int" paramCount="2" desc="Compute CRC32 hash code">

src/raylib.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,7 @@ typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args);
954954
typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data
955955
typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data
956956
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
957-
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
957+
typedef bool (*SaveFileTextCallback)(const char *fileName, const char *text); // FileIO: Save text data
958958

959959
//------------------------------------------------------------------------------------
960960
// Global Variables Definition

src/rmodels.c

Lines changed: 96 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3608,109 +3608,164 @@ BoundingBox GetMeshBoundingBox(Mesh mesh)
36083608
}
36093609

36103610
// Compute mesh tangents
3611-
// NOTE: To calculate mesh tangents and binormals we need mesh vertex positions and texture coordinates
3612-
// Implementation based on: https://answers.unity.com/questions/7789/calculating-tangents-vector4.html
36133611
void GenMeshTangents(Mesh *mesh)
36143612
{
3615-
if ((mesh->vertices == NULL) || (mesh->texcoords == NULL))
3613+
// Check if input mesh data is useful
3614+
if ((mesh == NULL) || (mesh->vertices == NULL) || (mesh->texcoords == NULL) || (mesh->normals == NULL))
36163615
{
3617-
TRACELOG(LOG_WARNING, "MESH: Tangents generation requires texcoord vertex attribute data");
3616+
TRACELOG(LOG_WARNING, "MESH: Tangents generation requires vertices, texcoords and normals vertex attribute data");
36183617
return;
36193618
}
36203619

3620+
// Allocate or reallocate tangents data
36213621
if (mesh->tangents == NULL) mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));
36223622
else
36233623
{
36243624
RL_FREE(mesh->tangents);
36253625
mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));
36263626
}
36273627

3628-
Vector3 *tan1 = (Vector3 *)RL_MALLOC(mesh->vertexCount*sizeof(Vector3));
3629-
Vector3 *tan2 = (Vector3 *)RL_MALLOC(mesh->vertexCount*sizeof(Vector3));
3628+
// Allocate temporary arrays for tangents calculation
3629+
Vector3 *tan1 = (Vector3 *)RL_CALLOC(mesh->vertexCount, sizeof(Vector3));
3630+
Vector3 *tan2 = (Vector3 *)RL_CALLOC(mesh->vertexCount, sizeof(Vector3));
36303631

3631-
if (mesh->vertexCount % 3 != 0)
3632+
if (tan1 == NULL || tan2 == NULL)
36323633
{
3633-
TRACELOG(LOG_WARNING, "MESH: vertexCount expected to be a multiple of 3. Expect uninitialized values.");
3634+
TRACELOG(LOG_WARNING, "MESH: Failed to allocate temporary memory for tangent calculation");
3635+
if (tan1) RL_FREE(tan1);
3636+
if (tan2) RL_FREE(tan2);
3637+
return;
36343638
}
36353639

3636-
for (int i = 0; i <= mesh->vertexCount - 3; i += 3)
3640+
// Process all triangles of the mesh
3641+
// 'triangleCount' must be always valid
3642+
for (int t = 0; t < mesh->triangleCount; t++)
36373643
{
3638-
// Get triangle vertices
3639-
Vector3 v1 = { mesh->vertices[(i + 0)*3 + 0], mesh->vertices[(i + 0)*3 + 1], mesh->vertices[(i + 0)*3 + 2] };
3640-
Vector3 v2 = { mesh->vertices[(i + 1)*3 + 0], mesh->vertices[(i + 1)*3 + 1], mesh->vertices[(i + 1)*3 + 2] };
3641-
Vector3 v3 = { mesh->vertices[(i + 2)*3 + 0], mesh->vertices[(i + 2)*3 + 1], mesh->vertices[(i + 2)*3 + 2] };
3644+
// Get triangle vertex indices
3645+
int i0, i1, i2;
3646+
3647+
if (mesh->indices != NULL)
3648+
{
3649+
// Use indices if available
3650+
i0 = mesh->indices[t*3 + 0];
3651+
i1 = mesh->indices[t*3 + 1];
3652+
i2 = mesh->indices[t*3 + 2];
3653+
}
3654+
else
3655+
{
3656+
// Sequential access for non-indexed mesh
3657+
i0 = t*3 + 0;
3658+
i1 = t*3 + 1;
3659+
i2 = t*3 + 2;
3660+
}
3661+
3662+
// Get triangle vertices position
3663+
Vector3 v1 = { mesh->vertices[i0*3 + 0], mesh->vertices[i0*3 + 1], mesh->vertices[i0*3 + 2] };
3664+
Vector3 v2 = { mesh->vertices[i1*3 + 0], mesh->vertices[i1*3 + 1], mesh->vertices[i1*3 + 2] };
3665+
Vector3 v3 = { mesh->vertices[i2*3 + 0], mesh->vertices[i2*3 + 1], mesh->vertices[i2*3 + 2] };
36423666

36433667
// Get triangle texcoords
3644-
Vector2 uv1 = { mesh->texcoords[(i + 0)*2 + 0], mesh->texcoords[(i + 0)*2 + 1] };
3645-
Vector2 uv2 = { mesh->texcoords[(i + 1)*2 + 0], mesh->texcoords[(i + 1)*2 + 1] };
3646-
Vector2 uv3 = { mesh->texcoords[(i + 2)*2 + 0], mesh->texcoords[(i + 2)*2 + 1] };
3668+
Vector2 uv1 = { mesh->texcoords[i0*2 + 0], mesh->texcoords[i0*2 + 1] };
3669+
Vector2 uv2 = { mesh->texcoords[i1*2 + 0], mesh->texcoords[i1*2 + 1] };
3670+
Vector2 uv3 = { mesh->texcoords[i2*2 + 0], mesh->texcoords[i2*2 + 1] };
36473671

3672+
// Calculate triangle edges
36483673
float x1 = v2.x - v1.x;
36493674
float y1 = v2.y - v1.y;
36503675
float z1 = v2.z - v1.z;
36513676
float x2 = v3.x - v1.x;
36523677
float y2 = v3.y - v1.y;
36533678
float z2 = v3.z - v1.z;
36543679

3680+
// Calculate texture coordinate differences
36553681
float s1 = uv2.x - uv1.x;
36563682
float t1 = uv2.y - uv1.y;
36573683
float s2 = uv3.x - uv1.x;
36583684
float t2 = uv3.y - uv1.y;
36593685

3686+
// Calculate denominator and check for degenerate UV
36603687
float div = s1*t2 - s2*t1;
3661-
float r = (div == 0.0f)? 0.0f : 1.0f/div;
3688+
float r = (fabsf(div) < 0.0001f)? 0.0f : 1.0f/div;
36623689

3690+
// Calculate tangent and bitangent directions
36633691
Vector3 sdir = { (t2*x1 - t1*x2)*r, (t2*y1 - t1*y2)*r, (t2*z1 - t1*z2)*r };
36643692
Vector3 tdir = { (s1*x2 - s2*x1)*r, (s1*y2 - s2*y1)*r, (s1*z2 - s2*z1)*r };
36653693

3666-
tan1[i + 0] = sdir;
3667-
tan1[i + 1] = sdir;
3668-
tan1[i + 2] = sdir;
3694+
// Accumulate tangents and bitangents for each vertex of the triangle
3695+
tan1[i0] = Vector3Add(tan1[i0], sdir);
3696+
tan1[i1] = Vector3Add(tan1[i1], sdir);
3697+
tan1[i2] = Vector3Add(tan1[i2], sdir);
36693698

3670-
tan2[i + 0] = tdir;
3671-
tan2[i + 1] = tdir;
3672-
tan2[i + 2] = tdir;
3699+
tan2[i0] = Vector3Add(tan2[i0], tdir);
3700+
tan2[i1] = Vector3Add(tan2[i1], tdir);
3701+
tan2[i2] = Vector3Add(tan2[i2], tdir);
36733702
}
36743703

3675-
// Compute tangents considering normals
3704+
// Calculate final tangents for each vertex
36763705
for (int i = 0; i < mesh->vertexCount; i++)
36773706
{
36783707
Vector3 normal = { mesh->normals[i*3 + 0], mesh->normals[i*3 + 1], mesh->normals[i*3 + 2] };
36793708
Vector3 tangent = tan1[i];
36803709

3681-
// TODO: Review, not sure if tangent computation is right, just used reference proposed maths...
3682-
#if defined(COMPUTE_TANGENTS_METHOD_01)
3683-
Vector3 tmp = Vector3Subtract(tangent, Vector3Scale(normal, Vector3DotProduct(normal, tangent)));
3684-
tmp = Vector3Normalize(tmp);
3685-
mesh->tangents[i*4 + 0] = tmp.x;
3686-
mesh->tangents[i*4 + 1] = tmp.y;
3687-
mesh->tangents[i*4 + 2] = tmp.z;
3688-
mesh->tangents[i*4 + 3] = 1.0f;
3689-
#else
3690-
Vector3OrthoNormalize(&normal, &tangent);
3691-
mesh->tangents[i*4 + 0] = tangent.x;
3692-
mesh->tangents[i*4 + 1] = tangent.y;
3693-
mesh->tangents[i*4 + 2] = tangent.z;
3694-
mesh->tangents[i*4 + 3] = (Vector3DotProduct(Vector3CrossProduct(normal, tangent), tan2[i]) < 0.0f)? -1.0f : 1.0f;
3695-
#endif
3710+
// Handle zero tangent (can happen with degenerate UVs)
3711+
if (Vector3Length(tangent) < 0.0001f)
3712+
{
3713+
// Create a tangent perpendicular to the normal
3714+
if (fabsf(normal.z) > 0.707f) tangent = (Vector3){ 1.0f, 0.0f, 0.0f };
3715+
else tangent = Vector3Normalize((Vector3){ -normal.y, normal.x, 0.0f });
3716+
3717+
mesh->tangents[i*4 + 0] = tangent.x;
3718+
mesh->tangents[i*4 + 1] = tangent.y;
3719+
mesh->tangents[i*4 + 2] = tangent.z;
3720+
mesh->tangents[i*4 + 3] = 1.0f;
3721+
continue;
3722+
}
3723+
3724+
// Gram-Schmidt orthogonalization to make tangent orthogonal to normal
3725+
// T_prime = T - N * dot(N, T)
3726+
Vector3 orthogonalized = Vector3Subtract(tangent, Vector3Scale(normal, Vector3DotProduct(normal, tangent)));
3727+
3728+
// Handle cases where orthogonalized vector is too small
3729+
if (Vector3Length(orthogonalized) < 0.0001f)
3730+
{
3731+
// Create a tangent perpendicular to the normal
3732+
if (fabsf(normal.z) > 0.707f) orthogonalized = (Vector3){ 1.0f, 0.0f, 0.0f };
3733+
else orthogonalized = Vector3Normalize((Vector3){ -normal.y, normal.x, 0.0f });
3734+
}
3735+
else
3736+
{
3737+
// Normalize the orthogonalized tangent
3738+
orthogonalized = Vector3Normalize(orthogonalized);
3739+
}
3740+
3741+
// Store the calculated tangent
3742+
mesh->tangents[i*4 + 0] = orthogonalized.x;
3743+
mesh->tangents[i*4 + 1] = orthogonalized.y;
3744+
mesh->tangents[i*4 + 2] = orthogonalized.z;
3745+
3746+
// Calculate the handedness (w component)
3747+
mesh->tangents[i*4 + 3] = (Vector3DotProduct(Vector3CrossProduct(normal, orthogonalized), tan2[i]) < 0.0f)? -1.0f : 1.0f;
36963748
}
36973749

3750+
// Free temporary arrays
36983751
RL_FREE(tan1);
36993752
RL_FREE(tan2);
37003753

3754+
// Update vertex buffers if available
37013755
if (mesh->vboId != NULL)
37023756
{
37033757
if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0)
37043758
{
3705-
// Update existing vertex buffer
3759+
// Update existing tangent vertex buffer
37063760
rlUpdateVertexBuffer(mesh->vboId[SHADER_LOC_VERTEX_TANGENT], mesh->tangents, mesh->vertexCount*4*sizeof(float), 0);
37073761
}
37083762
else
37093763
{
3710-
// Load a new tangent attributes buffer
3764+
// Create new tangent vertex buffer
37113765
mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false);
37123766
}
37133767

3768+
// Set up vertex attributes for shader
37143769
rlEnableVertexArray(mesh->vaoId);
37153770
rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, 4, RL_FLOAT, 0, 0, 0);
37163771
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT);

0 commit comments

Comments
 (0)