Having to Pass Ammo as an arguament to function

I’m introducing myself to Three.js and Ammo.js and I’m having some issues writing functions.
So, I’m sure I’m doing something novice here, but I’m at a bit of a loss.

When I’m calling Ammo constructors within functions, I’m having to pass Ammo as an arguament to the function - is this expected behaviour?

If I don’t include it, I get an error stating that “X is not a valid constructor”

Any pointers are greatly appreciated!

I’m only working in the main.js file as below:

// Style import
import './style.css'
// THREE import
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
// AMMO import
import Ammo from './js/ammo'

// Globals
var physicsWorld        = undefined;
var clock               = new THREE.Clock();
var scene               = undefined;
var camera              = undefined;
var renderer            = undefined;
var rigidBodyList       = new Array();
var tmpTransformation   = undefined;

// ====================== FUNCTIONS =======================

function QuaternionFromAxis(Ammo, x, y, z, a) {
  // Calculate sin(theta/2)
  let factor = Math.sin(a/2.0);
  // Calculate x, y and z of quaternion
  let Qx = x*factor;
  let Qy = y*factor;
  let Qz = z*factor;
  let Qw = Math.cos(a/2.0);

  let quaternion = new Ammo.btQuaternion(Qx, Qy, Qz, Qw);
  return quaternion
}

function randomColour() {
  let colour = Math.floor(Math.random()*(255 + 1)) * 0xffffff;
  return colour
}

// ======================= THREE.JS =======================

function setupGraphicsWorld() {
  // Clock setup
  clock     = new THREE.Clock();

  // Scene setup
  scene     = new THREE.Scene();

  // Camera setup
  camera    = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
  let CameraPosition = 30;
  camera.position.set(CameraPosition, CameraPosition/2, CameraPosition);
  camera.lookAt(new THREE.Vector3(0, 0, 0));

  // Renderer setup
  renderer = new THREE.WebGLRenderer({
    canvas:     document.querySelector('#bg'),
    antialias:  true,
    alpha:      true
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  // Set background colour
  renderer.setClearColor( 0xFEE8FF, 1);
  // Set tone mapping (HDR)
  renderer.toneMapping = THREE.ACESFilmicToneMapping;
  renderer.toneMappingExposure = 1;

  // Orbit controls setup
  const controls = new OrbitControls(camera, renderer.domElement);
  controls.update();

  // Grid Helper setup
  const gridHelper = new THREE.GridHelper(20, 50);
  scene.add(gridHelper);

  // Ambient Light setup
  const light = new THREE.AmbientLight(0x404040, 0.2);                    // Soft white light
  scene.add(light);

  // Directional light setup
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.6);
  directionalLight.position.set(1, 0.9, 0.4);
  scene.add(directionalLight);

  // Point Light
  const spotlight = new THREE.PointLight(0x404040, 1);                    // Declare spotlight
  spotlight.position.set(10, 10, -10);                                        // Set spotlight position
  const spotlightHelper = new THREE.PointLightHelper(spotlight);          // Declare spotlight helper
  scene.add(spotlight, spotlightHelper);                                  // Add spotlight and helper to scene
}

// ======================= AMMO.JS ========================

function setupPhysicsWorld(Ammo, g) {
  let collisionConfiguration  = new Ammo.btDefaultCollisionConfiguration();
  let dispatcher              = new Ammo.btCollisionDispatcher(collisionConfiguration);
  let overlappingPairCache    = new Ammo.btDbvtBroadphase();
  let solver                  = new Ammo.btSequentialImpulseConstraintSolver();

  physicsWorld = new Ammo.btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
  physicsWorld.setGravity(new Ammo.btVector3(0, g, 0));
}

// ======================== OBJECTS ========================

function createCube(Ammo, scale, position, mass, rot_quaternion, colour) {
  let quaternion = undefined;
  if(rot_quaternion == null) {quaternion = {x:0, y:0, z:0, w:1}}
  else {quaternion = rot_quaternion}
  // ------ Graphics World - Three.JS ------
  let newcube = 
    new THREE.Mesh(new THREE.BoxBufferGeometry(scale.x, scale.y, scale.z),
    new THREE.MeshPhongMaterial({color: colour}));
  newcube.position.set(position.x, position.y, position.z);
  scene.add(newcube);
  // ------ Physics World - Ammo.js ------
  let transform = new Ammo.btTransform();
  transform.setIdentity();
  transform.setOrigin(new Ammo.btVector3(position.x, position.y, position.z));
  transform.setRotation(new Ammo.btQuaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w));
  let defaultMotionState = new Ammo.btDefaultMotionState(transform);

  let structColShape = new Ammo.btBoxShape(new Ammo.btVector3(scale.x*0.5, scale.y*0.5, scale.z*0.5));
  structColShape.setMargin(0.05);

  let localInertia = new Ammo.btVector3(0, 0, 0);
  structColShape.calculateLocalInertia(mass, localInertia);

  let RBodyInfo = new Ammo.btRigidBodyConstructionInfo(mass, defaultMotionState, structColShape, localInertia);
  let RBody = new Ammo.btRigidBody(RBodyInfo);

  physicsWorld.addRigidBody(RBody);

  newcube.userData.physicsBody = RBody;
  rigidBodyList.push(newcube);
}

