I am currently trying to change the geometry of a cube in three js to that of a sphere after a certain time interval or an event click. I have tried to change the property of geometry from Three.BoxGeometry to Three.SphereGeometry but have had no luck. I have also tried to implement some "solutions" that I found, but have hit a wall there too.
Here is what I initially had:
export class ThreeJSService {
geometry: THREE.BoxGeometry;
camera: THREE.PerspectiveCamera;
cube: THREE.Mesh;
movingObject;
renderer: THREE.WebGLRenderer;
scene: THREE.Scene;
texture: THREE.Texture;
/**
* Setups scene for 3d objects
*/
constructor() {
this.scene = new THREE.Scene();
this.texture = new THREE.TextureLoader().load('assets/apartment_background.png');
this.scene.background = this.texture;
this.camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
this.renderer = new THREE.WebGLRenderer();
this.geometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
const material = new THREE.MeshBasicMaterial( {color: 0x348713} );
this.cube = new THREE.Mesh( this.geometry, material );
this.movingObject = {
object: this.cube,
geometry: this.geometry,
direction: {
x: 0.03,
y: 0,
},
};
}
/**
* Sets all the requirements needed for the scene
* @param {HTMLElement} parent The element to attach to
*/
setup(parent: HTMLElement) {
const canvas = this.renderer.domElement;
this.scene.add( this.cube );
this.camera.position.z = 5;
parent.appendChild(canvas);
}
// transform() {
// for ( var i = 0, l = this.geometry.vertices.length; i < l; i ++ ) {
//
// var vertex = this.geometry.vertices[ i ];
// vertex.normalize().multiplyScalar( 550 );
//
// // After a certain interval change the geometry from Cylinder to Sphere
//
// }
// }
/**
* Provides animation to the rendered object. Makes the cube move and sends it to another direction when getting to the border
* @param {number | undefined} headerHeight The height of the header
*/
animate() {
const header = document.getElementById('header')?.clientHeight;
this.renderer.setSize( window.innerWidth, window.innerHeight - (header ? header : 0));
this.movingObject.object.rotateX(0.01);
this.movingObject.object.rotateY(0.01);
requestAnimationFrame( this.animate.bind(this) );
this.renderer.render( this.scene, this.camera );
this.movingObject.object.position.x += this.movingObject.direction.x;
// Check if the position of the cube is on the border
if (this.cube.position.x > 7.3 || this.cube.position.x < -7.3) {
this.movingObject.direction.x = -this.movingObject.direction.x;
}
}
Any help would be greatly appreciated!
Here is a complete live example that shows a geometry is replaced after two seconds.
let camera, scene, renderer;
init();
render();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.set(2, 2, 2);
camera.lookAt(0, 0, 0);
scene = new THREE.Scene();
geometry = new THREE.BoxGeometry();
material = new THREE.MeshNormalMaterial();
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
setTimeout(function() {
mesh.geometry.dispose();
mesh.geometry = new THREE.SphereGeometry();
render();
}, 2000);
}
function render() {
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three@0.141/build/three.min.js"></script>
I managed to get it to work. This is my solution:
changeShape() {
this.interval = (Math.floor(Math.random() * (400 + 1)) * 1000);
// this.interval = Math.floor((Math.random() * (20 - 10 + 10)) + 10) * 1000;
if (this.switch) {
setTimeout(() => {
this.movingObject.object.geometry.dispose();
this.movingObject.object.geometry = new THREE.CylinderGeometry(0.5, 0.5, 2);
this.switch = false;
// console.log(this.interval);
}, this.interval);
} else {
setTimeout(() => {
this.movingObject.object.geometry.dispose();
this.movingObject.object.geometry = new THREE.SphereGeometry(0.5, 8, 8);
this.switch = true;
// console.log(this.interval);
}, this.interval);
}
}
Thank you for the assist!