Hey all, I’m about to start making a HUD for my game ('bout time, considering how far along I am.) and I want an effect sort of like in Crysis 2, where when you pan or look up/down the HUD doesn’t instantaneously move with you. My original thought was to have an ArrayList field where I would add the HUDNode’s position and after 5 runs of the update loop put the HUD node at the 0’th field of the array, then remove the 0 and resize it so it’s got a diff. zero. Add another cam location, and repeat. Problem is this is probably very prone to memory leaks, null pointers, etc. etc. It’s just not the best way to do it. Anyone have any ideas?
Slerp was a Quaternion method, so how would I go about doing this? Plus, it doesn’t quite solve my question about getting the HUD Node’s position (in the guiNode space) to make sense with the cam.getDirection() which is in the rootNode space
I wasn’t too specific with what I was looking for, I realize. What I’m trying to say is I want a bit of a delay between when you change the look direction and when the HUD translates there. It gives a feeling of depth to the HUD, like it’s not just 2D simulated pictures on the screen but rather a projection of a HUD in front of you… or something like that. Either way I loved the effect it gave in Crysis 2 and other games, and I’d like to implement it myself.
Like it leaves behind trails or the movement just lags with camera movement? The latter is pretty trivial.
Keep a vector3f hudDirection.
Draw the hud using hudDirection to influence positioning.
if hudDirection != lookDirection then slerp hudDirection towards lookDirection.
Job done.
But how much delay would this give me? I assume I’d do that like the following:
[java]
Vector3f hudDir;
simpleUpdate(tpf) {
…
hudDir = hudNode.getLocalTranslation().normalizeLocal();
if(hudDir != cam.getDirection())
hudDir.slerp(cam.getDirection().clone());
…
}
[/java]
Something like that. I’m not at my work computer, I’m at school, so the slerp method is probably not just called slerp(Vector3f vector); but I’m sure it’s not that much different than what I’m guessing. Thanks for the help!
It would give you as much delay as you want.
Just be aware that you have various options for the sort of behaviour you want and different approaches will give you them.
For example if your movement is from 0->1 do you want:
0.2, 0.4, 0.6, 0.8, 1.0
or
0.5, 0.75, 0.825, 0.9125, etc
Both are easy to do, both can look good in the right situations.
I can’t remember off hand if slerp is quaternion, vector3f or both … I think it might be a quaternion function. The principle remains the same though.
Alright, well thanks! I’ll get to it now and post code for anyone who might find it useful!
There’s a bit of a problem with that code. The hudDir quaternion is never not equal to the camera direction because it’s rotation is based on the guiNode. It’s rotation is constantly the same, whereas the camera’s rotation is contantly changing with the world’s grid. I tried getWorldRotation() and getLocalRotation(), but both returned (0, 0, 0, 1). Sort of at a loss now, I’m trying to think if maybe I could do the node in 3D and try it…
Keep a direction vector that is slerped to the camera direction. Start it as the camera direction and then every frame use slerp to make it closer to the actual camera direction. If they are really similar then just make it the same.
This will be your “hud” direction.
With this direction vector, do a dot product with the camera’s left vector and a dot product with the camera’s up vector. Multiply these dot products by some amount to get your x, y displacement for your HUD. You will have to experiment a bit.
Sorry… I meant orientation. I’m getting the impression that this might be too hard for you but here goes some pseudo code…
[java]
Quaternion hudRotation…
someUpdate(float tpf) {
hudRotation.slerp(cam.getRotation(), catchUpSpeed * tpf);
// check to see if hudRotation is sufficiently close to cam.getRotation() and reset it
Vector3f dir = hudRotation.mult(Vector3f.UNIT_Z);
float x = dir.dot(cam.getLeft());
float y = dir.dot(cam.getUp());
hudNode.setLocalTranslation( someMultiplier * x, someMultipler * y, 0);
}
[/java]
If catchupSpeed is 1 then the HUD will take a little over a second to catch up (since it’s actually a factorial style progression).
The x might need to have its sign swapped. Or y does. someMultiplier should be the maximum number of pixels to swing the HUD if the camera does a 90 degree rotation.
I see, thanks a lot! So I could change my catch up speed to something more like 0.5f or something different and I’d get a varied result? Also, the multipliers could be tinkered to get a different result per x and y. Thanks a lot again!