three.js create a mesh from a gltf objections - three.js

I have rendered a gltf object in three.js, but the issue is I don't think it contains a mesh. I want to use a ray caster to move the object with an on click event handler. I have all the code in place to do this, but it doesn't register when I click.
Code to load the object:
var loader = new THREE.GLTFLoader();
loader.load(
// resource URL
'./vitra_eames_plastic_chair/scene.gltf',
// called when the resource is loaded
function ( object ) {
object.animations; // Array<THREE.AnimationClip>
object.scene; // THREE.Scene
object.scenes; // Array<THREE.Scene>
object.cameras; // Array<THREE.Camera>
object.asset; // Object
var object = new THREE.Mesh(gltf.asset, new THREE.MeshLambertMaterial({ color: Math.random() * 0xffffff }));
object.scene.position.x = -75;
object.scene.position.y = -75;
object.scene.position.z = -75;
object.scene.rotation.x = 50;
object.scene.rotation.y = 50;
object.scene.rotation.z = 50;
object.scene.scale.x = .5;
object.scene.scale.y = .5;
object.scene.scale.z = .5;
object.scene.castShadow = true;
object.scene.receiveShadow = true;
boxScene.add(object.scene);
objects.push(object.scene);
},
// called while loading is progressing
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
// called when loading has errors
function ( error ) {
console.log( 'An error happened' );
}
);
I also have this code, which generates boxes. Here, the event handler works, but obviously the object were loaded differently. Any advice would be greatly appreciated.
var geometry = new THREE.BoxGeometry(1, 1, 1);
for (var i = 0; i < 50; i++) {
var object = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({ color: Math.random() * 0xffffff }));
object.position.x = Math.random() * 50 - 25;
object.position.y = Math.random() * 10 + 1;
object.position.z = Math.random() * 50 - 25;
object.rotation.x = Math.random() * 2 * Math.PI;
object.rotation.y = Math.random() * 2 * Math.PI;
object.rotation.z = Math.random() * 2 * Math.PI;
object.scale.x = Math.random() * 3 + 1;
object.scale.y = Math.random() * 3 + 1;
object.scale.z = Math.random() * 3 + 1;
object.castShadow = true;
object.receiveShadow = true;
boxScene.add(object);
objects.push(object);
}

I think you have to change your onLoad() callback of GLTFLoader.load() to fix the problem. You are creating a mesh with object.asset which is not correct. Instead, you can add object.scene directly to your scene graph. So in most cases the callback can simply be like this:
var loader = new THREE.GLTFLoader();
loader.load( function( gltf ) {
scene.add( gltf.scene );
) };
Check out the source code of the following example to see this approach in action.
https://threejs.org/examples/webgl_loader_gltf.html

Related

How to add measurement details while line drawing in three.js

I'm trying to add the length of the start point and endpoint of the line geometry. I have a line but I have no idea how to show some unit measurement data in the form of the text while drawing the wall in mouse move itself.
Here's the fiddle
var renderer, scene, camera;
var line;
var count = 0;
var mouse = new THREE.Vector3();
init();
animate();
function init() {
// info
var info = document.createElement('div');
info.style.position = 'absolute';
info.style.top = '30px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.style.color = '#fff';
info.style.fontWeight = 'bold';
info.style.backgroundColor = 'transparent';
info.style.zIndex = '1';
info.style.fontFamily = 'Monospace';
info.innerHTML = "three.js - animated line using BufferGeometry";
document.body.appendChild(info);
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 0, 1000);
// geometry
var geometry = new THREE.BufferGeometry();
var MAX_POINTS = 500;
positions = new Float32Array(MAX_POINTS * 3);
geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
// material
var material = new THREE.LineBasicMaterial({
color: 0xff0000,
linewidth: 2
});
// line
line = new THREE.Line(geometry, material);
scene.add(line);
document.addEventListener("mousemove", onMouseMove, false);
document.addEventListener('mousedown', onMouseDown, false);
}
// update line
function updateLine() {
positions[count * 3 - 3] = mouse.x;
positions[count * 3 - 2] = mouse.y;
positions[count * 3 - 1] = mouse.z;
line.geometry.attributes.position.needsUpdate = true;
}
// mouse move handler
function onMouseMove(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
mouse.z = 0;
mouse.unproject(camera);
if( count !== 0 ){
updateLine();
}
}
// add point
function addPoint(event){
console.log("point nr " + count + ": " + mouse.x + " " + mouse.y + " " + mouse.z);
positions[count * 3 + 0] = mouse.x;
positions[count * 3 + 1] = mouse.y;
positions[count * 3 + 2] = mouse.z;
count++;
line.geometry.setDrawRange(0, count);
updateLine();
}
// mouse down handler
function onMouseDown(evt) {
// on first click add an extra point
if( count === 0 ){
addPoint();
}
addPoint();
}
// render
function render() {
renderer.render(scene, camera);
}
// animate
function animate() {
requestAnimationFrame(animate);
render();
}
I'm trying to achieve the measurement like the above.
The simplest way is to use CSS2D labels. You can assign a regular HTML <div> to act as a label. It displays flat on top of your <canvas> renderer without rotations so it's always facing the camera. See here for a demo on how to set up your CSS2DRenderer:
https://threejs.org/examples/#css2d_label
All you'd have to do is take the average of 2 Vector3s, and assign that as your label's position.
// Get distance and midpoint
var distance = vectorA.distanceTo(vectorB);
var midpoint = new Vector3();
midpoint.copy(vectorA);
midpoint.add(vectorB).multiplyScalar(0.5);
// Create label, set distance and position
const labelDiv = document.createElement( 'div' );
labelDiv.className = 'label';
labelDiv.textContent = "Distance: " + distance;
labelDiv.style.marginTop = '-1em';
const distLabel = new CSS2DObject( labelDiv );
distLabel.position.copy( midpoint );
cssScene.add( distLabel );

