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
This commit is contained in:
Bastien Montagne 2014-04-13 12:51:06 +02:00
parent 776f8d5a6f
commit e29698d3cd
6 changed files with 69 additions and 15 deletions

View File

@ -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 */

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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();