#include "landscape.h"
#include "entity.h"
#include "root.h"
-#include "transform.h"
using namespace std;
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;
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)
{
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));
}
}
}
+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
#include "mspgame_api.h"
#include "owned.h"
#include "system.h"
+#include "transform.h"
namespace Msp::Game {
class Entity;
+class Landscape;
class MSPGAME_API LandscapeGenerator
{
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
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