How can i call the BufferGeometryUtils from threejs? - three.js

I tried to merge two geometries pre-loaded from two PLY files, the console of the browser told me should be use the BufferGeometryUtils.mergeBufferGeometries() for merge de two geometries into one, but I some problems for call this from the class.
Here is my code:
var scene = new THREE.Scene();
var singleGeometry, material, mesh;
var loader = new THREE.PLYLoader();
function loadPLY(path) {
return new Promise(resolve => {
loader.load(path, result => {
console.log('Success');
resolve(result);
});
});
}
init();
Promise.all([
loadPLY("ply/Paso_1_mandible.ply"),
loadPLY("ply/maxila.ply")
])
.then(geometries => {
geometries.forEach(geometry => geometry.computeVertexNormals());
singleGeometry = new THREE.BufferGeometry();
singleGeometry = THREE.BufferGeometryUtils.mergeBufferGeometries(geometries);
material = new THREE.MeshPhongMaterial({color: 0x0055ff });
mesh = new THREE.Mesh(singleGeometry, material);
mesh.position.y = 1;
mesh.position.z = 1;
mesh.position.x = 1;
mesh.scale.multiplyScalar( 0.0001 );
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add(mesh);
})
.then(() => {
animate();
})
.catch(err => {console.error(err);});
but I got this error:
TypeError: "THREE.BufferGeometryUtils is undefined"
here is the link to the documentation:
class BufferGeometryUtils

It's in examples/js/BufferGeometryUtils.js in the THREE master distro.
https://github.com/mrdoob/three.js/archive/master.zip

The error TypeError: "THREE.BufferGeometryUtils is undefined" is quite clear.
You need to include the BufferGeometryUtils class / file in your code.
As it is in the examples folder, it is not included in the main Three.js library.

Related

How do I render a svg as a mesh in three js

Im trying to render a SVG file as a mesh using SVGLoader in my three js application, but its not working
I followed the documentation to the SVGLoader step by step but still nothing
here is the documentation : https://threejs.org/docs/index.html?q=svg#examples/en/loaders/SVGLoader
and here is my code that i've tried :
const loader = new SVGLoader();
const group = new Group();
loader.load(
"../public/assets/svg/logo.svg",
function (data) {
const paths = data.paths;
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
const material = new MeshBasicMaterial({
color: path.color,
side: DoubleSide,
depthWrite: false,
});
const shapes = SVGLoader.createShapes(path);
for (let j = 0; j < shapes.length; j++) {
const shape = shapes[j];
const geometry = new ShapeGeometry(shape);
const mesh = new Mesh(geometry, material);
group.add(mesh);
}
}
},
function (xhr) {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
function (error) {
console.log("An error happened", error);
}
);
scene.add(group);
Im not getting any error messages when I run my code.

how do we load multiple OBJ Loader & MTL Loader in array (Three.js)

It is only Loading Last model which in the array.
based on this source
Create an instance of LoadingManager and apply it to the ctor of all loaders you are going to create. In the next step, assign an onLoad() callback to the manager so you can execute code when everything has been loaded.
but I don't know how to write it
this is my code
// build markerControls
let patternArray = ["hiro", "pattern-markerobj1"];
let colorArray = [0xff8800, 0xffff00, ];
let mtlobj = ['fish-2', 'percobaan', ];
let scale = [0.25, 0.0025, ];
for (let i = 0; i < 2; i++) {
markerRoot1 = new THREE.Group();
scene.add(markerRoot1);
let markerControls1 = new THREEx.ArMarkerControls(arToolkitContext, markerRoot1, {
type: 'pattern',
patternUrl: "data/" + patternArray[i] + ".patt",
})
let geometry1 = new THREE.PlaneBufferGeometry(1, 1, 4, 4);
// let texture = loader.load( 'images/earth.jpg', render );
let material1 = new THREE.MeshBasicMaterial({
color: colorArray[i],
opacity: 0.0005
});
mesh1 = new THREE.Mesh(geometry1, material1);
mesh1.rotation.x = -Math.PI / 2;
markerRoot1.add(mesh1);
function onProgress(xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
}
function onError(xhr) {
console.log('An error happened');
}
new THREE.MTLLoader()
.setPath('models/')
.load(mtlobj[i] + '.mtl',function (materials) {
materials.preload();
new THREE.OBJLoader()
.setMaterials(materials)
.setPath('models/')
.load(mtlobj[i] + '.obj', function (group) {
mesh0 = group.children[0];
mesh0.material.side = THREE.DoubleSide;
mesh0.position.y = 0.25;
mesh0.scale.set(scale[i], scale[i], scale[i]);
markerRoot1.add(mesh0);
}, onProgress, onError);
});
}
screenshot: all 3D models are loaded in the last marker :')
the fish model (mtlobj[0]) should be included in the Hiro index[0] marker. but the hiro marker doesn't contain fish ->screenshot: marker hero -> why no fish?
can you help me to rewrite the code using LoadingManager according to this directive ? Mugen87
?

Loading multiple textures from different url's fails

