diff options
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/addon/properties.py | 7 | ||||
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 2 | ||||
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 7 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.cpp | 16 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.h | 1 | ||||
-rw-r--r-- | intern/cycles/subd/subd_dice.h | 2 | ||||
-rw-r--r-- | intern/cycles/subd/subd_split.cpp | 67 |
7 files changed, 97 insertions, 5 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index d65718f6e19..a5887bb9e2d 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -383,6 +383,13 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=8.0, ) + cls.max_subdivisions = IntProperty( + name="Max Subdivisions", + description="Stop subdividing when this level is reached even if the dice rate would produce finer tessellation", + min=0, max=16, + default=12, + ) + cls.film_exposure = FloatProperty( name="Exposure", description="Image brightness scale", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index afad3b83983..a4e6809390d 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -235,6 +235,8 @@ class CyclesRender_PT_geometery(CyclesButtonsPanel, Panel): sub.label("Subdivision Rate:") sub.prop(cscene, "dicing_rate", text="Render") sub.prop(cscene, "preview_dicing_rate", text="Preview") + sub.separator() + sub.prop(cscene, "max_subdivisions") else: row = layout.row() row.label("Volume Sampling:") diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index ba0ba7892e8..09e27c2282d 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -661,13 +661,15 @@ static void create_subd_mesh(Scene *scene, BL::Mesh& b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders, - float dicing_rate) + float dicing_rate, + int max_subdivisions) { Mesh basemesh; create_mesh(scene, &basemesh, b_mesh, used_shaders); SubdParams sdparams(mesh, used_shaders[0], true, false); sdparams.dicing_rate = max(0.1f, RNA_float_get(cmesh, "dicing_rate") * dicing_rate); + sdparams.max_level = max_subdivisions; scene->camera->update(); sdparams.camera = scene->camera; @@ -784,7 +786,8 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, if(b_mesh) { if(render_layer.use_surfaces && !hide_tris) { if(cmesh.data && experimental && RNA_enum_get(&cmesh, "subdivision_type")) - create_subd_mesh(scene, mesh, b_ob, b_mesh, &cmesh, used_shaders, dicing_rate); + create_subd_mesh(scene, mesh, b_ob, b_mesh, &cmesh, used_shaders, + dicing_rate, max_subdivisions); else create_mesh(scene, mesh, b_mesh, used_shaders); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 803a997ca6e..6291b38d462 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -64,10 +64,12 @@ BlenderSync::BlenderSync(BL::RenderEngine& b_engine, experimental(false), is_cpu(is_cpu), dicing_rate(1.0f), + max_subdivisions(12), progress(progress) { PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate") : RNA_float_get(&cscene, "dicing_rate"); + max_subdivisions = RNA_int_get(&cscene, "max_subdivisions"); } BlenderSync::~BlenderSync() @@ -127,16 +129,24 @@ bool BlenderSync::sync_recalc() } } - bool dicing_rate_changed = false; + bool dicing_prop_changed = false; if(experimental) { PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); + float updated_dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate") : RNA_float_get(&cscene, "dicing_rate"); if(dicing_rate != updated_dicing_rate) { dicing_rate = updated_dicing_rate; - dicing_rate_changed = true; + dicing_prop_changed = true; + } + + int updated_max_subdivisions = RNA_int_get(&cscene, "max_subdivisions"); + + if(max_subdivisions != updated_max_subdivisions) { + max_subdivisions = updated_max_subdivisions; + dicing_prop_changed = true; } } @@ -146,7 +156,7 @@ bool BlenderSync::sync_recalc() if(b_mesh->is_updated()) { mesh_map.set_recalc(*b_mesh); } - else if(dicing_rate_changed) { + else if(dicing_prop_changed) { PointerRNA cmesh = RNA_pointer_get(&b_mesh->ptr, "cycles"); if(RNA_enum_get(&cmesh, "subdivision_type")) diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 4918b7871f8..6ff5326f39f 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -173,6 +173,7 @@ private: bool is_cpu; float dicing_rate; + int max_subdivisions; struct RenderLayerInfo { RenderLayerInfo() diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h index 2b11e4b0bf5..8450a43129e 100644 --- a/intern/cycles/subd/subd_dice.h +++ b/intern/cycles/subd/subd_dice.h @@ -40,6 +40,7 @@ struct SubdParams { int test_steps; int split_threshold; float dicing_rate; + int max_level; Camera *camera; Transform objecttoworld; @@ -53,6 +54,7 @@ struct SubdParams { test_steps = 3; split_threshold = 1; dicing_rate = 0.1f; + max_level = 12; camera = NULL; } diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp index 05f58cf30f7..c4af8cc8c43 100644 --- a/intern/cycles/subd/subd_split.cpp +++ b/intern/cycles/subd/subd_split.cpp @@ -112,6 +112,59 @@ 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; + float2 P01 = sub.P01; + 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)); + 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(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int depth) { if(depth > 32) { @@ -172,6 +225,10 @@ void DiagSplit::split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef 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); @@ -228,6 +285,9 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de 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); } @@ -253,6 +313,9 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de 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); } @@ -275,6 +338,8 @@ void DiagSplit::split_triangle(Patch *patch) 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); @@ -328,6 +393,8 @@ void DiagSplit::split_quad(Patch *patch) 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); + split(sub_split, ef_split); QuadDice dice(params); |