Using Three.js with Laravel - Require is not defined - laravel

I'm in the process of converting my project over to Laravel, and this uses the Three.js library. I followed their Import via Modules documentation, but get the error Uncaught ReferenceError: require is not defined at stl:71, so I assume it isn't being loaded correctly.
I did the following...
Ran "npm install three" in my Laravel root directory
Ran "npm run dev"
Put the following code snippet in the script section of my blade template
var THREE = require('three');
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
function animate() {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
}
animate();
I'm still getting familiar with using Laravel and NPM, where I think I may need to import the library somewhere before using it. The ThreeJS documentation doesn't make any mention of this though (when using the NPM module) so I am confused.
Pretty sure I can import it in the resources\app.js for global access, but only need to use it on certain pages. Being the case, I would prefer to figure out why var THREE = require('three'); isn't working.

Create a file under public/js/three.js and put your codes in there.
Then in your blade file add this in script section
<script src="/js/three.js" type="module"></script>
Hope it might work
Another way would be changing your webpack config file to:
webpack.mix.js
mix.webpackConfig({
module: {
rules: [{
test: /\.js?$/,
use: [{
loader: 'babel-loader',
options: mix.config.babel()
}]
}]
}
});

Take a look at Three.js documentation
Important note:
Because the library relies on ES modules, any script that references it must use type="module"
...Like:
<script type="module">
Then you can do stuff like:
import * as THREE from 'https://unpkg.com/three/build/three.module.js';
Read more about Javascript modules here

Related

Issue with orbit controls and effect composer

I'm Gabriele and I'm new in three.js world, I have an issue with a code, my orbitcontrols were works good, but when I added the composer to make the scene blurred they stopped working... Google's Console (in the browser) don't show me any error, so I don't know what happening to the code. I declared every js that I used in the code.
Somebody can help me please?
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.dispose();
controls.update();
controls.reset();
composer = new THREE.EffectComposer(renderer);
renderPass = new THREE.RenderPass(scene, camera);
composer.addPass(renderPass);
horizontalBlur = new THREE.ShaderPass({
...THREE.HorizontalBlurShader,
uniforms: {
...THREE.HorizontalBlurShader.uniforms,
h: {value: 1.0 / window.innerWidth * window.devicePixelRatio},
},
})
composer.addPass(horizontalBlur)
verticalBlur = new THREE.ShaderPass({
...THREE.VerticalBlurShader,
uniforms: {
...THREE.VerticalBlurShader.uniforms,
v: {value: 1.0 / window.innerHeight * window.devicePixelRatio },
},
})
composer.addPass(verticalBlur)
}
controls.dispose();
controls.update();
controls.reset();
There is no need to call these methods. Especially calling dispose() is problematic since this method will remove all event listeners of OrbitControls. Just do this and try again:
controls = new THREE.OrbitControls(camera, renderer.domElement);
In general, the usage of EffectComposer should not affect controls in any form.

How do I import code from THREE.js examples?

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

Three.js mesh doesn't appear with the build version of the library but appears when using old ones library?

I want to use the build version of three.js (https://threejs.org/build/three.js) for a project.
I was using an old one version of the library and everything was fine and my mesh (loaded form a .json file) appeared normally.
Here's my code :
var renderer, scene, camera, mesh, material;
initMesh();
function initMesh() {
var controls;
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set(0,500,700);
camera.up = new THREE.Vector3(0,0,0);
camera.lookAt(new THREE.Vector3(0,0,0));
scene = new THREE.Scene();
scene.add(camera);
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var loader = new THREE.JSONLoader();
loader.load('test.json', function(geometry) {
material = new THREE.MeshBasicMaterial({ color: 0x00ff84, wireframe: true, wireframeLinewidth: 3 });
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
render();
});
}
var render = function () {
requestAnimationFrame( render );
renderer.render(scene, camera);
};
Here is what I got when using old one library.
I don't see what I miss ? Any idea ? Thank you.
I tried with your example
Removing this line fixed the issue: camera.up = new THREE.Vector3(0,0,0);

Error creating WebGL context enyo

I am trying simple spinning cube sample of three.js in enyo framework.
I am getting error as
THREE.WebGLRenderer:Error creating WebGL context.
Here is my code:
enyo.kind({
name:"Cubetest",
create:function () {
// body...
this.inherited(arguments);
this.drawCube();
//alert("in create");
},
rendered : function(){
this.inherited(arguments);
//this.drawCube();
},
drawCube : function(){
var scene = new THREE.Scene();
console.log(scene);
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
console.log(camera);
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
console.log(cube);
console.log(scene);
camera.position.z = 5;
var render = function () {
requestAnimationFrame( render );
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
};
render();
}
});
What may be problem here?
It supports CanvasRenderer.
If I replace WebGLRenderer by CanvasRenderer,it works fine.
I believe the problem you are running into is that you are appending a DOM node to the body before Enyo has created its DOM nodes. When Enyo creates its nodes, it wipes out the one created by three. You should leave DOM manipulation to Enyo, for the most part.
In Enyo, you do not have a DOM node until after rendered() is called. You should only create the three DOM node within the node created for your kind. You can get the DOM node from Enyo by calling this.hasNode(), which will return the DOM node (or null if rendered() has not been called yet).
Change your method to have three use your kind's node and things should work better.

Three.js OBJLoader does not load obj file

I am trying to load a obj file using OBJloader.js
I am trying to load "plane.obj" file which exists inside the same folder where the html files exists and "OBJLoader.js" also exists in the same folder.
Page doesn't show up anything.
Here is the code :
var scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.CubeGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material); scene.add(cube); camera.position.z = 5;
function render() {
requestAnimationFrame(render);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
var texture = THREE.ImageUtils.loadTexture( 'tex.jpg' );
var loader = new THREE.OBJLoader();
loader.load( 'plane.obj', function ( object ) {
scene.add( object );
} );
render();
This is likely caused by trying to load a resource from the file system. You're probably getting a same origin policy security violation and need to serve up your page and resources from the same protocol, domain and port. There are a few easy ways to do this - I use a simple http server app via Node JS. check out How to run things locally for more options.
Well, it turned out for me to be caused by the absence of light in the scene. Also, improper camera position may also lead to "invisible" OBJ models. Try adding the following lines:
var ambientLight = new THREE.AmbientLight(0xffffff);
scene.add(ambientLight);

Resources