Original Post
I'm writing a map editor for a simple, old, closed-source 3D game. This game engine has no concept of objects - the maps are only a lot of display lists, textures, and vertices, with collision meshes generated from the display lists at runtime. While my program is capable of grouping vertices and manipulating them as a whole, it ultimately needs to know the world coordinates of each vertex to export for this engine. I'm using a Wii remote to move the cursor, which is a floating cube. Whenever a vertex is inside the cube it can be dragged around or selected. Dragging also moves all selected vertices; additionally, the D-pad can be used to move them one unit at a time. I also hope to implement rotating all selected vertices around the camera's Z axis. Currently the camera is not able to rotate on the Z axis, because last time I tried to do that it nearly drove me batty. I'd love to get that working though. The actual Wiimote and cursor logic is done in Lua, using LuaGL. (The interface itself, if it matters, is GTK+ with GtkGlExt.) A function in the script is called periodically with a pointer to the window, which contains the cursor (and potentially multiple cursors in the future). It reads the Wiimote's IR/motion sensors to see where it's pointing (which gives you a rough distance-from-screen as well) and uses that to update the cursor position. Originally, I was using this code to do the transformations necessary for moving the camera, cursor, and selected vertices. It worked fine for the first two, but if I pointed my camera straight down the Y axis and moved some vertices they'd all just fly off in various directions.
-- Transforms coordinates relative to a point to world coordinates.
-- Inputs:
-- -FromX, FromY, FromZ: Point which coordinates are relative to.
-- -FromRotX, FromRotY: Rotation of this point.
-- -MoveX, MoveY, MoveZ: Distance from point.
-- Returns: X, Y and Z world coords.
-- Notes:
-- If distance is not important you can use 0,0,0 for FromX,FromY,FromZ. This
-- allows you to move something relative to its current position while
-- accounting for camera rotation, e.g:
-- DX, DY, DZ = MoveFromPoint(0, 0, 0, RotX, RotY, DX, DY, DZ)
function MoveFromPoint(FromX, FromY, FromZ, FromRotX, FromRotY, MoveX, MoveY, MoveZ)
--Reset matrices
gl.MatrixMode(gl.PROJECTION)
gl.PushMatrix()
gl.LoadIdentity()
gl.MatrixMode(gl.MODELVIEW)
gl.PushMatrix()
gl.LoadIdentity()
--Rotate
gl.Rotate(FromRotX, 1.0, 0.0, 0.0)
gl.Rotate(FromRotY, 0.0, 1.0, 0.0)
--Get resulting modelview
Matrix = gl.GetArray(gl.MODELVIEW_MATRIX)
--Restore matrices
gl.PopMatrix()
gl.MatrixMode(gl.PROJECTION)
gl.PopMatrix()
gl.MatrixMode(gl.MODELVIEW)
--[[How the 1-based 1-dimensional indices of Matrix map to a 4x4 matrix:
0__1__2__3
0|1 2 3 4
1|5 6 7 8
2|9 10 11 12
3|13 14 15 16 ]]
--Move
local X, Y, Z
X = -FromX + (MoveX * Matrix[1]) + (MoveY * Matrix[2]) + (MoveZ * Matrix[3])
Y = -FromY + (MoveX * Matrix[5]) + (MoveY * Matrix[6]) + (MoveZ * Matrix[7])
Z = -FromZ + (MoveX * Matrix[9]) + (MoveY * Matrix[10]) + (MoveZ * Matrix[11])
return X, Y, Z
end
Someone else suggested this, which looks right to me:function MoveFromPoint(FromX, FromY, FromZ, FromRotX, FromRotY, MoveX, MoveY, MoveZ)
--Assume we're in MODELVIEW matrix mode
gl.PushMatrix()
gl.LoadIdentity()
-- Starting point
gl.Translate(FromX, FromY, FromZ)
-- Apply rotate
gl.Rotate(FromRotX, 1.0, 0.0, 0.0)
gl.Rotate(FromRotY, 0.0, 1.0, 0.0)
-- Apply move
gl.Translate(MoveX, MoveY, MoveZ)
--Get resulting modelview
Matrix = gl.GetArray(gl.MODELVIEW_MATRIX)
--Restore matrix
gl.PopMatrix()
-- The translated point is in the last row of the matrix
return Matrix[12], Matrix[13], Matrix[14]
endHowever, this isn't working properly either - the cursor is not moving with the camera at all; always moving relative to the origin with no rotation. I know very little about 3D/matrix math but it certainly looks like it should work; I can see it translate to the starting point (in this case, the camera position), rotate, and then move the specified distance, which in my mental visualization should do the job exactly. It seems only the last gl.Translate() is actually having any effect. I have verified that the inputs are correct.