so://phie

freezo

A retro platform game
git clone git://soophie.de/freezo

blob: 15e403cbba2f9860d37f74479e5e67e9b116304a (63013 bytes)[raw]

1/**********************************************************************************************

2*

3* raymath v1.5 - Math functions to work with Vector2, Vector3, Matrix and Quaternions

4*

5* CONVENTIONS:

6* - Matrix structure is defined as row-major (memory layout) but parameters naming AND all

7* math operations performed by the library consider the structure as it was column-major

8* It is like transposed versions of the matrices are used for all the maths

9* It benefits some functions making them cache-friendly and also avoids matrix

10* transpositions sometimes required by OpenGL

11* Example: In memory order, row0 is [m0 m4 m8 m12] but in semantic math row0 is [m0 m1 m2 m3]

12* - Functions are always self-contained, no function use another raymath function inside,

13* required code is directly re-implemented inside

14* - Functions input parameters are always received by value (2 unavoidable exceptions)

15* - Functions use always a "result" variable for return

16* - Functions are always defined inline

17* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)

18* - No compound literals used to make sure libray is compatible with C++

19*

20* CONFIGURATION:

21* #define RAYMATH_IMPLEMENTATION

22* Generates the implementation of the library into the included file.

23* If not defined, the library is in header only mode and can be included in other headers

24* or source files without problems. But only ONE file should hold the implementation.

25*

26* #define RAYMATH_STATIC_INLINE

27* Define static inline functions code, so #include header suffices for use.

28* This may use up lots of memory.

29*

30*

31* LICENSE: zlib/libpng

32*

33* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5)

34*

35* This software is provided "as-is", without any express or implied warranty. In no event

36* will the authors be held liable for any damages arising from the use of this software.

37*

38* Permission is granted to anyone to use this software for any purpose, including commercial

39* applications, and to alter it and redistribute it freely, subject to the following restrictions:

40*

41* 1. The origin of this software must not be misrepresented; you must not claim that you

42* wrote the original software. If you use this software in a product, an acknowledgment

43* in the product documentation would be appreciated but is not required.

44*

45* 2. Altered source versions must be plainly marked as such, and must not be misrepresented

46* as being the original software.

47*

48* 3. This notice may not be removed or altered from any source distribution.

49*

50**********************************************************************************************/

51

52#ifndef RAYMATH_H

53#define RAYMATH_H

54

55#if defined(RAYMATH_IMPLEMENTATION) && defined(RAYMATH_STATIC_INLINE)

56 #error "Specifying both RAYMATH_IMPLEMENTATION and RAYMATH_STATIC_INLINE is contradictory"

57#endif

58

59// Function specifiers definition

60#if defined(RAYMATH_IMPLEMENTATION)

61 #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)

62 #define RMAPI __declspec(dllexport) extern inline // We are building raylib as a Win32 shared library (.dll)

63 #elif defined(BUILD_LIBTYPE_SHARED)

64 #define RMAPI __attribute__((visibility("default"))) // We are building raylib as a Unix shared library (.so/.dylib)

65 #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)

66 #define RMAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll)

67 #else

68 #define RMAPI extern inline // Provide external definition

69 #endif

70#elif defined(RAYMATH_STATIC_INLINE)

71 #define RMAPI static inline // Functions may be inlined, no external out-of-line definition

72#else

73 #if defined(__TINYC__)

74 #define RMAPI static inline // plain inline not supported by tinycc (See issue #435)

75 #else

76 #define RMAPI inline // Functions may be inlined or external definition used

77 #endif

78#endif

79

80//----------------------------------------------------------------------------------

81// Defines and Macros

82//----------------------------------------------------------------------------------

83#ifndef PI

84 #define PI 3.14159265358979323846f

85#endif

86

87#ifndef EPSILON

88 #define EPSILON 0.000001f

89#endif

90

91#ifndef DEG2RAD

92 #define DEG2RAD (PI/180.0f)

93#endif

94

95#ifndef RAD2DEG

96 #define RAD2DEG (180.0f/PI)

97#endif

98

99// Get float vector for Matrix

100#ifndef MatrixToFloat

101 #define MatrixToFloat(mat) (MatrixToFloatV(mat).v)

102#endif

103

104// Get float vector for Vector3

105#ifndef Vector3ToFloat

106 #define Vector3ToFloat(vec) (Vector3ToFloatV(vec).v)

107#endif

108

109//----------------------------------------------------------------------------------

110// Types and Structures Definition

111//----------------------------------------------------------------------------------

112#if !defined(RL_VECTOR2_TYPE)

113// Vector2 type

114typedef struct Vector2 {

115 float x;

116 float y;

117} Vector2;

118#define RL_VECTOR2_TYPE

119#endif

120

121#if !defined(RL_VECTOR3_TYPE)

122// Vector3 type

123typedef struct Vector3 {

124 float x;

125 float y;

126 float z;

127} Vector3;

128#define RL_VECTOR3_TYPE

129#endif

130

131#if !defined(RL_VECTOR4_TYPE)

132// Vector4 type

133typedef struct Vector4 {

134 float x;

135 float y;

136 float z;

137 float w;

138} Vector4;

139#define RL_VECTOR4_TYPE

140#endif

141

142#if !defined(RL_QUATERNION_TYPE)

143// Quaternion type

144typedef Vector4 Quaternion;

145#define RL_QUATERNION_TYPE

146#endif

147

148#if !defined(RL_MATRIX_TYPE)

149// Matrix type (OpenGL style 4x4 - right handed, column major)

150typedef struct Matrix {

151 float m0, m4, m8, m12; // Matrix first row (4 components)

152 float m1, m5, m9, m13; // Matrix second row (4 components)

153 float m2, m6, m10, m14; // Matrix third row (4 components)

154 float m3, m7, m11, m15; // Matrix fourth row (4 components)

155} Matrix;

156#define RL_MATRIX_TYPE

157#endif

158

159// NOTE: Helper types to be used instead of array return types for *ToFloat functions

160typedef struct float3 {

161 float v[3];

162} float3;

163

164typedef struct float16 {

165 float v[16];

166} float16;

167

168#include <math.h> // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), floor(), fminf(), fmaxf(), fabsf()

169

170//----------------------------------------------------------------------------------

171// Module Functions Definition - Utils math

172//----------------------------------------------------------------------------------

173

174// Clamp float value

175RMAPI float Clamp(float value, float min, float max)

176{

177 float result = (value < min) ? min : value;

178

179 if (result > max) result = max;

180

181 return result;

182}

183

184// Calculate linear interpolation between two floats

185RMAPI float Lerp(float start, float end, float amount)

186{

187 float result = start + amount*(end - start);

188

189 return result;

190}

191

192// Normalize input value within input range

193RMAPI float Normalize(float value, float start, float end)

194{

195 float result = (value - start)/(end - start);

196

197 return result;

198}

199

200// Remap input value within input range to output range

201RMAPI float Remap(float value, float inputStart, float inputEnd, float outputStart, float outputEnd)

202{

203 float result = (value - inputStart)/(inputEnd - inputStart)*(outputEnd - outputStart) + outputStart;

204

205 return result;

206}

207

208// Wrap input value from min to max

209RMAPI float Wrap(float value, float min, float max)

210{

211 float result = value - (max - min)*floorf((value - min)/(max - min));

212

213 return result;

214}

215

216// Check whether two given floats are almost equal

217RMAPI int FloatEquals(float x, float y)

218{

219#if !defined(EPSILON)

220 #define EPSILON 0.000001f

221#endif

222

223 int result = (fabsf(x - y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y))));

224

225 return result;

226}

227

228//----------------------------------------------------------------------------------

229// Module Functions Definition - Vector2 math

230//----------------------------------------------------------------------------------

231

232// Vector with components value 0.0f

233RMAPI Vector2 Vector2Zero(void)

234{

235 Vector2 result = { 0.0f, 0.0f };

236

237 return result;

238}

239

240// Vector with components value 1.0f

241RMAPI Vector2 Vector2One(void)

242{

243 Vector2 result = { 1.0f, 1.0f };

244

245 return result;

246}

247

248// Add two vectors (v1 + v2)

249RMAPI Vector2 Vector2Add(Vector2 v1, Vector2 v2)

250{

251 Vector2 result = { v1.x + v2.x, v1.y + v2.y };

252

253 return result;

254}

255

256// Add vector and float value

257RMAPI Vector2 Vector2AddValue(Vector2 v, float add)

258{

259 Vector2 result = { v.x + add, v.y + add };

260

261 return result;

262}

263

264// Subtract two vectors (v1 - v2)

265RMAPI Vector2 Vector2Subtract(Vector2 v1, Vector2 v2)

266{

267 Vector2 result = { v1.x - v2.x, v1.y - v2.y };

268

269 return result;

270}

271

272// Subtract vector by float value

273RMAPI Vector2 Vector2SubtractValue(Vector2 v, float sub)

274{

275 Vector2 result = { v.x - sub, v.y - sub };

276

277 return result;

278}

279

280// Calculate vector length

281RMAPI float Vector2Length(Vector2 v)

282{

283 float result = sqrtf((v.x*v.x) + (v.y*v.y));

284

285 return result;

286}

287

288// Calculate vector square length

289RMAPI float Vector2LengthSqr(Vector2 v)

290{

291 float result = (v.x*v.x) + (v.y*v.y);

292

293 return result;

294}

295

296// Calculate two vectors dot product

