Hello again, maybe someone can help to solve some basic maths?

How do i get this point no matter what rotation is the mesh?

I understand that you need to get the mesh AABB, then you could get the .Size property to get the size of the object but if its rotated then i get confused.

Maybe someone already have solved something like this?

  • xyz replied to this.
  • kuligs2 Why are you using two nodes for a plane? use just a single plane. And try it without lerping first.
    This works as expected for me:

    $plane.global_position.y = -1e10
    for mesh in $meshy_node.get_children():
    	$plane.global_position.y = max($plane.global_position.y, (mesh.global_transform * mesh.get_aabb()).end.y)

    kuligs2 use get_aabb() to get the local aa bounding box. From that, deduce the local coordinates of all 8 corner points, transform them using node's global transform matrix and find which transformed point has the largest y coordinate.

    Alternatively, you can just multiply the local aabb with node's global matrix and get its top.

      xyz but arent the local coordinates "local"? Meaning if they are rotated then the Y axis is also rotated, and then the longest axis in "local" is for example Y but in global where the node is rotated the longest axis is for example X.

      But yeah its all about aabb(). Just need to find maths that work... 🙁

      • xyz replied to this.

        kuligs2 but arent the local coordinates "local"?

        That's why you're transforming them by multiplying with node's global matrix - to get the global coordinates.

        var global_aabb = mesh_node.global_transform * mesh_node.get_aabb()

          xyz

          Oh, the matrix thing threw me off, so i didnt get what you meant. Ill try it later to see how it turns out 🙂, thank you!

          Doing test and cant understand why am i not getting the correct result. Result is off by about 0.2 units in Y axis

          extends Node3D
          @onready var node_3d_bottom: Node3D = $Node3D_bottom
          @onready var node_3d_2_top: Node3D = $Node3D2_top
          @onready var node_3d_3_plane: Node3D = $Node3D3_plane
          @onready var node_3d_2_top_2: Node3D = $Node3D2_top2
          var global_aabb:AABB
          var local_aabb:AABB
          var arr_y = []
          
          # Called when the node enters the scene tree for the first time.
          func _ready() -> void:
          	
          	var mt:MeshInstance3D = node_3d_2_top_2.get_children()[0]
          	
          	global_aabb= node_3d_2_top_2.global_transform * mt.get_aabb()
          	local_aabb =  mt.get_aabb()
          	var arr = []
          	
          	for i in range(8):
          		var pt = local_aabb.get_endpoint(i)
          		var pt_glob = mt.to_global(pt)
          		arr.append(pt_glob)
          	
          	for p in arr:
          		
          		arr_y.append(p.y)
          	
          	print("pos: ",global_aabb.position)
          	print("siz: ",global_aabb.size)
          	print("end: ",global_aabb.end)
          	print("top node: ",node_3d_3_plane.global_position)
          	print("arr: ",arr)
          	print("arr_y: ",arr_y)
          	print("arr_y max: ",arr_y.max())
          	pass # Replace with function body.
          
          
          # Called every frame. 'delta' is the elapsed time since the previous frame.
          func _process(delta: float) -> void:
          	node_3d_3_plane.global_position.y = lerp(node_3d_3_plane.global_position.y,arr_y.max(),0.8*delta)
          	
          	pass

          The red plane is lerping towards the arr_y.max() value which is 4.22, same value is from the global_aabb= node_3d_2_top_2.global_transform * mt.get_aabb() where the resulted .end vector Y axis is at 4.22. But placing the red plane along the Y axis to the end of the bounding box is at 4.40

          STD: @ ready

          pos: (-0.772845, 2.689352, -1.050277)
          siz: (1.54569, 1.536256, 1.723653)
          end: (0.772845, 4.225608, 0.673377)
          top node: (0, 0, 0)
          arr: [(-0.003363, 3.372365, 0.673377), (-0.162882, 4.225608, 0.176858), (-0.613326, 2.891711, 0.043362), (-0.772845, 3.744954, -0.453156), (0.772845, 3.170006, 0.076256), (0.613326, 4.023249, -0.420262), (0.162882, 2.689352, -0.553757), (0.003363, 3.542595, -1.050277)]
          arr_y: [3.37236499786377, 4.22560787200928, 2.89171099662781, 3.74495387077332, 3.17000603675842, 4.02324867248535, 2.68935203552246, 3.54259490966797]
          arr_y max: 4.22560787200928

          not sure why am i not getting that 4.4 Y as the largest size.

          • xyz replied to this.

            kuligs2 global matrix and aabb should both be taken from the same node. Your code is taking each from a different node.

              xyz in my tests it didnt matter if multiply with global transform in the begining or use to_global() result is the same.

              Or maybe i dont understand what you mean?

              • xyz replied to this.

                kuligs2 Or maybe i dont understand what you mean?

                to_global() only works with points, not with AABBs. Nevertheless, the distinction is not really between multiplying by the matrix or using to_global(), it's about which node you're getting the global transformation from. If you want the global aabb of a mesh instance, you need to get the aabb and the global transformation matrix from that same mesh instance node. So instead of:

                global_aabb = node_3d_2_top_2.global_transform * mt.get_aabb()

                It should be:

                global_aabb = mt.global_transform * mt.get_aabb()

                  xyz like i said, the numbers are the same:

                  var global_aabb:AABB
                  var global_aabb2:AABB
                  var local_aabb:AABB
                  var arr_y = []
                  
                  # Called when the node enters the scene tree for the first time.
                  func _ready() -> void:
                  	
                  	var mt:MeshInstance3D = node_3d_2_top_2.get_children()[0]
                  	
                  	global_aabb= mt.global_transform * mt.get_aabb()
                  	global_aabb2= node_3d_2_top_2.global_transform * mt.get_aabb()
                  	local_aabb =  mt.get_aabb()
                  	var arr = []
                  	
                  	for i in range(8):
                  		var pt = local_aabb.get_endpoint(i)
                  		var pt_glob = mt.to_global(pt)
                  		arr.append(pt_glob)
                  	
                  	for p in arr:
                  		
                  		arr_y.append(p.y)
                  	
                  	print("pos1: ",global_aabb.position)
                  	print("pos2: ",global_aabb2.position)
                  	print("siz1: ",global_aabb.size)
                  	print("siz2: ",global_aabb2.size)
                  	print("end1: ",global_aabb.end)
                  	print("end2: ",global_aabb2.end)
                  	print("top node: ",node_3d_3_plane.global_position)
                  	print("arr: ",arr)
                  	print("arr_y: ",arr_y)
                  	print("arr_y max: ",arr_y.max())
                  	pass # Replace with function body.
                  pos1: (-0.772845, 2.689352, -1.050277)
                  pos2: (-0.772845, 2.689352, -1.050277)
                  siz1: (1.54569, 1.536256, 1.723653)
                  siz2: (1.54569, 1.536256, 1.723653)
                  end1: (0.772845, 4.225608, 0.673377)
                  end2: (0.772845, 4.225608, 0.673377)

                  that node is a scene with meshinstance thats why to get the mesh i need to grab first child. other than that i dont see where the problem is.

                  • xyz replied to this.

                    kuligs2 Make a simple test example with only a single mesh instance and a plane that aligns to wanted aabb top. See if that works first. Then proceed to implement it in more complex setup.

                    Btw how did you determine that numbers are not correct?

                      xyz I have another node in that scene (red plane) and i manually (eye balled) to place it along the Y axis at the edge of the presumed aabb extents that it barely touches the node below it.

                      If i lerp the max Y value for that red plane, starting from 0.0 in global coords of the scene then it looks like that. Which is clearly visible that its not the extent of the node/mesh as the blue thing is clipping

                      Also i noticed this:
                      editor seems to have different bounding box than aabb?

                      • xyz replied to this.

                        kuligs2 As I said, try it with a simple scene, without lerping. If you lerp with ever smaller increments, the final position might actually never be reached.

                        The editor bb you highlighted looks like it bounds multiple nodes, not a single mesh.

                          xyz well yes that node scene has one child mesh and that mesh has 3 more child meshes. Dont they add up internally?

                          As i said the numbers are the same, dont matter if i lerp or use resulted values, they are about 0.2 apart.

                          Simple node works, im guessing the child meshes dont add up 🙁 ..

                          • xyz replied to this.

                            kuligs2 im guessing the child meshes dont add up 🙁

                            Right, because get_aabb() is a methot of VisualInstance3D class which knows nothing about 3D transforms or scene structure. If you want an enclosing AABB of bunch of child AABBs you'll have to compound them together yourself. Transform each AABB to global space as we've already discussed and then iteratively use AABB::merge() to get the total global enclosing AABB. Or simply find which global AABB has the highest end.y and use that.

                              xyz in theory its understandable but in practice something is not working.

                              @onready var node_3d_2_top_2: Node3D = $Node3D2_top2
                              func _ready() -> void:
                              	
                              	var mt = node_3d_2_top_2.get_children()#[0]
                              
                              	for c in mt:
                              		global_aabb2 = global_aabb2.merge(c.get_aabb())
                              	
                              	global_aabb2= global_aabb2 *node_3d_2_top_2.global_transform# * local_aabb
                              
                              	var arr = []
                              	
                              	for i in range(8):
                              		var pt = global_aabb2.get_endpoint(i)
                              		arr.append(pt)
                              	
                              	for p in arr:
                              		arr_y.append(p.y)
                              	
                              	
                              	print("pos2: ",global_aabb2.position)
                              	
                              	print("siz2: ",global_aabb2.size)
                              	
                              	print("end2: ",global_aabb2.end)
                              	
                              	print("arr: ",arr)
                              	print("arr_y: ",arr_y)
                              	print("arr_y max: ",arr_y.max())
                              	pass # Replace with function body.

                              • xyz replied to this.

                                kuligs2 From your descriptions and images, it's not really clear what is "not working". You'll have to describe it in more detail. What you expect to happen vs what is happening, using the simplest possible setup. Your initial question "how to get mesh instance's aabb" was answered. What exact type of aligning are you actually trying to implement? There was a plane in your previous examples, now it's gone. Please be more precise with describing the problem and be aware of xy problem.

                                Btw. you need to merge global AABBs. Merging local ones makes no sense as all AABBs need to be in the same (global) coordinate space.

                                  xyz Im sorry for not being able to make my problem clear. As i thought that my first post was clearly defined. I want to get a certain point (furthest extent in one axis) in global coordinates no matter how mesh/node is rotated.

                                  Following your advice on using aabb ive concluded that it gives me wrong values, no matter which of your suggestion i implement.

                                  So far i have not found a solution based on official documentation and your suggestions.

                                  I reorganized the code and nodes so it would be easier to track.

                                  extends Node3D
                                  @onready var red_plane: Node3D = $Red_plane
                                  @onready var meshy_node: Node3D = $MeshyNode
                                  
                                  var global_aabb:AABB
                                  var arr_y = []
                                  
                                  func _ready() -> void:
                                  	
                                  	var mesh_array = meshy_node.get_children()
                                  
                                  	for mesh in mesh_array:
                                  		var mesh_aabb = mesh.get_aabb()
                                  		var mesh_glob_trans = mesh.global_transform
                                  		var glob_mesh_aabb = mesh_aabb * mesh_glob_trans
                                  		
                                  		global_aabb = global_aabb.merge(glob_mesh_aabb)
                                  
                                  	var arr = []
                                  	
                                  	for i in range(8):
                                  		var pt = global_aabb.get_endpoint(i)
                                  		arr.append(pt)
                                  	
                                  	for p in arr:
                                  		arr_y.append(p.y)
                                  	
                                  	print("pos1: ",global_aabb.position)
                                  	print("siz1: ",global_aabb.size)
                                  	print("end1: ",global_aabb.end)
                                  	print("arr: ",arr)
                                  	print("arr_y: ",arr_y)
                                  	print("arr_y max: ",arr_y.max())
                                  
                                  func _process(delta: float) -> void:
                                  	red_plane.global_position.y = lerp(red_plane.global_position.y,arr_y.max(),0.8*delta)
                                  	
                                  	pass

                                  Result

                                  pos1: (-0.200719, -4.347878, -3.79828)
                                  siz1: (2.579584, 6.751319, 7.38325)
                                  end1: (2.378866, 2.403441, 3.58497)
                                  arr: [(-0.200719, -4.347878, -3.79828), (-0.200719, -4.347878, 3.58497), (-0.200719, 2.403441, -3.79828), (-0.200719, 2.403441, 3.58497), (2.378866, -4.347878, -3.79828), (2.378866, -4.347878, 3.58497), (2.378866, 2.403441, -3.79828), (2.378866, 2.403441, 3.58497)]
                                  arr_y: [-4.34787845611572, -4.34787845611572, 2.40344095230103, 2.40344095230103, -4.34787845611572, -4.34787845611572, 2.40344095230103, 2.40344095230103]
                                  arr_y max: 2.40344095230103


                                  Where you can see that red plane is where the highest aabb point is for sure but its not the correct value for some reason. Becasue if i manually in editor transform the red plane into the furthest Y towards UP direction position then i get approximate value of Y=4.40

                                  Imo the merging of aabb makes the results somehow wrong, i dont understand how it merges, The documentation does not explains it.

                                  • xyz replied to this.