ThreeJS - delineate between meshes - three.js

I am displaying a number of different models simultaneously in three.
Some models have the same texture, and it can make it hard to tell where one starts and another ends.
As an example, first image is from my three viewer, second image is from Blender:
It is not obvious in three where the two objects intersect.
I've so far attempted to alter lighting and material settings but have been without success on that front.
I also tried an outline post processing effect but due to what I think is a disorderly output from Sketchup (where the models were made) the outline effect is chaotic:
I am trying to find a good way to clearly delineate between models.

Raycaster from mouse position. De-emphasize the other models' opacity or something. Or if you're serious, you could try the clipping stencil. There's some really good examples for mesh BVH that demonstrates this. https://gkjohnson.github.io/three-mesh-bvh/example/bundle/clippedEdges.html

Related

three.js filling gaps between edges

I created a model in Blender of a block with a hole in it:
I export it as an .obj file, and import it in ThreeJS with the OBJLoader add-on.
When I use it in my app, it appears to draw a face over the sides of the hole:
Is there a setting I need to use in ThreeJS to avoid having it close over gaps like this? Or is the problem in how I'm creating the model? I'm totally lost here, any guidance appreciated.
EDIT: I discovered through trial-and-error that the problem is having irregularly-shaped faces, like the ones adjacent to the hole. I "solved" my problem by triangulating the model; while this changes its shape slightly, it ensures that every vertex in the hole is part of a triangle face, which seems to be the magic answer.
I'm still very curious about why this is, especially since the triangulation has made the corners of the box a bit weird.
EDIT 2: Sorry for the delay. Here's the blender file: https://gofile.io/?c=EoxH1r
The problem you are having is because of ngons (polygons with more than 4 sides).
Modelling for three.js is just like modelling for games, so it is best to avoid polygons with more than 4 sides because when the renderer (or video card, I dunno) tries to render the model, it has to apply triangulation and may do it in an unexpected way.
As you said, applying triangulation to the model fixed the issue, but automatically applying triangulation in your modelling app may also yield unexpected results. So your best bet is to alter the model so you get the results you expect.
Here is a youtube video I found that seems to explain a lot about ngons.
https://www.youtube.com/watch?v=BjnCV2PIkKA
(though I only watched the first minute or so)
Here is an example of how I would do it, red lines representing added edges. Remember to do it all the way around on both sides and apply your smoothing groups before exporting.

Transparency with complex shapes in three.js

I'm trying to render a fairly complex lamp using Three.js: https://sayduck.com/3d/xhcn
The product is split up in multiple meshes similar to this one:
The main issue is that I also need to use transparent PNG textures (in order to achieve the complex shape while keeping polygon counts low) like this:
As you can see from the live demo, this gives really weird results, especially when rotating the camera around the lamp - I believe due to z-ordering of the meshes.
I've been reading answers to similar questions on SO, like https://stackoverflow.com/a/15995475/5974754 or https://stackoverflow.com/a/37651610/5974754 to get an understanding of the underlying mechanism of how transparency is handled in Three.js and WebGL.
I think that in theory, what I need to do is, each frame, explicitly define a renderOrder for each mesh with a transparent texture (because the order based on distance to camera changes when moving around), so that Three.js knows which pixel is currently closest to the camera.
However, even ignoring for the moment that explicitly setting the order each frame seems far from trivial, I am not sure I understand how to set this order theoretically.
My meshes have fairly complex shapes and are quite intertwined, which means that from a given camera angle, some part of mesh A can be closer to the camera than some part of mesh B, while somewhere else, part of mesh B are closer.
In this situation, it seems impossible to define a closer mesh, and thus a proper renderOrder.
Have I understood correctly, and this is basically reaching the limits of what WebGL can handle?
Otherwise, if this is doable, is the approach with two render scenes (one for opaque meshes first, then one for transparent ones ordered back to front) the right one? How should I go about defining the back to front renderOrder the way that Three.js expects?
Thanks a lot for your help!

Create floor with dynamic soft reflections