297RMAPI float Vector2DotProduct(Vector2 v1, Vector2 v2)

298{

299 float result = (v1.x*v2.x + v1.y*v2.y);

300

301 return result;

302}

303

304// Calculate distance between two vectors

305RMAPI float Vector2Distance(Vector2 v1, Vector2 v2)

306{

307 float result = sqrtf((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y));

308

309 return result;

310}

311

312// Calculate square distance between two vectors

313RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2)

314{

315 float result = ((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y));

316

317 return result;

318}

319

320// Calculate angle between two vectors

321// NOTE: Angle is calculated from origin point (0, 0)

322RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)

323{

324 float result = 0.0f;

325

326 float dot = v1.x*v2.x + v1.y*v2.y;

327 float det = v1.x*v2.y - v1.y*v2.x;

328

329 result = atan2f(det, dot);

330

331 return result;

332}

333

334// Calculate angle defined by a two vectors line

335// NOTE: Parameters need to be normalized

336// Current implementation should be aligned with glm::angle

337RMAPI float Vector2LineAngle(Vector2 start, Vector2 end)

338{

339 float result = 0.0f;

340

341 // TODO(10/9/2023): Currently angles move clockwise, determine if this is wanted behavior

342 result = -atan2f(end.y - start.y, end.x - start.x);

343

344 return result;

345}

346

347// Scale vector (multiply by value)

348RMAPI Vector2 Vector2Scale(Vector2 v, float scale)

349{

350 Vector2 result = { v.x*scale, v.y*scale };

351

352 return result;

353}

354

355// Multiply vector by vector

356RMAPI Vector2 Vector2Multiply(Vector2 v1, Vector2 v2)

357{

358 Vector2 result = { v1.x*v2.x, v1.y*v2.y };

359

360 return result;

361}

362

363// Negate vector

364RMAPI Vector2 Vector2Negate(Vector2 v)

365{

366 Vector2 result = { -v.x, -v.y };

367

368 return result;

369}

370

371// Divide vector by vector

372RMAPI Vector2 Vector2Divide(Vector2 v1, Vector2 v2)

373{

374 Vector2 result = { v1.x/v2.x, v1.y/v2.y };

375

376 return result;

377}

378

379// Normalize provided vector

380RMAPI Vector2 Vector2Normalize(Vector2 v)

381{

382 Vector2 result = { 0 };

383 float length = sqrtf((v.x*v.x) + (v.y*v.y));

384

385 if (length > 0)

386 {

387 float ilength = 1.0f/length;

388 result.x = v.x*ilength;

389 result.y = v.y*ilength;

390 }

391

392 return result;

393}

394

395// Transforms a Vector2 by a given Matrix

396RMAPI Vector2 Vector2Transform(Vector2 v, Matrix mat)

397{

398 Vector2 result = { 0 };

399

400 float x = v.x;

401 float y = v.y;

402 float z = 0;

403

404 result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12;

405 result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13;

406

407 return result;

408}

409

410// Calculate linear interpolation between two vectors

411RMAPI Vector2 Vector2Lerp(Vector2 v1, Vector2 v2, float amount)

412{

413 Vector2 result = { 0 };

414

415 result.x = v1.x + amount*(v2.x - v1.x);

416 result.y = v1.y + amount*(v2.y - v1.y);

417

418 return result;

419}

420

421// Calculate reflected vector to normal

422RMAPI Vector2 Vector2Reflect(Vector2 v, Vector2 normal)

423{

424 Vector2 result = { 0 };

425

426 float dotProduct = (v.x*normal.x + v.y*normal.y); // Dot product

427

428 result.x = v.x - (2.0f*normal.x)*dotProduct;

429 result.y = v.y - (2.0f*normal.y)*dotProduct;

430

431 return result;

432}

433

434// Rotate vector by angle

435RMAPI Vector2 Vector2Rotate(Vector2 v, float angle)

436{

437 Vector2 result = { 0 };

438

439 float cosres = cosf(angle);

440 float sinres = sinf(angle);

441

442 result.x = v.x*cosres - v.y*sinres;

443 result.y = v.x*sinres + v.y*cosres;

444

445 return result;

446}

447

448// Move Vector towards target

449RMAPI Vector2 Vector2MoveTowards(Vector2 v, Vector2 target, float maxDistance)

450{

451 Vector2 result = { 0 };

452

453 float dx = target.x - v.x;

454 float dy = target.y - v.y;

455 float value = (dx*dx) + (dy*dy);

456

457 if ((value == 0) || ((maxDistance >= 0) && (value <= maxDistance*maxDistance))) return target;

458

459 float dist = sqrtf(value);

460

461 result.x = v.x + dx/dist*maxDistance;

462 result.y = v.y + dy/dist*maxDistance;

463

464 return result;

465}

466

467// Invert the given vector

468RMAPI Vector2 Vector2Invert(Vector2 v)

469{

470 Vector2 result = { 1.0f/v.x, 1.0f/v.y };

471

472 return result;

473}

474

475// Clamp the components of the vector between

476// min and max values specified by the given vectors

477RMAPI Vector2 Vector2Clamp(Vector2 v, Vector2 min, Vector2 max)

478{

479 Vector2 result = { 0 };

480

481 result.x = fminf(max.x, fmaxf(min.x, v.x));

482 result.y = fminf(max.y, fmaxf(min.y, v.y));

483

484 return result;

485}

486

487// Clamp the magnitude of the vector between two min and max values

488RMAPI Vector2 Vector2ClampValue(Vector2 v, float min, float max)

489{

490 Vector2 result = v;

491

492 float length = (v.x*v.x) + (v.y*v.y);

493 if (length > 0.0f)

494 {

495 length = sqrtf(length);

496

497 float scale = 1; // By default, 1 as the neutral element.

498 if (length < min)

499 {

500 scale = min/length;

501 }

502 else if (length > max)

503 {

504 scale = max/length;

505 }

506

507 result.x = v.x*scale;

508 result.y = v.y*scale;

509 }

510

511 return result;

512}

513

514// Check whether two given vectors are almost equal

515RMAPI int Vector2Equals(Vector2 p, Vector2 q)

516{

517#if !defined(EPSILON)

518 #define EPSILON 0.000001f

519#endif

520

521 int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&

522 ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y)))));

523

524 return result;

525}

526

527//----------------------------------------------------------------------------------

528// Module Functions Definition - Vector3 math

529//----------------------------------------------------------------------------------

530

531// Vector with components value 0.0f

532RMAPI Vector3 Vector3Zero(void)

533{

534 Vector3 result = { 0.0f, 0.0f, 0.0f };

535

536 return result;

537}

538

539// Vector with components value 1.0f

540RMAPI Vector3 Vector3One(void)

541{

542 Vector3 result = { 1.0f, 1.0f, 1.0f };

543

544 return result;

545}

546

547// Add two vectors

548RMAPI Vector3 Vector3Add(Vector3 v1, Vector3 v2)

549{

550 Vector3 result = { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };

551

552 return result;

553}

554

555// Add vector and float value

556RMAPI Vector3 Vector3AddValue(Vector3 v, float add)

557{

558 Vector3 result = { v.x + add, v.y + add, v.z + add };

559

560 return result;

561}

562

563// Subtract two vectors

564RMAPI Vector3 Vector3Subtract(Vector3 v1, Vector3 v2)

565{

566 Vector3 result = { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };

567

568 return result;

569}

570

571// Subtract vector by float value

572RMAPI Vector3 Vector3SubtractValue(Vector3 v, float sub)

573{

574 Vector3 result = { v.x - sub, v.y - sub, v.z - sub };

575

576 return result;

577}

578

579// Multiply vector by scalar

580RMAPI Vector3 Vector3Scale(Vector3 v, float scalar)

581{

582 Vector3 result = { v.x*scalar, v.y*scalar, v.z*scalar };

583

584 return result;

585}

586

587// Multiply vector by vector

588RMAPI Vector3 Vector3Multiply(Vector3 v1, Vector3 v2)

589{

590 Vector3 result = { v1.x*v2.x, v1.y*v2.y, v1.z*v2.z };

591

592 return result;

593}

594

595// Calculate two vectors cross product

596RMAPI Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2)

597{

598 Vector3 result = { v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x };

599

600 return result;

601}

602

603// Calculate one vector perpendicular vector

604RMAPI Vector3 Vector3Perpendicular(Vector3 v)

605{

606 Vector3 result = { 0 };

607

608 float min = fabsf(v.x);

609 Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f};

610

611 if (fabsf(v.y) < min)

612 {

613 min = fabsf(v.y);

614 Vector3 tmp = {0.0f, 1.0f, 0.0f};

615 cardinalAxis = tmp;

616 }

617

618 if (fabsf(v.z) < min)

619 {

620 Vector3 tmp = {0.0f, 0.0f, 1.0f};

621 cardinalAxis = tmp;

622 }

623

624 // Cross product between vectors

625 result.x = v.y*cardinalAxis.z - v.z*cardinalAxis.y;

626 result.y = v.z*cardinalAxis.x - v.x*cardinalAxis.z;

627 result.z = v.x*cardinalAxis.y - v.y*cardinalAxis.x;

628

629 return result;

630}

631

632// Calculate vector length

633RMAPI float Vector3Length(const Vector3 v)

634{

635 float result = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);

636

637 return result;

638}

639

640// Calculate vector square length

641RMAPI float Vector3LengthSqr(const Vector3 v)

642{

643 float result = v.x*v.x + v.y*v.y + v.z*v.z;

644

645 return result;

646}

