1. Hello Guest! It's with a heavy heart that we must announce the removal of the Legacy GMC Archive. If you wish to save anything from it, now's the time! Please see this topic for more information.
    Dismiss Notice

GM:S 1.4 Difficulties determining the nearest instance in 3D space

Discussion in 'Programming' started by Prometheus1998_, Mar 6, 2019.

  1. Prometheus1998_

    Prometheus1998_ Member

    Joined:
    Aug 26, 2018
    Posts:
    22
    I'm trying to create a script that returns the nearest instance in 3-dimensional space, by looping through all active instances of the object, evaluating the distance using the built-in function "point_distance_3d", sorting the ds_grid containing the data so that the smallest distance value is in the [0,1] position, and returning the id saved in the [0,0] position.

    Code:
    ///instance_nearest_3d(x,y,z,obj)
    object = argument3;
    arg_x = argument0;
    arg_y = argument1;
    arg_z = argument2;
    
    var instances = ds_grid_create(instance_number( object ),1);
    
    for(var i = 0; i < instance_number( object ); i += 1) {
        var inst = instance_find( object , i);
        var dist = point_distance_3d(inst.x,inst.y,inst.z, arg_x , arg_y , arg_z )
       
        ds_grid_add(instances,0,i,inst.id);
        ds_grid_add(instances,1,i,dist);
    }
    
    ds_grid_sort(instances,1,true);
    
    var val = ds_grid_get(instances,0,0);
    
    ds_grid_destroy(instances);
    
    return val;
    

    For ease of testing, I've been using a flat plane, assuming all objects are on the same z-level (z = 0).

    The grid I have been using to test has nine objects, arranged like so:

    | a b c |
    | d e f |
    | g h i |

    The object running the test starts in the "e" position, but indicates the closest object it tests for is in the "i" position. In addition, despite running in the "Step" event, it only calculates the nearest object once. It behaves exactly the same if I change the "ascending" parameter for ds_grid_sort from true to false.

    Replacing the script in the spoiler tags above with the built-in function "instance_nearest" functions exactly the way it should, so I'm reasonably confident the problem is in the ds_grid, either saving the data or sorting it. Given the way it (doesn't) change behavior when switching how it sorts the information in the grid, I'm pretty sure I messed up the sorting. I just can't figure out how, and would appreciate any help that can be provided.
     
  2. Simon Gust

    Simon Gust Member

    Joined:
    Nov 15, 2016
    Posts:
    3,218
    May I ask what the ds grid exactly reads?

    Where are the origins placed on these instaces?
    Are your arg_x, arg_y, arg_z exactly the x, y and z of the searching instance?
     
  3. TheSnidr

    TheSnidr Heavy metal viking dentist GMC Elder

    Joined:
    Jun 21, 2016
    Posts:
    474
    If you only need the single nearest instance, it's easier to use "with" and store the nearest instance in a variable:
    Code:
    var dist = 99999;
    var nearest = - 1;
    with object
    {
        var d = point_distance_3d(stuff);
        if (d < dist)
        {
            dist = d;
            nearest = id;
         }
    }
    return nearest;
     
  4. Prometheus1998_

    Prometheus1998_ Member

    Joined:
    Aug 26, 2018
    Posts:
    22
    By origins, do you mean the exact x and y value of the object that the sprite is drawn from?
    They are procedurally placed, centered on the player object.

    The ds_grid's 0 column contains the "id" variable of each object, the 1 column contains the calculated distance.

    Arg_x, arg_y, and arg_z are the exact coordinates that the script calculates the distance to. It can be the coordinates of the calling function, or it can be some other coordinate entirely.

    Let me know if I understand the concept behind this correctly, please:
    First, the code initializes the "dist" variable to an arbitrarily large number that's unlikely to ever come up as a legitimate distance value, and sets the "nearest" variable to -1, which will never be a real id. From there, it executes code in all other instances (looping through by instance number?), calculating the distance between the two points in 3d space. If this distance is shorter than the existing value in the "dist" variable, it sets the "dist" variable to this new value, sets "nearest" to that instance's id, and continues on. The first instance that the code operates through should always overwrite the "dist" and "nearest" variables.
    At the end of the "with" construction, the closest instance's id should be stored in the nearest variable. If the "nearest" variable is still -1, there are no valid active instances to be found.
     
  5. TheSnidr

    TheSnidr Heavy metal viking dentist GMC Elder

    Joined:
    Jun 21, 2016
    Posts:
    474
    Correct you are! On all accounts actually. Good job!
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice