Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMai Lavelle <mai.lavelle@gmail.com>2016-07-17 02:42:28 +0300
committerMai Lavelle <mai.lavelle@gmail.com>2016-07-29 10:36:30 +0300
commitc96ae81160ad1a943fafaca44a7d5e97c2d7a0d7 (patch)
tree83905d5a6bf2583f44d9dcf90410b5a0c024822c /intern/cycles/render/mesh_subdivision.cpp
parentf74645578c9dd38c2543d1211b779a019363b04f (diff)
Cycles microdisplacement: ngons and attributes for subdivision meshes
This adds support for ngons and attributes on subdivision meshes. Ngons are needed for proper attribute interpolation as well as correct Catmull-Clark subdivision. Several changes are made to achieve this: - new primitive `SubdFace` added to `Mesh` - 3 more textures are used to store info on patches from subd meshes - Blender export uses loop interface instead of tessface for subd meshes - `Attribute` class is updated with a simplified way to pass primitive counts around and to support ngons. - extra points for ngons are generated for O(1) attribute interpolation - curves are temporally disabled on subd meshes to avoid various bugs with implementation - old unneeded code is removed from `subd/` - various fixes and improvements Reviewed By: brecht Differential Revision: https://developer.blender.org/D2108
Diffstat (limited to 'intern/cycles/render/mesh_subdivision.cpp')
-rw-r--r--intern/cycles/render/mesh_subdivision.cpp224
1 files changed, 224 insertions, 0 deletions
diff --git a/intern/cycles/render/mesh_subdivision.cpp b/intern/cycles/render/mesh_subdivision.cpp
new file mode 100644
index 00000000000..fe8e41e8d35
--- /dev/null
+++ b/intern/cycles/render/mesh_subdivision.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mesh.h"
+#include "attribute.h"
+
+#include "subd_split.h"
+#include "subd_patch.h"
+
+#include "util_foreach.h"
+
+CCL_NAMESPACE_BEGIN
+
+void Mesh::tessellate(DiagSplit *split)
+{
+ int num_faces = subd_faces.size();
+
+ Attribute *attr_vN = subd_attributes.find(ATTR_STD_VERTEX_NORMAL);
+ float3* vN = attr_vN->data_float3();
+
+ for(int f = 0; f < num_faces; f++) {
+ SubdFace& face = subd_faces[f];
+
+ if(face.is_quad()) {
+ /* quad */
+ LinearQuadPatch patch;
+ float3 *hull = patch.hull;
+ float3 *normals = patch.normals;
+
+ patch.patch_index = face.ptex_offset;
+ patch.shader = face.shader;
+
+ for(int i = 0; i < 4; i++) {
+ hull[i] = verts[subd_face_corners[face.start_corner+i]];
+ }
+
+ if(face.smooth) {
+ for(int i = 0; i < 4; i++) {
+ normals[i] = vN[subd_face_corners[face.start_corner+i]];
+ }
+ }
+ else {
+ float3 N = face.normal(this);
+ for(int i = 0; i < 4; i++) {
+ normals[i] = N;
+ }
+ }
+
+ swap(hull[2], hull[3]);
+ swap(normals[2], normals[3]);
+
+ /* Quad faces need to be split at least once to line up with split ngons, we do this
+ * here in this manner because if we do it later edge factors may end up slightly off.
+ */
+ QuadDice::SubPatch subpatch;
+ subpatch.patch = &patch;
+
+ subpatch.P00 = make_float2(0.0f, 0.0f);
+ subpatch.P10 = make_float2(0.5f, 0.0f);
+ subpatch.P01 = make_float2(0.0f, 0.5f);
+ subpatch.P11 = make_float2(0.5f, 0.5f);
+ split->split_quad(&patch, &subpatch);
+
+ subpatch.P00 = make_float2(0.5f, 0.0f);
+ subpatch.P10 = make_float2(1.0f, 0.0f);
+ subpatch.P01 = make_float2(0.5f, 0.5f);
+ subpatch.P11 = make_float2(1.0f, 0.5f);
+ split->split_quad(&patch, &subpatch);
+
+ subpatch.P00 = make_float2(0.0f, 0.5f);
+ subpatch.P10 = make_float2(0.5f, 0.5f);
+ subpatch.P01 = make_float2(0.0f, 1.0f);
+ subpatch.P11 = make_float2(0.5f, 1.0f);
+ split->split_quad(&patch, &subpatch);
+
+ subpatch.P00 = make_float2(0.5f, 0.5f);
+ subpatch.P10 = make_float2(1.0f, 0.5f);
+ subpatch.P01 = make_float2(0.5f, 1.0f);
+ subpatch.P11 = make_float2(1.0f, 1.0f);
+ split->split_quad(&patch, &subpatch);
+ }
+ else {
+ /* ngon */
+ float3 center_vert = make_float3(0.0f, 0.0f, 0.0f);
+ float3 center_normal = make_float3(0.0f, 0.0f, 0.0f);
+
+ float inv_num_corners = 1.0f/float(face.num_corners);
+ for(int corner = 0; corner < face.num_corners; corner++) {
+ center_vert += verts[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
+ center_normal += vN[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
+ }
+
+ for(int corner = 0; corner < face.num_corners; corner++) {
+ LinearQuadPatch patch;
+ float3 *hull = patch.hull;
+ float3 *normals = patch.normals;
+
+ patch.patch_index = face.ptex_offset + corner;
+
+ patch.shader = face.shader;
+
+ hull[0] = verts[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
+ hull[1] = verts[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
+ hull[2] = verts[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
+ hull[3] = center_vert;
+
+ hull[1] = (hull[1] + hull[0]) * 0.5;
+ hull[2] = (hull[2] + hull[0]) * 0.5;
+
+ if(face.smooth) {
+ normals[0] = vN[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
+ normals[1] = vN[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
+ normals[2] = vN[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
+ normals[3] = center_normal;
+
+ normals[1] = (normals[1] + normals[0]) * 0.5;
+ normals[2] = (normals[2] + normals[0]) * 0.5;
+ }
+ else {
+ float3 N = face.normal(this);
+ for(int i = 0; i < 4; i++) {
+ normals[i] = N;
+ }
+ }
+
+ split->split_quad(&patch);
+ }
+ }
+ }
+
+ /* interpolate center points for attributes */
+ foreach(Attribute& attr, subd_attributes.attributes) {
+ char* data = attr.data();
+ size_t stride = attr.data_sizeof();
+ int ngons = 0;
+
+ switch(attr.element) {
+ case ATTR_ELEMENT_VERTEX: {
+ for(int f = 0; f < num_faces; f++) {
+ SubdFace& face = subd_faces[f];
+
+ if(!face.is_quad()) {
+ char* center = data + (verts.size() - num_subd_verts + ngons) * stride;
+ attr.zero_data(center);
+
+ float inv_num_corners = 1.0f / float(face.num_corners);
+
+ for(int corner = 0; corner < face.num_corners; corner++) {
+ attr.add_with_weight(center,
+ data + subd_face_corners[face.start_corner + corner] * stride,
+ inv_num_corners);
+ }
+
+ ngons++;
+ }
+ }
+ } break;
+ case ATTR_ELEMENT_VERTEX_MOTION: {
+ // TODO(mai): implement
+ } break;
+ case ATTR_ELEMENT_CORNER: {
+ for(int f = 0; f < num_faces; f++) {
+ SubdFace& face = subd_faces[f];
+
+ if(!face.is_quad()) {
+ char* center = data + (subd_face_corners.size() + ngons) * stride;
+ attr.zero_data(center);
+
+ float inv_num_corners = 1.0f / float(face.num_corners);
+
+ for(int corner = 0; corner < face.num_corners; corner++) {
+ attr.add_with_weight(center,
+ data + (face.start_corner + corner) * stride,
+ inv_num_corners);
+ }
+
+ ngons++;
+ }
+ }
+ } break;
+ case ATTR_ELEMENT_CORNER_BYTE: {
+ for(int f = 0; f < num_faces; f++) {
+ SubdFace& face = subd_faces[f];
+
+ if(!face.is_quad()) {
+ uchar* center = (uchar*)data + (subd_face_corners.size() + ngons) * stride;
+
+ float inv_num_corners = 1.0f / float(face.num_corners);
+ float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ for(int corner = 0; corner < face.num_corners; corner++) {
+ for(int i = 0; i < 4; i++) {
+ val[i] += float(*(data + (face.start_corner + corner) * stride + i)) * inv_num_corners;
+ }
+ }
+
+ for(int i = 0; i < 4; i++) {
+ center[i] = uchar(min(max(val[i], 0.0f), 255.0f));
+ }
+
+ ngons++;
+ }
+ }
+ } break;
+ default: break;
+ }
+ }
+}
+
+CCL_NAMESPACE_END
+