diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-11-21 05:00:03 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-11-21 05:00:03 +0400 |
commit | fdadfde5c5cc2c5b7255834170b32c4d169bdd42 (patch) | |
tree | f681b0c10cf8341d783586874b1c75f4fd7a73db /intern/cycles/render/camera.cpp | |
parent | f43e75c4d6decffe813f28b083a54158758ff5f9 (diff) |
Fix #33158: motion vector pass wrong in cycles in some scenes, wrong vectors
due to float precision problem in matrix inverse.
Diffstat (limited to 'intern/cycles/render/camera.cpp')
-rw-r--r-- | intern/cycles/render/camera.cpp | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 308ebd0794a..32c273c1248 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -89,13 +89,12 @@ void Camera::update() Transform ndctoraster = transform_scale(width, height, 1.0f); /* raster to screen */ - Transform screentoraster = ndctoraster; - - screentoraster = ndctoraster * + Transform screentondc = transform_scale(1.0f/(viewplane.right - viewplane.left), 1.0f/(viewplane.top - viewplane.bottom), 1.0f) * transform_translate(-viewplane.left, -viewplane.bottom, 0.0f); + Transform screentoraster = ndctoraster * screentondc; Transform rastertoscreen = transform_inverse(screentoraster); /* screen to camera */ @@ -105,14 +104,24 @@ void Camera::update() screentocamera = transform_inverse(transform_orthographic(nearclip, farclip)); else screentocamera = transform_identity(); + + Transform cameratoscreen = transform_inverse(screentocamera); rastertocamera = screentocamera * rastertoscreen; + cameratoraster = screentoraster * cameratoscreen; cameratoworld = matrix; screentoworld = cameratoworld * screentocamera; rastertoworld = cameratoworld * rastertocamera; ndctoworld = rastertoworld * ndctoraster; - worldtoraster = transform_inverse(rastertoworld); + + /* note we recompose matrices instead of taking inverses of the above, this + * is needed to avoid inverting near degenerate matrices that happen due to + * precision issues with large scenes */ + worldtocamera = transform_inverse(matrix); + worldtoscreen = cameratoscreen * worldtocamera; + worldtondc = screentondc * worldtoscreen; + worldtoraster = ndctoraster * worldtondc; /* differentials */ if(type == CAMERA_ORTHOGRAPHIC) { @@ -160,10 +169,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->rastertoworld = rastertoworld; kcam->rastertocamera = rastertocamera; kcam->cameratoworld = cameratoworld; - kcam->worldtoscreen = transform_inverse(screentoworld); + kcam->worldtocamera = worldtocamera; + kcam->worldtoscreen = worldtoscreen; kcam->worldtoraster = worldtoraster; - kcam->worldtondc = transform_inverse(ndctoworld); - kcam->worldtocamera = transform_inverse(cameratoworld); + kcam->worldtondc = worldtondc; /* camera motion */ kcam->have_motion = 0; @@ -181,8 +190,8 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) } else { if(use_motion) { - kcam->motion.pre = transform_inverse(motion.pre * rastertocamera); - kcam->motion.post = transform_inverse(motion.post * rastertocamera); + kcam->motion.pre = cameratoraster * transform_inverse(motion.pre); + kcam->motion.post = cameratoraster * transform_inverse(motion.post); } else { kcam->motion.pre = worldtoraster; |