Implemented meshing chunk's mesh data resources.

This commit is contained in:
Relintai 2020-06-28 19:02:49 +02:00
parent cb6d8f5156
commit 0138c02bf8
3 changed files with 99 additions and 159 deletions

View File

@ -439,125 +439,46 @@ void VoxelMesher::add_mesh_data_resource(Ref<MeshDataResource> mesh, const Vecto
}
void VoxelMesher::add_mesh_data_resource_transform(Ref<MeshDataResource> mesh, const Transform transform, const Rect2 uv_rect) {
ERR_FAIL_COND(mesh->get_array().size() == 0);
if (mesh->get_array().size() == 0)
return;
Array verts = mesh->get_array().get(Mesh::ARRAY_VERTEX);
const Array &arr = mesh->get_array();
for (int i = 0; i < verts.size(); ++i) {
Vector3 vert = verts[i];
PoolVector3Array vertices = arr[Mesh::ARRAY_VERTEX];
PoolVector3Array normals = arr[Mesh::ARRAY_NORMAL];
PoolVector2Array uvs = arr[Mesh::ARRAY_TEX_UV];
PoolColorArray colors = arr[Mesh::ARRAY_COLOR];
PoolIntArray indices = arr[Mesh::ARRAY_INDEX];
vert = transform.xform(vert);
if (vertices.size() == 0)
return;
add_vertex(vert);
int orig_vert_size = _vertices.size();
for (int i = 0; i < vertices.size(); ++i) {
if (normals.size() > 0)
add_normal(transform.basis.xform(normals[i]));
if (normals.size() > 0) {
Vector2 uv = uvs[i];
uv.x = uv_rect.size.width * uv.x + uv_rect.position.x;
uv.y = uv_rect.size.height * uv.y + uv_rect.position.y;
add_uv(uv);
}
if (colors.size() > 0)
add_color(colors[i]);
add_vertex(transform.xform(vertices[i]));
}
if (mesh->get_array().size() <= Mesh::ARRAY_NORMAL)
return;
Array normals = mesh->get_array().get(Mesh::ARRAY_NORMAL);
for (int i = 0; i < normals.size(); ++i) {
Vector3 normal = normals[i];
normal = transform.basis.xform(normal);
add_normal(normal);
}
/*
if (mesh->get_array().size() <= Mesh::ARRAY_TANGENT)
return;
Array tangents = mesh->get_array().get(Mesh::ARRAY_TANGENT);
for (int i = 0; i < verts.size(); ++i) {
Plane p(tangents[i * 4 + 0], tangents[i * 4 + 1], tangents[i * 4 + 2], tangents[i * 4 + 3]);
Vector3 tangent = p.normal;
Vector3 binormal = p.normal.cross(tangent).normalized() * p.d;
tangent = local_transform.basis.xform(tangent);
binormal = local_transform.basis.xform(binormal);
add_t(normal);
add_binorm
}*/
if (mesh->get_array().size() <= Mesh::ARRAY_COLOR)
return;
Array colors = mesh->get_array().get(Mesh::ARRAY_COLOR);
for (int i = 0; i < colors.size(); ++i) {
Color color = colors[i];
add_color(color);
}
if (mesh->get_array().size() <= Mesh::ARRAY_TEX_UV)
return;
Array tex_uv = mesh->get_array().get(Mesh::ARRAY_TEX_UV);
for (int i = 0; i < tex_uv.size(); ++i) {
Vector2 uv = tex_uv[i];
uv.x *= uv_rect.size.x;
uv.y *= uv_rect.size.y;
uv.x += uv_rect.position.x;
uv.y += uv_rect.position.y;
add_uv(uv);
}
/*
if (mesh->get_array().size() <= Mesh::ARRAY_TEX_UV2)
return;
Array tex_uv2 = mesh->get_array().get(Mesh::ARRAY_TEX_UV2);
for (int i = 0; i < tex_uv.size(); ++i) {
Vector2 uv = tex_uv2[i];
add_uv2(uv);
}*/
/*
if (mesh->get_array().size() <= Mesh::ARRAY_BONES)
return;
Array bones = mesh->get_array().get(Mesh::ARRAY_BONES);
for (int i = 0; i < bones.size(); ++i) {
int bone = bones[i];
add_bone(bone);
}*/
/*
if (mesh->get_array().size() <= Mesh::ARRAY_WEIGHTS)
return;
Array weights = mesh->get_array().get(Mesh::ARRAY_WEIGHTS);
for (int i = 0; i < weights.size(); ++i) {
float weight = weights[i];
add_weight(weight);
}*/
if (mesh->get_array().size() <= Mesh::ARRAY_INDEX)
return;
Array indices = mesh->get_array().get(Mesh::ARRAY_INDEX);
int ic = get_vertex_count() - verts.size();
int orig_indices_count = _indices.size();
_indices.resize(_indices.size() + indices.size());
for (int i = 0; i < indices.size(); ++i) {
int index = indices[i];
add_indices(ic + index);
_indices.set(orig_indices_count + i, orig_vert_size + indices[i]);
}
}
#endif

View File

@ -1103,6 +1103,14 @@ VoxelChunkDefault::~VoxelChunkDefault() {
}
_lights.clear();
#if MESH_DATA_RESOURCE_PRESENT
for (int i = 0; i < _collider_bodies.size(); ++i) {
PhysicsServer::get_singleton()->free(_collider_bodies[i]);
}
_collider_bodies.clear();
#endif
}
void VoxelChunkDefault::_setup_channels() {
@ -1150,10 +1158,6 @@ void VoxelChunkDefault::_build_phase(int phase) {
next_phase();
return;
}
case BUILD_PHASE_PROP_SETUP: {
next_phase();
return;
}
case BUILD_PHASE_TERRARIN_MESH_SETUP: {
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _meshers.get(i);
@ -1199,15 +1203,11 @@ void VoxelChunkDefault::_build_phase(int phase) {
}
}
for (int i = 0; i < _prop_meshers.size(); ++i) {
Ref<VoxelMesher> mesher = _prop_meshers.get(i);
ERR_CONTINUE(!mesher.is_valid());
temp_arr_collider.append_array(mesher->build_collider());
}
if (temp_arr_collider.size() == 0 && temp_arr_collider_liquid.size() == 0 && temp_arr_collider_prop.size() == 0) {
if (temp_arr_collider.size() == 0 && temp_arr_collider_liquid.size() == 0
#ifdef MESH_DATA_RESOURCE_PRESENT
&& get_mesh_data_resource_count() == 0
#endif
) {
next_phase();
return;
}
@ -1245,16 +1245,6 @@ void VoxelChunkDefault::_build_phase(int phase) {
temp_arr_collider_liquid.resize(0);
}
if (temp_arr_collider_prop.size() != 0) {
if (!has_meshes(MESH_INDEX_PROP, MESH_TYPE_INDEX_BODY)) {
create_colliders(MESH_INDEX_PROP);
}
PhysicsServer::get_singleton()->shape_set_data(get_mesh_rid(MESH_INDEX_PROP, MESH_TYPE_INDEX_SHAPE), temp_arr_collider_prop);
temp_arr_collider_prop.resize(0);
}
next_phase();
return;
@ -1477,12 +1467,21 @@ void VoxelChunkDefault::_build_phase(int phase) {
return;
}
case BUILD_PHASE_PROP_MESH: {
if (_props.size() == 0) {
#ifdef MESH_DATA_RESOURCE_PRESENT
case BUILD_PHASE_MESH_DATA_RESOURCES: {
if (get_mesh_data_resource_count() == 0) {
next_phase();
return;
}
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> m = _meshers.get(i);
ERR_CONTINUE(!m.is_valid());
m->add_mesh_data_resource_transform(get_mesh_data_resource(i), get_mesh_data_resource_transform(i), get_mesh_data_resource_uv_rect(i));
}
Ref<VoxelMesher> mesher;
for (int i = 0; i < _meshers.size(); ++i) {
Ref<VoxelMesher> m = _meshers.get(i);
@ -1533,8 +1532,8 @@ void VoxelChunkDefault::_build_phase(int phase) {
VS::get_singleton()->mesh_add_surface_from_arrays(mesh_rid, VisualServer::PRIMITIVE_TRIANGLES, temp_mesh_arr);
if (_library->get_material(0).is_valid())
VS::get_singleton()->mesh_surface_set_material(mesh_rid, 0, _library->get_material(0)->get_rid());
if (_library->get_prop_material(0).is_valid())
VS::get_singleton()->mesh_surface_set_material(mesh_rid, 0, _library->get_prop_material(0)->get_rid());
if ((_build_flags & BUILD_FLAG_CREATE_LODS) != 0) {
if (_lod_num >= 1) {
@ -1543,8 +1542,8 @@ void VoxelChunkDefault::_build_phase(int phase) {
VisualServer::get_singleton()->mesh_add_surface_from_arrays(get_mesh_rid_index(MESH_INDEX_PROP, MESH_TYPE_INDEX_MESH, 1), VisualServer::PRIMITIVE_TRIANGLES, temp_mesh_arr);
if (get_library()->get_material(1).is_valid())
VisualServer::get_singleton()->mesh_surface_set_material(get_mesh_rid_index(MESH_INDEX_PROP, MESH_TYPE_INDEX_MESH, 1), 0, get_library()->get_material(1)->get_rid());
if (get_library()->get_prop_material(1).is_valid())
VisualServer::get_singleton()->mesh_surface_set_material(get_mesh_rid_index(MESH_INDEX_PROP, MESH_TYPE_INDEX_MESH, 1), 0, get_library()->get_prop_material(1)->get_rid());
}
if (_lod_num >= 2) {
@ -1552,13 +1551,13 @@ void VoxelChunkDefault::_build_phase(int phase) {
VisualServer::get_singleton()->mesh_add_surface_from_arrays(get_mesh_rid_index(MESH_INDEX_PROP, MESH_TYPE_INDEX_MESH, 2), VisualServer::PRIMITIVE_TRIANGLES, temp_mesh_arr2);
if (get_library()->get_material(2).is_valid())
VisualServer::get_singleton()->mesh_surface_set_material(get_mesh_rid_index(MESH_INDEX_PROP, MESH_TYPE_INDEX_MESH, 2), 0, get_library()->get_material(2)->get_rid());
if (get_library()->get_prop_material(2).is_valid())
VisualServer::get_singleton()->mesh_surface_set_material(get_mesh_rid_index(MESH_INDEX_PROP, MESH_TYPE_INDEX_MESH, 2), 0, get_library()->get_prop_material(2)->get_rid());
}
if (_lod_num >= 3) {
Ref<ShaderMaterial> mat = get_library()->get_material(0);
Ref<SpatialMaterial> spmat = get_library()->get_material(0);
Ref<ShaderMaterial> mat = get_library()->get_prop_material(0);
Ref<SpatialMaterial> spmat = get_library()->get_prop_material(0);
Ref<Texture> tex;
if (mat.is_valid()) {
@ -1573,8 +1572,8 @@ void VoxelChunkDefault::_build_phase(int phase) {
VisualServer::get_singleton()->mesh_add_surface_from_arrays(get_mesh_rid_index(MESH_INDEX_PROP, MESH_TYPE_INDEX_MESH, 3), VisualServer::PRIMITIVE_TRIANGLES, temp_mesh_arr);
if (get_library()->get_material(3).is_valid())
VisualServer::get_singleton()->mesh_surface_set_material(get_mesh_rid_index(MESH_INDEX_PROP, MESH_TYPE_INDEX_MESH, 3), 0, get_library()->get_material(3)->get_rid());
if (get_library()->get_prop_material(3).is_valid())
VisualServer::get_singleton()->mesh_surface_set_material(get_mesh_rid_index(MESH_INDEX_PROP, MESH_TYPE_INDEX_MESH, 3), 0, get_library()->get_prop_material(3)->get_rid());
}
}
@ -1607,6 +1606,7 @@ void VoxelChunkDefault::_build_phase(int phase) {
return;
}
#endif
case BUILD_PHASE_FINALIZE: {
update_transforms();
@ -1650,16 +1650,31 @@ void VoxelChunkDefault::_build_phase_physics_process(int phase) {
temp_arr_collider_liquid.resize(0);
}
if (temp_arr_collider_prop.size() != 0) {
if (!has_meshes(MESH_INDEX_PROP, MESH_TYPE_INDEX_BODY)) {
create_colliders(MESH_INDEX_PROP);
}
PhysicsServer::get_singleton()->shape_set_data(get_mesh_rid(MESH_INDEX_PROP, MESH_TYPE_INDEX_SHAPE), temp_arr_collider_prop);
temp_arr_collider_prop.resize(0);
#if MESH_DATA_RESOURCE_PRESENT
for (int i = 0; i < _collider_bodies.size(); ++i) {
PhysicsServer::get_singleton()->free(_collider_bodies[i]);
}
_collider_bodies.clear();
for (int i = 0; i < get_mesh_data_resource_count(); ++i) {
Ref<MeshDataResource> mdr = get_mesh_data_resource(i);
for (int j = 0; j < mdr->get_collision_shape_count(); ++i) {
Ref<Shape> shape = mdr->get_collision_shape(j);
if (!shape.is_valid()) {
continue;
}
RID body = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC);
PhysicsServer::get_singleton()->body_add_shape(body, shape->get_rid(), get_mesh_data_resource_transform(j));
_collider_bodies.push_back(body);
}
}
#endif
set_active_build_phase_type(BUILD_PHASE_TYPE_NORMAL);
next_phase();
}
@ -1835,11 +1850,12 @@ void VoxelChunkDefault::_bind_methods() {
BIND_CONSTANT(BUILD_PHASE_DONE);
BIND_CONSTANT(BUILD_PHASE_SETUP);
BIND_CONSTANT(BUILD_PHASE_PROP_SETUP);
BIND_CONSTANT(BUILD_PHASE_TERRARIN_MESH_SETUP);
BIND_CONSTANT(BUILD_PHASE_COLLIDER);
BIND_CONSTANT(BUILD_PHASE_TERRARIN_MESH);
BIND_CONSTANT(BUILD_PHASE_PROP_MESH);
#ifdef MESH_DATA_RESOURCE_PRESENT
BIND_CONSTANT(BUILD_PHASE_MESH_DATA_RESOURCES);
#endif
BIND_CONSTANT(BUILD_PHASE_LIGHTS);
BIND_CONSTANT(BUILD_PHASE_FINALIZE);
BIND_CONSTANT(BUILD_PHASE_MAX);

View File

@ -72,12 +72,13 @@ public:
enum {
BUILD_PHASE_DONE = 0,
BUILD_PHASE_SETUP,
BUILD_PHASE_PROP_SETUP,
BUILD_PHASE_TERRARIN_MESH_SETUP,
BUILD_PHASE_COLLIDER,
BUILD_PHASE_LIGHTS,
BUILD_PHASE_TERRARIN_MESH,
BUILD_PHASE_PROP_MESH,
#ifdef MESH_DATA_RESOURCE_PRESENT
BUILD_PHASE_MESH_DATA_RESOURCES,
#endif
BUILD_PHASE_FINALIZE,
BUILD_PHASE_MAX
};
@ -286,11 +287,13 @@ protected:
Array temp_array;
PoolVector<Vector3> temp_arr_collider;
PoolVector<Vector3> temp_arr_collider_liquid;
PoolVector<Vector3> temp_arr_collider_prop;
ActiveBuildPhaseType _active_build_phase_type;
Vector<Ref<VoxelLight> > _lights;
#if MESH_DATA_RESOURCE_PRESENT
Vector<RID> _collider_bodies;
#endif
};
VARIANT_ENUM_CAST(VoxelChunkDefault::DefaultChannels);