diff options
Diffstat (limited to 'intern/cycles/blender/blender_mesh.cpp')
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 272 |
1 files changed, 185 insertions, 87 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 7135e938afb..1f0aa5eef34 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -18,6 +18,7 @@ #include "mesh.h" #include "object.h" #include "scene.h" +#include "camera.h" #include "blender_sync.h" #include "blender_session.h" @@ -35,10 +36,54 @@ CCL_NAMESPACE_BEGIN +/* Per-face bit flags. */ +enum { + /* Face has no special flags. */ + FACE_FLAG_NONE = (0 << 0), + /* Quad face was split using 1-3 diagonal. */ + FACE_FLAG_DIVIDE_13 = (1 << 0), + /* Quad face was split using 2-4 diagonal. */ + FACE_FLAG_DIVIDE_24 = (1 << 1), +}; + +/* Get vertex indices to create triangles from a given face. + * + * Two triangles has vertex indices in the original Blender-side face. + * If face is already a quad tri_b will not be initialized. + */ +inline void face_split_tri_indices(const int num_verts, + const int face_flag, + int tri_a[3], + int tri_b[3]) +{ + if(face_flag & FACE_FLAG_DIVIDE_24) { + tri_a[0] = 0; + tri_a[1] = 1; + tri_a[2] = 3; + if(num_verts == 4) { + tri_b[0] = 2; + tri_b[1] = 3; + tri_b[2] = 1; + } + } + else /*if(face_flag & FACE_FLAG_DIVIDE_13)*/ { + tri_a[0] = 0; + tri_a[1] = 1; + tri_a[2] = 2; + if(num_verts == 4) { + tri_b[0] = 0; + tri_b[1] = 2; + tri_b[2] = 3; + } + } +} + /* Tangent Space */ struct MikkUserData { - MikkUserData(const BL::Mesh mesh_, BL::MeshTextureFaceLayer *layer_, int num_faces_) + MikkUserData(const BL::Mesh& mesh_, + BL::MeshTextureFaceLayer *layer_, + int num_faces_) : mesh(mesh_), layer(layer_), num_faces(num_faces_) { tangent.resize(num_faces*4); @@ -85,7 +130,7 @@ static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float BL::MeshTextureFace tf = userdata->layer->data[face_num]; float3 tfuv; - switch (vert_num) { + switch(vert_num) { case 0: tfuv = get_float3(tf.uv1()); break; @@ -140,7 +185,13 @@ static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const floa 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, const vector<int>& nverts, bool need_sign, bool active_render) +static void mikk_compute_tangents(BL::Mesh& b_mesh, + BL::MeshTextureFaceLayer *b_layer, + Mesh *mesh, + const vector<int>& nverts, + const vector<int>& face_flags, + bool need_sign, + bool active_render) { /* setup userdata */ MikkUserData userdata(b_mesh, b_layer, nverts.size()); @@ -199,28 +250,31 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer *b_l } 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]); + int tri_a[3], tri_b[3]; + face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b); + + tangent[0] = float4_to_float3(userdata.tangent[i*4 + tri_a[0]]); + tangent[1] = float4_to_float3(userdata.tangent[i*4 + tri_a[1]]); + tangent[2] = float4_to_float3(userdata.tangent[i*4 + tri_a[2]]); tangent += 3; if(tangent_sign) { - tangent_sign[0] = userdata.tangent[i*4 + 0].w; - tangent_sign[1] = userdata.tangent[i*4 + 1].w; - tangent_sign[2] = userdata.tangent[i*4 + 2].w; + tangent_sign[0] = userdata.tangent[i*4 + tri_a[0]].w; + tangent_sign[1] = userdata.tangent[i*4 + tri_a[1]].w; + tangent_sign[2] = userdata.tangent[i*4 + tri_a[2]].w; tangent_sign += 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[0] = float4_to_float3(userdata.tangent[i*4 + tri_b[0]]); + tangent[1] = float4_to_float3(userdata.tangent[i*4 + tri_b[1]]); + tangent[2] = float4_to_float3(userdata.tangent[i*4 + tri_b[2]]); tangent += 3; if(tangent_sign) { - tangent_sign[0] = userdata.tangent[i*4 + 0].w; - tangent_sign[1] = userdata.tangent[i*4 + 2].w; - tangent_sign[2] = userdata.tangent[i*4 + 3].w; + tangent_sign[0] = userdata.tangent[i*4 + tri_b[0]].w; + tangent_sign[1] = userdata.tangent[i*4 + tri_b[1]].w; + tangent_sign[2] = userdata.tangent[i*4 + tri_b[2]].w; tangent_sign += 3; } } @@ -229,7 +283,11 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer *b_l /* Create Volume Attribute */ -static void create_mesh_volume_attribute(BL::Object b_ob, Mesh *mesh, ImageManager *image_manager, AttributeStandard std, float frame) +static void create_mesh_volume_attribute(BL::Object& b_ob, + Mesh *mesh, + ImageManager *image_manager, + AttributeStandard std, + float frame) { BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob); @@ -250,11 +308,14 @@ static void create_mesh_volume_attribute(BL::Object b_ob, Mesh *mesh, ImageManag is_float, is_linear, INTERPOLATION_LINEAR, - EXTENSION_REPEAT, + EXTENSION_CLIP, true); } -static void create_mesh_volume_attributes(Scene *scene, BL::Object b_ob, Mesh *mesh, float frame) +static void create_mesh_volume_attributes(Scene *scene, + BL::Object& b_ob, + Mesh *mesh, + float frame) { /* for smoke volume rendering */ if(mesh->need_attribute(scene, ATTR_STD_VOLUME_DENSITY)) @@ -272,8 +333,9 @@ static void create_mesh_volume_attributes(Scene *scene, BL::Object b_ob, Mesh *m /* Create vertex color attributes. */ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, - BL::Mesh b_mesh, - const vector<int>& nverts) + BL::Mesh& b_mesh, + const vector<int>& nverts, + const vector<int>& face_flags) { BL::Mesh::tessface_vertex_colors_iterator l; for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) { @@ -288,14 +350,25 @@ static void attr_create_vertex_color(Scene *scene, size_t i = 0; for(l->data.begin(c); c != l->data.end(); ++c, ++i) { - cdata[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1()))); - cdata[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2()))); - cdata[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3()))); + int tri_a[3], tri_b[3]; + face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b); + uchar4 colors[4]; + colors[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1()))); + colors[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2()))); + colors[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3()))); if(nverts[i] == 4) { - cdata[3] = cdata[0]; - cdata[4] = cdata[2]; - cdata[5] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4()))); + colors[3] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4()))); + } + + cdata[0] = colors[tri_a[0]]; + cdata[1] = colors[tri_a[1]]; + cdata[2] = colors[tri_a[2]]; + + if(nverts[i] == 4) { + cdata[3] = colors[tri_b[0]]; + cdata[4] = colors[tri_b[1]]; + cdata[5] = colors[tri_b[2]]; cdata += 6; } else @@ -307,8 +380,9 @@ static void attr_create_vertex_color(Scene *scene, /* Create uv map attributes. */ static void attr_create_uv_map(Scene *scene, Mesh *mesh, - BL::Mesh b_mesh, - const vector<int>& nverts) + BL::Mesh& b_mesh, + const vector<int>& nverts, + const vector<int>& face_flags) { if(b_mesh.tessface_uv_textures.length() != 0) { BL::Mesh::tessface_uv_textures_iterator l; @@ -332,15 +406,26 @@ static void attr_create_uv_map(Scene *scene, size_t i = 0; for(l->data.begin(t); t != l->data.end(); ++t, ++i) { - fdata[0] = get_float3(t->uv1()); - fdata[1] = get_float3(t->uv2()); - fdata[2] = get_float3(t->uv3()); + int tri_a[3], tri_b[3]; + face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b); + + float3 uvs[4]; + uvs[0] = get_float3(t->uv1()); + uvs[1] = get_float3(t->uv2()); + uvs[2] = get_float3(t->uv3()); + if(nverts[i] == 4) { + uvs[3] = get_float3(t->uv4()); + } + + fdata[0] = uvs[tri_a[0]]; + fdata[1] = uvs[tri_a[1]]; + fdata[2] = uvs[tri_a[2]]; fdata += 3; if(nverts[i] == 4) { - fdata[0] = get_float3(t->uv1()); - fdata[1] = get_float3(t->uv3()); - fdata[2] = get_float3(t->uv4()); + fdata[0] = uvs[tri_b[0]]; + fdata[1] = uvs[tri_b[1]]; + fdata[2] = uvs[tri_b[2]]; fdata += 3; } } @@ -355,20 +440,32 @@ static void attr_create_uv_map(Scene *scene, name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)); - mikk_compute_tangents(b_mesh, &(*l), mesh, nverts, need_sign, active_render); + mikk_compute_tangents(b_mesh, + &(*l), + mesh, + nverts, + face_flags, + need_sign, + active_render); } } } else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) { bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN); - mikk_compute_tangents(b_mesh, NULL, mesh, nverts, need_sign, true); + mikk_compute_tangents(b_mesh, + NULL, + mesh, + nverts, + face_flags, + need_sign, + true); } } /* Create vertex pointiness attributes. */ static void attr_create_pointiness(Scene *scene, Mesh *mesh, - BL::Mesh b_mesh) + BL::Mesh& b_mesh) { if(mesh->need_attribute(scene, ATTR_STD_POINTINESS)) { const int numverts = b_mesh.vertices.length(); @@ -432,7 +529,10 @@ static void attr_create_pointiness(Scene *scene, /* Create Mesh */ -static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders) +static void create_mesh(Scene *scene, + Mesh *mesh, + BL::Mesh& b_mesh, + const vector<uint>& used_shaders) { /* count vertices and faces */ int numverts = b_mesh.vertices.length(); @@ -482,6 +582,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< /* create faces */ vector<int> nverts(numfaces); + vector<int> face_flags(numfaces, FACE_FLAG_NONE); int fi = 0, ti = 0; for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) { @@ -517,16 +618,19 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< if(is_zero(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) || is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]]))) { - mesh->set_triangle(ti++, vi[0], vi[1], vi[3], shader, smooth); - mesh->set_triangle(ti++, vi[2], vi[3], vi[1], shader, smooth); + // TODO(mai): order here is probably wrong + mesh->set_triangle(ti++, vi[0], vi[1], vi[3], shader, smooth, true); + mesh->set_triangle(ti++, vi[2], vi[3], vi[1], shader, smooth, true); + face_flags[fi] |= FACE_FLAG_DIVIDE_24; } else { - mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth); - mesh->set_triangle(ti++, vi[0], vi[2], vi[3], shader, smooth); + mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth, true); + mesh->set_triangle(ti++, vi[0], vi[2], vi[3], shader, smooth, true); + face_flags[fi] |= FACE_FLAG_DIVIDE_13; } } else - mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth); + mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth, false); nverts[fi] = n; } @@ -534,8 +638,8 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< /* Create all needed attributes. * The calculate functions will check whether they're needed or not. */ - attr_create_vertex_color(scene, mesh, b_mesh, nverts); - attr_create_uv_map(scene, mesh, b_mesh, nverts); + attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags); + attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags); /* for volume objects, create a matrix to transform from object space to * mesh texture space. this does not work with deformations but that can @@ -551,51 +655,36 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< } } -static void create_subd_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders) +static void create_subd_mesh(Scene *scene, + Mesh *mesh, + BL::Object b_ob, + BL::Mesh& b_mesh, + PointerRNA *cmesh, + const vector<uint>& used_shaders, + float dicing_rate, + int max_subdivisions) { - /* create subd mesh */ - SubdMesh sdmesh; - - /* create vertices */ - BL::Mesh::vertices_iterator v; + Mesh basemesh; + create_mesh(scene, &basemesh, b_mesh, used_shaders); - for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) - sdmesh.add_vert(get_float3(v->co())); - - /* create faces */ - BL::Mesh::tessfaces_iterator f; + SubdParams sdparams(mesh, used_shaders[0], true, false); + sdparams.dicing_rate = max(0.1f, RNA_float_get(cmesh, "dicing_rate") * dicing_rate); + sdparams.max_level = max_subdivisions; - for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) { - int4 vi = get_int4(f->vertices_raw()); - int n = (vi[3] == 0) ? 3: 4; - //int shader = used_shaders[f->material_index()]; - - if(n == 4) - sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]); - else - sdmesh.add_face(vi[0], vi[1], vi[2]); - } - - /* finalize subd mesh */ - sdmesh.finish(); - - /* parameters */ - bool need_ptex = mesh->need_attribute(scene, ATTR_STD_PTEX_FACE_ID) || - mesh->need_attribute(scene, ATTR_STD_PTEX_UV); - - SubdParams sdparams(mesh, used_shaders[0], true, need_ptex); - sdparams.dicing_rate = RNA_float_get(cmesh, "dicing_rate"); - //scene->camera->update(); - //sdparams.camera = scene->camera; + scene->camera->update(); + sdparams.camera = scene->camera; + sdparams.objecttoworld = get_transform(b_ob.matrix_world()); /* tesselate */ DiagSplit dsplit(sdparams); - sdmesh.tessellate(&dsplit); + basemesh.tessellate(&dsplit); } /* Sync */ -Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris) +Mesh *BlenderSync::sync_mesh(BL::Object& b_ob, + bool object_updated, + bool hide_tris) { /* When viewport display is not needed during render we can force some * caches to be releases from blender side in order to reduce peak memory @@ -615,10 +704,13 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri BL::Object::material_slots_iterator slot; for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { - if(material_override) + if(material_override) { find_shader(material_override, used_shaders, scene->default_surface); - else - find_shader(slot->material(), used_shaders, scene->default_surface); + } + else { + BL::ID b_material(slot->material()); + find_shader(b_material, used_shaders, scene->default_surface); + } } if(used_shaders.size() == 0) { @@ -693,8 +785,9 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri if(b_mesh) { if(render_layer.use_surfaces && !hide_tris) { - if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision")) - create_subd_mesh(scene, mesh, b_mesh, &cmesh, used_shaders); + if(cmesh.data && experimental && RNA_enum_get(&cmesh, "subdivision_type")) + create_subd_mesh(scene, mesh, b_ob, b_mesh, &cmesh, used_shaders, + dicing_rate, max_subdivisions); else create_mesh(scene, mesh, b_mesh, used_shaders); @@ -716,7 +809,10 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri /* displacement method */ if(cmesh.data) { - const int method = RNA_enum_get(&cmesh, "displacement_method"); + const int method = get_enum(cmesh, + "displacement_method", + Mesh::DISPLACE_NUM_METHODS, + Mesh::DISPLACE_BUMP); if(method == 0 || !experimental) mesh->displacement_method = Mesh::DISPLACE_BUMP; @@ -748,7 +844,9 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri return mesh; } -void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion_time) +void BlenderSync::sync_mesh_motion(BL::Object& b_ob, + Object *object, + float motion_time) { /* ensure we only sync instanced meshes once */ Mesh *mesh = object->mesh; |