diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2014-04-13 14:51:06 +0400 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2014-04-13 14:51:13 +0400 |
commit | e29698d3cdeb57b4a765d9c3c7ce2a3bb37606fb (patch) | |
tree | 2137956ccc06095765311a5df94c5ea49eb6ec46 /intern | |
parent | 776f8d5a6fa00403e6c46887fbb19956edbd4f05 (diff) |
Split Normals I (5/5): Add support of split normals to Cycles.
Idea and code by Brecht, many thanks!
Reviewers: brecht
Reviewed By: brecht
CC: campbellbarton, dingto
Differential Revision: https://developer.blender.org/D369
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 51 | ||||
-rw-r--r-- | intern/cycles/blender/blender_util.h | 7 | ||||
-rw-r--r-- | intern/cycles/render/attribute.cpp | 8 | ||||
-rw-r--r-- | intern/cycles/render/attribute.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 16 | ||||
-rw-r--r-- | intern/cycles/render/mesh.h | 1 |
6 files changed, 69 insertions, 15 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index fb667d1ba2f..dce1109aa88 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -248,6 +248,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< int numverts = b_mesh.vertices.length(); int numfaces = b_mesh.tessfaces.length(); int numtris = 0; + bool use_loop_normals = b_mesh.use_auto_smooth(); BL::Mesh::vertices_iterator v; BL::Mesh::tessfaces_iterator f; @@ -271,6 +272,20 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N) *N = get_float3(v->normal()); + /* create generated coordinates from undeformed coordinates */ + if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { + Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED); + + float3 loc, size; + mesh_texture_space(b_mesh, loc, size); + + float3 *generated = attr->data_float3(); + size_t i = 0; + + for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) + generated[i++] = get_float3(v->undeformed_co())*size - loc; + } + /* create faces */ vector<int> nverts(numfaces); int fi = 0, ti = 0; @@ -282,6 +297,28 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< int shader = used_shaders[mi]; bool smooth = f->use_smooth(); + /* split vertices if normal is different + * + * note all vertex attributes must have been set here so we can split + * and copy attributes in split_vertex without remapping later */ + if(use_loop_normals) { + BL::Array<float, 12> loop_normals = f->split_normals(); + + for(int i = 0; i < n; i++) { + float3 loop_N = make_float3(loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]); + + if(N[vi[i]] != loop_N) { + int new_vi = mesh->split_vertex(vi[i]); + + /* set new normal and vertex index */ + N = attr_N->data_float3(); + N[new_vi] = loop_N; + vi[i] = new_vi; + } + } + } + + /* create triangles */ if(n == 4) { if(is_zero(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) || is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]]))) { @@ -382,20 +419,6 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< } } - /* create generated coordinates from undeformed coordinates */ - if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { - Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED); - - float3 loc, size; - mesh_texture_space(b_mesh, loc, size); - - float3 *generated = attr->data_float3(); - size_t i = 0; - - for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) - generated[i++] = get_float3(v->undeformed_co())*size - loc; - } - /* for volume objects, create a matrix to transform from object space to * mesh texture space. this does not work with deformations but that can * probably only be done well with a volume grid mapping of coordinates */ diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 45ca0e17550..b2046b290b2 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -42,7 +42,12 @@ void python_thread_state_restore(void **python_thread_state); static inline BL::Mesh object_to_mesh(BL::BlendData data, BL::Object object, BL::Scene scene, bool apply_modifiers, bool render, bool calc_undeformed) { - return data.meshes.new_from_object(scene, object, apply_modifiers, (render)? 2: 1, true, calc_undeformed); + BL::Mesh me = data.meshes.new_from_object(scene, object, apply_modifiers, (render)? 2: 1, false, calc_undeformed); + if (me.use_auto_smooth()) { + me.calc_normals_split(me.auto_smooth_angle()); + } + me.calc_tessface(); + return me; } static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size) diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index ce232e90ffc..14805b6f11a 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -96,6 +96,14 @@ void Attribute::add(const VoxelAttribute& f) buffer.push_back(data[i]); } +void Attribute::add(const char *data) +{ + size_t size = data_sizeof(); + + for(size_t i = 0; i < size; i++) + buffer.push_back(data[i]); +} + size_t Attribute::data_sizeof() const { if(element == ATTR_ELEMENT_VOXEL) diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h index 3dc7b7f7401..9fc32db8444 100644 --- a/intern/cycles/render/attribute.h +++ b/intern/cycles/render/attribute.h @@ -82,6 +82,7 @@ public: void add(const float3& f); void add(const Transform& f); void add(const VoxelAttribute& f); + void add(const char *data); static bool same_storage(TypeDesc a, TypeDesc b); static const char *standard_name(AttributeStandard std); diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 2ae15e09efb..ddcc42a9ae9 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -134,6 +134,22 @@ void Mesh::clear() transform_normal = transform_identity(); } +int Mesh::split_vertex(int vertex) +{ + /* copy vertex location and vertex attributes */ + verts.push_back(verts[vertex]); + + foreach(Attribute& attr, attributes.attributes) { + if(attr.element == ATTR_ELEMENT_VERTEX) { + vector<char> tmp(attr.data_sizeof()); + memcpy(&tmp[0], attr.data() + tmp.size()*vertex, tmp.size()); + attr.add(&tmp[0]); + } + } + + return verts.size() - 1; +} + void Mesh::set_triangle(int i, int v0, int v1, int v2, int shader_, bool smooth_) { Triangle tri; diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index eec20acd3a9..247e3dd555e 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -114,6 +114,7 @@ public: void add_triangle(int v0, int v1, int v2, int shader, bool smooth); void add_curve_key(float3 loc, float radius); void add_curve(int first_key, int num_keys, int shader); + int split_vertex(int vertex); void compute_bounds(); void add_face_normals(); |