@@ -3,6 +3,7 @@ const debug = @import("../debug.zig");
3
3
const math = @import ("../math.zig" );
4
4
const plane = @import ("../spatial/plane.zig" );
5
5
const boundingbox = @import ("../spatial/boundingbox.zig" );
6
+ const rays = @import ("../spatial/rays.zig" );
6
7
const mesh = @import ("../graphics/mesh.zig" );
7
8
const colors = @import ("../colors.zig" );
8
9
const graphics = @import ("../platform/graphics.zig" );
@@ -17,6 +18,7 @@ const Vec2 = math.Vec2;
17
18
const Plane = plane .Plane ;
18
19
const Mesh = mesh .Mesh ;
19
20
const BoundingBox = boundingbox .BoundingBox ;
21
+ const Ray = rays .Ray ;
20
22
21
23
// From https://github.com/fabioarnold/3d-game/blob/master/src/QuakeMap.zig
22
24
// This is so cool!
@@ -295,7 +297,7 @@ pub const Solid = struct {
295
297
var worldhit : ? QuakeMapHit = null ;
296
298
297
299
const size = bounds .max .sub (bounds .min ).scale (0.5 );
298
- const planes = getExpandedPlanes (self , size );
300
+ const planes = self . getExpandedPlanes (size );
299
301
300
302
const point = bounds .center ;
301
303
const next = point .add (velocity );
@@ -306,8 +308,11 @@ pub const Solid = struct {
306
308
for (0.. planes .len ) | idx | {
307
309
const ep = planes [idx ];
308
310
if (ep ) | p | {
311
+ // must start in front but end in back
312
+ if (p .testPoint (point ) == .BACK )
313
+ continue ;
309
314
if (p .testPoint (next ) == .FRONT )
310
- return null ;
315
+ continue ;
311
316
312
317
const hit = p .intersectLine (point , next );
313
318
if (hit ) | h | {
@@ -330,8 +335,100 @@ pub const Solid = struct {
330
335
.loc = h ,
331
336
.plane = p ,
332
337
};
338
+
339
+ // convex, so should only have one collision
340
+ break ;
341
+ }
342
+ }
343
+ }
344
+ }
345
+
346
+ return worldhit ;
347
+ }
348
+
349
+ pub fn checkLineCollision (self : * const Solid , start : Vec3 , end : Vec3 ) ? QuakeMapHit {
350
+ var worldhit : ? QuakeMapHit = null ;
351
+
352
+ if (self .faces .items .len == 0 )
353
+ return null ;
354
+
355
+ for (0.. self .faces .items .len ) | idx | {
356
+ const p = self .faces .items [idx ].plane ;
357
+ // must start in front and end in back
358
+ if (p .testPoint (start ) == .BACK )
359
+ continue ;
360
+ if (p .testPoint (end ) == .FRONT )
361
+ continue ;
362
+
363
+ const hit = p .intersectLine (start , end );
364
+
365
+ if (hit ) | h | {
366
+ var didhit = true ;
367
+ for (0.. self .faces .items .len ) | h_idx | {
368
+ if (idx == h_idx )
369
+ continue ;
370
+
371
+ // check that this hit point is behind the other clip planes
372
+ const pp = self .faces .items [h_idx ].plane ;
373
+ if (pp .testPoint (h ) == .FRONT ) {
374
+ didhit = false ;
375
+ break ;
333
376
}
334
377
}
378
+
379
+ if (didhit ) {
380
+ worldhit = .{
381
+ .loc = h ,
382
+ .plane = p ,
383
+ };
384
+
385
+ // convex, so should only have one collision
386
+ break ;
387
+ }
388
+ }
389
+ }
390
+
391
+ return worldhit ;
392
+ }
393
+
394
+ pub fn checkRayCollision (self : * const Solid , ray : Ray ) ? QuakeMapHit {
395
+ var worldhit : ? QuakeMapHit = null ;
396
+
397
+ if (self .faces .items .len == 0 )
398
+ return null ;
399
+
400
+ for (0.. self .faces .items .len ) | idx | {
401
+ const p = self .faces .items [idx ].plane ;
402
+
403
+ // must start in front!
404
+ if (p .testPoint (ray .pos ) == .BACK )
405
+ continue ;
406
+
407
+ const hit = ray .intersectPlane (p , true );
408
+
409
+ if (hit ) | h | {
410
+ var didhit = true ;
411
+ for (0.. self .faces .items .len ) | h_idx | {
412
+ if (idx == h_idx )
413
+ continue ;
414
+
415
+ // check that this hit point is behind the other clip planes
416
+ const pp = self .faces .items [h_idx ].plane ;
417
+ if (pp .testPoint (h .hit_pos ) == .FRONT ) {
418
+ didhit = false ;
419
+ break ;
420
+ }
421
+ }
422
+
423
+ if (didhit ) {
424
+ worldhit = .{
425
+ .loc = h .hit_pos ,
426
+ .plane = p ,
427
+ };
428
+
429
+ // convex, so should only have one collision
430
+ break ;
431
+ }
335
432
}
336
433
}
337
434
0 commit comments