Blender V5.0
Projections.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2002-2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "Projections.h"
6#include <cmath>
7
8#include <algorithm>
9
10const int vertmap[8][3] = {
11 {0, 0, 0},
12 {0, 0, 1},
13 {0, 1, 0},
14 {0, 1, 1},
15 {1, 0, 0},
16 {1, 0, 1},
17 {1, 1, 0},
18 {1, 1, 1},
19};
20
21const int centmap[3][3][3][2] = {
22 {{{0, 0}, {0, 1}, {1, 1}}, {{0, 2}, {0, 3}, {1, 3}}, {{2, 2}, {2, 3}, {3, 3}}},
23
24 {{{0, 4}, {0, 5}, {1, 5}}, {{0, 6}, {0, 7}, {1, 7}}, {{2, 6}, {2, 7}, {3, 7}}},
25
26 {{{4, 4}, {4, 5}, {5, 5}}, {{4, 6}, {4, 7}, {5, 7}}, {{6, 6}, {6, 7}, {7, 7}}}};
27
28const int edgemap[12][2] = {
29 {0, 4},
30 {1, 5},
31 {2, 6},
32 {3, 7},
33 {0, 2},
34 {1, 3},
35 {4, 6},
36 {5, 7},
37 {0, 1},
38 {2, 3},
39 {4, 5},
40 {6, 7},
41};
42
43const int facemap[6][4] = {
44 {0, 1, 2, 3},
45 {4, 5, 6, 7},
46 {0, 1, 4, 5},
47 {2, 3, 6, 7},
48 {0, 2, 4, 6},
49 {1, 3, 5, 7},
50};
51
55static void crossProduct(int64_t res[3], const int64_t a[3], const int64_t b[3])
56{
57 res[0] = a[1] * b[2] - a[2] * b[1];
58 res[1] = a[2] * b[0] - a[0] * b[2];
59 res[2] = a[0] * b[1] - a[1] * b[0];
60}
61
62static void crossProduct(double res[3], const double a[3], const double b[3])
63{
64 res[0] = a[1] * b[2] - a[2] * b[1];
65 res[1] = a[2] * b[0] - a[0] * b[2];
66 res[2] = a[0] * b[1] - a[1] * b[0];
67}
68
72static int64_t dotProduct(const int64_t a[3], const int64_t b[3])
73{
74 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
75}
76
77static void normalize(double a[3])
78{
79 double mag = a[0] * a[0] + a[1] * a[1] + a[2] * a[2];
80 if (mag > 0) {
81 mag = sqrt(mag);
82 a[0] /= mag;
83 a[1] /= mag;
84 a[2] /= mag;
85 }
86}
87
88/* Create projection axes for cube+triangle intersection testing.
89 * 0, 1, 2: cube face normals
90 *
91 * 3: triangle normal
92 *
93 * 4, 5, 6,
94 * 7, 8, 9,
95 * 10, 11, 12: cross of each triangle edge vector with each cube
96 * face normal
97 */
98static void create_projection_axes(int64_t axes[NUM_AXES][3], const int64_t tri[3][3])
99{
100 /* Cube face normals */
101 axes[0][0] = 1;
102 axes[0][1] = 0;
103 axes[0][2] = 0;
104 axes[1][0] = 0;
105 axes[1][1] = 1;
106 axes[1][2] = 0;
107 axes[2][0] = 0;
108 axes[2][1] = 0;
109 axes[2][2] = 1;
110
111 /* Get triangle edge vectors */
112 int64_t tri_edges[3][3];
113 for (int i = 0; i < 3; i++) {
114 for (int j = 0; j < 3; j++) {
115 tri_edges[i][j] = tri[(i + 1) % 3][j] - tri[i][j];
116 }
117 }
118
119 /* Triangle normal */
120 crossProduct(axes[3], tri_edges[0], tri_edges[1]);
121
122 // Face edges and triangle edges
123 int ct = 4;
124 for (int i = 0; i < 3; i++) {
125 for (int j = 0; j < 3; j++) {
126 crossProduct(axes[ct], axes[j], tri_edges[i]);
127 ct++;
128 }
129 }
130}
131
136 int64_t tri[3][3],
137 int64_t /*error*/,
138 int triind)
139{
140 int i;
142 inherit->index = triind;
143
144 int64_t axes[NUM_AXES][3];
145 create_projection_axes(axes, tri);
146
147 /* Normalize face normal and store */
148 double dedge1[] = {(double)tri[1][0] - (double)tri[0][0],
149 (double)tri[1][1] - (double)tri[0][1],
150 (double)tri[1][2] - (double)tri[0][2]};
151 double dedge2[] = {(double)tri[2][0] - (double)tri[1][0],
152 (double)tri[2][1] - (double)tri[1][1],
153 (double)tri[2][2] - (double)tri[1][2]};
154 crossProduct(inherit->norm, dedge1, dedge2);
155 normalize(inherit->norm);
156
157 int64_t cubeedge[3][3];
158 for (i = 0; i < 3; i++) {
159 for (int j = 0; j < 3; j++) {
160 cubeedge[i][j] = 0;
161 }
162 cubeedge[i][i] = cube[1][i] - cube[0][i];
163 }
164
165 /* Project the cube on to each axis */
166 for (int axis = 0; axis < NUM_AXES; axis++) {
167 CubeProjection &cube_proj = cubeProj[axis];
168
169 /* Origin */
170 cube_proj.origin = dotProduct(axes[axis], cube[0]);
171
172 /* 3 direction vectors */
173 for (i = 0; i < 3; i++) {
174 cube_proj.edges[i] = dotProduct(axes[axis], cubeedge[i]);
175 }
176
177 /* Offsets of 2 ends of cube projection */
178 int64_t max = 0;
179 int64_t min = 0;
180 for (i = 1; i < 8; i++) {
181 int64_t proj = (vertmap[i][0] * cube_proj.edges[0] + vertmap[i][1] * cube_proj.edges[1] +
182 vertmap[i][2] * cube_proj.edges[2]);
183 max = std::max(proj, max);
184 min = std::min(proj, min);
185 }
186 cube_proj.min = min;
187 cube_proj.max = max;
188 }
189
190 /* Project the triangle on to each axis */
191 for (int axis = 0; axis < NUM_AXES; axis++) {
192 const int64_t vts[3] = {dotProduct(axes[axis], tri[0]),
193 dotProduct(axes[axis], tri[1]),
194 dotProduct(axes[axis], tri[2])};
195
196 // Triangle
197 inherit->tri_proj[axis][0] = vts[0];
198 inherit->tri_proj[axis][1] = vts[0];
199 for (i = 1; i < 3; i++) {
200 inherit->tri_proj[axis][0] = std::min(vts[i], inherit->tri_proj[axis][0]);
201 inherit->tri_proj[axis][1] = std::max(vts[i], inherit->tri_proj[axis][1]);
202 }
203 }
204}
205
211{
212 // Copy inheritable projections
213 this->inherit = parent->inherit;
214
215 // Shrink cube projections
216 for (int i = 0; i < NUM_AXES; i++) {
217 cubeProj[i].origin = parent->cubeProj[i].origin;
218
219 for (int j = 0; j < 3; j++) {
220 cubeProj[i].edges[j] = parent->cubeProj[i].edges[j] >> 1;
221 }
222
223 cubeProj[i].min = parent->cubeProj[i].min >> 1;
224 cubeProj[i].max = parent->cubeProj[i].max >> 1;
225 }
226}
227
229{
230 int i, j, k;
231 int bmask[3][2] = {{0, 0}, {0, 0}, {0, 0}};
232 unsigned char boxmask = 0;
233 int64_t child_len = cubeProj[0].edges[0] >> 1;
234
235 for (i = 0; i < 3; i++) {
236 int64_t mid = cubeProj[i].origin + child_len;
237
238 // Check bounding box
239 if (mid >= inherit->tri_proj[i][0]) {
240 bmask[i][0] = 1;
241 }
242 if (mid < inherit->tri_proj[i][1]) {
243 bmask[i][1] = 1;
244 }
245 }
246
247 // Fill in masks
248 int ct = 0;
249 for (i = 0; i < 2; i++) {
250 for (j = 0; j < 2; j++) {
251 for (k = 0; k < 2; k++) {
252 boxmask |= ((bmask[0][i] & bmask[1][j] & bmask[2][k]) << ct);
253 ct++;
254 }
255 }
256 }
257
258 // Return bounding box masks
259 return boxmask;
260}
261
265void CubeTriangleIsect::shift(const int off[3])
266{
267 for (int i = 0; i < NUM_AXES; i++) {
268 cubeProj[i].origin += (off[0] * cubeProj[i].edges[0] + off[1] * cubeProj[i].edges[1] +
269 off[2] * cubeProj[i].edges[2]);
270 }
271}
272
277{
278 for (int i = 0; i < NUM_AXES; i++) {
279 /*
280 int64_t proj0 = cubeProj[i][0] +
281 vertmap[inherit->cubeEnds[i][0]][0] * cubeProj[i][1] +
282 vertmap[inherit->cubeEnds[i][0]][1] * cubeProj[i][2] +
283 vertmap[inherit->cubeEnds[i][0]][2] * cubeProj[i][3] ;
284 int64_t proj1 = cubeProj[i][0] +
285 vertmap[inherit->cubeEnds[i][1]][0] * cubeProj[i][1] +
286 vertmap[inherit->cubeEnds[i][1]][1] * cubeProj[i][2] +
287 vertmap[inherit->cubeEnds[i][1]][2] * cubeProj[i][3] ;
288 */
289
290 int64_t proj0 = cubeProj[i].origin + cubeProj[i].min;
291 int64_t proj1 = cubeProj[i].origin + cubeProj[i].max;
292
293 if (proj0 > inherit->tri_proj[i][1] || proj1 < inherit->tri_proj[i][0]) {
294 return 0;
295 }
296 }
297
298 return 1;
299}
300
302{
303 for (int i = 0; i < NUM_AXES; i++) {
304
305 int64_t proj0 = cubeProj[i].origin;
306 int64_t proj1 = cubeProj[i].origin + cubeProj[i].edges[edgeInd];
307
308 if (proj0 < proj1) {
309 if (proj0 > inherit->tri_proj[i][1] || proj1 < inherit->tri_proj[i][0]) {
310 return 0;
311 }
312 }
313 else {
314 if (proj1 > inherit->tri_proj[i][1] || proj0 < inherit->tri_proj[i][0]) {
315 return 0;
316 }
317 }
318 }
319
320 // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] ) ;
321 return 1;
322}
323
325{
326 int i = 3;
327
328 int64_t proj0 = cubeProj[i].origin;
329 int64_t proj1 = cubeProj[i].origin + cubeProj[i].edges[edgeInd];
330 int64_t proj2 = inherit->tri_proj[i][1];
331 int64_t d = proj1 - proj0;
332 double alpha;
333
334 if (d == 0) {
335 alpha = 0.5;
336 }
337 else {
338 alpha = (double)((proj2 - proj0)) / (double)d;
339
340 if (alpha < 0 || alpha > 1) {
341 alpha = 0.5;
342 }
343 }
344
345 return (float)alpha;
346}
const int edgemap[12][2]
const int centmap[3][3][3][2]
static int64_t dotProduct(const int64_t a[3], const int64_t b[3])
const int vertmap[8][3]
static void create_projection_axes(int64_t axes[NUM_AXES][3], const int64_t tri[3][3])
const int facemap[6][4]
static void crossProduct(int64_t res[3], const int64_t a[3], const int64_t b[3])
#define NUM_AXES
Definition Projections.h:45
const int vertmap[8][3]
long long int int64_t
CubeTriangleIsect()=default
void shift(const int off[3])
int isIntersecting() const
int isIntersectingPrimary(int edgeInd) const
CubeProjection cubeProj[NUM_AXES]
Projections of the cube vertices.
Definition Projections.h:78
unsigned char getBoxMask()
TriangleProjection * inherit
Inheritable portion.
Definition Projections.h:75
float getIntersectionPrimary(int edgeInd) const
VecBase< float, D > normalize(VecOp< float, D >) RET
#define sqrt
#define min(a, b)
Definition sort.cc:36
int64_t edges[3]
Definition Projections.h:65
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251