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:
parent
776f8d5a6f
commit
e29698d3cd
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue