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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2022-01-20 14:20:30 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2022-01-20 14:21:34 +0300
commit4425e0cd64ff23b77c553041858a150665a32ba3 (patch)
tree45c76d67d99499377dc719679c22e87effc86d8f /intern
parent9b4c017031f94237d75320349e933462772d773e (diff)
Subdivision: add support for vertex creasing
This adds vertex creasing support for OpenSubDiv for modeling, rendering, Alembic and USD I/O. For modeling, vertex creasing follows the edge creasing implementation with an operator accessible through the Vertex menu in Edit Mode, and some parameter in the properties panel. The option in the Subsurf and Multires to use edge creasing also affects vertex creasing. The vertex crease data is stored as a CustomData layer, unlike edge creases which for now are stored in `MEdge`, but will in the future also be moved to a `CustomData` layer. See comments for details on the difference in behavior for the `CD_CREASE` layer between egdes and vertices. For Cycles this adds sockets on the Mesh node to hold data about which vertices are creased (one socket for the indices, one for the weigths). Viewport rendering of vertex creasing reuses the same color scheme as for edges and creased vertices are drawn bigger than uncreased vertices. For Alembic and USD, vertex crease support follows the edge crease implementation, they are always read, but only exported if a `Subsurf` modifier is present on the Mesh. Reviewed By: brecht, fclem, sergey, sybren, campbellbarton Differential Revision: https://developer.blender.org/D10145
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/blender/mesh.cpp10
-rw-r--r--intern/cycles/scene/alembic.cpp6
-rw-r--r--intern/cycles/scene/alembic.h2
-rw-r--r--intern/cycles/scene/alembic_read.cpp38
-rw-r--r--intern/cycles/scene/alembic_read.h3
-rw-r--r--intern/cycles/scene/mesh.cpp16
-rw-r--r--intern/cycles/scene/mesh.h6
-rw-r--r--intern/cycles/scene/mesh_subdivision.cpp36
8 files changed, 108 insertions, 9 deletions
diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp
index 5e2b700427a..4ec25a868ae 100644
--- a/intern/cycles/blender/mesh.cpp
+++ b/intern/cycles/blender/mesh.cpp
@@ -1071,7 +1071,15 @@ static void create_subd_mesh(Scene *scene,
for (BL::MeshEdge &e : b_mesh.edges) {
if (e.crease() != 0.0f) {
- mesh->add_crease(e.vertices()[0], e.vertices()[1], e.crease());
+ mesh->add_edge_crease(e.vertices()[0], e.vertices()[1], e.crease());
+ }
+ }
+
+ for (BL::MeshVertexCreaseLayer &c : b_mesh.vertex_creases) {
+ for (int i = 0; i < c.data.length(); ++i) {
+ if (c.data[i].value() != 0.0f) {
+ mesh->add_vertex_crease(i, c.data[i].value());
+ }
}
}
diff --git a/intern/cycles/scene/alembic.cpp b/intern/cycles/scene/alembic.cpp
index 7780b13eecb..a8aec133fb6 100644
--- a/intern/cycles/scene/alembic.cpp
+++ b/intern/cycles/scene/alembic.cpp
@@ -1178,6 +1178,12 @@ void AlembicProcedural::read_subd(AlembicObject *abc_object, Abc::chrono_t frame
cached_data.subd_creases_weight.copy_to_socket(
frame_time, mesh, mesh->get_subd_creases_weight_socket());
+ cached_data.subd_vertex_crease_indices.copy_to_socket(
+ frame_time, mesh, mesh->get_subd_vert_creases_socket());
+
+ cached_data.subd_vertex_crease_weights.copy_to_socket(
+ frame_time, mesh, mesh->get_subd_vert_creases_weight_socket());
+
mesh->set_num_subd_faces(mesh->get_subd_shader().size());
/* Update attributes. */
diff --git a/intern/cycles/scene/alembic.h b/intern/cycles/scene/alembic.h
index 6068ea3ef03..9ea4737bea1 100644
--- a/intern/cycles/scene/alembic.h
+++ b/intern/cycles/scene/alembic.h
@@ -320,6 +320,8 @@ struct CachedData {
DataStore<int> num_ngons;
DataStore<array<int>> subd_creases_edge;
DataStore<array<float>> subd_creases_weight;
+ DataStore<array<int>> subd_vertex_crease_indices;
+ DataStore<array<float>> subd_vertex_crease_weights;
/* hair data */
DataStore<array<float3>> curve_keys;
diff --git a/intern/cycles/scene/alembic_read.cpp b/intern/cycles/scene/alembic_read.cpp
index 07874b7528e..33908dff6e5 100644
--- a/intern/cycles/scene/alembic_read.cpp
+++ b/intern/cycles/scene/alembic_read.cpp
@@ -478,7 +478,9 @@ static void add_subd_polygons(CachedData &cached_data, const SubDSchemaData &dat
cached_data.uv_loops.add_data(uv_loops, time);
}
-static void add_subd_creases(CachedData &cached_data, const SubDSchemaData &data, chrono_t time)
+static void add_subd_edge_creases(CachedData &cached_data,
+ const SubDSchemaData &data,
+ chrono_t time)
{
if (!(data.crease_indices.valid() && data.crease_indices.valid() &&
data.crease_sharpnesses.valid())) {
@@ -517,6 +519,37 @@ static void add_subd_creases(CachedData &cached_data, const SubDSchemaData &data
}
}
+static void add_subd_vertex_creases(CachedData &cached_data,
+ const SubDSchemaData &data,
+ chrono_t time)
+{
+ if (!(data.corner_indices.valid() && data.crease_sharpnesses.valid())) {
+ return;
+ }
+
+ const ISampleSelector iss = ISampleSelector(time);
+ const Int32ArraySamplePtr creases_indices = data.crease_indices.getValue(iss);
+ const FloatArraySamplePtr creases_sharpnesses = data.crease_sharpnesses.getValue(iss);
+
+ if (!(creases_indices && creases_sharpnesses) ||
+ creases_indices->size() != creases_sharpnesses->size()) {
+ return;
+ }
+
+ array<float> sharpnesses;
+ sharpnesses.reserve(creases_indices->size());
+ array<int> indices;
+ indices.reserve(creases_indices->size());
+
+ for (size_t i = 0; i < creases_indices->size(); i++) {
+ indices.push_back_reserved((*creases_indices)[i]);
+ sharpnesses.push_back_reserved((*creases_sharpnesses)[i]);
+ }
+
+ cached_data.subd_vertex_crease_indices.add_data(indices, time);
+ cached_data.subd_vertex_crease_weights.add_data(sharpnesses, time);
+}
+
static void read_subd_geometry(CachedData &cached_data, const SubDSchemaData &data, chrono_t time)
{
const ISampleSelector iss = ISampleSelector(time);
@@ -525,7 +558,8 @@ static void read_subd_geometry(CachedData &cached_data, const SubDSchemaData &da
if (data.topology_variance != kHomogenousTopology || cached_data.shader.size() == 0) {
add_subd_polygons(cached_data, data, time);
- add_subd_creases(cached_data, data, time);
+ add_subd_edge_creases(cached_data, data, time);
+ add_subd_vertex_creases(cached_data, data, time);
}
}
diff --git a/intern/cycles/scene/alembic_read.h b/intern/cycles/scene/alembic_read.h
index e95750ce691..94018b82747 100644
--- a/intern/cycles/scene/alembic_read.h
+++ b/intern/cycles/scene/alembic_read.h
@@ -76,9 +76,10 @@ struct SubDSchemaData {
vector<FaceSetShaderIndexPair> shader_face_sets;
- // Those are unsupported for now.
Alembic::AbcGeom::IInt32ArrayProperty corner_indices;
Alembic::AbcGeom::IFloatArrayProperty corner_sharpnesses;
+
+ // Those are unsupported for now.
Alembic::AbcGeom::IInt32Property face_varying_interpolate_boundary;
Alembic::AbcGeom::IInt32Property face_varying_propagate_corners;
Alembic::AbcGeom::IInt32Property interpolate_boundary;
diff --git a/intern/cycles/scene/mesh.cpp b/intern/cycles/scene/mesh.cpp
index e65b8462e34..c381d7a54ff 100644
--- a/intern/cycles/scene/mesh.cpp
+++ b/intern/cycles/scene/mesh.cpp
@@ -141,6 +141,9 @@ NODE_DEFINE(Mesh)
subdivision_type_enum.insert("catmull_clark", SUBDIVISION_CATMULL_CLARK);
SOCKET_ENUM(subdivision_type, "Subdivision Type", subdivision_type_enum, SUBDIVISION_NONE);
+ SOCKET_INT_ARRAY(subd_vert_creases, "Subdivision Vertex Crease", array<int>());
+ SOCKET_FLOAT_ARRAY(
+ subd_vert_creases_weight, "Subdivision Vertex Crease Weights", array<float>());
SOCKET_INT_ARRAY(subd_creases_edge, "Subdivision Crease Edges", array<int>());
SOCKET_FLOAT_ARRAY(subd_creases_weight, "Subdivision Crease Weights", array<float>());
SOCKET_INT_ARRAY(subd_face_corners, "Subdivision Face Corners", array<int>());
@@ -408,7 +411,7 @@ Mesh::SubdFace Mesh::get_subd_face(size_t index) const
return s;
}
-void Mesh::add_crease(int v0, int v1, float weight)
+void Mesh::add_edge_crease(int v0, int v1, float weight)
{
subd_creases_edge.push_back_slow(v0);
subd_creases_edge.push_back_slow(v1);
@@ -419,6 +422,17 @@ void Mesh::add_crease(int v0, int v1, float weight)
tag_subd_creases_weight_modified();
}
+void Mesh::add_vertex_crease(int v, float weight)
+{
+ assert(v < verts.size());
+
+ subd_vert_creases.push_back_slow(v);
+ subd_vert_creases_weight.push_back_slow(weight);
+
+ tag_subd_vert_creases_modified();
+ tag_subd_vert_creases_weight_modified();
+}
+
void Mesh::copy_center_to_motion_step(const int motion_step)
{
Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
diff --git a/intern/cycles/scene/mesh.h b/intern/cycles/scene/mesh.h
index 254672d0620..07acd5328d2 100644
--- a/intern/cycles/scene/mesh.h
+++ b/intern/cycles/scene/mesh.h
@@ -160,6 +160,9 @@ class Mesh : public Geometry {
NODE_SOCKET_API_ARRAY(array<int>, subd_creases_edge)
NODE_SOCKET_API_ARRAY(array<float>, subd_creases_weight)
+ NODE_SOCKET_API_ARRAY(array<int>, subd_vert_creases)
+ NODE_SOCKET_API_ARRAY(array<float>, subd_vert_creases_weight)
+
/* Subdivisions parameters */
NODE_SOCKET_API(float, subd_dicing_rate)
NODE_SOCKET_API(int, subd_max_level)
@@ -210,7 +213,8 @@ class Mesh : public Geometry {
void add_vertex_slow(float3 P);
void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
void add_subd_face(int *corners, int num_corners, int shader_, bool smooth_);
- void add_crease(int v0, int v1, float weight);
+ void add_edge_crease(int v0, int v1, float weight);
+ void add_vertex_crease(int v, float weight);
void copy_center_to_motion_step(const int motion_step);
diff --git a/intern/cycles/scene/mesh_subdivision.cpp b/intern/cycles/scene/mesh_subdivision.cpp
index 35f15cfafbc..7c88e310527 100644
--- a/intern/cycles/scene/mesh_subdivision.cpp
+++ b/intern/cycles/scene/mesh_subdivision.cpp
@@ -82,24 +82,54 @@ template<>
bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTags(TopologyRefiner &refiner,
ccl::Mesh const &mesh)
{
+ /* Historical maximum crease weight used at Pixar, influencing the maximum in OpenSubDiv. */
+ static constexpr float CREASE_SCALE = 10.0f;
+
size_t num_creases = mesh.get_subd_creases_weight().size();
+ size_t num_vertex_creases = mesh.get_subd_vert_creases().size();
+
+ /* The last loop is over the vertices, so early exit to avoid iterating them needlessly. */
+ if (num_creases == 0 && num_vertex_creases == 0) {
+ return true;
+ }
for (int i = 0; i < num_creases; i++) {
ccl::Mesh::SubdEdgeCrease crease = mesh.get_subd_crease(i);
Index edge = findBaseEdge(refiner, crease.v[0], crease.v[1]);
if (edge != INDEX_INVALID) {
- setBaseEdgeSharpness(refiner, edge, crease.crease * 10.0f);
+ setBaseEdgeSharpness(refiner, edge, crease.crease * CREASE_SCALE);
}
}
+ std::map<int, float> vertex_creases;
+
+ for (size_t i = 0; i < num_vertex_creases; ++i) {
+ const int vertex_idx = mesh.get_subd_vert_creases()[i];
+ const float weight = mesh.get_subd_vert_creases_weight()[i];
+
+ vertex_creases[vertex_idx] = weight * CREASE_SCALE;
+ }
+
for (int i = 0; i < mesh.get_verts().size(); i++) {
+ float sharpness = 0.0f;
+ std::map<int, float>::const_iterator iter = vertex_creases.find(i);
+
+ if (iter != vertex_creases.end()) {
+ sharpness = iter->second;
+ }
+
ConstIndexArray vert_edges = getBaseVertexEdges(refiner, i);
if (vert_edges.size() == 2) {
- float sharpness = refiner.getLevel(0).getEdgeSharpness(vert_edges[0]);
- sharpness = ccl::min(sharpness, refiner.getLevel(0).getEdgeSharpness(vert_edges[1]));
+ const float sharpness0 = refiner.getLevel(0).getEdgeSharpness(vert_edges[0]);
+ const float sharpness1 = refiner.getLevel(0).getEdgeSharpness(vert_edges[1]);
+
+ sharpness += ccl::min(sharpness0, sharpness1);
+ sharpness = ccl::min(sharpness, CREASE_SCALE);
+ }
+ if (sharpness != 0.0f) {
setBaseVertexSharpness(refiner, i, sharpness);
}
}