647

648// Calculate two vectors dot product

649RMAPI float Vector3DotProduct(Vector3 v1, Vector3 v2)

650{

651 float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);

652

653 return result;

654}

655

656// Calculate distance between two vectors

657RMAPI float Vector3Distance(Vector3 v1, Vector3 v2)

658{

659 float result = 0.0f;

660

661 float dx = v2.x - v1.x;

662 float dy = v2.y - v1.y;

663 float dz = v2.z - v1.z;

664 result = sqrtf(dx*dx + dy*dy + dz*dz);

665

666 return result;

667}

668

669// Calculate square distance between two vectors

670RMAPI float Vector3DistanceSqr(Vector3 v1, Vector3 v2)

671{

672 float result = 0.0f;

673

674 float dx = v2.x - v1.x;

675 float dy = v2.y - v1.y;

676 float dz = v2.z - v1.z;

677 result = dx*dx + dy*dy + dz*dz;

678

679 return result;

680}

681

682// Calculate angle between two vectors

683RMAPI float Vector3Angle(Vector3 v1, Vector3 v2)

684{

685 float result = 0.0f;

686

687 Vector3 cross = { v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x };

688 float len = sqrtf(cross.x*cross.x + cross.y*cross.y + cross.z*cross.z);

689 float dot = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);

690 result = atan2f(len, dot);

691

692 return result;

693}

694

695// Negate provided vector (invert direction)

696RMAPI Vector3 Vector3Negate(Vector3 v)

697{

698 Vector3 result = { -v.x, -v.y, -v.z };

699

700 return result;

701}

702

703// Divide vector by vector

704RMAPI Vector3 Vector3Divide(Vector3 v1, Vector3 v2)

705{

706 Vector3 result = { v1.x/v2.x, v1.y/v2.y, v1.z/v2.z };

707

708 return result;

709}

710

711// Normalize provided vector

712RMAPI Vector3 Vector3Normalize(Vector3 v)

713{

714 Vector3 result = v;

715

716 float length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);

717 if (length != 0.0f)

718 {

719 float ilength = 1.0f/length;

720

721 result.x *= ilength;

722 result.y *= ilength;

723 result.z *= ilength;

724 }

725

726 return result;

727}

728

729//Calculate the projection of the vector v1 on to v2

730RMAPI Vector3 Vector3Project(Vector3 v1, Vector3 v2)

731{

732 Vector3 result = { 0 };

733

734 float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);

735 float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);

736

737 float mag = v1dv2/v2dv2;

738

739 result.x = v2.x*mag;

740 result.y = v2.y*mag;

741 result.z = v2.z*mag;

742

743 return result;

744}

745

746//Calculate the rejection of the vector v1 on to v2

747RMAPI Vector3 Vector3Reject(Vector3 v1, Vector3 v2)

748{

749 Vector3 result = { 0 };

750

751 float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);

752 float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);

753

754 float mag = v1dv2/v2dv2;

755

756 result.x = v1.x - (v2.x*mag);

757 result.y = v1.y - (v2.y*mag);

758 result.z = v1.z - (v2.z*mag);

759

760 return result;

761}

762

763// Orthonormalize provided vectors

764// Makes vectors normalized and orthogonal to each other

765// Gram-Schmidt function implementation

766RMAPI void Vector3OrthoNormalize(Vector3 *v1, Vector3 *v2)

767{

768 float length = 0.0f;

769 float ilength = 0.0f;

770

771 // Vector3Normalize(*v1);

772 Vector3 v = *v1;

773 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);

774 if (length == 0.0f) length = 1.0f;

775 ilength = 1.0f/length;

776 v1->x *= ilength;

777 v1->y *= ilength;

778 v1->z *= ilength;

779

780 // Vector3CrossProduct(*v1, *v2)

781 Vector3 vn1 = { v1->y*v2->z - v1->z*v2->y, v1->z*v2->x - v1->x*v2->z, v1->x*v2->y - v1->y*v2->x };

782

783 // Vector3Normalize(vn1);

784 v = vn1;

785 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);

786 if (length == 0.0f) length = 1.0f;

787 ilength = 1.0f/length;

788 vn1.x *= ilength;

789 vn1.y *= ilength;

790 vn1.z *= ilength;

791

792 // Vector3CrossProduct(vn1, *v1)

793 Vector3 vn2 = { vn1.y*v1->z - vn1.z*v1->y, vn1.z*v1->x - vn1.x*v1->z, vn1.x*v1->y - vn1.y*v1->x };

794

795 *v2 = vn2;

796}

797

798// Transforms a Vector3 by a given Matrix

799RMAPI Vector3 Vector3Transform(Vector3 v, Matrix mat)

800{

801 Vector3 result = { 0 };

802

803 float x = v.x;

804 float y = v.y;

805 float z = v.z;

806

807 result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12;

808 result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13;

809 result.z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14;

810

811 return result;

812}

813

814// Transform a vector by quaternion rotation

815RMAPI Vector3 Vector3RotateByQuaternion(Vector3 v, Quaternion q)

816{

817 Vector3 result = { 0 };

818

819 result.x = v.x*(q.x*q.x + q.w*q.w - q.y*q.y - q.z*q.z) + v.y*(2*q.x*q.y - 2*q.w*q.z) + v.z*(2*q.x*q.z + 2*q.w*q.y);

820 result.y = v.x*(2*q.w*q.z + 2*q.x*q.y) + v.y*(q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z) + v.z*(-2*q.w*q.x + 2*q.y*q.z);

821 result.z = v.x*(-2*q.w*q.y + 2*q.x*q.z) + v.y*(2*q.w*q.x + 2*q.y*q.z)+ v.z*(q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z);

822

823 return result;

824}

825

826// Rotates a vector around an axis

827RMAPI Vector3 Vector3RotateByAxisAngle(Vector3 v, Vector3 axis, float angle)

828{

829 // Using Euler-Rodrigues Formula

830 // Ref.: https://en.wikipedia.org/w/index.php?title=Euler%E2%80%93Rodrigues_formula

831

832 Vector3 result = v;

833

834 // Vector3Normalize(axis);

835 float length = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);

836 if (length == 0.0f) length = 1.0f;

837 float ilength = 1.0f/length;

838 axis.x *= ilength;

839 axis.y *= ilength;

840 axis.z *= ilength;

841

842 angle /= 2.0f;

843 float a = sinf(angle);

844 float b = axis.x*a;

845 float c = axis.y*a;

846 float d = axis.z*a;

847 a = cosf(angle);

848 Vector3 w = { b, c, d };

849

850 // Vector3CrossProduct(w, v)

851 Vector3 wv = { w.y*v.z - w.z*v.y, w.z*v.x - w.x*v.z, w.x*v.y - w.y*v.x };

852

853 // Vector3CrossProduct(w, wv)

854 Vector3 wwv = { w.y*wv.z - w.z*wv.y, w.z*wv.x - w.x*wv.z, w.x*wv.y - w.y*wv.x };

855

856 // Vector3Scale(wv, 2*a)

857 a *= 2;

858 wv.x *= a;

859 wv.y *= a;

860 wv.z *= a;

861

862 // Vector3Scale(wwv, 2)

863 wwv.x *= 2;

864 wwv.y *= 2;

865 wwv.z *= 2;

866

867 result.x += wv.x;

868 result.y += wv.y;

869 result.z += wv.z;

870

871 result.x += wwv.x;

872 result.y += wwv.y;

873 result.z += wwv.z;

874

875 return result;

876}

877

878// Calculate linear interpolation between two vectors

879RMAPI Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount)

880{

881 Vector3 result = { 0 };

882

883 result.x = v1.x + amount*(v2.x - v1.x);

884 result.y = v1.y + amount*(v2.y - v1.y);

885 result.z = v1.z + amount*(v2.z - v1.z);

886

887 return result;

888}

889

890// Calculate reflected vector to normal

891RMAPI Vector3 Vector3Reflect(Vector3 v, Vector3 normal)

892{

893 Vector3 result = { 0 };

894

895 // I is the original vector

896 // N is the normal of the incident plane

897 // R = I - (2*N*(DotProduct[I, N]))

898

899 float dotProduct = (v.x*normal.x + v.y*normal.y + v.z*normal.z);

900

901 result.x = v.x - (2.0f*normal.x)*dotProduct;

902 result.y = v.y - (2.0f*normal.y)*dotProduct;

903 result.z = v.z - (2.0f*normal.z)*dotProduct;

904

905 return result;

906}

907

908// Get min value for each pair of components

909RMAPI Vector3 Vector3Min(Vector3 v1, Vector3 v2)

910{

911 Vector3 result = { 0 };

912

913 result.x = fminf(v1.x, v2.x);

914 result.y = fminf(v1.y, v2.y);

915 result.z = fminf(v1.z, v2.z);

916

917 return result;

918}

919

920// Get max value for each pair of components

921RMAPI Vector3 Vector3Max(Vector3 v1, Vector3 v2)

922{

923 Vector3 result = { 0 };

924

925 result.x = fmaxf(v1.x, v2.x);

926 result.y = fmaxf(v1.y, v2.y);

927 result.z = fmaxf(v1.z, v2.z);

928

929 return result;

930}

931

932// Compute barycenter coordinates (u, v, w) for point p with respect to triangle (a, b, c)

933// NOTE: Assumes P is on the plane of the triangle

934RMAPI Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c)

