controlling camera orientation on a sphere surface?

Started by majestik_m00se, January 25, 2012, 11:43:12 PM

Previous topic - Next topic

majestik_m00se

Hi,
I'm trying to get the camera orientation correct such that the player can walk on (or fly over) the surface of a sphere (for simplicity, assume the sphere is centered at JPCT world center 0,0,0). 

For the x and y camera axes, I'd like to just use "mouse look" values to set camera X and Y rotation to change the camera orientation, so that the player can move left/right on the surface of the sphere and look up or down. I'd also like to use a normal vector to the sphere surface to move the camera down until it collides with the sphere for simulating gravity. I've adapted code I've used on flat worlds and tested it out on the sphere, and it seems like it should be fine.

The problem I've been having is adjusting the camera Z-axis orientation so the camera view is always parallel to the surface.  At the moment i don't adjust the Z axis, so it's only correct if you are traveling along a major axis of the sphere, other locations/orientations on the sphere and the camera's Z rotation is wrong and the camera view looks tilted.

I've tried various things, such as taking the current camera position, converting it to polar (alt,az,radius) coordinates, then like adding 1 to the radius (to get a polar coordinate above the camera), and converting it back to cartesian x,y,z.

I've tried using that vector and also the normalized version of that vector as the "up" vector for the camera setOrientation, (something like camera.setOrientation(currentCamDirection,newUp).   But I get bizarre / incorrect results, camera does not point anywhere useful and mouse control of the camera x and y rotation becomes messed up.

I'm a bit of a 3D vector geometry dummy so I'm sure there's a simpler approach or something, suggestions/ideas welcome.

Thanks!
Ed




EgonOlsen

I have some rough ideas, but i'm not sure what is actually given and what needs to be calculated in your case...Do you know the polygon below the current position? Do you know a tangent vector to the sphere at that point?

majestik_m00se

well I don't know how to get a particular sphere polygon below the camera, maybe there is a way to get it seeing I constructed it. I build the sphere just by iterating through the spherical coordinates at a given r and creating verticies/triangles by converting the coords back to cartesian:

for (float alt=-(float)Math.PI; alt < Math.PI; alt = alt+span) {
for (float az=-(float)Math.PI; az < Math.PI; az = az+span) {

surface.addTriangle(p2c(alt,az,varHt(alt,az,r)),
p2c(alt+span,az,r),
p2c(alt,az+span,r);

surface.addTriangle(p2c(alt,az+span,r),
p2c(alt+span,az,r),
p2c(alt+span,az+span,r));
}
}

         protected SimpleVector p2c (float a, float z, float r) {
SimpleVector v = new SimpleVector();
v.x = (float) (r * Math.cos(a) * Math.sin(z));
v.y = (float) (r * Math.sin(a) * Math.sin(z));
v.z = (float) (r * Math.cos(z));
return v;
}


There is probably a way to access the triangles in the mesh later but I'm pretty new to JPct/OpenGL programming, so I am not sure how.

The tangent on the sphere below the camera should in theory be easier to get.  The tangent plane to the point on the sphere should be orthogonal (normal?) to the camera's current position vector, then to select a particular tangent vector on that plane you would somehow take the camera's current direction into account? Some sort of vector addition/subtraction/math there but it's where I am fuzzy.

I assume though that the sphere itself doesn't enter into the calculations for the camera orientation, it can be derived solely based on the camera's position and current orientation.   I was thinking that maybe what I want is to set the camera's XZ plane to something orthogonal to it's position, and then somehow modify the x and y orientation of the camera based on the mouse-look deltas, but leave the z orientation as-is.  No idea how to do that though...


so the summary of what I have/what I need is:

have:
camera current position (== a vector that is normal to the polygon on the sphere below the current position I think)
camera current direction

need:
way to set camera Z orientation based on the above, leaving camera x and y orientation as-is.

Thanks for replying Egon, appreciate the  help.  This board seems pretty active and well run!
Ed


Vi_O

You have to make it in 2 steps :

first, set your sphere object collision type to CHECK_OTHERS and set it's collision listener to whatever you want (for your case, I guess it's the camera)
then, when you want to check the polygon under the camera it's :

World.calcMinDistance(Camera.getPosition(),Camera.getUpVector(), someDistance);

It will fire a CollisionEvent on your listener with the id of your polygon that you can check within the polygon manager of your object.

Something like this :

public void collision(final CollisionEvent ce) {
if (ce.getAlgorithm() == CollisionEvent.ALGORITHM_RAY) {
if (ce.getPolygonIDs().length > 0) {
_normalVector.normalize(ce.getTargets()[0].getPolygonManager()
.getTransformedNormal(ce.getPolygonIDs()[0]));
_tangentVector = _normalVector.calcCross(CROSS_PROD_VECTOR);
}
}
}


Hope it helps...

Edit :
Btw, I think it would be nice if the calcMinDistance would return the normal or id of the polygon reached (or maybe event the CollisionEvent ?) that would make the code easier ^^

EgonOlsen

I think that the collision check should rather be done with an inverted copy of the sphere by using a vector from the center to the camera's position. Because otherwise you would need the camera's up vector, which you actually want to calculate.

Vi_O

Yes, that's right, the vector between the camera and the sphere center would be better. But has it to be a reversed sphere ? Why not just inversing the vector and make the ray origin from the camera ?

BTW, if the field is a sphere, isn't the UpVector just the Ray direction ?

majestik_m00se

yeah I keep getting back to eliminating the sphere from the calculations.  After all, in theory it should be possible to adjust the camera so it's XZ plane is normal to a ray from the origin, whether the sphere is there or not.

since the sphere is at world 0,0,0 (at least currently), isn't the camera position essentially that vector? if so would I be able to use that calcCross() function to get the tangent vector?

also even if this works, how do I 'combine' the result of that with the other orientation information for camera x and y axis that I'm getting from the mouse look routine?

thanks again for helping me on this, i'm learning a lot about vector geometry if nothing else!
Ed

Vi_O

Yeah, calcCross with a constant_vector (that would be, in fact, your sphere/planet axis) should give you a usable tangent vector. (I don't know if you can have a better one with just rotating the normal of 90°)

For the positioning, I've done something like this :


camera.setOrientation(_normalVector, _tangentVector);
camera.rotateAxis(_normalVector, _leftRightAngle);
camera.rotateAxis(_tangentVector, _upDownAngle);


where upDownAngle and leftRightAngle should be your angles gotten by the mouse events (I'm not sure how mouse works as I'm using jpct on android)