[Bf-blender-cvs] [ff3df2ea568] master: Merge branch 'blender-v2.92-release'

Jacques Lucke noreply at git.blender.org
Fri Feb 12 17:51:36 CET 2021


Commit: ff3df2ea568f6f55cdee74ce6ed5586c15af2062
Author: Jacques Lucke
Date:   Fri Feb 12 17:50:44 2021 +0100
Branches: master
https://developer.blender.org/rBff3df2ea568f6f55cdee74ce6ed5586c15af2062

Merge branch 'blender-v2.92-release'

===================================================================



===================================================================

diff --cc source/blender/blenkernel/intern/geometry_set.cc
index 2eaef8fc121,6db15c9393d..7eb41a6c623
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@@ -577,85 -544,68 +579,147 @@@ bool InstancesComponent::is_empty() con
    return transforms_.size() == 0;
  }
  
+ static blender::Array<int> generate_unique_instance_ids(Span<int> original_ids)
+ {
+   using namespace blender;
+   Array<int> unique_ids(original_ids.size());
+ 
+   Set<int> used_unique_ids;
+   used_unique_ids.reserve(original_ids.size());
+   Vector<int> instances_with_id_collision;
+   for (const int instance_index : original_ids.index_range()) {
+     const int original_id = original_ids[instance_index];
+     if (used_unique_ids.add(original_id)) {
+       /* The original id has not been used by another instance yet. */
+       unique_ids[instance_index] = original_id;
+     }
+     else {
+       /* The original id of this instance collided with a previous instance, it needs to be looked
+        * at again in a second pass. Don't generate a new random id here, because this might collide
+        * with other existing ids. */
+       instances_with_id_collision.append(instance_index);
+     }
+   }
+ 
+   Map<int, RandomNumberGenerator> generator_by_original_id;
+   for (const int instance_index : instances_with_id_collision) {
+     const int original_id = original_ids[instance_index];
+     RandomNumberGenerator &rng = generator_by_original_id.lookup_or_add_cb(original_id, [&]() {
+       RandomNumberGenerator rng;
+       rng.seed_random(original_id);
+       return rng;
+     });
+ 
+     const int max_iteration = 100;
+     for (int iteration = 0;; iteration++) {
+       /* Try generating random numbers until an unused one has been found. */
+       const int random_id = rng.get_int32();
+       if (used_unique_ids.add(random_id)) {
+         /* This random id is not used by another instance. */
+         unique_ids[instance_index] = random_id;
+         break;
+       }
+       if (iteration == max_iteration) {
+         /* It seems to be very unlikely that we ever run into this case (assuming there are less
+          * than 2^30 instances). However, if that happens, it's better to use an id that is not
+          * unique than to be stuck in an infinite loop. */
+         unique_ids[instance_index] = original_id;
+         break;
+       }
+     }
+   }
+ 
+   return unique_ids;
+ }
+ 
+ blender::Span<int> InstancesComponent::almost_unique_ids() const
+ {
+   std::lock_guard lock(almost_unique_ids_mutex_);
+   if (almost_unique_ids_.size() != ids_.size()) {
+     almost_unique_ids_ = generate_unique_instance_ids(ids_);
+   }
+   return almost_unique_ids_;
+ }
+ 
 +/** \} */
 +
 +/* -------------------------------------------------------------------- */
 +/** \name Volume Component
 + * \{ */
 +
 +VolumeComponent::VolumeComponent() : GeometryComponent(GeometryComponentType::Volume)
 +{
 +}
 +
 +VolumeComponent::~VolumeComponent()
 +{
 +  this->clear();
 +}
 +
 +GeometryComponent *VolumeComponent::copy() const
 +{
 +  VolumeComponent *new_component = new VolumeComponent();
 +  if (volume_ != nullptr) {
 +    new_component->volume_ = BKE_volume_copy_for_eval(volume_, false);
 +    new_component->ownership_ = GeometryOwnershipType::Owned;
 +  }
 +  return new_component;
 +}
 +
 +void VolumeComponent::clear()
 +{
 +  BLI_assert(this->is_mutable());
 +  if (volume_ != nullptr) {
 +    if (ownership_ == GeometryOwnershipType::Owned) {
 +      BKE_id_free(nullptr, volume_);
 +    }
 +    volume_ = nullptr;
 +  }
 +}
 +
 +bool VolumeComponent::has_volume() const
 +{
 +  return volume_ != nullptr;
 +}
 +
 +/* Clear the component and replace it with the new volume. */
 +void VolumeComponent::replace(Volume *volume, GeometryOwnershipType ownership)
 +{
 +  BLI_assert(this->is_mutable());
 +  this->clear();
 +  volume_ = volume;
 +  ownership_ = ownership;
 +}
 +
 +/* Return the volume and clear the component. The caller takes over responsibility for freeing the
 + * volume (if the component was responsible before). */
 +Volume *VolumeComponent::release()
 +{
 +  BLI_assert(this->is_mutable());
 +  Volume *volume = volume_;
 +  volume_ = nullptr;
 +  return volume;
 +}
 +
 +/* Get the volume from this component. This method can be used by multiple threads at the same
 + * time. Therefore, the returned volume should not be modified. No ownership is transferred. */
 +const Volume *VolumeComponent::get_for_read() const
 +{
 +  return volume_;
 +}
 +
 +/* Get the volume from this component. This method can only be used when the component is mutable,
 + * i.e. it is not shared. The returned volume can be modified. No ownership is transferred. */
 +Volume *VolumeComponent::get_for_write()
 +{
 +  BLI_assert(this->is_mutable());
 +  if (ownership_ == GeometryOwnershipType::ReadOnly) {
 +    volume_ = BKE_volume_copy_for_eval(volume_, false);
 +    ownership_ = GeometryOwnershipType::Owned;
 +  }
 +  return volume_;
 +}
 +
  /** \} */
  
  /* -------------------------------------------------------------------- */



More information about the Bf-blender-cvs mailing list