-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathminimath.h
More file actions
4982 lines (4409 loc) · 282 KB
/
Copy pathminimath.h
File metadata and controls
4982 lines (4409 loc) · 282 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// __ ____ __ ___ ______
// | ' \ | ' ` \_
// _| __ |_| __ __ | _ _
// _ __ ___ (_) | | (_) | | | | | __ _| |_| |__
// | '_ ` _ \| | | | | | | | | | |/ _` | __| '_ \_
// | | | | | | | | | | | | | | | | (_| | |_| | | |
// |_| |_| |_|_|__| |__|_|__| |__| |__|\__,_|\__|_| |_|
//
// https://github.com/Flix01/Header-Only-GL-Helpers
/** MIT License
*
* Copyright (c) 2019 Flix (https://github.com/Flix01/)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
Some functions are ported from
-> the OgreMath library (www.ogre3d.org) - MIT licensed.
-> the repository https://github.com/juj/MathGeoLib - Apache 2 license
-> the glm library (https://github.com/g-truc/glm) - licensed under the Happy Bunny License (Modified MIT) or the MIT License.
-> Eric's Blog: https://lxjk.github.io/2017/09/03/Fast-4x4-Matrix-Inverse-with-SSE-SIMD-Explained.html
================
GETTING STARTED:
================
-> minimath.h is a stb-like header-only column-major mini math library.
That means that MINIMATH_IMPLEMENTATION must be defined in a single c or c++ file before including minimath.h.
-> The main type used is "nmoat" (miNiMath flOAT): if NM_DOUBLE_PRECISION is defined it's a double, otherwise it's a float.
-> There are 3 levels of API that can be used:
<0> [C/C++] Functions starting with "nmh_" (e.g. nmh_sin(...)).
These functions are simply low-level math functions.
(example: nmh_sin(...) defaults to sinf(...), or to sin(...) when NM_DOUBLE_PRECISION is defined).
<1> [C/C++] Functions starting with "nm_" (e.g. nm_Mat4Mul(nmoat* result16,const nmoat* ml16,const nmoat* mr16)):
Although this API is not type-safe (because we can do: nmoat v2[2];nm_Mat4Mul(v2,...) without any compiler error),
it's the preferred API to use: it's non-intrusive because it works on plain C arrays.
You can even disable everything else by defining NM_NO_MATH_STRUCTS.
<2> [C/C++] Structs vec2,vec3,vec4,quat,mat3,mat4 and functions starting with vec2_,vec3_,vec4_,quat_,mat3_,mat4_, plus
functions like make_vec2(...),[...],make_mat4(...):
This API is type-safe (example: mat4 dst,a,b;[fill a and b here];mat4_mul(&dst,&a,&b);).
<3> [C++ only] Structs vec2,vec3,vec4,quat,mat3,mat4 and their methods.
Example: mat4 a,b;mat4 c = a*b;
<4> [C++ only (experimental)] A PARTIAL glm library (https://github.com/g-truc/glm) compatibility layer, that can be
activated using the definition NM_BEST_GLM_COMPATIBILITY. Example file "glm_test.cpp":
#define NM_BEST_GLM_COMPATIBILITY
#define MINIMATH_IMPLEMENTATION
#include <minimath.h>
glm::mat4 camera(float Translate, glm::vec2 const & Rotate) {
glm::mat4 Projection = glm::perspective(glm::radians(45.0f), 4.0f / 3.0f, 0.1f, 100.f);
glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Translate));
View = glm::rotate(View, Rotate.y, glm::vec3(-1.0f, 0.0f, 0.0f));
View = glm::rotate(View, Rotate.x, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 Model = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f));
return Projection * View * Model;
}
int main(int argc,char* argv[]) {
glm::mat4 result = camera(25.f,glm::vec2(60.f,30.f));
return 1;
}
=======================
SOME USEFUL DEFINITIONS
=======================
NM_DOUBLE_PRECISION minimath.h works with doubles instead of floats.
NM_NO_MATH_STRUCTS only API <0> and <1> are available (good choice!).
NM_BEST_GLM_COMPATIBILITY [C++ only] enables API <4>.
NM_GLM_MATRIX_SUBSCRIPT_OPERATOR [C++ only: already defined by NM_BEST_GLM_COMPATIBILITY] It affects the C++ [] operator of mat3 and mat4, making it work like in glm (not the best choice IMO: better use the col[col][row] field explicitly).
NM_HAS_CFG if too many NM_ defs pollute your project settings, just define NM_HAS_CFG, create "minimath_cfg.h" and put all the other NM_ defs there.
NM_NAMESPACE [C++ only] [needs a name] wraps API <2> and <3> with namespace NM_NAMESPACE (and if <4> is enabled, it overwrites the "glm" namespace).
NM_NO_CPP_CTRS [C++ only] with this, to init structs you can't use C++ ctrs anymore, but now you can use C-style: vec2 v2={{{1,2}}}; [vec2 v2={1,2}; works with a warning] Tip: vec2 v2=make_vec2(1,2); WORKS in ANY case.
NM_NM_NO_C_INITIALIZATION [C only or C++ with NM_NO_CPP_CTRS] some old compiler does not even support C-style initialization (because of anonymous sub-structs). With this def we can still use something like: vec2 v2=make_vec2(1,2);
NM_USE_SIMD [Experimental] together with the correct compilation flags, this def enables SIMD acceleration for a VERY FEW functions (and I've not even sure that this actually speeds up code in optimized release mode).
NM_ALIGN_STRUCTS [Experimental] it aligns all struct (intended to speed up NM_USE_SIMD a bit, but it's not required by NM_USE_SIMD).
NM_COMPILER_SUPPORTS_NONPOD_ANONYMOUS_MEMBERS [C++ only][Experimental] mat3 and mat4 structs can have, in some cases, handy anonymous fields: vec3 xAxis,yAxis,zAxis(,and tra for mat4). This is only possible if vec3 is a POD-type (always true in C, or with NM_NO_CPP_CTRS in C++). This def tries to see if your compiler can keep vec3 non-POD and still add the 'axis' fields.
NM_USE_MEMCPY [impl includes <string.h>] It uses memcpy instead of a for loop to copy arrays.
NM_NO_STDIO [excludes <stdio.h> from header] It disables all the "print" functions.
NM_NO_ASSERT Disables NM_ASSERTs
NM_ASSERT_ON_BAD_QUATERNION_CTR the quat struct C++ constructor, and the make_quat(...) function (but NOT the C-style init: quat q={{{x,y,z,w}}};), take w as first argument (like glm). To avoid common errors this def can be defined.
NM_NO_WARNING_SUPPRESSION by default a few warnings are silenced; with this definition you can see them all.
NM_NO_C99_MATH_FUNCTIONS Disables C99 single precision floating point math functions (e.g. sinf, cosf): old compilers might not support them.
========
IN CODE:
========
NM_ASSERT(some bool cond); Default assert macro
NM_STRUCT_SIZE_CHECK; It asserts if the structs have strange sizes
=====
TIPS:
=====
-> To get a raw nmoat pointer of a struct, you can just use the "e" field for vec/quat and the "m" field for mat3/4 (ex: vec3 v;nmoat* vp=v.e; mat4 m;nmoat* mp=m.m;).
=====
TODO:
=====
-> Find and fix all errors.
-> Use a unique and consistent naming convention for all functions.
-> Find and add missing functions, and make all accessible from the 3 APIs.
-> Avoid implementing <3> or <4> using <2>, but whenever possible always use <1> in implementations.
-> Document functions better.
-> Provide examples, or tests. Check correctness of everything.
*/
#ifndef MINIMATH_H_
#define MINIMATH_H_
#define NM_VERSION "1.0 WIP"
#define NM_VERSION_NUM 0007
#ifdef NM_HAS_CFG
# include "minimath_cfg.h"
#endif
#ifndef NM_API_DEF
#define NM_API_DEF /* no-op */
#endif
#ifndef NM_RESTRICT
#define NM_RESTRICT __restrict
// __restrict (C99), otherwise try: restrict (C11) or: /* no-op */
#endif
#ifndef NM_API_INL
#define NM_API_INL __inline
// C99, otherwise try: __inline or /* no-op */
/* Hint: To be conformant with the C standard, every pure (= not 'static' or 'extern') inline definition
in the .h file, must be matched with a corresponding 'extern' declaration in the implementation file.
Otherwise under some compiler settings we can have 'undefined reference' errors */
#endif
#ifndef NM_API_STATIC
#define NM_API_STATIC static
#endif
#ifndef NM_API_EXT
#define NM_API_EXT extern
#endif
#ifndef NM_API_EXT_INL
#define NM_API_EXT_INL NM_API_EXT NM_API_INL
/* On GCC: The combination of inline and extern has almost the effect of a macro.
* The way to use it is to put a function definition in a header file with these keywords,
* and put another copy of the definition (lacking inline and extern) in a library file.
* The definition in the header file causes most calls to the function to be inlined.
* If any uses of the function remain, they refer to the single copy in the library. */
#endif
#ifndef NM_API_DEF_EXT
#define NM_API_DEF_EXT NM_API_DEF NM_API_EXT
#endif
#ifndef NM_API_DEF_EXT_INL
# ifndef __cplusplus
# define NM_API_DEF_EXT_INL NM_API_DEF NM_API_EXT_INL
# else
# define NM_API_DEF_EXT_INL NM_API_DEF
# endif
#endif
#ifndef NM_API_DEF_INL
#define NM_API_DEF_INL NM_API_DEF NM_API_INL
#endif
#ifndef NM_API_EXPLICIT
#define NM_API_EXPLICIT explicit
#endif
#ifndef NM_API_INL_STATIC
#define NM_API_INL_STATIC NM_API_INL NM_API_STATIC
#endif
#if (defined(NM_USE_DOUBLE_PRECISION) || defined(NM_DOUBLE_PRECISION))
# undef NM_DOUBLE_PRECISION
# define NM_DOUBLE_PRECISION
# undef NM_USE_DOUBLE_PRECISION
# define NM_USE_DOUBLE_PRECISION
#endif
#ifdef NM_DOUBLE_PRECISION
typedef double nmoat;
#else
typedef float nmoat;
#endif
#ifndef NM_SLERP_EPSILON
# define NM_SLERP_EPSILON ((nmoat)0.0001)
#endif //NM_SLERP_EPSILON
#ifndef NM_EPSILON
# define NM_EPSILON ((nmoat)0.00000000001)
#endif
#ifdef NM_ALIGN_STRUCTS
# ifdef NM_DOUBLE_PRECISION
# define NM_STRUCT_ALIGNMENT_AMOUNT (32)
# else
# define NM_STRUCT_ALIGNMENT_AMOUNT (16)
# endif
# ifdef _MSC_VER
# define NM_PRE_ALIGN(X) __declspec(align(X))
# define NM_POST_ALIGN(X) /* no-op */
# else //_MSC_VER
# define NM_PRE_ALIGN(X) /* no-op */
# define NM_POST_ALIGN(X) __attribute__((aligned(X)))
# endif //_MSC_VER
# define NM_PRE_ALIGN_DEFAULT NM_PRE_ALIGN(NM_STRUCT_ALIGNMENT_AMOUNT)
# define NM_POST_ALIGN_DEFAULT NM_POST_ALIGN(NM_STRUCT_ALIGNMENT_AMOUNT)
#else //NM_ALIGN_STRUCTS
# define NM_PRE_ALIGN(X) /* no-op */
# define NM_POST_ALIGN(X) /* no-op */
# define NM_PRE_ALIGN_DEFAULT /* no-op */
# define NM_POST_ALIGN_DEFAULT /* no-op */
#endif //NM_ALIGN_STRUCTS
//--------------------------------------------------
#include <math.h>
#ifndef M_PI
#define M_PI ((nmoat)3.14159265358979323846)
#endif
#ifndef M_HALF_PI
#define M_HALF_PI ((nmoat)(3.14159265358979323846/2.0))
#endif
#ifndef M_PIOVER180
#define M_PIOVER180 ((nmoat)(3.14159265358979323846/180.0))
#endif
#ifndef M_180OVERPI
#define M_180OVERPI ((nmoat)(180.0/3.14159265358979323846))
#endif
#ifndef M_DEG2RAD
#define M_DEG2RAD(X) (X*(nmoat)M_PIOVER180)
#endif
#ifndef M_RAD2DEG
#define M_RAD2DEG(X) (X*(nmoat)M_180OVERPI)
#endif
#ifndef NM_NO_STDIO
#include <stdio.h> // printf(...), FILE*
#endif
//#include <stddef.h> /* size_t */
#ifdef NM_BEST_GLM_COMPATIBILITY
# ifndef NM_NAMESPACE
# define NM_NAMESPACE glm
# endif
# undef NM_GLM_MATRIX_SUBSCRIPT_OPERATOR
# define NM_GLM_MATRIX_SUBSCRIPT_OPERATOR
#endif //NM_BEST_GLM_COMPATIBILITY
#ifndef __cplusplus
# undef NM_NO_CPP_CTRS
# define NM_NO_CPP_CTRS
# ifdef NM_NAMESPACE
# undef NM_NAMESPACE
# warning NM_NAMESPACE will be ignored and undefined (plain C compilation).
# endif //NM_NAMESPACE
#else //__cplusplus
#endif //__cplusplus
#ifndef NM_ASSERT
# if (!defined(NDEBUG) && !defined(_NDEBUG) && !defined(NM_NO_ASSERT))
# ifndef __cplusplus
# include <assert.h>
# else //__cplusplus
# include <cassert>
# endif //__cplusplus
# define NM_ASSERT(X) assert(X)
# else
# define NM_ASSERT(X) /* no-op */
# endif
#endif //NM_ASSERT
#ifndef COMPILER_SUPPORTS_GCC_DIAGNOSTIC // We define this
# if (defined(__GNUC__) || defined(__MINGW__) || defined(__clang__))
# define COMPILER_SUPPORTS_GCC_DIAGNOSTIC
# endif
#endif
#ifndef NM_NO_WARNING_SUPPRESSION
# ifdef COMPILER_SUPPORTS_GCC_DIAGNOSTIC
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wpragmas"
# pragma GCC diagnostic ignored "-Wunknown-warning-option"
# pragma GCC diagnostic ignored "-Wmissing-braces"
# pragma GCC diagnostic ignored "-Wrestrict"
# elif defined(_MSC_VER)
# pragma warning( push )
//# pragma warning (disable: 4127) // condition expression is constant
//# pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
# pragme warning (disable: 4190) // "-Wreturn-type-c-linkage"
# endif
#endif // NM_NO_WARNING_SUPPRESSION
#ifdef __cplusplus
extern "C" {
#endif //__cplusplus
#define nmh_radians(deg) M_DEG2RAD(deg)
#define nmh_degrees(rad) M_RAD2DEG(rad)
#if (!defined(NM_DOUBLE_PRECISION) && !defined(NM_NO_C99_MATH_FUNCTIONS))
# define nmh_sin(v) sinf(v)
# define nmh_cos(v) cosf(v)
# define nmh_tan(v) tanf(v)
# define nmh_asin(v) asinf(v)
# define nmh_acos(v) acosf(v)
# define nmh_atan(v) atanf(v)
# define nmh_atan2(y,x) atan2f(y,x)
# define nmh_sqrt(v) sqrtf(v)
# define nmh_fabs(v) fabsf(v)
# define nmh_fmod(a,b) fmodf(a,b)
# define nmh_pow(x,y) powf(x,y)
# define nmh_round(v) ((v) < 0.0f ? ceilf((v) - 0.5f) : floorf((v) + 0.5f))
# define nmh_ceil(v) ceilf(v)
# define nmh_floor(v) floorf(v)
# if (defined(GNU_SOURCE) || defined(NM_HAS_SINCOS))
# define nmh_sincos(ANGLE,PSIN,PCOS) {sincosf(ANGLE,PSIN,PCOS);} // old compilers
# else
# define nmh_sincos(ANGLE,PSIN,PCOS) {*PSIN=sinf(ANGLE);*PCOS=cosf(ANGLE);} // new compilers can optimize this in -O2 or -O3
# endif
#else //NM_DOUBLE_PRECISION || NM_NO_C99_MATH_FUNCTIONS
# define nmh_sin(v) sin(v)
# define nmh_cos(v) cos(v)
# define nmh_tan(v) tan(v)
# define nmh_asin(v) asin(v)
# define nmh_acos(v) acos(v)
# define nmh_atan(v) atan(v)
# define nmh_atan2(y,x) atan2(y,x)
# define nmh_sqrt(v) sqrt(v)
# define nmh_fabs(v) fabs(v)
# define nmh_fmod(a,b) fmod(a,b)
# define nmh_pow(x,y) pow(x,y)
# define nmh_round(v) ((v) < 0.0 ? ceil((v) - 0.5) : floor((v) + 0.5))
# define nmh_ceil(v) ceil(v)
# define nmh_floor(v) floor(v)
# if (defined(GNU_SOURCE) || defined(NM_HAS_SINCOS))
# define nmh_sincos(ANGLE,PSIN,PCOS) {sincos(ANGLE,PSIN,PCOS);} // old compilers
# else
# define nmh_sincos(ANGLE,PSIN,PCOS) {*PSIN=sin(ANGLE);*PCOS=cos(ANGLE);} // new compilers can optimize this in -O2 or -O3
# endif
#endif // NM_DOUBLE_PRECISION
#define nmh_fractional_part(v) nmh_fmod(v,(nmoat)1.0)
NM_API_DEF_EXT_INL int nm_AreEqualEps(const nmoat* NM_RESTRICT a,const nmoat* NM_RESTRICT b,int num_nmoats,nmoat eps);
NM_API_DEF_EXT_INL int nm_AreEqual(const nmoat* NM_RESTRICT a,const nmoat* NM_RESTRICT b,int num_nmoats);
NM_API_DEF_EXT_INL nmoat* nm_Vec2Copy(nmoat* NM_RESTRICT dst2,const nmoat* NM_RESTRICT src2);
NM_API_DEF_EXT_INL nmoat* nm_Vec2Add(nmoat* NM_RESTRICT dst2,const nmoat* NM_RESTRICT a2,const nmoat* NM_RESTRICT b2);
NM_API_DEF_EXT_INL nmoat* nm_Vec2Sub(nmoat* NM_RESTRICT dst2,const nmoat* NM_RESTRICT a2,const nmoat* NM_RESTRICT b2);
NM_API_DEF_EXT_INL nmoat* nm_Vec2Mul(nmoat* NM_RESTRICT dst2,const nmoat* NM_RESTRICT a2,const nmoat* NM_RESTRICT b2);
NM_API_DEF_EXT_INL nmoat* nm_Vec2Div(nmoat* NM_RESTRICT dst2,const nmoat* NM_RESTRICT a2,const nmoat* NM_RESTRICT b2);
NM_API_DEF_EXT_INL nmoat* nm_Vec2MulSca(nmoat* NM_RESTRICT dst2,const nmoat* NM_RESTRICT a2,nmoat s);
NM_API_DEF_EXT_INL nmoat* nm_Vec2DivSca(nmoat* NM_RESTRICT dst2,const nmoat* NM_RESTRICT a2,nmoat s);
NM_API_DEF_EXT_INL nmoat* nm_Vec2Neg(nmoat* NM_RESTRICT dst2,const nmoat* NM_RESTRICT a2);
NM_API_DEF_EXT_INL nmoat* nm_Vec2SAdd(nmoat* NM_RESTRICT dst2,const nmoat* NM_RESTRICT a2);
NM_API_DEF_EXT_INL nmoat* nm_Vec2SSub(nmoat* NM_RESTRICT dst2,const nmoat* NM_RESTRICT a2);
NM_API_DEF_EXT_INL nmoat* nm_Vec2SMul(nmoat* NM_RESTRICT dst2,const nmoat* NM_RESTRICT a2);
NM_API_DEF_EXT_INL nmoat* nm_Vec2SDiv(nmoat* NM_RESTRICT dst2,const nmoat* NM_RESTRICT a2);
NM_API_DEF_EXT_INL nmoat* nm_Vec2SMulSca(nmoat* NM_RESTRICT dst2,nmoat s);
NM_API_DEF_EXT_INL nmoat* nm_Vec2SDivSca(nmoat* NM_RESTRICT dst2,nmoat s);
NM_API_DEF_EXT_INL nmoat* nm_Vec2SNeg(nmoat* NM_RESTRICT dst2);
NM_API_DEF_EXT_INL nmoat nm_Vec2Length2(const nmoat* NM_RESTRICT a2);
NM_API_DEF_EXT_INL nmoat nm_Vec2Length(const nmoat* NM_RESTRICT a2);
NM_API_DEF_EXT_INL void nm_Vec2Normalize(nmoat* NM_RESTRICT v2);
NM_API_DEF_EXT_INL nmoat* nm_Vec2Normalized(nmoat* NM_RESTRICT vOut2,const nmoat* NM_RESTRICT v2);
NM_API_DEF_EXT_INL nmoat nm_Vec2DistSquared(const nmoat* NM_RESTRICT a2,const nmoat* NM_RESTRICT b2);
NM_API_DEF_EXT_INL nmoat nm_Vec2Dist(const nmoat* NM_RESTRICT a2,const nmoat* NM_RESTRICT b2);
NM_API_DEF_EXT_INL nmoat* nm_Vec3Copy(nmoat* NM_RESTRICT dst3,const nmoat* NM_RESTRICT src3);
NM_API_DEF_EXT_INL nmoat* nm_Vec3Add(nmoat* NM_RESTRICT dst3,const nmoat* NM_RESTRICT a3,const nmoat* NM_RESTRICT b3);
NM_API_DEF_EXT_INL nmoat* nm_Vec3Sub(nmoat* NM_RESTRICT dst3,const nmoat* NM_RESTRICT a3,const nmoat* NM_RESTRICT b3);
NM_API_DEF_EXT_INL nmoat* nm_Vec3Mul(nmoat* NM_RESTRICT dst3,const nmoat* NM_RESTRICT a3,const nmoat* NM_RESTRICT b3);
NM_API_DEF_EXT_INL nmoat* nm_Vec3Div(nmoat* NM_RESTRICT dst3,const nmoat* NM_RESTRICT a3,const nmoat* NM_RESTRICT b3);
NM_API_DEF_EXT_INL nmoat* nm_Vec3MulSca(nmoat* NM_RESTRICT dst3,const nmoat* NM_RESTRICT a3,nmoat s);
NM_API_DEF_EXT_INL nmoat* nm_Vec3DivSca(nmoat* NM_RESTRICT dst3,const nmoat* NM_RESTRICT a3,nmoat s);
NM_API_DEF_EXT_INL nmoat* nm_Vec3Neg(nmoat* NM_RESTRICT dst3,const nmoat* NM_RESTRICT a3);
NM_API_DEF_EXT_INL nmoat* nm_Vec3SAdd(nmoat* NM_RESTRICT dst3,const nmoat* NM_RESTRICT a3);
NM_API_DEF_EXT_INL nmoat* nm_Vec3SSub(nmoat* NM_RESTRICT dst3,const nmoat* NM_RESTRICT a3);
NM_API_DEF_EXT_INL nmoat* nm_Vec3SMul(nmoat* NM_RESTRICT dst3,const nmoat* NM_RESTRICT a3);
NM_API_DEF_EXT_INL nmoat* nm_Vec3SDiv(nmoat* NM_RESTRICT dst3,const nmoat* NM_RESTRICT a3);
NM_API_DEF_EXT_INL nmoat* nm_Vec3SMulSca(nmoat* NM_RESTRICT dst3,nmoat s);
NM_API_DEF_EXT_INL nmoat* nm_Vec3SDivSca(nmoat* NM_RESTRICT dst3,nmoat s);
NM_API_DEF_EXT_INL nmoat* nm_Vec3SNeg(nmoat* NM_RESTRICT dst3);
NM_API_DEF_EXT_INL nmoat nm_Vec3Dot(const nmoat* a3,const nmoat* b3);
NM_API_DEF_EXT_INL nmoat nm_Vec3Length2(const nmoat* NM_RESTRICT a3);
NM_API_DEF_EXT_INL nmoat nm_Vec3Length(const nmoat* NM_RESTRICT a3);
NM_API_DEF_EXT_INL void nm_Vec3Normalize(nmoat* NM_RESTRICT v3);
NM_API_DEF_EXT_INL nmoat* nm_Vec3Normalized(nmoat* NM_RESTRICT vOut3,const nmoat* NM_RESTRICT v3);
NM_API_DEF_EXT_INL nmoat* nm_Vec3Cross(nmoat* NM_RESTRICT vOut3,const nmoat* NM_RESTRICT a3,const nmoat* NM_RESTRICT b3);
NM_API_DEF_EXT_INL nmoat nm_Vec3DistSquared(const nmoat* NM_RESTRICT a3,const nmoat* NM_RESTRICT b3);
NM_API_DEF_EXT_INL nmoat nm_Vec3Dist(const nmoat* NM_RESTRICT a3,const nmoat* NM_RESTRICT b3);
NM_API_DEF_EXT_INL nmoat* nm_Vec4Copy(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT src4);
NM_API_DEF_EXT_INL nmoat* nm_Vec4Add(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4);
NM_API_DEF_EXT_INL nmoat* nm_Vec4Sub(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4);
NM_API_DEF_EXT_INL nmoat* nm_Vec4Mul(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4);
NM_API_DEF_EXT_INL nmoat* nm_Vec4Div(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4);
NM_API_DEF_EXT_INL nmoat* nm_Vec4MulSca(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT a4,nmoat s);
NM_API_DEF_EXT_INL nmoat* nm_Vec4DivSca(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT a4,nmoat s);
NM_API_DEF_EXT_INL nmoat* nm_Vec4Neg(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT a4);
NM_API_DEF_EXT_INL nmoat* nm_Vec4SAdd(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT a4);
NM_API_DEF_EXT_INL nmoat* nm_Vec4SSub(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT a4);
NM_API_DEF_EXT_INL nmoat* nm_Vec4SMul(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT a4);
NM_API_DEF_EXT_INL nmoat* nm_Vec4SDiv(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT a4);
NM_API_DEF_EXT_INL nmoat* nm_Vec4SMulSca(nmoat* NM_RESTRICT dst4,nmoat s);
NM_API_DEF_EXT_INL nmoat* nm_Vec4SDivSca(nmoat* NM_RESTRICT dst4,nmoat s);
NM_API_DEF_EXT_INL nmoat* nm_Vec4SNeg(nmoat* NM_RESTRICT dst4);
NM_API_DEF_EXT_INL nmoat nm_Vec4Length2(const nmoat* NM_RESTRICT a4);
NM_API_DEF_EXT_INL nmoat nm_Vec4Length(const nmoat* NM_RESTRICT a4);
NM_API_DEF_EXT_INL void nm_Vec4Normalize(nmoat* NM_RESTRICT v4);
NM_API_DEF_EXT_INL nmoat* nm_Vec4Normalized(nmoat* NM_RESTRICT vOut4,const nmoat* NM_RESTRICT v4);
NM_API_DEF_EXT_INL nmoat nm_Vec4DistSquared(const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4);
NM_API_DEF_EXT_INL nmoat nm_Vec4Dist(const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4);
NM_API_DEF_EXT_INL nmoat* nm_QuatCopy(nmoat* NM_RESTRICT dst4,const nmoat* NM_RESTRICT src4);
NM_API_DEF_EXT_INL nmoat nm_QuatLength2(const nmoat* NM_RESTRICT q4);
NM_API_DEF_EXT_INL nmoat nm_QuatLength(const nmoat* NM_RESTRICT q4);
NM_API_DEF_EXT_INL nmoat* nm_QuatLerp(nmoat* NM_RESTRICT result4,const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4,nmoat t,int normalizeQOutAfterLerp/*=1*/);
NM_API_DEF_EXT_INL nmoat* nm_QuatSlerpEps(nmoat* NM_RESTRICT result4,const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4,nmoat slerpTime_In_0_1,int normalizeResult4AfterLerp/*=1*/,nmoat eps/*=NM_SLERP_EPSILON*/);
NM_API_DEF_EXT_INL nmoat* nm_QuatSlerp(nmoat* NM_RESTRICT result4,const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4,nmoat slerpTime_In_0_1,int normalizeResult4AfterLerp/*=1*/);
NM_API_DEF_EXT_INL void nm_QuatNormalize(nmoat* NM_RESTRICT q4);
NM_API_DEF_EXT_INL nmoat* nm_QuatNormalized(nmoat* NM_RESTRICT result4,const nmoat* NM_RESTRICT q4);
NM_API_DEF_EXT_INL nmoat nm_QuatDot(const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4);
NM_API_DEF_EXT_INL nmoat* nm_QuatNegated(nmoat* NM_RESTRICT qOut4,const nmoat* NM_RESTRICT src4);
NM_API_DEF_EXT_INL void nm_QuatNegate(nmoat* NM_RESTRICT q4);
NM_API_DEF_EXT_INL nmoat* nm_QuatMul(nmoat* NM_RESTRICT qOut4,const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4);
NM_API_DEF_EXT_INL nmoat* nm_QuatMul3Quats(nmoat* NM_RESTRICT qOut4,const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4,const nmoat* NM_RESTRICT c4);
NM_API_DEF_EXT_INL nmoat* nm_QuatConjugated(nmoat* NM_RESTRICT qOut4,const nmoat* NM_RESTRICT q4);
NM_API_DEF_EXT_INL void nm_QuatConjugate(nmoat* NM_RESTRICT q4);
NM_API_DEF_EXT_INL nmoat* nm_QuatInverted(nmoat* NM_RESTRICT qOut4,const nmoat* NM_RESTRICT q4);
NM_API_DEF_EXT_INL void nm_QuatInverse(nmoat* NM_RESTRICT q4);
NM_API_DEF_EXT_INL nmoat* nm_QuatMulVec3(nmoat* NM_RESTRICT vOut3,const nmoat* NM_RESTRICT q4,const nmoat* NM_RESTRICT vIn3);
NM_API_DEF_EXT_INL nmoat* nm_QuatMulVec3Inv(nmoat* NM_RESTRICT vOut3,const nmoat* NM_RESTRICT q4,const nmoat* NM_RESTRICT vIn3);
NM_API_DEF_EXT_INL nmoat* nm_QuatFromAngleAxis(nmoat* NM_RESTRICT qOut4,nmoat rfAngle,nmoat rkAxisX,nmoat rkAxisY,nmoat rkAxisZ);
NM_API_DEF_EXT_INL nmoat* nm_QuatFromAngleAxisVec3(nmoat* NM_RESTRICT qOut4,nmoat rfAngle,const nmoat* NM_RESTRICT rkAxis3);
NM_API_DEF_EXT_INL void nm_QuatToAngleAxis(const nmoat* NM_RESTRICT q4,nmoat* NM_RESTRICT rfAngleOut1,nmoat* NM_RESTRICT rkAxisOut3);
NM_API_DEF_EXT_INL nmoat* nm_QuatRotateFromAxisAngle(nmoat* NM_RESTRICT q4,nmoat rfAngle,nmoat rkAxisX,nmoat rkAxisY,nmoat rkAxisZ);
NM_API_DEF_EXT_INL nmoat* nm_QuatRotateFromAxisAngleVec3(nmoat* NM_RESTRICT q4,nmoat rfAngle,const nmoat* NM_RESTRICT rkAxis3);
NM_API_DEF_EXT_INL nmoat* nm_QuatFromLookAtYX(nmoat* NM_RESTRICT qOut4,nmoat sourcePosX,nmoat sourcePosY,nmoat sourcePosZ,nmoat targetPosX,nmoat targetPosY,nmoat targetPosZ);
NM_API_DEF_EXT_INL nmoat* nm_QuatFromEuler(nmoat* NM_RESTRICT qOut4,nmoat fAngleX,nmoat fAngleY,nmoat fAngleZ,int eulerRotationMode);
NM_API_DEF_EXT_INL void nm_QuatGetAngularVelocity(nmoat* NM_RESTRICT angVel3,const nmoat* newQuat4,const nmoat* oldQuat4,nmoat halfTimeStep);
NM_API_DEF_EXT_INL void nm_QuatAdvance(nmoat* NM_RESTRICT qOut4,const nmoat* NM_RESTRICT q4,const nmoat* NM_RESTRICT angVel3,nmoat halfTimeStep);
NM_API_DEF_EXT_INL nmoat* nm_Mat3Copy(nmoat* NM_RESTRICT dst9,const nmoat* NM_RESTRICT src9);
NM_API_DEF_EXT_INL nmoat* nm_Mat3Identity(nmoat* NM_RESTRICT result9);
NM_API_DEF_EXT_INL nmoat* nm_Mat3Mul(nmoat* NM_RESTRICT result9,const nmoat* NM_RESTRICT ml9,const nmoat* NM_RESTRICT mr9);
NM_API_DEF_EXT_INL nmoat* nm_Mat3Mul_NoCheck(nmoat* NM_RESTRICT result9,const nmoat* NM_RESTRICT ml9,const nmoat* NM_RESTRICT mr9);
NM_API_DEF_EXT_INL nmoat* nm_Mat3Mul3(nmoat* NM_RESTRICT result9,const nmoat* NM_RESTRICT a9,const nmoat* NM_RESTRICT b9,const nmoat* NM_RESTRICT c9);
NM_API_DEF_EXT_INL nmoat* nm_Mat3Mul3_NoCheck(nmoat* NM_RESTRICT result9,const nmoat* NM_RESTRICT a9,const nmoat* NM_RESTRICT b9,const nmoat* NM_RESTRICT c9);
NM_API_DEF_EXT_INL nmoat* nm_QuatFromMat3(nmoat* NM_RESTRICT result4,const nmoat* NM_RESTRICT m9);
NM_API_DEF_EXT_INL nmoat* nm_Mat3FromQuat(nmoat* NM_RESTRICT result9,const nmoat* NM_RESTRICT q4);
NM_API_DEF_EXT_INL void nm_Mat3TransposeInPlace(nmoat* NM_RESTRICT m9);
NM_API_DEF_EXT_INL nmoat* nm_Mat3Transpose(nmoat* NM_RESTRICT mOut9,const nmoat* NM_RESTRICT m9);
NM_API_DEF_EXT_INL int nm_Mat3Invert(nmoat* NM_RESTRICT mOut9,const nmoat* NM_RESTRICT m9);
NM_API_DEF_EXT_INL int nm_Mat3InvertInPlace(nmoat* NM_RESTRICT m9);
NM_API_DEF_EXT_INL const nmoat* nm_Mat3SlerpEps(nmoat* NM_RESTRICT mOut9,const nmoat* NM_RESTRICT mStart9,const nmoat* NM_RESTRICT mEnd9,nmoat slerpTime_In_0_1,nmoat eps);
NM_API_DEF_EXT_INL const nmoat* nm_Mat3Slerp(nmoat* NM_RESTRICT mOut9,const nmoat* NM_RESTRICT mStart9,const nmoat* NM_RESTRICT mEnd9,nmoat slerpTime_In_0_1);
NM_API_DEF_EXT_INL nmoat* nm_Mat3FromEulerXYZ(nmoat* NM_RESTRICT m9,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL nmoat* nm_Mat3FromEulerXZY(nmoat* NM_RESTRICT m9,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL nmoat* nm_Mat3FromEulerYXZ(nmoat* NM_RESTRICT m9,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL nmoat* nm_Mat3FromEulerYZX(nmoat* NM_RESTRICT m9,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL nmoat* nm_Mat3FromEulerZXY(nmoat* NM_RESTRICT m9,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL nmoat* nm_Mat3FromEulerZYX(nmoat* NM_RESTRICT m9,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL int nm_Mat3ToEulerXYZ(const nmoat* NM_RESTRICT m9,nmoat* x,nmoat* y,nmoat* z);
NM_API_DEF_EXT_INL int nm_Mat3ToEulerXZY(const nmoat* NM_RESTRICT m9,nmoat* x,nmoat* y,nmoat* z);
NM_API_DEF_EXT_INL int nm_Mat3ToEulerYXZ(const nmoat* NM_RESTRICT m9,nmoat* x,nmoat* y,nmoat* z);
NM_API_DEF_EXT_INL int nm_Mat3ToEulerYZX(const nmoat* NM_RESTRICT m9,nmoat* x,nmoat* y,nmoat* z);
NM_API_DEF_EXT_INL int nm_Mat3ToEulerZXY(const nmoat* NM_RESTRICT m9,nmoat* x,nmoat* y,nmoat* z);
NM_API_DEF_EXT_INL int nm_Mat3ToEulerZYX(const nmoat* NM_RESTRICT m9,nmoat* x,nmoat* y,nmoat* z);
NM_API_DEF_EXT_INL void nm_Mat3FromEuler(nmoat* m9,nmoat x,nmoat y,nmoat z,int eulerRotationMode);
NM_API_DEF_EXT_INL int nm_Mat3ToEuler(const nmoat* m9,nmoat* x,nmoat* y,nmoat* z,int eulerRotationMode);
NM_API_DEF_EXT_INL nmoat* nm_Mat4Copy(nmoat* NM_RESTRICT dst16,const nmoat* NM_RESTRICT src16);
NM_API_DEF_EXT_INL nmoat* nm_Mat4Identity(nmoat* NM_RESTRICT result16);
NM_API_DEF_EXT_INL nmoat* nm_Mat4Mul(nmoat* NM_RESTRICT result16,const nmoat* NM_RESTRICT ml16,const nmoat* NM_RESTRICT mr16);
NM_API_DEF_EXT_INL nmoat* nm_Mat4Mul_NoCheck(nmoat* NM_RESTRICT result16,const nmoat* NM_RESTRICT ml16,const nmoat* NM_RESTRICT mr16);
/*NM_API_DEF_EXT_INL nmoat* nm_Mat4RotateByMat4_NoCheck(nmoat* NM_RESTRICT result16,const nmoat* NM_RESTRICT ml16,const nmoat* NM_RESTRICT mr16);
NM_API_DEF_EXT_INL nmoat* nm_Mat4RotateByMat4(nmoat* NM_RESTRICT result16,const nmoat* NM_RESTRICT ml16,const nmoat* NM_RESTRICT mr16);*/
NM_API_DEF_EXT_INL void nm_Mat4LookAt(nmoat* NM_RESTRICT mOut16,nmoat eyeX,nmoat eyeY,nmoat eyeZ,nmoat centerX,nmoat centerY,nmoat centerZ,nmoat upX,nmoat upY,nmoat upZ);
NM_API_DEF_EXT_INL void nm_Mat4Perspective(nmoat* NM_RESTRICT mOut16,nmoat degfovy,nmoat aspect, nmoat zNear, nmoat zFar);
NM_API_DEF_EXT_INL void nm_Mat4Ortho(nmoat* NM_RESTRICT mOut16,nmoat left,nmoat right, nmoat bottom, nmoat top,nmoat nearVal,nmoat farVal);
NM_API_DEF_EXT_INL void nm_Mat4Ortho3D(nmoat* NM_RESTRICT mOut16,nmoat cameraTargetDistance,nmoat degfovy,nmoat aspect,nmoat znear,nmoat zfar);
NM_API_DEF_EXT_INL int nm_Mat4Project(nmoat objX,nmoat objY,nmoat objZ,const nmoat* NM_RESTRICT mvMatrix16,const nmoat* NM_RESTRICT pMatrix16,const int* viewport4,nmoat* NM_RESTRICT winX,nmoat* NM_RESTRICT winY,nmoat* NM_RESTRICT winZ);
NM_API_DEF_EXT_INL int nm_Mat4UnProjectMvpInv(nmoat winX,nmoat winY,nmoat winZ,const nmoat* NM_RESTRICT mvpMatrixInv16,const int* viewport4,nmoat* NM_RESTRICT objX,nmoat* NM_RESTRICT objY,nmoat* NM_RESTRICT objZ);
NM_API_DEF_EXT_INL int nm_Mat4UnProject(nmoat winX,nmoat winY,nmoat winZ,const nmoat* NM_RESTRICT mvMatrix16, const nmoat* NM_RESTRICT pMatrix16, const int* viewport4,nmoat* NM_RESTRICT objX,nmoat* NM_RESTRICT objY,nmoat* NM_RESTRICT objZ);
NM_API_DEF_EXT_INL int nm_Mat4UnProject4MvpInv(nmoat winX,nmoat winY,nmoat winZ,nmoat clipW,const nmoat* NM_RESTRICT mvpMatrixInv16,const int* viewport4,nmoat nearVal,nmoat farVal,nmoat* NM_RESTRICT objX,nmoat* NM_RESTRICT objY,nmoat* NM_RESTRICT objZ,nmoat* NM_RESTRICT objW);
NM_API_DEF_EXT_INL int nm_Mat4UnProject4(nmoat winX, nmoat winY, nmoat winZ, nmoat clipW, const nmoat* NM_RESTRICT mvMatrix16, const nmoat* NM_RESTRICT pMatrix16, const int* viewport4, nmoat nearVal, nmoat farVal, nmoat* NM_RESTRICT objX, nmoat* NM_RESTRICT objY, nmoat* NM_RESTRICT objZ, nmoat* NM_RESTRICT objW);
NM_API_DEF_EXT_INL void nm_Mat4UnProjectMouseCoords(nmoat* NM_RESTRICT rayOriginOut3,nmoat* NM_RESTRICT rayDirOut3,int mouseX,int mouseY,const nmoat* NM_RESTRICT vpMatrixInv,const int* viewport4);
NM_API_DEF_EXT_INL int nm_Mat4GetMeshUnderMouseFromRay(int numMeshes,void (*getMeshDataCallback)(int idx,nmoat* mMatrix16InOut,nmoat aabbMinOut[3],nmoat aabbMaxOut[3],void* userData),const nmoat* rayOrigin3,const nmoat* rayDir3,nmoat* pOptionalDistanceOut,void* userData);
NM_API_DEF_EXT_INL void nm_Mat4ExtractScalingFromTransformMatrix(const nmoat* NM_RESTRICT m16,nmoat* NM_RESTRICT scaOut3,nmoat* NM_RESTRICT optionalMOut16);
NM_API_DEF_EXT_INL nmoat* nm_Mat4PickMatrix(nmoat* NM_RESTRICT mOut16,nmoat x,nmoat y,nmoat width,nmoat height,const int* viewport4); // similar to old: glLoadIdentity();gluPickMatrix(x,y,width,height,viewport); [plus glGet(...matrixmode...) to return the matrix]. As usual, return value is the same as mOut16 (for chaining usage).
NM_API_DEF_EXT_INL nmoat* nm_Mat4Translate(nmoat* NM_RESTRICT mInOut16,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL nmoat* nm_Mat4Rotate(nmoat* NM_RESTRICT mInOut16,nmoat degAngle,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL nmoat* nm_Mat4Scale(nmoat* NM_RESTRICT mInOut16,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL void nm_Mat4TransposeInPlace(nmoat* NM_RESTRICT m16);
NM_API_DEF_EXT_INL nmoat* nm_Mat4Transpose(nmoat* NM_RESTRICT mOut16,const nmoat* NM_RESTRICT m16);
NM_API_DEF_EXT_INL int nm_Mat4Invert(nmoat* NM_RESTRICT mOut16,const nmoat* NM_RESTRICT m16);
NM_API_DEF_EXT_INL int nm_Mat4InvertInPlace(nmoat* NM_RESTRICT m16);
NM_API_DEF_EXT_INL nmoat* nm_Mat4InvertTransformMatrixWithoutScaling(nmoat* NM_RESTRICT mOut16,const nmoat* NM_RESTRICT m16);
NM_API_DEF_EXT_INL nmoat* nm_Mat4InvertTransformMatrix(nmoat* NM_RESTRICT mOut16,const nmoat* NM_RESTRICT m16);
NM_API_DEF_EXT_INL void nm_Mat4InvertXZAxisInPlace(nmoat* NM_RESTRICT m16);
NM_API_DEF_EXT_INL nmoat* nm_Mat4InvertXZAxis(nmoat* NM_RESTRICT mOut16,const nmoat* NM_RESTRICT m16);
NM_API_DEF_EXT_INL void nm_Mat4MulDir(const nmoat* NM_RESTRICT m16,nmoat* NM_RESTRICT dirOut3,const nmoat dirX,nmoat dirY,nmoat dirZ);
/*NM_API_DEF_EXT_INL void nm_Mat4MulDirWithWDivision(const nmoat* NM_RESTRICT m16,nmoat* NM_RESTRICT dirOut3,const nmoat dirX,nmoat dirY,nmoat dirZ);*/
NM_API_DEF_EXT_INL void nm_Mat4MulPos(const nmoat* NM_RESTRICT m16,nmoat* NM_RESTRICT posOut3,const nmoat posX,nmoat posY,nmoat posZ);
NM_API_DEF_EXT_INL void nm_Mat4MulPosWithWDivision(const nmoat* NM_RESTRICT m16,nmoat* NM_RESTRICT posOut3,const nmoat posX,nmoat posY,nmoat posZ);
NM_API_DEF_EXT_INL int nm_AreMat4EqualEps(const nmoat* NM_RESTRICT a16,const nmoat* NM_RESTRICT b16,nmoat eps);
NM_API_DEF_EXT_INL int nm_AreMat4Equal(const nmoat* NM_RESTRICT a16,const nmoat* NM_RESTRICT b16);
NM_API_DEF_EXT_INL nmoat* nm_QuatFromMat4(nmoat* NM_RESTRICT result4,const nmoat* NM_RESTRICT m16);
NM_API_DEF_EXT_INL nmoat* nm_Mat4SetRotationFromQuat(nmoat* NM_RESTRICT result16,const nmoat* NM_RESTRICT q4);
NM_API_DEF_EXT_INL nmoat* nm_Mat3GetFromMat4(nmoat* NM_RESTRICT dst9,const nmoat* NM_RESTRICT src16);
NM_API_DEF_EXT_INL void nm_Mat4SetRotationFromMat3(nmoat* NM_RESTRICT dst16,const nmoat* NM_RESTRICT src9);
NM_API_DEF_EXT_INL const nmoat* nm_Mat4FromMRotScaTra(nmoat* NM_RESTRICT dst16,const nmoat* NM_RESTRICT rot9,nmoat scaX,nmoat scaY,nmoat scaZ,nmoat traX,nmoat traY,nmoat traZ);
NM_API_DEF_EXT_INL const nmoat* nm_Mat4FromQRotScaTra(nmoat* NM_RESTRICT dst16,const nmoat* NM_RESTRICT rot4,nmoat scaX,nmoat scaY,nmoat scaZ,nmoat traX,nmoat traY,nmoat traZ);
NM_API_DEF_EXT_INL const nmoat* nm_Mat4SlerpEps(nmoat* NM_RESTRICT mOut16,const nmoat* NM_RESTRICT mStart16,const nmoat* NM_RESTRICT mEnd16,nmoat slerpTime_In_0_1,nmoat eps);
NM_API_DEF_EXT_INL const nmoat* nm_Mat4Slerp(nmoat* NM_RESTRICT mOut16,const nmoat* NM_RESTRICT mStart16,const nmoat* NM_RESTRICT mEnd16,nmoat slerpTime_In_0_1);
NM_API_DEF_EXT_INL nmoat* nm_Mat4Mul3(nmoat* NM_RESTRICT result16,const nmoat* NM_RESTRICT a16,const nmoat* NM_RESTRICT b16,const nmoat* NM_RESTRICT c16);
NM_API_DEF_EXT_INL nmoat* nm_Mat4Mul3_NoCheck(nmoat* NM_RESTRICT result16,const nmoat* NM_RESTRICT a16,const nmoat* NM_RESTRICT b16,const nmoat* NM_RESTRICT c16);
NM_API_DEF_EXT_INL nmoat* nm_Mat4FromEulerXYZ(nmoat* NM_RESTRICT m16,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL nmoat* nm_Mat4FromEulerXZY(nmoat* NM_RESTRICT m16,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL nmoat* nm_Mat4FromEulerYXZ(nmoat* NM_RESTRICT m16,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL nmoat* nm_Mat4FromEulerYZX(nmoat* NM_RESTRICT m16,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL nmoat* nm_Mat4FromEulerZXY(nmoat* NM_RESTRICT m16,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL nmoat* nm_Mat4FromEulerZYX(nmoat* NM_RESTRICT m16,nmoat x,nmoat y,nmoat z);
NM_API_DEF_EXT_INL int nm_Mat4ToEulerXYZ(const nmoat* NM_RESTRICT m16,nmoat* x,nmoat* y,nmoat* z);
NM_API_DEF_EXT_INL int nm_Mat4ToEulerXZY(const nmoat* NM_RESTRICT m16,nmoat* x,nmoat* y,nmoat* z);
NM_API_DEF_EXT_INL int nm_Mat4ToEulerYXZ(const nmoat* NM_RESTRICT m16,nmoat* x,nmoat* y,nmoat* z);
NM_API_DEF_EXT_INL int nm_Mat4ToEulerYZX(const nmoat* NM_RESTRICT m16,nmoat* x,nmoat* y,nmoat* z);
NM_API_DEF_EXT_INL int nm_Mat4ToEulerZXY(const nmoat* NM_RESTRICT m16,nmoat* x,nmoat* y,nmoat* z);
NM_API_DEF_EXT_INL int nm_Mat4ToEulerZYX(const nmoat* NM_RESTRICT m16,nmoat* x,nmoat* y,nmoat* z);
NM_API_DEF_EXT_INL void nm_Mat4FromEuler(nmoat* m16,nmoat x,nmoat y,nmoat z,int eulerRotationMode);
NM_API_DEF_EXT_INL int nm_Mat4ToEuler(const nmoat* m16,nmoat* x,nmoat* y,nmoat* z,int eulerRotationMode);
NM_API_DEF_EXT_INL const nmoat* nm_Mat4LookAtYX(nmoat* NM_RESTRICT mInOut16,nmoat lookAtX,nmoat lookAtY,nmoat lookAtZ,nmoat minDistanceAllowed/*=0*/,nmoat maxDistanceAllowed/*=0*/,nmoat pitchLimit/* = 1.483486111*/);
NM_API_DEF_EXT_INL const nmoat* nm_Mat4LookAtYX2D(nmoat* NM_RESTRICT mInOut16,nmoat lookAtX,nmoat lookAtZ,nmoat minDistanceAllowed/*=0*/,nmoat maxDistanceAllowed/*=0*/,nmoat pitchLimit/* = 1.483486111*/);
NM_API_DEF_EXT_INL int nm_AreMat3EqualEps(const nmoat* NM_RESTRICT a9,const nmoat* NM_RESTRICT b9,nmoat eps);
NM_API_DEF_EXT_INL int nm_AreMat3Equal(const nmoat* NM_RESTRICT a9,const nmoat* NM_RESTRICT b9);
NM_API_DEF_EXT_INL int nm_AreQuatEqualEps(const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4,nmoat eps);
NM_API_DEF_EXT_INL int nm_AreQuatEqual(const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4);
NM_API_DEF_EXT_INL int nm_AreVec4EqualEps(const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4,nmoat eps);
NM_API_DEF_EXT_INL int nm_AreVec4Equal(const nmoat* NM_RESTRICT a4,const nmoat* NM_RESTRICT b4);
NM_API_DEF_EXT_INL int nm_AreVec3EqualEps(const nmoat* NM_RESTRICT a3,const nmoat* NM_RESTRICT b3,nmoat eps);
NM_API_DEF_EXT_INL int nm_AreVec3Equal(const nmoat* NM_RESTRICT a3,const nmoat* NM_RESTRICT b3);
NM_API_DEF_EXT_INL int nm_AreVec2EqualEps(const nmoat* NM_RESTRICT a2,const nmoat* NM_RESTRICT b2,nmoat eps);
NM_API_DEF_EXT_INL int nm_AreVec2Equal(const nmoat* NM_RESTRICT a2,const nmoat* NM_RESTRICT b2);
NM_API_DEF_EXT_INL int nm_AreVec3EqualEps3(const nmoat* NM_RESTRICT a3,const nmoat* NM_RESTRICT b3,const nmoat* NM_RESTRICT eps3);
NM_API_DEF_EXT_INL int nm_AreVec3EqualEpsRadius(const nmoat* NM_RESTRICT a3,const nmoat* NM_RESTRICT b3,nmoat epsRadiusSquared);
NM_API_DEF_EXT_INL int nm_AreVec2EqualEps2(const nmoat* NM_RESTRICT a2,const nmoat* NM_RESTRICT b2,const nmoat* NM_RESTRICT eps2);
NM_API_DEF_EXT_INL int nm_AreVec2EqualEpsRadius(const nmoat* NM_RESTRICT a2,const nmoat* NM_RESTRICT b2,nmoat epsRadiusSquared);
#ifndef NM_NO_STDIO
NM_API_DEF_EXT_INL void nm_Vec2_fprintp(const nmoat* NM_RESTRICT v2,FILE* stream,int width, int precision);
NM_API_DEF_EXT_INL void nm_Vec2_fprint(const nmoat* NM_RESTRICT v2,FILE* stream);
NM_API_DEF_EXT_INL void nm_Vec2_printp(const nmoat* NM_RESTRICT v2,int width, int precision);
NM_API_DEF_EXT_INL void nm_Vec3_fprintp(const nmoat* NM_RESTRICT v3,FILE* stream,int width, int precision);
NM_API_DEF_EXT_INL void nm_Vec3_fprint(const nmoat* NM_RESTRICT v3,FILE* stream);
NM_API_DEF_EXT_INL void nm_Vec3_printp(const nmoat* NM_RESTRICT v3,int width, int precision);
NM_API_DEF_EXT_INL void nm_Vec3_print(const nmoat* NM_RESTRICT v3);
NM_API_DEF_EXT_INL void nm_Vec4_fprintp(const nmoat* NM_RESTRICT v4,FILE* stream,int width, int precision);
NM_API_DEF_EXT_INL void nm_Vec4_fprint(const nmoat* NM_RESTRICT v4,FILE* stream);
NM_API_DEF_EXT_INL void nm_Vec4_printp(const nmoat* NM_RESTRICT v4,int width, int precision);
NM_API_DEF_EXT_INL void nm_Vec4_print(const nmoat* NM_RESTRICT v4);
NM_API_DEF_EXT_INL void nm_Quat_fprintp(const nmoat* NM_RESTRICT q4,FILE* stream,int width, int precision);
NM_API_DEF_EXT_INL void nm_Quat_fprint(const nmoat* NM_RESTRICT q4,FILE* stream);
NM_API_DEF_EXT_INL void nm_Quat_printp(const nmoat* NM_RESTRICT q4,int width, int precision);
NM_API_DEF_EXT_INL void nm_Quat_print(const nmoat* NM_RESTRICT q4);
NM_API_DEF_EXT_INL void nm_Mat3_fprintp(const nmoat* NM_RESTRICT m9,FILE* stream,int width, int precision);
NM_API_DEF_EXT_INL void nm_Mat3_fprint(const nmoat* NM_RESTRICT m9,FILE* stream);
NM_API_DEF_EXT_INL void nm_Mat3_printp(const nmoat* NM_RESTRICT m9,int width, int precision);
NM_API_DEF_EXT_INL void nm_Mat3_print(const nmoat* NM_RESTRICT m9);
NM_API_DEF_EXT_INL void nm_Mat4_fprintp(const nmoat* NM_RESTRICT m16,FILE* stream,int width, int precision);
NM_API_DEF_EXT_INL void nm_Mat4_fprint(const nmoat* NM_RESTRICT m16,FILE* stream);
NM_API_DEF_EXT_INL void nm_Mat4_printp(const nmoat* NM_RESTRICT m16,int width, int precision);
NM_API_DEF_EXT_INL void nm_Mat4_print(const nmoat* NM_RESTRICT m16);
#endif //NM_NO_STDIO
NM_API_DEF_EXT_INL void nm_PlaneNormalize(nmoat* NM_RESTRICT p4);
NM_API_DEF_EXT_INL nmoat nm_PlanePointDistance(const nmoat* NM_RESTRICT plane4,const nmoat* NM_RESTRICT pt3);
// returns the frustum radius (by value) and the scalar (positive) distance from the the camera eye to the frustum center (by 'pFrustumCenterDistanceOut').
// 'cameraTargetDistanceForUnstableOrtho3DModeOnly_or_zero': the arg name is correct when the result is passed to 'nm_GetLightViewProjectionMatrix' functions.
// Otherwise simply set it when using an ortho3D camera frustum (that needs a camera-target distance), or just set it to zero.
NM_API_DEF_EXT_INL nmoat nm_GetFrustumRadiusAndCenterDistance(nmoat* NM_RESTRICT pFrustumCenterDistanceOut,nmoat cameraNearClippingPlane,nmoat cameraFarClippingPlane,nmoat cameraFovyDeg,nmoat cameraAspectRatio,nmoat cameraTargetDistanceForUnstableOrtho3DModeOnly_or_zero);
// 'frustumCenterOut3' is in world space (mandatory arg).
// 'cameraVMatrixInverse16' must be orthonormal (no scaling).
NM_API_DEF_EXT_INL void nm_GetFrustumCenterFromCenterDistance(nmoat* NM_RESTRICT frustumCenterOut3,const nmoat* NM_RESTRICT cameraVMatrixInverse16,nmoat frustumCenterDistance);
// 'optionalPMatrixInverse16' is required only if you need to retrieve (one or more of) the arguments that follow them (otherwise their value is untouched).
// 'normalizedLightDirection3' must be in world space.
NM_API_DEF_EXT_INL void nm_GetLightViewProjectionMatrixExtra(nmoat* NM_RESTRICT lvpMatrixOut16
,const nmoat* NM_RESTRICT cameraVMatrixInverse16,const nmoat* NM_RESTRICT cameraFrustumCenterInWorldSpace,nmoat cameraFrustumRadius
,const nmoat* NM_RESTRICT normalizedLightDirection3,unsigned short shadowMapWidth,unsigned short shadowMapHeight
,const nmoat* NM_RESTRICT optionalCameraPMatrixInverse16
,nmoat* NM_RESTRICT optionalLightViewportClippingOut4,nmoat optionalCameraFrustumPointsInNDCLightSpaceOut[8][4]
,nmoat* NM_RESTRICT optionalLVPMatrixForFrustumCullingUsageOut16 // Highly experimental and untested
);
// 'normalizedLightDirection3' must be in world space.
NM_API_DEF_EXT_INL void nm_GetLightViewProjectionMatrix(nmoat* NM_RESTRICT lvpMatrixOut16
,const nmoat* NM_RESTRICT cameraVMatrixInverse16,const nmoat* NM_RESTRICT cameraFrustumCenterInWorldSpace,nmoat cameraFrustumRadius
,const nmoat* NM_RESTRICT normalizedLightDirection3,unsigned short shadowMapWidth,unsigned short shadowMapHeight);
NM_API_DEF_EXT_INL void nm_GetFrustumPlaneEquations(nmoat planeEquationsOut[6][4],const nmoat* NM_RESTRICT vpMatrix16,int normalizePlanes);
NM_API_DEF_EXT_INL int nm_FrustumOBBVisibilityTest(const nmoat frustumPlanes[6][4],const nmoat* NM_RESTRICT mfMatrix16,nmoat aabbMinX,nmoat aabbMinY,nmoat aabbMinZ,nmoat aabbMaxX,nmoat aabbMaxY,nmoat aabbMaxZ);
NM_API_DEF_EXT_INL int nm_FrustumBSVisibilityTest(const nmoat normalizedFrustumPlanes[6][4],const nmoat* NM_RESTRICT mfMatrix16,nmoat bsCenterX,nmoat bsCenterY,nmoat bsCenterZ,nmoat bsRadius,const nmoat* NM_RESTRICT optionalFrustumCenterInMfSpace3,nmoat optionalFrustumRadius);
NM_API_DEF_EXT_INL int nm_IsAabbVisible(const nmoat normalizedFrustumPlanes[6][4],const nmoat* NM_RESTRICT mfMatrix16,const nmoat* NM_RESTRICT aabbMin3,const nmoat* NM_RESTRICT aabbMax3,nmoat aabbRadius,nmoat scalingX,nmoat scalingY,nmoat scalingZ,const nmoat* NM_RESTRICT optionalFrustumCenterInMfSpace3,nmoat optionalFrustumRadius);
// 1-dimensional DFT (and its inverse) when 'size_pot' is a power of two, and 2^('log2size')='size_pot'.
// 'inverse_transform' and 'dont_scale_inverse_transform_like_fftw3_does' are boolean values.
NM_API_DEF_EXT_INL void nm_DiscreteFourierTransform1D(nmoat out[][2],const nmoat in[][2],int size_pot,int log2size,int inverse_transform,int dont_scale_inverse_transform_like_fftw3_does);
// These two function used to be implementation-private, and are now exposed (TODO: find out what they do and document them)
NM_API_DEF_EXT_INL void nm_GetFrustumPoints(nmoat frustumPoints[8][4],const nmoat* NM_RESTRICT vpMatrixInverse16);
NM_API_DEF_EXT_INL void nm_GetFrustumAabbCenterAndHalfExtents(nmoat* NM_RESTRICT frustumCenterOut3,nmoat* NM_RESTRICT frustumHalfExtentsOut3,const nmoat frustumPoints[8][4]);
// these defs starts at 1 to match an enum order used by Blender
// (note that when NM_NO_MATH_STRUCTS is defined, enum EulerRotationMode is not present)
#define NM_EULER_XYZ 1
#define NM_EULER_XZY 2
#define NM_EULER_YXZ 3
#define NM_EULER_YZX 4
#define NM_EULER_ZXY 5
#define NM_EULER_ZYX 6
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef NM_NAMESPACE
namespace NM_NAMESPACE {
#endif //NM_NAMESPACE
#ifndef NM_NO_MATH_STRUCTS
// Warning: enum starts at 1 to match an enum order used by Blender
enum EulerRotationMode {
EULER_XYZ = NM_EULER_XYZ, // 1
EULER_XZY = NM_EULER_XZY, // 2
EULER_YXZ = NM_EULER_YXZ, // 3
EULER_YZX = NM_EULER_YZX, // 4
EULER_ZXY = NM_EULER_ZXY, // 5
EULER_ZYX = NM_EULER_ZYX // 6
//AXIS_ANGLE = -1 // (these are used by Blender too)
//QUATERNION_WXYZ = 0
};
typedef enum EulerRotationMode EulerRotationMode;
NM_API_DEF_EXT_INL nmoat radians(nmoat deg);
NM_API_DEF_EXT_INL nmoat degrees(nmoat rad);
// ---------------
// vec2 definition
// ---------------
#ifdef NM_NO_CPP_CTRS
# ifndef NM_NO_C_INITIALIZATION
# define NM_RETURN_VEC2_CTR(X,Y) return (vec2){{{(X),(Y)}}};
# else //NM_NO_C_INITIALIZATION
# define NM_RETURN_VEC2_CTR(X,Y) {vec2 r;r.x=X;r.y=Y;return r;}
# endif //NM_NO_C_INITIALIZATION
#else
# define NM_RETURN_VEC2_CTR(X,Y) return vec2(X,Y);
#endif
NM_PRE_ALIGN_DEFAULT struct vec2 {
// if we had to use alignas(...), we should have put it here (AFAIK it's the same)
union {
struct {nmoat x,y;};
nmoat e[2];
};
# ifdef __cplusplus
# ifndef NM_NO_CPP_CTRS
NM_API_INL vec2() : x(0),y(0) {}
NM_API_INL vec2(nmoat v) : x(v),y(v) {}
NM_API_INL vec2(nmoat _x,nmoat _y) : x(_x),y(_y) {}
NM_API_INL vec2(const vec2& o) : x(o.x),y(o.y) {}
# endif //NM_NO_CPP_CTRS
# ifndef NM_NO_STDIO
void fprintp(FILE* stream,int width, int precision) const;
void fprint(FILE* stream) const;
void printp(int width, int precision) const;
void print() const;
# endif //NM_NO_STDIO
//NM_API_INL nmoat operator[](int i) const {NM_ASSERT(i>=0 && i<2);return *(((nmoat*)&x)+i);}
//NM_API_INL nmoat& operator[](int i) {NM_ASSERT(i>=0 && i<2);return *(((nmoat*)&x)+i);}
NM_API_INL const nmoat& operator[](int i) const {NM_ASSERT(i>=0 && i<2);return e[i];}
NM_API_INL nmoat& operator[](int i) {NM_ASSERT(i>=0 && i<2);return e[i];}
NM_API_INL const vec2& operator=(const vec2& o) {x=o.x;y=o.y;return *this;}
NM_API_INL const vec2& operator=(nmoat s) {x=s;y=s;return *this;}
NM_API_INL vec2 operator+(const vec2& o) const {NM_RETURN_VEC2_CTR(x+o.x,y+o.y)}
NM_API_INL void operator+=(const vec2& o) {x+=o.x;y+=o.y;}
NM_API_INL vec2 operator+(nmoat s) const {NM_RETURN_VEC2_CTR(x+s,y+s)}
NM_API_INL void operator+=(nmoat s) {x+=s;y+=s;}
NM_API_INL vec2 operator-(const vec2& o) const {NM_RETURN_VEC2_CTR(x-o.x,y-o.y)}
NM_API_INL void operator-=(const vec2& o) {x-=o.x;y-=o.y;}
NM_API_INL vec2 operator-(nmoat s) const {NM_RETURN_VEC2_CTR(x-s,y-s)}
NM_API_INL void operator-=(nmoat s) {x-=s;y-=s;}
NM_API_INL vec2 operator-() const {NM_RETURN_VEC2_CTR(-x,-y)}
NM_API_INL vec2 operator*(const vec2& o) const {NM_RETURN_VEC2_CTR(x*o.x,y*o.y)}
NM_API_INL void operator*=(const vec2& o) {x*=o.x;y*=o.y;}
NM_API_INL vec2 operator*(nmoat s) const {NM_RETURN_VEC2_CTR(x*s,y*s)}
NM_API_INL void operator*=(nmoat s) {x*=s;y*=s;}
NM_API_INL vec2 operator/(const vec2& o) const {NM_RETURN_VEC2_CTR(x/o.x,y/o.y)}
NM_API_INL void operator/=(const vec2& o) {x/=o.x;y/=o.y;}
NM_API_INL vec2 operator/(nmoat s) const {NM_RETURN_VEC2_CTR(x/s,y/s)}
NM_API_INL void operator/=(nmoat s) {x/=s;y/=s;}
NM_API_INL nmoat dot(const vec2& o) const {return x*o.x+y*o.y;}
NM_API_INL nmoat length2() const {return x*x+y*y;}
NM_API_INL nmoat length() const {return nmh_sqrt(x*x+y*y);}
NM_API_INL void normalize() {const nmoat len=length();if (len>0) {x/=len;y/=len;} else {x=y=(nmoat)0;}}
NM_API_INL vec2 normalized() const {const nmoat len=length();if (len>0) NM_RETURN_VEC2_CTR(x/len,y/len) else NM_RETURN_VEC2_CTR(0,0)}
NM_API_INL vec2 lerp(const vec2& o,nmoat t) const {nmoat ct = (nmoat)1-t;NM_RETURN_VEC2_CTR(x*ct+o.x*t,y*ct+o.y*t)}
NM_API_INL vec2 proj(const vec2& onto) const {return onto*this->dot(onto)/onto.dot(onto);}
NM_API_INL nmoat angle_between(const vec2& o) const {return nmh_acos(this->dot(o)/(this->length()*o.length()));}
# endif //__cplusplus
} NM_POST_ALIGN_DEFAULT;
#ifndef __cplusplus
typedef struct vec2 vec2;
#endif
NM_API_DEF_INL vec2 make_vec2(nmoat _x, nmoat _y) {NM_RETURN_VEC2_CTR(_x,_y)}
#ifndef NM_NO_STDIO
NM_API_DEF_EXT_INL void vec2_fprintp(const vec2* v2,FILE* stream,int width, int precision);
NM_API_DEF_EXT_INL void vec2_fprint(const vec2* v2,FILE* stream);
NM_API_DEF_EXT_INL void vec2_printp(const vec2* v2,int width, int precision);
NM_API_DEF_EXT_INL void vec2_print(const vec2* v2);
#ifdef __cplusplus
NM_API_INL void vec2::fprintp(FILE* stream,int width, int precision) const {vec2_fprintp(this,stream,width,precision);}
NM_API_INL void vec2::fprint(FILE* stream) const {vec2_fprint(this,stream);}
NM_API_INL void vec2::printp(int width, int precision) const {vec2_printp(this,width,precision);}
NM_API_INL void vec2::print() const {vec2_print(this);}
#endif //__cplusplus
#endif //NM_NO_STDIO
//NM_API_DEF_EXT_INL vec2 vec2_copy(const vec2* src);
NM_API_DEF_EXT_INL vec2 vec2_add(const vec2* a,const vec2* b);
NM_API_DEF_EXT_INL vec2 vec2_sub(const vec2* a,const vec2* b);
NM_API_DEF_EXT_INL vec2 vec2_neg(const vec2* src);
NM_API_DEF_EXT_INL vec2 vec2_mul(const vec2* a,const vec2* b);
NM_API_DEF_EXT_INL vec2 vec2_mulsca(const vec2* src,nmoat f);
NM_API_DEF_EXT_INL vec2 vec2_div(const vec2* a,const vec2* b);
NM_API_DEF_EXT_INL vec2 vec2_divsca(const vec2* src,nmoat f);
NM_API_DEF_EXT_INL const vec2* vec2_sadd(vec2* dst,const vec2* src);
NM_API_DEF_EXT_INL const vec2* vec2_ssub(vec2* dst,const vec2* src);
NM_API_DEF_EXT_INL const vec2* vec2_inv(vec2* dst);
NM_API_DEF_EXT_INL const vec2* vec2_smul(vec2* dst,const vec2* src);
NM_API_DEF_EXT_INL const vec2* vec2_smulsca(vec2* dst,nmoat f);
NM_API_DEF_EXT_INL const vec2* vec2_sdiv(vec2* dst,const vec2* src);
NM_API_DEF_EXT_INL const vec2* vec2_sdivsca(vec2* dst,nmoat f);
NM_API_DEF_EXT_INL nmoat vec2_dot(const vec2* a,const vec2* b);
NM_API_DEF_EXT_INL nmoat vec2_length2(const vec2* a);
NM_API_DEF_EXT_INL nmoat vec2_length(const vec2* a);
NM_API_DEF_EXT_INL const vec2* vec2_normalize(vec2* dst);
NM_API_DEF_EXT_INL vec2 vec2_normalized(const vec2* src);
NM_API_DEF_EXT_INL vec2 vec2_lerp(const vec2* a,const vec2* b,nmoat t);
NM_API_DEF_EXT_INL vec2 vec2_proj(const vec2* src,const vec2* onto);
NM_API_DEF_EXT_INL nmoat vec2_angle_between(const vec2* a,const vec2* b);
NM_API_DEF_EXT_INL int vec2_areequaleps(const vec2* a,const vec2* b,nmoat eps);
NM_API_DEF_EXT_INL int vec2_areequal(const vec2* a,const vec2* b);
// ---------------
// vec3 definition
// ---------------
#ifdef NM_NO_CPP_CTRS
# ifndef NM_NO_C_INITIALIZATION
# define NM_RETURN_VEC3_CTR(X,Y,Z) return (vec3){{{(X),(Y),(Z)}}};
# else //NM_NO_C_INITIALIZATION
# define NM_RETURN_VEC3_CTR(X,Y,Z) {vec3 r;r.x=X;r.y=Y;r.z=Z;return r;}
# endif //NM_NO_C_INITIALIZATION
#else
# define NM_RETURN_VEC3_CTR(X,Y,Z) return vec3(X,Y,Z);
#endif
#undef NM_VEC3_MUST_BE_POD
#undef NM_QUERY_MAT3_VEC3_AXIS_VECTORS
#undef NM_QUERY_MAT4_VEC3_AXIS_VECTORS
#if (defined(NM_NO_CPP_CTRS) || defined(NM_COMPILER_SUPPORTS_NONPOD_ANONYMOUS_MEMBERS))
# ifndef NM_NO_AXIS_VECTORS_IN_STRUCT_MAT3
# define NM_QUERY_MAT3_VEC3_AXIS_VECTORS
# endif //NM_NO_AXIS_VECTORS_IN_STRUCT_MAT3
# if (!defined(NM_NO_AXIS_VECTORS_IN_STRUCT_MAT4) && !defined(NM_AXIS_VEC4_IN_STRUCT_MAT4))
# define NM_QUERY_MAT4_VEC3_AXIS_VECTORS
# endif
#endif
#if (defined(NM_QUERY_MAT3_VEC3_AXIS_VECTORS) || defined(NM_QUERY_MAT4_VEC3_AXIS_VECTORS))
# define NM_VEC3_MUST_BE_POD
#endif
NM_PRE_ALIGN_DEFAULT struct vec3 {
union {
struct {nmoat x,y,z;};
nmoat e[3];
};
# ifdef __cplusplus
# ifndef NM_NO_CPP_CTRS
NM_API_INL vec3() : x(0),y(0),z(0) {}
NM_API_INL vec3(nmoat v) : x(v),y(v),z(v) {}
NM_API_INL vec3(nmoat _x,nmoat _y,nmoat _z) : x(_x),y(_y),z(_z) {}
NM_API_INL vec3(const vec2& o,nmoat _z=(nmoat)0) : x(o.x),y(o.y),z(_z) {}
NM_API_INL vec3(const vec3& o) : x(o.x),y(o.y),z(o.z) {}
# endif //NM_NO_CPP_CTRS
# if (!defined(NM_NO_CPP_CTRS) || !defined(NM_VEC3_MUST_BE_POD))
// These are placed inside the def block, because, in some (rare) cases,
// vec3 can be used inside an anonymous sub-member in mat3 or mat4 (and it must be POD)
NM_API_INL const vec3& operator=(const vec3& o) {x=o.x;y=o.y;z=o.z;return *this;}
NM_API_INL const vec3& operator=(const vec2& o) {x=o.x;y=o.y;return *this;}
NM_API_INL const vec3& operator=(nmoat s) {x=y=z=s;return *this;}
# endif // !NM_NO_CPP_CTRS || !NM_VEC3_MUST_BE_POD
# ifndef NM_NO_STDIO
void fprintp(FILE* stream,int width, int precision) const;
void fprint(FILE* stream) const;
void printp(int width, int precision) const;
void print() const;
# endif //NM_NO_STDIO
NM_API_INL const nmoat& operator[](int i) const {NM_ASSERT(i>=0 && i<3);return e[i];}
NM_API_INL nmoat& operator[](int i) {NM_ASSERT(i>=0 && i<3);return e[i];}
NM_API_INL vec3 operator+(const vec3& o) const {NM_RETURN_VEC3_CTR(x+o.x,y+o.y,z+o.z)}
NM_API_INL void operator+=(const vec3& o) {x+=o.x;y+=o.y;z+=o.z;}
NM_API_INL vec3 operator+(nmoat s) const {NM_RETURN_VEC3_CTR(x+s,y+s,z+s)}
NM_API_INL void operator+=(nmoat s) {x+=s;y+=s;z+=s;}
NM_API_INL vec3 operator-(const vec3& o) const {NM_RETURN_VEC3_CTR(x-o.x,y-o.y,z-o.z)}
NM_API_INL void operator-=(const vec3& o) {x-=o.x;y-=o.y;z-=o.z;}
NM_API_INL vec3 operator-(nmoat s) const {NM_RETURN_VEC3_CTR(x-s,y-s,z-s)}
NM_API_INL void operator-=(nmoat s) {x-=s;y-=s;z-=s;}
NM_API_INL vec3 operator-() const {NM_RETURN_VEC3_CTR(-x,-y,-z)}
NM_API_INL vec3 operator*(const vec3& o) const {NM_RETURN_VEC3_CTR(x*o.x,y*o.y,z*o.z)}
NM_API_INL void operator*=(const vec3& o) {x*=o.x;y*=o.y;z*=o.z;}
NM_API_INL vec3 operator*(nmoat s) const {NM_RETURN_VEC3_CTR(x*s,y*s,z*s)}
NM_API_INL void operator*=(nmoat s) {x*=s;y*=s;z*=s;}
NM_API_INL vec3 operator/(const vec3& o) const {NM_RETURN_VEC3_CTR(x/o.x,y/o.y,z/o.z)}
NM_API_INL void operator/=(const vec3& o) {x/=o.x;y/=o.y;z/=o.z;}
NM_API_INL vec3 operator/(nmoat s) const {NM_RETURN_VEC3_CTR(x/s,y/s,z/s)}
NM_API_INL void operator/=(nmoat s) {x/=s;y/=s;z/=s;}
NM_API_INL nmoat dot(const vec3& o) const {return x*o.x+y*o.y+z*o.z;}
NM_API_INL vec3 cross(const vec3& o) const {NM_RETURN_VEC3_CTR(y*o.z-z*o.y,z*o.x-x*o.z,x*o.y-y*o.x)}
NM_API_INL nmoat length2() const {return x*x+y*y+z*z;}
NM_API_INL nmoat length() const {return nmh_sqrt(x*x+y*y+z*z);}
NM_API_INL void normalize() {const nmoat len=length();if (len>0) {x/=len;y/=len;z/=len;} else {x=y=z=(nmoat)0;}}
NM_API_INL vec3 normalized() const {const nmoat len=length();if (len>0) NM_RETURN_VEC3_CTR(x/len,y/len,z/len) else NM_RETURN_VEC3_CTR(0,0,0)}
NM_API_INL vec3 lerp(const vec3& o,nmoat t) const {nmoat ct = (nmoat)1-t;NM_RETURN_VEC3_CTR(x*ct+o.x*t,y*ct+o.y*t,z*ct+o.z*t)}
NM_API_INL vec3 proj(const vec3& onto) const {return onto*this->dot(onto)/onto.dot(onto);}
NM_API_INL nmoat angle_between(const vec3& o) const {return nmh_acos(this->dot(o)/(this->length()*o.length()));}
# endif //__cplusplus
} NM_POST_ALIGN_DEFAULT;
typedef struct vec3 vec3;
NM_API_DEF_INL vec3 make_vec3(nmoat _x, nmoat _y, nmoat _z) {NM_RETURN_VEC3_CTR(_x,_y,_z)}
#ifndef NM_NO_STDIO
NM_API_DEF_EXT_INL void vec3_fprintp(const vec3* v3,FILE* stream,int width, int precision);
NM_API_DEF_EXT_INL void vec3_fprint(const vec3* v3,FILE* stream);
NM_API_DEF_EXT_INL void vec3_printp(const vec3* v3,int width, int precision);
NM_API_DEF_EXT_INL void vec3_print(const vec3* v3);
#ifdef __cplusplus
NM_API_INL void vec3::fprintp(FILE* stream,int width, int precision) const {vec3_fprintp(this,stream,width,precision);}
NM_API_INL void vec3::fprint(FILE* stream) const {vec3_fprint(this,stream);}
NM_API_INL void vec3::printp(int width, int precision) const {vec3_printp(this,width,precision);}
NM_API_INL void vec3::print() const {vec3_print(this);}
#endif //__cplusplus
#endif //NM_NO_STDIO
//NM_API_DEF_EXT_INL vec3 vec3_copy(const vec3* src);
NM_API_DEF_EXT_INL vec3 vec3_add(const vec3* a,const vec3* b);
NM_API_DEF_EXT_INL vec3 vec3_sub(const vec3* a,const vec3* b);
NM_API_DEF_EXT_INL vec3 vec3_neg(const vec3* src);
NM_API_DEF_EXT_INL vec3 vec3_mul(const vec3* a,const vec3* b);
NM_API_DEF_EXT_INL vec3 vec3_mulsca(const vec3* src,nmoat f);
NM_API_DEF_EXT_INL vec3 vec3_div(const vec3* a,const vec3* b);
NM_API_DEF_EXT_INL vec3 vec3_divsca(const vec3* src,nmoat f);
NM_API_DEF_EXT_INL const vec3* vec3_sadd(vec3* dst,const vec3* src);
NM_API_DEF_EXT_INL const vec3* vec3_ssub(vec3* dst,const vec3* src);
NM_API_DEF_EXT_INL const vec3* vec3_inv(vec3* dst);
NM_API_DEF_EXT_INL const vec3* vec3_smul(vec3* dst,const vec3* src);
NM_API_DEF_EXT_INL const vec3* vec3_smulsca(vec3* dst,nmoat f);
NM_API_DEF_EXT_INL const vec3* vec3_sdiv(vec3* dst,const vec3* src);
NM_API_DEF_EXT_INL const vec3* vec3_sdivsca(vec3* dst,nmoat f);
NM_API_DEF_EXT_INL nmoat vec3_dot(const vec3* a,const vec3* b);
NM_API_DEF_EXT_INL vec3 vec3_cross(const vec3* a,const vec3* b);
NM_API_DEF_EXT_INL nmoat vec3_length3(const vec3* a);
NM_API_DEF_EXT_INL nmoat vec3_length(const vec3* a);
NM_API_DEF_EXT_INL const vec3* vec3_normalize(vec3* dst);
NM_API_DEF_EXT_INL vec3 vec3_normalized(const vec3* src);
NM_API_DEF_EXT_INL vec3 vec3_lerp(const vec3* a,const vec3* b,nmoat t);
NM_API_DEF_EXT_INL vec3 vec3_proj(const vec3* src,const vec3* onto);
NM_API_DEF_EXT_INL nmoat vec3_angle_between(const vec3* a,const vec3* b);
NM_API_DEF_EXT_INL int vec3_areequaleps(const vec3* a,const vec3* b,nmoat eps);
NM_API_DEF_EXT_INL int vec3_areequal(const vec3* a,const vec3* b);
// ---------------
// vec4 definition
// ---------------
#ifdef NM_NO_CPP_CTRS
# ifndef NM_NO_C_INITIALIZATION
# define NM_RETURN_VEC4_CTR(X,Y,Z,W) return (vec4){{{(X),(Y),(Z),(W)}}};
# else //NM_NO_C_INITIALIZATION
# define NM_RETURN_VEC4_CTR(X,Y,Z,W) {vec4 r;r.x=X;r.y=Y;r.z=Z;r.w=W;return r;}
# endif //NM_NO_C_INITIALIZATION
#else
# define NM_RETURN_VEC4_CTR(X,Y,Z,W) return vec4(X,Y,Z,W);
#endif
#undef NM_VEC4_MUST_BE_POD
#undef NM_QUERY_MAT4_VEC4_AXIS_VECTORS
#if (defined(NM_NO_CPP_CTRS) || defined(NM_COMPILER_SUPPORTS_NONPOD_ANONYMOUS_MEMBERS))
# if (!defined(NM_NO_AXIS_VECTORS_IN_STRUCT_MAT4) && defined(NM_AXIS_VEC4_IN_STRUCT_MAT4))
# define NM_QUERY_MAT4_VEC4_AXIS_VECTORS
# define NM_VEC4_MUST_BE_POD
# endif
#endif
#if (defined(NM_QUERY_MAT4_VEC3_AXIS_VECTORS) && defined(NM_QUERY_MAT4_VEC4_AXIS_VECTORS))
# error NM_QUERY_MAT4_VEC3_AXIS_VECTORS and NM_QUERY_MAT4_VEC4_AXIS_VECTORS should be mutually exclusive.
#endif
NM_PRE_ALIGN_DEFAULT struct vec4 {
union {
struct {nmoat x,y,z,w;};