rotation around a sphere

Posted By: Carlos3DGS

rotation around a sphere - 01/12/12 21:57

I am playing around with spheric levels instead of flat ones, and am having a bit of trouble with player movement around the sphere. I have an almost working code, but it gets strange results at the poles (top & bottom).

Placing the player model on the sphere's surface is pretty straightforward. For a sphere with a radius of 500 for example I do the following:
place_on_surface(My_Planet, My_Vehicle, 500);
Code:
void place_on_surface(ENTITY* Planet, ENTITY* Vehicle, var planet_radius)
{
   VECTOR relative_pos;
   var desired_distance;
   
   //get vehicle position relative to the planet center
	vec_diff(relative_pos.x,Vehicle.x,Planet.x);
	
	//set desired distance from radius
	desired_distance=abs(Vehicle.min_z)+planet_radius;
	vec_normalize(relative_pos,desired_distance);
	vec_add(relative_pos,Planet.x);
	
	//place the vehicle on the planet surface
	vec_set(vehicle.x,relative_pos);
}




Now here comes the tricky part I am having trouble with, the player's rotations. So far this attempt is pretty close to what I want. but I get very strange results when the player reaches the top or bottom of the sphere:
rotate_on_surface(My_Planet,My_Vehicle,my_pan);
Code:
void rotate_on_surface(ENTITY* Planet, ENTITY* Vehicle, var desired_pan)
{
	VECTOR relative_pos;
	ANGLE relative_ang;
	ANGLE result_ang;
	
	//get vehicle position relative to the planet center
	vec_diff(relative_pos.x,Vehicle.x,Planet.x);
	
	//tranform relative position to angle
	vec_to_angle(relative_ang.pan,relative_pos.x);
	
	//build new angle
	vec_set(result_ang,vector(0,0,90));
	ang_rotate(result_ang,vector(0,-relative_ang.pan-90,0));
	ang_rotate(result_ang,vector(0,0,-relative_ang.tilt));
	ang_rotate(result_ang,vector(desired_pan,0,0));
	
	//rotate vehicle
	vec_set(vehicle.pan,result_ang);
}



I keep the desired absolute orientation (pan I want the vehicle to look at) in a separate variable so it dosn't get messsed up during the calculations.

The resuts are "almost" what I need, but even separating the pan like I do does not make my vehicle cross the planet surface in a straight line unless it is going straight across the equator... The farther it is from the middle (equator) the more it turns towards the poles (north/south), kind of like traveling in circles orbiting the poles and turning more and more towards them! And when walking directly on the north/south poles it just goes crazy! (it does stay aligned to the planet, but the pan just freaks out)
Movement Code:
Code:
while(1)
{
   c_move(My_Vehicle,vector(key_w-key_s,0,0),nullvector,IGNORE_MODELS);
   my_pan=cycle(my_pan+key_a-key_d,0,360);
   rotate_on_surface(My_Planet,My_Vehicle,my_pan);
   place_on_surface(My_Planet, My_Vehicle, 500);
   wait(1);
}



Has anyone tried something similar before?
Can you spot what I am doing wrong here?
Any advice would be great.

EDIT:
Uploaded an example video to youtube:
http://www.youtube.com/watch?v=KjgIwm75e8U
(keep in mind this is just placeholder art to test the code)

EDIT2:
Added a second video with a free camera further away so its easier to see whats going on with the vehicle withought getting dizzy:
http://www.youtube.com/watch?v=NXkbrUEMpfQ
Posted By: MrGuest

Re: rotation around a sphere - 01/13/12 10:45

