How do I import code from THREE.js examples? - three.js

I am currently building a React application that utilizes THREE.js.
I want to import some code from THREE.js library, which is not part of the official distribution. Under the official repo for THREE.js, there are some modules under the examples folder, which the official doc for THREE.js makes use of to showcase examples.
How can I make use of these modules and use them in my own code?
In my app, I wanted to use the THREE.STLExporter module.
(https://github.com/mrdoob/three.js/blob/master/examples/js/exporters/STLExporter.js)
Because I already installed three as a dependency for my app, I first tried simply doing import * as THREE from 'three', which did not seem to do the trick.
Then I tried to access the examples folder directly and grab the module manually by doing `require('three/examples/js/exporters/STLExporter'), but this did not work either.
I have checked the source code for the official docs and noticed that the examples directly include the necessary modules in tags, but I don't want to do that because I am building a React app. I want to be able to include modules either via NPM or storing the code for the module within my app.
Please help out a noob here. Thank you!

You can create a separate three.js file that will import "three", add any examples code to it and export as an object, here is a snippet that works with THREE.OrbitControls:
import * as THREE from 'three';
window.THREE = THREE; // THREE.OrbitControls expects THREE to be a global object
require('three/examples/js/controls/OrbitControls');
export default window.THREE;
Then use three.js file in your app like this:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import THREE from "./three";
class App extends Component {
componentDidMount() {
// BASIC THREE.JS THINGS: SCENE, CAMERA, RENDERER
// Three.js Creating a scene tutorial
// https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 5;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// MOUNT INSIDE OF REACT
this.mount.appendChild(renderer.domElement); // mount a scene inside of React using a ref
// CAMERA CONTROLS
// https://threejs.org/docs/index.html#examples/controls/OrbitControls
this.controls = new THREE.OrbitControls(camera);
// ADD CUBE AND LIGHTS
// https://threejs.org/docs/index.html#api/en/geometries/BoxGeometry
// https://threejs.org/docs/scenes/geometry-browser.html#BoxGeometry
var geometry = new THREE.BoxGeometry(2, 2, 2);
var material = new THREE.MeshPhongMaterial( {
color: 0x156289,
emissive: 0x072534,
side: THREE.DoubleSide,
flatShading: true
} );
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
var lights = [];
lights[ 0 ] = new THREE.PointLight( 0xffffff, 1, 0 );
lights[ 1 ] = new THREE.PointLight( 0xffffff, 1, 0 );
lights[ 2 ] = new THREE.PointLight( 0xffffff, 1, 0 );
lights[ 0 ].position.set( 0, 200, 0 );
lights[ 1 ].position.set( 100, 200, 100 );
lights[ 2 ].position.set( - 100, - 200, - 100 );
scene.add( lights[ 0 ] );
scene.add( lights[ 1 ] );
scene.add( lights[ 2 ] );
// SCALE ON RESIZE
// Check "How can scene scale be preserved on resize?" section of Three.js FAQ
// https://threejs.org/docs/index.html#manual/en/introduction/FAQ
// code below is taken from Three.js fiddle
// http://jsfiddle.net/Q4Jpu/
// remember these initial values
var tanFOV = Math.tan( ( ( Math.PI / 180 ) * camera.fov / 2 ) );
var windowHeight = window.innerHeight;
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize( event ) {
camera.aspect = window.innerWidth / window.innerHeight;
// adjust the FOV
camera.fov = ( 360 / Math.PI ) * Math.atan( tanFOV * ( window.innerHeight / windowHeight ) );
camera.updateProjectionMatrix();
camera.lookAt( scene.position );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.render( scene, camera );
}
// ANIMATE THE SCENE
var animate = function() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
};
animate();
}
render() {
return <div ref={ref => (this.mount = ref)} />;
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
working demo on stackblitz https://stackblitz.com/edit/react-three-example-import?file=index.js

You should import the full path of the module:
import { STLExporter } as THREE from 'three/examples/jsm/STLExporter

Related

My threeJS class only apply meshs settings to 1 of 2 models in my scene

I am creating a scene in three js with two models in .glb format; I am following a pre-recorded class and I have followed exactly all the steps. We create a class for the models in model.js and in index.js we define them.
Everything was working fine until from model.js we created a material for the models and it only loads in one of them. I have checked everything, searched for similar answers here and I can't find the error because everything seems to be fine.
This is model.js (the class)
import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
class Model {
constructor(obj){
//console.log(obj)
this.name = obj.name
this.file = obj.file
this.scene = obj.scene
this.loader = new GLTFLoader()
this.dracoLoader = new DRACOLoader()
this.dracoLoader.setDecoderPath('./draco/')
this.loader.setDRACOLoader(this.dracoLoader)
this.init()
}
init (){
this.loader.load(this.file, (response) => {
console.log(response)
this.mesh = response.scene.children[0]
this.material = new THREE.MeshBasicMaterial({
color: 'blue',
wireframe: true
})
this.mesh.material = this.material
this.scene.add(this.mesh)
})
}
}
export default Model
And this is my index.js (the scene)
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import Model from './model';
/*------------------------------
Renderer
------------------------------*/
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
/*------------------------------
Scene & Camera
------------------------------*/
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
50,
window.innerWidth / window.innerHeight,
0.1,
100
);
camera.position.z = 5;
camera.position.y = 1;
/*------------------------------
Mesh
------------------------------*/
const geometry = new THREE.BoxGeometry(2, 2, 2);
const material = new THREE.MeshBasicMaterial( {
color: 0x00ff00,
} );
const cube = new THREE.Mesh( geometry, material );
//scene.add( cube );
/*------------------------------
OrbitControls
------------------------------*/
const controls = new OrbitControls( camera, renderer.domElement );
/*------------------------------
Helpers
------------------------------*/
const gridHelper = new THREE.GridHelper( 10, 10 );
scene.add( gridHelper );
const axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );
/*------------------------------
Models
------------------------------*/
const laptop = new Model({
name: 'laptop',
file: './models/laptop.glb',
scene: scene
})
const humano = new Model({
name: 'humano',
file: './models/humano.glb',
scene: scene
})
/*------------------------------
Loop
------------------------------*/
const animate = function () {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
animate();
/*------------------------------
Resize
------------------------------*/
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
window.addEventListener( 'resize', onWindowResize, false );
And this is how it look like:
I tried to have it searched throughout the index without success.
I suspect this is the error, but the truth is that I am very novice and I have no clue how or why my children element comes out empty.
This is my teachers console
And this is mine....
I'm also a Three.js novice, but it looks like DracoLoader loads a geometry not a mesh so the way you're crafting your model might be causing the issue. Does instantiating a new THREE.Mesh with the downloaded geometry and material fix the issue:
init (){
this.loader.load(this.file, (response) => {
console.log(response)
this.geometry = response.scene.children[0];
this.material = new THREE.MeshBasicMaterial({
color: 'blue',
wireframe: true
})
this.mesh = new THREE.Mesh( this.geometry, this.material );
this.scene.add(this.mesh)
})
}

How to access the any property of imported point-cloud object

I’m trying to access any property of my imported point-cloud model.
When I console.log the model within the function loader.load it works. The first problem is that I don’t know how to get the same result outside the function. I did it only with the last three lines of code but initializing the object with different name.
I used the code for point-cloud models from three.js docs and everything works fine except when I want to change the size of the points. I guess it is due to the different structure of my model (photo attached).
Here’s the code that I use.
import './style.css'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { PCDLoader } from 'three/examples/jsm/loaders/PCDLoader'
import { BufferAttribute, BufferGeometry } from 'three';
let camera, scene, renderer;
init();
render();
function init() {
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 0.01, 40 );
camera.position.set( 0, 0, 7 );
scene.add( camera );
const controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // use if there is no animation loop
controls.minDistance = 0.5;
controls.maxDistance = 10;
//scene.add( new THREE.AxesHelper( 1 ) );
const loader = new PCDLoader();
loader.load( 'pointcloud.pcd', function ( points ) {
points.geometry.center();
points.geometry.rotateY( Math.PI );
points.geometry.rotateX( Math.PI );
points.geometry.rotateZ( Math.PI );
scene.add( points );
console.log(points)
render();
} );
window.addEventListener( 'resize', onWindowResize );
window.addEventListener( 'keypress', keyboard );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function keyboard( ev ) {
const points = scene.getObjectByProperty( 'pointcloud.pcd' );
switch ( ev.key || String.fromCharCode( ev.keyCode || ev.charCode ) ) {
case '+':
points.material.size *= 1.2;
break;
case '-':
points.material.size /= 1.2;
break;
}
render();
}
function render() {
renderer.render( scene, camera );
}
// I used this to acces the object
const points2 = scene.getObjectByProperty( 'points' );
console.log(points2)
enter image description here
change let camera, scene, renderer; to let camera, scene, renderer, points
to make 'points' global.
because the 'points' object only live inside the function, try create a variable outside the loader.load function, then assign the 'points' object to the new variable before render(); now you can access the 'points' from outside this function

Orbit Controls doesn't work with no error

I would like to implement Orbit Control in my program but when I followed exactly each step of some tutorial, nothing happen.
This is my code :
import * as THREE from 'https://unpkg.com/three#0.126.1/build/three.module.js';
import { OrbitControls } from 'https://unpkg.com/three#0.127.0/examples/jsm/controls/OrbitControls.js';
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
camera.position.set( 2, 3, 2 );
camera.lookAt(0,0,0);
var controls = new OrbitControls(camera, renderer.domElement);
and this is what it's looks like :
Code Render
but nothing happen. It doesn't rotate or zoom.
Thank you for helping
I found the problem.
I used this import :
import * as THREE from './build/three.module.js';
import { OrbitControls } from './examples/jsm/controls/OrbitControls.js';
And the main difference is than I added :
controls.addEventListener('change',render);
function render(){
renderer.render(scene, camera);
}

Clickable element with ThreeJS PerspectiveCamera

I’ve created a panoramic image with PerspectiveCamera and all went well. I’ve also managed to add controls.
Now I want to place a clickable element (link/button/whatever) in the scene but I have no clue how to add and position the clickable element…every tip/suggestion is highly appreciated! Here is my code sofar:
function init() {
const container = document.getElementById( 'three-image' );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1100 );
scene = new THREE.Scene();
const geometry = new THREE.SphereGeometry( 500, 60, 40 );
// invert the geometry on the x-axis so that all of the faces point inward
geometry.scale( - 1, 1, 1 );
//let imageLocation = <?php echo $block->getPanoramaImages();?>;
let imageLocation = '/three/luifel.jpg';
//alert(imageLocation)
const texture = new THREE.TextureLoader().load(imageLocation);
const material = new THREE.MeshBasicMaterial( { map: texture } );
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
container.style.touchAction = 'none';
container.addEventListener( 'pointerdown', onPointerDown );
document.addEventListener( 'wheel', onDocumentMouseWheel );
window.addEventListener( 'resize', onWindowResize );
}
If you're looking to attach an html element to a 3d element, you can project a 3d position to 2d and use that.
var vector = new THREE.Vector3(100,0,0); // some point
vector.project(camera);
var widthHalf = window.innerWidth / 2;
var heightHalf = window.innerHeight / 2;
vector.x = vector.x * widthHalf + widthHalf;
vector.y = -(vector.y * heightHalf) + heightHalf;
vector.z = 0;
If you want to attach to an object, use the objects position in world space:
vector.setFromMatrixPosition(obj.matrixWorld);
vector.project(camera);
...etc
EDIT:
I've created an example here:
https://codepen.io/flatworldstudio/pen/LYbgvgY

Three.js - Camera collision with scene

This is my first question in StackOverflow, but I've been browsing it for some years now, so I kindly ask you to bear with me. :)
I've been experimenting with Three.js to create a 3D world, and everything looked fine until I needed to control the camera. Since I'm using this lib to avoid having to do matricial calculations myself I found and added TrackballControls to my code aswell. It worked fine but then my camera could pass through the 3D shapes, and also below terrain. Unfortunately, although the movement is exactly what I needed, it didn't serve the purpose of allowing camera to respect collision.
My scene is simply the ground (thin BoxGeometry) and a cube (normal-sized BoxGeometry), and a rotating sphere that shares directionalLight position for a "sun light" effect. Some people here suggested adding Physijs to the code and simulate() physics within the scene, and adding a BoxMesh to the camera to make the physics apply to it aswell, but it simply didn't work (scene turned blank).
My working code so far (without Physijs) is:
window.onload = function() {
var renderer, scene, camera, ground, box, sphere, ambient_light, sun_light, controls;
var angle = 0;
var clock = new THREE.Clock();
init();
render();
function init(){
// Create renderer and add it to the page
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff );
renderer.shadowMapEnabled = true;
document.body.appendChild( renderer.domElement );
// Create a scene to hold our awesome 3D world
scene = new THREE.Scene();
/*** 3D WORLD ***/
// Objects
ground = new THREE.Mesh(
new THREE.BoxGeometry(50, 1, 50),
new THREE.MeshLambertMaterial({ color: 0x33CC33 }),
0 // mass
);
ground.receiveShadow = true;
scene.add( ground );
box = new THREE.Mesh(
new THREE.BoxGeometry( 10, 10, 10 ),
new THREE.MeshLambertMaterial({ color: 0xDD3344 })
);
box.position.y = 5;
box.castShadow = true;
scene.add( box );
sphere = new THREE.Mesh(
new THREE.SphereGeometry( 3, 32, 32 ),
new THREE.MeshBasicMaterial({ color: 0xFFBB00 })
);
sphere.position.set( 1, 15.5, 5 );
scene.add( sphere );
// Light
ambient_light = new THREE.AmbientLight( 0x333333 );
ambient_light.mass = 0;
scene.add( ambient_light );
sun_light = new THREE.DirectionalLight( 0xBBBBBB );
sun_light.position.set( 1, 15.5, 5 );
sun_light.castShadow = true;
sun_light.shadowCameraNear = 1;
sun_light.shadowCameraFar = 100;
sun_light.shadowCameraLeft = -50;
sun_light.shadowCameraRight = 50;
sun_light.shadowCameraTop = -50;
sun_light.shadowCameraBottom = 50;
sun_light.shadowBias = -.01;
scene.add( sun_light );
// Create a camera
camera = new THREE.PerspectiveCamera(
45, // FOV
window.innerWidth / window.innerHeight, // Aspect Ratio
1, // Near plane
1000 // Far plane
);
camera.position.set( 30, 30, 30 ); // Position camera
camera.lookAt( box.position ); // Look at the scene origin
scene.add(camera);
// After swapping THREE.Mesh to Physijs.BoxMesh, this is where I'd attach a BoxMesh to the camera
window.addEventListener( 'resize', onWindowResize, false );
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 4.0;
controls.panSpeed = 0.3;
controls.staticMoving = true; // No sliding after-effects
}
function render() {
// use requestAnimationFrame to create a render loop
angle += .007;
var oscillateZ = Math.sin(angle * (Math.PI*4));
var oscillateX = -Math.cos(angle * (Math.PI*4));
//console.log(oscillateZ);
sphere.position.setZ( sphere.position.z + oscillateZ );
sphere.position.setX( sphere.position.x + oscillateX );
sun_light.position.setZ( sun_light.position.z + oscillateZ );
sun_light.position.setX( sun_light.position.x + oscillateX );
requestAnimationFrame( render );
controls.update();
renderer.render( scene, camera );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
};
Can you guys enlighten me? Thank you for your time!
#Edit
Physijs attempt

Resources