Three.js Perspective Camera "undefined is not a function" - javascript

I have a program that used to work, but I am now getting the "undefined is not a function" error from within the three.js file. The error is pointing to line 10466 of the uncompressed library, and this line is within the declaration of THREE.PerspectiveCamera. Where is the problem? Thanks!
var assets = {};
var modelLoader = new THREE.JSONLoader(true);
modelLoader.load("assets/horse.js", onLoadedAssets);
var loading = setTimeout(function() {
console.log("loading...");
}, 1000);
var scene, camera, renderer, controls;
var horse, box;
function init() {
scene = new THREE.Scene();
var w = window.innerWidth,
h = window.innerHeight;
camera = THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.y = 0;
camera.target = new THREE.Vector3(0, 0, 0);
var light1 = new THREE.DirectionalLight(0xefefff, 2);
light1.position.set(1, 1, 1).normalize();
scene.add(light1);
var light2 = new THREE.DirectionalLight(0xffefef, 2);
light2.position.set(-1, -1, -1).normalize();
scene.add(light2);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize, false);
box = new Box(500, 500, 500);
horse = new Horse();
}
function animate() {
requestAnimationFrame(animate);
render();
}
var prevTime = Date.now();
function render() {
camera.position.x = 560 + Math.random() * 40;
camera.position.z = 560 + Math.random() * 40;
camera.lookAt(camera.target);
if (horse.animation) {
var time = Date.now();
horse.animation.update(time - prevTime);
prevTime = time;
}
renderer.render(scene, camera);
}
function onLoadedAssets(geometry) {
clearTimeout(loading);
console.log("loaded assets.")
geometry.computeFaceNormals();
geometry.computeVertexNormals();
var material = new THREE.MeshLambertMaterial({
color: 0x606060,
morphTargets: true
});
var mesh = new THREE.Mesh(geometry, material);
mesh.scale.set(1, 1, 1);
var animation = new THREE.MorphAnimation(mesh);
animation.play();
animation.isPlaying = false;
assets["horse"] = {
mesh: mesh,
animation: animation
};
init();
animate();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(w, h);
}
function Horse() {
var self;
self = assets["horse"];
scene.add(self.mesh);
self.startMoving = function() {
self.animation.isPlaying = true;
};
self.stopMoving = function() {
self.animation.isPlaying = false;
};
return self;
}
function Box(xidth, yidth, zidth) {
var self = this;
var geometry = new THREE.BoxGeometry(xidth, yidth, zidth);
var material = new THREE.MeshBasicMaterial({
color: 0x666666,
opacity: 0.4,
transparent: true
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
self.geometry = geometry;
self.cube = cube;
}

your error seems to be in this line
camera = THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);
Try putting a new before the THREE...
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);

Related

Three.js: How to change "diffuseMap" and "roughnessMap" to "cubeMap"?

