godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.13k stars 79 forks source link

Add a function like `MultiMesh.set_as_bulk_array()` for AStar #4658

Open KnightNine opened 2 years ago

KnightNine commented 2 years ago

Describe the project you are working on

I have a lot of Astar points and connections since it is a 3D Astar map.

Describe the problem or limitation you are having in your project

this function is very slow:

func data_to_AStar_obj(data):
    var obj = AStar.new()
        #add points 
    for point_index in data.keys():
        obj.add_point(point_index,data[point_index][0])
    #then connect them
    for point_index in data.keys():
        for connection in data[point_index][1]:
            obj.connect_points(point_index,connection,true)
    return obj

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Add a way to speed up this process with a function similar to the multimesh's set_as_bulk_array function.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

the parameters of this new function would be:

if connected_point_index is -1, it is not connected so you can have less than the total number of connections.

If this enhancement will not be used often, can it be worked around with a few lines of script?

I'm probably gonna have to write a method of doing this in c++... after I learn how to use c++. or I'll need to write a whole new Astar method altogether.

this probably won't be used often unless you have large 3D Astar maps.

Is there a reason why this should be core and not an add-on in the asset library?

this feature is tied to the core functions.

KnightNine commented 2 years ago

will this jank code work and if it does, would it be any faster than the above in GDScript?

void AStar::set_as_bulk_array(const PoolVector<real_t> &pool_points, int max_connections, const PoolVector<int> &pool_connections )
{

    //wipe all points
    clear();

    int size = pool_points.size();
    ERR_FAIL_COND_MSG(size % 6 > 0, vformat("pool_points size lacks data for each point"));

    PoolVector<real_t>::Read r = pool_points.read();
    for (int i = 0; i < size / 4; i++) {

        int p_id = r[i * 6 + 0];
        float x = r[i * 6 + 1];
        float y = r[i * 6 + 2];
        float z = r[i * 6 + 3];
        float p_weight_scale = r[i * 6 + 4];
        int p_parallel_support_layers = r[i * 6 + 5];

        ERR_FAIL_COND_MSG(p_id < 0, vformat("Can't add a point with negative id: %d.", p_id));
        ERR_FAIL_COND_MSG(p_weight_scale < 1, vformat("Can't add a point with weight scale less than one: %f.", p_weight_scale));
        ERR_FAIL_INDEX_MSG(p_parallel_support_layers, 1 << 32, vformat("Can't add a point with p_parallel_support_layers less than 0 or more than 2^32 - 1: %f.", p_parallel_support_layers));

        Vector3 p_pos = Vector3(x, y, z);

        Point* pt = memnew(Point);
        pt->id = p_id;
        pt->pos = p_pos;
        pt->weight_scale = p_weight_scale;
        pt->parallel_support_layers = p_parallel_support_layers;
        pt->prev_point = nullptr;
        pt->open_pass = 0;
        pt->closed_pass = 0;
        pt->enabled = true;
        points.set(p_id, pt);

    }

    PoolVector < int>::Read r1 = pool_connections.read();
    size = pool_connections.size();
    int i_mult = max_connections + 1;
    ERR_FAIL_COND_MSG(size % i_mult > 0, vformat("pool_connections size lacks data for each point"));

    for (int i = 0; i < size / i_mult; i++) {

        int p_id = r1[i * i_mult + 0];
        for (int j = 1; j < i_mult; j++) {

            int p_with_id = r1[i * i_mult + j];
            if (p_with_id >= 0) {
                connect_points(p_id, p_with_id);
            }

        }

    }
}

On a separate note, is there any way to run the Godot engine without compiling it? so that I can quickly test my jank additions and changes.

Zireael07 commented 2 years ago

, is there any way to run the Godot engine without compiling it? so that I can quickly test my jank additions and changes.

If your additions are C++, nope, your best bet are modules which should compile faster than modifying Godot source but still require recompiling it.

If you want to change Godot source, double nope.

DanGrizzly commented 1 month ago

Bump. This is sorely needed for large maps, because there's no way to duplicate, save, export or bake initialised AStar3D objects.

AThousandShips commented 1 month ago

@DanGrizzly Please don't bump without contributing significant new information. Use the :+1: reaction button on the first post instead.