Updating Three.js Skeletal Animations to New Mixer Based System - javascript

The mixer system was introduced in r73, and I've been trying since then to update my game to this new system.
I am ALMOST there except one thing. Cross-fading on some animations with certain geometries have a slight delay that did not exist in r72. I hacked r72's BlendCharacter and Animation functions to allow callbacks and it works great. In 73 this was not necessary has it has this functionality built in via an event trigger.
In the following fiddle everything works as intended (r72).
http://jsfiddle.net/titansoftime/a93w5hw0/
<script src="http://www.titansoftime.com/webgl/Three72.full.js"></script>
<script src="http://www.titansoftime.com/webgl/BlendCharacter2.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/DDSLoader.js"></script>
var scene, camera, renderer, ambient, directional;
var mesh, geoCache={};
var clock, jsLoader, ddsLoader;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 20;
camera.position.y = 10;
ambient = new THREE.AmbientLight(0xffffff);
scene.add(ambient);
directional = new THREE.DirectionalLight(0xffffff,1);
directional.position.set(1,1,0);
scene.add(directional);
clock = new THREE.Clock();
jsLoader = new THREE.JSONLoader(true);
ddsLoader = new THREE.DDSLoader();
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff, 1 );
document.getElementById('idle').onclick = function(e){
play('Idle',true);
};
document.getElementById('run').onclick = function(e){
play('Run',true);
};
document.getElementById('melee').onclick = function(e){
play('MelleAttack');
};
document.getElementById('magic').onclick = function(e){
play('MagicAttack');
};
document.body.appendChild( renderer.domElement );
loadFloor();
loadModel();
}
function createModel(json){
var geo, geo2;
if( geoCache[json.name] ){
geo = geoCache[json.name];
}else{
geo2 = jsLoader.parse(json).geometry;
var m = new THREE.SkinnedMesh( geo2 );
m.normalizeSkinWeights();
geo2 = m.geometry;
geo = new THREE.BufferGeometry().fromGeometry(geo2);
geo.bones = geo2.bones;
geo.animations = geo2.animations;
geoCache[json.name] = geo;
}
var tex = ddsLoader.load('http://www.titansoftime.com/utils.php?task=getTexture&id=16');
var mat = new THREE.MeshPhongMaterial({map:tex,skinning:true,side:THREE.DoubleSide});
mesh = new THREE.BlendCharacter();
mesh.load(geo,mat);
//mesh.scale.set(10,10,10);
//mesh.mixer = new THREE.AnimationMixer( mesh );
//parseAnimations();
scene.add(mesh);
play('Idle',true);
camera.lookAt(new THREE.Vector3(mesh.position.x,7,mesh.position.z));
}
function loadModel(){
$.ajax({
url: 'http://www.titansoftime.com/utils.php',
data: 'task=getModel&id=16',
crossDomain: true,
type: 'POST',
success: function(response){
createModel(JSON.parse(response));
}
});
}
function loadFloor(){
var geo = new THREE.PlaneBufferGeometry(50,50);
geo.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
var mat = new THREE.MeshBasicMaterial({color:0x0000ff});
var mesh = new THREE.Mesh(geo,mat);
scene.add(mesh);
}
function play(name,loop){
loop = loop || false;
var anim = mesh.animations[name];
anim.loop = loop;
if( mesh.currentAnimation ){
var cur = mesh.animations[mesh.currentAnimation];
var theTime = 0.175;
if( !cur.loop ){
var diff = cur.data.length - cur.currentTime;
theTime = Math.max(0,Math.min(theTime,diff));
}
console.log('blending: '+name);
mesh.crossfade(name,theTime,function(){
play('Idle',true)
});
}else{
console.log('playing: '+name);
mesh.play(name,loop);
}
}
function animate() {
requestAnimationFrame( animate );
var delta = clock.getDelta();
if( mesh ){
mesh.update( delta );
}
THREE.AnimationHandler.update(delta);
renderer.render( scene, camera );
}
This one (r78) works almost fine except for one animation (Magic Attack) has a small but noticeable delay before returning to the Idle animation. On other models it's the Melee animation, on some there is no problem at all. Super confused as they all work properly in 72.
http://jsfiddle.net/titansoftime/2sh95etj/
<script src="https://rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/master/examples/js/loaders/DDSLoader.js"></script>
var scene, camera, renderer, ambient, directional;
var mesh, geoCache={};
var clock, jsLoader, ddsLoader;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 20;
camera.position.y = 10;
ambient = new THREE.AmbientLight(0xffffff);
scene.add(ambient);
directional = new THREE.DirectionalLight(0xffffff,1);
directional.position.set(1,1,0);
scene.add(directional);
clock = new THREE.Clock();
jsLoader = new THREE.JSONLoader(true);
ddsLoader = new THREE.DDSLoader();
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff, 1 );
document.getElementById('idle').onclick = function(e){
play('Idle',true);
};
document.getElementById('run').onclick = function(e){
play('Run',true);
};
document.getElementById('melee').onclick = function(e){
play('MelleAttack');
};
document.getElementById('magic').onclick = function(e){
play('MagicAttack');
};
document.body.appendChild( renderer.domElement );
loadFloor();
loadModel();
}
function createModel(json){
var geo, geo2;
if( geoCache[json.name] ){
geo = geoCache[json.name];
}else{
geo2 = jsLoader.parse(json).geometry;
var m = new THREE.SkinnedMesh( geo2 );
m.normalizeSkinWeights();
geo2 = m.geometry;
geo = new THREE.BufferGeometry().fromGeometry(geo2);
geo.bones = geo2.bones;
geo.animations = geo2.animations;
geoCache[json.name] = geo;
}
var tex = ddsLoader.load('http://www.titansoftime.com/utils.php?task=getTexture&id=16');
var mat = new THREE.MeshPhongMaterial({map:tex,skinning:true,side:THREE.DoubleSide});
mesh = new THREE.SkinnedMesh(geo,mat);
//mesh.scale.set(10,10,10);
mesh.mixer = new THREE.AnimationMixer( mesh );
parseAnimations();
play('Idle',true);
scene.add(mesh);
camera.lookAt(new THREE.Vector3(mesh.position.x,7,mesh.position.z));
}
function loadModel(){
$.ajax({
url: 'http://www.titansoftime.com/utils.php',
data: 'task=getModel&id=16',
crossDomain: true,
type: 'POST',
success: function(response){
createModel(JSON.parse(response));
}
});
}
function loadFloor(){
var geo = new THREE.PlaneBufferGeometry(50,50);
geo.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
var mat = new THREE.MeshBasicMaterial({color:0x0000ff});
var mesh = new THREE.Mesh(geo,mat);
scene.add(mesh);
}
function play(name,loop){
var to = mesh.animations[ name ];
if( mesh.currentAnimation ){
var from = mesh.animations[ mesh.currentAnimation ];
to.reset();
if( loop ){
to.setLoop(THREE.LoopRepeat);
to.clampWhenFinished = false;
}else{
to.setLoop(THREE.LoopOnce, 0);
to.clampWhenFinished = true;
mesh.mixer.addEventListener('finished',function(e){
play('Idle',true);
});
}
from.play();
to.play();
from.enabled = true;
to.enabled = true;
from.crossFadeTo( to, 0.3 );
}else{
to.play();
}
mesh.currentAnimation = name;
}
function parseAnimations(){
var o, anim, anims = {};
console.log(mesh);
for( var i=0,len=mesh.geometry.animations.length;i<len;i++){
o = mesh.geometry.animations[i];
if( o ){
anim = mesh.mixer.clipAction(o,mesh);
anim.setEffectiveWeight(1);
anims[o.name] = anim;
}
}
mesh.animations = anims;
}
function animate() {
requestAnimationFrame( animate );
var delta = clock.getDelta();
if( mesh ){
if( mesh.mixer ){
mesh.mixer.update( delta );
}
}
renderer.render( scene, camera );
}
Why is this happening?
UPDATE: I noticed this is issue is not limited to blending between animations. One of my animations just looping now has a delay!
72: http://jsfiddle.net/titansoftime/8v0pasp5/
78: http://jsfiddle.net/titansoftime/n6apnj3z/
What is going on!? Was there some sort of auto correcting behavior or something along those lines in 72 that has been removed?

