Skip to main content

The First Concave Prisms

·717 words·4 mins

Drawing the Curve
#

Been a while but I’m finally making my concave / convex prism dreams come true! Here’s some debug art.

And here’s a drawing of the concave prism.

I’ve been following a pull request for 2D Constructive Solid Geometry nodes in Godot. Here it is: https://github.com/godotengine/godot/pull/99911

At first I thought this is exactly what I need for my lens prisms. I could create circles and a rectangle and then add or subtract them from each other to get the desired shapes.

Then I realized it was still going to bake down to a polygon. My concern there is that when the player moves the prism around in the laser beam there will be jumps in angle rather than a continuous change in angle. The curve needs to be perfect because the laser beams shooting out from the prism will betray any imperfections.

Besides, that PR is still under some debate. So maths to the rescue!

Refracting the Light
#

Okay, now for the hard part.

Looks like the only information I really need is the object that collided, the collision point, and the collision normal. That makes sense. It’s complicated a little bit by the fact that I have a reverse ray cast for when a beam is exiting a prism.

I’ll need to override the collision point and normal in both cases.

Alright. The happy path is working. The one lovely case where there are intersections with the bounding rect that foretell intersections with the arc. That way, I can detect intersections with the bounding rect and if they exist then I manually detect the intersection with arc and used that instead.

Great.

But then there are cases where the ray originates from inside the bounding rect and those collisions go undetected. Sad face.

I could maybe always check for collisions if it’s an internal ray. But I can imagine situations where this happens with an external ray. Let’s see if I can cook it up.

Oh right. It won’t let me.

So that points me in the direction of one possible solution. I just need to update my collision polygon to be closer to the reality. It’ll be accurate enough to detect collisions with other prisms correctly and to detect when a laser hits it. It’s not going to be accurate enough to send the reflected or refracted ray in the correct direction but I’ve got that solved already.

Yeah, there we go. Look at this beauty.

The laser beam originates from inside the bounding rect but it still collides with the prism and casts an internal ray.

This case is working now, too, looks like. Laser from the side.

I feel like this is not yet working, though?

That’s kinda interesting. It’s because I’m doing a reverse cast to determine the exit point and instead of getting the first exit point, I’m getting the last one.

It’s highlighted by the white circle here:

The reason I did a reverse cast in the first place is because there’s no way to detect when a ray stops colliding with a CollisionObject2D. You can only detect when it starts colliding.

I could model the inverse of the prism. Then when the ray collides with the inverse I know it’s an exit.

I’m doing some of my own collision detection anyway so another possibility is to implement my own collision check for internal rays. I could even use the exit point determined by the reverse cast as the far limit, then search for other exit points between that and the entry point.

Or I guess just calculate the intersection between the ray and the circle and if it’s present then that’s the exit point. That’s the way.

Question then is how to integrate it with the current implementation.

Currently Laser is responsible for determining the collision points with any shape and up until now, one-size-fits-all has been fine. But now I need to use different techniques depending on what the Laser collided with so the logic for determining the exit point should be on the prism. I’m only ever shooting lasers so that’ll be good enough. If the exit point logic is on the prism, should the entry point logic be there, too?

I could also just use different logic for convex vs. concave shapes.