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:
authorMai Lavelle <mai.lavelle@gmail.com>2016-07-17 02:42:28 +0300
committerMai Lavelle <mai.lavelle@gmail.com>2016-07-29 10:36:30 +0300
commitc96ae81160ad1a943fafaca44a7d5e97c2d7a0d7 (patch)
tree83905d5a6bf2583f44d9dcf90410b5a0c024822c /intern/cycles/subd/subd_split.cpp
parentf74645578c9dd38c2543d1211b779a019363b04f (diff)
Cycles microdisplacement: ngons and attributes for subdivision meshes
This adds support for ngons and attributes on subdivision meshes. Ngons are needed for proper attribute interpolation as well as correct Catmull-Clark subdivision. Several changes are made to achieve this: - new primitive `SubdFace` added to `Mesh` - 3 more textures are used to store info on patches from subd meshes - Blender export uses loop interface instead of tessface for subd meshes - `Attribute` class is updated with a simplified way to pass primitive counts around and to support ngons. - extra points for ngons are generated for O(1) attribute interpolation - curves are temporally disabled on subd meshes to avoid various bugs with implementation - old unneeded code is removed from `subd/` - various fixes and improvements Reviewed By: brecht Differential Revision: https://developer.blender.org/D2108
Diffstat (limited to 'intern/cycles/subd/subd_split.cpp')
-rw-r--r--intern/cycles/subd/subd_split.cpp199
1 files changed, 21 insertions, 178 deletions
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index c4af8cc8c43..3c91ad8ab0d 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -40,12 +40,6 @@ void DiagSplit::dispatch(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef)
edgefactors_quad.push_back(ef);
}
-void DiagSplit::dispatch(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef)
-{
- subpatches_triangle.push_back(sub);
- edgefactors_triangle.push_back(ef);
-}
-
float3 DiagSplit::to_world(Patch *patch, float2 uv)
{
float3 P;
@@ -112,34 +106,6 @@ void DiagSplit::partition_edge(Patch *patch, float2 *P, int *t0, int *t1, float2
}
}
-static float2 right_to_equilateral(float2 P)
-{
- static const float2 A = make_float2(1.0f, 0.5f);
- static const float2 B = make_float2(0.0f, sinf(M_PI_F/3.0f));
- return make_float2(dot(P, A), dot(P, B));
-}
-
-static void limit_edge_factors(const TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int max_t)
-{
- float2 Pu = sub.Pu;
- float2 Pv = sub.Pv;
- float2 Pw = sub.Pw;
-
- if(sub.patch->is_triangle()) {
- Pu = right_to_equilateral(Pu);
- Pv = right_to_equilateral(Pv);
- Pw = right_to_equilateral(Pw);
- }
-
- int tu = int(max_t * len(Pw - Pv));
- int tv = int(max_t * len(Pw - Pu));
- int tw = int(max_t * len(Pv - Pu));
-
- ef.tu = tu <= 1 ? 1 : min(ef.tu, tu);
- ef.tv = tv <= 1 ? 1 : min(ef.tv, tv);
- ef.tw = tw <= 1 ? 1 : min(ef.tw, tw);
-}
-
static void limit_edge_factors(const QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int max_t)
{
float2 P00 = sub.P00;
@@ -147,13 +113,6 @@ static void limit_edge_factors(const QuadDice::SubPatch& sub, QuadDice::EdgeFact
float2 P10 = sub.P10;
float2 P11 = sub.P11;
- if(sub.patch->is_triangle()) {
- P00 = right_to_equilateral(P00);
- P01 = right_to_equilateral(P01);
- P10 = right_to_equilateral(P10);
- P11 = right_to_equilateral(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));
@@ -165,84 +124,6 @@ static void limit_edge_factors(const QuadDice::SubPatch& sub, QuadDice::EdgeFact
ef.tv1 = tv1 <= 1 ? 1 : min(ef.tv1, tv1);
}
-void DiagSplit::split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int depth)
-{
- if(depth > 32) {
- /* We should never get here, but just in case end recursion safely. */
- ef.tu = 1;
- ef.tv = 1;
- ef.tw = 1;
-
- dispatch(sub, ef);
- return;
- }
-
- assert(ef.tu == T(sub.patch, sub.Pv, sub.Pw));
- assert(ef.tv == T(sub.patch, sub.Pw, sub.Pu));
- assert(ef.tw == T(sub.patch, sub.Pu, sub.Pv));
-
- int non_uniform_count = int(ef.tu == DSPLIT_NON_UNIFORM) +
- int(ef.tv == DSPLIT_NON_UNIFORM) +
- int(ef.tw == DSPLIT_NON_UNIFORM);
-
- switch(non_uniform_count) {
- case 1: {
- /* TODO(mai): one edge is non-uniform, split into two triangles */
- // fallthru
- }
- case 2: {
- /* TODO(mai): two edges are non-uniform, split into triangle and quad */
- // fallthru
- }
- case 3: {
- /* all three edges are non-uniform, split into three quads */
-
- /* partition edges */
- QuadDice::EdgeFactors ef0, ef1, ef2;
- float2 Pu, Pv, Pw, Pcenter;
-
- partition_edge(sub.patch, &Pu, &ef1.tv0, &ef2.tu0, sub.Pw, sub.Pv, ef.tu);
- partition_edge(sub.patch, &Pv, &ef0.tv0, &ef1.tu0, sub.Pu, sub.Pw, ef.tv);
- partition_edge(sub.patch, &Pw, &ef2.tv0, &ef0.tu0, sub.Pv, sub.Pu, ef.tw);
- Pcenter = (Pu + Pv + Pw) * (1.0f / 3.0f);
-
- /* split */
- int tsplit01 = T(sub.patch, Pv, Pcenter);
- int tsplit12 = T(sub.patch, Pu, Pcenter);
- int tsplit20 = T(sub.patch, Pw, Pcenter);
-
- ef0.tu1 = tsplit01;
- ef0.tv1 = tsplit20;
-
- ef1.tu1 = tsplit12;
- ef1.tv1 = tsplit01;
-
- ef2.tu1 = tsplit20;
- ef2.tv1 = tsplit12;
-
- /* create subpatches */
- QuadDice::SubPatch sub0 = {sub.patch, sub.Pu, Pw, Pv, Pcenter};
- QuadDice::SubPatch sub1 = {sub.patch, sub.Pw, Pv, Pu, Pcenter};
- QuadDice::SubPatch sub2 = {sub.patch, sub.Pv, Pu, Pw, Pcenter};
-
- limit_edge_factors(sub0, ef0, 1 << params.max_level);
- limit_edge_factors(sub1, ef1, 1 << params.max_level);
- limit_edge_factors(sub2, ef2, 1 << params.max_level);
-
- split(sub0, ef0, depth+1);
- split(sub1, ef1, depth+1);
- split(sub2, ef2, depth+1);
-
- break;
- }
- default: {
- /* all edges uniform, no splitting needed */
- dispatch(sub, ef);
- break;
- }
- }
-}
-
void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int depth)
{
if(depth > 32) {
@@ -259,6 +140,16 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de
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
+ * 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;
}
@@ -324,69 +215,21 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de
}
}
-void DiagSplit::split_triangle(Patch *patch)
-{
- TriangleDice::SubPatch sub_split;
- TriangleDice::EdgeFactors ef_split;
-
- sub_split.patch = patch;
- sub_split.Pu = make_float2(1.0f, 0.0f);
- sub_split.Pv = make_float2(0.0f, 1.0f);
- sub_split.Pw = make_float2(0.0f, 0.0f);
-
- ef_split.tu = T(patch, sub_split.Pv, sub_split.Pw);
- ef_split.tv = T(patch, sub_split.Pw, sub_split.Pu);
- ef_split.tw = T(patch, sub_split.Pu, sub_split.Pv);
-
- limit_edge_factors(sub_split, ef_split, 1 << params.max_level);
-
- split(sub_split, ef_split);
-
- TriangleDice dice(params);
-
- for(size_t i = 0; i < subpatches_triangle.size(); i++) {
- TriangleDice::SubPatch& sub = subpatches_triangle[i];
- TriangleDice::EdgeFactors& ef = edgefactors_triangle[i];
-
- ef.tu = max(ef.tu, 1);
- ef.tv = max(ef.tv, 1);
- ef.tw = max(ef.tw, 1);
-
- dice.dice(sub, ef);
- }
-
- subpatches_triangle.clear();
- edgefactors_triangle.clear();
-
- /* triangle might be split into quads so dice quad subpatches as well */
- QuadDice qdice(params);
-
- 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);
-
- qdice.dice(sub, ef);
- }
-
- subpatches_quad.clear();
- edgefactors_quad.clear();
-}
-
-void DiagSplit::split_quad(Patch *patch)
+void DiagSplit::split_quad(Patch *patch, QuadDice::SubPatch *subpatch)
{
QuadDice::SubPatch sub_split;
QuadDice::EdgeFactors ef_split;
- 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);