three.js mousepick(raycaster) not working on loaded models - three.js

I have a problem with mousepick, when mouse is over a mesh, it shows picked, but it does not pick it when mouse is over a loaded model (3ds).
My code:
// raycasting
export function cameraPick() {
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( scene.children );
for ( var i = 0; i < intersects.length; i++ ) {
var intersection = intersects[ i ];
var obj = intersection.object;
return obj;
}
return null;
}
// rendering
main loop
var animate = function() {
requestAnimationFrame(animate);
media.renderer.render(scene, camera);
var v = media.cameraPick();
if (v) {
v.position.x+=.1;
}
};

Try to use camera.updateProjectionMatrix() after you changed states of the scene (like animation, new model in scene or whatever new in the scene...).
More: https://threejs.org/docs/#api/en/cameras/PerspectiveCamera.updateProjectionMatrix

solution from prisoner849
var intersects = raycaster.intersectObjects( scene.children, true );

Related

Assigning PointsMaterial to loaded (animated) FBX

Using this answer I've been able to assign a points material to a loaded GLTF model.
If I apply the same technique to an animated FBX model, the model loads and points material is assigned but the animation no longer works. Presumably because the technique works by duplicating the mesh.
How can I adapt this technique to include the animation?
Using PointsMaterial for loaded GLTF: (working)
const gltfLoader = new GLTFLoader();
gltfLoader.load( 'models/model.gltf', function ( gltf ) {
model = gltf.scene;
let pointsArray = [];
let v3 = new THREE.Vector3();
model.traverse(child => {
if (child.isMesh){
let pos = child.geometry.attributes.position;
for (let i = 0; i < pos.count; i++){
v3.fromBufferAttribute(pos, i);
pointsArray.push(v3.clone());
}
}
});
let particle_model_geometry = new THREE.BufferGeometry().setFromPoints( pointsArray );
particle_model_geometry.center();
particle_model = new THREE.Points( particle_model_geometry, points_material );
scene.add( particle_model );
render();
} );
Usings PointsMaterial for loaded FBX: (not working)
const loader = new FBXLoader();
loader.load( 'models/model.fbx', function ( object ) {
mixer = new THREE.AnimationMixer( object );
const action = mixer.clipAction( object.animations[ 1 ] );
action.play();
let pointsArray = [];
let v3 = new THREE.Vector3();
object.traverse(child => {
if ( child.isMesh ){
let pos = child.geometry.attributes.position;
for (let i = 0; i < pos.count; i++){
v3.fromBufferAttribute( pos, i );
pointsArray.push( v3.clone() );
}
}
});
let particle_model_geometry = new THREE.BufferGeometry().setFromPoints( pointsArray );
particle_model_geometry.center();
particle_model = new THREE.Points( particle_model_geometry, points_material );
scene.add( particle_model );
} );

three.js getObjectByName() results in undefined

I am attempting to change the opacity of an object in the update function but I am not able to call on the object by name. It always returns undefined.
This code is a fragment. There are many cars using the same function. I commented, "IS THIS CORRECT?", for the questionable lines. Please comment if clarification is needed.
// ***Program starts at the bottom
// initialize the scene
function init() {
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 1000);
camera.position.set(-71, 29, 103);
getCarAnim('Car1');
scene.add(parentCar1);
update(renderer, scene, camera);
return scene;
}
// importing the car model
function getCarAnim(path) {
var objLoader = new THREE.OBJLoader();
objLoader.load('/resource/3D Models/' + path + '.obj', function (obj) {
obj.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material = carMaterial;
child.material.transparent = true;
if (path == 'Car1') { // IS THIS CORRECT?
child.name = "Car1";
}
}
});
if (path == 'Car1') {
parentCar1.add(obj);
parentCar1.position.x = 15;
parentCar1.position.y = 0.9;
parentCar1.position.z = 3;
}
}
// rendering/updating the frame to screen
function update (renderer, scene, camera) {
renderer.render(scene, camera);
if (parentCar1.position.x <= 15) {
parentCar1.getObjectByName("Car1").material.opacity = .2; // IS THIS CORRECT?
}
requestAnimationFrame(function() {
update(renderer, scene, camera);
})
}
//**** program starts here
// This variable is the parent of the imported car model.
// It allows an imported object to be called upon
// so it can be animated in the update function.
var parentCar1 = new THREE.Object3D;
var carMaterial = new THREE.MeshLambertMaterial({color: 'rgb(152,152,152)'});
var scene = init();

