OverviewFilesCommitsIssuesDocsReleasesPeers

dc-terrain / src / dc_terrain_generator.h

212 lines · c ref:
#ifndef DC_TERRAIN_GENERATOR_H
#define DC_TERRAIN_GENERATOR_H

#include <godot_cpp/classes/resource.hpp>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/core/gdvirtual.gen.inc>

#include "dc_generator.h"
#include "dc_generator_noise.h"
#include "dc_generator_mesh_sdf.h"
#include "dc_generator_geiss.h"

namespace godot {

// ---------------------------------------------------------------------------
// DCTerrainGenerator — abstract Resource base class
// ---------------------------------------------------------------------------
// Wraps the pure-C++ DCGenerator interface so generators can be assigned
// in the Godot inspector or created from GDScript.
class DCTerrainGenerator : public Resource {
    GDCLASS(DCTerrainGenerator, Resource)

protected:
    static void _bind_methods();

public:
    // Returns the underlying C++ generator. Subclasses must implement.
    virtual DCGenerator* get_native_generator() { return nullptr; }
};

// ---------------------------------------------------------------------------
// DCTerrainGeneratorNoise — wraps DCGeneratorNoise with inspector properties
// ---------------------------------------------------------------------------
class DCTerrainGeneratorNoise : public DCTerrainGenerator {
    GDCLASS(DCTerrainGeneratorNoise, DCTerrainGenerator)

    DCGeneratorNoise impl_;
    DensityConfig config_;
    bool dirty_ = true;  // deferred reconfigure

    void _apply_config();

protected:
    static void _bind_methods();

public:
    DCTerrainGeneratorNoise();

    DCGenerator* get_native_generator() override { _apply_config(); return &impl_; }

    // DensityConfig property accessors
    void set_seed(int p_val);
    int get_seed() const;

    void set_primary_frequency(float p_val);
    float get_primary_frequency() const;
    void set_primary_strength(float p_val);
    float get_primary_strength() const;

    void set_tunnel_frequency(float p_val);
    float get_tunnel_frequency() const;
    void set_tunnel_strength(float p_val);
    float get_tunnel_strength() const;
    void set_tunnel_radius(float p_val);
    float get_tunnel_radius() const;

    void set_ridge_frequency(float p_val);
    float get_ridge_frequency() const;
    void set_ridge_strength(float p_val);
    float get_ridge_strength() const;

    void set_warp_frequency(float p_val);
    float get_warp_frequency() const;
    void set_warp_strength(float p_val);
    float get_warp_strength() const;

    void set_detail_frequency(float p_val);
    float get_detail_frequency() const;
    void set_detail_strength(float p_val);
    float get_detail_strength() const;

    void set_ground_bias(float p_val);
    float get_ground_bias() const;

    void set_solid_floor_depth(float p_val);
    float get_solid_floor_depth() const;
    void set_sky_height(float p_val);
    float get_sky_height() const;

    void set_flat_center_radius(float p_val);
    float get_flat_center_radius() const;

    void set_terrain_size(float p_val);
    float get_terrain_size() const;

    void set_use_noise(bool p_val);
    bool get_use_noise() const;

    void set_spherical(bool p_val);
    bool get_spherical() const;
    void set_planet_radius(float p_val);
    float get_planet_radius() const;

    void set_max_noise_octaves(int p_val);
    int get_max_noise_octaves() const;
    void set_max_ridge_octaves(int p_val);
    int get_max_ridge_octaves() const;

    void set_voronoi_cell_count(int p_val);
    int get_voronoi_cell_count() const;
    void set_floor_strength(float p_val);
    float get_floor_strength() const;
    void set_floor_height_min(float p_val);
    float get_floor_height_min() const;
    void set_floor_height_max(float p_val);
    float get_floor_height_max() const;
    void set_room_height(float p_val);
    float get_room_height() const;
};

// ---------------------------------------------------------------------------
// DCTerrainGeneratorMeshSDF — loads an OBJ mesh and generates SDF from it
// ---------------------------------------------------------------------------
// Use for verification (fandisk) or stamping arbitrary mesh shapes as terrain.
class DCTerrainGeneratorMeshSDF : public DCTerrainGenerator {
    GDCLASS(DCTerrainGeneratorMeshSDF, DCTerrainGenerator)

    DCGeneratorMeshSDF impl_;
    String mesh_path_;

protected:
    static void _bind_methods();

public:
    DCGenerator* get_native_generator() override { return &impl_; }

    void set_mesh_path(const String& p_path);
    String get_mesh_path() const;

    // Reload the mesh from disk (call after changing mesh_path)
    void reload();

    // Inspector info
    int get_triangle_count() const;
};

// ---------------------------------------------------------------------------
// DCTerrainGeneratorGeiss — GPU Gems 3 ch.1 (Geiss) terrain
//
// Exists to be COMPARED: the same field hyper-tps raymarches, meshed here, so
// marching and meshing can be measured against each other on identical terrain.
//
// GPU ONLY. The field samples eight 16^3 noise volumes, and until volume_dir
// points at them has_gpu_shader() is false and the generator produces nothing
// but air -- deliberately, so a half-loaded field can never be mistaken for the
// real one. Check is_loaded() before trusting a mesh built from it.
// ---------------------------------------------------------------------------
class DCTerrainGeneratorGeiss : public DCTerrainGenerator {
    GDCLASS(DCTerrainGeneratorGeiss, DCTerrainGenerator)

    DCGeneratorGeiss impl_;
    String volume_dir_;
    bool loaded_ = false;

protected:
    static void _bind_methods();

public:
    DCGenerator* get_native_generator() override { return &impl_; }

    void set_volume_dir(const String& p_path);
    String get_volume_dir() const { return volume_dir_; }

    // Loads the eight .vol files from volume_dir. All or nothing.
    bool reload();
    bool is_loaded() const { return loaded_; }
};

// ---------------------------------------------------------------------------
// DCTerrainGeneratorScript — calls GDScript virtual _evaluate()
// ---------------------------------------------------------------------------
// WARNING: _evaluate() is called from worker threads. The GDScript VM is
// single-threaded, so this class uses a mutex + deferred call to serialize
// evaluation. This means it will be slower than native generators.
// For production use, prefer DCTerrainGeneratorNoise or a native C++ subclass.
class DCTerrainGeneratorScript : public DCTerrainGenerator {
    GDCLASS(DCTerrainGeneratorScript, DCTerrainGenerator)

    // Bridge object: C++ DCGenerator that forwards to the Godot script.
    class ScriptBridge : public DCGenerator {
        DCTerrainGeneratorScript* owner_;
    public:
        ScriptBridge(DCTerrainGeneratorScript* o) : owner_(o) {}
        float evaluate(float x, float y, float z, float lod_voxel_size) override;
    };
    ScriptBridge bridge_{this};

protected:
    static void _bind_methods();

public:
    DCGenerator* get_native_generator() override { return &bridge_; }

    // Virtual method that GDScript subclasses override.
    // Returns density: positive = solid, negative = air.
    GDVIRTUAL4R(float, _evaluate, float, float, float, float)
};

} // namespace godot

#endif // DC_TERRAIN_GENERATOR_H