#Movement around a Sphere (3js & AmmoJS)

36 messages ยท Page 1 of 1 (latest)

lyric holly
#

Hello, I'm new to 3js and Ammo.js development and I seem to have hit a roadblock that I cannot figure out. Im a trying to have consistent movement around a sphere, using gravity(through ammo.js) to keep the character at the surface of the sphere. At the spawn point of origin the character, flashlight, and Camera, all behave as expected, but as I move down the sphere, the flashlight eventually morphs away, and when I get to the very bottom of the sphere the character rapidly spins no matter which direction I try to go (wasd). Any guidance, solutions, or tips for troubleshooting would be greatly appreciated. Here is my animation loop which I believe is the problem function of my code, and the planet (sphere) center is at (0, 50, 0):

The animate function:

lyric holly
#

this is the current set up: ``` const sphereRadius = 50; // Radius of the sphere

if (character) {
    const sphereCenter = new THREE.Vector3(0, sphereCenterY, 0);

    // Update local axes based on character's position
    localUp.copy(character.position).sub(sphereCenter).normalize();
    localRight.crossVectors(localForward, localUp).normalize();
    localForward.crossVectors(localUp, localRight).normalize();


    mouse.movementX = 0;

// Compute the position of the character on the sphere's surface

let fv2 = new THREE.Vector3(0, 0, -1);

fv2.crossVectors(localUp, localRight).normalize();

// Calculate the forward vector (desired horizontal rotation)
let forwardVector = new THREE.Vector3(0, 0, 1); // Adjust this as needed // problem area

// Calculate the quaternion to rotate the character's forward direction to the desired forward vector
let horizontalRotation = new THREE.Quaternion().setFromUnitVectors(fv2, forwardVector);

// Set the character's orientation directly
character.quaternion.copy(horizontalRotation);

// Calculate the new position based on the orientation
let velocityDirection = new THREE.Vector3(0, 0, 0);

if (keys.w) {
velocityDirection.add(localForward);
}
if (keys.s) {
velocityDirection.sub(localForward);
}
if (keys.a) {
velocityDirection.add(localRight);
}
if (keys.d) {
velocityDirection.sub(localRight);
}

velocityDirection.normalize();

// Apply character speed and update position directly
velocityDirection.multiplyScalar(characterSpeed);
character.position.add(velocityDirection);

// Make sure the character stays on the sphere's surface
character.position.sub(sphereCenter).normalize().multiplyScalar(sphereRadius).add(sphereCenter);

    character.forwardVector = localForward;```
#

there are no issues with the movement in the above snippet, only in the character to sphere surface up logic. Whenever I go forward the character tilts as if Im going backwards, and vice versa in every direction. The last abnormality occurs at 0, -50, 0(the bottom of the sphere) where the character does this strange flipping motion. Any guidance would be greatly appreciated, and let me know if there is anything else you need to know.

languid sonnet
#

Mmmkay. That's a decent start; let me chew on this a little bit, thank you!

languid sonnet
#

