three.js: loading svg with textureloader not working since r78 - javascript

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.

Related

Three JS GLTFLoader is faulty with vue

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.

Three.js: flip image loaded with loadTextureCube

I have a legacy code snippet that has long since been part of a web application. The goal is to render a cube from 6 image urls via three.js. The problem is, that the bottom image is flipped around on its y axis. All other sides look fine.
There is no way to flip the original image, since they are provided by an external service. Also when I open the bottom image directly, it is displayed correctly, only in the three.js cube its flipped.
Since I have no prior experience with three.js, I first looked at the documentation for this functionality and realized that the code used in our script is deprecated. unfortunately there is no detailed documentation of the old function (THREE.ImageUtils.loadTextureCube) - or I was simply unable to find it (if someone knows where it is, a link would be great!).
I know that for the long term, a reimplementation to replace all deprecated functions would in order, but since this would take a lot more time (for someone unfamiliar with three.js), I first wanted to check if the problem can be fixed using the existing code base.
I read in various other posts/issues that this is a known issue because three.js for some internal reason defaults to flipY=true on textures. The problem I have is that I don't know (due to lack of documentation) how to change this parameter on one side of the cube only. I expect a function can be applied to the loader that could update this parameter for one of the images or a transformation could be applied to the loaded image afterwards.
I really hope somebody knows (remembers) how this can be achieved with the old loader function.
The following partial code is from my script:
// passed list of urls (images.bottom is flipped around)
var urls = [ images.left, images.right, images.top, images.bottom, images.back, images.front ];
// SCENE
scene = new THREE.Scene();
// TEXTURES
textureCube = THREE.ImageUtils.loadTextureCube( urls );
textureCube.format = THREE.RGBFormat;
textureCube.mapping = THREE.CubeReflectionMapping;
// MATERIALS
var cubeShader = THREE.ShaderLib[ "cube" ];
var cubeMaterial = new THREE.ShaderMaterial( {
fragmentShader: cubeShader.fragmentShader,
vertexShader: cubeShader.vertexShader,
uniforms: cubeShader.uniforms,
depthWrite: false,
side: THREE.BackSide
} );
cubeMaterial.uniforms[ "tCube" ].value = textureCube;
var cubeGeometry = new THREE.BoxGeometry(50,50,50);
cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
scene.add( cube );
// RENDER
renderer = new THREE.WebGLRenderer();
renderer.autoClear = false;
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( containerWidth, containerHeight );
renderer.setFaceCulling( THREE.CullFaceNone );
$container.append( renderer.domElement );
...

Texture not displayed on object Forge Three.js

I am trying to display a textured plane with Three.js. I'm working with Forge RCDB.
At first, I managed to display the plane, but instead of being textured, it was completely black... I made some changes and now nothing is displayed anymore...
Here is my code :
render () {
var viewer=NOP_VIEWER;
var scene=viewer.impl.scene;
var camera = viewer.autocamCamera;
var renderer = viewer.impl.renderer();
renderer.render( scene, camera );
}
and in the function supposed to display the textured plane :
new THREE.TextureLoader(texture).load(texture, this.render);
tex.wrapS = THREE.RepeatWrapping //ClampToEdgeWrapping //MirroredRepeatWrapping
tex.wrapT = THREE.RepeatWrapping //ClampToEdgeWrapping //MirroredRepeatWrapping
tex.mapping = THREE.UVMapping
At the beginning I used loadTexture(). I managed to display my plane, but it was all black, and no texture was applied on it.
Then, I use THREE.TextureLoader().load(), in this case, I believe it is trying to find the image on localhost. The image is downloaded, I can see it on the console.
But now I get these errors :
Uncaught TypeError: scope.manager.itemStart is not a function
and :
Uncaught TypeError: renderer.render is not a function
Now the object is not displayed, even in black.
So I think this may be linked to render, but I don't understand how...
I found this, and it answers my question partially.
Finally, I decided to keep THREE.ImageUtils.loadTexture(), and I replaced MeshLambertMaterial by MeshBasicMaterial.
No need for render.

Render heavy model / mesh on three.js

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

How to texture animated js model exported from blender ? [Three.js]

I have successfully animated a model in blender using bone animation technique and i have also textured it in blender using uv texturing. Then Using three.js export add-on in blender i have exported the model making sure uv and animation in checked in. However i don't know the technique to load the texture for the animated model. I viewed the morph normal example included in three.js where there is simple color texture is used using Lambert material. I have texture from external file. How do i load the texture. In js animated model file there is location for the texture and it is in same location. But it doesn't load. i used the face material technique as well.
the location for three.js example that i used to modify:
http://threejs.org/examples/webgl_morphnormals.html
Here is my code:
var loader = new THREE.JSONLoader();
loader.load( "bird_final.js", function( geometry, materials ) {
morphColorsToFaceColors( geometry );
geometry.computeMorphNormals();
// the old code to set color to the model
//var material = new THREE.MeshLambertMaterial( { color: 0xffffff, morphTargets: true, morphNormals: true, vertexColors: THREE.FaceColors, shading: THREE.SmoothShading } );
// my code
var meshAnim = new THREE.MorphAnimMesh( geometry, new THREE.MeshFaceMaterial( materials ) );
meshAnim.duration = 500;
meshAnim.scale.set( 20, 20, 20 );
meshAnim.position.y = 150;
meshAnim.position.x = -100;
scene1.add( meshAnim );
morphs.push( meshAnim );
} );
Except the documentation and some basic tutorials scattered across the web, is there anywhere i can learn three.js from ground up. like i know setting up scene and creating basic geometry stuffs but some detail info like loading textured model loading scenes etc.
I have created a series of commented examples for Three.js that illustrate features one at a time, starting with very basic features and progressing to more advanced ones (including loading models).
http://stemkoski.github.io/Three.js
Hope this helps!
Working with complex geometry, materials, textures, and animations are some of the hardest things to figure out in THREE.js - that's why we started there with our editor.
We make all of these easy. Export an FBX file (or OBJ/MTL, or Collada) from Blender. Bring it into a project in Verold Studio, then load it into your THREE.js program using our loader. Service is free for use, you pay us if you want enablement services or have a client who wants a maintenance/support agreement.
See the example below, couldn't be easier to bring your scene to THREE.js,
http://jsfiddle.net/rossmckegney/EeMCk/
// 1. Set and then start the animation :)
this.model.setAnimation("mixamo.com");
this.model.playAnimation(true);
//this.model.pauseAnimation();
// 2. Get the threedata for a model
console.log(this.model.threeData);
// 3. Move the model
this.tweenObjectTo(
this.model.threeData, // the model
new THREE.Vector3(1, 0, 0), // go to
new THREE.Quaternion(), // rotation
1, // time, in seconds
false, // smooth start
true); // smooth end
// 4. Clone the model
that = this;
this.model2 = this.model.clone({
success_hierarchy: function(clonedModel) {
that.veroldEngine.getActiveScene().addChildObject(clonedModel);
}
});

Categories