This is the code I would like to work with:
var container;
var camera, scene, renderer;
let exrCubeRenderTarget, exrBackground;
let newEnvMap;
let torusMesh, planeMesh;
var mouseX = 0,
mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var object;
init();
animate();
function init() {
container = document.createElement("div");
container.className = "object";
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
2000
);
camera.position.z = 250;
// scene
scene = new THREE.Scene();
scene.add(camera);
// manager
function loadModel() {
THREE.DefaultLoadingManager.onLoad = function() {
pmremGenerator.dispose();
};
// -----------------
function loadObjectAndAndEnvMap() {
const textureLoader = new THREE.TextureLoader();
const diffuseMap = textureLoader.load('https://threejs.org/examples/textures/brick_diffuse.jpg');
const roughnessMap = textureLoader.load('https://threejs.org/examples/textures/brick_roughness.jpg');
object.traverse(function(child) {
//This allow us to check if the children is an instance of the Mesh constructor
if (child instanceof THREE.Mesh) {
child.material = new THREE.MeshStandardMaterial({
color: "#555",
roughness: 1.0,
metalness: 0.5,
envMapIntensity: 5.0
});
child.material.envMap = newEnvMap;
child.material.map = diffuseMap;
child.material.roughnessMap = roughnessMap;
child.material.needsUpdate = true;
//Sometimes there are some vertex normals missing in the .obj files, ThreeJs will compute them
}
});
object.position.y = -90;
scene.add(object);
}
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
new THREE.EXRLoader()
.setDataType(THREE.UnsignedByteType)
.load(
"https://threejs.org/examples/textures/piz_compressed.exr",
function(texture) {
exrCubeRenderTarget = pmremGenerator.fromEquirectangular(texture);
exrBackground = exrCubeRenderTarget.texture;
newEnvMap = exrCubeRenderTarget ? exrCubeRenderTarget.texture : null;
loadObjectAndAndEnvMap(); // Add envmap once the texture has been loaded
texture.dispose();
}
);
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.outputEncoding = THREE.sRGBEncoding;
}
var manager = new THREE.LoadingManager(loadModel);
manager.onProgress = function(item, loaded, total) {
console.log(item, loaded, total);
};
var loader = new THREE.OBJLoader(manager);
loader.load(
"https://threejs.org/examples/models/obj/female02/female02.obj",
function(obj) {
object = obj;
}
);
//
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
document.addEventListener("mousemove", onDocumentMouseMove, false);
//
window.addEventListener("resize", onWindowResize, false);
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 2;
mouseY = (event.clientY - windowHalfY) / 2;
}
//
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (-mouseY - camera.position.y) * 0.05;
camera.lookAt(scene.position);
scene.background = exrBackground;
renderer.toneMappingExposure = 1.0;
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.125.2/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.125.2/examples/js/loaders/OBJLoader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.125.2/examples/js/loaders/EXRLoader.js"></script>
Instead of the existing material, I would like to have a metallic material like here.
For this, I have tried to delete diffuseMap and roughnessMap, and add cubeMap.
That's my not working result:
var container;
var camera, scene, renderer;
let newEnvMap;
let torusMesh, planeMesh;
var mouseX = 0,
mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var object;
init();
animate();
function init() {
container = document.createElement("div");
container.className = "object";
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
2000
);
camera.position.z = 250;
// scene
scene = new THREE.Scene();
scene.add(camera);
// manager
function loadModel() {
THREE.DefaultLoadingManager.onLoad = function() {
pmremGenerator.dispose();
};
// -----------------
function loadObjectAndAndEnvMap() {
const textureLoader = new THREE.TextureLoader();
textureLoader.load('https://threejs.org/examples/textures/2294472375_24a3b8ef46_o.jpg', function(texture) {
texture.encoding = THREE.sRGBEncoding;
texture.mapping = THREE.EquirectangularReflectionMapping;
init(texture);
animate();
});
object.traverse(function(child) {
//This allow us to check if the children is an instance of the Mesh constructor
if (child instanceof THREE.Mesh) {
child.material = new THREE.MeshStandardMaterial({
color: "#555",
roughness: 1.0,
metalness: 0.5,
envMapIntensity: 5.0
});
child.material.envMap = newEnvMap;
child.material.needsUpdate = true;
//Sometimes there are some vertex normals missing in the .obj files, ThreeJs will compute them
}
});
object.position.y = -90;
scene.add(object);
}
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.outputEncoding = THREE.sRGBEncoding;
}
var manager = new THREE.LoadingManager(loadModel);
manager.onProgress = function(item, loaded, total) {
console.log(item, loaded, total);
};
var loader = new THREE.OBJLoader(manager);
loader.load(
"https://threejs.org/examples/models/obj/female02/female02.obj",
function(obj) {
object = obj;
}
);
//
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
document.addEventListener("mousemove", onDocumentMouseMove, false);
//
window.addEventListener("resize", onWindowResize, false);
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 2;
mouseY = (event.clientY - windowHalfY) / 2;
}
//
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (-mouseY - camera.position.y) * 0.05;
camera.lookAt(scene.position);
renderer.toneMappingExposure = 1.0;
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.125.2/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.125.2/examples/js/loaders/OBJLoader.js"></script>
The background should be transparent in the end, only the OBJ object should be visible.
Could somebody help me please? Would be soooo happy about it!
There's not much you need to change to make it metallic:
child.material = new THREE.MeshStandardMaterial({
color: "#555",
roughness: 0.0, // <- roughness 0
metalness: 1.0, // <- metalness 1
envMapIntensity: 1.0
});
child.material.envMap = newEnvMap;
// Then you only need the envMap, remove the other stuff
//child.material.map = diffuseMap;
//child.material.roughnessMap = roughnessMap;
//child.material.needsUpdate = true;
And finally, if you don't want the background, remove it from the Render loop:
//scene.background = exrBackground;
Live demo:
var container;
var camera, scene, renderer;
let exrCubeRenderTarget, exrBackground;
let newEnvMap;
let torusMesh, planeMesh;
var mouseX = 0,
mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var object;
init();
animate();
function init() {
container = document.createElement("div");
container.className = "object";
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
2000
);
camera.position.z = 250;
// scene
scene = new THREE.Scene();
scene.add(camera);
// manager
function loadModel() {
THREE.DefaultLoadingManager.onLoad = function() {
pmremGenerator.dispose();
};
// -----------------
function loadObjectAndAndEnvMap() {
const textureLoader = new THREE.TextureLoader();
const diffuseMap = textureLoader.load('https://threejs.org/examples/textures/brick_diffuse.jpg');
const roughnessMap = textureLoader.load('https://threejs.org/examples/textures/brick_roughness.jpg');
object.traverse(function(child) {
//This allow us to check if the children is an instance of the Mesh constructor
if (child instanceof THREE.Mesh) {
child.material = new THREE.MeshStandardMaterial({
color: "#555",
roughness: 0.0,
metalness: 1.0,
envMapIntensity: 5.0
});
child.material.envMap = newEnvMap;
//child.material.map = diffuseMap;
//child.material.roughnessMap = roughnessMap;
//child.material.needsUpdate = true;
//Sometimes there are some vertex normals missing in the .obj files, ThreeJs will compute them
}
});
object.position.y = -90;
scene.add(object);
}
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
new THREE.EXRLoader()
.setDataType(THREE.UnsignedByteType)
.load(
"https://threejs.org/examples/textures/piz_compressed.exr",
function(texture) {
exrCubeRenderTarget = pmremGenerator.fromEquirectangular(texture);
exrBackground = exrCubeRenderTarget.texture;
newEnvMap = exrCubeRenderTarget ? exrCubeRenderTarget.texture : null;
loadObjectAndAndEnvMap(); // Add envmap once the texture has been loaded
texture.dispose();
}
);
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.outputEncoding = THREE.sRGBEncoding;
}
var manager = new THREE.LoadingManager(loadModel);
manager.onProgress = function(item, loaded, total) {
console.log(item, loaded, total);
};
var loader = new THREE.OBJLoader(manager);
loader.load(
"https://threejs.org/examples/models/obj/female02/female02.obj",
function(obj) {
object = obj;
}
);
//
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
document.addEventListener("mousemove", onDocumentMouseMove, false);
//
window.addEventListener("resize", onWindowResize, false);
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 2;
mouseY = (event.clientY - windowHalfY) / 2;
}
//
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (-mouseY - camera.position.y) * 0.05;
camera.lookAt(scene.position);
//scene.background = exrBackground;
renderer.toneMappingExposure = 1.0;
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.125.2/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.125.2/examples/js/loaders/OBJLoader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.125.2/examples/js/loaders/EXRLoader.js"></script>

