Helps in the movement of the spacecraft

I’ve been having a problem for 3 days, I’m trying to do this continuous direction tracking for my ship, however in the video you can see that the movement is a bit wrong, it changes directions and inverts some things, I’m trying to replicate the same flight tracking as some games but this is bothering me, any help is welcome

2023-11-28 19-06-25.mkv (4.0 MB)

The type of control I need you can see here in this game:

you have to post code to help. But my first guess is the camera has controls on it, of which its doing a .lookAt() constantly to a target thats not updating to the view so when it flips it reflips itself to be upright

Instead use your viewing target as its target and add some easing. Look at the source of of the various Controls three.js docs
Scroll to the bottom of each page and click its source link

Excuse me, I’ll send the code below, researching on my own I discovered that the problem is because of the gigantic sizes, but shrinking is not an option for me because I need it, the real problem is how shaky the ship is.

import * as THREE from “./modules/three.module.js”;
import { OrbitControls } from “./modules/OrbitControls.js”;
import { Lensflare, LensflareElement } from ‘./modules/Lensflare.js’;
import { UnrealBloomPass } from ‘./modules/UnrealBloomPass.js’;
import { RenderPass } from ‘./modules/RenderPass.js’;
import { GLTFLoader } from ‘./modules/GLTFLoader.js’;
import { EffectComposer } from ‘./modules/EffectComposer.js’;

let scene, camera, renderer;
let planets = {};
let bloomPass;
let composer;
let escalaModelo = 0.1;
let moons = {};
let velocidadeDaLuz = false;
let currentControls;
let startTime;
let spaceship;
let spaceshipSpeed = 0;
let cameraDistance = 0.0001;
let targetCameraDistance = 3;
let spaceshipAccelerating = false;

let spaceshipControls;
let clock = new THREE.Clock();

function init() {
setupScene();
setupCamera();
setupRenderer();
loadSpaceshipModel();
createPlanets();
createSun();
startTime = Date.now();

spaceshipControls = {
    moveForward: false,
    moveBackward: false,
    rotateLeft: false,
    rotateRight: false,
};



document.addEventListener('keydown', onKeyDown);
document.addEventListener('keyup', onKeyUp);

}

const listener = new THREE.AudioListener();

const ambientSound = new THREE.Audio(listener);

const ambientSoundLoader = new THREE.AudioLoader();
ambientSoundLoader.load(‘./deep-space-ambiance-48854.mp3’, (buffer) => {
ambientSound.setBuffer(buffer);
ambientSound.setLoop(true);
ambientSound.setVolume(1);
ambientSound.play();
});

function setupScene() {
scene = new THREE.Scene();
}

function setupCamera() {
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.0001, 10000000000000);
camera.position.set(0, 5, -10);
}

function setupRenderer() {
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: false
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
}

function loadSpaceshipModel() {
const loader = new GLTFLoader();
const listener = new THREE.AudioListener();

loader.load('./nave/scene.gltf', (gltf) => {
    spaceship = gltf.scene;
    scene.add(spaceship);

    spaceship.position.set(0, 0, 0);
    spaceship.scale.set(0.00001, 0.00001, 0.00001);

    const mixer = new THREE.AnimationMixer(spaceship);

    gltf.animations.forEach((clip) => {
        mixer.clipAction(clip).play();
    });

    scene.mixer = mixer;

    scene.add(listener);

    const accelerationSound = new THREE.Audio(listener);
    const speedSound = new THREE.Audio(listener);

    spaceship.add(accelerationSound);
    spaceship.add(speedSound);

    const accelerationSoundLoader = new THREE.AudioLoader();
    const speedSoundLoader = new THREE.AudioLoader();

    accelerationSoundLoader.load('./spacecraft-engine-loop-01-58205.mp3', (buffer) => {
        accelerationSound.setBuffer(buffer);
        accelerationSound.setLoop(false);
        accelerationSound.setVolume(1);
    });

    speedSoundLoader.load('./alien-ship-takeoff-28339.mp3', (buffer) => {
        speedSound.setBuffer(buffer);
        speedSound.setLoop(false);
        speedSound.setVolume(1);
    });
});

}
const cameraSmoothingFactor = 0.1;
let cameraTargetPosition = new THREE.Vector3();

