1 /*
2 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package view.f32;
26
27 import view.f32.pool.F32x3TrianglePool;
28
29 public interface F32 {
30 F32x4x4.Factory f32x4x4Factory();
31
32 F32x3.Factory f32x3Factory();
33
34 F32x2.Factory f32x2Factory();
35
36 F32x3Triangle.Factory f32x3TriangleFactory();
37
38 F32x2Triangle.Factory f32x2TriangleFactory();
39
40 default F32x4x4 f32x4x4(
41 float x0y0, float x1y0, float x2y0, float x3y0,
42 float x0y1, float x1y1, float x2y1, float x3y1,
43 float x0y2, float x1y2, float x2y2, float x3y2,
44 float x0y3, float x1y3, float x2y3, float x3y3
45 ) {
46 return f32x4x4Factory().of(x0y0, x1y0, x2y0, x3y0,
47 x0y1, x1y1, x2y1, x3y1,
48 x0y2, x1y2, x2y2, x3y2,
49 x0y3, x1y3, x2y3, x3y3);
50 }
51
52 default F32x2 f32x2(float x, float y) {
53 return f32x2Factory().of(x, y);
54 }
55
56 default F32x3 f32x3(float x, float y, float z) {
57 return f32x3Factory().of(x, y, z);
58 }
59
60 default F32x3Triangle f32x3Triangle(F32x3 v0, F32x3 v1, F32x3 v2, int rgb) {
61 return f32x3TriangleFactory().of(v0, v1, v2, rgb);
62 }
63
64 default F32x2Triangle f32x2Triangle(F32x2 v0, F32x2 v1, F32x2 v2, float zplane, float normal, int rgb) {
65 return f32x2TriangleFactory().of(v0, v1, v2, zplane, normal, rgb);
66 }
67
68 default F32x4x4 mul(F32x4x4 lhs, F32x4x4 rhs) {
69 return f32x4x4(
70 lhs.x0y0() * rhs.x0y0() + lhs.x1y0() * rhs.x0y1() + lhs.x2y0() * rhs.x0y2() + lhs.x3y0() * rhs.x0y3(),
71 lhs.x0y0() * rhs.x1y0() + lhs.x1y0() * rhs.x1y1() + lhs.x2y0() * rhs.x1y2() + lhs.x3y0() * rhs.x1y3(),
72 lhs.x0y0() * rhs.x2y0() + lhs.x1y0() * rhs.x2y1() + lhs.x2y0() * rhs.x2y2() + lhs.x3y0() * rhs.x2y3(),
73 lhs.x0y0() * rhs.x3y0() + lhs.x1y0() * rhs.x3y1() + lhs.x2y0() * rhs.x3y2() + lhs.x3y0() * rhs.x3y3(),
74
75 lhs.x0y1() * rhs.x0y0() + lhs.x1y1() * rhs.x0y1() + lhs.x2y1() * rhs.x0y2() + lhs.x3y1() * rhs.x0y3(),
76 lhs.x0y1() * rhs.x1y0() + lhs.x1y1() * rhs.x1y1() + lhs.x2y1() * rhs.x1y2() + lhs.x3y1() * rhs.x1y3(),
77 lhs.x0y1() * rhs.x2y0() + lhs.x1y1() * rhs.x2y1() + lhs.x2y1() * rhs.x2y2() + lhs.x3y1() * rhs.x2y3(),
78 lhs.x0y1() * rhs.x3y0() + lhs.x1y1() * rhs.x3y1() + lhs.x2y1() * rhs.x3y2() + lhs.x3y1() * rhs.x3y3(),
79
80 lhs.x0y2() * rhs.x0y0() + lhs.x1y2() * rhs.x0y1() + lhs.x2y2() * rhs.x0y2() + lhs.x3y2() * rhs.x0y3(),
81 lhs.x0y2() * rhs.x1y0() + lhs.x1y2() * rhs.x1y1() + lhs.x2y2() * rhs.x1y2() + lhs.x3y2() * rhs.x1y3(),
82 lhs.x0y2() * rhs.x2y0() + lhs.x1y2() * rhs.x2y1() + lhs.x2y2() * rhs.x2y2() + lhs.x3y2() * rhs.x2y3(),
83 lhs.x0y2() * rhs.x3y0() + lhs.x1y2() * rhs.x3y1() + lhs.x2y2() * rhs.x3y2() + lhs.x3y2() * rhs.x3y3(),
84
85 lhs.x0y3() * rhs.x0y0() + lhs.x1y3() * rhs.x0y1() + lhs.x2y3() * rhs.x0y2() + lhs.x3y3() * rhs.x0y3(),
86 lhs.x0y3() * rhs.x1y0() + lhs.x1y3() * rhs.x1y1() + lhs.x2y3() * rhs.x1y2() + lhs.x3y3() * rhs.x1y3(),
87 lhs.x0y3() * rhs.x2y0() + lhs.x1y3() * rhs.x2y1() + lhs.x2y3() * rhs.x2y2() + lhs.x3y3() * rhs.x2y3(),
88 lhs.x0y3() * rhs.x3y0() + lhs.x1y3() * rhs.x3y1() + lhs.x2y3() * rhs.x3y2() + lhs.x3y3() * rhs.x3y3()
89
90 );
91 }
92
93 // https://stackoverflow.com/questions/28075743/how-do-i-compose-a-rotation-matrix-with-human-readable-angles-from-scratch/28084380#28084380
94
95
96 //https://medium.com/swlh/understanding-3d-matrix-transforms-with-pixijs-c76da3f8bd8
97 default F32x4x4 transformation(float x, float y, float z) {
98 return f32x4x4(
99 1f, 0f, 0f, 0f,
100 0f, 1f, 0f, 0f,
101 0f, 0f, 1f, 0f,
102 x, y, z, 1f
103 );
104 }
105
106 default F32x4x4 transformation(float v) {
107 return transformation(v, v, v);
108 }
109
110 default F32x4x4 scale(float x, float y, float z) {
111 return f32x4x4(
112 x, 0f, 0f, 0f,
113 0f, y, 0f, 0f,
114 0f, 0f, z, 0f,
115 0f, 0f, 0f, 1f
116 );
117 }
118
119 default F32x4x4 scale(float v) {
120 return scale(v, v, v);
121 }
122
123 default F32x4x4 rotX(float thetaRadians) {
124 float sinTheta = (float) Math.sin(thetaRadians);
125 float cosTheta = (float) Math.cos(thetaRadians);
126 return f32x4x4(
127 1f, 0f, 0f, 0f,
128 0f, cosTheta, -sinTheta, 0f,
129 0f, sinTheta, cosTheta, 0f,
130 0f, 0f, 0f, 1f
131
132 );
133 }
134
135 default F32x4x4 rotZ(float thetaRadians) {
136 float sinTheta = (float) Math.sin(thetaRadians);
137 float cosTheta = (float) Math.cos(thetaRadians);
138 return f32x4x4(
139 cosTheta, sinTheta, 0f, 0f,
140 -sinTheta, cosTheta, 0f, 0f,
141 0f, 0f, 1f, 0f,
142 0f, 0f, 0f, 1f
143 );
144 }
145
146 default F32x4x4 rotY(float thetaRadians) {
147 float sinTheta = (float) Math.sin(thetaRadians);
148 float cosTheta = (float) Math.cos(thetaRadians);
149 return f32x4x4(
150 cosTheta, 0f, sinTheta, 0f,
151 0f, 1f, 0f, 0f,
152 -sinTheta, 0f, cosTheta, 0f,
153 0f, 0f, 0f, 1f
154 );
155 }
156
157 default F32x4x4 rot(float thetaX, float thetaY, float thetaZ) {
158 return mul(mul(rotX(thetaX), rotY(thetaY)), rotZ(thetaZ));
159 }
160
161 // https://medium.com/swlh/understanding-3d-matrix-transforms-with-pixijs-c76da3f8bd8
162
163
164 /*
165 https://youtu.be/ih20l3pJoeU?t=973
166 https://stackoverflow.com/questions/28075743/how-do-i-compose-a-rotation-matrix-with-human-readable-angles-from-scratch/28084380#28084380^
167 -------------------- far
168 \ / ^ ^
169 \ / | | far-near
170 \ / | |
171 \__________/ near | v
172 ^ |
173 v v
174 \^/
175 [x,y,z]
176
177 */
178 default F32x4x4 projection(float width, float height, float near, float far, float fieldOfViewDeg) {
179 float aspectRatio = height / width;
180 float fieldOfViewRadians = (float) (1.0f / Math.tan((fieldOfViewDeg * 0.5f) / 180.0 * Math.PI));
181 return f32x4x4(
182 aspectRatio * fieldOfViewRadians, 0f, 0f, 0f,
183 0f, fieldOfViewRadians, 0f, 0f,
184 0f, 0f, far / (far - near), (-far * near) / (far - near),
185 0f, 0f, (-far * near) / (far - near), 0f);
186 }
187
188 static float side(float x, float y, F32x2 v0, F32x2 v1) {
189 return (v1.y() - v0.y() * (x - v0.x()) + (-v1.x() + v0.x()) * (y - v0.y()));
190 }
191
192 /*
193 V0 V0
194 | \ | \
195 | \ | \ P2
196 | P1 \ | \
197 V1------V0 V1------V0
198
199
200 Barycentric coordinate allows to express new p coordinates as a linear combination of p1, p2, p3.
201 More precisely, it defines 3 scalars a, b, c such that :
202
203 x = a * x1 + b * x2 + c * x3
204 y = a * y1 + b * y2 + c * y3
205 a + b + c = 1
206
207
208 a = ((y2 - y3)*(x - x3) + (x3 - x2)*(y - y3)) / ((y2 - y3)*(x1 - x3) + (x3 - x2)*(y1 - y3))
209 b = ((y3 - y1)*(x - x3) + (x1 - x3)*(y - y3)) / ((y2 - y3)*(x1 - x3) + (x3 - x2)*(y1 - y3))
210 c = 1 - a - b
211
212 p lies in T if and only if 0 <= a <= 1 and 0 <= b <= 1 and 0 <= c <= 1
213 */
214
215 static boolean inside(float x, float y, float x0, float y0, float x1, float y1, float x2, float y2) {
216 var denominator = ((y1 - y2) * (x0 - x2) + (x2 - x1) * (y0 - y2));
217 var a = ((y1 - y2) * (x - x2) + (x2 - x1) * (y - y2)) / denominator;
218 var b = ((y2 - y0) * (x - x2) + (x0 - x2) * (y - y2)) / denominator;
219 var c = 1 - a - b;
220 return 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1;
221 }
222
223 static boolean inside(float x, float y, F32x2 v0, F32x2 v1, F32x2 v2) {
224 return inside(x, y, v0.x(), v0.y(), v1.x(), v1.y(), v2.x(), v2.y());
225 }
226
227 static boolean inside(float x, float y, F32x2Triangle tri) {
228 return inside(x, y, tri.v0(), tri.v1(), tri.v2());
229 }
230
231 static boolean onLine(float x, float y, F32x2 v0, F32x2 v1, float deltaSquare) {
232 float dxl = v1.x() - v0.x();
233 float dyl = v1.y() - v0.y();
234 ;
235 float cross = (x - v0.x()) * dyl - (y - v0.y()) * dxl;
236 if ((cross * cross) < deltaSquare) {
237 if (dxl * dxl >= dyl * dyl)
238 return dxl > 0 ? v0.x() <= x && x <= v1.x() : v1.x() <= x && x <= v0.x();
239 else
240 return dyl > 0 ? v0.y() <= y && y <= v1.y() : v1.y() <= y && y <= v0.y();
241 } else {
242 return false;
243 }
244 }
245
246 float deltaSquare = 2000f;
247
248 static boolean onEdge(float x, float y, F32x2Triangle tri) {
249 return onLine(x, y, tri.v0(), tri.v1(), deltaSquare)
250 || onLine(x, y, tri.v1(), tri.v2(), deltaSquare)
251 || onLine(x, y, tri.v2(), tri.v0(), deltaSquare);
252 }
253
254 static boolean useRgb(boolean filled, float x, float y, F32x2Triangle tri) {
255 return filled ? inside(x, y, tri) : onEdge(x, y, tri);
256 }
257
258 static int rgb(boolean filled, float x, float y, F32x2Triangle tri, int rgb) {
259 return useRgb(filled, x, y, tri) ? tri.rgb() : rgb;
260 }
261
262 /*
263 v0----v1 v0----v2
264 \ | \ |
265 \ | \ |
266 \ | ---> \ |
267 \ | \ |
268 \| \|
269 v2 v1
270 */
271 static F32x3Triangle rewind(F32x3Triangle i) {
272 var temp = i.v1();
273 ((F32x3TrianglePool.PoolEntry) i).pool().f32x3Entries[((F32x3TrianglePool.PoolEntry) i).v1Idx()] = i.v2();
274 ((F32x3TrianglePool.PoolEntry) i).pool().f32x3Entries[((F32x3TrianglePool.PoolEntry) i).v2Idx()] = temp;
275 return i;
276 }
277
278 default F32x3Triangle mul(F32x3Triangle i, F32x4x4 m4) {
279 return f32x3Triangle(mul(i.v0(), m4), mul(i.v1(), m4), mul(i.v2(), m4), i.rgb());
280 }
281
282 default F32x3Triangle add(F32x3Triangle i, F32x3 v3) {
283 return f32x3Triangle(add(i.v0(), v3), add(i.v1(), v3), add(i.v2(), v3), i.rgb());
284 }
285
286 default F32x3Triangle mul(F32x3Triangle i, float s) {
287 return f32x3Triangle(mul(i.v0(), s), mul(i.v1(), s), mul(i.v2(), s), i.rgb());
288 }
289
290 default F32x3Triangle add(F32x3Triangle i, float s) {
291 return f32x3Triangle(add(i.v0(), s), add(i.v1(), s), add(i.v2(), s), i.rgb());
292 }
293
294 default F32x3 centre(F32x3Triangle i) {// the average of all the vertices
295 return div(getVectorSum(i), 3);
296 }
297
298 default F32x3 getVectorSum(F32x3Triangle i) {// the sum of all the vertices
299 return add(add(i.v0(), i.v1()), i.v2());
300 }
301
302 default F32x3 normal(F32x3Triangle i) {
303 return crossProd(sub(i.v1(), i.v0()), sub(i.v2(), i.v0()));
304 }
305
306 default F32x3 normalSumOfSquares(F32x3Triangle i) {
307 return div(normal(i), sumOfSq(normal(i)));
308 }
309
310 /* return another vec3 after multiplying by m4
311 we pad this vec3 to vec 4 with '1' as w
312 we normalize the result
313 */
314
315 default F32x3 mul(F32x3 f32x3, F32x4x4 m) {
316 F32x3 o = f32x3(
317 f32x3.x() * m.x0y0() + f32x3.y() * m.x0y1() + f32x3.z() * m.x0y2() + 1f * m.x0y3(),
318 f32x3.x() * m.x1y0() + f32x3.y() * m.x1y1() + f32x3.z() * m.x1y2() + 1f * m.x1y3(),
319 f32x3.x() * m.x2y0() + f32x3.y() * m.x2y1() + f32x3.z() * m.x2y2() + 1f * m.x2y3()
320 );
321 float w = f32x3.x() * m.x3y0() + f32x3.y() * m.x3y1() + f32x3.z() * m.x3y2() + 1f * m.x3y3();
322 // if (w!=0.0) {
323 o = div(o, w);
324 // }
325 return o;
326 }
327
328 default F32x3 mul(F32x3 i, float s) {
329 return f32x3(i.x() * s, i.y() * s, i.z() * s);
330 }
331
332 default F32x3 add(F32x3 i, float s) {
333
334 return f32x3(i.x() + s, i.y() + s, i.z() + s);
335 }
336
337 default F32x3 div(F32x3 i, float s) {
338 if (s == 0) {
339 return i;
340 }
341 return f32x3(i.x() / s, i.y() / s, i.z() / s);
342 }
343
344 default F32x3 add(F32x3 lhs, F32x3 rhs) {
345 return f32x3(lhs.x() + rhs.x(), lhs.y() + rhs.y(), lhs.z() + rhs.z());
346 }
347
348 default F32x3 sub(F32x3 lhs, F32x3 rhs) {
349 return f32x3(lhs.x() - rhs.x(), lhs.y() - rhs.y(), lhs.z() - rhs.z());
350 }
351
352 default F32x3 mul(F32x3 lhs, F32x3 rhs) {
353 return f32x3(lhs.x() * rhs.x(), lhs.y() * rhs.y(), lhs.z() * rhs.z());
354 }
355
356 default F32x3 div(F32x3 lhs, F32x3 rhs) {
357 return f32x3(lhs.x() / rhs.x(), lhs.y() / rhs.y(), lhs.z() / rhs.z());
358 }
359
360 default float sumOfSq(F32x3 i) {
361 return i.x() * i.x() + i.y() * i.y() + i.z() * i.z();
362 }
363
364 default float sumOf(F32x3 i) {
365 return i.x() + i.y() + i.z();
366 }
367
368 default float hypot(F32x3 i) {
369 return (float) Math.sqrt(sumOfSq(i));
370 }
371
372 default F32x3 crossProd(F32x3 lhs, F32x3 rhs) {
373 return f32x3(
374 lhs.y() * rhs.z() - lhs.z() * rhs.x(),
375 lhs.z() * rhs.x() - lhs.x() * rhs.z(),
376 lhs.x() * rhs.y() - lhs.y() * rhs.x());
377
378 }
379
380 /*
381 lhs= | 1| rhs= | 2|
382 | 3| | 7|
383 | 4| |-5|
384
385 lhs0*rhs0 + lhs1*rhs1 + lhs2*rhs2
386 1 * 2 + 3 * 7 + 4 *-5
387
388 3 + 21 + -20
389
390 4
391
392 */
393 default float dotProd(F32x3 lhs, F32x3 rhs) {
394 return lhs.x() * rhs.x() + lhs.y() * rhs.y() + lhs.z() * rhs.z();
395 }
396 }