threejs: Move camera to position inside another object

I'm trying to move the camera controlled by trackballControl into the position of an object.
Right now it's working but as you can see in my fiddle, each time the camera changes position it also changes the z which isn't what I want.
I'm trying to keep the same position but only rotate the globe into the position of the cube.
Here is my code so far
var camera, scene, renderer, controls, cubeMesh;
document.querySelector('button').onclick = function () {
camera.position.copy(cubeMesh.position);
camera.lookAt(controls.target);
};
var initLights = function () {
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(1, 1, 1);
scene.add(light);
var light = new THREE.DirectionalLight(0x002288);
light.position.set(-1, -1, -1);
scene.add(light);
var light = new THREE.AmbientLight(0x222222);
scene.add(light);
};
var init = function () {
renderer = new THREE.WebGLRenderer({antialias: false});
renderer.setSize(window.innerWidth, window.innerHeight);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 300;
scene = new THREE.Scene();
controls = new THREE.TrackballControls(camera);
controls.target.set(0, 0, 0);
controls.rotateSpeed = 2;
document.body.appendChild(renderer.domElement);
var sphereGeom = new THREE.SphereGeometry(100, 32, 32);
var sphereMat = new THREE.MeshPhongMaterial({
color: 0xfb3550,
flatShading: true
});
var sphereMesh = new THREE.Mesh(sphereGeom, sphereMat);
//cube
var cubeDim = 20;
var cubeGeom = new THREE.BoxGeometry(cubeDim, cubeDim, cubeDim);
var cubeMat = new THREE.MeshPhongMaterial({
color: 0x7cf93e,
flatShading: true
});
cubeMesh = new THREE.Mesh(cubeGeom, cubeMat);
var spherical = new THREE.Spherical();
spherical.set(100 + cubeDim / 2, 0.4, 0);
cubeMesh.position.setFromSpherical(spherical);
var zero = new THREE.Vector3(0, 0, 0);
cubeMesh.lookAt(zero);
scene.add(sphereMesh);
sphereMesh.add(cubeMesh);
initLights();
};
var render = function () {
renderer.render(scene, camera);
};
var animate = function () {
requestAnimationFrame(animate);
controls.update();
render();
};
init();
animate()
You can test it in my fiddle here
Here is a fiddle where the camera is zoomed a little bit out by clicking the button.
JS Fiddle
var camera, scene, renderer, controls, cubeMesh;
document.querySelector('button').onclick = function () {
let x = cubeMesh.position.x
let y = cubeMesh.position.y
let z = cubeMesh.position.z
camera.position.x = 0
camera.position.y = y + 200
camera.position.z = z + 100
camera.lookAt(controls.target);
};
var initLights = function () {
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(1, 1, 1);
scene.add(light);
var light = new THREE.DirectionalLight(0x002288);
light.position.set(-1, -1, -1);
scene.add(light);
var light = new THREE.AmbientLight(0x222222);
scene.add(light);
};
var init = function () {
renderer = new THREE.WebGLRenderer({antialias: false});
renderer.setSize(window.innerWidth, window.innerHeight);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 300;
scene = new THREE.Scene();
controls = new THREE.TrackballControls(camera);
controls.target.set(0, 0, 0);
controls.rotateSpeed = 2;
document.body.appendChild(renderer.domElement);
var sphereGeom = new THREE.SphereGeometry(100, 32, 32);
var sphereMat = new THREE.MeshPhongMaterial({
color: 0xfb3550,
flatShading: true
});
var sphereMesh = new THREE.Mesh(sphereGeom, sphereMat);
//cube
var cubeDim = 20;
var cubeGeom = new THREE.BoxGeometry(cubeDim, cubeDim, cubeDim);
var cubeMat = new THREE.MeshPhongMaterial({
color: 0x7cf93e,
flatShading: true
});
cubeMesh = new THREE.Mesh(cubeGeom, cubeMat);
var spherical = new THREE.Spherical();
spherical.set(100 + cubeDim / 2, 0.4, 0);
cubeMesh.position.setFromSpherical(spherical);
var zero = new THREE.Vector3(0, 0, 0);
cubeMesh.lookAt(zero);
scene.add(sphereMesh);
sphereMesh.add(cubeMesh);
initLights();
};
var render = function () {
console.log(camera.position)
renderer.render(scene, camera);
};
var animate = function () {
requestAnimationFrame(animate);
controls.update();
render();
};
init();
animate()
You have to set the camera target to the position where you want to look at.
var newTarget = new THREE.Vector3(0, 0, 0);
newTarget.copy(cubeMesh.position);
camera.lookAt(newTarget);
and the THREE.TrackballControls has to be notified to update from the camera THREE.TrackballControls.update:
document.querySelector('button').onclick = function () {
var newTarget = new THREE.Vector3(0, 0, 0);
newTarget.copy(cubeMesh.position);
controls.reset();
camera.lookAt(newTarget)
camera.updateProjectionMatrix();
controls.update();
};
If the current camera position should be kept and not be reseted, then the position has to be read form the world matrix of the camera and the initial position of the camera has to be set to its current position:
document.querySelector('button').onclick = function ()
var newPosition = new THREE.Vector3(0, 0, 0);
newPosition.applyMatrix4( camera.matrixWorld );
var newTarget = new THREE.Vector3(0, 0, 0);
newTarget.copy(cubeMesh.position);
controls.reset();
camera.position.copy(newPosition);
camera.lookAt(newTarget)
camera.updateProjectionMatrix();
controls.update();
};
See the example:
var camera, scene, renderer, controls, cubeMesh;
document.getElementById('reset').onclick = function () {
var newTarget = new THREE.Vector3(0, 0, 0);
newTarget.copy(cubeMesh.position);
controls.reset();
camera.lookAt(newTarget)
camera.updateProjectionMatrix();
controls.update();
};
document.getElementById('target').onclick = function () {
var newPosition = new THREE.Vector3(0, 0, 0);
newPosition.applyMatrix4( camera.matrixWorld );
var newTarget = new THREE.Vector3(0, 0, 0);
newTarget.copy(cubeMesh.position);
controls.reset();
camera.position.copy(newPosition);
camera.lookAt(newTarget)
camera.updateProjectionMatrix();
controls.update();
};
var initLights = function () {
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(1, 1, 1);
scene.add(light);
var light = new THREE.DirectionalLight(0x002288);
light.position.set(-1, -1, -1);
scene.add(light);
var light = new THREE.AmbientLight(0x222222);
scene.add(light);
};
var init = function () {
renderer = new THREE.WebGLRenderer({antialias: false});
renderer.setSize(window.innerWidth, window.innerHeight);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 300;
scene = new THREE.Scene();
controls = new THREE.TrackballControls(camera);
controls.target.set(0, 0, 0);
controls.rotateSpeed = 2;
document.body.appendChild(renderer.domElement);
var sphereGeom = new THREE.SphereGeometry(100, 32, 32);
var sphereMat = new THREE.MeshPhongMaterial({
color: 0xfb3550,
flatShading: true
});
var sphereMesh = new THREE.Mesh(sphereGeom, sphereMat);
//cube
var cubeDim = 20;
var cubeGeom = new THREE.BoxGeometry(cubeDim, cubeDim, cubeDim);
var cubeMat = new THREE.MeshPhongMaterial({
color: 0x7cf93e,
flatShading: true
});
cubeMesh = new THREE.Mesh(cubeGeom, cubeMat);
var spherical = new THREE.Spherical();
spherical.set(100 + cubeDim / 2, 0.4, 0);
cubeMesh.position.setFromSpherical(spherical);
var zero = new THREE.Vector3(0, 0, 0);
cubeMesh.lookAt(zero);
scene.add(sphereMesh);
sphereMesh.add(cubeMesh);
initLights();
};
var render = function () {
renderer.render(scene, camera);
};
var animate = function () {
requestAnimationFrame(animate);
controls.update();
render();
};
init();
animate();
button {
position : absolute;
top : 0;
right : 0;
}
.button2 {
position : absolute;
top : 0;
left : 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>
<button id="reset" class="button2">
reset camera
</button>
<button id="target">
look at target
</button>

Three.js - Animation is not playing

I have problem with animating object exported via blender plugin from blender to THREE.js. Animation did not start running...
Of course, I tried many combinations of settings when exporting from blender and importing to THREE.js library, but without success.
Here is code, what I think should work. Comment Critical section annotate where is probably some mistake. Link to source JSON is in the example too. Of course, I can provide source *.blend file, if needed...
var tgaLoader = new THREE.TGALoader();
var objectLoader = new THREE.ObjectLoader();
var clock = new THREE.Clock();
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
document.getElementById('container').appendChild(renderer.domElement);
objectLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/scavenger.json', function (loadedScene) {
scene = loadedScene;
mesh = scene.children[0];
scene.background = new THREE.Color('white');
mesh.material = new THREE.MeshPhongMaterial({ map: tgaLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/SCA_BODY_V0.TGA') });
hemiLight = new THREE.HemisphereLight('white', 'white', 0.6);
scene.add(hemiLight);
camera = new THREE.PerspectiveCamera(30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000);
camera.position.set(500, 200, -100);
controls = new THREE.OrbitControls(camera);
controls.target.set(0, 50, 0);
controls.update();
var geometry = new THREE.PlaneBufferGeometry(200, 200);
var material = new THREE.MeshPhongMaterial({ shininess: 0.1 });
var ground = new THREE.Mesh(geometry, material);
ground.rotation.x = - Math.PI / 2;
scene.add(ground);
mesh.scale.set(-1, -1, 1);
// Critical section...
mixer = new THREE.AnimationMixer(mesh);
var sequence = THREE.AnimationClip.CreateFromMorphTargetSequence('animation', mesh.geometry.morphTargets, 25, true);
var animation = mixer.clipAction(sequence);
animation.play();
// End of critital section
animate();
});
window.onresize = function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
};
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
var delta = 0.75 * clock.getDelta();
mixer.update(delta);
renderer.render(scene, camera);
}
body {
margin: 0px;
overflow: hidden;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
<script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/TGALoader.js" type="application/javascript"></script>
<script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>
Thanks for any suggestion.
I dug in into animation and noticed that it uses morphTargets. And then I remembered about this example. So, the key moment is to set .morphTarget parameter of a material to true, so, I've applied it to the material in your code snippet and it started to work:
mesh.material = new THREE.MeshPhongMaterial({
map: tgaLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/SCA_BODY_V0.TGA'),
morphTargets: true
});
Though, I'm not sure, if such an approach is correct, but, at least, it's working )
var tgaLoader = new THREE.TGALoader();
var objectLoader = new THREE.ObjectLoader();
var clock = new THREE.Clock();
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
document.getElementById('container').appendChild(renderer.domElement);
objectLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/scavenger.json', function (loadedScene) {
scene = loadedScene;
mesh = scene.children[0];
scene.background = new THREE.Color('white');
mesh.material = new THREE.MeshPhongMaterial({ map: tgaLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/SCA_BODY_V0.TGA'), morphTargets: true });
hemiLight = new THREE.HemisphereLight('white', 'white', 0.6);
scene.add(hemiLight);
camera = new THREE.PerspectiveCamera(30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000);
camera.position.set(500, 200, -100);
controls = new THREE.OrbitControls(camera);
controls.target.set(0, 50, 0);
controls.update();
var geometry = new THREE.PlaneBufferGeometry(200, 200);
var material = new THREE.MeshPhongMaterial({ shininess: 0.1 });
var ground = new THREE.Mesh(geometry, material);
ground.rotation.x = - Math.PI / 2;
scene.add(ground);
mesh.scale.set(-1, -1, 1);
// Critical section...
mixer = new THREE.AnimationMixer(mesh);
var sequence = THREE.AnimationClip.CreateFromMorphTargetSequence('animation', mesh.geometry.morphTargets, 25, true);
var animation = mixer.clipAction(sequence);
animation.play();
// End of critital section
animate();
});
window.onresize = function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
};
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
var delta = 0.75 * clock.getDelta();
mixer.update(delta);
renderer.render(scene, camera);
}
body {
margin: 0px;
overflow: hidden;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
<script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/TGALoader.js" type="application/javascript"></script>
<script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>

How to control fps with requestAnimationFrame?

I have used FBX format with three js. It seems like requestAnimationFrame is the de facto way to animate things now. The animation was working very speed, Like lightening. Can't find any solutions to control the fps.
See the below image.
Source code:
if (!Detector.webgl)
Detector.addGetWebGLMessage();
var container, stats, controls;
var camera, scene, renderer, light, mesh;
var clock = new THREE.Clock();
var mixers = [];
var mouseX = 0, mouseY = 0;
var spdx = 0, spdy = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000);
scene = new THREE.Scene();
// grid
var gridHelper = new THREE.GridHelper(28, 28, 0x303030, 0x303030);
gridHelper.position.set(0, -0.04, 0);
scene.add(gridHelper);
// 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);
};
var onProgress = function (xhr) {
if (xhr.lengthComputable) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log(Math.round(percentComplete, 2) + '% downloaded');
}
};
var onError = function (xhr) {
console.error(xhr);
};
var loader = new THREE.FBXLoader(manager);
loader.load('assests/JetEngine_Ani.fbx', function (object) {
object.mixer = new THREE.AnimationMixer(object);
mixers.push(object.mixer);
var action = object.mixer.clipAction(object.animations[ 0 ]);
action.play();
scene.add(object);
}, onProgress, onError);
renderer = new THREE.WebGLRenderer({alpha: true});
renderer.setClearColor(0xdddddd, 1);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target.set(0, 12, 0);
camera.position.z = 850;
controls.update();
window.addEventListener('resize', onWindowResize, false);
light = new THREE.HemisphereLight(0xffffff, 0x444444, 1.0);
light.position.set(0, 1, 0);
scene.add(light);
light = new THREE.DirectionalLight(0xffffff, 1.0);
light.position.set(0, 1, 0);
scene.add(light); }
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight); }
function onDocumentMouseMove(event) {
mouseX = event.clientX;
mouseY = event.clientY;
}
function animate() {
requestAnimationFrame(animate);
if (mixers.length > 0) {
for (var i = 0; i < mixers.length; i++) {
mixers[ i ].update(clock.getDelta());
}
}
stats.update();
render();
}
function render() {
renderer.render(scene, camera);
}
How to control the animation speed. Is there have other ways or only through fps(frames per second).
How can I reduce the animation speed??..
You want to control the duration of your AnimationAction loop. To do so, you can use this pattern:
action.setDuration( 10 ).play();
three.js r.87

