1
votes

I am using Three.JS and have gotten a .glb file to display beautifully with some mouse movement.

I'm now trying to add DeviceOrientationControls to my GLtf/GLB scene, so I can move around the scene when moving the mobile phone around, however I can't quite work it out. No matter what I try I always get one error or another.

I have tried adapting the code from this example: https://threejs.org/examples/misc_controls_deviceorientation.html

This is my current code without any DeviceOrientationControls code added:

HTML

<!-- three.min.js r87 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>

<!-- GLTFLoader.js -->
<script src="https://cdn.jsdelivr.net/gh/mrdoob/three.js@r92/examples/js/loaders/GLTFLoader.js"></script>

<!-- Orientation Controls -->
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/DeviceOrientationControls.js"></script> 

<div id="overlay">
            <div>
                <button id="startButton">Start Demo</button>
                <p>Using device orientation might require a user interaction.</p>
            </div>
        </div>
<div class="single-object">
<div id="container"></div>

JS

window.addEventListener("load", loadGltf, false);
window.addEventListener("resize", onWindowResize, false);
const progressBar = document.querySelector("progress");

const gltfStore = {};

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x111111);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

// Attach to container 
container = document.getElementById( 'container' );

//Setup camera
const camera = new THREE.PerspectiveCamera(
  75, window.innerWidth / window.innerHeight,0.1, 1000 );

camera.position.set(0, 0, 0);
camera.lookAt(0, 0, 5);

windowHalfX = window.innerWidth / 2,
        windowHalfY = window.innerHeight / 2,
        mouseX = 0,
        mouseY = 0;

//Re-establish camera view on window resize
function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

//Lighting
const lightFill = new THREE.PointLight(0xffffff, 1, 500);
lightFill.position.set(0, 0, 5);
scene.add(lightFill);

const lightKey = new THREE.PointLight(0xffffff, 1, 500);
lightKey.position.set(20, 0, 20);
scene.add(lightKey);

const loader = new THREE.GLTFLoader();

// Device Orientation


      // Load the GLB file
function loadGltf() {
  loader.load(
    "<?php echo get_template_directory_uri();?>/objects/SM_LookDev_TextureTest_FromFBX.glb",
    function(gltf) {
      scene.add(gltf.scene);
       mesh = gltf.scene;
      gltf.scene.children[0];
      gltfStore.scene = gltf.scene;
      // Set listener
       document.addEventListener("mousemove", onMouseMove);

    } 
  );

container.appendChild(renderer.domElement); 



// Mouse movement

function onMouseMove(event) {

          mouseX = (event.clientX - windowHalfX) / 10;
          mouseY = (event.clientY - windowHalfY) / 30;
}


  function animate() {
    requestAnimationFrame(animate);
    // Adjust mouse and scene position
    camera.position.x += (mouseX - camera.position.x) * .0005;
        camera.position.y += (-mouseY - camera.position.y) * .0003;
        camera.lookAt(0,0,10);
    renderer.render(scene, camera);

  }

  animate();
}

I have gathered from the examples that I need to add these lines (I think):

controls = new DeviceOrientationControls( camera );
controls.update();

and the below for the start button...

var startButton = document.getElementById( 'startButton' );
            startButton.addEventListener( 'click', function () {

                init();
                animate();

            }, false );

EDIT

Below is an example of where I have tried to add the lines, but have not worked successfully.

window.addEventListener("load", loadGltf, false);
window.addEventListener("resize", onWindowResize, false);
const progressBar = document.querySelector("progress");

// Add Start Button

var startButton = document.getElementById( 'startButton' );
            startButton.addEventListener( 'click', function () {

                init();
                animate();

            }, false );


const gltfStore = {};

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x111111);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

// Attach to container 
container = document.getElementById( 'container' );

//Setup camera
const camera = new THREE.PerspectiveCamera(
  75, window.innerWidth / window.innerHeight,0.1, 1000 );

camera.position.set(0, 0, 0);
camera.lookAt(0, 0, 5);

windowHalfX = window.innerWidth / 2,
        windowHalfY = window.innerHeight / 2,
        mouseX = 0,
        mouseY = 0;

//Re-establish camera view on window resize
function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