function createSphere(Ammo, radius, position, mass, rot_quaternion, colour) {
  let quaternion = undefined;
  if(rot_quaternion == null) {quaternion = {x:0, y:0, z:0, w:1}}
  else {quaternion = rot_quaternion}
  // ------ Graphics World - Three.JS ------
  let newsphere = 
    new THREE.Mesh(new THREE.SphereBufferGeometry(radius, 30, 30),
    new THREE.MeshPhongMaterial({color: colour}));
  newsphere.position.set(position.x, position.y, position.z);
  scene.add(newsphere);
  // ------ Physics World - Ammo.js ------
  let transform = new Ammo.btTransform();
  transform.setIdentity();
  transform.setOrigin(new Ammo.btVector3(position.x, position.y, position.z));
  transform.setRotation(new Ammo.btQuaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w));
  let defaultMotionState = new Ammo.btDefaultMotionState(transform);

  let structColShape = new Ammo.btSphereShape(radius);
  structColShape.setMargin(0.05);

  let localInertia = new Ammo.btVector3(0, 0, 0);
  structColShape.calculateLocalInertia(mass, localInertia);

  let RBodyInfo = new Ammo.btRigidBodyConstructionInfo(mass, defaultMotionState, structColShape, localInertia);
  let RBody = new Ammo.btRigidBody(RBodyInfo);

  physicsWorld.addRigidBody(RBody);

  newsphere.userData.physicsBody = RBody;
  rigidBodyList.push(newsphere);
}

function launchSphere(Ammo, radius, position, mass, rot_quaternion, velocity, colour) {
  let quaternion = undefined;
  if(rot_quaternion == null) {quaternion = {x:0, y:0, z:0, w:1}}
  else {quaternion = rot_quaternion}
  // ------ Graphics World - Three.JS ------
  let newsphere = 
    new THREE.Mesh(new THREE.SphereBufferGeometry(radius, 30, 30),
    new THREE.MeshPhongMaterial({color: colour}));
  newsphere.position.set(position.x, position.y, position.z);
  scene.add(newsphere);
  // ------ Physics World - Ammo.js ------
  let transform = new Ammo.btTransform();
  transform.setIdentity();
  transform.setOrigin(new Ammo.btVector3(position.x, position.y, position.z));
  transform.setRotation(new Ammo.btQuaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w));
  let defaultMotionState = new Ammo.btDefaultMotionState(transform);

  let structColShape = new Ammo.btSphereShape(radius);
  structColShape.setMargin(0.05);

  let localInertia = new Ammo.btVector3(0, 0, 0);
  structColShape.calculateLocalInertia(mass, localInertia);

  let RBodyInfo = new Ammo.btRigidBodyConstructionInfo(mass, defaultMotionState, structColShape, localInertia);
  let RBody = new Ammo.btRigidBody(RBodyInfo);
  RBody.setLinearVelocity(velocity);

  physicsWorld.addRigidBody(RBody);

  newsphere.userData.physicsBody = RBody;
  rigidBodyList.push(newsphere);
}

// ======================= ANIMATION =======================

// Animation loop
function animate() {
  let deltaTime = clock.getDelta();
  updatephysicsWorld(deltaTime);
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}

// Physics loop
function updatephysicsWorld(deltaTime) {
  physicsWorld.stepSimulation(deltaTime, 10);
  for (let i = 0; i < rigidBodyList.length; i++) {
    let Graphics_Obj = rigidBodyList[i];
    let Physics_Obj = Graphics_Obj.userData.physicsBody;
    let motionState = Physics_Obj.getMotionState();
    if (motionState) {
      motionState.getWorldTransform(tmpTransformation);
      let new_pos = tmpTransformation.getOrigin();
      let new_qua = tmpTransformation.getRotation();
      Graphics_Obj.position.set(new_pos.x(), new_pos.y(), new_pos.z());
      Graphics_Obj.quaternion.set(new_qua.x(), new_qua.y(), new_qua.z(), new_qua.w());
    }
  }
}