I am trying to render textures on planes loaded from different URL's. For some reason after 2nd or 3rd image I can see in browser that loading image is stuck and it is not being rendered.
Adding the code used:
function init() {
loadPicturesFromDirectUrl();
}
function loadPicturesFromDirectUrl(currentPictureIndex) {
if (currentPictureIndex === undefined) {
currentPictureIndex = 0;
}
var picture = data.pictures[currentPictureIndex];
var loader = new THREE.TextureLoader();
loader.load(picture.url, function (texture) {
renderPicture(picture, texture);
currentPictureIndex++;
if (currentPictureIndex > data.pictures.length - 1) {
return;
}
loadPicturesFromDirectUrl(currentPictureIndex);
}, null, function (e) {
console.log(e);
});
}
function renderPicture(picture, texture) {
var planeGeometry = new THREE.PlaneGeometry(picture.size.width, picture.size.height);
var planeMaterial = new THREE.MeshBasicMaterial({ map: texture });
var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
planeMesh.position.x = picture.location.x;
planeMesh.position.y = picture.location.y;
planeMesh.rotateY(myzeum.toRadians(180));
scene.add(planeMesh);
}
You may want to try to preload all the pictures in one function and store them in an array and render them only after all of them have been loaded. Like so:
var all_textures = [];
function init() {
loadPicturesFromDirectUrl();
for int (i = 0; i < all_picture.length; i++) {
renderPicture(data.pictures[i], all_textures[i])
}
}
function loadPicturesFromDirectUrl(currentPictureIndex) {
if (currentPictureIndex === undefined) {
currentPictureIndex = 0;
}
var picture = data.pictures[currentPictureIndex];
var loader = new THREE.TextureLoader();
loader.load(picture.url, function (texture) {
all_textures[currentPictureIndex] = texture
currentPictureIndex++;
if (currentPictureIndex > data.pictures.length - 1) {
return;
}
loadPicturesFromDirectUrl(currentPictureIndex);
}, null, function (e) {
console.log(e);
});
}
function renderPicture(picture, texture) {
var planeGeometry = new THREE.PlaneGeometry(picture.size.width, picture.size.height);
var planeMaterial = new THREE.MeshBasicMaterial({ map: texture });
var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
planeMesh.position.x = picture.location.x;
planeMesh.position.y = picture.location.y;
planeMesh.rotateY(myzeum.toRadians(180));
scene.add(planeMesh);
}

Three.js OBJLoader without adding object to scene

I created a function for loading obj files in Three.js. Instead of adding the object directly to the scene in that function, I want to return it to the upper function.
Current code:
var loadObjFile = function(modelConfiguration) {
var mtlLoader = new THREE.MTLLoader();
mtlLoader.load(modelConfiguration.mtl, function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load(modelConfiguration.obj, function (object3d) {
object3d.name = modelConfiguration.name;
scene.add(object3d);
});
});
};
Things I tried
Rewritting the function in difference ways. But couldn't get it to return the object3d. Example:
var loadObjFile = function(modelConfiguration) {
var mtlLoader = new THREE.MTLLoader();
var obj;
mtlLoader.load(modelConfiguration.mtl, function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load(modelConfiguration.obj, function (object3d) {
object3d.name = modelConfiguration.name;
obj = object3d;
});
});
return obj;
};
Instead of adding the object3d to the scene, I added it to a dummy group and returned this group. It worked but later on I have a lot of unnecessary groups. I also tried to extract the object from the group with group.children[0] and group.getObjectByName(modelConfiguration.name) but it didn't work either. Example:
var loadObjFile = function(modelConfiguration) {
var mtlLoader = new THREE.MTLLoader();
var group;
mtlLoader.load(modelConfiguration.mtl, function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load(modelConfiguration.obj, function (object3d) {
object3d.name = modelConfiguration.name;
group.add(object3d);
});
});
return group; // works, but unneccessary group
//return group.children[0]; // error: undefined object
//return group.getObjectByName(modelConfiguration.name); // error: undefined object
};
Thank you in advance!
use a lambda:
var loadObjFile = function(modelConfiguration, onObj) {
var mtlLoader = new THREE.MTLLoader();
var obj;
mtlLoader.load(modelConfiguration.mtl, function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load(modelConfiguration.obj, function (object3d) {
object3d.name = modelConfiguration.name;
obj = object3d;
onObj(obj);
});
});
};
use:
loadObjFile(myModelConfig, function(obj){
console.log(obj);
})

raycast : Cannot read property 'visible' of undefined

i'm trying to load my .obj & MTL file into threejs and apply simple wall collision using raycaster. The scene has walls and other objects.
Used pointer control example
the loading and texturing are in place
problem is when using raycaster it throws an error "cannot read property visible of undefined" I guess my referencing is bad.
i used scene.children for passing objects in raycaster
here is the code for ray caster and obj loader. please let me know where im going wrong
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl( 'neavik/' );
mtlLoader.setPath( 'neavik/' );
mtlLoader.load( 'room.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( 'neavik/' );
objLoader.load( 'room.obj', function ( object ) {
object.position.y = - 5;
object.scale.x=object.scale.y=object.scale.z=0.05
object.traverse( function( child ) { if ( child instanceof THREE.Mesh ) {
if (child.material.name == "Interior_wall") {
child.material = innerwall;
child.castShadow = true;
child.receiveShadow = true;
}
if (child.material.name == "Loby") {
child.material = innerwall1;
child.castShadow = true;
child.receiveShadow = true;
}
if (child.material.name == "TV_Black_Plastic") {
child.material = Black;
child.castShadow = true;
child.receiveShadow = true;
}});
object.name = "object";
scene.add( object );
});
} );
//Raycast
var rayCaster = new THREE.Raycaster(controls.getObject().position, cameraDirection);
var intersects = rayCaster.intersectObject(scene.children, true); //getting error on this line
$("#status").html("camera direction x: " + cameraDirection.x + " , z: " + cameraDirection.z);
// rest of the code
I had the same error and in my case the reason was that the object to be intersected was not existing yet or found at time of intersection.
Therefore I added a kind of null check to prevent this error message:
if (typeof scene != "undefined")

Resources