diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-11-03 19:36:02 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-11-03 19:36:02 +0400 |
commit | 9db3f2368cb933002a48291c69170922eeb0256d (patch) | |
tree | a7819cc85455bc9bac511e368c42f5ba2406e9f4 | |
parent | a434ab54c668f25045fe49098b3e4b5cf4b7e6ab (diff) |
Cycles: use mikktspace now for computing tangents from UV maps. This avoids ugly
averaged tangents at UV seams but instead now the seams will show as discontinuities
in the tangent.
-rw-r--r-- | intern/cycles/SConscript | 2 | ||||
-rw-r--r-- | intern/cycles/blender/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 193 | ||||
-rw-r--r-- | intern/cycles/blender/blender_object.cpp | 11 | ||||
-rw-r--r-- | intern/cycles/blender/blender_util.h | 23 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_geometry.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/attribute.cpp | 2 |
7 files changed, 135 insertions, 99 deletions
diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index a7b8637e3ad..c0e0353d37d 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -29,7 +29,7 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']: incs.extend('. bvh render device kernel kernel/osl kernel/svm util subd'.split()) incs.extend('#intern/guardedalloc #source/blender/makesrna #source/blender/makesdna'.split()) incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.split()) -incs.extend('#extern/glew/include'.split()) +incs.extend('#extern/glew/include #intern/mikktspace'.split()) incs.append(cycles['BF_OIIO_INC']) incs.append(cycles['BF_BOOST_INC']) incs.append(cycles['BF_PYTHON_INC']) diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index 96948e49d1a..292c37d6b61 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -7,6 +7,7 @@ set(INC ../util ../subd ../../guardedalloc + ../../mikktspace ../../../source/blender/makesdna ../../../source/blender/makesrna ../../../source/blender/blenloader diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 7055cf981c7..b1b1a638219 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -29,32 +29,138 @@ #include "util_foreach.h" +#include "mikktspace.h" + CCL_NAMESPACE_BEGIN -/* Find/Add */ +/* Tangent Space */ -static float3 tangent_from_triangle(float3 v0, float3 v1, float3 v2, float3 tx0, float3 tx1, float3 tx2) -{ - float3 duv1 = tx2 - tx0; - float3 duv2 = tx2 - tx1; - float3 dp1 = v2 - v0; - float3 dp2 = v2 - v1; - float det = duv1[0] * duv2[1] - duv1[1] * duv2[0]; - - if(det != 0.0f) { - return normalize(dp1 * duv2[1] - dp2 * duv1[1]); +struct MikkUserData { + MikkUserData(const BL::Mesh mesh_, const BL::MeshTextureFaceLayer layer_, int num_faces_) + : mesh(mesh_), layer(layer_), num_faces(num_faces_) + { + tangent.resize(num_faces*4); } - else { - /* give back a sane default, using a valid edge as a fallback */ - float3 edge = v1 - v0; - if(len(edge) == 0.0f) - edge = v2 - v0; + BL::Mesh mesh; + BL::MeshTextureFaceLayer layer; + int num_faces; + vector<float4> tangent; +}; + +static int mikk_get_num_faces(const SMikkTSpaceContext *context) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + return userdata->num_faces; +} + +static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + BL::MeshTessFace f = userdata->mesh.tessfaces[face_num]; + int4 vi = get_int4(f.vertices_raw()); + + return (vi[3] == 0)? 3: 4; +} - return normalize(edge); +static void mikk_get_position(const SMikkTSpaceContext *context, float P[3], const int face_num, const int vert_num) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + BL::MeshTessFace f = userdata->mesh.tessfaces[face_num]; + int4 vi = get_int4(f.vertices_raw()); + BL::MeshVertex v = userdata->mesh.vertices[vi[vert_num]]; + float3 vP = get_float3(v.co()); + + P[0] = vP.x; + P[1] = vP.y; + P[2] = vP.z; +} + +static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float uv[2], const int face_num, const int vert_num) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + BL::MeshTextureFace tf = userdata->layer.data[face_num]; + float3 tfuv; + + if(vert_num == 0) + tfuv = get_float3(tf.uv1()); + else if(vert_num == 1) + tfuv = get_float3(tf.uv2()); + else if(vert_num == 2) + tfuv = get_float3(tf.uv3()); + else + tfuv = get_float3(tf.uv4()); + + uv[0] = tfuv.x; + uv[1] = tfuv.y; +} + +static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], const int face_num, const int vert_num) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + BL::MeshTessFace f = userdata->mesh.tessfaces[face_num]; + int4 vi = get_int4(f.vertices_raw()); + BL::MeshVertex v = userdata->mesh.vertices[vi[vert_num]]; + float3 vN = get_float3(v.normal()); + + N[0] = vN.x; + N[1] = vN.y; + N[2] = vN.z; +} + +static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const float T[], const float sign, const int face, const int vert) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + + userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign); +} + +static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector<int>& nverts) +{ + /* setup userdata */ + MikkUserData userdata(b_mesh, b_layer, nverts.size()); + + /* setup interface */ + SMikkTSpaceInterface interface; + memset(&interface, 0, sizeof(interface)); + interface.m_getNumFaces = mikk_get_num_faces; + interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face; + interface.m_getPosition = mikk_get_position; + interface.m_getTexCoord = mikk_get_texture_coordinate; + interface.m_getNormal = mikk_get_normal; + interface.m_setTSpaceBasic = mikk_set_tangent_space; + + /* setup context */ + SMikkTSpaceContext context; + memset(&context, 0, sizeof(context)); + context.m_pUserData = &userdata; + context.m_pInterface = &interface; + + /* compute tangents */ + genTangSpaceDefault(&context); + + /* create attribute */ + /* todo: create float4 attribute for sign */ + Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("Tangent")); + float3 *tangent = attr->data_float3(); + + for (int i = 0; i < nverts.size(); i++) { + tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]); + tangent[1] = float4_to_float3(userdata.tangent[i*4 + 1]); + tangent[2] = float4_to_float3(userdata.tangent[i*4 + 2]); + tangent += 3; + + if(nverts[i] == 4) { + tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]); + tangent[1] = float4_to_float3(userdata.tangent[i*4 + 2]); + tangent[2] = float4_to_float3(userdata.tangent[i*4 + 3]); + tangent += 3; + } } } +/* Create Mesh */ + static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders) { /* create vertices */ @@ -167,54 +273,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< if(!l->active_render()) continue; - Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("Tangent")); - - /* compute average tangents per vertex */ - float3 *tangents = attr->data_float3(); - memset(tangents, 0, sizeof(float3)*mesh->verts.size()); - - BL::MeshTextureFaceLayer::data_iterator t; - - size_t fi = 0; /* face index */ - b_mesh.tessfaces.begin(f); - for(l->data.begin(t); t != l->data.end() && f != b_mesh.tessfaces.end(); ++t, ++fi, ++f) { - int4 vi = get_int4(f->vertices_raw()); - - float3 tx0 = get_float3(t->uv1()); - float3 tx1 = get_float3(t->uv2()); - float3 tx2 = get_float3(t->uv3()); - - float3 v0 = mesh->verts[vi[0]]; - float3 v1 = mesh->verts[vi[1]]; - float3 v2 = mesh->verts[vi[2]]; - - /* calculate tangent for the triangle; - * get vertex positions, and find change in position with respect - * to the texture coords in the first texture coord dimension */ - float3 tangent0 = tangent_from_triangle(v0, v1, v2, tx0, tx1, tx2); - - if(nverts[fi] == 4) { - /* quad tangent */ - float3 tx3 = get_float3(t->uv4()); - float3 v3 = mesh->verts[vi[3]]; - float3 tangent1 = tangent_from_triangle(v0, v2, v3, tx0, tx2, tx3); - - tangents[vi[0]] += 0.5f*(tangent0 + tangent1); - tangents[vi[1]] += tangent0; - tangents[vi[2]] += 0.5f*(tangent0 + tangent1); - tangents[vi[3]] += tangent1; - } - else { - /* triangle tangent */ - tangents[vi[0]] += tangent0; - tangents[vi[1]] += tangent0; - tangents[vi[2]] += tangent0; - } - } - - /* normalize tangent vectors */ - for(int i = 0; i < mesh->verts.size(); i++) - tangents[i] = normalize(tangents[i]); + mikk_compute_tangents(b_mesh, *l, mesh, nverts); } } @@ -351,7 +410,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated) create_mesh(scene, mesh, b_mesh, used_shaders); /* free derived mesh */ - object_remove_mesh(b_data, b_mesh); + b_data.meshes.remove(b_mesh); } /* displacement method */ @@ -409,7 +468,7 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion) mesh->attributes.remove(std); /* free derived mesh */ - object_remove_mesh(b_data, b_mesh); + b_data.meshes.remove(b_mesh); } } diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 6de2b0f08fa..1b920249733 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -330,10 +330,10 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) int num_particles = object_count_particles(*b_ob); if(b_ob->is_duplicator()) { - hide = true; /* duplicators hidden by default */ + hide = true; /* duplicators hidden by default */ /* dupli objects */ - object_create_duplilist(*b_ob, b_scene); + b_ob->dupli_list_create(b_scene, 2); BL::Object::dupli_list_iterator b_dup; int b_index = 0; @@ -361,10 +361,9 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) ++b_index; } - object_free_duplilist(*b_ob); + b_ob->dupli_list_clear(); } - /* sync particles and check if we should render or hide particle emitter */ BL::Object::particle_systems_iterator b_psys; for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) { @@ -422,7 +421,7 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override) int frame = b_scene.frame_current(); for(int motion = -1; motion <= 1; motion += 2) { - scene_frame_set(b_scene, frame + motion); + b_scene.frame_set(frame + motion, 0.0f); /* camera object */ if(b_cam) @@ -432,7 +431,7 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override) sync_objects(b_v3d, motion); } - scene_frame_set(b_scene, frame); + b_scene.frame_set(frame, 0.0f); /* tag camera for motion update */ if(scene->camera->motion_modified(prevcam)) diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 98460036d17..df1e99882b8 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -52,24 +52,6 @@ static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size } } -static inline void object_remove_mesh(BL::BlendData data, BL::Mesh mesh) -{ - /* TODO: BlendData.meshes ideally should be also a subclass of BlendDataMeshes */ - BL::BlendDataMeshes mesh_data(data.ptr); - - mesh_data.remove(mesh); -} - -static inline void object_create_duplilist(BL::Object self, BL::Scene scene) -{ - self.dupli_list_create(scene, 2); -} - -static inline void object_free_duplilist(BL::Object self) -{ - self.dupli_list_clear(); -} - static inline bool BKE_object_is_modified(BL::Object self, BL::Scene scene, bool preview) { return self.is_modified(scene, (preview)? (1<<0): (1<<1))? true: false; @@ -88,11 +70,6 @@ static inline string image_user_file_path(BL::ImageUser iuser, BL::Image ima, in return string(filepath); } -static inline void scene_frame_set(BL::Scene scene, int frame) -{ - scene.frame_set(frame, 0.0f); -} - /* Utilities */ static inline Transform get_transform(BL::Array<float, 16> array) diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index e0f9e337652..501fed95002 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -49,7 +49,7 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack, int attr_offset = find_attribute(kg, sd, ATTR_STD_TANGENT); if(attr_offset != ATTR_STD_NOT_FOUND) { - data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); + data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL); object_normal_transform(kg, sd, &data); } else { diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 4bcaef0fb17..c7a9ab3e51a 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -163,7 +163,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) else if(std == ATTR_STD_UV) attr = add(name, TypeDesc::TypePoint, Attribute::CORNER); else if(std == ATTR_STD_TANGENT) - attr = add(name, TypeDesc::TypeVector, Attribute::VERTEX); + attr = add(name, TypeDesc::TypeVector, Attribute::CORNER); else if(std == ATTR_STD_GENERATED) attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); else if(std == ATTR_STD_POSITION_UNDEFORMED) |