joys of [urlhttp://en.wikipedia.org/wiki/Gimbal_lock]Gimbal lock[/url] you'll need to use quaternion instead of euler calculations.

I think there's an ang_for_axis of something like that which will get you moving as expected
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/13/12 13:09

I have been giving it some thought, but am still a little confused...

ang_for_axis(ANGLE* vAng, VECTOR* vAxis, var angle);

The way I understand this function (which is probably wrong) I think the values I would need are as follows?:

vAng=vector(desired_pan,0,0);
vAxsis=N
angle=a

Being "N" a normal vector perpendicular to my vehicle position relative to the planet center?
And "a" being the tilt if my vehicle faced the planet center +90?

Posted By: EvilSOB

Re: rotation around a sphere - 01/13/12 13:55

Heres an IDEA to think on... it may work, it may not.
But seeing as you have a project to test it in, it will be easier for
you to test than it is for me. laugh

Make a new SPHERE_MDL entity (PASSABLE & INVISIBLE) that surrounds the
existing planet, with the same origin point.

Do a c-trace from your Vehicle OUTWARDS to hit the new sphere.
The HIT struct now contains info about that hit, that means that the
HIT.nx,ny,nz contain the NORMAL of a perfect sphere at the point your ship is
touching it...
You may be able to use that normal to calculate your angles.

I suspect something like this...
Code:
...
   vec_set(Vehicle.pan, hit.nx);                     //set to same as captured normal
   vec_rotate(Vehicle.pan, vector(90,90,0));         //rotate vector to pan/tilt/roll orientation (needs tinkering)
   vec_to_angle(Vehicle.pan, Vehicle.pan);           //convert from direction-vector to angle
   ang_add(Vehickle.pan, vector(desired_pan,0,0));   //rotate to desired pan
...

BTW. This calculation does NOT need to be done IN the entity... A temp vector will do..

Best of luck dude... Your in a hairy area...
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/13/12 14:10

Very interesting idea indeed, that should make everything much simpler!

One question though... Does c_trace hit backfaces? Or are they ignored?

EDIT: seems like backfaces are not hit so I made a planet model with inverted normals. At first it was spazzing out, till I set me=vehicle and INGORE_ME in the trace. But I still get very very strange results though.
Posted By: EvilSOB

Re: rotation around a sphere - 01/13/12 15:10

I forgot, c_trace detecting backfaces was phased out AGES ago.. sorry.
[EDIT] A way around this is to reverse the c-trace vectors, ie "c_trace(outside_sphere, vehicle.x, blah)", but who cares now...

But if you got the detection running thats a start.

Importantly, is the planet model PERFECTLY smooth? Otherwise you may get odd behaviour.
Even more odd than when it works RIGHT! Normals are strange little beasties.

So to start getting you to understand normals, we will go a step at a time...
First we will capture the normal, and convert it to an angle.

So if you are getting the normals OK, remember they will need INVERTING as they are
INSIDE faces, and therefore upside-down to what you want. So firstly you need to do this...
Code:
...
   VECTOR temp;
   vec_inverse(vec_set(temp, hit.nx));   //invert direction vector
   vec_to_angle(Vehicle.pan, temp);
...

to get the corrected vector, and force it into the Vehicle.
It may be worth TEMPORARILY increasing the gap between the vehicle and the surface
so when the vehicle performs 'odd' rotations, it wont collide with the surface, and 'disturb' the results.
Or at least make the planet PASSABLE to avoid the above...

While doing this test, put a DEBUG_VAR display showing the pan/tilt/roll of the vehicle.

Then have a fly around the planet, observing the vehicle rotations, and try to figure out the pattern.
(YES, I know. The vehicle's x-axis will currently be pointing UPWARD from the core, thats expected at this point)

HINT: Keep a CLOSE eye on the ROLL value when approaching the poles,
or when the pan or tilt values suddenly "jump' ...


I'll be waiting...


Posted By: Carlos3DGS

Re: rotation around a sphere - 01/13/12 15:50

I was working on another version and a new video while you posted.

I ended up not using a second sphere and just using the original planet tracing from out to the planet core.

This is the surrent code:
Code:
VECTOR start_trace;
VECTOR Temp_Vec;

//get the start coordinates for the trace
vec_set(start_trace,Vehicle.x);
vec_sub(start_trace,Planet.x);
vec_normalize(start_trace,vec_length(start_trace)*2);
vec_add(start_trace,Planet.x);

//perform the trace ignoring the vehicle
me=Vehicle;
c_trace(start_trace, Planet.x,IGNORE_ME);

//do angle calculations in a temporary vector
vec_set(Temp_Vec, hit.nx);                     //set to same as captured normal
   vec_rotate(Temp_Vec, vector(90,90,0));         //rotate vector to pan/tilt/roll orientation (needs tinkering)
   vec_to_angle(Temp_Vec, Temp_Vec);           //convert from direction-vector to angle
   ang_add(Temp_Vec, vector(desired_pan,0,0));   //rotate to desired pan

//place results into the vehicle
vec_set(vehicle.pan,Temp_Vec);




And these are the results:
http://www.youtube.com/watch?v=tqJ8LLydSj4

Working on a version that will show pan/tilt/roll on screen to try to understand what is happening...
Posted By: JibbSmart

Re: rotation around a sphere - 01/13/12 16:17

Okay, here's a couple things.
First, if your level is always going to be perfectly spherical (or you always want to treat it as perfectly spherical), then the surface normal is just the player position relative to the sphere's origin.

Secondly, I wouldn't have an "absolute pan", since that just won't work rotating with arbitrary axes. This is explained a little bit in this thread that deals with a very similar problem, which is ultimately resolved using this function.

I hope these are helpful.

Jibb
Posted By: EvilSOB

Re: rotation around a sphere - 01/13/12 16:22

Looking at this video, you still have some code somewhere that is rotating the vehicle.

This is making the testing look off. If you CANT disable this other panning, then
create another 'ghost' vehicle entity that gets its x/y/z from the 'real'
vehicle
(but a bit further out from the core), but ONLY gets its pan/ilt/roll from the above code...



You say youre NOT using a second sphere... thats cool FOR NOW.
I see the one in the video IS smooth, but will that always be the case?
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/13/12 17:10

For the finished version of this... Nope, the planets will not be perfect spheres. I currrently disabled my "random planet generator" code for testing while I learn how to get these rotations right. Planets will look more like this:
http://www.youtube.com/watch?v=m8meN7xX7-Y
random planet generator (and shader) working in this video.

But for vehicle angles I will probably not take into account the real surface normals. Just the distance from center and treat it as a sphere (seems waay to commplicated for what I need).
I might consider it though, but after I get how this movement works into my brain for simple spheres.

Off-topic:
The planet gerator works fine but the shader causes random crashes. After getting this movement thing to work I was going to send you a pm about the shader since it is based on the "random terrain shader" we worked on.


Back on topic:
Jibb I read those two threads but am still a little confused with the function...
alignToVec(ANGLE* entAng, VECTOR* vec, VECTOR* axis, var factor)

as an example with my current problem, what data would I put into that function?

entAng= vector(desired_pan,0,0) ?
vec= vec_sub(vehicle.x,planet.x) ?
axis= vector(0,0,1) ?
factor= 1 ?

Did I understand this correctly?
Posted By: JibbSmart

Re: rotation around a sphere - 01/13/12 17:24

Almost -- entAng needs to be the player's actual angle (and not just a representation of it), since that will get directly changed by the function. That is:
alignToVec(my.pan, vec, vector(0, 0, 1), 1); // you got vec right, as well

Also, to smooth things out, you might want to have the last parameter be time_step.

What this will do is align your model to the normal by its local z axis by changing its orientation as little as possible -- so really, whatever your model's previous angle was will determine the direction it is ultimately facing. Then you can use ang_add/ang_rotate (I always forget which one) afterwards if you want to change the ship's pan relative to its current orientation.

It'll make more sense as you put it into practice and fiddle with it, I think.

The planet generator looks really cool grin
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/13/12 19:24

Thanks for the compliment on the random planet generator! It took alot of work to figure out all the math for that, I still consider it (and the shader) a work in progress but it's pretty close to what I want.

I got the rotations to work with your function, thanks alot!

Only one problem though... Now I somehow managed to mess up the positioning of my vehicle! This is starting to turn into a huge headache (literally).

The function:
Code:
void align_to_surface(ENTITY* Planet, ENTITY* Vehicle)
{
   VECTOR start_trace;
	VECTOR Temp_Vec;
	
	
	//get the surface position
   vec_set(start_trace,Vehicle.x);
	vec_sub(start_trace,Planet.x);
	vec_normalize(start_trace,vec_length(start_trace)*2);
	vec_add(start_trace,Planet.x);
	me=Vehicle;
	c_trace(start_trace, Planet.x,IGNORE_ME);
	
	//place vehicle on surface 
	//(taking into account vehicle min_z)
	vec_set(Temp_Vec,hit.x);
	vec_sub(Temp_Vec,Planet.x);
	vec_normalize(Temp_Vec,vec_length(Temp_Vec.x)-Vehicle.min_z);
	vec_add(Temp_Vec,Planet.x);
	vec_set(Vehicle.x,Temp_Vec);
	
	//rotate towards planet core
	vec_sub(Temp_Vec,Planet.x);
	alignToVec(Vehicle.pan, Temp_Vec, vector(0, 0, 1), 1); 
}



JibbSmart's AlignToVec funtion:
Click to reveal..
Code:
function alignToVec(ANGLE* entAng, VECTOR* vec, VECTOR* axis, var factor) {
	vec_rotate(axis, entAng);
	vec_normalize(axis, 1);
	vec_normalize(vec, 1);
	VECTOR rotAxis;
	vec_cross(rotAxis, vec, axis);
	var angle = -acos((float)vec_dot(axis, vec)) * factor * vec_length(rotAxis);
	ANGLE rotAngle;
	ang_for_axis(rotAngle, rotAxis, angle);
	ang_add(entAng, rotAngle);
}



My movement code:
Code:
c_move(vehicle,vector(key_w-key_s,0,0),nullvector,IGNORE_MODELS);
ang_rotate(vehicle.pan,vector(key_a-key_d,0,0));
align_to_surface(Planet, Vehicle);



I know its ugly withought any time_step in there, but its just for testing till I get it to work properly.

This is the result:
http://www.youtube.com/watch?v=1Y2uTAf8twI

EDIT:
it looks as if it was detecting the planet as a box or something... But I have set it's POLYGON flag, I swear!
set(Planet,POLYGON);
Posted By: JibbSmart

Re: rotation around a sphere - 01/13/12 20:26

Weird. I would debug the trace visually -- I'd draw_point3d at the hit position, and use DEBUG_VAR to show vec_length(Temp_Vec) before and after you use vec_normalize.
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/13/12 21:07

debugging function:
Code:
void align_to_surface(ENTITY* Planet, ENTITY* Vehicle)
{
        VECTOR start_trace;
	VECTOR Temp_Vec;
	
	
	//get the surface position
        vec_set(start_trace,Vehicle.x);
	vec_sub(start_trace,Planet.x);
	      
	vec_normalize(start_trace,vec_length(start_trace)*2);
	vec_add(start_trace,Planet.x);
	me=Vehicle;
	c_trace(start_trace, Planet.x,IGNORE_ME);
	
	      //DEBUGGING
	      draw_line3d(start_trace,NULL,100);
	      draw_line3d(start_trace,COLOR_RED,100);
	      draw_line3d(Planet.x,COLOR_RED,100);
	      draw_point3d(hit.x,COLOR_RED,100,16);
	
	//place vehicle on surface 
	//(taking into account vehicle min_z)
	vec_set(Temp_Vec,hit.x);
	vec_sub(Temp_Vec,Planet.x);

	      //DEBUGGING
	      DEBUG_VAR(vec_length(Temp_Vec), 100);

	vec_normalize(Temp_Vec,vec_length(Temp_Vec.x)-Vehicle.min_z);

	      //DEBUGGING
	      DEBUG_VAR(vec_length(Temp_Vec), 120);

	vec_add(Temp_Vec,Planet.x);
	vec_set(Vehicle.x,Temp_Vec);
	
	//rotate towards planet core
	vec_sub(Temp_Vec,Planet.x);
	alignToVec(Vehicle.pan, Temp_Vec, vector(0, 0, 1), 1); 
}



RESULT:
http://www.youtube.com/watch?v=r3j5MKgXWR8
Posted By: msmith2468

Re: rotation around a sphere - 01/13/12 21:08

I got it working.
It was doing the same thing as yours did in your video but when i made the planet use its polygon it worked perfect.

Double check your planet.
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/13/12 21:11

checked it... planet is using polygon cry

EDIT:
I am soooooooooooooo stuuuuuupid!!!
Since I am not using my planet generator code... you cannot see the water (another translucent sphere the same size as planet) so I forgot it was even there! I set polygon flag for water too and it works now... Time to go buy another brain!

Anyway thanks alot for your comment, you got me thinking in the right direction when i went to double check planet's polygon flag!

Now I'm off to check the results with my randomly generated planets, and mabe i will consider making the code take into account surface normals...
Posted By: msmith2468

Re: rotation around a sphere - 01/13/12 21:32

Here is a download link to all my files in a zipped folder.
It should run as is.

http://www.mikeswickedgames.com/Planet%20movement.zip
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/14/12 00:07

Got it working also with non-spheric surface normals. Wasn't hard at all, I just had to change Temp_Vec for hit.nx

Anyway, I just thought you guys might want to see it working after helping me out:
http://www.youtube.com/watch?v=DJJD1jZ2Ob0

Two new objectives (but they will have to wait till monday):

1-Making it walk to places (no pathfinding or anything complicated, just simple "look towards objective - move forward"), either to another object on the planet surface or to a mouse click on the surface...
2-Fixing those random crashes that the shader produces (I'm pretty sure its the shader, not assigning the material stops the random crashes)
Posted By: JibbSmart

Re: rotation around a sphere - 01/14/12 01:18

Great work laugh It looks good!

1- Shouldn't be too hard. If the object is aligned according to its spherical co-ordinates rather than the normal beneath it, you can just translate the destination into a position relative to the object's orientation (vec_rotateback) and rotate the object's pan (relative to its z axis) towards that point. Since you use actual surface normals, we can set up a temporary angle that uses the spherical co-ordinates instead.

2- A shader shouldn't be able to crash a program. Divide by zero and square root of a negative number, the obvious suspects in traditional programming, don't cause crashes in shaders in my experience -- we just get zero instead. It could be a driver problem. Then again, it could be both -- perhaps the driver's supposed to not crash, but it does, and perhaps the code that triggers it is undesirable anyway.

Anyway, that's just food for thought. Enjoy your weekend and forget about this for now.
Posted By: msmith2468

Re: rotation around a sphere - 01/14/12 03:08

It looks Very good! Well done.
Your project looks very interesting id like to see how it progresses. keep us updated.
Posted By: EvilSOB

Re: rotation around a sphere - 01/14/12 07:37

Excellent... looking really good.

Question though... HOW did you get it going in the end?

Or did you re-build your "rotate_on_surface" function?

[EDIT] HERE is MY version of the code MrSmith posted.
Its BASICALLY the same, Ive just compacted the code a lot, and done some minor bug-fixes,
AND Ive made the functions more 'controllable' with added parameters...
Enjoy... Hopefully someone may find some useful tidbits in there of use or interest...


Posted By: Carlos3DGS

Re: rotation around a sphere - 01/14/12 13:29

The link dosn't work.

Oh and I barely had to change the code to get it to work, just a couple tweaks and also setting the water POLYGON flag.

Code:
void align_to_surface(ENTITY* Planet, ENTITY* Vehicle)
{
   VECTOR start_trace;
	VECTOR Temp_Vec;
	
	
	//get the surface position
   vec_set(start_trace,Vehicle.x);
	vec_sub(start_trace,Planet.x);
	      
	vec_normalize(start_trace,vec_length(start_trace)*2);
	vec_add(start_trace,Planet.x);
	me=Vehicle;
	c_trace(start_trace, Planet.x,IGNORE_ME|IGNORE_PASSABLE);
	
	      //DEBUGGING
	      //draw_line3d(start_trace,NULL,100);
	      //draw_line3d(start_trace,COLOR_RED,100);
	      //draw_line3d(Planet.x,COLOR_RED,100);
	      //draw_point3d(hit.x,COLOR_RED,100,16);
	
	//place vehicle on surface 
	//(taking into account vehicle min_z)
	vec_set(Temp_Vec,hit.x);
	vec_sub(Temp_Vec,Planet.x);
	      //DEBUGGING
	      DEBUG_VAR(vec_length(Temp_Vec), 100);
	vec_normalize(Temp_Vec,vec_length(Temp_Vec.x)-Vehicle.min_z);
	      //DEBUGGING
	      DEBUG_VAR(vec_length(Temp_Vec), 120);
	vec_add(Temp_Vec,Planet.x);
	vec_set(Vehicle.x,Temp_Vec);
	
	//rotate towards planet core
	vec_sub(Temp_Vec,Planet.x);
	alignToVec(Vehicle.pan, hit.nx, vector(0, 0, 1), 1); 
	alignToVec(Vehicle.pan, hit.nx, vector(0, 0, 1), 1); 
	alignToVec(Vehicle.pan, hit.nx, vector(0, 0, 1), 1); 
	alignToVec(Vehicle.pan, hit.nx, vector(0, 0, 1), 1); 
	alignToVec(Vehicle.pan, hit.nx, vector(0, 0, 1), 1); 
}


There are several alignToVec calls at the end to speed up the rotation smooth a little. Don't know if there is a better way to do it... And on monday I will also take a look at the code and try to optimize the calculations and simplify my code.

and here is the movement code:
Code:
c_move(vehicle,vector(key_w-key_s,0,0),nullvector,IGNORE_MODELS);
		ang_rotate(vehicle.pan,vector(key_a-key_d,0,0));
		align_to_surface(Planet[1], vehicle);


I'm also thinking of tweaking the movement code. that c_move bothers me since I'm not really going to use collision detection (hence the IGNORE_MODELS) for the "planet overview" in my game, I just use c_move to get the movement forward/back aligned with the vehicle orientation.
So I might think of doing those calculations myself in a custom function to get it working faster than a standard c_move.
Posted By: EvilSOB

Re: rotation around a sphere - 01/14/12 14:19

THIS link is fixed... damned typos!

Yeah, the bugs I fixed WERE very minor ones.

Is it REALLY worth replacing c_move with non-engine calculations?
Is cpu-usage THAT critical? I cant see custom-coding that has no collisions
actually ending up much faster.

Take a look at my code, (now that you can), as I have already done some optimising...
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/14/12 15:06

I guess removing c_move is not really important, it was just a thought. But its probably not worth the trouble.

I took a look at you code and was wondering if embedding instructions into eachother improves speed or not.
If they don't, even though your code looks alot more compact it has the same count of instructions:
Code:
ITEM		MY	YOURS
vec_set		3	3
vec_sub		3	3
vec_add		2	2
vec_length	2	2
vec_normalize	2	2
c_trace		1	1
*		1	1
-		1	0
+		0	1
local_vars	2	1
external_vars	2	3


Note: I didn't take into account the extra if and return your function has, since I think its a nice safeguard and will incorporate that into mine (and didn't count the extra debug instructions in mine since they will be removed).

I'm still thinking how to reduce the amount of instructions needed though (It may not be that critical, but I'm usually very strict with my code's speed and efficiency), function by function little ineficient code can end up acumulating to something noticeable. I am used to first getting things to work and then revising it's speed efficiency (even where aparently not necessary), but it will have to wait, have to see my gf now, and go to my father's birthday later tonight.
Posted By: WretchedSid

Re: rotation around a sphere - 01/14/12 15:25

The only thing that really is cost intensive is the c_trace, everything else doesn't really matter. And even the c_trace() won't have any noticeable performance impact unless you do it a thousand times/frame.
Posted By: EvilSOB

Re: rotation around a sphere - 01/14/12 15:49

I am stating the following MOSTLY from experiences, rather than written facts.

I BELIEVE the embedded commands give a small improvement.
And some of them more than others. I do the embedding as a personal
preference towards compact code more than speed.

I'll use the example of 'vec_normalize' to SUGGEST there is some speed
improvements to be gained by embedding.
'vec_normalize' CAN be embeddind in other commands, but you will see that
I never do so. That is because OCCASIONAL compiles will generate a
'empty pointer' error at run-time at the 'output' time of the vec_normalize.
I suspect that the embedding is 'out running' the commands ability to update the data.
Whereas exactly the same code JUST with the 'vec_normalize' NON-embedded works fine.
This SUGGESTS that the embedded code is running faster.
I have never actually tried any time-elapsed tests...

But I know for a FACT that creating/destroying LOCAL vars does slow things down.
Thats why you will often examples of my code around that use STATIC local vars.
These only get created once, but CAN cause problems if more that one instance of
that function is running, cause they will "share" thar var... AND that var will
remain set at the SAME value it was at when the last instance of the function ended.
And accssing GLOBAL vars is no faster OR slower than local ones.


If you truly want to scorch you brain with optimising at the expence of readability,
look at ALL the VEC_??? functions being used. If you check the manual, you
will find many of them show the actual CORE algorithms they use.
Replace those VEC_??? calls with its intrinsic algorithm and you WILL gain speed.
Also, in some situations you may see you dont actually need the WHOLE algorithm,
and so you can leave some off. More time saved.
BUT, some of the VEC_??? commands do have some error-protection you will lose,
and others have data type-casting 'adptatability' that you will lose.
And none of this is mentioned in the manual, so its hard to say what you are
losing, and you aint going to be gaining THAT much...
Oh... and the 'readability' of you script will go to hell, AND you will find it
hard going to find people willing to help debug something like that... let alone able...

And another thing to think about.. Youve spent DAYS generating the code,
and spent WEEKS debugging the bastard...
And NOW you want to take your pretty tested code and butcher it into an
un-recognisable mess that will need de-bugging ALL OVER AGAIN!! And this time
most of the code will be un-intelligble algebraic gibberish.
And all to gain 3 or 4 FPS?? At best?? Nuts! IMHO.

But ... each to their own.
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/15/12 11:24

Thanks for the info and tips! I'll start to work on the next part (at least for a couple hours I have free today).

Originally Posted By: Carlos3DGS
Making it walk to places (no fancy pathfinding or anything complicated, just simple "look towards objective - move forward"), either to another object on the planet surface or to a mouse click on the surface...


Originally Posted By: JibbSmart
Shouldn't be too hard. If the object is aligned according to its spherical co-ordinates rather than the normal beneath it, you can just translate the destination into a position relative to the object's orientation (vec_rotateback) and rotate the object's pan (relative to its z axis) towards that point. Since you use actual surface normals, we can set up a temporary angle that uses the spherical co-ordinates instead.


I'm kinda confused, so I will try to start planning it all out and see if along the way it all starts to make more sense to me.
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/15/12 14:06

I have been giving it some thought and after several diagrams (more than I would like to admit), I think I have finally understood what you said.

Would it be something like this?:

(p)=point
(V)=vector

I'm still kind of stuck figuring out how to calculate how to rotate it...
-I assume the vector being rotated would be Real_Path=(Destination-Moving_Vehicle).
-And the rotation would be centered around Moving_Vehicle (giving me Temp_Path as the result).
-Then I could calculate Temp_Destination=(Moving_Vehicle+Temp_Path).

But I am still not sure how to calculate by how much I want Real_Path to be rotated.
And I am completely lost about the last step: how to calculate the local pan for Moving_Vehicle looking towards Temp_Destination

EDIT:
I think I got the first part figured out:
Code:
void look_at(ENTITY* Vehicle, VECTOR* Destination, ENTITY* Planet)
{
   VECTOR V_Nrml;
   VECTOR V_Path;
   ANGLE Rotation;
   

   //get our vehicle's normal to the planet
   vec_diff(V_Nrml,Vehicle.x,Planet.x);
   //get the direction to our destination
   vec_diff(V_Path,Destination,Vehicle.x);
   //translate the destination to our plane
   vec_to_angle(Rotation,V_Nrml);
   vec_rotateback(V_Path,Rotation);
   

   //make our vehicle look towards the new path
   //???
}}



Edit2:
Or mabe I'm just stuck cause I have not understood you correctly and am going in the wrong direction...
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/17/12 19:40

I have been stuck on this problem for the last few days and cannot seem to get it working correctly. Any help would be great.

I have gone through various different aproaches to the problem, this is my current one:


Transforming the positions:
-First I take the position of my origin (vehicle to be moved) and calculate the angle I would need to rotate that vector by if I wanted it at the center (north pole).
-then I rotate the destination by that same angle.

Calculating angles:
-In a temporary variable I store the pan our vehicle would have if it was looking at our new destination from the center.
-In another temporary variable transform our vehicle's current angle to what it would have if it was stating straight (aligned to north pole).

Calculating the final result:
-I subtract the pan of our two stored (temporary) angles to get the difference between the two.
-I ang_add() the difference of both pans to our vehicle's angle (to get a pan rotation aligned to it's local axis).

