diff options
Diffstat (limited to 'sdl/glframe.c')
-rw-r--r-- | sdl/glframe.c | 302 |
1 files changed, 263 insertions, 39 deletions
diff --git a/sdl/glframe.c b/sdl/glframe.c index b3dc33e..fbf8cd6 100644 --- a/sdl/glframe.c +++ b/sdl/glframe.c @@ -8,25 +8,26 @@ */ #include <GL/glew.h> +#include <stdio.h> #include "glframe.h" void glframe_reset(GLFrame *frame) { - frame->v_location[0] = 0.0f; - frame->v_location[1] = 0.0f; - frame->v_location[2] = 0.0f; - - frame->v_forward[0] = 0.0f; - frame->v_forward[1] = 0.0f; - frame->v_forward[2] = -1.0f; - - frame->v_up[0] = 0.0f; - frame->v_up[1] = 1.0f; - frame->v_up[2] = 0.0f; + frame->v_location[0] = 0.0f; + frame->v_location[1] = 0.0f; + frame->v_location[2] = 0.0f; + + frame->v_forward[0] = 0.0f; + frame->v_forward[1] = 0.0f; + frame->v_forward[2] = -1.0f; + + frame->v_up[0] = 0.0f; + frame->v_up[1] = 1.0f; + frame->v_up[2] = 0.0f; } /* get a 4x4 transformation matrix that describes the camera orientation */ -void glframe_get_camera_orientation(GLFrame *frame, M3DMatrix44f m) +inline void glframe_get_camera_orientation(GLFrame *frame, M3DMatrix44f m) { M3DVector3f x, z; @@ -60,32 +61,26 @@ void glframe_get_camera_orientation(GLFrame *frame, M3DMatrix44f m) } /* perform viewing or modeling transformations */ -/* some of the code is unimplemented */ -void glframe_apply_camera_transform(GLFrame *frame) +inline void glframe_apply_camera_transform(GLFrame *frame, const int rot_only) { - /* XXX: rotation only, should be passed in as a parameter */ - int rot_only = 0; - M3DMatrix44f m; glframe_get_camera_orientation(frame, m); - m3dPrintMatrix44f(m); - glMultMatrixf(m); - /* if rotation only, then do not do the translation */ if (!rot_only) - glTranslatef(-frame->v_location[0], -frame->v_location[1], -frame->v_location[2]); + glTranslatef(-frame->v_location[0], -frame->v_location[1], + -frame->v_location[2]); #if 0 - gluLookAt(v_location[0], v_location[1], v_location[2], - v_location[0] + v_forward[0], - v_location[1] + v_forward[1], - v_location[2] + v_forward[2], - v_up[0], v_up[1], v_up[2]); + gluLookAt(frame->v_location[0], frame->v_location[1], frame->v_location[2], + frame->v_location[0] + frame->v_forward[0], + frame->v_location[1] + frame->v_forward[1], + frame->v_location[2] + frame->v_forward[2], + frame->v_up[0], frame->v_up[1], frame->v_up[2]); #endif } -void glframe_move_forward(GLFrame *frame, float delta) +inline void glframe_move_forward(GLFrame *frame, const float delta) { /* move along direction of front direction */ frame->v_location[0] += frame->v_forward[0] * delta; @@ -93,25 +88,63 @@ void glframe_move_forward(GLFrame *frame, float delta) frame->v_location[2] += frame->v_forward[2] * delta; } -/* rotate left or right */ -void glframe_rotate_local_y(GLFrame *frame, float angle) +/* move up or down */ +inline void glframe_move_up(GLFrame *frame, const float delta) +{ + frame->v_location[0] += frame->v_up[0] * delta; + frame->v_location[1] += frame->v_up[1] * delta; + frame->v_location[2] += frame->v_up[2] * delta; +} + +/* move left or right */ +inline void glframe_move_right(GLFrame *frame, const float delta) +{ + M3DVector3f x; + + m3dCrossProductf(x, frame->v_up, frame->v_forward); + frame->v_location[0] += x[0] * delta; + frame->v_location[1] += x[1] * delta; + frame->v_location[2] += x[2] * delta; +} + +inline void glframe_translate_world(GLFrame *frame, const float x, const float y, + const float z) +{ + frame->v_location[0] += x; + frame->v_location[1] += y; + frame->v_location[2] += z; +} + +inline void glframe_translate_local(GLFrame *frame, const float x, const float y, + const float z) +{ + glframe_move_forward(frame, z); + glframe_move_up(frame, y); + glframe_move_right(frame, x); +} + +/* yaw */ +void glframe_rotate_local_y(GLFrame *frame, const float angle) { M3DMatrix44f rotmat; M3DVector3f newvect; - /* just rotate around the up vector */ /* create a rotation matrix around up vector */ - m3dRotationMatrix44f(rotmat, angle, frame->v_up[0], frame->v_up[1], frame->v_up[2]); + m3dRotationMatrix44f(rotmat, angle, frame->v_up[0], frame->v_up[1], + frame->v_up[2]); /* rotate forward pointing vector (inlined 3x3 transform) */ - newvect[0] = rotmat[0] * frame->v_forward[0] + rotmat[4] * frame->v_forward[1] + rotmat[8] * frame->v_forward[2]; - newvect[1] = rotmat[1] * frame->v_forward[0] + rotmat[5] * frame->v_forward[1] + rotmat[9] * frame->v_forward[2]; - newvect[2] = rotmat[2] * frame->v_forward[0] + rotmat[6] * frame->v_forward[1] + rotmat[10] * frame->v_forward[2]; + newvect[0] = rotmat[0] * frame->v_forward[0] + rotmat[4] * + frame->v_forward[1] + rotmat[8] * frame->v_forward[2]; + newvect[1] = rotmat[1] * frame->v_forward[0] + rotmat[5] * + frame->v_forward[1] + rotmat[9] * frame->v_forward[2]; + newvect[2] = rotmat[2] * frame->v_forward[0] + rotmat[6] * + frame->v_forward[1] + rotmat[10] * frame->v_forward[2]; m3dCopyVector3f(frame->v_forward, newvect); } -/* rotate up or down */ -void glframe_rotate_local_x(GLFrame *frame, float angle) +/* pitch */ +void glframe_rotate_local_x(GLFrame *frame, const float angle) { M3DMatrix44f rotmat; M3DVector3f newfwdvec; @@ -130,9 +163,12 @@ void glframe_rotate_local_x(GLFrame *frame, float angle) m3dRotationMatrix44f(rotmat, angle, x[0], x[1], x[2]); /* rotate forward pointing vector (inlined 3x3 transform) */ - newfwdvec[0] = rotmat[0] * frame->v_forward[0] + rotmat[4] * frame->v_forward[1] + rotmat[8] * frame->v_forward[2]; - newfwdvec[1] = rotmat[1] * frame->v_forward[0] + rotmat[5] * frame->v_forward[1] + rotmat[9] * frame->v_forward[2]; - newfwdvec[2] = rotmat[2] * frame->v_forward[0] + rotmat[6] * frame->v_forward[1] + rotmat[10] * frame->v_forward[2]; + newfwdvec[0] = rotmat[0] * frame->v_forward[0] + rotmat[4] * + frame->v_forward[1] + rotmat[8] * frame->v_forward[2]; + newfwdvec[1] = rotmat[1] * frame->v_forward[0] + rotmat[5] * + frame->v_forward[1] + rotmat[9] * frame->v_forward[2]; + newfwdvec[2] = rotmat[2] * frame->v_forward[0] + rotmat[6] * + frame->v_forward[1] + rotmat[10] * frame->v_forward[2]; /* calculate new up vector */ m3dCrossProductf(newupvec, x, newfwdvec); @@ -141,3 +177,191 @@ void glframe_rotate_local_x(GLFrame *frame, float angle) m3dCopyVector3f(frame->v_up, newupvec); } +/* roll */ +void glframe_rotate_local_z(GLFrame *frame, const float angle) +{ + M3DMatrix44f rotmat; + M3DVector3f newupvec; + + m3dRotationMatrix44f(rotmat, angle, frame->v_forward[0], frame->v_forward[1], + frame->v_forward[2]); + + /* rotate forward pointing vector (inlined 3x3 transform) */ + newupvec[0] = rotmat[0] * frame->v_up[0] + rotmat[4] * frame->v_up[1] + + rotmat[8] * frame->v_up[2]; + newupvec[1] = rotmat[1] * frame->v_up[0] + rotmat[5] * frame->v_up[1] + + rotmat[9] * frame->v_up[2]; + newupvec[2] = rotmat[2] * frame->v_up[0] + rotmat[6] * frame->v_up[1] + + rotmat[10] * frame->v_up[2]; + m3dCopyVector3f(frame->v_up, newupvec); +} + +/* reset axes to make sure they are orthonormal, should be called occasionally + * if the matrix is long-lived and frequently transformed + */ +void gl_frame_normalize(GLFrame *frame) +{ + M3DVector3f x; + + m3dCrossProductf(x, frame->v_up, frame->v_forward); + + /* use result to recalculate forward vector */ + m3dCrossProductf(frame->v_forward, x, frame->v_up); + + /* also check for unit length */ + m3dNormalizeVectorf(frame->v_up); + m3dNormalizeVectorf(frame->v_forward); +} + +/* assemble the matrix */ +void glframe_get_matrix(GLFrame *frame, M3DMatrix44f m, const int rot_only) +{ + M3DVector3f x; + + m3dCrossProductf(x, frame->v_up, frame->v_forward); + + m3dSetMatrixColumn44f(m, x, 0); + m[3] = 0.0f; + + m3dSetMatrixColumn44f(m, frame->v_up, 1); + m[7] = 0.0f; + + m3dSetMatrixColumn44f(m, frame->v_forward, 2); + m[11] = 0.0f; + + if (rot_only) + { + m[12] = 0.0f; + m[13] = 0.0f; + m[14] = 0.0f; + } + else + m3dSetMatrixColumn44f(m, frame->v_location, 3); + + m[15] = 1.0f; +} + +/* position as an object in the scene, this places and orients a coordinate + * frame for other objects besides the camera + */ +void gl_frame_apply_actor_transform(GLFrame *frame) +{ + M3DMatrix44f rotmat; + glframe_get_matrix(frame, rotmat, 0); + + /* apply rotation to the current matrix */ + glMultMatrixf(rotmat); +} + +/* rotate in world coordinates */ +void glframe_rotate_world(GLFrame *frame, const float angle, const float x, + const float y, const float z) +{ + M3DMatrix44f rotmat; + + /* create the rotation matrix */ + m3dRotationMatrix44f(rotmat, angle, x, y, z); + + M3DVector3f newvect; + + newvect[0] = rotmat[0] * frame->v_up[0] + rotmat[4] * + frame->v_up[1] + rotmat[8] * frame->v_up[2]; + newvect[1] = rotmat[1] * frame->v_up[0] + rotmat[5] * + frame->v_up[1] + rotmat[9] * frame->v_up[2]; + newvect[2] = rotmat[2] * frame->v_up[0] + rotmat[6] * + frame->v_up[1] + rotmat[10] * frame->v_up[2]; + + m3dCopyVector3f(frame->v_up, newvect); + + /* transform the forward axis */ + newvect[0] = rotmat[0] * frame->v_forward[0] + rotmat[4] * + frame->v_forward[1] + rotmat[8] * frame->v_forward[2]; + newvect[1] = rotmat[1] * frame->v_forward[0] + rotmat[5] * + frame->v_forward[1] + rotmat[9] * frame->v_forward[2]; + newvect[2] = rotmat[2] * frame->v_forward[0] + rotmat[6] * + frame->v_forward[1] + rotmat[10] * frame->v_forward[2]; + + m3dCopyVector3f(frame->v_forward, newvect); +} + +/* rotate around a local axis */ +void glframe_rotate_local(GLFrame *frame, const float angle, const float x, + const float y, const float z) +{ + M3DVector3f world_vec; + M3DVector3f local_vec; + m3dLoadVector3f(local_vec, x, y, z); + + glframe_local_to_world(frame, local_vec, world_vec); + glframe_rotate_world(frame, angle, world_vec[0], world_vec[1], world_vec[2]); +} + +/* convert coordinate systems, do the transformation represented by the rotation + * and position on the point + */ +void glframe_local_to_world(GLFrame *frame, const M3DVector3f local, M3DVector3f world) +{ + M3DMatrix44f rotmat; + + glframe_get_matrix(frame, rotmat, 1); + + world[0] = rotmat[0] * local[0] + rotmat[4] * local[1] + rotmat[8] * local[2]; + world[1] = rotmat[1] * local[0] + rotmat[5] * local[1] + rotmat[9] * local[2]; + world[2] = rotmat[2] * local[0] + rotmat[6] * local[1] + rotmat[10] * local[2]; + + /* translate the point */ + world[0] += frame->v_location[0]; + world[1] += frame->v_location[1]; + world[2] += frame->v_location[2]; +} + +/* change world coordinates into "local" coordinates */ +void glframe_world_to_local(GLFrame *frame, const M3DVector3f world, M3DVector3f local) +{ + /* translate the origin */ + M3DVector3f new_world; + new_world[0] = world[0] - frame->v_location[0]; + new_world[1] = world[1] - frame->v_location[1]; + new_world[2] = world[2] - frame->v_location[2]; + + /* create the rotation matrix based on the vectors */ + M3DMatrix44f rotmat; + M3DMatrix44f invmat; + glframe_get_matrix(frame, rotmat, 1); + + /* do the rotation based on inverted matrix */ + if (m3dInvertMatrix44f(invmat, rotmat) == -1) + fprintf(stderr, "glframe: m3dInvertMatrix44f() failed\n"); + + local[0] = invmat[0] * new_world[0] + invmat[4] * + new_world[1] + invmat[8] * new_world[2]; + local[1] = invmat[1] * new_world[0] + invmat[5] * + new_world[1] + invmat[9] * new_world[2]; + local[2] = invmat[2] * new_world[0] + invmat[6] * + new_world[1] + invmat[10] * new_world[2]; +} + +/* transform a point by frame matrix */ +void glframe_transform_point(GLFrame *frame, const M3DVector3f src, M3DVector3f dst) +{ + M3DMatrix44f m; + + /* rotate and translate */ + glframe_get_matrix(frame, m, 0); + + dst[0] = m[0] * src[0] + m[4] * src[1] + m[8] * src[2] + m[12]; + dst[1] = m[1] * src[0] + m[5] * src[1] + m[9] * src[2] + m[13]; + dst[2] = m[2] * src[0] + m[6] * src[1] + m[10] * src[2] + m[14]; +} + +/* rotate a vector by frame matrix */ +void glframe_rotate_vector(GLFrame *frame, M3DVector3f src, M3DVector3f dst) +{ + M3DMatrix44f m; + glframe_get_matrix(frame, m, 1); /* rotate only */ + + dst[0] = m[0] * src[0] + m[4] * src[1] + m[8] * src[2]; + dst[1] = m[1] * src[0] + m[5] * src[1] + m[9] * src[2]; + dst[2] = m[2] * src[0] + m[6] * src[1] + m[10] * src[2]; +} + |