Line up Procedurally Generated Rooms

Godot Version

Godot 4

Question

Hey friends I’m currently having trouble lining up procedurally generated rooms that I made in Blender. As of right now, I can line up the door position of the previous room to the door position of the new room, but I cannot for the life of me rotate the new room to match the old room’s orientation.

Each door has an Node3d labeled attach point which is used to determine the rotation and position of the door. Each “buiding_block” or room has an attach point that is set to Vector(0,0,0) with a rotation of Vector3(0, 180, 0).

GodotEngineNvidiaProfile2024.09.13-17.44.25.01-ezgif.com-video-to-gif-converter

I tried setting the new room’s rotation equal to the attach point that I wanted to attach to the old room using:

instance.rotation = attach_loc.rotation
instance.global_rotation = attach_point.global_rotation

but that wasn’t working.

This is what the two attach points should look like when they are properly aligned:

but 3/4’s of the time they’re 90-180 degrees off like this:

I feel like there is a piece of math that I’m missing and it should be super easy to figure out. Here’s the rest of the code:

func set_block_location() -> void:

	var attach_point : Attach_Point = pick_random_attach_point()
	var instance : building_blocks = block[0].instantiate() #.pick_random().instantiate()
	var attach_loc : Attach_Point = instance.attach_points.pick_random()
	attach_loc.taken = true
	blocks_container.add_child(instance)
	
	instance.rotation = attach_loc.rotation
	instance.global_rotation = attach_point.global_rotation
	var distance = (attach_point.global_position - attach_loc.global_position).length()
	var new_position = distance * (attach_point.global_position - attach_loc.global_position).normalized()
	
	instance.global_position = new_position

Only looked at your code briefly (sleep is calling me) but are you missing the rotation difference?

To rotate the new room so that its attach point lines up with the attach point from the previous room, wouldn’t you need to calculate the difference between their orientations and then apply that to the instance?

If your only copying over the global rotation like this:

instance.global_rotation = attach_point.global_rotation

You’re not adjusting for the fact that the attach points on each room may not be oriented the same way. For example:

One room might have its attach point facing north (positive Z).

The other room might have its attach point facing east (positive X).

Sorry if that makes no sense, or if I’ve not read the code right, I’m tired :joy: feel free to let me know if you want me to clarify anything I’ve said.

Hm I tried this earlier, but was still having problems.

When I find the difference of the two attach points using this code:

instance.global_rotation = attach_loc.global_rotation - attach_point.global_rotation

it’ll work when either the instance or the attach point is 90/-90 degrees, but when both the instance, and attachpoint is 180/-180 or 0 degrees it will overlap the previous room like so:

We’re so close yet so far.

The most painful part is that I’ve done this before, just in unity, so that knowledge doesn’t really apply very well here :sob: I’ll have another look if you or someone else hasn’t figured it out by the time I wake up tomorrow, and see if I can’t help a little more.

1 Like

Ok, I’ve been thinking, and I feel like the problem definitely comes from how the relative rotation is being handled.

Have you tried using looking_at() rather than manually finding the difference? Something like:

instance.global_transform = instance.global_transform.looking_at(attach_point.global_transform.origin, Vector2.UP)

Not sure if that’ll do it, but I’d say it’s worth a try.

That seemed to give the instance some really weird rotations. Sorry, I came from Unreal Engine, so I’m having a hard time wrapping my head around all these new concepts that come packaged with unreal lmao. Thanks for helping me find new methods though.

Okay, I figured it out. The problem was finding the inverse of 0, and 180 the instance wouldn’t invert itself by multiplying it by a -1 value so we would need to calculate the difference of the two points and add 180 by it to ensure both 0, and 180 would be inverted.

instance.global_rotation_degrees.y = (attach_point.global_rotation_degrees - attach_loc.global_rotation_degrees).y + 180

Thank you for helping me figure that out Kyanberu!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.