Current code:
Code:
void look_at(ENTITY* Vehicle, VECTOR* Destination, ENTITY* Planet)
{
   VECTOR Dest;
   VECTOR V_Nrml;
   ANGLE V_Ang;
   VECTOR V_Path;
   var Displacement;
   ANGLE T_Ang;

	
   //get our vehicle's normal from the planet core
   vec_diff(V_Nrml,Vehicle.x,Planet.x);
	  
 
   //get vehicle's absolute angle from core
   vec_to_angle(V_Ang,V_Nrml);
   //transform it to angle from the top of our planet
   V_Ang.tilt=90-V_Ang.tilt;

   
   //translate Path
   vec_diff(V_Path,Destination,Planet.x);
   vec_rotate(V_Path,V_Ang);

   
   //get our absolute pan angle towards new path
   vec_to_angle(T_Ang,V_Path);

   
   //get our vehicle's absolute pan angle
   vec_set(V_Ang,Vehicle.pan);
   alignToVec(V_Ang, vector(0, 0, 1), vector(0, 0, 1), 1);

   
   //get the difference in angles
   Displacement=V_Ang.pan-T_Ang.pan;
   //rotate vehicle's local axsis
   ang_rotate(Vehicle.pan,vector(Displacement,0,0));
}



Result:
http://www.youtube.com/watch?v=UUCzsM9d3rg
Posted By: JibbSmart

