#include "proc_geometry.h"
namespace godot {
void ProcGeometry::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_mesh"), &ProcGeometry::get_mesh);
ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &ProcGeometry::set_mesh);
ClassDB::bind_method(D_METHOD("get_curves"), &ProcGeometry::get_curves);
ClassDB::bind_method(D_METHOD("set_curves", "curves"), &ProcGeometry::set_curves);
ClassDB::bind_method(D_METHOD("get_pointcloud"), &ProcGeometry::get_pointcloud);
ClassDB::bind_method(D_METHOD("set_pointcloud", "pointcloud"), &ProcGeometry::set_pointcloud);
ClassDB::bind_method(D_METHOD("get_instances"), &ProcGeometry::get_instances);
ClassDB::bind_method(D_METHOD("set_instances", "instances"), &ProcGeometry::set_instances);
ClassDB::bind_method(D_METHOD("get_volume"), &ProcGeometry::get_volume);
ClassDB::bind_method(D_METHOD("set_volume", "volume"), &ProcGeometry::set_volume);
ClassDB::bind_method(D_METHOD("is_empty"), &ProcGeometry::is_empty);
ClassDB::bind_method(D_METHOD("duplicate_geometry"), &ProcGeometry::duplicate_geometry);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "ProcMesh"), "set_mesh", "get_mesh");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curves", PROPERTY_HINT_RESOURCE_TYPE, "ProcCurves"), "set_curves", "get_curves");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "pointcloud", PROPERTY_HINT_RESOURCE_TYPE, "ProcPointCloud"), "set_pointcloud", "get_pointcloud");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "instances", PROPERTY_HINT_RESOURCE_TYPE, "ProcInstances"), "set_instances", "get_instances");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "volume", PROPERTY_HINT_RESOURCE_TYPE, "ProcVolume"), "set_volume", "get_volume");
}
bool ProcGeometry::is_empty() const {
return mesh.is_null() && curves.is_null() && pointcloud.is_null() && instances.is_null() && volume.is_null();
}
int ProcGeometry::domain_size(AttrDomain p_domain) const {
int total = 0;
if (mesh.is_valid()) {
total += mesh->domain_size(p_domain);
}
if (curves.is_valid()) {
total += curves->domain_size(p_domain);
}
if (pointcloud.is_valid()) {
total += pointcloud->domain_size(p_domain);
}
if (instances.is_valid()) {
total += instances->domain_size(p_domain);
}
return total;
}
Ref<ProcMesh> ProcGeometry::ensure_mesh() {
if (mesh.is_null()) {
mesh.instantiate();
}
return mesh;
}
Ref<ProcCurves> ProcGeometry::ensure_curves() {
if (curves.is_null()) {
curves.instantiate();
}
return curves;
}
Ref<ProcPointCloud> ProcGeometry::ensure_pointcloud() {
if (pointcloud.is_null()) {
pointcloud.instantiate();
}
return pointcloud;
}
Ref<ProcInstances> ProcGeometry::ensure_instances() {
if (instances.is_null()) {
instances.instantiate();
}
return instances;
}
Ref<ProcVolume> ProcGeometry::ensure_volume() {
if (volume.is_null()) {
volume.instantiate();
}
return volume;
}
Ref<ProcGeometry> ProcGeometry::duplicate_geometry() const {
Ref<ProcGeometry> dup;
dup.instantiate();
if (mesh.is_valid()) {
dup->mesh = mesh->duplicate_mesh();
}
if (curves.is_valid()) {
dup->curves = curves->duplicate_curves();
}
if (pointcloud.is_valid()) {
dup->pointcloud = pointcloud->duplicate_pointcloud();
}
if (instances.is_valid()) {
dup->instances = instances->duplicate_instances();
}
if (volume.is_valid()) {
dup->volume = volume->duplicate_volume();
}
return dup;
}
void ProcGeometry::join(const Ref<ProcGeometry> &p_other) {
if (p_other.is_null()) {
return;
}
// Join meshes
if (p_other->mesh.is_valid() && p_other->mesh->vertex_count() > 0) {
Ref<ProcMesh> m = ensure_mesh();
int base_vertex = m->positions.size();
int base_index = m->indices.size();
m->positions.append_array(p_other->mesh->positions);
m->normals.append_array(p_other->mesh->normals);
m->uvs.append_array(p_other->mesh->uvs);
m->colors.append_array(p_other->mesh->colors);
// Offset indices
PackedInt32Array other_indices = p_other->mesh->indices;
int32_t *ow = other_indices.ptrw();
for (int i = 0; i < other_indices.size(); i++) {
ow[i] += base_vertex;
}
m->indices.append_array(other_indices);
// Propagate attributes
m->point_attrs.propagate_from(p_other->mesh->point_attrs);
}
// Join instances
if (p_other->instances.is_valid() && p_other->instances->instance_count() > 0) {
Ref<ProcInstances> inst = ensure_instances();
int base_ref = inst->references.size();
// Add references
for (int i = 0; i < p_other->instances->references.size(); i++) {
inst->references.push_back(p_other->instances->references[i]);
}
// Add instances with offset reference indices
for (int i = 0; i < p_other->instances->instance_count(); i++) {
inst->transforms.push_back(p_other->instances->transforms[i]);
}
PackedInt32Array other_refs = p_other->instances->reference_indices;
int32_t *rw = other_refs.ptrw();
for (int i = 0; i < other_refs.size(); i++) {
rw[i] += base_ref;
}
inst->reference_indices.append_array(other_refs);
}
// Join point clouds
if (p_other->pointcloud.is_valid() && p_other->pointcloud->point_count() > 0) {
Ref<ProcPointCloud> pc = ensure_pointcloud();
pc->positions.append_array(p_other->pointcloud->positions);
pc->radii.append_array(p_other->pointcloud->radii);
}
}
} // namespace godot