Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/subd/subd_dice.cpp')
-rw-r--r--intern/cycles/subd/subd_dice.cpp454
1 files changed, 231 insertions, 223 deletions
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 &params_) : 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 &params_) : 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(&params.camera->worldtoraster, P);
+ sub.patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y);
+ if (params.camera)
+ P = transform_perspective(&params.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