Page 1 of 1

How to calculate the up vector in Lua/celx?

Posted: 03.04.2004, 21:37
by AuReality
I hope someone here can help me out with a Lua/celx problem I have been struggling with for over 4 days now:

Given
- the current camera position
- the current camera orientation
- the 'line of sight' to an object position
- frame set to "observer" (i.e. camera)
Then
how do I calculate the current 'up' vector in a .celx Lua script?
I.e. the vector pointing up from the position I am looking at.

I have tried several methods, involving normal math, matrix calculations and quaternions, but with no success. I am quite lost here...

Can someone help?

(I can send the script if you want to have a look)

Paul

Re: How to calculate the up vector in Lua/celx?

Posted: 04.04.2004, 08:30
by Harry
AuReality wrote:(given:)
- the current camera orientation
[...]
Then how do I calculate the current 'up' vector in a .celx Lua script?
I.e. the vector pointing up from the position I am looking at.

This has been bothering me some time ago too, and I hadn't yet got around to find out how to do it. But your question made me look into this again:
This C++ code, copied from Observer::setTargetSpeed, is used to transform vectors (in this case in the line of sight instead of "up") by a quaternion:

Code: Select all

Vec3f(0, 0, -s) * getOrientation().toMatrix4();

The problem here is the "toMatrix4()"-conversion from a quaternion to a rotation matrix and the resulting multiplication between a vector and a matrix, which aren't available in Celx-scripting. So I think you either have to implement this in Lua yourself, or wait for the next Celestia-version (I will check in a rotation:transform(vector) which does this).

Anybody who knows about this stuff care to comment if this is correct, and why a 4x4-Matrix is used in observer.cpp? A 3x3 Matrix seems to work ok too.

Harald

Re: How to calculate the up vector in Lua/celx?

Posted: 04.04.2004, 09:39
by AuReality
Harry wrote:This has been bothering me some time ago too, and I hadn't yet got around to find out how to do it. But your question made me look into this again:
This C++ code, copied from Observer::setTargetSpeed, is used to transform vectors (in this case in the line of sight instead of "up") by a quaternion:

Code: Select all

Vec3f(0, 0, -s) * getOrientation().toMatrix4();

The problem here is the "toMatrix4()"-conversion from a quaternion to a rotation matrix and the resulting multiplication between a vector and a matrix, which aren't available in Celx-scripting.
Thanks so far Harald.
Harry wrote:So I think you either have to implement this in Lua yourself,
I have no problem doing this in Lua myself, if only I knew how..
If I am correct, the formula to be applied (pseudo code) is
newUp = defaultUp * getOrientation()
where 'newUp' is [0,1,0] when the line of sight is [0,0,-1], ie looking along the z-axis.

I found this text on Internet:

Internet wrote:If a 3-vector is represented by a homogeneous quaternion, that is one whose scalar part is zero, then to rotate a vector <0, V> through an angle theta
about a unit axis vector A, do the following:

let Q = < -cos(theta/2), A * sin(theta/2) >

rotated vector = Q * <0, V> * COMP Q

and worked this out in Lua like this:

Code: Select all


function vector(x,y,z)

-- wrapper for celestia:newvector() function

return celestia:newvector(x,y,z)

end

function comp(q)

-- this functions calculates the complement of quaternion/orientation 'q'

   return celestia:newrotation(-1 * vector(q.x,q.y,q.z),q.w)

end


function rotationToVector(rot)

-- convert a rotation to a vector, ie only use the vector part

   return vector(rot.x,rot.y,rot.z)

end


function vectorRotate (v,a,theta)

-- quaternion implementation of rotation vector 'v' around axis 'a' by angle 'theta'

   local q = celestia:newrotation(  math.sin(theta/2)*a, -math.cos(theta/2))
   local rv =  rotationToVector(q * celestia:newrotation(v,0) * comp(q))
   
   return rv:normalize()

end


and then tried using this to calculate the upvector from the current orientation:

Code: Select all


yaxis = vector(0,1,0)
obs = celestia:getobserver()
up = vectorRotate(yaxis,vector(obs.x,obs.y,obs.z),obs.w)



