• Welcome to Dark Bit Factory & Gravity.
 

Help with understanding demo source

Started by madeyes, July 03, 2016

Previous topic - Next topic

0 Members and 0 Guests are viewing this topic.

madeyes

Hi!
I'm going through the source code to the old Excess demo - Cortex Sous-vide for learning purposes (even though it is DirectX 9 the algorithms are still useful). I'm stuck on a method that is used in a few places to control the position of the camera and some other objects. I'm sure someone in here knows the theory behind this and can point me in the right direction. I'm not even sure what background reading to do.
Code is at the bottom of this post. The code should be understandable in isolation, but the full source is here https://github.com/kusma/vlee/tree/cortex-sous-vide
getCubePos is the method used to get the position for the camera in 3D. I have plotted out the points that would be returned from getCubeKeyframe in the attached image.
With this image, the getCubeKeyframe method makes a bit more sense to me.
The more confusing part to me is why 4 samples are taken, and what the tangents and those particular polynomials are for. I guess the polynomials are to make the path curved?

After a bit of research I think they are Hermite basis functions?

Thanks!
madeyes



Vector3 getCubeKeyframe(int key)
{
const Vector3 keyframes[] = {
Vector3(0,   0,   0),
Vector3(60,  0,   0),
Vector3(120, 0,   0),
Vector3(120, 60,  0),
Vector3(120, 120, 0),
Vector3(60,  120, 0),
Vector3(0,   120, 0),
Vector3(0,   120, 60),
Vector3(0,   120, 120),
Vector3(0,   60,  120),
Vector3(0,   0,   120),
Vector3(0,   0,   60),
Vector3(0,   0,   0),
Vector3(0,   0,  -60),
Vector3(0,   0,  -120),
Vector3(60,  0,  -120),
Vector3(120, 0,  -120),
Vector3(120,-60,  -120),
Vector3(120,-120,-120),
Vector3(60, -120,-120),
Vector3(0,  -120,-120),
Vector3(0,  -120,-60),
Vector3(0,  -120, 0),
Vector3(0,  -60, 0)
};
return keyframes[key % ARRAY_SIZE(keyframes)] * 0.5
   + keyframes[(key - 1) % ARRAY_SIZE(keyframes)] * 0.25
   + keyframes[(key + 1) % ARRAY_SIZE(keyframes)] * 0.25;
}

Vector3 getCubePos(float cam_time)
{
int k0 = int(floor(cam_time) - 1);
int k1 = k0 + 1;
int k2 = k1 + 1;
int k3 = k2 + 1;

Vector3 samples[4] = {
getCubeKeyframe(k0), getCubeKeyframe(k1), getCubeKeyframe(k2), getCubeKeyframe(k3)
};

Vector3 tangents[2] = {
(samples[2] - samples[0]) / 2.0,
(samples[3] - samples[1]) / 2.0
};

float t = cam_time - floor(cam_time);
float t2 = t * t;
float t3 = t2 * t;
float w[4] = {
// 2t^3 - 3t^2 + 1
2.0f * t3 - 3.0f * t2 + 1.0f,
// t^3 - 2t^2 + t
1.0f * t3 - 2.0f * t2 + t,
// -2t^3 + 3t^2
w[2] = -2.0f * t3 + 3.0f * t2,
// t^3 - t^2
w[3] =  1.0f * t3 - 1.0f * t2
};

return samples[1] * w[0] +
   tangents[0] * w[1] +
   samples[2] * w[2] +
   tangents[1] * w[3];
}

hellfire

#1
Quote from: madeyes on July 03, 2016
The more confusing part to me is why 4 samples are taken, and what the tangents and those particular polynomials are for.
If you just look at two adjacent points of the curve, you can't say much about the path in between.
All you can do is to draw a straight line (linear interpolation).
If you take the tangents into account, you know in what direction the path starts at the first point and in what direction it continues at the next point. That's all you need to make it a curve.
In this example the tangents are not explicitly given but simply point to the previous / the next point in the curve (that's why you're always looking at four points).
This simplified type is called catmull rom spline.
The w[] is just polynomial interpolation to make it "round".
Also have a look over here.
Challenge Trophies Won:

madeyes

Thanks for your help. I've got a lot of reading to do!