]> git.tdb.fi Git - libs/game.git/commitdiff
Support adding prop entities to Landscape
authorMikko Rasa <tdb@tdb.fi>
Fri, 19 May 2023 20:38:10 +0000 (23:38 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 19 May 2023 20:38:10 +0000 (23:38 +0300)
source/game/landscape.cpp
source/game/landscape.h

index 1612d447bdbe0697ffff22e792c2166197724f9e..c9c2814c63d1416ce311e694f6e9c5716e1f5496 100644 (file)
@@ -1,7 +1,6 @@
 #include "landscape.h"
 #include "entity.h"
 #include "root.h"
-#include "transform.h"
 
 using namespace std;
 
@@ -18,6 +17,11 @@ Landscape::Landscape(Stage &s, const HeightmapTerrainSetup &t, float b):
        block_size = grid_size*terrain_setup.grid_spacing;
 }
 
+bool Landscape::terrain_index_compare(const Terrain &t, const LinAl::Vector<int, 2> &i)
+{
+       return t.index.y<i.y || (t.index.y==i.y && t.index.x<i.x);
+}
+
 void Landscape::set_generator(LandscapeGenerator *g)
 {
        generator = g;
@@ -33,9 +37,7 @@ void Landscape::generate(const Geometry::BoundingBox<float, 2> &bounds)
 
        for(int y=min_index.y; y<=max_index.y; ++y)
        {
-               auto i = lower_bound(terrains, LinAl::Vector<int, 2>(min_index.x, y), [](const Terrain &t, const LinAl::Vector<int, 2> &n){
-                       return t.index.y<n.y || (t.index.y==n.y && t.index.x<n.x);
-               });
+               auto i = lower_bound(terrains, LinAl::Vector<int, 2>(min_index.x, y), terrain_index_compare);
 
                for(int x=min_index.x; x<=max_index.x; ++x)
                {
@@ -48,7 +50,7 @@ void Landscape::generate(const Geometry::BoundingBox<float, 2> &bounds)
                                if(generator)
                                {
                                        LinAl::Vector<float, 2> base = center-block_size_vec/2.0f;
-                                       generator->generate_block({ base, base+block_size_vec }, terrain);
+                                       generator->generate_block(*this, { base, base+block_size_vec }, terrain);
                                }
                                i = terrains.emplace(i, index, move(entity), move(terrain));
                        }
@@ -57,4 +59,18 @@ void Landscape::generate(const Geometry::BoundingBox<float, 2> &bounds)
        }
 }
 
+LinAl::Vector<float, 3> Landscape::get_ground_position(const LinAl::Vector<float, 3> &p) const
+{
+       LinAl::Vector<int, 2> index(round(p.x/block_size), round(p.y/block_size));
+       auto i = lower_bound(terrains, index, terrain_index_compare);
+       if(i==terrains.end() || i->index!=index)
+               return compose(p.slice<2>(0), 0.0f);
+
+       LinAl::Vector<float, 3> center = i->entity->get_transform()->get_position();
+       LinAl::Vector<float, 2> corner = center.slice<2>(0) - i->terrain->get_size()/2.0f;
+       LinAl::Vector<float, 2> p_xy = p.slice<2>(0);
+       float z = i->terrain->get_elevation(p_xy-corner);
+       return center+compose(p_xy, z);
+}
+
 } // namespace Msp::Game
index b31402baee9a13459f6ce2a40f92eab9e428fa00..93197183041901d4df5612a5425979a2d25871cb 100644 (file)
@@ -7,10 +7,12 @@
 #include "mspgame_api.h"
 #include "owned.h"
 #include "system.h"
+#include "transform.h"
 
 namespace Msp::Game {
 
 class Entity;
+class Landscape;
 
 class MSPGAME_API LandscapeGenerator
 {
@@ -18,7 +20,7 @@ protected:
        LandscapeGenerator() = default;
 
 public:
-       virtual void generate_block(const Geometry::BoundingBox<float, 2> &, Handle<HeightmapTerrain>) = 0;
+       virtual void generate_block(Landscape &, const Geometry::BoundingBox<float, 2> &, Handle<HeightmapTerrain>) = 0;
 };
 
 class MSPGAME_API Landscape: public System
@@ -31,22 +33,46 @@ private:
                Owned<HeightmapTerrain> terrain;
        };
 
+       struct Prop
+       {
+               Owned<Entity> entity;
+       };
+
        Owned<Entity> subroot;
        const HeightmapTerrainSetup &terrain_setup;
        float block_size = 100.0f;
        LandscapeGenerator *generator = nullptr;
        std::vector<Terrain> terrains;
+       std::vector<Prop> props;
 
 public:
        Landscape(Stage &, const HeightmapTerrainSetup &, float);
 
+private:
+       static bool terrain_index_compare(const Terrain &, const LinAl::Vector<int, 2> &);
+
+public:
        void set_generator(LandscapeGenerator *);
        void generate(const Geometry::BoundingBox<float, 2> &);
        LinAl::Vector<float, 3> get_ground_position(const LinAl::Vector<float, 3> &) const;
 
+       template<typename T>
+               requires std::is_base_of_v<Entity, T>
+       void add_prop(const T::Setup &, TransformValues);
+
        void tick(Time::TimeDelta) override { }
 };
 
+
+template<typename T>
+       requires std::is_base_of_v<Entity, T>
+void Landscape::add_prop(const T::Setup &setup, TransformValues tf)
+{
+       tf.position = get_ground_position(tf.position);
+       Owned<T> prop(subroot, setup, tf);
+       props.emplace_back(std::move(prop));
+}
+
 } // namespace Msp::Game
 
 #endif