diff options
Diffstat (limited to 'intern/cycles/subd/subd_dice.cpp')
-rw-r--r-- | intern/cycles/subd/subd_dice.cpp | 166 |
1 files changed, 10 insertions, 156 deletions
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp index 7c74f21950e..36981a20f3c 100644 --- a/intern/cycles/subd/subd_dice.cpp +++ b/intern/cycles/subd/subd_dice.cpp @@ -48,6 +48,11 @@ void EdgeDice::reserve(int num_verts) vert_offset = mesh->verts.size(); tri_offset = mesh->num_triangles(); + /* todo: optimize so we can reserve in advance, this is like push_back_slow() */ + if(vert_offset + num_verts > mesh->verts.capacity()) { + mesh->reserve_mesh(size_t((vert_offset + num_verts) * 1.2), mesh->num_triangles()); + } + mesh->resize_mesh(vert_offset + num_verts, tri_offset); Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL); @@ -66,6 +71,7 @@ int EdgeDice::add_vert(Patch *patch, float2 uv) mesh_P[vert_offset] = P; mesh_N[vert_offset] = N; + params.mesh->vert_patch_uv[vert_offset] = make_float2(uv.x, uv.y); if(params.ptex) { Attribute *attr_ptex_uv = params.mesh->attributes.add(ATTR_STD_PTEX_UV); @@ -75,6 +81,8 @@ int EdgeDice::add_vert(Patch *patch, float2 uv) ptex_uv[vert_offset] = make_float3(uv.x, uv.y, 0.0f); } + params.mesh->num_subd_verts++; + return vert_offset++; } @@ -86,7 +94,8 @@ void EdgeDice::add_triangle(Patch *patch, int v0, int v1, int v2) if(mesh->triangles.size() == mesh->triangles.capacity()) mesh->reserve_mesh(mesh->verts.size(), size_t(max(mesh->num_triangles() + 1, 1) * 1.2)); - mesh->add_triangle(v0, v1, v2, params.shader, params.smooth, false); + mesh->add_triangle(v0, v1, v2, patch->shader, true); + params.mesh->triangle_patch[params.mesh->num_triangles()-1] = patch->patch_index; if(params.ptex) { Attribute *attr_ptex_face_id = params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID); @@ -340,160 +349,5 @@ void QuadDice::dice(SubPatch& sub, EdgeFactors& ef) assert(vert_offset == params.mesh->verts.size()); } -/* TriangleDice */ - -TriangleDice::TriangleDice(const SubdParams& params_) -: EdgeDice(params_) -{ -} - -void TriangleDice::reserve(EdgeFactors& ef, int M) -{ - int num_verts = ef.tu + ef.tv + ef.tw; - - for(int m = M-2; m > 0; m -= 2) - num_verts += 3 + (m-1)*3; - - if(!(M & 1)) - num_verts++; - - EdgeDice::reserve(num_verts); -} - -float2 TriangleDice::map_uv(SubPatch& sub, float2 uv) -{ - /* map UV from subpatch to patch parametric coordinates */ - return uv.x*sub.Pu + uv.y*sub.Pv + (1.0f - uv.x - uv.y)*sub.Pw; -} - -int TriangleDice::add_vert(SubPatch& sub, float2 uv) -{ - return EdgeDice::add_vert(sub.patch, map_uv(sub, uv)); -} - -void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M) -{ - // XXX normals are flipped, why? - - /* grid is constructed starting from the outside edges, and adding - * progressively smaller inner triangles that connected to the outer - * one, until M = 1 or 2, the we fill up the last part. */ - vector<int> outer_u, outer_v, outer_w; - int m; - - /* add outer corners vertices */ - { - float2 p_u = make_float2(1.0f, 0.0f); - float2 p_v = make_float2(0.0f, 1.0f); - float2 p_w = make_float2(0.0f, 0.0f); - - int corner_u = add_vert(sub, p_u); - int corner_v = add_vert(sub, p_v); - int corner_w = add_vert(sub, p_w); - - outer_u.push_back(corner_v); - outer_v.push_back(corner_w); - outer_w.push_back(corner_u); - - for(int i = 1; i < ef.tu; i++) - outer_u.push_back(add_vert(sub, interp(p_v, p_w, i/(float)ef.tu))); - for(int i = 1; i < ef.tv; i++) - outer_v.push_back(add_vert(sub, interp(p_w, p_u, i/(float)ef.tv))); - for(int i = 1; i < ef.tw; i++) - outer_w.push_back(add_vert(sub, interp(p_u, p_v, i/(float)ef.tw))); - - outer_u.push_back(corner_w); - outer_v.push_back(corner_u); - outer_w.push_back(corner_v); - } - - for(m = M-2; m > 0; m -= 2) { - vector<int> inner_u, inner_v, inner_w; - - const float t0 = m / (float)M; - float2 center = make_float2(1.0f/3.0f, 1.0f/3.0f); - - /* 3 corner vertices */ - float2 p_u = interp(center, make_float2(1.0f, 0.0f), t0); - float2 p_v = interp(center, make_float2(0.0f, 1.0f), t0); - float2 p_w = interp(center, make_float2(0.0f, 0.0f), t0); - - int corner_u = add_vert(sub, p_u); - int corner_v = add_vert(sub, p_v); - int corner_w = add_vert(sub, p_w); - - /* construct array of vertex indices for each side */ - inner_u.push_back(corner_v); - inner_v.push_back(corner_w); - inner_w.push_back(corner_u); - - for(int i = 1; i < m; i++) { - /* add vertices between corners */ - const float t1 = i / (float)m; - - inner_u.push_back(add_vert(sub, interp(p_v, p_w, t1))); - inner_v.push_back(add_vert(sub, interp(p_w, p_u, t1))); - inner_w.push_back(add_vert(sub, interp(p_u, p_v, t1))); - } - - inner_u.push_back(corner_w); - inner_v.push_back(corner_u); - inner_w.push_back(corner_v); - - /* stitch together inner/outer with triangles */ - 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; - outer_w = inner_w; - } - - /* fill up last part */ - if(m == -1) { - /* single triangle */ - add_triangle(sub.patch, outer_w[0], outer_u[0], outer_v[0]); - } - else { - /* center vertex + up to 6 triangles */ - int center = add_vert(sub, make_float2(1.0f/3.0f, 1.0f/3.0f)); - - add_triangle(sub.patch, outer_w[0], outer_w[1], center); - /* if this is false then there is only one triangle on this side */ - if(outer_w.size() > 2) - add_triangle(sub.patch, outer_w[1], outer_w[2], center); - - add_triangle(sub.patch, outer_u[0], outer_u[1], center); - if(outer_u.size() > 2) - add_triangle(sub.patch, outer_u[1], outer_u[2], center); - - add_triangle(sub.patch, outer_v[0], outer_v[1], center); - if(outer_v.size() > 2) - add_triangle(sub.patch, outer_v[1], outer_v[2], center); - } -} - -void TriangleDice::dice(SubPatch& sub, EdgeFactors& ef) -{ - /* todo: handle 2 1 1 resolution */ - int M = max(ef.tu, max(ef.tv, ef.tw)); - - /* Due to the "slant" of the edges of a triangle compared to a quad, the internal - * triangles end up smaller, causing over-tessellation. This is to correct for this - * difference in area. Technically its only correct for equilateral triangles, but - * its better than how it was. - * - * (2*cos(radians(30))/3)**0.5 - */ - float S = 0.7598356856515927f; - M = max((int)ceil(S*M), 1); - - reserve(ef, M); - add_grid(sub, ef, M); - - assert(vert_offset == params.mesh->verts.size()); -} - CCL_NAMESPACE_END |