Skip to content

Commit de95f59

Browse files
committed
feat: added GJK+EPA, updated example 6 with GJK demo, updated renderer API with GJK camera culling
1 parent f5d809f commit de95f59

File tree

10 files changed

+834
-279
lines changed

10 files changed

+834
-279
lines changed

examples/example_basic_6.c

Lines changed: 115 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Index of this file:
4747
#include "pl_draw_ext.h"
4848
#include "pl_starter_ext.h"
4949
#include "pl_collision_ext.h"
50+
#include "pl_gjk_ext.h"
5051
#include "pl_screen_log_ext.h"
5152

5253
//-----------------------------------------------------------------------------
@@ -95,6 +96,7 @@ const plGraphicsI* gptGfx = NULL;
9596
const plDrawI* gptDraw = NULL;
9697
const plStarterI* gptStarter = NULL;
9798
const plCollisionI* gptCollision = NULL;
99+
const plGjkI* gptGjk = NULL;
98100
const plScreenLogI* gptScreenLog = NULL;
99101

100102
//-----------------------------------------------------------------------------
@@ -133,6 +135,7 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData)
133135
gptDraw = pl_get_api_latest(ptApiRegistry, plDrawI);
134136
gptStarter = pl_get_api_latest(ptApiRegistry, plStarterI);
135137
gptCollision = pl_get_api_latest(ptApiRegistry, plCollisionI);
138+
gptGjk = pl_get_api_latest(ptApiRegistry, plGjkI);
136139
gptScreenLog = pl_get_api_latest(ptApiRegistry, plScreenLogI);
137140

138141
return ptAppData;
@@ -159,6 +162,7 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData)
159162
gptDraw = pl_get_api_latest(ptApiRegistry, plDrawI);
160163
gptStarter = pl_get_api_latest(ptApiRegistry, plStarterI);
161164
gptCollision = pl_get_api_latest(ptApiRegistry, plCollisionI);
165+
gptGjk = pl_get_api_latest(ptApiRegistry, plGjkI);
162166
gptScreenLog = pl_get_api_latest(ptApiRegistry, plScreenLogI);
163167

164168
// use window API to create a window
@@ -275,13 +279,19 @@ pl_app_update(plAppData* ptAppData)
275279

276280
// simple variation setting to check things (until gizmo extension is stable)
277281
static uint32_t uVariation = 0;
278-
if(gptIO->is_key_pressed(PL_KEY_V, false))
282+
if(gptIO->is_key_pressed(PL_KEY_V, false) && uVariation < 3)
279283
uVariation++;
280-
if(gptIO->is_key_pressed(PL_KEY_B, false))
284+
if(gptIO->is_key_pressed(PL_KEY_B, false) && uVariation > 0)
281285
uVariation--;
282286

283-
// use screen log extension to display variation
287+
// toggle GJK mode
288+
static bool bUseGjk = false;
289+
if(gptIO->is_key_pressed(PL_KEY_G, false))
290+
bUseGjk = !bUseGjk;
291+
292+
// use screen log extension to display variation and mode
284293
gptScreenLog->add_message_ex(117, 0, PL_COLOR_32_WHITE, 2.0, "Variation: %u", uVariation);
294+
gptScreenLog->add_message_ex(118, 0, PL_COLOR_32_WHITE, 2.0, "Mode: %s (G to toggle)", bUseGjk ? "GJK" : "Collision Ext");
285295