935{

936 Vector3 result = { 0 };

937

938 Vector3 v0 = { b.x - a.x, b.y - a.y, b.z - a.z }; // Vector3Subtract(b, a)

939 Vector3 v1 = { c.x - a.x, c.y - a.y, c.z - a.z }; // Vector3Subtract(c, a)

940 Vector3 v2 = { p.x - a.x, p.y - a.y, p.z - a.z }; // Vector3Subtract(p, a)

941 float d00 = (v0.x*v0.x + v0.y*v0.y + v0.z*v0.z); // Vector3DotProduct(v0, v0)

942 float d01 = (v0.x*v1.x + v0.y*v1.y + v0.z*v1.z); // Vector3DotProduct(v0, v1)

943 float d11 = (v1.x*v1.x + v1.y*v1.y + v1.z*v1.z); // Vector3DotProduct(v1, v1)

944 float d20 = (v2.x*v0.x + v2.y*v0.y + v2.z*v0.z); // Vector3DotProduct(v2, v0)

945 float d21 = (v2.x*v1.x + v2.y*v1.y + v2.z*v1.z); // Vector3DotProduct(v2, v1)

946

947 float denom = d00*d11 - d01*d01;

948

949 result.y = (d11*d20 - d01*d21)/denom;

950 result.z = (d00*d21 - d01*d20)/denom;

951 result.x = 1.0f - (result.z + result.y);

952

953 return result;

954}

955

956// Projects a Vector3 from screen space into object space

957// NOTE: We are avoiding calling other raymath functions despite available

958RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view)

959{

960 Vector3 result = { 0 };

961

962 // Calculate unprojected matrix (multiply view matrix by projection matrix) and invert it

963 Matrix matViewProj = { // MatrixMultiply(view, projection);

964 view.m0*projection.m0 + view.m1*projection.m4 + view.m2*projection.m8 + view.m3*projection.m12,

965 view.m0*projection.m1 + view.m1*projection.m5 + view.m2*projection.m9 + view.m3*projection.m13,

966 view.m0*projection.m2 + view.m1*projection.m6 + view.m2*projection.m10 + view.m3*projection.m14,

967 view.m0*projection.m3 + view.m1*projection.m7 + view.m2*projection.m11 + view.m3*projection.m15,

968 view.m4*projection.m0 + view.m5*projection.m4 + view.m6*projection.m8 + view.m7*projection.m12,

969 view.m4*projection.m1 + view.m5*projection.m5 + view.m6*projection.m9 + view.m7*projection.m13,

970 view.m4*projection.m2 + view.m5*projection.m6 + view.m6*projection.m10 + view.m7*projection.m14,

971 view.m4*projection.m3 + view.m5*projection.m7 + view.m6*projection.m11 + view.m7*projection.m15,

972 view.m8*projection.m0 + view.m9*projection.m4 + view.m10*projection.m8 + view.m11*projection.m12,

973 view.m8*projection.m1 + view.m9*projection.m5 + view.m10*projection.m9 + view.m11*projection.m13,

974 view.m8*projection.m2 + view.m9*projection.m6 + view.m10*projection.m10 + view.m11*projection.m14,

975 view.m8*projection.m3 + view.m9*projection.m7 + view.m10*projection.m11 + view.m11*projection.m15,

976 view.m12*projection.m0 + view.m13*projection.m4 + view.m14*projection.m8 + view.m15*projection.m12,

977 view.m12*projection.m1 + view.m13*projection.m5 + view.m14*projection.m9 + view.m15*projection.m13,

978 view.m12*projection.m2 + view.m13*projection.m6 + view.m14*projection.m10 + view.m15*projection.m14,

979 view.m12*projection.m3 + view.m13*projection.m7 + view.m14*projection.m11 + view.m15*projection.m15 };

980

981 // Calculate inverted matrix -> MatrixInvert(matViewProj);

982 // Cache the matrix values (speed optimization)

983 float a00 = matViewProj.m0, a01 = matViewProj.m1, a02 = matViewProj.m2, a03 = matViewProj.m3;

984 float a10 = matViewProj.m4, a11 = matViewProj.m5, a12 = matViewProj.m6, a13 = matViewProj.m7;

985 float a20 = matViewProj.m8, a21 = matViewProj.m9, a22 = matViewProj.m10, a23 = matViewProj.m11;

986 float a30 = matViewProj.m12, a31 = matViewProj.m13, a32 = matViewProj.m14, a33 = matViewProj.m15;

987

988 float b00 = a00*a11 - a01*a10;

989 float b01 = a00*a12 - a02*a10;

990 float b02 = a00*a13 - a03*a10;

991 float b03 = a01*a12 - a02*a11;

992 float b04 = a01*a13 - a03*a11;

993 float b05 = a02*a13 - a03*a12;

994 float b06 = a20*a31 - a21*a30;

995 float b07 = a20*a32 - a22*a30;

996 float b08 = a20*a33 - a23*a30;

997 float b09 = a21*a32 - a22*a31;

998 float b10 = a21*a33 - a23*a31;

999 float b11 = a22*a33 - a23*a32;

1000

1001 // Calculate the invert determinant (inlined to avoid double-caching)

1002 float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);

1003

1004 Matrix matViewProjInv = {

1005 (a11*b11 - a12*b10 + a13*b09)*invDet,

1006 (-a01*b11 + a02*b10 - a03*b09)*invDet,

1007 (a31*b05 - a32*b04 + a33*b03)*invDet,

1008 (-a21*b05 + a22*b04 - a23*b03)*invDet,

1009 (-a10*b11 + a12*b08 - a13*b07)*invDet,

1010 (a00*b11 - a02*b08 + a03*b07)*invDet,

1011 (-a30*b05 + a32*b02 - a33*b01)*invDet,

1012 (a20*b05 - a22*b02 + a23*b01)*invDet,

1013 (a10*b10 - a11*b08 + a13*b06)*invDet,

1014 (-a00*b10 + a01*b08 - a03*b06)*invDet,

1015 (a30*b04 - a31*b02 + a33*b00)*invDet,

1016 (-a20*b04 + a21*b02 - a23*b00)*invDet,

1017 (-a10*b09 + a11*b07 - a12*b06)*invDet,

1018 (a00*b09 - a01*b07 + a02*b06)*invDet,

1019 (-a30*b03 + a31*b01 - a32*b00)*invDet,

1020 (a20*b03 - a21*b01 + a22*b00)*invDet };

1021

1022 // Create quaternion from source point

1023 Quaternion quat = { source.x, source.y, source.z, 1.0f };

1024

1025 // Multiply quat point by unprojecte matrix

1026 Quaternion qtransformed = { // QuaternionTransform(quat, matViewProjInv)

1027 matViewProjInv.m0*quat.x + matViewProjInv.m4*quat.y + matViewProjInv.m8*quat.z + matViewProjInv.m12*quat.w,

1028 matViewProjInv.m1*quat.x + matViewProjInv.m5*quat.y + matViewProjInv.m9*quat.z + matViewProjInv.m13*quat.w,

1029 matViewProjInv.m2*quat.x + matViewProjInv.m6*quat.y + matViewProjInv.m10*quat.z + matViewProjInv.m14*quat.w,

1030 matViewProjInv.m3*quat.x + matViewProjInv.m7*quat.y + matViewProjInv.m11*quat.z + matViewProjInv.m15*quat.w };

1031

1032 // Normalized world points in vectors

1033 result.x = qtransformed.x/qtransformed.w;

1034 result.y = qtransformed.y/qtransformed.w;

1035 result.z = qtransformed.z/qtransformed.w;

1036

1037 return result;

1038}

1039

1040// Get Vector3 as float array

1041RMAPI float3 Vector3ToFloatV(Vector3 v)

1042{

1043 float3 buffer = { 0 };

1044

1045 buffer.v[0] = v.x;

1046 buffer.v[1] = v.y;

1047 buffer.v[2] = v.z;

1048

1049 return buffer;

1050}

1051

1052// Invert the given vector

1053RMAPI Vector3 Vector3Invert(Vector3 v)

1054{

1055 Vector3 result = { 1.0f/v.x, 1.0f/v.y, 1.0f/v.z };

1056

1057 return result;

1058}

1059

1060// Clamp the components of the vector between

1061// min and max values specified by the given vectors

1062RMAPI Vector3 Vector3Clamp(Vector3 v, Vector3 min, Vector3 max)

1063{

1064 Vector3 result = { 0 };

1065

1066 result.x = fminf(max.x, fmaxf(min.x, v.x));

1067 result.y = fminf(max.y, fmaxf(min.y, v.y));

1068 result.z = fminf(max.z, fmaxf(min.z, v.z));

1069

1070 return result;

1071}

1072

1073// Clamp the magnitude of the vector between two values

1074RMAPI Vector3 Vector3ClampValue(Vector3 v, float min, float max)

1075{

1076 Vector3 result = v;

1077

1078 float length = (v.x*v.x) + (v.y*v.y) + (v.z*v.z);

1079 if (length > 0.0f)

1080 {

1081 length = sqrtf(length);

1082

1083 float scale = 1; // By default, 1 as the neutral element.

1084 if (length < min)

1085 {

1086 scale = min/length;

1087 }

1088 else if (length > max)

1089 {

1090 scale = max/length;

1091 }

1092

1093 result.x = v.x*scale;

1094 result.y = v.y*scale;

1095 result.z = v.z*scale;

1096 }

1097

1098 return result;

1099}

1100

1101// Check whether two given vectors are almost equal

