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
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2017-02-10 15:23:40 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2017-02-10 15:34:09 +0300
commitfd7e9f797433e6739798f33ed3cb33022c0f7d2f (patch)
tree6af47feab4e4af9f16c12f3ce1ba3630c397a8a0 /intern/cycles/blender
parentd395d81bfc9e1c312159ff7b9ca9ba514a46af95 (diff)
Cycles: Fix pointiness attribute giving wrong results with autosplit
Basically made the algorithm to handle vertices with the same coordinate as a single vertex.
Diffstat (limited to 'intern/cycles/blender')
-rw-r--r--intern/cycles/blender/blender_mesh.cpp131
1 files changed, 106 insertions, 25 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 04da8e2915f..c3e8c28adbc 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -533,19 +533,80 @@ static void attr_create_pointiness(Scene *scene,
if(!mesh->need_attribute(scene, ATTR_STD_POINTINESS)) {
return;
}
- const int numverts = b_mesh.vertices.length();
+ const int num_verts = b_mesh.vertices.length();
AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes;
Attribute *attr = attributes.add(ATTR_STD_POINTINESS);
float *data = attr->data_float();
- vector<int> counter(numverts, 0);
- vector<float> raw_data(numverts, 0.0f);
- vector<float3> edge_accum(numverts, make_float3(0.0f, 0.0f, 0.0f));
- /* Calculate pointiness using single ring neighborhood. */
+ /* STEP 1: Find out duplicated vertices and point duplicates to a single
+ * original vertex.
+ */
+ /* This array stores index of the original vertex for the given vertex
+ * index.
+ */
+ vector<int> vert_orig_index(num_verts);
+ BL::Mesh::vertices_iterator v;
+ int vert_index = 0;
+ for(b_mesh.vertices.begin(v);
+ v != b_mesh.vertices.end();
+ ++v, ++vert_index)
+ {
+ const float3 vert_co = get_float3(v->co());
+ bool found = false;
+ int other_vert_index;
+ for(other_vert_index = 0;
+ other_vert_index < vert_index;
+ ++other_vert_index)
+ {
+ const float3 other_vert_co =
+ get_float3(b_mesh.vertices[other_vert_index].co());
+ if(other_vert_co == vert_co) {
+ found = true;
+ break;
+ }
+ }
+ if(found) {
+ vert_orig_index[vert_index] = other_vert_index;
+ }
+ else {
+ vert_orig_index[vert_index] = vert_index;
+ }
+ }
+ /* STEP 2: Calculate vertex normals taking into account their possible
+ * duplicates which gets "welded" together.
+ */
+ vector<float3> vert_normal(num_verts, make_float3(0.0f, 0.0f, 0.0f));
+ /* First we accumulate all vertex normals in the original index. */
+ for(vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const float3 normal = get_float3(b_mesh.vertices[vert_index].normal());
+ const int orig_index = vert_orig_index[vert_index];
+ vert_normal[orig_index] += normal;
+ }
+ /* Then we normalize the accumulated result and flush it to all duplicates
+ * as well.
+ */
+ for(vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const int orig_index = vert_orig_index[vert_index];
+ vert_normal[vert_index] = normalize(vert_normal[orig_index]);
+ }
+ /* STEP 3: Calculate pointiness using single ring neighborhood. */
+ vector<int> counter(num_verts, 0);
+ vector<float> raw_data(num_verts, 0.0f);
+ vector<float3> edge_accum(num_verts, make_float3(0.0f, 0.0f, 0.0f));
BL::Mesh::edges_iterator e;
- int i = 0;
- for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) {
- int v0 = b_mesh.edges[i].vertices()[0],
- v1 = b_mesh.edges[i].vertices()[1];
+ set< std::pair<int, int> > visited_edges;
+ int edge_index = 0;
+ memset(&counter[0], 0, sizeof(int) * counter.size());
+ for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
+ const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
+ v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
+ int sorted_v0 = v0, sorted_v1 = v1;
+ if(sorted_v0 > sorted_v1) {
+ swap(sorted_v0, sorted_v1);
+ }
+ if(visited_edges.find(std::pair<int, int>(sorted_v0, sorted_v1)) != visited_edges.end()) {
+ continue;
+ }
+ visited_edges.insert(std::pair<int, int>(sorted_v0, sorted_v1));
float3 co0 = get_float3(b_mesh.vertices[v0].co()),
co1 = get_float3(b_mesh.vertices[v1].co());
float3 edge = normalize(co1 - co0);
@@ -554,32 +615,52 @@ static void attr_create_pointiness(Scene *scene,
++counter[v0];
++counter[v1];
}
- i = 0;
- BL::Mesh::vertices_iterator v;
- for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++i) {
- if(counter[i] > 0) {
- float3 normal = get_float3(b_mesh.vertices[i].normal());
- float angle = safe_acosf(dot(normal, edge_accum[i] / counter[i]));
- raw_data[i] = angle * M_1_PI_F;
+ vert_index = 0;
+ for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++vert_index) {
+ const int orig_index = vert_orig_index[vert_index];
+ if(orig_index != vert_index) {
+ /* Skip duplicates, they'll be overwritten later on. */
+ continue;
+ }
+ if(counter[vert_index] > 0) {
+ const float3 normal = vert_normal[vert_index];
+ const float angle =
+ safe_acosf(dot(normal,
+ edge_accum[vert_index] / counter[vert_index]));
+ raw_data[vert_index] = angle * M_1_PI_F;
}
else {
- raw_data[i] = 0.0f;
+ raw_data[vert_index] = 0.0f;
}
}
- /* Blur vertices to approximate 2 ring neighborhood. */
- memset(&counter[0], 0, sizeof(int) * counter.size());
+ /* STEP 3: Blur vertices to approximate 2 ring neighborhood. */
memcpy(data, &raw_data[0], sizeof(float) * raw_data.size());
- i = 0;
- for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) {
- int v0 = b_mesh.edges[i].vertices()[0],
- v1 = b_mesh.edges[i].vertices()[1];
+ memset(&counter[0], 0, sizeof(int) * counter.size());
+ edge_index = 0;
+ visited_edges.clear();
+ for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
+ const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
+ v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
+ int sorted_v0 = v0, sorted_v1 = v1;
+ if(sorted_v0 > sorted_v1) {
+ swap(sorted_v0, sorted_v1);
+ }
+ if(visited_edges.find(std::pair<int, int>(sorted_v0, sorted_v1)) != visited_edges.end()) {
+ continue;
+ }
+ visited_edges.insert(std::pair<int, int>(sorted_v0, sorted_v1));
data[v0] += raw_data[v1];
data[v1] += raw_data[v0];
++counter[v0];
++counter[v1];
}
- for(i = 0; i < numverts; ++i) {
- data[i] /= counter[i] + 1;
+ for(vert_index = 0; vert_index < num_verts; ++vert_index) {
+ data[vert_index] /= counter[vert_index] + 1;
+ }
+ /* STEP 4: Copy attribute to the duplicated vertices. */
+ for(vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const int orig_index = vert_orig_index[vert_index];
+ data[vert_index] = data[orig_index];
}
}