I just realized that the output of CUDAVolumetricRender[]
uses (quite marked) perspective, which I do not want (for scientific data representation, it can be very misleading). How do I turn it off? (i.e. make it use an isometric projection)
1 Answer
I believe what you mean when you speak of heavy perspective is the difference between orthogonal and perspective projection.
t = TransformationMatrix[
RescalingTransform[{{-3, 3}, {-3, 3}, {-3, 3}}].RotationTransform[
Pi/5, {1, 0, 0}].RotationTransform[-Pi/4, {0, 0, 1}]];
p = {{1, 0, 0, 0}, {0, 0, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 1}};
GraphicsRow[
With[{lines =
Table[{i, j}, {i, -2, 2, .3}, {j, -2, 2, .3}] /. {x_, y_} :> {x,
y, 0}},
Graphics3D[{Thick, Line[lines], Line[Transpose[lines]], Cuboid[]},
Boxed -> False, ViewMatrix -> #]
] & /@ {Automatic, {t, p}}, ImageSize -> 500]
The difference is rather subtle but when you observe the images closer then you see that in the left (perspective) image the parallel lines of the grid will meet somewhere if they would be longer. In the right image (orthogonal) this is not the case. Furthermore, you see that in the perspective projection distant grid-squares are smaller than the ones in the front. In the right image, all squares which are of the same size.
Let's look at the behavior of Image3D
data = Table[
If[z == 0 && (Mod[x, 8] == 0 || Mod[y, 8] == 0) || (Abs[x] < 8 &&
Abs[y] < 8 && -16 < z < 0), 255, 0], {z, -50, 50}, {y, -50,
50}, {x, -50, 50}];
Image3D[data, "Byte"]
I wouldn't call this heavy perspective. At most it looks similar to the projection of the normal Graphics3D
. Let's see what happens in the cuda renderer
CUDAVolumetricRender[data, Height -> 400, Width -> 400]
This doesn't look so bad at all. Unfortunately, the control of the CUDAVolumetricRender
is implemented differently so I could not get the same viewpoint as in the Image3D
but you could play yourself.
Let's say you really want to change the perspective in the CUDAVolumetricRender
then I'm pretty sure you have to code it yourself. To give you a starting point: I would strongly advise to investigate in the iNewFrame
function at line 663 of volumeRender_kernel.cu
. Looks like this is the function which calculates the final projection:
static void iNewFrame() {
mint ii, jj;
mint pixel;
#define PI 3.14159265f
float theta, psi;
theta = -viewRotation.x*PI/180.0f;
psi = -viewRotation.y*PI/180.0f;
invViewMatrix[0] = cos(psi);
invViewMatrix[4] = sin(theta)*sin(psi);
invViewMatrix[8] = -cos(theta)*sin(psi);
invViewMatrix[1] = 0.0f;
invViewMatrix[5] = cos(theta);
invViewMatrix[9] = sin(theta);
invViewMatrix[2] = sin(psi);
invViewMatrix[6] = -sin(theta)*cos(psi);
invViewMatrix[10]= cos(theta)*cos(psi);
invViewMatrix[3] = -invViewMatrix[0]*viewTranslation.x - \
invViewMatrix[1]*viewTranslation.y - invViewMatrix[2]*viewTranslation.z;
invViewMatrix[7] = -invViewMatrix[4]*viewTranslation.x -\
invViewMatrix[5]*viewTranslation.y - invViewMatrix[6]*viewTranslation.z;
invViewMatrix[11] = -invViewMatrix[8]*viewTranslation.x -\
invViewMatrix[9]*viewTranslation.y - invViewMatrix[10]*viewTranslation.z;
/* ... */
}
$InstallationDirectory <> \ "\\SystemFiles\\Links\\CUDALink\\CSource\\volumeRender_kernel.cu"
$\endgroup$