Initial commit
This commit is contained in:
178
modules/world/world_terrain_lod.cpp
Normal file
178
modules/world/world_terrain_lod.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
#include <core/hash_map.h>
|
||||
#include <core/math/vector3.h>
|
||||
#include <scene/resources/packed_scene.h>
|
||||
#include <scene/resources/primitive_meshes.h>
|
||||
#include <scene/3d/mesh_instance.h>
|
||||
#include "direct_lod_multimesh.h"
|
||||
#include "world_chunk.h"
|
||||
#include "terrain_object.h"
|
||||
#include "world_terrain_lod.h"
|
||||
|
||||
void WorldTerrainLod::init_lod(int mind, int maxd,
|
||||
float density_range)
|
||||
{
|
||||
int i;
|
||||
|
||||
min_dist = mind;
|
||||
max_dist = maxd;
|
||||
this->density_range = density_range;
|
||||
}
|
||||
void WorldTerrainLod::update()
|
||||
{
|
||||
}
|
||||
|
||||
void WorldTerrainLod::create_chunk(const WorldChunk *chunk, const List<TerrainObject> &obj_list)
|
||||
{
|
||||
int i, j, id;
|
||||
if (mesh_h.has(chunk->get_loc()))
|
||||
return;
|
||||
int lod_offset = 1 << chunk->get_lod();
|
||||
int obj_count = obj_list.size();
|
||||
printf("create_chunk started %d\n", obj_count);
|
||||
|
||||
LodMultiMesh3D *mi = memnew(LodMultiMesh3D);
|
||||
id = 0;
|
||||
int rcount = chunk->get_transforms_count() / lod_offset;
|
||||
const Transform *xfptr = chunk->get_transforms();
|
||||
const float *variances = chunk->get_variance();
|
||||
Vector<int> ids;
|
||||
ids.resize(rcount);
|
||||
printf("ids size: %d rcount: %d\n", ids.size(), rcount);
|
||||
HashMap<int, List<Transform> > instances;
|
||||
for (j = 0; j < rcount; j++) {
|
||||
float variance = variances[j * lod_offset];
|
||||
int obj_id = (int)(variance * obj_count);
|
||||
printf("3 %d %d", j, rcount);
|
||||
ids.write[j] = obj_id;
|
||||
if (!instances.has(obj_id))
|
||||
instances[obj_id] = List<Transform>();
|
||||
instances[obj_id].push_back(xfptr[j * lod_offset]);
|
||||
printf("6");
|
||||
}
|
||||
const List<TerrainObject>::Element *e = obj_list.front();
|
||||
int count = 0;
|
||||
while (e) {
|
||||
printf("obj: %d\n", count);
|
||||
const TerrainObject *obj = &e->get();
|
||||
if (!instances.has(count))
|
||||
instances[count] = List<Transform>();
|
||||
Ref<Mesh> mesh = obj->get_mesh(chunk->get_lod());
|
||||
printf("lod: %d mesh: %p, instance count: %d\n", chunk->get_lod(), mesh.ptr(), instances[count].size());
|
||||
mi->add_mesh(obj->get_mesh(chunk->get_lod()));
|
||||
mi->set_instance_count(count, instances[count].size());
|
||||
const List<Transform>::Element *ep = instances[count].front();
|
||||
int pcount = 0;
|
||||
while (ep) {
|
||||
const Transform &pxform = ep->get();
|
||||
printf("ep %d %d %ls\n", count, pcount, String(pxform.origin).c_str());
|
||||
mi->set_instance_transform(count, pcount++, pxform);
|
||||
ep = ep->next();
|
||||
}
|
||||
e = e->next();
|
||||
count++;
|
||||
}
|
||||
#if 0
|
||||
for (j = 0; j < mesh_grass.size(); j++) {
|
||||
if (!new_points[*org].has(j))
|
||||
continue;
|
||||
const List<struct new_point> &nps = new_points[*org][j];
|
||||
mi->add_mesh(mesh_grass[j]);
|
||||
mi->set_instance_count(id, nps.size());
|
||||
const List<struct new_point>::Element *e = nps.front();
|
||||
int icount = 0;
|
||||
while(e) {
|
||||
mi->set_instance_transform(id, icount++, e->get().xform);
|
||||
e = e->next();
|
||||
}
|
||||
id++;
|
||||
}
|
||||
#endif
|
||||
mi->hide();
|
||||
mi->set_world(NULL);
|
||||
mi->set_global_transform(Transform(Basis(), chunk->get_loc().to_vec3()));
|
||||
meshes.push_back(mi);
|
||||
mesh_h[chunk->get_loc()] = mi;
|
||||
mi->set_world(gworld.ptr());
|
||||
mi->show();
|
||||
}
|
||||
void WorldTerrainLod::cleanup(const Transform &vxform)
|
||||
{
|
||||
if (meshes.size() > 0)
|
||||
printf("meshes.size() %p %d\n", this, meshes.size());
|
||||
List<LodMultiMesh3D *>::Element *e = meshes.front();
|
||||
while(e) {
|
||||
LodMultiMesh3D *ve = e->get();
|
||||
List<LodMultiMesh3D *>::Element *ne = e->next();
|
||||
Vector3 rpos = ve->get_center();
|
||||
Vector3 vpos = vxform.origin;
|
||||
Vector3i loc(ve->get_global_transform().origin);
|
||||
if (!valid_org(vxform, ve->get_global_transform().origin, 0.5f)) {
|
||||
memfree(ve);
|
||||
meshes.erase(e);
|
||||
mesh_h.erase(loc);
|
||||
}
|
||||
e = ne;
|
||||
}
|
||||
}
|
||||
static inline bool too_close(const Transform &vxform, const Vector3 &org, float zmin)
|
||||
{
|
||||
Vector3 lpoint = vxform.xform_inv(org);
|
||||
if (-lpoint.z < zmin)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool WorldTerrainLod::valid_org(const Transform &vxform, const Vector3 &org, float margin) const
|
||||
{
|
||||
bool ret = true;
|
||||
float view_angle = M_PI / 3.0f;
|
||||
float view_s = Math::sin(view_angle);
|
||||
if (too_close(vxform, org, min_dist))
|
||||
return false;
|
||||
// if (vxform.origin.distance_squared_to(org) > max_dist * max_dist)
|
||||
// return false;
|
||||
//if (min_dist > 0 && vxform.origin.distance_squared_to(org) < min_dist * min_dist)
|
||||
// return false;
|
||||
Vector3 lpoint = vxform.xform_inv(org);
|
||||
/* View is in -Z direction */
|
||||
if (lpoint.z > -min_dist + margin || lpoint.z < -max_dist - margin)
|
||||
ret = false;
|
||||
if (lpoint.x < -view_s * max_dist -8.0f - margin|| lpoint.x > view_s * max_dist + 8.0f + margin)
|
||||
ret = false;
|
||||
if (lpoint.y < -36.0f || lpoint.y > 36.0f)
|
||||
ret = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WorldTerrainLod::update_visibility(const Transform &vxform)
|
||||
{
|
||||
List<LodMultiMesh3D *>::Element *e = meshes.front();
|
||||
|
||||
while(e) {
|
||||
LodMultiMesh3D *mi = e->get();
|
||||
Transform xform = mi->get_global_transform();
|
||||
// Vector3 lpoint = vxform.xform_inv(xform.origin);
|
||||
if (mi->is_visible() && !valid_org(vxform, xform.origin, 1.0f)) {
|
||||
mi->hide();
|
||||
mi->set_world(NULL);
|
||||
} else if (!mi->is_visible() && valid_org(vxform, xform.origin, 0.0f)) {
|
||||
mi->show();
|
||||
mi->set_world(gworld.ptr());
|
||||
}
|
||||
e = e->next();
|
||||
}
|
||||
}
|
||||
void WorldTerrainLod::set_world(Ref<World> world)
|
||||
{
|
||||
if (!world.ptr())
|
||||
printf("exited world %p\n", gworld.ptr());
|
||||
gworld = world;
|
||||
List<LodMultiMesh3D *>::Element *e = meshes.front();
|
||||
while(e) {
|
||||
LodMultiMesh3D *mi = e->get();
|
||||
mi->set_world(gworld.ptr());
|
||||
e = e->next();
|
||||
}
|
||||
if (gworld.ptr())
|
||||
printf("entered world %p\n", gworld.ptr());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user