1 /*
2 * Copyright 2011-2016 Blender Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "render/attribute.h"
18 #include "render/camera.h"
19 #include "render/mesh.h"
20
21 #include "subd/subd_patch.h"
22 #include "subd/subd_patch_table.h"
23 #include "subd/subd_split.h"
24
25 #include "util/util_algorithm.h"
26 #include "util/util_foreach.h"
27 #include "util/util_hash.h"
28
29 CCL_NAMESPACE_BEGIN
30
31 #ifdef WITH_OPENSUBDIV
32
33 CCL_NAMESPACE_END
34
35 # include <opensubdiv/far/patchMap.h>
36 # include <opensubdiv/far/patchTableFactory.h>
37 # include <opensubdiv/far/primvarRefiner.h>
38 # include <opensubdiv/far/topologyRefinerFactory.h>
39
40 /* specializations of TopologyRefinerFactory for ccl::Mesh */
41
42 namespace OpenSubdiv {
43 namespace OPENSUBDIV_VERSION {
44 namespace Far {
45 template<>
resizeComponentTopology(TopologyRefiner & refiner,ccl::Mesh const & mesh)46 bool TopologyRefinerFactory<ccl::Mesh>::resizeComponentTopology(TopologyRefiner &refiner,
47 ccl::Mesh const &mesh)
48 {
49 setNumBaseVertices(refiner, mesh.verts.size());
50 setNumBaseFaces(refiner, mesh.subd_faces.size());
51
52 const ccl::Mesh::SubdFace *face = mesh.subd_faces.data();
53
54 for (int i = 0; i < mesh.subd_faces.size(); i++, face++) {
55 setNumBaseFaceVertices(refiner, i, face->num_corners);
56 }
57
58 return true;
59 }
60
61 template<>
assignComponentTopology(TopologyRefiner & refiner,ccl::Mesh const & mesh)62 bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTopology(TopologyRefiner &refiner,
63 ccl::Mesh const &mesh)
64 {
65 const ccl::Mesh::SubdFace *face = mesh.subd_faces.data();
66
67 for (int i = 0; i < mesh.subd_faces.size(); i++, face++) {
68 IndexArray face_verts = getBaseFaceVertices(refiner, i);
69
70 int *corner = &mesh.subd_face_corners[face->start_corner];
71
72 for (int j = 0; j < face->num_corners; j++, corner++) {
73 face_verts[j] = *corner;
74 }
75 }
76
77 return true;
78 }
79
80 template<>
assignComponentTags(TopologyRefiner & refiner,ccl::Mesh const & mesh)81 bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTags(TopologyRefiner &refiner,
82 ccl::Mesh const &mesh)
83 {
84 const ccl::Mesh::SubdEdgeCrease *crease = mesh.subd_creases.data();
85
86 for (int i = 0; i < mesh.subd_creases.size(); i++, crease++) {
87 Index edge = findBaseEdge(refiner, crease->v[0], crease->v[1]);
88
89 if (edge != INDEX_INVALID) {
90 setBaseEdgeSharpness(refiner, edge, crease->crease * 10.0f);
91 }
92 }
93
94 for (int i = 0; i < mesh.verts.size(); i++) {
95 ConstIndexArray vert_edges = getBaseVertexEdges(refiner, i);
96
97 if (vert_edges.size() == 2) {
98 float sharpness = refiner.getLevel(0).getEdgeSharpness(vert_edges[0]);
99 sharpness = ccl::min(sharpness, refiner.getLevel(0).getEdgeSharpness(vert_edges[1]));
100
101 setBaseVertexSharpness(refiner, i, sharpness);
102 }
103 }
104
105 return true;
106 }
107
108 template<>
assignFaceVaryingTopology(TopologyRefiner &,ccl::Mesh const &)109 bool TopologyRefinerFactory<ccl::Mesh>::assignFaceVaryingTopology(TopologyRefiner & /*refiner*/,
110 ccl::Mesh const & /*mesh*/)
111 {
112 return true;
113 }
114
115 template<>
reportInvalidTopology(TopologyError,char const *,ccl::Mesh const &)116 void TopologyRefinerFactory<ccl::Mesh>::reportInvalidTopology(TopologyError /*err_code*/,
117 char const * /*msg*/,
118 ccl::Mesh const & /*mesh*/)
119 {
120 }
121 } /* namespace Far */
122 } /* namespace OPENSUBDIV_VERSION */
123 } /* namespace OpenSubdiv */
124
125 CCL_NAMESPACE_BEGIN
126
127 using namespace OpenSubdiv;
128
129 /* struct that implements OpenSubdiv's vertex interface */
130
131 template<typename T> struct OsdValue {
132 T value;
133
OsdValueOsdValue134 OsdValue()
135 {
136 }
137
ClearOsdValue138 void Clear(void * = 0)
139 {
140 memset(&value, 0, sizeof(T));
141 }
142
AddWithWeightOsdValue143 void AddWithWeight(OsdValue<T> const &src, float weight)
144 {
145 value += src.value * weight;
146 }
147 };
148
AddWithWeight(OsdValue<uchar4> const & src,float weight)149 template<> void OsdValue<uchar4>::AddWithWeight(OsdValue<uchar4> const &src, float weight)
150 {
151 for (int i = 0; i < 4; i++) {
152 value[i] += (uchar)(src.value[i] * weight);
153 }
154 }
155
156 /* class for holding OpenSubdiv data used during tessellation */
157
158 class OsdData {
159 Mesh *mesh;
160 vector<OsdValue<float3>> verts;
161 Far::TopologyRefiner *refiner;
162 Far::PatchTable *patch_table;
163 Far::PatchMap *patch_map;
164
165 public:
OsdData()166 OsdData() : mesh(NULL), refiner(NULL), patch_table(NULL), patch_map(NULL)
167 {
168 }
169
~OsdData()170 ~OsdData()
171 {
172 delete refiner;
173 delete patch_table;
174 delete patch_map;
175 }
176
build_from_mesh(Mesh * mesh_)177 void build_from_mesh(Mesh *mesh_)
178 {
179 mesh = mesh_;
180
181 /* type and options */
182 Sdc::SchemeType type = Sdc::SCHEME_CATMARK;
183
184 Sdc::Options options;
185 options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY);
186
187 /* create refiner */
188 refiner = Far::TopologyRefinerFactory<Mesh>::Create(
189 *mesh, Far::TopologyRefinerFactory<Mesh>::Options(type, options));
190
191 /* adaptive refinement */
192 int max_isolation = calculate_max_isolation();
193 refiner->RefineAdaptive(Far::TopologyRefiner::AdaptiveOptions(max_isolation));
194
195 /* create patch table */
196 Far::PatchTableFactory::Options patch_options;
197 patch_options.endCapType = Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
198
199 patch_table = Far::PatchTableFactory::Create(*refiner, patch_options);
200
201 /* interpolate verts */
202 int num_refiner_verts = refiner->GetNumVerticesTotal();
203 int num_local_points = patch_table->GetNumLocalPoints();
204
205 verts.resize(num_refiner_verts + num_local_points);
206 for (int i = 0; i < mesh->verts.size(); i++) {
207 verts[i].value = mesh->verts[i];
208 }
209
210 OsdValue<float3> *src = verts.data();
211 for (int i = 0; i < refiner->GetMaxLevel(); i++) {
212 OsdValue<float3> *dest = src + refiner->GetLevel(i).GetNumVertices();
213 Far::PrimvarRefiner(*refiner).Interpolate(i + 1, src, dest);
214 src = dest;
215 }
216
217 if (num_local_points) {
218 patch_table->ComputeLocalPointValues(&verts[0], &verts[num_refiner_verts]);
219 }
220
221 /* create patch map */
222 patch_map = new Far::PatchMap(*patch_table);
223 }
224
subdivide_attribute(Attribute & attr)225 void subdivide_attribute(Attribute &attr)
226 {
227 Far::PrimvarRefiner primvar_refiner(*refiner);
228
229 if (attr.element == ATTR_ELEMENT_VERTEX) {
230 int num_refiner_verts = refiner->GetNumVerticesTotal();
231 int num_local_points = patch_table->GetNumLocalPoints();
232
233 attr.resize(num_refiner_verts + num_local_points);
234 attr.flags |= ATTR_FINAL_SIZE;
235
236 char *src = attr.buffer.data();
237
238 for (int i = 0; i < refiner->GetMaxLevel(); i++) {
239 char *dest = src + refiner->GetLevel(i).GetNumVertices() * attr.data_sizeof();
240
241 if (attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
242 primvar_refiner.Interpolate(i + 1, (OsdValue<float> *)src, (OsdValue<float> *&)dest);
243 }
244 else if (attr.same_storage(attr.type, TypeFloat2)) {
245 primvar_refiner.Interpolate(i + 1, (OsdValue<float2> *)src, (OsdValue<float2> *&)dest);
246 }
247 else {
248 primvar_refiner.Interpolate(i + 1, (OsdValue<float4> *)src, (OsdValue<float4> *&)dest);
249 }
250
251 src = dest;
252 }
253
254 if (num_local_points) {
255 if (attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
256 patch_table->ComputeLocalPointValues(
257 (OsdValue<float> *)&attr.buffer[0],
258 (OsdValue<float> *)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
259 }
260 else if (attr.same_storage(attr.type, TypeFloat2)) {
261 patch_table->ComputeLocalPointValues(
262 (OsdValue<float2> *)&attr.buffer[0],
263 (OsdValue<float2> *)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
264 }
265 else {
266 patch_table->ComputeLocalPointValues(
267 (OsdValue<float4> *)&attr.buffer[0],
268 (OsdValue<float4> *)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
269 }
270 }
271 }
272 else if (attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) {
273 // TODO(mai): fvar interpolation
274 }
275 }
276
calculate_max_isolation()277 int calculate_max_isolation()
278 {
279 /* loop over all edges to find longest in screen space */
280 const Far::TopologyLevel &level = refiner->GetLevel(0);
281 Transform objecttoworld = mesh->subd_params->objecttoworld;
282 Camera *cam = mesh->subd_params->camera;
283
284 float longest_edge = 0.0f;
285
286 for (size_t i = 0; i < level.GetNumEdges(); i++) {
287 Far::ConstIndexArray verts = level.GetEdgeVertices(i);
288
289 float3 a = mesh->verts[verts[0]];
290 float3 b = mesh->verts[verts[1]];
291
292 float edge_len;
293
294 if (cam) {
295 a = transform_point(&objecttoworld, a);
296 b = transform_point(&objecttoworld, b);
297
298 edge_len = len(a - b) / cam->world_to_raster_size((a + b) * 0.5f);
299 }
300 else {
301 edge_len = len(a - b);
302 }
303
304 longest_edge = max(longest_edge, edge_len);
305 }
306
307 /* calculate isolation level */
308 int isolation = (int)(log2f(max(longest_edge / mesh->subd_params->dicing_rate, 1.0f)) + 1.0f);
309
310 return min(isolation, 10);
311 }
312
313 friend struct OsdPatch;
314 friend class Mesh;
315 };
316
317 /* ccl::Patch implementation that uses OpenSubdiv for eval */
318
319 struct OsdPatch : Patch {
320 OsdData *osd_data;
321
OsdPatchOsdPatch322 OsdPatch()
323 {
324 }
OsdPatchOsdPatch325 OsdPatch(OsdData *data) : osd_data(data)
326 {
327 }
328
evalOsdPatch329 void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
330 {
331 const Far::PatchTable::PatchHandle *handle = osd_data->patch_map->FindPatch(patch_index, u, v);
332 assert(handle);
333
334 float p_weights[20], du_weights[20], dv_weights[20];
335 osd_data->patch_table->EvaluateBasis(*handle, u, v, p_weights, du_weights, dv_weights);
336
337 Far::ConstIndexArray cv = osd_data->patch_table->GetPatchVertices(*handle);
338
339 float3 du, dv;
340 if (P)
341 *P = make_float3(0.0f, 0.0f, 0.0f);
342 du = make_float3(0.0f, 0.0f, 0.0f);
343 dv = make_float3(0.0f, 0.0f, 0.0f);
344
345 for (int i = 0; i < cv.size(); i++) {
346 float3 p = osd_data->verts[cv[i]].value;
347
348 if (P)
349 *P += p * p_weights[i];
350 du += p * du_weights[i];
351 dv += p * dv_weights[i];
352 }
353
354 if (dPdu)
355 *dPdu = du;
356 if (dPdv)
357 *dPdv = dv;
358 if (N) {
359 *N = cross(du, dv);
360
361 float t = len(*N);
362 *N = (t != 0.0f) ? *N / t : make_float3(0.0f, 0.0f, 1.0f);
363 }
364 }
365 };
366
367 #endif
368
tessellate(DiagSplit * split)369 void Mesh::tessellate(DiagSplit *split)
370 {
371 #ifdef WITH_OPENSUBDIV
372 OsdData osd_data;
373 bool need_packed_patch_table = false;
374
375 if (subdivision_type == SUBDIVISION_CATMULL_CLARK) {
376 if (subd_faces.size()) {
377 osd_data.build_from_mesh(this);
378 }
379 }
380 else
381 #endif
382 {
383 /* force linear subdivision if OpenSubdiv is unavailable to avoid
384 * falling into catmull-clark code paths by accident
385 */
386 subdivision_type = SUBDIVISION_LINEAR;
387
388 /* force disable attribute subdivision for same reason as above */
389 foreach (Attribute &attr, subd_attributes.attributes) {
390 attr.flags &= ~ATTR_SUBDIVIDED;
391 }
392 }
393
394 int num_faces = subd_faces.size();
395
396 Attribute *attr_vN = subd_attributes.find(ATTR_STD_VERTEX_NORMAL);
397 float3 *vN = (attr_vN) ? attr_vN->data_float3() : NULL;
398
399 /* count patches */
400 int num_patches = 0;
401 for (int f = 0; f < num_faces; f++) {
402 SubdFace &face = subd_faces[f];
403
404 if (face.is_quad()) {
405 num_patches++;
406 }
407 else {
408 num_patches += face.num_corners;
409 }
410 }
411
412 /* build patches from faces */
413 #ifdef WITH_OPENSUBDIV
414 if (subdivision_type == SUBDIVISION_CATMULL_CLARK) {
415 vector<OsdPatch> osd_patches(num_patches, &osd_data);
416 OsdPatch *patch = osd_patches.data();
417
418 for (int f = 0; f < num_faces; f++) {
419 SubdFace &face = subd_faces[f];
420
421 if (face.is_quad()) {
422 patch->patch_index = face.ptex_offset;
423 patch->from_ngon = false;
424 patch->shader = face.shader;
425 patch++;
426 }
427 else {
428 for (int corner = 0; corner < face.num_corners; corner++) {
429 patch->patch_index = face.ptex_offset + corner;
430 patch->from_ngon = true;
431 patch->shader = face.shader;
432 patch++;
433 }
434 }
435 }
436
437 /* split patches */
438 split->split_patches(osd_patches.data(), sizeof(OsdPatch));
439 }
440 else
441 #endif
442 {
443 vector<LinearQuadPatch> linear_patches(num_patches);
444 LinearQuadPatch *patch = linear_patches.data();
445
446 for (int f = 0; f < num_faces; f++) {
447 SubdFace &face = subd_faces[f];
448
449 if (face.is_quad()) {
450 float3 *hull = patch->hull;
451 float3 *normals = patch->normals;
452
453 patch->patch_index = face.ptex_offset;
454 patch->from_ngon = false;
455
456 for (int i = 0; i < 4; i++) {
457 hull[i] = verts[subd_face_corners[face.start_corner + i]];
458 }
459
460 if (face.smooth) {
461 for (int i = 0; i < 4; i++) {
462 normals[i] = vN[subd_face_corners[face.start_corner + i]];
463 }
464 }
465 else {
466 float3 N = face.normal(this);
467 for (int i = 0; i < 4; i++) {
468 normals[i] = N;
469 }
470 }
471
472 swap(hull[2], hull[3]);
473 swap(normals[2], normals[3]);
474
475 patch->shader = face.shader;
476 patch++;
477 }
478 else {
479 /* ngon */
480 float3 center_vert = make_float3(0.0f, 0.0f, 0.0f);
481 float3 center_normal = make_float3(0.0f, 0.0f, 0.0f);
482
483 float inv_num_corners = 1.0f / float(face.num_corners);
484 for (int corner = 0; corner < face.num_corners; corner++) {
485 center_vert += verts[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
486 center_normal += vN[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
487 }
488
489 for (int corner = 0; corner < face.num_corners; corner++) {
490 float3 *hull = patch->hull;
491 float3 *normals = patch->normals;
492
493 patch->patch_index = face.ptex_offset + corner;
494 patch->from_ngon = true;
495
496 patch->shader = face.shader;
497
498 hull[0] =
499 verts[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
500 hull[1] =
501 verts[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
502 hull[2] =
503 verts[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
504 hull[3] = center_vert;
505
506 hull[1] = (hull[1] + hull[0]) * 0.5;
507 hull[2] = (hull[2] + hull[0]) * 0.5;
508
509 if (face.smooth) {
510 normals[0] =
511 vN[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
512 normals[1] =
513 vN[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
514 normals[2] =
515 vN[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
516 normals[3] = center_normal;
517
518 normals[1] = (normals[1] + normals[0]) * 0.5;
519 normals[2] = (normals[2] + normals[0]) * 0.5;
520 }
521 else {
522 float3 N = face.normal(this);
523 for (int i = 0; i < 4; i++) {
524 normals[i] = N;
525 }
526 }
527
528 patch++;
529 }
530 }
531 }
532
533 /* split patches */
534 split->split_patches(linear_patches.data(), sizeof(LinearQuadPatch));
535 }
536
537 /* interpolate center points for attributes */
538 foreach (Attribute &attr, subd_attributes.attributes) {
539 #ifdef WITH_OPENSUBDIV
540 if (subdivision_type == SUBDIVISION_CATMULL_CLARK && attr.flags & ATTR_SUBDIVIDED) {
541 if (attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) {
542 /* keep subdivision for corner attributes disabled for now */
543 attr.flags &= ~ATTR_SUBDIVIDED;
544 }
545 else if (subd_faces.size()) {
546 osd_data.subdivide_attribute(attr);
547
548 need_packed_patch_table = true;
549 continue;
550 }
551 }
552 #endif
553
554 char *data = attr.data();
555 size_t stride = attr.data_sizeof();
556 int ngons = 0;
557
558 switch (attr.element) {
559 case ATTR_ELEMENT_VERTEX: {
560 for (int f = 0; f < num_faces; f++) {
561 SubdFace &face = subd_faces[f];
562
563 if (!face.is_quad()) {
564 char *center = data + (verts.size() - num_subd_verts + ngons) * stride;
565 attr.zero_data(center);
566
567 float inv_num_corners = 1.0f / float(face.num_corners);
568
569 for (int corner = 0; corner < face.num_corners; corner++) {
570 attr.add_with_weight(center,
571 data + subd_face_corners[face.start_corner + corner] * stride,
572 inv_num_corners);
573 }
574
575 ngons++;
576 }
577 }
578 } break;
579 case ATTR_ELEMENT_VERTEX_MOTION: {
580 // TODO(mai): implement
581 } break;
582 case ATTR_ELEMENT_CORNER: {
583 for (int f = 0; f < num_faces; f++) {
584 SubdFace &face = subd_faces[f];
585
586 if (!face.is_quad()) {
587 char *center = data + (subd_face_corners.size() + ngons) * stride;
588 attr.zero_data(center);
589
590 float inv_num_corners = 1.0f / float(face.num_corners);
591
592 for (int corner = 0; corner < face.num_corners; corner++) {
593 attr.add_with_weight(
594 center, data + (face.start_corner + corner) * stride, inv_num_corners);
595 }
596
597 ngons++;
598 }
599 }
600 } break;
601 case ATTR_ELEMENT_CORNER_BYTE: {
602 for (int f = 0; f < num_faces; f++) {
603 SubdFace &face = subd_faces[f];
604
605 if (!face.is_quad()) {
606 uchar *center = (uchar *)data + (subd_face_corners.size() + ngons) * stride;
607
608 float inv_num_corners = 1.0f / float(face.num_corners);
609 float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
610
611 for (int corner = 0; corner < face.num_corners; corner++) {
612 for (int i = 0; i < 4; i++) {
613 val[i] += float(*(data + (face.start_corner + corner) * stride + i)) *
614 inv_num_corners;
615 }
616 }
617
618 for (int i = 0; i < 4; i++) {
619 center[i] = uchar(min(max(val[i], 0.0f), 255.0f));
620 }
621
622 ngons++;
623 }
624 }
625 } break;
626 default:
627 break;
628 }
629 }
630
631 #ifdef WITH_OPENSUBDIV
632 /* pack patch tables */
633 if (need_packed_patch_table) {
634 delete patch_table;
635 patch_table = new PackedPatchTable;
636 patch_table->pack(osd_data.patch_table);
637 }
638 #endif
639 }
640
641 CCL_NAMESPACE_END
642