tl;dr: Skip to My consideration and My questions.
The goal
I want to write a function that lets me place models on surfaces. The model is placed at a given location with an orientation that aligns with both the orientation of the surface, and the direction that the player (who is placing the model) is facing.
However, a location for a model may be rejected if:
- Part of the model clips into the ground or a wall.
- Part of the model reaches over a cliff.
- The slope of the surface is too steep.
So the following 3 examples should all be rejected:
The situation
The space in which models may be placed contains many surfaces with irregular elevations and orientations. Below is an example of what an irregular surface may look like:
The elevation between the left and right half of this surface differs not too much, but there is a small but very very steep slope right in the middle of it. If I were to place a model that aligns with the surfaceâs normal right in the middle of that surface, it will be rejected as per condition 1. (Part of the model clips into the ground or a wall)
Unfortunately, the space in which models may be placed has many of those locations where a naĂŻve algorithm that aligns a model with the surfaceâs normal, would lead to rejection. This happens, for example, through little rocks on the surface or stairs that would cause the model to clip into its steps. So using a naĂŻve algorithm that aligns a model with the surfaceâs normal would lead to bad user experience.
However, a smarter algorithm might detect that the area surrounding the model is on average flat enough to place the model in such a way that it passes all 3 conditions:
In this example, the model does not clip into the ground or a wall. It does not reach over a cliff, and it also does not rest on a steep slope. This is the kind of algorithm I would like to write.
My consideration
- First I would need to find the location for the model and check if there is enough space. I could do this by casting a ray down vertically (for the location) and 4 other rays diagonally to check if it does not hit a surface too far up or down. Visual representation:
- If all rays have hit a BasePart, I would construct a new (virtual) plane to place the model on using the 5 positions returned by the 5 rays. Visual representation:
- Finally, I would check if the slope of this virtual surface is not too steep, and then I would align the model on this virtual surface such that it faces the same direction as the player.
Unfortunately this algorithm does have its flaws. For example, if one of the rays in step 1 returns a location that is only slightly higher up than the others, there is no good way of knowing if this means that the ray hit a wall, or if the surface is slanted. You could check the direction of the returned normal as well, but then you run into the problem where models may not be placed on e.g. stairs, because the algorithm treats the side of a step as a wall.
My questions
That all being said, I have a couple of questions:
a. Is this a smart way of tackling the problem, or is there a better approach that I am missing?
b. If this approach is fine, how would I execute the second and third step of my algorithm? (Constructing a plane using the 5 given locations, and aligning the model on this surface, facing the same direction of a player)