I know this is a well known question but I was not able to find a good answer.
My usage
I use three.js to display 3D models created through drone pictures (here an example).
The problem
I can't render heavy models (1M vertices, 2M faces) : Chrome or WebGl crashed.
What I tried
I used Threejs.org examples for all my tests to be sure that it was not my code that didn't work. I made my test on a x64 Chrome with --max_old_space_size=6144 flag.
Import model in .dae with ColladaLoader --> 2.5Go of RAM is used and Chrome crash (displaying "not enough memory")
Import model in .obj with OBJLoader + MTLLoader --> 2.8Go of RAM is used and WebGl crash
I red many posts about Three.js and memory allocation but many of them speak about remove an object from the scene
Possible solutions
I saw that .stl (binary) file are more compact, but as far as I know
there is no texture with these files, so I can't use it
Use BinaryLoader (which has GeometryBuffer output) but I need to convert .dae or .obj to binary files and I don't know how to do that
Load my model in multiple parts to not load in one shot ? But I didn't saw any example or posts with that kind of treatment
How to reproduce
For the code, I use basics examples on Threejs.org. For models :
If you want to try with .dae you can find on this folder a working example (WorkingModel.dae / .jpg) and the model who don't work (BigModel.dae / .jpg)
If you want to try with .obj you can find on this folder a working example (WorkingModel.dae / .jpg / .mtl) and the model who don't work (BigModel.dae / .jpg / .mtl)
Any ideas to load the big one ?
Thanks !
EDIT 1 :
I tried to put a breakpoint in the SuccessCallback to see if the overload of RAM is during the load or after. I was not able to hit the breakpoint, so the overload of RAM is before the SuccessCallback.
Then I went step by step in the ColladaLoader to find what is using so much RAM. Here is the "callstack" :
myCollada.load()
ColladaLoader.parse()
Geometry.parse()
Mesh.parse()
Source.parse (hit 3 times) = +400mo in RAM
Vertices.parse = +0mo in RAM
Triangles.parse = +1500mo in RAM
this.geometry3js.computeVertexNormals() = RAM go over 2600Mo and chrome crash
Could I do any other tests to find the reason of this problem ?
Thanks
Your textures are waaaay to big, and besides, you don't need them because your model has baked vertex colors, which includes baked lighting. Your model therefore does not require UVs eiher.
Use ColladaLoader2, and this pattern. It should work.
var loader = new THREE.ColladaLoader();
loader.load( 'BigModel.dae', function ( collada ) {
var dae = collada.scene;
dae.traverse( function( child ) {
if ( child instanceof THREE.Mesh ) {
child.geometry.removeAttribute( 'uv' ); // you don't need it
child.material = new THREE.MeshBasicMaterial( { // scene lights not required
vertexColors: THREE.VertexColors // you have them, use them
} );
scene.add( child );
}
} );
} );
three.js r.86
Related
I have a glb model which I am loading into my Vue project via Three js. I have managed to import several other models for practice, but the one I actually want on my page will not load. I have tried playing around with different scaling, positions, background colors (since the object is mostly black), and camera angles but I am not able to get it in frame no matter what I do. I am able to see the model perfectly in any regular gltf view, but I cannot see it in my project, what am I doing wrong here?
Edit: As a side note, I also tried changing the scale in blender, but that did not change the result.
const loader = new GLTFLoader();
let me = this; // must refer to the instance in vue in order to be added to the scene, have tested this with other models
loader.load(
'pantalla_ball_2.glb',
function(gltf) {
gltf.scene.traverse(function( node ) {
if ( node.isMesh ) { node.castShadow = true; }
});
gltf.scene.scale.set(1,1,1) // Have tried several scales from 0.01 to 200
me.scene.add(gltf.scene);
console.log("added") // added is successfully called every time
},
function(xhr) {
console.log(xhr);
},
function(err) {
console.log(err); // no errors appear in console
}
);
The object loading perfectly in 3d viewer below
Thanks to JP4 for his helpful comments, the issue was the ambient lighting was not strong enough to illuminate the object sufficiently enough to be seen. The axis helpers showed me that the object was there thanks to the gaps in the axes.
I have a set of models in *.obj format that come without material files (*.mtl files). Some online services display these models correctly: https://3dviewer.net/, https://sketchfab.com/. But - according to the three.js documentation - in my project I only get an incorrect display of the model:
instead of:
The developer https://3dviewer.net/ said that the idea on this service is that if the *.mtl file is not found, then the script sets the default color / material - paints the entire product in one color.
How to color an object from a *.obj file to a selected color using three.js tools?
For testing, I attach a model file that comes without a material file: test sample *.obj file.
It seems the OBJ is not exported correctly. When using macOS preview, BabylonJS or the OBJLoader of three.js, the faces seem to have the wrong winding order. You should get the desired result by doing the following in your onLoad() callback:
const material = new THREE.MeshPhongMaterial( { color: 0xff0000, side: THREE.BackSide } );
obj.traverse( function( child ) {
if ( child.isMesh ) child.material = material;
} );
I am trying to load quite complex .3ds model into three.js using TDSLoader exactly the same way as in three.js/examples: https://github.com/mrdoob/three.js/blob/master/examples/webgl_loader_3ds.html
but what I get looks like this Result when it is supposed to look like this Loaded using https://3dviewer.net/. I can see that this online viewer uses three.js so it is possible. I also know that TDSLoader loads textures but does not map them for some reason (if I move texture out of the folder I get an load resource error). Code looks like this:
var loader = new THREE.TextureLoader();
var normal = loader.load('textures/normal.png');
var loader = new THREE.TDSLoader();
loader.setPath('textures/');
loader.load('textures/CAT_336D.3ds', function (object) {
object.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material.normalMap = normal;
}
});
scene.add(object);
});
My model has 23 types of materials but the loader loads only 2 - black and yellow, you can see that glass, metal and others are missing. How do I map all textures and materials? Maybe it does not work because the model is too big? (over 160 meshes, around 30MB)
The following has worked well for me with svg files in R76 and R77 of Three.js, but in R78 I can only get it to work with pngs and jpgs
var floor = new THREE.TextureLoader();
floor.load('layout.svg', function ( texture ) {
var geometry = new THREE.PlaneBufferGeometry(4096, 4096);
var material = new THREE.MeshBasicMaterial( { map: texture } );
var mesh = new THREE.Mesh(geometry, material);
mesh.rotation.x = -Math.PI / 2;
scene.add(mesh);
} );
Since the problem arose, I added the progress and error functions to the load arguments...
function ( xhr ) {
console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
},
function ( xhr ) {
console.log( 'An error happened' );
}
...which tells me that in r78, the svg is 100% loaded, but it doesn't show up in the scene.
I should add that I also used this with phongmaterial for the reflection properties, and with transparency to show svg elements apparently floating in a skymap, great fun.
My question is, how can I get this working?
In R77, the svg would map to a planeBufferGeometry in FF or chrome.
In R78 it wont load, no errors shown on Firebug.
UPDATE
I investigated SVGLoader.js, SVGRenderer.js (which also requires Projector.js). Renders an svg file facing camera, responds to translations, but not rotations; i.e. no perspective view possible.
I added an xml header to the svg file, then a doctype, but threejs obviously isn't bothered by their absence. Using localhost makes no difference in FF, required in Chrome
So the problem seems to lie either with TextureLoader or WebGLRenderer, which have both had quite a reshuffle in R78.
I also briefly tried the dev version, which acts as r78 does.
Can anyone suggest where I go from here? I'm not sure whether to submit a bug, or a "feature restore".
Here's the desired effect.
Now my understanding is that prior to R78, svgs were internally converted to raster images before rendering.
To continue to use svg images in R78 onwards with Textureloader, convert them to pngs beforehand.
OR if the svg always faces the camera, use the THREE.SVGLoader.
OR If the separate svg elements are required in a three.js scene, convert them to paths and use this example to make a 2d shape or a 3d extruded shape.
My lesson here was not to rely on examples to just work. I should dig right in, break things, and stay up to date with issues on Github.
And use more than one browser; at the time, Chrome was going through a buggy phase not entirely unrelated to this.
I'm currently using Three.js, version 71. I first create my models using blender, and then I export them as a JSON file. I then use THREE.JSONLoader to load the models into my scene using the following:
this.jsonLoader.load(pathToModelFile, function(geometry, materials) {
//...
});
The materials list only contains THREE.MeshPhongMaterial at index 0. This material seems to require a light source (like THREE.SpotLight for example) to be in my scene. Otherwise, my model will be black.
I basically just want to be able to load my models and not need to use a light source in order to see them. Therefore, I have the following questions, and answering any one of them would solve my problem:
Is there some flag or property in THREE.MeshPhongMaterial I could change that would allow my model to be seen without a light source?
If number 1 isn't possible, is there a way to use THREE.JSONLoader to give me a different kind of material that doesn't need a light source? For example, like THREE.MeshBasicMaterial?
Is there some way to export my models from blender that will already have the required flags/properties set (if possible)?
It sounds like I'm having the same problem that this guy mentions in the following link, but he never received an answer: Switch lighting of THREE.MeshPhongMaterial on / off dynamically
1 dont know, think not
2 yes
var jsonLoader = new THREE.JSONLoader();
jsonLoader.load(model, addthree1ToScene);
function addthree1ToScene( geometry, materials )
{
material = new THREE.MeshBasicMaterial(blahblah);
three1 = new THREE.Mesh( geometry, material );
scene.add( three1 );
console.log(three1);
}
3 yes, in Blender you can set a material type on mesh before exporting, or you can edit material variables in the exported file
EDIT:
Or most stupid way, it is possible to edit Material in expoted Json File, via discussion to this answer.