Are there vertices on imported STL files in tree.js? - three.js

I am trying to import STL files and then reduce the number of vertices using this great mesh simplification function:
http://www.blurspline.com/labs/3D/bunny/
https://github.com/mrdoob/three.js/issues/5806
It seems that geometry.vertices returns "Undefined" after I import via STLLoader. And I think this has to be the reason this does not work for me.
I´m using this code to import it;
var loader = new THREE.STLLoader();
loader.load( 'mySTLfile.stl', function ( geometry ) {
geometriesParams.push({type: 'Test', args: [ ], scale: 100, meshScale:1 });
console.log("Vertices:"+geometry.vertices);
THREE.Test = function() {
return geometry.clone();
};
updateInfo()
} );
Why aren't there any vertices on imported STL files? And does anyone know of a solution to this?

STLLoaderreturns THREE.BufferGeometry.
In your loader callback, you can convert your geometry to THREE.Geometry like so:
var geometry = new THREE.Geometry().fromBufferGeometry( geometry );
three.js r.84

Related

OutlinePass is not rendered to scene in THREE.js

I followed these examples to make the outline for objects when they are selected:
https://threejs.org/examples/?q=out#webgl_postprocessing_outline
https://github.com/scqilin/three-OutlinePass
No error is found, yet outline does not appear when the object is selected. The highlightSelectedObject function is correcly triggered when an object is selected. selectedObjects is not null.
In my case, THREE.js is installed in the project file. Scene, camera and renderer are instantiated elsewhere.
import * as THREE from "../../build/three.module.js";
import {OutlinePass} from "../../examples/jsm/postprocessing/OutlinePass.js";
import {RenderPass} from "../../examples/jsm/postprocessing/RenderPass.js";
import {EffectComposer} from "../../examples/jsm/postprocessing/EffectComposer.js";
Function:
function highlightSelectedObject(selectedObjects) {
if (selectedObjects != null) {
const scene = project.currentScene.scene;
const camera = project.currentScene.camera;
const renderer = project.renderer;
var composer = new EffectComposer(renderer);
var renderPass = new RenderPass(scene, camera);
var outlinePass = new OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera, selectedObjects);
outlinePass.renderToScreen = true;
outlinePass.selectedObjects = selectedObjects;
composer.addPass(renderPass);
composer.addPass(outlinePass);
const params = {
edgeStrength: 2,
edgeGlow: 1,
edgeThickness: 1.0,
pulsePeriod: 0,
usePatternTexture: false
};
outlinePass.edgeStrength = params.edgeStrength;
outlinePass.edgeGlow = params.edgeGlow;
outlinePass.visibleEdgeColor.set(0xffffff);
outlinePass.hiddenEdgeColor.set(0xffffff);
composer.render(scene, camera);
}
}
The path to THREE.js should be correct. Is it a problem with render?
I had a similar issue. Upon looking at another example, I found that setting outlinePass.renderToScreen = true allowed it to work. It might not be there depending what version of the the outlinePass.js you are using. I looked at the code on the deployed example and it is there.

A-Frame THREE.TextureLoader loading texture whice is looking whitewashed

I am updating an a-image scr using THREE.TextureLoader
let loader = new THREE.TextureLoader()
const imgload = loader.load(
'./test.png',
function ( texture ) {
firstFrameImage.getObject3D('mesh').material.map = texture
firstFrameImage.getObject3D('mesh').material.needsUpdate = true
},
// onProgress callback currently not supported
undefined,
// onError callback
function ( err ) {
console.error( 'An error happened.' );
}
)
Its updating the texture but its making the texture whitewashed. Can any one help?
Original image:
original
Updated texture coming as:
after update
Try to fix this by doing this:
texture.encoding = THREE.sRGBEncoding;
Color deviations like this mostly occur because of wrong color space definitions.

How to clone a Skinned Mesh?