This is a bug in three.js.
https://github.com/mrdoob/three.js/issues/9056
Closing.

Related

How to add env map onto gltf object

Im having quite a bit of trouble adding an environment map to a loaded GLTF / GLB file, as of now I get some sort of reflection instead of a black dot with a light point on it,
I was reading a bit of the document for three js and think I can pull it off with the standardmeshmaterial and applying it somehow to the object(gltf) and adding the mesh into the scene. I tried a similar mockup but the item disappears. I dont know how to go about it, help guys.
This is the environment map im trying to apply to it, (or something similar)
https://hdrihaven.com/files/hdri_images/tonemapped/8192/venice_sunset.jpg
here is the codepen I am working on
https://codepen.io/8AD/pen/XWpxmpO
HTML
<script src="https://unpkg.com/three#0.87.1/build/three.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/d9f87fb1a2c5db1ea0e2feda9bd42b39b5bedc41/build/three.min.js"></script>
<!-- OrbitControls.js -->
<script src="https://rawcdn.githack.com/mrdoob/three.js/d9f87fb1a2c5db1ea0e2feda9bd42b39b5bedc41/examples/js/controls/OrbitControls.js"></script>
<!-- DRACOLoader.js -->
<script src="https://rawcdn.githack.com/mrdoob/three.js/d9f87fb1a2c5db1ea0e2feda9bd42b39b5bedc41/examples/js/loaders/DRACOLoader.js"></script>
<!-- GLTFLoader.js -->
<script src="https://rawcdn.githack.com/mrdoob/three.js/d9f87fb1a2c5db1ea0e2feda9bd42b39b5bedc41/examples/js/loaders/GLTFLoader.js"></script>
<div id="3dmain">
</div>
JS
var gltf = null;
var mixer = null;
var clock = new THREE.Clock();
var controls;
var camera;
init();
animate();
var renderCalls = [];
function render () {
requestAnimationFrame( render );
renderCalls.forEach((callback)=>{ callback(); });
}
render();
function init() {
width = window.innerWidth;
height = window.innerHeight;
scene = new THREE.Scene();
var light = new THREE.PointLight( 0xffffcc, 20, 200 );
light.position.set( 4, 30, 80 );
scene.add( light );
var light2 = new THREE.AmbientLight( 0x20202A, 20, 100 );
light2.position.set( 30, -10, 30 );
scene.add( light2 );
camera = new THREE.PerspectiveCamera( 60, width / height, 0.01, 10000 );
camera.position.set(0, 3, 10);
window.addEventListener( 'resize', function () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}, false );
var geometry = new THREE.BoxGeometry(100, 5, 100);
var material = new THREE.MeshLambertMaterial({
color: "#707070"
});
var manager = new THREE.LoadingManager();
manager.onProgress = function ( item, loaded, total ) {
console.log( item, loaded, total );
};
var loader = new THREE.GLTFLoader();
loader.setCrossOrigin( 'anonymous' );
var scale = 0.01;
var url = "https://8ad.studio/wp-content/uploads/3D%20Assets/blimp.glb";
loader.load(url, function (data) {
gltf = data;
var object = gltf.scene;
object.scale.set(scale, scale, scale);
//object.position.y = -5;
//object.position.x = 4;
object.castShadow = true;
object.receiveShadow = true;
var animations = gltf.animations;
if ( animations && animations.length ) {
mixer = new THREE.AnimationMixer( object );
for ( var i = 0; i < animations.length; i ++ ) {
var animation = animations[ i ];
mixer.clipAction( animation ).play();
}
}
scene.add(object);
});
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true } );
renderer.setClearColor( 0x000000, 0 );
renderer.shadowMap.enabled = true;
controls = new THREE.OrbitControls( camera,);
controls.rotateSpeed = 0.3;
controls.zoomSpeed = 0.9;
controls.minDistance = 14;
controls.maxDistance = 14;
controls.minPolarAngle = 0; // radians
controls.maxPolarAngle = Math.PI /2; // radians
controls.enableDamping = true;
controls.dampingFactor = 0.05;
var renderCalls = [];
renderCalls.push(function(){
controls.update()
});
renderer.setSize( width, height );
renderer.gammaOutput = true;
document.getElementById('3dmain').appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
if (mixer) mixer.update(clock.getDelta());
controls.update();
render();
}
function render() {
renderer.render( scene, camera );
}
You have to include RGBELoader into your app for importing HDR textures and make use of PMREMGenerator in order to pre-process the environment map for the usage with a PBR material.
var gltf = null;
var mixer = null;
var clock = new THREE.Clock();
var controls;
var camera;
var renderer;
init();
animate();
var renderCalls = [];
function render() {
requestAnimationFrame(render);
renderCalls.forEach((callback) => {
callback();
});
}
render();
function init() {
width = window.innerWidth;
height = window.innerHeight;
scene = new THREE.Scene();
var light = new THREE.PointLight(0xffffcc, 20, 200);
light.position.set(4, 30, 80);
scene.add(light);
var light2 = new THREE.AmbientLight(0x20202A, 20, 100);
light2.position.set(30, -10, 30);
scene.add(light2);
camera = new THREE.PerspectiveCamera(60, width / height, 0.01, 10000);
camera.position.set(0, 3, 10);
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1;
renderer.setClearColor(0x000000, 0);
renderer.shadowMap.enabled = true;
window.addEventListener('resize', function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}, false);
var geometry = new THREE.BoxGeometry(100, 5, 100);
var material = new THREE.MeshLambertMaterial({
color: "#707070"
});
var manager = new THREE.LoadingManager();
manager.onProgress = function(item, loaded, total) {
console.log(item, loaded, total);
};
var scale = 0.01;
var url = "https://8ad.studio/wp-content/uploads/3D%20Assets/blimp.glb";
var loader = new THREE.GLTFLoader();
loader.setCrossOrigin('anonymous');
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
const rgbeLoader = new THREE.RGBELoader();
rgbeLoader.load('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr', function(texture) {
const envMap = pmremGenerator.fromEquirectangular(texture).texture;
scene.background = envMap;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
loader.load(url, function(data) {
gltf = data;
var object = gltf.scene;
object.scale.set(scale, scale, scale);
//object.position.y = -5;
//object.position.x = 4;
object.castShadow = true;
object.receiveShadow = true;
var animations = gltf.animations;
if (animations && animations.length) {
mixer = new THREE.AnimationMixer(object);
for (var i = 0; i < animations.length; i++) {
var animation = animations[i];
mixer.clipAction(animation).play();
}
}
scene.add(object);
});
});
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.rotateSpeed = 0.3;
controls.zoomSpeed = 0.9;
controls.minDistance = 14;
controls.maxDistance = 14;
controls.minPolarAngle = 0; // radians
controls.maxPolarAngle = Math.PI / 2; // radians
controls.enableDamping = true;
controls.dampingFactor = 0.05;
var renderCalls = [];
renderCalls.push(function() {
controls.update()
});
renderer.setSize(width, height);
document.getElementById('3dmain').appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
if (mixer) mixer.update(clock.getDelta());
controls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.127/build/three.js"></script>
<!-- OrbitControls.js -->
<script src="https://cdn.jsdelivr.net/npm/three#0.127/examples/js/controls/OrbitControls.js"></script>
<!-- DRACOLoader.js -->
<script src="https://cdn.jsdelivr.net/npm/three#0.127/examples/js/loaders/DRACOLoader.js"></script>
<!-- GLTFLoader.js -->
<script src="https://cdn.jsdelivr.net/npm/three#0.127/examples/js/loaders/GLTFLoader.js"></script>
<!-- RGBELoader.js -->
<script src="https://cdn.jsdelivr.net/npm/three#0.127/examples/js/loaders/RGBELoader.js"></script>
<div id="3dmain">
</div>
The example applies the environment map to Scene.environment. However, you could also traverse through the glTF object and apply it to each material's envMap property.

