Skip to content

Commit 03fd335

Browse files
authored
Merge pull request #39 from MikePehel/opt/trail-batching
opt: batch trail rendering and fix ribbon twisting
2 parents 76ecd2f + e3f2bd9 commit 03fd335

File tree

1 file changed

+29
-20
lines changed

1 file changed

+29
-20
lines changed

src/vehicle.c

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@ void vehicle_draw(vehicle_t *v, view_mode_t view_mode, bool selected,
437437
col_roll_neg = (Color){ 255, 40, 80, 255 }; // red (port)
438438
}
439439

440+
// Batched line trail: single rlBegin/rlEnd instead of per-segment DrawLine3D
441+
rlBegin(RL_LINES);
440442
for (int i = 1; i < v->trail_count; i++) {
441443
int idx0 = (start + i - 1) % v->trail_capacity;
442444
int idx1 = (start + i) % v->trail_capacity;
@@ -485,23 +487,26 @@ void vehicle_draw(vehicle_t *v, view_mode_t view_mode, bool selected,
485487
cb += (col_roll_neg.b - cb) * rt * 0.7f;
486488
}
487489

488-
Color c;
489-
c.r = (unsigned char)(cr > 255 ? 255 : cr);
490-
c.g = (unsigned char)(cg > 255 ? 255 : cg);
491-
c.b = (unsigned char)(cb > 255 ? 255 : cb);
492-
c.a = (unsigned char)(t * trail_color.a);
493-
DrawLine3D(v->trail[idx0], v->trail[idx1], c);
490+
unsigned char ccr = (unsigned char)(cr > 255 ? 255 : cr);
491+
unsigned char ccg = (unsigned char)(cg > 255 ? 255 : cg);
492+
unsigned char ccb = (unsigned char)(cb > 255 ? 255 : cb);
493+
unsigned char ca = (unsigned char)(t * trail_color.a);
494+
rlColor4ub(ccr, ccg, ccb, ca);
495+
rlVertex3f(v->trail[idx0].x, v->trail[idx0].y, v->trail[idx0].z);
496+
rlVertex3f(v->trail[idx1].x, v->trail[idx1].y, v->trail[idx1].z);
494497
}
498+
rlEnd();
495499
} else {
496500
// ── Speed ribbon trail (mode 2) ──
497-
// Precompute per-vertex perpendicular by averaging adjacent segment
498-
// directions so ribbon edges flow smoothly at joints.
501+
// Batched triangle ribbon: single rlBegin/rlEnd instead of per-quad DrawTriangle3D.
502+
// Perpendicular blending (70% previous + 30% current) prevents twisting on tight turns.
499503
float max_speed = v->trail_speed_max > 1.0f ? v->trail_speed_max : 1.0f;
500504
float max_half_w = v->model_scale * 0.25f;
501505
float min_half_w = 0.02f;
502506
Vector3 prev_perp = {0};
503507
bool have_prev = false;
504508

509+
rlBegin(RL_TRIANGLES);
505510
for (int i = 1; i < v->trail_count; i++) {
506511
int idx0 = (start + i - 1) % v->trail_capacity;
507512
int idx1 = (start + i) % v->trail_capacity;
@@ -518,16 +523,14 @@ void vehicle_draw(vehicle_t *v, view_mode_t view_mode, bool selected,
518523

519524
// Compute perpendicular: use world-up cross for horizontal flight,
520525
// camera-based billboard for vertical flight
521-
float vert = fabsf(dir.y);
526+
float vt = fabsf(dir.y);
522527
Vector3 perp;
523-
if (vert < 0.7f) {
524-
// Mostly horizontal: cross with world up
528+
if (vt < 0.7f) {
525529
Vector3 up = { 0, 1, 0 };
526530
perp = (Vector3){ dir.z * up.y - dir.y * up.z,
527531
dir.x * up.z - dir.z * up.x,
528532
dir.y * up.x - dir.x * up.y };
529533
} else {
530-
// Mostly vertical: cross with world forward (Z)
531534
Vector3 fwd = { 0, 0, 1 };
532535
perp = (Vector3){ dir.y * fwd.z - dir.z * fwd.y,
533536
dir.z * fwd.x - dir.x * fwd.z,
@@ -541,12 +544,16 @@ void vehicle_draw(vehicle_t *v, view_mode_t view_mode, bool selected,
541544
perp.x /= plen; perp.y /= plen; perp.z /= plen;
542545
}
543546

544-
// Ensure consistent orientation (don't flip side-to-side)
547+
// Ensure consistent orientation then blend with previous to reduce twisting
545548
if (have_prev) {
546549
float dot = perp.x*prev_perp.x + perp.y*prev_perp.y + perp.z*prev_perp.z;
547-
if (dot < 0.0f) {
548-
perp.x = -perp.x; perp.y = -perp.y; perp.z = -perp.z;
549-
}
550+
if (dot < 0.0f) { perp.x = -perp.x; perp.y = -perp.y; perp.z = -perp.z; }
551+
float blend = 0.3f;
552+
perp.x = prev_perp.x * (1.0f - blend) + perp.x * blend;
553+
perp.y = prev_perp.y * (1.0f - blend) + perp.y * blend;
554+
perp.z = prev_perp.z * (1.0f - blend) + perp.z * blend;
555+
float nlen = sqrtf(perp.x*perp.x + perp.y*perp.y + perp.z*perp.z);
556+
if (nlen > 0.001f) { perp.x /= nlen; perp.y /= nlen; perp.z /= nlen; }
550557
}
551558
prev_perp = perp;
552559
have_prev = true;
@@ -574,11 +581,13 @@ void vehicle_draw(vehicle_t *v, view_mode_t view_mode, bool selected,
574581
Vector3 d = { p1.x + perp.x*hw1, p1.y + perp.y*hw1, p1.z + perp.z*hw1 };
575582
Vector3 e = { p1.x - perp.x*hw1, p1.y - perp.y*hw1, p1.z - perp.z*hw1 };
576583

577-
DrawTriangle3D(a, b, d, c);
578-
DrawTriangle3D(b, e, d, c);
579-
DrawTriangle3D(d, b, a, c);
580-
DrawTriangle3D(d, e, b, c);
584+
rlColor4ub(c.r, c.g, c.b, c.a);
585+
rlVertex3f(a.x, a.y, a.z); rlVertex3f(b.x, b.y, b.z); rlVertex3f(d.x, d.y, d.z);
586+
rlVertex3f(b.x, b.y, b.z); rlVertex3f(e.x, e.y, e.z); rlVertex3f(d.x, d.y, d.z);
587+
rlVertex3f(d.x, d.y, d.z); rlVertex3f(b.x, b.y, b.z); rlVertex3f(a.x, a.y, a.z);
588+
rlVertex3f(d.x, d.y, d.z); rlVertex3f(e.x, e.y, e.z); rlVertex3f(b.x, b.y, b.z);
581589
}
590+
rlEnd();
582591
}
583592
}
584593

0 commit comments

Comments
 (0)