function lateUpdateCamera() {
if (spaceship) {
cameraTargetPosition.copy(spaceship.position);
}

camera.position.lerp(cameraTargetPosition, 0.01); 

const forwardDirection = new THREE.Vector3(0, 0, 1);
forwardDirection.applyQuaternion(spaceship.quaternion);
const lookAtPosition = new THREE.Vector3().addVectors(camera.position, forwardDirection);
camera.lookAt(lookAtPosition);

}

function animateSpaceship() {
if (spaceship) {
const acceleration = 5000;
const deceleration = 0.01;
const maxSpeed = velocidadeDaLuz ? 29979245860 : 1000000;
const maxCameraDistance = 0.0005;
const minCameraDistance = 0.0002;
const zoomSpeed = 0.005;

    if (spaceshipAccelerating) {
        if (velocidadeDaLuz) {
            spaceshipSpeed = maxSpeed;
        } else {
            spaceshipSpeed += acceleration;
        }
    } else {
        spaceshipSpeed -= deceleration * spaceshipSpeed;
    }

    spaceshipSpeed = Math.max(spaceshipSpeed, 0);
    spaceshipSpeed = Math.min(spaceshipSpeed, maxSpeed);

    const direction = new THREE.Vector3(0, 0, 1);
    direction.applyQuaternion(spaceship.quaternion);
    spaceship.position.add(direction.multiplyScalar(spaceshipSpeed * clock.getDelta()));

    targetCameraDistance = minCameraDistance + (maxCameraDistance - minCameraDistance) * (spaceshipSpeed / maxSpeed);
    cameraDistance += (targetCameraDistance - cameraDistance);

    const cameraOffset = new THREE.Vector3(0, 0.00001, -cameraDistance);
    const relativeCameraOffset = cameraOffset.applyQuaternion(spaceship.quaternion);
    const cameraPosition = spaceship.position.clone().add(relativeCameraOffset);

    camera.position.copy(cameraPosition);

    const forwardDirection = new THREE.Vector3(0, 0, 1);
    forwardDirection.applyQuaternion(spaceship.quaternion);
    const lookAtPosition = new THREE.Vector3().addVectors(spaceship.position, forwardDirection);

    const upDirection = new THREE.Vector3(0, 1, 0);
    upDirection.applyQuaternion(spaceship.quaternion);
    camera.up.copy(upDirection);

    camera.lookAt(lookAtPosition);

    spaceship.rotation.z = 0;

    spaceship.children[1].setVolume(spaceshipSpeed / maxSpeed);

    if (spaceshipSpeed > 0 && !spaceship.children[1].isPlaying) {
        spaceship.children[1].play();
    } else if (spaceshipSpeed === 0 && spaceship.children[1].isPlaying) {
        spaceship.children[1].pause();
    }

    const spaceshipSpeedKM = spaceshipSpeed * escalaModelo;
    document.getElementById('velocidadeNave').textContent = spaceshipSpeedKM.toFixed(0) + ' KM/S';
}

}

function onKeyDown(event) {
switch (event.code) {
case ‘KeyW’:
spaceshipAccelerating = true;
break;
case ‘KeyF’:
toggleSpeedOfLight();
break;
}
}

function toggleSpeedOfLight() {
if (velocidadeDaLuz) {
velocidadeDaLuz = false;
spaceshipSpeed = 0;
spaceship.visible = camera.position.distanceTo(spaceship.position) < 100000;
} else {
velocidadeDaLuz = true;
spaceshipSpeed = 299792;
spaceship.visible = true;
}
}

function onKeyUp(event) {
switch (event.code) {
case ‘KeyW’:
spaceshipAccelerating = false;
break;
}
}