//Lighting
const lightFill = new THREE.PointLight(0xffffff, 1, 500);
lightFill.position.set(0, 0, 5);
scene.add(lightFill);

const lightKey = new THREE.PointLight(0xffffff, 1, 500);
lightKey.position.set(20, 0, 20);
scene.add(lightKey);

const loader = new THREE.GLTFLoader();

// Added Device Orientation Controls
controls = new DeviceOrientationControls( camera );

      // Load the GLB file
function loadGltf() {
  loader.load(
    "<?php echo get_template_directory_uri();?>/objects/SM_LookDev_TextureTest_FromFBX.glb",
    function(gltf) {
      scene.add(gltf.scene);
       mesh = gltf.scene;
      gltf.scene.children[0];
      gltfStore.scene = gltf.scene;
      // Set listener
       document.addEventListener("mousemove", onMouseMove);

    } 
  );

container.appendChild(renderer.domElement); 



// Mouse movement

function onMouseMove(event) {

          mouseX = (event.clientX - windowHalfX) / 10;
          mouseY = (event.clientY - windowHalfY) / 30;
}


  function animate() {
    requestAnimationFrame(animate);
    // Adjust mouse and scene position
    camera.position.x += (mouseX - camera.position.x) * .0005;
        camera.position.y += (-mouseY - camera.position.y) * .0003;
        camera.lookAt(0,0,10);

// Add Controls Update
controls.update();

    renderer.render(scene, camera);

  }

  animate();
}

When adding the lines like this, I get these 2 error messages:

Uncaught TypeError: Cannot read property 'addEventListener' of null

and

Uncaught ReferenceError: Cannot access 'loader' before initialization at loadGltf

So, I am unsure how to actually add these lines into my specific code to get it to work? Any assistance would be appreciated

1
So what's the error you're getting, or what problem are you encountering? It sounds like you simply haven't incorporated those two lines of code necessary to make it work. You initialize controls after you create the camera, and controls.update() goes inside your animate() function.Marquizzo
Well thats my question, how do I incorporate these lines correctly? I'll update the question to show how I add them in, and what error I get. Wherever I move them I get some kind of errorKiki
I updated the question to reflect my attempts more and show the errors.... any help will be so so so appreciated! Thank you in advanceKiki

1 Answers

0
votes

It's hard to tell exactly the reason why it's not working, especially since your question includes so much extraneous code. You should try to ask your questions with a minimal reproducible example.

First, you're importing your <scripts> from varying sources, and varying versions. The Three.js and GLTFLoader you're loading is r92, but the DeviceOrientationControls script doesn't specify a version, so it's loading the latest at r112, which might no longer be compatible with ThreeJS r92.

Secondly, you're using:

controls = new DeviceOrientationControls( camera );, when it should be:

controls = new THREE.DeviceOrientationControls( camera );

Finally, make sure you organize your code, and call your functions in a sequential manner. Is loadGltf() being called before you initiate const loader = new THREE.GLTFLoader()? Does startButton exist, and is it defined before you call startButton.addEventListener();?

Here is a minimal example implementing the orientation controls: Notice that both scripts are being imported from the same source with r92 to ensure compatibility.

window.addEventListener("resize", resize);

const renderer = new THREE.WebGLRenderer({canvas: document.querySelector("canvas")});
const camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
const controls = new THREE.DeviceOrientationControls( camera );

// Make a scene with geometry
const scene = new THREE.Scene();
const geometry = new THREE.DodecahedronBufferGeometry(100,1);
const material = new THREE.MeshBasicMaterial({
  color: 0xff9900,
  wireframe: true,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

function resize() {
  var width = window.innerWidth;
  var height = window.innerHeight;
  
	renderer.setSize(width, height, false);
	camera.aspect = width / height;
	camera.updateProjectionMatrix();
}

function animate(time) {
  controls.update();
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}

resize();
animate(0);
body { margin: 0; }
<canvas></canvas>

<!-- three.min.js r92 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>

<!-- Orientation Controls r92 -->
<script src="https://cdn.jsdelivr.net/gh/mrdoob/three.js@r92/examples/js/controls/DeviceOrientationControls.js"></script>

Note:

Apple disabled gyroscope access by default since iOS 12.2, so you'll have to enable it in settings when testing. See here for a discussion on the matter.