Exporting Textures with Offsets to GLTF from Three.js Scene - javascript

EDIT:
I had a question about exporting to obj and mtl but discovered that I could export from three.js using GLTFExporter.js and had success getting the geometry and texture out of three.js from that.
The issue I'm having with the GLTF Exporter is that I have textures that have offset and repeat settings that seem to not be exported from three.js when I open the file in Blender. In Blender the whole texture takes up the MeshPlane that used to only have a small part of the texture showing in Three.js scene.
Might anyone know what I could add to the GLTF Exporter to be able to record and keep the repeat and offset texture settings?
Many Thanks :)

I've hit this myself.. and as far as I know, the answer is No.
Offset and Repeat are THREE.js specific features. Some other libraries have equivalents.. some engines use direct texture matrix manipulation to achieve the same effect.
One workaround is to modify your models UV coordinates before exporting to reflect the settings of texture.offset and texture.repeat.
You would basically multiply each vertex UV by the texture.repeat, and then add texture.offset. That would effectively "bake" those parameters into the model UV's, but then would require you to reset .repeat and .offset back to 1,1 and 0,0 respectively, in order to render the model correctly again in THREE.js.
Here's a slightly relevant thread from the GLTF working group:
https://github.com/KhronosGroup/glTF/issues/107

Related

THREE.js FBXLoader treats .png as if it is a .psd, and doesn't load the material

When using the THREE.js FBXLoader to load a .fbx file, it is loading the model partially, with the alpha textured parts of the model not being loaded.
I am getting the error:
FBXLoader: PSD textures are not supported, creating empty placeholder texture for pinebranchColor.psd
Despite there being no .psd files in the materials folder. As you can see from the below screenshot, it seems to think that in the material alphaMap, the texture name is pinebranchColor.psd.
This is what the FBX model is being rendered as:
And this is what it renders as if I load the GLTF version (note: the transparent parts for the leaves are not picked up as transparent) - which is closer to how it should look, but not fully.
This is how the model is supposed to look, according to sketchfab :
Why do you think it says the alpha material is a .psd? Could this be as referenced in the .fbx file itself? The original problem was how do I get the alpha/transparency for the leaves to render correctly, rather than as block colour. Maybe I could set a property in the THREE.js material of the GLTF version and that would work?
This is the first model I have ever imported into THREE.js as I have just started learning, so please explain as best you can.
EDIT:
In dev tools I found a material for the leaves, and set transparent to true. This worked! To an extent. But there are still some rendering issues. So I think this is the route to go down.
I'm not sure why the FBX alpha material could not be loaded, but I solved the transparency problem with the GLTF version by using the THREE.js scene.traverse function, and setting the material transparent property to true, for all leaf materials in the scene.
This solved the core issue, but there were still some artifacts as seen in this picture, where leaves behind are blacked out:
The solution was to also set alphaTest to 0.5 on the material, giving this result:
Here is the code:
gltf.scene.traverse(child => {
if (child.isMesh && child.name.includes('leaf')) {
child.material.alphaTest = 0.5;
child.material.transparent = true;
}
});

three.js Raycaster does seem to work on the basis of the first key frame of animation all the time

Raycasting selection is working fine for my project on static meshes, however for animated meshes the ray selection doesn't seem to see the movement of the mesh and only responds to the mesh's non-animated (original) position.
This is an animated model that can only pick up the pose state below the first frame and creates a small red dot when I detect the model
The bones matrices are computed by the CPU, but the new vertex positions are computed by GPU.
So the CPU has access to the first pose only.
That's why RayCasting does not work (properly) for skinned meshes.
My idea is to update the model position when updating the animation, or use GPU calculations to get the location, but I don't know how to do it. I'm looking forward to your suggestions. Thank you.
Static model
Animated model
jsfddle view
Currently, raycasting in three.js supports morph targets (for THREE.Geometry only) by replicating the vertex shader computations on the CPU.
So yes, in theory, you could add the same functionality to support raycasting for skinned meshes for both THREE.Geometry and THREE.BufferGeometry. However, a more efficient approach would be to use "GPU picking".
You can find an example of GPU picking in this three.js example. In the example, the objects are not animated, but the concept is the same.
three.js r.98

Get modified mesh displaced by displacementMap in three.js