Re: rotation around a sphere - 01/18/12 03:49

I was thinking something like this:
Code:
void look_at(ENTITY* Vehicle, VECTOR* Destination, ENTITY* Planet)
{
   VECTOR V_Nrml;
   ANGLE V_Ang;
   VECTOR V_Path;

   // copy my angle
   vec_set(V_Ang, Vehicle.pan);
	
   //get our vehicle's normal from the planet core
   vec_diff(V_Nrml, Vehicle.x, Planet.x);

   // orientate temporary angle as if on a perfect sphere
   alignToVec(V_Ang, V_Nrml, vector(0, 0, 1), 1);

   // get destination position relative to the vehicle's orientation
   vec_diff(V_Path, Destination, Vehicle.x);
   vec_rotateback(V_Path, V_Ang);

   // convert to an angle
   vec_to_angle(V_Ang, V_Path);

   // now, V_Ang's pan is our angle
   ang_rotate(Vehicle.pan, vector(V_Ang.pan, 0, 0)); // maybe ang_add?
}

That's kinda what I had in mind. Not really tested, but hopefully the idea comes across.
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/18/12 16:40

Thanks alot! It seems I was closer to the solution on my first attempt than on the latter.

I implemented as-is and it worked great! (excluding some special cases)
http://www.youtube.com/watch?v=cGHNkYPWsJU

