diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-10-10 18:21:58 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-10-10 18:21:58 +0400 |
commit | 56f798db8c0643062fb2f6902a02978a71ac477c (patch) | |
tree | 35793ea5b1e6d252798f310d9251829f7cce9380 /intern/cycles/blender | |
parent | 725cfab2dc8a505d16680c114b6b7c0e6d7326a5 (diff) |
Cycles: make anistropic BSDF / tangent work without UV map, based on generated
coordinates map to a sphere.
Diffstat (limited to 'intern/cycles/blender')
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 125 |
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; |