let crosshairX = 0;
let crosshairY = 0;
let azimuth = 0;
let inclination = 0;
function updateSpaceshipRotation() {
if (spaceship) {
const rotationSpeed = 0.1;

    const mouseXNormalized = (crosshairX / window.innerWidth) * 2 - 1;
    const mouseYNormalized = (crosshairY / window.innerHeight) * 2 - 1;

    azimuth += rotationSpeed * mouseXNormalized;
    inclination -= rotationSpeed * mouseYNormalized; 

    const forward = new THREE.Vector3(
        Math.sin(azimuth) * Math.cos(inclination),
        Math.sin(inclination),
        Math.cos(azimuth) * Math.cos(inclination)
    );

    const right = new THREE.Vector3(-forward.z, 0, forward.x).normalize();
    const up = new THREE.Vector3().crossVectors(forward, right).normalize();

    spaceship.matrix.identity();
    spaceship.matrix.makeBasis(right, up, forward);
    spaceship.rotation.setFromRotationMatrix(spaceship.matrix);
}

}

document.addEventListener(‘mousemove’, (event) => {
crosshairX = event.clientX;
crosshairY = event.clientY;

const deltaX = crosshairX - window.innerWidth / 2;
const deltaY = crosshairY - window.innerHeight / 2;

});

const crosshair = document.getElementById(‘crosshair’);
document.addEventListener(‘mousemove’, (event) => {
crosshair.style.left = ${crosshairX - crosshair.clientWidth / 2}px;
crosshair.style.top = ${crosshairY - crosshair.clientHeight / 2}px;
});

function createPlanet(options) {
const { radius, texturePath, orbitRadius, rotationSpeed, inclination, colorLine, axialTilt, AxialRotate, orbitalPeriod, axialPeriod } = options;
const planet = createSphere(radius, texturePath);

planet.orbitRadius = orbitRadius * 5000;
planet.rotationSpeed = rotationSpeed;
planet.inclination = inclination;
planet.AxialRotate = AxialRotate;
planet.axialTilt = axialTilt;
planet.orbitalPeriod = orbitalPeriod; 
planet.axialPeriod = axialPeriod; 
planet.castShadow = true;
planet.receiveShadow = true;


const initialPosition = options.initialPosition || new THREE.Vector3(0, 0, 0);
planet.positionOffset = options.positionOffset || new THREE.Vector3(0, 0, 0);


planet.position.copy(initialPosition);

if (options.parentPlanet) {
    options.parentPlanet.add(planet);
} else {
    scene.add(planet);
}

planet.orbitLineColor = options.colorLine || 0xFFFFFF;

planet.scale.set(radius, radius, radius);
planet.rotation.x = inclination;

if (options.moons) {
    planet.moons = options.moons;
    moons = { ...moons, ...options.moons.reduce((acc, moon) => ({ ...acc, [moon.id]: moon }), {}) };
}

return planet;

}

function createMoon(parentPlanet, options) {
const {
id,
radius,
texturePath,
orbitRadius1,
rotationSpeed,
inclination1,
axialTilt,
orbitalPeriod,
axialPeriod,
moonOptions,
} = options;

const moon = createPlanet({
    id,
    radius,
    texturePath,
    orbitRadius: orbitRadius1,
    rotationSpeed,
    orbitalPeriod,
    axialPeriod,
    axialTilt,
    inclination: inclination1,
});

parentPlanet.add(moon);

moons[id] = moon;

if (moonOptions && moonOptions.showOrbitLine) {
    createMoonOrbitLine(moon, moonOptions.orbitRadius, moonOptions.inclination, moonOptions.colorLine);
}

return moon;

}

function createSun() {
const sunGeometry = new THREE.SphereGeometry(696340 * 5000, 64, 64);

const textureLoader = new THREE.TextureLoader();
const sunTexture = textureLoader.load(‘/images/sun_present.png’);

const sunMaterial = new THREE.MeshBasicMaterial({
map: sunTexture,
transparent: true,
});

const sun = new THREE.Mesh(sunGeometry, sunMaterial);
sun.position.set(0, 0, 0);

const renderScene = new RenderPass(scene, camera);
const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 2, 0, 0.3);
composer = new EffectComposer(renderer);
composer.addPass(renderScene);
composer.addPass(bloomPass);