// ========================= DEMOS =========================
function DemoJenga(Ammo) {
  // Jenga Block
  let offset = 0;
  for (let i = 1; i < 20; i++) {
    if (i%2 == 0) {     // Even
      createCube(Ammo, new THREE.Vector3(6, 1, 2), new THREE.Vector3(0, i + offset, -2), 1, null, Math.random() * 0xffffff);
      createCube(Ammo, new THREE.Vector3(6, 1, 2), new THREE.Vector3(0, i + offset, 0), 1, null, Math.random() * 0xffffff);
      createCube(Ammo, new THREE.Vector3(6, 1, 2), new THREE.Vector3(0, i + offset, 2), 1, null, Math.random() * 0xffffff);
    }
    else {              // Odd
      createCube(Ammo, new THREE.Vector3(2, 1, 6), new THREE.Vector3(-2, i + offset, 0), 1, null, Math.random() * 0xffffff);
      createCube(Ammo, new THREE.Vector3(2, 1, 6), new THREE.Vector3(0, i + offset, 0), 1, null, Math.random() * 0xffffff);
      createCube(Ammo, new THREE.Vector3(2, 1, 6), new THREE.Vector3(2, i + offset, 0), 1, null, Math.random() * 0xffffff);
    }
  }
  // Launch sphere - Ammo, radius, position, mass, rot_quaternion, velocity, colour
  launchSphere(Ammo, 2, new THREE.Vector3(30, 10, -30), 10, null, new Ammo.btVector3(-40, 0, 40), Math.random() * 0xffffff);
}

function DemoSpheresAndCubes(Ammo) {
  // Falling cubes - Ammo, scale, position, mass, rot_quaternion, colour
  createCube(Ammo, new THREE.Vector3(0.4, 0.4, 0.4), new THREE.Vector3(0, 1, 0), 1, null, Math.random() * 0xffffff);
  createCube(Ammo, new THREE.Vector3(0.2, 0.2, 0.2), new THREE.Vector3(1, 3, 0), 1, null, Math.random() * 0xffffff);
  createCube(Ammo, new THREE.Vector3(0.4, 0.4, 0.4), new THREE.Vector3(1, 2, 1), 1, null, Math.random() * 0xffffff);
  createCube(Ammo, new THREE.Vector3(0.6, 0.6, 0.6), new THREE.Vector3(0.5, 4, 2), 1, null, Math.random() * 0xffffff);
  createCube(Ammo, new THREE.Vector3(0.8, 0.8, 0.8), new THREE.Vector3(2.5, 10, 0.5), 1, null, Math.random() * 0xffffff);
  createCube(Ammo, new THREE.Vector3(0.8, 0.8, 0.8), new THREE.Vector3(2, 6, 2.5), 1, null, Math.random() * 0xffffff);
  createCube(Ammo, new THREE.Vector3(0.4, 0.4, 0.4), new THREE.Vector3(2, 10, 2.5), 1, null, Math.random() * 0xffffff);
  createCube(Ammo, new THREE.Vector3(0.2, 0.2, 0.2), new THREE.Vector3(2, 20, 2.5), 1, null, Math.random() * 0xffffff);
  
  // Falling spheres - Ammo, radius, position, mass, rot_quaternion, colour
  for (let i = 0; i < 100; i++) {
    createSphere(Ammo, Math.random(), new THREE.Vector3((Math.random()-0.5)*10, Math.random()*10, (Math.random()-0.5)*10), 1, null, Math.random() * 0xffffff);
  }
}

function DemoDoor(Ammo) {
  // Frame
  // Three.js
  let loader = new GLTFLoader();
  loader.load('recources/PuertaDeLaLuna.glb',
    function (gltf) {
      gltf.scene.translateY(3.1);
      scene.add(gltf.scene);
    },
    undefined,
    function (error) {
      console.error(error);
    }
  );

}

// ==================== Initialisation =====================

function StartApp(Ammo) {
  // Set up physics world
  console.log("%cStarting Ammo.JS", "color: lightgreen");
  tmpTransformation = new Ammo.btTransform();
  setupPhysicsWorld(Ammo, -10);
  console.log("%cGravity = " + physicsWorld.getGravity().y(), "color: lightgreen");

  // Set up graphics world
  console.log("%cStarting Three.JS", "color: lightskyblue");
  setupGraphicsWorld();
  console.log("%cThree.JS initialised", "color: lightskyblue");

  // Declare objects  
  // Base - Ammo, scale, position, mass, rot_quaternion, colour
  createCube(Ammo, new THREE.Vector3(50, 1, 50), new THREE.Vector3(0, 0, 0), 0, null, 0xffffff);

  // Demos:
  //DemoSpheresAndCubes(Ammo);
  //DemoJenga(Ammo);
  //DemoDoor(Ammo);

  // Start animation loop
  animate();
}

// ==================== Initialise App ====================
Ammo().then(StartApp);