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-10-10 18:21:58 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2012-10-10 18:21:58 +0400
commit56f798db8c0643062fb2f6902a02978a71ac477c (patch)
tree35793ea5b1e6d252798f310d9251829f7cce9380 /intern
parent725cfab2dc8a505d16680c114b6b7c0e6d7326a5 (diff)
Cycles: make anistropic BSDF / tangent work without UV map, based on generated
coordinates map to a sphere.
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/blender/blender_mesh.cpp125
1 files changed, 96 insertions, 29 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 8f737be9765..bbc9b00b0dc 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -33,7 +33,23 @@ CCL_NAMESPACE_BEGIN
/* Find/Add */
-static float3 tri_calc_tangent(float3 v0, float3 v1, float3 v2, float3 tx0, float3 tx1, float3 tx2)
+static float3 tangent_uv_from_generated(float3 P)
+{
+ float length = len(P);
+
+ if(length == 0.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float u = 0.0f;
+ if(!(P.x == 0.0f && P.y == 0.0f))
+ u = (1.0f - atan2f(P.x, P.y))/(2.0f*M_PI_F);
+
+ float v = 1.0f - acosf(clamp(P.z/length, -1.0f, 1.0f))/M_PI_F;
+
+ return make_float3(u, v, 0.0f);
+}
+
+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;
@@ -89,27 +105,6 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
nverts.push_back(n);
}
- /* create generated coordinates. todo: we should actually get the orco
- * coordinates from modifiers, for now we use texspace loc/size which
- * is available in the api. */
- if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
- Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
- float3 loc = get_float3(b_mesh.texspace_location());
- float3 size = get_float3(b_mesh.texspace_size());
-
- if(size.x != 0.0f) size.x = 0.5f/size.x;
- if(size.y != 0.0f) size.y = 0.5f/size.y;
- if(size.z != 0.0f) size.z = 0.5f/size.z;
-
- loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
-
- float3 *fdata = attr->data_float3();
- size_t i = 0;
-
- for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
- fdata[i++] = get_float3(v->co())*size - loc;
- }
-
/* create vertex color attributes */
{
BL::Mesh::tessface_vertex_colors_iterator l;
@@ -181,16 +176,16 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
}
/* create texcoord-based tangent attributes */
- {
+ bool need_tangent = mesh->need_attribute(scene, ATTR_STD_TANGENT);
+
+ if(need_tangent) {
BL::Mesh::tessface_uv_textures_iterator l;
for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
- AttributeStandard std = (l->active_render())? ATTR_STD_TANGENT: ATTR_STD_NONE;
-
- if(!mesh->need_attribute(scene, std))
+ if(!l->active_render())
continue;
- Attribute *attr = mesh->attributes.add(std, ustring("Tangent"));
+ Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("Tangent"));
/* compute average tangents per vertex */
float3 *tangents = attr->data_float3();
@@ -214,13 +209,85 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
/* 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 = tri_calc_tangent(v0, v1, v2, tx0, tx1, tx2);
+ 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 = tri_calc_tangent(v0, v2, v3, tx0, tx2, tx3);
+ 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]);
+
+ need_tangent = false;
+ }
+ }
+
+ /* create generated coordinates. todo: we should actually get the orco
+ * coordinates from modifiers, for now we use texspace loc/size which
+ * is available in the api. */
+ if(mesh->need_attribute(scene, ATTR_STD_GENERATED) || need_tangent) {
+ Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
+ float3 loc = get_float3(b_mesh.texspace_location());
+ float3 size = get_float3(b_mesh.texspace_size());
+
+ if(size.x != 0.0f) size.x = 0.5f/size.x;
+ if(size.y != 0.0f) size.y = 0.5f/size.y;
+ if(size.z != 0.0f) size.z = 0.5f/size.z;
+
+ loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
+
+ 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->co())*size - loc;
+
+ /* if there is no UV map, we generated tangents from generated coordinates */
+ if(need_tangent) {
+ 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());
+
+ size_t fi = 0; /* face index */
+ for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++fi, ++f) {
+ int4 vi = get_int4(f->vertices_raw());
+
+ float3 tx0 = tangent_uv_from_generated(generated[vi[0]]);
+ float3 tx1 = tangent_uv_from_generated(generated[vi[1]]);
+ float3 tx2 = tangent_uv_from_generated(generated[vi[2]]);
+
+ 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 = tangent_uv_from_generated(generated[vi[3]]);
+ 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;