Three.js CanvasRenderer Artifacts - three.js

I am trying to load a collada file using Threejs. All works well, but if I make the object spin I can see that the rendering is not right. Check the image:
Here is the code (which was partially stolen from another example):
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = 'Drag to spin the cube';
container.appendChild( info );
camera = new THREE.PerspectiveCamera( 20, window.innerWidth / window.innerHeight, .1, 10000 );
camera.position.x=50;
camera.position.y=50;
camera.position.z=50;
camera.lookAt(new THREE.Vector3(0,0,0));
scene = new THREE.Scene();
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
var ambientLight = new THREE.AmbientLight(0x000000);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(100,50,80).normalize();
scene.add(directionalLight);
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true; // this rotates so it looks right
loader.load('models/VM.dae', function (result) {
cube = result.scene;
// cube.doubleSided = true;
// cube.flipSided = true;
console.log(cube);
cube.updateMatrix();
scene.add(result.scene);
animate();
});
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
cube.rotation.y += 0.01;
// plane.rotation.y = cube.rotation.y += ( targetRotation - cube.rotation.y ) * 0.05;
renderer.render( scene, camera );
}
New update:
I changed the loader to a MTL+OBJ one. The result is exactly the same:
var loader = new THREE.OBJMTLLoader();
loader.addEventListener("load", function (event) {
cube = event.content;
cube.doubleSided = true;
console.log(event);
scene.add(cube);
animate();
});
loader.load ("models/VM.obj", "models/VM.mtl");
Fiddle: http://jsfiddle.net/qMqH7/

Your model is throwing errors in the Console, I would suggest you track them down.
What you are seeing is a known limitation of CanvasRenderer related to depth-sorting. It is made worse by your geometry which has several elongated faces. The model renders correctly with WebGLRenderer.
Also, object.doubleSided has been deprecated. It has been replaced by material.side = THREE.DoubleSide. It does not appear that flag is required in this case.
three.js r.58

Related

three.js outline does not work when scene set `scene.background=texture`

I caeate outline according to this example https://threejs.org/examples/?q=out#webgl_postprocessing_outline.And this is the result.It is works well.But when i set scene.background=texture,it is not work.IAnd i check the three.js document about scene.background. (If not null, sets the background used when rendering the scene, and is always rendered first. Can be set to a Color which sets the clear color, a Texture covering the canvas, or a CubeTexture. Default is null).I want to find out why outline disappear.Here is the code.
var scene, camera, renderer;
var light, floor;
var WIDTH,HEIGHT;
var controls;
var composer;
var composer, effectFXAA, outlinePass;
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
init();
animation()
function init () {
scene = new THREE.Scene();
var textureLoader = new THREE.TextureLoader();
textureLoader.load('img/bg.png', function(texture){
scene.background = texture;
});
camera = new THREE.PerspectiveCamera(45, WIDTH/HEIGHT, 0.1, 800);
camera.position.set(0,150,150);
scene.add(camera);
scene.add(new THREE.AmbientLight(0xffffff));
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(WIDTH, HEIGHT);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
controls = new OrbitControls(camera);
var shape = new THREE.Shape();
shape.moveTo(0,4);
shape.lineTo(0,96);
shape.lineTo(4,100);
shape.lineTo(96,100);
shape.lineTo(100,96);
shape.lineTo(100,4);
shape.lineTo(96, 0 );
shape.lineTo(84,0);
shape.lineTo(80,4);
shape.lineTo(20, 4);
shape.lineTo(16, 0);
shape.lineTo(4, 0 );
shape.lineTo(0, 4);
var geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings );
var material = new THREE.MeshLambertMaterial( { color: 0x0E2350 } );
mesh = new THREE.Mesh( geometry, material ) ;
mesh.rotation.x = -Math.PI/2;
mesh.translateX(-50);
mesh.translateY(-50);
scene.add(mesh);
composer = new THREE.EffectComposer( renderer );
var renderPass = new THREE.RenderPass( scene, camera );
composer.addPass( renderPass );
outlinePass = new THREE.OutlinePass( new THREE.Vector2( window.innerWidth, window.innerHeight ), scene, camera );
outlinePass.edgeStrength = 3;
outlinePass.edgeGlow = 3.0;
outlinePass.edgeThickness = 0.1;
outlinePass.visibleEdgeColor.setHex(0x19C0EE);
composer.addPass( outlinePass );
effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
effectFXAA.uniforms[ 'resolution' ].value.set( 1 / window.innerWidth, 1 / window.innerHeight );
effectFXAA.renderToScreen = true;
composer.addPass( effectFXAA );
outlinePass.selectedObjects = [mesh];
}
function animation() {
requestAnimationFrame(animation);
composer.render();
render();
controls.update();
};
function render () {
renderer.render(scene, camera)
};

