Blender V4.3
SilhouetteGeomEngine.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008-2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <cstdio>
12#include <cstring>
13
14#include "Silhouette.h"
16
18
19#include "BLI_sys_types.h"
20
21#include "BKE_global.hh"
22
23using namespace std;
24
25namespace Freestyle {
26
27Vec3r SilhouetteGeomEngine::_Viewpoint = Vec3r(0, 0, 0);
28real SilhouetteGeomEngine::_translation[3] = {0, 0, 0};
29real SilhouetteGeomEngine::_modelViewMatrix[4][4] = {
30 {1, 0, 0, 0},
31 {0, 1, 0, 0},
32 {0, 0, 1, 0},
33 {0, 0, 0, 1},
34};
35real SilhouetteGeomEngine::_projectionMatrix[4][4] = {
36 {1, 0, 0, 0},
37 {0, 1, 0, 0},
38 {0, 0, 1, 0},
39 {0, 0, 0, 1},
40};
41real SilhouetteGeomEngine::_transform[4][4] = {
42 {1, 0, 0, 0},
43 {0, 1, 0, 0},
44 {0, 0, 1, 0},
45 {0, 0, 0, 1},
46};
47int SilhouetteGeomEngine::_viewport[4] = {1, 1, 1, 1};
48real SilhouetteGeomEngine::_Focal = 0.0;
49
50real SilhouetteGeomEngine::_glProjectionMatrix[4][4] = {
51 {1, 0, 0, 0},
52 {0, 1, 0, 0},
53 {0, 0, 1, 0},
54 {0, 0, 0, 1},
55};
56real SilhouetteGeomEngine::_glModelViewMatrix[4][4] = {
57 {1, 0, 0, 0},
58 {0, 1, 0, 0},
59 {0, 0, 1, 0},
60 {0, 0, 0, 1},
61};
62real SilhouetteGeomEngine::_znear = 0.0;
63real SilhouetteGeomEngine::_zfar = 100.0;
64bool SilhouetteGeomEngine::_isOrthographicProjection = false;
65
66SilhouetteGeomEngine *SilhouetteGeomEngine::_pInstance = nullptr;
67
68void SilhouetteGeomEngine::setTransform(const real iModelViewMatrix[4][4],
69 const real iProjectionMatrix[4][4],
70 const int iViewport[4],
71 real iFocal)
72{
73 uint i, j;
74 _translation[0] = iModelViewMatrix[3][0];
75 _translation[1] = iModelViewMatrix[3][1];
76 _translation[2] = iModelViewMatrix[3][2];
77
78 for (i = 0; i < 4; i++) {
79 for (j = 0; j < 4; j++) {
80 _modelViewMatrix[i][j] = iModelViewMatrix[j][i];
81 _glModelViewMatrix[i][j] = iModelViewMatrix[i][j];
82 }
83 }
84
85 for (i = 0; i < 4; i++) {
86 for (j = 0; j < 4; j++) {
87 _projectionMatrix[i][j] = iProjectionMatrix[j][i];
88 _glProjectionMatrix[i][j] = iProjectionMatrix[i][j];
89 }
90 }
91
92 for (i = 0; i < 4; i++) {
93 for (j = 0; j < 4; j++) {
94 _transform[i][j] = 0;
95 for (uint k = 0; k < 4; k++) {
96 _transform[i][j] += _projectionMatrix[i][k] * _modelViewMatrix[k][j];
97 }
98 }
99 }
100
101 for (i = 0; i < 4; i++) {
102 _viewport[i] = iViewport[i];
103 }
104 _Focal = iFocal;
105
106 _isOrthographicProjection = (iProjectionMatrix[3][3] != 0.0);
107}
108
110{
111 _znear = iZNear;
112 _zfar = iZFar;
113}
114
116{
117 memcpy(viewport, _viewport, sizeof(int[4]));
118}
119
120void SilhouetteGeomEngine::ProjectSilhouette(vector<SVertex *> &ioVertices)
121{
122 Vec3r newPoint;
123 vector<SVertex *>::iterator sv, svend;
124 for (sv = ioVertices.begin(), svend = ioVertices.end(); sv != svend; sv++) {
126 (*sv)->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport);
127 (*sv)->setPoint2D(newPoint);
128 }
129}
130
132{
133 Vec3r newPoint;
135 ioVertex->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport);
136 ioVertex->setPoint2D(newPoint);
137}
138
140{
141 if (_isOrthographicProjection) {
142 return t;
143 }
144
145 // we need to compute for each parameter t the corresponding parameter T which gives the
146 // intersection in 3D.
147 real T;
148
149 // suffix w for world, c for camera, r for retina, i for image
150 Vec3r Aw = (fe)->vertexA()->point3D();
151 Vec3r Bw = (fe)->vertexB()->point3D();
152 Vec3r Ac, Bc;
153 GeomUtils::fromWorldToCamera(Aw, Ac, _modelViewMatrix);
154 GeomUtils::fromWorldToCamera(Bw, Bc, _modelViewMatrix);
155 Vec3r ABc = Bc - Ac;
156#if 0
157 if (G.debug & G_DEBUG_FREESTYLE) {
158 cout << "Ac " << Ac << endl;
159 cout << "Bc " << Bc << endl;
160 cout << "ABc " << ABc << endl;
161 }
162#endif
163 Vec3r Ai = (fe)->vertexA()->point2D();
164 Vec3r Bi = (fe)->vertexB()->point2D();
165 Vec3r Ii = Ai + t * (Bi - Ai); // the intersection point in the 2D image space
166 Vec3r Ir, Ic;
167 GeomUtils::fromImageToRetina(Ii, Ir, _viewport);
168
169 real alpha, beta, denom;
170 real m11 = _projectionMatrix[0][0];
171 real m13 = _projectionMatrix[0][2];
172 real m22 = _projectionMatrix[1][1];
173 real m23 = _projectionMatrix[1][2];
174
175 if (fabs(ABc[0]) > 1.0e-6) {
176 alpha = ABc[2] / ABc[0];
177 beta = Ac[2] - alpha * Ac[0];
178 denom = alpha * (Ir[0] + m13) + m11;
179 if (fabs(denom) < 1.0e-6) {
180 goto iter;
181 }
182 Ic[0] = -beta * (Ir[0] + m13) / denom;
183#if 0
184 Ic[1] = -(Ir[1] + m23) * (alpha * Ic[0] + beta) / m22;
185 Ic[2] = alpha * (Ic[0] - Ac[0]) + Ac[2];
186#endif
187 T = (Ic[0] - Ac[0]) / ABc[0];
188 }
189 else if (fabs(ABc[1]) > 1.0e-6) {
190 alpha = ABc[2] / ABc[1];
191 beta = Ac[2] - alpha * Ac[1];
192 denom = alpha * (Ir[1] + m23) + m22;
193 if (fabs(denom) < 1.0e-6) {
194 goto iter;
195 }
196 Ic[1] = -beta * (Ir[1] + m23) / denom;
197#if 0
198 Ic[0] = -(Ir[0] + m13) * (alpha * Ic[1] + beta) / m11;
199 Ic[2] = alpha * (Ic[1] - Ac[1]) + Ac[2];
200#endif
201 T = (Ic[1] - Ac[1]) / ABc[1];
202 }
203 else {
204 iter:
205 bool x_coords, less_than;
206 if (fabs(Bi[0] - Ai[0]) > 1.0e-6) {
207 x_coords = true;
208 less_than = Ai[0] < Bi[0];
209 }
210 else {
211 x_coords = false;
212 less_than = Ai[1] < Bi[1];
213 }
214 Vec3r Pc, Pr, Pi;
215 real T_sta = 0.0;
216 real T_end = 1.0;
217 real delta_x, delta_y, dist, dist_threshold = 1.0e-6;
218 int i, max_iters = 100;
219 for (i = 0; i < max_iters; i++) {
220 T = T_sta + 0.5 * (T_end - T_sta);
221 Pc = Ac + T * ABc;
222 GeomUtils::fromCameraToRetina(Pc, Pr, _projectionMatrix);
223 GeomUtils::fromRetinaToImage(Pr, Pi, _viewport);
224 delta_x = Ii[0] - Pi[0];
225 delta_y = Ii[1] - Pi[1];
226 dist = sqrt(delta_x * delta_x + delta_y * delta_y);
227 if (dist < dist_threshold) {
228 break;
229 }
230 if (x_coords) {
231 if (less_than) {
232 if (Pi[0] < Ii[0]) {
233 T_sta = T;
234 }
235 else {
236 T_end = T;
237 }
238 }
239 else {
240 if (Pi[0] > Ii[0]) {
241 T_sta = T;
242 }
243 else {
244 T_end = T;
245 }
246 }
247 }
248 else {
249 if (less_than) {
250 if (Pi[1] < Ii[1]) {
251 T_sta = T;
252 }
253 else {
254 T_end = T;
255 }
256 }
257 else {
258 if (Pi[1] > Ii[1]) {
259 T_sta = T;
260 }
261 else {
262 T_end = T;
263 }
264 }
265 }
266 }
267#if 0
268 if (G.debug & G_DEBUG_FREESTYLE) {
269 cout << "SilhouetteGeomEngine::ImageToWorldParameter(): #iters = " << i
270 << ", dist = " << dist << "\n";
271 }
272#endif
273 if (i == max_iters && G.debug & G_DEBUG_FREESTYLE) {
274 cout << "SilhouetteGeomEngine::ImageToWorldParameter(): reached to max_iters (dist = "
275 << dist << ")\n";
276 }
277 }
278
279 return T;
280}
281
283{
284 Vec3r newPoint;
285 GeomUtils::fromWorldToImage(M, newPoint, _transform, _viewport);
286 return newPoint;
287}
288
290{
291 Vec3r newPoint, p;
292 GeomUtils::fromCameraToRetina(M, p, _projectionMatrix);
293 GeomUtils::fromRetinaToImage(p, newPoint, _viewport);
294 return newPoint;
295}
296
297} /* namespace Freestyle */
@ G_DEBUG_FREESTYLE
sqrt(x)+1/max(0
unsigned int uint
Various tools for geometry.
Class to perform all geometric operations dedicated to silhouette. That, for example,...
Classes to define a silhouette structure.
void setPoint2D(const Vec3r &iPoint2D)
Definition Silhouette.h:291
const Vec3r & point3D() const
Definition Silhouette.h:225
static Vec3r CameraToImage(const Vec3r &M)
static void setFrustum(real iZNear, real iZFar)
static void setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4], const int iViewport[4], real iFocal)
static void ProjectSilhouette(std::vector< SVertex * > &ioVertices)
static real ImageToWorldParameter(FEdge *fe, real t)
static Vec3r WorldToImage(const Vec3r &M)
static void retrieveViewport(int viewport[4])
ccl_device_inline float2 fabs(const float2 a)
#define M
#define T
#define G(x, y, z)
void fromRetinaToImage(const Vec3r &p, Vec3r &q, const int viewport[4])
void fromWorldToImage(const Vec3r &p, Vec3r &q, const real model_view_matrix[4][4], const real projection_matrix[4][4], const int viewport[4])
void fromWorldToCamera(const Vec3r &p, Vec3r &q, const real model_view_matrix[4][4])
void fromCameraToRetina(const Vec3r &p, Vec3r &q, const real projection_matrix[4][4])
void fromImageToRetina(const Vec3r &p, Vec3r &q, const int viewport[4])
VecMat::Vec3< real > Vec3r
Definition Geom.h:30
inherits from class Rep
Definition AppCanvas.cpp:20
double real
Definition Precision.h:14
ccl_device_inline float beta(float x, float y)
Definition util/math.h:833