Solved
Add arbitrary point of rotation to a particle rendering routine
Posted on 2010-11-23
I thought I have a decent understanding of graphics pipelines, but apparently do not. I found some code that fairly efficiently renders particles, and I've convinced the code to do a lot of things it didn’t originally do, but I'm missing something. Also, if anyone has ideas of better zones to post this in, please let me know.
First, here's the basic code. Since my problem is in the concepts rather than the programming, I'll leave it as pseudocode:
variables:
fov (field of view),
cx (x value of the center pixel),
cy (y value of the center pixel),
pan (amount to pan the particles),
tilt (amount to tilt the particles),
cameraX (x value of the camera),
cameraY (y value of the camera),
cameraZ (z value of the camera),
screenWidth (the width of the screen to display to)
focalLength = screenWidth / 2 * (cos( fov / 2 ) / sin( fov / 2 ));
matrix.identity();
matrix.appendRotation( pan, Y_AXIS );
matrix.appendRotation( tilt, X_AXIS );
matrix.appendTranslation( cameraX, cameraY, cameraZ );
p00 = matrix.rawData[ 0 ];
p01 = matrix.rawData[ 1 ];
p02 = matrix.rawData[ 2 ];
p10 = matrix.rawData[ 4 ];
p11 = matrix.rawData[ 5 ];
p12 = matrix.rawData[ 6 ];
p20 = matrix.rawData[ 8 ];
p21 = matrix.rawData[ 9 ];
p22 = matrix.rawData[ 10 ];
p30 = matrix.rawData[ 12 ];
p31 = matrix.rawData[ 13 ];
p32 = matrix.rawData[ 14 ];
for each point {x, y, z}:
{
d = focalLength + p32 + x * p02 + y * p12 + z * p22;
if (d < 0)
{
d = -d;
}
w = focalLength / d;
xi = (int)( w * ( x * p00 + y * p10 + z * p20 ) + cx + p30);
if (xi >= screenWidth || xi < 0)
{
continue;
}
yi = (int)( w * ( x * p01 + y * p11 + z * p21 ) + cy + p31);
buffer_index = xi + (yi * screenWidth);
}
This algorithm works perfectly, and looks fantastic. Obviously, the code for the matrix work calls a library. The library's help says that appending a transformation does exactly what it should - it multiplies by putting the new transformation on the left of the existing matrix. I can double check that using the debugger to verify if necessary.
The problem comes about when I try adding in rotation around an arbitrary point. From what I understand, that should be relatively easy - simply change the matrix setup from the above to the following:
matrix.identity();
matrix.appendTranslation( -centerOfRotationX, -centerOfRotationY, -centerOfRotationZ );
matrix.appendRotation( pan, Y_AXIS );
matrix.appendRotation( tilt, X_AXIS );
matrix.appendTranslation( centerOfRotationX, centerOfRotationY, centerOfRotationZ );
matrix.appendTranslation( cameraX, cameraY, cameraZ );
However, this causes problems. As long as I leave the centerOfRotation at the origin, everything is good, as it had been. However, when I set any other center of rotation, my values are off. It seems to be rotating around some other position. The most obvious way that this problem presents itself is that I draw the center of rotation a different color from all the other particles, and as I pan or tilt the particles, the center of rotation moves on the screen. (How much it moves depends on how "zoomed in" to the center I am.) Obviously, the center of rotation should not ever move.
I've tried everything I can think of. I removed the camera translations and added them only into the xi, yi calculations (with an added scale to the matrix manipulations to account for zoom capabilities), and it seemed to be a little bit better, but the problem was still there. I’ve completely removed the camera translations, and the problem still presents itself.
The only thing that seems to help is for me to add a "magic" number to the focalLength. I set my program so I could tweak the number, and see the results, and I can get the movement of the center of rotation to be down to a few pixels in both the x and y direction, but I'm sure that's not right (and I haven't figured out where the "magic" number comes from, other than trial and error). If it helps any, one data point I've had is that when I set the center of rotation to {0, -1, 0}, the only wobble is along the y-axis. When I set to {-1, 0, 0} or {0, 0, -1}, there is wobble in both the x- and y-axis. The wobble seems to be a projection of a circle or occasionally a projection of a figure 8. But maybe none of that matters – it’s effectively altering the zoom, so maybe I’m just zooming out enough to mitigate the issue. (Probably, not, though – that would mean I could simply set the “magic” to a huge number, and the problem would stop evidencing itself, and I haven’t seen that.)
I've been working on this for days and making no progress. Can anyone give me any ideas?
Thanks!