Why can not see models fbx in three.js?

I'm trying to load models using this js code.
The code is based on an example from this page.
https://threejs.org/examples/?q=fbx#webgl_loader_fbx
function A1(){
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(65,window.innerWidth/window.innerHeight, 0.1, 10000);
var container = document.getElementById( 'program3d' );
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth , window.innerHeight );
container.appendChild( renderer.domElement );
renderer.setSize (400, 400);
renderer.setClearColor ( 0xC8C7C7 );
camera.position.z= 5;
camera.position.x= 0;
camera.position.y= 0;
var ambientLight = new THREE.AmbientLight ( 0xfffef5, 0.45 );
scene.add (ambientLight);
var directionalLight = new THREE.DirectionalLight (0xfff2e8, 0.8 );
directionalLight.position.set (0.1, 1, 0.2);
scene.add(directionalLight);
var light1 =new THREE.PointLight(0xFFFFFF, 4 , 30);
//scene.add (light1);
var light2 =new THREE.PointLight(0xFFFFFF, 4 , 30);
//scene.add (light2);
var light3 =new THREE.PointLight(0xFFFFFF, 4 , 30);
//scene.add (light3);
var update = function (){
var time = Date.now() * 0.0005;
light1.position.x = Math.sin ( time * 0.7) * 30;
light1.position.y = Math.cos ( time * 0.5) * 40;
light1.position.z = Math.cos ( time * 0.3) * 30;
light2.position.x = Math.cos ( time * 0.3) * 30;
light2.position.y = Math.sin ( time * 0.5) * 40;
light2.position.z = Math.sin ( time * 0.7) * 30;
light3.position.x = Math.sin ( time * 0.7) * 30;
light3.position.y = Math.cos ( time * 0.3) * 40;
light3.position.z = Math.sin ( time * 0.3) * 30;};
var loader = new THREE.FBXLoader();
loader.load( 'models/2B.fbx', function ( object ) {
object.mixer = new THREE.AnimationMixer( object );
mixers.push( object.mixer );
var action = object.mixer.clipAction( object.animations[ 0 ] );
action.play();
object.traverse( function ( child ) {
if ( child.isMesh ) {
child.castShadow = true;
child.receiveShadow = true;
}});
scene.add( object );} );
var stats = new Stats();
container.appendChild( stats.dom );
var clock = new THREE.Clock();
var mixers = [];
function animate() {
if ( mixers.length > 0 ) {
for ( var i = 0; i < mixers.length; i ++ ) {
mixers[ i ].update( clock.getDelta() );
}}}
var controls = new THREE.TrackballControls (camera);
var end_scene = function(){
requestAnimationFrame (end_scene);
animate();
controls.update();
renderer.render(scene, camera);
update();};
end_scene();};
The problem is: The code displays only some models.
in console there are not any errors
Models on which I checked the code
Work
https://dropmefiles.com/6eQrs
does not work
https://dropmefiles.com/Mxo2R
Perhaps the problem is in the textures but I can not say for sure.

Unable to intersect Points