scene.add(sun);

const textureFlare0 = textureLoader.load("./images/sunligh1.png");
const lensflare = new Lensflare();
lensflare.addElement(new LensflareElement(textureFlare0, 10, 0));
lensflare.renderOrder = 0; 
scene.add(lensflare);

const sunLight = new THREE.PointLight(0xffffff, 2, 10000000000000000);
sunLight.position.set(0, 0, 0);
sunLight.castShadow = true;
sunLight.shadow.mapSize.width = 2048;
sunLight.shadow.mapSize.height = 2048;
sunLight.shadow.camera.left = -sunLight.distance;
sunLight.shadow.camera.right = sunLight.distance;
sunLight.shadow.camera.top = sunLight.distance;
sunLight.shadow.camera.bottom = -sunLight.distance;

sunLight.decay = 0; 
scene.add(sunLight);
return sun;

}

function createPlanets() {
planets.mercury = createPlanet({ radius: 2349, texturePath: ‘/images/planetas/mercurio.jpg’, orbitRadius: 57910000, rotationSpeed: 0.000000005, inclination: 0.0701, axialTilt: 0.034,colorLine: 0x800080, orbitalPeriod: 88 * 24 * 60 * 60, axialPeriod: 58.65 * 24 * 60 * 60, initialPosition: new THREE.Vector3(-4600120 , 0 , -6981690), positionOffset: new THREE.Vector3(-4600120, 0, -6981690)});
planets.venus = createPlanet({ radius: 6051, texturePath: ‘/images/planetas/venus.jpg’, orbitRadius: 108200000, rotationSpeed: 0.000000005, inclination: 0.0339, axialTilt: 0.177, colorLine: 0xCCCC00, orbitalPeriod: 225 * 24 * 60 * 60, axialPeriod: -116.75 * 24 * 60 * 60, initialPosition: new THREE.Vector3(10747600, 0, 10894200), positionOffset: new THREE.Vector3(10747600, 0, 10894200)});
planets.earth = createPlanet({ radius: 6378, texturePath: ‘./images/planetas/terra day.jpg’, orbitRadius: 149600000, rotationSpeed: 0.000000002, inclination: 0, axialTilt: 0, colorLine: 0x0000FF, orbitalPeriod: 365 * 24 * 60 * 60, axialPeriod: 1 * 24 * 60 * 60, initialPosition: new THREE.Vector3(14709829, 0, 15209823), positionOffset: new THREE.Vector3(14709829, 0, 15209823)});
planets.earth.moons = [
createMoon(planets.earth, { id: “lua”, radius: 1737, texturePath:‘./images/luas/moon2.jpg’, orbitRadius1: 3840, rotationSpeed: 0.0005, inclination1: 0.0514, axialTilt: 0.2, orbitalPeriod: 0.0005 * 24 * 60 * 60, axialPeriod: 27.32 * 24 * 60 * 60, moonOptions: {
showOrbitLine: true,
orbitRadius: 305,
inclination: 0.0514,
colorLine: 0xFFFF,
},}),
];

planets.mars = createPlanet({ radius: 3396, texturePath: '/images/planetas/marte.jpg', orbitRadius: 227940000, rotationSpeed: 0.000000000002, inclination: 0.0185, axialTilt: 0.25,colorLine: 0x800000, orbitalPeriod: 687 * 24 * 60 * 60, axialPeriod: 1.03 * 24 * 60 * 60, initialPosition: new THREE.Vector3(-20666900, 0, 24920930),  positionOffset: new THREE.Vector3(-20666900, 0, 24920930)});
planets.jupiter = createPlanet({ radius: 71492, texturePath: './images/planetas/jupiter.jpg', orbitRadius: 778330000, rotationSpeed: 0.0000000000000002, inclination: 0.0131, axialTilt: 0.3, colorLine: 0x8B4513, orbitalPeriod: 4333 * 24 * 60 * 60, axialPeriod: 0.41 * 24 * 60 * 60, initialPosition: new THREE.Vector3(74057360, 0, 81652080),  positionOffset: new THREE.Vector3(74057360, 0, 81652080)});
planets.jupiter.moons = [
    createMoon(planets.jupiter, { id: "io", radius: 3.642, texturePath:'./images/luas/luas jupiter/io.jpg', orbitRadius1: 42170,rotationSpeed: 0.0005, inclination1: 0, orbitalPeriod: 0.005 * 24 * 60 * 60, axialPeriod: 1.77 * 24 * 60 * 60, moonOptions: {
        showOrbitLine: true,
        orbitRadius: 301.5,
        inclination: 0,
        colorLine: 0xFFFF, 
    },}),
    createMoon(planets.jupiter, { id: "europa", radius: 3.131, texturePath:'./images/luas/luas jupiter/europa.jpg', orbitRadius1: 67103,rotationSpeed: 0.0005, inclination1: 0, axialTilt: 0.2 ,orbitalPeriod: 3.55 * 24 * 60 * 60, axialPeriod: 3.55 * 24 * 60 * 60 }),
    createMoon(planets.jupiter, { id: "ganymedes", radius: 5.268, texturePath:'./images/luas/luas jupiter/ganymedes.jpg', orbitRadius1:  107041,rotationSpeed: 0.0005, inclination1: 0, orbitalPeriod: 7.15 * 24 * 60 * 60, axialPeriod: 7.15 * 24 * 60 * 60 }),
    createMoon(planets.jupiter, { id: "calisto", radius: 4.820, texturePath:'./images/luas/luas jupiter/callisto.jpg', orbitRadius1:  188270,rotationSpeed: 0.0005, inclination1: 0, orbitalPeriod: 16.69 * 24 * 60 * 60, axialPeriod: 16.69 * 24 * 60 * 60 }),
];
planets.saturn = createPlanet({ radius: 60268, texturePath: './images/planetas/saturno.jpg', orbitRadius: 1429400000, rotationSpeed: 0.0000000000000002, inclination: 0.0249, colorLine: 0xCD853F, axialTilt: 0.26,orbitalPeriod: 10759 * 24 * 60 * 60, axialPeriod: 0.43 * 24 * 60 * 60, initialPosition: new THREE.Vector3(135357295, 0, 151332578),  positionOffset: new THREE.Vector3(135357295, 0, 151332578)});
planets.urano = createPlanet({ radius: 25559 , texturePath: './images/planetas/urano.jpg', orbitRadius: 2870990000, rotationSpeed: 0.0000000000000002, inclination: 0.0077, colorLine: 0x008B8B, axialTilt: 0.82,orbitalPeriod: 30687 * 24 * 60 * 60, axialPeriod: -0.72 * 24 * 60 * 60, initialPosition: new THREE.Vector3(274893846, 0, 300441970),  positionOffset: new THREE.Vector3(274893846, 0, 300441970)});
planets.netuno = createPlanet({ radius: 24764, texturePath: './images/planetas/netuno.jpg', orbitRadius: 4504300000, rotationSpeed: 0.0000000000000002, inclination: 0.0177 , colorLine: 0x000080, axialTilt: 0.28,orbitalPeriod: 60190 * 24 * 60 * 60, axialPeriod: 0.67 * 24 * 60 * 60,  initialPosition: new THREE.Vector3(445294083, 0, 455394649),  positionOffset: new THREE.Vector3(445294083, 0, 455394649)});
for (const planetKey in planets) {
    if (planets.hasOwnProperty(planetKey)) {
        const planet = planets[planetKey];
        createPlanetOrbitLine(planet, planet.orbitRadius, planet.inclination, planet.colorLine);
    }
}

scene.add(planets.mercury, planets.venus, planets.earth, ...planets.earth.moons, planets.mars, planets.jupiter, ...planets.jupiter.moons,planets.saturn, planets.urano, planets.netuno);

}

