[Bf-blender-cvs] [45447510826] cycles_procedural_api: add support for subdivision meshes
Kévin Dietrich
noreply at git.blender.org
Sun Dec 6 06:26:29 CET 2020
Commit: 45447510826bf8dca2f98de21af2bf8f504cc226
Author: Kévin Dietrich
Date: Fri Dec 4 16:49:56 2020 +0100
Branches: cycles_procedural_api
https://developer.blender.org/rB45447510826bf8dca2f98de21af2bf8f504cc226
add support for subdivision meshes
===================================================================
M intern/cycles/blender/blender_object.cpp
M intern/cycles/render/alembic.cpp
M intern/cycles/render/alembic.h
===================================================================
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 862e94a231e..abda51c6fdc 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -535,6 +535,11 @@ void BlenderSync::sync_procedural(BL::Object &b_ob,
abc_object->set_path(object_path);
abc_object->set_used_shaders(used_shaders);
+ PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
+ const float subd_dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate);
+ abc_object->set_subd_dicing_rate(subd_dicing_rate);
+ abc_object->set_subd_max_level(max_subdivisions);
+
procedural->add_object(abc_object);
}
diff --git a/intern/cycles/render/alembic.cpp b/intern/cycles/render/alembic.cpp
index b24d132aa28..38d1e5982aa 100644
--- a/intern/cycles/render/alembic.cpp
+++ b/intern/cycles/render/alembic.cpp
@@ -419,6 +419,9 @@ NODE_DEFINE(AlembicObject)
SOCKET_STRING(path, "Alembic Path", ustring());
SOCKET_NODE_ARRAY(used_shaders, "Used Shaders", &Shader::node_type);
+ SOCKET_INT(subd_max_level, "Max Subdivision Level", 1);
+ SOCKET_FLOAT(subd_dicing_rate, "Subdivision Dicing Rate", 1.0f);
+
return type;
}
@@ -445,7 +448,8 @@ bool AlembicObject::has_data_loaded() const
return data_loaded;
}
-void AlembicObject::read_face_sets(IPolyMeshSchema &schema, array<int> &polygon_to_shader)
+template<typename SchemaType>
+void AlembicObject::read_face_sets(SchemaType &schema, array<int> &polygon_to_shader)
{
/* TODO(@kevindietrich) at the moment this is only supported for meshes whose topology remains
* constant (with possible vertex animation) */
@@ -573,6 +577,150 @@ void AlembicObject::load_all_data(IPolyMeshSchema &schema, Progress &progress)
data_loaded = true;
}
+void AlembicObject::load_all_data(ISubDSchema &schema, Progress &progress)
+{
+ cached_data.clear();
+
+ AttributeRequestSet requested_attributes = get_requested_attributes();
+
+ const TimeSamplingPtr time_sampling = schema.getTimeSampling();
+ cached_data.vertices.set_time_sampling(*time_sampling);
+ cached_data.triangles.set_time_sampling(*time_sampling);
+ cached_data.triangles_loops.set_time_sampling(*time_sampling);
+ cached_data.shader.set_time_sampling(*time_sampling);
+ cached_data.subd_start_corner.set_time_sampling(*time_sampling);
+ cached_data.subd_num_corners.set_time_sampling(*time_sampling);
+ cached_data.subd_smooth.set_time_sampling(*time_sampling);
+ cached_data.subd_ptex_offset.set_time_sampling(*time_sampling);
+ cached_data.subd_face_corners.set_time_sampling(*time_sampling);
+ cached_data.num_ngons.set_time_sampling(*time_sampling);
+ cached_data.subd_creases_edge.set_time_sampling(*time_sampling);
+ cached_data.subd_creases_weight.set_time_sampling(*time_sampling);
+
+ /* start by reading the face sets (per face shader), as we directly split polygons to triangles
+ */
+ array<int> polygon_to_shader;
+ read_face_sets(schema, polygon_to_shader);
+
+ /* read topology */
+ for (size_t i = 0; i < schema.getNumSamples(); ++i) {
+ if (progress.get_cancel()) {
+ return;
+ }
+
+ const ISampleSelector iss = ISampleSelector(static_cast<index_t>(i));
+ const ISubDSchema::Sample sample = schema.getValue(iss);
+
+ const double time = time_sampling->getSampleTime(static_cast<index_t>(i));
+
+ add_positions(sample.getPositions(), time, cached_data);
+
+ const Int32ArraySamplePtr face_counts = sample.getFaceCounts();
+ const Int32ArraySamplePtr face_indices = sample.getFaceIndices();
+
+ /* read faces */
+ array<int> subd_start_corner;
+ array<int> shader;
+ array<int> subd_num_corners;
+ array<bool> subd_smooth;
+ array<int> subd_ptex_offset;
+ array<int> subd_face_corners;
+
+ const size_t num_faces = face_counts->size();
+ const int *face_counts_array = face_counts->get();
+ const int *face_indices_array = face_indices->get();
+
+ int num_ngons = 0;
+ int num_corners = 0;
+ for (size_t i = 0; i < face_counts->size(); i++) {
+ num_ngons += (face_counts_array[i] == 4 ? 0 : 1);
+ num_corners += face_counts_array[i];
+ }
+
+ subd_start_corner.reserve(num_faces);
+ subd_num_corners.reserve(num_faces);
+ subd_smooth.reserve(num_faces);
+ subd_ptex_offset.reserve(num_faces);
+ shader.reserve(num_faces);
+ subd_face_corners.reserve(num_corners);
+
+ int start_corner = 0;
+ int current_shader = 0;
+ int ptex_offset = 0;
+
+ for (size_t i = 0; i < face_counts->size(); i++) {
+ num_corners = face_counts_array[i];
+
+ if (!polygon_to_shader.empty()) {
+ current_shader = polygon_to_shader[i];
+ }
+
+ subd_start_corner.push_back_reserved(start_corner);
+ subd_num_corners.push_back_reserved(num_corners);
+
+ for (int j = 0; j < num_corners; ++j) {
+ subd_face_corners.push_back_reserved(face_indices_array[start_corner + j]);
+ }
+
+ shader.push_back_reserved(current_shader);
+ subd_smooth.push_back_reserved(1);
+ subd_ptex_offset.push_back_reserved(ptex_offset);
+
+ ptex_offset += (num_corners == 4 ? 1 : num_corners);
+
+ start_corner += num_corners;
+ }
+
+ cached_data.shader.add_data(shader, time);
+ cached_data.subd_start_corner.add_data(subd_start_corner, time);
+ cached_data.subd_num_corners.add_data(subd_num_corners, time);
+ cached_data.subd_smooth.add_data(subd_smooth, time);
+ cached_data.subd_ptex_offset.add_data(subd_ptex_offset, time);
+ cached_data.subd_face_corners.add_data(subd_face_corners, time);
+ cached_data.num_ngons.add_data(num_ngons, time);
+
+ /* read creases */
+ Int32ArraySamplePtr creases_length = sample.getCreaseLengths();
+ Int32ArraySamplePtr creases_indices = sample.getCreaseIndices();
+ FloatArraySamplePtr creases_sharpnesses = sample.getCreaseSharpnesses();
+
+ if (creases_length && creases_indices && creases_sharpnesses) {
+ array<int> creases_edge;
+ array<float> creases_weight;
+
+ creases_edge.reserve(creases_sharpnesses->size() * 2);
+ creases_weight.reserve(creases_sharpnesses->size());
+
+ int length_offset = 0;
+ int weight_offset = 0;
+ for (size_t c = 0; c < creases_length->size(); ++c) {
+ const int crease_length = creases_length->get()[c];
+
+ for (size_t j = 0; j < crease_length - 1; ++j) {
+ creases_edge.push_back_reserved(creases_indices->get()[length_offset + j]);
+ creases_edge.push_back_reserved(creases_indices->get()[length_offset + j + 1]);
+ creases_weight.push_back_reserved(creases_sharpnesses->get()[weight_offset++]);
+ }
+
+ length_offset += crease_length;
+ }
+
+ cached_data.subd_creases_edge.add_data(creases_edge, time);
+ cached_data.subd_creases_weight.add_data(creases_weight, time);
+ }
+
+ /* TODO(@kevindietrich) : attributes, need test files */
+ }
+
+ if (progress.get_cancel()) {
+ return;
+ }
+
+ setup_transform_cache();
+
+ data_loaded = true;
+}
+
void AlembicObject::load_all_data(const ICurvesSchema &schema,
Progress &progress,
float default_radius)
@@ -951,6 +1099,9 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
else if (ICurves::matches(object->iobject.getHeader())) {
read_curves(scene, object, frame_time, progress);
}
+ else if (ISubD::matches(object->iobject.getHeader())) {
+ read_subd(scene, object, frame_time, progress);
+ }
}
clear_modified();
@@ -1102,6 +1253,124 @@ void AlembicProcedural::read_mesh(Scene *scene,
}
}
+void AlembicProcedural::read_subd(Scene *scene,
+ AlembicObject *abc_object,
+ Abc::chrono_t frame_time,
+ Progress &progress)
+{
+ ISubD subd_mesh(abc_object->iobject, Alembic::Abc::kWrapExisting);
+
+ Mesh *mesh = nullptr;
+
+ /* create a mesh node in the scene if not already done */
+ if (!abc_object->get_object()) {
+ mesh = scene->create_node<Mesh>();
+ mesh->set_owner(this);
+ mesh->name = abc_object->iobject.getName();
+
+ array<Node *> used_shaders = abc_object->get_used_shaders();
+ mesh->set_used_shaders(used_shaders);
+
+ /* create object*/
+ Object *object = scene->create_node<Object>();
+ object->set_owner(this);
+ object->set_geometry(mesh);
+ object->set_tfm(abc_object->xform);
+ object->name = abc_object->iobject.getName();
+
+ abc_object->set_object(object);
+ }
+ else {
+ mesh = static_cast<Mesh *>(abc_object->get_object()->get_geometry());
+ }
+
+ ISubDSchema schema = subd_mesh.getSchema();
+
+ if (!abc_object->has_data_loaded()) {
+ abc_object->load_all_data(schema, progress);
+ }
+
+ if (schema.getSubdivisionSchemeProperty().getValue() == "catmull-clark") {
+ mesh->set_subdivision_type(Mesh::SubdivisionType::SUBDIVISION_CATMULL_CLARK);
+ }
+ else {
+ mesh->set_subdivision_type(Mesh::SubdivisionType::SUBDIVISION_LINEAR);
+ }
+
+ mesh->set_subd_max_level(abc_object->get_subd_max_level());
+ mesh->set_subd_dicing_rate(abc_object->get_subd_dicing_rate());
+
+ CachedData &cached_data = abc_object->get_cached_data();
+
+ /* udpate sockets */
+
+ Object *object = abc_object->get_object();
+ cached_data.transforms.copy_to_socket(frame_time, object, object->get_tfm_socket());
+
+ cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket());
+
+ /* cached_data.shader is also used for subd_shader */
+ cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_subd_shader_socket());
+
+ cached_data.subd_start_corner.copy_to_socket(frame_time, mesh, mesh->get_subd_start_corner_socket());
+
+ cached_data.subd_num_corners.copy_to_socket(frame_time, mesh, mesh->get_subd_num_corners_socket());
+
+ cached_data.subd_smooth.copy_to_socket(frame_time, mesh, mesh->get_subd_smooth_socket());
+
+ cached_data.subd_ptex_offset.copy_to_socket(frame_time, mesh, mesh->get_subd_ptex_offset_socket());
+
+ cached_data.subd_face_corners.copy_to_socket(frame_time, mesh, mesh->get_subd_face_corners_socket());
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list