The first 1:45 of the video is showing the "pathfinding" working flawlessly.
At 1:45 I start showing the special cases where it dosn't.

Observing this strange behaviour I think I have discovered why it messes up. It seems like it is happening when it reaches the equivalent point, but on the opposite side of the planet. In the video you can observe this not only happens when traveling north-to-south or south-to-north poles, it also happens with any opposite points (West-to-East, NE-to-SW, etc...)

I have designed a function to detect if the point is on the same side of the planet or not (relative to a plane cut oriented by the Origin's normal from the planet core).

Code:
int hemisphere_compare(VECTOR* Origin, VECTOR* Destination, ENTITY* Planet)
{
	VECTOR Plane_Normal;
	VECTOR Point;
	int hemisphere;
	
	//get values relative to planet core
	vec_diff(Plane_Normal,Origin,Planet.x);
	vec_diff(Point,Destination,Planet.x);
	//normalize vectors
	vec_normalize(Plane_Normal,1);
	vec_normalize(Point,1);
	
	//calculate hemisphere of Destination
	//relative to a plane-cut oriented by Origin's normal
	hemisphere=vec_dot(Plane_Normal,Point);
	
	if(hemisphere>0)//if on my same hemisphere
	{
		return(1);
	}
	else//if on opposite hemisphere
	{
		return(0);
	}
}




This function should be usefull to fix the problem, but I'm not sure where to plug this in your function (probalby above the last two lines, to do something different with those last two lines afterwards?).
But what I am mostly confused with is... how to modify that last part of your function depending on the results of mine?

current brain status: dazed and confused
confused

EDIT:
I have done further tests drawning an axsis going through the planet's core aligned to our vehicle's normal (blue line).
http://www.youtube.com/watch?v=a-1EbjmkwMk
This proves the problem is not when going through the same point on the opposite side?
current brain status: even more dazed and extremely confused...

EDIT2:
Done further tests, this time debugging V_Path (green line).
V_Path is the temporary path for the pan calculations. It is a rotated version of our destination.
http://www.youtube.com/watch?v=ntPkiiZTV8Y
Aha! Finally found the culprit! It seems the problem occurs when our temporary path is aligned vertically.
(I'm a little less confused now, I understand what is causing this but it seems I can't figure out how to fix it)
Posted By: JibbSmart

Re: rotation around a sphere - 01/18/12 18:14

Interesting. I think the problem is that, as you've noticed earlier, alignToVec doesn't completely align the axes in one go (this is due to rounding errors that get exacerbated with a larger angle between the two axes). Since on the other side of the planet the vector could be a little behind or a little in front of your vehicle (in object space), these little inaccuracies cause the vehicle to change its mind about which direction it should go.

Here are a few ideas:

First, we can confirm this by adding a few more alignToVec calls (like you did earlier) and see if that makes the problem less likely to occur (that is, it'll hopefully mean the destination needs to be much closer to the opposite pole for the problem to occur).

Secondly, if the vehicle adjusts its angle gradually rather than instantly (add a max_rotation parameter to the look_at function and make sure the function never rotates the vehicle more than the amount given in this parameter -- make it 5*time_step, for example, and the vehicle won't adjust its pan by more than 5 degrees per tick), its turning circle might let the vehicle get far enough away from its destination's pole that it can escape that "inaccurate zone" and continue to its destination.

Thirdly, if the vehicle only checks the angle to its destination once a second or so, it should be able to get far enough away from the pole after the first check that any checks after that will be fairly consistent.

Any one of these should help, I think. The first is fairly inefficient, but could be used to confirm whether or not that's the root of the problem. In the end, a combination of the second and third solutions might be ideal, but the first would be the quickest way to confirm what the actual problem is.
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/18/12 18:49

Originally Posted By: JibbSmart
First, we can confirm this by adding a few more alignToVec calls (like you did earlier) and see if that makes the problem less likely to occur (that is, it'll hopefully mean the destination needs to be much closer to the opposite pole for the problem to occur).


Actually my first tests (not posted on this thread) had very strange results do to that. I did think of that and modified your function to get instant rotations:
Originally Posted By: JibbSmart's alignToVec thread
Call "alignToVec(........, 1)" once every frame over several frames to complete the alignment (this will be quite smooth and quite quick), or several times in one frame for a complete alignment in only one frame.
If you would rather deal with the imprecisions yourself, remove the "* vec_length(rotAxis);".

Modified version of your function I am currently using:
Click to reveal..
Code:
function alignToVec(ANGLE* entAng, VECTOR* vec, VECTOR* axis, var factor) {
	vec_rotate(axis, entAng);
	vec_normalize(axis, 1);
	vec_normalize(vec, 1);
	VECTOR rotAxis;
	vec_cross(rotAxis, vec, axis);
	var angle = -acos((float)vec_dot(axis, vec)) * factor; // * vec_length(rotAxis);
	ANGLE rotAngle;
	ang_for_axis(rotAngle, rotAxis, angle);
	ang_add(entAng, rotAngle);
}



Originally Posted By: JibbSmart
Secondly, if the vehicle adjusts its angle gradually rather than instantly (add a max_rotation parameter to the look_at function and make sure the function never rotates the vehicle more than the amount given in this parameter -- make it 5*time_step, for example, and the vehicle won't adjust its pan by more than 5 degrees per tick), its turning circle might let the vehicle get far enough away from its destination's pole that it can escape that "inaccurate zone" and continue to its destination.

Could be a solution but... When reaching the "problematic zones" wouldn't it do a wierd little turn before going back to it's correct path? I would like to avoid that strange behaviour if possible.
Another problem I see with this approach is if the destination is close to the moving vehicle, if it's not far enough for it to fully rotate towards it before reaching the destination, it would result in the vehicle going around it's destination in circles forever.

Originally Posted By: JibbSmart
Thirdly, if the vehicle only checks the angle to its destination once a second or so, it should be able to get far enough away from the pole after the first check that any checks after that will be fairly consistent.

I like this idea more, but it leaves the solution to randomness. If by any chance the delay between checks lands close to the "problematic zone" it could result in the vehicle going back and fourth. I don't feel confortable leaving the solution to a random delay that could potencially land on a problematic zone sometimes.


Originally Posted By: Carlos3DGS
EDIT:
I have done further tests drawning an axsis going through the planet's core aligned to our vehicle's normal (blue line).
http://www.youtube.com/watch?v=a-1EbjmkwMk
This proves the problem is not when going through the same point on the opposite side?
current brain status: even more dazed and extremely confused...

EDIT2:
Done further tests, this time debugging V_Path (green line).
V_Path is the temporary path for the pan calculations. It is a rotated version of our destination.
http://www.youtube.com/watch?v=ntPkiiZTV8Y
Aha! Finally found the culprit! It seems the problem occurs when our temporary path is aligned vertically.
(I'm a little less confused now, I understand what is causing this but it seems I can't figure out how to fix it)

I am sorry, I was editing my previous post while you were answering. I wanted to repost this part just in case you missed it. (check the green line in the second video at 1:20 and after)

I think the solution could be to check if V_Path is straight up or down (that seems to be the problem), and if it is aligned vertically then do not rotate the vehicle and let it contiue in a straight line untill the the rotated destination (V_Path) is not vertically aligned anymore. Not sure if that could be the solution, just a random thought...

EDIT:
Nevermind, I think I understood you wrong before. Is this a gimbal-lock problem where I translate the gimbal lock centered around an arbitrary rotated axsis because I used vec_rotateback()?
If so... Is there any way to overcome this problem removing the "vec_to_angle(V_Ang, V_Path);" in the look_at function? And mabe replacing it using your alignToVec() function to perform the calculation?
Posted By: JibbSmart

Re: rotation around a sphere - 01/18/12 19:21

Quote:
I think the solution could be to check if V_Path is straight up or down (that seems to be the problem), and if it is aligned vertically then do not rotate the vehicle and let it contiue in straight line untill the the rotated destination (V_Path) is not vertically aligned anymore. Not sure if that could be the solution, just a random thought...
Yes, that sounds ideal. V_Path is (in theory, anyway) straight up or down when the destination is directly opposite the vehicle's position (that is, if the vehicle was to tunnel straight down through the planet it'd surface at its destination). As such, in this case, there is no "shortest path" to the destination, and the vehicle can move in any direction it wants (ideally, I guess, continue in the direction it was already heading). (EDIT: I see your edit, but I still think this is the ideal solution, once we get that green line to stop wobbling so much laugh )

The way the green line wobbles, it appears that the alignToVec function isn't very accurate, and I think this is the problem:
Quote:
Modified version of your function I am currently using:...
That's actually how I originally wrote it, only to find that rounding errors caused a lot of trouble. This is because vec_length(rotAxis) can get quite small. I added in that multiplication so that the final angle always undershoots the rotation, so it still looks smooth as you approach the appropriate orientation; without it, the final result can overshoot, resulting in weird behaviour (which could well be the cause of that wobbly V_Path).

So I recommend uncommenting that extra bit and seeing if multiple alignToVec(...)s reduce the problem.

I hope that's useful (and correct!).
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/18/12 20:22

Tried it, and I thought we had it... It took a while but finally it happened again. (I guess I was just being lucky for a while)

Results:
http://www.youtube.com/watch?v=3ggFWxYgIhs


Curent version of alignToVec:
Code:
function alignToVec(ANGLE* entAng, VECTOR* vec, VECTOR* axis, var factor) {
	vec_rotate(axis, entAng);
	vec_normalize(axis, 1);
	vec_normalize(vec, 1);
	VECTOR rotAxis;
	vec_cross(rotAxis, vec, axis);
	
	//USE ONLY ONE OF THE FOLLOWING TWO LINES!!!!!!!
	//var angle = -acos((float)vec_dot(axis, vec)) * factor; // instant rotation
	var angle = -acos((float)vec_dot(axis, vec)) * factor * vec_length(rotAxis); //smooth rotation
	
	ANGLE rotAngle;
	ang_for_axis(rotAngle, rotAxis, angle);
	ang_add(entAng, rotAngle);
}



Current version of look_at:
Code:
void look_at(ENTITY* Vehicle, VECTOR* Destination, ENTITY* Planet)
{
	VECTOR V_Nrml;
	ANGLE V_Ang;
	VECTOR V_Path;

	// copy my angle
	vec_set(V_Ang, Vehicle.pan);
	
	//get our vehicle's normal from the planet core
	vec_diff(V_Nrml, Vehicle.x, Planet.x);

	// orientate temporary angle as if on a perfect sphere
	alignToVec(V_Ang, V_Nrml, vector(0, 0, 1), 1);
	alignToVec(V_Ang, V_Nrml, vector(0, 0, 1), 1);
	alignToVec(V_Ang, V_Nrml, vector(0, 0, 1), 1);
	alignToVec(V_Ang, V_Nrml, vector(0, 0, 1), 1);
	alignToVec(V_Ang, V_Nrml, vector(0, 0, 1), 1);

	// get destination position relative to the vehicle's orientation
	vec_diff(V_Path, Destination, Vehicle.x);
	vec_rotateback(V_Path, V_Ang);
	
	//DEBUG path
	vec_set(testv1,V_Path);
		vec_normalize(testv1,1000);
		vec_add(testv1,Planet.x);
		draw_line3d(testv1,NULL,100);
		draw_line3d(testv1,COLOR_GREEN,100);
		draw_line3d(Planet.x,COLOR_GREEN,100);

	// convert to an angle
	vec_to_angle(V_Ang, V_Path);
	
	//AVOID GIMBAL LOCK!!!
	if(V_Ang.tilt>85||V_Ang.tilt<-85)
	{
	   return;
	}

	// now, V_Ang's pan is our angle
	ang_rotate(Vehicle.pan, vector(V_Ang.pan, 0, 0));
}




Spherical movement is such a pain! cry

Also... look closely at the video. The green (V_Path) line does seem to have a problem when vertical.
But... look even closer at the blue line and red dot when I am on the opposite side of the planet than the vehicle (the same side as destination). The vehicle is not opposite of destination when the problem happens! (it is sort of close by, but not directly opposite)

I'm confused again... seems the problem is not when opposite of the destination?!?!?!?
Posted By: JibbSmart

Re: rotation around a sphere - 01/18/12 21:10

That is weird. Hmm... V_Path, in theory, should only be vertical when the destination is on the exact opposite side of the planet to the vehicle. I wonder if alignToVec was more imprecise than I thought, or if there's another issue we're not seeing. Sorry, that's all I've got for now frown
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/18/12 21:11

I made another debug version where I can toggle the planet's INVISIBLE flag to see the vectors' behaviour better (also reduced the vehicle's speed to see the vector movement easier).

I still don't understand why it's happening, but for sure the destination is not opposite of the vehicle.

I thought I would upload a video of this so you can take a look, mabe you can understand what is happening better than I can being able to see the vectors through the planet:
http://www.youtube.com/watch?v=hvLp5axXRjQ
(a problematic test begins at 1:54)

green=V_Path

blue=aligned from vehicle to planet core and out through the other side

red=from vehicle to destination

red dot=destination
Posted By: JibbSmart

Re: rotation around a sphere - 01/18/12 22:39

Okay. It looks to me like V_Ang is not being affected by alignToVec at all -- notice how the green line moves as the vehicle climbs up mountains or tips into valleys. This seems to be the source of the problem -- the vehicle tilts up a mountain, and decides the target is behind it, so it goes back down the mountain, leveling out on flat ground, only to discover the target is behind it again.

This means alignToVec is either not modifying V_Ang, or it's modifying it incorrectly (I have just now noticed that V_Ang also modifies its two VECTOR* parameters, which is really a bad idea [my bad, that is -- that's how I wrote it] -- it should probably be modified to copy those parameters to two local VECTORs and then modify those, so that only the ANGLE is modified at the end).
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/19/12 02:14

I have done more tests to prove your concept, and I think you have found the problem.
I move my vehicle into a valley, and then click on a destination on the opposite side of the planet... He gets stuck every time.
I think you nailed it! Now I'm trying to think of how to fix it. But why would alignToVec not be working?
Posted By: JibbSmart

Re: rotation around a sphere - 01/19/12 03:10

Let's see... well, I guess the first step would be to stop the function modifying the other VECTORs -- only the ANGLE should be modified, and I wonder if re-using the same vectors over and over again after they've been modified has something to do with the problem.
Code:
function alignToVec(ANGLE* entAng, VECTOR* vec, VECTOR* axis, var factor) {
	VECTOR locVec, locAxis;
	vec_set(locVec, vec);
	vec_set(locAxis, axis);
	vec_rotate(locAxis, entAng);
	vec_normalize(locAxis, 1);
	vec_normalize(locVec, 1);
	VECTOR rotAxis;
	vec_cross(rotAxis, locVec, locAxis);
	
	//USE ONLY ONE OF THE FOLLOWING TWO LINES!!!!!!!
	//var angle = -acos((float)vec_dot(locAxis, locVec)) * factor; // instant rotation
	var angle = -acos((float)vec_dot(locAxis, locVec)) * factor * vec_length(rotAxis); //smooth rotation
	
	ANGLE rotAngle;
	ang_for_axis(rotAngle, rotAxis, angle);
	ang_add(entAng, rotAngle);
}

The next thing I would try is to make sure we're passing the correct information -- alignToVec(&V_Ang, &V_Nrml, vector(0, 0, 1), 1);

We add in the "&" to make sure we're passing a pointer to those parameters -- something Lite-C normally does automatically, but under occasional circumstances it won't. If the wrong address is being passed, V_Ang won't get modified, and we get the behaviour we've been seeing.

Fingers crossed!
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/19/12 16:18

Tried your new function, also tried adding the "&" and it didn't solve it.

I was reading the manuall for that "&" behaviour and added some "*" to your function for ent_Ang, but that didn't solve it either.

modified alignToVec:
Click to reveal..
Code:
function alignToVec(ANGLE* entAng, VECTOR* vec, VECTOR* axis, var factor) {
	VECTOR locVec, locAxis;
	vec_set(locVec, vec);
	vec_set(locAxis, axis);
	vec_rotate(locAxis, *entAng);
	vec_normalize(locAxis, 1);
	vec_normalize(locVec, 1);
	VECTOR rotAxis;
	vec_cross(rotAxis, locVec, locAxis);
	
	//USE ONLY ONE OF THE FOLLOWING TWO LINES!!!!!!!
	var angle = -acos((float)vec_dot(locAxis, locVec)) * factor; // instant rotation
	//var angle = -acos((float)vec_dot(locAxis, locVec)) * factor * vec_length(rotAxis); //smooth rotation
	
	ANGLE rotAngle;
	ang_for_axis(rotAngle, rotAxis, angle);
	ang_add(*entAng, rotAngle);
}



I have also been thinking around that direction... what difference is there between accesing an entitie's angle or a declared ANGLE one?

I tried taking V_Ang out of look_at() to turn it into a global variable, but that didn't fix it either.

Also tried adding in some wait instructions into my movement code so it will wait between each step (just in case mutiple modifications of our pan were causeing this), but that didn't fix it either.

movement code:
Click to reveal..
Code:
void vehicle_movement(ENTITY* Vehicle, ENTITY* Planet)
{
	while(1)
	{
		//set pathfinding objective
		if(mouse_left)
		{
			if(mouse_ent==Planet)
			{
				vec_set(vehicle_objective,mouse_3D);
			}
		}
		if(key_w||key_s||key_a||key_d)//MANUAL DRIVING OVERRIDE
		{
			vec_fill(vehicle_objective,0);//cancel pathfinding
			ang_rotate(Vehicle.pan,vector(10*(key_a-key_d)*time_step,0,0));//manual steering
			c_move(Vehicle,vector(2*(key_w-key_s)*time_step,0,0),nullvector,IGNORE_MODELS | IGNORE_PASSABLE | IGNORE_SPRITES);//manual movement
			align_to_surface(Planet, Vehicle);
		}
		else if(vec_dist(Vehicle.x,vehicle_objective)>5)//AUTO PATHFINDING
		{
			if(vehicle_objective.x!=0&&vehicle_objective.y!=0&&vehicle_objective.z!=0)//if there is an objective
			{
			   wait(1);//<-----
				look_at(Vehicle,vehicle_objective,Planet);//automatic steering
				wait(1);//<-----
				c_move(Vehicle,vector(2*time_step,0,0),nullvector,IGNORE_MODELS | IGNORE_PASSABLE | IGNORE_SPRITES);//automatic movement
				wait(1);//<-----
				align_to_surface(Planet, Vehicle);
				wait(1);//<-----
			}
		}
		wait(1);
	}
}



Just as a test I modified the last instruction in the align_to_surface function to not take into account surface normals.
Click to reveal..
Code:
void align_to_surface(ENTITY* Planet, ENTITY* Vehicle)
{
	VECTOR start_trace;
	VECTOR Temp_Vec;
	var safeguard;
	
	
	//get the surface position
	vec_set(start_trace,Vehicle.x);
	vec_sub(start_trace,Planet.x);
	
	vec_normalize(start_trace,vec_length(start_trace)*2);
	vec_add(start_trace,Planet.x);
	me=Vehicle;
	safeguard=c_trace(start_trace, Planet.x,IGNORE_ME|IGNORE_PASSABLE|IGNORE_SPRITES);
	if(safeguard<=0)
	{
		return;
	}
	
	
	//place vehicle on surface 
	//(taking into account vehicle min_z)
	vec_set(Temp_Vec,hit.x);
	vec_sub(Temp_Vec,Planet.x);
	vec_normalize(Temp_Vec,vec_length(Temp_Vec.x)-Vehicle.min_z);
	vec_add(Temp_Vec,Planet.x);
	vec_set(Vehicle.x,Temp_Vec);
	
	//rotate towards surface normal
	vec_sub(Temp_Vec,Planet.x);
	
	//USE ONLY ONE OF THE TWO INSTRUCTIONS BELOW
	//alignToVec(Vehicle.pan, hit.nx, vector(0, 0, 1), 1); //align to surface normal
	alignToVec(Vehicle.pan, Temp_Vec, vector(0, 0, 1), 1); //align to perfect sphere
}


That fixed it, but it was a really nice feature i would like to keep. Withough it, it looks like my vehicle is just gliding/hovering on ice. And it dosn't explain why alignToVec dosn't work in the other function anyway...

Still trying to think why it would modify entity.pan but not a declared ANGLE variable, what could the difference be?

Also thinking of other workarounds, but none have worked so far...

EDIT:
I tried to directly use the vehicle angles in the calculations instead of V_Ang to see if alignToVec() just dosn't like anything that is not entity related... Changes had no effect, same problem in valleys.

Click to reveal..
Code:
void look_at(ENTITY* Vehicle, VECTOR* Destination, ENTITY* Planet)
{
	VECTOR V_Nrml;
	ANGLE V_Ang;
	VECTOR V_Path;
	ANGLE Path_Ang;	
	
	//this time I store angles (for later) and directly modify the vehicle's pan in the calculations
	vec_set(V_Ang, Vehicle.pan);
	
	//get our vehicle's normal from the planet core
	vec_diff(V_Nrml, Vehicle.x, Planet.x);

	// orient angle by planet normal (perfect sphere)
	alignToVec(&Vehicle.pan, &V_Nrml, vector(0, 0, 1), 1);

	// get destination position relative to the vehicle
	vec_diff(V_Path, Destination, Vehicle.x);
	//rotate relative destination by absolute orientation
	vec_rotateback(V_Path, Vehicle.pan);
	// convert to an angle
	vec_to_angle(Path_Ang, V_Path);
	
	
	//DEBUG path
	vec_set(testv1,V_Path);
	vec_normalize(testv1,1000);
	vec_add(testv1,Planet.x);
	draw_line3d(testv1,NULL,100);
	draw_line3d(testv1,COLOR_GREEN,100);
	draw_line3d(Planet.x,COLOR_GREEN,100);
	
	//avoid gimbal lock
	if(Path_Ang.tilt>89||Path_Ang.tilt<-89)
	{
	   vec_set(Vehicle.pan,V_Ang);//restore saved angle
		return;//don't rotate
	}

	// rotate angle by Path_Ang
	ang_rotate(Vehicle.pan, vector(Path_Ang.pan, 0, 0));
}


Posted By: EvilSOB

Re: rotation around a sphere - 01/19/12 18:03

A lot of this maths has gone over my head, so I havent read everything CAREFULLY,
so please forgive me if Ive missed something somewhere...

One thing does spring to mind is that the 'alignToVec' functions DOES use the
angle already contained in 'entAng' as a start point.

So, when you are using this function to calculate your directions, could it be
that it is being adversly affected by the fact that the entity has been rotated
slightly to match the 'lumpy' surface angles?
Posted By: Carlos3DGS

Re: rotation around a sphere - 01/19/12 21:16

I did try a test starting out with a non-rotated angle and then aligning that to the surface normal (as if it were a perfect sphere).

Didn't work out, seems like the vec_rotate, vec_to_angle, and ang_rotate are working. But it looks like the alignToVec instruction does not...

Result:
http://www.youtube.com/watch?v=Y-UgW4IUHrs

Code:
void look_at(ENTITY* Vehicle, VECTOR* Destination, ENTITY* Planet)
{
	VECTOR V_Nrml;
	ANGLE V_Ang;
	VECTOR V_Path;
	ANGLE Path_Ang;
	var hemisphere;	
	
	//this time I start off with a nuetral angle for the calculations
	vec_fill(V_Ang, 0);//standing stright up with zero pan
	
	//get our vehicle's normal from the planet core
	vec_diff(V_Nrml, Vehicle.x, Planet.x);

	// orient angle by planet normal (perfect sphere)
	alignToVec(V_Ang, V_Nrml, vector(0, 0, 1), 1);

	// get destination position relative to the planet core
	vec_diff(V_Path, Destination, Vehicle.x);
	//rotate relative destination by absolute orientation
	vec_rotateback(V_Path, V_Ang);
	// convert to an angle
	vec_to_angle(Path_Ang, V_Path);
	
	
	//DEBUG path
	vec_set(testv1,V_Path);
	vec_normalize(testv1,1000);
	vec_add(testv1,Planet.x);
	draw_line3d(testv1,NULL,100);
	draw_line3d(testv1,COLOR_GREEN,100);
	draw_line3d(Planet.x,COLOR_GREEN,100);
	
	//avoid gimbal lock
	if(Path_Ang.tilt>89||Path_Ang.tilt<-89)
	{
		return;//don't rotate
	}

	// rotate angle by Path_Ang
	ang_rotate(V_Ang, vector(Path_Ang.pan, 0, 0));
	vec_set(Vehicle.pan,V_Ang);
}



I don't undertand it though, in my align_to_surface() function it works, but in my look_at() it seems to not do anything when I use alignToVec().

Also if you take a look at the movement code I posted in the above post, it actually calls look_at first, then moves, then align_to_surface... So if it was a problem with rotating several times, the last one should be failing, not the look_at()

I just don't understand it...
Posted By: JibbSmart

Re: rotation around a sphere - 01/20/12 23:00

Sorry, I have no idea why the function might not be working under those circumstances frown
© 2024 lite-C Forums