function createSphere(radius, texturePath) {
const geometry = new THREE.SphereGeometry(radius, 64, 64);
const texture = new THREE.TextureLoader().load(texturePath);
const material = new THREE.MeshStandardMaterial({
map: texture,
metalness: 1,
depthWrite: false,
opacity: 1,
transparent: true,
});

const object = new THREE.Mesh(geometry, material);
texture.castShadow = true;
texture.receiveShadow = true;

return object;

}

function createMoonOrbitLine(parentObject, orbitRadius, inclination, lineColor) {
const points = ;
const parentPosition = parentObject.parent.position.clone();

for (let i = 0; i <= 360; i += 0.2) {
    const angle = i * (Math.PI / 180);
    const x = orbitRadius * Math.cos(angle);
    const z = orbitRadius * Math.sin(angle);
    const y = orbitRadius * Math.sin(inclination) * Math.cos(angle);

    points.push(new THREE.Vector3().copy(parentPosition).add(new THREE.Vector3(x, y, z)));
}

const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ color: new THREE.Color(lineColor) });
const line = new THREE.Line(geometry, material);

parentObject.parent.add(line);
return line;

}

function createPlanetOrbitLine(planet) {
const lineColor = planet.orbitLineColor || 0xFFFFFF;

const points = [];
const planetPosition = planet.position.clone();

for (let i = 0; i <= 360; i += 0.2) {
    const angle = i * (Math.PI / 180);
    const x = planet.orbitRadius * Math.cos(angle);
    const z = planet.orbitRadius * Math.sin(angle);
    const y = planet.orbitRadius * Math.sin(planet.inclination) * Math.cos(angle);

    points.push(new THREE.Vector3().copy(planetPosition).add(new THREE.Vector3(x, y, z)));
}

const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ color: new THREE.Color(lineColor) });
const line = new THREE.Line(geometry, material);

