When mass is set to a positive integer, position is Nan and mass is undefined

58 views Asked by At

I've created a simple scene using cannon.js and three.js with a few meshes, but for some reason, when I set the mass of a mesh to any positive number, the position is set to Nan, and the mass is set to undefined.

I've tried to add an if statement to world.step(delta) so it only runs if delta > 0, but the objects appear only sometimes, and they don't have gravity. This is my code:

    import * as THREE from 'three'
    import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js'
    import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; // Import the GLTFLoader
  
    const scene = new THREE.Scene()
    //scene.add(new THREE.AxesHelper(5))
    const camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      1000
    )
    camera.position.set(0, 0, 0)

    const cameraDirection = new THREE.Vector3();

    window.onload = function() {
    renderer.domElement.requestPointerLock();

    renderer.domElement.onclick = function() {
    renderer.domElement.requestPointerLock();
    }
  };
    
    const renderer = new THREE.WebGLRenderer({
      alpha: true,
      antialias: true
    })
    renderer.shadowMap.enabled = true
    renderer.setSize(window.innerWidth, window.innerHeight)
    document.body.appendChild(renderer.domElement)

    const controls = new PointerLockControls(camera, renderer.domElement)
    controls.sensitivity = 0.1

    const world = new CANNON.World();
    world.gravity.set(0, -5, 0);

    const normalMaterial = new THREE.MeshNormalMaterial()
    const phongMaterial = new THREE.MeshPhongMaterial()

            const cubeGeometry = new THREE.BoxGeometry(1, 1, 1)
            const cubeMesh = new THREE.Mesh(cubeGeometry, normalMaterial)
            cubeMesh.position.x = -4
            cubeMesh.position.y = 3
            cubeMesh.castShadow = true
            scene.add(cubeMesh)
            const cubeShape = new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5))
            const cubeBody = new CANNON.Body({ mass: 1 })
            cubeBody.addShape(cubeShape)
            cubeBody.position.x = cubeMesh.position.x
            cubeBody.position.y = cubeMesh.position.y
            cubeBody.position.z = cubeMesh.position.z
            world.addBody(cubeBody)

            const sphereGeometry = new THREE.SphereGeometry()
            const sphereMesh = new THREE.Mesh(sphereGeometry, normalMaterial)
            sphereMesh.position.x = -2
            sphereMesh.position.y = 3
            sphereMesh.castShadow = true
            scene.add(sphereMesh)
            const sphereShape = new CANNON.Sphere(1)
            const sphereBody = new CANNON.Body({ mass: 1 })
            sphereBody.addShape(sphereShape)
            sphereBody.position.x = sphereMesh.position.x
            sphereBody.position.y = sphereMesh.position.y
            sphereBody.position.z = sphereMesh.position.z
            world.addBody(sphereBody)

            const floorGeometry = new THREE.BoxGeometry(10, 1, 10)
            const floorMesh = new THREE.Mesh(floorGeometry, normalMaterial)
            floorMesh.position.x = -4
            floorMesh.position.y = -2
            floorMesh.castShadow = true
            scene.add(floorMesh)
            const floorShape = new CANNON.Box(new CANNON.Vec3(5, 0.5, 5))
            const floorBody = new CANNON.Body({ mass: 0 })
            floorBody.addShape(floorShape)
            floorBody.position.x = floorMesh.position.x
            floorBody.position.y = floorMesh.position.y
            floorBody.position.z = floorMesh.position.z
            world.addBody(floorBody)

            const wall1Geometry = new THREE.BoxGeometry(10, 10, 1)
            const wall1Mesh = new THREE.Mesh(wall1Geometry, normalMaterial)
            wall1Mesh.position.x = -4
            wall1Mesh.position.y = 3.5
            wall1Mesh.position.z = 5.5
            wall1Mesh.castShadow = true
            scene.add(wall1Mesh)
            const wall1Shape = new CANNON.Box(new CANNON.Vec3(5, 5, 0.5))
            const wall1Body = new CANNON.Body({ mass: 0 })
            wall1Body.addShape(wall1Shape)
            wall1Body.position.x = wall1Mesh.position.x
            wall1Body.position.y = wall1Mesh.position.y
            wall1Body.position.z = wall1Mesh.position.z
            world.addBody(wall1Body)

            const wall2Geometry = new THREE.BoxGeometry(10, 10, 1)
            const wall2Mesh = new THREE.Mesh(wall2Geometry, normalMaterial)
            wall2Mesh.position.x = -4
            wall2Mesh.position.y = 3.5
            wall2Mesh.position.z = -5.5
            wall2Mesh.castShadow = true
            scene.add(wall2Mesh)
            const wall2Shape = new CANNON.Box(new CANNON.Vec3(5, 5, 0.5))
            const wall2Body = new CANNON.Body({ mass: 0 })
            wall2Body.addShape(wall2Shape)
            wall2Body.position.x = wall2Mesh.position.x
            wall2Body.position.y = wall2Mesh.position.y
            wall2Body.position.z = wall2Mesh.position.z
            world.addBody(wall2Body)

            const wall3Geometry = new THREE.BoxGeometry(1, 10, 10)
            const wall3Mesh = new THREE.Mesh(wall3Geometry, normalMaterial)
            wall3Mesh.position.x = 1.5
            wall3Mesh.position.y = 3.5
            wall3Mesh.castShadow = true
            scene.add(wall3Mesh)
            const wall3Shape = new CANNON.Box(new CANNON.Vec3(5, 5, 0.5))
            const wall3Body = new CANNON.Body({ mass: 0 })
            wall3Body.addShape(wall3Shape)
            wall3Body.position.x = wall3Mesh.position.x
            wall3Body.position.y = wall3Mesh.position.y
            wall3Body.position.z = wall3Mesh.position.z
            world.addBody(wall3Body)

            const wall4Geometry = new THREE.BoxGeometry(1, 10, 10)
            const wall4Mesh = new THREE.Mesh(wall4Geometry, normalMaterial)
            wall4Mesh.position.x = -9.5
            wall4Mesh.position.y = 3.5
            wall4Mesh.castShadow = true
            scene.add(wall4Mesh)
            const wall4Shape = new CANNON.Box(new CANNON.Vec3(5, 5, 0.5))
            const wall4Body = new CANNON.Body({ mass: 0 })
            wall4Body.addShape(wall4Shape)
            wall4Body.position.x = wall4Mesh.position.x
            wall4Body.position.y = wall4Mesh.position.y
            wall4Body.position.z = wall4Mesh.position.z
            world.addBody(wall4Body)

    const loader = new GLTFLoader();
    loader.load('untitled.glb', (gltf) => {
      const levelModel = gltf.scene;
      const scaleFactor = 0.1; // Adjust this value as needed
  levelModel.scale.set(scaleFactor, scaleFactor, scaleFactor);
      levelModel.position.set(-5, -1.9, -6);
      scene.add(levelModel);
    });

    const clock = new THREE.Clock()
            let delta

    class Box extends THREE.Mesh {
      constructor({
        width,
        height,
        depth,
        color = '#00ff00',
        velocity = {
          x: 0,
          y: 0,
          z: 0
        },
        position = {
          x: 0,
          y: 0,
          z: 0
        },
        zAcceleration = false
      }) {
        super(
          new THREE.BoxGeometry(width, height, depth),
          new THREE.MeshStandardMaterial({ color })
        )

        this.width = width
        this.height = height
        this.depth = depth
  
        this.position.set(position.x, position.y, position.z)
  
        this.right = this.position.x + this.width / 2
        this.left = this.position.x - this.width / 2
  
        this.bottom = this.position.y - this.height / 2
        this.top = this.position.y + this.height / 2
  
        this.front = this.position.z + this.depth / 2
        this.back = this.position.z - this.depth / 2
  
        this.velocity = velocity
        this.gravity = -0.002
  
        this.zAcceleration = zAcceleration
      }
  
      updateSides() {
        this.right = this.position.x + this.width / 2
        this.left = this.position.x - this.width / 2
  
        this.bottom = this.position.y - this.height / 2
        this.top = this.position.y + this.height / 2
  
        this.front = this.position.z + this.depth / 2
        this.back = this.position.z - this.depth / 2
        camera.position.copy(cube.position)
      }
  
      update(ground) {
        this.updateSides()
  
        if (this.zAcceleration) this.velocity.z += 0.0003
  
        this.position.x += this.velocity.x
        this.position.z += this.velocity.z
  
        this.applyGravity(ground)
      }
      applyGravity(ground) {
        this.velocity.y += this.gravity
  
        // this is where we hit the ground
        if (
          boxCollision({
            box1: this,
            box2: ground
          })
        ) {
          const friction = 0.5
          this.velocity.y *= friction
          this.velocity.x *= friction
          //this.velocity.y = -this.velocity.y
        } else this.position.y += this.velocity.y
        
      }
    }
  
    function boxCollision({ box1, box2 }) {
      const xCollision = box1.right >= box2.left && box1.left <= box2.right
      const yCollision =
        box1.bottom + box1.velocity.y <= box2.top && box1.top >= box2.bottom
      const zCollision = box1.front >= box2.back && box1.back <= box2.front
  
      return xCollision && yCollision && zCollision
    }
    const cube = new Box({
      width: 1,
      height: 1,
      depth: 1,
      velocity: {
        x: 0,
        y: -0.01,
        z: 0
      }
    })
    cube.castShadow = false
    scene.add(cube)
  
    const ground = new Box({
      width: 10,
      height: 0.5,
      depth: 50,
      color: '#0369a1',
      position: {
        x: 0,
        y: -2,
        z: 0
      }
    })
    ground.receiveShadow = true
    scene.add(ground)
  
    const light = new THREE.DirectionalLight(0xffffff, 1)
    light.position.y = 3
    light.position.z = 1
    light.castShadow = true
    scene.add(light)
  
    scene.add(new THREE.AmbientLight(0xffffff, 0.5))
  
    camera.position.z = 5
  
    const keys = {
      a: {
        pressed: false
      },
      d: {
        pressed: false
      },
      s: {
        pressed: false
      },
      w: {
        pressed: false
      }
    }
    window.addEventListener('keydown', (event) => {
      switch (event.code) {
        case 'KeyA':
          keys.a.pressed = true
          break
        case 'KeyD':
          keys.d.pressed = true
          break
        case 'KeyS':
          keys.s.pressed = true
          break
        case 'KeyW':
          keys.w.pressed = true
          break
        case 'Space':
          cube.velocity.y = 0.08
          break
      }
    })
  
    window.addEventListener('keyup', (event) => {
      switch (event.code) {
        case 'KeyA':
          keys.a.pressed = false
          break
        case 'KeyD':
          keys.d.pressed = false
          break
        case 'KeyS':
          keys.s.pressed = false
          break
        case 'KeyW':
          keys.w.pressed = false
          break
      }
    })
  
    let frames = 0

    function animate() {
      const animationId = requestAnimationFrame(animate)
      renderer.render(scene, camera)

      delta = Math.min(clock.getDelta(), 0.1)
      world.step(delta);

      camera.getWorldDirection(cameraDirection);

          // Copy coordinates from Cannon to Three.js
                cubeMesh.position.set(cubeBody.position.x, cubeBody.position.y, cubeBody.position.z)
                cubeMesh.quaternion.set(
                    cubeBody.quaternion.x,
                    cubeBody.quaternion.y,
                    cubeBody.quaternion.z,
                    cubeBody.quaternion.w
                )
                sphereMesh.position.set(sphereBody.position.x, sphereBody.position.y, sphereBody.position.z)
                sphereMesh.quaternion.set(
                    sphereBody.quaternion.x,
                    sphereBody.quaternion.y,
                    sphereBody.quaternion.z,
                    sphereBody.quaternion.w
                )
                console.log(cubeMesh.position, cubeMesh.mass, sphereMesh.position, sphereMesh.mass)

      // movement code
      const movement = new THREE.Vector3();

// Check for key presses and update movement vector
if (keys.d.pressed) {
      movement.x -= cameraDirection.z;
      movement.z += cameraDirection.x;
    }
    if (keys.a.pressed) {
      movement.x += cameraDirection.z;
      movement.z -= cameraDirection.x;
    }
    if (keys.s.pressed) {
      movement.x -= cameraDirection.x;
      movement.z -= cameraDirection.z;
    }
    if (keys.w.pressed) {
      movement.x += cameraDirection.x;
      movement.z += cameraDirection.z;
    }

    const slideForce = 0.2; // Adjust this value to control the sliding force

if (keys.d.pressed) {
  const force = new CANNON.Vec3(slideForce, 0, 0);
  cubeBody.applyImpulse(force, cubeBody.position);
}
if (keys.a.pressed) {
  const force = new CANNON.Vec3(-slideForce, 0, 0);
  cubeBody.applyImpulse(force, cubeBody.position);
}
if (keys.s.pressed) {
  const force = new CANNON.Vec3(0, 0, slideForce);
  cubeBody.applyImpulse(force, cubeBody.position);
}
if (keys.w.pressed) {
  const force = new CANNON.Vec3(0, 0, -slideForce);
  cubeBody.applyImpulse(force, cubeBody.position);
}

    // Normalize the movement vector if needed
    if (movement.length() > 0) {
      movement.normalize();
    }

    // Apply movement vector to the cube's velocity
    cube.velocity.x = movement.x * 0.05;
    cube.velocity.z = movement.z * 0.05;
      
    cube.update(ground);


      frames++
    }
    animate()

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

There are 0 answers