I have a model i'm exporting from blender 2.76b into json and then loading with three.js 71. Blender the model looks fine. In webGL the model is completely black. I'm think it has something to do with the textures but i'm not sure. The model is a fairly complex model made from maya and exported as an fbx. I've tested with simpler models and different textures and not had any problems but there's something wrong with this one.
Any suggestions would be appreciated greatly.
Link to the json: http://we.tl/GnQiOfAhOD
Here's the code.
<!DOCTYPE html>
<html lang="en">
<head>
<title>MultiLoader</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 {
font-family: Monospace;
background-color: #000;
color: #000;
margin: 0px;
overflow: hidden;
}
#info {
text-align: center;
padding: 10px;
z-index: 10;
width: 100%;
position: absolute;
}
a {
text-decoration: underline;
cursor: pointer;
}
#stats { position: absolute; top:0; left: 0 }
#stats #fps { background: transparent !important }
#stats #fps #fpsText { color: #aaa !important }
#stats #fps #fpsGraph { display: none }
</style>
</head>
<body>
<div id="info">MultiLoader Testing</div>
<script src="build/three.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<script src="js/ColladaLoader.js"></script>
<script src="js/OBJLoader.js"></script>
<script>
WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 1,
FAR = 10000;
var container, stats;
var camera, scene, renderer;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
// SCENE
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xffffff, 500, 10000 );
// CAMERA
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.position.set(60, 40, 120);
camera.lookAt(scene.position);
scene.add(camera);
//LIGHTS
var front = new THREE.DirectionalLight( 0xffffff, 5.4 );
front.position.set( 0, 140, 1500 );
front.position.multiplyScalar( 1.1 );
//front.color.setHSL( 0.6, 0.075, 1 );
scene.add( front );
var ambient = new THREE.AmbientLight(0xffffff);
scene.add( ambient );
var back = new THREE.DirectionalLight( 0xffffff, 0.5 );
back.position.set( 0, -140, -1500);
scene.add( back );
//Avatar Tests
var loader = new THREE.JSONLoader();
loader.load('models/Maya/modelExport.json', function ( geometry, materials ) {
material = new THREE.MeshFaceMaterial( materials );
avatar = new THREE.Mesh( geometry, material );
}
);
loader.onLoadComplete=function(){
avatar.scale.set(30, 30, 30);
var position = new THREE.Vector3(0,-20,0);
avatar.position.add(position);
scene.add( avatar );
}
// RENDERER
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( scene.fog.color );
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.shadowMapEnabled = true;
container.appendChild( renderer.domElement );
// Orbit Controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
//controls.addEventListener( 'change', render ); // add this only if there is no animation loop (requestAnimationFrame)
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = true;
//
stats = new Stats();
container.appendChild( stats.domElement );
//
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 render() {
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
</body>
</html>
There are several issues with the code and model.
For the model: The entry mapLight should have been named mapDiffuse. I know you are exporting the model so you need to find how to make this happen.
For the code:
Your ambient light is very strong. It washes out everything. Try a value of 0x222222 or remove it from the scene totally.
Your camera does not need to be added to the scene.
Remove renderer.setClearColor( fog_color ) just to see if you get the correct meshes and materials first. Then you can go the scene effects.
Your texture size is way big. It is not supported in webgl. Try a size of 1024 and then move up is you need to.
Finally your loader.onLoadComplete() is never called (and will never be). Move that part of the code in your loader.load() callback function.
After all this you will see your girl.
Related
I'm starting on three.js and I'm already stuck on a trivial case : display an image on a sprite. I can only get a black plane following the lines written in the documentation:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>TEST Sprite</title>
<style>
body { margin: 0; background-color:#000; }
canvas { width: 100%; height: 100%; }
#glRender {
position:absolute;
top: 50px;
left: 200px;
min-width: 200px;
width: 50%;
min-height: 200px;
z-index: 1;
height: 50%;
border: 10px solid #38272C;
}
</style>
</head>
<body>
<div id="glRender"></div>
<script src="http://threejs.org/build/three.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 / 2, window.innerHeight / 2 );
container = document.getElementById( 'glRender' );
document.body.appendChild( container );
container.appendChild( renderer.domElement );
// A simple cube
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 );
// completely black...
var photoTexLoad = new THREE.TextureLoader().load( 'http://s2.favim.com/610/150817/plage-summer-Favim.com-3137863.jpg' );
var matPhoto = new THREE.SpriteMaterial( { map: photoTexLoad, color: 0xffffff } );
var sprite = new THREE.Sprite( matPhoto );
sprite.scale.set( 2, 2, 2 );
sprite.position.set( 1, 0, 0.5 );
scene.add( sprite );
camera.position.z = 5;
function render() {
requestAnimationFrame( render );
cube.rotation.x += 0.01;
cube.rotation.y += 0.1;
renderer.render( scene, camera );
}
render();
</script>
</body>
</html>
I get the spinning green cube intersecting with a black plane.
What did I miss to have the image displayed on the plane?
.TextureLoader().load() is asynchronous. Trying to apply it immediately after invoking it leads to a black plane in your code most likely because the texture has not finished loading.
You can solve this by:
Passing a callback to .load as a 2nd parameter. (It is called once the texture has finished loading):
var matPhoto,
sprite,
texloader = new THREE.TextureLoader();
texloader.load('http://s2.favim.com/610/150817/plage-summer-Favim.com-3137863.jpg',
function(tex) {
matPhoto = new THREE.SpriteMaterial( { map: tex, color: 0xffffff } );
sprite = new THREE.Sprite( matPhoto );
//...etc...
}
);
OR
set an event listener:
var texloader = new THREE.TextureLoader();
texloader.load('http://s2.favim.com/610/150817/plage-summer-Favim.com-3137863.jpg');
textureLoader.addEventListener('load', function(event){
// event.content holds the texture---------------v
matPhoto = new THREE.SpriteMaterial( { map: event.content, color: 0xffffff } ); = event.content;
});
I just found out I got the "CORS" issue highlighted in question three.js: texture goes all black
The code is working fine but I cannot try to load an image from external website or directly on my computer, only files on my localhost.
For testing, I now use a specific instance of google chrome using a desktop shortcut launching the browser as : "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --args --user-data-dir="C:/Chrome dev session" --disable-web-security
i have an instance of dat.GUI. I added a "comboBox" to that instance to make a selection of possible values. When i run my app, the dat.GUI appears with the comboBox but there is a problem: I cannot change it's default value (my gui is frozen), here is my code:
<html>
<head>
<title>Stack Overflow</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<div id="container"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="js/three.min.js"></script>
<script src="js/optimer_regular.typeface.js"></script>
<script src="js/TrackballControls.js"></script>
<script src="js/stats.min.js"></script>
<script src="js/threex.dynamictexture.js"></script>
<script src="js/dat.gui.min.js"></script>
<script>
//Basic Three components
var scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000 );
//position camera
camera.position.z = 700;
//Set camera controls
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 ];
//Set the renderer
var renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//Set the lights
var light;
scene.add( new THREE.AmbientLight( 0x404040 ) );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 1, 1 );
scene.add( light );
//GUI
initGUI();
//Let's add a cube
var geometry = new THREE.BoxGeometry( 50, 50, 50 );
var material = new THREE.MeshBasicMaterial( { color: 0x5484d3 } );
var cube = new THREE.Mesh( geometry, material );
cube.position.set(0,20,50)
scene.add( cube );
function initGUI(){ //HERE IS THE MEAT, I THINK
var LevelView = function() {
this.level = 'Operacion';
// Define render logic ...
};
var gui = new dat.GUI();
var text = new LevelView();
gui.add(text, 'level', [ 'Operacion', 'Procesos', 'Participantes', 'Fuentes de Datos', 'Logica de software', 'Telecomunicaciones', 'Infraestructura'] ).onChange(function(value){
this.level = value;
});
}
function animate() {
requestAnimationFrame( animate );
render();
}
//Render scene
function render() {
controls.update();
renderer.render( scene, camera );
}
animate();
</script>
</body>
</html>
¿What i am doing wrong? I need to be able to change values with my GUI.
Solution: If you use a mouse-controlled camera with three.js, you have to comment the following line in the MouseListener of the mouseDown action:
event.preventDefault();
Place div containing dat.gui element bellow Three.js div
<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
and then dat.gui
<div id="gui"></div>
I am new in three.js and using the following code I want to know how to change the background by clicking a button. So I think there is something different than using "switch" and "break". Here is something with .loadTexture am I right?
<html lang="en">
<head>
<title>gyroscopic</title>
<meta charset="utf-8">
<meta name="viewport" content="user-scalable=no, initial-scale=1">
<style>
body {
margin: 0px;
background-color: #000000;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="three.min.js"></script>
<script src="DeviceOrientationControls.js"></script>
<script>
(function() {
"use strict"
window.addEventListener('load', function() {
var container, camera, scene, renderer, controls, geometry, mesh;
var animate = function(){
window.requestAnimationFrame( animate );
controls.update();
renderer.render(scene, camera);
};
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 1, 1100);
controls = new THREE.DeviceOrientationControls( camera );
scene = new THREE.Scene();
var geometry = new THREE.SphereGeometry( 500, 316, 18 );
geometry.applyMatrix( new THREE.Matrix4().makeScale( -1, 1, 1 ) );
var material = new THREE.MeshBasicMaterial( {
map: THREE.ImageUtils.loadTexture( 'pic.jpg' )
} );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
var geometry = new THREE.BoxGeometry( 100, 100, 100, 4, 4, 4 );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.domElement.style.position = 'absolute';
renderer.domElement.style.top = 0;
container.appendChild(renderer.domElement);
window.addEventListener('resize', function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}, false);
animate();
}, false);
})();
</script>
</body>
</html>
You should be able to change the texture using .loadTexture on a button click listener.
So you would probably add something like this to your HTML:
<button id="change-background">Change Background</button>
Then in Javascript:
var backgroundButton = document.getElementById('change-background');
backgroundButton.addEventListener('click', function(){
material.map = THREE.ImageUtils.loadTexture('//new image path//');
});
You'll obviously need to replace the //new image path// with whatever URL you have for the new image.
The only question would be whether this updates the material on the mesh as well. I'm sure it does, but have no way of testing it at present.
I embed misc_controls_orbit example in 800x600 frame inside a larger webpage with other content.
My problem is when i scroll my mousewheel, it's do both scroll the webpage and zoom my object even when my mouse is inside or outside the frame.
What i need now is when my mouse is inside the frame, it's only zoom the object, not scroll all webpage with it, and when the mouse is outside the frame, it's will only scroll the webpage, not zoom object (like Sketchfab embeds here:http://www.klaasnienhuis.nl/2012/09/sketchfab-embeds/ )
This problem seem like only happen with OrbitControls, Trackball is not, i had search and try in many way but still no result, can anyone help me? (sr my bad english, hope you understand, plz ask if you don't)
this is original misc_controls_orbit code i'm using:
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - orbit controls</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 {
color: #000;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
background-color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color:#000;
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
a {
color: red;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
three.js - orbit controls example
</div>
<script src="../build/three.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer;
var cross;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 500;
controls = new THREE.OrbitControls( camera );
controls.addEventListener( 'change', render );
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
// world
var geometry = new THREE.CylinderGeometry( 0, 10, 30, 4, 1 );
var material = new THREE.MeshLambertMaterial( { color:0xffffff, shading: THREE.FlatShading } );
for ( var i = 0; i < 500; i ++ ) {
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = ( Math.random() - 0.5 ) * 1000;
mesh.position.y = ( Math.random() - 0.5 ) * 1000;
mesh.position.z = ( Math.random() - 0.5 ) * 1000;
mesh.updateMatrix();
mesh.matrixAutoUpdate = false;
scene.add( mesh );
}
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( scene.fog.color, 1 );
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
function animate() {
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
Use a canvas to render webgl and add an event listener
Use this html:
<canvas id="webglcanvas" width="800" height="600"></canvas>
with this javascript
function onMouseWheel(evt) {
evt.preventDefault();
/* TODO : your zoom */
}
function addMouseHandler(canvas) {
canvas.addEventListener('mousemove', onMouseMove, false);
canvas.addEventListener('mousedown', onMouseDown, false);
canvas.addEventListener('mouseup', onMouseUp, false);
canvas.addEventListener('onwheel' in document ? 'wheel' : 'mousewheel', onMouseWheel, false);
}
function createScene(canvas) {
renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true
});
// Set the viewport size
renderer.setSize(canvas.width, canvas.height);
}
$(document).ready(function () {
var canvas = document.getElementById("webglcanvas");
// create the scene
createScene(canvas);
// add mouse handling so we can rotate the scene
addMouseHandler(canvas);
// Run the run loop
run();
});
I have a 'choose file' button I want to use for loading a client side file instead of loading from the server path in loader.load() on line 86. I'm guessing I need to use File API but haven't figured out how after looking at this solution.
Existing web page that loads file from server path in line 86:
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-color:#fea47c;
}
div {
position:relative;
left:200px;
top:0px;
background-color: #eeeeee;
border:1px solid black;
width:550px;
height:550px;
}
canvas {
width:550px;
height:550px;
}
input#file
{
position:relative;left:425px;
}
</style>
</head>
<body>
<input type="file" name="file" id="file"></input><br><br>
<script src="https://raw.github.com/mrdoob/three.js/master/build/three.min.js"></script>
<script src="https://raw.github.com/mrdoob/three.js/master/examples/js/loaders/STLLoader.js"></script>
<script src="https://raw.github.com/mrdoob/three.js/master/examples/js/controls/TrackballControls.js"></script>
<script>
var container, camera, scene, renderer, controls;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var width = container.clientWidth;
var height = container.clientHeight;
camera = new THREE.PerspectiveCamera(
35, // field of view in degrees?
width / height, // canvas based aspect ratio; use when canvas is smaller than page
.1 , // distance to nearest side of rendered space
10000 // distance to farthest side of rendered space
);
camera.position.set( 0, 0, 10);
scene = new THREE.Scene();
controls = new THREE.TrackballControls( camera , container);
controls.addEventListener( 'change', render );
// object
var loader = new THREE.STLLoader();
loader.addEventListener( 'load', function ( event ) {
var geometry = event.content;
var material = new THREE.MeshLambertMaterial( { ambient: 0xff5533, color: 0xff5533 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
} );
loader.load( 'path to .stl file on server usually goes here' );
// lights
scene.add( new THREE.AmbientLight( 0x222222 ) );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
directionalLight.position = camera.position;
scene.add( directionalLight );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( width , height );
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function addLight( x, y, z, color, intensity ) {
var directionalLight = new THREE.DirectionalLight( color, intensity );
directionalLight.position.set( x, y, z )
scene.add( directionalLight );
}
function onWindowResize() {
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize( width, height );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
render();
}
function render() {
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
</body>
</html>
Is the script on a server? In general web browsers are made to not permit file:// references except when the page itself is a file:// reference (and even then you might need to set some security/debug flags, varying according to the browser). So if you are running a webgl script in a page that's accessed via http:// you may be out of luck unless you piggyback through a file service like dropbox.