Can you get a short video of the flipping motion, by any chance? The motion tilt is probably not directly related to double-cover issues (though I'm still pondering that). If I had to guess I'd say that your issue at the pole is because of a breakdown in the tangent frame there; specifically that at that point your assumption that fv2 will be helpfully rotatable to (0, 0, -1) breaks down. (For instance, if fv2 turns out to actually be very close to (0, 0, -1) after the cross product then the Quaternion.setFromUnitVectors() operation will be super sensitive as to what its exact value is, because you're rotating from one side of a sphere to the almost directly opposite one.

lyric holly
#

yeah I can get you a vid in about 20 mins, not at my pc rn, but would the flipping be solved by changing a specific value or making the entire set up more dynamic?

languid sonnet
#

I think you might need to make the setup more dynamic.

#

In particular, the first thing that comes to mind is to keep the character's local frame and, rather than computing a global rotation, compute the local rotation, then multiply that with the character's current orientation to get its new one.

lyric holly
#

Alright I think I made it more dynamic, but I'm still getting the same tilting error, here is the video

#

it seems like it should be a flipped value somewhere thats causing the inverse directions but I've been troubleshooting this all day to no avail

languid sonnet
#

Ooof, yeah, I see what you mean.

#

Is your source available anywhere?

lyric holly
#

like the entire code file?

languid sonnet
#

nodnod

lyric holly
#

ahh I think I know you mean, like a github repo, or smth? I'm whipping up a codepen.io rn

languid sonnet
#

Yeah, exactly.

lyric holly
languid sonnet
#

Thanks! Will probably have to wait until tomorrow to take a look but I'll try and do it then.

lyric holly
#

have you noticed the error in my ways, lol

languid sonnet
#

I was just digging into it! Good timing. ๐Ÿ™‚ No good answer yet but.

lyric holly
#

sweet! just let me know if you need any clarification on anything

languid sonnet
#

Will do!

languid sonnet
#

Small update: I have a local version running based on the codepen and am debugging that. ๐Ÿ™‚

languid sonnet
#

Well, the fix for the tilting is so straightforward I probably should've realized it directly: you're computing the rotation quaternion backwards. Instead of let horizontalRotation = new THREE.Quaternion().setFromUnitVectors(localForward, forwardVector); you want let horizontalRotation = new THREE.Quaternion().setFromUnitVectors(forwardVector, localForward); . The other issue, though, takes a little more and I'm poking at that.

#

Whoops, almost. This still has the left/right tilt backwards. ๐Ÿ˜›

#

Oh! But that's happening because you rotate the character so their forward direction changes, but their right direction stays the same.

languid sonnet
#

I think I know what you want to do (you want to use Matrix4.makeBasis() to build a rotation matrix from your forward/up/right and either use that to generate the appropriate quaternion or just set the character's rotation directly) but it'll take me a little bit to get that right and I'm heading to bed for now.

lyric holly
#

Just now seeing this, thank you so much for your help!

lyric holly
#

I don't know if this helps but in my troubleshooting I found that: ```// Calculate the quaternion to rotate the character's forward direction to the desired forward vector
let horizontalRotation = new THREE.Quaternion().setFromUnitVectors(character.up, localUp);

// Set the character's orientation directly
character.quaternion.copy(horizontalRotation);``` always keeps the character pointing up in relation to the surface of the sphere, but it also makes the direction where the character is facing always trying to face the bottom center of the sphere.

languid sonnet
#

Augh, still being nerdsniped. ๐Ÿ˜› I did find one issue with your code, though: there are a few places where it acts as though Three is a left-handed coordinate system. For instance, in some of the camera positioning code that's there, it calculates a right vector as up ร— forwards, but in a right-handed system up ร— forwards points left, not right.

languid sonnet
#

Here's an updated/fixed version of the code โ€” there are still coordinate system issues that you'll want to fix, but. One of the big things I've done in a couple of places here is replace some by-hand calculations with the proper 3d versions of same โ€” wherever you can, you want to let THREE / linear algebra do the math for you. Have a look at how I did the camera offset right towards the end of the file to see the sort of thing I mean โ€” instead of finding up, forward, etc. and using them to manually position the camera '5 up, 4 forward' or whatnot, you can just define the offset vector in local space (in this case, that's [0, 5, -10]) and use the character's transformation matrix (specifically the rotation part of it) to turn that into a world-space offset vector that you then add to the character position to get the camera position.

lyric holly
#

wow

#

thank you so much in this endeavor, I had been trying to debug this for forever, if I end up releasing this you'll definitely been getting a shoutout. How did you learn so much about quanterions and 3js, I couldn't find any good resources about this subject online?

languid sonnet
#

Well, for 3JS it was mostly just reading the documentation to figure out exactly where the functionality I was looking for was hiding, but I knew the general operations I wanted. The quaternion / linear algebra knowledge in my case at least is just the result of long experience.

#

(Oh, and one other thing โ€” I added left and right arrow keys for rotation, as a bit more of an example; you might want to look at how I did that rotation.)