From 731ffd3cd4c1d578fb02d39dc512bace850c2e8b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 28 Nov 2013 00:13:32 +0100 Subject: Cycles: remove approximate subdivision surface with gregory patches code. It was never fully implemented and will be replaced by OpenSubdiv. Only linear subdivision remains now. Also includes some refactoring in the split/dice code, adding a SubdParams struct to pass around parameters more easily. --- intern/cycles/subd/CMakeLists.txt | 9 - intern/cycles/subd/subd_build.cpp | 669 ------------------------------------ intern/cycles/subd/subd_build.h | 73 ---- intern/cycles/subd/subd_dice.cpp | 78 ++--- intern/cycles/subd/subd_dice.h | 40 ++- intern/cycles/subd/subd_edge.h | 70 ---- intern/cycles/subd/subd_face.h | 109 ------ intern/cycles/subd/subd_mesh.cpp | 270 ++++----------- intern/cycles/subd/subd_mesh.h | 30 +- intern/cycles/subd/subd_patch.cpp | 163 --------- intern/cycles/subd/subd_patch.h | 39 +-- intern/cycles/subd/subd_ring.cpp | 236 ------------- intern/cycles/subd/subd_ring.h | 75 ---- intern/cycles/subd/subd_split.cpp | 31 +- intern/cycles/subd/subd_split.h | 11 +- intern/cycles/subd/subd_stencil.cpp | 101 ------ intern/cycles/subd/subd_stencil.h | 65 ---- intern/cycles/subd/subd_vert.h | 121 ------- 18 files changed, 157 insertions(+), 2033 deletions(-) delete mode 100644 intern/cycles/subd/subd_build.cpp delete mode 100644 intern/cycles/subd/subd_build.h delete mode 100644 intern/cycles/subd/subd_edge.h delete mode 100644 intern/cycles/subd/subd_face.h delete mode 100644 intern/cycles/subd/subd_ring.cpp delete mode 100644 intern/cycles/subd/subd_ring.h delete mode 100644 intern/cycles/subd/subd_stencil.cpp delete mode 100644 intern/cycles/subd/subd_stencil.h delete mode 100644 intern/cycles/subd/subd_vert.h (limited to 'intern/cycles/subd') 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 - * - * 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..f77df388c87 100644 --- a/intern/cycles/subd/subd_dice.cpp +++ b/intern/cycles/subd/subd_dice.cpp @@ -26,22 +26,20 @@ 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); } void EdgeDice::reserve(int num_verts, int num_tris) { + Mesh *mesh = params.mesh; + vert_offset = mesh->verts.size(); tri_offset = mesh->triangles.size(); @@ -60,7 +58,7 @@ 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; @@ -68,12 +66,13 @@ int EdgeDice::add_vert(Patch *patch, float2 uv) 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); + tri_offset++; } -void EdgeDice::stitch_triangles(vector& outer, vector& inner) +void EdgeDice::stitch_triangles(Patch *patch, vector& outer, vector& inner) { if(inner.size() == 0 || outer.size() == 0) return; // XXX avoid crashes for Mu or Mv == 1, missing polygons @@ -106,14 +105,14 @@ void EdgeDice::stitch_triangles(vector& outer, vector& 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 +120,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 +138,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(¶ms.camera->worldtoraster, P); return P; } @@ -222,7 +222,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 +270,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 +288,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 +299,27 @@ void QuadDice::dice(SubPatch& sub, EdgeFactors& ef) vector 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 +417,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 +429,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 +452,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..037b17bbfc8 100644 --- a/intern/cycles/subd/subd_dice.h +++ b/intern/cycles/subd/subd_dice.h @@ -31,28 +31,48 @@ class Camera; class Mesh; class Patch; +struct SubdParams { + Mesh *mesh; + int shader; + bool smooth; + + int test_steps; + int split_threshold; + float dicing_rate; + Camera *camera; + + SubdParams(Mesh *mesh_, int shader_, bool smooth_ = true) + { + mesh = mesh_; + shader = shader_; + smooth = smooth_; + + 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& outer, vector& inner); + void stitch_triangles(Patch *patch, vector& outer, vector& inner); }; /* Quad EdgeDice @@ -86,7 +106,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 +160,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..29e487cd5d9 100644 --- a/intern/cycles/subd/subd_mesh.cpp +++ b/intern/cycles/subd/subd_mesh.cpp @@ -28,37 +28,60 @@ #include -#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" 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); + } +}; + +/* Subd Face */ + +class SubdFace +{ +public: + int id; + int numverts; + int verts[4]; + + SubdFace(int id_) + { + id = id_; + numverts = 0; + } +}; + +/* Subd Mesh */ + SubdMesh::SubdMesh() { } SubdMesh::~SubdMesh() { - pair em; - foreach(SubdVert *vertex, verts) delete vertex; - foreach(em, edge_map) - delete em.second; foreach(SubdFace *face, faces) delete face; verts.clear(); - edges.clear(); - edge_map.clear(); faces.clear(); } @@ -85,224 +108,63 @@ SubdFace *SubdMesh::add_face(int v0, int v1, int v2, int v3) SubdFace *SubdMesh::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()); + /* skip ngons */ + if(num < 3 || num > 4) 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; - } - - current = add_edge(index[num-1], index[0]); - assert(current != NULL); - - current->face = f; - last->next = current; - current->prev = last; + SubdFace *f = new SubdFace(faces.size()); - current->next = first_edge; - first_edge->prev = current; + for(int i = 0; i < num; i++) + f->verts[i] = index[i]; - f->edge = first_edge; + f->numverts = num; faces.push_back(f); return f; } -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; - - return can_add_edge(index[num-1], index[0]); -} - -bool SubdMesh::can_add_edge(int i, int j) -{ - /* check for degenerate edge */ - if(i == j) - return false; - - /* make sure edge has not been added yet. */ - return find_edge(i, j) == NULL; -} - -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; -} - -SubdEdge *SubdMesh::find_edge(int i, int j) +bool SubdMesh::finish() { - map::const_iterator it = edge_map.find(Key(i, j)); - - return (it == edge_map.end())? NULL: it->second; -} - -bool SubdMesh::link_boundary() -{ - /* link boundary edges once the mesh has been created */ - int num = 0; - - /* create boundary edges */ - int num_edges = edges.size(); - - for(int e = 0; e < num_edges; e++) { - SubdEdge *edge = edges[e]; - - if(edge->pair == NULL) { - SubdEdge *pair = new SubdEdge(edge->id + 1); - - int i = edge->from()->id; - int j = edge->to()->id; - - assert(edge_map.find(Key(j, i)) == edge_map.end()); - - pair->vert = verts[j]; - edge_map[Key(j, i)] = pair; - - edge->pair = pair; - pair->pair = edge; - - num++; - } - } - - /* link boundary edges */ - for(int e = 0; e < num_edges; e++) { - SubdEdge *edge = edges[e]; - - if(edge->pair->face == NULL) - link_boundary_edge(edge->pair); - } - - /* detect boundary intersections */ - int boundaryIntersections = 0; - int num_verts = verts.size(); - - for(int v = 0; v < num_verts; v++) { - SubdVert *vertex = verts[v]; - - int boundarySubdEdges = 0; - for(SubdVert::EdgeIterator it(vertex->edges()); !it.isDone(); it.advance()) - if(it.current()->is_boundary()) - boundarySubdEdges++; - - if(boundarySubdEdges > 2) { - assert((boundarySubdEdges & 1) == 0); - boundaryIntersections++; - } - } - - if(boundaryIntersections != 0) { - fprintf(stderr, "Invalid mesh, boundary intersections found!\n"); - return false; - } - return true; } -void SubdMesh::link_boundary_edge(SubdEdge *edge) -{ - /* link this boundary edge. */ - - /* make sure next pointer has not been set. */ - assert(edge->face == NULL); - assert(edge->next == NULL); - - SubdEdge *next = edge; - - while(next->pair->face != NULL) { - /* get pair prev */ - SubdEdge *e = next->pair->next; - - while(e->next != next->pair) - e = e->next; - - next = e; - } - - 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; -} - -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 diff --git a/intern/cycles/subd/subd_mesh.h b/intern/cycles/subd/subd_mesh.h index e4bd5f192ab..96557692f05 100644 --- a/intern/cycles/subd/subd_mesh.h +++ b/intern/cycles/subd/subd_mesh.h @@ -35,20 +35,18 @@ CCL_NAMESPACE_BEGIN -class SubdFace; class SubdVert; -class SubdEdge; +class SubdFace; class DiagSplit; class Mesh; -/* Subd Mesh, half edge based for dynamic mesh manipulation */ +/* Subd Mesh with simple linear subdivision */ class SubdMesh { public: vector verts; - vector edges; vector faces; SubdMesh(); @@ -60,28 +58,8 @@ 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); - -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; - }; - - map edge_map; + bool finish(); + void tessellate(DiagSplit *split); }; 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..b851fef16ae 100644 --- a/intern/cycles/subd/subd_patch.h +++ b/intern/cycles/subd/subd_patch.h @@ -22,15 +22,11 @@ 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; }; @@ -67,39 +63,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 - * - * 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& index; - vertex_compare(const vector& 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 vmap(num_verts); - vector 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 - * - * 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 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(¶ms.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 subpatches_triangle; vector 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 - * - * 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 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__ */ - -- cgit v1.2.3 From 44d1c92e60f85fd0d757b9fc503ae32284540814 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 28 Nov 2013 01:28:57 +0100 Subject: Cycles: add ptex face ID and UV attributes. Not the most memory efficient way to store these things but it's simple and implementing it better requires some work to natively support subd grids as a primitive in some way. --- intern/cycles/subd/subd_dice.cpp | 22 ++++++++++++++++++++++ intern/cycles/subd/subd_dice.h | 4 +++- intern/cycles/subd/subd_patch.h | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) (limited to 'intern/cycles/subd') diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp index f77df388c87..05ff5ca4b65 100644 --- a/intern/cycles/subd/subd_dice.cpp +++ b/intern/cycles/subd/subd_dice.cpp @@ -34,6 +34,11 @@ EdgeDice::EdgeDice(const SubdParams& params_) vert_offset = 0; 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) @@ -63,12 +68,29 @@ int EdgeDice::add_vert(Patch *patch, float2 uv) 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(Patch *patch, int v0, int v1, int v2) { 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++; } diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h index 037b17bbfc8..9cf5b0d50b8 100644 --- a/intern/cycles/subd/subd_dice.h +++ b/intern/cycles/subd/subd_dice.h @@ -35,17 +35,19 @@ 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) + 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; diff --git a/intern/cycles/subd/subd_patch.h b/intern/cycles/subd/subd_patch.h index b851fef16ae..48f35d78711 100644 --- a/intern/cycles/subd/subd_patch.h +++ b/intern/cycles/subd/subd_patch.h @@ -28,6 +28,7 @@ public: virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v) = 0; virtual bool is_triangle() { return false; } virtual BoundBox bound() = 0; + virtual int ptex_face_id() { return -1; } }; /* Linear Quad Patch */ -- cgit v1.2.3 From 62bf24a5c3ec244cfdfea16b446e2de2e593181d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 28 Nov 2013 02:10:02 +0100 Subject: Cycles: experimental OpenSubdiv code. This code can't actually be enabled for building and is incomplete, but it's here because we know we want to support this at some point and there's not much reason to have it in a separate branch if a simple #ifdef can disable it. --- intern/cycles/subd/subd_mesh.cpp | 247 +++++++++++++++++++++++++++++++++++++++ intern/cycles/subd/subd_mesh.h | 16 ++- 2 files changed, 260 insertions(+), 3 deletions(-) (limited to 'intern/cycles/subd') diff --git a/intern/cycles/subd/subd_mesh.cpp b/intern/cycles/subd/subd_mesh.cpp index 29e487cd5d9..0db20656f39 100644 --- a/intern/cycles/subd/subd_mesh.cpp +++ b/intern/cycles/subd/subd_mesh.cpp @@ -35,6 +35,251 @@ #include "util_debug.h" #include "util_foreach.h" +#ifdef WITH_OPENSUBDIV + +#include +#include +#include +#include +#include +#include + +CCL_NAMESPACE_BEGIN + +/* typedefs */ +typedef OpenSubdiv::OsdVertex OsdVertex; +typedef OpenSubdiv::FarMesh OsdFarMesh; +typedef OpenSubdiv::FarMeshFactory OsdFarMeshFactory; +typedef OpenSubdiv::HbrCatmarkSubdivision OsdHbrCatmarkSubdivision; +typedef OpenSubdiv::HbrFace OsdHbrFace; +typedef OpenSubdiv::HbrHalfedge OsdHbrHalfEdge; +typedef OpenSubdiv::HbrMesh OsdHbrMesh; +typedef OpenSubdiv::HbrVertex 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(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; +} + +OpenSubdMesh::~OpenSubdMesh() +{ + OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh; + + if(hbrmesh) + delete hbrmesh; +} + +void OpenSubdMesh::add_vert(const float3& co) +{ + OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh; + + OsdVertex v; + positions.push_back(co.x); + positions.push_back(co.y); + positions.push_back(co.z); + hbrmesh->NewVertex(num_verts++, v); +} + +void OpenSubdMesh::add_face(int v0, int v1, int v2) +{ + int index[3] = {v0, v1, v2}; + return add_face(index, 3); +} + +void OpenSubdMesh::add_face(int v0, int v1, int v2, int v3) +{ + int index[4] = {v0, v1, v2, v3}; + add_face(index, 4); +} + +void OpenSubdMesh::add_face(int *index, int num) +{ + OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh; + +#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); + + if(origin==NULL || destination==NULL) + assert("An edge was specified that connected a nonexistent vertex\n"); + + if(origin == destination) + assert("An edge was specified that connected a vertex to itself\n"); + + if(opposite && opposite->GetOpposite()) + assert("A non-manifold edge incident to more than 2 faces was found\n"); + + 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 + + OsdHbrFace *face = hbrmesh->NewFace(num, index, 0); + + /* this is required for limit eval patch table? */ + face->SetPtexIndex(num_ptex_faces); + + if(num == 4) + num_ptex_faces++; + else + num_ptex_faces += num; +} + +bool OpenSubdMesh::finish() +{ + OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh; + + /* finish hbr mesh construction */ + hbrmesh->SetInterpolateBoundaryMethod(OsdHbrMesh::k_InterpolateBoundaryEdgeOnly); + hbrmesh->Finish(); + + return true; +} + +void OpenSubdMesh::tessellate(DiagSplit *split) +{ + if (num_ptex_faces == 0) + return; + + const int level = 3; + const bool requirefvar = false; + + /* convert HRB to FAR mesh */ + OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh; + + OsdFarMeshFactory meshFactory(hbrmesh, level, true); + OsdFarMesh *farmesh = meshFactory.Create(requirefvar); + int num_hbr_verts = hbrmesh->GetNumVertices(); + + delete hbrmesh; + hbrmesh = NULL; + _hbrmesh = NULL; + + /* refine HBR mesh with vertex coordinates */ + OsdCpuComputeController *compute_controller = new OsdCpuComputeController(); + OsdCpuComputeContext *compute_context = OsdCpuComputeContext::Create(farmesh); + + OsdCpuVertexBuffer *vbuf_base = OsdCpuVertexBuffer::Create(3, num_hbr_verts); + vbuf_base->UpdateData(&positions[0], 0, num_verts); + + compute_controller->Refine(compute_context, farmesh->GetKernelBatches(), vbuf_base); + compute_controller->Synchronize(); + + /* split & dice patches */ + OpenSubdPatch patch(farmesh, vbuf_base); + + for(int f = 0; f < num_ptex_faces; f++) { + patch.face_id = f; + split->split_quad(&patch); + } + + /* clean up */ + delete farmesh; + delete compute_controller; + delete compute_context; + delete vbuf_base; +} + +CCL_NAMESPACE_END + +#else /* WITH_OPENSUBDIV */ + CCL_NAMESPACE_BEGIN /* Subd Vertex */ @@ -169,3 +414,5 @@ void SubdMesh::tessellate(DiagSplit *split) CCL_NAMESPACE_END +#endif /* WITH_OPENSUBDIV */ + diff --git a/intern/cycles/subd/subd_mesh.h b/intern/cycles/subd/subd_mesh.h index 96557692f05..f6aefc20318 100644 --- a/intern/cycles/subd/subd_mesh.h +++ b/intern/cycles/subd/subd_mesh.h @@ -35,8 +35,10 @@ CCL_NAMESPACE_BEGIN +#ifndef WITH_OPENSUBDIV class SubdVert; class SubdFace; +#endif class DiagSplit; class Mesh; @@ -46,9 +48,6 @@ class Mesh; class SubdMesh { public: - vector verts; - vector faces; - SubdMesh(); ~SubdMesh(); @@ -60,6 +59,17 @@ public: bool finish(); void tessellate(DiagSplit *split); + +protected: +#ifdef WITH_OPENSUBDIV + void *_hbrmesh; + vector positions; + int num_verts, num_ptex_faces; +#else + vector verts; + vector faces; +#endif + }; CCL_NAMESPACE_END -- cgit v1.2.3