Blender V4.3
patch_table.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2014 DreamWorks Animation LLC
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
9#include "subd/patch_table.h"
10#include "kernel/types.h"
11
12#include "util/math.h"
13
14#ifdef WITH_OPENSUBDIV
15# include <opensubdiv/far/patchTable.h>
16#endif
17
19
20#ifdef WITH_OPENSUBDIV
21
22using namespace OpenSubdiv;
23
24/* functions for building patch maps */
25
26struct PatchMapQuadNode {
27 /* sets all the children to point to the patch of index */
28 void set_child(int index)
29 {
30 for (int i = 0; i < 4; i++) {
31 children[i] = index | PATCH_MAP_NODE_IS_SET | PATCH_MAP_NODE_IS_LEAF;
32 }
33 }
34
35 /* sets the child in quadrant to point to the node or patch of the given index */
36 void set_child(unsigned char quadrant, int index, bool is_leaf = true)
37 {
38 assert(quadrant < 4);
39 children[quadrant] = index | PATCH_MAP_NODE_IS_SET | (is_leaf ? PATCH_MAP_NODE_IS_LEAF : 0);
40 }
41
42 uint children[4];
43};
44
45template<class T> static int resolve_quadrant(T &median, T &u, T &v)
46{
47 int quadrant = -1;
48
49 if (u < median) {
50 if (v < median) {
51 quadrant = 0;
52 }
53 else {
54 quadrant = 1;
55 v -= median;
56 }
57 }
58 else {
59 if (v < median) {
60 quadrant = 3;
61 }
62 else {
63 quadrant = 2;
64 v -= median;
65 }
66 u -= median;
67 }
68
69 return quadrant;
70}
71
72static void build_patch_map(PackedPatchTable &table,
73 OpenSubdiv::Far::PatchTable *patch_table,
74 int offset)
75{
76 int num_faces = 0;
77
78 for (int array = 0; array < table.num_arrays; array++) {
79 Far::ConstPatchParamArray params = patch_table->GetPatchParams(array);
80
81 for (int j = 0; j < patch_table->GetNumPatches(array); j++) {
82 num_faces = max(num_faces, (int)params[j].GetFaceId());
83 }
84 }
85 num_faces++;
86
88 quadtree.reserve(num_faces + table.num_patches);
89 quadtree.resize(num_faces);
90
91 /* adjust offsets to make indices relative to the table */
92 int handle_index = -(table.num_patches * PATCH_HANDLE_SIZE);
93 offset += table.total_size();
94
95 /* populate the quadtree from the FarPatchArrays sub-patches */
96 for (int array = 0; array < table.num_arrays; array++) {
97 Far::ConstPatchParamArray params = patch_table->GetPatchParams(array);
98
99 for (int i = 0; i < patch_table->GetNumPatches(array); i++, handle_index += PATCH_HANDLE_SIZE)
100 {
101 const Far::PatchParam &param = params[i];
102 unsigned short depth = param.GetDepth();
103
104 PatchMapQuadNode *node = &quadtree[params[i].GetFaceId()];
105
106 if (depth == (param.NonQuadRoot() ? 1 : 0)) {
107 /* special case : regular BSpline face w/ no sub-patches */
108 node->set_child(handle_index + offset);
109 continue;
110 }
111
112 int u = param.GetU();
113 int v = param.GetV();
114 int pdepth = param.NonQuadRoot() ? depth - 2 : depth - 1;
115 int half = 1 << pdepth;
116
117 for (int j = 0; j < depth; j++) {
118 int delta = half >> 1;
119
120 int quadrant = resolve_quadrant(half, u, v);
121 assert(quadrant >= 0);
122
123 half = delta;
124
125 if (j == pdepth) {
126 /* we have reached the depth of the sub-patch : add a leaf */
127 assert(!(node->children[quadrant] & PATCH_MAP_NODE_IS_SET));
128 node->set_child(quadrant, handle_index + offset, true);
129 break;
130 }
131 else {
132 /* travel down the child node of the corresponding quadrant */
133 if (!(node->children[quadrant] & PATCH_MAP_NODE_IS_SET)) {
134 /* create a new branch in the quadrant */
135 quadtree.push_back(PatchMapQuadNode());
136
137 int idx = (int)quadtree.size() - 1;
138 node->set_child(quadrant, idx * 4 + offset, false);
139
140 node = &quadtree[idx];
141 }
142 else {
143 /* travel down an existing branch */
144 uint idx = node->children[quadrant] & PATCH_MAP_NODE_INDEX_MASK;
145 node = &(quadtree[(idx - offset) / 4]);
146 }
147 }
148 }
149 }
150 }
151
152 /* copy into table */
153 assert(table.table.size() == table.total_size());
154 uint map_offset = table.total_size();
155
156 table.num_nodes = quadtree.size() * 4;
157 table.table.resize(table.total_size());
158
159 uint *data = &table.table[map_offset];
160
161 for (int i = 0; i < quadtree.size(); i++) {
162 for (int j = 0; j < 4; j++) {
163 assert(quadtree[i].children[j] & PATCH_MAP_NODE_IS_SET);
164 *(data++) = quadtree[i].children[j];
165 }
166 }
167}
168
169#endif
170
171/* packed patch table functions */
172
178
179void PackedPatchTable::pack(Far::PatchTable *patch_table, int offset)
180{
181 num_arrays = 0;
182 num_patches = 0;
183 num_indices = 0;
184 num_nodes = 0;
185
186#ifdef WITH_OPENSUBDIV
187 num_arrays = patch_table->GetNumPatchArrays();
188
189 for (int i = 0; i < num_arrays; i++) {
190 int patches = patch_table->GetNumPatches(i);
191 int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices();
192
193 num_patches += patches;
194 num_indices += patches * num_control;
195 }
196
198 uint *data = table.data();
199
200 uint *array = data;
202 uint *param = index + num_indices;
203 uint *handle = param + num_patches * PATCH_PARAM_SIZE;
204
205 uint current_param = 0;
206
207 for (int i = 0; i < num_arrays; i++) {
208 *(array++) = patch_table->GetPatchArrayDescriptor(i).GetType();
209 *(array++) = patch_table->GetNumPatches(i);
210 *(array++) = (index - data) + offset;
211 *(array++) = (param - data) + offset;
212
213 Far::ConstIndexArray indices = patch_table->GetPatchArrayVertices(i);
214
215 for (int j = 0; j < indices.size(); j++) {
216 *(index++) = indices[j];
217 }
218
219 const Far::PatchParamTable &param_table = patch_table->GetPatchParamTable();
220
221 int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices();
222 int patches = patch_table->GetNumPatches(i);
223
224 for (int j = 0; j < patches; j++, current_param++) {
225 *(param++) = param_table[current_param].field0;
226 *(param++) = param_table[current_param].field1;
227
228 *(handle++) = (array - data) - PATCH_ARRAY_SIZE + offset;
229 *(handle++) = (param - data) - PATCH_PARAM_SIZE + offset;
230 *(handle++) = j * num_control;
231 }
232 }
233
234 build_patch_map(*this, patch_table, offset);
235#else
236 (void)patch_table;
237 (void)offset;
238#endif
239}
240
242{
243 uint *src = table.data();
244
245 /* arrays */
246 for (int i = 0; i < num_arrays; i++) {
247 *(dest++) = *(src++);
248 *(dest++) = *(src++);
249 *(dest++) = *(src++) + doffset;
250 *(dest++) = *(src++) + doffset;
251 }
252
253 /* indices */
254 for (int i = 0; i < num_indices; i++) {
255 *(dest++) = *(src++);
256 }
257
258 /* params */
259 for (int i = 0; i < num_patches; i++) {
260 *(dest++) = *(src++);
261 *(dest++) = *(src++);
262 }
263
264 /* handles */
265 for (int i = 0; i < num_patches; i++) {
266 *(dest++) = *(src++) + doffset;
267 *(dest++) = *(src++) + doffset;
268 *(dest++) = *(src++);
269 }
270
271 /* nodes */
272 for (int i = 0; i < num_nodes; i++) {
273 *(dest++) = *(src++) + doffset;
274 }
275}
276
unsigned int uint
ATTR_WARN_UNUSED_RESULT const BMVert * v
T * resize(size_t newsize)
size_t size() const
Definition half.h:42
#define CCL_NAMESPACE_END
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define PATCH_MAP_NODE_IS_SET
#define PATCH_MAP_NODE_IS_LEAF
#define PATCH_MAP_NODE_INDEX_MASK
#define PATCH_NODE_SIZE
Definition patch_table.h:33
#define PATCH_HANDLE_SIZE
Definition patch_table.h:32
#define PATCH_ARRAY_SIZE
Definition patch_table.h:30
#define PATCH_PARAM_SIZE
Definition patch_table.h:31
void pack(Far::PatchTable *patch_table, int offset=0)
void copy_adjusting_offsets(uint *dest, int doffset)
array< uint > table
Definition patch_table.h:36
float max
ccl_device_inline bool is_leaf(const ccl_global KernelLightTreeNode *knode)
Definition tree.h:79