286296
// sphere <-> sphere collision
287297
{
@@ -303,19 +313,33 @@ pl_app_update(plAppData* ptAppData)
303313
uint32_t uColor0 = PL_COLOR_32_RED;
304314
uint32_t uColor1 = PL_COLOR_32_RED;
305315

306-
if(gptCollision->sphere_sphere(&tSphere0, &tSphere1))
307-
uColor0 = PL_COLOR_32_GREEN;
308-
309-
plCollisionInfo tInfo = {0};
310-
if(gptCollision->pen_sphere_sphere(&tSphere0, &tSphere1, &tInfo))
316+
if(bUseGjk)
311317
{
312-
uColor1 = PL_COLOR_32_GREEN;
313-
gptDraw->add_3d_cross(ptAppData->pt3dDrawlist, tInfo.tPoint, 0.1f, (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_RED});
314-
gptDraw->add_3d_line(ptAppData->pt3dDrawlist, tInfo.tPoint, pl_add_vec3(tInfo.tPoint, pl_mul_vec3_scalarf(tInfo.tNormal, tInfo.fPenetration)), (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_GREEN});
318+
plGjkCollisionInfo tInfo = {0};
319+
if(gptGjk->pen(pl_gjk_support_sphere, &tSphere0, pl_gjk_support_sphere, &tSphere1, &tInfo))
320+
{
321+
uColor0 = PL_COLOR_32_GREEN;
322+
uColor1 = PL_COLOR_32_GREEN;
323+
gptDraw->add_3d_cross(ptAppData->pt3dDrawlist, tInfo.tPoint, 0.1f, (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_RED});
324+
gptDraw->add_3d_line(ptAppData->pt3dDrawlist, tInfo.tPoint, pl_add_vec3(tInfo.tPoint, pl_mul_vec3_scalarf(tInfo.tNormal, tInfo.fPenetration)), (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_GREEN});
325+
}
326+
}
327+
else
328+
{
329+
if(gptCollision->sphere_sphere(&tSphere0, &tSphere1))
330+
uColor0 = PL_COLOR_32_GREEN;
331+
332+
plCollisionInfo tInfo = {0};
333+
if(gptCollision->pen_sphere_sphere(&tSphere0, &tSphere1, &tInfo))
334+
{
335+
uColor1 = PL_COLOR_32_GREEN;
336+
gptDraw->add_3d_cross(ptAppData->pt3dDrawlist, tInfo.tPoint, 0.1f, (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_RED});
337+
gptDraw->add_3d_line(ptAppData->pt3dDrawlist, tInfo.tPoint, pl_add_vec3(tInfo.tPoint, pl_mul_vec3_scalarf(tInfo.tNormal, tInfo.fPenetration)), (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_GREEN});
338+
}
315339
}
316340

317341
gptDraw->add_3d_band_xy_filled(ptAppData->pt3dDrawlist, (plVec3){2.0f, 4.0f, 0.0f}, 0.05f, 0.25f, 0, (plDrawSolidOptions){.uColor = uColor0});
318-
gptDraw->add_3d_band_xy_filled(ptAppData->pt3dDrawlist, (plVec3){2.0f, 4.5f, 0.0f}, 0.05f, 0.25f, 0, (plDrawSolidOptions){.uColor = uColor1});
342+
gptDraw->add_3d_band_xy_filled(ptAppData->pt3dDrawlist, (plVec3){2.0f, 4.5f, 0.0f}, 0.05f, 0.25f, 0, (plDrawSolidOptions){.uColor = uColor1});
319343
}
320344

321345
// box <-> sphere collision
@@ -334,26 +358,97 @@ pl_app_update(plAppData* ptAppData)
334358
if(uVariation == 2) tSphere1.tCenter = (plVec3){5.2f, 2.9f, 0.0f};
335359
if(uVariation == 3) tSphere1.tCenter = (plVec3){4.3f, 2.0f, 0.0f};
336360
gptDraw->add_3d_sphere(ptAppData->pt3dDrawlist, tSphere1, 0, 0, (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_CYAN});
337-
361+
338362
uint32_t uColor0 = PL_COLOR_32_RED;
339363
uint32_t uColor1 = PL_COLOR_32_RED;
340364

341-
if(gptCollision->box_sphere(&tBox0, &tSphere1))
342-
uColor0 = PL_COLOR_32_GREEN;
365+
if(bUseGjk)
366+
{
367+
plGjkCollisionInfo tInfo = {0};
368+
if(gptGjk->pen(pl_gjk_support_box, &tBox0, pl_gjk_support_sphere, &tSphere1, &tInfo))
369+
{
370+
uColor0 = PL_COLOR_32_GREEN;
371+
uColor1 = PL_COLOR_32_GREEN;
372+
gptDraw->add_3d_cross(ptAppData->pt3dDrawlist, tInfo.tPoint, 0.1f, (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_RED});
373+
gptDraw->add_3d_line(ptAppData->pt3dDrawlist, tInfo.tPoint, pl_add_vec3(tInfo.tPoint, pl_mul_vec3_scalarf(tInfo.tNormal, tInfo.fPenetration)), (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_GREEN});
374+
}
375+
}
376+
else
377+
{
378+
if(gptCollision->box_sphere(&tBox0, &tSphere1))
379+
uColor0 = PL_COLOR_32_GREEN;
380+
381+
plCollisionInfo tInfo = {0};
382+
if(gptCollision->pen_box_sphere(&tBox0, &tSphere1, &tInfo))
383+
{
384+
uColor1 = PL_COLOR_32_GREEN;
385+
gptDraw->add_3d_cross(ptAppData->pt3dDrawlist, tInfo.tPoint, 0.1f, (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_RED});
386+
gptDraw->add_3d_line(ptAppData->pt3dDrawlist, tInfo.tPoint, pl_add_vec3(tInfo.tPoint, pl_mul_vec3_scalarf(tInfo.tNormal, tInfo.fPenetration)), (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_GREEN});
387+
}
388+
}
343389

