1 /* cogl-graphene.c
2 *
3 * Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
4 *
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use, copy,
9 * modify, merge, publish, distribute, sublicense, and/or sell copies
10 * of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * SPDX-License-Identifier: MIT
26 *
27 */
28
29 #include "cogl/cogl-graphene.h"
30
31 typedef struct _Point2f
32 {
33 float x;
34 float y;
35 } Point2f;
36
37 typedef struct _Point3f
38 {
39 float x;
40 float y;
41 float z;
42 } Point3f;
43
44 typedef struct _Point4f
45 {
46 float x;
47 float y;
48 float z;
49 float w;
50 } Point4f;
51
52 static void
init_matrix_rows(const graphene_matrix_t * matrix,unsigned int n_rows,graphene_vec4_t * rows)53 init_matrix_rows (const graphene_matrix_t *matrix,
54 unsigned int n_rows,
55 graphene_vec4_t *rows)
56 {
57 graphene_matrix_t m;
58 unsigned int i;
59
60 graphene_matrix_transpose (matrix, &m);
61
62 for (i = 0; i < n_rows; i++)
63 graphene_matrix_get_row (&m, i, &rows[i]);
64 }
65
66 static void
transform_points_f2(const graphene_matrix_t * matrix,size_t stride_in,const void * points_in,size_t stride_out,void * points_out,int n_points)67 transform_points_f2 (const graphene_matrix_t *matrix,
68 size_t stride_in,
69 const void *points_in,
70 size_t stride_out,
71 void *points_out,
72 int n_points)
73 {
74 graphene_vec4_t rows[3];
75 int i;
76
77 init_matrix_rows (matrix, G_N_ELEMENTS (rows), rows);
78
79 for (i = 0; i < n_points; i++)
80 {
81 Point2f p = *(Point2f *)((uint8_t *)points_in + i * stride_in);
82 Point3f *o = (Point3f *)((uint8_t *)points_out + i * stride_out);
83 graphene_vec4_t point;
84
85 graphene_vec4_init (&point, p.x, p.y, 0.f, 1.f);
86
87 o->x = graphene_vec4_dot (&rows[0], &point);
88 o->y = graphene_vec4_dot (&rows[1], &point);
89 o->z = graphene_vec4_dot (&rows[2], &point);
90 }
91 }
92
93 static void
project_points_f2(const graphene_matrix_t * matrix,size_t stride_in,const void * points_in,size_t stride_out,void * points_out,int n_points)94 project_points_f2 (const graphene_matrix_t *matrix,
95 size_t stride_in,
96 const void *points_in,
97 size_t stride_out,
98 void *points_out,
99 int n_points)
100 {
101 graphene_vec4_t rows[4];
102 int i;
103
104 init_matrix_rows (matrix, G_N_ELEMENTS (rows), rows);
105
106 for (i = 0; i < n_points; i++)
107 {
108 Point2f p = *(Point2f *)((uint8_t *)points_in + i * stride_in);
109 Point4f *o = (Point4f *)((uint8_t *)points_out + i * stride_out);
110 graphene_vec4_t point;
111
112 graphene_vec4_init (&point, p.x, p.y, 0.f, 1.f);
113
114 o->x = graphene_vec4_dot (&rows[0], &point);
115 o->y = graphene_vec4_dot (&rows[1], &point);
116 o->z = graphene_vec4_dot (&rows[2], &point);
117 o->w = graphene_vec4_dot (&rows[3], &point);
118 }
119 }
120
121 static void
transform_points_f3(const graphene_matrix_t * matrix,size_t stride_in,const void * points_in,size_t stride_out,void * points_out,int n_points)122 transform_points_f3 (const graphene_matrix_t *matrix,
123 size_t stride_in,
124 const void *points_in,
125 size_t stride_out,
126 void *points_out,
127 int n_points)
128 {
129 graphene_vec4_t rows[3];
130 int i;
131
132 init_matrix_rows (matrix, G_N_ELEMENTS (rows), rows);
133
134 for (i = 0; i < n_points; i++)
135 {
136 Point3f p = *(Point3f *)((uint8_t *)points_in + i * stride_in);
137 Point3f *o = (Point3f *)((uint8_t *)points_out + i * stride_out);
138 graphene_vec4_t point;
139
140 graphene_vec4_init (&point, p.x, p.y, p.z, 1.f);
141
142 o->x = graphene_vec4_dot (&rows[0], &point);
143 o->y = graphene_vec4_dot (&rows[1], &point);
144 o->z = graphene_vec4_dot (&rows[2], &point);
145 }
146 }
147
148 static void
project_points_f3(const graphene_matrix_t * matrix,size_t stride_in,const void * points_in,size_t stride_out,void * points_out,int n_points)149 project_points_f3 (const graphene_matrix_t *matrix,
150 size_t stride_in,
151 const void *points_in,
152 size_t stride_out,
153 void *points_out,
154 int n_points)
155 {
156 graphene_vec4_t rows[4];
157 int i;
158
159 init_matrix_rows (matrix, G_N_ELEMENTS (rows), rows);
160
161 for (i = 0; i < n_points; i++)
162 {
163 Point3f p = *(Point3f *)((uint8_t *)points_in + i * stride_in);
164 Point4f *o = (Point4f *)((uint8_t *)points_out + i * stride_out);
165 graphene_vec4_t point;
166
167 graphene_vec4_init (&point, p.x, p.y, p.z, 1.f);
168
169 o->x = graphene_vec4_dot (&rows[0], &point);
170 o->y = graphene_vec4_dot (&rows[1], &point);
171 o->z = graphene_vec4_dot (&rows[2], &point);
172 o->w = graphene_vec4_dot (&rows[3], &point);
173 }
174 }
175
176 static void
project_points_f4(const graphene_matrix_t * matrix,size_t stride_in,const void * points_in,size_t stride_out,void * points_out,int n_points)177 project_points_f4 (const graphene_matrix_t *matrix,
178 size_t stride_in,
179 const void *points_in,
180 size_t stride_out,
181 void *points_out,
182 int n_points)
183 {
184 graphene_vec4_t rows[4];
185 int i;
186
187 init_matrix_rows (matrix, G_N_ELEMENTS (rows), rows);
188
189 for (i = 0; i < n_points; i++)
190 {
191 Point4f p = *(Point4f *)((uint8_t *)points_in + i * stride_in);
192 Point4f *o = (Point4f *)((uint8_t *)points_out + i * stride_out);
193 graphene_vec4_t point;
194
195 graphene_vec4_init (&point, p.x, p.y, p.z, p.w);
196
197 o->x = graphene_vec4_dot (&rows[0], &point);
198 o->y = graphene_vec4_dot (&rows[1], &point);
199 o->z = graphene_vec4_dot (&rows[2], &point);
200 o->w = graphene_vec4_dot (&rows[3], &point);
201 }
202 }
203
204 void
cogl_graphene_matrix_project_point(const graphene_matrix_t * matrix,float * x,float * y,float * z,float * w)205 cogl_graphene_matrix_project_point (const graphene_matrix_t *matrix,
206 float *x,
207 float *y,
208 float *z,
209 float *w)
210 {
211 graphene_vec4_t p;
212
213 graphene_vec4_init (&p, *x, *y, *z, *w);
214 graphene_matrix_transform_vec4 (matrix, &p, &p);
215
216 *x = graphene_vec4_get_x (&p);
217 *y = graphene_vec4_get_y (&p);
218 *z = graphene_vec4_get_z (&p);
219 *w = graphene_vec4_get_w (&p);
220 }
221
222 void
cogl_graphene_matrix_transform_points(const graphene_matrix_t * matrix,int n_components,size_t stride_in,const void * points_in,size_t stride_out,void * points_out,int n_points)223 cogl_graphene_matrix_transform_points (const graphene_matrix_t *matrix,
224 int n_components,
225 size_t stride_in,
226 const void *points_in,
227 size_t stride_out,
228 void *points_out,
229 int n_points)
230 {
231 /* The results of transforming always have three components... */
232 g_return_if_fail (stride_out >= sizeof (Point3f));
233
234 if (n_components == 2)
235 {
236 transform_points_f2 (matrix,
237 stride_in, points_in,
238 stride_out, points_out,
239 n_points);
240 }
241 else
242 {
243 g_return_if_fail (n_components == 3);
244
245 transform_points_f3 (matrix,
246 stride_in, points_in,
247 stride_out, points_out,
248 n_points);
249 }
250 }
251
252 void
cogl_graphene_matrix_project_points(const graphene_matrix_t * matrix,int n_components,size_t stride_in,const void * points_in,size_t stride_out,void * points_out,int n_points)253 cogl_graphene_matrix_project_points (const graphene_matrix_t *matrix,
254 int n_components,
255 size_t stride_in,
256 const void *points_in,
257 size_t stride_out,
258 void *points_out,
259 int n_points)
260 {
261 if (n_components == 2)
262 {
263 project_points_f2 (matrix,
264 stride_in, points_in,
265 stride_out, points_out,
266 n_points);
267 }
268 else if (n_components == 3)
269 {
270 project_points_f3 (matrix,
271 stride_in, points_in,
272 stride_out, points_out,
273 n_points);
274 }
275 else
276 {
277 g_return_if_fail (n_components == 4);
278
279 project_points_f4 (matrix,
280 stride_in, points_in,
281 stride_out, points_out,
282 n_points);
283 }
284 }
285