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
|
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_affine_pre_h
#define cglm_affine_pre_h
/*
Functions:
CGLM_INLINE void glm_translate_to(mat4 m, vec3 v, mat4 dest);
CGLM_INLINE void glm_translate(mat4 m, vec3 v);
CGLM_INLINE void glm_translate_x(mat4 m, float to);
CGLM_INLINE void glm_translate_y(mat4 m, float to);
CGLM_INLINE void glm_translate_z(mat4 m, float to);
CGLM_INLINE void glm_rotate_x(mat4 m, float angle, mat4 dest);
CGLM_INLINE void glm_rotate_y(mat4 m, float angle, mat4 dest);
CGLM_INLINE void glm_rotate_z(mat4 m, float angle, mat4 dest);
CGLM_INLINE void glm_rotate(mat4 m, float angle, vec3 axis);
CGLM_INLINE void glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis);
CGLM_INLINE void glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis);
CGLM_INLINE void glm_spin(mat4 m, float angle, vec3 axis);
*/
#include "common.h"
#include "util.h"
#include "vec3.h"
#include "vec4.h"
#include "mat4.h"
#include "affine-mat.h"
/*!
* @brief translate existing transform matrix by v vector
* and stores result in same matrix
*
* @param[in, out] m affine transform
* @param[in] v translate vector [x, y, z]
*/
CGLM_INLINE
void
glm_translate(mat4 m, vec3 v) {
#if defined(CGLM_SIMD)
glmm_128 m0, m1, m2, m3;
m0 = glmm_load(m[0]);
m1 = glmm_load(m[1]);
m2 = glmm_load(m[2]);
m3 = glmm_load(m[3]);
glmm_store(m[3],
glmm_fmadd(m0, glmm_set1(v[0]),
glmm_fmadd(m1, glmm_set1(v[1]),
glmm_fmadd(m2, glmm_set1(v[2]), m3))));
#else
glm_vec4_muladds(m[0], v[0], m[3]);
glm_vec4_muladds(m[1], v[1], m[3]);
glm_vec4_muladds(m[2], v[2], m[3]);
#endif
}
/*!
* @brief translate existing transform matrix by v vector
* and store result in dest
*
* source matrix will remain same
*
* @param[in] m affine transform
* @param[in] v translate vector [x, y, z]
* @param[out] dest translated matrix
*/
CGLM_INLINE
void
glm_translate_to(mat4 m, vec3 v, mat4 dest) {
glm_mat4_copy(m, dest);
glm_translate(dest, v);
}
/*!
* @brief translate existing transform matrix by x factor
*
* @param[in, out] m affine transform
* @param[in] x x factor
*/
CGLM_INLINE
void
glm_translate_x(mat4 m, float x) {
#if defined(CGLM_SIMD)
glmm_store(m[3], glmm_fmadd(glmm_load(m[0]), glmm_set1(x), glmm_load(m[3])));
#else
vec4 v1;
glm_vec4_scale(m[0], x, v1);
glm_vec4_add(v1, m[3], m[3]);
#endif
}
/*!
* @brief translate existing transform matrix by y factor
*
* @param[in, out] m affine transform
* @param[in] y y factor
*/
CGLM_INLINE
void
glm_translate_y(mat4 m, float y) {
#if defined(CGLM_SIMD)
glmm_store(m[3], glmm_fmadd(glmm_load(m[1]), glmm_set1(y), glmm_load(m[3])));
#else
vec4 v1;
glm_vec4_scale(m[1], y, v1);
glm_vec4_add(v1, m[3], m[3]);
#endif
}
/*!
* @brief translate existing transform matrix by z factor
*
* @param[in, out] m affine transform
* @param[in] z z factor
*/
CGLM_INLINE
void
glm_translate_z(mat4 m, float z) {
#if defined(CGLM_SIMD)
glmm_store(m[3], glmm_fmadd(glmm_load(m[2]), glmm_set1(z), glmm_load(m[3])));
#else
vec4 v1;
glm_vec4_scale(m[2], z, v1);
glm_vec4_add(v1, m[3], m[3]);
#endif
}
/*!
* @brief rotate existing transform matrix around X axis by angle
* and store result in dest
*
* @param[in] m affine transform
* @param[in] angle angle (radians)
* @param[out] dest rotated matrix
*/
CGLM_INLINE
void
glm_rotate_x(mat4 m, float angle, mat4 dest) {
CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
float c, s;
c = cosf(angle);
s = sinf(angle);
t[1][1] = c;
t[1][2] = s;
t[2][1] = -s;
t[2][2] = c;
glm_mul_rot(m, t, dest);
}
/*!
* @brief rotate existing transform matrix around Y axis by angle
* and store result in dest
*
* @param[in] m affine transform
* @param[in] angle angle (radians)
* @param[out] dest rotated matrix
*/
CGLM_INLINE
void
glm_rotate_y(mat4 m, float angle, mat4 dest) {
CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
float c, s;
c = cosf(angle);
s = sinf(angle);
t[0][0] = c;
t[0][2] = -s;
t[2][0] = s;
t[2][2] = c;
glm_mul_rot(m, t, dest);
}
/*!
* @brief rotate existing transform matrix around Z axis by angle
* and store result in dest
*
* @param[in] m affine transform
* @param[in] angle angle (radians)
* @param[out] dest rotated matrix
*/
CGLM_INLINE
void
glm_rotate_z(mat4 m, float angle, mat4 dest) {
CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT;
float c, s;
c = cosf(angle);
s = sinf(angle);
t[0][0] = c;
t[0][1] = s;
t[1][0] = -s;
t[1][1] = c;
glm_mul_rot(m, t, dest);
}
/*!
* @brief rotate existing transform matrix
* around given axis by angle at ORIGIN (0,0,0)
*
* **❗️IMPORTANT ❗️**
*
* If you need to rotate object around itself e.g. center of object or at
* some point [of object] then `glm_rotate_at()` would be better choice to do so.
*
* Even if object's model transform is identity, rotation may not be around
* center of object if object does not lay out at ORIGIN perfectly.
*
* Using `glm_rotate_at()` with center of bounding shape ( AABB, Sphere ... )
* would be an easy option to rotate around object if object is not at origin.
*
* One another option to rotate around itself at any point is `glm_spin()`
* which is perfect if only rotating around model position is desired e.g. not
* specific point on model for instance center of geometry or center of mass,
* again if geometry is not perfectly centered at origin at identity transform,
* rotation may not be around geometry.
*
* @param[in, out] m affine transform
* @param[in] angle angle (radians)
* @param[in] axis axis
*/
CGLM_INLINE
void
glm_rotate(mat4 m, float angle, vec3 axis) {
CGLM_ALIGN_MAT mat4 rot;
glm_rotate_make(rot, angle, axis);
glm_mul_rot(m, rot, m);
}
/*!
* @brief rotate existing transform
* around given axis by angle at given pivot point (rotation center)
*
* @param[in, out] m affine transform
* @param[in] pivot rotation center
* @param[in] angle angle (radians)
* @param[in] axis axis
*/
CGLM_INLINE
void
glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis) {
CGLM_ALIGN(8) vec3 pivotInv;
glm_vec3_negate_to(pivot, pivotInv);
glm_translate(m, pivot);
glm_rotate(m, angle, axis);
glm_translate(m, pivotInv);
}
/*!
* @brief creates NEW rotation matrix by angle and axis at given point
*
* this creates rotation matrix, it assumes you don't have a matrix
*
* this should work faster than glm_rotate_at because it reduces
* one glm_translate.
*
* @param[out] m affine transform
* @param[in] pivot rotation center
* @param[in] angle angle (radians)
* @param[in] axis axis
*/
CGLM_INLINE
void
glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis) {
CGLM_ALIGN(8) vec3 pivotInv;
glm_vec3_negate_to(pivot, pivotInv);
glm_translate_make(m, pivot);
glm_rotate(m, angle, axis);
glm_translate(m, pivotInv);
}
/*!
* @brief rotate existing transform matrix
* around given axis by angle around self (doesn't affected by position)
*
* @param[in, out] m affine transform
* @param[in] angle angle (radians)
* @param[in] axis axis
*/
CGLM_INLINE
void
glm_spin(mat4 m, float angle, vec3 axis) {
CGLM_ALIGN_MAT mat4 rot;
glm_rotate_atm(rot, m[3], angle, axis);
glm_mat4_mul(m, rot, m);
}
#endif /* cglm_affine_pre_h */
|