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:
authorAlexander Pinzon Fernandez <apinzonf@gmail.com>2013-12-11 20:10:22 +0400
committerAlexander Pinzon Fernandez <apinzonf@gmail.com>2013-12-11 20:10:22 +0400
commit2658a3c1b44717f497f187a38000c804eb37bbba (patch)
treeee55c673feabced8b6ec8bf9a8aa4d82a3cda3db /intern/cycles/subd
parent4005cb1c6a63a217df0e887c741beee2c1359301 (diff)
parent09b859d03f0ee138c4273ef8460e91d9888387a1 (diff)
Merge branch 'master' into soc-2013-sketch_meshsoc-2013-sketch_mesh
Conflicts: release/scripts/addons source/blender/blenloader/intern/readfile.c source/blender/blenloader/intern/writefile.c source/blender/editors/object/object_modifier.c source/blender/makesrna/intern/rna_modifier.c source/blender/modifiers/intern/MOD_laplaciandeform.c
Diffstat (limited to 'intern/cycles/subd')
-rw-r--r--intern/cycles/subd/CMakeLists.txt9
-rw-r--r--intern/cycles/subd/subd_build.cpp669
-rw-r--r--intern/cycles/subd/subd_build.h73
-rw-r--r--intern/cycles/subd/subd_dice.cpp100
-rw-r--r--intern/cycles/subd/subd_dice.h42
-rw-r--r--intern/cycles/subd/subd_edge.h70
-rw-r--r--intern/cycles/subd/subd_face.h109
-rw-r--r--intern/cycles/subd/subd_mesh.cpp493
-rw-r--r--intern/cycles/subd/subd_mesh.h40
-rw-r--r--intern/cycles/subd/subd_patch.cpp163
-rw-r--r--intern/cycles/subd/subd_patch.h40
-rw-r--r--intern/cycles/subd/subd_ring.cpp236
-rw-r--r--intern/cycles/subd/subd_ring.h75
-rw-r--r--intern/cycles/subd/subd_split.cpp31
-rw-r--r--intern/cycles/subd/subd_split.h11
-rw-r--r--intern/cycles/subd/subd_stencil.cpp101
-rw-r--r--intern/cycles/subd/subd_stencil.h65
-rw-r--r--intern/cycles/subd/subd_vert.h121
18 files changed, 427 insertions, 2021 deletions
diff --git a/intern/cycles/subd/CMakeLists.txt b/intern/cycles/subd/CMakeLists.txt
index 838776d60bf..2641f6d9c0c 100644
--- a/intern/cycles/subd/CMakeLists.txt
+++ b/intern/cycles/subd/CMakeLists.txt
@@ -12,26 +12,17 @@ set(INC_SYS
)
set(SRC
- subd_build.cpp
subd_dice.cpp
subd_mesh.cpp
subd_patch.cpp
- subd_ring.cpp
subd_split.cpp
- subd_stencil.cpp
)
set(SRC_HEADERS
- subd_build.h
subd_dice.h
- subd_edge.h
- subd_face.h
subd_mesh.h
subd_patch.h
- subd_ring.h
subd_split.h
- subd_stencil.h
- subd_vert.h
)
include_directories(${INC})
diff --git a/intern/cycles/subd/subd_build.cpp b/intern/cycles/subd/subd_build.cpp
deleted file mode 100644
index f3c2837c37c..00000000000
--- a/intern/cycles/subd/subd_build.cpp
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
- *
- * Modifications copyright (c) 2011, Blender Foundation. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "subd_build.h"
-#include "subd_edge.h"
-#include "subd_face.h"
-#include "subd_ring.h"
-#include "subd_mesh.h"
-#include "subd_patch.h"
-#include "subd_stencil.h"
-#include "subd_vert.h"
-
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_math.h"
-#include "util_string.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Builder */
-
-SubdBuilder *SubdBuilder::create(bool linear)
-{
- if(linear)
- return new SubdLinearBuilder();
- else
- return new SubdAccBuilder();
-}
-
-/* Gregory ACC Stencil */
-
-class GregoryAccStencil {
-public:
- SubdFaceRing *ring;
- StencilMask stencil[20];
-
- GregoryAccStencil(SubdFaceRing *ring_)
- {
- ring = ring_;
-
- for(int i = 0; i < 20; i++)
- stencil[i].resize(ring->num_verts());
- }
-
- StencilMask& get(int i)
- {
- assert(i < 20);
- return stencil[i];
- }
-
- float& get(int i, SubdVert *vert)
- {
- assert(i < 20);
- return stencil[i][ring->vert_index(vert)];
- }
-};
-
-static float pseudoValence(SubdVert *vert)
-{
- float valence = (float)vert->valence();
-
- if(vert->is_boundary()) {
- /* we treat boundary verts as being half a closed mesh. corners are
- * special case. n = 4 for corners and n = 2*(n-1) for boundaries. */
- if(valence == 2) return 4;
- return (valence - 1)*2;
- }
-
- return valence;
-}
-
-/* Subd ACC Builder */
-
-SubdAccBuilder::SubdAccBuilder()
-{
-}
-
-SubdAccBuilder::~SubdAccBuilder()
-{
-}
-
-Patch *SubdAccBuilder::run(SubdFace *face)
-{
- SubdFaceRing ring(face, face->edge);
- GregoryAccStencil stencil(&ring);
- float3 position[20];
-
- computeCornerStencil(&ring, &stencil);
- computeEdgeStencil(&ring, &stencil);
- computeInteriorStencil(&ring, &stencil);
-
- ring.evaluate_stencils(position, stencil.stencil, 20);
-
- if(face->num_edges() == 3) {
- GregoryTrianglePatch *patch = new GregoryTrianglePatch();
- memcpy(patch->hull, position, sizeof(float3)*20);
- return patch;
- }
- else if(face->num_edges() == 4) {
- GregoryQuadPatch *patch = new GregoryQuadPatch();
- memcpy(patch->hull, position, sizeof(float3)*20);
- return patch;
- }
-
- assert(0); /* n-gons should have been split already */
- return NULL;
-}
-
-/* Gregory Patch */
-
-void SubdAccBuilder::computeCornerStencil(SubdFaceRing *ring, GregoryAccStencil *stencil)
-{
- const int cornerIndices[7] = {8, 11, 19, 16, 6, 9, 12};
- int primitiveOffset = ring->is_quad()? 0: 4;
-
- SubdEdge *firstEdge = ring->firstEdge();
-
- /* compute corner control points */
- int v = 0;
-
- for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) {
- SubdVert *vert = it.current()->from();
- int valence = vert->valence();
- int cid = cornerIndices[primitiveOffset+v];
-
- if(vert->is_boundary()) {
- /* compute vertex limit position */
- SubdEdge *edge0 = vert->edge;
- SubdEdge *edge1 = vert->edge->prev;
-
- assert(edge0->face == NULL);
- assert(edge0->to() != vert);
- assert(edge1->face == NULL);
- assert(edge1->from() != vert);
-
- stencil->get(cid, vert) = 2.0f/3.0f;
- stencil->get(cid, edge0->to()) = 1.0f/6.0f;
- stencil->get(cid, edge1->from()) = 1.0f/6.0f;
-
- assert(stencil->get(cid).is_normalized());
- }
- else {
- stencil->get(cid, vert) = 3.0f*valence*valence;
-
- for(SubdVert::EdgeIterator eit(vert->edge); !eit.isDone(); eit.advance()) {
- SubdEdge *edge = eit.current();
- assert(vert->co == edge->from()->co);
-
- stencil->get(cid, edge->to()) = 12.0f;
-
- if(SubdFaceRing::is_triangle(edge->face)) {
- /* distribute weight to all verts */
- stencil->get(cid, vert) += 1.0f;
- stencil->get(cid, edge->to()) += 1.0f;
- stencil->get(cid, edge->next->to()) += 1.0f;
- }
- else
- stencil->get(cid, edge->next->to()) = 3.0f;
- }
-
- /* normalize stencil. */
- stencil->get(cid).normalize();
- }
- }
-}
-
-void SubdAccBuilder::computeEdgeStencil(SubdFaceRing *ring, GregoryAccStencil *stencil)
-{
- const int cornerIndices[7] = {8, 11, 19, 16, 6, 9, 12};
- const int edge1Indices[7] = {9, 13, 18, 14, 7, 10, 13};
- const int edge2Indices[7] = {12, 10, 15, 17, 14, 8, 11};
- int primitiveOffset = ring->is_quad()? 0: 4;
-
- float tangentScales[14] = {
- 0.0f, 0.0f, 0.0f, 0.667791f, 1.0f,
- 1.11268f, 1.1284f, 1.10289f, 1.06062f,
- 1.01262f, 0.963949f, 0.916926f, 0.872541f, 0.831134f
- };
-
- SubdEdge *firstEdge = ring->firstEdge();
-
- /* compute corner / edge control points */
- int v = 0;
-
- for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) {
- SubdVert *vert = it.current()->from();
- int valence = vert->valence();
- int cid = cornerIndices[primitiveOffset+v];
-
- int i1 = 0, i2 = 0, j = 0;
-
- for(SubdVert::EdgeIterator eit(vert->edge); !eit.isDone(); eit.advance(), j++) {
- SubdEdge *edge = eit.current();
-
- /* find index of "our" edge for edge control points */
- if(edge == it.current())
- i1 = j;
- if(edge == it.current()->prev->pair)
- i2 = j;
- }
-
- if(vert->is_boundary()) {
- int num_verts = ring->num_verts();
- StencilMask r0(num_verts);
- StencilMask r1(num_verts);
-
- computeBoundaryTangentStencils(ring, vert, r0, r1);
-
- int k = valence - 1;
- float omega = M_PI_F / k;
-
- int eid1 = edge1Indices[primitiveOffset + v];
- int eid2 = edge2Indices[primitiveOffset + v];
-
- if(it.current()->is_boundary()) {
- assert(it.current()->from() == vert);
-
- stencil->get(eid1, vert) = 2.0f / 3.0f;
- stencil->get(eid1, it.current()->to()) = 1.0f / 3.0f;
-
- assert(stencil->get(eid1).is_normalized());
-
- if(valence == 2) {
- for(int i = 0; i < num_verts; i++)
- stencil->get(eid1)[i] += r0[i] * 0.0001f;
- }
- }
- else {
- stencil->get(eid1) = stencil->get(cid);
-
- /* compute index of it.current() around vert */
- int idx = 0;
-
- for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), idx++)
- if(eit.current() == it.current())
- break;
-
- assert(idx != valence);
-
- float c = cosf(idx * omega);
- float s = sinf(idx * omega);
-
- for(int i = 0; i < num_verts; i++)
- stencil->get(eid1)[i] += (r0[i] * s + r1[i] * c) / 3.0f;
- }
-
- if(it.current()->prev->is_boundary()) {
- assert(it.current()->prev->pair->from() == vert);
-
- stencil->get(eid2, vert) = 2.0f / 3.0f;
- stencil->get(eid2, it.current()->prev->pair->to()) = 1.0f / 3.0f;
-
- assert(stencil->get(eid2).is_normalized());
-
- if(valence == 2) {
- for(int i = 0; i < num_verts; i++)
- stencil->get(eid2)[i] += r0[i] * 0.0001f;
- }
- }
- else {
- stencil->get(eid2) = stencil->get(cid);
-
- /* compute index of it.current() around vert */
- int idx = 0;
-
- for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), idx++)
- if(eit.current() == it.current()->prev->pair)
- break;
-
- assert(idx != valence);
-
- float c = cosf(idx * omega);
- float s = sinf(idx * omega);
-
- for(int i = 0; i < num_verts; i++)
- stencil->get(eid2)[i] += (r0[i] * s + r1[i] * c) / 3;
- }
- }
- else {
- float costerm = cosf(M_PI_F / valence);
- float sqrtterm = sqrtf(4.0f + costerm*costerm);
-
- /* float tangentScale = 1.0f; */
- float tangentScale = tangentScales[min(valence, 13U)];
-
- float alpha = (1.0f + costerm / sqrtterm) / (3.0f * valence) * tangentScale;
- float beta = 1.0f / (3.0f * valence * sqrtterm) * tangentScale;
-
-
- int eid1 = edge1Indices[primitiveOffset + v];
- int eid2 = edge2Indices[primitiveOffset + v];
-
- stencil->get(eid1) = stencil->get(cid);
- stencil->get(eid2) = stencil->get(cid);
-
- j = 0;
- for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), j++) {
- SubdEdge *edge = eit.current();
- assert(vert->co == edge->from()->co);
-
- float costerm1_a = cosf(M_PI_F * 2 * (j-i1) / valence);
- float costerm1_b = cosf(M_PI_F * (2 * (j-i1)-1) / valence); /* -1 instead of +1 b/c of edge->next->to() */
-
- float costerm2_a = cosf(M_PI_F * 2 * (j-i2) / valence);
- float costerm2_b = cosf(M_PI_F * (2 * (j-i2)-1) / valence); /* -1 instead of +1 b/c of edge->next->to() */
-
-
- stencil->get(eid1, edge->to()) += alpha * costerm1_a;
- stencil->get(eid2, edge->to()) += alpha * costerm2_a;
-
- if(SubdFaceRing::is_triangle(edge->face)) {
- /* @@ this probably does not provide watertight results!! (1/3 + 1/3 + 1/3 != 1) */
-
- /* distribute weight to all verts */
- stencil->get(eid1, vert) += beta * costerm1_b / 3.0f;
- stencil->get(eid1, edge->to()) += beta * costerm1_b / 3.0f;
- stencil->get(eid1, edge->next->to()) += beta * costerm1_b / 3.0f;
-
- stencil->get(eid2, vert) += beta * costerm2_b / 3.0f;
- stencil->get(eid2, edge->to()) += beta * costerm2_b / 3.0f;
- stencil->get(eid2, edge->next->to()) += beta * costerm2_b / 3.0f;
- }
- else {
- stencil->get(eid1, edge->next->to()) += beta * costerm1_b;
- stencil->get(eid2, edge->next->to()) += beta * costerm2_b;
- }
- }
- }
- }
-}
-
-void SubdAccBuilder::computeInteriorStencil(SubdFaceRing *ring, GregoryAccStencil *stencil)
-{
- static int corner1Indices[7] = {8, 11, 19, 16, 6, 9, 12};
- static int corner2Indices[7] = {11, 19, 16, 8, 9, 12, 6};
- static int edge1Indices[7] = {9, 13, 18, 14, 7, 10, 13};
- static int edge2Indices[7] = {10, 15, 17, 12, 8, 11, 14};
- static int interior1Indices[7] = {1, 3, 6, 4, 1, 3, 5};
- static int interior2Indices[7] = {2, 7, 5, 0, 2, 4, 0};
-
- int primitiveOffset = ring->is_quad()? 0: 4;
-
- SubdFace * face = ring->face();
- SubdEdge *firstEdge = ring->firstEdge();
-
- /* interior control points */
- int v = 0;
- for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) {
- SubdEdge *edge = it.current();
-
- if(edge->is_boundary()) {
- float valence1 = pseudoValence(edge->from());
- float valence2 = pseudoValence(edge->to());
-
- float weights1[4];
- float weights2[4];
-
- if(ring->is_quad()) {
- weights1[0] = 3 * valence1;
- weights1[1] = 6;
- weights1[2] = 3;
- weights1[3] = 6;
-
- weights2[0] = 6;
- weights2[1] = 3 * valence2;
- weights2[2] = 6;
- weights2[3] = 3;
- }
- else {
- assert(ring->is_triangle());
- weights1[0] = 3 * valence1 + 1;
- weights1[1] = 7;
- weights1[2] = 7;
-
- weights2[0] = 7;
- weights2[1] = 3 * valence2 + 1;
- weights2[2] = 7;
- }
-
- int idx1 = interior1Indices[primitiveOffset+v];
- int idx2 = interior2Indices[primitiveOffset+v];
-
- int i = 0;
- for(SubdFace::EdgeIterator it_sub(face->edges(edge)); !it_sub.isDone(); it_sub.advance(), i++) {
- SubdVert *vert = it_sub.current()->from();
- stencil->get(idx1, vert) += weights1[i];
- stencil->get(idx2, vert) += weights2[i];
- }
-
- stencil->get(idx1).normalize();
- stencil->get(idx2).normalize();
- }
- else {
- SubdVert *e0 = edge->from();
- float costerm0 = cosf(M_2PI_F / pseudoValence(e0));
-
- SubdVert *f0 = edge->to();
- float costerm1 = cosf(M_2PI_F / pseudoValence(f0));
-
- /* p0 +------+ q0
- * | |
- * f0 +======+ e0 <=== current edge
- * | |
- * p1 +------+ q1
- */
-
- SubdVert *q0 = edge->next->to();
- SubdVert *p0 = edge->prev->from();
-
- SubdVert *p1 = edge->pair->next->to();
- SubdVert *q1 = edge->pair->prev->from();
-
-
- StencilMask x(ring->num_verts());
- StencilMask y(ring->num_verts());
-
- for(int i = 0; i < ring->num_verts(); i++) {
- x[i] =
- (costerm1 * stencil->get(corner1Indices[primitiveOffset+v])[i] -
- (2*costerm0 + costerm1) * stencil->get(edge1Indices[primitiveOffset+v])[i] +
- 2*costerm0 * stencil->get(edge2Indices[primitiveOffset+v])[i]) / 3.0f;
- }
-
- /* y = (2*( midedgeA1 - midedgeB1) + 4*(centroidA - centroidB))/18.0f; */
- y[ring->vert_index(p0)] = 1;
- y[ring->vert_index(p1)] = -1;
-
- /* add centroidA */
- if(ring->is_triangle()) {
- y[ring->vert_index(p0)] += 4.0f / 3.0f;
- y[ring->vert_index(e0)] += 4.0f / 3.0f;
- y[ring->vert_index(f0)] += 4.0f / 3.0f;
- }
- else {
- y[ring->vert_index(p0)] += 1;
- y[ring->vert_index(q0)] += 1;
- y[ring->vert_index(e0)] += 1;
- y[ring->vert_index(f0)] += 1;
- }
-
- /* sub centroidB */
- if(SubdFaceRing::is_triangle(edge->pair->face)) {
- y[ring->vert_index(p1)] -= 4.0f / 3.0f;
- y[ring->vert_index(e0)] -= 4.0f / 3.0f;
- y[ring->vert_index(f0)] -= 4.0f / 3.0f;
-
- }
- else {
- y[ring->vert_index(p1)] -= 1;
- y[ring->vert_index(q1)] -= 1;
- y[ring->vert_index(e0)] -= 1;
- y[ring->vert_index(f0)] -= 1;
- }
-
- y /= 18.0f;
-
- if(ring->is_triangle()) {
- x *= 3.0f / 4.0f;
- y *= 3.0f / 4.0f;
- }
-
- /* this change makes the triangle boundaries smoother, but distorts the quads next to them */
-#if 0
- if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face)) {
- y *= 4.0f / 3.0f;
- }
-#endif
-
- stencil->get(interior1Indices[primitiveOffset+v]) = stencil->get(edge1Indices[primitiveOffset+v]);
- stencil->get(interior1Indices[primitiveOffset+v]) += x;
- stencil->get(interior1Indices[primitiveOffset+v]) += y;
-
- for(int i = 0; i < ring->num_verts(); i++) {
- x[i] =
- (costerm0 * stencil->get(corner2Indices[primitiveOffset+v])[i] -
- (2*costerm1 + costerm0) * stencil->get(edge2Indices[primitiveOffset+v])[i] +
- 2*costerm1 * stencil->get(edge1Indices[primitiveOffset+v])[i]) / 3.0f;
- }
-
- /* y = (2*( midedgeA2 - midedgeB2) + 4*(centroidA - centroidB))/18.0f; */
- y = 0.0f;
-
- /* (2*( midedgeA2 - midedgeB2) */
- y[ring->vert_index(q0)] = 1;
- y[ring->vert_index(q1)] = -1;
-
- /* add centroidA */
- if(ring->is_triangle()) {
- y[ring->vert_index(p0)] += 4.0f / 3.0f;
- y[ring->vert_index(e0)] += 4.0f / 3.0f;
- y[ring->vert_index(f0)] += 4.0f / 3.0f;
- }
- else {
- y[ring->vert_index(p0)] += 1;
- y[ring->vert_index(q0)] += 1;
- y[ring->vert_index(e0)] += 1;
- y[ring->vert_index(f0)] += 1;
- }
-
- /* sub centroidB */
- if(SubdFaceRing::is_triangle(edge->pair->face)) {
- y[ring->vert_index(p1)] -= 4.0f / 3.0f;
- y[ring->vert_index(e0)] -= 4.0f / 3.0f;
- y[ring->vert_index(f0)] -= 4.0f / 3.0f;
-
- }
- else {
- y[ring->vert_index(p1)] -= 1;
- y[ring->vert_index(q1)] -= 1;
- y[ring->vert_index(e0)] -= 1;
- y[ring->vert_index(f0)] -= 1;
- }
-
- y /= 18.0f;
-
- if(ring->is_triangle()) {
- x *= 3.0f / 4.0f;
- y *= 3.0f / 4.0f;
- }
-
- /* this change makes the triangle boundaries smoother, but distorts the quads next to them. */
-#if 0
- if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face))
- y *= 4.0f / 3.0f;
-#endif
-
- stencil->get(interior2Indices[primitiveOffset+v]) = stencil->get(edge2Indices[primitiveOffset+v]);
- stencil->get(interior2Indices[primitiveOffset+v]) += x;
- stencil->get(interior2Indices[primitiveOffset+v]) += y;
- }
- }
-}
-
-void SubdAccBuilder::computeBoundaryTangentStencils(SubdFaceRing *ring, SubdVert *vert, StencilMask & r0, StencilMask & r1)
-{
- assert(vert->is_boundary());
- assert(r0.size() == ring->num_verts());
- assert(r1.size() == ring->num_verts());
-
- SubdEdge *edge0 = vert->edge;
- assert(edge0->face == NULL);
- assert(edge0->to() != vert);
-
- SubdEdge *edgek = vert->edge->prev;
- assert(edgek->face == NULL);
- assert(edgek->from() != vert);
-
- int valence = vert->valence();
-
- int k = valence - 1;
- float omega = M_PI_F / k;
- float s = sinf(omega);
- float c = cosf(omega);
-
- float factor = 1.0f / (3 * k + c);
-
- float gamma = -4 * s * factor;
- r0[ring->vert_index(vert)] = gamma;
- /* r1[ring->vert_index(vert)] = 0; */
-
- float salpha0 = -((1 + 2 * c) * sqrtf(1 + c)) * factor / sqrtf(1 - c);
- float calpha0 = 1.0f / 2.0f;
-
- r0[ring->vert_index(edge0->to())] = salpha0;
- r1[ring->vert_index(edge0->to())] = calpha0;
-
- float salphak = salpha0;
- float calphak = -1.0f / 2.0f;
-
- r0[ring->vert_index(edgek->from())] = salphak;
- r1[ring->vert_index(edgek->from())] = calphak;
-
- int j = 0;
- for(SubdVert::EdgeIterator it(vert->edges()); !it.isDone(); it.advance(), j++) {
- SubdEdge *edge = it.current();
-
- if(j == k) break;
-
- SubdVert *p = edge->to();
- SubdVert *q = edge->pair->prev->from();
-
- float alphaj = 4 * sinf(j * omega) * factor;
- float betaj = (sinf(j * omega) + sinf((j + 1) * omega)) * factor;
-
- if(j != 0)
- r0[ring->vert_index(p)] += alphaj;
-
- if(edge->pair->prev->prev->prev == edge->pair) {
- r0[ring->vert_index(vert)] += betaj / 3.0f;
- r0[ring->vert_index(edge->pair->from())] += betaj / 3.0f;
- r0[ring->vert_index(q)] += betaj / 3.0f;
- }
- else
- r0[ring->vert_index(q)] += betaj;
- }
-
- if(valence == 2) {
- /* r0 perpendicular to r1 */
- r0[ring->vert_index(vert)] = -4.0f / 3.0f;
- r0[ring->vert_index(edgek->from())] = 1.0f / 2.0f;
- r0[ring->vert_index(edge0->to())] = 1.0f / 2.0f;
- r0[ring->vert_index(edge0->next->to())] = 1.0f / 3.0f;
- }
-}
-
-/* Subd Linear Builder */
-
-SubdLinearBuilder::SubdLinearBuilder()
-{
-}
-
-SubdLinearBuilder::~SubdLinearBuilder()
-{
-}
-
-Patch *SubdLinearBuilder::run(SubdFace *face)
-{
- Patch *patch;
- float3 *hull;
-
- if(face->num_edges() == 3) {
- LinearTrianglePatch *lpatch = new LinearTrianglePatch();
- hull = lpatch->hull;
- patch = lpatch;
- }
- else if(face->num_edges() == 4) {
- LinearQuadPatch *lpatch = new LinearQuadPatch();
- hull = lpatch->hull;
- patch = lpatch;
- }
- else {
- assert(0); /* n-gons should have been split already */
- return NULL;
- }
-
- int i = 0;
-
- for(SubdFace::EdgeIterator it(face->edge); !it.isDone(); it.advance())
- hull[i++] = it.current()->from()->co;
-
- if(face->num_edges() == 4)
- swap(hull[2], hull[3]);
-
- return patch;
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/subd/subd_build.h b/intern/cycles/subd/subd_build.h
deleted file mode 100644
index 8353fb5993a..00000000000
--- a/intern/cycles/subd/subd_build.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2011-2013 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
- */
-
-#ifndef __SUBD_BUILD_H__
-#define __SUBD_BUILD_H__
-
-CCL_NAMESPACE_BEGIN
-
-class SubdFace;
-class SubdFaceRing;
-class SubdVert;
-class GregoryAccStencil;
-class Patch;
-class StencilMask;
-
-/* Builder */
-
-class SubdBuilder
-{
-public:
- virtual ~SubdBuilder() {};
- virtual Patch *run(SubdFace *face) = 0;
- static SubdBuilder *create(bool linear);
-};
-
-/* Approximate Catmull Clark using Loop's approximation */
-
-class SubdAccBuilder : public SubdBuilder
-{
-public:
- SubdAccBuilder();
- ~SubdAccBuilder();
-
- Patch *run(SubdFace *face);
-
-protected:
- /* Gregory Patch */
- void computeCornerStencil(SubdFaceRing *ring, GregoryAccStencil *stencil);
- void computeEdgeStencil(SubdFaceRing *ring, GregoryAccStencil *stencil);
- void computeInteriorStencil(SubdFaceRing *ring, GregoryAccStencil *stencil);
- void computeBoundaryTangentStencils(SubdFaceRing *ring,
- SubdVert *vert,
- StencilMask & r0, StencilMask & r1);
-};
-
-/* Linear Subdivision */
-
-class SubdLinearBuilder : public SubdBuilder
-{
-public:
- SubdLinearBuilder();
- ~SubdLinearBuilder();
-
- Patch *run(SubdFace *face);
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_BUILD_H__ */
-
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index a42a2fc833b..05ff5ca4b65 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -26,22 +26,25 @@ CCL_NAMESPACE_BEGIN
/* EdgeDice Base */
-EdgeDice::EdgeDice(Mesh *mesh_, int shader_, bool smooth_, float dicing_rate_)
+EdgeDice::EdgeDice(const SubdParams& params_)
+: params(params_)
{
- mesh = mesh_;
mesh_P = NULL;
mesh_N = NULL;
vert_offset = 0;
- dicing_rate = dicing_rate_;
- shader = shader_;
- smooth = smooth_;
- camera = NULL;
- mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
+ params.mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
+
+ if(params.ptex) {
+ params.mesh->attributes.add(ATTR_STD_PTEX_UV);
+ params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
+ }
}
void EdgeDice::reserve(int num_verts, int num_tris)
{
+ Mesh *mesh = params.mesh;
+
vert_offset = mesh->verts.size();
tri_offset = mesh->triangles.size();
@@ -60,20 +63,38 @@ int EdgeDice::add_vert(Patch *patch, float2 uv)
patch->eval(&P, &dPdu, &dPdv, uv.x, uv.y);
N = normalize(cross(dPdu, dPdv));
- assert(vert_offset < mesh->verts.size());
+ assert(vert_offset < params.mesh->verts.size());
mesh_P[vert_offset] = P;
mesh_N[vert_offset] = N;
+ if(params.ptex) {
+ Attribute *attr_ptex_uv = params.mesh->attributes.add(ATTR_STD_PTEX_UV);
+ params.mesh->attributes.reserve();
+
+ float3 *ptex_uv = attr_ptex_uv->data_float3();
+ ptex_uv[vert_offset] = make_float3(uv.x, uv.y, 0.0f);
+ }
+
return vert_offset++;
}
-void EdgeDice::add_triangle(int v0, int v1, int v2)
+void EdgeDice::add_triangle(Patch *patch, int v0, int v1, int v2)
{
- mesh->add_triangle(v0, v1, v2, shader, smooth);
+ params.mesh->add_triangle(v0, v1, v2, params.shader, params.smooth);
+
+ if(params.ptex) {
+ Attribute *attr_ptex_face_id = params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
+ params.mesh->attributes.reserve();
+
+ float *ptex_face_id = attr_ptex_face_id->data_float();
+ ptex_face_id[tri_offset] = (float)patch->ptex_face_id();
+ }
+
+ tri_offset++;
}
-void EdgeDice::stitch_triangles(vector<int>& outer, vector<int>& inner)
+void EdgeDice::stitch_triangles(Patch *patch, vector<int>& outer, vector<int>& inner)
{
if(inner.size() == 0 || outer.size() == 0)
return; // XXX avoid crashes for Mu or Mv == 1, missing polygons
@@ -106,14 +127,14 @@ void EdgeDice::stitch_triangles(vector<int>& outer, vector<int>& inner)
v2 = inner[++i];
}
- add_triangle(v0, v1, v2);
+ add_triangle(patch, v0, v1, v2);
}
}
/* QuadDice */
-QuadDice::QuadDice(Mesh *mesh_, int shader_, bool smooth_, float dicing_rate_)
-: EdgeDice(mesh_, shader_, smooth_, dicing_rate_)
+QuadDice::QuadDice(const SubdParams& params_)
+: EdgeDice(params_)
{
}
@@ -121,7 +142,8 @@ void QuadDice::reserve(EdgeFactors& ef, int Mu, int Mv)
{
/* XXX need to make this also work for edge factor 0 and 1 */
int num_verts = (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1) + (Mu - 1)*(Mv - 1);
- EdgeDice::reserve(num_verts, 0);
+ int num_tris = 0;
+ EdgeDice::reserve(num_verts, num_tris);
}
float2 QuadDice::map_uv(SubPatch& sub, float u, float v)
@@ -138,8 +160,8 @@ float3 QuadDice::eval_projected(SubPatch& sub, float u, float v)
float3 P;
sub.patch->eval(&P, NULL, NULL, uv.x, uv.y);
- if(camera)
- P = transform_perspective(&camera->worldtoraster, P);
+ if(params.camera)
+ P = transform_perspective(&params.camera->worldtoraster, P);
return P;
}
@@ -222,7 +244,7 @@ float QuadDice::scale_factor(SubPatch& sub, EdgeFactors& ef, int Mu, int Mv)
float Apatch = max(A1, max(A2, max(A3, A4)))*4.0f;
/* solve for scaling factor */
- float Atri = dicing_rate*dicing_rate*0.5f;
+ float Atri = params.dicing_rate*params.dicing_rate*0.5f;
float Ntris = Apatch/Atri;
// XXX does the -sqrt solution matter
@@ -270,8 +292,8 @@ void QuadDice::add_grid(SubPatch& sub, int Mu, int Mv, int offset)
int i3 = offset + 4 + i + j*(Mu-1);
int i4 = offset + 4 + (i-1) + j*(Mu-1);
- add_triangle(i1, i2, i3);
- add_triangle(i1, i3, i4);
+ add_triangle(sub.patch, i1, i2, i3);
+ add_triangle(sub.patch, i1, i3, i4);
}
}
}
@@ -288,7 +310,7 @@ void QuadDice::dice(SubPatch& sub, EdgeFactors& ef)
Mv = max((int)ceil(S*Mv), 2); // XXX handle 0 & 1?
/* reserve space for new verts */
- int offset = mesh->verts.size();
+ int offset = params.mesh->verts.size();
reserve(ef, Mu, Mv);
/* corners and inner grid */
@@ -299,27 +321,27 @@ void QuadDice::dice(SubPatch& sub, EdgeFactors& ef)
vector<int> outer, inner;
add_side_u(sub, outer, inner, Mu, Mv, ef.tu0, 0, offset);
- stitch_triangles(outer, inner);
+ stitch_triangles(sub.patch, outer, inner);
/* top side */
add_side_u(sub, outer, inner, Mu, Mv, ef.tu1, 1, offset);
- stitch_triangles(inner, outer);
+ stitch_triangles(sub.patch, inner, outer);
/* left side */
add_side_v(sub, outer, inner, Mu, Mv, ef.tv0, 0, offset);
- stitch_triangles(inner, outer);
+ stitch_triangles(sub.patch, inner, outer);
/* right side */
add_side_v(sub, outer, inner, Mu, Mv, ef.tv1, 1, offset);
- stitch_triangles(outer, inner);
+ stitch_triangles(sub.patch, outer, inner);
- assert(vert_offset == mesh->verts.size());
+ assert(vert_offset == params.mesh->verts.size());
}
/* TriangleDice */
-TriangleDice::TriangleDice(Mesh *mesh_, int shader_, bool smooth_, float dicing_rate_)
-: EdgeDice(mesh_, shader_, smooth_, dicing_rate_)
+TriangleDice::TriangleDice(const SubdParams& params_)
+: EdgeDice(params_)
{
}
@@ -417,9 +439,9 @@ void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M)
inner_w.push_back(corner_v);
/* stitch together inner/outer with triangles */
- stitch_triangles(outer_u, inner_u);
- stitch_triangles(outer_v, inner_v);
- stitch_triangles(outer_w, inner_w);
+ stitch_triangles(sub.patch, outer_u, inner_u);
+ stitch_triangles(sub.patch, outer_v, inner_v);
+ stitch_triangles(sub.patch, outer_w, inner_w);
outer_u = inner_u;
outer_v = inner_v;
@@ -429,18 +451,18 @@ void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M)
/* fill up last part */
if(m == -1) {
/* single triangle */
- add_triangle(outer_w[0], outer_u[0], outer_v[0]);
+ add_triangle(sub.patch, outer_w[0], outer_u[0], outer_v[0]);
}
else {
/* center vertex + 6 triangles */
int center = add_vert(sub, make_float2(1.0f/3.0f, 1.0f/3.0f));
- add_triangle(outer_w[0], outer_w[1], center);
- add_triangle(outer_w[1], outer_w[2], center);
- add_triangle(outer_u[0], outer_u[1], center);
- add_triangle(outer_u[1], outer_u[2], center);
- add_triangle(outer_v[0], outer_v[1], center);
- add_triangle(outer_v[1], outer_v[2], center);
+ add_triangle(sub.patch, outer_w[0], outer_w[1], center);
+ add_triangle(sub.patch, outer_w[1], outer_w[2], center);
+ add_triangle(sub.patch, outer_u[0], outer_u[1], center);
+ add_triangle(sub.patch, outer_u[1], outer_u[2], center);
+ add_triangle(sub.patch, outer_v[0], outer_v[1], center);
+ add_triangle(sub.patch, outer_v[1], outer_v[2], center);
}
}
@@ -452,7 +474,7 @@ void TriangleDice::dice(SubPatch& sub, EdgeFactors& ef)
reserve(ef, M);
add_grid(sub, ef, M);
- assert(vert_offset == mesh->verts.size());
+ assert(vert_offset == params.mesh->verts.size());
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h
index 250de59c6c3..9cf5b0d50b8 100644
--- a/intern/cycles/subd/subd_dice.h
+++ b/intern/cycles/subd/subd_dice.h
@@ -31,28 +31,50 @@ class Camera;
class Mesh;
class Patch;
+struct SubdParams {
+ Mesh *mesh;
+ int shader;
+ bool smooth;
+ bool ptex;
+
+ int test_steps;
+ int split_threshold;
+ float dicing_rate;
+ Camera *camera;
+
+ SubdParams(Mesh *mesh_, int shader_, bool smooth_ = true, bool ptex_ = false)
+ {
+ mesh = mesh_;
+ shader = shader_;
+ smooth = smooth_;
+ ptex = ptex_;
+
+ test_steps = 3;
+ split_threshold = 1;
+ dicing_rate = 0.1f;
+ camera = NULL;
+ }
+
+};
+
/* EdgeDice Base */
class EdgeDice {
public:
- Camera *camera;
- Mesh *mesh;
+ SubdParams params;
float3 *mesh_P;
float3 *mesh_N;
- float dicing_rate;
size_t vert_offset;
size_t tri_offset;
- int shader;
- bool smooth;
- EdgeDice(Mesh *mesh, int shader, bool smooth, float dicing_rate);
+ EdgeDice(const SubdParams& params);
void reserve(int num_verts, int num_tris);
int add_vert(Patch *patch, float2 uv);
- void add_triangle(int v0, int v1, int v2);
+ void add_triangle(Patch *patch, int v0, int v1, int v2);
- void stitch_triangles(vector<int>& outer, vector<int>& inner);
+ void stitch_triangles(Patch *patch, vector<int>& outer, vector<int>& inner);
};
/* Quad EdgeDice
@@ -86,7 +108,7 @@ public:
int tv1;
};
- QuadDice(Mesh *mesh, int shader, bool smooth, float dicing_rate);
+ QuadDice(const SubdParams& params);
void reserve(EdgeFactors& ef, int Mu, int Mv);
float3 eval_projected(SubPatch& sub, float u, float v);
@@ -140,7 +162,7 @@ public:
int tw;
};
- TriangleDice(Mesh *mesh, int shader, bool smooth, float dicing_rate);
+ TriangleDice(const SubdParams& params);
void reserve(EdgeFactors& ef, int M);
diff --git a/intern/cycles/subd/subd_edge.h b/intern/cycles/subd/subd_edge.h
deleted file mode 100644
index edf98c8a5a0..00000000000
--- a/intern/cycles/subd/subd_edge.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Original code in the public domain -- castanyo@yahoo.es
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __SUBD_EDGE_H__
-#define __SUBD_EDGE_H__
-
-#include "subd_mesh.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Half Edge */
-
-class SubdEdge
-{
-public:
- int id;
-
- SubdEdge *next;
- SubdEdge *prev;
- SubdEdge *pair;
- SubdVert *vert;
- SubdFace *face;
-
- SubdEdge(int id_)
- {
- id = id_;
- next = NULL;
- prev = NULL;
- pair = NULL;
- vert = NULL;
- face = NULL;
- }
-
- /* vertex queries */
- SubdVert *from() { return vert; }
- SubdVert *to() { return next->vert; }
-
- /* face queries */
- bool is_boundary() { return !(face && pair->face); }
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_EDGE_H__ */
-
diff --git a/intern/cycles/subd/subd_face.h b/intern/cycles/subd/subd_face.h
deleted file mode 100644
index 8f8a9ec3f47..00000000000
--- a/intern/cycles/subd/subd_face.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Original code in the public domain -- castanyo@yahoo.es
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __SUBD_FACE_H__
-#define __SUBD_FACE_H__
-
-#include "subd_edge.h"
-#include "subd_mesh.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Face */
-
-class SubdFace
-{
-public:
- int id;
- SubdEdge *edge;
-
- SubdFace(int id_)
- {
- id = id_;
- edge = NULL;
- }
-
- bool contains(SubdEdge *e)
- {
- for(EdgeIterator it(edges()); !it.isDone(); it.advance())
- if(it.current() == e)
- return true;
-
- return false;
- }
-
- int num_edges()
- {
- int num = 0;
-
- for(EdgeIterator it(edges()); !it.isDone(); it.advance())
- num++;
-
- return num;
- }
-
- bool is_boundary()
- {
- for(EdgeIterator it(edges()); !it.isDone(); it.advance()) {
- SubdEdge *edge = it.current();
-
- if(edge->pair->face == NULL)
- return true;
- }
-
- return false;
- }
-
- /* iterate over edges in clockwise order */
- class EdgeIterator
- {
- public:
- EdgeIterator(SubdEdge *e) : end(NULL), cur(e) { }
-
- virtual void advance()
- {
- if (end == NULL) end = cur;
- cur = cur->next;
- }
-
- virtual bool isDone() { return end == cur; }
- virtual SubdEdge *current() { return cur; }
-
- private:
- SubdEdge *end;
- SubdEdge *cur;
- };
-
- EdgeIterator edges() { return EdgeIterator(edge); }
- EdgeIterator edges(SubdEdge *edge) { return EdgeIterator(edge); }
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_FACE_H__ */
-
diff --git a/intern/cycles/subd/subd_mesh.cpp b/intern/cycles/subd/subd_mesh.cpp
index becd5b9b5ec..0db20656f39 100644
--- a/intern/cycles/subd/subd_mesh.cpp
+++ b/intern/cycles/subd/subd_mesh.cpp
@@ -28,282 +28,391 @@
#include <stdio.h>
-#include "subd_build.h"
-#include "subd_edge.h"
-#include "subd_face.h"
#include "subd_mesh.h"
#include "subd_patch.h"
#include "subd_split.h"
-#include "subd_vert.h"
#include "util_debug.h"
#include "util_foreach.h"
+#ifdef WITH_OPENSUBDIV
+
+#include <osd/vertex.h>
+#include <osd/mesh.h>
+#include <osd/cpuComputeController.h>
+#include <osd/cpuVertexBuffer.h>
+#include <osd/cpuEvalLimitController.h>
+#include <osd/evalLimitContext.h>
+
CCL_NAMESPACE_BEGIN
-SubdMesh::SubdMesh()
+/* typedefs */
+typedef OpenSubdiv::OsdVertex OsdVertex;
+typedef OpenSubdiv::FarMesh<OsdVertex> OsdFarMesh;
+typedef OpenSubdiv::FarMeshFactory<OsdVertex> OsdFarMeshFactory;
+typedef OpenSubdiv::HbrCatmarkSubdivision<OsdVertex> OsdHbrCatmarkSubdivision;
+typedef OpenSubdiv::HbrFace<OsdVertex> OsdHbrFace;
+typedef OpenSubdiv::HbrHalfedge<OsdVertex> OsdHbrHalfEdge;
+typedef OpenSubdiv::HbrMesh<OsdVertex> OsdHbrMesh;
+typedef OpenSubdiv::HbrVertex<OsdVertex> OsdHbrVertex;
+typedef OpenSubdiv::OsdCpuComputeContext OsdCpuComputeContext;
+typedef OpenSubdiv::OsdCpuComputeController OsdCpuComputeController;
+typedef OpenSubdiv::OsdCpuEvalLimitContext OsdCpuEvalLimitContext;
+typedef OpenSubdiv::OsdCpuEvalLimitController OsdCpuEvalLimitController;
+typedef OpenSubdiv::OsdCpuVertexBuffer OsdCpuVertexBuffer;
+typedef OpenSubdiv::OsdEvalCoords OsdEvalCoords;
+typedef OpenSubdiv::OsdVertexBufferDescriptor OsdVertexBufferDescriptor;
+
+/* OpenSubdiv Patch */
+
+class OpenSubdPatch : public Patch {
+public:
+ int face_id;
+
+ OpenSubdPatch(OsdFarMesh *farmesh, OsdCpuVertexBuffer *vbuf_base)
+ {
+ face_id = 0;
+
+ /* create buffers for evaluation */
+ vbuf_P = OsdCpuVertexBuffer::Create(3, 1);
+ vbuf_dPdu = OsdCpuVertexBuffer::Create(3, 1);
+ vbuf_dPdv = OsdCpuVertexBuffer::Create(3, 1);
+
+ P = vbuf_P->BindCpuBuffer();
+ dPdu = vbuf_dPdu->BindCpuBuffer();
+ dPdv = vbuf_dPdv->BindCpuBuffer();
+
+ /* setup evaluation context */
+ OsdVertexBufferDescriptor in_desc(0, 3, 3), out_desc(0, 3, 3); /* offset, length, stride */
+
+ evalctx = OsdCpuEvalLimitContext::Create(farmesh, false);
+ evalctx->GetVertexData().Bind(in_desc, vbuf_base, out_desc, vbuf_P, vbuf_dPdu, vbuf_dPdv);
+ }
+
+ ~OpenSubdPatch()
+ {
+ evalctx->GetVertexData().Unbind();
+
+ delete evalctx;
+ delete vbuf_P;
+ delete vbuf_dPdu;
+ delete vbuf_dPdv;
+ }
+
+ void eval(float3 *P_, float3 *dPdu_, float3 *dPdv_, float u, float v)
+ {
+ OsdEvalCoords coords;
+ coords.u = u;
+ coords.v = v;
+ coords.face = face_id;
+
+ evalctrl.EvalLimitSample<OsdCpuVertexBuffer,OsdCpuVertexBuffer>(coords, evalctx, 0);
+
+ *P_ = make_float3(P[0], P[1], P[2]);
+ if (dPdu_) *dPdu_ = make_float3(dPdv[0], dPdv[1], dPdv[2]);
+ if (dPdv_) *dPdv_ = make_float3(dPdu[0], dPdu[1], dPdu[2]);
+
+ /* optimize: skip evaluating derivatives when not needed */
+ /* todo: swapped derivatives, different winding convention? */
+ }
+
+ BoundBox bound()
+ {
+ /* not implemented */
+ BoundBox bbox = BoundBox::empty;
+ return bbox;
+ }
+
+ int ptex_face_id()
+ {
+ return face_id;
+ }
+
+protected:
+ OsdCpuEvalLimitController evalctrl;
+ OsdCpuEvalLimitContext *evalctx;
+ OsdCpuVertexBuffer *vbuf_P;
+ OsdCpuVertexBuffer *vbuf_dPdu;
+ OsdCpuVertexBuffer *vbuf_dPdv;
+ float *P;
+ float *dPdu;
+ float *dPdv;
+};
+
+/* OpenSubdiv Mesh */
+
+OpenSubdMesh::OpenSubdMesh()
{
+ /* create osd mesh */
+ static OsdHbrCatmarkSubdivision catmark;
+ OsdHbrMesh *hbrmesh = new OsdHbrMesh(&catmark);
+
+ /* initialize class */
+ num_verts = 0;
+ num_ptex_faces = 0;
+ _hbrmesh = (void*)hbrmesh;
}
-SubdMesh::~SubdMesh()
+OpenSubdMesh::~OpenSubdMesh()
{
- pair<Key, SubdEdge*> em;
-
- foreach(SubdVert *vertex, verts)
- delete vertex;
- foreach(em, edge_map)
- delete em.second;
- foreach(SubdFace *face, faces)
- delete face;
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- verts.clear();
- edges.clear();
- edge_map.clear();
- faces.clear();
+ if(hbrmesh)
+ delete hbrmesh;
}
-SubdVert *SubdMesh::add_vert(const float3& co)
+void OpenSubdMesh::add_vert(const float3& co)
{
- SubdVert *v = new SubdVert(verts.size());
- v->co = co;
- verts.push_back(v);
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- return v;
+ OsdVertex v;
+ positions.push_back(co.x);
+ positions.push_back(co.y);
+ positions.push_back(co.z);
+ hbrmesh->NewVertex(num_verts++, v);
}
-SubdFace *SubdMesh::add_face(int v0, int v1, int v2)
+void OpenSubdMesh::add_face(int v0, int v1, int v2)
{
int index[3] = {v0, v1, v2};
return add_face(index, 3);
}
-SubdFace *SubdMesh::add_face(int v0, int v1, int v2, int v3)
+void OpenSubdMesh::add_face(int v0, int v1, int v2, int v3)
{
int index[4] = {v0, v1, v2, v3};
- return add_face(index, 4);
+ add_face(index, 4);
}
-SubdFace *SubdMesh::add_face(int *index, int num)
+void OpenSubdMesh::add_face(int *index, int num)
{
- /* test non-manifold cases */
- if(!can_add_face(index, num)) {
- /* we could try to add face in opposite winding instead .. */
- fprintf(stderr, "Warning: non manifold mesh, invalid face '%lu'.\n", (unsigned long)faces.size());
- return NULL;
- }
-
- SubdFace *f = new SubdFace(faces.size());
-
- SubdEdge *first_edge = NULL;
- SubdEdge *last = NULL;
- SubdEdge *current = NULL;
-
- /* add edges */
- for(int i = 0; i < num-1; i++) {
- current = add_edge(index[i], index[i+1]);
- assert(current != NULL);
-
- current->face = f;
-
- if(last != NULL) {
- last->next = current;
- current->prev = last;
- }
- else
- first_edge = current;
-
- last = current;
- }
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- current = add_edge(index[num-1], index[0]);
- assert(current != NULL);
-
- current->face = f;
+#ifndef NDEBUG
+ /* sanity checks */
+ for(int j = 0; j < num; j++) {
+ OsdHbrVertex *origin = hbrmesh->GetVertex(index[j]);
+ OsdHbrVertex *destination = hbrmesh->GetVertex(index[(j+1)%num]);
+ OsdHbrHalfEdge *opposite = destination->GetEdge(origin);
- last->next = current;
- current->prev = last;
+ if(origin==NULL || destination==NULL)
+ assert("An edge was specified that connected a nonexistent vertex\n");
- current->next = first_edge;
- first_edge->prev = current;
+ if(origin == destination)
+ assert("An edge was specified that connected a vertex to itself\n");
- f->edge = first_edge;
- faces.push_back(f);
+ if(opposite && opposite->GetOpposite())
+ assert("A non-manifold edge incident to more than 2 faces was found\n");
- return f;
-}
+ if(origin->GetEdge(destination))
+ assert("An edge connecting two vertices was specified more than once."
+ "It's likely that an incident face was flipped\n");
+ }
+#endif
-bool SubdMesh::can_add_face(int *index, int num)
-{
- /* manifold check */
- for(int i = 0; i < num-1; i++)
- if(!can_add_edge(index[i], index[i+1]))
- return false;
+ OsdHbrFace *face = hbrmesh->NewFace(num, index, 0);
+
+ /* this is required for limit eval patch table? */
+ face->SetPtexIndex(num_ptex_faces);
- return can_add_edge(index[num-1], index[0]);
+ if(num == 4)
+ num_ptex_faces++;
+ else
+ num_ptex_faces += num;
}
-bool SubdMesh::can_add_edge(int i, int j)
+bool OpenSubdMesh::finish()
{
- /* check for degenerate edge */
- if(i == j)
- return false;
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- /* make sure edge has not been added yet. */
- return find_edge(i, j) == NULL;
-}
+ /* finish hbr mesh construction */
+ hbrmesh->SetInterpolateBoundaryMethod(OsdHbrMesh::k_InterpolateBoundaryEdgeOnly);
+ hbrmesh->Finish();
-SubdEdge *SubdMesh::add_edge(int i, int j)
-{
- SubdEdge *edge;
-
- /* find pair */
- SubdEdge *pair = find_edge(j, i);
-
- if(pair != NULL) {
- /* create edge with same id */
- edge = new SubdEdge(pair->id + 1);
-
- /* link edge pairs */
- edge->pair = pair;
- pair->pair = edge;
-
- /* not sure this is necessary? */
- pair->vert->edge = pair;
- }
- else {
- /* create edge */
- edge = new SubdEdge(2*edges.size());
-
- /* add only unpaired edges */
- edges.push_back(edge);
- }
-
- /* assign vertex and put into map */
- edge->vert = verts[i];
- edge_map[Key(i, j)] = edge;
-
- /* face and next are set by add_face */
-
- return edge;
+ return true;
}
-SubdEdge *SubdMesh::find_edge(int i, int j)
+void OpenSubdMesh::tessellate(DiagSplit *split)
{
- map<Key, SubdEdge*>::const_iterator it = edge_map.find(Key(i, j));
+ if (num_ptex_faces == 0)
+ return;
- return (it == edge_map.end())? NULL: it->second;
-}
+ const int level = 3;
+ const bool requirefvar = false;
-bool SubdMesh::link_boundary()
-{
- /* link boundary edges once the mesh has been created */
- int num = 0;
-
- /* create boundary edges */
- int num_edges = edges.size();
+ /* convert HRB to FAR mesh */
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- for(int e = 0; e < num_edges; e++) {
- SubdEdge *edge = edges[e];
+ OsdFarMeshFactory meshFactory(hbrmesh, level, true);
+ OsdFarMesh *farmesh = meshFactory.Create(requirefvar);
+ int num_hbr_verts = hbrmesh->GetNumVertices();
- if(edge->pair == NULL) {
- SubdEdge *pair = new SubdEdge(edge->id + 1);
+ delete hbrmesh;
+ hbrmesh = NULL;
+ _hbrmesh = NULL;
- int i = edge->from()->id;
- int j = edge->to()->id;
+ /* refine HBR mesh with vertex coordinates */
+ OsdCpuComputeController *compute_controller = new OsdCpuComputeController();
+ OsdCpuComputeContext *compute_context = OsdCpuComputeContext::Create(farmesh);
- assert(edge_map.find(Key(j, i)) == edge_map.end());
+ OsdCpuVertexBuffer *vbuf_base = OsdCpuVertexBuffer::Create(3, num_hbr_verts);
+ vbuf_base->UpdateData(&positions[0], 0, num_verts);
- pair->vert = verts[j];
- edge_map[Key(j, i)] = pair;
-
- edge->pair = pair;
- pair->pair = edge;
-
- num++;
- }
- }
+ compute_controller->Refine(compute_context, farmesh->GetKernelBatches(), vbuf_base);
+ compute_controller->Synchronize();
- /* link boundary edges */
- for(int e = 0; e < num_edges; e++) {
- SubdEdge *edge = edges[e];
+ /* split & dice patches */
+ OpenSubdPatch patch(farmesh, vbuf_base);
- if(edge->pair->face == NULL)
- link_boundary_edge(edge->pair);
+ for(int f = 0; f < num_ptex_faces; f++) {
+ patch.face_id = f;
+ split->split_quad(&patch);
}
-
- /* detect boundary intersections */
- int boundaryIntersections = 0;
- int num_verts = verts.size();
- for(int v = 0; v < num_verts; v++) {
- SubdVert *vertex = verts[v];
+ /* clean up */
+ delete farmesh;
+ delete compute_controller;
+ delete compute_context;
+ delete vbuf_base;
+}
- int boundarySubdEdges = 0;
- for(SubdVert::EdgeIterator it(vertex->edges()); !it.isDone(); it.advance())
- if(it.current()->is_boundary())
- boundarySubdEdges++;
+CCL_NAMESPACE_END
- if(boundarySubdEdges > 2) {
- assert((boundarySubdEdges & 1) == 0);
- boundaryIntersections++;
- }
+#else /* WITH_OPENSUBDIV */
+
+CCL_NAMESPACE_BEGIN
+
+/* Subd Vertex */
+
+class SubdVert
+{
+public:
+ int id;
+ float3 co;
+
+ SubdVert(int id_)
+ {
+ id = id_;
+ co = make_float3(0.0f, 0.0f, 0.0f);
}
+};
- if(boundaryIntersections != 0) {
- fprintf(stderr, "Invalid mesh, boundary intersections found!\n");
- return false;
+/* Subd Face */
+
+class SubdFace
+{
+public:
+ int id;
+ int numverts;
+ int verts[4];
+
+ SubdFace(int id_)
+ {
+ id = id_;
+ numverts = 0;
}
+};
- return true;
+/* Subd Mesh */
+
+SubdMesh::SubdMesh()
+{
}
-void SubdMesh::link_boundary_edge(SubdEdge *edge)
+SubdMesh::~SubdMesh()
{
- /* link this boundary edge. */
+ foreach(SubdVert *vertex, verts)
+ delete vertex;
+ foreach(SubdFace *face, faces)
+ delete face;
- /* make sure next pointer has not been set. */
- assert(edge->face == NULL);
- assert(edge->next == NULL);
-
- SubdEdge *next = edge;
+ verts.clear();
+ faces.clear();
+}
- while(next->pair->face != NULL) {
- /* get pair prev */
- SubdEdge *e = next->pair->next;
+SubdVert *SubdMesh::add_vert(const float3& co)
+{
+ SubdVert *v = new SubdVert(verts.size());
+ v->co = co;
+ verts.push_back(v);
- while(e->next != next->pair)
- e = e->next;
+ return v;
+}
- next = e;
- }
+SubdFace *SubdMesh::add_face(int v0, int v1, int v2)
+{
+ int index[3] = {v0, v1, v2};
+ return add_face(index, 3);
+}
- edge->next = next->pair;
- next->pair->prev = edge;
-
- /* adjust vertex edge, so that it's the boundary edge. (required for is_boundary()) */
- if(edge->vert->edge != edge)
- edge->vert->edge = edge;
+SubdFace *SubdMesh::add_face(int v0, int v1, int v2, int v3)
+{
+ int index[4] = {v0, v1, v2, v3};
+ return add_face(index, 4);
+}
+
+SubdFace *SubdMesh::add_face(int *index, int num)
+{
+ /* skip ngons */
+ if(num < 3 || num > 4)
+ return NULL;
+
+ SubdFace *f = new SubdFace(faces.size());
+
+ for(int i = 0; i < num; i++)
+ f->verts[i] = index[i];
+
+ f->numverts = num;
+ faces.push_back(f);
+
+ return f;
+}
+
+bool SubdMesh::finish()
+{
+ return true;
}
-void SubdMesh::tessellate(DiagSplit *split, bool linear, Mesh *mesh, int shader, bool smooth)
+void SubdMesh::tessellate(DiagSplit *split)
{
- SubdBuilder *builder = SubdBuilder::create(linear);
int num_faces = faces.size();
for(int f = 0; f < num_faces; f++) {
SubdFace *face = faces[f];
- Patch *patch = builder->run(face);
+ Patch *patch;
+ float3 *hull;
+
+ if(face->numverts == 3) {
+ LinearTrianglePatch *lpatch = new LinearTrianglePatch();
+ hull = lpatch->hull;
+ patch = lpatch;
+ }
+ else if(face->numverts == 4) {
+ LinearQuadPatch *lpatch = new LinearQuadPatch();
+ hull = lpatch->hull;
+ patch = lpatch;
+ }
+ else {
+ assert(0); /* n-gons should have been split already */
+ continue;
+ }
+
+ for(int i = 0; i < face->numverts; i++)
+ hull[i] = verts[face->verts[i]]->co;
+
+ if(face->numverts == 4)
+ swap(hull[2], hull[3]);
if(patch->is_triangle())
- split->split_triangle(mesh, patch, shader, smooth);
+ split->split_triangle(patch);
else
- split->split_quad(mesh, patch, shader, smooth);
+ split->split_quad(patch);
delete patch;
}
-
- delete builder;
}
CCL_NAMESPACE_END
+#endif /* WITH_OPENSUBDIV */
+
diff --git a/intern/cycles/subd/subd_mesh.h b/intern/cycles/subd/subd_mesh.h
index e4bd5f192ab..f6aefc20318 100644
--- a/intern/cycles/subd/subd_mesh.h
+++ b/intern/cycles/subd/subd_mesh.h
@@ -35,22 +35,19 @@
CCL_NAMESPACE_BEGIN
-class SubdFace;
+#ifndef WITH_OPENSUBDIV
class SubdVert;
-class SubdEdge;
+class SubdFace;
+#endif
class DiagSplit;
class Mesh;
-/* Subd Mesh, half edge based for dynamic mesh manipulation */
+/* Subd Mesh with simple linear subdivision */
class SubdMesh
{
public:
- vector<SubdVert*> verts;
- vector<SubdEdge*> edges;
- vector<SubdFace*> faces;
-
SubdMesh();
~SubdMesh();
@@ -60,28 +57,19 @@ public:
SubdFace *add_face(int v0, int v1, int v2, int v3);
SubdFace *add_face(int *index, int num);
- bool link_boundary();
- void tessellate(DiagSplit *split, bool linear,
- Mesh *mesh, int shader, bool smooth);
+ bool finish();
+ void tessellate(DiagSplit *split);
protected:
- bool can_add_face(int *index, int num);
- bool can_add_edge(int i, int j);
- SubdEdge *add_edge(int i, int j);
- SubdEdge *find_edge(int i, int j);
- void link_boundary_edge(SubdEdge *edge);
-
- struct Key {
- Key() {}
- Key(int v0, int v1) : p0(v0), p1(v1) {}
-
- bool operator<(const Key& k) const
- { return (p0 < k.p0 || (p0 == k.p0 && p1 < k.p1)); }
-
- int p0, p1;
- };
+#ifdef WITH_OPENSUBDIV
+ void *_hbrmesh;
+ vector<float> positions;
+ int num_verts, num_ptex_faces;
+#else
+ vector<SubdVert*> verts;
+ vector<SubdFace*> faces;
+#endif
- map<Key, SubdEdge *> edge_map;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_patch.cpp b/intern/cycles/subd/subd_patch.cpp
index 4a029277370..fe9fa791813 100644
--- a/intern/cycles/subd/subd_patch.cpp
+++ b/intern/cycles/subd/subd_patch.cpp
@@ -27,14 +27,6 @@ CCL_NAMESPACE_BEGIN
/* De Casteljau Evaluation */
-static float3 decasteljau_quadratic(float t, const float3 cp[3])
-{
- float3 d0 = cp[0] + t*(cp[1] - cp[0]);
- float3 d1 = cp[1] + t*(cp[2] - cp[1]);
-
- return d0 + t*(d1 - d0);
-}
-
static void decasteljau_cubic(float3 *P, float3 *dt, float t, const float3 cp[4])
{
float3 d0 = cp[0] + t*(cp[1] - cp[0]);
@@ -63,17 +55,6 @@ static void decasteljau_bicubic(float3 *P, float3 *du, float3 *dv, const float3
if(du) decasteljau_cubic(du, NULL, v, utn);
}
-static float3 decasteljau_tangent(const float3 cp[12], float u, float v)
-{
- float3 ucp[3];
-
- decasteljau_cubic(ucp+0, NULL, v, cp);
- decasteljau_cubic(ucp+1, NULL, v, cp+4);
- decasteljau_cubic(ucp+2, NULL, v, cp+8);
-
- return decasteljau_quadratic(u, ucp);
-}
-
/* Linear Quad Patch */
void LinearQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
@@ -138,149 +119,5 @@ BoundBox BicubicPatch::bound()
return bbox;
}
-/* Bicubic Patch with Tangent Fields */
-
-void BicubicTangentPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
-{
- decasteljau_bicubic(P, NULL, NULL, hull, u, v);
-
- if(dPdu) *dPdu = decasteljau_tangent(utan, u, v);
- if(dPdv) *dPdv = decasteljau_tangent(vtan, v, u);
-}
-
-BoundBox BicubicTangentPatch::bound()
-{
- BoundBox bbox = BoundBox::empty;
-
- for(int i = 0; i < 16; i++)
- bbox.grow(hull[i]);
-
- return bbox;
-}
-
-/* Gregory Patch */
-
-static float no_zero_div(float f)
-{
- if(f == 0.0f) return 1.0f;
- return f;
-}
-
-void GregoryQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
-{
- float3 bicubic[16];
-
- float U = 1 - u;
- float V = 1 - v;
-
- /* 8 9 10 11
- * 12 0\1 2/3 13
- * 14 4/5 6\7 15
- * 16 17 18 19
- */
-
- bicubic[5] = (u*hull[1] + v*hull[0])/no_zero_div(u + v);
- bicubic[6] = (U*hull[2] + v*hull[3])/no_zero_div(U + v);
- bicubic[9] = (u*hull[5] + V*hull[4])/no_zero_div(u + V);
- bicubic[10] = (U*hull[6] + V*hull[7])/no_zero_div(U + V);
-
- // Map gregory control points to bezier control points.
- bicubic[0] = hull[8];
- bicubic[1] = hull[9];
- bicubic[2] = hull[10];
- bicubic[3] = hull[11];
- bicubic[4] = hull[12];
- bicubic[7] = hull[13];
- bicubic[8] = hull[14];
- bicubic[11] = hull[15];
- bicubic[12] = hull[16];
- bicubic[13] = hull[17];
- bicubic[14] = hull[18];
- bicubic[15] = hull[19];
-
- decasteljau_bicubic(P, dPdu, dPdv, bicubic, u, v);
-}
-
-BoundBox GregoryQuadPatch::bound()
-{
- BoundBox bbox = BoundBox::empty;
-
- for(int i = 0; i < 20; i++)
- bbox.grow(hull[i]);
-
- return bbox;
-}
-
-void GregoryTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
-{
- /* 6
- *
- * 14 0/1 7
- *
- * 13 5/4 3\2 8
- *
- * 12 11 10 9
- */
-
- float w = 1 - u - v;
- float uu = u * u;
- float vv = v * v;
- float ww = w * w;
- float uuu = uu * u;
- float vvv = vv * v;
- float www = ww * w;
-
- float U = 1 - u;
- float V = 1 - v;
- float W = 1 - w;
-
- float3 C0 = ( v*U * hull[5] + u*V * hull[4] ) / no_zero_div(v*U + u*V);
- float3 C1 = ( w*V * hull[3] + v*W * hull[2] ) / no_zero_div(w*V + v*W);
- float3 C2 = ( u*W * hull[1] + w*U * hull[0] ) / no_zero_div(u*W + w*U);
-
- *P =
- (hull[12] * www + 3*hull[11] * ww*u + 3*hull[10] * w*uu + hull[ 9]*uuu) * (w + u) +
- (hull[ 9] * uuu + 3*hull[ 8] * uu*v + 3*hull[ 7] * u*vv + hull[ 6]*vvv) * (u + v) +
- (hull[ 6] * vvv + 3*hull[14] * vv*w + 3*hull[13] * v*ww + hull[12]*www) * (v + w) -
- (hull[12] * www*w + hull[ 9] * uuu*u + hull[ 6] * vvv*v) +
- 12*(C0 * u*v*ww + C1 * uu*v*w + C2 * u*vv*w);
-
- if(dPdu || dPdv) {
- float3 E1 = (hull[12]*www + 3*hull[11]*ww*u + 3*hull[10]*w*uu + hull[ 9]*uuu);
- float3 E2 = (hull[ 9]*uuu + 3*hull[ 8]*uu*v + 3*hull[ 7]*u*vv + hull[ 6]*vvv);
- float3 E3 = (hull[ 6]*vvv + 3*hull[14]*vv*w + 3*hull[13]*v*ww + hull[12]*www);
-
- if(dPdu) {
- float3 E1u = 3*( - hull[12]*ww + hull[11]*(ww-2*u*w) + hull[10]*(2*u*w-uu) + hull[ 9]*uu);
- float3 E2u = 3*( hull[ 9]*uu + 2*hull[ 8]*u*v + hull[ 7]*vv );
- float3 E3u = 3*( - hull[14]*vv - 2*hull[13]*v*w - hull[12]*ww);
- float3 Su = 4*( -hull[12]*www + hull[9]*uuu);
- float3 Cu = 12*( C0*(ww*v-2*u*v*w) + C1*(2*u*v*w-uu*v) + C2*vv*(w-u) );
-
- *dPdu = E1u*(w+u) + (E2+E2u*(u+v)) + (E3u*(v+w)-E3) - Su + Cu;
- }
-
- if(dPdv) {
- float3 E1v = 3*(-hull[12]*ww - 2*hull[11]*w*u - hull[10]*uu );
- float3 E2v = 3*( hull[ 8]*uu + 2*hull[ 7]*u*v + hull[ 6]*vv);
- float3 E3v = 3*( hull[ 6]*vv + hull[14]*(2*w*v-vv) + hull[13]*(ww-2*w*v) - hull[12]*ww);
- float3 Sv = 4*(-hull[12]*www + hull[ 6]*vvv);
- float3 Cv = 12*(C0*(u*ww-2*u*v*w) + C1*uu*(w-v) + C2*(2*u*v*w-u*vv));
-
- *dPdv = ((E1v*(w+u)-E1) + (E2+E2v*(u+v)) + E3v*(v+w) - Sv + Cv );
- }
- }
-}
-
-BoundBox GregoryTrianglePatch::bound()
-{
- BoundBox bbox = BoundBox::empty;
-
- for(int i = 0; i < 20; i++)
- bbox.grow(hull[i]);
-
- return bbox;
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_patch.h b/intern/cycles/subd/subd_patch.h
index 7755740ea0c..48f35d78711 100644
--- a/intern/cycles/subd/subd_patch.h
+++ b/intern/cycles/subd/subd_patch.h
@@ -22,16 +22,13 @@
CCL_NAMESPACE_BEGIN
-class Mesh;
-
-/* Base */
-
class Patch {
public:
virtual ~Patch() {}
virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v) = 0;
- virtual bool is_triangle() = 0;
+ virtual bool is_triangle() { return false; }
virtual BoundBox bound() = 0;
+ virtual int ptex_face_id() { return -1; }
};
/* Linear Quad Patch */
@@ -67,39 +64,6 @@ public:
BoundBox bound();
};
-/* Bicubic Patch with Tangent Fields */
-
-class BicubicTangentPatch : public Patch {
-public:
- float3 hull[16];
- float3 utan[12];
- float3 vtan[12];
-
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v);
- bool is_triangle() { return false; }
- BoundBox bound();
-};
-
-/* Gregory Patches */
-
-class GregoryQuadPatch : public Patch {
-public:
- float3 hull[20];
-
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v);
- bool is_triangle() { return false; }
- BoundBox bound();
-};
-
-class GregoryTrianglePatch : public Patch {
-public:
- float3 hull[20];
-
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v);
- bool is_triangle() { return true; }
- BoundBox bound();
-};
-
CCL_NAMESPACE_END
#endif /* __SUBD_PATCH_H__ */
diff --git a/intern/cycles/subd/subd_ring.cpp b/intern/cycles/subd/subd_ring.cpp
deleted file mode 100644
index 66eab02231c..00000000000
--- a/intern/cycles/subd/subd_ring.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "subd_face.h"
-#include "subd_ring.h"
-#include "subd_stencil.h"
-#include "subd_vert.h"
-
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_math.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Utility for sorting verts by index */
-
-class vertex_compare
-{
-public:
- const vector<int>& index;
- vertex_compare(const vector<int>& index_) : index(index_) {}
- bool operator()(int a, int b) const { return index[a] < index[b]; }
-};
-
-/* Subd Face Ring */
-
-SubdFaceRing::SubdFaceRing(SubdFace *face, SubdEdge *firstEdge)
-{
- m_face = face;
- m_firstEdge = firstEdge;
- m_num_edges = face->num_edges();
-
- assert(m_num_edges == 3 || m_num_edges == 4);
-
- initVerts();
-}
-
-int SubdFaceRing::num_verts()
-{
- return m_verts.size();
-}
-
-SubdVert *SubdFaceRing::vertexAt(int i)
-{
- return m_verts[i];
-}
-
-int SubdFaceRing::vert_index(SubdVert *vertex)
-{
- int count = this->num_verts();
-
- for(int i = 0; i < count; i++)
- if(m_verts[i] == vertex)
- return i;
-
- assert(0);
- return 0;
-}
-
-void SubdFaceRing::evaluate_stencils(float3 *P, StencilMask *mask, int num)
-{
- /* first we sort verts by id. this way verts will always be added
- * in the same order to ensure the exact same float ops happen for control
- * points of other patches, so we get water-tight patches */
- int num_verts = m_verts.size();
-
- vector<int> vmap(num_verts);
- vector<int> vertid(num_verts);
-
- for(int v = 0; v < num_verts; v++) {
- vmap[v] = v;
- vertid[v] = m_verts[v]->id;
- }
-
- sort(vmap.begin(), vmap.end(), vertex_compare(vertid));
-
- /* then evaluate the stencils */
- for(int j = 0; j < num; j++) {
- float3 p = make_float3(0.0f, 0.0f, 0.0f);
-
- for(int i = 0; i < num_verts; i++) {
- int idx = vmap[i];
- p += m_verts[idx]->co * mask[j][idx];
- }
-
- P[j] = p;
- }
-}
-
-bool SubdFaceRing::is_triangle()
-{
- return m_num_edges == 3;
-}
-
-bool SubdFaceRing::is_quad()
-{
- return m_num_edges == 4;
-}
-
-int SubdFaceRing::num_edges()
-{
- return m_num_edges;
-}
-
-bool SubdFaceRing::is_regular(SubdFace *face)
-{
- if(!is_quad(face))
- return false;
-
- for(SubdFace::EdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
- SubdEdge *edge = it.current();
-
- /* regular faces don't have boundary edges */
- if(edge->is_boundary())
- return false;
-
- /* regular faces only have ordinary verts */
- if(edge->vert->valence() != 4)
- return false;
-
- /* regular faces are only adjacent to quads */
- for(SubdVert::EdgeIterator eit(edge); !eit.isDone(); eit.advance())
- if(eit.current()->face == NULL || eit.current()->face->num_edges() != 4)
- return false;
- }
-
- return true;
-}
-
-bool SubdFaceRing::is_triangle(SubdFace *face)
-{
- return face->num_edges() == 3;
-}
-bool SubdFaceRing::is_quad(SubdFace *face)
-{
- return face->num_edges() == 4;
-}
-
-bool SubdFaceRing::is_boundary(SubdFace *face)
-{
- /* note that face->is_boundary() returns a different result. That function
- * returns true when any of the *edges* are on the boundary. however, this
- * function returns true if any of the face *verts* are on the boundary. */
-
- for(SubdFace::EdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
- SubdEdge *edge = it.current();
-
- if(edge->vert->is_boundary())
- return true;
- }
-
- return false;
-}
-
-void SubdFaceRing::initVerts()
-{
- m_verts.reserve(16);
-
- /* add face verts */
- for(SubdFace::EdgeIterator it(m_firstEdge); !it.isDone(); it.advance()) {
- SubdEdge *edge = it.current();
- m_verts.push_back(edge->from());
- }
-
- // @@ Add support for non manifold surfaces!
- // The fix:
- // - not all colocals should point to the same edge.
- // - multiple colocals could belong to different boundaries, make sure they point to the right one.
-
- // @@ When the face neighborhood wraps that could result in overlapping stencils.
-
- // Add surronding verts.
- for(SubdFace::EdgeIterator it(m_firstEdge); !it.isDone(); it.advance()) {
- SubdEdge *firstEdge = it.current();
-
- int i = 0;
-
- /* traverse edges around vertex */
- for(SubdVert::ReverseEdgeIterator eit(firstEdge); !eit.isDone(); eit.advance(), i++) {
- SubdEdge *edge = eit.current();
-
- assert(edge->from()->co == firstEdge->from()->co);
-
- add_vert(edge->to());
-
- if(edge->face != NULL)
- add_vert(edge->next->to());
- }
-
- assert(i == firstEdge->from()->valence());
- }
-}
-
-
-void SubdFaceRing::add_vert(SubdVert *vertex)
-{
- /* avoid having duplicate verts */
- if(!has_vert(vertex))
- m_verts.push_back(vertex);
-}
-
-bool SubdFaceRing::has_vert(SubdVert *vertex)
-{
- int num_verts = m_verts.size();
-
- for(int i = 0; i < num_verts; i++)
- if(m_verts[i]->co == vertex->co)
- return true;
-
- return false;
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/subd/subd_ring.h b/intern/cycles/subd/subd_ring.h
deleted file mode 100644
index f25342233b0..00000000000
--- a/intern/cycles/subd/subd_ring.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#ifndef __SUBD_FACE_RING_H__
-#define __SUBD_FACE_RING_H__
-
-CCL_NAMESPACE_BEGIN
-
-class StencilMask;
-class SubdVert;
-class SubdEdge;
-class SubdFace;
-
-class SubdFaceRing
-{
-public:
- SubdFaceRing(SubdFace *face, SubdEdge *edge);
-
- SubdFace *face() { return m_face; }
- SubdEdge *firstEdge() { return m_firstEdge; }
-
- int num_verts();
- SubdVert *vertexAt(int i);
- int vert_index(SubdVert *vertex);
-
- void evaluate_stencils(float3 *P, StencilMask *mask, int num);
-
- bool is_triangle();
- bool is_quad();
- int num_edges();
-
- static bool is_regular(SubdFace *face);
- static bool is_triangle(SubdFace *face);
- static bool is_quad(SubdFace *face);
- static bool is_boundary(SubdFace *face);
-
-protected:
- void initVerts();
- void add_vert(SubdVert *vertex);
- bool has_vert(SubdVert *vertex);
-
-protected:
- SubdFace *m_face;
- SubdEdge *m_firstEdge;
-
- int m_num_edges;
- vector<SubdVert*> m_verts;
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_FACE_RING_H__ */
-
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index 6c1486cecca..417ecfffd49 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -29,12 +29,9 @@ CCL_NAMESPACE_BEGIN
/* DiagSplit */
-DiagSplit::DiagSplit()
+DiagSplit::DiagSplit(const SubdParams& params_)
+: params(params_)
{
- test_steps = 3;
- split_threshold = 1;
- dicing_rate = 0.1f;
- camera = NULL;
}
void DiagSplit::dispatch(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef)
@@ -54,8 +51,8 @@ float3 DiagSplit::project(Patch *patch, float2 uv)
float3 P;
patch->eval(&P, NULL, NULL, uv.x, uv.y);
- if(camera)
- P = transform_perspective(&camera->worldtoraster, P);
+ if(params.camera)
+ P = transform_perspective(&params.camera->worldtoraster, P);
return P;
}
@@ -66,8 +63,8 @@ int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend)
float Lsum = 0.0f;
float Lmax = 0.0f;
- for(int i = 0; i < test_steps; i++) {
- float t = i/(float)(test_steps-1);
+ for(int i = 0; i < params.test_steps; i++) {
+ float t = i/(float)(params.test_steps-1);
float3 P = project(patch, Pstart + t*(Pend - Pstart));
@@ -80,10 +77,10 @@ int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend)
Plast = P;
}
- int tmin = (int)ceil(Lsum/dicing_rate);
- int tmax = (int)ceil((test_steps-1)*Lmax/dicing_rate); // XXX paper says N instead of N-1, seems wrong?
+ int tmin = (int)ceil(Lsum/params.dicing_rate);
+ int tmax = (int)ceil((params.test_steps-1)*Lmax/params.dicing_rate); // XXX paper says N instead of N-1, seems wrong?
- if(tmax - tmin > split_threshold)
+ if(tmax - tmin > params.split_threshold)
return DSPLIT_NON_UNIFORM;
return tmax;
@@ -244,7 +241,7 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de
dispatch(sub, ef);
}
-void DiagSplit::split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth)
+void DiagSplit::split_triangle(Patch *patch)
{
TriangleDice::SubPatch sub_split;
TriangleDice::EdgeFactors ef_split;
@@ -260,8 +257,7 @@ void DiagSplit::split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth
split(sub_split, ef_split);
- TriangleDice dice(mesh, shader, smooth, dicing_rate);
- dice.camera = camera;
+ TriangleDice dice(params);
for(size_t i = 0; i < subpatches_triangle.size(); i++) {
TriangleDice::SubPatch& sub = subpatches_triangle[i];
@@ -282,7 +278,7 @@ void DiagSplit::split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth
edgefactors_triangle.clear();
}
-void DiagSplit::split_quad(Mesh *mesh, Patch *patch, int shader, bool smooth)
+void DiagSplit::split_quad(Patch *patch)
{
QuadDice::SubPatch sub_split;
QuadDice::EdgeFactors ef_split;
@@ -300,8 +296,7 @@ void DiagSplit::split_quad(Mesh *mesh, Patch *patch, int shader, bool smooth)
split(sub_split, ef_split);
- QuadDice dice(mesh, shader, smooth, dicing_rate);
- dice.camera = camera;
+ QuadDice dice(params);
for(size_t i = 0; i < subpatches_quad.size(); i++) {
QuadDice::SubPatch& sub = subpatches_quad[i];
diff --git a/intern/cycles/subd/subd_split.h b/intern/cycles/subd/subd_split.h
index 9dd10f8af8f..3f9a2721977 100644
--- a/intern/cycles/subd/subd_split.h
+++ b/intern/cycles/subd/subd_split.h
@@ -41,12 +41,9 @@ public:
vector<TriangleDice::SubPatch> subpatches_triangle;
vector<TriangleDice::EdgeFactors> edgefactors_triangle;
- int test_steps;
- int split_threshold;
- float dicing_rate;
- Camera *camera;
+ SubdParams params;
- DiagSplit();
+ DiagSplit(const SubdParams& params);
float3 project(Patch *patch, float2 uv);
int T(Patch *patch, float2 Pstart, float2 Pend);
@@ -59,8 +56,8 @@ public:
void dispatch(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef);
void split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int depth=0);
- void split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth);
- void split_quad(Mesh *mesh, Patch *patch, int shader, bool smooth);
+ void split_triangle(Patch *patch);
+ void split_quad(Patch *patch);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_stencil.cpp b/intern/cycles/subd/subd_stencil.cpp
deleted file mode 100644
index 5f76a942a59..00000000000
--- a/intern/cycles/subd/subd_stencil.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2011-2013 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 "subd_stencil.h"
-
-#include "util_debug.h"
-#include "util_math.h"
-
-CCL_NAMESPACE_BEGIN
-
-StencilMask::StencilMask()
-{
-}
-
-StencilMask::StencilMask(int size)
-{
- /* initialize weights to zero. */
- weights.resize(size, 0.0f);
-}
-
-void StencilMask::resize(int size)
-{
- weights.resize(size, 0.0f);
-}
-
-StencilMask& StencilMask::operator=(float value)
-{
- const int size = weights.size();
- for(int i = 0; i < size; i++)
- weights[i] = value;
-
- return *this;
-}
-
-void StencilMask::operator+=(const StencilMask& mask)
-{
- assert(mask.size() == size());
-
- const int size = weights.size();
- for(int i = 0; i < size; i++)
- weights[i] += mask.weights[i];
-}
-
-void StencilMask::operator-=(const StencilMask& mask)
-{
- assert(mask.size() == size());
-
- const int size = weights.size();
- for(int i = 0; i < size; i++)
- weights[i] -= mask.weights[i];
-}
-
-void StencilMask::operator*=(float scale)
-{
- const int size = weights.size();
-
- for(int i = 0; i < size; i++)
- weights[i] *= scale;
-}
-
-void StencilMask::operator/=(float scale)
-{
- *this *= 1.0f/scale;
-}
-
-float StencilMask::sum() const
-{
- float total = 0.0f;
- const int size = weights.size();
-
- for(int i = 0; i < size; i++)
- total += weights[i];
-
- return total;
-}
-
-bool StencilMask::is_normalized() const
-{
- return fabsf(sum() - 1.0f) < 0.0001f;
-}
-
-void StencilMask::normalize()
-{
- *this /= sum();
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/subd/subd_stencil.h b/intern/cycles/subd/subd_stencil.h
deleted file mode 100644
index e11d8f37cd3..00000000000
--- a/intern/cycles/subd/subd_stencil.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#ifndef __SUBD_STENCIL__
-#define __SUBD_STENCIL__
-
-#include "util_types.h"
-#include "util_vector.h"
-
-CCL_NAMESPACE_BEGIN
-
-class StencilMask
-{
-public:
- StencilMask();
- StencilMask(int size);
-
- void resize(int size);
-
- StencilMask& operator=(float value);
-
- void operator+=(const StencilMask& mask);
- void operator-=(const StencilMask& mask);
- void operator*=(float scale);
- void operator/=(float scale);
-
- int size() const { return weights.size(); }
-
- float operator[](int i) const { return weights[i]; }
- float& operator[](int i) { return weights[i]; }
-
- float sum() const;
- bool is_normalized() const;
- void normalize();
-
-private:
- vector<float> weights;
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_STENCIL__ */
-
diff --git a/intern/cycles/subd/subd_vert.h b/intern/cycles/subd/subd_vert.h
deleted file mode 100644
index 638019547ae..00000000000
--- a/intern/cycles/subd/subd_vert.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Original code in the public domain -- castanyo@yahoo.es
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __SUBD_VERTEX_H__
-#define __SUBD_VERTEX_H__
-
-#include "subd_edge.h"
-#include "subd_mesh.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Vertex */
-
-class SubdVert
-{
-public:
- int id;
- float3 co;
-
- SubdEdge *edge;
- SubdVert *next;
- SubdVert *prev;
-
- SubdVert(int id_)
- {
- id = id_;
- edge = NULL;
- co = make_float3(0.0f, 0.0f, 0.0f);
-
- next = this;
- prev = this;
- }
-
- /* valence */
- int valence()
- {
- int num = 0;
-
- for(EdgeIterator it(edges()); !it.isDone(); it.advance())
- num++;
-
- return num;
- }
-
- /* edge queries */
- bool is_boundary() { return (edge && !edge->face); }
-
- /* iterator over edges in counterclockwise order */
- class EdgeIterator
- {
- public:
- EdgeIterator(SubdEdge *e) : end(NULL), cur(e) { }
-
- virtual void advance()
- {
- if(end == NULL) end = cur;
- cur = cur->pair->next;
- //cur = cur->prev->pair;
- }
-
- virtual bool isDone() { return end == cur; }
- virtual SubdEdge *current() { return cur; }
-
- private:
- SubdEdge *end;
- SubdEdge *cur;
- };
-
- /* iterator over edges in clockwise order */
- class ReverseEdgeIterator
- {
- public:
- ReverseEdgeIterator(SubdEdge *e) : end(NULL), cur(e) { }
-
- virtual void advance()
- {
- if(end == NULL) end = cur;
- cur = cur->prev->pair;
- }
-
- virtual bool isDone() { return end == cur; }
- virtual SubdEdge *current() { return cur; }
-
- private:
- SubdEdge *end;
- SubdEdge *cur;
- };
-
- EdgeIterator edges() { return EdgeIterator(edge); }
- EdgeIterator edges(SubdEdge *edge) { return EdgeIterator(edge); }
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_VERTEX_H__ */
-