diff options
Diffstat (limited to 'intern/cycles/subd/subd_build.cpp')
-rw-r--r-- | intern/cycles/subd/subd_build.cpp | 669 |
1 files changed, 0 insertions, 669 deletions
diff --git a/intern/cycles/subd/subd_build.cpp b/intern/cycles/subd/subd_build.cpp deleted file mode 100644 index f3c2837c37c..00000000000 --- a/intern/cycles/subd/subd_build.cpp +++ /dev/null @@ -1,669 +0,0 @@ -/* - * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com> - * - * Modifications copyright (c) 2011, Blender Foundation. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "subd_build.h" -#include "subd_edge.h" -#include "subd_face.h" -#include "subd_ring.h" -#include "subd_mesh.h" -#include "subd_patch.h" -#include "subd_stencil.h" -#include "subd_vert.h" - -#include "util_algorithm.h" -#include "util_debug.h" -#include "util_math.h" -#include "util_string.h" - -CCL_NAMESPACE_BEGIN - -/* Subd Builder */ - -SubdBuilder *SubdBuilder::create(bool linear) -{ - if(linear) - return new SubdLinearBuilder(); - else - return new SubdAccBuilder(); -} - -/* Gregory ACC Stencil */ - -class GregoryAccStencil { -public: - SubdFaceRing *ring; - StencilMask stencil[20]; - - GregoryAccStencil(SubdFaceRing *ring_) - { - ring = ring_; - - for(int i = 0; i < 20; i++) - stencil[i].resize(ring->num_verts()); - } - - StencilMask& get(int i) - { - assert(i < 20); - return stencil[i]; - } - - float& get(int i, SubdVert *vert) - { - assert(i < 20); - return stencil[i][ring->vert_index(vert)]; - } -}; - -static float pseudoValence(SubdVert *vert) -{ - float valence = (float)vert->valence(); - - if(vert->is_boundary()) { - /* we treat boundary verts as being half a closed mesh. corners are - * special case. n = 4 for corners and n = 2*(n-1) for boundaries. */ - if(valence == 2) return 4; - return (valence - 1)*2; - } - - return valence; -} - -/* Subd ACC Builder */ - -SubdAccBuilder::SubdAccBuilder() -{ -} - -SubdAccBuilder::~SubdAccBuilder() -{ -} - -Patch *SubdAccBuilder::run(SubdFace *face) -{ - SubdFaceRing ring(face, face->edge); - GregoryAccStencil stencil(&ring); - float3 position[20]; - - computeCornerStencil(&ring, &stencil); - computeEdgeStencil(&ring, &stencil); - computeInteriorStencil(&ring, &stencil); - - ring.evaluate_stencils(position, stencil.stencil, 20); - - if(face->num_edges() == 3) { - GregoryTrianglePatch *patch = new GregoryTrianglePatch(); - memcpy(patch->hull, position, sizeof(float3)*20); - return patch; - } - else if(face->num_edges() == 4) { - GregoryQuadPatch *patch = new GregoryQuadPatch(); - memcpy(patch->hull, position, sizeof(float3)*20); - return patch; - } - - assert(0); /* n-gons should have been split already */ - return NULL; -} - -/* Gregory Patch */ - -void SubdAccBuilder::computeCornerStencil(SubdFaceRing *ring, GregoryAccStencil *stencil) -{ - const int cornerIndices[7] = {8, 11, 19, 16, 6, 9, 12}; - int primitiveOffset = ring->is_quad()? 0: 4; - - SubdEdge *firstEdge = ring->firstEdge(); - - /* compute corner control points */ - int v = 0; - - for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) { - SubdVert *vert = it.current()->from(); - int valence = vert->valence(); - int cid = cornerIndices[primitiveOffset+v]; - - if(vert->is_boundary()) { - /* compute vertex limit position */ - SubdEdge *edge0 = vert->edge; - SubdEdge *edge1 = vert->edge->prev; - - assert(edge0->face == NULL); - assert(edge0->to() != vert); - assert(edge1->face == NULL); - assert(edge1->from() != vert); - - stencil->get(cid, vert) = 2.0f/3.0f; - stencil->get(cid, edge0->to()) = 1.0f/6.0f; - stencil->get(cid, edge1->from()) = 1.0f/6.0f; - - assert(stencil->get(cid).is_normalized()); - } - else { - stencil->get(cid, vert) = 3.0f*valence*valence; - - for(SubdVert::EdgeIterator eit(vert->edge); !eit.isDone(); eit.advance()) { - SubdEdge *edge = eit.current(); - assert(vert->co == edge->from()->co); - - stencil->get(cid, edge->to()) = 12.0f; - - if(SubdFaceRing::is_triangle(edge->face)) { - /* distribute weight to all verts */ - stencil->get(cid, vert) += 1.0f; - stencil->get(cid, edge->to()) += 1.0f; - stencil->get(cid, edge->next->to()) += 1.0f; - } - else - stencil->get(cid, edge->next->to()) = 3.0f; - } - - /* normalize stencil. */ - stencil->get(cid).normalize(); - } - } -} - -void SubdAccBuilder::computeEdgeStencil(SubdFaceRing *ring, GregoryAccStencil *stencil) -{ - const int cornerIndices[7] = {8, 11, 19, 16, 6, 9, 12}; - const int edge1Indices[7] = {9, 13, 18, 14, 7, 10, 13}; - const int edge2Indices[7] = {12, 10, 15, 17, 14, 8, 11}; - int primitiveOffset = ring->is_quad()? 0: 4; - - float tangentScales[14] = { - 0.0f, 0.0f, 0.0f, 0.667791f, 1.0f, - 1.11268f, 1.1284f, 1.10289f, 1.06062f, - 1.01262f, 0.963949f, 0.916926f, 0.872541f, 0.831134f - }; - - SubdEdge *firstEdge = ring->firstEdge(); - - /* compute corner / edge control points */ - int v = 0; - - for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) { - SubdVert *vert = it.current()->from(); - int valence = vert->valence(); - int cid = cornerIndices[primitiveOffset+v]; - - int i1 = 0, i2 = 0, j = 0; - - for(SubdVert::EdgeIterator eit(vert->edge); !eit.isDone(); eit.advance(), j++) { - SubdEdge *edge = eit.current(); - - /* find index of "our" edge for edge control points */ - if(edge == it.current()) - i1 = j; - if(edge == it.current()->prev->pair) - i2 = j; - } - - if(vert->is_boundary()) { - int num_verts = ring->num_verts(); - StencilMask r0(num_verts); - StencilMask r1(num_verts); - - computeBoundaryTangentStencils(ring, vert, r0, r1); - - int k = valence - 1; - float omega = M_PI_F / k; - - int eid1 = edge1Indices[primitiveOffset + v]; - int eid2 = edge2Indices[primitiveOffset + v]; - - if(it.current()->is_boundary()) { - assert(it.current()->from() == vert); - - stencil->get(eid1, vert) = 2.0f / 3.0f; - stencil->get(eid1, it.current()->to()) = 1.0f / 3.0f; - - assert(stencil->get(eid1).is_normalized()); - - if(valence == 2) { - for(int i = 0; i < num_verts; i++) - stencil->get(eid1)[i] += r0[i] * 0.0001f; - } - } - else { - stencil->get(eid1) = stencil->get(cid); - - /* compute index of it.current() around vert */ - int idx = 0; - - for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), idx++) - if(eit.current() == it.current()) - break; - - assert(idx != valence); - - float c = cosf(idx * omega); - float s = sinf(idx * omega); - - for(int i = 0; i < num_verts; i++) - stencil->get(eid1)[i] += (r0[i] * s + r1[i] * c) / 3.0f; - } - - if(it.current()->prev->is_boundary()) { - assert(it.current()->prev->pair->from() == vert); - - stencil->get(eid2, vert) = 2.0f / 3.0f; - stencil->get(eid2, it.current()->prev->pair->to()) = 1.0f / 3.0f; - - assert(stencil->get(eid2).is_normalized()); - - if(valence == 2) { - for(int i = 0; i < num_verts; i++) - stencil->get(eid2)[i] += r0[i] * 0.0001f; - } - } - else { - stencil->get(eid2) = stencil->get(cid); - - /* compute index of it.current() around vert */ - int idx = 0; - - for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), idx++) - if(eit.current() == it.current()->prev->pair) - break; - - assert(idx != valence); - - float c = cosf(idx * omega); - float s = sinf(idx * omega); - - for(int i = 0; i < num_verts; i++) - stencil->get(eid2)[i] += (r0[i] * s + r1[i] * c) / 3; - } - } - else { - float costerm = cosf(M_PI_F / valence); - float sqrtterm = sqrtf(4.0f + costerm*costerm); - - /* float tangentScale = 1.0f; */ - float tangentScale = tangentScales[min(valence, 13U)]; - - float alpha = (1.0f + costerm / sqrtterm) / (3.0f * valence) * tangentScale; - float beta = 1.0f / (3.0f * valence * sqrtterm) * tangentScale; - - - int eid1 = edge1Indices[primitiveOffset + v]; - int eid2 = edge2Indices[primitiveOffset + v]; - - stencil->get(eid1) = stencil->get(cid); - stencil->get(eid2) = stencil->get(cid); - - j = 0; - for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), j++) { - SubdEdge *edge = eit.current(); - assert(vert->co == edge->from()->co); - - float costerm1_a = cosf(M_PI_F * 2 * (j-i1) / valence); - float costerm1_b = cosf(M_PI_F * (2 * (j-i1)-1) / valence); /* -1 instead of +1 b/c of edge->next->to() */ - - float costerm2_a = cosf(M_PI_F * 2 * (j-i2) / valence); - float costerm2_b = cosf(M_PI_F * (2 * (j-i2)-1) / valence); /* -1 instead of +1 b/c of edge->next->to() */ - - - stencil->get(eid1, edge->to()) += alpha * costerm1_a; - stencil->get(eid2, edge->to()) += alpha * costerm2_a; - - if(SubdFaceRing::is_triangle(edge->face)) { - /* @@ this probably does not provide watertight results!! (1/3 + 1/3 + 1/3 != 1) */ - - /* distribute weight to all verts */ - stencil->get(eid1, vert) += beta * costerm1_b / 3.0f; - stencil->get(eid1, edge->to()) += beta * costerm1_b / 3.0f; - stencil->get(eid1, edge->next->to()) += beta * costerm1_b / 3.0f; - - stencil->get(eid2, vert) += beta * costerm2_b / 3.0f; - stencil->get(eid2, edge->to()) += beta * costerm2_b / 3.0f; - stencil->get(eid2, edge->next->to()) += beta * costerm2_b / 3.0f; - } - else { - stencil->get(eid1, edge->next->to()) += beta * costerm1_b; - stencil->get(eid2, edge->next->to()) += beta * costerm2_b; - } - } - } - } -} - -void SubdAccBuilder::computeInteriorStencil(SubdFaceRing *ring, GregoryAccStencil *stencil) -{ - static int corner1Indices[7] = {8, 11, 19, 16, 6, 9, 12}; - static int corner2Indices[7] = {11, 19, 16, 8, 9, 12, 6}; - static int edge1Indices[7] = {9, 13, 18, 14, 7, 10, 13}; - static int edge2Indices[7] = {10, 15, 17, 12, 8, 11, 14}; - static int interior1Indices[7] = {1, 3, 6, 4, 1, 3, 5}; - static int interior2Indices[7] = {2, 7, 5, 0, 2, 4, 0}; - - int primitiveOffset = ring->is_quad()? 0: 4; - - SubdFace * face = ring->face(); - SubdEdge *firstEdge = ring->firstEdge(); - - /* interior control points */ - int v = 0; - for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) { - SubdEdge *edge = it.current(); - - if(edge->is_boundary()) { - float valence1 = pseudoValence(edge->from()); - float valence2 = pseudoValence(edge->to()); - - float weights1[4]; - float weights2[4]; - - if(ring->is_quad()) { - weights1[0] = 3 * valence1; - weights1[1] = 6; - weights1[2] = 3; - weights1[3] = 6; - - weights2[0] = 6; - weights2[1] = 3 * valence2; - weights2[2] = 6; - weights2[3] = 3; - } - else { - assert(ring->is_triangle()); - weights1[0] = 3 * valence1 + 1; - weights1[1] = 7; - weights1[2] = 7; - - weights2[0] = 7; - weights2[1] = 3 * valence2 + 1; - weights2[2] = 7; - } - - int idx1 = interior1Indices[primitiveOffset+v]; - int idx2 = interior2Indices[primitiveOffset+v]; - - int i = 0; - for(SubdFace::EdgeIterator it_sub(face->edges(edge)); !it_sub.isDone(); it_sub.advance(), i++) { - SubdVert *vert = it_sub.current()->from(); - stencil->get(idx1, vert) += weights1[i]; - stencil->get(idx2, vert) += weights2[i]; - } - - stencil->get(idx1).normalize(); - stencil->get(idx2).normalize(); - } - else { - SubdVert *e0 = edge->from(); - float costerm0 = cosf(M_2PI_F / pseudoValence(e0)); - - SubdVert *f0 = edge->to(); - float costerm1 = cosf(M_2PI_F / pseudoValence(f0)); - - /* p0 +------+ q0 - * | | - * f0 +======+ e0 <=== current edge - * | | - * p1 +------+ q1 - */ - - SubdVert *q0 = edge->next->to(); - SubdVert *p0 = edge->prev->from(); - - SubdVert *p1 = edge->pair->next->to(); - SubdVert *q1 = edge->pair->prev->from(); - - - StencilMask x(ring->num_verts()); - StencilMask y(ring->num_verts()); - - for(int i = 0; i < ring->num_verts(); i++) { - x[i] = - (costerm1 * stencil->get(corner1Indices[primitiveOffset+v])[i] - - (2*costerm0 + costerm1) * stencil->get(edge1Indices[primitiveOffset+v])[i] + - 2*costerm0 * stencil->get(edge2Indices[primitiveOffset+v])[i]) / 3.0f; - } - - /* y = (2*( midedgeA1 - midedgeB1) + 4*(centroidA - centroidB))/18.0f; */ - y[ring->vert_index(p0)] = 1; - y[ring->vert_index(p1)] = -1; - - /* add centroidA */ - if(ring->is_triangle()) { - y[ring->vert_index(p0)] += 4.0f / 3.0f; - y[ring->vert_index(e0)] += 4.0f / 3.0f; - y[ring->vert_index(f0)] += 4.0f / 3.0f; - } - else { - y[ring->vert_index(p0)] += 1; - y[ring->vert_index(q0)] += 1; - y[ring->vert_index(e0)] += 1; - y[ring->vert_index(f0)] += 1; - } - - /* sub centroidB */ - if(SubdFaceRing::is_triangle(edge->pair->face)) { - y[ring->vert_index(p1)] -= 4.0f / 3.0f; - y[ring->vert_index(e0)] -= 4.0f / 3.0f; - y[ring->vert_index(f0)] -= 4.0f / 3.0f; - - } - else { - y[ring->vert_index(p1)] -= 1; - y[ring->vert_index(q1)] -= 1; - y[ring->vert_index(e0)] -= 1; - y[ring->vert_index(f0)] -= 1; - } - - y /= 18.0f; - - if(ring->is_triangle()) { - x *= 3.0f / 4.0f; - y *= 3.0f / 4.0f; - } - - /* this change makes the triangle boundaries smoother, but distorts the quads next to them */ -#if 0 - if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face)) { - y *= 4.0f / 3.0f; - } -#endif - - stencil->get(interior1Indices[primitiveOffset+v]) = stencil->get(edge1Indices[primitiveOffset+v]); - stencil->get(interior1Indices[primitiveOffset+v]) += x; - stencil->get(interior1Indices[primitiveOffset+v]) += y; - - for(int i = 0; i < ring->num_verts(); i++) { - x[i] = - (costerm0 * stencil->get(corner2Indices[primitiveOffset+v])[i] - - (2*costerm1 + costerm0) * stencil->get(edge2Indices[primitiveOffset+v])[i] + - 2*costerm1 * stencil->get(edge1Indices[primitiveOffset+v])[i]) / 3.0f; - } - - /* y = (2*( midedgeA2 - midedgeB2) + 4*(centroidA - centroidB))/18.0f; */ - y = 0.0f; - - /* (2*( midedgeA2 - midedgeB2) */ - y[ring->vert_index(q0)] = 1; - y[ring->vert_index(q1)] = -1; - - /* add centroidA */ - if(ring->is_triangle()) { - y[ring->vert_index(p0)] += 4.0f / 3.0f; - y[ring->vert_index(e0)] += 4.0f / 3.0f; - y[ring->vert_index(f0)] += 4.0f / 3.0f; - } - else { - y[ring->vert_index(p0)] += 1; - y[ring->vert_index(q0)] += 1; - y[ring->vert_index(e0)] += 1; - y[ring->vert_index(f0)] += 1; - } - - /* sub centroidB */ - if(SubdFaceRing::is_triangle(edge->pair->face)) { - y[ring->vert_index(p1)] -= 4.0f / 3.0f; - y[ring->vert_index(e0)] -= 4.0f / 3.0f; - y[ring->vert_index(f0)] -= 4.0f / 3.0f; - - } - else { - y[ring->vert_index(p1)] -= 1; - y[ring->vert_index(q1)] -= 1; - y[ring->vert_index(e0)] -= 1; - y[ring->vert_index(f0)] -= 1; - } - - y /= 18.0f; - - if(ring->is_triangle()) { - x *= 3.0f / 4.0f; - y *= 3.0f / 4.0f; - } - - /* this change makes the triangle boundaries smoother, but distorts the quads next to them. */ -#if 0 - if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face)) - y *= 4.0f / 3.0f; -#endif - - stencil->get(interior2Indices[primitiveOffset+v]) = stencil->get(edge2Indices[primitiveOffset+v]); - stencil->get(interior2Indices[primitiveOffset+v]) += x; - stencil->get(interior2Indices[primitiveOffset+v]) += y; - } - } -} - -void SubdAccBuilder::computeBoundaryTangentStencils(SubdFaceRing *ring, SubdVert *vert, StencilMask & r0, StencilMask & r1) -{ - assert(vert->is_boundary()); - assert(r0.size() == ring->num_verts()); - assert(r1.size() == ring->num_verts()); - - SubdEdge *edge0 = vert->edge; - assert(edge0->face == NULL); - assert(edge0->to() != vert); - - SubdEdge *edgek = vert->edge->prev; - assert(edgek->face == NULL); - assert(edgek->from() != vert); - - int valence = vert->valence(); - - int k = valence - 1; - float omega = M_PI_F / k; - float s = sinf(omega); - float c = cosf(omega); - - float factor = 1.0f / (3 * k + c); - - float gamma = -4 * s * factor; - r0[ring->vert_index(vert)] = gamma; - /* r1[ring->vert_index(vert)] = 0; */ - - float salpha0 = -((1 + 2 * c) * sqrtf(1 + c)) * factor / sqrtf(1 - c); - float calpha0 = 1.0f / 2.0f; - - r0[ring->vert_index(edge0->to())] = salpha0; - r1[ring->vert_index(edge0->to())] = calpha0; - - float salphak = salpha0; - float calphak = -1.0f / 2.0f; - - r0[ring->vert_index(edgek->from())] = salphak; - r1[ring->vert_index(edgek->from())] = calphak; - - int j = 0; - for(SubdVert::EdgeIterator it(vert->edges()); !it.isDone(); it.advance(), j++) { - SubdEdge *edge = it.current(); - - if(j == k) break; - - SubdVert *p = edge->to(); - SubdVert *q = edge->pair->prev->from(); - - float alphaj = 4 * sinf(j * omega) * factor; - float betaj = (sinf(j * omega) + sinf((j + 1) * omega)) * factor; - - if(j != 0) - r0[ring->vert_index(p)] += alphaj; - - if(edge->pair->prev->prev->prev == edge->pair) { - r0[ring->vert_index(vert)] += betaj / 3.0f; - r0[ring->vert_index(edge->pair->from())] += betaj / 3.0f; - r0[ring->vert_index(q)] += betaj / 3.0f; - } - else - r0[ring->vert_index(q)] += betaj; - } - - if(valence == 2) { - /* r0 perpendicular to r1 */ - r0[ring->vert_index(vert)] = -4.0f / 3.0f; - r0[ring->vert_index(edgek->from())] = 1.0f / 2.0f; - r0[ring->vert_index(edge0->to())] = 1.0f / 2.0f; - r0[ring->vert_index(edge0->next->to())] = 1.0f / 3.0f; - } -} - -/* Subd Linear Builder */ - -SubdLinearBuilder::SubdLinearBuilder() -{ -} - -SubdLinearBuilder::~SubdLinearBuilder() -{ -} - -Patch *SubdLinearBuilder::run(SubdFace *face) -{ - Patch *patch; - float3 *hull; - - if(face->num_edges() == 3) { - LinearTrianglePatch *lpatch = new LinearTrianglePatch(); - hull = lpatch->hull; - patch = lpatch; - } - else if(face->num_edges() == 4) { - LinearQuadPatch *lpatch = new LinearQuadPatch(); - hull = lpatch->hull; - patch = lpatch; - } - else { - assert(0); /* n-gons should have been split already */ - return NULL; - } - - int i = 0; - - for(SubdFace::EdgeIterator it(face->edge); !it.isDone(); it.advance()) - hull[i++] = it.current()->from()->co; - - if(face->num_edges() == 4) - swap(hull[2], hull[3]); - - return patch; -} - -CCL_NAMESPACE_END - |