I perform a trace and when it hits the world I get a location and the surface normal. Does anyone have a good way to find out if I hit a wall or a floor?
3 Answers
What Thomas said in his comment: the surface normals on the floor are pointed up, while the walls are pointed sideways.
(I'm leaving my response about the dot product because that will work too and helps explain how to work with 3D vectors, but phillips comment points out a simpler approach I didn't think of)
Just check the normal's Z component. So, if you wanted "floors" to be surfaces with normals < 45°, you could check if the Z value is > 0.707 (because sin(45°)=0.707). In fact, this is how Unreal checks if the Pawn is on a "floor" -- it compares the floor's normal Z value to WalkableFloorZ, which is 0.7 by default.
What you should probably do is get the dot product of the surface normal and a vector pointed straight up: if the trace crossed the floor then the dot product will be near 1, while if it was a wall then the dot product will be near 0, and if it was the ceiling then it'll be near -1
The threshold of how near is a value you can tune to see what works for your level:
var threshold = .1;
if (abs(1 - dotProduct) < threshold) {then...
-
\$\begingroup\$ Ah, I was looking at the wrong way. I was using the surface normal with the dot of the current orientation of the camera. Using the an up vector make much more sense. Thanks \$\endgroup\$– JackCommented Sep 25, 2012 at 2:49
-
1\$\begingroup\$ That will work. However, it would be cheaper to check the normal's Z component. So, if you wanted "floors" to be surfaces with normals > 45°, you could check if the Z value is > 0.707 (because sin(45°)=0.707). In fact, this is how Unreal checks if the Pawn is on a "floor" -- it compares the floor's normal Z value to WalkableFloorZ, which is 0.7 by default. \$\endgroup\$– PhillipCommented Sep 25, 2012 at 22:16
Without knowing more about your implementation, a simple way to determine if you're hitting a wall or a floor is by taking the direction your body is moving into consideration.
- If you're moving left or right, and a collision occurs, then you've hit a wall.
- If you're moving or falling down, and a collision occurs, then you've hit a floor.
So you can use the velocity of your entity to determine the nature of the collision.
-
-
\$\begingroup\$ He said he's performing a trace, so there is no body in motion. \$\endgroup\$– jhockingCommented Sep 25, 2012 at 0:18
As "Zack The Human" said, you should consider which way your character is moving. Another idea is to check which side of your player/object collided. If the bottom of your character collide you either hit the floor or an object you can stand on. Another method is to provide a pointer/reference to the object you collided with and conclude from that what you collided with.
Each of them has there perks in different situations, and they can all be implemented together. For example if I'm making a platformer I check the direction my player is moving and where the object I collided with is located. This way I can conclude if my player was moving down and collided with an object under it, that is hit the floor or a platform. Same goes for walls, if my player is moving left and hits an object to the left of it, stop moving left.
You should really learn 2D before 3D. Its easier to learn the concepts.
programming
when I asked. Though it's still fairly vague. \$\endgroup\$