EmiOnGit / warbler_grass

A bevy plugin for creating 3d grass in your game
Apache License 2.0
120 stars 11 forks source link

Splitting `Spawner` functionality #41

Closed EmiOnGit closed 1 year ago

EmiOnGit commented 1 year ago

What problem does this solve or what need does it fill?

I've been working on implementation for the density map and height map for a while now. They are also the main blocker for implementing the editor.

After a lot of fiddling following problems remain unsolved with the current design: The GrassSpawner is not idiomatic. It panics at runtime if any combination you input is not compatible. However, it's not easy to see if a combination would work;

To demonstrate that assume following input HeightMap, DensityMap and HeightRepresentation::PerBlade(heights). It does define all 3 needed attributes but it's impossible with the current architecture to know the amount of grass blades before processing the density map further.

What should happen if the amount of heights given doesn't match the amount of blades extracted from the density map? Should it use default values for the rest? Should it repeat the heights from the beginning? How would the programmer know which height corresponds to which grass blade?

Also if we decide to spawn just as many blades as heights are given, does this mean the density suddenly corresponds to the heights? This wouldn't make much sense

This is not only hard to figure out for the user. Also the codebase has some error prone places where all relevant combinations have to be checked and specific behavior has to trigger accordingly.

This approach is not maintainable in the longer run as bugs will sneak in at some point.

Describe the solution you'd like

I'd like to split the current GrassSpawner functionality in 2 main ways that are supported. This can be done using 2 separate Bundles

// Mainly using maps. Should be used for serious projects as it has many advantages

struct WarblerBundle { // or GrassBundle?
    height_map: HeightMap,
    density_map: DensityMap,
    height:  enum {Uniform(f32), from_texture(Image)} ,
    aabb: Aabb,
    mesh: Handle<Mesh>,
    #[bundle]
    spatial: SpatialBundle //Transform Globaltransform Visibility ComputedVisibility 
}
// Using explicitly given positions. 
// Is easier to set up and can be used for tiny games/prototyping
struct WarblersExplicitBundle { // Maybe other name
      grass: struct { 
          positions: Vec(Vec3), 
          height: f32
      },
      mesh: Handle<Mesh>,
      #[bundle]
      spatial: SpatialBundle
}

Describe what is for debate

The design for the two bundles is important for usability later on. Suggestions are very welcomed here

EmiOnGit commented 1 year ago

@janhohenheim sorry to bother you. Do you have any thoughts on this by any chance?

janhohenheim commented 1 year ago

I can check in a few hours :)

EmiOnGit commented 1 year ago

Thanks a lot! I also updated the issue text :)