1102RMAPI int Vector3Equals(Vector3 p, Vector3 q)

1103{

1104#if !defined(EPSILON)

1105 #define EPSILON 0.000001f

1106#endif

1107

1108 int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&

1109 ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&

1110 ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z)))));

1111

1112 return result;

1113}

1114

1115// Compute the direction of a refracted ray

1116// v: normalized direction of the incoming ray

1117// n: normalized normal vector of the interface of two optical media

1118// r: ratio of the refractive index of the medium from where the ray comes

1119// to the refractive index of the medium on the other side of the surface

1120RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r)

1121{

1122 Vector3 result = { 0 };

1123

1124 float dot = v.x*n.x + v.y*n.y + v.z*n.z;

1125 float d = 1.0f - r*r*(1.0f - dot*dot);

1126

1127 if (d >= 0.0f)

1128 {

1129 d = sqrtf(d);

1130 v.x = r*v.x - (r*dot + d)*n.x;

1131 v.y = r*v.y - (r*dot + d)*n.y;

1132 v.z = r*v.z - (r*dot + d)*n.z;

1133

1134 result = v;

1135 }

1136

1137 return result;

1138}

1139

1140//----------------------------------------------------------------------------------

1141// Module Functions Definition - Matrix math

1142//----------------------------------------------------------------------------------

1143

1144// Compute matrix determinant

1145RMAPI float MatrixDeterminant(Matrix mat)

1146{

1147 float result = 0.0f;

1148

1149 // Cache the matrix values (speed optimization)

1150 float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;

1151 float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;

1152 float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;

1153 float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;

1154

1155 result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 +

1156 a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 +

1157 a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 +

1158 a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 +

1159 a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 +

1160 a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;

1161

1162 return result;

1163}

1164

1165// Get the trace of the matrix (sum of the values along the diagonal)

1166RMAPI float MatrixTrace(Matrix mat)

1167{

1168 float result = (mat.m0 + mat.m5 + mat.m10 + mat.m15);

1169

1170 return result;

1171}

1172

1173// Transposes provided matrix

1174RMAPI Matrix MatrixTranspose(Matrix mat)

1175{

1176 Matrix result = { 0 };

1177

1178 result.m0 = mat.m0;

1179 result.m1 = mat.m4;

1180 result.m2 = mat.m8;

1181 result.m3 = mat.m12;

1182 result.m4 = mat.m1;

1183 result.m5 = mat.m5;

1184 result.m6 = mat.m9;

1185 result.m7 = mat.m13;

1186 result.m8 = mat.m2;

1187 result.m9 = mat.m6;

1188 result.m10 = mat.m10;

1189 result.m11 = mat.m14;

1190 result.m12 = mat.m3;

1191 result.m13 = mat.m7;

1192 result.m14 = mat.m11;

1193 result.m15 = mat.m15;

1194

1195 return result;

1196}

1197

1198// Invert provided matrix

1199RMAPI Matrix MatrixInvert(Matrix mat)

1200{

1201 Matrix result = { 0 };

1202

1203 // Cache the matrix values (speed optimization)

1204 float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;

1205 float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;

1206 float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;

1207 float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;

1208

1209 float b00 = a00*a11 - a01*a10;

1210 float b01 = a00*a12 - a02*a10;

1211 float b02 = a00*a13 - a03*a10;

1212 float b03 = a01*a12 - a02*a11;

1213 float b04 = a01*a13 - a03*a11;

1214 float b05 = a02*a13 - a03*a12;

1215 float b06 = a20*a31 - a21*a30;

1216 float b07 = a20*a32 - a22*a30;

1217 float b08 = a20*a33 - a23*a30;

1218 float b09 = a21*a32 - a22*a31;

1219 float b10 = a21*a33 - a23*a31;

1220 float b11 = a22*a33 - a23*a32;

1221

1222 // Calculate the invert determinant (inlined to avoid double-caching)

1223 float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);

1224

1225 result.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;

1226 result.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;

1227 result.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;

1228 result.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet;

1229 result.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet;

1230 result.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet;

1231 result.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet;

1232 result.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet;

1233 result.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet;

1234 result.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet;

1235 result.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet;

1236 result.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet;

1237 result.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet;

1238 result.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet;

1239 result.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet;

1240 result.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet;

1241

1242 return result;

1243}

1244

1245// Get identity matrix

1246RMAPI Matrix MatrixIdentity(void)

1247{

1248 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,

1249 0.0f, 1.0f, 0.0f, 0.0f,

1250 0.0f, 0.0f, 1.0f, 0.0f,

1251 0.0f, 0.0f, 0.0f, 1.0f };

1252

1253 return result;

1254}

1255

1256// Add two matrices

1257RMAPI Matrix MatrixAdd(Matrix left, Matrix right)

1258{

1259 Matrix result = { 0 };

1260

1261 result.m0 = left.m0 + right.m0;

1262 result.m1 = left.m1 + right.m1;

1263 result.m2 = left.m2 + right.m2;

1264 result.m3 = left.m3 + right.m3;

1265 result.m4 = left.m4 + right.m4;

1266 result.m5 = left.m5 + right.m5;

1267 result.m6 = left.m6 + right.m6;

1268 result.m7 = left.m7 + right.m7;

1269 result.m8 = left.m8 + right.m8;

1270 result.m9 = left.m9 + right.m9;

1271 result.m10 = left.m10 + right.m10;

1272 result.m11 = left.m11 + right.m11;

1273 result.m12 = left.m12 + right.m12;

1274 result.m13 = left.m13 + right.m13;

1275 result.m14 = left.m14 + right.m14;

1276 result.m15 = left.m15 + right.m15;

1277

1278 return result;

1279}

1280

1281// Subtract two matrices (left - right)

1282RMAPI Matrix MatrixSubtract(Matrix left, Matrix right)

1283{

1284 Matrix result = { 0 };

1285

1286 result.m0 = left.m0 - right.m0;

1287 result.m1 = left.m1 - right.m1;

1288 result.m2 = left.m2 - right.m2;

1289 result.m3 = left.m3 - right.m3;

1290 result.m4 = left.m4 - right.m4;

1291 result.m5 = left.m5 - right.m5;

1292 result.m6 = left.m6 - right.m6;

1293 result.m7 = left.m7 - right.m7;

1294 result.m8 = left.m8 - right.m8;

1295 result.m9 = left.m9 - right.m9;

1296 result.m10 = left.m10 - right.m10;

1297 result.m11 = left.m11 - right.m11;

1298 result.m12 = left.m12 - right.m12;

1299 result.m13 = left.m13 - right.m13;

1300 result.m14 = left.m14 - right.m14;

1301 result.m15 = left.m15 - right.m15;

1302

1303 return result;

1304}

1305

1306// Get two matrix multiplication

1307// NOTE: When multiplying matrices... the order matters!

1308RMAPI Matrix MatrixMultiply(Matrix left, Matrix right)

1309{

1310 Matrix result = { 0 };

1311

1312 result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12;

1313 result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13;

1314 result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14;

1315 result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15;

1316 result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12;

1317 result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13;

1318 result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14;

1319 result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15;

1320 result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12;

1321 result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13;

1322 result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14;

1323 result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15;

1324 result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12;

1325 result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13;

1326 result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14;

1327 result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15;

1328

1329 return result;

1330}

1331

1332// Get translation matrix

1333RMAPI Matrix MatrixTranslate(float x, float y, float z)

1334{

1335 Matrix result = { 1.0f, 0.0f, 0.0f, x,

1336 0.0f, 1.0f, 0.0f, y,

1337 0.0f, 0.0f, 1.0f, z,

1338 0.0f, 0.0f, 0.0f, 1.0f };

1339

1340 return result;

1341}

1342

1343// Create rotation matrix from axis and angle

1344// NOTE: Angle should be provided in radians

1345RMAPI Matrix MatrixRotate(Vector3 axis, float angle)

1346{

1347 Matrix result = { 0 };

1348

1349 float x = axis.x, y = axis.y, z = axis.z;

1350

1351 float lengthSquared = x*x + y*y + z*z;

1352

1353 if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f))

1354 {

1355 float ilength = 1.0f/sqrtf(lengthSquared);

1356 x *= ilength;

1357 y *= ilength;

1358 z *= ilength;

1359 }

1360

1361 float sinres = sinf(angle);

1362 float cosres = cosf(angle);

1363 float t = 1.0f - cosres;

1364

1365 result.m0 = x*x*t + cosres;

1366 result.m1 = y*x*t + z*sinres;

1367 result.m2 = z*x*t - y*sinres;

1368 result.m3 = 0.0f;

1369

1370 result.m4 = x*y*t - z*sinres;

1371 result.m5 = y*y*t + cosres;

1372 result.m6 = z*y*t + x*sinres;

1373 result.m7 = 0.0f;

1374

1375 result.m8 = x*z*t + y*sinres;

1376 result.m9 = y*z*t - x*sinres;

1377 result.m10 = z*z*t + cosres;

1378 result.m11 = 0.0f;

1379

1380 result.m12 = 0.0f;

1381 result.m13 = 0.0f;

1382 result.m14 = 0.0f;

1383 result.m15 = 1.0f;

1384

1385 return result;

1386}

1387

1388// Get x-rotation matrix

1389// NOTE: Angle must be provided in radians

1390RMAPI Matrix MatrixRotateX(float angle)