Using three.js am trying to create a floor that reflects the objects that sit upon it. Preferably the floor material should reflect not like a mirror but in a more 'matte' or diffused way.
To achieve this I looked to Jaume Sanchez Elias who has made a great example using a cube camera: Look for the "smooth material" example on this page:
http://www.clicktorelease.com/blog/making-of-cruciform
Here is my attempt using the same technique. But as you see the reflections are misplaced, they do not appear underneath the mountain objects as expected.
http://dev.udart.dk/stackoverflow_reflections/
I am looking to correct this or to use any other technique that will achieve a more correct diffused reflection.
There are three.js examples using the cube camera technique but they all create mirror-like effects not a soft reflection.
Vibber. Parallax-corrected cubemaps, the technique used in cru·ci·form, only works for closed volumes, like cubes. It works really well to simulate correct reflections inside a room, but not so much for outdoors or open/large scenes. They also can't reflect anything that it's inside the cubemap, you'd have to split the volume in many sub-volumes.
I can think of a couple of solutions for what you want to achieve:
SSR: Screen-space reflections, you can find more info in many places on the internet. It's not the most trivial of effects to implement, and you might have to change the way you render your scene.
Simpler post-processing approach: since you have a flat floor, render the mountains vertically flipped on a framebuffer object, blur it, and render the regular scene on top. For extra effect, render the depth of the flipped mountains, and use that value as the blur radius, to get diffuse reflections.
As always, there's a ton of ways to achieve the (un)expected result :)

What is the most efficient way in three.js to update a face color independently across many meshes that all share the same geometry?

In a three.js project (viewable here) I have 500 cubes, all of the same size and all statically positioned. On each of these cubes, five of the faces always remain the same color; however, the color of the sixth face can be dynamically updated, and this modification occurs across many of the cubes in a single frame and also occurs across most frames.
I've been able to implement this scene several different ways, but I have not been completely satisfied with the performance of anything I've tried. I know I must not have hit upon the right technique yet or maybe I'm not implementing one quite right. From a performance standpoint, what is the best way to change the color of these cube faces while maintaining independence across each of the cubes?
Here is what I have tried so far:
Create 500 individual CubeGeometry and Mesh instances. Change the color of a geometry face as described in the answer here: Change the colors of a cube's faces. So far this method has performed the best for me, but 500 identical geometries seems less than ideal, especially because I'm not able to achieve a regular 60fps with a good GPU. Rendering takes about 11-20ms here.
Create one CubeGeometry and use it across 500 Mesh instances. Create an array of MeshBasicMaterials to create a MeshFaceMaterial for each Mesh. Five of the MeshBasicMaterial instances are the same, representing the five statically colored sides of each cube. Create a unique MeshBasicMaterial to add to the MeshFaceMaterial for each Mesh. Update the color of this unique material with thisMesh.material.materials[3].uniforms.diffuse.value.copy(newColor). This method renders quite slower than the first method, 90-110ms, which seems surprising to me. Maybe it's because 500 cubes with 6 materials each = 3000 materials to process???
Any advice you can offer would be much appreciated!
I discovered that three.js performs a WebGL draw for each mesh in your scene, and this is what was really hurting my performance. I looked into yaku's suggestion of using BufferGeometry, which I'm sure would be a great route, but using BufferGeometry appears to be relatively difficult unless you have a good amount of experience with WebGL/OpenGL.
However, I came across an alternative solution that was incredibly effective. I still created individual meshes for each of my 500 cubes, but then I used GeometryUtils.merge() to merge each of those meshes into a generic geometry to represent the entire group of cubes. I then used that group geometry to create a group mesh. An explanation of GeometryUtils.merge() is here.
What's especially nice about this tactic is that you still have access to all the faces that were part of the underlying geometries/meshes that you merge. In my project, this allowed me to still have full control over the face colors that I wanted control over:
// For 500 merged cubes, there will be 3000 faces in the geometry.
// This code will get the fourth face (index 3) of any cube.
_mergedCubesMesh.geometry.faces[(cubeIdx * 6) + 3].color

Outline rendering of transparent cylinders

I am trying to render cylinders for a CAD-like project. As multiple of these will be nested in each other, I am looking to display them similar to this: http://mrwadeturner.pbworks.com/f/1305815353/FC_Cylinder_41702_lg.gif
i.e. I want the outline and the base and bottom circles traced out and the rest should be (semi-)transparent.
Note that this is different from using regular wireframe settings, because that will trace out every face of the sides of the cylinder. The other approach I found - rendering the object twice, once in color and slightly enlarged and once it "regular" version on top - unfortunately won't work either, since multiple cylinders will be nested.
I think this should be possible with custom vertex and fragment shaders, but I am not very proficient in using them. What would be the best way of achieving this effect?
Thanks a lot!
Sound like you just need to apply various textures to the same faces. Next you want to try to create custom texture that is going to be a simple transparent .png image with solid dashed border. Then you'll have to set side:THREE.FrontSide and side:THREE.BackSide to your textures and play around with depthTest.
Another approach is to use lines that you age going to create vertex-by-vertex. See this example for custom line implementation: Hilbert curve and Shapes generation
Hope that helps!

Resources