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
How to calculate the up vector in Lua/celx?
Re: How to calculate the up vector in Lua/celx?
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
-
Topic authorAuReality
- Posts: 45
- Joined: 05.12.2003
- With us: 20 years 11 months
- Location: Groningen, The Netherlands
Re: How to calculate the up vector in Lua/celx?
Thanks so far Harald.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.
I have no problem doing this in Lua myself, if only I knew how..Harry wrote:So I think you either have to implement this in Lua yourself,
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?
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
-
Topic authorAuReality
- Posts: 45
- Joined: 05.12.2003
- With us: 20 years 11 months
- Location: Groningen, The Netherlands
Re: How to calculate the up vector in Lua/celx?
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?
AuReality wrote:I don't grasp what the transform() does
Me neither - this is merely Copy&Paste from the Celestia sources
Harald