How do I load collada object to three.js? - three.js

I'm new to three.js and am having trouble loading a collada object to it. I can't get home.dae to render in the browser.
I updated the code under SECOND UPDATE based on the answers.
// INITIAL
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);
var loader = new THREE.ColladaLoader();
loader.load('home.dae', function(collada){
scene.add(collada);
});
function render() {
renderer.render(scene, camera);
}
render();
// SECOND UPDATE
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.set(0,1,4);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var loader = new THREE.ColladaLoader();
loader.load('home.dae', function(collada){
scene.add(collada.scene);
});
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();

Your render function is called only once. Try with this -
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
Also check if you file path is valid.

Few things that come to mind:
as #Rasheduzzaman already noted, the render-function is called too early (when you call render(), the scene.add(collada); call can not have happened. Use his Answer instead.
the collada-loader works a bit differently: the documentation isn't clear about this, but the returned object is a collection of all the stuff that could've been in the collada-file, see here for a list: https://github.com/mrdoob/three.js/blob/dev/examples/js/loaders/ColladaLoader.js#L181-L204 (also: use the debugger from the browser-devtools to inspect the data you find there). You will probably want to do scene.add(collada.scene) or similar.
you are not setting a position for the camera, so it is located at (0,0,0), which might not be a great idea, try camera.position.set(0,1,4) or something like that.
you need to know what to expect: what is the size of the model you are loading? Where is it placed? Make sure to point your camera there (could use camera.lookAt(object.position)) and adjust nearPlane and farPlane accordingly.

Related

GLTF animation is not working in Three js

I'm struggling to get an animation to play together with my GLTF 3D model. Most similar issues that I've seen on Stack Overflow are relating to the mixer not being updated. Which is not the problem in my case.
This is my fiddle: https://jsfiddle.net/rixi/djqz1nb5/11/
import * as THREE from "https://threejsfundamentals.org/threejs/resources/threejs/r122/build/three.module.js";
import { GLTFLoader } from "https://threejsfundamentals.org/threejs/resources/threejs/r132/examples/jsm/loaders/GLTFLoader.js";
import { OrbitControls } from "https://threejsfundamentals.org/threejs/resources/threejs/r132/examples/jsm/controls/OrbitControls.js";
let clock, controls, scene, camera, renderer, mixer, container, model;
initScene();
animate();
function initScene() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
clock = new THREE.Clock();
renderer = new THREE.WebGLRenderer();
controls = new OrbitControls(camera, renderer.domElement);
controls.update();
container = document.getElementById("container");
container.appendChild(renderer.domElement);
renderer.setSize(window.innerWidth, window.innerHeight);
}
scene.background = new THREE.Color("#f8edeb");
// LIGHT
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(2, 2, 5);
//HELPERS
const axesHelper = new THREE.AxesHelper(5);
let gridHelper = new THREE.GridHelper(30, 30);
scene.add(light, axesHelper, gridHelper);
//GLTF START
const GLTFloader = new GLTFLoader();
GLTFloader.load("https://richardlundquist.github.io/library/alice_TEST2.glb", function (gltf) {
model = gltf;
mixer = new THREE.AnimationMixer(gltf.scene);
mixer.clipAction(gltf.animations[0]).play();
scene.add(model.scene);
});
camera.position.set(0, 20, 50);
function animate() {
requestAnimationFrame(animate);
let delta = clock.getDelta();
if (mixer) {
mixer.update(clock.getDelta());
}
renderer.render(scene, camera);
}
There is no error in the console. The animation is listed in the array and plays as it should in Don McCurdy's GLTF viewer (https://gltf-viewer.donmccurdy.com/)
But for some reason it will not play in my three js setup. Any clues? I would be extremely grateful for any help or hints on how to solve the issue.
I found two critical errors here.
At the top of your code, you pull in Three r122 with GLTFLoader r132. These need to be the same revision. Try setting them all to r132.
You call getDelta() twice here:
let delta = clock.getDelta();
if (mixer) {
mixer.update(clock.getDelta());
}
The second call to getDelta() comes immediately after the first, so always returns zero delta time. Thus, the animation never moves forward.

Manually specifying camera matrices in ThreeJS

