So I've been messing around with 3D graphics in Java (using lwjgl), and I've hit a bit of a roadblock. I have a heightmap and a cube, and I want to find a way to have the cube rotate to follow the terrain smoothly. At the moment, the cube can rotate freely around the y axis (up is 0,1,0), and it can move directly in the direction it's facing.
Here's my idea: find the plane formed by projecting the bottom corners of the cube onto the terrain. That's the plane that I want to rotate my cube's bottom face into, so I took a cross product with the up vector and the normal vector of that plane. Then I took the angle between the two, and calculated an axis-angle rotation matrix around that plane. I mulitplied the y rotation matrix by that matrix, and used that as my model matrix:
Matrix4 upTransform = Matrix4.createRotateY(yrot);
// calculate plane of cube
Vector3 bl = new Vector3();
bl.x -= SCALE / 2;
bl.z -= SCALE / 2;
bl = upTransform.transform(bl);
bl.y = game.getMap().getY(position.x + bl.x, position.z + bl.z);
Vector3 tl = new Vector3();
tl.x -= SCALE / 2;
tl.z += SCALE / 2;
tl = upTransform.transform(tl);
tl.y = game.getMap().getY(position.x + tl.x, position.z + tl.z);
Vector3 br = new Vector3();
br.x += SCALE / 2;
br.z -= SCALE / 2;
br = upTransform.transform(br);
br.y = game.getMap().getY(position.x + br.x, position.z + br.z);
Vector3 normal = Vector3.cross(Vector3.diff(br, bl),
Vector3.diff(tl, bl)).normalize();
// calculate rotation axis
Vector3 axis = Vector3.cross(normal, up).normalize();
// calculate angle between plane of cube and plane of texture
float angle = (float)Math.acos(Vector3.dot(up, normal));
// calculate rotation
Matrix4 terrainTransform = new Matrix4().setRotate(axis, angle);
Matrix4 rot = Matrix4.multiply(upTransform, terrainTransform);
game.getMap().getY(x, z)
returns the height of the map at the x,z coordinate provided. Vector3.diff(a, b)
returns a - b, and Matrix4.multiply(A, B)
returns A * B.
My issue is that the cube rotates weirdly and has strange shear effects.
Does anyone have comments on my general approach, or on my implementation? I'm really not sure what to do here, as this is pretty much where my linear algebra knowledge reaches its limits.