I'm using MindAr and Three.js to build a scene where I can detect the marker and then load an image and a gltf model with its animation on top of the marker, so I tried to merge three.js code with mindar code
the problem is that I'm not able to load the gltf model, its not showing
here's my code
and please if anyone has any idea would be great
Thanks
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/mind-ar#1.1.5/dist/mindar-image-three.prod.js"></script>
<script type="module">
import { GLTFLoader } from 'https://cdn.jsdelivr.net/npm/three#0.114/examples/jsm/loaders/GLTFLoader.js';
const THREE = window.MINDAR.IMAGE.THREE;
const mindarThree = new window.MINDAR.IMAGE.MindARThree({
container: document.querySelector("#container"),
imageTargetSrc: "./assets/targets.mind"
});
const {renderer, scene, camera} = mindarThree;
var mixer;
const anchor = mindarThree.addAnchor(0);
var geometry = new THREE.PlaneGeometry(1, 0.55);
var texture = new THREE.TextureLoader().load( "./assets/TextureImage.png" );
var material = new THREE.MeshBasicMaterial( { map: texture } );
var mesh = new THREE.Mesh(geometry, material);
anchor.group.add(mesh);
var loader = new GLTFLoader();
loader.load( './assets/3DObject.glb', function ( gltf ) {
console.log(gltf);
console.log(anchor.group);
anchor.group.add( gltf.scene );
gltf.scene.scale.set(0.5,0.5,0.5);
console.log(scene);
/* mixer = new THREE.AnimationMixer( gltf.scene );
gltf.animations.forEach( ( clip ) => {
mixer.clipAction( clip ).play();
} ); */
},
// called while loading is progressing
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
// called when loading has errors
function ( error ) {
console.log( 'An error happened' );
} );
function animate() {
requestAnimationFrame( animate );
var delta = clock.getDelta();
if ( mixer ) mixer.update( delta );
renderer.render( scene, camera );
}
const start = async() => {
await mindarThree.start();
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
}
const startButton = document.querySelector("#startButton");
startButton.addEventListener("click", () => {
start();
});
stopButton.addEventListener("click", () => {
mindarThree.stop();
mindarThree.renderer.setAnimationLoop(null);
});
</script>
<style>
body {
margin: 0;
}
#container {
width: 100vw;
height: 100vh;
position: relative;
overflow: hidden;
}
#control {
position: fixed;
top: 0;
left: 0;
z-index: 2;
}
</style>
</head>
<body>
<div id="control">
<button id="startButton">Start</button>
<button id="stopButton">Stop</button>
</div>
<div id="container">
</div>
</body>
</html>
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 have a 3D model placed in a map using mapbox with javascript (using this tutorial) and I'm trying to change the object's location when a button is clicked. The object isn't moving, though, and I don't really know how to fix it.
This is the function I wrote to make the location change (I can see all those console logs when I hit the button, so I know the part that isn't working is the actual location update itself):
function updateObjectLocation(id,newTransform) {
let objectLayer = map.getLayer(id);
if (typeof objectLayer === 'undefined') {
console.log('layer ' + id + ' does not exist');
} else {
console.log(objectLayer);
console.log(newTransform);
objectLayer.render = function(gl, matrix) {
var rotationX = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(1,0,0),
newTransform.rotateX
);
var rotationY = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(0,1,0),
newTransform.rotateY
);
var rotationZ = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(0,0,1),
newTransform.rotateZ
);
var m = new THREE.Matrix4().fromArray(matrix);
var l = new THREE.Matrix4()
.makeTranslation(
newTransform.translateX,
newTransform.translateY,
newTransform.translateZ
)
.scale(
new THREE.Vector3(
newTransform.scale,
- newTransform.scale,
newTransform.scale
)
)
.multiply(rotationX)
.multiply(rotationY)
.multiply(rotationZ);
this.camera.projectionMatrix = m.multiply(l);
this.renderer.state.reset();
this.renderer.render(this.scene, this.camera);
this.map.triggerRepaint();
};
}
}
Welcome to Stackoverflow. The solution is much simpler, you only have to modify the transformation, no need to rewrite the render method.
Here you have a fiddle with the solution how to move a 3D model
And here the full code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Add a 3D model</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.css" rel="stylesheet" />
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
#move {
display: block;
position: relative;
margin: 0px auto;
width: 50%;
height: 40px;
padding: 10px;
border: none;
border-radius: 3px;
font-size: 12px;
text-align: center;
color: #fff;
background: #ee8a65;
}
</style>
</head>
<body>
<script src="https://unpkg.com/three#0.106.2/build/three.min.js"></script>
<script src="https://unpkg.com/three#0.106.2/examples/js/loaders/GLTFLoader.js">
</script>
<div id="map"></div>
<button id="move">Move</button>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoianNjYXN0cm8iLCJhIjoiY2s2YzB6Z25kMDVhejNrbXNpcmtjNGtpbiJ9.28ynPf1Y5Q8EyB_moOHylw';
var map = (window.map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
zoom: 18,
center: [148.9819, -35.3981],
pitch: 60,
antialias: true // create the gl context with MSAA antialiasing, so custom layers are antialiased
}));
// parameters to ensure the model is georeferenced correctly on the map
var modelOrigin = [148.9819, -35.39847];
var modelOrigin2 = [148.9816, -35.39851];
var modelAltitude = 0;
var modelRotate = [Math.PI / 2, 0, 0];
var modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(
modelOrigin,
modelAltitude
);
// transformation parameters to position, rotate and scale the 3D model onto the map
var modelTransform = {
translateX: modelAsMercatorCoordinate.x,
translateY: modelAsMercatorCoordinate.y,
translateZ: modelAsMercatorCoordinate.z,
rotateX: modelRotate[0],
rotateY: modelRotate[1],
rotateZ: modelRotate[2],
/* Since our 3D model is in real world meters, a scale transform needs to be
* applied since the CustomLayerInterface expects units in MercatorCoordinates.
*/
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
};
var THREE = window.THREE;
// configuration of the custom layer for a 3D model per the CustomLayerInterface
var customLayer = {
id: '3d-model',
type: 'custom',
renderingMode: '3d',
onAdd: function (map, gl) {
this.camera = new THREE.Camera();
this.scene = new THREE.Scene();
// create two three.js lights to illuminate the model
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(0, -70, 100).normalize();
this.scene.add(directionalLight);
var directionalLight2 = new THREE.DirectionalLight(0xffffff);
directionalLight2.position.set(0, 70, 100).normalize();
this.scene.add(directionalLight2);
// use the three.js GLTF loader to add the 3D model to the three.js scene
var loader = new THREE.GLTFLoader();
loader.load(
'https://docs.mapbox.com/mapbox-gl-js/assets/34M_17/34M_17.gltf',
function (gltf) {
this.scene.add(gltf.scene);
}.bind(this)
);
this.map = map;
// use the Mapbox GL JS map canvas for three.js
this.renderer = new THREE.WebGLRenderer({
canvas: map.getCanvas(),
context: gl,
antialias: true
});
this.renderer.autoClear = false;
},
render: function (gl, matrix) {
var rotationX = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(1, 0, 0),
modelTransform.rotateX
);
var rotationY = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(0, 1, 0),
modelTransform.rotateY
);
var rotationZ = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(0, 0, 1),
modelTransform.rotateZ
);
var m = new THREE.Matrix4().fromArray(matrix);
var l = new THREE.Matrix4()
.makeTranslation(
modelTransform.translateX,
modelTransform.translateY,
modelTransform.translateZ
)
.scale(
new THREE.Vector3(
modelTransform.scale,
-modelTransform.scale,
modelTransform.scale
)
)
.multiply(rotationX)
.multiply(rotationY)
.multiply(rotationZ);
this.camera.projectionMatrix = m.multiply(l);
this.renderer.state.reset();
this.renderer.render(this.scene, this.camera);
this.map.triggerRepaint();
}
};
map.on('style.load', function () {
map.addLayer(customLayer, 'waterway-label');
});
document.getElementById('move').addEventListener('click', function () {
// creating an event listener to modify the position to modelOrigin2
modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(
modelOrigin2,
modelAltitude
);
// transformation parameters to position, rotate and scale the 3D model onto the map
modelTransform = {
translateX: modelAsMercatorCoordinate.x,
translateY: modelAsMercatorCoordinate.y,
translateZ: modelAsMercatorCoordinate.z,
rotateX: modelRotate[0],
rotateY: modelRotate[1],
rotateZ: modelRotate[2],
/* Since our 3D model is in real world meters, a scale transform needs to be
* applied since the CustomLayerInterface expects units in MercatorCoordinates.
*/
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
};
});
</script>
</body>
</html>
BTW, if you are trying to create a much more interactive experience between Mapbox and Three.js, but I would recommend you to check out the latest version of threebox as it enables you to add as many models and 3D layers as you want but also to do things like these below with only a few lines of code
map.on('style.load', function () {
map.addLayer({
id: 'custom_layer',
type: 'custom',
renderingMode: '3d',
onAdd: function (map, mbxContext) {
window.tb = new Threebox(
map,
mbxContext,
{ defaultLights: true }
);
var options = {
obj: '/3D/soldier/soldier.glb',
type: 'gltf',
scale: 1,
units: 'meters',
rotation: { x: 90, y: 0, z: 0 } //default rotation
}
tb.loadObj(options, function (model) {
soldier = model.setCoords(origin);
tb.add(soldier);
})
},
render: function (gl, matrix) {
tb.update();
}
});
})
- 3D models built-in and custom animations
- Full raycast support MouseOver/Mouseout, Selected, Drag&Drop, Drag&Rotate, Wireframe
- CSS2D Tooltips and Labels that consider altitude
**- Three.js and Mapbox cameras sync with depth adjustment **
- Include geolocated models of monuments
i tried to import 3d model in .dae format in three js like below i am able to import it properly but i can not see textures for that model even thought i have textures folder and no error related to that. so i added one function using my function (switchtexture()) by passing object of child and matching the name of child i can give assign texture but no success can someone tell me where i am doing wrong ? is this right way or not
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - collada - skinning</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
background: #777;
padding: 0;
margin: 0;
font-weight: bold;
overflow: hidden;
}
#info {
position: absolute;
top: 0px;
width: 100%;
color: #ffffff;
padding: 5px;
font-family: Monospace;
font-size: 13px;
text-align: center;
}
a {
color: #ffffff;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
three.js webgl - collada - skinning
</div>
<script src="js/three.js"></script>
<script src="js/ColladaLoader.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/Detector.js"></script>
<script src="js/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats, clock;
var camera, scene, renderer, mixer;
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( - 7, 4, 7 );
scene = new THREE.Scene();
clock = new THREE.Clock();
// collada
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load("./wolf/Wolf_dae.dae", function (collada) {
var object = collada.scene;
mixer = new THREE.AnimationMixer( object );
object.traverse( function ( child ) {
switchTexture(child);
if ( child instanceof THREE.SkinnedMesh ) {
var clip = THREE.AnimationClip.parseAnimation( child.geometry.animation, child.geometry.bones );
mixer.clipAction( clip, child ).play();
}
} );
object.scale.set(1,1,1);
object.position.set(0, 0, 0);
object.rotateX(- Math.PI/2);
scene.add( object );
} );
//
var gridHelper = new THREE.GridHelper( 5, 20 );
scene.add( gridHelper );
//
var ambientLight = new THREE.AmbientLight( 0xcccccc );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( -1, 0.5, -1 ).normalize();
scene.add( directionalLight );
//
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
container.appendChild( renderer.domElement );
//
controls = new THREE.OrbitControls( camera, renderer.domElement );
//
stats = new Stats();
container.appendChild( stats.dom );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function switchTexture(obj) {
// for Textures
var imageDir = './wolf/textures/';
var images = {
"Wolf_obj_fur": imageDir + 'Wolf_Fur.jpg'
};
for (var prop in images) {
if (obj.name == prop) {
obj.children[0].material.map = THREE.ImageUtils.loadTexture(images[prop], {}, function () {
// add callback here if you want
});
}
}
}
function render() {
var delta = clock.getDelta();
if ( mixer !== undefined ) {
mixer.update( delta );
}
renderer.render( scene, camera );
}
</script>
</body>
</html>
here is the jiddle to see the code
https://jsfiddle.net/saisoft00/jv7rnos2/
and i downloaded the 3d model from this
https://free3d.com/3d-model/wolf-rigged-and-game-ready-42808.html
Try using THREE.MeshStandardMaterial for the mesh materials.
Your switchTexture will look something like this:
function switchTexture(obj) {
// for Textures
var imageDir = './wolf/textures/';
var images = {
"Wolf_obj_fur": imageDir + 'Wolf_Fur.jpg'
};
for (var prop in images) {
var material = new THREE.MeshStandardMaterial( {
map: new THREE.TextureLoader().load(images[prop])
});
if (obj.name == prop) {
obj.children[0].material = material;
}
}
}
You should also move from ImageUtils to TextureLoader, ImageUtils was deprecated.
I've tried multiple times to target my rect area light and it won't work. I am able to use a spot light and target and I don't understand why this would work and the other wouldn't. Normally, as in this example: threejs.org/examples/?q=obj#webgl_loader_obj2 there is an object plain. When I added the code pertaining to the target like the position and matrix the plain disappears and so does my OBJ. I honestly can't find anything on the issue pertaining to rectarea lights. Please help if you see what is wrong, thanks.
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0 0 0 0;
padding: 0 0 0 0;
border: none;
cursor: default;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 100;
display:block;
}
#info a {
color: #f00;
font-weight: bold;
text-decoration: underline;
cursor: pointer
}
#glFullscreen {
width: 100%;
height: 100vh;
min-width: 640px;
min-height: 360px;
position: relative;
overflow: hidden;
z-index: 0;
}
#example {
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: #000000;
}
#feedback {
color: darkorange;
}
#dat {
user-select: none;
position: absolute;
left: 0;
top: 0;
z-Index: 200;
}
</style>
</head>
<body>
<div id="glFullscreen">
<canvas id="example"></canvas>
</div>
<div id="dat">
</div>
<div id="info">
three.js - OBJLoader2 direct loader test
<div id="feedback"></div>
</div>
<script src="Detector.js"></script>
<script src="http://threejs.org/build/three.min.js"></script>
<script src="TrackballControls.js"></script>
<script src="MTLLoader.js"></script>
<script src="dat.gui.min.js"></script>
<script src="OBJLoader2.js"></script>
<script>
'use strict';
var OBJLoader2Example = (function () {
function OBJLoader2Example( elementToBindTo ) {
this.renderer = null;
this.canvas = elementToBindTo;
this.aspectRatio = 1;
this.recalcAspectRatio();
this.scene = null;
this.cameraDefaults = {
posCamera: new THREE.Vector3( 0.0, 175.0, 500.0 ),
posCameraTarget: new THREE.Vector3( 0, 0, 0 ),
near: 0.1,
far: 10000,
fov: 45
};
this.camera = null;
this.cameraTarget = this.cameraDefaults.posCameraTarget;
this.controls = null;
this.smoothShading = true;
this.doubleSide = false;
this.cube = null;
this.pivot = null;
}
OBJLoader2Example.prototype.initGL = function () {
this.renderer = new THREE.WebGLRenderer( {
canvas: this.canvas,
antialias: true,
autoClear: true
} );
this.renderer.setClearColor( 0x050505 );
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera( this.cameraDefaults.fov, this.aspectRatio, this.cameraDefaults.near, this. cameraDefaults.far );
this.resetCamera();
this.controls = new THREE.TrackballControls( this.camera, this.renderer.domElement );
var ambientLight = new THREE.AmbientLight( 0xffffff );
var directionalLight1 = new THREE.DirectionalLight( 0xC0C090, .4 );
var directionalLight2 = new THREE.DirectionalLight( 0xC0C090, .4 );
var directionalLight3 = new THREE.DirectionalLight( 0xC0C090, .4 );
var directionalLight4 = new THREE.DirectionalLight( 0xC0C090, .4 );
directionalLight1.position.set( -100, -50, 100 );
directionalLight2.position.set( 100, 50, -100 );
directionalLight3.position.set( -100, -50, -100 );
directionalLight4.position.set( 100, 50, 100 );
/*this.scene.add(directionalLight2);
this.scene.add(directionalLight1);
this.scene.add(directionalLight3);
this.scene.add(directionalLight4);*/
var helper = new THREE.GridHelper( 1200, 60, 0xFF4444, 0x404040 );
this.scene.add( helper );
var geometry = new THREE.BoxGeometry( .5, .5, .5 );
var material = new THREE.MeshNormalMaterial();
this.cube = new THREE.Mesh( geometry, material );
this.pivot = new THREE.Object3D();
this.pivot.name = 'Pivot';
this.scene.add( this.pivot );
var lighta = new THREE.RectAreaLight( 0xffffbb, 82, 1, 2 );
lighta.position.set(0, 0, 1 );
this.scene.add( lighta);
var helper = new THREE.RectAreaLightHelper( lighta );
// light.target.position.set( 0, 0, 0 );
// lighta.target.matrixWorldNeedsUpdate();
this.scene.add( helper );
};
OBJLoader2Example.prototype.initPostGL = function ( objDef ) {
var scope = this;
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( objDef.texturePath );
mtlLoader.setCrossOrigin( 'anonymous' );
mtlLoader.load( objDef.fileMtl, function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader2();
objLoader.setSceneGraphBaseNode( scope.pivot );
objLoader.setMaterials( materials.materials );
objLoader.setPath( objDef.path );
objLoader.setDebug( false, false );
var onSuccess = function ( object3d ) {
console.log( 'Loading complete. Meshes were attached to: ' + object3d.name );
};
var onProgress = function ( event ) {
if ( event.lengthComputable ) {
var percentComplete = event.loaded / event.total * 100;
var output = 'Download of "' + objDef.fileObj + '": ' + Math.round( percentComplete ) + '%';
console.log(output);
}
};
var onError = function ( event ) {
console.error( 'Error of type "' + event.type + '" occurred when trying to load: ' + event.src );
};
objLoader.load( objDef.fileObj, onSuccess, onProgress, onError );
});
return true;
};
OBJLoader2Example.prototype.resizeDisplayGL = function () {
this.controls.handleResize();
this.recalcAspectRatio();
this.renderer.setSize( this.canvas.offsetWidth, this.canvas.offsetHeight, false );
this.updateCamera();
};
OBJLoader2Example.prototype.recalcAspectRatio = function () {
this.aspectRatio = ( this.canvas.offsetHeight === 0 ) ? 1 : this.canvas.offsetWidth / this.canvas.offsetHeight;
};
OBJLoader2Example.prototype.resetCamera = function () {
this.camera.position.copy( this.cameraDefaults.posCamera );
this.cameraTarget.copy( this.cameraDefaults.posCameraTarget );
this.updateCamera();
};
OBJLoader2Example.prototype.updateCamera = function () {
this.camera.aspect = this.aspectRatio;
this.camera.lookAt( this.cameraTarget );
this.camera.updateProjectionMatrix();
};
OBJLoader2Example.prototype.render = function () {
if ( ! this.renderer.autoClear ) this.renderer.clear();
this.controls.update();
this.cube.rotation.x += 0.05;
this.cube.rotation.y += 0.05;
this.renderer.render( this.scene, this.camera );
};
OBJLoader2Example.prototype.alterSmoothShading = function () {
var scope = this;
scope.smoothShading = ! scope.smoothShading;
console.log( scope.smoothShading ? 'Enabling SmoothShading' : 'Enabling FlatShading');
scope.traversalFunction = function ( material ) {
material.shading = scope.smoothShading ? THREE.SmoothShading : THREE.FlatShading;
material.needsUpdate = true;
};
var scopeTraverse = function ( object3d ) {
scope.traverseScene( object3d );
};
scope.pivot.traverse( scopeTraverse );
};
OBJLoader2Example.prototype.alterDouble = function () {
var scope = this;
scope.doubleSide = ! scope.doubleSide;
console.log( scope.doubleSide ? 'Enabling DoubleSide materials' : 'Enabling FrontSide materials');
scope.traversalFunction = function ( material ) {
material.side = scope.doubleSide ? THREE.DoubleSide : THREE.FrontSide;
};
var scopeTraverse = function ( object3d ) {
scope.traverseScene( object3d );
};
scope.pivot.traverse( scopeTraverse );
};
OBJLoader2Example.prototype.traverseScene = function ( object3d ) {
if ( object3d.material instanceof THREE.MultiMaterial ) {
var materials = object3d.material.materials;
for ( var name in materials ) {
if ( materials.hasOwnProperty( name ) ) this.traversalFunction( materials[ name ] );
}
} else if ( object3d.material ) {
this.traversalFunction( object3d.material );
}
};
return OBJLoader2Example;
})();
var app = new OBJLoader2Example( document.getElementById( 'example' ) );
// Init dat.gui and controls
var OBJLoader2Control = function() {
this.smoothShading = app.smoothShading;
this.doubleSide = app.doubleSide;
};
var objLoader2Control = new OBJLoader2Control();
var gui = new dat.GUI( {
autoPlace: false,
width: 320
} );
var menuDiv = document.getElementById( 'dat' );
menuDiv.appendChild(gui.domElement);
var folderQueue = gui.addFolder( 'OBJLoader2 Options' );
var controlSmooth = folderQueue.add( objLoader2Control, 'smoothShading' ).name( 'Smooth Shading' );
controlSmooth.onChange( function( value ) {
console.log( 'Setting smoothShading to: ' + value );
app.alterSmoothShading();
});
var controlDouble = folderQueue.add( objLoader2Control, 'doubleSide' ).name( 'Double Side Materials' );
controlDouble.onChange( function( value ) {
console.log( 'Setting doubleSide to: ' + value );
app.alterDouble();
});
folderQueue.open();
// init three.js example application
var resizeWindow = function () {
app.resizeDisplayGL();
};
var render = function () {
requestAnimationFrame( render );
app.render();
};
window.addEventListener( 'resize', resizeWindow, false );
console.log( 'Starting initialisation phase...' );
app.initGL();
app.resizeDisplayGL();
app.initPostGL( {
fileObj: 'ex.obj',
fileMtl: 'ex.mtl'
} );
//pp.position.set( 0, 0, 0 );
render();
</script>
</body>
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 )
};