Code cleanup to use array.data() rather than &array[0]
[blender.git] / intern / cycles / render / mesh_subdivision.cpp
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 "mesh.h"
18 #include "attribute.h"
19
20 #include "subd_split.h"
21 #include "subd_patch.h"
22 #include "subd_patch_table.h"
23
24 #include "util_foreach.h"
25
26 CCL_NAMESPACE_BEGIN
27
28 #ifdef WITH_OPENSUBDIV
29
30 CCL_NAMESPACE_END
31
32 #include <opensubdiv/far/topologyRefinerFactory.h>
33 #include <opensubdiv/far/primvarRefiner.h>
34 #include <opensubdiv/far/patchTableFactory.h>
35 #include <opensubdiv/far/patchMap.h>
36
37 /* specializations of TopologyRefinerFactory for ccl::Mesh */
38
39 namespace OpenSubdiv {
40 namespace OPENSUBDIV_VERSION {
41 namespace Far {
42         template<>
43         bool TopologyRefinerFactory<ccl::Mesh>::resizeComponentTopology(TopologyRefiner& refiner, ccl::Mesh const& mesh)
44         {
45                 setNumBaseVertices(refiner, mesh.verts.size());
46                 setNumBaseFaces(refiner, mesh.subd_faces.size());
47
48                 const ccl::Mesh::SubdFace* face = mesh.subd_faces.data();
49
50                 for(int i = 0; i < mesh.subd_faces.size(); i++, face++) {
51                         setNumBaseFaceVertices(refiner, i, face->num_corners);
52                 }
53
54                 return true;
55         }
56
57         template<>
58         bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTopology(TopologyRefiner& refiner, ccl::Mesh const& mesh)
59         {
60                 const ccl::Mesh::SubdFace* face = mesh.subd_faces.data();
61
62                 for(int i = 0; i < mesh.subd_faces.size(); i++, face++) {
63                         IndexArray face_verts = getBaseFaceVertices(refiner, i);
64
65                         int* corner = &mesh.subd_face_corners[face->start_corner];
66
67                         for(int j = 0; j < face->num_corners; j++, corner++) {
68                                 face_verts[j] = *corner;
69                         }
70                 }
71
72                 return true;
73         }
74
75         template<>
76         bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTags(TopologyRefiner& refiner, ccl::Mesh const& mesh)
77         {
78                 const ccl::Mesh::SubdEdgeCrease* crease = mesh.subd_creases.data();
79
80                 for(int i = 0; i < mesh.subd_creases.size(); i++, crease++) {
81                         Index edge = findBaseEdge(refiner, crease->v[0], crease->v[1]);
82
83                         if(edge != INDEX_INVALID) {
84                                 setBaseEdgeSharpness(refiner, edge, crease->crease * 10.0f);
85                         }
86                 }
87
88                 for(int i = 0; i < mesh.verts.size(); i++) {
89                         ConstIndexArray vert_edges = getBaseVertexEdges(refiner, i);
90
91                         if(vert_edges.size() == 2) {
92                                 float sharpness = refiner.getLevel(0).getEdgeSharpness(vert_edges[0]);
93                                 sharpness = std::min(sharpness, refiner.getLevel(0).getEdgeSharpness(vert_edges[1]));
94
95                                 setBaseVertexSharpness(refiner, i, sharpness);
96                         }
97                 }
98
99                 return true;
100         }
101
102         template<>
103         bool TopologyRefinerFactory<ccl::Mesh>::assignFaceVaryingTopology(TopologyRefiner& /*refiner*/, ccl::Mesh const& /*mesh*/)
104         {
105                 return true;
106         }
107
108         template<>
109         void TopologyRefinerFactory<ccl::Mesh>::reportInvalidTopology(TopologyError /*err_code*/,
110                 char const */*msg*/, ccl::Mesh const& /*mesh*/)
111         {
112         }
113 } /* namespace Far */
114 } /* namespace OPENSUBDIV_VERSION */
115 } /* namespace OpenSubdiv */
116
117 CCL_NAMESPACE_BEGIN
118
119 using namespace OpenSubdiv;
120
121 /* struct that implements OpenSubdiv's vertex interface */
122
123 template<typename T>
124 struct OsdValue {
125         T value;
126
127         OsdValue() {}
128
129         void Clear(void* = 0) {
130                 memset(&value, 0, sizeof(T));
131         }
132
133         void AddWithWeight(OsdValue<T> const& src, float weight) {
134                 value += src.value * weight;
135         }
136 };
137
138 template<>
139 void OsdValue<uchar4>::AddWithWeight(OsdValue<uchar4> const& src, float weight)
140 {
141         for(int i = 0; i < 4; i++) {
142                 value[i] += (uchar)(src.value[i] * weight);
143         }
144 }
145
146 /* class for holding OpenSubdiv data used during tessellation */
147
148 class OsdData {
149         Mesh* mesh;
150         vector<OsdValue<float3> > verts;
151         Far::TopologyRefiner* refiner;
152         Far::PatchTable* patch_table;
153         Far::PatchMap* patch_map;
154
155 public:
156         OsdData() : mesh(NULL), refiner(NULL), patch_table(NULL), patch_map(NULL) {}
157
158         ~OsdData()
159         {
160                 delete refiner;
161                 delete patch_table;
162                 delete patch_map;
163         }
164
165         void build_from_mesh(Mesh* mesh_)
166         {
167                 mesh = mesh_;
168
169                 /* type and options */
170                 Sdc::SchemeType type = Sdc::SCHEME_CATMARK;
171
172                 Sdc::Options options;
173                 options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY);
174
175                 /* create refiner */
176                 refiner = Far::TopologyRefinerFactory<Mesh>::Create(*mesh,
177                                 Far::TopologyRefinerFactory<Mesh>::Options(type, options));
178
179                 /* adaptive refinement */
180                 int max_isolation = 10;
181                 refiner->RefineAdaptive(Far::TopologyRefiner::AdaptiveOptions(max_isolation));
182
183                 /* create patch table */
184                 Far::PatchTableFactory::Options patch_options;
185                 patch_options.endCapType = Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
186
187                 patch_table = Far::PatchTableFactory::Create(*refiner, patch_options);
188
189                 /* interpolate verts */
190                 int num_refiner_verts = refiner->GetNumVerticesTotal();
191                 int num_local_points = patch_table->GetNumLocalPoints();
192
193                 verts.resize(num_refiner_verts + num_local_points);
194                 for(int i = 0; i < mesh->verts.size(); i++) {
195                         verts[i].value = mesh->verts[i];
196                 }
197
198                 OsdValue<float3>* src = verts.data();
199                 for(int i = 0; i < refiner->GetMaxLevel(); i++) {
200                         OsdValue<float3>* dest = src + refiner->GetLevel(i).GetNumVertices();
201                         Far::PrimvarRefiner(*refiner).Interpolate(i+1, src, dest);
202                         src = dest;
203                 }
204
205                 patch_table->ComputeLocalPointValues(&verts[0], &verts[num_refiner_verts]);
206
207                 /* create patch map */
208                 patch_map = new Far::PatchMap(*patch_table);
209         }
210
211         void subdivide_attribute(Attribute& attr)
212         {
213                 Far::PrimvarRefiner primvar_refiner(*refiner);
214
215                 if(attr.element == ATTR_ELEMENT_VERTEX) {
216                         int num_refiner_verts = refiner->GetNumVerticesTotal();
217                         int num_local_points = patch_table->GetNumLocalPoints();
218
219                         attr.resize(num_refiner_verts + num_local_points);
220                         attr.flags |= ATTR_FINAL_SIZE;
221
222                         char* src = attr.buffer.data();
223
224                         for(int i = 0; i < refiner->GetMaxLevel(); i++) {
225                                 char* dest = src + refiner->GetLevel(i).GetNumVertices() * attr.data_sizeof();
226
227                                 if(attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
228                                         primvar_refiner.Interpolate(i+1, (OsdValue<float>*)src, (OsdValue<float>*&)dest);
229                                 }
230                                 else {
231                                         primvar_refiner.Interpolate(i+1, (OsdValue<float4>*)src, (OsdValue<float4>*&)dest);
232                                 }
233
234                                 src = dest;
235                         }
236
237                         if(attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
238                                 patch_table->ComputeLocalPointValues((OsdValue<float>*)&attr.buffer[0],
239                                                                          (OsdValue<float>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
240                         }
241                         else {
242                                 patch_table->ComputeLocalPointValues((OsdValue<float4>*)&attr.buffer[0],
243                                                                          (OsdValue<float4>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
244                         }
245                 }
246                 else if(attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) {
247                         // TODO(mai): fvar interpolation
248                 }
249         }
250
251         friend struct OsdPatch;
252         friend class Mesh;
253 };
254
255 /* ccl::Patch implementation that uses OpenSubdiv for eval */
256
257 struct OsdPatch : Patch {
258         OsdData* osd_data;
259
260         OsdPatch(OsdData* data) : osd_data(data) {}
261
262         void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
263         {
264                 const Far::PatchTable::PatchHandle* handle = osd_data->patch_map->FindPatch(patch_index, u, v);
265                 assert(handle);
266
267                 float p_weights[20], du_weights[20], dv_weights[20];
268                 osd_data->patch_table->EvaluateBasis(*handle, u, v, p_weights, du_weights, dv_weights);
269
270                 Far::ConstIndexArray cv = osd_data->patch_table->GetPatchVertices(*handle);
271
272                 float3 du, dv;
273                 if(P) *P = make_float3(0.0f, 0.0f, 0.0f);
274                 du = make_float3(0.0f, 0.0f, 0.0f);
275                 dv = make_float3(0.0f, 0.0f, 0.0f);
276
277                 for(int i = 0; i < cv.size(); i++) {
278                         float3 p = osd_data->verts[cv[i]].value;
279
280                         if(P) *P += p * p_weights[i];
281                         du += p * du_weights[i];
282                         dv += p * dv_weights[i];
283                 }
284
285                 if(dPdu) *dPdu = du;
286                 if(dPdv) *dPdv = dv;
287                 if(N) *N = normalize(cross(du, dv));
288         }
289
290         BoundBox bound() { return BoundBox::empty; }
291 };
292
293 #endif
294
295 void Mesh::tessellate(DiagSplit *split)
296 {
297 #ifdef WITH_OPENSUBDIV
298         OsdData osd_data;
299         bool need_packed_patch_table = false;
300
301         if(subdivision_type == SUBDIVISION_CATMULL_CLARK) {
302                 osd_data.build_from_mesh(this);
303         }
304         else
305 #endif
306         {
307                 /* force linear subdivision if OpenSubdiv is unavailable to avoid
308                  * falling into catmull-clark code paths by accident
309                  */
310                 subdivision_type = SUBDIVISION_LINEAR;
311
312                 /* force disable attribute subdivision for same reason as above */
313                 foreach(Attribute& attr, subd_attributes.attributes) {
314                         attr.flags &= ~ATTR_SUBDIVIDED;
315                 }
316         }
317
318         int num_faces = subd_faces.size();
319
320         Attribute *attr_vN = subd_attributes.find(ATTR_STD_VERTEX_NORMAL);
321         float3* vN = attr_vN->data_float3();
322
323         for(int f = 0; f < num_faces; f++) {
324                 SubdFace& face = subd_faces[f];
325
326                 if(face.is_quad()) {
327                         /* quad */
328                         QuadDice::SubPatch subpatch;
329
330                         LinearQuadPatch quad_patch;
331 #ifdef WITH_OPENSUBDIV
332                         OsdPatch osd_patch(&osd_data);
333
334                         if(subdivision_type == SUBDIVISION_CATMULL_CLARK) {
335                                 osd_patch.patch_index = face.ptex_offset;
336
337                                 subpatch.patch = &osd_patch;
338                         }
339                         else
340 #endif
341                         {
342                                 float3 *hull = quad_patch.hull;
343                                 float3 *normals = quad_patch.normals;
344
345                                 quad_patch.patch_index = face.ptex_offset;
346
347                                 for(int i = 0; i < 4; i++) {
348                                         hull[i] = verts[subd_face_corners[face.start_corner+i]];
349                                 }
350
351                                 if(face.smooth) {
352                                         for(int i = 0; i < 4; i++) {
353                                                 normals[i] = vN[subd_face_corners[face.start_corner+i]];
354                                         }
355                                 }
356                                 else {
357                                         float3 N = face.normal(this);
358                                         for(int i = 0; i < 4; i++) {
359                                                 normals[i] = N;
360                                         }
361                                 }
362
363                                 swap(hull[2], hull[3]);
364                                 swap(normals[2], normals[3]);
365
366                                 subpatch.patch = &quad_patch;
367                         }
368
369                         subpatch.patch->shader = face.shader;
370
371                         /* Quad faces need to be split at least once to line up with split ngons, we do this
372                          * here in this manner because if we do it later edge factors may end up slightly off.
373                          */
374                         subpatch.P00 = make_float2(0.0f, 0.0f);
375                         subpatch.P10 = make_float2(0.5f, 0.0f);
376                         subpatch.P01 = make_float2(0.0f, 0.5f);
377                         subpatch.P11 = make_float2(0.5f, 0.5f);
378                         split->split_quad(subpatch.patch, &subpatch);
379
380                         subpatch.P00 = make_float2(0.5f, 0.0f);
381                         subpatch.P10 = make_float2(1.0f, 0.0f);
382                         subpatch.P01 = make_float2(0.5f, 0.5f);
383                         subpatch.P11 = make_float2(1.0f, 0.5f);
384                         split->split_quad(subpatch.patch, &subpatch);
385
386                         subpatch.P00 = make_float2(0.0f, 0.5f);
387                         subpatch.P10 = make_float2(0.5f, 0.5f);
388                         subpatch.P01 = make_float2(0.0f, 1.0f);
389                         subpatch.P11 = make_float2(0.5f, 1.0f);
390                         split->split_quad(subpatch.patch, &subpatch);
391
392                         subpatch.P00 = make_float2(0.5f, 0.5f);
393                         subpatch.P10 = make_float2(1.0f, 0.5f);
394                         subpatch.P01 = make_float2(0.5f, 1.0f);
395                         subpatch.P11 = make_float2(1.0f, 1.0f);
396                         split->split_quad(subpatch.patch, &subpatch);
397                 }
398                 else {
399                         /* ngon */
400 #ifdef WITH_OPENSUBDIV
401                         if(subdivision_type == SUBDIVISION_CATMULL_CLARK) {
402                                 OsdPatch patch(&osd_data);
403
404                                 patch.shader = face.shader;
405
406                                 for(int corner = 0; corner < face.num_corners; corner++) {
407                                         patch.patch_index = face.ptex_offset + corner;
408
409                                         split->split_quad(&patch);
410                                 }
411                         }
412                         else
413 #endif
414                         {
415                                 float3 center_vert = make_float3(0.0f, 0.0f, 0.0f);
416                                 float3 center_normal = make_float3(0.0f, 0.0f, 0.0f);
417
418                                 float inv_num_corners = 1.0f/float(face.num_corners);
419                                 for(int corner = 0; corner < face.num_corners; corner++) {
420                                         center_vert += verts[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
421                                         center_normal += vN[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
422                                 }
423
424                                 for(int corner = 0; corner < face.num_corners; corner++) {
425                                         LinearQuadPatch patch;
426                                         float3 *hull = patch.hull;
427                                         float3 *normals = patch.normals;
428
429                                         patch.patch_index = face.ptex_offset + corner;
430
431                                         patch.shader = face.shader;
432
433                                         hull[0] = verts[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
434                                         hull[1] = verts[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
435                                         hull[2] = verts[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
436                                         hull[3] = center_vert;
437
438                                         hull[1] = (hull[1] + hull[0]) * 0.5;
439                                         hull[2] = (hull[2] + hull[0]) * 0.5;
440
441                                         if(face.smooth) {
442                                                 normals[0] = vN[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
443                                                 normals[1] = vN[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
444                                                 normals[2] = vN[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
445                                                 normals[3] = center_normal;
446
447                                                 normals[1] = (normals[1] + normals[0]) * 0.5;
448                                                 normals[2] = (normals[2] + normals[0]) * 0.5;
449                                         }
450                                         else {
451                                                 float3 N = face.normal(this);
452                                                 for(int i = 0; i < 4; i++) {
453                                                         normals[i] = N;
454                                                 }
455                                         }
456
457                                         split->split_quad(&patch);
458                                 }
459                         }
460                 }
461         }
462
463         /* interpolate center points for attributes */
464         foreach(Attribute& attr, subd_attributes.attributes) {
465 #ifdef WITH_OPENSUBDIV
466                 if(subdivision_type == SUBDIVISION_CATMULL_CLARK && attr.flags & ATTR_SUBDIVIDED) {
467                         if(attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) {
468                                 /* keep subdivision for corner attributes disabled for now */
469                                 attr.flags &= ~ATTR_SUBDIVIDED;
470                         }
471                         else {
472                                 osd_data.subdivide_attribute(attr);
473
474                                 need_packed_patch_table = true;
475                                 continue;
476                         }
477                 }
478 #endif
479
480                 char* data = attr.data();
481                 size_t stride = attr.data_sizeof();
482                 int ngons = 0;
483
484                 switch(attr.element) {
485                         case ATTR_ELEMENT_VERTEX: {
486                                 for(int f = 0; f < num_faces; f++) {
487                                         SubdFace& face = subd_faces[f];
488
489                                         if(!face.is_quad()) {
490                                                 char* center = data + (verts.size() - num_subd_verts + ngons) * stride;
491                                                 attr.zero_data(center);
492
493                                                 float inv_num_corners = 1.0f / float(face.num_corners);
494
495                                                 for(int corner = 0; corner < face.num_corners; corner++) {
496                                                         attr.add_with_weight(center,
497                                                                              data + subd_face_corners[face.start_corner + corner] * stride,
498                                                                              inv_num_corners);
499                                                 }
500
501                                                 ngons++;
502                                         }
503                                 }
504                         } break;
505                         case ATTR_ELEMENT_VERTEX_MOTION: {
506                                 // TODO(mai): implement
507                         } break;
508                         case ATTR_ELEMENT_CORNER: {
509                                 for(int f = 0; f < num_faces; f++) {
510                                         SubdFace& face = subd_faces[f];
511
512                                         if(!face.is_quad()) {
513                                                 char* center = data + (subd_face_corners.size() + ngons) * stride;
514                                                 attr.zero_data(center);
515
516                                                 float inv_num_corners = 1.0f / float(face.num_corners);
517
518                                                 for(int corner = 0; corner < face.num_corners; corner++) {
519                                                         attr.add_with_weight(center,
520                                                                              data + (face.start_corner + corner) * stride,
521                                                                              inv_num_corners);
522                                                 }
523
524                                                 ngons++;
525                                         }
526                                 }
527                         } break;
528                         case ATTR_ELEMENT_CORNER_BYTE: {
529                                 for(int f = 0; f < num_faces; f++) {
530                                         SubdFace& face = subd_faces[f];
531
532                                         if(!face.is_quad()) {
533                                                 uchar* center = (uchar*)data + (subd_face_corners.size() + ngons) * stride;
534
535                                                 float inv_num_corners = 1.0f / float(face.num_corners);
536                                                 float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
537
538                                                 for(int corner = 0; corner < face.num_corners; corner++) {
539                                                         for(int i = 0; i < 4; i++) {
540                                                                 val[i] += float(*(data + (face.start_corner + corner) * stride + i)) * inv_num_corners;
541                                                         }
542                                                 }
543
544                                                 for(int i = 0; i < 4; i++) {
545                                                         center[i] = uchar(min(max(val[i], 0.0f), 255.0f));
546                                                 }
547
548                                                 ngons++;
549                                         }
550                                 }
551                         } break;
552                         default: break;
553                 }
554         }
555
556 #ifdef WITH_OPENSUBDIV
557         /* pack patch tables */
558         if(need_packed_patch_table) {
559                 delete patch_table;
560                 patch_table = new PackedPatchTable;
561                 patch_table->pack(osd_data.patch_table);
562         }
563 #endif
564 }
565
566 CCL_NAMESPACE_END
567