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