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.
How to get MeshInstantce3D extents
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
- Edited
Also i noticed this:
editor seems to have different bounding box than aabb?
- Edited
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.
- Edited
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.
- Edited
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.
- Best Answerset by kuligs2
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)
Well, there are many ways of doing it, but yes, your method works aswell. Your solution is compact and straight to the point, while i was trying to debug step by step to see what kind of values are produced because to me it didnt made sense.
This was just an exercise to learn how things work.
Before i looked up in here this is what i came up with and it produced same result.
# this works
var mesh_array = meshy_node.get_children()
for mesh in mesh_array:
var mesh_aabb = mesh.get_aabb().abs()
var mesh_glob_trans = mesh.global_transform
var glob_mesh_aabb = mesh_glob_trans * mesh_aabb
global_aabb = global_aabb.merge(glob_mesh_aabb)
then get the .end prop from that aabb to get the desired Y position.
Note: .abs() is optional, it still produces same result.
but TLDR my problem was that the order of multiplication was not correct (wierd). In meths it didnt matter if you multiply 5x2 or 2x5, result is the same. Here i guess it matters.
#does not work
var glob_mesh_aabb = mesh_aabb * mesh_glob_trans
to
#works
var glob_mesh_aabb = mesh_glob_trans * mesh_aabb
- Edited
kuligs2 Yeah using operator *
with a transform object basically does matrix-matrix multiplication which is non-commutative.
Also note that you call merge()
on global_aabb
without previously initializing it with your first aabb. So the default zero aabb will get merged into your final bbox. This may cause incorrect final box if none of your boxes envelops the global origin.
kuligs2 merge()
is a method of an aabb object. The object needs to be one of your boxes before merging it with another of your boxes, otherwise, at the first iteration, it'll merge your first box with the default [(0,0,0), (0,0,0)] box.
# merges box1, box2 and the default zero box
var box: AABB #now contains default zero box
box.merge(box1)
box.merge(box2)
# properly merges only box1 and box2
var box: AABB = box1
box.merge(box2)