Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2012-11-03 19:36:02 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2012-11-03 19:36:02 +0400
commit9db3f2368cb933002a48291c69170922eeb0256d (patch)
treea7819cc85455bc9bac511e368c42f5ba2406e9f4 /intern
parenta434ab54c668f25045fe49098b3e4b5cf4b7e6ab (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.
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/SConscript2
-rw-r--r--intern/cycles/blender/CMakeLists.txt1
-rw-r--r--intern/cycles/blender/blender_mesh.cpp193
-rw-r--r--intern/cycles/blender/blender_object.cpp11
-rw-r--r--intern/cycles/blender/blender_util.h23
-rw-r--r--intern/cycles/kernel/svm/svm_geometry.h2
-rw-r--r--intern/cycles/render/attribute.cpp2
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)