Animating Three.js vertices

I'm trying to animate individual vertices from a collada model.
The vertices ARE animating fine once but then they don't animate anymore.
1: Load my collada
// name obj
var orgVerts = false;
var desVerts = false;
var material = new THREE.MeshBasicMaterial({ color:0x1e5679, wireframe:true });
var loader = new THREE.ColladaLoader();
var nameModel = false;
loader.options.convertUpAxis = true;
loader.load( '3d/name.dae', function ( collada ) {
nameModel = collada.scene.children[0].children[0];
nameModel.material = material;
nameModel.geometry.dynamic = true;
nameModel.position.set(0,0,0);//x,z,y- if you think in blender dimensions ;)
nameModel.scale.x = .0035;
nameModel.scale.y = .0035;
nameModel.scale.z = .0035;
scene.add(nameModel);
orgVerts = nameModel.geometry.vertices; // make a backup of all verts
genVerts(); // create a new array of random verts
});
2: in my render function
var render = function () {
requestAnimationFrame(render);
// do stuff
if(nameModel){
if(window.globalCurrentSlide != 0){
for(var r=0; r < nameModel.geometry.vertices.length; r++){
var vert = desVerts[r]; // loop through all the destination verts
nameModel.geometry.vertices[r].x = nameModel.geometry.vertices[r].x - (nameModel.geometry.vertices[r].x - vert.x)/20;
nameModel.geometry.vertices[r].y = nameModel.geometry.vertices[r].y - (nameModel.geometry.vertices[r].y - vert.y)/20;
nameModel.geometry.vertices[r].z = nameModel.geometry.vertices[r].z - (nameModel.geometry.vertices[r].z - vert.z)/20;
}
}else{
for(var t=0; t < nameModel.geometry.vertices.length; t++){
var vert2 = orgVerts[t]; // loop through all the original verts
nameModel.geometry.vertices[t].x = nameModel.geometry.vertices[t].x - (nameModel.geometry.vertices[t].x - vert2.x)/20;
nameModel.geometry.vertices[t].y = nameModel.geometry.vertices[t].y - (nameModel.geometry.vertices[t].y - vert2.y)/20;
nameModel.geometry.vertices[t].z = nameModel.geometry.vertices[t].z - (nameModel.geometry.vertices[t].z - vert2.z)/20;
}
}
nameModel.geometry.verticesNeedUpdate = true;
nameModel.rotation.y += .005;
}
renderer.render( scene, camera );
}
window.globalCurrentSlide is set to 0 to start with and everything is fine. if I change window.globalCurrentSlide to 1, all the vertices animate correctly... BUT when I change window.globalCurrentSlide back to 0 the vertices don't animate back to their original positions. I've debugged heaps and can 100% say that BOTH desVerts and orgVerts don't change and they are correct. Any ideas? It's driving me nuts.
PS: I know the code could be condensed, I'm just playing ATM
The answer was that my orgVerts was just a reference NOT a clone. use:
var geometry = nameModel.geometry.clone();
orgVerts = geometry.vertices;

TrackballControls with Collada kfAnimation Three JS

