diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index a2142d77a9e..ada5ea55fb2 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -41,7 +41,7 @@ if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI) endif() if(WITH_CYCLES_OSL) - list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES}) + list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES} ${LLVM_LIBRARY}) endif() include_directories(${INC}) diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 55a2a30b9a8..df187f046e5 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -703,15 +703,14 @@ static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node) } /* finalize subd mesh */ - sdmesh.link_boundary(); + sdmesh.finish(); - /* subdivide */ - DiagSplit dsplit; - //dsplit.camera = state.scene->camera; - //dsplit.dicing_rate = 5.0f; - dsplit.dicing_rate = state.dicing_rate; - xml_read_float(&dsplit.dicing_rate, node, "dicing_rate"); - sdmesh.tessellate(&dsplit, false, mesh, shader, smooth); + /* parameters */ + SubdParams sdparams(mesh, shader, smooth); + xml_read_float(&sdparams.dicing_rate, node, "dicing_rate"); + + DiagSplit dsplit(sdparams);; + sdmesh.tessellate(&dsplit); } else { /* create vertices */ @@ -789,12 +788,11 @@ static void xml_read_patch(const XMLReadState& state, pugi::xml_node node) mesh->used_shaders.push_back(state.shader); /* split */ - DiagSplit dsplit; - //dsplit.camera = state.scene->camera; - //dsplit.dicing_rate = 5.0f; - dsplit.dicing_rate = state.dicing_rate; - xml_read_float(&dsplit.dicing_rate, node, "dicing_rate"); - dsplit.split_quad(mesh, patch, state.shader, state.smooth); + SubdParams sdparams(mesh, state.shader, state.smooth); + xml_read_float(&sdparams.dicing_rate, node, "dicing_rate"); + + DiagSplit dsplit(sdparams); + dsplit.split_quad(patch); delete patch; diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index e42af60c27b..45ec92a7961 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -365,7 +365,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< } } -static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector& used_shaders) +static void create_subd_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector& used_shaders) { /* create subd mesh */ SubdMesh sdmesh; @@ -386,21 +386,20 @@ static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, con if(n == 4) sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]); -#if 0 else sdmesh.add_face(vi[0], vi[1], vi[2]); -#endif } /* finalize subd mesh */ - sdmesh.link_boundary(); + sdmesh.finish(); - /* subdivide */ - DiagSplit dsplit; - dsplit.camera = NULL; - dsplit.dicing_rate = RNA_float_get(cmesh, "dicing_rate"); + SubdParams sdparams(mesh, used_shaders[0], true); + sdparams.dicing_rate = RNA_float_get(cmesh, "dicing_rate"); + //scene->camera->update(); + //sdparams.camera = scene->camera; - sdmesh.tessellate(&dsplit, false, mesh, used_shaders[0], true); + DiagSplit dsplit(sdparams);; + sdmesh.tessellate(&dsplit); } /* Sync */ @@ -482,7 +481,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri if(b_mesh) { if(render_layer.use_surfaces && !hide_tris) { if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision")) - create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders); + create_subd_mesh(scene, mesh, b_mesh, &cmesh, used_shaders); else create_mesh(scene, mesh, b_mesh, used_shaders); } 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; - } + for(int i = 0; i < num; i++) + f->verts[i] = index[i]; - current = add_edge(index[num-1], index[0]); - assert(current != NULL); - - current->face = f; - - last->next = current; - current->prev = last; - - current->next = first_edge; - first_edge->prev = current; - - f->edge = first_edge; + f->numverts = num; faces.push_back(f); return f; } -bool SubdMesh::can_add_face(int *index, int num) +bool SubdMesh::finish() { - /* 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) -{ - 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) +void SubdMesh::tessellate(DiagSplit *split) { - /* 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) -{ - 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__ */ -