1391{

1392 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,

1393 0.0f, 1.0f, 0.0f, 0.0f,

1394 0.0f, 0.0f, 1.0f, 0.0f,

1395 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity()

1396

1397 float cosres = cosf(angle);

1398 float sinres = sinf(angle);

1399

1400 result.m5 = cosres;

1401 result.m6 = sinres;

1402 result.m9 = -sinres;

1403 result.m10 = cosres;

1404

1405 return result;

1406}

1407

1408// Get y-rotation matrix

1409// NOTE: Angle must be provided in radians

1410RMAPI Matrix MatrixRotateY(float angle)

1411{

1412 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,

1413 0.0f, 1.0f, 0.0f, 0.0f,

1414 0.0f, 0.0f, 1.0f, 0.0f,

1415 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity()

1416

1417 float cosres = cosf(angle);

1418 float sinres = sinf(angle);

1419

1420 result.m0 = cosres;

1421 result.m2 = -sinres;

1422 result.m8 = sinres;

1423 result.m10 = cosres;

1424

1425 return result;

1426}

1427

1428// Get z-rotation matrix

1429// NOTE: Angle must be provided in radians

1430RMAPI Matrix MatrixRotateZ(float angle)

1431{

1432 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,

1433 0.0f, 1.0f, 0.0f, 0.0f,

1434 0.0f, 0.0f, 1.0f, 0.0f,

1435 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity()

1436

1437 float cosres = cosf(angle);

1438 float sinres = sinf(angle);

1439

1440 result.m0 = cosres;

1441 result.m1 = sinres;

1442 result.m4 = -sinres;

1443 result.m5 = cosres;

1444

1445 return result;

1446}

1447

1448

1449// Get xyz-rotation matrix

1450// NOTE: Angle must be provided in radians

1451RMAPI Matrix MatrixRotateXYZ(Vector3 angle)

1452{

1453 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,

1454 0.0f, 1.0f, 0.0f, 0.0f,

1455 0.0f, 0.0f, 1.0f, 0.0f,

1456 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity()

1457

1458 float cosz = cosf(-angle.z);

1459 float sinz = sinf(-angle.z);

1460 float cosy = cosf(-angle.y);

1461 float siny = sinf(-angle.y);

1462 float cosx = cosf(-angle.x);

1463 float sinx = sinf(-angle.x);

1464

1465 result.m0 = cosz*cosy;

1466 result.m1 = (cosz*siny*sinx) - (sinz*cosx);

1467 result.m2 = (cosz*siny*cosx) + (sinz*sinx);

1468

1469 result.m4 = sinz*cosy;

1470 result.m5 = (sinz*siny*sinx) + (cosz*cosx);

1471 result.m6 = (sinz*siny*cosx) - (cosz*sinx);

1472

1473 result.m8 = -siny;

1474 result.m9 = cosy*sinx;

1475 result.m10= cosy*cosx;

1476

1477 return result;

1478}

1479

1480// Get zyx-rotation matrix

1481// NOTE: Angle must be provided in radians

1482RMAPI Matrix MatrixRotateZYX(Vector3 angle)

1483{

1484 Matrix result = { 0 };

1485

1486 float cz = cosf(angle.z);

1487 float sz = sinf(angle.z);

1488 float cy = cosf(angle.y);

1489 float sy = sinf(angle.y);

1490 float cx = cosf(angle.x);

1491 float sx = sinf(angle.x);

1492

1493 result.m0 = cz*cy;

1494 result.m4 = cz*sy*sx - cx*sz;

1495 result.m8 = sz*sx + cz*cx*sy;

1496 result.m12 = 0;

1497

1498 result.m1 = cy*sz;

1499 result.m5 = cz*cx + sz*sy*sx;

1500 result.m9 = cx*sz*sy - cz*sx;

1501 result.m13 = 0;

1502

1503 result.m2 = -sy;

1504 result.m6 = cy*sx;

1505 result.m10 = cy*cx;

1506 result.m14 = 0;

1507

1508 result.m3 = 0;

1509 result.m7 = 0;

1510 result.m11 = 0;

1511 result.m15 = 1;

1512

1513 return result;

1514}

1515

1516// Get scaling matrix

1517RMAPI Matrix MatrixScale(float x, float y, float z)

1518{

1519 Matrix result = { x, 0.0f, 0.0f, 0.0f,

1520 0.0f, y, 0.0f, 0.0f,

1521 0.0f, 0.0f, z, 0.0f,

1522 0.0f, 0.0f, 0.0f, 1.0f };

1523

1524 return result;

1525}

1526

1527// Get perspective projection matrix

1528RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far)

1529{

1530 Matrix result = { 0 };

1531

1532 float rl = (float)(right - left);

1533 float tb = (float)(top - bottom);

1534 float fn = (float)(far - near);

1535

1536 result.m0 = ((float)near*2.0f)/rl;

1537 result.m1 = 0.0f;

1538 result.m2 = 0.0f;

1539 result.m3 = 0.0f;

1540

1541 result.m4 = 0.0f;

1542 result.m5 = ((float)near*2.0f)/tb;

1543 result.m6 = 0.0f;

1544 result.m7 = 0.0f;

1545

1546 result.m8 = ((float)right + (float)left)/rl;

1547 result.m9 = ((float)top + (float)bottom)/tb;

1548 result.m10 = -((float)far + (float)near)/fn;

1549 result.m11 = -1.0f;

1550

1551 result.m12 = 0.0f;

1552 result.m13 = 0.0f;

1553 result.m14 = -((float)far*(float)near*2.0f)/fn;

1554 result.m15 = 0.0f;

1555

1556 return result;

1557}

1558

1559// Get perspective projection matrix

1560// NOTE: Fovy angle must be provided in radians

1561RMAPI Matrix MatrixPerspective(double fovY, double aspect, double nearPlane, double farPlane)

1562{

1563 Matrix result = { 0 };

1564

1565 double top = nearPlane*tan(fovY*0.5);

1566 double bottom = -top;

1567 double right = top*aspect;

1568 double left = -right;

1569

1570 // MatrixFrustum(-right, right, -top, top, near, far);

1571 float rl = (float)(right - left);

1572 float tb = (float)(top - bottom);

1573 float fn = (float)(farPlane - nearPlane);

1574

1575 result.m0 = ((float)nearPlane*2.0f)/rl;

1576 result.m5 = ((float)nearPlane*2.0f)/tb;

1577 result.m8 = ((float)right + (float)left)/rl;

1578 result.m9 = ((float)top + (float)bottom)/tb;

1579 result.m10 = -((float)farPlane + (float)nearPlane)/fn;

1580 result.m11 = -1.0f;

1581 result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/fn;

1582

1583 return result;

1584}

1585

1586// Get orthographic projection matrix

1587RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, double nearPlane, double farPlane)

1588{

1589 Matrix result = { 0 };

1590

1591 float rl = (float)(right - left);

1592 float tb = (float)(top - bottom);

1593 float fn = (float)(farPlane - nearPlane);

1594

1595 result.m0 = 2.0f/rl;

1596 result.m1 = 0.0f;

1597 result.m2 = 0.0f;

1598 result.m3 = 0.0f;

1599 result.m4 = 0.0f;

1600 result.m5 = 2.0f/tb;

1601 result.m6 = 0.0f;

1602 result.m7 = 0.0f;

1603 result.m8 = 0.0f;

1604 result.m9 = 0.0f;

1605 result.m10 = -2.0f/fn;

1606 result.m11 = 0.0f;

1607 result.m12 = -((float)left + (float)right)/rl;

1608 result.m13 = -((float)top + (float)bottom)/tb;

1609 result.m14 = -((float)farPlane + (float)nearPlane)/fn;

1610 result.m15 = 1.0f;

1611

1612 return result;

1613}

1614

1615// Get camera look-at matrix (view matrix)

1616RMAPI Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)

1617{

1618 Matrix result = { 0 };

1619

1620 float length = 0.0f;

1621 float ilength = 0.0f;

1622

1623 // Vector3Subtract(eye, target)

1624 Vector3 vz = { eye.x - target.x, eye.y - target.y, eye.z - target.z };

1625

1626 // Vector3Normalize(vz)

1627 Vector3 v = vz;

1628 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);

1629 if (length == 0.0f) length = 1.0f;

1630 ilength = 1.0f/length;

1631 vz.x *= ilength;

1632 vz.y *= ilength;

1633 vz.z *= ilength;

1634

1635 // Vector3CrossProduct(up, vz)

1636 Vector3 vx = { up.y*vz.z - up.z*vz.y, up.z*vz.x - up.x*vz.z, up.x*vz.y - up.y*vz.x };

1637

1638 // Vector3Normalize(x)

1639 v = vx;

1640 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);

1641 if (length == 0.0f) length = 1.0f;

1642 ilength = 1.0f/length;

1643 vx.x *= ilength;

1644 vx.y *= ilength;

1645 vx.z *= ilength;

1646

1647 // Vector3CrossProduct(vz, vx)

1648 Vector3 vy = { vz.y*vx.z - vz.z*vx.y, vz.z*vx.x - vz.x*vx.z, vz.x*vx.y - vz.y*vx.x };

1649

1650 result.m0 = vx.x;

1651 result.m1 = vy.x;

1652 result.m2 = vz.x;

1653 result.m3 = 0.0f;

1654 result.m4 = vx.y;

1655 result.m5 = vy.y;

1656 result.m6 = vz.y;

1657 result.m7 = 0.0f;

1658 result.m8 = vx.z;

1659 result.m9 = vy.z;

