xyz at the moment item node contains pre defined properties that link to a visual mesh scene .item_mesh which is a meshinstance3d.

I get what you mean, using colliders, but first i need to fugure out how to translate the rotated node and calculate the correct insertion point in to the parent node so that its AABB is placed above the existing AABB of all other child nodes.

This is just an exercise using transforms, and real life situation on how to do things. It doesnt have to be realistic.

  • xyz replied to this.

    kuligs2 Calculate the global max y of the bounding box that's on top of the stack as we already determined in your previous question. In the same fashion you can calculate the global min y of the bounding box you're trying to place. The last thing you need is the global position if the node you're placing. To get the needed offset from the stack top just subtract those two things (aabb global min y and node's global y position)

    The most important thing is to keep all calculations in the same coordinate space. The global space is the best option here because it's easy to convert from/to, and simplest to mentally visualize.

      xyz Well thats where im having trouble. I got the top most Y (total_size.y) with the existing meshes in the parent node. then add the picked up nodes AABB with size (total_size.y = total_size.y + p_aabb.size.y). But somehow i cant get the offset.

      When i calculate var result_y = total_size.y - picked_up_obj.item_mesh.global_transform.origin.y it gives me the wrong offest.

      So far i got this

      	var total_size:Vector3
      	var p_aabb = picked_up_obj.item_mesh.global_transform * picked_up_obj.item_mesh.get_aabb()
      	for n in hand_node.get_children():
      		if n is Item:
      			var child:Item = n
      			var mesh=child.item_mesh
      			var m_aabb = mesh.global_transform*mesh.get_aabb().abs()
      
      			total_size.y =  max(total_size.y,m_aabb.end.y) - hand_node.global_position.y
      			
      	var pp = PLANE.instantiate()
      	
      	
      	if hand_node.get_children().size() == 0:
      		hand_node.add_child(pp)
      	else:
      		hand_node.add_child(pp)
      		pp.position=total_size
      
      	total_size.y = total_size.y + p_aabb.size.y
      	var result_y = total_size.y - picked_up_obj.item_mesh.global_transform.origin.y
      	total_size.y = result_y
      • xyz replied to this.

        xyz
        player.gd
        After calculations:

        picked_up_obj.pick_up(hand_node,result_y)

        Item.gd:

        func pick_up(player,pos):
        	
        	if picked_up_by == player:
        		
        		return
        		
        	pick_up_position = pos
        	
        	picked_up_by = player
        	original_transform = global_transform
        	
        	freeze = true
        	collision_layer = 0
        	collision_mask=0
        	
        	self.reparent(player)
        	pass
        
        func _physics_process(_delta):
        	if !picked_up_by: return
        	if is_in_position:return
        
        	if not global_transform.origin.distance_to(picked_up_by.global_transform.origin + pick_up_position) < 0.01:
        
        		global_transform.origin = lerp(global_transform.origin, picked_up_by.global_transform.origin + pick_up_position, speed*_delta)
        	else:
        		if not is_in_position:
        			is_in_position = true
        			print("Item in position!")
        	pass
        • xyz replied to this.

          kuligs2 If you're setting the position of picked_up_object then you should take its (global) position when calculating the offset, not the position of its child picked_up_object.item_mesh. Wehatever node you set the position of, its (global) position should be used to calculate the offset. Otherwise there might be a mismatch, as you're using one node to calculate the offset and then apply that offset to a different node.

            xyz doesnt this return AABB in global coordinates?

            var p_aabb = picked_up_obj.item_mesh.global_transform * picked_up_obj.item_mesh.get_aabb()

            And this:

            	for n in hand_node.get_children():
            		if n is Item:
            			var child:Item = n
            			var mesh=child.item_mesh
            			var m_aabb = mesh.global_transform*mesh.get_aabb().abs()
            
            			total_size.y =  max(total_size.y,m_aabb.end.y) - hand_node.global_position.y

            WHere

            var m_aabb = mesh.global_transform*mesh.get_aabb().abs()

            Is in global coords?

            then i just add picked up AABB size to the hand's AABB max Y value

            total_size.y = total_size.y + p_aabb.size.y

            And then calculate the picked_up_obj nodes offset:

            var result_y = total_size.y - picked_up_obj.item_mesh.global_transform.origin.y

            It seems to me that all these are in global coords?

            I dont see where im missing something?

            • xyz replied to this.

              xyz

              its the picked_up_obj's mesh instance

              @onready var item_mesh:MeshInstance3D=get_mesh_instance(item_visual_node)
              func get_mesh_instance(visual_node):
              	
              	for child in visual_node.get_children():
              		if child is MeshInstance3D:
              			return child
              			
              	return null
              	
              	
              	pass

              Its just a mesh of the object. Object has other properties as its part of the class Item

              • xyz replied to this.

                kuligs2 Well you take the position of this item_mesh node while calculating the offset, but when positioning your object, you don't position that node but instead you position the scene's top node. You need to use the top node for both. I.e. you need to calculate the offset for the same node you plan to reposition.

                As I already said, make a simpler, minimal setup, preferably in a fresh project, and use it to test and figure things out. It'll be much easier to get the hang of things when there is no other stuff around. Also, when you have a minimal project that reproduces the problem, it's easy to share it so someone else can inspect it and see what exactly you're doing wrong.

                  xyz Setting up blank scene is troublesome, as real scene tend to be complicated and so in the end ill have to debug the complex scene.

                  Also i am lazy 😃

                  BTW. Seems like i finally got somewhat the correct positions.

                  Seems a bit off with this one, as to me it seem sto be floating too much but its most definately (aproximately) in position.

                  so the finisher move was this:
                  This part stays the same:

                  	var total_size:Vector3
                  	var p_aabb = picked_up_obj.item_mesh.global_transform * picked_up_obj.item_mesh.get_aabb()
                  	for n in hand_node.get_children():
                  		if n is Item:
                  			var child:Item = n
                  			var mesh=child.item_mesh
                  			var m_aabb = mesh.global_transform*mesh.get_aabb().abs()
                  
                  			total_size.y =  max(total_size.y,m_aabb.end.y) - hand_node.global_position.y

                  The c bellow is the offset thing that works for some reason. and then i just add the offset to the total_size which is the top_most_y of all child nodes in the hand_node.

                  	var c = picked_up_obj.global_transform.origin-p_aabb.get_center()+(p_aabb.size/2)
                  	var gg = total_size + c
                  	
                  	total_size.y = gg.y
                  	
                  
                  	return total_size

                  Works if hat is rotated a bit too

                  Now need to pull in them meshes closer with collision meshes.

                  One way would be lerp top mesh Y to negative value until the top mesh collides with bottom mesh.

                  • xyz replied to this.

                    kuligs2 One way would be lerp top mesh Y to negative value until the top mesh collides with bottom mesh.

                    Better to use binary search instead of lerping.

                      kuligs2 Oh, it totally applies. Lerping would be analogous to linear search so sampling collisions in binary search fashion may bring the number of iterations way down to logarithm of iteration you'd use with lerping. And since we're dealing with a continuum here, you'd get much more precision at the cost of just a few iterations as binary search converges very fast to the solution.

                        xyz Interesting, but does godot have some buit in methods/functions for this?
                        Oh the Array class seem to have it?


                        https://docs.godotengine.org/en/stable/classes/class_array.html#class-array-method-bsearch
                        But they dont call it binary, so im not 100% sure if it is binary search.

                        But need to wrap my head around on how to use this in my situation. Which values to iterate through.

                        The way i imagined it, i could just move some increment each _physics_process(_delta) frame until something collides, then stop.

                        Another idea was to somehow enable gravity for the top most object in the "hand" node and let it fall until it collides. But that gravity is like gravity for that top most node but its attached to the hand, so no matter where the hand is, and what orientation it is (upside down or whatever) the "moving" node will always move like it gravitates to the nearest collider object.

                        Will do some tests later to see how to do this, and see what works or not 🙂

                          kuligs2 If you don't need it to happen instantly then incrementing the position gradually in _physics_process() might be fine, you'll end up with some type of falling animation. Otherwise, if it has to happen instantly then a binary search would be better.

                          Note that you'd not use the literal binary search over discrete values, but instead you search for a non-colliding position that is very near to a colliding position, and you do this in a binary search manner: Start with two faraway positions, one that is not colliding and other that you're sure is colliding and then close in to the wanted position halving the increment to one side or other, just like binary search does with sorted values.

                          Alternatively if you want to use Array's binary search facilities, put all positions between those two extremes into an array (with some small increment), and then use Array::bsearch_custom() to do the search. This might actually be slower than using a custom iteration because you need to linearly iterate over all values when populating the array, but still faster than linear search because it doesn't require a collision check for each position in the array.

                          kuligs2 But they dont call it binary

                          A binary search means that what's being searched is iteratively divided by two. At each step you're halving what needs to be searched. I.e., binary = two.