Threejs How to set camera for large scale objects

I am rendering a cityscape using Three.js. When attempting to view the scene I can't seem to get the camera near/far settings correct to render the whole scene. When I increase the camera's far plane - I am able to see the model, but it appears blue (image below) until I zoom into it. Is there a way to see the entire model without having to zoom super close to the scene?
var scene = new THREE.Scene()
scene.background = new THREE.Color(33,33,33);
var ambient = new THREE.AmbientLight(0xe8ecff, 1.4)
ambient.name = 'ambientLight'
scene.add(ambient)
var directionalLight1 = new THREE.DirectionalLight(0xfff1f1, 0.7)
directionalLight1.name = 'directionalLight1'
directionalLight1.position.set(-1500, 900, 1500)
directionalLight1.castShadow = true
scene.add(directionalLight1)
directionalLight1.shadow.camera.right = 2500
directionalLight1.shadow.camera.left = -2500
directionalLight1.shadow.camera.top = 2500
directionalLight1.shadow.camera.bottom = -2500
directionalLight1.shadow.camera.near = 0
directionalLight1.shadow.camera.far = 5000
var shadowCameraHelper = new THREE.CameraHelper(directionalLight1.shadow.camera)
shadowCameraHelper.visible = false
shadowCameraHelper.name = 'directionalLight1Helper'
scene.add(shadowCameraHelper)
var directionalLight2 = new THREE.DirectionalLight(0x87c0ff, 0.2)
directionalLight2.name = 'directionalLight2'
directionalLight2.position.set(1, 1, -1)
scene.add(directionalLight2)
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 1, 10000);
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
var canvas = document.getElementById("canvas");
canvas.appendChild( renderer.domElement );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
camera.position.set(-400, 700, 500)
function animate (){
requestAnimationFrame( animate );
controls.update();
stats.update()
renderer.render( scene, camera );
}
animate();
var loader = new THREE.ObjectLoader
loader.load("example_mesh.json",
function(obj){
var bb = new THREE.Box3()
bb.expandByObject(obj)
var center = new THREE.Vector3()
bb.getCenter(center)
let modelSettings = { x: -center.x, y: center.y, z: -center.z }
let cameraRadius = this.boundingBox.geometry.boundingSphere.radius/2 * (1 + Math.sqrt(5))
obj.position.set(modelSettings.x, modelSettings.y, modelSettings.z)
camera.position.set(cameraRadius, cameraRadius, cameraRadius);
controls.target.set(0,modelSettings.y, 0)
controls.update()
scene.add(obj)
}, onProgress, onError)
When an object is being clipped out of the camera's focal length, you can use Object3D.scale. AFter adjusting this scaler value the entire building is visible in the camera on load and does not get clipped. You adjust the objects scale during the loading callback.
var scene = new THREE.Scene()
scene.background = new THREE.Color(33,33,33);
var ambient = new THREE.AmbientLight(0xe8ecff, 1.4)
ambient.name = 'ambientLight'
scene.add(ambient)
var directionalLight1 = new THREE.DirectionalLight(0xfff1f1, 0.7)
directionalLight1.name = 'directionalLight1'
directionalLight1.position.set(-1500, 900, 1500)
directionalLight1.castShadow = true
scene.add(directionalLight1)
directionalLight1.shadow.camera.right = 2500
directionalLight1.shadow.camera.left = -2500
directionalLight1.shadow.camera.top = 2500
directionalLight1.shadow.camera.bottom = -2500
directionalLight1.shadow.camera.near = 0
directionalLight1.shadow.camera.far = 5000
var shadowCameraHelper = new THREE.CameraHelper(directionalLight1.shadow.camera)
shadowCameraHelper.visible = false
shadowCameraHelper.name = 'directionalLight1Helper'
scene.add(shadowCameraHelper)
var directionalLight2 = new THREE.DirectionalLight(0x87c0ff, 0.2)
directionalLight2.name = 'directionalLight2'
directionalLight2.position.set(1, 1, -1)
scene.add(directionalLight2)
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 1, 10000);
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
var canvas = document.getElementById("canvas");
canvas.appendChild( renderer.domElement );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
camera.position.set(-400, 700, 500)
function animate (){
requestAnimationFrame( animate );
controls.update();
stats.update()
renderer.render( scene, camera );
}
animate();
var loader = new THREE.ObjectLoader
loader.load("example_mesh.json",
function(obj){
// adjust the scale of the object in the scene.
// default scale is (1,1,1)
obj.scale.set( .1, .1, .1 );
var bb = new THREE.Box3()
bb.expandByObject(obj)
var center = new THREE.Vector3()
bb.getCenter(center)
let modelSettings = { x: -center.x, y: center.y, z: -center.z }
let cameraRadius = this.boundingBox.geometry.boundingSphere.radius/2 * (1 + Math.sqrt(5))
obj.position.set(modelSettings.x, modelSettings.y, modelSettings.z)
camera.position.set(cameraRadius, cameraRadius, cameraRadius);
controls.target.set(0,modelSettings.y, 0)
controls.update()
scene.add(obj)
}, onProgress, onError)