1660 result.m10 = vz.z;

1661 result.m11 = 0.0f;

1662 result.m12 = -(vx.x*eye.x + vx.y*eye.y + vx.z*eye.z); // Vector3DotProduct(vx, eye)

1663 result.m13 = -(vy.x*eye.x + vy.y*eye.y + vy.z*eye.z); // Vector3DotProduct(vy, eye)

1664 result.m14 = -(vz.x*eye.x + vz.y*eye.y + vz.z*eye.z); // Vector3DotProduct(vz, eye)

1665 result.m15 = 1.0f;

1666

1667 return result;

1668}

1669

1670// Get float array of matrix data

1671RMAPI float16 MatrixToFloatV(Matrix mat)

1672{

1673 float16 result = { 0 };

1674

1675 result.v[0] = mat.m0;

1676 result.v[1] = mat.m1;

1677 result.v[2] = mat.m2;

1678 result.v[3] = mat.m3;

1679 result.v[4] = mat.m4;

1680 result.v[5] = mat.m5;

1681 result.v[6] = mat.m6;

1682 result.v[7] = mat.m7;

1683 result.v[8] = mat.m8;

1684 result.v[9] = mat.m9;

1685 result.v[10] = mat.m10;

1686 result.v[11] = mat.m11;

1687 result.v[12] = mat.m12;

1688 result.v[13] = mat.m13;

1689 result.v[14] = mat.m14;

1690 result.v[15] = mat.m15;

1691

1692 return result;

1693}

1694

1695//----------------------------------------------------------------------------------

1696// Module Functions Definition - Quaternion math

1697//----------------------------------------------------------------------------------

1698

1699// Add two quaternions

1700RMAPI Quaternion QuaternionAdd(Quaternion q1, Quaternion q2)

1701{

1702 Quaternion result = {q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w};

1703

1704 return result;

1705}

1706

1707// Add quaternion and float value

1708RMAPI Quaternion QuaternionAddValue(Quaternion q, float add)

1709{

1710 Quaternion result = {q.x + add, q.y + add, q.z + add, q.w + add};

1711

1712 return result;

1713}

1714

1715// Subtract two quaternions

1716RMAPI Quaternion QuaternionSubtract(Quaternion q1, Quaternion q2)

1717{

1718 Quaternion result = {q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w};

1719

1720 return result;

1721}

1722

1723// Subtract quaternion and float value

1724RMAPI Quaternion QuaternionSubtractValue(Quaternion q, float sub)

1725{

1726 Quaternion result = {q.x - sub, q.y - sub, q.z - sub, q.w - sub};

1727

1728 return result;

1729}

1730

1731// Get identity quaternion

1732RMAPI Quaternion QuaternionIdentity(void)

1733{

1734 Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };

1735

1736 return result;

1737}

1738

1739// Computes the length of a quaternion

1740RMAPI float QuaternionLength(Quaternion q)

1741{

1742 float result = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);

1743

1744 return result;

1745}

1746

1747// Normalize provided quaternion

1748RMAPI Quaternion QuaternionNormalize(Quaternion q)

1749{

1750 Quaternion result = { 0 };

1751

1752 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);

1753 if (length == 0.0f) length = 1.0f;

1754 float ilength = 1.0f/length;

1755

1756 result.x = q.x*ilength;

1757 result.y = q.y*ilength;

1758 result.z = q.z*ilength;

1759 result.w = q.w*ilength;

1760

1761 return result;

1762}

1763

1764// Invert provided quaternion

1765RMAPI Quaternion QuaternionInvert(Quaternion q)

1766{

1767 Quaternion result = q;

1768

1769 float lengthSq = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w;

1770

1771 if (lengthSq != 0.0f)

1772 {

1773 float invLength = 1.0f/lengthSq;

1774

1775 result.x *= -invLength;

1776 result.y *= -invLength;

1777 result.z *= -invLength;

1778 result.w *= invLength;

1779 }

1780

1781 return result;

1782}

1783

1784// Calculate two quaternion multiplication

1785RMAPI Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2)

1786{

1787 Quaternion result = { 0 };

1788

1789 float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w;

1790 float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w;

1791

1792 result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby;

1793 result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz;

1794 result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx;

1795 result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz;

1796

1797 return result;

1798}

1799

1800// Scale quaternion by float value

1801RMAPI Quaternion QuaternionScale(Quaternion q, float mul)

1802{

1803 Quaternion result = { 0 };

1804

1805 result.x = q.x*mul;

1806 result.y = q.y*mul;

1807 result.z = q.z*mul;

1808 result.w = q.w*mul;

1809

1810 return result;

1811}

1812

1813// Divide two quaternions

1814RMAPI Quaternion QuaternionDivide(Quaternion q1, Quaternion q2)

1815{

1816 Quaternion result = { q1.x/q2.x, q1.y/q2.y, q1.z/q2.z, q1.w/q2.w };

1817

1818 return result;

1819}

1820

1821// Calculate linear interpolation between two quaternions

1822RMAPI Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount)

1823{

1824 Quaternion result = { 0 };

1825

1826 result.x = q1.x + amount*(q2.x - q1.x);

1827 result.y = q1.y + amount*(q2.y - q1.y);

1828 result.z = q1.z + amount*(q2.z - q1.z);

1829 result.w = q1.w + amount*(q2.w - q1.w);

1830

1831 return result;

1832}

1833

1834// Calculate slerp-optimized interpolation between two quaternions

1835RMAPI Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount)

1836{

1837 Quaternion result = { 0 };

1838

1839 // QuaternionLerp(q1, q2, amount)

1840 result.x = q1.x + amount*(q2.x - q1.x);

1841 result.y = q1.y + amount*(q2.y - q1.y);

1842 result.z = q1.z + amount*(q2.z - q1.z);

1843 result.w = q1.w + amount*(q2.w - q1.w);

1844

1845 // QuaternionNormalize(q);

1846 Quaternion q = result;

1847 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);

1848 if (length == 0.0f) length = 1.0f;

1849 float ilength = 1.0f/length;

1850

1851 result.x = q.x*ilength;

1852 result.y = q.y*ilength;

1853 result.z = q.z*ilength;

1854 result.w = q.w*ilength;

1855

1856 return result;

1857}

1858

1859// Calculates spherical linear interpolation between two quaternions

1860RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)

1861{

1862 Quaternion result = { 0 };

1863

1864#if !defined(EPSILON)

1865 #define EPSILON 0.000001f

1866#endif

1867

1868 float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;

1869

1870 if (cosHalfTheta < 0)

1871 {

1872 q2.x = -q2.x; q2.y = -q2.y; q2.z = -q2.z; q2.w = -q2.w;

1873 cosHalfTheta = -cosHalfTheta;

1874 }

1875

1876 if (fabsf(cosHalfTheta) >= 1.0f) result = q1;

1877 else if (cosHalfTheta > 0.95f) result = QuaternionNlerp(q1, q2, amount);

1878 else

1879 {

1880 float halfTheta = acosf(cosHalfTheta);

1881 float sinHalfTheta = sqrtf(1.0f - cosHalfTheta*cosHalfTheta);

1882

1883 if (fabsf(sinHalfTheta) < EPSILON)

1884 {

1885 result.x = (q1.x*0.5f + q2.x*0.5f);

1886 result.y = (q1.y*0.5f + q2.y*0.5f);

1887 result.z = (q1.z*0.5f + q2.z*0.5f);

1888 result.w = (q1.w*0.5f + q2.w*0.5f);

1889 }

1890 else

1891 {

1892 float ratioA = sinf((1 - amount)*halfTheta)/sinHalfTheta;

1893 float ratioB = sinf(amount*halfTheta)/sinHalfTheta;

1894

1895 result.x = (q1.x*ratioA + q2.x*ratioB);

1896 result.y = (q1.y*ratioA + q2.y*ratioB);

1897 result.z = (q1.z*ratioA + q2.z*ratioB);

1898 result.w = (q1.w*ratioA + q2.w*ratioB);

1899 }

1900 }

1901

1902 return result;

1903}

1904

1905// Calculate quaternion based on the rotation from one vector to another

1906RMAPI Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to)

1907{

1908 Quaternion result = { 0 };

1909

1910 float cos2Theta = (from.x*to.x + from.y*to.y + from.z*to.z); // Vector3DotProduct(from, to)

1911 Vector3 cross = { from.y*to.z - from.z*to.y, from.z*to.x - from.x*to.z, from.x*to.y - from.y*to.x }; // Vector3CrossProduct(from, to)

1912

1913 result.x = cross.x;

1914 result.y = cross.y;

1915 result.z = cross.z;

1916 result.w = 1.0f + cos2Theta;

1917

1918 // QuaternionNormalize(q);

1919 // NOTE: Normalize to essentially nlerp the original and identity to 0.5

1920 Quaternion q = result;

1921 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);

1922 if (length == 0.0f) length = 1.0f;

1923 float ilength = 1.0f/length;

1924

1925 result.x = q.x*ilength;

1926 result.y = q.y*ilength;

1927 result.z = q.z*ilength;

1928 result.w = q.w*ilength;

1929

1930 return result;

1931}

1932

1933// Get a quaternion for a given rotation matrix

1934RMAPI Quaternion QuaternionFromMatrix(Matrix mat)

