I'm a complete beginner with three.js and am just trying to get to grips with creating a basic scene. I have copied and pasted code from a tutorial into VSCode and executed it through the live server extension.
This is the code below:
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta charset="utf-8" />
<title>Three.js Basic Scene</title>
<style>
body {
margin: 0;
padding: 0;
}
canvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script src="three.min.js"></script>
<script>
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor(0xDDDDDD, 1);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT);
camera.position.z = 50;
scene.add(camera);
var boxGeometry = new THREE.BoxGeometry(10, 10, 10);
var basicMaterial = new THREE.MeshBasicMaterial({ color: 0x0095DD });
var cube = new THREE.Mesh(boxGeometry, basicMaterial);
scene.add(cube);
cube.rotation.set(0.4, 0.2, 0);
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
</script>
</body>
</html>
The intended output is a blue cube on the screen with a white background, however all i am getting is a completely white screen. Any ideas why this is happening when the code is completely copied and pasted?
Related
I am trying to code an STL model viewer in three.js
This is the code:
<!-- prerenderer -->
<!doctype html>
<html>
<head>
<title>Enjoy your model</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="../libs/three.js"></script>
<script src="../libs/OrbitControls.js"></script>
<script src="../libs/STLLoader.js"></script >
<style type="text/css">
body { padding-top:10px; word-wrap:break-word; width: 100vw; height: 100vh; margin: 0; overflow: hidden;}
form { text-align: center; }
</style>
</head>
<body>
<div >
<form action="/">
<input type="submit" value="Back to the homepage!" />
</form>
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 50, window.innerWidth/window.innerHeight, 1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById("WebGL-output").appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.center = new THREE.Vector3(
);
var loader = new THREE.STLLoader();
loader.load( 'myModel.stl', function ( geometry ) {
Var mesh = new THREE.Mesh (geometry);
Mesh.scale.set (0.1, 0.1, 0.1);
// mesh.rotation.set (- Math.PI / 2, Math.PI / 2, 0);
// mesh.scale.set (0.3, 0.3, 0.3);
// mesh.receiveShadow = true;
Scene.add (mesh);
} );
camera.position.z = 5;
var animate = function () {
requestAnimationFrame( animate );
renderer.render(scene, camera);
};
animate();
</script>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script >
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="../libs/bootstrap.min.js"></script>
</body>
</html>
What i get is Uncaught SyntaxError: Cannot use import statement outside a module for Orbit Controls and STLLoader.
What's even weirder is that sometimes it works, other times it does not
Then i tried this:
<!DOCTYPE html>
<html>
<head>
<title>Example 01.02 - First Scene</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script src="../libs/OrbitControls.js"></script>
<script src="../libs/STLLoader.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>
<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
// Necessary for camera/plane rotation
var degree = Math.PI/180;
// Setup
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);
//bind rendered to the dom element
document.getElementById("WebGL-output").appendChild(renderer.domElement);
// Resize after viewport-size-change
window.addEventListener("resize", function () {
var height = window.innerHeight;
var width = window.innerWidth;
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
});
// Adding controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
// Ground (comment out line: "scene.add( plane );" if Ground is not needed...)
var plane = new THREE.Mesh(
new THREE.PlaneBufferGeometry(500, 500 ),
new THREE.MeshPhongMaterial( { color: 0x999999, specular: 0x101010 } )
);
plane.rotation.x = -90 * degree;
plane.position.y = 0;
scene.add( plane );
plane.receiveShadow = true;
// ASCII file - STL Import
var loader = new THREE.STLLoader();
loader.load( '../esp32.stl', function ( geometry ) {
var material = new THREE.MeshLambertMaterial( { color: 0xFFFFFF, specular: 0x111111, shininess: 200 } );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set( 0, 0, 0);
scene.add( mesh );
} );
// Binary files - STL Import
loader.load( '../esp32.stl', function ( geometry ) {
var material = new THREE.MeshLambertMaterial( { color: 0xFFFFFF, specular: 0x111111, shininess: 200 } );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set( 0, 20, 0);
scene.add( mesh );
} );
// Camera positioning
camera.position.z = 100;
camera.position.y = 100;
camera.rotation.x = -45 * degree;
// Ambient light (necessary for Phong/Lambert-materials, not for Basic)
var ambientLight = new THREE.AmbientLight(0xffffff, 1);
scene.add(ambientLight);
// Draw scene
var render = function () {
renderer.render(scene, camera);
};
// Run game loop (render,repeat)
var GameLoop = function () {
requestAnimationFrame(GameLoop);
render();
};
GameLoop();
</script>
</body>
</html>
And i get a black screen and
Uncaught TypeError: THREE.STLLoader is not a constructor
at test2.html:65
and
Uncaught ReferenceError: module is not defined
at STLLoader.js:32
All i want is to load an stl file and have some orbit controls to rotate around it.
EDIT:
Look at all these errors that pop up for god knows why:
Uncaught SyntaxError: Cannot use import statement outside a module
ot OrbitControls
Uncaught ReferenceError: module is not defined
at STLLoader.js:32
test2.html:51 Uncaught TypeError: THREE.OrbitControls is not a constructor
at test2.html:51
How hard can it be to just even load a model?
EDIT 2:
I am doing everything BY THE BOOK, and new errors pop up like :
Uncaught SyntaxError: The requested module '../libs/STLLoader.js' does not provide an export named 'STLLoader'
Sounds similar to Uncaught SyntaxError: Cannot use import statement outside a module
Depending on how you include OrbitControls and STLLoader, via <script> or import, you will need to copy from 'examples/js' or 'examples/jsm' respectively.
I am using the basic example on three.js but am unable to interact with the object to rotate via mouse interaction. Am I missing something obvious? My desired functionality is to rotate an object (such as a box) left,right,up,down, etc. The code I am using is as follows:
<!DOCTYPE html>
<script src="scripts/three.min.js"></script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My first Three.js app</title>
<style>
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script src="scripts/three.min.js"></script>
<script>
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( 3, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
var render = function () {
requestAnimationFrame( render );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
};
render();
</script>
</body>
</html>
You are missing EventListeners, your scene doesnt know about your mouse moving.
See this simple example from mr.doob on how to spin a cube with the mouse:
http://mrdoob.github.io/three.js/examples/canvas_geometry_cube.html
Similiar to the rotation on the Y-Axis (left, right) you can add rotation on the X-Axis (up, down) too.
I have been trying to incorporate FirstPersonControls following this example which is a bit more complicated to what I need. I haven't implemented the controls yet but I still am not able to see the content of what I am loading. This is my code so far:
<html>
<head>
<title> Prototype 2 </title>
<meta charset="utf-8">
<!--Include this one if the code doesn't work <script src="js/keyboard.js"></script>-->
<style>
body {
background-color: #ffffff;
margin: 0;
overflow: hidden;
font-family: arial;
}
#container {
position: absolute;
/*left: 0;
right: 0;
top: 0;
bottom: 0;*/
width: 100%;
height: 100%;
/*background-color: rgba(0,0,0,0.5);*/
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="js/three.min.js" type="text/javascript" ></script>
<script src="js/FirstPersonControls.js"></script>
</head>
<body>
<div id="container" >
</div >
<script src="js/main2.js"> </script>
</body>
</html>
This is main2.js
var container, scene, camera, renderer, controls, mesh;
function init() {
container = $('#container');
var WIDTH = container.width(),
HEIGHT = container.height();
//Scene
scene = new THREE.Scene();
//Render
renderer = new THREE.WebGLRenderer( {antialias: true} );
renderer.setClearColor( 0x000000 );
renderer.setSize( WIDTH, HEIGHT);
container.append( renderer.domelement);
//Camera
camera = new THREE.PerspectiveCamera( 45, WIDTH / HEIGHT, 0.1, 20000 );
//Might need this stuff later
camera.position.z = 10;
camera.position.y = 10;
camera.position.x = 20;
scene.add(camera);
//Create a light
var light = new THREE.PointLight(0xffffff);
light.position.set(-100,200,100);
scene.add(light);
//Here we load our custom shape
var loader = new THREE.JSONLoader();
loader.load("threejs_objects/lightwave.js", function( geometry){
// var material = new THREE.MeshLambertMaterial({color: 0xff0000});
var material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true} );
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
objects.push( mesh );
});
//If Window resizing...
window.addEventListener('resize', function(){
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
renderer.setSize( WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
});
}
function render(){
renderer.render( scene, camera);
}
function animate() {
requestAnimationFrame( animate );
render();
}
init();
animate();
Thanks!
Your code is running before the browser has parsed the HTML document and built the DOM.
Put your code inside onload.
window.onload = function() {
// your js code ( all the code inside the main2.js )
};
I'm starting to play with three.js and was wondering if there's a simple plugin to add the trackball functionality so I can see how the changes I'm making in code is affecting the "underside" of the simple object.
I tried to follow:
http://mrdoob.github.com/three.js/examples/misc_controls_trackball.html
But I'm getting a lot of EventDispatcher errors.
By try, I mean I've:
added "TrackballControls.js"
added "Detector.js"
added this bit of code:
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
controls.addEventListener( 'change', render );
I did notice that the three.js used in the example is different than the one at (but not sure if it matters):
http://cdnjs.cloudflare.com/ajax/libs/three.js/r53/three.min.js
Any suggestions would be extremely helpful as I'm just starting out.
Thank you for your time!
Update:
I tried using the latest build of Three.js from here:
https://github.com/mrdoob/three.js/blob/master/build/three.js
I couldn't find official builds of TrackballControls.js and Detector.js so I used these versions:
http://threejsdoc.appspot.com/doc/three.js/src.source/extras/controls/TrackballControls.js.html
http://mrdoob.github.com/three.js/examples/js/Detector.js
Here's the code that I could not get to work (it's a combination of http://www.aerotwist.com/tutorials/getting-started-with-three-js/ and http://mrdoob.github.com/three.js/examples/misc_controls_trackball.html and trying to make the object into a ring/torus):
<!doctype html>
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Getting Started with Three.js | Aerotwist</title>
<meta name="description" content="The home of Creative Coder and developer Paul Lewis. Tutorial, experiments and considered opinions found here.">
<meta name="author" content="Paul Lewis">
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="Three.js"></script>
<script src="TrackballControls.js"></script>
<script src="Detector.js"></script>
</head>
<style>
#container {
background: #000;
width: 400px;
height: 300px;
}
</style>
<body>
<div id="container"></div>
</body>
<script type="text/javascript">
function animate() {
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
}
var WIDTH = 400,
HEIGHT = 300;
// set some camera attributes
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;
// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('#container');
// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera =
new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR);
var scene = new THREE.Scene();
// TrackBall code from http://mrdoob.github.com/three.js/examples/misc_controls_trackball.html
var controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
//controls.addEventListener( 'change', render ); // this was how it used to be at: http://mrdoob.github.com/three.js/examples/misc_controls_trackball.html
controls.domElement.addEventListener( 'change', render ); // I changed this to fix error message: "controls.addEventListener is not a function"
// --------------------------
// add the camera to the scene
scene.add(camera);
// the camera starts at 0,0,0
// so pull it back
camera.position.z = 300;
// start the renderer
renderer.setSize(WIDTH, HEIGHT);
// attach the render-supplied DOM element
$container.append(renderer.domElement);
// ------------------------
// create the sphere's material
var sphereMaterial =
new THREE.MeshLambertMaterial(
{
color: 0xCC0000
});
// -------------------------------
// ################ try torus
var centerpiece = new THREE.TorusGeometry();
var sphere = new THREE.Mesh(
centerpiece,
sphereMaterial);
// add the sphere to the scene
scene.add(sphere);
// ---------------------------
// create a point light
var pointLight =
new THREE.PointLight(0xFFFFFF);
// set its position
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;
// add to the scene
scene.add(pointLight);
// -------------------------
// draw!
renderer.render(scene, camera);
</script>
Whenever I click anywhere on the page I get this error message:
_eye.copy(...).subSelf is not a function
Any ideas?
Thank you for your time!
Make sure you're using all the files from the same version. Ideally from the latest.
I'm starting with Three.js, and I'm trying to set up a simple first person controls in my scene, which is containing a single sphere. I just see a black screen. There are no errors.
Without FirstPersonControls, I can see the sphere.
What am I doing wrong ?
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
#container {
width: 400px;
height: 300px;
}
</style>
<script type="text/javascript" src="js/Three.js"></script>
<script type="text/javascript">
var controls;
window.onload = function() {
var RENDER_WIDTH = 400, RENDER_HEIGHT = 300;
// Creating scene
var scene = new THREE.Scene();
// Camera
var camera = new THREE.PerspectiveCamera(45, RENDER_WIDTH / RENDER_HEIGHT, 0.1, 10000);
camera.position.z = 300;
scene.add(camera);
controls = new THREE.FirstPersonControls(camera);
controls.movementSpeed = 1000;
controls.lookSpeed = 0.125;
controls.lookVertical = true;
// Sphere
var sphereMaterial = new THREE.MeshLambertMaterial({
color: 0x00ff00
});
var radius = 50, segments = 16, rings = 16;
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(radius, segments, rings),
sphereMaterial
);
scene.add(sphere);
// Light
scene.add(new THREE.AmbientLight(0x333333));
var light = new THREE.PointLight(0xffffff, 0.9);
light.position.set(50, 200, 50);
scene.add(light);
// Render
var container = document.getElementById('container');
var renderer = new THREE.WebGLRenderer();
renderer.setSize(RENDER_WIDTH, RENDER_HEIGHT);
renderer.setClearColorHex(0x000000, 1);
container.appendChild(renderer.domElement);
var clock = new THREE.Clock();
setInterval(function() {
var delta = clock.getDelta();
controls.update(delta);
renderer.render(scene, camera);
}, 100);
};
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
FirstPersonControls is designed to work with full-width canvases, so you need to set
var RENDER_WIDTH = window.innerWidth, RENDER_HEIGHT = window.innerHeight;
Also remove you style settings.
Finally, to make it easier to "find" your sphere, set controls.lookVertical = false -- just for now.
From that point, you'll just have to experiment.