On my chrome browser, I've got an error:
undefined is not a function
at the line: dom.addEventListener( 'mouseup', onMouseUp, false);
I'm learning webGL and here is my actual code:
<html>
<head>
<?php include "header.php"?>
<title>Learning WebGL</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="/glmatrix/glMatrix.min.js"></script>
<script type="text/javascript" src="../three.min.js"></script>
<script type="text/javascript" src="../requestAnimationFrame.js"> </script>
<script>
var renderer = null,
scene = null,
camera = null,
cube = null,
animating = false;
function onload()
{
var container = document.getElementById("container");
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(container.offsetWidth, container.offsetHeight);
container.appendChild(renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, container.offsetWidth/container.offsetHeight, 1, 4000);
camera.position.set(0,0,3);
var light = new THREE.DirectionalLight(0xffffff, 1.5);
light.position.set(0,0,1);
scene.add(light);
var mapUrl = "/test.jpg";
var map = THREE.ImageUtils.loadTexture(mapUrl);
var material = new THREE.MeshPhongMaterial({map: map});
var geometry = new THREE.CubeGeometry(1,1,1);
cube = new THREE.Mesh(geometry, material);
cube.rotation.x = Math.PI / 5;
cube.rotation.y = Math.PI / 5;
scene.add(cube);
addMouseHandler();
run();
}
function run()
{
renderer.render(scene,camera);
if(animating){
cube.rotation.y -= 0.01;
}
requestAnimationFrame(run);
}
function addMouseHandler()
{
var mydom = renderer.domElement;
mydom.addEventlistener('mouseup', onMouseUp, false);
}
function onMouseUp(event){
event.preventDefault();
animating = !animating;
}
</script>
</head>
<body onload="onload();">
<?php include "navigation.php"?>
<div id="container" style="width:95%; height:95%; position:absolute;">
</div>
<div id="prompt" style="width:95%; height:6%; bottom:0; position:absolute;">
Click to animate the cube
</div>
</body>
</html>
I've tried changing the variable name from "dom" to "mydom" but that doesn't help.
Many thanks!
Related
In a simple IFC.js application, loading IFC models (and fragments for that matter) fails with TypeError: this.geometry is undefined when accelerating the raycast using three-mesh-bvh. Removing that makes the application work again. I have tried with plenty of different IFC models, all of which work when removing the acceleration. Even the test models (Schependomlaan.ifc for example) fail when loading them.
Source of the app: https://github.com/gjkf/simple-ifc
app.js:
import { AmbientLight, AxesHelper, DirectionalLight, GridHelper, PerspectiveCamera, Scene, WebGLRenderer } from 'three';
import { acceleratedRaycast, computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { IFCLoader } from 'web-ifc-three/IFCLoader';
//Creates the Three.js scene
const scene = new Scene();
//Object to store the size of the viewport
const size = {
width: window.innerWidth,
height: window.innerHeight,
};
//Creates the camera (point of view of the user)
const camera = new PerspectiveCamera(75, size.width / size.height);
camera.position.z = 15;
camera.position.y = 13;
camera.position.x = 8;
//Creates the lights of the scene
const lightColor = 0xffffff;
const ambientLight = new AmbientLight(lightColor, 0.5);
scene.add(ambientLight);
const directionalLight = new DirectionalLight(lightColor, 1);
directionalLight.position.set(0, 10, 0);
directionalLight.target.position.set(-5, 0, 0);
scene.add(directionalLight);
scene.add(directionalLight.target);
//Sets up the renderer, fetching the canvas of the HTML
const threeCanvas = document.getElementById("three-canvas");
const renderer = new WebGLRenderer({ canvas: threeCanvas, alpha: true });
renderer.setSize(size.width, size.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
//Creates grids and axes in the scene
const grid = new GridHelper(50, 30);
scene.add(grid);
const axes = new AxesHelper();
axes.material.depthTest = false;
axes.renderOrder = 1;
scene.add(axes);
//Creates the orbit controls (to navigate the scene)
const controls = new OrbitControls(camera, threeCanvas);
controls.enableDamping = true;
controls.target.set(-2, 0, 0);
//Animation loop
const animate = () => {
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
animate();
//Adjust the viewport to the size of the browser
window.addEventListener("resize", () => {
(size.width = window.innerWidth), (size.height = window.innerHeight);
camera.aspect = size.width / size.height;
camera.updateProjectionMatrix();
renderer.setSize(size.width, size.height);
});
//Sets up the IFC loading
const ifcLoader = new IFCLoader();
ifcLoader.ifcManager.useWebWorkers(true, "worker/IFCWorker.js");
ifcLoader.ifcManager.setWasmPath("../wasm/");
ifcLoader.ifcManager.applyWebIfcConfig({
USE_FAST_BOOLS: true,
COORDINATE_TO_ORIGIN: true,
});
ifcLoader.ifcManager.setupThreeMeshBVH(
acceleratedRaycast,
computeBoundsTree,
disposeBoundsTree
);
const input = document.getElementById("file-input");
input.addEventListener(
"change",
async (changed) => {
const ifcURL = URL.createObjectURL(changed.target.files[0]);
// ifcLoader.load(ifcURL, (ifcModel) => scene.add(ifcModel));
const model = await ifcLoader.loadAsync(ifcURL, (e) => console.log(e));
console.log(model);
scene.add(model);
},
false
);
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<title>IFC.js</title>
</head>
<body>
<input type="file" id="file-input" accept=".ifc, .ifcXML, .ifcZIP">
<canvas id="three-canvas"></canvas>
<script src="bundle.js"></script>
</body>
</html>
I made this simple application to nail down the problem, but in a different (Angular) project I would really need the accelerated raycasting to ensure the experience is smooth.
The problem was with your call to "setupThreeMeshBVH()"
This is a proper call with a proper sequence👇
ifcLoader.ifcManager.setupThreeMeshBVH(
computeBoundsTree,
disposeBoundsTree,
acceleratedRaycast
);
In your code, you had given "computeBoundsTree" as the second parameter whereas it should be first.
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 working on an anatomy application based on three.js. Recently I am trying to visualize a skeleton and an ecorche model. Both of us are .obj-s with an .mtl file and there are jpeg files as textures. My problem is that my app visualize the two models but on the ecorche the are no textures and the skeleton is black. The problem is somewhere in the obj and mtl loader. I guess there is also an easier way to load the models.
The files of a model is in a separate folder.
My other question is how I can manage to make a button that change the actual model to the other one.
Thank you for your help!
Here is the code:
if (!Detector.webgl) {
Detector.addGetWebGLMessage();
}
var container;
var camera, controls, scene, renderer;
var lighting, ambient, keyLight, fillLight, backLight;
var windowDivideX = window.innerWidth / 3.4;
var files=['WorkAlpha.obj','untitled.mtl'];
init();
animate();
function init() {
container = document.createElement('viewer');
document.body.appendChild(container);
/*Creating Camera*/
camera = new THREE.PerspectiveCamera(45, windowDivideX /
window.innerHeight, 1, 100);
camera.position.y = 0;
camera.position.z = 40;
camera.position.x = 0;
/* Scene and Lights */
scene = new THREE.Scene();
lighting = false;
ambient = new THREE.AmbientLight(0xEAE1EA, 0.3);
scene.add(ambient);
keyLight = new THREE.DirectionalLight(0xEAE1EA, 0.6);
//(new THREE.Color('hsl(30, 80%, 0%)'), 1.0);
keyLight.position.set(-100, 0, 100);
fillLight = new THREE.DirectionalLight(0xEAE1EA, 0.6);
//(new THREE.Color('hsl(30, 80%, 0%)'), 0.6);
fillLight.position.set(100, 0, 100);
backLight = new THREE.DirectionalLight(0xffffff, 0.6);
backLight.position.set(100, 0, -100).normalize();
//ambient.intensity = 0.1;
scene.add(keyLight);
scene.add(fillLight);
scene.add(backLight);
/////////////////////////////////////////////////////////////////////////
/* Model */
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl('assets/');
mtlLoader.setPath('assets/');
mtlLoader.load(files [0], function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('assets/');
objLoader.load('WorkAlpha.obj', function (object) {
object.position.y = 3;object.position.x = 0;
object.position.z = 0;
object.name = "muscles";
scene.add(object);
});
});
mtlLoader.setBaseUrl('skeleton/');
mtlLoader.setPath('skeleton/');
mtlLoader.load(files[1], function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('skeleton/');
objLoader.load('untitled.obj', function (object) {
object.position.y = -15;object.position.x = 0;
object.position.z = 0;
object.name = "skeleton";
scene.add(object);
});
});
/* Renderer */
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(windowDivideX, window.innerHeight);
renderer.setClearColor(0xC9D2D3);
container.appendChild(renderer.domElement);
/* Controls */
controls = new THREE.OrbitControls(camera,
renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = true;
controls.maxPolarAngle = Math.PI/2;
/* Events */
window.addEventListener('resize', onWindowResize, false);
window.addEventListener('keydown', onKeyboardEvent, false);
}
function onWindowResize() {
camera.aspect = windowDivideX / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(windowDivideX, window.innerHeight);
}
function onKeyboardEvent(e) {
if (e.code === 'KeyL') {
lighting = !lighting;
if (lighting) {
ambient.intensity = 0.25;
scene.add(keyLight);
scene.add(fillLight);
scene.add(backLight);
} else {
ambient.intensity = 1.0;
scene.remove(keyLight);
scene.remove(fillLight);
scene.remove(backLight);
}
}
}
function animate() {
requestAnimationFrame(animate);
controls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
Here you can see the HTML:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="three.js"></script>
<script src="Detector.js"></script>
<script src="OrbitControls.js"></script>
<script src="OBJLoader.js"></script>
<script src="MTLLoader.js"></script>
<script src="TrackballControls.js"></script>
<script
src="https://threejs.org/examples/js/renderers/Projector.js">
</script>
<script
src="https://threejs.org/examples/js/renderers/CanvasRenderer.js">
</script>
<link rel="stylesheet" href="bootstrap.min.css">
<script src="jquery.min.js"></script>
<script src="bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="design.css">
</head>
<body>
<script src="3d.js"></script>
</body>
</html>
I use ShaderMaterial to create real material for my cube. But it not works well. As can see, only first face work well. Even when i use different texture for different faces, it not works. I don't know what is problem with my code.
Here is my code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Test_material</title>
<style type="text/css" media="all">
canvas {
border: 1px solid #000;
}
</style>
</head>
<body>
<div id='container'></div>
<script type="text/javascript" src="js/threejs/Three.js">
</script>
<script type="text/javascript" src="js/lib/util.js">
</script>
<script type="text/javascript" src="js/threejs/TrackballControls.js"></script>
<script>
var WIDTH= 400;
var HEIGHT = 400;
var container = document.getElementById('container');
var camera =new THREE.PerspectiveCamera(25, WIDTH/HEIGHT, 1, 10000);
camera.position.set(0,300,100);
var animate;
var scene = new THREE.Scene();
scene.add(camera);
camera.lookAt(scene.position);
var controls = new THREE.TrackballControls(camera);
//custom shape
materialArr = [];
var data = new utils.Storage.ResourceStorage();
data.load({
'textures': {
'track_normal_0' : 'images/pattern/track_normal_0.jpg',
'track_diffuse_0' : 'images/pattern/track_diffuse_0.jpg',
'track_specular_0' : 'images/pattern/track_specular_0.jpg',
'track_normal_0' : 'images/pattern/track_normal_0.jpg',
'track_diffuse_0' : 'images/pattern/track_diffuse_0.jpg',
'track_specular_0' : 'images/pattern/track_specular_0.jpg',
'track_normal_1' : 'images/pattern/track_normal_1.jpg',
'track_diffuse_1' : 'images/pattern/track_diffuse_1.jpg',
'track_specular_1' : 'images/pattern/track_specular_1.jpg',
'track_normal_2' : 'images/pattern/track_normal_2.jpg',
'track_diffuse_2' : 'images/pattern/track_diffuse_2.jpg',
'track_specular_2' : 'images/pattern/track_specular_2.jpg',
'track_normal_3' : 'images/pattern/track_normal_3.jpg',
'track_diffuse_3' : 'images/pattern/track_diffuse_3.jpg',
'track_specular_3' : 'images/pattern/track_specular_3.jpg',
'track_normal_4' : 'images/pattern/track_normal_4.jpg',
'track_diffuse_4' : 'images/pattern/track_diffuse_4.jpg',
'track_specular_4' : 'images/pattern/track_specular_4.jpg',
'track_normal_5' : 'images/pattern/track_normal_5.jpg',
'track_diffuse_5' : 'images/pattern/track_diffuse_5.jpg',
'track_specular_5' : 'images/pattern/track_specular_5.jpg',
},
'onReady': init
});
function init(){
var materialArr = [];
for (var i=0; i< 6; i++){
var shader = THREE.ShaderLib['normalmap'];
var normalTexture = data.getTexture('track_normal_' + i).clone();
normalTexture.needsUpdate = true;
var diffuseTexture = data.getTexture('track_diffuse_' + i);
diffuseTexture.needsUpdate = true;
var specularTexture = data.getTexture('track_specular_' + i);
specularTexture.needsUpdate = true;
var uniforms = THREE.UniformsUtils.clone(shader.uniforms);
uniforms['tNormal'].value = normalTexture;
uniforms['tDiffuse'].value = diffuseTexture;
uniforms['tSpecular'].value = specularTexture;
uniforms['enableDiffuse'].value = true;
uniforms['enableSpecular'].value = true;
uniforms['uSpecularColor'].value.setHex(0x00cc00);
uniforms['uDiffuseColor'].value.setHex(0x0000ff);
<!--uniforms['uShininess'].value = 100;-->
var material = new THREE.ShaderMaterial({
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader + " ",
uniforms: uniforms,
lights: true
});
material.perPixel = true;
material.needsUpdate = true;
materialArr.push(material);
}
var geometry = new THREE.CubeGeometry(40, 40, 40);
geometry.computeTangents();
var material = new THREE.MeshFaceMaterial(materialArr);
for (var i=0; i< material.materials.length; i++){
material.materials[i].needsUpdate = true;
}
mesh =new THREE.Mesh(geometry, material);
scene.add(mesh);
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(WIDTH, HEIGHT);
container.appendChild(renderer.domElement);
var dirLight = new THREE.DirectionalLight(0xffffff);
scene.add(dirLight);
var ambientLight = new THREE.AmbientLight(0xcddacc);
scene.add(ambientLight);
renderer.render(scene, camera);
animate = function (){
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
};
animate();
}
</script>
</body>
</html>
My result
I would suggest using a single material and tweaking the UVs of the geometry instead. Take a look at the minecraft example to see how to do that.
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.