Why is my PlaneGeometry not receiving a shadow?

I am using three.js to create a scene that has a model on it. I have a plane on which the model sits, and a spotlight shining on the model.
The model is made up of a number of different objects. All of the objects are set to receive and cast shadows. Shadows are being cast on the model itself from other areas of the model.
The plane, however, won't receive shadows. I'm unsure why.
I have adjusted the spotLight.shadowCameraNear and spotLight.shadowCameraFar properties to ensure both the model and plane are within the shadow area. Still nothing.
Below is a screenshot of the model with the spotlight visible.
I have the shadowmap enabled and set to the soft maps:
renderer.shadowMap.enabled = true; // Shadow map enabled
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
My code is as follows:
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats, controls;
var camera, scene, renderer, sceneAnimationClip ;
var clock = new THREE.Clock();
var mixers = [];
var globalObjects = [];
init();
function init() {
var loader = new THREE.TextureLoader();
container = document.createElement( 'div' );
document.body.appendChild( container );
// Scene
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xffffff, 50, 100 );
// Camera
camera = new THREE.PerspectiveCamera( 30, (window.innerWidth / window.innerHeight), 1, 10000 );
camera.position.x = 1000;
camera.position.y = 50;
camera.position.z = 1500;
scene.add( camera );
// LIGHTS
var spotLight = new THREE.SpotLight( 0xffffff,1 );
spotLight.position.set( 5, 5, 6 );
spotLight.castShadow = true;
spotLight.target.position.set(-1, 0, 2 );
spotLight.shadowDarkness = 0.5;
spotLight.shadowCameraNear = 4;
spotLight.shadowCameraFar = 25;
scene.add( spotLight );
// Camera helper for spotlight
var helper = new THREE.CameraHelper( spotLight.shadow.camera );
scene.add( helper );
// ground
var geometry = new THREE.PlaneGeometry( 30, 30 );
geometry.receiveShadow = true;
var material = new THREE.MeshBasicMaterial( {color: 0xcccccc, side: THREE.DoubleSide} );
material.receiveShadow = true;
var floor = new THREE.Mesh( geometry, material );
floor.receiveShadow = true;
floor.position.y = -1;
floor.rotation.x = Math.PI / 2;
scene.add( floor );
// stats
stats = new Stats();
container.appendChild( stats.dom );
// model
var manager = new THREE.LoadingManager();
manager.onProgress = function( item, loaded, total ) {
console.log( item, loaded, total );
};
// BEGIN Clara.io JSON loader code
var i = 0;
var objectLoader = new THREE.ObjectLoader();
objectLoader.load("final-master-20170426.json", function ( object ) {
var textureLoader = new THREE.TextureLoader();
object.traverse( function ( child )
{
if ( child instanceof THREE.Mesh ) {
var material = child.material.clone();
material.shininess = 0;
material.wireframe = false;
material.normalScale = new THREE.Vector2( 1, 1 );
/* Roof Glass */
if(child.name == 'Roof_Glass') {
material.shininess = 100;
material.alphaMap = grayscale;
material.transparent = true;
}
// Beading
if(child.name.endsWith('_Beading')) {
material.color.setHex( 0x1e1e1e );
material.shininess = 100;
}
/* Pillars */
if(
child.name.indexOf('Pillar') == 0 ||
child.name == 'Main_Frame' ||
child.name == 'Main_Cross_Supports' ||
child.name == 'roof_batons' ||
child.name == 'Roof_Flashings'
) {
material.color.setHex( 0x1e1e1e );
material.shininess = 100;
}
/* Lamps */
if(child.name.indexOf('Lamp') == 0) {
material.color.setHex( 0x1e1e1e );
material.shininess = 100;
}
// Set shadows for everything
material.castShadow = true;
material.receiveShadow = true;
child.material = material;
material = undefined;
globalObjects[child.name] = child;
console.log(child);
}
});
object.position.y = -1;
object.position.x = 0;
scene.add( object );
scene.fog = new THREE.Fog( 0xffffff, 50, 100 );
i++;
} );
// END Clara.io JSON loader code
renderer = new THREE.WebGLRenderer({
'antialias': true
});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( scene.fog.color );
container.appendChild( renderer.domElement );
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.shadowMap.enabled = true; // Shadow map enabled
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// controls, camera
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.target.set( 0, 0, 0 );
controls.maxPolarAngle = Math.PI * 0.5;
camera.position.set( 8, 3, 10 );
controls.update();
window.addEventListener( 'resize', onWindowResize, false );
animate();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
requestAnimationFrame( animate );
stats.update();
render();
}
function render() {
var delta = 0.75 * clock.getDelta();
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
This was fixed by using a THREE.MeshPhongMaterial instead of a THREE.MeshBasicMaterial.

Loading a JSON model in three.js

I have been trying to display a 3D json model using three.js. I am fairly new to three.js and have tried everything I can think of, but don't know anything else to try.
Currently when I try to load the model I get an error that says:
Uncaught TypeError: Cannot read property 'visible' of undefinedr # three.min.js:602r # three.min.js:602render # three.min.js:649render # test.html:106animate # test.html:100
I really am not sure where to go from here. Thanks for any help.
Here is my code:
<script type="text/javascript">
if (!Detector.webgl) Detector.addGetWebGLMessage();
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var FLOOR = 0;
var container;
var camera, scene;
var webglRenderer;
var zmesh, geometry;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
document.addEventListener(
'mousemove',
onDocumentMouseMove,
false
);
init();
animate();
// Renderer
webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
webglRenderer.domElement.style.position = 'relative';
container.appendChild(webglRenderer.domElement);
// Loader
var loader = new THREE.JSONLoader(),
callbackModel = function(geometry) {
createScene(geometry, 90, FLOOR, -50, 105)
};
loader.load('can.js', callbackModel);
function init() {
container = document.createElement('div');
document.body.appendChild(container);
// Camera
camera = new THREE.PerspectiveCamera(
75,
SCREEN_WIDTH / SCREEN_HEIGHT,
1,
100000
);
camera.position.z = 75;
// Scene
scene = new THREE.Scene();
// Lights
var ambient = new THREE.AmbientLight(0xffffff);
scene.add(ambient);
// More lights
var directionalLight = new THREE.DirectionalLight(0xffeedd);
directionalLight.position.set(0, -70, 100).normalize();
scene.add(directionalLight);
}
function createScene( geometry, x, y, z, b ) {
zmesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial() );
zmesh.position.set( 0, 16, 0 );
zmesh.scale.set( 1, 1, 1 );
scene.add( zmesh );
}
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX);
mouseY = (event.clientY - windowHalfY);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
if(webglRenderer != undefined && zmesh != undefined) {
zmesh.rotation.set(-mouseY/500 + 1, -mouseX/200, 0);
webglRenderer.render(scene, camera);
}
}
</script>
If your JSON file contains material information, then a materials array will be passed to your callback function, and you need to do this:
callbackModel = function( geometry, materials ) {
// your code
};
...
zmesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );
Otherwise, you need to define your own material. For example,
zmesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: 0xff000 } ) );
three.js r.77