I unable to intersect Three.Points but i am able to intersect THREE.Mesh, below is my code: Can someone please help me to understand what mistake i am making. When i intersect the Points all i get is 0.
function init()
{
geometry = new THREE.Geometry();
vertex = new THREE.Vector3();
vertex.x=( [i + 3 ] * 140 ) - 1330;
vertex.y = - ( [i + 3 ] * 180 ) + 990;
vertex.z = 100;
geometry.vertices.push(vertex);
var particleTexture = THREE.ImageUtils.loadTexture(imgstr);
var materials = new THREE.PointsMaterial({
map:particleTexture,
size: 150
});
particles = new THREE.Points(geometry, materials);
scene.add(particles);
targetList.push(particles);
}
function onDocumentMouseMove( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function onDocumentMouseDown(event){
var projector = new THREE.Projector();
var vector = new THREE.Vector3(
(event.clientX / window.innerWidth) * 2 - 1,
-(event.clientY / window.innerHeight) * 2 + 1,
0.5);
projector.unprojectVector(vector, camera);
var raycaster = new THREE.Raycaster(camera.position,vector.sub(camera.position).normalize());
var intersects = raycaster.intersectObjects(targetList);
console.log(intersects.length);
}
function onDocumentMouseDown( event ) {
event.preventDefault();
if(event.which == 1) {
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera( mouse, camera );
raycaster.params.Points.threshold = 100000; // bigger number = bigger sensitivity
var intersects = raycaster.intersectObjects( myobjectsarray,false); // myobject array is array of THREE.Points object
if ( intersects.length > 0 ) {console.log('tadaah',intersects);}
}
}

ThreeJS : Raycasts is off on some computers

I've been doing a ThreeJS project and using raycasting to interesect with objects within the canvas.
I have 4 computers to test it on, all updated with the latest repo.
On one of the computers the raycasting is off from where the mouse are... and I have no idea what is causing it to behave differently from the others.
Any ideas?
The code:
// Performs a Raycast for Ortho camera type
PerformOrthographicRaycast: function (event, canvas, renderer, camera, objects) {
var vector = new THREE.Vector3(0, 0, 0);
var dir = new THREE.Vector3(0, 0, 0);
vector.x = ((event.clientX - canvas.getBoundingClientRect().left) / renderer.domElement.width) * 2 - 1;
vector.y = -((event.clientY - canvas.getBoundingClientRect().top) / renderer.domElement.height) * 2 + 1;;
vector.z = -1; // z = - 1 important!
vector.unproject(camera);
dir.set(0, 0, -1).transformDirection(camera.matrixWorld);
this._Raycaster.set(vector, dir);
var intersects = this._Raycaster.intersectObjects(objects, true);
if (intersects.length) {
return intersects;
}
else
return null;
},
See this example. Look at messages in the console.
<script src="js/controls/EventsControls.js"></script>
EventsControls = new EventsControls( camera, renderer.domElement );
EventsControls.draggable = false;
EventsControls.mouseOver = function () {
this.container.style.cursor = 'pointer';
this.mouseOvered.currentHex = this.mouseOvered.material.emissive.getHex();
this.mouseOvered.material.emissive.setHex( 0xff0000 );
console.log( 'the key at number ' + this.mouseOveredItem + ' is select' );
}
//
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
EventsControls.attach( mesh );
//
function render() {
EventsControls.update();
controls.update();
renderer.render(scene, camera);
}
I found out that the problem was with Windows "enlarge" or "scale" users can set in their theme settings.
In the renderer you can find the pixelratio which is modified when the scaling has been changed. The following solution works for me:
vector.x = renderer.devicePixelRatio * ((event.clientX - canvas.getBoundingClientRect().left) / renderer.domElement.width) * 2 - 1;
vector.y = renderer.devicePixelRatio * -((event.clientY - canvas.getBoundingClientRect().top) / renderer.domElement.height) * 2 + 1;;

how can I update THREE.Sprite color

jsfiddle here
I create a material with a default color, in this case 0xffffff.
Then later, I want to change the color. I can't figure out where to change it - particle.color = 0xffffff * Math.random(); doesn't work. There is no particle.color, but there is a particle.material.color, which if I change gives me an error.
Do I need to create new materials for every sprite? Is there a way I can simply change the color of a THREE.Sprite?
var material = new THREE.SpriteCanvasMaterial({
color: 0xffffff,
program: function (context) {
context.beginPath();
context.arc(0, 0, 0.5, 0, PI2, true);
context.fill();
}
});
for (var i = 0; i < 50; i++) {
particle = new THREE.Sprite(material);
particle.position.x = Math.random() * 2 - 1;
particle.position.y = Math.random() * 2 - 1;
particle.position.z = Math.random() * 2 - 1;
particle.position.normalize();
particle.position.multiplyScalar(Math.random() * 10 + 450);
particle.scale.x = particle.scale.y = 20;
particle.color = 0xffffff * Math.random();
scene.add(particle);
}
particle.material.color = new THREE.Color(0x0066CC);
or
particle.material.color.set(0x0066CC); Threejs: R.73
from the docs:
http://threejs.org/docs/#Reference/Math/Color

Resources