mohsenph69 / Godot-MTerrain-plugin

A GDExtension plugin which give godot the ability to produce highly optimized Terrain for Open world games
MIT License
372 stars 19 forks source link

Align with normals #26

Open Fre3bie opened 5 months ago

Fre3bie commented 5 months ago

I was wondering if there's a straightforward way to have grass placement be aligned with the terrain surface normals? I've been looking over the code but I can't seem to find a way to go about it. I know we can read the normal data for each pixel, but how would we go about using that data to change the transform of an instanced mesh?

Is there a way to adjust the transforms outside of the LOD settings for randomized positions, rotations, etc?

mohsenph69 commented 5 months ago

This is possible to do, But we need just to write some extra code, This is where grass data is generated for each grass:

Godot-MTerrain-plugin/gdextension/src/grass /mgrass.cpp

                if( (ptr[ibyte] & (1 << ibit)) != 0){
                    for(int r=0;r<grass_in_cell;r++){
                        index=count*BUFFER_STRID_FLOAT;
                        int rand_index = y*grass_region_pixel_width_lod + x*grass_in_cell + r;
                        const float* ptr = rand_buffer + (rand_index%rand_buffer_size)*BUFFER_STRID_FLOAT;
                        buffer.resize(buffer.size()+12);
                        float* ptrw = (float*)buffer.ptrw();
                        ptrw += index;
                        memcpy(ptrw,ptr,BUFFER_STRID_BYTE);
                        Vector3 pos;
                        pos.x = root_g->world_pos.x + x*grass_data->density + ptrw[3];
                        pos.z = root_g->world_pos.z + y*grass_data->density + ptrw[11];
                        ptrw[7] += grid->get_height(pos);
                        if(std::isnan(ptrw[7])){
                            buffer.resize(buffer.size()-12);
                            continue;
                        }
                        ptrw[3] = pos.x;
                        ptrw[11] = pos.z;
                        count++;
                    }
                }
            }

There is a transform matrix inside each buffer which is has 12 floating point, right now that 12 floating point just get copied from random buffer that is generated from from GrassLodSetting: memcpy(ptrw,ptr,BUFFER_STRID_BYTE);

And then its height will determine by terrain: ptrw[7] += grid->get_height(pos);

You can generate that buffer by getting terrain normal grid->get_normal(pos)

off-course we need to put this in a if statement (And it is much better that if statement not be in the loop so it will not check each time, maybe creating another loop) so we will have control on this! And every change we make here, we should do the same where grass physics is generated!

I had this in my mind to make that, working, if you know c++, you can make this a send me a pull a request so you also contribute to this!

otherwise I will see if I can make that working in future!!