diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 9e11cc1ae0b..ed19fb2672b 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -601,37 +601,50 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion if(numverts) { /* find attributes */ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); + Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); bool new_attribute = false; /* add new attributes if they don't exist already */ if(!attr_mP) { attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); + if(attr_N) + attr_mN = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL); new_attribute = true; } /* load vertex data from mesh */ float3 *mP = attr_mP->data_float3() + time_index*numverts; + float3 *mN = (attr_mN)? attr_mN->data_float3() + time_index*numverts: NULL; BL::Mesh::vertices_iterator v; int i = 0; - for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < numverts; ++v, ++i) + for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < numverts; ++v, ++i) { mP[i] = get_float3(v->co()); + if(mN) + mN[i] = get_float3(v->normal()); + } /* in case of new attribute, we verify if there really was any motion */ if(new_attribute) { if(i != numverts || memcmp(mP, &mesh->verts[0], sizeof(float3)*numverts) == 0) { /* no motion, remove attributes again */ mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION); + if(attr_mN) + mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL); } else if(time_index > 0) { /* motion, fill up previous steps that we might have skipped because * they had no motion, but we need them anyway now */ float3 *P = &mesh->verts[0]; + float3 *N = (attr_N)? attr_N->data_float3(): NULL; - for(int step = 0; step < time_index; step++) + for(int step = 0; step < time_index; step++) { memcpy(attr_mP->data_float3() + step*numverts, P, sizeof(float3)*numverts); + memcpy(attr_mN->data_float3() + step*numverts, N, sizeof(float3)*numverts); + } } } } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index f708f019912..2590717d378 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -471,6 +471,7 @@ typedef enum AttributeStandard { ATTR_STD_POSITION_UNDEFORMED, ATTR_STD_POSITION_UNDISPLACED, ATTR_STD_MOTION_VERTEX_POSITION, + ATTR_STD_MOTION_VERTEX_NORMAL, ATTR_STD_PARTICLE, ATTR_STD_CURVE_INTERCEPT, ATTR_STD_PTEX_FACE_ID, diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index e730cab0c60..f524a9fa3bc 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -165,6 +165,8 @@ const char *Attribute::standard_name(AttributeStandard std) return "undisplaced"; else if(std == ATTR_STD_MOTION_VERTEX_POSITION) return "motion_P"; + else if(std == ATTR_STD_MOTION_VERTEX_NORMAL) + return "motion_N"; else if(std == ATTR_STD_PARTICLE) return "particle"; else if(std == ATTR_STD_CURVE_INTERCEPT) @@ -275,6 +277,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) case ATTR_STD_MOTION_VERTEX_POSITION: attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION); break; + case ATTR_STD_MOTION_VERTEX_NORMAL: + attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION); + break; case ATTR_STD_PTEX_FACE_ID: attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE); break; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 0d09328119c..8e2cc97eba0 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -242,6 +242,21 @@ void Mesh::compute_bounds() bounds = bnds; } +static float3 compute_face_normal(const Mesh::Triangle& t, float3 *verts) +{ + float3 v0 = verts[t.v[0]]; + float3 v1 = verts[t.v[1]]; + float3 v2 = verts[t.v[2]]; + + float3 norm = cross(v1 - v0, v2 - v0); + float normlen = len(norm); + + if(normlen == 0.0f) + return make_float3(0.0f, 0.0f, 0.0f); + + return norm / normlen; +} + void Mesh::add_face_normals() { /* don't compute if already there */ @@ -261,17 +276,7 @@ void Mesh::add_face_normals() Triangle *triangles_ptr = &triangles[0]; for(size_t i = 0; i < triangles_size; i++) { - Triangle t = triangles_ptr[i]; - float3 v0 = verts_ptr[t.v[0]]; - float3 v1 = verts_ptr[t.v[1]]; - float3 v2 = verts_ptr[t.v[2]]; - - float3 norm = cross(v1 - v0, v2 - v0); - float normlen = len(norm); - if(normlen == 0.0f) - fN[i] = make_float3(0.0f, 0.0f, 0.0f); - else - fN[i] = norm / normlen; + fN[i] = compute_face_normal(triangles_ptr[i], verts_ptr); if(flip) fN[i] = -fN[i]; @@ -289,36 +294,69 @@ void Mesh::add_face_normals() void Mesh::add_vertex_normals() { - /* don't compute if already there */ - if(attributes.find(ATTR_STD_VERTEX_NORMAL)) - return; - - /* get attributes */ - Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL); - Attribute *attr_vN = attributes.add(ATTR_STD_VERTEX_NORMAL); - - float3 *fN = attr_fN->data_float3(); - float3 *vN = attr_vN->data_float3(); - - /* compute vertex normals */ - memset(vN, 0, verts.size()*sizeof(float3)); - + bool flip = transform_negative_scaled; size_t verts_size = verts.size(); size_t triangles_size = triangles.size(); - bool flip = transform_negative_scaled; - if(triangles_size) { - Triangle *triangles_ptr = &triangles[0]; + /* static vertex normals */ + if(!attributes.find(ATTR_STD_VERTEX_NORMAL)) { + /* get attributes */ + Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL); + Attribute *attr_vN = attributes.add(ATTR_STD_VERTEX_NORMAL); - for(size_t i = 0; i < triangles_size; i++) - for(size_t j = 0; j < 3; j++) - vN[triangles_ptr[i].v[j]] += fN[i]; + float3 *fN = attr_fN->data_float3(); + float3 *vN = attr_vN->data_float3(); + + /* compute vertex normals */ + memset(vN, 0, verts.size()*sizeof(float3)); + + if(triangles_size) { + Triangle *triangles_ptr = &triangles[0]; + + for(size_t i = 0; i < triangles_size; i++) + for(size_t j = 0; j < 3; j++) + vN[triangles_ptr[i].v[j]] += fN[i]; + } + + for(size_t i = 0; i < verts_size; i++) { + vN[i] = normalize(vN[i]); + if(flip) + vN[i] = -vN[i]; + } } - for(size_t i = 0; i < verts_size; i++) { - vN[i] = normalize(vN[i]); - if(flip) - vN[i] = -vN[i]; + /* motion vertex normals */ + Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + Attribute *attr_mN = attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); + + if(false && !attr_mN) { + /* create attribute */ + attr_mN = attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL); + + for(int step = 0; step < motion_steps - 1; step++) { + float3 *mP = attr_mP->data_float3() + step*verts.size(); + float3 *mN = attr_mN->data_float3() + step*verts.size(); + + /* compute */ + memset(mN, 0, verts.size()*sizeof(float3)); + + if(triangles_size) { + Triangle *triangles_ptr = &triangles[0]; + + for(size_t i = 0; i < triangles_size; i++) { + for(size_t j = 0; j < 3; j++) { + float3 fN = compute_face_normal(triangles_ptr[i], mP); + mN[triangles_ptr[i].v[j]] += fN; + } + } + } + + for(size_t i = 0; i < verts_size; i++) { + mN[i] = normalize(mN[i]); + if(flip) + mN[i] = -mN[i]; + } + } } } diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index f7d2f2d0a8e..2ed4efe7f2b 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -228,6 +228,8 @@ bool Scene::need_global_attribute(AttributeStandard std) return Pass::contains(film->passes, PASS_UV); if(std == ATTR_STD_MOTION_VERTEX_POSITION) return need_motion() != MOTION_NONE; + if(std == ATTR_STD_MOTION_VERTEX_NORMAL) + return need_motion() == MOTION_BLUR; return false; }