but this absolutely does not what I want.
It is unclear to me if the 'w' part of an orientation is the angle to be applied.
Or rather: I do not know what angle to use in my vectorRotate function.


Harry wrote:[]... or wait for the next Celestia-version (I will check in a rotation:transform(vector) which does this).


Must be cool to be able to put these functions in celx yourself :-)
I appreciate the help Harald.
However, I'd like to go on with my script asap.
So if you, or someone else, can confirm that I am trying to do the right thing but in a wrong way, rather than doing the wrong thing in the right way, or even worse, trying to do the wrong thing in the wrong way....

Paul

Re: How to calculate the up vector in Lua/celx?

Posted: 04.04.2004, 11:38
by Harry
AuReality wrote:I have no problem doing this in Lua myself, if only I knew how..
If I am correct, the formula to be applied (pseudo code) is
newUp = defaultUp * getOrientation()
where 'newUp' is [0,1,0] when the line of sight is [0,0,-1], ie looking along the z-axis.
[....]
but this absolutely does not what I want.

I don't have much experience with quaternions either, and I don't know why the code you use doesn't work. Anyway, there is one thing I should explain because it's unintuitive and badly documented:
There are two incompatible ways to create a quaternion:
- celestia:newrotation(vector, w)
- celestia:newrotation(w, x, y, z)
The first one already takes care of the "theta/2" stuff, so
newrotation(celestia:newvector(x,y,z), w)
is not the same as
newrotation(w, x, y, z)
(This is ugly, but I don't want to break compatibility with 1.3.1)

I just implemented the code I mentioned in my first post (using a transformation matrix) in Lua, but only using a 3x3 Matrix (I still don't know why a 4x4 is used in Celestia, so maybe this is wrong - but tests worked out ok. If you run into problems, maybe you have to extend it):

Code: Select all

function transform(v, q)
  -- Vec3f(0, 0, -s) * getOrientation().toMatrix4();
  matrix = { }

  x = q.x;
  y = q.y;
  z = q.z;
  w = q.w;

  wx = w * x * 2;
  wy = w * y * 2;
  wz = w * z * 2;
  xx = x * x * 2;
  xy = x * y * 2;
  xz = x * z * 2;
  yy = y * y * 2;
  yz = y * z * 2;
  zz = z * z * 2;

  matrix[0] = { x= 1 - yy - zz, y= xy - wz,     z= xz + wy }
  matrix[1] = { x= xy + wz,     y= 1 - xx - zz, z= yz - wx }
  matrix[2] = { x= xz - wy,     y= yz + wx,     z= 1 - xx - yy }

  nx = (matrix[0].x * v.x + matrix[1].x * v.y + matrix[2].x * v.z)
  ny = (matrix[0].y * v.x + matrix[1].y * v.y + matrix[2].y * v.z)
  nz = (matrix[0].z * v.x + matrix[1].z * v.y + matrix[2].z * v.z)

  return celestia:newvector(nx, ny, nz)
end


With this, this should work:

Code: Select all

yaxis = vector(0,1,0)
obs = celestia:getobserver()
orientation = obs:getorientation()
up = transform(yaxis, orientation)


HTH,
Harald

Re: How to calculate the up vector in Lua/celx?

Posted: 04.04.2004, 14:32
by AuReality
Harry wrote:[..]
With this, this should work:

Code: Select all

yaxis = vector(0,1,0)
obs = celestia:getobserver()
orientation = obs:getorientation()
up = transform(yaxis, orientation)


HTH,
Harald


It works!
This is incredibly cool. Now I can really get on with the script creator I am working on. Thanks a 1000 lightyears Harald!
I don't grasp what the transform() does - I will study it - but at the moment I don't care..
I will make sure to credit you in the script creator.

Paul

Re: How to calculate the up vector in Lua/celx?

Posted: 04.04.2004, 15:20
by Harry
AuReality wrote:I don't grasp what the transform() does

Me neither - this is merely Copy&Paste from the Celestia sources ;)

Harald