How to detect the lines based on their distance to camera?

Hello Babylon experts!

Let’s say we have a non-standard 3D shape. As we rotate the camera, is there a way to show the lines which are in front of the camera as solid and the ones in the back as dashed?

The pictures below tries to show how the lines should look like as we rotate the camera:
pic

I tried dozens of ways but no luck so far. Here’s an example of a basic shape.

https://www.babylonjs-playground.com/#S7NDM3#1

Any help would be greatly appreciated!

2 Likes

Welcome on this forum :slightly_smiling_face:
I would say that the best approach would be a dedicated shader in your case. I wish some shader experts can show you a demo.

3 Likes

I think you can just draw faces that are pointing away from the camera with dotted lines.

Use the dot product of the camera direction and the face normal.

Edit: nope, this won’t work when a shape overlaps itself.

I wonder if you can do something similar to what the bounding box renderer does.

2 Likes

Thanks you so much for your suggestion. This seems very promising. I am working on it to see if I can apply the same approach to my problem.

1 Like

I still can’t figure out a way to do this. Any other suggestion/ideas ?

You could always hide the border lines of the shape - and then write a function to redraw the lines, using the vertices from the shape. Would be a bit of work to write that function, but should all work.

in pseudo code:

  • detect which face is closest to the camera
  • get all faces and their vertices
  • redraw lines as solid for those faces that are facing the camera
  • redraw lines as dotted, for all others.

Which part are you having problems with? Detecting which face is closet? Or displaying the border lines?

How can I detect faces which are closest to camera?

I could imagine a couple of different ways to do it, depending on the effect you’re trying to achieve. Two ways I might approach it are one, by setting an invisible plane at some point in front of the camera and then as the object is rotated around whichever faces are colliding with the plane are those you could consider facing the camera. The second way would be to send out a ray or multiple rays from the camera towards the object …

Thanks for your suggestion. I already tried similar approaches to those you suggested. They seem practical at first but once I dig deeper, each shows some sort of shortcomings given the complexity of shapes as they are generated randomly. There always some small faces that won’t collide with the plane or the ray.

Did you try a strobing ray?

Or you could take the normals from each of the corners of the faces and determine a minimum angle pointing towards the plane of the camera that represents “facing”

No, I haven’t done so.

Thanks, do you know of any similar sample I can take a look at?

Yea, try this for ray casting. In this case, you would spin the ray caster source programmatically and fast… (rather than via mouse as in this demo) so that it’s hitting any face facing it. And of course, you’d only have select the first face it hits, rather than every face.
https://www.babylonjs-playground.com/#KNE0O#241
https://doc.babylonjs.com/babylon101/raycasts

As for normals, just came up with that idea, so haven’t seen it done… but i’m pretty sure it’d work! here’s a good playground to visualize them.
https://www.babylonjs-playground.com/#1ENDNT#9
And doc: Show Vertex Normals - Babylon.js Documentation

I’d think that any face with each of its normals facing the plane of the camera at 90degrees is 100% facing the camera. And then you could make some adjustment + or - 90degrees to accommodate a face that is mostly facing the camera…

This is kind of equivalent to sending out a ray from each of the corners of each face to a plane in line with a camera… And if the Ray hits the plane at 90, voila

Thank you for your suggestion. I updated the playground with a ray caster. I also show vertex normals on one of the lines.

https://www.babylonjs-playground.com/#S7NDM3#2

There are some points to consider given my circumstance. The objects in the playground you shared are simple meshes like a box. But I am dealing with a series of lines attached together that forms a shape. This can be seen in my playground. Fortunately, I have functions in my code to detect the faces but still its kinda of different as compared to a single shape. As you see in the photo, rays may hit surface with red color but they cannot hit blue and green surfaces since they not in the same axis.

jpeg

Oh i see. The problem is a bit different than just drawing solid lines for any face facing the camera, right? You actually need to be able to draw solid lines for the border or partial border that is not occluded by another face.

Given the need to draw partial lines - i think that means you need to take a point by point on the line approach. Got it. So, I think i’d try sending out a ray from every point on every line towards the plane of the camera. And if it hits anything on its way to the camera, it draws as dotted, otherwise it draws as solid.

Yeah, there are a lot of issues which relates to the shape of the mesh and off course these shapes are randomly generated. I made a simple screenshot of how rotation works. The four stages of the shape I shared in the first post are a clear example of this. Notice how solid and dashed lines need to be changed.They may also be holes/semi holes in the mesh. One issue is that the ray cast approach currently only works in one axis. I think I need something like a 3D ray caster to cover left/right side or top/bottom of the shape as well. In the images in the first post, you will see front, top and right side but consider a situation that the shape is rotated in a way you see front, bottom and left side. Since the object can be freely rotated, any combination should be possible. There are two problems:

  1. Given the fact that the shape is actually a series of connected lines, how to detect the borders that are facing the camera (lines that are in front of others)?

  2. How to partially render those lines with dashed/solid lines if it is an edge case.

Thank you for your suggestion but I think there should be a better way than sending out a ray from every point on every line. There may be other approaches to this like using multi material or LOD but I am not sure if they can help in this situation.

Gotcha. Well, i’m beginning to like Jerome’s suggestion from the outset then… a shader that you could apply as a material to each plane that converts any solid lines beneath it to dotted lines…

1 Like

hi
let me check it
but for clear the main question

this is result we need?