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_INLINE float b3AbsFloat( float a )
160{
161 return a < 0 ? -a : a;
162}
163
165B3_INLINE float b3MinFloat( float a, float b )
166{
167 return a < b ? a : b;
168}
169
171B3_INLINE float b3MaxFloat( float a, float b )
172{
173 return a > b ? a : b;
174}
175
177B3_INLINE float b3ClampFloat( float a, float lower, float upper )
178{
179 return a < lower ? lower : ( upper < a ? upper : a );
180}
181
183B3_INLINE float b3LerpFloat( float a, float b, float alpha )
184{
185 return ( 1.0f - alpha ) * a + alpha * b;
186}
187
192B3_API float b3Atan2( float y, float x );
193
196B3_API b3CosSin b3ComputeCosSin( float radians );
197
199B3_INLINE float b3Sin( float radians )
200{
201 b3CosSin cs = b3ComputeCosSin( radians );
202 return cs.sine;
203}
204
206B3_INLINE float b3Cos( float radians )
207{
208 b3CosSin cs = b3ComputeCosSin( radians );
209 return cs.cosine;
210}
211
213B3_INLINE float b3UnwindAngle( float radians )
214{
215 // Assuming this is deterministic
216 return remainderf( radians, 2.0f * B3_PI );
217}
218
220B3_INLINE b3Vec3 b3Add( b3Vec3 a, b3Vec3 b )
221{
222 return B3_LITERAL( b3Vec3 ){ a.x + b.x, a.y + b.y, a.z + b.z };
223}
224
226B3_INLINE b3Vec3 b3Sub( b3Vec3 a, b3Vec3 b )
227{
228 return B3_LITERAL( b3Vec3 ){ a.x - b.x, a.y - b.y, a.z - b.z };
229}
230
232B3_INLINE b3Vec3 b3Mul( b3Vec3 a, b3Vec3 b )
233{
234 return B3_LITERAL( b3Vec3 ){ a.x * b.x, a.y * b.y, a.z * b.z };
235}
236
238B3_INLINE b3Vec3 b3Neg( b3Vec3 a )
239{
240 return B3_LITERAL( b3Vec3 ){ -a.x, -a.y, -a.z };
241}
242
244B3_INLINE float b3Dot( b3Vec3 a, b3Vec3 b )
245{
246 return a.x * b.x + a.y * b.y + a.z * b.z;
247}
248
250B3_INLINE float b3Length( b3Vec3 v )
251{
252 return sqrtf( b3Dot( v, v ) );
253}
254
256B3_INLINE float b3LengthSquared( b3Vec3 a )
257{
258 return a.x * a.x + a.y * a.y + a.z * a.z;
259}
260
262B3_INLINE float b3Distance( b3Vec3 a, b3Vec3 b )
263{
264 b3Vec3 dv = { b.x - a.x, b.y - a.y, b.z - a.z };
265 return b3Length( dv );
266}
267
269B3_INLINE float b3DistanceSquared( b3Vec3 a, b3Vec3 b )
270{
271 b3Vec3 dv = { b.x - a.x, b.y - a.y, b.z - a.z };
272 return dv.x * dv.x + dv.y * dv.y + dv.z * dv.z;
273}
274
277{
278 float lengthSquared = a.x * a.x + a.y * a.y + a.z * a.z;
279
280 if ( lengthSquared > 1000.0f * FLT_MIN )
281 {
282 float s = 1.0f / sqrtf( lengthSquared );
283 b3Vec3 u = { s * a.x, s * a.y, s * a.z };
284 return u;
285 }
286
287 return B3_LITERAL( b3Vec3 ){ 0.0f, 0.0f, 0.0f };
288}
289
292B3_INLINE b3Vec3 b3GetLengthAndNormalize( float* length, b3Vec3 a )
293{
294 *length = b3Length( a );
295 if ( *length < FLT_EPSILON )
296 {
297 return b3Vec3_zero;
298 }
299
300 float invLength = 1.0f / *length;
301 b3Vec3 n = { invLength * a.x, invLength * a.y, invLength * a.z };
302 return n;
303}
304
306B3_INLINE b3Vec3 b3Perp( b3Vec3 a )
307{
308 // Suppose vector a has all equal components and is a unit vector: a = (s, s, s)
309 // Then 3*s*s = 1, s = sqrt(1/3) = 0.57735. This means that at least one component
310 // of a unit vector must be greater or equal to 0.57735.
311 b3Vec3 p;
312 if ( a.x < -0.5f || 0.5f < a.x )
313 {
314 p = B3_LITERAL( b3Vec3 ){ a.y, -a.x, 0.0f };
315 }
316 else
317 {
318 p = B3_LITERAL( b3Vec3 ){ 0.0f, a.z, -a.y };
319 }
320
321 return b3Normalize( p );
322}
323
325B3_INLINE bool b3IsNormalized( b3Vec3 a )
326{
327 float aa = b3Dot( a, a );
328 return b3AbsFloat( 1.0f - aa ) < 100.0f * FLT_EPSILON;
329}
330
332B3_INLINE b3Vec3 b3MulAdd( b3Vec3 a, float s, b3Vec3 b )
333{
334 return B3_LITERAL( b3Vec3 ){ a.x + s * b.x, a.y + s * b.y, a.z + s * b.z };
335}
336
338B3_INLINE b3Vec3 b3MulSub( b3Vec3 a, float s, b3Vec3 b )
339{
340 return B3_LITERAL( b3Vec3 ){ a.x - s * b.x, a.y - s * b.y, a.z - s * b.z };
341}
342
344B3_INLINE b3Vec3 b3MulSV( float s, b3Vec3 a )
345{
346 return B3_LITERAL( b3Vec3 ){ s * a.x, s * a.y, s * a.z };
347}
348
350B3_INLINE b3Vec3 b3Cross( b3Vec3 a, b3Vec3 b )
351{
352 b3Vec3 c;
353 c.x = a.y * b.z - a.z * b.y;
354 c.y = a.z * b.x - a.x * b.z;
355 c.z = a.x * b.y - a.y * b.x;
356 return c;
357}
358
360B3_INLINE b3Vec3 b3Lerp( b3Vec3 a, b3Vec3 b, float alpha )
361{
362 B3_ASSERT( 0.0f <= alpha && alpha <= 1.0f );
363
364 b3Vec3 c = {
365 ( 1.0f - alpha ) * a.x + alpha * b.x,
366 ( 1.0f - alpha ) * a.y + alpha * b.y,
367 ( 1.0f - alpha ) * a.z + alpha * b.z,
368 };
369 return c;
370}
371
373B3_INLINE b3Vec3 b3Blend2( float s, b3Vec3 a, float t, b3Vec3 b )
374{
375 b3Vec3 d = {
376 s * a.x + t * b.x,
377 s * a.y + t * b.y,
378 s * a.z + t * b.z,
379 };
380 return d;
381}
382
384B3_INLINE b3Vec3 b3Abs( b3Vec3 a )
385{
386 return B3_LITERAL( b3Vec3 ){
387 b3AbsFloat( a.x ),
388 b3AbsFloat( a.y ),
389 b3AbsFloat( a.z ),
390 };
391}
392
394B3_INLINE b3Vec3 b3Sign( b3Vec3 a )
395{
396 return B3_LITERAL( b3Vec3 ){
397 a.x >= 0.0f ? 1.0f : -1.0f,
398 a.y >= 0.0f ? 1.0f : -1.0f,
399 a.z >= 0.0f ? 1.0f : -1.0f,
400 };
401}
402
404B3_INLINE b3Vec3 b3Min( b3Vec3 a, b3Vec3 b )
405{
406 return B3_LITERAL( b3Vec3 ){
407 b3MinFloat( a.x, b.x ),
408 b3MinFloat( a.y, b.y ),
409 b3MinFloat( a.z, b.z ),
410 };
411}
412
414B3_INLINE b3Vec3 b3Max( b3Vec3 a, b3Vec3 b )
415{
416 return B3_LITERAL( b3Vec3 ){
417 b3MaxFloat( a.x, b.x ),
418 b3MaxFloat( a.y, b.y ),
419 b3MaxFloat( a.z, b.z ),
420 };
421}
422
424B3_INLINE b3Vec3 b3Clamp( b3Vec3 a, b3Vec3 lower, b3Vec3 upper )
425{
426 b3Vec3 b;
427 b.x = b3ClampFloat( a.x, lower.x, upper.x );
428 b.y = b3ClampFloat( a.y, lower.y, upper.y );
429 b.z = b3ClampFloat( a.z, lower.z, upper.z );
430 return b;
431}
432
436{
437 b3Vec3 absScale = b3Abs( a );
439 b3Vec3 safeScale = b3Mul( b3Sign( a ), b3Max( absScale, minScale ) );
440 return safeScale;
441}
442
444B3_INLINE bool b3IsNormalizedQuat( b3Quat q )
445{
446 float qq = q.v.x * q.v.x + q.v.y * q.v.y + q.v.z * q.v.z + q.s * q.s;
447 return 1.0f - 20.0f * FLT_EPSILON < qq && qq < 1.0f + 20.0f * FLT_EPSILON;
448}
449
452{
453 // v + 2 * cross(q.v, cross(q.v, v) + q.s * v)
454 // B3_ASSERT( b3IsNormalizedQuat( q ) );
455 b3Vec3 t1 = b3Cross( q.v, v );
456 b3Vec3 t2 = b3MulAdd( t1, q.s, v );
457 b3Vec3 t3 = b3Cross( q.v, t2 );
458 return b3MulAdd( v, 2.0f, t3 );
459}
460
463{
464 // v + 2 * cross(q.v, cross(q.v, v) - q.s * v)
465 // B3_ASSERT( b3IsNormalizedQuat( q ) );
466 b3Vec3 t1 = b3Cross( q.v, v );
467 b3Vec3 t2 = b3MulSub( t1, q.s, v );
468 b3Vec3 t3 = b3Cross( q.v, t2 );
469 return b3MulAdd( v, 2.0f, t3 );
470}
471
473B3_INLINE float b3DotQuat( b3Quat a, b3Quat b )
474{
475 return a.v.x * b.v.x + a.v.y * b.v.y + a.v.z * b.v.z + a.s * b.s;
476}
477
479B3_INLINE b3Quat b3MulQuat( b3Quat q1, b3Quat q2 )
480{
481 b3Vec3 t1 = b3Cross( q1.v, q2.v );
482 b3Vec3 t2 = b3MulAdd( t1, q1.s, q2.v );
483 b3Vec3 t3 = b3MulAdd( t2, q2.s, q1.v );
484 b3Quat q = { t3, q1.s * q2.s - b3Dot( q1.v, q2.v ) };
485 return q;
486}
487
490B3_INLINE b3Quat b3InvMulQuat( b3Quat q1, b3Quat q2 )
491{
492 b3Vec3 t1 = b3Cross( q2.v, q1.v );
493 b3Vec3 t2 = b3MulAdd( t1, q1.s, q2.v );
494 b3Vec3 t3 = b3MulSub( t2, q2.s, q1.v );
495 b3Quat q = { t3, q1.s * q2.s + b3Dot( q1.v, q2.v ) };
496 return q;
497}
498
501{
502 return B3_LITERAL( b3Quat ){ { -q.v.x, -q.v.y, -q.v.z }, q.s };
503}
504
507{
508 return B3_LITERAL( b3Quat ){ { -q.v.x, -q.v.y, -q.v.z }, -q.s };
509}
510
513{
514 float lengthSq = b3DotQuat( q, q );
515 if ( lengthSq > 1000.0f * FLT_MIN )
516 {
517 float s = 1.0f / sqrtf( lengthSq );
518 b3Quat qn = { { s * q.v.x, s * q.v.y, s * q.v.z }, s * q.s };
519 return qn;
520 }
521
522 return b3Quat_identity;
523}
524
526B3_INLINE b3Quat b3MakeQuatFromAxisAngle( b3Vec3 axis, float radians )
527{
528 B3_ASSERT( b3IsNormalized( axis ) );
529 b3CosSin cs = b3ComputeCosSin( 0.5f * radians );
530 b3Quat q = { { cs.sine * axis.x, cs.sine * axis.y, cs.sine * axis.z }, cs.cosine };
531 return q;
532}
533
535B3_INLINE b3Vec3 b3GetAxisAngle( float* radians, b3Quat q )
536{
537 float length = sqrtf( q.v.x * q.v.x + q.v.y * q.v.y + q.v.z * q.v.z );
538 *radians = 2.0f * b3Atan2( length, q.s );
539 if ( length > 0.0f )
540 {
541 float invLength = 1.0f / length;
542 b3Vec3 axis = { invLength * q.v.x, invLength * q.v.y, invLength * q.v.z };
543 return axis;
544 }
545
546 return b3Vec3_zero;
547}
548
550B3_INLINE float b3GetQuatAngle( b3Quat q )
551{
552 float length = sqrtf( q.v.x * q.v.x + q.v.y * q.v.y + q.v.z * q.v.z );
553 return 2.0f * b3Atan2( length, q.s );
554}
555
558
561
563B3_INLINE float b3GetTwistAngle( b3Quat q )
564{
565 // Account for polarity to keep the twist angle in range.
566 // This is simpler than asking the user to check polarity or unwinding.
567 float twist = q.s < 0.0f ? b3Atan2( -q.v.z, -q.s ) : b3Atan2( q.v.z, q.s );
568 twist *= 2.0f;
569 B3_ASSERT( -B3_PI <= twist && twist <= B3_PI );
570 return twist;
571}
572
574B3_INLINE float b3GetSwingAngle( b3Quat q )
575{
576 // Polarity should not matter because all terms are squared.
577 float x = sqrtf( q.v.z * q.v.z + q.s * q.s );
578 float y = sqrtf( q.v.x * q.v.x + q.v.y * q.v.y );
579 float swing = 2.0f * b3Atan2( y, x );
580 B3_ASSERT( 0.0f <= swing && swing <= B3_PI );
581 return swing;
582}
583
585B3_INLINE b3Quat b3NLerp( b3Quat q1, b3Quat q2, float alpha )
586{
587 B3_VALIDATE( 0.0f <= alpha && alpha <= 1.0f );
588 if ( b3DotQuat( q1, q2 ) < 0.0f )
589 {
590 q1 = B3_LITERAL( b3Quat ){ { -q1.v.x, -q1.v.y, -q1.v.z }, -q1.s };
591 }
592
593 b3Quat q;
594 q.v = b3Lerp( q1.v, q2.v, alpha );
595 q.s = ( 1.0f - alpha ) * q1.s + alpha * q2.s;
596
597 return b3NormalizeQuat( q );
598}
599
604{
605 b3Transform out;
606 out.p = b3Add( b3RotateVector( a.q, b.p ), a.p );
607 out.q = b3MulQuat( a.q, b.q );
608 return out;
609}
610
615{
616 b3Transform out;
617 out.p = b3InvRotateVector( a.q, b3Sub( b.p, a.p ) );
618 out.q = b3InvMulQuat( a.q, b.q );
619 return out;
620}
621
624{
625 b3Transform out;
626 out.p = b3InvRotateVector( t.q, b3Neg( t.p ) );
627 out.q = b3Conjugate( t.q );
628 return out;
629}
630
633{
634 b3Vec3 rv = b3RotateVector( t.q, v );
635 return b3Add( rv, t.p );
636}
637
640{
641 return b3InvRotateVector( t.q, b3Sub( v, t.p ) );
642}
643
644// World position boundary. These cross between the double precision world space at the public
645// boundary and the float interior. One set of bodies serves both modes: the typedefs collapse
646// the types in float mode and the explicit float casts become no-ops.
647
649B3_INLINE b3Pos b3ToPos( b3Vec3 v )
650{
651 return B3_LITERAL( b3Pos ){ v.x, v.y, v.z };
652}
653
655B3_INLINE b3Vec3 b3ToVec3( b3Pos p )
656{
657 return B3_LITERAL( b3Vec3 ){ (float)p.x, (float)p.y, (float)p.z };
658}
659
664B3_INLINE float b3RoundDownFloat( double x )
665{
666#if defined( BOX3D_DOUBLE_PRECISION )
667 float f = (float)x;
668 return (double)f > x ? nextafterf( f, -FLT_MAX ) : f;
669#else
670 return (float)x;
671#endif
672}
673
675B3_INLINE float b3RoundUpFloat( double x )
676{
677#if defined( BOX3D_DOUBLE_PRECISION )
678 float f = (float)x;
679 return (double)f < x ? nextafterf( f, FLT_MAX ) : f;
680#else
681 return (float)x;
682#endif
683}
684
686B3_INLINE b3Vec3 b3SubPos( b3Pos a, b3Pos b )
687{
688 return B3_LITERAL( b3Vec3 ){ (float)( a.x - b.x ), (float)( a.y - b.y ), (float)( a.z - b.z ) };
689}
690
692B3_INLINE b3Pos b3OffsetPos( b3Pos p, b3Vec3 d )
693{
694 return B3_LITERAL( b3Pos ){ p.x + d.x, p.y + d.y, p.z + d.z };
695}
696
698B3_INLINE b3Pos b3LerpPosition( b3Pos a, b3Pos b, float t )
699{
700 return B3_LITERAL( b3Pos ){
701 ( 1.0f - t ) * a.x + t * b.x,
702 ( 1.0f - t ) * a.y + t * b.y,
703 ( 1.0f - t ) * a.z + t * b.z,
704 };
705}
706
709{
710 b3Vec3 r = b3RotateVector( t.q, p );
711 return B3_LITERAL( b3Pos ){ t.p.x + r.x, t.p.y + r.y, t.p.z + r.z };
712}
713
716{
717 b3Vec3 d = { (float)( p.x - t.p.x ), (float)( p.y - t.p.y ), (float)( p.z - t.p.z ) };
718 return b3InvRotateVector( t.q, d );
719}
720
723{
724 b3Transform C;
725 C.q = b3InvMulQuat( A.q, B.q );
726 b3Vec3 d = { (float)( B.p.x - A.p.x ), (float)( B.p.y - A.p.y ), (float)( B.p.z - A.p.z ) };
727 C.p = b3InvRotateVector( A.q, d );
728 return C;
729}
730
733{
735 C.q = b3MulQuat( A.q, B.q );
736 b3Vec3 r = b3RotateVector( A.q, B.p );
737 C.p = B3_LITERAL( b3Pos ){ A.p.x + r.x, A.p.y + r.y, A.p.z + r.z };
738 return C;
739}
740
743{
744 b3Transform r;
745 r.q = t.q;
746 r.p = B3_LITERAL( b3Vec3 ){ (float)( t.p.x - base.x ), (float)( t.p.y - base.y ), (float)( t.p.z - base.z ) };
747 return r;
748}
749
752{
754 w.p = b3ToPos( t.p );
755 w.q = t.q;
756 return w;
757}
758
762B3_INLINE b3AABB b3OffsetAABB( b3AABB localBox, b3Pos origin )
763{
764 b3AABB out;
765 out.lowerBound.x = b3RoundDownFloat( origin.x + localBox.lowerBound.x );
766 out.lowerBound.y = b3RoundDownFloat( origin.y + localBox.lowerBound.y );
767 out.lowerBound.z = b3RoundDownFloat( origin.z + localBox.lowerBound.z );
768 out.upperBound.x = b3RoundUpFloat( origin.x + localBox.upperBound.x );
769 out.upperBound.y = b3RoundUpFloat( origin.y + localBox.upperBound.y );
770 out.upperBound.z = b3RoundUpFloat( origin.z + localBox.upperBound.z );
771 return out;
772}
773
775B3_INLINE float b3Det( b3Matrix3 m )
776{
777 return b3Dot( m.cx, b3Cross( m.cy, m.cz ) );
778}
779
782{
783 b3Vec3 b = {
784 m.cx.x * a.x + m.cy.x * a.y + m.cz.x * a.z,
785 m.cx.y * a.x + m.cy.y * a.y + m.cz.y * a.z,
786 m.cx.z * a.x + m.cy.z * a.y + m.cz.z * a.z,
787 };
788 return b;
789}
790
793{
794 return B3_LITERAL( b3Matrix3 ){
795 { -a.cx.x, -a.cx.y, -a.cx.z },
796 { -a.cy.x, -a.cy.y, -a.cy.z },
797 { -a.cz.x, -a.cz.y, -a.cz.z },
798 };
799}
800
804{
805 return B3_LITERAL( b3Matrix3 ){
806 { a.cx.x + b.cx.x, a.cx.y + b.cx.y, a.cx.z + b.cx.z },
807 { a.cy.x + b.cy.x, a.cy.y + b.cy.y, a.cy.z + b.cy.z },
808 { a.cz.x + b.cz.x, a.cz.y + b.cz.y, a.cz.z + b.cz.z },
809 };
810}
811
815{
816 return B3_LITERAL( b3Matrix3 ){
817 { a.cx.x - b.cx.x, a.cx.y - b.cx.y, a.cx.z - b.cx.z },
818 { a.cy.x - b.cy.x, a.cy.y - b.cy.y, a.cy.z - b.cy.z },
819 { a.cz.x - b.cz.x, a.cz.y - b.cz.y, a.cz.z - b.cz.z },
820 };
821}
822
824B3_INLINE b3Matrix3 b3MulSM( float s, b3Matrix3 a )
825{
826 return B3_LITERAL( b3Matrix3 ){
827 { s * a.cx.x, s * a.cx.y, s * a.cx.z },
828 { s * a.cy.x, s * a.cy.y, s * a.cy.z },
829 { s * a.cz.x, s * a.cz.y, s * a.cz.z },
830 };
831}
832
836{
837 b3Matrix3 out;
838 out.cx = b3MulMV( a, b.cx );
839 out.cy = b3MulMV( a, b.cy );
840 out.cz = b3MulMV( a, b.cz );
841 return out;
842}
843
846{
847 b3Matrix3 out;
848 out.cx = B3_LITERAL( b3Vec3 ){ m.cx.x, m.cy.x, m.cz.x };
849 out.cy = B3_LITERAL( b3Vec3 ){ m.cx.y, m.cy.y, m.cz.y };
850 out.cz = B3_LITERAL( b3Vec3 ){ m.cx.z, m.cy.z, m.cz.z };
851
852 return out;
853}
854
857{
858 float det = b3Det( m );
859 if ( b3AbsFloat( det ) > 1000.0f * FLT_MIN )
860 {
861 float invDet = 1.0f / det;
862 b3Matrix3 out;
863 out.cx = b3MulSV( invDet, b3Cross( m.cy, m.cz ) );
864 out.cy = b3MulSV( invDet, b3Cross( m.cz, m.cx ) );
865 out.cz = b3MulSV( invDet, b3Cross( m.cx, m.cy ) );
866
867 return b3Transpose( out );
868 }
869
870 return b3Mat3_zero;
871}
872
876{
877 float det = b3Det( m );
878 if ( b3AbsFloat( det ) > 1000.0f * FLT_MIN )
879 {
880 float invDet = 1.0f / det;
881 b3Matrix3 s;
882 s.cx = b3Cross( m.cy, m.cz );
883 s.cy = b3Cross( m.cz, m.cx );
884 s.cz = b3Cross( m.cx, m.cy );
885
886 b3Vec3 b = {
887 invDet * b3Dot( s.cx, a ),
888 invDet * b3Dot( s.cy, a ),
889 invDet * b3Dot( s.cz, a ),
890 };
891
892 return b;
893 }
894
895 return b3Vec3_zero;
896}
897
900{
901 float det = b3Det( m );
902 if ( b3AbsFloat( det ) > 1000.0f * FLT_MIN )
903 {
904 float invDet = 1.0f / det;
905 b3Matrix3 out;
906 out.cx = b3MulSV( invDet, b3Cross( m.cy, m.cz ) );
907 out.cy = b3MulSV( invDet, b3Cross( m.cz, m.cx ) );
908 out.cz = b3MulSV( invDet, b3Cross( m.cx, m.cy ) );
909 return out;
910 }
911
912 return b3Mat3_zero;
913}
914
917{
918 b3Matrix3 out;
919 out.cx = b3Abs( m.cx );
920 out.cy = b3Abs( m.cy );
921 out.cz = b3Abs( m.cz );
922
923 return out;
924}
925
930{
931 float xx = q.v.x * q.v.x;
932 float yy = q.v.y * q.v.y;
933 float zz = q.v.z * q.v.z;
934 float xy = q.v.x * q.v.y;
935 float xz = q.v.x * q.v.z;
936 float xw = q.v.x * q.s;
937 float yz = q.v.y * q.v.z;
938 float yw = q.v.y * q.s;
939 float zw = q.v.z * q.s;
940
941 return B3_LITERAL( b3Matrix3 ){
942 { 1.0f - 2.0f * ( yy + zz ), 2.0f * ( xy + zw ), 2.0f * ( xz - yw ) },
943 { 2.0f * ( xy - zw ), 1.0f - 2.0f * ( xx + zz ), 2.0f * ( yz + xw ) },
944 { 2.0f * ( xz + yw ), 2.0f * ( yz - xw ), 1.0f - 2.0f * ( xx + yy ) },
945 };
946}
947
950B3_API b3Matrix3 b3Steiner( float mass, b3Vec3 origin );
951
953B3_INLINE b3AABB b3MakeAABB( const b3Vec3* points, int count, float radius )
954{
955 B3_ASSERT( count > 0 );
956 b3AABB a = { points[0], points[0] };
957 for ( int i = 1; i < count; ++i )
958 {
959 a.lowerBound = b3Min( a.lowerBound, points[i] );
960 a.upperBound = b3Max( a.upperBound, points[i] );
961 }
962
963 b3Vec3 r = { radius, radius, radius };
964 a.lowerBound = b3Sub( a.lowerBound, r );
965 a.upperBound = b3Add( a.upperBound, r );
966
967 return a;
968}
969
971B3_INLINE bool b3AABB_Contains( b3AABB a, b3AABB b )
972{
973 if ( a.lowerBound.x > b.lowerBound.x || b.upperBound.x > a.upperBound.x )
974 return false;
975 if ( a.lowerBound.y > b.lowerBound.y || b.upperBound.y > a.upperBound.y )
976 return false;
977 if ( a.lowerBound.z > b.lowerBound.z || b.upperBound.z > a.upperBound.z )
978 return false;
979
980 return true;
981}
982
984B3_INLINE float b3AABB_Area( b3AABB a )
985{
986 b3Vec3 delta = b3Sub( a.upperBound, a.lowerBound );
987 return 2.0f * ( delta.x * delta.y + delta.y * delta.z + delta.z * delta.x );
988}
989
992{
993 return b3MulSV( 0.5f, b3Add( a.upperBound, a.lowerBound ) );
994}
995
998{
999 return b3MulSV( 0.5f, b3Sub( a.upperBound, a.lowerBound ) );
1000}
1001
1004{
1005 b3AABB out;
1006 out.lowerBound = b3Min( a.lowerBound, b.lowerBound );
1007 out.upperBound = b3Max( a.upperBound, b.upperBound );
1008 return out;
1009}
1010
1012B3_INLINE b3AABB b3AABB_Inflate( b3AABB a, float extension )
1013{
1014 b3Vec3 radius = { extension, extension, extension };
1015
1016 b3AABB out;
1017 out.lowerBound = b3Sub( a.lowerBound, radius );
1018 out.upperBound = b3Add( a.upperBound, radius );
1019 return out;
1020}
1021
1023B3_INLINE bool b3AABB_Overlaps( b3AABB a, b3AABB b )
1024{
1025 // No intersection if separated along one axis
1026 if ( a.upperBound.x < b.lowerBound.x || a.lowerBound.x > b.upperBound.x )
1027 return false;
1028 if ( a.upperBound.y < b.lowerBound.y || a.lowerBound.y > b.upperBound.y )
1029 return false;
1030 if ( a.upperBound.z < b.lowerBound.z || a.lowerBound.z > b.upperBound.z )
1031 return false;
1032
1033 // Overlapping on all axis means bounds are intersecting
1034 return true;
1035}
1036
1041{
1042 b3Vec3 center = b3TransformPoint( transform, b3AABB_Center( a ) );
1043 b3Matrix3 m = b3MakeMatrixFromQuat( transform.q );
1044 b3Vec3 extent = b3MulMV( b3AbsMatrix3( m ), b3AABB_Extents( a ) );
1045 b3AABB out = { b3Sub( center, extent ), b3Add( center, extent ) };
1046 return out;
1047}
1048
1051{
1052 return b3Clamp( point, a.lowerBound, a.upperBound );
1053}
1054
1057{
1058 b3Vec3 point1;
1059 float fraction1;
1060 b3Vec3 point2;
1061 float fraction2;
1063
1066
1069
1072
1074B3_API bool b3IsValidFloat( float a );
1075
1077B3_API bool b3IsValidVec3( b3Vec3 a );
1078
1080B3_API bool b3IsValidQuat( b3Quat q );
1081
1084
1087
1089B3_API bool b3IsValidAABB( b3AABB a );
1090
1092B3_API bool b3IsBoundedAABB( b3AABB a );
1093
1095B3_API bool b3IsSaneAABB( b3AABB a );
1096
1098B3_API bool b3IsValidPlane( b3Plane a );
1099
1101B3_API bool b3IsValidPosition( b3Pos p );
1102
1105 // math
1107
1115
1116#ifdef __cplusplus
1117
1119B3_FORCE_INLINE b3Vec3& operator+=( b3Vec3& a, b3Vec3 b )
1120{
1121 a.x += b.x;
1122 a.y += b.y;
1123 a.z += b.z;
1124 return a;
1125}
1126
1128B3_FORCE_INLINE b3Vec3& operator-=( b3Vec3& a, b3Vec3 b )
1129{
1130 a.x -= b.x;
1131 a.y -= b.y;
1132 a.z -= b.z;
1133 return a;
1134}
1135
1137B3_FORCE_INLINE b3Vec3& operator*=( b3Vec3& a, float s )
1138{
1139 a.x *= s;
1140 a.y *= s;
1141 a.z *= s;
1142 return a;
1143}
1144
1146B3_FORCE_INLINE b3Vec3 operator-( b3Vec3 a )
1147{
1148 return { -a.x, -a.y, -a.z };
1149}
1150
1152B3_FORCE_INLINE b3Vec3 operator*( float s, b3Vec3 a )
1153{
1154 return { s * a.x, s * a.y, s * a.z };
1155}
1156
1158B3_FORCE_INLINE b3Vec3 operator*( b3Vec3 a, float s )
1159{
1160 return { s * a.x, s * a.y, s * a.z };
1161}
1162
1164B3_FORCE_INLINE b3Vec3 operator*( b3Vec3 a, b3Vec3 b )
1165{
1166 return { a.x * b.x, a.y * b.y, a.z * b.z };
1167}
1168
1170B3_FORCE_INLINE b3Vec3 operator+( b3Vec3 a, b3Vec3 b )
1171{
1172 return { a.x + b.x, a.y + b.y, a.z + b.z };
1173}
1174
1176B3_FORCE_INLINE b3Vec3 operator-( b3Vec3 a, b3Vec3 b )
1177{
1178 return { a.x - b.x, a.y - b.y, a.z - b.z };
1179}
1180
1181#if defined( BOX3D_DOUBLE_PRECISION )
1182
1184B3_FORCE_INLINE b3Pos operator+( b3Pos a, b3Vec3 b )
1185{
1186 return { a.x + b.x, a.y + b.y, a.z + b.z };
1187}
1188
1190B3_FORCE_INLINE b3Pos operator-( b3Pos a, b3Vec3 b )
1191{
1192 return { a.x - b.x, a.y - b.y, a.z - b.z };
1193}
1194
1196B3_FORCE_INLINE b3Vec3 operator-( b3Pos a, b3Pos b )
1197{
1198 return { (float)( a.x - b.x ), (float)( a.y - b.y ), (float)( a.z - b.z ) };
1199}
1200
1201#endif
1202
1203#endif
1204 // 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:199
b3AABB b3AABB_Union(b3AABB a, b3AABB b)
Get the union of two axis-aligned bounding boxes.
Definition math_functions.h:1003
b3Pos b3ToPos(b3Vec3 v)
Convert a vector to a world position.
Definition math_functions.h:649
b3AABB b3MakeAABB(const b3Vec3 *points, int count, float radius)
Get the AABB of a point cloud.
Definition math_functions.h:953
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:424
b3Pos b3TransformWorldPoint(b3WorldTransform t, b3Vec3 p)
Transform a local point to a world position. Rotation in float, translation in double.
Definition math_functions.h:708
bool b3AABB_Contains(b3AABB a, b3AABB b)
Does a fully contain b?
Definition math_functions.h:971
b3Vec3 b3InvRotateVector(b3Quat q, b3Vec3 v)
Inverse rotate a vector.
Definition math_functions.h:462
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:325
b3Vec3 b3ToVec3(b3Pos p)
Lossy conversion of a world position to a float vector.
Definition math_functions.h:655
B3_FORCE_INLINE b3Matrix3 b3MakeMatrixFromQuat(b3Quat q)
Make a matrix from a quaternion.
Definition math_functions.h:929
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:444
float b3AABB_Area(b3AABB a)
Get the surface area of an axis-aligned bounding box.
Definition math_functions.h:984
b3Matrix3 b3InvertMatrix(b3Matrix3 m)
General matrix inverse.
Definition math_functions.h:856
b3Transform b3ToRelativeTransform(b3WorldTransform t, b3Pos base)
Shift a world transform into the frame of a base position.
Definition math_functions.h:742
b3Matrix3 b3InvertT(b3Matrix3 m)
Invert a matrix.
Definition math_functions.h:899
float b3Cos(float radians)
Definition math_functions.h:206
b3Matrix3 b3SubMM(b3Matrix3 a, b3Matrix3 b)
Matrix subtraction.
Definition math_functions.h:814
b3Vec3 b3Sub(b3Vec3 a, b3Vec3 b)
Vector subtraction.
Definition math_functions.h:226
#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:732
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:506
b3Transform b3InvMulWorldTransforms(b3WorldTransform A, b3WorldTransform B)
Relative transform of frame B in frame A. The narrow phase boundary.
Definition math_functions.h:722
float b3Dot(b3Vec3 a, b3Vec3 b)
Vector dot product.
Definition math_functions.h:244
b3Vec3 b3ClosestPointToAABB(b3Vec3 point, b3AABB a)
Get the closest point on an axis-aligned bounding box.
Definition math_functions.h:1050
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:875
b3Quat b3InvMulQuat(b3Quat q1, b3Quat q2)
Compute a relative quaternion.
Definition math_functions.h:490
float b3DistanceSquared(b3Vec3 a, b3Vec3 b)
Squared distance between two points.
Definition math_functions.h:269
float b3AbsFloat(float a)
Definition math_functions.h:159
b3Matrix3 b3NegateMat3(b3Matrix3 a)
Negate a matrix.
Definition math_functions.h:792
b3Vec3 b3GetLengthAndNormalize(float *length, b3Vec3 a)
Normalize a vector and return the length.
Definition math_functions.h:292
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:845
float b3UnwindAngle(float radians)
Convert any angle into the range [-pi, pi].
Definition math_functions.h:213
b3Matrix3 b3AbsMatrix3(b3Matrix3 m)
Get the component-wise absolute value of a matrix.
Definition math_functions.h:916
b3Vec3 b3MulMV(b3Matrix3 m, b3Vec3 a)
Multiply a matrix times a column vector.
Definition math_functions.h:781
b3Transform b3MulTransforms(b3Transform a, b3Transform b)
Multiply two transforms.
Definition math_functions.h:603
float b3GetQuatAngle(b3Quat q)
Get the angle for a quaternion in radians.
Definition math_functions.h:550
b3AABB b3AABB_Transform(b3Transform transform, b3AABB a)
Transform an axis-aligned bounding box.
Definition math_functions.h:1040
float b3DotQuat(b3Quat a, b3Quat b)
Compute dot product of two quaternions. Useful for polarity tests.
Definition math_functions.h:473
b3Vec3 b3AABB_Center(b3AABB a)
Get the center of an axis-aligned bounding box.
Definition math_functions.h:991
float b3RoundUpFloat(double x)
Narrow a world coordinate to float, rounding toward positive infinity.
Definition math_functions.h:675
float b3Distance(b3Vec3 a, b3Vec3 b)
Distance between two points.
Definition math_functions.h:262
b3Quat b3MakeQuatFromMatrix(const b3Matrix3 *m)
Extract a quaternion from a rotation matrix.
b3Pos b3OffsetPos(b3Pos p, b3Vec3 d)
p + d
Definition math_functions.h:692
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:220
b3Vec3 b3SubPos(b3Pos a, b3Pos b)
a - b, demoted to float. The primary precision boundary operation.
Definition math_functions.h:686
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:414
b3Quat b3NLerp(b3Quat q1, b3Quat q2, float alpha)
Linearly interpolate and normalize between two quaternions.
Definition math_functions.h:585
b3Matrix3 b3AddMM(b3Matrix3 a, b3Matrix3 b)
Matrix addition.
Definition math_functions.h:803
b3Vec3 b3MulSV(float s, b3Vec3 a)
s * a
Definition math_functions.h:344
b3Vec3 b3MulAdd(b3Vec3 a, float s, b3Vec3 b)
a + s * b
Definition math_functions.h:332
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:451
b3Vec3 b3Neg(b3Vec3 a)
Vector negation.
Definition math_functions.h:238
b3Vec3 b3Sign(b3Vec3 a)
Component-wise -1 or 1 (1 if zero).
Definition math_functions.h:394
b3Vec3 b3SafeScale(b3Vec3 a)
Create a safe scaling value for scaling collision.
Definition math_functions.h:435
b3Vec3 b3Lerp(b3Vec3 a, b3Vec3 b, float alpha)
Linearly interpolate between two vectors.
Definition math_functions.h:360
b3Vec3 b3Mul(b3Vec3 a, b3Vec3 b)
Vector component-wise multiplication.
Definition math_functions.h:232
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:639
#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:183
b3Vec3 b3Blend2(float s, b3Vec3 a, float t, b3Vec3 b)
Blend two vectors: s * a + t * b.
Definition math_functions.h:373
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:614
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:563
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:1012
b3Vec3 b3GetAxisAngle(float *radians, b3Quat q)
Get the axis and angle from a quaternion. Assumes the quaternion is normalized.
Definition math_functions.h:535
b3Quat b3Conjugate(b3Quat q)
Quaternion conjugate (cheap inverse).
Definition math_functions.h:500
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:775
float b3GetSwingAngle(b3Quat q)
Swing angle used for cone limit.
Definition math_functions.h:574
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:762
float b3ClampFloat(float a, float lower, float upper)
Definition math_functions.h:177
bool b3AABB_Overlaps(b3AABB a, b3AABB b)
Do two axis-aligned boxes overlap?
Definition math_functions.h:1023
b3Transform b3InvertTransform(b3Transform t)
Get the inverse of a transform.
Definition math_functions.h:623
float b3MaxFloat(float a, float b)
Definition math_functions.h:171
b3Vec3 b3Perp(b3Vec3 a)
Get a unit vector that is perpendicular to the supplied vector.
Definition math_functions.h:306
b3Vec3 b3MulSub(b3Vec3 a, float s, b3Vec3 b)
a - s * b
Definition math_functions.h:338
b3Vec3 b3InvTransformWorldPoint(b3WorldTransform t, b3Pos p)
Transform a world position to a local point. One double subtraction, then float.
Definition math_functions.h:715
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:276
b3Vec3 b3TransformPoint(b3Transform t, b3Vec3 v)
Transform a point.
Definition math_functions.h:632
b3Matrix3 b3MulMM(b3Matrix3 a, b3Matrix3 b)
Matrix multiplication.
Definition math_functions.h:835
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:664
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:526
b3Vec3 b3AABB_Extents(b3AABB a)
Get the extents (half-widths) of an axis-aligned bounding box.
Definition math_functions.h:997
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:350
b3Quat b3NormalizeQuat(b3Quat q)
Normalize a quaternion.
Definition math_functions.h:512
b3Pos b3LerpPosition(b3Pos a, b3Pos b, float t)
World position interpolation for sweeps and sampling.
Definition math_functions.h:698
b3Vec3 b3Min(b3Vec3 a, b3Vec3 b)
Component-wise minimum value.
Definition math_functions.h:404
b3WorldTransform b3MakeWorldTransform(b3Transform t)
Promote a float transform to a world transform. Lossless.
Definition math_functions.h:751
float b3LengthSquared(b3Vec3 a)
Vector length squared.
Definition math_functions.h:256
b3Quat b3MulQuat(b3Quat q1, b3Quat q2)
Multiply two quaternions.
Definition math_functions.h:479
float b3MinFloat(float a, float b)
Definition math_functions.h:165
b3Vec3 b3Abs(b3Vec3 a)
Component-wise absolute value.
Definition math_functions.h:384
b3Matrix3 b3MulSM(float s, b3Matrix3 a)
Multiply a matrix by a scalar, component-wise.
Definition math_functions.h:824
float b3Length(b3Vec3 v)
Vector length.
Definition math_functions.h:250
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:1057
A rigid transform.
Definition math_functions.h:65
A 2D vector.
Definition math_functions.h:34
A 3D vector.
Definition math_functions.h:41