## orientation of trace_plane_normal

Discuss programming in the QuakeC language.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

### orientation of trace_plane_normal

Hi guys, I'm trying to orientate a tripod model near a slope, using trace_plane_normal
This is the tripod in global coordinates: It has red for x axis, green for y axis and blue for z axis

Now, if I use this code I created

Code: Select all

``````//self is parent entity (that I've hidden in the screenshot for a clearer image), which has its own coordinates, but, in this case, it moves on global coordinates except for turning Y axis as yaw
void Orient_Think()
{
makevectors(self.angles);
traceline(self.origin,self.origin+(-v_up*128),MOVE_HITMODEL,self);
fracdown = trace_fraction;
local vector v = trace_plane_normal;
makevectors(trace_plane_normal);
vectest = vectoangles(v);
setorigin(tripod,trace_endpos);
tripod.angles = vectest;
self.nextthink = time + 1;
self.think = Orient_Think;
}
``````
And, as you can see, orientation changes accordingly to slop perpendicular vector, but x axis and z axis are switched, plus y axis is inverted

Now, I also created a code for make sure tripod turns on yaw accordingly to parent entity orientation like so

Code: Select all

``````makevectors(self.angles);
traceline(self.origin,self.origin+(-v_up*128),MOVE_HITMODEL,self);
fracdown = trace_fraction;
if(trace_fraction < 1){
local vector v = normalize(trace_plane_normal);
vectest = vectoangles([v_x,v_y,v_z],-v_forward);
}
setorigin(tripod,trace_endpos);
tripod.angles = vectest;
``````
And, it rotates on Y axis, but still X and Z axis are switched
I also tried to invert axis using something like

Code: Select all

``````vectest = vectoangles([v_z,v_y,v_x],-v_forward);
``````
but orientation is all messed up, so I presume it's not the correct way to do it.
How can I retrieve correct orientation of a trace_plane_normal and how can I manage those data to rotate the axis ternary as I want?

Thanks a lot for any clarification, because, on this subject I'm completely ignorant (it requires math..GAHHH )!
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

### Re: orientation of trace_plane_normal

So you have a forward, right, up value of your object, and you have a plane_normal that you want to rotate it around.
(those vectors need to be perpendicular to each other, you can use crossproducts if you know two of them. if you have three arbitrary points, forward=b-a;up=crossproduct(forward,c-a);right=crossproduct(forward,up); should get you three perpendicular vectors(remember to normalize as needed), but this does still impose a specific pair of points to give primary direction with the tertiary point only for roll angles, so you might want to use the midpoint between b and c instead of b if its not three points of a quad)

so if the plane's normal is to end up as your new 'up' vector, then the new forward vector is:
newforward = oldforward - dot(oldforward*plane_normal)*plane_normal;
(note: plane_normal points outwards, so you should read this as 'push into the plane by as much as the vector currently points away', meaning the resulting vector travels along the plane. you will have a singularity if oldforward points exactly towards the plane)
(also note: scaling that dot product by 2 will cause it to 'bounce' instead, with perfect energy conservation - values between 1 and 2 will bounce more normally)
you can do the same maths with the right vector too, but probably you'll find that term will just drop from your equations.
to turn that into angles, you can just use vectoangles(newforward,plane_normal), the plane_normal is of course your newup vector, and the newright vector isn't even relevant on account of it being known to be perpendicular and thus orientation can come from the forward vector with the up vector providing purely the roll angle.

note that none of this includes logic for the centre of gravity, so nothing will topple, so expect weirdness from steep slopes.
also note that the result of the maths is an exact value, there is no room for interpolation in its formula, which means you will likely want to somehow add your own smoothing if its a dynamic entity.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

### Re: orientation of trace_plane_normal

thanks a lot Spike, newforward = v_forward - dotproduct(v_forward,v)*v did the trick(kinda)!
Of course that needs a lot of polishing but it's a good start. I think it would be better that FTE would have more helper function for rotation, like align to entity, rotate towards entity, look at, orbit, etc..I'll try to create some wrapper funcs and adding them to craFTEr github repo.
Anyway, I didn't understand the preface you wrote: how can choose three arbitrary points on a surface in FTE? I mean, I can chose three vectors, but I cannot (at least that I'm aware of) choose three vertices on a mesh..

this is the working code

Code: Select all

``````void Orient_Think()
{
makevectors(self.angles);
traceline(self.origin,self.origin+(-v_up*128),MOVE_HITMODEL,self);
fracdown = trace_fraction;
local vector v = trace_plane_normal;
local vector newforward = v_forward - dotproduct(v_forward,v)*v;
vectest = vectoangles(newforward,v);
setorigin(tripod,trace_endpos);
tripod.angles = vectest;
if(fracdown < 1){
viewOffsZ += frametime * 10;
}
else{
viewOffsZ -= frametime * 10;
}
setorigin(self,[self.origin_x,self.origin_y,viewOffsZ]);
self.nextthink = time + THINK_REFRESH;
self.think = Orient_Think;
}
``````
I'll PM you later because I tested a bug on latest release of FTE regarding CSQC traceline (it crashes on v5399)
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

### Re: orientation of trace_plane_normal

regarding that huge part in a parenthasis in the first paragraph of my previous post:
you said a tripod. tripods are defined in terms of three legs, or more specifically by 3 feet(not the unit), aka 3 points.
or if its a model then you can just use makevectors, obviously, and skip trying to calculate an orientation from arbitrary points. although if its animated you could possibly use gettaginfo to get the three points from three bones, or getsurface* to get three points from a brushmodel, but sounds like just makevectors will do.

fte has a couple of rotatevectorsby* builtins if you want to do basic forward kinematics, but there's no translations there which limits its usefulness. its nothing that you couldn't also do in qc, just with the maths hidden (and in native code).
as to additional utility functions, QC is limited in terms of arguments to builtins. You cannot simply pass a couple of matricies to the engine, which makes orientation stuff messy. one option would be to use quats (especially if you want to interpolate stuff, but that's its own kind of mess), or to use pointers-to-4x3-matricies (where pointers-to-locals cannot really be supported, so encouraging that would be bad, and half the time you can drop one of the axis anyway), and using just eular angles results in non-linear motion etc. remember that stuff gets more messy when you have translations and scale values too, with skew.
so yeah, I've no idea what aproach to take, so I've taken none.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

### Re: orientation of trace_plane_normal

Yeah, my fault, I said a tripod, because it was a gizmo model, very simple and useful to understand axis orientation, it wasn't meant to be overcomplicated!

My opinion is that, whatever approach you'd like to take (quaternions for example) it'd be transparent to quakec devs. There should be functions like

Code: Select all

``vector orbit(entity target, entity subject, vector angle, float offset)``
or

Code: Select all

``vector lookat(entity target, entity subject, float offset)``
or something like that, where qc devs use entities and floats and return vectors. Because doing complex calculous in quakec is tedious, having native code that did the job for you would be better!

Regarding rotatevectorsby* builtins: never be able to use them, as I've never been able to orientate a bone targeting its parent or other characters bone. It gives always weird orientation

PS:I pm'd you the traceline bug stuff
Meadow Fun!! - my first commercial game, made with FTEQW game engine