Box3D 0.1.0
A 3D physics engine for games
Loading...
Searching...
No Matches
math_functions.h
1// SPDX-FileCopyrightText: 2025 Erin Catto
2// SPDX-License-Identifier: MIT
3
4#pragma once
5
6#include "base.h"
7
8#include <float.h>
9
10// for sqrtf and remainderf
11#include <math.h>
12#include <stdbool.h>
13
19
21#define B3_PI 3.14159265359f
22
24#define B3_DEG_TO_RAD 0.01745329251f
25
27#define B3_RAD_TO_DEG 57.2957795131f
28
30#define B3_MIN_SCALE 0.01f
31
33typedef struct b3Vec2
34{
35 float x;
36 float y;
37} b3Vec2;
38
40typedef struct b3Vec3
41{
42 float x;
43 float y;
44 float z;
45} b3Vec3;
46
49typedef struct b3CosSin
50{
52 float cosine;
53 float sine;
54} b3CosSin;
55
57typedef struct b3Quat
58{
59 b3Vec3 v;
60 float s;
61} b3Quat;
62
64typedef struct b3Transform
65{
66 b3Vec3 p;
67 b3Quat q;
69
70#if defined( BOX3D_DOUBLE_PRECISION )
71
74typedef struct b3Pos
75{
76 double x, y, z;
77} b3Pos;
78
81typedef struct b3WorldTransform
82{
83 b3Pos p;
84 b3Quat q;
86
87#else
88
90typedef b3Vec3 b3Pos;
91
94
95#endif
96
98typedef struct b3Matrix3
99{
100 b3Vec3 cx, cy, cz;
101} b3Matrix3;
102
104typedef struct b3AABB
105{
106 b3Vec3 lowerBound;
107 b3Vec3 upperBound;
108} b3AABB;
109
112typedef struct b3Plane
113{
114 b3Vec3 normal;
115 float offset;
116} b3Plane;
117
118static const b3Vec3 b3Vec3_zero = { 0.0f, 0.0f, 0.0f };
119static const b3Vec3 b3Vec3_one = { 1.0f, 1.0f, 1.0f };
120static const b3Vec3 b3Vec3_axisX = { 1.0f, 0.0f, 0.0f };
121static const b3Vec3 b3Vec3_axisY = { 0.0f, 1.0f, 0.0f };
122static const b3Vec3 b3Vec3_axisZ = { 0.0f, 0.0f, 1.0f };
123static const b3Quat b3Quat_identity = { { 0.0f, 0.0f, 0.0f }, 1.0f };
124static const b3Transform b3Transform_identity = { { 0.0f, 0.0f, 0.0f }, { { 0.0f, 0.0f, 0.0f }, 1.0f } };
125static const b3Matrix3 b3Mat3_zero = {
126 { 0.0f, 0.0f, 0.0f },
127 { 0.0f, 0.0f, 0.0f },
128 { 0.0f, 0.0f, 0.0f },
129};
130static const b3Matrix3 b3Mat3_identity = {
131 { 1.0f, 0.0f, 0.0f },
132 { 0.0f, 1.0f, 0.0f },
133 { 0.0f, 0.0f, 1.0f },
134};
135
136// Valid in both modes: 0.0f promotes to double, the identity rotation stays float
137static const b3Pos b3Pos_zero = { 0.0f, 0.0f, 0.0f };
138static const b3WorldTransform b3WorldTransform_identity = { { 0.0f, 0.0f, 0.0f }, { { 0.0f, 0.0f, 0.0f }, 1.0f } };
139
141B3_INLINE int b3MinInt( int a, int b )
142{
143 return a < b ? a : b;
144}
145
147B3_INLINE int b3MaxInt( int a, int b )
148{
149 return a > b ? a : b;
150}
151
153B3_INLINE int b3ClampInt( int a, int lower, int upper )
154{
155 return a < lower ? lower : ( upper < a ? upper : a );
156}
157
159B3_API bool b3IsValidFloat( float a );
160
162B3_INLINE float b3AbsFloat( float a )
163{
164 return a < 0 ? -a : a;
165}
166
168B3_INLINE float b3MinFloat( float a, float b )
169{
170 return a < b ? a : b;
171}
172
174B3_INLINE float b3MaxFloat( float a, float b )
175{
176 return a > b ? a : b;
177}
178
180B3_INLINE float b3ClampFloat( float a, float lower, float upper )
181{
182 return a < lower ? lower : ( upper < a ? upper : a );
183}
184
186B3_INLINE float b3LerpFloat( float a, float b, float alpha )
187{
188 return ( 1.0f - alpha ) * a + alpha * b;
189}
190
195B3_API float b3Atan2( float y, float x );
196
199B3_API b3CosSin b3ComputeCosSin( float radians );
200
202B3_INLINE float b3Sin( float radians )
203{
204 b3CosSin cs = b3ComputeCosSin( radians );
205 return cs.sine;
206}
207
209B3_INLINE float b3Cos( float radians )
210{
211 b3CosSin cs = b3ComputeCosSin( radians );
212 return cs.cosine;
213}
214
216B3_INLINE float b3UnwindAngle( float radians )
217{
218 // Assuming this is deterministic
219 return remainderf( radians, 2.0f * B3_PI );
220}
221
223B3_INLINE b3Vec3 b3Add( b3Vec3 a, b3Vec3 b )
224{
225 return B3_LITERAL( b3Vec3 ){ a.x + b.x, a.y + b.y, a.z + b.z };
226}
227
229B3_INLINE b3Vec3 b3Sub( b3Vec3 a, b3Vec3 b )
230{
231 return B3_LITERAL( b3Vec3 ){ a.x - b.x, a.y - b.y, a.z - b.z };
232}
233
235B3_INLINE b3Vec3 b3Mul( b3Vec3 a, b3Vec3 b )
236{
237 return B3_LITERAL( b3Vec3 ){ a.x * b.x, a.y * b.y, a.z * b.z };
238}
239
241B3_INLINE b3Vec3 b3Neg( b3Vec3 a )
242{
243 return B3_LITERAL( b3Vec3 ){ -a.x, -a.y, -a.z };
244}
245
247B3_INLINE float b3Dot( b3Vec3 a, b3Vec3 b )
248{
249 return a.x * b.x + a.y * b.y + a.z * b.z;
250}
251
253B3_INLINE float b3Length( b3Vec3 v )
254{
255 return sqrtf( b3Dot( v, v ) );
256}
257
259B3_INLINE float b3LengthSquared( b3Vec3 a )
260{
261 return a.x * a.x + a.y * a.y + a.z * a.z;
262}
263
265B3_INLINE float b3Distance( b3Vec3 a, b3Vec3 b )
266{
267 b3Vec3 dv = { b.x - a.x, b.y - a.y, b.z - a.z };
268 return b3Length( dv );
269}
270
272B3_INLINE float b3DistanceSquared( b3Vec3 a, b3Vec3 b )
273{
274 b3Vec3 dv = { b.x - a.x, b.y - a.y, b.z - a.z };
275 return dv.x * dv.x + dv.y * dv.y + dv.z * dv.z;
276}
277
280{
281 float lengthSquared = a.x * a.x + a.y * a.y + a.z * a.z;
282
283 if ( lengthSquared > 1000.0f * FLT_MIN )
284 {
285 float s = 1.0f / sqrtf( lengthSquared );
286 b3Vec3 u = { s * a.x, s * a.y, s * a.z };
287 return u;
288 }
289
290 return B3_LITERAL( b3Vec3 ){ 0.0f, 0.0f, 0.0f };
291}
292
295B3_INLINE b3Vec3 b3GetLengthAndNormalize( float* length, b3Vec3 a )
296{
297 *length = b3Length( a );
298 if ( *length < FLT_EPSILON )
299 {
300 return b3Vec3_zero;
301 }
302
303 float invLength = 1.0f / *length;
304 b3Vec3 n = { invLength * a.x, invLength * a.y, invLength * a.z };
305 return n;
306}
307
309B3_INLINE b3Vec3 b3Perp( b3Vec3 a )
310{
311 // Suppose vector a has all equal components and is a unit vector: a = (s, s, s)
312 // Then 3*s*s = 1, s = sqrt(1/3) = 0.57735. This means that at least one component
313 // of a unit vector must be greater or equal to 0.57735.
314 b3Vec3 p;
315 if ( a.x < -0.5f || 0.5f < a.x )
316 {
317 p = B3_LITERAL( b3Vec3 ){ a.y, -a.x, 0.0f };
318 }
319 else
320 {
321 p = B3_LITERAL( b3Vec3 ){ 0.0f, a.z, -a.y };
322 }
323
324 return b3Normalize( p );
325}
326
328B3_INLINE bool b3IsNormalized( b3Vec3 a )
329{
330 float aa = b3Dot( a, a );
331 return b3AbsFloat( 1.0f - aa ) < 100.0f * FLT_EPSILON;
332}
333
335B3_INLINE b3Vec3 b3MulAdd( b3Vec3 a, float s, b3Vec3 b )
336{
337 return B3_LITERAL( b3Vec3 ){ a.x + s * b.x, a.y + s * b.y, a.z + s * b.z };
338}
339
341B3_INLINE b3Vec3 b3MulSub( b3Vec3 a, float s, b3Vec3 b )
342{
343 return B3_LITERAL( b3Vec3 ){ a.x - s * b.x, a.y - s * b.y, a.z - s * b.z };
344}
345
347B3_INLINE b3Vec3 b3MulSV( float s, b3Vec3 a )
348{
349 return B3_LITERAL( b3Vec3 ){ s * a.x, s * a.y, s * a.z };
350}
351
353B3_INLINE b3Vec3 b3Cross( b3Vec3 a, b3Vec3 b )
354{
355 b3Vec3 c;
356 c.x = a.y * b.z - a.z * b.y;
357 c.y = a.z * b.x - a.x * b.z;
358 c.z = a.x * b.y - a.y * b.x;
359 return c;
360}
361
363B3_INLINE b3Vec3 b3Lerp( b3Vec3 a, b3Vec3 b, float alpha )
364{
365 B3_ASSERT( 0.0f <= alpha && alpha <= 1.0f );
366
367 b3Vec3 c = {
368 ( 1.0f - alpha ) * a.x + alpha * b.x,
369 ( 1.0f - alpha ) * a.y + alpha * b.y,
370 ( 1.0f - alpha ) * a.z + alpha * b.z,
371 };
372 return c;
373}
374
376B3_INLINE b3Vec3 b3Blend2( float s, b3Vec3 a, float t, b3Vec3 b )
377{
378 b3Vec3 d = {
379 s * a.x + t * b.x,
380 s * a.y + t * b.y,
381 s * a.z + t * b.z,
382 };
383 return d;
384}
385
387B3_INLINE b3Vec3 b3Abs( b3Vec3 a )
388{
389 return B3_LITERAL( b3Vec3 ){
390 b3AbsFloat( a.x ),
391 b3AbsFloat( a.y ),
392 b3AbsFloat( a.z ),
393 };
394}
395
397B3_INLINE b3Vec3 b3Sign( b3Vec3 a )
398{
399 return B3_LITERAL( b3Vec3 ){
400 a.x >= 0.0f ? 1.0f : -1.0f,
401 a.y >= 0.0f ? 1.0f : -1.0f,
402 a.z >= 0.0f ? 1.0f : -1.0f,
403 };
404}
405
407B3_INLINE b3Vec3 b3Min( b3Vec3 a, b3Vec3 b )
408{
409 return B3_LITERAL( b3Vec3 ){
410 b3MinFloat( a.x, b.x ),
411 b3MinFloat( a.y, b.y ),
412 b3MinFloat( a.z, b.z ),
413 };
414}
415
417B3_INLINE b3Vec3 b3Max( b3Vec3 a, b3Vec3 b )
418{
419 return B3_LITERAL( b3Vec3 ){
420 b3MaxFloat( a.x, b.x ),
421 b3MaxFloat( a.y, b.y ),
422 b3MaxFloat( a.z, b.z ),
423 };
424}
425
427B3_INLINE b3Vec3 b3Clamp( b3Vec3 a, b3Vec3 lower, b3Vec3 upper )
428{
429 b3Vec3 b;
430 b.x = b3ClampFloat( a.x, lower.x, upper.x );
431 b.y = b3ClampFloat( a.y, lower.y, upper.y );
432 b.z = b3ClampFloat( a.z, lower.z, upper.z );
433 return b;
434}
435
439{
440 b3Vec3 absScale = b3Abs( a );
442 b3Vec3 safeScale = b3Mul( b3Sign( a ), b3Max( absScale, minScale ) );
443 return safeScale;
444}
445
447B3_INLINE bool b3IsNormalizedQuat( b3Quat q )
448{
449 float qq = q.v.x * q.v.x + q.v.y * q.v.y + q.v.z * q.v.z + q.s * q.s;
450 return 1.0f - 20.0f * FLT_EPSILON < qq && qq < 1.0f + 20.0f * FLT_EPSILON;
451}
452
455{
456 // v + 2 * cross(q.v, cross(q.v, v) + q.s * v)
457 // B3_ASSERT( b3IsNormalizedQuat( q ) );
458 b3Vec3 t1 = b3Cross( q.v, v );
459 b3Vec3 t2 = b3MulAdd( t1, q.s, v );
460 b3Vec3 t3 = b3Cross( q.v, t2 );
461 return b3MulAdd( v, 2.0f, t3 );
462}
463
466{
467 // v + 2 * cross(q.v, cross(q.v, v) - q.s * v)
468 // B3_ASSERT( b3IsNormalizedQuat( q ) );
469 b3Vec3 t1 = b3Cross( q.v, v );
470 b3Vec3 t2 = b3MulSub( t1, q.s, v );
471 b3Vec3 t3 = b3Cross( q.v, t2 );
472 return b3MulAdd( v, 2.0f, t3 );
473}
474
476B3_INLINE float b3DotQuat( b3Quat a, b3Quat b )
477{
478 return a.v.x * b.v.x + a.v.y * b.v.y + a.v.z * b.v.z + a.s * b.s;
479}
480
482B3_INLINE b3Quat b3MulQuat( b3Quat q1, b3Quat q2 )
483{
484 b3Vec3 t1 = b3Cross( q1.v, q2.v );
485 b3Vec3 t2 = b3MulAdd( t1, q1.s, q2.v );
486 b3Vec3 t3 = b3MulAdd( t2, q2.s, q1.v );
487 b3Quat q = { t3, q1.s * q2.s - b3Dot( q1.v, q2.v ) };
488 return q;
489}
490
493B3_INLINE b3Quat b3InvMulQuat( b3Quat q1, b3Quat q2 )
494{
495 b3Vec3 t1 = b3Cross( q2.v, q1.v );
496 b3Vec3 t2 = b3MulAdd( t1, q1.s, q2.v );
497 b3Vec3 t3 = b3MulSub( t2, q2.s, q1.v );
498 b3Quat q = { t3, q1.s * q2.s + b3Dot( q1.v, q2.v ) };
499 return q;
500}
501
504{
505 return B3_LITERAL( b3Quat ){ { -q.v.x, -q.v.y, -q.v.z }, q.s };
506}
507
510{
511 return B3_LITERAL( b3Quat ){ { -q.v.x, -q.v.y, -q.v.z }, -q.s };
512}
513
516{
517 float lengthSq = b3DotQuat( q, q );
518 if ( lengthSq > 1000.0f * FLT_MIN )
519 {
520 float s = 1.0f / sqrtf( lengthSq );
521 b3Quat qn = { { s * q.v.x, s * q.v.y, s * q.v.z }, s * q.s };
522 return qn;
523 }
524
525 return b3Quat_identity;
526}
527
529B3_INLINE b3Quat b3MakeQuatFromAxisAngle( b3Vec3 axis, float radians )
530{
531 B3_ASSERT( b3IsNormalized( axis ) );
532 b3CosSin cs = b3ComputeCosSin( 0.5f * radians );
533 b3Quat q = { { cs.sine * axis.x, cs.sine * axis.y, cs.sine * axis.z }, cs.cosine };
534 return q;
535}
536
538B3_INLINE b3Vec3 b3GetAxisAngle( float* radians, b3Quat q )
539{
540 float length = sqrtf( q.v.x * q.v.x + q.v.y * q.v.y + q.v.z * q.v.z );
541 *radians = 2.0f * b3Atan2( length, q.s );
542 if ( length > 0.0f )
543 {
544 float invLength = 1.0f / length;
545 b3Vec3 axis = { invLength * q.v.x, invLength * q.v.y, invLength * q.v.z };
546 return axis;
547 }
548
549 return b3Vec3_zero;
550}
551
553B3_INLINE float b3GetQuatAngle( b3Quat q )
554{
555 float length = sqrtf( q.v.x * q.v.x + q.v.y * q.v.y + q.v.z * q.v.z );
556 return 2.0f * b3Atan2( length, q.s );
557}
558
561
564
566B3_INLINE float b3GetTwistAngle( b3Quat q )
567{
568 // Account for polarity to keep the twist angle in range.
569 // This is simpler than asking the user to check polarity or unwinding.
570 float twist = q.s < 0.0f ? b3Atan2( -q.v.z, -q.s ) : b3Atan2( q.v.z, q.s );
571 twist *= 2.0f;
572 B3_ASSERT( -B3_PI <= twist && twist <= B3_PI );
573 return twist;
574}
575
577B3_INLINE float b3GetSwingAngle( b3Quat q )
578{
579 // Polarity should not matter because all terms are squared.
580 float x = sqrtf( q.v.z * q.v.z + q.s * q.s );
581 float y = sqrtf( q.v.x * q.v.x + q.v.y * q.v.y );
582 float swing = 2.0f * b3Atan2( y, x );
583 B3_ASSERT( 0.0f <= swing && swing <= B3_PI );
584 return swing;
585}
586
588B3_INLINE b3Quat b3NLerp( b3Quat q1, b3Quat q2, float alpha )
589{
590 B3_VALIDATE( 0.0f <= alpha && alpha <= 1.0f );
591 if ( b3DotQuat( q1, q2 ) < 0.0f )
592 {
593 q1 = B3_LITERAL( b3Quat ){ { -q1.v.x, -q1.v.y, -q1.v.z }, -q1.s };
594 }
595
596 b3Quat q;
597 q.v = b3Lerp( q1.v, q2.v, alpha );
598 q.s = ( 1.0f - alpha ) * q1.s + alpha * q2.s;
599
600 return b3NormalizeQuat( q );
601}
602
607{
608 b3Transform out;
609 out.p = b3Add( b3RotateVector( a.q, b.p ), a.p );
610 out.q = b3MulQuat( a.q, b.q );
611 return out;
612}
613
618{
619 b3Transform out;
620 out.p = b3InvRotateVector( a.q, b3Sub( b.p, a.p ) );
621 out.q = b3InvMulQuat( a.q, b.q );
622 return out;
623}
624
627{
628 b3Transform out;
629 out.p = b3InvRotateVector( t.q, b3Neg( t.p ) );
630 out.q = b3Conjugate( t.q );
631 return out;
632}
633
636{
637 b3Vec3 rv = b3RotateVector( t.q, v );
638 return b3Add( rv, t.p );
639}
640
643{
644 return b3InvRotateVector( t.q, b3Sub( v, t.p ) );
645}
646
647// World position boundary. These cross between the double precision world space at the public
648// boundary and the float interior. One set of bodies serves both modes: the typedefs collapse
649// the types in float mode and the explicit float casts become no-ops.
650
652B3_INLINE b3Pos b3ToPos( b3Vec3 v )
653{
654 return B3_LITERAL( b3Pos ){ v.x, v.y, v.z };
655}
656
658B3_INLINE b3Vec3 b3ToVec3( b3Pos p )
659{
660 return B3_LITERAL( b3Vec3 ){ (float)p.x, (float)p.y, (float)p.z };
661}
662
667B3_INLINE float b3RoundDownFloat( double x )
668{
669#if defined( BOX3D_DOUBLE_PRECISION )
670 float f = (float)x;
671 return (double)f > x ? nextafterf( f, -FLT_MAX ) : f;
672#else
673 return (float)x;
674#endif
675}
676
678B3_INLINE float b3RoundUpFloat( double x )
679{
680#if defined( BOX3D_DOUBLE_PRECISION )
681 float f = (float)x;
682 return (double)f < x ? nextafterf( f, FLT_MAX ) : f;
683#else
684 return (float)x;
685#endif
686}
687
689B3_INLINE b3Vec3 b3SubPos( b3Pos a, b3Pos b )
690{
691 return B3_LITERAL( b3Vec3 ){ (float)( a.x - b.x ), (float)( a.y - b.y ), (float)( a.z - b.z ) };
692}
693
695B3_INLINE b3Pos b3OffsetPos( b3Pos p, b3Vec3 d )
696{
697 return B3_LITERAL( b3Pos ){ p.x + d.x, p.y + d.y, p.z + d.z };
698}
699
701B3_INLINE b3Pos b3LerpPosition( b3Pos a, b3Pos b, float t )
702{
703 return B3_LITERAL( b3Pos ){
704 ( 1.0f - t ) * a.x + t * b.x,
705 ( 1.0f - t ) * a.y + t * b.y,
706 ( 1.0f - t ) * a.z + t * b.z,
707 };
708}
709
712{
713 b3Vec3 r = b3RotateVector( t.q, p );
714 return B3_LITERAL( b3Pos ){ t.p.x + r.x, t.p.y + r.y, t.p.z + r.z };
715}
716
719{
720 b3Vec3 d = { (float)( p.x - t.p.x ), (float)( p.y - t.p.y ), (float)( p.z - t.p.z ) };
721 return b3InvRotateVector( t.q, d );
722}
723
726{
727 b3Transform C;
728 C.q = b3InvMulQuat( A.q, B.q );
729 b3Vec3 d = { (float)( B.p.x - A.p.x ), (float)( B.p.y - A.p.y ), (float)( B.p.z - A.p.z ) };
730 C.p = b3InvRotateVector( A.q, d );
731 return C;
732}
733
736{
738 C.q = b3MulQuat( A.q, B.q );
739 b3Vec3 r = b3RotateVector( A.q, B.p );
740 C.p = B3_LITERAL( b3Pos ){ A.p.x + r.x, A.p.y + r.y, A.p.z + r.z };
741 return C;
742}
743
746{
747 b3Transform r;
748 r.q = t.q;
749 r.p = B3_LITERAL( b3Vec3 ){ (float)( t.p.x - base.x ), (float)( t.p.y - base.y ), (float)( t.p.z - base.z ) };
750 return r;
751}
752
755{
757 w.p = b3ToPos( t.p );
758 w.q = t.q;
759 return w;
760}
761
765B3_INLINE b3AABB b3OffsetAABB( b3AABB localBox, b3Pos origin )
766{
767 b3AABB out;
768 out.lowerBound.x = b3RoundDownFloat( origin.x + localBox.lowerBound.x );
769 out.lowerBound.y = b3RoundDownFloat( origin.y + localBox.lowerBound.y );
770 out.lowerBound.z = b3RoundDownFloat( origin.z + localBox.lowerBound.z );
771 out.upperBound.x = b3RoundUpFloat( origin.x + localBox.upperBound.x );
772 out.upperBound.y = b3RoundUpFloat( origin.y + localBox.upperBound.y );
773 out.upperBound.z = b3RoundUpFloat( origin.z + localBox.upperBound.z );
774 return out;
775}
776
778B3_INLINE float b3Det( b3Matrix3 m )
779{
780 return b3Dot( m.cx, b3Cross( m.cy, m.cz ) );
781}
782
785{
786 b3Vec3 b = {
787 m.cx.x * a.x + m.cy.x * a.y + m.cz.x * a.z,
788 m.cx.y * a.x + m.cy.y * a.y + m.cz.y * a.z,
789 m.cx.z * a.x + m.cy.z * a.y + m.cz.z * a.z,
790 };
791 return b;
792}
793
796{
797 return B3_LITERAL( b3Matrix3 ){
798 { -a.cx.x, -a.cx.y, -a.cx.z },
799 { -a.cy.x, -a.cy.y, -a.cy.z },
800 { -a.cz.x, -a.cz.y, -a.cz.z },
801 };
802}
803
807{
808 return B3_LITERAL( b3Matrix3 ){
809 { a.cx.x + b.cx.x, a.cx.y + b.cx.y, a.cx.z + b.cx.z },
810 { a.cy.x + b.cy.x, a.cy.y + b.cy.y, a.cy.z + b.cy.z },
811 { a.cz.x + b.cz.x, a.cz.y + b.cz.y, a.cz.z + b.cz.z },
812 };
813}
814
818{
819 return B3_LITERAL( b3Matrix3 ){
820 { a.cx.x - b.cx.x, a.cx.y - b.cx.y, a.cx.z - b.cx.z },
821 { a.cy.x - b.cy.x, a.cy.y - b.cy.y, a.cy.z - b.cy.z },
822 { a.cz.x - b.cz.x, a.cz.y - b.cz.y, a.cz.z - b.cz.z },
823 };
824}
825
827B3_INLINE b3Matrix3 b3MulSM( float s, b3Matrix3 a )
828{
829 return B3_LITERAL( b3Matrix3 ){
830 { s * a.cx.x, s * a.cx.y, s * a.cx.z },
831 { s * a.cy.x, s * a.cy.y, s * a.cy.z },
832 { s * a.cz.x, s * a.cz.y, s * a.cz.z },
833 };
834}
835
839{
840 b3Matrix3 out;
841 out.cx = b3MulMV( a, b.cx );
842 out.cy = b3MulMV( a, b.cy );
843 out.cz = b3MulMV( a, b.cz );
844 return out;
845}
846
849{
850 b3Matrix3 out;
851 out.cx = B3_LITERAL( b3Vec3 ){ m.cx.x, m.cy.x, m.cz.x };
852 out.cy = B3_LITERAL( b3Vec3 ){ m.cx.y, m.cy.y, m.cz.y };
853 out.cz = B3_LITERAL( b3Vec3 ){ m.cx.z, m.cy.z, m.cz.z };
854
855 return out;
856}
857
860{
861 float det = b3Det( m );
862 if ( b3AbsFloat( det ) > 1000.0f * FLT_MIN )
863 {
864 float invDet = 1.0f / det;
865 b3Matrix3 out;
866 out.cx = b3MulSV( invDet, b3Cross( m.cy, m.cz ) );
867 out.cy = b3MulSV( invDet, b3Cross( m.cz, m.cx ) );
868 out.cz = b3MulSV( invDet, b3Cross( m.cx, m.cy ) );
869
870 return b3Transpose( out );
871 }
872
873 return b3Mat3_zero;
874}
875
879{
880 float det = b3Det( m );
881 if ( b3AbsFloat( det ) > 1000.0f * FLT_MIN )
882 {
883 float invDet = 1.0f / det;
884 b3Matrix3 s;
885 s.cx = b3Cross( m.cy, m.cz );
886 s.cy = b3Cross( m.cz, m.cx );
887 s.cz = b3Cross( m.cx, m.cy );
888
889 b3Vec3 b = {
890 invDet * b3Dot( s.cx, a ),
891 invDet * b3Dot( s.cy, a ),
892 invDet * b3Dot( s.cz, a ),
893 };
894
895 return b;
896 }
897
898 return b3Vec3_zero;
899}
900
903{
904 float det = b3Det( m );
905 if ( b3AbsFloat( det ) > 1000.0f * FLT_MIN )
906 {
907 float invDet = 1.0f / det;
908 b3Matrix3 out;
909 out.cx = b3MulSV( invDet, b3Cross( m.cy, m.cz ) );
910 out.cy = b3MulSV( invDet, b3Cross( m.cz, m.cx ) );
911 out.cz = b3MulSV( invDet, b3Cross( m.cx, m.cy ) );
912 return out;
913 }
914
915 return b3Mat3_zero;
916}
917
920{
921 b3Matrix3 out;
922 out.cx = b3Abs( m.cx );
923 out.cy = b3Abs( m.cy );
924 out.cz = b3Abs( m.cz );
925
926 return out;
927}
928
933{
934 float xx = q.v.x * q.v.x;
935 float yy = q.v.y * q.v.y;
936 float zz = q.v.z * q.v.z;
937 float xy = q.v.x * q.v.y;
938 float xz = q.v.x * q.v.z;
939 float xw = q.v.x * q.s;
940 float yz = q.v.y * q.v.z;
941 float yw = q.v.y * q.s;
942 float zw = q.v.z * q.s;
943
944 return B3_LITERAL( b3Matrix3 ){
945 { 1.0f - 2.0f * ( yy + zz ), 2.0f * ( xy + zw ), 2.0f * ( xz - yw ) },
946 { 2.0f * ( xy - zw ), 1.0f - 2.0f * ( xx + zz ), 2.0f * ( yz + xw ) },
947 { 2.0f * ( xz + yw ), 2.0f * ( yz - xw ), 1.0f - 2.0f * ( xx + yy ) },
948 };
949}
950
953B3_API b3Matrix3 b3Steiner( float mass, b3Vec3 origin );
954
956B3_INLINE b3AABB b3MakeAABB( const b3Vec3* points, int count, float radius )
957{
958 B3_ASSERT( count > 0 );
959 b3AABB a = { points[0], points[0] };
960 for ( int i = 1; i < count; ++i )
961 {
962 a.lowerBound = b3Min( a.lowerBound, points[i] );
963 a.upperBound = b3Max( a.upperBound, points[i] );
964 }
965
966 b3Vec3 r = { radius, radius, radius };
967 a.lowerBound = b3Sub( a.lowerBound, r );
968 a.upperBound = b3Add( a.upperBound, r );
969
970 return a;
971}
972
974B3_INLINE bool b3AABB_Contains( b3AABB a, b3AABB b )
975{
976 if ( a.lowerBound.x > b.lowerBound.x || b.upperBound.x > a.upperBound.x )
977 return false;
978 if ( a.lowerBound.y > b.lowerBound.y || b.upperBound.y > a.upperBound.y )
979 return false;
980 if ( a.lowerBound.z > b.lowerBound.z || b.upperBound.z > a.upperBound.z )
981 return false;
982
983 return true;
984}
985
987B3_INLINE float b3AABB_Area( b3AABB a )
988{
989 b3Vec3 delta = b3Sub( a.upperBound, a.lowerBound );
990 return 2.0f * ( delta.x * delta.y + delta.y * delta.z + delta.z * delta.x );
991}
992
995{
996 return b3MulSV( 0.5f, b3Add( a.upperBound, a.lowerBound ) );
997}
998
1001{
1002 return b3MulSV( 0.5f, b3Sub( a.upperBound, a.lowerBound ) );
1003}
1004
1007{
1008 b3AABB out;
1009 out.lowerBound = b3Min( a.lowerBound, b.lowerBound );
1010 out.upperBound = b3Max( a.upperBound, b.upperBound );
1011 return out;
1012}
1013
1015B3_INLINE b3AABB b3AABB_Inflate( b3AABB a, float extension )
1016{
1017 b3Vec3 radius = { extension, extension, extension };
1018
1019 b3AABB out;
1020 out.lowerBound = b3Sub( a.lowerBound, radius );
1021 out.upperBound = b3Add( a.upperBound, radius );
1022 return out;
1023}
1024
1026B3_INLINE bool b3AABB_Overlaps( b3AABB a, b3AABB b )
1027{
1028 // No intersection if separated along one axis
1029 if ( a.upperBound.x < b.lowerBound.x || a.lowerBound.x > b.upperBound.x )
1030 return false;
1031 if ( a.upperBound.y < b.lowerBound.y || a.lowerBound.y > b.upperBound.y )
1032 return false;
1033 if ( a.upperBound.z < b.lowerBound.z || a.lowerBound.z > b.upperBound.z )
1034 return false;
1035
1036 // Overlapping on all axis means bounds are intersecting
1037 return true;
1038}
1039
1044{
1045 b3Vec3 center = b3TransformPoint( transform, b3AABB_Center( a ) );
1046 b3Matrix3 m = b3MakeMatrixFromQuat( transform.q );
1047 b3Vec3 extent = b3MulMV( b3AbsMatrix3( m ), b3AABB_Extents( a ) );
1048 b3AABB out = { b3Sub( center, extent ), b3Add( center, extent ) };
1049 return out;
1050}
1051
1054{
1055 return b3Clamp( point, a.lowerBound, a.upperBound );
1056}
1057
1060{
1061 b3Vec3 point1;
1062 float fraction1;
1063 b3Vec3 point2;
1064 float fraction2;
1066
1069
1072
1075
1077B3_API bool b3IsValidFloat( float a );
1078
1080B3_API bool b3IsValidVec3( b3Vec3 a );
1081
1083B3_API bool b3IsValidQuat( b3Quat q );
1084
1087
1090
1092B3_API bool b3IsValidAABB( b3AABB a );
1093
1095B3_API bool b3IsBoundedAABB( b3AABB a );
1096
1098B3_API bool b3IsSaneAABB( b3AABB a );
1099
1101B3_API bool b3IsValidPlane( b3Plane a );
1102
1104B3_API bool b3IsValidPosition( b3Pos p );
1105
1108 // math
1110
1118
1119#ifdef __cplusplus
1120
1122B3_FORCE_INLINE b3Vec3& operator+=( b3Vec3& a, b3Vec3 b )
1123{
1124 a.x += b.x;
1125 a.y += b.y;
1126 a.z += b.z;
1127 return a;
1128}
1129
1131B3_FORCE_INLINE b3Vec3& operator-=( b3Vec3& a, b3Vec3 b )
1132{
1133 a.x -= b.x;
1134 a.y -= b.y;
1135 a.z -= b.z;
1136 return a;
1137}
1138
1140B3_FORCE_INLINE b3Vec3& operator*=( b3Vec3& a, float s )
1141{
1142 a.x *= s;
1143 a.y *= s;
1144 a.z *= s;
1145 return a;
1146}
1147
1149B3_FORCE_INLINE b3Vec3 operator-( b3Vec3 a )
1150{
1151 return { -a.x, -a.y, -a.z };
1152}
1153
1155B3_FORCE_INLINE b3Vec3 operator*( float s, b3Vec3 a )
1156{
1157 return { s * a.x, s * a.y, s * a.z };
1158}
1159
1161B3_FORCE_INLINE b3Vec3 operator*( b3Vec3 a, float s )
1162{
1163 return { s * a.x, s * a.y, s * a.z };
1164}
1165
1167B3_FORCE_INLINE b3Vec3 operator*( b3Vec3 a, b3Vec3 b )
1168{
1169 return { a.x * b.x, a.y * b.y, a.z * b.z };
1170}
1171
1173B3_FORCE_INLINE b3Vec3 operator+( b3Vec3 a, b3Vec3 b )
1174{
1175 return { a.x + b.x, a.y + b.y, a.z + b.z };
1176}
1177
1179B3_FORCE_INLINE b3Vec3 operator-( b3Vec3 a, b3Vec3 b )
1180{
1181 return { a.x - b.x, a.y - b.y, a.z - b.z };
1182}
1183
1184#if defined( BOX3D_DOUBLE_PRECISION )
1185
1187B3_FORCE_INLINE b3Pos operator+( b3Pos a, b3Vec3 b )
1188{
1189 return { a.x + b.x, a.y + b.y, a.z + b.z };
1190}
1191
1193B3_FORCE_INLINE b3Pos operator-( b3Pos a, b3Vec3 b )
1194{
1195 return { a.x - b.x, a.y - b.y, a.z - b.z };
1196}
1197
1199B3_FORCE_INLINE b3Vec3 operator-( b3Pos a, b3Pos b )
1200{
1201 return { (float)( a.x - b.x ), (float)( a.y - b.y ), (float)( a.z - b.z ) };
1202}
1203
1204#endif
1205
1206#endif
1207 // math_cpp
#define B3_ASSERT(condition)
Assert that a condition is true.
Definition base.h:127
#define B3_VALIDATE(...)
Validation is typically only enabled in debug builds.
Definition base.h:140
float cosine
cosine and sine
Definition math_functions.h:52
float b3Sin(float radians)
Definition math_functions.h:202
b3AABB b3AABB_Union(b3AABB a, b3AABB b)
Get the union of two axis-aligned bounding boxes.
Definition math_functions.h:1006
b3Pos b3ToPos(b3Vec3 v)
Convert a vector to a world position.
Definition math_functions.h:652
b3AABB b3MakeAABB(const b3Vec3 *points, int count, float radius)
Get the AABB of a point cloud.
Definition math_functions.h:956
int b3MinInt(int a, int b)
Definition math_functions.h:141
bool b3IsValidPlane(b3Plane a)
Is this a valid plane? Normal is a unit vector. Not Nan or infinity.
b3Vec3 b3Clamp(b3Vec3 a, b3Vec3 lower, b3Vec3 upper)
Component-wise clamped value.
Definition math_functions.h:427
b3Pos b3TransformWorldPoint(b3WorldTransform t, b3Vec3 p)
Transform a local point to a world position. Rotation in float, translation in double.
Definition math_functions.h:711
bool b3AABB_Contains(b3AABB a, b3AABB b)
Does a fully contain b?
Definition math_functions.h:974
b3Vec3 b3InvRotateVector(b3Quat q, b3Vec3 v)
Inverse rotate a vector.
Definition math_functions.h:465
bool b3IsValidAABB(b3AABB a)
Is this a valid bounding box? Not Nan or infinity. Upper bound greater than or equal to lower bound.
bool b3IsNormalized(b3Vec3 a)
Is a vector normalized? In other words, does it have unit length?
Definition math_functions.h:328
b3Vec3 b3ToVec3(b3Pos p)
Lossy conversion of a world position to a float vector.
Definition math_functions.h:658
B3_FORCE_INLINE b3Matrix3 b3MakeMatrixFromQuat(b3Quat q)
Make a matrix from a quaternion.
Definition math_functions.h:932
b3SegmentDistanceResult b3SegmentDistance(b3Vec3 p1, b3Vec3 q1, b3Vec3 p2, b3Vec3 q2)
Compute the closest points on two line segments.
bool b3IsNormalizedQuat(b3Quat q)
Does the supplied quaternion have unit length?
Definition math_functions.h:447
float b3AABB_Area(b3AABB a)
Get the surface area of an axis-aligned bounding box.
Definition math_functions.h:987
b3Matrix3 b3InvertMatrix(b3Matrix3 m)
General matrix inverse.
Definition math_functions.h:859
b3Transform b3ToRelativeTransform(b3WorldTransform t, b3Pos base)
Shift a world transform into the frame of a base position.
Definition math_functions.h:745
b3Matrix3 b3InvertT(b3Matrix3 m)
Invert a matrix.
Definition math_functions.h:902
float b3Cos(float radians)
Definition math_functions.h:209
b3Matrix3 b3SubMM(b3Matrix3 a, b3Matrix3 b)
Matrix subtraction.
Definition math_functions.h:817
b3Vec3 b3Sub(b3Vec3 a, b3Vec3 b)
Vector subtraction.
Definition math_functions.h:229
#define B3_MIN_SCALE
Minimum scale used for scaling collision meshes, etc.
Definition math_functions.h:30
b3WorldTransform b3MulWorldTransforms(b3WorldTransform A, b3Transform B)
Compose a world transform with a local transform.
Definition math_functions.h:735
b3Vec3 b3Pos
In single precision mode these types are the same.
Definition math_functions.h:90
b3Quat b3NegateQuat(b3Quat q)
Component-wise quaternion negation.
Definition math_functions.h:509
b3Transform b3InvMulWorldTransforms(b3WorldTransform A, b3WorldTransform B)
Relative transform of frame B in frame A. The narrow phase boundary.
Definition math_functions.h:725
float b3Dot(b3Vec3 a, b3Vec3 b)
Vector dot product.
Definition math_functions.h:247
b3Vec3 b3ClosestPointToAABB(b3Vec3 point, b3AABB a)
Get the closest point on an axis-aligned bounding box.
Definition math_functions.h:1053
b3Matrix3 b3Steiner(float mass, b3Vec3 origin)
Get the inertia tensor of an offset point.
b3Vec3 b3Solve3(b3Matrix3 m, b3Vec3 a)
Solve a matrix equation.
Definition math_functions.h:878
b3Quat b3InvMulQuat(b3Quat q1, b3Quat q2)
Compute a relative quaternion.
Definition math_functions.h:493
float b3DistanceSquared(b3Vec3 a, b3Vec3 b)
Squared distance between two points.
Definition math_functions.h:272
float b3AbsFloat(float a)
Definition math_functions.h:162
b3Matrix3 b3NegateMat3(b3Matrix3 a)
Negate a matrix.
Definition math_functions.h:795
b3Vec3 b3GetLengthAndNormalize(float *length, b3Vec3 a)
Normalize a vector and return the length.
Definition math_functions.h:295
b3Quat b3ComputeQuatBetweenUnitVectors(b3Vec3 v1, b3Vec3 v2)
Find a quaternion that rotates one vector to another.
b3Matrix3 b3Transpose(b3Matrix3 m)
Matrix transpose.
Definition math_functions.h:848
float b3UnwindAngle(float radians)
Convert any angle into the range [-pi, pi].
Definition math_functions.h:216
b3Matrix3 b3AbsMatrix3(b3Matrix3 m)
Get the component-wise absolute value of a matrix.
Definition math_functions.h:919
b3Vec3 b3MulMV(b3Matrix3 m, b3Vec3 a)
Multiply a matrix times a column vector.
Definition math_functions.h:784
b3Transform b3MulTransforms(b3Transform a, b3Transform b)
Multiply two transforms.
Definition math_functions.h:606
float b3GetQuatAngle(b3Quat q)
Get the angle for a quaternion in radians.
Definition math_functions.h:553
b3AABB b3AABB_Transform(b3Transform transform, b3AABB a)
Transform an axis-aligned bounding box.
Definition math_functions.h:1043
float b3DotQuat(b3Quat a, b3Quat b)
Compute dot product of two quaternions. Useful for polarity tests.
Definition math_functions.h:476
b3Vec3 b3AABB_Center(b3AABB a)
Get the center of an axis-aligned bounding box.
Definition math_functions.h:994
float b3RoundUpFloat(double x)
Narrow a world coordinate to float, rounding toward positive infinity.
Definition math_functions.h:678
float b3Distance(b3Vec3 a, b3Vec3 b)
Distance between two points.
Definition math_functions.h:265
b3Quat b3MakeQuatFromMatrix(const b3Matrix3 *m)
Extract a quaternion from a rotation matrix.
b3Pos b3OffsetPos(b3Pos p, b3Vec3 d)
p + d
Definition math_functions.h:695
float b3Atan2(float y, float x)
Compute an approximate arctangent in the range [-pi, pi] This is hand coded for cross-platform determ...
b3CosSin b3ComputeCosSin(float radians)
Compute the cosine and sine of an angle in radians.
b3Vec3 b3Add(b3Vec3 a, b3Vec3 b)
Vector addition.
Definition math_functions.h:223
b3Vec3 b3SubPos(b3Pos a, b3Pos b)
a - b, demoted to float. The primary precision boundary operation.
Definition math_functions.h:689
bool b3IsValidQuat(b3Quat q)
Is this a valid quaternion? Not NaN or infinity. Is normalized.
b3Vec3 b3Max(b3Vec3 a, b3Vec3 b)
Component-wise maximum value.
Definition math_functions.h:417
b3Quat b3NLerp(b3Quat q1, b3Quat q2, float alpha)
Linearly interpolate and normalize between two quaternions.
Definition math_functions.h:588
b3Matrix3 b3AddMM(b3Matrix3 a, b3Matrix3 b)
Matrix addition.
Definition math_functions.h:806
b3Vec3 b3MulSV(float s, b3Vec3 a)
s * a
Definition math_functions.h:347
b3Vec3 b3MulAdd(b3Vec3 a, float s, b3Vec3 b)
a + s * b
Definition math_functions.h:335
b3SegmentDistanceResult b3LineDistance(b3Vec3 p1, b3Vec3 d1, b3Vec3 p2, b3Vec3 d2)
Compute the closest points on two infinite lines.
int b3MaxInt(int a, int b)
Definition math_functions.h:147
b3Vec3 b3RotateVector(b3Quat q, b3Vec3 v)
Rotate a vector.
Definition math_functions.h:454
b3Vec3 b3Neg(b3Vec3 a)
Vector negation.
Definition math_functions.h:241
b3Vec3 b3Sign(b3Vec3 a)
Component-wise -1 or 1 (1 if zero).
Definition math_functions.h:397
b3Vec3 b3SafeScale(b3Vec3 a)
Create a safe scaling value for scaling collision.
Definition math_functions.h:438
b3Vec3 b3Lerp(b3Vec3 a, b3Vec3 b, float alpha)
Linearly interpolate between two vectors.
Definition math_functions.h:363
b3Vec3 b3Mul(b3Vec3 a, b3Vec3 b)
Vector component-wise multiplication.
Definition math_functions.h:235
bool b3IsBoundedAABB(b3AABB a)
Is this AABB reasonably close to the origin? See B3_HUGE.
b3Vec3 b3InvTransformPoint(b3Transform t, b3Vec3 v)
Inverse transform a point.
Definition math_functions.h:642
#define B3_PI
https://en.wikipedia.org/wiki/Pi
Definition math_functions.h:21
float b3LerpFloat(float a, float b, float alpha)
Interpolate a scalar.
Definition math_functions.h:186
b3Vec3 b3Blend2(float s, b3Vec3 a, float t, b3Vec3 b)
Blend two vectors: s * a + t * b.
Definition math_functions.h:376
B3_FORCE_INLINE b3Transform b3InvMulTransforms(b3Transform a, b3Transform b)
Creates a transform that converts a local point in frame B to a local point in frame A.
Definition math_functions.h:617
bool b3IsValidTransform(b3Transform a)
Is this a valid transform? Not NaN or infinity. Is normalized.
bool b3IsValidMatrix3(b3Matrix3 a)
Is this a valid matrix? Not NaN or infinity.
float b3GetTwistAngle(b3Quat q)
Twist angle around the z-axis, used for twist limit and revolute angle limit.
Definition math_functions.h:566
int b3ClampInt(int a, int lower, int upper)
Definition math_functions.h:153
b3Vec3 b3PointToSegmentDistance(b3Vec3 a, b3Vec3 b, b3Vec3 q)
Compute the closest point on the segment a-b to the target q.
b3AABB b3AABB_Inflate(b3AABB a, float extension)
Add uniform padding to an axis-aligned bounding box.
Definition math_functions.h:1015
b3Vec3 b3GetAxisAngle(float *radians, b3Quat q)
Get the axis and angle from a quaternion. Assumes the quaternion is normalized.
Definition math_functions.h:538
b3Quat b3Conjugate(b3Quat q)
Quaternion conjugate (cheap inverse).
Definition math_functions.h:503
bool b3IsValidPosition(b3Pos p)
Is this a valid world position? Not NaN or infinity.
float b3Det(b3Matrix3 m)
Compute the determinant of a 3-by-3 matrix.
Definition math_functions.h:778
float b3GetSwingAngle(b3Quat q)
Swing angle used for cone limit.
Definition math_functions.h:577
b3AABB b3OffsetAABB(b3AABB localBox, b3Pos origin)
Translate a local AABB by a world origin, rounding outward so the float box always contains the doubl...
Definition math_functions.h:765
float b3ClampFloat(float a, float lower, float upper)
Definition math_functions.h:180
bool b3AABB_Overlaps(b3AABB a, b3AABB b)
Do two axis-aligned boxes overlap?
Definition math_functions.h:1026
b3Transform b3InvertTransform(b3Transform t)
Get the inverse of a transform.
Definition math_functions.h:626
float b3MaxFloat(float a, float b)
Definition math_functions.h:174
b3Vec3 b3Perp(b3Vec3 a)
Get a unit vector that is perpendicular to the supplied vector.
Definition math_functions.h:309
b3Vec3 b3MulSub(b3Vec3 a, float s, b3Vec3 b)
a - s * b
Definition math_functions.h:341
b3Vec3 b3InvTransformWorldPoint(b3WorldTransform t, b3Pos p)
Transform a world position to a local point. One double subtraction, then float.
Definition math_functions.h:718
bool b3IsValidFloat(float a)
Is this a valid number? Not NaN or infinity.
bool b3IsValidWorldTransform(b3WorldTransform t)
Is this a valid world transform? Not NaN or infinity. Rotation is normalized.
bool b3IsSaneAABB(b3AABB a)
Is this AABB valid and reasonable?
b3Vec3 b3Normalize(b3Vec3 a)
Normalize a vector. Returns a zero vector if the input vector is very small.
Definition math_functions.h:279
b3Vec3 b3TransformPoint(b3Transform t, b3Vec3 v)
Transform a point.
Definition math_functions.h:635
b3Matrix3 b3MulMM(b3Matrix3 a, b3Matrix3 b)
Matrix multiplication.
Definition math_functions.h:838
b3Transform b3WorldTransform
In single precision mode these types are the same.
Definition math_functions.h:93
float b3RoundDownFloat(double x)
Narrow a world coordinate to float, rounding toward negative infinity.
Definition math_functions.h:667
b3Quat b3MakeQuatFromAxisAngle(b3Vec3 axis, float radians)
Make a quaternion that is equivalent to rotating around an axis by a specified angle.
Definition math_functions.h:529
b3Vec3 b3AABB_Extents(b3AABB a)
Get the extents (half-widths) of an axis-aligned bounding box.
Definition math_functions.h:1000
bool b3IsValidVec3(b3Vec3 a)
Is this a valid vector? Not NaN or infinity.
b3Vec3 b3Cross(b3Vec3 a, b3Vec3 b)
https://en.wikipedia.org/wiki/Cross_product
Definition math_functions.h:353
b3Quat b3NormalizeQuat(b3Quat q)
Normalize a quaternion.
Definition math_functions.h:515
b3Pos b3LerpPosition(b3Pos a, b3Pos b, float t)
World position interpolation for sweeps and sampling.
Definition math_functions.h:701
b3Vec3 b3Min(b3Vec3 a, b3Vec3 b)
Component-wise minimum value.
Definition math_functions.h:407
b3WorldTransform b3MakeWorldTransform(b3Transform t)
Promote a float transform to a world transform. Lossless.
Definition math_functions.h:754
float b3LengthSquared(b3Vec3 a)
Vector length squared.
Definition math_functions.h:259
b3Quat b3MulQuat(b3Quat q1, b3Quat q2)
Multiply two quaternions.
Definition math_functions.h:482
float b3MinFloat(float a, float b)
Definition math_functions.h:168
b3Vec3 b3Abs(b3Vec3 a)
Component-wise absolute value.
Definition math_functions.h:387
b3Matrix3 b3MulSM(float s, b3Matrix3 a)
Multiply a matrix by a scalar, component-wise.
Definition math_functions.h:827
float b3Length(b3Vec3 v)
Vector length.
Definition math_functions.h:253
Axis aligned bounding box.
Definition math_functions.h:105
Cosine and sine pair.
Definition math_functions.h:50
A 3x3 matrix.
Definition math_functions.h:99
A plane.
Definition math_functions.h:113
A quaternion.
Definition math_functions.h:58
The closest points between to segments or infinite lines.
Definition math_functions.h:1060
A rigid transform.
Definition math_functions.h:65
A 2D vector.
Definition math_functions.h:34
A 3D vector.
Definition math_functions.h:41