Why raycaster.intersectObjects work fine with Geometry built in scene but work bad with model loaded form exterior?

I wanna make a measure tool in three.js,and I use reycaster function to do it.
When I use it with Geometry built in scene,it was fine.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ytest</title>
<script src="JSandCSS/three.js"></script>
<script src="JSandCSS/OrbitControls.js"></script>
<script src="JSandCSS/OBJLoader.js"></script>
<script src="JSandCSS/Raycaster.js"></script>
</head>
<body>
<script>
var scene = new THREE.Scene();
var group = new THREE.Group;
var mouse = new THREE.Vector2();
var raycaster = new THREE.Raycaster();
var objects = [];
var particleMaterial;
particlecount = 0;
var container, stats, titleinfo;
scene.add(group);
var geometry = new THREE.SphereGeometry(5, 32, 32);
geometry.scale(10, 10, 10);
var material = new THREE.MeshBasicMaterial({
color: 0xffff00
});
var sphere = new THREE.Mesh(geometry, material);
group.add(sphere);
objects.push(sphere);
var light = new THREE.PointLight(0xffffff);
light.position.set(300, 400, 200);
light.intensity.set = 0.1;
scene.add(light);
scene.add(new THREE.AmbientLight(0x333333));
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(200, 200, 200);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.render(scene, camera);
renderer.setClearColor(0x808080, 0.5);
render();
var controls = new THREE.OrbitControls(camera);
controls.addEventListener('change', render);
animate();
window.addEventListener('resize', handleWindowResize, false);
window.addEventListener('mousedown', onDocumentMouseDown, false);
function onDocumentMouseDown(event) {
event.preventDefault();
mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse.y = -(event.clientY / renderer.domElement.clientHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(objects);
var PI2 = Math.PI * 2;
var pointLoader = new THREE.TextureLoader();
particleMaterial = new THREE.SpriteMaterial({
map: pointLoader.load("pic/measurepoint.png"),
});
if(intersects.length > 0) {
if(particlecount == 0) {
var particle1 = new THREE.Sprite(particleMaterial);
particle1.name = 'particle1';
particle1.position.copy(intersects[0].point);
particle1.scale.x = particle1.scale.y = 5;
scene.add(particle1);
particlecount = 1;
} else {
if(particlecount !== 2) {
var particle2 = new THREE.Sprite(particleMaterial);
particle2.name = 'particle2';
particle2.position.copy(intersects[0].point);
particle2.scale.x = particle2.scale.y = 5;
scene.add(particle2);
particlecount = 2;
a = scene.getObjectByName('particle1');
b = scene.getObjectByName('particle2');
var dis = a.position.distanceTo(b.position);
alert('distance between two point is' + dis);
scene.remove(a);
scene.remove(b);
particlecount = 0;
}
}
}
}
function render() {
renderer.render(scene, camera);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function handleWindowResize() {
HEIGHT = window.innerHeight;
WIDTH = window.innerWidth;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
}
</script>
</body>
</html>
enter image description here
But When I loaded a model,it doesn't work.As you see result of "alert(intersects.length)" is 0.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ytest</title>
<script src="JSandCSS/three.js"></script>
<script src="JSandCSS/OrbitControls.js"></script>
<script src="JSandCSS/OBJLoader.js"></script>
<script src="JSandCSS/Raycaster.js"></script>
</head>
<body>
<script>
var scene = new THREE.Scene();
var group = new THREE.Group;
var mouse = new THREE.Vector2();
var raycaster = new THREE.Raycaster();
var objects = [];
var particleMaterial;
particlecount = 0;
var container, stats, titleinfo;
scene.add(group);
var textureLoader = new THREE.TextureLoader();
var mat = new THREE.MeshLambertMaterial({
map: textureLoader.load("model/earth/texture.jpg"),
specularMap: textureLoader.load("model/earth/specular.jpg"),
lightMap: textureLoader.load("model/earth/light.jpg")
});
var loader = new THREE.OBJLoader();
loader.load('model/earth/earth.obj',
function chuanzhi(obj) {
obj.traverse(function(child) {
if(child instanceof THREE.Mesh) {
child.material = mat;
}
});
Mesh = obj;
obj.scale.set(2, 2, 2);
group.add(obj);
objects.push(Mesh);
});
var light = new THREE.PointLight(0xffffff);
light.position.set(300, 400, 200);
light.intensity.set = 0.1;
scene.add(light);
scene.add(new THREE.AmbientLight(0x333333));
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(200, 200, 200);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.render(scene, camera);
renderer.setClearColor(0x808080, 0.5);
render();
var controls = new THREE.OrbitControls(camera);
controls.addEventListener('change', render);
animate();
window.addEventListener('resize', handleWindowResize, false);
window.addEventListener('mousedown', onDocumentMouseDown, false);
function onDocumentMouseDown(event) {
event.preventDefault();
mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse.y = -(event.clientY / renderer.domElement.clientHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(objects);
var PI2 = Math.PI * 2;
var pointLoader = new THREE.TextureLoader();
particleMaterial = new THREE.SpriteMaterial({
map: pointLoader.load("pic/measurepoint.png"),
});
alert(intersects.length);
if(intersects.length > 0) {
if(particlecount == 0) {
var particle1 = new THREE.Sprite(particleMaterial);
particle1.name = 'particle1';
particle1.position.copy(intersects[0].point);
particle1.scale.x = particle1.scale.y = 5;
scene.add(particle1);
particlecount = 1;
} else {
if(particlecount !== 2) {
var particle2 = new THREE.Sprite(particleMaterial);
particle2.name = 'particle2';
particle2.position.copy(intersects[0].point);
particle2.scale.x = particle2.scale.y = 5;
scene.add(particle2);
particlecount = 2;
a = scene.getObjectByName('particle1');
b = scene.getObjectByName('particle2');
var dis = a.position.distanceTo(b.position);
alert('distance between two point is' + dis);
scene.remove(a);
scene.remove(b);
particlecount = 0;
}
}
}
}
function render() {
renderer.render(scene, camera);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function handleWindowResize() {
HEIGHT = window.innerHeight;
WIDTH = window.innerWidth;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
}
</script>
</body>
</html>
I wanna know why it happened,and how I can use it correctly.Could you help me ?

Categories

Resources