scene.add(line);

return line;

}

function updateOrbitingObjectPosition(object, parentObject, startTime) {
const timeElapsed = (Date.now() - startTime) / 1000;
const orbitalAngle = (timeElapsed object.orbitalPeriod) / object.orbitalPeriod * 2 * Math.PI; const axialAngle = (timeElapsed object.axialPeriod) / object.axialPeriod * 2 * Math.PI;

const inclinationAngle = object.inclination;

if (parentObject) {
    const xWithoutOffset = parentObject.position.x + object.orbitRadius * Math.cos(orbitalAngle);
    const zWithoutOffset = parentObject.position.z + object.orbitRadius * Math.sin(orbitalAngle);
    const yWithoutOffset = parentObject.position.y + object.orbitRadius * Math.sin(inclinationAngle) * Math.cos(orbitalAngle);

    const x = xWithoutOffset + object.positionOffset.x;
    const z = zWithoutOffset + object.positionOffset.z;
    const y = yWithoutOffset + object.positionOffset.y;

    object.position.set(x, y, z);
    object.rotation.x = inclinationAngle + axialAngle;
    
}
if (!object.visible) {
    // Defina a visibilidade do objeto com base na sua posição
    object.visible = camera.position.distanceTo(object.position) < 100000;
}

}

function focusCameraOnPlanet(planetId) {
selectedMoonId = null;
selectedPlanetId = planetId;

if (planetId && planets[planetId]) {
    const selectedPlanet = planets[planetId];

    currentControls.target.copy(selectedPlanet.position);
}

}

function focusMoon(moonId) {
selectedPlanetId = null;
selectedMoonId = moonId;

if (moonId && moons[moonId]) {
    const selectedMoon = moons[moonId];
    camera.lookAt(selectedMoon.position);
    currentControls.target = selectedMoon.position;
}

}

function animate() {
requestAnimationFrame(animate);
animateSpaceship();
updateSpaceshipRotation();
lateUpdateCamera();
for (const planet in planets) {
if (planets.hasOwnProperty(planet)) {
const obj = planets[planet];
updateOrbitingObjectPosition(obj, scene, startTime);
if (obj.moons) {
obj.moons.forEach((moon, index) => {
updateOrbitingObjectPosition(moon, obj, startTime);
});
}
}
}

composer.render();

window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  });

}

