Welcome to mirror list, hosted at ThFree Co, Russian Federation.

geometry.cc « intern « blenkernel « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 014197ed423edf5c840a2c192fed1ee90d9f0884 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
 * 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 "BKE_geometry.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"

#include "MEM_guardedalloc.h"

namespace blender::bke {

/* Make a copy of the geometry. */
Geometry::Geometry(const Geometry &other)
{
  if (other.mesh_ != nullptr) {
    mesh_ = BKE_mesh_copy_for_eval(other.mesh_, false);
    /* Own the new mesh, regardless of whether the original mesh was owned. */
    mesh_owned_ = true;
  }
}

Geometry::~Geometry()
{
  this->mesh_reset();
}

void Geometry::user_add()
{
  users_.fetch_add(1);
}

void Geometry::user_remove()
{
  const int new_users = users_.fetch_sub(1) - 1;
  if (new_users == 0) {
    delete this;
  }
}

bool Geometry::is_mutable() const
{
  /* If the geometry is shared, it is read-only. */
  /* The user count can be 0, when this is called from the destructor. */
  return users_ <= 1;
}

/**
 * Replace the mesh in the geometry. The caller remains the owner of the given mesh and is
 * responsible for freeing it eventually.
 */
void Geometry::mesh_set_and_keep_ownership(Mesh *mesh)
{
  BLI_assert(this->is_mutable());
  this->mesh_reset();
  mesh_ = mesh;
  mesh_owned_ = false;
}

/**
 * Replace the mesh in the geometry. The geometry becomes responsible for freeing the mesh.
 */
void Geometry::mesh_set_and_transfer_ownership(Mesh *mesh)
{
  BLI_assert(this->is_mutable());
  this->mesh_reset();
  mesh_ = mesh;
  mesh_owned_ = true;
}

/**
 * Clear any mesh data the geometry might have.
 */
void Geometry::mesh_reset()
{
  BLI_assert(this->is_mutable());
  if (mesh_ != nullptr) {
    if (mesh_owned_) {
      BKE_id_free(nullptr, mesh_);
    }
    mesh_ = nullptr;
  }
}

/**
 * Get the mesh from the geometry. This mesh should only be read and not modified. This can be used
 * on shared geometries.
 * Might return null.
 */
Mesh *Geometry::mesh_get_for_read()
{
  return mesh_;
}

/**
 * Get the mesh from the geometry. The caller is allowed to modify the mesh. This method can only
 * be used on mutable geometries.
 * Might return null.
 */
Mesh *Geometry::mesh_get_for_write()
{
  BLI_assert(this->is_mutable());
  return mesh_;
}

/**
 * Return the mesh in the geometry and remove it. This only works on mutable geometries.
 * Might return null;
 */
Mesh *Geometry::mesh_release()
{
  BLI_assert(this->is_mutable());
  Mesh *mesh = mesh_;
  mesh_ = nullptr;
  return mesh;
}

/**
 * Changes the given pointer so that it points to a mutable geometry. This might do nothing, create
 * a new empty geometry or copy the entire geometry.
 */
void make_geometry_mutable(GeometryPtr &geometry)
{
  if (!geometry) {
    /* If the pointer is null, create a new instance. */
    geometry = GeometryPtr{new Geometry()};
  }
  else if (geometry->is_mutable()) {
    /* If the instance is mutable already, do nothing. */
  }
  else {
    /* This geometry is shared, make a copy that is independent of the other users. */
    Geometry *shared_geometry = geometry.release();
    Geometry *new_geometry = new Geometry(*shared_geometry);
    shared_geometry->user_remove();
    geometry = GeometryPtr{new_geometry};
  }
}

}  // namespace blender::bke