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;
}
const char *cuda_error_string(CUresult result)
static const char *cuda_error_string(CUresult result)
{
switch(result) {
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)
{
CUresult result;
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;
if(cuDeviceGetCount(&count) != CUDA_SUCCESS)
}
result = cuDeviceGetCount(&count);
if(result != CUDA_SUCCESS) {
fprintf(stderr, "CUDA cuDeviceGetCount: %s\n", CUDADevice::cuda_error_string(result));
return;
}
vector<DeviceInfo> display_devices;

View File

@@ -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 */
@@ -106,13 +105,23 @@ void Camera::update()
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;

View File

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