init();
animate();

I solved the ship’s orientation problem, however this problem of her having agitation and tremors has been bothering me for days

It will help everyone if you use an online service like https://jsfiddle.net to post examples with in the future.
Also you dont need to post the whole thing. Think of the issue in the smallest form, a ship, a cursor, movement, a grid to help know of space

Sorry, I’ll explain better, I have a problem, and it’s simple, my ship changes its direction following the aim I set. However, when it goes up, instead of just continuing and turning around, it reaches a point where it simply reverses instead of continuing. I will leave the relevant part of the code and the video showing this.

let crosshairX = 0;
let crosshairY = 0;
let azimuth = 0;
let inclination = 0;
function updateSpaceshipRotation() {
if (spaceship) {
const rotationSpeed = 0.1;

    const mouseXNormalized = (crosshairX / window.innerWidth) * 2 - 1;
    const mouseYNormalized = (crosshairY / window.innerHeight) * 2 - 1;

    azimuth += rotationSpeed * mouseXNormalized;
    inclination -= rotationSpeed * mouseYNormalized; 

    const forward = new THREE.Vector3(
        Math.sin(azimuth) * Math.cos(inclination),
        Math.sin(inclination),
        Math.cos(azimuth) * Math.cos(inclination)
    );

    const right = new THREE.Vector3(-forward.z, 0, forward.x).normalize();
    const up = new THREE.Vector3().crossVectors(forward, right).normalize();

    spaceship.matrix.identity();
    spaceship.matrix.makeBasis(right, up, forward);
    spaceship.rotation.setFromRotationMatrix(spaceship.matrix);
}

}

2023-11-29 22-08-25.mkv (5.9 MB)

You should console log the right up and forward values and look for funky jump numbers when the bug occurs.
OR another way, isolate the axis it happens on by setting up a different view with the camera and feed it the same idea of the math to see how that behaves

Going on the first, lets say to feed ONLY the axis inclination
Is crosshairXY in screen space?
crosshairX = window.innerWidth / 2 or center of screen
crosshairY = ( window.innerHeight / 2 ) - 100px for the cursor is upwards

crosshairX = 0
crosshairY = 285.5

mouseYNormalized = 285.5 * 2 - 1; = 570
mouseXNormalized = 0 * 2 - 1; = 0

mouseYNormalized here at 570 is not normalized then

inclination += rotationSpeed = 0.2 * mouseYNormalized = 1
azimuth += 0.2 * 0
so x = Math.sin(0) * Math.cos(inclination)

So we cant feed Math.sin 0 cause thats * 0 always

so lets just say azimuth every frame is +0.1
and inclination is - 0.1

var azimuth = 0;
var inclination = 0;
for (var i = 0; i < 40; i++) {
  console.log("x", Math.sin(azimuth) * Math.cos(inclination) );
  console.log("y", Math.sin(inclination) );
  console.log("z", Math.cos(azimuth) * Math.cos(inclination) );
  console.log("+++++++++");
  azimuth += 0.1;
  inclination -= 0.1;
}

Punching in values to graphing desmos
(tweaked calcs to add vars)

Lets say the inclination is very low
around the mid you can see how its flattening all of the curves


at this point I could be totes wrong, but thats how I debug things, its all just number pushing

notice here the wave pattern of the curves, black then red until it starts to flatten then it flips before flatten, maybe thats just teh optical of the image

Thank you, I had already suspected that as the sine value reached 0 it ended up inverting the directions, so I used the quaternion to rotate Y and aziumte for X, I merged the 2 and in this workaround I made each one control an axis.

image

CODE

    const quaternion = new THREE.Quaternion();
    quaternion.setFromAxisAngle(new THREE.Vector3(0, 1, 0), azimuth);
    quaternion.multiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), inclination));

    spaceship.quaternion.copy(quaternion);

I’ll leave a video of how it turned out

2023-11-30 11-41-45.mkv (7.5 MB)