imported json model not casting shadow

I have exported two models from Blender, each to a separate json file using the latest three.js exporter, then I tried to load it and add to my test app. I have set all the required parameters to enable the shadow casting, but still the shadows are not appearing at all.. Any ideas as to what may be wrong here?
var renderer, camera, scene, controls;
/////// JSON DATA ////
var static_objects = [
{
name:"ground",
pos:{
x:-45.0, y:-1, z:14.0
},
size:20,
model_url: "obj.moon_ground.json",
},
{
name:"cylinder",
pos:{
x:-20.0, y:5.0, z:0.0
},
size:10,
model_url:"obj.cylinder.json",
}
];
var ObjectsToLoad = static_objects.length || 0;
///////////////////////////
function initRenderer( width, height){
console.log(" - renderer");
if(Detector.webgl){
renderer = new THREE.WebGLRenderer({antialias:true});
}else{
renderer = THREE.CanvasRenderer();
}
//// container ////
container = document.createElement( 'div' );
document.body.appendChild( container );
/////////////////////
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( width, height );
renderer.shadowMap.enabled = true;
renderer.shadowMapSoft = true;
renderer.setClearColor( 0x142639, 1 );
///////////////////////
container.appendChild( renderer.domElement );
}
function initCamera(width, height){
console.log(" - camera");
camera = new THREE.PerspectiveCamera(55, width/height, 1, 100 );
camera.position.set(17.05217, 8.07079, 0.0);
camera.lookAt( static_objects[1].pos );
controls = new THREE.OrbitControls( camera );
}
function InitLights(){
console.log(" - lights");
var ambient_light = new THREE.AmbientLight( 0xD0D0D0, 0.25);
scene.add(ambient_light);
var spot_light = new THREE.SpotLight( 0xC1C1C1 );
spot_light.position.set( -1.8, 38, 2.5 );
spot_light.castShadow = true;
spot_light.shadowDarkness = 3.5;
spot_light.shadowCameraNear = 0.1;
spot_light.shadowCameraFar = 41;
spot_light.shadowCameraFov = 45;
spot_light.shadowMapWidth = 1024;
spot_light.shadowMapHeight = 1024;
spot_light.target.position.set( static_objects[1].pos.x, static_objects[1].pos.y, static_objects[1].pos.z );
scene.add(spot_light);
var c_helper = new THREE.CameraHelper( spot_light.shadow.camera );
scene.add( c_helper );
}
function initScene(){
console.log(" - scene");
scene = new THREE.Scene();
}
function loadObjects(){
console.log(" - StaticObjects");
var loader = new THREE.JSONLoader();
for(var o = 0; o < static_objects.length; o++ ){
var o_data = static_objects[o];
loader.load( o_data.model_url, initObject(o) );
}
}
function initObject(o_id){
console.log("loading object "+ o_id );
return function(geometry, materials) {
geometry.translate( 0.0, 0.0, -2.0 );
mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );
mesh.scale.set( static_objects[o_id].size, static_objects[o_id].size, static_objects[o_id].size ) ;
mesh.position.set( static_objects[o_id].pos.x, static_objects[o_id].pos.y, static_objects[o_id].pos.z );
mesh.traverse( function( node ) { if ( node instanceof THREE.Mesh ) { node.castShadow = true; node.receiveShadow = true; } } );
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.rotation.y = -Math.PI/2;
ObjectsToLoad--;
scene.add(mesh);
}
}
function initAll(){
console.log(" initializing:");
initRenderer(window.innerWidth / 2, window.innerHeight / 2);
initScene();
initCamera(window.innerWidth / 2, window.innerHeight / 2);
InitLights();
loadObjects();
animate();
}
function animate(){
window.requestAnimationFrame( animate );
if(ObjectsToLoad === 0){
render_all();
}
}
function render_all(){
//var timer = Date.now() * 0.001;
controls.update();
renderer.render(scene, camera);
}
initAll();
it appears that the spot_light had to be moved a little bit up along the Y axis. now it works perfectly.

Categories