344-
plCollisionInfo tInfo = {0};
345-
if(gptCollision->pen_box_sphere(&tBox0, &tSphere1, &tInfo))
390+
gptDraw->add_3d_band_xy_filled(ptAppData->pt3dDrawlist, (plVec3){5.0f, 4.0f, 0.0f}, 0.05f, 0.25f, 0, (plDrawSolidOptions){.uColor = uColor0});
391+
gptDraw->add_3d_band_xy_filled(ptAppData->pt3dDrawlist, (plVec3){5.0f, 4.5f, 0.0f}, 0.05f, 0.25f, 0, (plDrawSolidOptions){.uColor = uColor1});
392+
}
393+
394+
// convex poly (icosahedron) <-> sphere collision (GJK only)
395+
{
396+
static const float fPhi = 1.618033988f; // golden ratio
397+
static const plVec3 tPolyCenter = {9.0f, 2.0f, 0.0f};
398+
static const float fScale = 0.5f;
399+
400+
// icosahedron vertices (centered at origin, then offset)
401+
plVec3 atIcoVerts[12] = {
402+
{-1, fPhi, 0}, { 1, fPhi, 0}, {-1, -fPhi, 0}, { 1, -fPhi, 0},
403+
{ 0, -1, fPhi}, { 0, 1, fPhi}, { 0, -1, -fPhi}, { 0, 1, -fPhi},
404+
{ fPhi, 0, -1}, { fPhi, 0, 1}, {-fPhi, 0, -1}, {-fPhi, 0, 1}
405+
};
406+
for (int ii = 0; ii < 12; ii++) {
407+
atIcoVerts[ii].x = atIcoVerts[ii].x * fScale + tPolyCenter.x;
408+
atIcoVerts[ii].y = atIcoVerts[ii].y * fScale + tPolyCenter.y;
409+
atIcoVerts[ii].z = atIcoVerts[ii].z * fScale + tPolyCenter.z;
410+
}
411+
412+
plConvexPoly tPoly = {
413+
.pVertices = atIcoVerts,
414+
.iVertexCount = 12
415+
};
416+
417+
// draw icosahedron edges
418+
static const int aiEdges[][2] = {
419+
{0,1},{0,5},{0,7},{0,10},{0,11},{1,5},{1,7},{1,8},{1,9},
420+
{2,3},{2,4},{2,6},{2,10},{2,11},{3,4},{3,6},{3,8},{3,9},
421+
{4,5},{4,9},{4,11},{5,9},{5,11},{6,7},{6,8},{6,10},{7,8},
422+
{7,10},{8,9},{10,11}
423+
};
424+
for (int ii = 0; ii < 30; ii++)
425+
gptDraw->add_3d_line(ptAppData->pt3dDrawlist, atIcoVerts[aiEdges[ii][0]], atIcoVerts[aiEdges[ii][1]], (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_WHITE});
426+
427+
plSphere tSphere1 = {
428+
.fRadius = 0.5f,
429+
.tCenter = {8.1f, 2.0f, 0.0f}
430+
};
431+
if(uVariation == 1) tSphere1.tCenter = (plVec3){8.5f, 2.0f, 0.0f};
432+
if(uVariation == 2) tSphere1.tCenter = (plVec3){9.0f, 2.8f, 0.0f};
433+
if(uVariation == 3) tSphere1.tCenter = (plVec3){7.5f, 2.0f, 0.0f};
434+
gptDraw->add_3d_sphere(ptAppData->pt3dDrawlist, tSphere1, 0, 0, (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_CYAN});
435+
436+
uint32_t uColor0 = PL_COLOR_32_RED;
437+
uint32_t uColor1 = PL_COLOR_32_RED;
438+
439+
plGjkCollisionInfo tInfo = {0};
440+
if(gptGjk->pen(pl_gjk_support_convex_poly, &tPoly, pl_gjk_support_sphere, &tSphere1, &tInfo))
346441
{
442+
uColor0 = PL_COLOR_32_GREEN;
347443
uColor1 = PL_COLOR_32_GREEN;
348444
gptDraw->add_3d_cross(ptAppData->pt3dDrawlist, tInfo.tPoint, 0.1f, (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_RED});
349445
gptDraw->add_3d_line(ptAppData->pt3dDrawlist, tInfo.tPoint, pl_add_vec3(tInfo.tPoint, pl_mul_vec3_scalarf(tInfo.tNormal, tInfo.fPenetration)), (plDrawLineOptions){.fThickness = 0.01f, .uColor = PL_COLOR_32_GREEN});
350446
}
351447

352-
gptDraw->add_3d_band_xy_filled(ptAppData->pt3dDrawlist, (plVec3){5.0f, 4.0f, 0.0f}, 0.05f, 0.25f, 0, (plDrawSolidOptions){.uColor = uColor0});
353-
gptDraw->add_3d_band_xy_filled(ptAppData->pt3dDrawlist, (plVec3){5.0f, 4.5f, 0.0f}, 0.05f, 0.25f, 0, (plDrawSolidOptions){.uColor = uColor1});
448+
gptDraw->add_3d_band_xy_filled(ptAppData->pt3dDrawlist, (plVec3){8.0f, 4.0f, 0.0f}, 0.05f, 0.25f, 0, (plDrawSolidOptions){.uColor = uColor0});
449+
gptDraw->add_3d_band_xy_filled(ptAppData->pt3dDrawlist, (plVec3){8.0f, 4.5f, 0.0f}, 0.05f, 0.25f, 0, (plDrawSolidOptions){.uColor = uColor1});
354450
}
355451

356-
357452
// start main pass & return the encoder being used
358453
plRenderEncoder* ptEncoder = gptStarter->begin_main_pass();
359454

0 commit comments

Comments
 (0)