I need to have multiple identical, animated models on a scene. If possible, I would like them to have a shared geometry and material, but if it is impossible, having them instanced per model will suffice too.
Unfortunately, the only way to achieve this result I found is to go through JSONLoader for every model instance.
SkinnedMesh does have a clone() method, but it seems not to be fully implemented yet. If used and both original and cloned mesh are present on the scene, only one will appear, and cloned one will be without animation.
I have attempted to use this example with shared skeletons:
https://github.com/mrdoob/three.js/pull/11666
...and indeed it works, but I need to be able to play different animations for every model instance, having them all play the same one is not sufficient, sadly. I hoped I could do similar hax and insert my own skeleton (made out of bones from the JSON file), but it behaves very much like if I just used clone() from SkinnedMesh.
I am using this code:
https://github.com/arturitu/threejs-animation-workflow/blob/master/js/main.js
Basically what I'd like to achieve is
var onLoad = function (geometry, materials) {
window.geometry = geometry;
character = new THREE.SkinnedMesh(
geometry,
new THREE.MeshFaceMaterial(materials)
);
character2 = character.someMagicalClone();
scene.add(character);
scene.add(character2);
(...)
I need any clue... and while I wait for help, I am busily deconstructing constructor for SkinnedMesh and JSONLoader for clues ;)
Thanks in advance!
I found a solution in this pull request:
https://github.com/mrdoob/three.js/pull/14494
in short, there are two functions added:
function cloneAnimated( source ) {
var cloneLookup = new Map();
var clone = source.clone();
parallelTraverse( source, clone, function ( sourceNode, clonedNode ) {
cloneLookup.set( sourceNode, clonedNode );
} );
source.traverse( function ( sourceMesh ) {
if ( ! sourceMesh.isSkinnedMesh ) return;
var sourceBones = sourceMesh.skeleton.bones;
var clonedMesh = cloneLookup.get( sourceMesh );
clonedMesh.skeleton = sourceMesh.skeleton.clone();
clonedMesh.skeleton.bones = sourceBones.map( function ( sourceBone ) {
if ( ! cloneLookup.has( sourceBone ) ) {
throw new Error( 'THREE.AnimationUtils: Required bones are not descendants of the given object.' );
}
return cloneLookup.get( sourceBone );
} );
clonedMesh.bind( clonedMesh.skeleton, sourceMesh.bindMatrix );
} );
return clone;
}
function parallelTraverse( a, b, callback ) {
callback( a, b );
for ( var i = 0; i < a.children.length; i ++ ) {
parallelTraverse( a.children[ i ], b.children[ i ], callback );
}
}
As I understand it rebinds cloned skeleton to the cloned mesh.
so topic example could look like:
var onLoad = function (geometry, materials) {
window.geometry = geometry;
character = new THREE.SkinnedMesh(
geometry,
new THREE.MeshFaceMaterial(materials)
);
character2 = cloneAnimated(character); // <-- used that new function
scene.add(character);
scene.add(character2);
(...)

STLLoader does not create valid geometry for STLExporter

I am using the STLLoader to import models into a scene that also has other objects. After that, I export the entire scene using STLExporter. Any STL models previously imported does not appear to export with the rest of the scene. Why is that and how can I make it work?
In addition to three.min.js, the following libraries were also used:
STLExporter.js
STLLoader.js
fileSaver.js
Import:
var stlLoader = new THREE.STLLoader();
stlLoader.load( 'models/anymodel.stl', function ( geometry ) {
var model = new THREE.Mesh(geometry, material);
model.position.set(0, 0, 0);
model.name="model"
scene.add(model);
})
Export:
var exporter = new THREE.STLExporter();
var txt = exporter.parse(scene);
var blob = new Blob([txt], { type: "text/plain;charset=utf-8" });
saveAs(blob, "export.stl");
In the STLExporter, there is a line that checks if an object is valid geometry. If not, the object is skipped. A model imported with STLLoader does not appear have valid geometry.

WebGLRenderingContext ERROR loading texture maps

First of all, thank you for this wonderfull work, i'm having a lot of fun working with three.js.
I tried to find answer about a recurent issue, .WebGLRenderingContext: GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 2
I'm making a website in webgl, i spend few week understanding all about three.js but i can't fix this issue.
I get this message on Chrome and firefox (latest) each time i try to load a canvas into a map, bumpmap and specmap.
All my mesh are loaded from obj files, by the way i rewrote OBJMTLLoader.js to be able to load more parameters from obj files and more.
here the code used to load image.
THREE.MTLLoader.loadTexture = function ( url, mapping, onLoad, onError ) {
var isCompressed = url.toLowerCase().endsWith( ".dds" );
var texture = null;
if ( isCompressed ) {
texture = THREE.ImageUtils.loadCompressedTexture( url, mapping, onLoad, onError );
} else {
var image = new Image();
texture = new THREE.Texture( image, mapping );
var loader = new THREE.ImageLoader();
loader.addEventListener( 'load', function ( event ) {
texture.image = THREE.MTLLoader.ensurePowerOfTwo_( event.content );
texture.needsUpdate = true;
if ( onLoad )
onLoad( texture );
} );
loader.addEventListener( 'error', function ( event ) {
if ( onError ) onError( event.message );
} );
loader.crossOrigin = this.crossOrigin;
loader.load( url, image );
}
return texture;
};
I'm pretty sure it is from this, because when i disable this function, no more warning.
Is it because the mesh has a texture with an empty image while loading datas ?
Is there any restriction on the dimensions of image ?
For now everything works fines, but i feel strange having those message in console.
Thanks
This error become because the Three.js buffers are outdated. When your add some textures (map,bumpMap ...) to a Mesh, you must recompose the buffers like this :
ob is THREE.Mesh, mt is a Material, tex is a texture.
tex.needsUpdate = true;
mt.map = tex;
ob.material = mt;
ob.geometry.buffersNeedUpdate = true;
ob.geometry.uvsNeedUpdate = true;
mt.needsUpdate = true;
That's all folks !
Hope it's help.
Regards.
Sayris

Resources