I am trying to get back and export the mesh that is being displaced by a displacementMap.
The shader is transforming vertexes according to this line (from
three.js/src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl):
transformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );
This is displacing a vertex according to the displacementMap, mixed with the uv coordinates for that vertex.
I am trying to create this mesh/geometry so that I can then later export it.
I have created a "demo" of the problem here:
Github Page
I would like the displaced mesh, as seen in the viewport, up on pressing exportSTL. However I am only getting the undisplaced plane.
I understand why this happens, the displacement only happens in the shader and is not really displacing the geometry of the plane directly.
I have not found a method provided by three.js and so far have not found any way in getting the changes from the shader.
So I am trying to do it with a function in the "demo.js".
However, I am a WebGL/three.js newbie and have problems re-creating what the shader does.
I have found exporters handling morphTargets, but these are of no help.
After reading this question I tried PlaneBufferGeometry, as this is closer to the shader - but this produces the same results for me.
I think this question originally tried to produce something similar, but accepted an unrelated question.
In the end I would like to draw on a HTML-canvas which then updates the texture in real time (I have this part working). The user can then export the mesh for 3d printing.
Is there a way three.js can give me the modified geometry of the shader?
Or can someone help me translate the shader line in to a "conventional" Three.js function?
Maybe this is totally the wrong approach to get a displaced mesh?
Update - Example is working
Thanks to the example from DeeFisher I can now calculate the displacement in CPU, as originally suggested by imerso.
If you click on the Github Page now, you will get a working example.
At the moment I do not fully understand why I have to mirror the canvas to get the correct displacement in the end, but this is at worst a minor nuissance.
To do that while still using a shader for the displacement, you will need to switch to WebGL2 and use Transform-Feedback (Google search: WebGL2 Transform-Feedback).
An alternative would be to read the texture back to CPU, and scan it while displacing the vertices using CPU only (Google search: WebGL readPixels).
Both alternatives will require some effort, so no code sample at this time. =)
BABYLON.js can be used in conjunction with THREE.js and it allows you to displace the actual mesh vertices when applying displacement maps:
var sphere = BABYLON.Mesh.CreateSphere("Sphere", 64, 10, scene, true);
sphere.applyDisplacementMap(url, minHeight, maxHeight, onSuccess, uvOffset, uvScale)
See an example of the function in use here.
You can then use a for to loop transfer the BABYLON mesh data into a THREE mesh object.

Three.js + .OBJ loading : triangular faces only?

This will concerns only polygonals faces (object's faces with more than 4 edges)..
In 3DSMAX there are 3 exporting modes for .OBJ : Triangles, Quads and Polygons.
I've made many tests and get the same results with the two available workflows (importing .obj with OBJLoader and importing .js via convert_obj_three.py) :
polygons are not supported (see this image)
quads is ok for most polygonals objects, but three.js generates additionnals parasites faces onto some of them
The best result is obtained by setting export to Triangles mode (and thus to export heavier models), is it a known problem ?
I don't think it's a known problem, but rather something threejs just doesn't do. In 3d it's easier to deal with triangles than quads or polygons. I'm not 100% sure, you might want to check on github

Background with three.js

Can anybody help me with three.js?
I need to draw background, something, like a THREE.Sprite, but it neet to be UNDER any 3d object, that will draw later. I have a camera, that can be move only on Z axis.
I tryed to use:
cube mapping shader - PROBLEM: artefacts with shadow planes, it's unstable draw
THREE.Sprite that dublicate camera moving - PROBLEM: artefacts with shadow plane - it have a edge highlighting OR drawing only other spirtes without objects.
HTML DOM Background - PROBLEM: big and ugly aliasing in models.
What can I try more? Thanks!
You could maybe try drawing in several passes, i.e. making a first render of the background scene to a buffer, and then a second one over the first "buffer". Maybe using the buffer as background (painting it in 2D with an orthographic projection, and disabling depth buffer writes in that pass).
I haven't tried it myself with three.js, but that's how I'd do that with "traditional" OpenGL.
If you want a "3d" background i.e. something that will follow the rotation of your camera, but not react to the movement (be infinitely far), then the only way to do it is with a cubemap.
The other solution is a environment dome - a fully 3d object.
If you want a static background, then you should be able todo just a html background, i'm not sure why this would fail and what 'aliasing in models' you are talking about.

Categories