Blender V4.3
dice.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "scene/camera.h"
6#include "scene/mesh.h"
7
8#include "subd/dice.h"
9#include "subd/patch.h"
10
12
13/* EdgeDice Base */
14
28
29void EdgeDice::reserve(int num_verts, int num_triangles)
30{
31 Mesh *mesh = params.mesh;
32
33 vert_offset = mesh->get_verts().size();
34 tri_offset = mesh->num_triangles();
35
36 mesh->resize_mesh(mesh->get_verts().size() + num_verts, mesh->num_triangles());
37 mesh->reserve_mesh(mesh->get_verts().size() + num_verts, mesh->num_triangles() + num_triangles);
38
39 Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
40
41 mesh_P = mesh->verts.data() + vert_offset;
42 mesh_N = attr_vN->data_float3() + vert_offset;
43
44 params.mesh->num_subd_verts += num_verts;
45}
46
47void EdgeDice::set_vert(Patch *patch, int index, float2 uv)
48{
49 float3 P, N;
50
51 patch->eval(&P, NULL, NULL, &N, uv.x, uv.y);
52
53 assert(index < params.mesh->verts.size());
54
55 mesh_P[index] = P;
56 mesh_N[index] = N;
57 params.mesh->vert_patch_uv[index + vert_offset] = make_float2(uv.x, uv.y);
58}
59
60void EdgeDice::add_triangle(Patch *patch, int v0, int v1, int v2)
61{
62 Mesh *mesh = params.mesh;
63
64 mesh->add_triangle(v0 + vert_offset, v1 + vert_offset, v2 + vert_offset, patch->shader, true);
65 params.mesh->triangle_patch[params.mesh->num_triangles() - 1] = patch->patch_index;
66
67 tri_offset++;
68}
69
71{
72 int Mu = max(sub.edge_u0.T, sub.edge_u1.T);
73 int Mv = max(sub.edge_v0.T, sub.edge_v1.T);
74 Mu = max(Mu, 2);
75 Mv = max(Mv, 2);
76
77 int outer_T = sub.edges[edge].T;
78 int inner_T = ((edge % 2) == 0) ? Mv - 2 : Mu - 2;
79
80 if (inner_T < 0 || outer_T < 0) {
81 return; // XXX avoid crashes for Mu or Mv == 1, missing polygons
82 }
83
84 /* stitch together two arrays of verts with triangles. at each step,
85 * we compare using the next verts on both sides, to find the split
86 * direction with the smallest diagonal, and use that in order to keep
87 * the triangle shape reasonable. */
88 for (size_t i = 0, j = 0; i < inner_T || j < outer_T;) {
89 int v0, v1, v2;
90
91 v0 = sub.get_vert_along_grid_edge(edge, i);
92 v1 = sub.get_vert_along_edge(edge, j);
93
94 if (j == outer_T) {
95 v2 = sub.get_vert_along_grid_edge(edge, ++i);
96 }
97 else if (i == inner_T) {
98 v2 = sub.get_vert_along_edge(edge, ++j);
99 }
100 else {
101 /* length of diagonals */
102 float len1 = len_squared(mesh_P[sub.get_vert_along_grid_edge(edge, i)] -
103 mesh_P[sub.get_vert_along_edge(edge, j + 1)]);
104 float len2 = len_squared(mesh_P[sub.get_vert_along_edge(edge, j)] -
105 mesh_P[sub.get_vert_along_grid_edge(edge, i + 1)]);
106
107 /* use smallest diagonal */
108 if (len1 < len2) {
109 v2 = sub.get_vert_along_edge(edge, ++j);
110 }
111 else {
112 v2 = sub.get_vert_along_grid_edge(edge, ++i);
113 }
114 }
115
116 add_triangle(sub.patch, v1, v0, v2);
117 }
118}
119
120/* QuadDice */
121
122QuadDice::QuadDice(const SubdParams &params_) : EdgeDice(params_) {}
123
124float2 QuadDice::map_uv(Subpatch &sub, float u, float v)
125{
126 /* map UV from subpatch to patch parametric coordinates */
127 float2 d0 = interp(sub.c00, sub.c01, v);
128 float2 d1 = interp(sub.c10, sub.c11, v);
129 return interp(d0, d1, u);
130}
131
133{
134 float2 uv = map_uv(sub, u, v);
135 float3 P;
136
137 sub.patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y);
138 if (params.camera) {
140 }
141
142 return P;
143}
144
145void QuadDice::set_vert(Subpatch &sub, int index, float u, float v)
146{
147 EdgeDice::set_vert(sub.patch, index, map_uv(sub, u, v));
148}
149
150void QuadDice::set_side(Subpatch &sub, int edge)
151{
152 int t = sub.edges[edge].T;
153
154 /* set verts on the edge of the patch */
155 for (int i = 0; i < t; i++) {
156 float f = i / (float)t;
157
158 float u, v;
159 switch (edge) {
160 case 0:
161 u = 0;
162 v = f;
163 break;
164 case 1:
165 u = f;
166 v = 1;
167 break;
168 case 2:
169 u = 1;
170 v = 1.0f - f;
171 break;
172 case 3:
173 default:
174 u = 1.0f - f;
175 v = 0;
176 break;
177 }
178
179 set_vert(sub, sub.get_vert_along_edge(edge, i), u, v);
180 }
181}
182
183float QuadDice::quad_area(const float3 &a, const float3 &b, const float3 &c, const float3 &d)
184{
185 return triangle_area(a, b, d) + triangle_area(a, d, c);
186}
187
188float QuadDice::scale_factor(Subpatch &sub, int Mu, int Mv)
189{
190 /* estimate area as 4x largest of 4 quads */
191 float3 P[3][3];
192
193 for (int i = 0; i < 3; i++) {
194 for (int j = 0; j < 3; j++) {
195 P[i][j] = eval_projected(sub, i * 0.5f, j * 0.5f);
196 }
197 }
198
199 float A1 = quad_area(P[0][0], P[1][0], P[0][1], P[1][1]);
200 float A2 = quad_area(P[1][0], P[2][0], P[1][1], P[2][1]);
201 float A3 = quad_area(P[0][1], P[1][1], P[0][2], P[1][2]);
202 float A4 = quad_area(P[1][1], P[2][1], P[1][2], P[2][2]);
203 float Apatch = max(A1, max(A2, max(A3, A4))) * 4.0f;
204
205 /* solve for scaling factor */
206 float Atri = params.dicing_rate * params.dicing_rate * 0.5f;
207 float Ntris = Apatch / Atri;
208
209 // XXX does the -sqrt solution matter
210 // XXX max(D, 0.0) is highly suspicious, need to test cases
211 // where D goes negative
212 float N = 0.5f * (Ntris - (sub.edge_u0.T + sub.edge_u1.T + sub.edge_v0.T + sub.edge_v1.T));
213 float D = 4.0f * N * Mu * Mv + (Mu + Mv) * (Mu + Mv);
214 float S = (Mu + Mv + sqrtf(max(D, 0.0f))) / (2 * Mu * Mv);
215
216 return S;
217}
218
219void QuadDice::add_grid(Subpatch &sub, int Mu, int Mv, int offset)
220{
221 /* create inner grid */
222 float du = 1.0f / (float)Mu;
223 float dv = 1.0f / (float)Mv;
224
225 for (int j = 1; j < Mv; j++) {
226 for (int i = 1; i < Mu; i++) {
227 float u = i * du;
228 float v = j * dv;
229
230 set_vert(sub, offset + (i - 1) + (j - 1) * (Mu - 1), u, v);
231
232 if (i < Mu - 1 && j < Mv - 1) {
233 int i1 = offset + (i - 1) + (j - 1) * (Mu - 1);
234 int i2 = offset + i + (j - 1) * (Mu - 1);
235 int i3 = offset + i + j * (Mu - 1);
236 int i4 = offset + (i - 1) + j * (Mu - 1);
237
238 add_triangle(sub.patch, i1, i2, i3);
239 add_triangle(sub.patch, i1, i3, i4);
240 }
241 }
242 }
243}
244
246{
247 /* compute inner grid size with scale factor */
248 int Mu = max(sub.edge_u0.T, sub.edge_u1.T);
249 int Mv = max(sub.edge_v0.T, sub.edge_v1.T);
250
251#if 0 /* Doesn't work very well, especially at grazing angles. */
252 float S = scale_factor(sub, ef, Mu, Mv);
253#else
254 float S = 1.0f;
255#endif
256
257 Mu = max((int)ceilf(S * Mu), 2); // XXX handle 0 & 1?
258 Mv = max((int)ceilf(S * Mv), 2); // XXX handle 0 & 1?
259
260 /* inner grid */
261 add_grid(sub, Mu, Mv, sub.inner_grid_vert_offset);
262
263 /* sides */
264 set_side(sub, 0);
265 set_side(sub, 1);
266 set_side(sub, 2);
267 set_side(sub, 3);
268
269 stitch_triangles(sub, 0);
270 stitch_triangles(sub, 1);
271 stitch_triangles(sub, 2);
272 stitch_triangles(sub, 3);
273}
274
#define A2
Definition RandGen.cpp:28
#define A1
Definition RandGen.cpp:27
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
Attribute * add(ustring name, TypeDesc type, AttributeElement element)
float3 * data_float3()
void add(const float &f)
void reserve(int num_verts, int num_triangles)
Definition dice.cpp:29
void add_triangle(Patch *patch, int v0, int v1, int v2)
Definition dice.cpp:60
float3 * mesh_N
Definition dice.h:54
size_t vert_offset
Definition dice.h:55
void stitch_triangles(Subpatch &sub, int edge)
Definition dice.cpp:70
size_t tri_offset
Definition dice.h:56
float3 * mesh_P
Definition dice.h:53
SubdParams params
Definition dice.h:52
void set_vert(Patch *patch, int index, float2 uv)
Definition dice.cpp:47
EdgeDice(const SubdParams &params)
Definition dice.cpp:15
AttributeSet attributes
int shader
Definition subd/patch.h:22
int patch_index
Definition subd/patch.h:21
virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)=0
QuadDice(const SubdParams &params)
Definition dice.cpp:122
float scale_factor(Subpatch &sub, int Mu, int Mv)
Definition dice.cpp:188
float2 map_uv(Subpatch &sub, float u, float v)
Definition dice.cpp:124
void add_grid(Subpatch &sub, int Mu, int Mv, int offset)
Definition dice.cpp:219
float3 eval_projected(Subpatch &sub, float u, float v)
Definition dice.cpp:132
void set_vert(Subpatch &sub, int index, float u, float v)
Definition dice.cpp:145
void dice(Subpatch &sub)
Definition dice.cpp:245
float quad_area(const float3 &a, const float3 &b, const float3 &c, const float3 &d)
Definition dice.cpp:183
void set_side(Subpatch &sub, int edge)
Definition dice.cpp:150
int get_vert_along_grid_edge(int edge, int n) const
Definition subpatch.h:96
edge_t edges[4]
Definition subpatch.h:51
float2 c11
Definition subpatch.h:45
int inner_grid_vert_offset
Definition subpatch.h:18
edge_t edge_v1
Definition subpatch.h:53
edge_t edge_u0
Definition subpatch.h:53
float2 c01
Definition subpatch.h:45
class Patch * patch
Definition subpatch.h:17
edge_t edge_u1
Definition subpatch.h:53
edge_t edge_v0
Definition subpatch.h:53
float2 c10
Definition subpatch.h:45
float2 c00
Definition subpatch.h:45
int get_vert_along_edge(int e, int n) const
Definition subpatch.h:200
local_group_size(16, 16) .push_constant(Type b
ccl_device_inline float3 transform_perspective(ccl_private const ProjectionTransform *t, const float3 a)
#define CCL_NAMESPACE_END
#define NULL
#define ceilf(x)
ccl_device_forceinline float2 make_float2(const float x, const float y)
#define sqrtf(x)
#define set_vert(a, b, quarter)
draw_view in_light_buf[] float
static float verts[][3]
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
@ ATTR_STD_VERTEX_NORMAL
@ ATTR_STD_PTEX_FACE_ID
@ ATTR_STD_PTEX_UV
ccl_device_inline float len_squared(const float2 a)
ccl_device_inline float2 interp(const float2 a, const float2 b, float t)
#define N
ProjectionTransform worldtoraster
size_t num_triangles() const
Definition scene/mesh.h:80
void add_triangle(int v0, int v1, int v2, int shader, bool smooth)
bool ptex
Definition dice.h:26
Mesh * mesh
Definition dice.h:25
Camera * camera
Definition dice.h:32
float dicing_rate
Definition dice.h:30
float x
float y
float max
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float triangle_area(ccl_private const float3 &v1, ccl_private const float3 &v2, ccl_private const float3 &v3)
Definition util/math.h:584