Revision: 51265
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=51265
Author:   blendix
Date:     2012-10-10 14:21:58 +0000 (Wed, 10 Oct 2012)
Log Message:
-----------
Cycles: make anistropic BSDF / tangent work without UV map, based on generated
coordinates map to a sphere.

Modified Paths:
--------------
    trunk/blender/intern/cycles/blender/blender_mesh.cpp

Modified: trunk/blender/intern/cycles/blender/blender_mesh.cpp
===================================================================
--- trunk/blender/intern/cycles/blender/blender_mesh.cpp        2012-10-10 
14:19:35 UTC (rev 51264)
+++ trunk/blender/intern/cycles/blender/blender_mesh.cpp        2012-10-10 
14:21:58 UTC (rev 51265)
@@ -33,8 +33,24 @@
 
 /* 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;
        float3 dp1 = v2 - v0;
@@ -89,27 +105,6 @@
                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 @@
        }
 
        /* 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,13 @@
                                /* 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;
@@ -238,8 +233,80 @@
                        /* 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;
+                                       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]);
+               }
+       }
 }
 
 static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, 
const vector<uint>& used_shaders)

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to