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
Related
I want to apply a script(from javascript) only in ONE DIV(not at all the page). Is it possible? (I think it's a resize problem if we modify the height of the div it partly works but the width doesn't affect by change(I talk about the div))
Here's my script:
var camera2, scene2;
function init2() {
var container, stats;
container = document.createElement( 'div' );
document.body.appendChild( container );
camera2 = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
camera2.position.z = 250;
scene2 = new THREE.Scene();
var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
scene2.add( ambientLight );
var pointLight = new THREE.PointLight( 0xffffff, 0.8 );
camera2.add( pointLight );
scene2.add( camera2 );
var loader = new THREE.OBJLoader();
var mtlLoader = new THREE.MTLLoader();
mtlLoader.load( "3d_models/OBJ/ano/ano.mtl", function( materials ) {
materials.preload();
console.log(materials);
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.load("3d_models/OBJ/ano/ano.obj", function ( object ) {
console.log(object.children[0])
scene2.add( object );
onRenderFcts.push(function(){
object.rotation.y += 0.03;
})
});
},
function ( xhr ) {
console.log( 'OBJ ' + ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
function ( error ) {
console.log(error);
});
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
}
And is it possible to change the background, it's actually a black background I just want a transparent background.
EDIT: Here is the screenshot: the golden rign is my 3d object and the green square is my div
image
EDIT2: To clarify the problem, I have a page and on the page there is a div just want to apply the three.js function only on this div. So at the end, i could see my golden ring only in the div
I obtained a "correct" result by grope. Here's the code I modify:
container = document.createElement( 'div' );
var att = document.createAttribute("class");
att.value = "test";
container.setAttributeNode(att);
document.body.appendChild( container );
then here's the test and canvas class in css:
.test{
width:100px;
height:100px;
position: fixed;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -100px;
}
canvas{
width:500px;
height:500px;
margin-top: -275px;
margin-left: -630px;
}
But now there is another problem. If a I try to call the script on a more complex code it doesn't work ! The console doesn't notice error. Here's the picture describing the situation: img
So the golden ring should be on the marker(the logo on the left) and in the black zone there is normally the golden ring rotate normally. Also the blackzone can be fixed with the tips in the com of my first post.
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.
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 have the following Three.js code:
<html>
<head>
<title>My first Three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="js/three.min.js"></script>
<script src="js/optimer_regular.typeface.js"></script>
<script>
//Basic Three components
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 );
//Let´s add a 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 );
camera.position.z = 5;
//Let´s add a text
var material2 = new THREE.MeshPhongMaterial({
color: 0x00ff00
});
var textGeom = new THREE.TextGeometry( 'Sitescope', {
font: 'optimer',
weight: 'normal'
});
var textMesh = new THREE.Mesh( textGeom, material2 );
scene.add( textMesh );
//Render scene
function render() {
requestAnimationFrame( render );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
}
render();
</script>
</body>
When i run my code, My cube renders well but my text does not appear anywhere.
The only output that i get in the javascript console is:
THREE.WebGLRenderer 69.
Could anyone tell me why my text does not appear? (I am a beginner in Three.js) Thanks!
When using a THREE.MeshPhongMaterial() you need a light in the scene. Otherwise the model will come out black. If your scene background is also black you will never know if the model was drawn or not. Take a look at this fiddle. I am using THREE.MeshNormalMaterial(). Replace it with PhongMaterial to see what I am talking about. You can see the text is being drawn with black color just because it is over the green cube.
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();
});