Three.js Applying Repeated Texture to JSON Scene Object

I have a basic json scene exported from the three.js/editor. I want to add a repeated texture wrap to an object in this scene but I do not know how to do so since the only examples I have found add the wrap in the creation of the object.
I have already tried accessing the texture and giving it a wrap, but I think I might need to add a texture to the object from the JavaScript then declare the texture wrap instead of trying to add it to an already loaded texture.
<script>
var camera, scene, renderer;
var mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
scene = new THREE.Scene();
var objectLoader = new THREE.ObjectLoader();
objectLoader.load( "models/cube.json", function ( obj ) {
scene.add( obj )
obj.traverse(function(child) {
if (child instanceof THREE.Mesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
obj.name = "cube";
obj.position.set(0,0,0);
obj.scale.set(200,200,200);
});
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//
window.addEventListener( 'resize', onWindowResize, false );
while (scene.getObjectByName('Box 1')){
var texture = scene.getObjectByName('Box 1').material;
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 2, 2 );
}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
if (scene.getObjectByName('Box 1') ){
scene.getObjectByName('Box 1').material.map.offset.x += 0.001;
}
renderer.render( scene, camera );
}
</script>
You need to set the wrap and repeat properties of the texture/map and not of the material. Docs also say it's important to set needsUpdate to true, if wrap settings changed. And you are trying to set the properties before the json is loaded (in a while loop?). You should do it within the load callback.
objectLoader.load( "models/cube.json", function ( obj ) {
scene.add( obj )
obj.traverse(function(child) {
if (child instanceof THREE.Mesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
obj.name = "cube";
obj.position.set(0,0,0);
obj.scale.set(200,200,200);
var box1 = scene.getObjectByName('Box 1');
if (box1) {
var texture = box1.material.map;
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 2, 2 );
texture.needsUpdate = true;
}
});

Basic THREE.js scene setup

my question is simple but for the life of me i cannot figure out what is going on. I am trying to set up a basic three.js scene and add a simple cube with a BaiscMaterial however the cube is not showing up in my scene.
"use strict";
var renderer, scene, camera;
var light;
function init() {
var canvasWidth = 850;
var canvasHeight = 450;
var canvasRatio = canvasWidth / canvasHeight;
camera = new THREE.PerspectiveCamera(45, canvasRatio, 0.9, 1000);
camera.position.set(0, 200, -550);
camera.lookAt(0, 0, 0);
light = new THREE.AmbientLight(0xFFFFFF, 1);
light.position.set(-800, 900, 300);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(canvasWidth, canvasHeight);
renderer.setClearColorHex(0x000000, 1.0); //canvas color
renderer.gammaInput = true;
renderer.gammaOutput = true;
}
function cube() {
var cubeGeo = new THREE.CubeGeometry(1000, 1000, 1000);
var cubeMaterial = new THREE.MeshBasicMaterial();
var cube1 = new THREE.Mesh(cubeGeo, cubeMaterial);
cube1.position.set(0, 0, 0);
return cube1;
}
function fillScene() {
scene = new THREE.Scene();
scene.add(light);
var cube = cube();
scene.add(cube);
}
function addToDOM() {
var container = document.getElementById('container');
var canvas = container.getElementsByTagName('canvas');
if (canvas.length > 0) {
container.removeChild(canvas[0]);
}
container.appendChild(renderer.domElement);
}
function render() {
fillScene();
renderer.render(scene, camera);
}
try {
init();
fillScene();
addToDOM();
render();
} catch (e) {
var errorReport = "Your Program encountered an ERROR, cannot draw on canvas. Error was:<br/><br/>";
$('#container').append(errorReport + e);
}
First of all, Cube is updated to BoxGeometry now. And I see lots of problem on your code and improper function definition and usage.
Here's a very simple example from mr.doob's Github.
var scene, camera, renderer;
var geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 1000;
geometry = new THREE.BoxGeometry( 200, 200, 200 );
material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
See the demo here
P.S Three.js Docs is the best place for resources, it makes work alot easier with tons of example code.

GUI and Raycaster dont work together (three.js)

I have the following code to add a gui and the ability to click on objects.
When I set the controls as controls = new THREE.TrackballControls( camera, renderer.domElement); the GUI works but the Raycaster doesnt seem to work.
If I define the constrols as controls = new THREE.TrackballControls( camera); the raycaster works, however once I click the gui on the corner, then wherever I move the mouse the values of the gui change, while if I close it, the GUI resize with response to mouse movements
Can Anyone give me any hint how to fix this?
At the moment works but I'm able to unclick from the control by simultaneously left and right clicking
This link shows how far I have gone and give you an idea of the problem
http://subsurface.gr/joomla/threejs/StreamFnc_ws.html
Here is the full code:
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
// global variables
var camera, controls, scene, renderer;
var container, stats;
var raycaster, intersects;
var threshold = 0.05;
var mouse = new THREE.Vector2();
var cube;
// Parameters for GUI
var params = {
AAmin: 0.0,
AAmax: 1000.0
};
// main functions
init();
animate();
function init(){
container = document.createElement( 'div' );
document.body.appendChild( container );
//Setup Camera
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
camera.name = 'camera';
camera.position.z = 20;
// Setup world
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
// Setup lights
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( 1, 1, 1 );
scene.add( directionalLight );
directionalLight.name = 'directionalLight';
var directionalLight1 = new THREE.DirectionalLight( 0x002288 );
directionalLight1.position.set( -1, -1, -1 );
directionalLight1.name = 'directionalLight1';
scene.add( directionalLight1 );
var ambientLight = new THREE.AmbientLight( 0x222222 );
ambientLight.name = 'ambientLight';
scene.add( ambientLight );
raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = threshold;
// Main Scene
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
cube = new THREE.Mesh( geometry, material );
cube.name = 'mycube';
scene.add( cube );
// GUI parameter
var gui = new dat.GUI();
gui.add( params, 'AAmin', -1000, 500 );
gui.add( params, 'AAmax', 500, 2000 );
gui.open();
//renderer
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( scene.fog.color );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
//controls
controls = new THREE.TrackballControls( camera);
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
controls.addEventListener( 'change', render);
stats = new Stats();
container.appendChild( stats.dom );
// events
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
render();
}
function animate() {
requestAnimationFrame( animate );
render();
controls.update();
}
function render() {
renderer.render( scene, camera );
stats.update();
}
function onDocumentMouseDown( event ){
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
intersects = raycaster.intersectObject( cube );
if ( intersects.length > 0 ){
console.log("You click a cube!");
}
}
If I understand correctly, the TrackballControls is stopping propagation of the mouseDown event (bound to the renderer.domElement) -- meaning your onDocumentMouseDown handler isn't being invoked. Try moving your document.addEventListener(...) to come before new THREE.TrackballControls(...).
Responding to your comment below:
I see the problem now. There appears to be an incompatibility between TrackballControls and Dat.GUI in that the TrackballControls mouseup events stops propagation of the event, which causes Dat.GUI to bug out and get stuck resizing the UI for some reason.
I believe you can solve this by disabling TrackballControls when clicking the GUI, and re-enabling TrackballControls on mouseup:
gui.domElement.addEventListener( 'mousedown', function(){ controls.enabled = false; }, false );
document.addEventListener( 'mouseup', function(){ controls.enabled = true; }, false );

Importing 3D model exported from Blender/maya in Threejs and rendering it using CanvasRenderer for iPad

Am trying to create an app which will import the 3D model exported from Blender/Maya into ThreeJS. I have installed Blender and three js export option is also coming, however when am trying to load the exported JS (I tried renaming extension to json also) it is not working and showing blank screen. Can anyone help me with this by providing a sample code for this?
TIA.
Regards,
NileshW
add a div to the body
<div id="myScene"></div>
then..
<script>
// global
var scene, renderer, camera, cube, controls;
init();
animate();
function init() {
// scene box
var myScene = document.getElementById("myScene");
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, .01, 10000);
camera.position.z = 500;
var light = new THREE.AmbientLight(0xffffff); // soft white light
scene.add(light);
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
/* ==== OPTIONAL SPOTLIGHT ====
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(100, 1000, 2000);
spotLight.castShadow = true;
spotLight.shadowMapWidth = 1024;
spotLight.shadowMapHeight = 1024;
spotLight.shadowCameraNear = 500;
spotLight.shadowCameraFar = 4000;
spotLight.shadowCameraFov = 30;
scene.add(spotLight);
*/
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
myScene.appendChild(renderer.domElement);
loader = new THREE.JSONLoader();
loader.load("your_json_file.js", function (geometry, materials) {
mesh = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial(materials));
scene.add(mesh);
});
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
</script>
Have you tried the code from chawk - just change to use your test.js (check folder path)
If the code in you function init() is complete then it looks like you've missed a couple of things
You have created a camera, created a scene, created a loader, loaded a file and added mesh to the scene
You need to add the camera to the scene
You also need to add some light(s) to your scene
var camera, scene, renderer;
var geometry, material, mesh;
var controls;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 5, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 50, 50, 50 );
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 = false;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
scene = new THREE.Scene();
var light = new THREE.PointLight(0xffffff);
light.position.set(-100,200,100);
scene.add(light);
// Load in the mesh and add it to the scene.
var loader = new THREE.JSONLoader();
loader.load( "models/testnew.js", function(geometry){
var material = new THREE.MeshNormalMaterial({color: 0x55B663});
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
});
//
renderer = new THREE.CanvasRenderer();
renderer.setSize( 1000, 600);
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}

Resources