Blender V2.61 - r43446
|
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