diff options
Diffstat (limited to 'intern/cycles/subd')
-rw-r--r-- | intern/cycles/subd/CMakeLists.txt | 18 | ||||
-rw-r--r-- | intern/cycles/subd/subd_dice.cpp | 454 | ||||
-rw-r--r-- | intern/cycles/subd/subd_dice.h | 157 | ||||
-rw-r--r-- | intern/cycles/subd/subd_patch.cpp | 106 | ||||
-rw-r--r-- | intern/cycles/subd/subd_patch.h | 41 | ||||
-rw-r--r-- | intern/cycles/subd/subd_patch_table.cpp | 424 | ||||
-rw-r--r-- | intern/cycles/subd/subd_patch_table.h | 32 | ||||
-rw-r--r-- | intern/cycles/subd/subd_split.cpp | 351 | ||||
-rw-r--r-- | intern/cycles/subd/subd_split.h | 26 |
9 files changed, 817 insertions, 792 deletions
diff --git a/intern/cycles/subd/CMakeLists.txt b/intern/cycles/subd/CMakeLists.txt index 9669bdede7e..f5ceaa0436d 100644 --- a/intern/cycles/subd/CMakeLists.txt +++ b/intern/cycles/subd/CMakeLists.txt @@ -1,6 +1,6 @@ set(INC - .. + .. ) set(INC_SYS @@ -8,17 +8,17 @@ set(INC_SYS ) set(SRC - subd_dice.cpp - subd_patch.cpp - subd_split.cpp - subd_patch_table.cpp + subd_dice.cpp + subd_patch.cpp + subd_split.cpp + subd_patch_table.cpp ) set(SRC_HEADERS - subd_dice.h - subd_patch.h - subd_patch_table.h - subd_split.h + subd_dice.h + subd_patch.h + subd_patch_table.h + subd_split.h ) set(LIB diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp index c5ac54cfcc8..6b062ecfea2 100644 --- a/intern/cycles/subd/subd_dice.cpp +++ b/intern/cycles/subd/subd_dice.cpp @@ -24,327 +24,335 @@ CCL_NAMESPACE_BEGIN /* EdgeDice Base */ -EdgeDice::EdgeDice(const SubdParams& params_) -: params(params_) +EdgeDice::EdgeDice(const SubdParams ¶ms_) : params(params_) { - mesh_P = NULL; - mesh_N = NULL; - vert_offset = 0; + mesh_P = NULL; + mesh_N = NULL; + vert_offset = 0; - params.mesh->attributes.add(ATTR_STD_VERTEX_NORMAL); + params.mesh->attributes.add(ATTR_STD_VERTEX_NORMAL); - if(params.ptex) { - params.mesh->attributes.add(ATTR_STD_PTEX_UV); - params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID); - } + if (params.ptex) { + params.mesh->attributes.add(ATTR_STD_PTEX_UV); + params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID); + } } void EdgeDice::reserve(int num_verts) { - Mesh *mesh = params.mesh; + Mesh *mesh = params.mesh; - vert_offset = mesh->verts.size(); - tri_offset = mesh->num_triangles(); + 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()); - } + /* 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); + mesh->resize_mesh(vert_offset + num_verts, tri_offset); - Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL); + Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL); - mesh_P = mesh->verts.data(); - mesh_N = attr_vN->data_float3(); + mesh_P = mesh->verts.data(); + mesh_N = attr_vN->data_float3(); } int EdgeDice::add_vert(Patch *patch, float2 uv) { - float3 P, N; + float3 P, N; - patch->eval(&P, NULL, NULL, &N, uv.x, uv.y); + patch->eval(&P, NULL, NULL, &N, uv.x, uv.y); - assert(vert_offset < params.mesh->verts.size()); + assert(vert_offset < params.mesh->verts.size()); - mesh_P[vert_offset] = P; - mesh_N[vert_offset] = N; - params.mesh->vert_patch_uv[vert_offset] = make_float2(uv.x, uv.y); + 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); - params.mesh->attributes.resize(); + if (params.ptex) { + Attribute *attr_ptex_uv = params.mesh->attributes.add(ATTR_STD_PTEX_UV); + params.mesh->attributes.resize(); - float3 *ptex_uv = attr_ptex_uv->data_float3(); - ptex_uv[vert_offset] = make_float3(uv.x, uv.y, 0.0f); - } + float3 *ptex_uv = attr_ptex_uv->data_float3(); + ptex_uv[vert_offset] = make_float3(uv.x, uv.y, 0.0f); + } - params.mesh->num_subd_verts++; + params.mesh->num_subd_verts++; - return vert_offset++; + return vert_offset++; } void EdgeDice::add_triangle(Patch *patch, int v0, int v1, int v2) { - Mesh *mesh = params.mesh; + Mesh *mesh = params.mesh; - /* todo: optimize so we can reserve in advance, this is like push_back_slow() */ - if(mesh->triangles.size() == mesh->triangles.capacity()) - mesh->reserve_mesh(mesh->verts.size(), size_t(max(mesh->num_triangles() + 1, 1) * 1.2)); + /* todo: optimize so we can reserve in advance, this is like push_back_slow() */ + 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, patch->shader, true); - params.mesh->triangle_patch[params.mesh->num_triangles()-1] = patch->patch_index; + 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); - params.mesh->attributes.resize(); + if (params.ptex) { + Attribute *attr_ptex_face_id = params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID); + params.mesh->attributes.resize(); - float *ptex_face_id = attr_ptex_face_id->data_float(); - ptex_face_id[tri_offset] = (float)patch->ptex_face_id(); - } + float *ptex_face_id = attr_ptex_face_id->data_float(); + ptex_face_id[tri_offset] = (float)patch->ptex_face_id(); + } - tri_offset++; + tri_offset++; } -void EdgeDice::stitch_triangles(Patch *patch, vector<int>& outer, vector<int>& inner) +void EdgeDice::stitch_triangles(Patch *patch, vector<int> &outer, vector<int> &inner) { - if(inner.size() == 0 || outer.size() == 0) - return; // XXX avoid crashes for Mu or Mv == 1, missing polygons - - /* stitch together two arrays of verts with triangles. at each step, - * we compare using the next verts on both sides, to find the split - * direction with the smallest diagonal, and use that in order to keep - * the triangle shape reasonable. */ - for(size_t i = 0, j = 0; i+1 < inner.size() || j+1 < outer.size();) { - int v0, v1, v2; - - v0 = inner[i]; - v1 = outer[j]; - - if(j+1 == outer.size()) { - v2 = inner[++i]; - } - else if(i+1 == inner.size()) { - v2 = outer[++j]; - } - else { - /* length of diagonals */ - float len1 = len_squared(mesh_P[inner[i]] - mesh_P[outer[j+1]]); - float len2 = len_squared(mesh_P[outer[j]] - mesh_P[inner[i+1]]); - - /* use smallest diagonal */ - if(len1 < len2) - v2 = outer[++j]; - else - v2 = inner[++i]; - } - - add_triangle(patch, v0, v1, v2); - } + if (inner.size() == 0 || outer.size() == 0) + return; // XXX avoid crashes for Mu or Mv == 1, missing polygons + + /* stitch together two arrays of verts with triangles. at each step, + * we compare using the next verts on both sides, to find the split + * direction with the smallest diagonal, and use that in order to keep + * the triangle shape reasonable. */ + for (size_t i = 0, j = 0; i + 1 < inner.size() || j + 1 < outer.size();) { + int v0, v1, v2; + + v0 = inner[i]; + v1 = outer[j]; + + if (j + 1 == outer.size()) { + v2 = inner[++i]; + } + else if (i + 1 == inner.size()) { + v2 = outer[++j]; + } + else { + /* length of diagonals */ + float len1 = len_squared(mesh_P[inner[i]] - mesh_P[outer[j + 1]]); + float len2 = len_squared(mesh_P[outer[j]] - mesh_P[inner[i + 1]]); + + /* use smallest diagonal */ + if (len1 < len2) + v2 = outer[++j]; + else + v2 = inner[++i]; + } + + add_triangle(patch, v0, v1, v2); + } } /* QuadDice */ -QuadDice::QuadDice(const SubdParams& params_) -: EdgeDice(params_) +QuadDice::QuadDice(const SubdParams ¶ms_) : EdgeDice(params_) { } -void QuadDice::reserve(EdgeFactors& ef, int Mu, int Mv) +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); + /* 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); } -float2 QuadDice::map_uv(SubPatch& sub, float u, float v) +float2 QuadDice::map_uv(SubPatch &sub, float u, float v) { - /* map UV from subpatch to patch parametric coordinates */ - float2 d0 = interp(sub.P00, sub.P01, v); - float2 d1 = interp(sub.P10, sub.P11, v); - return interp(d0, d1, u); + /* map UV from subpatch to patch parametric coordinates */ + float2 d0 = interp(sub.P00, sub.P01, v); + float2 d1 = interp(sub.P10, sub.P11, v); + return interp(d0, d1, u); } -float3 QuadDice::eval_projected(SubPatch& sub, float u, float v) +float3 QuadDice::eval_projected(SubPatch &sub, float u, float v) { - float2 uv = map_uv(sub, u, v); - float3 P; + float2 uv = map_uv(sub, u, v); + float3 P; - sub.patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y); - if(params.camera) - P = transform_perspective(¶ms.camera->worldtoraster, P); + sub.patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y); + if (params.camera) + P = transform_perspective(¶ms.camera->worldtoraster, P); - return P; + return P; } -int QuadDice::add_vert(SubPatch& sub, float u, float v) +int QuadDice::add_vert(SubPatch &sub, float u, float v) { - return EdgeDice::add_vert(sub.patch, map_uv(sub, u, v)); + return EdgeDice::add_vert(sub.patch, map_uv(sub, u, v)); } -void QuadDice::add_side_u(SubPatch& sub, - vector<int>& outer, vector<int>& inner, - int Mu, int Mv, int tu, int side, int offset) +void QuadDice::add_side_u(SubPatch &sub, + vector<int> &outer, + vector<int> &inner, + int Mu, + int Mv, + int tu, + int side, + int offset) { - outer.clear(); - inner.clear(); + outer.clear(); + inner.clear(); - /* set verts on the edge of the patch */ - outer.push_back(offset + ((side)? 2: 0)); + /* set verts on the edge of the patch */ + outer.push_back(offset + ((side) ? 2 : 0)); - for(int i = 1; i < tu; i++) { - float u = i/(float)tu; - float v = (side)? 1.0f: 0.0f; + for (int i = 1; i < tu; i++) { + float u = i / (float)tu; + float v = (side) ? 1.0f : 0.0f; - outer.push_back(add_vert(sub, u, v)); - } + outer.push_back(add_vert(sub, u, v)); + } - outer.push_back(offset + ((side)? 3: 1)); + outer.push_back(offset + ((side) ? 3 : 1)); - /* set verts on the edge of the inner grid */ - for(int i = 0; i < Mu-1; i++) { - int j = (side)? Mv-1-1: 0; - inner.push_back(offset + 4 + i + j*(Mu-1)); - } + /* set verts on the edge of the inner grid */ + for (int i = 0; i < Mu - 1; i++) { + int j = (side) ? Mv - 1 - 1 : 0; + inner.push_back(offset + 4 + i + j * (Mu - 1)); + } } -void QuadDice::add_side_v(SubPatch& sub, - vector<int>& outer, vector<int>& inner, - int Mu, int Mv, int tv, int side, int offset) +void QuadDice::add_side_v(SubPatch &sub, + vector<int> &outer, + vector<int> &inner, + int Mu, + int Mv, + int tv, + int side, + int offset) { - outer.clear(); - inner.clear(); + outer.clear(); + inner.clear(); - /* set verts on the edge of the patch */ - outer.push_back(offset + ((side)? 1: 0)); + /* set verts on the edge of the patch */ + outer.push_back(offset + ((side) ? 1 : 0)); - for(int j = 1; j < tv; j++) { - float u = (side)? 1.0f: 0.0f; - float v = j/(float)tv; + for (int j = 1; j < tv; j++) { + float u = (side) ? 1.0f : 0.0f; + float v = j / (float)tv; - outer.push_back(add_vert(sub, u, v)); - } + outer.push_back(add_vert(sub, u, v)); + } - outer.push_back(offset + ((side)? 3: 2)); + outer.push_back(offset + ((side) ? 3 : 2)); - /* set verts on the edge of the inner grid */ - for(int j = 0; j < Mv-1; j++) { - int i = (side)? Mu-1-1: 0; - inner.push_back(offset + 4 + i + j*(Mu-1)); - } + /* set verts on the edge of the inner grid */ + for (int j = 0; j < Mv - 1; j++) { + int i = (side) ? Mu - 1 - 1 : 0; + inner.push_back(offset + 4 + i + j * (Mu - 1)); + } } -float QuadDice::quad_area(const float3& a, const float3& b, const float3& c, const float3& d) +float QuadDice::quad_area(const float3 &a, const float3 &b, const float3 &c, const float3 &d) { - return triangle_area(a, b, d) + triangle_area(a, d, c); + return triangle_area(a, b, d) + triangle_area(a, d, c); } -float QuadDice::scale_factor(SubPatch& sub, EdgeFactors& ef, int Mu, int Mv) +float QuadDice::scale_factor(SubPatch &sub, EdgeFactors &ef, int Mu, int Mv) { - /* estimate area as 4x largest of 4 quads */ - float3 P[3][3]; - - for(int i = 0; i < 3; i++) - for(int j = 0; j < 3; j++) - P[i][j] = eval_projected(sub, i*0.5f, j*0.5f); - - float A1 = quad_area(P[0][0], P[1][0], P[0][1], P[1][1]); - float A2 = quad_area(P[1][0], P[2][0], P[1][1], P[2][1]); - float A3 = quad_area(P[0][1], P[1][1], P[0][2], P[1][2]); - float A4 = quad_area(P[1][1], P[2][1], P[1][2], P[2][2]); - float Apatch = max(A1, max(A2, max(A3, A4)))*4.0f; - - /* solve for scaling factor */ - float Atri = params.dicing_rate*params.dicing_rate*0.5f; - float Ntris = Apatch/Atri; - - // XXX does the -sqrt solution matter - // XXX max(D, 0.0) is highly suspicious, need to test cases - // where D goes negative - float N = 0.5f*(Ntris - (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1)); - float D = 4.0f*N*Mu*Mv + (Mu + Mv)*(Mu + Mv); - float S = (Mu + Mv + sqrtf(max(D, 0.0f)))/(2*Mu*Mv); - - return S; + /* estimate area as 4x largest of 4 quads */ + float3 P[3][3]; + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + P[i][j] = eval_projected(sub, i * 0.5f, j * 0.5f); + + float A1 = quad_area(P[0][0], P[1][0], P[0][1], P[1][1]); + float A2 = quad_area(P[1][0], P[2][0], P[1][1], P[2][1]); + float A3 = quad_area(P[0][1], P[1][1], P[0][2], P[1][2]); + float A4 = quad_area(P[1][1], P[2][1], P[1][2], P[2][2]); + float Apatch = max(A1, max(A2, max(A3, A4))) * 4.0f; + + /* solve for scaling factor */ + float Atri = params.dicing_rate * params.dicing_rate * 0.5f; + float Ntris = Apatch / Atri; + + // XXX does the -sqrt solution matter + // XXX max(D, 0.0) is highly suspicious, need to test cases + // where D goes negative + float N = 0.5f * (Ntris - (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1)); + float D = 4.0f * N * Mu * Mv + (Mu + Mv) * (Mu + Mv); + float S = (Mu + Mv + sqrtf(max(D, 0.0f))) / (2 * Mu * Mv); + + return S; } -void QuadDice::add_corners(SubPatch& sub) +void QuadDice::add_corners(SubPatch &sub) { - /* add verts for patch corners */ - add_vert(sub, 0.0f, 0.0f); - add_vert(sub, 1.0f, 0.0f); - add_vert(sub, 0.0f, 1.0f); - add_vert(sub, 1.0f, 1.0f); + /* add verts for patch corners */ + add_vert(sub, 0.0f, 0.0f); + add_vert(sub, 1.0f, 0.0f); + add_vert(sub, 0.0f, 1.0f); + add_vert(sub, 1.0f, 1.0f); } -void QuadDice::add_grid(SubPatch& sub, int Mu, int Mv, int offset) +void QuadDice::add_grid(SubPatch &sub, int Mu, int Mv, int offset) { - /* create inner grid */ - float du = 1.0f/(float)Mu; - float dv = 1.0f/(float)Mv; - - for(int j = 1; j < Mv; j++) { - for(int i = 1; i < Mu; i++) { - float u = i*du; - float v = j*dv; - - add_vert(sub, u, v); - - if(i < Mu-1 && j < Mv-1) { - int i1 = offset + 4 + (i-1) + (j-1)*(Mu-1); - int i2 = offset + 4 + i + (j-1)*(Mu-1); - int i3 = offset + 4 + i + j*(Mu-1); - int i4 = offset + 4 + (i-1) + j*(Mu-1); - - add_triangle(sub.patch, i1, i2, i3); - add_triangle(sub.patch, i1, i3, i4); - } - } - } + /* create inner grid */ + float du = 1.0f / (float)Mu; + float dv = 1.0f / (float)Mv; + + for (int j = 1; j < Mv; j++) { + for (int i = 1; i < Mu; i++) { + float u = i * du; + float v = j * dv; + + add_vert(sub, u, v); + + if (i < Mu - 1 && j < Mv - 1) { + int i1 = offset + 4 + (i - 1) + (j - 1) * (Mu - 1); + int i2 = offset + 4 + i + (j - 1) * (Mu - 1); + int i3 = offset + 4 + i + j * (Mu - 1); + int i4 = offset + 4 + (i - 1) + j * (Mu - 1); + + add_triangle(sub.patch, i1, i2, i3); + add_triangle(sub.patch, i1, i3, i4); + } + } + } } -void QuadDice::dice(SubPatch& sub, EdgeFactors& ef) +void QuadDice::dice(SubPatch &sub, EdgeFactors &ef) { - /* compute inner grid size with scale factor */ - int Mu = max(ef.tu0, ef.tu1); - int Mv = max(ef.tv0, ef.tv1); + /* compute inner grid size with scale factor */ + int Mu = max(ef.tu0, ef.tu1); + int Mv = max(ef.tv0, ef.tv1); #if 0 /* Doesnt work very well, especially at grazing angles. */ - float S = scale_factor(sub, ef, Mu, Mv); + float S = scale_factor(sub, ef, Mu, Mv); #else - float S = 1.0f; + float S = 1.0f; #endif - Mu = max((int)ceil(S*Mu), 2); // XXX handle 0 & 1? - Mv = max((int)ceil(S*Mv), 2); // XXX handle 0 & 1? + Mu = max((int)ceil(S * Mu), 2); // XXX handle 0 & 1? + Mv = max((int)ceil(S * Mv), 2); // XXX handle 0 & 1? - /* reserve space for new verts */ - int offset = params.mesh->verts.size(); - reserve(ef, Mu, Mv); + /* reserve space for new verts */ + int offset = params.mesh->verts.size(); + reserve(ef, Mu, Mv); - /* corners and inner grid */ - add_corners(sub); - add_grid(sub, Mu, Mv, offset); + /* corners and inner grid */ + add_corners(sub); + add_grid(sub, Mu, Mv, offset); - /* bottom side */ - vector<int> outer, inner; + /* bottom side */ + vector<int> outer, inner; - add_side_u(sub, outer, inner, Mu, Mv, ef.tu0, 0, offset); - stitch_triangles(sub.patch, outer, inner); + add_side_u(sub, outer, inner, Mu, Mv, ef.tu0, 0, offset); + stitch_triangles(sub.patch, outer, inner); - /* top side */ - add_side_u(sub, outer, inner, Mu, Mv, ef.tu1, 1, offset); - stitch_triangles(sub.patch, inner, outer); + /* top side */ + add_side_u(sub, outer, inner, Mu, Mv, ef.tu1, 1, offset); + stitch_triangles(sub.patch, inner, outer); - /* left side */ - add_side_v(sub, outer, inner, Mu, Mv, ef.tv0, 0, offset); - stitch_triangles(sub.patch, inner, outer); + /* left side */ + add_side_v(sub, outer, inner, Mu, Mv, ef.tv0, 0, offset); + stitch_triangles(sub.patch, inner, outer); - /* right side */ - add_side_v(sub, outer, inner, Mu, Mv, ef.tv1, 1, offset); - stitch_triangles(sub.patch, outer, inner); + /* right side */ + add_side_v(sub, outer, inner, Mu, Mv, ef.tv1, 1, offset); + stitch_triangles(sub.patch, outer, inner); - assert(vert_offset == params.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 2bef8d4cf8d..eee54e01861 100644 --- a/intern/cycles/subd/subd_dice.h +++ b/intern/cycles/subd/subd_dice.h @@ -32,48 +32,47 @@ class Mesh; class Patch; struct SubdParams { - Mesh *mesh; - bool ptex; - - int test_steps; - int split_threshold; - float dicing_rate; - int max_level; - Camera *camera; - Transform objecttoworld; - - SubdParams(Mesh *mesh_, bool ptex_ = false) - { - mesh = mesh_; - ptex = ptex_; - - test_steps = 3; - split_threshold = 1; - dicing_rate = 1.0f; - max_level = 12; - camera = NULL; - } - + Mesh *mesh; + bool ptex; + + int test_steps; + int split_threshold; + float dicing_rate; + int max_level; + Camera *camera; + Transform objecttoworld; + + SubdParams(Mesh *mesh_, bool ptex_ = false) + { + mesh = mesh_; + ptex = ptex_; + + test_steps = 3; + split_threshold = 1; + dicing_rate = 1.0f; + max_level = 12; + camera = NULL; + } }; /* EdgeDice Base */ class EdgeDice { -public: - SubdParams params; - float3 *mesh_P; - float3 *mesh_N; - size_t vert_offset; - size_t tri_offset; + public: + SubdParams params; + float3 *mesh_P; + float3 *mesh_N; + size_t vert_offset; + size_t tri_offset; - explicit EdgeDice(const SubdParams& params); + explicit EdgeDice(const SubdParams ¶ms); - void reserve(int num_verts); + void reserve(int num_verts); - int add_vert(Patch *patch, float2 uv); - void add_triangle(Patch *patch, int v0, int v1, int v2); + int add_vert(Patch *patch, float2 uv); + void add_triangle(Patch *patch, int v0, int v1, int v2); - void stitch_triangles(Patch *patch, vector<int>& outer, vector<int>& inner); + void stitch_triangles(Patch *patch, vector<int> &outer, vector<int> &inner); }; /* Quad EdgeDice @@ -90,48 +89,58 @@ public: */ class QuadDice : public EdgeDice { -public: - struct SubPatch { - Patch *patch; - - float2 P00; - float2 P10; - float2 P01; - float2 P11; - }; - - struct EdgeFactors { - int tu0; - int tu1; - int tv0; - int tv1; - }; - - explicit QuadDice(const SubdParams& params); - - void reserve(EdgeFactors& ef, int Mu, int Mv); - float3 eval_projected(SubPatch& sub, float u, float v); - - float2 map_uv(SubPatch& sub, float u, float v); - int add_vert(SubPatch& sub, float u, float v); - - void add_corners(SubPatch& sub); - void add_grid(SubPatch& sub, int Mu, int Mv, int offset); - - void add_side_u(SubPatch& sub, - vector<int>& outer, vector<int>& inner, - int Mu, int Mv, int tu, int side, int offset); - - void add_side_v(SubPatch& sub, - vector<int>& outer, vector<int>& inner, - int Mu, int Mv, int tv, int side, int offset); - - float quad_area(const float3& a, const float3& b, const float3& c, const float3& d); - float scale_factor(SubPatch& sub, EdgeFactors& ef, int Mu, int Mv); - - void dice(SubPatch& sub, EdgeFactors& ef); + public: + struct SubPatch { + Patch *patch; + + float2 P00; + float2 P10; + float2 P01; + float2 P11; + }; + + struct EdgeFactors { + int tu0; + int tu1; + int tv0; + int tv1; + }; + + explicit QuadDice(const SubdParams ¶ms); + + void reserve(EdgeFactors &ef, int Mu, int Mv); + float3 eval_projected(SubPatch &sub, float u, float v); + + float2 map_uv(SubPatch &sub, float u, float v); + int add_vert(SubPatch &sub, float u, float v); + + void add_corners(SubPatch &sub); + void add_grid(SubPatch &sub, int Mu, int Mv, int offset); + + void add_side_u(SubPatch &sub, + vector<int> &outer, + vector<int> &inner, + int Mu, + int Mv, + int tu, + int side, + int offset); + + void add_side_v(SubPatch &sub, + vector<int> &outer, + vector<int> &inner, + int Mu, + int Mv, + int tv, + int side, + int offset); + + float quad_area(const float3 &a, const float3 &b, const float3 &c, const float3 &d); + float scale_factor(SubPatch &sub, EdgeFactors &ef, int Mu, int Mv); + + void dice(SubPatch &sub, EdgeFactors &ef); }; CCL_NAMESPACE_END -#endif /* __SUBD_DICE_H__ */ +#endif /* __SUBD_DICE_H__ */ diff --git a/intern/cycles/subd/subd_patch.cpp b/intern/cycles/subd/subd_patch.cpp index f8f5aa25d19..a975b7b6342 100644 --- a/intern/cycles/subd/subd_patch.cpp +++ b/intern/cycles/subd/subd_patch.cpp @@ -29,89 +29,93 @@ CCL_NAMESPACE_BEGIN static void decasteljau_cubic(float3 *P, float3 *dt, float t, const float3 cp[4]) { - float3 d0 = cp[0] + t*(cp[1] - cp[0]); - float3 d1 = cp[1] + t*(cp[2] - cp[1]); - float3 d2 = cp[2] + t*(cp[3] - cp[2]); + float3 d0 = cp[0] + t * (cp[1] - cp[0]); + float3 d1 = cp[1] + t * (cp[2] - cp[1]); + float3 d2 = cp[2] + t * (cp[3] - cp[2]); - d0 += t*(d1 - d0); - d1 += t*(d2 - d1); + d0 += t * (d1 - d0); + d1 += t * (d2 - d1); - *P = d0 + t*(d1 - d0); - if(dt) *dt = d1 - d0; + *P = d0 + t * (d1 - d0); + if (dt) + *dt = d1 - d0; } -static void decasteljau_bicubic(float3 *P, float3 *du, float3 *dv, const float3 cp[16], float u, float v) +static void decasteljau_bicubic( + float3 *P, float3 *du, float3 *dv, const float3 cp[16], float u, float v) { - float3 ucp[4], utn[4]; - - /* interpolate over u */ - decasteljau_cubic(ucp+0, utn+0, u, cp); - decasteljau_cubic(ucp+1, utn+1, u, cp+4); - decasteljau_cubic(ucp+2, utn+2, u, cp+8); - decasteljau_cubic(ucp+3, utn+3, u, cp+12); - - /* interpolate over v */ - decasteljau_cubic(P, dv, v, ucp); - if(du) decasteljau_cubic(du, NULL, v, utn); + float3 ucp[4], utn[4]; + + /* interpolate over u */ + decasteljau_cubic(ucp + 0, utn + 0, u, cp); + decasteljau_cubic(ucp + 1, utn + 1, u, cp + 4); + decasteljau_cubic(ucp + 2, utn + 2, u, cp + 8); + decasteljau_cubic(ucp + 3, utn + 3, u, cp + 12); + + /* interpolate over v */ + decasteljau_cubic(P, dv, v, ucp); + if (du) + decasteljau_cubic(du, NULL, v, utn); } /* Linear Quad Patch */ void LinearQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v) { - float3 d0 = interp(hull[0], hull[1], u); - float3 d1 = interp(hull[2], hull[3], u); + float3 d0 = interp(hull[0], hull[1], u); + float3 d1 = interp(hull[2], hull[3], u); - *P = interp(d0, d1, v); + *P = interp(d0, d1, v); - if(dPdu && dPdv) { - *dPdu = interp(hull[1] - hull[0], hull[3] - hull[2], v); - *dPdv = interp(hull[2] - hull[0], hull[3] - hull[1], u); - } + if (dPdu && dPdv) { + *dPdu = interp(hull[1] - hull[0], hull[3] - hull[2], v); + *dPdv = interp(hull[2] - hull[0], hull[3] - hull[1], u); + } - if(N) { - *N = normalize(interp(interp(normals[0], normals[1], u), interp(normals[2], normals[3], u), v)); - } + if (N) { + *N = normalize( + interp(interp(normals[0], normals[1], u), interp(normals[2], normals[3], u), v)); + } } BoundBox LinearQuadPatch::bound() { - BoundBox bbox = BoundBox::empty; + BoundBox bbox = BoundBox::empty; - for(int i = 0; i < 4; i++) - bbox.grow(hull[i]); + for (int i = 0; i < 4; i++) + bbox.grow(hull[i]); - return bbox; + return bbox; } /* Bicubic Patch */ void BicubicPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v) { - if(N) { - float3 dPdu_, dPdv_; - decasteljau_bicubic(P, &dPdu_, &dPdv_, hull, u, v); - - if(dPdu && dPdv) { - *dPdu = dPdu_; - *dPdv = dPdv_; - } - - *N = normalize(cross(dPdu_, dPdv_)); - } - else { - decasteljau_bicubic(P, dPdu, dPdv, hull, u, v); - } + if (N) { + float3 dPdu_, dPdv_; + decasteljau_bicubic(P, &dPdu_, &dPdv_, hull, u, v); + + if (dPdu && dPdv) { + *dPdu = dPdu_; + *dPdv = dPdv_; + } + + *N = normalize(cross(dPdu_, dPdv_)); + } + else { + decasteljau_bicubic(P, dPdu, dPdv, hull, u, v); + } } BoundBox BicubicPatch::bound() { - BoundBox bbox = BoundBox::empty; + BoundBox bbox = BoundBox::empty; - for(int i = 0; i < 16; i++) - bbox.grow(hull[i]); + for (int i = 0; i < 16; i++) + bbox.grow(hull[i]); - return bbox; + return bbox; } CCL_NAMESPACE_END diff --git a/intern/cycles/subd/subd_patch.h b/intern/cycles/subd/subd_patch.h index 84100139f2c..5209d4d0b07 100644 --- a/intern/cycles/subd/subd_patch.h +++ b/intern/cycles/subd/subd_patch.h @@ -23,37 +23,42 @@ CCL_NAMESPACE_BEGIN class Patch { -public: - virtual ~Patch() {} - virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v) = 0; - virtual BoundBox bound() = 0; - virtual int ptex_face_id() { return -1; } - - int patch_index; - int shader; + public: + virtual ~Patch() + { + } + virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v) = 0; + virtual BoundBox bound() = 0; + virtual int ptex_face_id() + { + return -1; + } + + int patch_index; + int shader; }; /* Linear Quad Patch */ class LinearQuadPatch : public Patch { -public: - float3 hull[4]; - float3 normals[4]; + public: + float3 hull[4]; + float3 normals[4]; - void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v); - BoundBox bound(); + void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v); + BoundBox bound(); }; /* Bicubic Patch */ class BicubicPatch : public Patch { -public: - float3 hull[16]; + public: + float3 hull[16]; - void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v); - BoundBox bound(); + void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v); + BoundBox bound(); }; CCL_NAMESPACE_END -#endif /* __SUBD_PATCH_H__ */ +#endif /* __SUBD_PATCH_H__ */ diff --git a/intern/cycles/subd/subd_patch_table.cpp b/intern/cycles/subd/subd_patch_table.cpp index f9671ee144d..4e873375725 100644 --- a/intern/cycles/subd/subd_patch_table.cpp +++ b/intern/cycles/subd/subd_patch_table.cpp @@ -30,7 +30,7 @@ #include "util/util_math.h" #ifdef WITH_OPENSUBDIV -#include <opensubdiv/far/patchTable.h> +# include <opensubdiv/far/patchTable.h> #endif CCL_NAMESPACE_BEGIN @@ -42,144 +42,146 @@ using namespace OpenSubdiv; /* functions for building patch maps */ struct PatchMapQuadNode { - /* sets all the children to point to the patch of index */ - void set_child(int index) - { - for(int i = 0; i < 4; i++) { - children[i] = index | PATCH_MAP_NODE_IS_SET | PATCH_MAP_NODE_IS_LEAF; - } - } - - /* sets the child in quadrant to point to the node or patch of the given index */ - void set_child(unsigned char quadrant, int index, bool is_leaf=true) - { - assert(quadrant < 4); - children[quadrant] = index | PATCH_MAP_NODE_IS_SET | (is_leaf ? PATCH_MAP_NODE_IS_LEAF : 0); - } - - uint children[4]; + /* sets all the children to point to the patch of index */ + void set_child(int index) + { + for (int i = 0; i < 4; i++) { + children[i] = index | PATCH_MAP_NODE_IS_SET | PATCH_MAP_NODE_IS_LEAF; + } + } + + /* sets the child in quadrant to point to the node or patch of the given index */ + void set_child(unsigned char quadrant, int index, bool is_leaf = true) + { + assert(quadrant < 4); + children[quadrant] = index | PATCH_MAP_NODE_IS_SET | (is_leaf ? PATCH_MAP_NODE_IS_LEAF : 0); + } + + uint children[4]; }; -template<class T> -static int resolve_quadrant(T& median, T& u, T& v) +template<class T> static int resolve_quadrant(T &median, T &u, T &v) { - int quadrant = -1; - - if(u < median) { - if(v < median) { - quadrant = 0; - } - else { - quadrant = 1; - v -= median; - } - } - else { - if(v < median) { - quadrant = 3; - } - else { - quadrant = 2; - v -= median; - } - u -= median; - } - - return quadrant; + int quadrant = -1; + + if (u < median) { + if (v < median) { + quadrant = 0; + } + else { + quadrant = 1; + v -= median; + } + } + else { + if (v < median) { + quadrant = 3; + } + else { + quadrant = 2; + v -= median; + } + u -= median; + } + + return quadrant; } -static void build_patch_map(PackedPatchTable& table, OpenSubdiv::Far::PatchTable* patch_table, int offset) +static void build_patch_map(PackedPatchTable &table, + OpenSubdiv::Far::PatchTable *patch_table, + int offset) { - int num_faces = 0; - - for(int array = 0; array < table.num_arrays; array++) { - Far::ConstPatchParamArray params = patch_table->GetPatchParams(array); - - for(int j = 0; j < patch_table->GetNumPatches(array); j++) { - num_faces = max(num_faces, (int)params[j].GetFaceId()); - } - } - num_faces++; - - vector<PatchMapQuadNode> quadtree; - quadtree.reserve(num_faces + table.num_patches); - quadtree.resize(num_faces); - - /* adjust offsets to make indices relative to the table */ - int handle_index = -(table.num_patches * PATCH_HANDLE_SIZE); - offset += table.total_size(); - - /* populate the quadtree from the FarPatchArrays sub-patches */ - for(int array = 0; array < table.num_arrays; array++) { - Far::ConstPatchParamArray params = patch_table->GetPatchParams(array); - - for(int i = 0; i < patch_table->GetNumPatches(array); i++, handle_index += PATCH_HANDLE_SIZE) { - const Far::PatchParam& param = params[i]; - unsigned short depth = param.GetDepth(); - - PatchMapQuadNode* node = &quadtree[params[i].GetFaceId()]; - - if(depth == (param.NonQuadRoot() ? 1 : 0)) { - /* special case : regular BSpline face w/ no sub-patches */ - node->set_child(handle_index + offset); - continue; - } - - int u = param.GetU(); - int v = param.GetV(); - int pdepth = param.NonQuadRoot() ? depth-2 : depth-1; - int half = 1 << pdepth; - - for(int j = 0; j < depth; j++) { - int delta = half >> 1; - - int quadrant = resolve_quadrant(half, u, v); - assert(quadrant >= 0); - - half = delta; - - if(j == pdepth) { - /* we have reached the depth of the sub-patch : add a leaf */ - assert(!(node->children[quadrant] & PATCH_MAP_NODE_IS_SET)); - node->set_child(quadrant, handle_index + offset, true); - break; - } - else { - /* travel down the child node of the corresponding quadrant */ - if(!(node->children[quadrant] & PATCH_MAP_NODE_IS_SET)) { - /* create a new branch in the quadrant */ - quadtree.push_back(PatchMapQuadNode()); - - int idx = (int)quadtree.size() - 1; - node->set_child(quadrant, idx*4 + offset, false); - - node = &quadtree[idx]; - } - else { - /* travel down an existing branch */ - uint idx = node->children[quadrant] & PATCH_MAP_NODE_INDEX_MASK; - node = &(quadtree[(idx - offset)/4]); - } - } - } - } - } - - /* copy into table */ - assert(table.table.size() == table.total_size()); - uint map_offset = table.total_size(); - - table.num_nodes = quadtree.size() * 4; - table.table.resize(table.total_size()); - - uint* data = &table.table[map_offset]; - - for(int i = 0; i < quadtree.size(); i++) { - for(int j = 0; j < 4; j++) { - assert(quadtree[i].children[j] & PATCH_MAP_NODE_IS_SET); - *(data++) = quadtree[i].children[j]; - } - } + int num_faces = 0; + + for (int array = 0; array < table.num_arrays; array++) { + Far::ConstPatchParamArray params = patch_table->GetPatchParams(array); + + for (int j = 0; j < patch_table->GetNumPatches(array); j++) { + num_faces = max(num_faces, (int)params[j].GetFaceId()); + } + } + num_faces++; + + vector<PatchMapQuadNode> quadtree; + quadtree.reserve(num_faces + table.num_patches); + quadtree.resize(num_faces); + + /* adjust offsets to make indices relative to the table */ + int handle_index = -(table.num_patches * PATCH_HANDLE_SIZE); + offset += table.total_size(); + + /* populate the quadtree from the FarPatchArrays sub-patches */ + for (int array = 0; array < table.num_arrays; array++) { + Far::ConstPatchParamArray params = patch_table->GetPatchParams(array); + + for (int i = 0; i < patch_table->GetNumPatches(array); + i++, handle_index += PATCH_HANDLE_SIZE) { + const Far::PatchParam ¶m = params[i]; + unsigned short depth = param.GetDepth(); + + PatchMapQuadNode *node = &quadtree[params[i].GetFaceId()]; + + if (depth == (param.NonQuadRoot() ? 1 : 0)) { + /* special case : regular BSpline face w/ no sub-patches */ + node->set_child(handle_index + offset); + continue; + } + + int u = param.GetU(); + int v = param.GetV(); + int pdepth = param.NonQuadRoot() ? depth - 2 : depth - 1; + int half = 1 << pdepth; + + for (int j = 0; j < depth; j++) { + int delta = half >> 1; + + int quadrant = resolve_quadrant(half, u, v); + assert(quadrant >= 0); + + half = delta; + + if (j == pdepth) { + /* we have reached the depth of the sub-patch : add a leaf */ + assert(!(node->children[quadrant] & PATCH_MAP_NODE_IS_SET)); + node->set_child(quadrant, handle_index + offset, true); + break; + } + else { + /* travel down the child node of the corresponding quadrant */ + if (!(node->children[quadrant] & PATCH_MAP_NODE_IS_SET)) { + /* create a new branch in the quadrant */ + quadtree.push_back(PatchMapQuadNode()); + + int idx = (int)quadtree.size() - 1; + node->set_child(quadrant, idx * 4 + offset, false); + + node = &quadtree[idx]; + } + else { + /* travel down an existing branch */ + uint idx = node->children[quadrant] & PATCH_MAP_NODE_INDEX_MASK; + node = &(quadtree[(idx - offset) / 4]); + } + } + } + } + } + + /* copy into table */ + assert(table.table.size() == table.total_size()); + uint map_offset = table.total_size(); + + table.num_nodes = quadtree.size() * 4; + table.table.resize(table.total_size()); + + uint *data = &table.table[map_offset]; + + for (int i = 0; i < quadtree.size(); i++) { + for (int j = 0; j < 4; j++) { + assert(quadtree[i].children[j] & PATCH_MAP_NODE_IS_SET); + *(data++) = quadtree[i].children[j]; + } + } } #endif @@ -188,108 +190,106 @@ static void build_patch_map(PackedPatchTable& table, OpenSubdiv::Far::PatchTable size_t PackedPatchTable::total_size() { - return num_arrays * PATCH_ARRAY_SIZE + - num_indices + - num_patches * (PATCH_PARAM_SIZE + PATCH_HANDLE_SIZE) + - num_nodes * PATCH_NODE_SIZE; + return num_arrays * PATCH_ARRAY_SIZE + num_indices + + num_patches * (PATCH_PARAM_SIZE + PATCH_HANDLE_SIZE) + num_nodes * PATCH_NODE_SIZE; } -void PackedPatchTable::pack(Far::PatchTable* patch_table, int offset) +void PackedPatchTable::pack(Far::PatchTable *patch_table, int offset) { - num_arrays = 0; - num_patches = 0; - num_indices = 0; - num_nodes = 0; + num_arrays = 0; + num_patches = 0; + num_indices = 0; + num_nodes = 0; #ifdef WITH_OPENSUBDIV - num_arrays = patch_table->GetNumPatchArrays(); + num_arrays = patch_table->GetNumPatchArrays(); - for(int i = 0; i < num_arrays; i++) { - int patches = patch_table->GetNumPatches(i); - int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices(); + for (int i = 0; i < num_arrays; i++) { + int patches = patch_table->GetNumPatches(i); + int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices(); - num_patches += patches; - num_indices += patches * num_control; - } + num_patches += patches; + num_indices += patches * num_control; + } - table.resize(total_size()); - uint* data = table.data(); + table.resize(total_size()); + uint *data = table.data(); - uint* array = data; - uint* index = array + num_arrays * PATCH_ARRAY_SIZE; - uint* param = index + num_indices; - uint* handle = param + num_patches * PATCH_PARAM_SIZE; + uint *array = data; + uint *index = array + num_arrays * PATCH_ARRAY_SIZE; + uint *param = index + num_indices; + uint *handle = param + num_patches * PATCH_PARAM_SIZE; - uint current_param = 0; + uint current_param = 0; - for(int i = 0; i < num_arrays; i++) { - *(array++) = patch_table->GetPatchArrayDescriptor(i).GetType(); - *(array++) = patch_table->GetNumPatches(i); - *(array++) = (index - data) + offset; - *(array++) = (param - data) + offset; + for (int i = 0; i < num_arrays; i++) { + *(array++) = patch_table->GetPatchArrayDescriptor(i).GetType(); + *(array++) = patch_table->GetNumPatches(i); + *(array++) = (index - data) + offset; + *(array++) = (param - data) + offset; - Far::ConstIndexArray indices = patch_table->GetPatchArrayVertices(i); + Far::ConstIndexArray indices = patch_table->GetPatchArrayVertices(i); - for(int j = 0; j < indices.size(); j++) { - *(index++) = indices[j]; - } + for (int j = 0; j < indices.size(); j++) { + *(index++) = indices[j]; + } - const Far::PatchParamTable& param_table = patch_table->GetPatchParamTable(); + const Far::PatchParamTable ¶m_table = patch_table->GetPatchParamTable(); - int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices(); - int patches = patch_table->GetNumPatches(i); + int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices(); + int patches = patch_table->GetNumPatches(i); - for(int j = 0; j < patches; j++, current_param++) { - *(param++) = param_table[current_param].field0; - *(param++) = param_table[current_param].field1; + for (int j = 0; j < patches; j++, current_param++) { + *(param++) = param_table[current_param].field0; + *(param++) = param_table[current_param].field1; - *(handle++) = (array - data) - PATCH_ARRAY_SIZE + offset; - *(handle++) = (param - data) - PATCH_PARAM_SIZE + offset; - *(handle++) = j * num_control; - } - } + *(handle++) = (array - data) - PATCH_ARRAY_SIZE + offset; + *(handle++) = (param - data) - PATCH_PARAM_SIZE + offset; + *(handle++) = j * num_control; + } + } - build_patch_map(*this, patch_table, offset); + build_patch_map(*this, patch_table, offset); #else - (void) patch_table; - (void) offset; + (void)patch_table; + (void)offset; #endif } -void PackedPatchTable::copy_adjusting_offsets(uint* dest, int doffset) +void PackedPatchTable::copy_adjusting_offsets(uint *dest, int doffset) { - uint* src = table.data(); - - /* arrays */ - for(int i = 0; i < num_arrays; i++) { - *(dest++) = *(src++); - *(dest++) = *(src++); - *(dest++) = *(src++) + doffset; - *(dest++) = *(src++) + doffset; - } - - /* indices */ - for(int i = 0; i < num_indices; i++) { - *(dest++) = *(src++); - } - - /* params */ - for(int i = 0; i < num_patches; i++) { - *(dest++) = *(src++); - *(dest++) = *(src++); - } - - /* handles */ - for(int i = 0; i < num_patches; i++) { - *(dest++) = *(src++) + doffset; - *(dest++) = *(src++) + doffset; - *(dest++) = *(src++); - } - - /* nodes */ - for(int i = 0; i < num_nodes; i++) { - *(dest++) = *(src++) + doffset; - } + uint *src = table.data(); + + /* arrays */ + for (int i = 0; i < num_arrays; i++) { + *(dest++) = *(src++); + *(dest++) = *(src++); + *(dest++) = *(src++) + doffset; + *(dest++) = *(src++) + doffset; + } + + /* indices */ + for (int i = 0; i < num_indices; i++) { + *(dest++) = *(src++); + } + + /* params */ + for (int i = 0; i < num_patches; i++) { + *(dest++) = *(src++); + *(dest++) = *(src++); + } + + /* handles */ + for (int i = 0; i < num_patches; i++) { + *(dest++) = *(src++) + doffset; + *(dest++) = *(src++) + doffset; + *(dest++) = *(src++); + } + + /* nodes */ + for (int i = 0; i < num_nodes; i++) { + *(dest++) = *(src++) + doffset; + } } CCL_NAMESPACE_END diff --git a/intern/cycles/subd/subd_patch_table.h b/intern/cycles/subd/subd_patch_table.h index 1765578c42e..118d410f8f0 100644 --- a/intern/cycles/subd/subd_patch_table.h +++ b/intern/cycles/subd/subd_patch_table.h @@ -21,11 +21,11 @@ #include "util/util_types.h" #ifdef WITH_OPENSUBDIV -#ifdef _MSC_VER -# include "iso646.h" -#endif +# ifdef _MSC_VER +# include "iso646.h" +# endif -#include <opensubdiv/far/patchTable.h> +# include <opensubdiv/far/patchTable.h> #endif CCL_NAMESPACE_BEGIN @@ -34,7 +34,9 @@ CCL_NAMESPACE_BEGIN using namespace OpenSubdiv; #else /* forward declare for when OpenSubdiv is unavailable */ -namespace Far { struct PatchTable; } +namespace Far { +struct PatchTable; +} #endif #define PATCH_ARRAY_SIZE 4 @@ -43,20 +45,20 @@ namespace Far { struct PatchTable; } #define PATCH_NODE_SIZE 1 struct PackedPatchTable { - array<uint> table; + array<uint> table; - size_t num_arrays; - size_t num_indices; - size_t num_patches; - size_t num_nodes; + size_t num_arrays; + size_t num_indices; + size_t num_patches; + size_t num_nodes; - /* calculated size from num_* members */ - size_t total_size(); + /* calculated size from num_* members */ + size_t total_size(); - void pack(Far::PatchTable* patch_table, int offset = 0); - void copy_adjusting_offsets(uint* dest, int doffset); + void pack(Far::PatchTable *patch_table, int offset = 0); + void copy_adjusting_offsets(uint *dest, int doffset); }; CCL_NAMESPACE_END -#endif /* __SUBD_PATCH_TABLE_H__ */ +#endif /* __SUBD_PATCH_TABLE_H__ */ diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp index 76261243359..803363bc240 100644 --- a/intern/cycles/subd/subd_split.cpp +++ b/intern/cycles/subd/subd_split.cpp @@ -28,233 +28,230 @@ CCL_NAMESPACE_BEGIN /* DiagSplit */ -DiagSplit::DiagSplit(const SubdParams& params_) -: params(params_) +DiagSplit::DiagSplit(const SubdParams ¶ms_) : params(params_) { } -void DiagSplit::dispatch(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef) +void DiagSplit::dispatch(QuadDice::SubPatch &sub, QuadDice::EdgeFactors &ef) { - subpatches_quad.push_back(sub); - edgefactors_quad.push_back(ef); + subpatches_quad.push_back(sub); + edgefactors_quad.push_back(ef); } float3 DiagSplit::to_world(Patch *patch, float2 uv) { - float3 P; + float3 P; - patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y); - if(params.camera) - P = transform_point(¶ms.objecttoworld, P); + patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y); + if (params.camera) + P = transform_point(¶ms.objecttoworld, P); - return P; + return P; } int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend) { - float3 Plast = make_float3(0.0f, 0.0f, 0.0f); - float Lsum = 0.0f; - float Lmax = 0.0f; + float3 Plast = make_float3(0.0f, 0.0f, 0.0f); + float Lsum = 0.0f; + float Lmax = 0.0f; - for(int i = 0; i < params.test_steps; i++) { - float t = i/(float)(params.test_steps-1); + for (int i = 0; i < params.test_steps; i++) { + float t = i / (float)(params.test_steps - 1); - float3 P = to_world(patch, Pstart + t*(Pend - Pstart)); + float3 P = to_world(patch, Pstart + t * (Pend - Pstart)); - if(i > 0) { - float L; + if (i > 0) { + float L; - if(!params.camera) { - L = len(P - Plast); - } - else { - Camera* cam = params.camera; + if (!params.camera) { + L = len(P - Plast); + } + else { + Camera *cam = params.camera; - float pixel_width = cam->world_to_raster_size((P + Plast) * 0.5f); - L = len(P - Plast) / pixel_width; - } + float pixel_width = cam->world_to_raster_size((P + Plast) * 0.5f); + L = len(P - Plast) / pixel_width; + } - Lsum += L; - Lmax = max(L, Lmax); - } + Lsum += L; + Lmax = max(L, Lmax); + } - Plast = P; - } + Plast = P; + } - 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? + 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 > params.split_threshold) - return DSPLIT_NON_UNIFORM; + if (tmax - tmin > params.split_threshold) + return DSPLIT_NON_UNIFORM; - return tmax; + return tmax; } -void DiagSplit::partition_edge(Patch *patch, float2 *P, int *t0, int *t1, float2 Pstart, float2 Pend, int t) +void DiagSplit::partition_edge( + Patch *patch, float2 *P, int *t0, int *t1, float2 Pstart, float2 Pend, int t) { - if(t == DSPLIT_NON_UNIFORM) { - *P = (Pstart + Pend)*0.5f; - *t0 = T(patch, Pstart, *P); - *t1 = T(patch, *P, Pend); - } - else { - int I = (int)floor((float)t*0.5f); - *P = interp(Pstart, Pend, (t == 0)? 0: I/(float)t); /* XXX is t faces or verts */ - *t0 = I; - *t1 = t - I; - } + if (t == DSPLIT_NON_UNIFORM) { + *P = (Pstart + Pend) * 0.5f; + *t0 = T(patch, Pstart, *P); + *t1 = T(patch, *P, Pend); + } + else { + int I = (int)floor((float)t * 0.5f); + *P = interp(Pstart, Pend, (t == 0) ? 0 : I / (float)t); /* XXX is t faces or verts */ + *t0 = I; + *t1 = t - I; + } } -static void limit_edge_factors(const QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int max_t) +static void limit_edge_factors(const QuadDice::SubPatch &sub, QuadDice::EdgeFactors &ef, int max_t) { - float2 P00 = sub.P00; - float2 P01 = sub.P01; - float2 P10 = sub.P10; - float2 P11 = sub.P11; - - int tu0 = int(max_t * len(P10 - P00)); - int tu1 = int(max_t * len(P11 - P01)); - int tv0 = int(max_t * len(P01 - P00)); - int tv1 = int(max_t * len(P11 - P10)); - - ef.tu0 = tu0 <= 1 ? 1 : min(ef.tu0, tu0); - ef.tu1 = tu1 <= 1 ? 1 : min(ef.tu1, tu1); - ef.tv0 = tv0 <= 1 ? 1 : min(ef.tv0, tv0); - ef.tv1 = tv1 <= 1 ? 1 : min(ef.tv1, tv1); + float2 P00 = sub.P00; + float2 P01 = sub.P01; + float2 P10 = sub.P10; + float2 P11 = sub.P11; + + int tu0 = int(max_t * len(P10 - P00)); + int tu1 = int(max_t * len(P11 - P01)); + int tv0 = int(max_t * len(P01 - P00)); + int tv1 = int(max_t * len(P11 - P10)); + + ef.tu0 = tu0 <= 1 ? 1 : min(ef.tu0, tu0); + ef.tu1 = tu1 <= 1 ? 1 : min(ef.tu1, tu1); + ef.tv0 = tv0 <= 1 ? 1 : min(ef.tv0, tv0); + ef.tv1 = tv1 <= 1 ? 1 : min(ef.tv1, tv1); } -void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int depth) +void DiagSplit::split(QuadDice::SubPatch &sub, QuadDice::EdgeFactors &ef, int depth) { - if(depth > 32) { - /* We should never get here, but just in case end recursion safely. */ - ef.tu0 = 1; - ef.tu1 = 1; - ef.tv0 = 1; - ef.tv1 = 1; + if (depth > 32) { + /* We should never get here, but just in case end recursion safely. */ + ef.tu0 = 1; + ef.tu1 = 1; + ef.tv0 = 1; + ef.tv1 = 1; - dispatch(sub, ef); - return; - } + dispatch(sub, ef); + return; + } - bool split_u = (ef.tu0 == DSPLIT_NON_UNIFORM || ef.tu1 == DSPLIT_NON_UNIFORM); - bool split_v = (ef.tv0 == DSPLIT_NON_UNIFORM || ef.tv1 == DSPLIT_NON_UNIFORM); + bool split_u = (ef.tu0 == DSPLIT_NON_UNIFORM || ef.tu1 == DSPLIT_NON_UNIFORM); + bool split_v = (ef.tv0 == DSPLIT_NON_UNIFORM || ef.tv1 == DSPLIT_NON_UNIFORM); - /* Split subpatches such that the ratio of T for opposite edges doesn't + /* Split subpatches such that the ratio of T for opposite edges doesn't * exceed 1.5, this reduces over tessellation for some patches - */ - bool tmp_split_v = split_v; - if(!split_u && min(ef.tu0, ef.tu1) > 8 && min(ef.tu0, ef.tu1)*1.5f < max(ef.tu0, ef.tu1)) - split_v = true; - if(!tmp_split_v && min(ef.tu0, ef.tu1) > 8 && min(ef.tv0, ef.tv1)*1.5f < max(ef.tv0, ef.tv1)) - split_u = true; - - /* alternate axis */ - if(split_u && split_v) { - split_u = depth % 2; - } - - if(split_u) { - /* partition edges */ - QuadDice::EdgeFactors ef0, ef1; - float2 Pu0, Pu1; - - partition_edge(sub.patch, - &Pu0, &ef0.tu0, &ef1.tu0, sub.P00, sub.P10, ef.tu0); - partition_edge(sub.patch, - &Pu1, &ef0.tu1, &ef1.tu1, sub.P01, sub.P11, ef.tu1); - - /* split */ - int tsplit = T(sub.patch, Pu0, Pu1); - ef0.tv0 = ef.tv0; - ef0.tv1 = tsplit; - - ef1.tv0 = tsplit; - ef1.tv1 = ef.tv1; - - /* create subpatches */ - QuadDice::SubPatch sub0 = {sub.patch, sub.P00, Pu0, sub.P01, Pu1}; - QuadDice::SubPatch sub1 = {sub.patch, Pu0, sub.P10, Pu1, sub.P11}; - - limit_edge_factors(sub0, ef0, 1 << params.max_level); - limit_edge_factors(sub1, ef1, 1 << params.max_level); - - split(sub0, ef0, depth+1); - split(sub1, ef1, depth+1); - } - else if(split_v) { - /* partition edges */ - QuadDice::EdgeFactors ef0, ef1; - float2 Pv0, Pv1; - - partition_edge(sub.patch, - &Pv0, &ef0.tv0, &ef1.tv0, sub.P00, sub.P01, ef.tv0); - partition_edge(sub.patch, - &Pv1, &ef0.tv1, &ef1.tv1, sub.P10, sub.P11, ef.tv1); - - /* split */ - int tsplit = T(sub.patch, Pv0, Pv1); - ef0.tu0 = ef.tu0; - ef0.tu1 = tsplit; - - ef1.tu0 = tsplit; - ef1.tu1 = ef.tu1; - - /* create subpatches */ - QuadDice::SubPatch sub0 = {sub.patch, sub.P00, sub.P10, Pv0, Pv1}; - QuadDice::SubPatch sub1 = {sub.patch, Pv0, Pv1, sub.P01, sub.P11}; - - limit_edge_factors(sub0, ef0, 1 << params.max_level); - limit_edge_factors(sub1, ef1, 1 << params.max_level); - - split(sub0, ef0, depth+1); - split(sub1, ef1, depth+1); - } - else { - dispatch(sub, ef); - } + */ + bool tmp_split_v = split_v; + if (!split_u && min(ef.tu0, ef.tu1) > 8 && min(ef.tu0, ef.tu1) * 1.5f < max(ef.tu0, ef.tu1)) + split_v = true; + if (!tmp_split_v && min(ef.tu0, ef.tu1) > 8 && min(ef.tv0, ef.tv1) * 1.5f < max(ef.tv0, ef.tv1)) + split_u = true; + + /* alternate axis */ + if (split_u && split_v) { + split_u = depth % 2; + } + + if (split_u) { + /* partition edges */ + QuadDice::EdgeFactors ef0, ef1; + float2 Pu0, Pu1; + + partition_edge(sub.patch, &Pu0, &ef0.tu0, &ef1.tu0, sub.P00, sub.P10, ef.tu0); + partition_edge(sub.patch, &Pu1, &ef0.tu1, &ef1.tu1, sub.P01, sub.P11, ef.tu1); + + /* split */ + int tsplit = T(sub.patch, Pu0, Pu1); + ef0.tv0 = ef.tv0; + ef0.tv1 = tsplit; + + ef1.tv0 = tsplit; + ef1.tv1 = ef.tv1; + + /* create subpatches */ + QuadDice::SubPatch sub0 = {sub.patch, sub.P00, Pu0, sub.P01, Pu1}; + QuadDice::SubPatch sub1 = {sub.patch, Pu0, sub.P10, Pu1, sub.P11}; + + limit_edge_factors(sub0, ef0, 1 << params.max_level); + limit_edge_factors(sub1, ef1, 1 << params.max_level); + + split(sub0, ef0, depth + 1); + split(sub1, ef1, depth + 1); + } + else if (split_v) { + /* partition edges */ + QuadDice::EdgeFactors ef0, ef1; + float2 Pv0, Pv1; + + partition_edge(sub.patch, &Pv0, &ef0.tv0, &ef1.tv0, sub.P00, sub.P01, ef.tv0); + partition_edge(sub.patch, &Pv1, &ef0.tv1, &ef1.tv1, sub.P10, sub.P11, ef.tv1); + + /* split */ + int tsplit = T(sub.patch, Pv0, Pv1); + ef0.tu0 = ef.tu0; + ef0.tu1 = tsplit; + + ef1.tu0 = tsplit; + ef1.tu1 = ef.tu1; + + /* create subpatches */ + QuadDice::SubPatch sub0 = {sub.patch, sub.P00, sub.P10, Pv0, Pv1}; + QuadDice::SubPatch sub1 = {sub.patch, Pv0, Pv1, sub.P01, sub.P11}; + + limit_edge_factors(sub0, ef0, 1 << params.max_level); + limit_edge_factors(sub1, ef1, 1 << params.max_level); + + split(sub0, ef0, depth + 1); + split(sub1, ef1, depth + 1); + } + else { + dispatch(sub, ef); + } } void DiagSplit::split_quad(Patch *patch, QuadDice::SubPatch *subpatch) { - QuadDice::SubPatch sub_split; - QuadDice::EdgeFactors ef_split; + QuadDice::SubPatch sub_split; + QuadDice::EdgeFactors ef_split; - if(subpatch) { - sub_split = *subpatch; - } - else { - sub_split.patch = patch; - sub_split.P00 = make_float2(0.0f, 0.0f); - sub_split.P10 = make_float2(1.0f, 0.0f); - sub_split.P01 = make_float2(0.0f, 1.0f); - sub_split.P11 = make_float2(1.0f, 1.0f); - } + if (subpatch) { + sub_split = *subpatch; + } + else { + sub_split.patch = patch; + sub_split.P00 = make_float2(0.0f, 0.0f); + sub_split.P10 = make_float2(1.0f, 0.0f); + sub_split.P01 = make_float2(0.0f, 1.0f); + sub_split.P11 = make_float2(1.0f, 1.0f); + } - ef_split.tu0 = T(patch, sub_split.P00, sub_split.P10); - ef_split.tu1 = T(patch, sub_split.P01, sub_split.P11); - ef_split.tv0 = T(patch, sub_split.P00, sub_split.P01); - ef_split.tv1 = T(patch, sub_split.P10, sub_split.P11); + ef_split.tu0 = T(patch, sub_split.P00, sub_split.P10); + ef_split.tu1 = T(patch, sub_split.P01, sub_split.P11); + ef_split.tv0 = T(patch, sub_split.P00, sub_split.P01); + ef_split.tv1 = T(patch, sub_split.P10, sub_split.P11); - limit_edge_factors(sub_split, ef_split, 1 << params.max_level); + limit_edge_factors(sub_split, ef_split, 1 << params.max_level); - split(sub_split, ef_split); + split(sub_split, ef_split); - QuadDice dice(params); + QuadDice dice(params); - for(size_t i = 0; i < subpatches_quad.size(); i++) { - QuadDice::SubPatch& sub = subpatches_quad[i]; - QuadDice::EdgeFactors& ef = edgefactors_quad[i]; + for (size_t i = 0; i < subpatches_quad.size(); i++) { + QuadDice::SubPatch &sub = subpatches_quad[i]; + QuadDice::EdgeFactors &ef = edgefactors_quad[i]; - ef.tu0 = max(ef.tu0, 1); - ef.tu1 = max(ef.tu1, 1); - ef.tv0 = max(ef.tv0, 1); - ef.tv1 = max(ef.tv1, 1); + ef.tu0 = max(ef.tu0, 1); + ef.tu1 = max(ef.tu1, 1); + ef.tv0 = max(ef.tv0, 1); + ef.tv1 = max(ef.tv1, 1); - dice.dice(sub, ef); - } + dice.dice(sub, ef); + } - subpatches_quad.clear(); - edgefactors_quad.clear(); + subpatches_quad.clear(); + edgefactors_quad.clear(); } CCL_NAMESPACE_END diff --git a/intern/cycles/subd/subd_split.h b/intern/cycles/subd/subd_split.h index 3368c93944b..6e68d8ee598 100644 --- a/intern/cycles/subd/subd_split.h +++ b/intern/cycles/subd/subd_split.h @@ -35,25 +35,25 @@ class Patch; #define DSPLIT_NON_UNIFORM -1 class DiagSplit { -public: - vector<QuadDice::SubPatch> subpatches_quad; - vector<QuadDice::EdgeFactors> edgefactors_quad; + public: + vector<QuadDice::SubPatch> subpatches_quad; + vector<QuadDice::EdgeFactors> edgefactors_quad; - SubdParams params; + SubdParams params; - explicit DiagSplit(const SubdParams& params); + explicit DiagSplit(const SubdParams ¶ms); - float3 to_world(Patch *patch, float2 uv); - int T(Patch *patch, float2 Pstart, float2 Pend); - void partition_edge(Patch *patch, float2 *P, int *t0, int *t1, - float2 Pstart, float2 Pend, int t); + float3 to_world(Patch *patch, float2 uv); + int T(Patch *patch, float2 Pstart, float2 Pend); + void partition_edge( + Patch *patch, float2 *P, int *t0, int *t1, float2 Pstart, float2 Pend, int t); - void dispatch(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef); - void split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int depth=0); + void dispatch(QuadDice::SubPatch &sub, QuadDice::EdgeFactors &ef); + void split(QuadDice::SubPatch &sub, QuadDice::EdgeFactors &ef, int depth = 0); - void split_quad(Patch *patch, QuadDice::SubPatch *subpatch=NULL); + void split_quad(Patch *patch, QuadDice::SubPatch *subpatch = NULL); }; CCL_NAMESPACE_END -#endif /* __SUBD_SPLIT_H__ */ +#endif /* __SUBD_SPLIT_H__ */ |