Fix #33158: motion vector pass wrong in cycles in some scenes, wrong vectors

due to float precision problem in matrix inverse.
This commit is contained in:
Brecht Van Lommel
2012-11-21 01:00:03 +00:00
parent f43e75c4d6
commit fdadfde5c5
3 changed files with 37 additions and 13 deletions

View File

@@ -60,7 +60,7 @@ public:
return (CUdeviceptr)mem; return (CUdeviceptr)mem;
} }
const char *cuda_error_string(CUresult result) static const char *cuda_error_string(CUresult result)
{ {
switch(result) { switch(result) {
case CUDA_SUCCESS: return "No errors"; case CUDA_SUCCESS: return "No errors";
@@ -915,12 +915,21 @@ Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background)
void device_cuda_info(vector<DeviceInfo>& devices) void device_cuda_info(vector<DeviceInfo>& devices)
{ {
CUresult result;
int count = 0; int count = 0;
if(cuInit(0) != CUDA_SUCCESS) result = cuInit(0);
if(result != CUDA_SUCCESS) {
if(result != CUDA_ERROR_NO_DEVICE)
fprintf(stderr, "CUDA cuInit: %s\n", CUDADevice::cuda_error_string(result));
return; return;
if(cuDeviceGetCount(&count) != CUDA_SUCCESS) }
result = cuDeviceGetCount(&count);
if(result != CUDA_SUCCESS) {
fprintf(stderr, "CUDA cuDeviceGetCount: %s\n", CUDADevice::cuda_error_string(result));
return; return;
}
vector<DeviceInfo> display_devices; vector<DeviceInfo> display_devices;

View File

@@ -89,13 +89,12 @@ void Camera::update()
Transform ndctoraster = transform_scale(width, height, 1.0f); Transform ndctoraster = transform_scale(width, height, 1.0f);
/* raster to screen */ /* raster to screen */
Transform screentoraster = ndctoraster; Transform screentondc =
screentoraster = ndctoraster *
transform_scale(1.0f/(viewplane.right - viewplane.left), transform_scale(1.0f/(viewplane.right - viewplane.left),
1.0f/(viewplane.top - viewplane.bottom), 1.0f) * 1.0f/(viewplane.top - viewplane.bottom), 1.0f) *
transform_translate(-viewplane.left, -viewplane.bottom, 0.0f); transform_translate(-viewplane.left, -viewplane.bottom, 0.0f);
Transform screentoraster = ndctoraster * screentondc;
Transform rastertoscreen = transform_inverse(screentoraster); Transform rastertoscreen = transform_inverse(screentoraster);
/* screen to camera */ /* screen to camera */
@@ -105,14 +104,24 @@ void Camera::update()
screentocamera = transform_inverse(transform_orthographic(nearclip, farclip)); screentocamera = transform_inverse(transform_orthographic(nearclip, farclip));
else else
screentocamera = transform_identity(); screentocamera = transform_identity();
Transform cameratoscreen = transform_inverse(screentocamera);
rastertocamera = screentocamera * rastertoscreen; rastertocamera = screentocamera * rastertoscreen;
cameratoraster = screentoraster * cameratoscreen;
cameratoworld = matrix; cameratoworld = matrix;
screentoworld = cameratoworld * screentocamera; screentoworld = cameratoworld * screentocamera;
rastertoworld = cameratoworld * rastertocamera; rastertoworld = cameratoworld * rastertocamera;
ndctoworld = rastertoworld * ndctoraster; 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 */ /* differentials */
if(type == CAMERA_ORTHOGRAPHIC) { if(type == CAMERA_ORTHOGRAPHIC) {
@@ -160,10 +169,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kcam->rastertoworld = rastertoworld; kcam->rastertoworld = rastertoworld;
kcam->rastertocamera = rastertocamera; kcam->rastertocamera = rastertocamera;
kcam->cameratoworld = cameratoworld; kcam->cameratoworld = cameratoworld;
kcam->worldtoscreen = transform_inverse(screentoworld); kcam->worldtocamera = worldtocamera;
kcam->worldtoscreen = worldtoscreen;
kcam->worldtoraster = worldtoraster; kcam->worldtoraster = worldtoraster;
kcam->worldtondc = transform_inverse(ndctoworld); kcam->worldtondc = worldtondc;
kcam->worldtocamera = transform_inverse(cameratoworld);
/* camera motion */ /* camera motion */
kcam->have_motion = 0; kcam->have_motion = 0;
@@ -181,8 +190,8 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
} }
else { else {
if(use_motion) { if(use_motion) {
kcam->motion.pre = transform_inverse(motion.pre * rastertocamera); kcam->motion.pre = cameratoraster * transform_inverse(motion.pre);
kcam->motion.post = transform_inverse(motion.post * rastertocamera); kcam->motion.post = cameratoraster * transform_inverse(motion.post);
} }
else { else {
kcam->motion.pre = worldtoraster; kcam->motion.pre = worldtoraster;

View File

@@ -82,9 +82,15 @@ public:
Transform screentoworld; Transform screentoworld;
Transform rastertoworld; Transform rastertoworld;
Transform ndctoworld; Transform ndctoworld;
Transform rastertocamera;
Transform cameratoworld; Transform cameratoworld;
Transform worldtoraster; Transform worldtoraster;
Transform worldtoscreen;
Transform worldtondc;
Transform worldtocamera;
Transform rastertocamera;
Transform cameratoraster;;
float3 dx; float3 dx;
float3 dy; float3 dy;