From 71588300d233f795fcf9b0b55ce397b9b81614ff Mon Sep 17 00:00:00 2001 From: Mai Lavelle Date: Mon, 18 Apr 2016 22:29:25 +0200 Subject: Cycles microdisplacement: fix handling of triangles in DiagSplit Theres still more room for improvement but this makes things useable. Reviewed By: brecht Differential Revision: https://developer.blender.org/D1921 --- intern/cycles/subd/subd_dice.cpp | 39 ++++++----- intern/cycles/subd/subd_split.cpp | 134 ++++++++++++++++++-------------------- 2 files changed, 88 insertions(+), 85 deletions(-) (limited to 'intern/cycles/subd') diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp index 4f27eaf7d1b..a5dfcd21ceb 100644 --- a/intern/cycles/subd/subd_dice.cpp +++ b/intern/cycles/subd/subd_dice.cpp @@ -259,17 +259,10 @@ float QuadDice::scale_factor(SubPatch& sub, EdgeFactors& ef, int Mu, int Mv) void QuadDice::add_corners(SubPatch& sub) { /* add verts for patch corners */ - if(sub.patch->is_triangle()) { - add_vert(sub, 0.0f, 0.0f); - add_vert(sub, 1.0f, 0.0f); - add_vert(sub, 0.0f, 1.0f); - } - else { - 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_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) @@ -458,15 +451,21 @@ void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M) add_triangle(sub.patch, outer_w[0], outer_u[0], outer_v[0]); } else { - /* center vertex + 6 triangles */ + /* 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); - add_triangle(sub.patch, outer_w[1], outer_w[2], 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); - add_triangle(sub.patch, outer_u[1], outer_u[2], 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); - add_triangle(sub.patch, outer_v[1], outer_v[2], center); + if(outer_v.size() > 2) + add_triangle(sub.patch, outer_v[1], outer_v[2], center); } } @@ -475,6 +474,16 @@ 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); diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp index 70081673597..05f58cf30f7 100644 --- a/intern/cycles/subd/subd_split.cpp +++ b/intern/cycles/subd/subd_split.cpp @@ -128,82 +128,62 @@ void DiagSplit::split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef assert(ef.tv == T(sub.patch, sub.Pw, sub.Pu)); assert(ef.tw == T(sub.patch, sub.Pu, sub.Pv)); - if(depth == 0) { - dispatch(sub, ef); - return; - } - - if(ef.tu == DSPLIT_NON_UNIFORM) { - /* partition edges */ - TriangleDice::EdgeFactors ef0, ef1; - float2 Psplit; - - partition_edge(sub.patch, - &Psplit, &ef1.tu, &ef0.tu, sub.Pv, sub.Pw, ef.tu); - - /* split */ - int tsplit = T(sub.patch, sub.Pu, Psplit); - ef0.tv = ef.tv; - ef0.tw = tsplit; - - ef1.tv = tsplit; - ef1.tw = ef.tw; + 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 */ - /* create subpatches */ - TriangleDice::SubPatch sub0 = {sub.patch, sub.Pu, Psplit, sub.Pw}; - TriangleDice::SubPatch sub1 = {sub.patch, sub.Pu, sub.Pv, Psplit}; + /* partition edges */ + QuadDice::EdgeFactors ef0, ef1, ef2; + float2 Pu, Pv, Pw, Pcenter; - split(sub0, ef0, depth+1); - split(sub1, ef1, depth+1); - } - else if(ef.tv == DSPLIT_NON_UNIFORM) { - /* partition edges */ - TriangleDice::EdgeFactors ef0, ef1; - float2 Psplit; + 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); - partition_edge(sub.patch, - &Psplit, &ef1.tu, &ef0.tu, sub.Pw, sub.Pu, ef.tv); + /* split */ + int tsplit01 = T(sub.patch, Pv, Pcenter); + int tsplit12 = T(sub.patch, Pu, Pcenter); + int tsplit20 = T(sub.patch, Pw, Pcenter); - /* split */ - int tsplit = T(sub.patch, sub.Pv, Psplit); - ef0.tv = ef.tw; - ef0.tw = tsplit; + ef0.tu1 = tsplit01; + ef0.tv1 = tsplit20; - ef1.tv = tsplit; - ef1.tw = ef.tu; + ef1.tu1 = tsplit12; + ef1.tv1 = tsplit01; - /* create subpatches */ - TriangleDice::SubPatch sub0 = {sub.patch, sub.Pv, Psplit, sub.Pu}; - TriangleDice::SubPatch sub1 = {sub.patch, sub.Pv, sub.Pw, Psplit}; + ef2.tu1 = tsplit20; + ef2.tv1 = tsplit12; - split(sub0, ef0, depth+1); - split(sub1, ef1, depth+1); - } - else if(ef.tw == DSPLIT_NON_UNIFORM) { - /* partition edges */ - TriangleDice::EdgeFactors ef0, ef1; - float2 Psplit; + /* 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}; - partition_edge(sub.patch, - &Psplit, &ef1.tu, &ef0.tu, sub.Pu, sub.Pv, ef.tw); + split(sub0, ef0, depth+1); + split(sub1, ef1, depth+1); + split(sub2, ef2, depth+1); - /* split */ - int tsplit = T(sub.patch, sub.Pw, Psplit); - ef0.tv = ef.tu; - ef0.tw = tsplit; - - ef1.tv = tsplit; - ef1.tw = ef.tv; - - /* create subpatches */ - TriangleDice::SubPatch sub0 = {sub.patch, sub.Pw, Psplit, sub.Pv}; - TriangleDice::SubPatch sub1 = {sub.patch, sub.Pw, sub.Pu, Psplit}; - - split(sub0, ef0, depth+1); - split(sub1, ef1, depth+1); + break; + } + default: { + /* all edges uniform, no splitting needed */ + dispatch(sub, ef); + break; + } } - else - dispatch(sub, ef); } void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int depth) @@ -303,10 +283,6 @@ void DiagSplit::split_triangle(Patch *patch) TriangleDice::SubPatch& sub = subpatches_triangle[i]; TriangleDice::EdgeFactors& ef = edgefactors_triangle[i]; - ef.tu = 4; - ef.tv = 4; - ef.tw = 4; - ef.tu = max(ef.tu, 1); ef.tv = max(ef.tv, 1); ef.tw = max(ef.tw, 1); @@ -316,6 +292,24 @@ void DiagSplit::split_triangle(Patch *patch) 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) -- cgit v1.2.3