3d vector math question
category: code [glöplog]
Hi everybody,
Lets say i have a curve defined by a equation (some kind of lissajous curve).
for any value of "t" i can get a (x,y,z) point.
Now I want to have a camera in a raytracer to follow that path.
Ray origin :
call f(t) and get a point : (x0,y0,z0)
Ray direction :
call f(t+delta) and get (x1,y1,z1)
from that we can calculate direction : (x1-x0, y1-y0, z1-z0) and normalize
Here is a picture
"A" vector is our ray origin - direction
the problem is how to throw the rays vertically and horizontally ?
(the blue arrows on the picture)
in my opinion we should calculate a "B" vector first (i dont know how...), then a "C" vector (from A and B cross product i think).
Then using B and C its easy to shoot rays...
My question :
is computation of B and C necessary or is there any other easy way to shoot rays ?
if its the best solution how can we calculate B ?
i know there might be an infinite possible B and C vector but if we define a Up vector like this (0,1,0) then only one B and C should be possible...
Lets say i have a curve defined by a equation (some kind of lissajous curve).
for any value of "t" i can get a (x,y,z) point.
Now I want to have a camera in a raytracer to follow that path.
Ray origin :
call f(t) and get a point : (x0,y0,z0)
Ray direction :
call f(t+delta) and get (x1,y1,z1)
from that we can calculate direction : (x1-x0, y1-y0, z1-z0) and normalize
Here is a picture
"A" vector is our ray origin - direction
the problem is how to throw the rays vertically and horizontally ?
(the blue arrows on the picture)
in my opinion we should calculate a "B" vector first (i dont know how...), then a "C" vector (from A and B cross product i think).
Then using B and C its easy to shoot rays...
My question :
is computation of B and C necessary or is there any other easy way to shoot rays ?
if its the best solution how can we calculate B ?
i know there might be an infinite possible B and C vector but if we define a Up vector like this (0,1,0) then only one B and C should be possible...
Get your side-vector by taking the cross-product of your front-vector (A) and your up-vector (B). Then get your proper up-vector by crossing your side and front vector.
I'll write a proper explenation in a second...
I'll write a proper explenation in a second...
Wait I'm not sure I understood your question completely, nvm.
Ok, so to get the vectors:
Given that you have:
* A direction (your A)
* A reference up position, for example (0, 1, 0)
You can get C from crossing A with (0, 1, 0).
Then, cross A and C to get the up-vector of the viewpoint, B.
Given that you have:
* A direction (your A)
* A reference up position, for example (0, 1, 0)
You can get C from crossing A with (0, 1, 0).
Then, cross A and C to get the up-vector of the viewpoint, B.
If you ever used gluLookAt, this is basically how it works.
Thx Lord Graga, basically its a lot simpler than what i tought.
maybe i should have figured out by myself...
maybe i should have figured out by myself...
Fuck yeah, I explained it right \o/
The basic problem is that there isn't enough information in the camera path to determine the roll of the camera. So you can't answer the question without more information.
A cheap solution is to define "up" to be the nearest direction to (0, 1, 0). That's unstable since then the camera can't look directly up or directly down. But it's easy and compact.
Another is to define it as the closest direction to "up" from the previous frame. This gives more freedom and less "weird" spinning but makes your camera orientation slightly dependent on framerate, plus of course changing the path in one place affects the roll in another, which may not be great for what you're doing. As a bonus you're free to add rolling whenever you think it looks awesome.
If you want full control you'll have to provide curves for the camera orientation, too.
A cheap solution is to define "up" to be the nearest direction to (0, 1, 0). That's unstable since then the camera can't look directly up or directly down. But it's easy and compact.
Another is to define it as the closest direction to "up" from the previous frame. This gives more freedom and less "weird" spinning but makes your camera orientation slightly dependent on framerate, plus of course changing the path in one place affects the roll in another, which may not be great for what you're doing. As a bonus you're free to add rolling whenever you think it looks awesome.
If you want full control you'll have to provide curves for the camera orientation, too.
you can also use the Frenet-Serret frame formulas (the BinNormal).
Your camera is at position A(t) = { x(t), y(t), z(t) }
Your camera direction D(t) is A'(t) = dA(t) / dt, ie, the derivative of A(t) ---> this is exactly what you computed when you evaluated normalize( A(t+delta) - A(t) ) for a small "delta".
Your camera "right" vector R(t) is the binormal A''(t). ie, the second derivative of A, which is the regular derivative of your camera direction D'(t) = dD(t)/dt.
So, you could do
camPos = f(t);
camDir = normalize( f(t+eps) - f(t) );
camRig = normalize( f(t+eps) - f(t)) - (f(t) - f(t-eps)) = f(t+eps) - 2*f(t) + f(t-eps) );
camUp = cross( camDir, camRig );
The problem with all this is that your camera rolls automatically as curves are taken, which is NOT what you might want from an artistic point of view. So it's better that you define an UP vector by yourself for every scene in the demo (and animate it probably) and do the cross product thing that Lord Graga explained to get your right vector.
Your camera is at position A(t) = { x(t), y(t), z(t) }
Your camera direction D(t) is A'(t) = dA(t) / dt, ie, the derivative of A(t) ---> this is exactly what you computed when you evaluated normalize( A(t+delta) - A(t) ) for a small "delta".
Your camera "right" vector R(t) is the binormal A''(t). ie, the second derivative of A, which is the regular derivative of your camera direction D'(t) = dD(t)/dt.
So, you could do
camPos = f(t);
camDir = normalize( f(t+eps) - f(t) );
camRig = normalize( f(t+eps) - f(t)) - (f(t) - f(t-eps)) = f(t+eps) - 2*f(t) + f(t-eps) );
camUp = cross( camDir, camRig );
The problem with all this is that your camera rolls automatically as curves are taken, which is NOT what you might want from an artistic point of view. So it's better that you define an UP vector by yourself for every scene in the demo (and animate it probably) and do the cross product thing that Lord Graga explained to get your right vector.
I implemented what Lord Graga suggested and yes, it worked beautifully, but as ♥ said, there is some problems when camera is looking up and down (i already noticed this before his post).
iq : I didnt know that Frenet-Serret equations, it seems really good, I will read about them and try as soon as i can.
iq : I didnt know that Frenet-Serret equations, it seems really good, I will read about them and try as soon as i can.
and also : its supposed (if its ever released :D) to be used in environment where size does matter, so there is a lot of chances that smallest working solution will be used