230 lines
8.4 KiB
C++
230 lines
8.4 KiB
C++
/*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "DNA_pointcloud_types.h"
|
|
|
|
#include "BKE_attribute_access.hh"
|
|
#include "BKE_geometry_set.hh"
|
|
#include "BKE_lib_id.h"
|
|
#include "BKE_pointcloud.h"
|
|
|
|
#include "attribute_access_intern.hh"
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Geometry Component Implementation
|
|
* \{ */
|
|
|
|
PointCloudComponent::PointCloudComponent() : GeometryComponent(GEO_COMPONENT_TYPE_POINT_CLOUD)
|
|
{
|
|
}
|
|
|
|
PointCloudComponent::~PointCloudComponent()
|
|
{
|
|
this->clear();
|
|
}
|
|
|
|
GeometryComponent *PointCloudComponent::copy() const
|
|
{
|
|
PointCloudComponent *new_component = new PointCloudComponent();
|
|
if (pointcloud_ != nullptr) {
|
|
new_component->pointcloud_ = BKE_pointcloud_copy_for_eval(pointcloud_, false);
|
|
new_component->ownership_ = GeometryOwnershipType::Owned;
|
|
}
|
|
return new_component;
|
|
}
|
|
|
|
void PointCloudComponent::clear()
|
|
{
|
|
BLI_assert(this->is_mutable());
|
|
if (pointcloud_ != nullptr) {
|
|
if (ownership_ == GeometryOwnershipType::Owned) {
|
|
BKE_id_free(nullptr, pointcloud_);
|
|
}
|
|
pointcloud_ = nullptr;
|
|
}
|
|
}
|
|
|
|
bool PointCloudComponent::has_pointcloud() const
|
|
{
|
|
return pointcloud_ != nullptr;
|
|
}
|
|
|
|
/* Clear the component and replace it with the new point cloud. */
|
|
void PointCloudComponent::replace(PointCloud *pointcloud, GeometryOwnershipType ownership)
|
|
{
|
|
BLI_assert(this->is_mutable());
|
|
this->clear();
|
|
pointcloud_ = pointcloud;
|
|
ownership_ = ownership;
|
|
}
|
|
|
|
/* Return the point cloud and clear the component. The caller takes over responsibility for freeing
|
|
* the point cloud (if the component was responsible before). */
|
|
PointCloud *PointCloudComponent::release()
|
|
{
|
|
BLI_assert(this->is_mutable());
|
|
PointCloud *pointcloud = pointcloud_;
|
|
pointcloud_ = nullptr;
|
|
return pointcloud;
|
|
}
|
|
|
|
/* Get the point cloud from this component. This method can be used by multiple threads at the same
|
|
* time. Therefore, the returned point cloud should not be modified. No ownership is transferred.
|
|
*/
|
|
const PointCloud *PointCloudComponent::get_for_read() const
|
|
{
|
|
return pointcloud_;
|
|
}
|
|
|
|
/* Get the point cloud from this component. This method can only be used when the component is
|
|
* mutable, i.e. it is not shared. The returned point cloud can be modified. No ownership is
|
|
* transferred. */
|
|
PointCloud *PointCloudComponent::get_for_write()
|
|
{
|
|
BLI_assert(this->is_mutable());
|
|
if (ownership_ == GeometryOwnershipType::ReadOnly) {
|
|
pointcloud_ = BKE_pointcloud_copy_for_eval(pointcloud_, false);
|
|
ownership_ = GeometryOwnershipType::Owned;
|
|
}
|
|
return pointcloud_;
|
|
}
|
|
|
|
bool PointCloudComponent::is_empty() const
|
|
{
|
|
return pointcloud_ == nullptr;
|
|
}
|
|
|
|
bool PointCloudComponent::owns_direct_data() const
|
|
{
|
|
return ownership_ == GeometryOwnershipType::Owned;
|
|
}
|
|
|
|
void PointCloudComponent::ensure_owns_direct_data()
|
|
{
|
|
BLI_assert(this->is_mutable());
|
|
if (ownership_ != GeometryOwnershipType::Owned) {
|
|
pointcloud_ = BKE_pointcloud_copy_for_eval(pointcloud_, false);
|
|
ownership_ = GeometryOwnershipType::Owned;
|
|
}
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Attribute Access
|
|
* \{ */
|
|
|
|
int PointCloudComponent::attribute_domain_size(const AttributeDomain domain) const
|
|
{
|
|
if (pointcloud_ == nullptr) {
|
|
return 0;
|
|
}
|
|
if (domain != ATTR_DOMAIN_POINT) {
|
|
return 0;
|
|
}
|
|
return pointcloud_->totpoint;
|
|
}
|
|
|
|
namespace blender::bke {
|
|
|
|
template<typename T>
|
|
static GVArray make_array_read_attribute(const void *data, const int domain_size)
|
|
{
|
|
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
|
|
}
|
|
|
|
template<typename T>
|
|
static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
|
|
{
|
|
return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
|
|
}
|
|
|
|
/**
|
|
* In this function all the attribute providers for a point cloud component are created. Most data
|
|
* in this function is statically allocated, because it does not change over time.
|
|
*/
|
|
static ComponentAttributeProviders create_attribute_providers_for_point_cloud()
|
|
{
|
|
static auto update_custom_data_pointers = [](GeometryComponent &component) {
|
|
PointCloudComponent &pointcloud_component = static_cast<PointCloudComponent &>(component);
|
|
PointCloud *pointcloud = pointcloud_component.get_for_write();
|
|
if (pointcloud != nullptr) {
|
|
BKE_pointcloud_update_customdata_pointers(pointcloud);
|
|
}
|
|
};
|
|
static CustomDataAccessInfo point_access = {
|
|
[](GeometryComponent &component) -> CustomData * {
|
|
PointCloudComponent &pointcloud_component = static_cast<PointCloudComponent &>(component);
|
|
PointCloud *pointcloud = pointcloud_component.get_for_write();
|
|
return pointcloud ? &pointcloud->pdata : nullptr;
|
|
},
|
|
[](const GeometryComponent &component) -> const CustomData * {
|
|
const PointCloudComponent &pointcloud_component = static_cast<const PointCloudComponent &>(
|
|
component);
|
|
const PointCloud *pointcloud = pointcloud_component.get_for_read();
|
|
return pointcloud ? &pointcloud->pdata : nullptr;
|
|
},
|
|
update_custom_data_pointers};
|
|
|
|
static BuiltinCustomDataLayerProvider position("position",
|
|
ATTR_DOMAIN_POINT,
|
|
CD_PROP_FLOAT3,
|
|
CD_PROP_FLOAT3,
|
|
BuiltinAttributeProvider::NonCreatable,
|
|
BuiltinAttributeProvider::Writable,
|
|
BuiltinAttributeProvider::NonDeletable,
|
|
point_access,
|
|
make_array_read_attribute<float3>,
|
|
make_array_write_attribute<float3>,
|
|
nullptr);
|
|
static BuiltinCustomDataLayerProvider radius("radius",
|
|
ATTR_DOMAIN_POINT,
|
|
CD_PROP_FLOAT,
|
|
CD_PROP_FLOAT,
|
|
BuiltinAttributeProvider::Creatable,
|
|
BuiltinAttributeProvider::Writable,
|
|
BuiltinAttributeProvider::Deletable,
|
|
point_access,
|
|
make_array_read_attribute<float>,
|
|
make_array_write_attribute<float>,
|
|
nullptr);
|
|
static BuiltinCustomDataLayerProvider id("id",
|
|
ATTR_DOMAIN_POINT,
|
|
CD_PROP_INT32,
|
|
CD_PROP_INT32,
|
|
BuiltinAttributeProvider::Creatable,
|
|
BuiltinAttributeProvider::Writable,
|
|
BuiltinAttributeProvider::Deletable,
|
|
point_access,
|
|
make_array_read_attribute<int>,
|
|
make_array_write_attribute<int>,
|
|
nullptr);
|
|
static CustomDataAttributeProvider point_custom_data(ATTR_DOMAIN_POINT, point_access);
|
|
return ComponentAttributeProviders({&position, &radius, &id}, {&point_custom_data});
|
|
}
|
|
|
|
} // namespace blender::bke
|
|
|
|
const blender::bke::ComponentAttributeProviders *PointCloudComponent::get_attribute_providers()
|
|
const
|
|
{
|
|
static blender::bke::ComponentAttributeProviders providers =
|
|
blender::bke::create_attribute_providers_for_point_cloud();
|
|
return &providers;
|
|
}
|
|
|
|
/** \} */
|