I'm working on a project where I will draw 3D graphics on a video that is filmed with a real camera. I get provided a static projection and view matrix and my task is to draw the actual graphics on top. I've got it working in pure WebGL and know I'm trying to do it in ThreeJS. The problem is that I can't find a way to manually set the projection and view matrix for the camera in ThreeJS.
I've tried to set camera.matrixAutoUpdate = false and calling camera.projectionMatrix.set(matrix) and camera.matrixWorldInverse.set(matrix), but it doesn't seam to work. It is like the actual variable isn't passed to the shader.
Does anyone know how this can be done?
This is what I've got so far:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.matrixAutoUpdate = false;
camera.projectionMatrix.set(...)
camera.matrixWorldInverse.set(...)
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.BoxGeometry();
var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
var animate = function() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
animate();

Animations in Three.js with GLTF from Blender Exporter

I am experimenting with GLTF and Three.js, and I am having a devil of a time trying to get animations to work. My end goal is to be able to create keyframe animated meshes in Blender, export them to GLTF, and use them in Aframe-based WebVR scenes. At the moment, however, I'm just trying to get them to load and animate in a simple Three.js test harness page.
I'm trying to do a very basic test to get this working. I took Blender's default cube scene, removed the camera and the light, and created a keyframe animation to spin the cube 360 degrees around the Z axis. I then exported that cube to GLTF. First, I tried the GLTF export add on, and then I tried exporting it to Collada and using Cesium's tool to convert it to GLTF. Both versions of the GLTF file load and render the cube properly, but the cube does not animate.
I was able to use this same blend file and export to JSON using Three's own JSON export add on for Blender, and everything works fine there. So, I feel like I must be doing something stupid in my Javascript or there is something about GLTF I am missing.
Can anyone tell me what I'm doing wrong here? I'm getting to hair-yanking time here.
Here's the Javascript I'm trying to use for the GLTF version (specifically the binary version from Cesium's tool):
var scene = null;
var camera = null;
var renderer = null;
var mixer = null;
var clock = new THREE.Clock();
function init3D() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var ambientLight = new THREE.AmbientLight(0x080818);
scene.add(ambientLight);
var pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(-5, 1, 5);
scene.add(pointLight);
camera.position.z = 5;
camera.position.y = 1.5;
}
function loadScene() {
// Instantiate a loader
var loader = new THREE.GLTFLoader();
// Load a glTF resource
loader.load('gltf/SpinCube.glb',
function (gltf) {
var model = gltf.scene;
scene.add(model);
mixer = new THREE.AnimationMixer(model);
mixer.clipAction(gltf.animations[0]).play();
render();
});
}
function render() {
requestAnimationFrame(render);
var delta = clock.getDelta();
if (mixer != null) {
mixer.update(delta);
};
renderer.render(scene, camera);
}
init3D();
loadScene();
The problem appeared to have been a bug in the version of Three.js's GLTF2Loader that I was using at the time. I pulled a copy of Three.js from the dev branch, and my animations showed correctly.

Three.js Stereo Effect not lining up

I'm using Stero Effect in Three.js for a simple VR player, and the views don't line up - i.e. the right view is pointing a little more to the left than the left view and vice versa.
I've looked through all the examples and I'm not sure what I'm doing wrong. No one else seems to have this problem
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1024);
scene = new THREE.Scene();
target = new THREE.Vector3();
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
renderer.autoClear = false;
effect = new THREE.StereoEffect(renderer);
effect.setSize(window.innerWidth, window.innerHeight);
//in the renderer
if(vrMode)
effect.render(scene, camera);
else
renderer.render(scene, camera);
Has anyone seen this before or know what else might cause it?
I think it's due to the eye separation parameter. Try to set it to 0 it worked for me.
The parameter is on the StereoEffect.js file: this.separation

Three.js OBJLoader does not load obj file

I am trying to load a obj file using OBJloader.js
I am trying to load "plane.obj" file which exists inside the same folder where the html files exists and "OBJLoader.js" also exists in the same folder.
Page doesn't show up anything.
Here is the code :
var scene = new THREE.Scene();
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);
var geometry = new THREE.CubeGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material); scene.add(cube); camera.position.z = 5;
function render() {
requestAnimationFrame(render);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
var texture = THREE.ImageUtils.loadTexture( 'tex.jpg' );
var loader = new THREE.OBJLoader();
loader.load( 'plane.obj', function ( object ) {
scene.add( object );
} );
render();
This is likely caused by trying to load a resource from the file system. You're probably getting a same origin policy security violation and need to serve up your page and resources from the same protocol, domain and port. There are a few easy ways to do this - I use a simple http server app via Node JS. check out How to run things locally for more options.
Well, it turned out for me to be caused by the absence of light in the scene. Also, improper camera position may also lead to "invisible" OBJ models. Try adding the following lines:
var ambientLight = new THREE.AmbientLight(0xffffff);
scene.add(ambientLight);

Resources