Blender V2.61 - r43446

blender_mesh.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include "mesh.h"
00020 #include "object.h"
00021 #include "scene.h"
00022 
00023 #include "blender_sync.h"
00024 #include "blender_util.h"
00025 
00026 #include "subd_mesh.h"
00027 #include "subd_patch.h"
00028 #include "subd_split.h"
00029 
00030 #include "util_foreach.h"
00031 
00032 CCL_NAMESPACE_BEGIN
00033 
00034 /* Find/Add */
00035 
00036 static bool mesh_need_attribute(Scene *scene, Mesh *mesh, Attribute::Standard std)
00037 {
00038     if(std == Attribute::STD_NONE)
00039         return false;
00040 
00041     foreach(uint shader, mesh->used_shaders)
00042         if(scene->shaders[shader]->attributes.find(std))
00043             return true;
00044     
00045     return false;
00046 }
00047 
00048 static bool mesh_need_attribute(Scene *scene, Mesh *mesh, ustring name)
00049 {
00050     if(name == ustring())
00051         return false;
00052 
00053     foreach(uint shader, mesh->used_shaders)
00054         if(scene->shaders[shader]->attributes.find(name))
00055             return true;
00056     
00057     return false;
00058 }
00059 
00060 static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
00061 {
00062     /* create vertices */
00063     BL::Mesh::vertices_iterator v;
00064 
00065     for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
00066         mesh->verts.push_back(get_float3(v->co()));
00067 
00068     /* create vertex normals */
00069     Attribute *attr_N = mesh->attributes.add(Attribute::STD_VERTEX_NORMAL);
00070     float3 *N = attr_N->data_float3();
00071 
00072     for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
00073         *N= get_float3(v->normal());
00074 
00075     /* create faces */
00076     BL::Mesh::faces_iterator f;
00077     vector<int> nverts;
00078 
00079     for(b_mesh.faces.begin(f); f != b_mesh.faces.end(); ++f) {
00080         int4 vi = get_int4(f->vertices_raw());
00081         int n = (vi[3] == 0)? 3: 4;
00082         int mi = clamp(f->material_index(), 0, used_shaders.size()-1);
00083         int shader = used_shaders[mi];
00084         bool smooth = f->use_smooth();
00085 
00086         mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
00087 
00088         if(n == 4)
00089             mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
00090 
00091         nverts.push_back(n);
00092     }
00093 
00094     /* create generated coordinates. todo: we should actually get the orco
00095        coordinates from modifiers, for now we use texspace loc/size which
00096        is available in the api. */
00097     if(mesh_need_attribute(scene, mesh, Attribute::STD_GENERATED)) {
00098         Attribute *attr = mesh->attributes.add(Attribute::STD_GENERATED);
00099         float3 loc = get_float3(b_mesh.texspace_location());
00100         float3 size = get_float3(b_mesh.texspace_size());
00101 
00102         if(size.x != 0.0f) size.x = 0.5f/size.x;
00103         if(size.y != 0.0f) size.y = 0.5f/size.y;
00104         if(size.z != 0.0f) size.z = 0.5f/size.z;
00105 
00106         loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
00107 
00108         float3 *fdata = attr->data_float3();
00109         BL::Mesh::vertices_iterator v;
00110         size_t i = 0;
00111 
00112         for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
00113             fdata[i++] = get_float3(v->co())*size - loc;
00114     }
00115 
00116     /* create vertex color attributes */
00117     {
00118         BL::Mesh::vertex_colors_iterator l;
00119 
00120         for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) {
00121             if(!mesh_need_attribute(scene, mesh, ustring(l->name().c_str())))
00122                 continue;
00123 
00124             Attribute *attr = mesh->attributes.add(
00125                 ustring(l->name().c_str()), TypeDesc::TypeColor, Attribute::CORNER);
00126 
00127             BL::MeshColorLayer::data_iterator c;
00128             float3 *fdata = attr->data_float3();
00129             size_t i = 0;
00130 
00131             for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
00132                 fdata[0] = color_srgb_to_scene_linear(get_float3(c->color1()));
00133                 fdata[1] = color_srgb_to_scene_linear(get_float3(c->color2()));
00134                 fdata[2] = color_srgb_to_scene_linear(get_float3(c->color3()));
00135 
00136                 if(nverts[i] == 4) {
00137                     fdata[3] = fdata[0];
00138                     fdata[4] = fdata[2];
00139                     fdata[5] = color_srgb_to_scene_linear(get_float3(c->color4()));
00140                     fdata += 6;
00141                 }
00142                 else
00143                     fdata += 3;
00144             }
00145         }
00146     }
00147 
00148     /* create uv map attributes */
00149     {
00150         BL::Mesh::uv_textures_iterator l;
00151 
00152         for(b_mesh.uv_textures.begin(l); l != b_mesh.uv_textures.end(); ++l) {
00153             Attribute::Standard std = (l->active_render())? Attribute::STD_UV: Attribute::STD_NONE;
00154             ustring name = ustring(l->name().c_str());
00155 
00156             if(!(mesh_need_attribute(scene, mesh, name) || mesh_need_attribute(scene, mesh, std)))
00157                 continue;
00158 
00159             Attribute *attr;
00160 
00161             if(l->active_render())
00162                 attr = mesh->attributes.add(std, name);
00163             else
00164                 attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);
00165 
00166             BL::MeshTextureFaceLayer::data_iterator t;
00167             float3 *fdata = attr->data_float3();
00168             size_t i = 0;
00169 
00170             for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
00171                 fdata[0] =  get_float3(t->uv1());
00172                 fdata[1] =  get_float3(t->uv2());
00173                 fdata[2] =  get_float3(t->uv3());
00174                 fdata += 3;
00175 
00176                 if(nverts[i] == 4) {
00177                     fdata[0] =  get_float3(t->uv1());
00178                     fdata[1] =  get_float3(t->uv3());
00179                     fdata[2] =  get_float3(t->uv4());
00180                     fdata += 3;
00181                 }
00182             }
00183         }
00184     }
00185 }
00186 
00187 static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
00188 {
00189     /* create subd mesh */
00190     SubdMesh sdmesh;
00191 
00192     /* create vertices */
00193     BL::Mesh::vertices_iterator v;
00194 
00195     for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
00196         sdmesh.add_vert(get_float3(v->co()));
00197 
00198     /* create faces */
00199     BL::Mesh::faces_iterator f;
00200 
00201     for(b_mesh.faces.begin(f); f != b_mesh.faces.end(); ++f) {
00202         int4 vi = get_int4(f->vertices_raw());
00203         int n= (vi[3] == 0)? 3: 4;
00204         //int shader = used_shaders[f->material_index()];
00205 
00206         if(n == 4)
00207             sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]);
00208         /*else
00209             sdmesh.add_face(vi[0], vi[1], vi[2]);*/
00210     }
00211 
00212     /* finalize subd mesh */
00213     sdmesh.link_boundary();
00214 
00215     /* subdivide */
00216     DiagSplit dsplit;
00217     dsplit.camera = NULL;
00218     dsplit.dicing_rate = RNA_float_get(cmesh, "dicing_rate");
00219 
00220     sdmesh.tesselate(&dsplit, false, mesh, used_shaders[0], true);
00221 }
00222 
00223 /* Sync */
00224 
00225 Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
00226 {
00227     /* test if we can instance or if the object is modified */
00228     BL::ID b_ob_data = b_ob.data();
00229     BL::ID key = (object_is_modified(b_ob))? b_ob: b_ob_data;
00230 
00231     /* find shader indices */
00232     vector<uint> used_shaders;
00233 
00234     BL::Object::material_slots_iterator slot;
00235     for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
00236         BL::Material material_override = render_layers.front().material_override;
00237 
00238         if(material_override)
00239             find_shader(material_override, used_shaders, scene->default_surface);
00240         else
00241             find_shader(slot->material(), used_shaders, scene->default_surface);
00242     }
00243 
00244     if(used_shaders.size() == 0)
00245         used_shaders.push_back(scene->default_surface);
00246     
00247     /* test if we need to sync */
00248     Mesh *mesh;
00249 
00250     if(!mesh_map.sync(&mesh, key)) {
00251         /* if transform was applied to mesh, need full update */
00252         if(object_updated && mesh->transform_applied);
00253         /* test if shaders changed, these can be object level so mesh
00254            does not get tagged for recalc */
00255         else if(mesh->used_shaders != used_shaders);
00256         else {
00257             /* even if not tagged for recalc, we may need to sync anyway
00258              * because the shader needs different mesh attributes */
00259             bool attribute_recalc = false;
00260 
00261             foreach(uint shader, mesh->used_shaders)
00262                 if(scene->shaders[shader]->need_update_attributes)
00263                     attribute_recalc = true;
00264 
00265             if(!attribute_recalc)
00266                 return mesh;
00267         }
00268     }
00269 
00270     /* ensure we only sync instanced meshes once */
00271     if(mesh_synced.find(mesh) != mesh_synced.end())
00272         return mesh;
00273     
00274     mesh_synced.insert(mesh);
00275 
00276     /* create derived mesh */
00277     BL::Mesh b_mesh = object_to_mesh(b_ob, b_scene, true, !preview);
00278     PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");
00279 
00280     vector<Mesh::Triangle> oldtriangle = mesh->triangles;
00281 
00282     mesh->clear();
00283     mesh->used_shaders = used_shaders;
00284     mesh->name = ustring(b_ob_data.name().c_str());
00285 
00286     if(b_mesh) {
00287         if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
00288             create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
00289         else
00290             create_mesh(scene, mesh, b_mesh, used_shaders);
00291 
00292         /* free derived mesh */
00293         object_remove_mesh(b_data, b_mesh);
00294     }
00295 
00296     /* displacement method */
00297     if(cmesh.data) {
00298         int method = RNA_enum_get(&cmesh, "displacement_method");
00299 
00300         if(method == 0 || !experimental)
00301             mesh->displacement_method = Mesh::DISPLACE_BUMP;
00302         else if(method == 1)
00303             mesh->displacement_method = Mesh::DISPLACE_TRUE;
00304         else
00305             mesh->displacement_method = Mesh::DISPLACE_BOTH;
00306     }
00307 
00308     /* tag update */
00309     bool rebuild = false;
00310 
00311     if(oldtriangle.size() != mesh->triangles.size())
00312         rebuild = true;
00313     else if(oldtriangle.size()) {
00314         if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
00315             rebuild = true;
00316     }
00317     
00318     mesh->tag_update(scene, rebuild);
00319 
00320     return mesh;
00321 }
00322 
00323 CCL_NAMESPACE_END
00324