Generate Points inside a rotated shape

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By fmt

Hey there. I’m trying to generate random points inside a rotated CollisionShape2D but when I rotate it It seems that it’s being rotate around the scene origin and not the shape pivot point. This is should be very simple but I’m just missing something. I’ve attached some screens of what is happening and the code.

Thanks in advanced

extends Node2D

@onready var spawning_areas = get_children()

func get_random_position():
    var index = randi_range(0, spawning_areas.size() - 1)
    var spawning_area = spawning_areas[index]
    
    var extent = spawning_area.shape.extents
    var spawn_rotation = spawning_area.transform.get_rotation()
    var origin = spawning_area.position - extent
    var spawn_area_origin = spawning_area.transform.origin - extent


    var x = randi_range(spawn_area_origin.x, spawn_area_origin.x + extent.x*2)
    var y = randi_range(spawn_area_origin.y, spawn_area_origin.y + extent.y*2)

    var return_pos =  Vector2(x,y).rotated(spawn_rotation)

    # also tried this... doesn't work...
    # return_pos.x = (cos(spawn_rotation) * (return_pos.x - origin.x) - sin(spawn_rotation) * (return_pos.y - origin.y)) + origin.x
    # return_pos.y = (sin(spawn_rotation) * (return_pos.x - origin.x) + cos(spawn_rotation) * (return_pos.y - origin.y)) + origin.y
    
    return return_pos
:bust_in_silhouette: Reply From: AlexSand

I would say you need to apply the rotation before the translation.
I also think something like this should work:

var pointInLocalCoo = SpawPoint(); // spawning in the area, without accounting for position or rotation
return spawning_area.transform * pointInLocalCoo ;

Thanks for the response. However I’ve tried both approaches (and some more) but none seem to work

Here is the updated code with the respective tries:

extends Node2D

@onready var spawning_areas = get_children()

func get_random_position():
  var index = randi_range(0, spawning_areas.size() - 1)
  var spawning_area = spawning_areas[index]

  var extent = spawning_area.shape.extents
  var spawn_rotation = spawning_area.transform.get_rotation()
  var origin = spawning_area.position - extent
  var spawn_area_origin = spawning_area.transform.origin - extent

  var x = randi_range(spawn_area_origin.x, spawn_area_origin.x + extent.x*2)
  var y = randi_range(spawn_area_origin.y, spawn_area_origin.y + extent.y*2)

  var return_pos =  Vector2(x,y).rotated(spawn_rotation)


  # also tried this... doesn't work...
  # - 1
  # return_pos.x = (cos(spawn_rotation) * (return_pos.x - origin.x) - sin(spawn_rotation) * (return_pos.y - origin.y)) + origin.x
  # return_pos.y = (sin(spawn_rotation) * (return_pos.x - origin.x) + cos(spawn_rotation) * (return_pos.y - origin.y)) + origin.y

  # - 2
  # var return_pos =  Vector2(x,y)
  # return_pos -= origin
  # return_pos = return_pos.rotated(spawn_rotation)
  # return_pos += origin

  # - 3
  # var return_pos =  Vector2(x,y) * spawn_area.transform
  # and
  # var return_pos =  spawn_area.transform * Vector2(x,y)

  # - 4
  # var x = randi_range(0, extent.x*2)
  # var y = randi_range(0, extent.y*2)
  # var return_pos =  spawning_area.transform * Vector2(x,y)


  return return_pos

fmt | 2023-04-09 19:57

Figured it out, the problem was that I need to account for where the pivot of the shape is. When I pick a point in the shape, the start needs to be the TOP-LEFT corner of the rectangle, and the end is the BOTTOM-RIGHT corner of the rectangle. So this is wrong:

var x = randi_range(0, extent.x*2)
var y = randi_range(0, extent.y*2)

as this was only correct if the pivot of the shape was on the TOP-LEFT corner, which is not the case, since the pivot is at the center of the shape.

As a result, I needed to change it to:

var x = randi_range(-extent.x, extent.x)
var y = randi_range(-extent.y, extent.y)

then you just need to apply the transform as you mentioned:

var return_pos =  spawning_area.transform * Vector2(x,y)

Quick extra question, since I was not able to find anything helpfull in google/godot docs…
Is there anyway to define/change the pivot of a node (be it programmatically or in the inspector) ?

Thanks a bunch for you response.

fmt | 2023-04-09 21:02