So I am trying to get a JSONLoader to work from threejs.org
Three.js is working for sure because I have no problem creating a cube. But when I try to load a js file throuh JSONLoader then nothing happens.
<html>
<head>
<title>My first Three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="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( { alpha: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// instantiate a loader
var loader = new THREE.JSONLoader();
// load a resource
loader.load(
// resource URL
'logo.js',
// Function when resource is loaded
function ( geometry, materials ) {
var material = new THREE.MultiMaterial( materials );
var object = new THREE.Mesh( geometry, material );
scene.add( object );
}
);
camera.position.z = 5;
var render = function () {
renderer.setClearColor( 0x000000, 0 );
requestAnimationFrame( render );
renderer.render(scene, camera);
};
render();
</script>
</body>
</html>
As mentioned in the title then the code is copy pasted from threejs own website and should be working.
Can someone help me figure what is going wrong?
here is a fiddle with the script of logo.js https://jsfiddle.net/380z6096/
the object has been exported from 3ds max with the 3ds Max JSExporter
I am using xampp and chrome.
Your camera is inside your geometry.
You can determine the dimensions of your geometry like so
geometry.computeBoundingSphere();
console.log( geometry.boundingSphere );
or
geometry.computeBoundingBox();
console.log( geometry.boundingBox );
Scale your geometry
object.scale.multiplyScalar( 0.01 );
Or move your camera back.
three.js r.75
Related
I've been attempting to get the SSAO post-processing shader to work with the latest (r77) version of three.js. I've been using the EffectComposer, with the code entirely duplicated from the example page here:
http://threejs.org/examples/webgl_postprocessing_ssao.html
The relevant code being:
var renderPass = new THREE.RenderPass( Engine.scene, Engine.camera );
ssaoPass = new THREE.ShaderPass( THREE.SSAOShader );
ssaoPass.renderToScreen = true;
// ...various ShaderPass setup parameters
Engine.effectComposer = new THREE.EffectComposer( Engine.renderer );
Engine.effectComposer.addPass(renderPass);
Engine.effectComposer.addPass(ssaoPass);
The issue I have been having is that that SSAO doesn't seem to work with SkinnedMeshes. It seems to take into account the position of the meshes before the skinning calculations are performed.
It looks like this:
Problem with SSAO on SkinnedMesh
Does anyone have any experience with this on the latest version? I've looked all over the place, but can't find any documentation about how to start fixing this at all.
I found mention of a fix for this in another SO post (ThreeJS SSAO Shader w/ Skinned/Animated Models), but the solution has been deprecated.
Thanks in advance, and happy to go into more detail if needed.
As requested, here is the complete code for the simple demo page:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="js/libs/jquery.min.js"></script>
<script type="text/javascript" src="js/libs/three.min.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/CopyShader.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/EffectComposer.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/MaskPass.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/RenderPass.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/ShaderPass.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/DotScreenShader.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/SSAOShader.js"></script>
<link rel="stylesheet" type="text/css" href="demo.css" />
</head>
<body>
<div id="demo-container"></div>
</body>
</html>
<script>
$(document).ready(function() {
window.doPostPro = 0;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 1, 1000);
camera.position.set(0, 200, 200);
camera.lookAt(new THREE.Vector3(0, 0, 0));
clock = new THREE.Clock();
// Setup the renderer.
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xFFFFFF );
function setupPostProcessing() {
// Setup render pass
var renderPass = new THREE.RenderPass( scene, camera );
// Setup depth pass
depthMaterial = new THREE.MeshDepthMaterial();
depthMaterial.depthPacking = THREE.RGBADepthPacking;
depthMaterial.blending = THREE.NoBlending;
depthRenderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
stencilBuffer: true
});
// Setup SSAO pass
ssaoPass = new THREE.ShaderPass( THREE.SSAOShader );
ssaoPass.renderToScreen = true;
//ssaoPass.uniforms[ "tDiffuse" ].value will be set by ShaderPass
ssaoPass.uniforms[ "tDepth" ].value = depthRenderTarget.texture;
ssaoPass.uniforms[ 'size' ].value.set( window.innerWidth, window.innerHeight );
ssaoPass.uniforms[ 'cameraNear' ].value = camera.near;
ssaoPass.uniforms[ 'cameraFar' ].value = camera.far;
//ssaoPass.uniforms[ 'onlyAO' ].value = ( postprocessing.renderMode == 1 );
ssaoPass.uniforms[ 'aoClamp' ].value = 0.3;
ssaoPass.uniforms[ 'lumInfluence' ].value = 0.5;
// Add pass to effect composer
effectComposer = new THREE.EffectComposer( renderer );
effectComposer.addPass( renderPass );
effectComposer.addPass( ssaoPass );
};
setupPostProcessing();
// Load the mesh.
var loader = new THREE.JSONLoader();
loader.load( "js/zombie.js", function( geometry, materials ) {
var originalMaterial = materials[ 0 ];
originalMaterial.skinning = true;
geometry.computeVertexNormals();
var mesh = new THREE.SkinnedMesh(geometry, originalMaterial);
window.animMixer = new THREE.AnimationMixer(mesh);
var animAction = animMixer.clipAction(geometry.animations[0]);
animAction.play();
scene.add(mesh);
});
var ambientLight = new THREE.AmbientLight( 0xCCCCCC );
scene.add( ambientLight );
$("#demo-container").append( renderer.domElement );
function render() {
if ( doPostPro ) {
// Render depth into depthRenderTarget
scene.overrideMaterial = depthMaterial;
renderer.render( scene, camera, depthRenderTarget, true );
// Render renderPass and SSAO shaderPass
scene.overrideMaterial = null;
effectComposer.render();
}
else {
renderer.render( scene, camera );
}
}
function animate() {
requestAnimationFrame( animate );
if ( window.animMixer != undefined ) {
var deltaTime = clock.getDelta();
animMixer.update(deltaTime);
}
render();
}
animate();
$(document).keyup(function(e) {
// P is pressed.
if ( e.which == 80 ) {
window.doPostPro = !window.doPostPro;
}
});
});
</script>
If you are skinning, and using this pattern in your render loop
// Render depth into depthRenderTarget
scene.overrideMaterial = depthMaterial;
renderer.render( scene, camera, depthRenderTarget, true );
you have to make sure to set
depthMaterial.skinning = true;
Thing is, if there are other elements in the scene that are not skinned, doing so will throw errors. In which case, this may be a three.js design issue that will have to be addressed.
three.js r.77
Created the following mesh in blender:
Whenever I load it into three.js I receive the following result:
I export to .obj format and triangulate all of my faces. Not sure why this is happening. Below is the threejs code I am using to render the mesh. I use the same code with other meshes and they render as expected. I'm guessing I've done something that three.js doesn't like with this mesh?
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="/js/three.js"></script>
<script type="text/javascript" src="/js/DDSLoader.js"></script>
<script type="text/javascript" src="/js/MTLLoader.js"></script>
<script type="text/javascript" src="/js/OBJLoader.js"></script>
<script type="text/javascript" src="/js/OrbitControls.js"></script>
<script type="text/javascript" src="/js/stats.js"></script>
<script type="text/javascript" src="/js/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>
<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 130;
camera.position.y = 40;
camera.position.z = 50;
camera.lookAt(scene.position);
scene.add(camera);
// create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
//webGLRenderer.setPixelRatio( window.devicePixelRatio );
webGLRenderer.setClearColor(new THREE.Color(0xffffff, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;
var ambient = new THREE.AmbientLight( 0x444444 );
ambient.intensity = 5;
scene.add( ambient );
if('stiletto_switchblade_knife.mtl' !== ''){
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl( '/assets/download/mesh/18/' );
mtlLoader.setPath( '/assets/download/mesh/18/' );
mtlLoader.load( 'stiletto_switchblade_knife.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( '/assets/download/mesh/18/' );
objLoader.load( 'stiletto_switchblade_knife.obj', function ( object ) {
//object.scale.set(100, 100, 100);
//object.rotation.x = -0.3;
scene.add( object );
});
});
} else {
var objLoader = new THREE.OBJLoader();
objLoader.setPath( '/assets/download/mesh/18/' );
objLoader.load( 'stiletto_switchblade_knife.obj', function ( object ) {
object.material = new THREE.MeshLambertMaterial({color: 0xFFFFFF});
//object.scale.set(100, 100, 100);
//object.rotation.x = -0.3;
scene.add( object );
});
}
// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
var controls = new THREE.OrbitControls(camera, webGLRenderer.domElement );
render();
// simple render
function render() {
stats.update();
controls.update();
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>
EDIT
Are meshes required to be watertight in three.js? If so that could be the problem as there are a couple areas that are not in this mesh. That's the only thing I can think of at the moment that differs between this and the meshes that render properly.
Renders like that turned up with OBJ models in three.js R76. It turned out that any object containing a stray "l" (line) element blew up just like what you have shown. I found the bad objects by searching the ASCII OBJ file on "l ", got rid of the strays by selecting and hiding all of the faces, and dealing with whatever was left.
Solved. Turned out I had left a few faces drawn inside of the mesh. This was causing the unexpected behavior. Interesting debugging method. I just started stripping away vertices and rendering with threejs until I found the section that was causing the issue.
I have Imported a simple extruded cube with 2 bones and a material from blender to threejs using the threejs exporter.
The model, material and bones export are fine. I can rotate the bones and the mesh and material are manipulated correctly.
Issue: When I apply a texture to the mesh then model disappears with following error.
type error material is undefined.
<html>
<head>
</head>
<body>
<script src="js/three.min.js"></script>
<script src="js/three.js"></script>
<script>
var scene,camera,renderer;
var skinnedMesh=[];
var material=[];
var texture=[];
var flag=0;
init();
function init()
{
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize( window.innerWidth, window.innerHeight-125 );
document.body.appendChild( renderer.domElement );
//////////
// CAMERA//
//////////
camera = new THREE.PerspectiveCamera( 70, window.innerWidth/Window.innerHeight, 1, 2000 );
camera.position.z = 15;
scene= new THREE.Scene();
scene.add(camera);
var loader = new THREE.JSONLoader;
loader.load('blockbone.js',loadmesh);
//////////
// LIGHT//
//////////
var light2 = new THREE.SpotLight(0xffffff);
light2.position.set(500,50,3000);
scene.add(light2);
render();
}
function loadmesh(geometry,material) {
//texture=(new THREE.MeshPhongMaterial( { map:
//THREE.ImageUtils.loadTexture( "10.png" ) }));
//texture.needsUpdate = true;
//material[0] = new THREE.MeshFaceMaterial(texture);
skinnedMesh = new THREE.SkinnedMesh(geometry,material[0]);
geometry.dynamic = true;
material[0].skinning = true;
scene.add(skinnedMesh);
}
function render()
{
scene.traverse(function(child){
if (child instanceof THREE.SkinnedMesh)
{
if (child.skeleton.bones[1].rotation.y<=1.5 && flag==0)
{
child.skeleton.bones[1].rotation.y +=.02;
}
else
{
flag=1;
}
if (child.skeleton.bones[1].rotation.y>=-3 && flag==1)
{
child.skeleton.bones[1].rotation.y -=.02;
}
else
{
flag=0;
}
child.skeleton.bones[0].rotation.y -=.01;
}
});
renderer.render(scene, camera);
requestAnimationFrame(render);
}
</script>
</body>
</html>
I have only manipulated textures on manually created meshes. Please suggest/advise what is going wrong.
I have solved this issue. The json file that I had exported from blender to use with Threejs was incomplete. In order to add an external texture to an externely loaded skinned mesh you must first add a texture in blender so that blender generates a UV map then export the json file.
Once the UV map is exported with json file you can then change the texture of the model.
Hope this helps other people.
I've been messing around with Threejs trying to get my sea legs, but I've run into a problem long before I expected to and I can't figure out if there's a mistake in my code or a mistake in the framework (I assume it's mine).
I want to replace an object with another when a button is pressed. My test code (below) loads a cube on the initial load, and I was hoping to replace it with a sphere when a button is pressed. However, that's not happening, and instead I'm getting the error:
TypeError: geometry.addEventListener is not a function
geometry.addEventListener( 'dispose', onGeometryDispose );
My html:
<!doctype html>
<html lang="en">
<head>
<title>My test</title>
<meta charset="utf-8">
</head>
<body style="margin: 0;">
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.js"></script>
<script src="OrbitControls.js"></script>
<script>
var WIDTH = 500,
HEIGHT = 500;
var scene = new THREE.Scene();
var aspect = WIDTH / HEIGHT;
var camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
camera.position.set(0,0,5);
scene.add(camera);
var renderer = new THREE.WebGLRenderer();
renderer.setSize( WIDTH , HEIGHT );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshNormalMaterial();
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
controls = new THREE.OrbitControls(camera, renderer.domElement);
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
}
animate();
</script>
<div>
<button onclick="updateThing();">Update Thing</button>
</div>
</body>
<script src="scripts.js" type="text/javascript" charset="utf-8"></script>
</html>
My function for making the change when the button is pressed:
function updateThing() {
scene.remove(cube)
var pos = new THREE.Vector3(0, 0, 0);
var geo = new THREE.Sphere(pos, parseFloat(1.4));
var mat = new THREE.MeshNormalMaterial();
sphere = new THREE.Mesh( geo, mat );
scene.add( sphere );
}
Am I doing something wrong?
Orbit controls can be found here: https://github.com/mrdoob/three.js/blob/master/examples/js/controls/OrbitControls.js
I believe you are looking for THREE.SphereGeometry instead of THREE.Sphere:
var geo = new THREE.SphereGeometry(parseFloat(1.4));
See documentation here and here.
I don't undestand why this script doesn't work in IE, while it works in Firefox and Chrome. When I try to use this script in IE, I get this message "ACTIVEX stop script".
Please help me.
<!DOCTYPE html>
<html>
<head>
<title>Getting Started with Three.js</title>
<script type="text/javascript" src="http://www.html5canvastutorials.com/libraries/Three.js"></script>
<script type="text/javascript">
window.onload = function() {
var renderer = new THREE.WebGLRenderer();
renderer.setSize( 800, 600 );
document.body.appendChild( renderer.domElement );
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
35, // Field of view
800 / 600, // Aspect ratio
0.1, // Near plane
10000 // Far plane
);
camera.position.set( 15, 10, 10 );
camera.lookAt( scene.position );
scene.add( camera );
var cube = new THREE.Mesh(
new THREE.CubeGeometry( 5, 5, 5 ),
new THREE.MeshLambertMaterial( { color: 0xFF0000 } )
);
scene.add( cube );
var light = new THREE.PointLight( 0xFFFF00 );
light.position.set( 10, 0, 10 );
scene.add( light );
renderer.render( scene, camera );
};
</script>
</head>
<body></body>
The Three.js WebGLRenderer doesn't work in IE (no WebGL support)
try
var renderer = new THREE.CanvasRenderer()
instead
As an alternative to the very simple solution above you can utilize alteredq and mrdoob's great Detector.js script that is included with the examples for three.js. If you use code like below you can use the WebGLRenderer as default and use canvas only if WebGL is not available. You can also use a flag like webglEnabled in order to set other options depending on your renderer later in your code.
var webglEnabled = false;
var webglReq = false;
if (Detector.webgl) {
renderer = new THREE.WebGLRenderer(
{
antialias: true,
preserveDrawingBuffer: true
}); // allow screenshot
webglEnabled = true; // set flag
}
else if (webglReq) { Detector.addGetWebGLMessage(); return false; }
else {
renderer = new THREE.CanvasRenderer();
}
renderer.setClearColorHex(0x000000, 1);
renderer.setSize(window.innerWidth, window.innerHeight);