Compare commits
8 Commits
302719dd19
...
25002b9735
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25002b9735 | ||
|
|
b318f5ef8d | ||
|
|
6ad88e497f | ||
|
|
4882866bd9 | ||
|
|
7cad4daf2f | ||
|
|
db6430230e | ||
|
|
e69850f91a | ||
|
|
f2ef003610 |
5
Makefile
5
Makefile
@@ -2,7 +2,8 @@
|
|||||||
all: godot-editor-main
|
all: godot-editor-main
|
||||||
godot-editor-main:
|
godot-editor-main:
|
||||||
cd godot; \
|
cd godot; \
|
||||||
scons platform=x11 target=release_debug tools=yes custom_modules=../modules -j6; \
|
scons platform=x11 target=release_debug tools=yes custom_modules=../modules -j6
|
||||||
scons platform=x11 target=release tools=no custom_modules=../modules -j6
|
# scons platform=x11 target=release tools=no custom_modules=../modules -j6;
|
||||||
|
# scons platform=server target=release_debug tools=yes custom_modules=../modules -j6
|
||||||
# scons platform=windows target=release tools=yes custom_modules=../modules -j6
|
# scons platform=windows target=release tools=yes custom_modules=../modules -j6
|
||||||
# scons platform=javascript target=release tools=yes custom_modules=../modules -j6
|
# scons platform=javascript target=release tools=yes custom_modules=../modules -j6
|
||||||
|
|||||||
9
Makefile.complete
Normal file
9
Makefile.complete
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
.PHONY: all godot-editor-main
|
||||||
|
all: godot-editor-main
|
||||||
|
godot-editor-main:
|
||||||
|
cd godot; \
|
||||||
|
scons platform=x11 target=release_debug tools=yes custom_modules=../modules -j6; \
|
||||||
|
scons platform=x11 target=release tools=no custom_modules=../modules -j6; \
|
||||||
|
scons platform=server target=release_debug tools=yes custom_modules=../modules -j6
|
||||||
|
# scons platform=windows target=release tools=yes custom_modules=../modules -j6
|
||||||
|
# scons platform=javascript target=release tools=yes custom_modules=../modules -j6
|
||||||
2
godot
2
godot
Submodule godot updated: 62f56af694...f0223ea8d3
Submodule modules/voxel updated: 6cd143d392...38ec2f43d1
@@ -886,6 +886,8 @@ void Characters_::load_body_parts(const String &path)
|
|||||||
if (FileAccess::exists(fn2f))
|
if (FileAccess::exists(fn2f))
|
||||||
female_faces.push_back(fn2f);
|
female_faces.push_back(fn2f);
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < male_hairs.size(); i++)
|
||||||
|
printf("hair %d: %ls\n", i, male_hairs[i].c_str());
|
||||||
assert(male_hairs.size() > 0 && female_hairs.size() > 0);
|
assert(male_hairs.size() > 0 && female_hairs.size() > 0);
|
||||||
assert(male_faces.size() > 0 && female_faces.size() > 0);
|
assert(male_faces.size() > 0 && female_faces.size() > 0);
|
||||||
assert(hair_materials.size() > 0);
|
assert(hair_materials.size() > 0);
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "world_height_map.h"
|
#include "world_height_map.h"
|
||||||
#include "road_grid.h"
|
#include "road_grid.h"
|
||||||
#include "roads.h"
|
#include "roads.h"
|
||||||
|
#include "spawner.h"
|
||||||
|
#include "traffic.h"
|
||||||
|
|
||||||
void register_world_types()
|
void register_world_types()
|
||||||
{
|
{
|
||||||
@@ -19,6 +21,10 @@ void register_world_types()
|
|||||||
Engine::get_singleton()->add_singleton(Engine::Singleton("WorldMapData", WorldMapData::get_singleton()));
|
Engine::get_singleton()->add_singleton(Engine::Singleton("WorldMapData", WorldMapData::get_singleton()));
|
||||||
RoadsData::create_singleton();
|
RoadsData::create_singleton();
|
||||||
Engine::get_singleton()->add_singleton(Engine::Singleton("RoadsData", RoadsData::get_singleton()));
|
Engine::get_singleton()->add_singleton(Engine::Singleton("RoadsData", RoadsData::get_singleton()));
|
||||||
|
Spawner::create_singleton();
|
||||||
|
Engine::get_singleton()->add_singleton(Engine::Singleton("Spawner", Spawner::get_singleton()));
|
||||||
|
Traffic::create_singleton();
|
||||||
|
Engine::get_singleton()->add_singleton(Engine::Singleton("Traffic", Traffic::get_singleton()));
|
||||||
ClassDB::register_class<WorldGenerator>();
|
ClassDB::register_class<WorldGenerator>();
|
||||||
ClassDB::register_class<WorldHeightMap>();
|
ClassDB::register_class<WorldHeightMap>();
|
||||||
ClassDB::register_class<DensityMap>();
|
ClassDB::register_class<DensityMap>();
|
||||||
@@ -32,6 +38,9 @@ void register_world_types()
|
|||||||
|
|
||||||
void unregister_world_types()
|
void unregister_world_types()
|
||||||
{
|
{
|
||||||
|
RoadsData::destroy_singleton();
|
||||||
|
Spawner::destroy_singleton();
|
||||||
|
Traffic::destroy_singleton();
|
||||||
WorldMapData::destroy_singleton();
|
WorldMapData::destroy_singleton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ RoadGrid::RoadGrid()
|
|||||||
{
|
{
|
||||||
grid_width = 16;
|
grid_width = 16;
|
||||||
grid_height = 16;
|
grid_height = 16;
|
||||||
|
astar.instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
RoadGrid::~RoadGrid()
|
RoadGrid::~RoadGrid()
|
||||||
@@ -336,6 +337,10 @@ void RoadGrid::build(Ref<Curve> curve, Ref<FastNoiseLite> noise)
|
|||||||
}
|
}
|
||||||
map_sites.write[i].avg_height = min_height * 0.7f + max_height * 0.3f;
|
map_sites.write[i].avg_height = min_height * 0.7f + max_height * 0.3f;
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < vertices.size(); i++)
|
||||||
|
astar->add_point(i, vertices[i], 20.0f);
|
||||||
|
for (i = 0; i < map_hedges.size(); i++)
|
||||||
|
astar->connect_points(map_hedges[i]->a, map_hedges[i]->b, false);
|
||||||
generate_building_positions();
|
generate_building_positions();
|
||||||
printf("building 3rd dimention done\n");
|
printf("building 3rd dimention done\n");
|
||||||
}
|
}
|
||||||
@@ -528,6 +533,7 @@ void RoadGrid::generate_3d_vertices(Ref<Curve> curve, Ref<FastNoiseLite> noise)
|
|||||||
d = CLAMP(d, 1.0f, 30.0f);
|
d = CLAMP(d, 1.0f, 30.0f);
|
||||||
diagram_vertex_heights.write[i] = d;
|
diagram_vertex_heights.write[i] = d;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
for (j = 0; j < 3; j++) {
|
for (j = 0; j < 3; j++) {
|
||||||
for (i = 0; i < map_hedges.size(); i++) {
|
for (i = 0; i < map_hedges.size(); i++) {
|
||||||
int x1 = map_hedges[i]->a;
|
int x1 = map_hedges[i]->a;
|
||||||
@@ -538,12 +544,51 @@ void RoadGrid::generate_3d_vertices(Ref<Curve> curve, Ref<FastNoiseLite> noise)
|
|||||||
diagram_vertex_heights.write[x2] = diagram_vertex_heights[x1] + dh / fabsf(dh) * 0.01f * xd;
|
diagram_vertex_heights.write[x2] = diagram_vertex_heights[x1] + dh / fabsf(dh) * 0.01f * xd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
vertices.resize(get_diagram_vertex_count());
|
vertices.resize(get_diagram_vertex_count());
|
||||||
for (i = 0; i < vertices.size(); i++) {
|
for (i = 0; i < vertices.size(); i++) {
|
||||||
vertices.write()[i].x = diagram_vertices[i].x;
|
vertices.write()[i].x = diagram_vertices[i].x;
|
||||||
vertices.write()[i].y = diagram_vertex_heights[i];
|
vertices.write()[i].y = diagram_vertex_heights[i];
|
||||||
vertices.write()[i].z = diagram_vertices[i].y;
|
vertices.write()[i].z = diagram_vertices[i].y;
|
||||||
}
|
}
|
||||||
|
smooth_heights();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoadGrid::smooth_heights()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
float ok = true;
|
||||||
|
while (ok) {
|
||||||
|
for (i = 0; i < map_hedges.size(); i++) {
|
||||||
|
int a = map_hedges[i]->a;
|
||||||
|
int b = map_hedges[i]->b;
|
||||||
|
Vector3 p1 = vertices[a];
|
||||||
|
Vector3 p2 = vertices[b];
|
||||||
|
float dst = p1.distance_to(p2);
|
||||||
|
float h = fabsf(p2.y - p1.y);
|
||||||
|
if (dst <= 48.0f && h > 0.0f) {
|
||||||
|
ok = false;
|
||||||
|
float m = (p1.y + p2.y) * 0.5f;
|
||||||
|
m = CLAMP(m, 0.0f, 70.0f);
|
||||||
|
p1.y = m;
|
||||||
|
p2.y = m;
|
||||||
|
} else if (h > 0.0f) {
|
||||||
|
ok = false;
|
||||||
|
float t = h / dst;
|
||||||
|
if (t > 0.35) {
|
||||||
|
ok = false;
|
||||||
|
float m1 = p1.y + (p2.y - p1.y) / 10.0f;
|
||||||
|
float m2 = p2.y + (p1.y - p2.y) / 10.0f;
|
||||||
|
p1.y = m1;
|
||||||
|
p2.y = m2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
vertices.write()[map_hedges[i]->a] = p1;
|
||||||
|
vertices.write()[map_hedges[i]->b] = p2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoadGrid::generate_building_positions()
|
void RoadGrid::generate_building_positions()
|
||||||
@@ -680,6 +725,7 @@ void RoadGrid::save_json(const String &path)
|
|||||||
f->close();
|
f->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
PoolVector<Vector3> RoadGrid::get_site_border(int site)
|
PoolVector<Vector3> RoadGrid::get_site_border(int site)
|
||||||
{
|
{
|
||||||
const struct map_site &msite = map_sites[site];
|
const struct map_site &msite = map_sites[site];
|
||||||
@@ -716,4 +762,73 @@ PoolVector<Vector3> RoadGrid::get_site_border(int site)
|
|||||||
assert(msite.polygon_ind.size() == ret.size());
|
assert(msite.polygon_ind.size() == ret.size());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PoolVector<Vector3> RoadGrid::get_site_border(int site, float offt)
|
||||||
|
{
|
||||||
|
int k, i;
|
||||||
|
float height = get_site_avg_height(site);
|
||||||
|
PoolVector<Vector3> border;
|
||||||
|
PoolVector<Vector3> poly = get_site_polygon_3d(site);
|
||||||
|
if (poly.size() == 0)
|
||||||
|
return PoolVector<Vector3>();
|
||||||
|
border.resize(poly.size());
|
||||||
|
for (k = 0; k < poly.size(); k++) {
|
||||||
|
i = k - 1;
|
||||||
|
if (i < 0)
|
||||||
|
i += poly.size();
|
||||||
|
Vector3 p1 = poly[i];
|
||||||
|
Vector3 p2 = poly[k];
|
||||||
|
Vector3 p3 = poly[(k + 1) % poly.size()];
|
||||||
|
Vector2 p1x(p1.x, p1.z);
|
||||||
|
Vector2 p2x(p2.x, p2.z);
|
||||||
|
Vector2 p3x(p2.x, p2.z);
|
||||||
|
Vector2 p4x(p3.x, p3.z);
|
||||||
|
Vector2 n1 = (p2x - p1x).tangent().normalized();
|
||||||
|
Vector2 n2 = (p4x - p3x).tangent().normalized();
|
||||||
|
p1x -= n1 * offt;
|
||||||
|
p2x -= n1 * offt;
|
||||||
|
p3x -= n2 * offt;
|
||||||
|
p4x -= n2 * offt;
|
||||||
|
Vector2 xp;
|
||||||
|
if (!Geometry::segment_intersects_segment_2d(p1x, p2x, p3x, p4x, &xp))
|
||||||
|
xp = p2x.linear_interpolate(p3x, 0.5) - (n1 + n2).normalized() * offt;
|
||||||
|
Vector3 tp(xp.x, height, xp.y);
|
||||||
|
border.write()[k] = tp;
|
||||||
|
}
|
||||||
|
return border;
|
||||||
|
}
|
||||||
|
|
||||||
|
PoolVector<Vector3> RoadGrid::get_site_radial_points(int site, float bofft, float offt)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
float height = get_site_avg_height(site), max_r = 0.0f;
|
||||||
|
PoolVector<Vector3> poly = get_site_border(site, bofft);
|
||||||
|
PoolVector<Vector3> ret;
|
||||||
|
if (poly.size() == 0)
|
||||||
|
return PoolVector<Vector3>();
|
||||||
|
List<Vector3> rpoints;
|
||||||
|
List<Vector3>::Element *e;
|
||||||
|
Vector3 center;
|
||||||
|
for (i = 0; i < poly.size(); i++)
|
||||||
|
center += poly[i];
|
||||||
|
center /= poly.size();
|
||||||
|
for (i = 0; i < poly.size(); i++) {
|
||||||
|
Vector3 ep1 = poly[i];
|
||||||
|
Vector3 ep2 = poly[(i + 1) % poly.size()];
|
||||||
|
Vector3 d = (ep2 - ep1).normalized();
|
||||||
|
rpoints.push_back(ep1);
|
||||||
|
float dst = ep1.distance_to(ep2);
|
||||||
|
while (dst > offt) {
|
||||||
|
ep1 += d * offt;
|
||||||
|
rpoints.push_back(ep1);
|
||||||
|
dst -= offt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret.resize(rpoints.size());
|
||||||
|
i = 0;
|
||||||
|
for (e = rpoints.front(); e; e = e->next())
|
||||||
|
ret.write()[i++] = e->get();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <core/reference.h>
|
#include <core/reference.h>
|
||||||
#include <scene/resources/curve.h>
|
#include <scene/resources/curve.h>
|
||||||
#include <core/math/random_number_generator.h>
|
#include <core/math/random_number_generator.h>
|
||||||
|
#include <core/math/a_star.h>
|
||||||
#include <modules/voxel/util/noise/fast_noise_lite.h>
|
#include <modules/voxel/util/noise/fast_noise_lite.h>
|
||||||
|
|
||||||
class CanvasItem;
|
class CanvasItem;
|
||||||
@@ -144,6 +145,7 @@ class RoadGrid: public Reference {
|
|||||||
GDCLASS(RoadGrid, Object)
|
GDCLASS(RoadGrid, Object)
|
||||||
protected:
|
protected:
|
||||||
Ref<RandomNumberGenerator> rnd;
|
Ref<RandomNumberGenerator> rnd;
|
||||||
|
Ref<AStar> astar;
|
||||||
int keep_seed;
|
int keep_seed;
|
||||||
List<struct cluster> clusters;
|
List<struct cluster> clusters;
|
||||||
Rect2 bounds;
|
Rect2 bounds;
|
||||||
@@ -209,10 +211,7 @@ protected:
|
|||||||
}
|
}
|
||||||
inline void insert_hedge_to_grid_cell(int x, int y, struct half_edge *hedge)
|
inline void insert_hedge_to_grid_cell(int x, int y, struct half_edge *hedge)
|
||||||
{
|
{
|
||||||
static int count = 0;
|
|
||||||
count++;
|
|
||||||
set(x, y, hedge);
|
set(x, y, hedge);
|
||||||
printf("count: %d\n", count);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
class hg hedge_grid;
|
class hg hedge_grid;
|
||||||
@@ -252,6 +251,7 @@ protected:
|
|||||||
}
|
}
|
||||||
float grid_width, grid_height;
|
float grid_width, grid_height;
|
||||||
void sort_angle(Vector<int> &sort_data);
|
void sort_angle(Vector<int> &sort_data);
|
||||||
|
void smooth_heights();
|
||||||
public:
|
public:
|
||||||
void build(Ref<Curve> curve, Ref<FastNoiseLite> noise);
|
void build(Ref<Curve> curve, Ref<FastNoiseLite> noise);
|
||||||
void draw_debug(Node *drawable, int size_x, int size_y) const;
|
void draw_debug(Node *drawable, int size_x, int size_y) const;
|
||||||
@@ -369,5 +369,31 @@ public:
|
|||||||
{
|
{
|
||||||
return map_sites[site].site_type;
|
return map_sites[site].site_type;
|
||||||
}
|
}
|
||||||
|
PoolVector<Vector3> get_site_border(int site, float offt);
|
||||||
|
PoolVector<Vector3> get_site_radial_points(int site, float bofft, float offt);
|
||||||
|
Ref<AStar> get_astar() const
|
||||||
|
{
|
||||||
|
return astar;
|
||||||
|
}
|
||||||
|
inline int get_closest_point(Vector3 to_position, bool include_disabled=false) const
|
||||||
|
{
|
||||||
|
return astar->get_closest_point(to_position, include_disabled);
|
||||||
|
}
|
||||||
|
inline Vector3 get_closest_position_in_segment(Vector3 to_position) const
|
||||||
|
{
|
||||||
|
return astar->get_closest_position_in_segment(to_position);
|
||||||
|
}
|
||||||
|
inline PoolVector<Vector3> get_point_path(int p_from_id, int p_to_id)
|
||||||
|
{
|
||||||
|
return astar->get_point_path(p_from_id, p_to_id);
|
||||||
|
}
|
||||||
|
inline PoolVector<int> get_id_path(int p_from_id, int p_to_id)
|
||||||
|
{
|
||||||
|
return astar->get_id_path(p_from_id, p_to_id);
|
||||||
|
}
|
||||||
|
inline Vector3 get_point_position(int p_id) const
|
||||||
|
{
|
||||||
|
return astar->get_point_position(p_id);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ Array Roads::curve_mesh(const PoolVector<Vector3> &points,
|
|||||||
Vector3 base = verts[k];
|
Vector3 base = verts[k];
|
||||||
float point = t + 2.0 + base.z;
|
float point = t + 2.0 + base.z;
|
||||||
float right = verts[k].x + tx;
|
float right = verts[k].x + tx;
|
||||||
if (t <= l - 2.0) {
|
if (t < l - 2.0) {
|
||||||
offt1 = curve3->interpolate_baked(point, true);
|
offt1 = curve3->interpolate_baked(point, true);
|
||||||
offt2 = curve3->interpolate_baked(point + 2.0, true);
|
offt2 = curve3->interpolate_baked(point + 2.0, true);
|
||||||
assert(offt1.distance_squared_to(offt2) > 0.0f);
|
assert(offt1.distance_squared_to(offt2) > 0.0f);
|
||||||
@@ -564,12 +564,22 @@ void RoadsData::_bind_methods()
|
|||||||
ClassDB::bind_method(D_METHOD("get_site_polygon_3d", "site"), &RoadsData::get_site_polygon_3d);
|
ClassDB::bind_method(D_METHOD("get_site_polygon_3d", "site"), &RoadsData::get_site_polygon_3d);
|
||||||
ClassDB::bind_method(D_METHOD("get_here_sites", "position"), &RoadsData::get_here_sites);
|
ClassDB::bind_method(D_METHOD("get_here_sites", "position"), &RoadsData::get_here_sites);
|
||||||
ClassDB::bind_method(D_METHOD("get_site_avg_height", "site"), &RoadsData::get_site_avg_height);
|
ClassDB::bind_method(D_METHOD("get_site_avg_height", "site"), &RoadsData::get_site_avg_height);
|
||||||
|
#if 0
|
||||||
ClassDB::bind_method(D_METHOD("get_site_border", "site"), &RoadsData::get_site_border);
|
ClassDB::bind_method(D_METHOD("get_site_border", "site"), &RoadsData::get_site_border);
|
||||||
|
#endif
|
||||||
ClassDB::bind_method(D_METHOD("site_is_town", "site"), &RoadsData::site_is_town);
|
ClassDB::bind_method(D_METHOD("site_is_town", "site"), &RoadsData::site_is_town);
|
||||||
ClassDB::bind_method(D_METHOD("site_is_farm", "site"), &RoadsData::site_is_farm);
|
ClassDB::bind_method(D_METHOD("site_is_farm", "site"), &RoadsData::site_is_farm);
|
||||||
ClassDB::bind_method(D_METHOD("get_site_count"), &RoadsData::get_site_count);
|
ClassDB::bind_method(D_METHOD("get_site_count"), &RoadsData::get_site_count);
|
||||||
ClassDB::bind_method(D_METHOD("save_json", "path"), &RoadsData::save_json);
|
ClassDB::bind_method(D_METHOD("save_json", "path"), &RoadsData::save_json);
|
||||||
ClassDB::bind_method(D_METHOD("get_site_type", "site"), &RoadsData::get_site_type);
|
ClassDB::bind_method(D_METHOD("get_site_type", "site"), &RoadsData::get_site_type);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_site_border", "site", "offt"), &RoadsData::get_site_border);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_site_radial_points", "site", "bofft", "offt"), &RoadsData::get_site_radial_points);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_closest_point", "to_position"), &RoadsData::get_closest_point);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_closest_position_in_segment", "to_position"), &RoadsData::get_closest_position_in_segment);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_point_path", "p_from_id", "p_to_id"), &RoadsData::get_point_path);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_id_path", "p_from_id", "p_to_id"), &RoadsData::get_id_path);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_point_position", "p_id"), &RoadsData::get_point_position);
|
||||||
|
|
||||||
}
|
}
|
||||||
void RoadsData::set_noise(Ref<FastNoiseLite> noise)
|
void RoadsData::set_noise(Ref<FastNoiseLite> noise)
|
||||||
{
|
{
|
||||||
@@ -606,7 +616,7 @@ float RoadsData::get_sdf(int x, int y, int z)
|
|||||||
int site = rg->get_site_from_point(x, z);
|
int site = rg->get_site_from_point(x, z);
|
||||||
// printf("in site %d %d %d\n", site, rg->site_is_town(site), rg->site_is_farm(site));
|
// printf("in site %d %d %d\n", site, rg->site_is_town(site), rg->site_is_farm(site));
|
||||||
if (site >= 0 && (rg->site_is_town(site) || rg->site_is_farm(site))) {
|
if (site >= 0 && (rg->site_is_town(site) || rg->site_is_farm(site))) {
|
||||||
ret = y - rg->get_site_avg_height(site) - CLAMP(n * 0.1f, -0.5f, 0.5f);
|
ret = y - rg->get_site_avg_height(site) - CLAMP(n * 0.1f, -0.05f, 0.05f);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#ifndef ROADS_H
|
||||||
|
#define ROADS_H
|
||||||
#include <modules/world/road_grid.h>
|
#include <modules/world/road_grid.h>
|
||||||
|
|
||||||
#include <scene/main/node.h>
|
#include <scene/main/node.h>
|
||||||
@@ -128,10 +130,12 @@ public:
|
|||||||
{
|
{
|
||||||
rg->save_json(path);
|
rg->save_json(path);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
inline PoolVector<Vector3> get_site_border(int site)
|
inline PoolVector<Vector3> get_site_border(int site)
|
||||||
{
|
{
|
||||||
return rg->get_site_border(site);
|
return rg->get_site_border(site);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
inline int get_site_count() const
|
inline int get_site_count() const
|
||||||
{
|
{
|
||||||
return rg->get_site_count();
|
return rg->get_site_count();
|
||||||
@@ -140,5 +144,38 @@ public:
|
|||||||
{
|
{
|
||||||
return rg->get_site_type(site);
|
return rg->get_site_type(site);
|
||||||
}
|
}
|
||||||
|
inline PoolVector<Vector3> get_site_border(int site, float offt)
|
||||||
|
{
|
||||||
|
return rg->get_site_border(site, offt);
|
||||||
|
}
|
||||||
|
inline PoolVector<Vector3> get_site_radial_points(int site, float bofft, float offt)
|
||||||
|
{
|
||||||
|
return rg->get_site_radial_points(site, bofft, offt);
|
||||||
|
}
|
||||||
|
inline Ref<AStar> get_astar() const
|
||||||
|
{
|
||||||
|
return rg->get_astar();
|
||||||
|
}
|
||||||
|
inline int get_closest_point(Vector3 to_position, bool include_disabled=false) const
|
||||||
|
{
|
||||||
|
return rg->get_closest_point(to_position, include_disabled);
|
||||||
|
}
|
||||||
|
inline Vector3 get_closest_position_in_segment(Vector3 to_position) const
|
||||||
|
{
|
||||||
|
return rg->get_closest_position_in_segment(to_position);
|
||||||
|
}
|
||||||
|
inline PoolVector<Vector3> get_point_path(int p_from_id, int p_to_id)
|
||||||
|
{
|
||||||
|
return rg->get_point_path(p_from_id, p_to_id);
|
||||||
|
}
|
||||||
|
inline PoolVector<int> get_id_path(int p_from_id, int p_to_id)
|
||||||
|
{
|
||||||
|
return rg->get_id_path(p_from_id, p_to_id);
|
||||||
|
}
|
||||||
|
inline Vector3 get_point_position(int p_id) const
|
||||||
|
{
|
||||||
|
return rg->get_point_position(p_id);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|||||||
182
modules/world/spawner.cpp
Normal file
182
modules/world/spawner.cpp
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
#include <cassert>
|
||||||
|
#include <scene/main/viewport.h>
|
||||||
|
#include <scene/3d/camera.h>
|
||||||
|
#include "spawner.h"
|
||||||
|
static Spawner *g_spawner_data = NULL;
|
||||||
|
Spawner * Spawner::get_singleton()
|
||||||
|
{
|
||||||
|
return g_spawner_data;
|
||||||
|
}
|
||||||
|
void Spawner::create_singleton()
|
||||||
|
{
|
||||||
|
g_spawner_data = memnew(Spawner);
|
||||||
|
}
|
||||||
|
void Spawner::destroy_singleton()
|
||||||
|
{
|
||||||
|
memdelete(g_spawner_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spawner::_bind_methods()
|
||||||
|
{
|
||||||
|
ClassDB::bind_method(D_METHOD("add_scene", "name", "scene"), &Spawner::add_scene);
|
||||||
|
ClassDB::bind_method(D_METHOD("remove_scene", "name"), &Spawner::remove_scene);
|
||||||
|
ClassDB::bind_method(D_METHOD("place_scene", "name", "place"), &Spawner::place_scene);
|
||||||
|
ClassDB::bind_method(D_METHOD("place_scene_relative", "name", "parent", "place"), &Spawner::place_scene_relative);
|
||||||
|
ClassDB::bind_method(D_METHOD("update_view", "node", "distance"), &Spawner::update_view);
|
||||||
|
}
|
||||||
|
void Spawner::add_scene(const StringName &name, Ref<PackedScene> scene)
|
||||||
|
{
|
||||||
|
lock.lock();
|
||||||
|
if (!scenes.has(name)) {
|
||||||
|
scenes[name] = scene;
|
||||||
|
positions[name] = PoolVector<struct spawn_object>();
|
||||||
|
}
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
void Spawner::remove_scene(const StringName &name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
lock.lock();
|
||||||
|
PoolVector<struct spawn_object> pos = positions[name];
|
||||||
|
for (i = 0; i < pos.size(); i++) {
|
||||||
|
if (!pos[i].active)
|
||||||
|
continue;
|
||||||
|
Object *po = ObjectDB::get_instance(pos[i].instance);
|
||||||
|
if (po) {
|
||||||
|
Node *pn = Object::cast_to<Node>(po);
|
||||||
|
if (pn)
|
||||||
|
pn->queue_delete();
|
||||||
|
}
|
||||||
|
pos.write()[i].active = false;
|
||||||
|
}
|
||||||
|
positions.erase(name);
|
||||||
|
scenes.erase(name);
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
void Spawner::place_scene(const StringName &name, const Transform &place)
|
||||||
|
{
|
||||||
|
lock.lock();
|
||||||
|
if (scenes.has(name)) {
|
||||||
|
struct spawn_object obj;
|
||||||
|
obj.xform = place;
|
||||||
|
obj.active = false;
|
||||||
|
obj.pooled = false;
|
||||||
|
obj.instance = -1;
|
||||||
|
PoolVector<struct spawn_object> pos = positions[name];
|
||||||
|
pos.resize(pos.size() + 1);
|
||||||
|
pos.write()[pos.size() - 1] = obj;
|
||||||
|
positions[name] = pos;
|
||||||
|
force_update = true;
|
||||||
|
}
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
void Spawner::place_scene_relative(const StringName &name, Node *parent, const Transform &place)
|
||||||
|
{
|
||||||
|
if (!parent)
|
||||||
|
return;
|
||||||
|
lock.lock();
|
||||||
|
if (scenes.has(name)) {
|
||||||
|
Node *n = scenes[name]->instance();
|
||||||
|
Spatial *sp = Object::cast_to<Spatial>(n);
|
||||||
|
sp->set_transform(place);
|
||||||
|
parent->call_deferred("add_child", sp);
|
||||||
|
}
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
void Spawner::update_view(Node *node, float distance)
|
||||||
|
{
|
||||||
|
if (!node)
|
||||||
|
return;
|
||||||
|
Viewport *view = node->get_viewport();
|
||||||
|
if (!view)
|
||||||
|
return;
|
||||||
|
Camera *cam = view->get_camera();
|
||||||
|
if (!cam)
|
||||||
|
return;
|
||||||
|
Transform cam_xform = cam->get_global_transform();
|
||||||
|
Vector3 org = cam_xform.origin;
|
||||||
|
if (org.distance_squared_to(last_org) < 64.0f && !force_update)
|
||||||
|
return;
|
||||||
|
last_org = org;
|
||||||
|
const String *key;
|
||||||
|
lock.lock();
|
||||||
|
for (key = positions.next(NULL); key; key = positions.next(key)) {
|
||||||
|
int i;
|
||||||
|
PoolVector<struct spawn_object> pos = positions[*key];
|
||||||
|
for (i = 0; i < pos.size(); i++) {
|
||||||
|
if (!pos[i].active && !pos[i].pooled) {
|
||||||
|
Transform x = pos[i].xform;
|
||||||
|
float d = org.distance_squared_to(x.origin);
|
||||||
|
if (d < distance * distance && pos[i].instance < 0) {
|
||||||
|
int j;
|
||||||
|
Node *pn = NULL;
|
||||||
|
bool pooling = false;
|
||||||
|
if (pos.size() > 4) {
|
||||||
|
for (j = 0; j < pos.size(); j++) {
|
||||||
|
if (j == i)
|
||||||
|
continue;
|
||||||
|
if (!pos[j].active && pos[j].instance >= 0 && pos[j].pooled) {
|
||||||
|
pos.write()[i].instance = pos[j].instance;
|
||||||
|
pos.write()[j].instance = -1;
|
||||||
|
pos.write()[j].pooled = false;
|
||||||
|
Object *po = ObjectDB::get_instance(pos[i].instance);
|
||||||
|
if (po) {
|
||||||
|
pn = Object::cast_to<Node>(po);
|
||||||
|
if (pn) {
|
||||||
|
pooling = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pn)
|
||||||
|
pn = scenes[*key]->instance();
|
||||||
|
assert(pn);
|
||||||
|
if (pn) {
|
||||||
|
Spatial *sp = Object::cast_to<Spatial>(pn);
|
||||||
|
assert(sp);
|
||||||
|
if (sp) {
|
||||||
|
if (!pooling)
|
||||||
|
view->add_child(sp);
|
||||||
|
sp->set_global_transform(x);
|
||||||
|
pos.write()[i].instance = sp->get_instance_id();
|
||||||
|
pos.write()[i].active = true;
|
||||||
|
pos.write()[i].pooled = false;
|
||||||
|
sp->show();
|
||||||
|
} else
|
||||||
|
memfree(pn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (pos[i].active) {
|
||||||
|
Transform x = pos[i].xform;
|
||||||
|
float d = org.distance_squared_to(x.origin);
|
||||||
|
if (d > distance * distance + 2500.0f) {
|
||||||
|
Object *po = ObjectDB::get_instance(pos[i].instance);
|
||||||
|
if (po) {
|
||||||
|
Node *pn = Object::cast_to<Node>(po);
|
||||||
|
if (pn)
|
||||||
|
pn->queue_delete();
|
||||||
|
}
|
||||||
|
pos.write()[i].active = false;
|
||||||
|
pos.write()[i].instance = -1;
|
||||||
|
pos.write()[i].pooled = false;
|
||||||
|
} else if (d > distance * distance + 600.0f) {
|
||||||
|
Object *po = ObjectDB::get_instance(pos[i].instance);
|
||||||
|
if (po) {
|
||||||
|
Spatial *pn = Object::cast_to<Spatial>(po);
|
||||||
|
pn->hide();
|
||||||
|
}
|
||||||
|
pos.write()[i].active = false;
|
||||||
|
pos.write()[i].pooled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
positions[*key] = pos;
|
||||||
|
}
|
||||||
|
force_update = false;
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
28
modules/world/spawner.h
Normal file
28
modules/world/spawner.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#include <scene/main/node.h>
|
||||||
|
#include <scene/resources/packed_scene.h>
|
||||||
|
class Spawner: public Object {
|
||||||
|
GDCLASS(Spawner, Object);
|
||||||
|
protected:
|
||||||
|
Vector3 last_org;
|
||||||
|
bool force_update;
|
||||||
|
HashMap<String, Ref<PackedScene> > scenes;
|
||||||
|
struct spawn_object {
|
||||||
|
Transform xform;
|
||||||
|
bool active;
|
||||||
|
bool pooled;
|
||||||
|
int instance;
|
||||||
|
};
|
||||||
|
HashMap<String, PoolVector<struct spawn_object> > positions;
|
||||||
|
Mutex lock;
|
||||||
|
static void _bind_methods();
|
||||||
|
public:
|
||||||
|
void add_scene(const StringName &name, Ref<PackedScene> scene);
|
||||||
|
void remove_scene(const StringName &name);
|
||||||
|
void place_scene(const StringName &name, const Transform &place);
|
||||||
|
void place_scene_relative(const StringName &name, Node *parent, const Transform &place);
|
||||||
|
void update_view(Node *node, float distance);
|
||||||
|
static void create_singleton();
|
||||||
|
static void destroy_singleton();
|
||||||
|
static Spawner *get_singleton();
|
||||||
|
};
|
||||||
|
|
||||||
324
modules/world/traffic.cpp
Normal file
324
modules/world/traffic.cpp
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
#include <cassert>
|
||||||
|
#include <core/resource.h>
|
||||||
|
#include <core/os/os.h>
|
||||||
|
#include <scene/main/scene_tree.h>
|
||||||
|
#include <scene/main/viewport.h>
|
||||||
|
#include <scene/3d/camera.h>
|
||||||
|
#include <scene/resources/packed_scene.h>
|
||||||
|
#include <scene/3d/vehicle_body.h>
|
||||||
|
|
||||||
|
#include "traffic.h"
|
||||||
|
|
||||||
|
Traffic::Traffic(): max_spawn_distance(120.0f),
|
||||||
|
min_spawn_distance(80),
|
||||||
|
delete_distance(Vector3(100.0f, -60.0f, 180.0f)),
|
||||||
|
physics_distance(Vector3(30.0f, -20.0f, 60.0f)),
|
||||||
|
list_cooldown(0.0), debug(false)
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
rnd.instance();
|
||||||
|
rnd->randomize();
|
||||||
|
call_deferred("idle_runner");
|
||||||
|
}
|
||||||
|
|
||||||
|
Traffic::~Traffic()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Traffic::_bind_methods()
|
||||||
|
{
|
||||||
|
ClassDB::bind_method(D_METHOD("idle_runner"), &Traffic::idle_runner);
|
||||||
|
ClassDB::bind_method(D_METHOD("add_traffic_vehicle", "scene"), &Traffic::add_traffic_vehicle);
|
||||||
|
ClassDB::bind_method(D_METHOD("remove_traffic_vehicle", "scene"), &Traffic::remove_traffic_vehicle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Traffic::add_traffic_vehicle(Ref<PackedScene> scene)
|
||||||
|
{
|
||||||
|
scenes.push_back(scene);
|
||||||
|
printf("traffic: added_scene: %d\n", scenes.size());
|
||||||
|
}
|
||||||
|
void Traffic::remove_traffic_vehicle(Ref<PackedScene> scene)
|
||||||
|
{
|
||||||
|
scenes.erase(scene);
|
||||||
|
printf("traffic: removed_scene: %d\n", scenes.size());
|
||||||
|
}
|
||||||
|
void Traffic::idle_runner()
|
||||||
|
{
|
||||||
|
uint64_t before, after;
|
||||||
|
float delta;
|
||||||
|
|
||||||
|
SceneTree *tree = SceneTree::get_singleton();
|
||||||
|
Viewport *view;
|
||||||
|
Camera *camera;
|
||||||
|
Transform cam_xform;
|
||||||
|
before = OS::get_singleton()->get_ticks_usec();
|
||||||
|
assert(tree);
|
||||||
|
delta = tree->get_idle_process_time();
|
||||||
|
if (state > 0 && debug)
|
||||||
|
debug_traffic();
|
||||||
|
|
||||||
|
if (state > 0)
|
||||||
|
control_traffic();
|
||||||
|
|
||||||
|
switch(state) {
|
||||||
|
case 0:
|
||||||
|
debug_mat.instance();
|
||||||
|
debug_mat->set_flag(SpatialMaterial::FLAG_DISABLE_DEPTH_TEST, true);
|
||||||
|
debug_mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
|
||||||
|
debug_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
|
||||||
|
instance = VS::get_singleton()->instance_create();
|
||||||
|
VS::get_singleton()->instance_set_scenario(instance, tree->get_root()->get_world()->get_scenario());
|
||||||
|
immediate = VS::get_singleton()->immediate_create();
|
||||||
|
VisualServer::get_singleton()->instance_set_base(instance, immediate);
|
||||||
|
VS::get_singleton()->immediate_set_material(immediate, debug_mat->get_rid());
|
||||||
|
tree->connect("idle_frame", this, "idle_runner");
|
||||||
|
state = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (list_cooldown > 0.0f) {
|
||||||
|
list_cooldown -= delta;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tree->get_nodes_in_group("traffic_spawn", &spawner_list);
|
||||||
|
spawner_e = spawner_list.front();
|
||||||
|
list_cooldown = 0.1f;
|
||||||
|
if (spawner_list.size() > 0)
|
||||||
|
state = 2;
|
||||||
|
spawn_cooldown = 0.0f;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (scenes.size() == 0)
|
||||||
|
return;
|
||||||
|
if (!spawner_e) {
|
||||||
|
state = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (spawn_cooldown > 0.0f) {
|
||||||
|
spawn_cooldown -= delta;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
view = tree->get_root();
|
||||||
|
if (!view)
|
||||||
|
return;
|
||||||
|
camera = view->get_camera();
|
||||||
|
if (!camera)
|
||||||
|
return;
|
||||||
|
cam_xform = camera->get_global_transform();
|
||||||
|
while (spawner_e) {
|
||||||
|
float dst;
|
||||||
|
VehicleBody *vb;
|
||||||
|
Node *nscene;
|
||||||
|
Spatial *sscene;
|
||||||
|
Transform xform;
|
||||||
|
Ref<PackedScene> scene;
|
||||||
|
Vector3 check_coordinates;
|
||||||
|
|
||||||
|
after = OS::get_singleton()->get_ticks_usec();
|
||||||
|
if (after - before > 2000ULL)
|
||||||
|
break;
|
||||||
|
Node *spawner;
|
||||||
|
Spatial *obj;
|
||||||
|
spawner = spawner_e->get();
|
||||||
|
if (!spawner)
|
||||||
|
goto pass_loop;
|
||||||
|
if (!spawner->is_in_group("spawn"))
|
||||||
|
goto pass_loop;
|
||||||
|
obj = Object::cast_to<Spatial>(spawner);
|
||||||
|
if (!obj)
|
||||||
|
goto pass_loop;
|
||||||
|
if (obj->has_meta("cooldown")) {
|
||||||
|
float cooldown = obj->get_meta("cooldown");
|
||||||
|
cooldown -= delta;
|
||||||
|
if (cooldown >= 0.0f) {
|
||||||
|
obj->set_meta("cooldown", cooldown);
|
||||||
|
goto pass_loop;
|
||||||
|
} else
|
||||||
|
obj->remove_meta("cooldown");
|
||||||
|
}
|
||||||
|
xform = obj->get_global_transform();
|
||||||
|
check_coordinates = cam_xform.xform_inv(xform.origin);
|
||||||
|
if (check_coordinates.z > -15.0f && check_coordinates.z < min_spawn_distance && fabsf(check_coordinates.x) < 20.0 )
|
||||||
|
goto pass_loop;
|
||||||
|
dst = xform.origin.distance_squared_to(cam_xform.origin);
|
||||||
|
if (check_coordinates.z > max_spawn_distance || check_coordinates.z < -50.0f || fabsf(check_coordinates.x) > 50.0f)
|
||||||
|
goto pass_loop;
|
||||||
|
printf("traffic: spawning scene\n");
|
||||||
|
scene = scenes[rnd->randi() % scenes.size()];
|
||||||
|
nscene = scene->instance();
|
||||||
|
sscene = Object::cast_to<Spatial>(nscene);
|
||||||
|
view->add_child(sscene);
|
||||||
|
sscene->set_global_transform(xform);
|
||||||
|
sscene->add_to_group("traffic_vehicle");
|
||||||
|
sscene->set("parked", false);
|
||||||
|
vb = Object::cast_to<VehicleBody>(nscene);
|
||||||
|
if (vb) {
|
||||||
|
vb->set_engine_force(2500.0f);
|
||||||
|
vb->set_steering(0);
|
||||||
|
RID space = PhysicsServer::get_singleton()->body_get_space(vb->get_rid());
|
||||||
|
vb->set_meta("space", space);
|
||||||
|
PhysicsServer::get_singleton()->body_set_space(vb->get_rid(), RID());
|
||||||
|
}
|
||||||
|
obj->set_meta("cooldown", 30.0f + rnd->randf() * 30.0);
|
||||||
|
spawn_cooldown = 0.2f;
|
||||||
|
pass_loop:
|
||||||
|
spawner_e = spawner_e->next();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
void Traffic::debug_traffic()
|
||||||
|
{
|
||||||
|
SceneTree *tree = SceneTree::get_singleton();
|
||||||
|
List<Node *> traffic_vehicles;
|
||||||
|
List<Node *>::Element *e;
|
||||||
|
tree->get_nodes_in_group("traffic_vehicle", &traffic_vehicles);
|
||||||
|
VS::get_singleton()->immediate_clear(immediate);
|
||||||
|
if (traffic_vehicles.size() == 0)
|
||||||
|
return;
|
||||||
|
printf("traffic: vehicles: %d\n", traffic_vehicles.size());
|
||||||
|
VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_LINES);
|
||||||
|
for (e = traffic_vehicles.front(); e; e = e->next()) {
|
||||||
|
Node *vnode = e->get();
|
||||||
|
if (!vnode)
|
||||||
|
continue;
|
||||||
|
Spatial *vsp = Object::cast_to<Spatial>(vnode);
|
||||||
|
if (!vsp)
|
||||||
|
continue;
|
||||||
|
Transform vxform = vsp->get_global_transform();
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(1, 0, 0, 1));
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, vxform.origin);
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(0, 0, 1, 1));
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, vxform.origin + Vector3(0, 30, 0));
|
||||||
|
if (vsp->has_meta("next_target")) {
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(1, 0, 0, 1));
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, vxform.origin);
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(1, 0, 0, 1));
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, vsp->get_meta("next_target"));
|
||||||
|
}
|
||||||
|
if (vsp->has_meta("target")) {
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(1, 0, 1, 1));
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, vxform.origin);
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(1, 0, 1, 1));
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, vsp->get_meta("target"));
|
||||||
|
}
|
||||||
|
if (vsp->has_meta("x_target")) {
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(0, 1, 0, 1));
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, vxform.origin);
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(0, 1, 0, 1));
|
||||||
|
Vector3 vp = vsp->get_meta("x_target");
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, vxform.xform(vp));
|
||||||
|
}
|
||||||
|
if (vsp->has_meta("vel")) {
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(1, 1, 1, 1));
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, vxform.origin);
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(0, 0, 1, 1));
|
||||||
|
Vector3 vp = vsp->get_meta("vel");
|
||||||
|
if (vp.length_squared() == 0.0f) {
|
||||||
|
vp += Vector3(0, 2, 0);
|
||||||
|
}
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, vxform.xform(vp));
|
||||||
|
}
|
||||||
|
if (vsp->has_meta("curve")) {
|
||||||
|
Ref<Curve3D> curve = vsp->get_meta("curve");
|
||||||
|
if (curve->get_point_count() > 0) {
|
||||||
|
float offt = curve->get_closest_offset(vxform.origin);
|
||||||
|
float plength = curve->get_baked_length();
|
||||||
|
float pstart = CLAMP(offt - 4.0f, 0.0f, plength);
|
||||||
|
Vector3 pt = curve->interpolate_baked(offt, false);
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(1, 1, 1, 1));
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, vxform.origin);
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(0, 1, 0, 1));
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, pt);
|
||||||
|
while (pstart < offt + 8.0 && pstart < plength) {
|
||||||
|
Vector3 opt = curve->interpolate_baked(pstart, false);
|
||||||
|
float c = (pstart - offt + 4.0) / 16.0f;
|
||||||
|
c = CLAMP(c, 0.0f, 1.0f);
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(1, c, c, 1));
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, opt);
|
||||||
|
VS::get_singleton()->immediate_color(immediate, Color(1, c, c, 1));
|
||||||
|
VS::get_singleton()->immediate_vertex(immediate, opt + Vector3(0, 10, 0));
|
||||||
|
pstart += 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VS::get_singleton()->immediate_end(immediate);
|
||||||
|
}
|
||||||
|
void Traffic::control_traffic()
|
||||||
|
{
|
||||||
|
Viewport *view;
|
||||||
|
Camera *camera;
|
||||||
|
Transform cam_xform;
|
||||||
|
SceneTree *tree = SceneTree::get_singleton();
|
||||||
|
List<Node *> traffic_vehicles;
|
||||||
|
List<Node *>::Element *e;
|
||||||
|
tree->get_nodes_in_group("traffic_vehicle", &traffic_vehicles);
|
||||||
|
view = tree->get_root();
|
||||||
|
camera = view->get_camera();
|
||||||
|
cam_xform = camera->get_global_transform();
|
||||||
|
for (e = traffic_vehicles.front(); e; e = e->next()) {
|
||||||
|
Node *node = e->get();
|
||||||
|
Spatial *sp = Object::cast_to<Spatial>(node);
|
||||||
|
Transform xform = sp->get_global_transform();
|
||||||
|
Vector3 check = cam_xform.xform_inv(xform.origin);
|
||||||
|
/* TODO: use AABB instead */
|
||||||
|
if (fabsf(check.x) > delete_distance.x ||
|
||||||
|
check.z > delete_distance.z ||
|
||||||
|
check.z < delete_distance.y)
|
||||||
|
sp->queue_delete();
|
||||||
|
else if (fabsf(check.x) > physics_distance.x + 1.0f ||
|
||||||
|
check.z > physics_distance.z + 1.0f ||
|
||||||
|
check.z < physics_distance.y - 1) {
|
||||||
|
if (!sp->has_meta("space"))
|
||||||
|
vehicle_disable_physics(sp);
|
||||||
|
} else if (fabsf(check.x) < physics_distance.x - 1.0f ||
|
||||||
|
check.z < physics_distance.z - 1.0f ||
|
||||||
|
check.z > physics_distance.y + 1) {
|
||||||
|
if (sp->has_meta("space"))
|
||||||
|
vehicle_enable_physics(sp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Traffic::vehicle_enable_physics(Spatial *obj)
|
||||||
|
{
|
||||||
|
RigidBody *body = Object::cast_to<RigidBody>(obj);
|
||||||
|
if (!body)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RID space = obj->get_meta("space");
|
||||||
|
PhysicsServer::get_singleton()->body_set_space(body->get_rid(), space);
|
||||||
|
obj->remove_meta("space");
|
||||||
|
if (obj->has_meta("velocity")) {
|
||||||
|
Vector3 velocity = obj->get_meta("velocity");
|
||||||
|
body->set_linear_velocity(velocity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Traffic::vehicle_disable_physics(Spatial *obj)
|
||||||
|
{
|
||||||
|
RigidBody *body = Object::cast_to<RigidBody>(obj);
|
||||||
|
if (!body)
|
||||||
|
return;
|
||||||
|
RID space = PhysicsServer::get_singleton()->body_get_space(body->get_rid());
|
||||||
|
Vector3 velocity = body->get_linear_velocity();
|
||||||
|
obj->set_meta("space", space);
|
||||||
|
obj->set_meta("velocity", velocity);
|
||||||
|
PhysicsServer::get_singleton()->body_set_space(body->get_rid(), RID());
|
||||||
|
}
|
||||||
|
|
||||||
|
static Traffic *g_traffic_data = NULL;
|
||||||
|
Traffic *Traffic::get_singleton()
|
||||||
|
{
|
||||||
|
return g_traffic_data;
|
||||||
|
}
|
||||||
|
void Traffic::create_singleton()
|
||||||
|
{
|
||||||
|
g_traffic_data = memnew(Traffic);
|
||||||
|
}
|
||||||
|
void Traffic::destroy_singleton()
|
||||||
|
{
|
||||||
|
memdelete(g_traffic_data);
|
||||||
|
g_traffic_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
48
modules/world/traffic.h
Normal file
48
modules/world/traffic.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#include <modules/world/roads.h>
|
||||||
|
class Traffic: public Object {
|
||||||
|
GDCLASS(Traffic, Object);
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
Vector<Ref<PackedScene> > scenes;
|
||||||
|
int state;
|
||||||
|
List<Node *> spawner_list;
|
||||||
|
List<Node *>::Element *spawner_e;
|
||||||
|
float max_spawn_distance;
|
||||||
|
float min_spawn_distance;
|
||||||
|
Vector3 delete_distance,
|
||||||
|
physics_distance;
|
||||||
|
Ref<RandomNumberGenerator> rnd;
|
||||||
|
float list_cooldown, spawn_cooldown;
|
||||||
|
RID immediate, instance;
|
||||||
|
Ref<SpatialMaterial> debug_mat;
|
||||||
|
bool debug;
|
||||||
|
|
||||||
|
void debug_traffic();
|
||||||
|
void control_traffic();
|
||||||
|
void vehicle_enable_physics(Spatial *obj);
|
||||||
|
void vehicle_disable_physics(Spatial *obj);
|
||||||
|
public:
|
||||||
|
Traffic();
|
||||||
|
~Traffic();
|
||||||
|
void add_traffic_vehicle(Ref<PackedScene> scene);
|
||||||
|
void remove_traffic_vehicle(Ref<PackedScene> scene);
|
||||||
|
void idle_runner();
|
||||||
|
|
||||||
|
inline void set_seed(int seed)
|
||||||
|
{
|
||||||
|
rnd->set_seed(seed);
|
||||||
|
}
|
||||||
|
inline int get_state()
|
||||||
|
{
|
||||||
|
return rnd->get_state();
|
||||||
|
}
|
||||||
|
inline void set_state(int seed)
|
||||||
|
{
|
||||||
|
rnd->set_state(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Traffic *get_singleton();
|
||||||
|
static void create_singleton();
|
||||||
|
static void destroy_singleton();
|
||||||
|
};
|
||||||
|
|
||||||
Reference in New Issue
Block a user