diff options
-rw-r--r-- | intern/cycles/blender/addon/properties.py | 4 | ||||
-rw-r--r-- | intern/cycles/blender/blender_camera.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 10 | ||||
-rw-r--r-- | intern/cycles/render/camera.cpp | 40 | ||||
-rw-r--r-- | intern/cycles/render/camera.h | 8 | ||||
-rw-r--r-- | intern/cycles/subd/subd_dice.cpp | 5 | ||||
-rw-r--r-- | intern/cycles/subd/subd_dice.h | 1 | ||||
-rw-r--r-- | intern/cycles/subd/subd_split.cpp | 54 | ||||
-rw-r--r-- | intern/cycles/subd/subd_split.h | 2 |
9 files changed, 117 insertions, 13 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 01aa619b306..3b5755e8062 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -938,8 +938,8 @@ class CyclesMeshSettings(bpy.types.PropertyGroup): ) cls.dicing_rate = FloatProperty( name="Dicing Rate", - description="", - min=0.001, max=1000.0, + description="Size of a micropolygon in pixels", + min=0.1, max=1000.0, default=1.0, ) diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 5bc9dfc7904..6b459ae575f 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -360,6 +360,12 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int blender_camera_viewplane(bcam, width, height, &cam->viewplane, &aspectratio, &sensor_size); + cam->width = bcam->full_width; + cam->height = bcam->full_height; + + cam->full_width = width; + cam->full_height = height; + /* panorama sensor */ if(bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) { float fit_xratio = (float)bcam->full_width*bcam->pixelaspect.x; diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 9eb4626eb3c..48c14a34aad 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -18,6 +18,7 @@ #include "mesh.h" #include "object.h" #include "scene.h" +#include "camera.h" #include "blender_sync.h" #include "blender_session.h" @@ -655,6 +656,7 @@ static void create_mesh(Scene *scene, static void create_subd_mesh(Scene *scene, Mesh *mesh, + BL::Object b_ob, BL::Mesh& b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders) @@ -691,8 +693,10 @@ static void create_subd_mesh(Scene *scene, SubdParams sdparams(mesh, used_shaders[0], true, need_ptex); sdparams.dicing_rate = RNA_float_get(cmesh, "dicing_rate"); - //scene->camera->update(); - //sdparams.camera = scene->camera; + + scene->camera->update(); + sdparams.camera = scene->camera; + sdparams.objecttoworld = get_transform(b_ob.matrix_world()); /* tesselate */ DiagSplit dsplit(sdparams); @@ -805,7 +809,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, if(b_mesh) { if(render_layer.use_surfaces && !hide_tris) { if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision")) - create_subd_mesh(scene, mesh, b_mesh, &cmesh, used_shaders); + create_subd_mesh(scene, mesh, b_ob, b_mesh, &cmesh, used_shaders); else create_mesh(scene, mesh, b_mesh, used_shaders); diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 0e343822223..028916c1b8f 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -158,12 +158,15 @@ void Camera::update() /* ndc to raster */ Transform ndctoraster = transform_scale(width, height, 1.0f) * bordertofull; + Transform full_ndctoraster = transform_scale(full_width, full_height, 1.0f) * bordertofull; /* raster to screen */ Transform screentondc = fulltoborder * transform_from_viewplane(viewplane); Transform screentoraster = ndctoraster * screentondc; Transform rastertoscreen = transform_inverse(screentoraster); + Transform full_screentoraster = full_ndctoraster * screentondc; + Transform full_rastertoscreen = transform_inverse(full_screentoraster); /* screen to camera */ Transform cameratoscreen; @@ -177,6 +180,7 @@ void Camera::update() Transform screentocamera = transform_inverse(cameratoscreen); rastertocamera = screentocamera * rastertoscreen; + Transform full_rastertocamera = screentocamera * full_rastertoscreen; cameratoraster = screentoraster * cameratoscreen; cameratoworld = matrix; @@ -196,12 +200,18 @@ void Camera::update() if(type == CAMERA_ORTHOGRAPHIC) { dx = transform_direction(&rastertocamera, make_float3(1, 0, 0)); dy = transform_direction(&rastertocamera, make_float3(0, 1, 0)); + full_dx = transform_direction(&full_rastertocamera, make_float3(1, 0, 0)); + full_dy = transform_direction(&full_rastertocamera, make_float3(0, 1, 0)); } else if(type == CAMERA_PERSPECTIVE) { dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) - transform_perspective(&rastertocamera, make_float3(0, 0, 0)); dy = transform_perspective(&rastertocamera, make_float3(0, 1, 0)) - transform_perspective(&rastertocamera, make_float3(0, 0, 0)); + full_dx = transform_perspective(&full_rastertocamera, make_float3(1, 0, 0)) - + transform_perspective(&full_rastertocamera, make_float3(0, 0, 0)); + full_dy = transform_perspective(&full_rastertocamera, make_float3(0, 1, 0)) - + transform_perspective(&full_rastertocamera, make_float3(0, 0, 0)); } else { dx = make_float3(0.0f, 0.0f, 0.0f); @@ -210,6 +220,8 @@ void Camera::update() dx = transform_direction(&cameratoworld, dx); dy = transform_direction(&cameratoworld, dy); + full_dx = transform_direction(&cameratoworld, full_dx); + full_dy = transform_direction(&cameratoworld, full_dy); /* TODO(sergey): Support other types of camera. */ if(type == CAMERA_PERSPECTIVE) { @@ -539,4 +551,32 @@ BoundBox Camera::viewplane_bounds_get() return bounds; } +float Camera::world_to_raster_size(float3 P) +{ + if(type == CAMERA_ORTHOGRAPHIC) { + return min(len(full_dx), len(full_dy)); + } + else if(type == CAMERA_PERSPECTIVE) { + /* Calculate as if point is directly ahead of the camera. */ + float3 raster = make_float3(0.5f*width, 0.5f*height, 0.0f); + float3 Pcamera = transform_perspective(&rastertocamera, raster); + + /* dDdx */ + float3 Ddiff = transform_direction(&cameratoworld, Pcamera); + float3 dx = len_squared(full_dx) < len_squared(full_dy) ? full_dx : full_dy; + float3 dDdx = normalize(Ddiff + dx) - normalize(Ddiff); + + /* dPdx */ + float dist = len(transform_point(&worldtocamera, P)); + float3 D = normalize(Ddiff); + return len(dist*dDdx - dot(dist*dDdx, D)*D); + } + else { + // TODO(mai): implement for CAMERA_PANORAMA + assert(!"pixel width calculation for panoramic projection not implemented yet"); + } + + return 1.0f; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 6fbb1dc3bc8..684b4458dfc 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -120,6 +120,8 @@ public: int width, height; int resolution; BoundBox2D viewplane; + /* width and height change during preview, so we need these for calculating dice rates. */ + int full_width, full_height; /* border */ BoundBox2D border; @@ -151,6 +153,9 @@ public: float3 dx; float3 dy; + float3 full_dx; + float3 full_dy; + /* update */ bool need_update; bool need_device_update; @@ -176,6 +181,9 @@ public: /* Public utility functions. */ BoundBox viewplane_bounds_get(); + /* Calculates the width of a pixel at point in world space. */ + float world_to_raster_size(float3 P); + private: /* Private utility functions. */ float3 transform_raster_to_world(float raster_x, float raster_y); diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp index 44bab066dde..301f30c8d95 100644 --- a/intern/cycles/subd/subd_dice.cpp +++ b/intern/cycles/subd/subd_dice.cpp @@ -305,7 +305,12 @@ void QuadDice::dice(SubPatch& sub, EdgeFactors& ef) 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); +#else + 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? diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h index b7e61748779..2b11e4b0bf5 100644 --- a/intern/cycles/subd/subd_dice.h +++ b/intern/cycles/subd/subd_dice.h @@ -41,6 +41,7 @@ struct SubdParams { int split_threshold; float dicing_rate; Camera *camera; + Transform objecttoworld; SubdParams(Mesh *mesh_, int shader_, bool smooth_ = true, bool ptex_ = false) { diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp index df4d451e8eb..095eefeab22 100644 --- a/intern/cycles/subd/subd_split.cpp +++ b/intern/cycles/subd/subd_split.cpp @@ -46,13 +46,13 @@ void DiagSplit::dispatch(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& edgefactors_triangle.push_back(ef); } -float3 DiagSplit::project(Patch *patch, float2 uv) +float3 DiagSplit::to_world(Patch *patch, float2 uv) { float3 P; patch->eval(&P, NULL, NULL, uv.x, uv.y); if(params.camera) - P = transform_perspective(¶ms.camera->worldtoraster, P); + P = transform_point(¶ms.objecttoworld, P); return P; } @@ -66,10 +66,21 @@ int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend) for(int i = 0; i < params.test_steps; i++) { float t = i/(float)(params.test_steps-1); - float3 P = project(patch, Pstart + t*(Pend - Pstart)); + float3 P = to_world(patch, Pstart + t*(Pend - Pstart)); if(i > 0) { - float L = len(P - Plast); + float L; + + 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; + } + Lsum += L; Lmax = max(L, Lmax); } @@ -103,6 +114,16 @@ void DiagSplit::partition_edge(Patch *patch, float2 *P, int *t0, int *t1, float2 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)); @@ -187,7 +208,25 @@ void DiagSplit::split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int depth) { - if((ef.tu0 == DSPLIT_NON_UNIFORM || ef.tu1 == DSPLIT_NON_UNIFORM)) { + 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; + } + + 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); + + if(split_u && split_v) { + split_u = depth % 2; + } + + if(split_u) { /* partition edges */ QuadDice::EdgeFactors ef0, ef1; float2 Pu0, Pu1; @@ -212,7 +251,7 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de split(sub0, ef0, depth+1); split(sub1, ef1, depth+1); } - else if(ef.tv0 == DSPLIT_NON_UNIFORM || ef.tv1 == DSPLIT_NON_UNIFORM) { + else if(split_v) { /* partition edges */ QuadDice::EdgeFactors ef0, ef1; float2 Pv0, Pv1; @@ -237,8 +276,9 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de split(sub0, ef0, depth+1); split(sub1, ef1, depth+1); } - else + else { dispatch(sub, ef); + } } void DiagSplit::split_triangle(Patch *patch) diff --git a/intern/cycles/subd/subd_split.h b/intern/cycles/subd/subd_split.h index df4935ee624..f04c51dedfe 100644 --- a/intern/cycles/subd/subd_split.h +++ b/intern/cycles/subd/subd_split.h @@ -45,7 +45,7 @@ public: DiagSplit(const SubdParams& params); - float3 project(Patch *patch, float2 uv); + 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); |