Following my previous post
I am developing a 3D model that moves based on input from accelerometer and gyroscope sensors. The 3D model is written with three.js, and the input data for rotation and translation are in JSON format. Currently the 3D cube moves in 3D space but I have two main problems:
- The 3D cube move off boundary when the accelerometer value is too high.
- It seems that the 3D cube only move in one axis, for example, even though there is X, Y and Z value, the object only translate in the Y axis, but not UP/DOWN.
I basically want the 3D cube to move only UP/DOWN using the X-axis data. Below is my code:
index.html
import * as THREE from "three"; import data from "../data/data.json" import "./style.css" const canvas = document.querySelector('#canvas'); const accelPanel = document.querySelector('#accelPanel'); const renderer = new THREE.WebGLRenderer({ canvas }); const fov = 70; const aspect = 2; // the canvas default const near = 20; const far = 500; const camera = new THREE.PerspectiveCamera(fov, aspect, near, far); camera.position.set(0, 50, 1.5); camera.up.set(0, 0, 1); camera.lookAt(0, 0, 0); const scene = new THREE.Scene(); { const color = 0x00afaf; const intensity = 10; const light = new THREE.PointLight(color, intensity); scene.add(light); } const boxGeometry = new THREE.BoxGeometry(); const boxMaterial = new THREE.MeshBasicMaterial({ color: "green", wireframe: false }); const object = new THREE.Mesh(boxGeometry, boxMaterial); var cubeAxis = new THREE.AxesHelper(3); object.add(cubeAxis); object.scale.set(5, 5, 5) scene.add(object); scene.background = new THREE.Color(0.22, 0.23, 0.22); let currentIndex = 0 let time = data[currentIndex].time let velocity = new THREE.Vector3() requestAnimationFrame(render); function render(dt) { dt *= 0.0001 // in seconds time += dt document.querySelector("#time").textContent = time.toFixed(2) // Find datapoint matching current time while (data[currentIndex].time < time) { currentIndex++ if (currentIndex >= data.length) return } const { rotX, rotY, rotZ, accX, accY, accZ } = data[currentIndex] const acceleration = new THREE.Vector3( accX, accY, accZ) object.rotation.set(rotX, rotY, rotZ) object.position.add(velocity.clone().multiplyScalar(dt)).add(acceleration.clone().multiplyScalar(50 * dt ** 2)) velocity.add(acceleration.clone().multiplyScalar(dt)) resizeToClient(); renderer.render(scene, camera); requestAnimationFrame(render); } function resizeToClient() { const needResize = resizeRendererToDisplaySize() if (needResize) { const canvas = renderer.domElement; camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); } } function resizeRendererToDisplaySize() { const canvas = renderer.domElement; const width = canvas.clientWidth; const height = canvas.clientHeight; const needResize = canvas.width !== width || canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize; }
index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <canvas id="canvas" width="1500" height="800" style="border:1px solid #000000;"></canvas> <div id="accelPanel"></div> <div id="info"> <div>t = <span id="time">0</span> s</div> </div> </body> </html>
I tried to modify these lines which are responsible of rotation and positioning:
object.rotation.set(rotX, rotY, rotZ) object.position.add(velocity.clone().multiplyScalar(dt)).add(acceleration.clone().multiplyScalar(50 * dt ** 2))
But it doesn’t seem that the problem is from coming from them.
this is an example of the input data:
[ { "time": 8029, "rotX": 0.836885376331281, "rotY": -0.05305800926062761, "rotZ": 0.03822271061867582, "accX": -0.0265087890625, "accY": -0.046376953125, "accZ": 0.0312451171875 }, { "time": 8030.000000000001, "rotX": 0.836885376331281, "rotY": -0.05305800926062761, "rotZ": 0.03822271061867582, "accX": -0.0265087890625, "accY": -0.046376953125, "accZ": 0.0312451171875 }, { "time": 8031, "rotX": 0.836885376331281, "rotY": -0.05305800926062761, "rotZ": 0.03822271061867582, "accX": -0.0265087890625, "accY": -0.046376953125, "accZ": 0.0312451171875 } ]
and this is how accelerometerX data looks like (Click here to download the data):
These are the movements UP and DOWN but somehow this is not showing in the animation.
Is there is a way to make the 3D cube moves similarly to the image below (only UP and DOWN and the car is just for illustration):
to have a look a live preview of the 3D cube, click here (it is from the previous post I made).
Advertisement
Answer
Looks like you’re doing all kinds of multiplication to the position, velocity, and acceleration
vectors, and it’s hard to gauge what magnitude the final position ends up having.
Why don’t you start with something simple, like object.position.y = accY * 30;
So the data that’s barely noticeable in the [-0.1, 0.1]
range gets turned to [-15, 15]
range, and then you can fine-tune it.
Another issue I’m noticing is that your camera position is (0, 50, 1.5)
, which is very high looking from the top-down, and therefore it’s not letting you see any y-axis movement. If you want your camera to capture up/down movement, don’t place it up so high: camera.position.set(0, 0, 15)
should suffice.