Hi guys I am working with kfAnimation animation from a Collada model. I want to include a trackball controls but when I do I exceed the size stack I dont know why my code is the following
function init() {
initRender();
// Camera
initCamera();
// Scene
initScene();
//controlls
initControls();
initGrid();
loadObjectAnimatedFrames();
window.addEventListener( 'resize', onWindowResize, false );
}
function loadObjectAnimatedFrames(){
loader = loader.load( 'sources/crack-animated.dae', function ( collada ) {
model = collada.scene;
animations = collada.animations;
kfAnimationsLength = animations.length;
//model.scale.x = model.scale.y = model.scale.z = 0.125; // 1/8 scale, modeled in cm
for ( var i = 0; i < kfAnimationsLength; ++i ) {
var animation = animations[ i ];
var kfAnimation = new THREE.KeyFrameAnimation( animation );
kfAnimation.timeScale = 1;
kfAnimations.push( kfAnimation );
}
start();
animate( lastTimestamp );
scene.add( model );
});
}
function initControls(){
controls = new THREE.TrackballControls(camera);
controls.minDistance = 100;
controls.maxDistance = 1800;
controls.addEventListener('change',render);
}
function animate( timestamp ) {
var frameTime = ( timestamp - lastTimestamp ) * 0.001;
if ( progress >= 0 && progress < 48 ) {
for ( var i = 0; i < kfAnimationsLength; ++i ) {
kfAnimations[ i ].update( frameTime );
}
} else if ( progress >= 48 ) {
for ( var i = 0; i < kfAnimationsLength; ++i ) {
kfAnimations[ i ].stop();
}
progress = 0;
start();
}
//pointLight.position.copy( camera.position );
progress += frameTime;
lastTimestamp = timestamp;
render();
}
I tried to put controls update inside animate and start function but I think it consumed a lot of resources. Also I tried to put inside render but same results.
Thanks for your help I hope some more experimented can help me.
Finally I found the solution and it was an option enableDamping and dampingFactor
function initControls(){
controls = new THREE.TrackballControls( camera, renderer.domElement );
//controls.addEventListener( 'change', render ); // add this only if there is no animation loop (requestAnimationFrame)
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = false;
}
after this I just add controls.update();
renderer.render( scene, camera );
requestAnimationFrame( animate );

Why does this cube not rotate around its own axes?

I've got a cube which I would like to rotate around its own axes in 3D space by using keyboard input. The cube is still rotating around the world axes.
Here's my code:
var rotation_matrix_y, rotation_matrix_x, rotation_matrix_z;
var geometry = new THREE.CubeGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({color: 0x00ff00, wireframe: true});
var cube = new THREE.Mesh(geometry, material);
var axisHelper = new THREE.AxisHelper( 5 );
cube.add( axisHelper );
scene.add(cube);
cube.rotation.set(0, 0, 0);
cube.matrix.makeRotationFromEuler(cube.rotation);
var render = function () {
document.addEventListener("keydown", onKeyDown, false);
function onKeyDown(e) {
// W - up
if (e.keyCode == 87) {
rotation_matrix_x = new THREE.Matrix4().makeRotationX(.0001);
cube.applyMatrix(rotation_matrix_x);
}
// S - down
if (e.keyCode == 83) {
rotation_matrix_x = new THREE.Matrix4().makeRotationX(-0.0001);
cube.applyMatrix(rotation_matrix_x);
}
// D - right
if (e.keyCode == 68) {
rotation_matrix_y = new THREE.Matrix4().makeRotationY(-0.0001);
cube.applyMatrix(rotation_matrix_y);
}
// A - left
if (e.keyCode == 65) {
rotation_matrix_y = new THREE.Matrix4().makeRotationY(0.0001);
cube.applyMatrix(rotation_matrix_y);
}
requestAnimationFrame(render);
stats.update();
renderer.render(scene, camera);
};
There are a couple of questions similar to this one, but they all seem to be outdated and some of the methods have been deprecated.
An easy way to rotate an object on its own x-axis is like so:
object.rotateX( radians );
There is also object.rotateY( radians ); and object.rotateZ( radians );
three.js r.66

Resources