1935{

1936 Quaternion result = { 0 };

1937

1938 float fourWSquaredMinus1 = mat.m0 + mat.m5 + mat.m10;

1939 float fourXSquaredMinus1 = mat.m0 - mat.m5 - mat.m10;

1940 float fourYSquaredMinus1 = mat.m5 - mat.m0 - mat.m10;

1941 float fourZSquaredMinus1 = mat.m10 - mat.m0 - mat.m5;

1942

1943 int biggestIndex = 0;

1944 float fourBiggestSquaredMinus1 = fourWSquaredMinus1;

1945 if (fourXSquaredMinus1 > fourBiggestSquaredMinus1)

1946 {

1947 fourBiggestSquaredMinus1 = fourXSquaredMinus1;

1948 biggestIndex = 1;

1949 }

1950

1951 if (fourYSquaredMinus1 > fourBiggestSquaredMinus1)

1952 {

1953 fourBiggestSquaredMinus1 = fourYSquaredMinus1;

1954 biggestIndex = 2;

1955 }

1956

1957 if (fourZSquaredMinus1 > fourBiggestSquaredMinus1)

1958 {

1959 fourBiggestSquaredMinus1 = fourZSquaredMinus1;

1960 biggestIndex = 3;

1961 }

1962

1963 float biggestVal = sqrtf(fourBiggestSquaredMinus1 + 1.0f)*0.5f;

1964 float mult = 0.25f/biggestVal;

1965

1966 switch (biggestIndex)

1967 {

1968 case 0:

1969 result.w = biggestVal;

1970 result.x = (mat.m6 - mat.m9)*mult;

1971 result.y = (mat.m8 - mat.m2)*mult;

1972 result.z = (mat.m1 - mat.m4)*mult;

1973 break;

1974 case 1:

1975 result.x = biggestVal;

1976 result.w = (mat.m6 - mat.m9)*mult;

1977 result.y = (mat.m1 + mat.m4)*mult;

1978 result.z = (mat.m8 + mat.m2)*mult;

1979 break;

1980 case 2:

1981 result.y = biggestVal;

1982 result.w = (mat.m8 - mat.m2)*mult;

1983 result.x = (mat.m1 + mat.m4)*mult;

1984 result.z = (mat.m6 + mat.m9)*mult;

1985 break;

1986 case 3:

1987 result.z = biggestVal;

1988 result.w = (mat.m1 - mat.m4)*mult;

1989 result.x = (mat.m8 + mat.m2)*mult;

1990 result.y = (mat.m6 + mat.m9)*mult;

1991 break;

1992 }

1993

1994 return result;

1995}

1996

1997// Get a matrix for a given quaternion

1998RMAPI Matrix QuaternionToMatrix(Quaternion q)

1999{

2000 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,

2001 0.0f, 1.0f, 0.0f, 0.0f,

2002 0.0f, 0.0f, 1.0f, 0.0f,

2003 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity()

2004

2005 float a2 = q.x*q.x;

2006 float b2 = q.y*q.y;

2007 float c2 = q.z*q.z;

2008 float ac = q.x*q.z;

2009 float ab = q.x*q.y;

2010 float bc = q.y*q.z;

2011 float ad = q.w*q.x;

2012 float bd = q.w*q.y;

2013 float cd = q.w*q.z;

2014

2015 result.m0 = 1 - 2*(b2 + c2);

2016 result.m1 = 2*(ab + cd);

2017 result.m2 = 2*(ac - bd);

2018

2019 result.m4 = 2*(ab - cd);

2020 result.m5 = 1 - 2*(a2 + c2);

2021 result.m6 = 2*(bc + ad);

2022

2023 result.m8 = 2*(ac + bd);

2024 result.m9 = 2*(bc - ad);

2025 result.m10 = 1 - 2*(a2 + b2);

2026

2027 return result;

2028}

2029

2030// Get rotation quaternion for an angle and axis

2031// NOTE: Angle must be provided in radians

2032RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)

2033{

2034 Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };

2035

2036 float axisLength = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);

2037

2038 if (axisLength != 0.0f)

2039 {

2040 angle *= 0.5f;

2041

2042 float length = 0.0f;

2043 float ilength = 0.0f;

2044

2045 // Vector3Normalize(axis)

2046 Vector3 v = axis;

2047 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);

2048 if (length == 0.0f) length = 1.0f;

2049 ilength = 1.0f/length;

2050 axis.x *= ilength;

2051 axis.y *= ilength;

2052 axis.z *= ilength;

2053

2054 float sinres = sinf(angle);

2055 float cosres = cosf(angle);

2056

2057 result.x = axis.x*sinres;

2058 result.y = axis.y*sinres;

2059 result.z = axis.z*sinres;

2060 result.w = cosres;

2061

2062 // QuaternionNormalize(q);

2063 Quaternion q = result;

2064 length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);

2065 if (length == 0.0f) length = 1.0f;

2066 ilength = 1.0f/length;

2067 result.x = q.x*ilength;

2068 result.y = q.y*ilength;

2069 result.z = q.z*ilength;

2070 result.w = q.w*ilength;

2071 }

2072

2073 return result;

2074}

2075

2076// Get the rotation angle and axis for a given quaternion

2077RMAPI void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle)

2078{

2079 if (fabsf(q.w) > 1.0f)

2080 {

2081 // QuaternionNormalize(q);

2082 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);

2083 if (length == 0.0f) length = 1.0f;

2084 float ilength = 1.0f/length;

2085

2086 q.x = q.x*ilength;

2087 q.y = q.y*ilength;

2088 q.z = q.z*ilength;

2089 q.w = q.w*ilength;

2090 }

2091

2092 Vector3 resAxis = { 0.0f, 0.0f, 0.0f };

2093 float resAngle = 2.0f*acosf(q.w);

2094 float den = sqrtf(1.0f - q.w*q.w);

2095

2096 if (den > EPSILON)

2097 {

2098 resAxis.x = q.x/den;

2099 resAxis.y = q.y/den;

2100 resAxis.z = q.z/den;

2101 }

2102 else

2103 {

2104 // This occurs when the angle is zero.

2105 // Not a problem: just set an arbitrary normalized axis.

2106 resAxis.x = 1.0f;

2107 }

2108

2109 *outAxis = resAxis;

2110 *outAngle = resAngle;

2111}

2112

2113// Get the quaternion equivalent to Euler angles

2114// NOTE: Rotation order is ZYX

2115RMAPI Quaternion QuaternionFromEuler(float pitch, float yaw, float roll)

2116{

2117 Quaternion result = { 0 };

2118

2119 float x0 = cosf(pitch*0.5f);

2120 float x1 = sinf(pitch*0.5f);

2121 float y0 = cosf(yaw*0.5f);

2122 float y1 = sinf(yaw*0.5f);

2123 float z0 = cosf(roll*0.5f);

2124 float z1 = sinf(roll*0.5f);

2125

2126 result.x = x1*y0*z0 - x0*y1*z1;

2127 result.y = x0*y1*z0 + x1*y0*z1;

2128 result.z = x0*y0*z1 - x1*y1*z0;

2129 result.w = x0*y0*z0 + x1*y1*z1;

2130

2131 return result;

2132}

2133

2134// Get the Euler angles equivalent to quaternion (roll, pitch, yaw)

2135// NOTE: Angles are returned in a Vector3 struct in radians

2136RMAPI Vector3 QuaternionToEuler(Quaternion q)

2137{

2138 Vector3 result = { 0 };

2139

2140 // Roll (x-axis rotation)

2141 float x0 = 2.0f*(q.w*q.x + q.y*q.z);

2142 float x1 = 1.0f - 2.0f*(q.x*q.x + q.y*q.y);

2143 result.x = atan2f(x0, x1);

2144

2145 // Pitch (y-axis rotation)

2146 float y0 = 2.0f*(q.w*q.y - q.z*q.x);

2147 y0 = y0 > 1.0f ? 1.0f : y0;

2148 y0 = y0 < -1.0f ? -1.0f : y0;

2149 result.y = asinf(y0);

2150

2151 // Yaw (z-axis rotation)

2152 float z0 = 2.0f*(q.w*q.z + q.x*q.y);

2153 float z1 = 1.0f - 2.0f*(q.y*q.y + q.z*q.z);

2154 result.z = atan2f(z0, z1);

2155

2156 return result;

2157}

2158

2159// Transform a quaternion given a transformation matrix

2160RMAPI Quaternion QuaternionTransform(Quaternion q, Matrix mat)

2161{

2162 Quaternion result = { 0 };

2163

2164 result.x = mat.m0*q.x + mat.m4*q.y + mat.m8*q.z + mat.m12*q.w;

2165 result.y = mat.m1*q.x + mat.m5*q.y + mat.m9*q.z + mat.m13*q.w;

2166 result.z = mat.m2*q.x + mat.m6*q.y + mat.m10*q.z + mat.m14*q.w;

2167 result.w = mat.m3*q.x + mat.m7*q.y + mat.m11*q.z + mat.m15*q.w;

2168

2169 return result;

2170}

2171

2172// Check whether two given quaternions are almost equal

2173RMAPI int QuaternionEquals(Quaternion p, Quaternion q)

2174{

2175#if !defined(EPSILON)

2176 #define EPSILON 0.000001f

2177#endif

2178

2179 int result = (((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&

2180 ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&

2181 ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) &&

2182 ((fabsf(p.w - q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))) ||

2183 (((fabsf(p.x + q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&

2184 ((fabsf(p.y + q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&

2185 ((fabsf(p.z + q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) &&

2186 ((fabsf(p.w + q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w))))));

2187

2188 return result;

2189}

2190

2191#endif // RAYMATH_H