2 * Copyright 2011, Blender Foundation.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "blender_sync.h"
24 #include "blender_util.h"
26 #include "subd_mesh.h"
27 #include "subd_patch.h"
28 #include "subd_split.h"
30 #include "util_foreach.h"
36 static bool mesh_need_attribute(Scene *scene, Mesh *mesh, Attribute::Standard std)
38 if(std == Attribute::STD_NONE)
41 foreach(uint shader, mesh->used_shaders)
42 if(scene->shaders[shader]->attributes.find(std))
48 static bool mesh_need_attribute(Scene *scene, Mesh *mesh, ustring name)
53 foreach(uint shader, mesh->used_shaders)
54 if(scene->shaders[shader]->attributes.find(name))
60 static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
63 BL::Mesh::vertices_iterator v;
65 for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
66 mesh->verts.push_back(get_float3(v->co()));
68 /* create vertex normals */
69 Attribute *attr_N = mesh->attributes.add(Attribute::STD_VERTEX_NORMAL);
70 float3 *N = attr_N->data_float3();
72 for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
73 *N= get_float3(v->normal());
76 BL::Mesh::faces_iterator f;
79 for(b_mesh.faces.begin(f); f != b_mesh.faces.end(); ++f) {
80 int4 vi = get_int4(f->vertices_raw());
81 int n = (vi[3] == 0)? 3: 4;
82 int mi = clamp(f->material_index(), 0, used_shaders.size()-1);
83 int shader = used_shaders[mi];
84 bool smooth = f->use_smooth();
86 mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
89 mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
94 /* create generated coordinates. todo: we should actually get the orco
95 coordinates from modifiers, for now we use texspace loc/size which
96 is available in the api. */
97 if(mesh_need_attribute(scene, mesh, Attribute::STD_GENERATED)) {
98 Attribute *attr = mesh->attributes.add(Attribute::STD_GENERATED);
99 float3 loc = get_float3(b_mesh.texspace_location());
100 float3 size = get_float3(b_mesh.texspace_size());
102 if(size.x != 0.0f) size.x = 0.5f/size.x;
103 if(size.y != 0.0f) size.y = 0.5f/size.y;
104 if(size.z != 0.0f) size.z = 0.5f/size.z;
106 loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
108 float3 *fdata = attr->data_float3();
109 BL::Mesh::vertices_iterator v;
112 for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
113 fdata[i++] = get_float3(v->co())*size - loc;
116 /* create vertex color attributes */
118 BL::Mesh::tessface_vertex_colors_iterator l;
120 for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
121 if(!mesh_need_attribute(scene, mesh, ustring(l->name().c_str())))
124 Attribute *attr = mesh->attributes.add(
125 ustring(l->name().c_str()), TypeDesc::TypeColor, Attribute::CORNER);
127 BL::MeshColorLayer::data_iterator c;
128 float3 *fdata = attr->data_float3();
131 for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
132 fdata[0] = color_srgb_to_scene_linear(get_float3(c->color1()));
133 fdata[1] = color_srgb_to_scene_linear(get_float3(c->color2()));
134 fdata[2] = color_srgb_to_scene_linear(get_float3(c->color3()));
139 fdata[5] = color_srgb_to_scene_linear(get_float3(c->color4()));
148 /* create uv map attributes */
150 BL::Mesh::tessface_uv_textures_iterator l;
152 for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
153 Attribute::Standard std = (l->active_render())? Attribute::STD_UV: Attribute::STD_NONE;
154 ustring name = ustring(l->name().c_str());
156 if(!(mesh_need_attribute(scene, mesh, name) || mesh_need_attribute(scene, mesh, std)))
161 if(l->active_render())
162 attr = mesh->attributes.add(std, name);
164 attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);
166 BL::MeshTextureFaceLayer::data_iterator t;
167 float3 *fdata = attr->data_float3();
170 for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
171 fdata[0] = get_float3(t->uv1());
172 fdata[1] = get_float3(t->uv2());
173 fdata[2] = get_float3(t->uv3());
177 fdata[0] = get_float3(t->uv1());
178 fdata[1] = get_float3(t->uv3());
179 fdata[2] = get_float3(t->uv4());
187 static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
189 /* create subd mesh */
192 /* create vertices */
193 BL::Mesh::vertices_iterator v;
195 for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
196 sdmesh.add_vert(get_float3(v->co()));
199 BL::Mesh::faces_iterator f;
201 for(b_mesh.faces.begin(f); f != b_mesh.faces.end(); ++f) {
202 int4 vi = get_int4(f->vertices_raw());
203 int n= (vi[3] == 0)? 3: 4;
204 //int shader = used_shaders[f->material_index()];
207 sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]);
209 sdmesh.add_face(vi[0], vi[1], vi[2]);*/
212 /* finalize subd mesh */
213 sdmesh.link_boundary();
217 dsplit.camera = NULL;
218 dsplit.dicing_rate = RNA_float_get(cmesh, "dicing_rate");
220 sdmesh.tesselate(&dsplit, false, mesh, used_shaders[0], true);
225 Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool holdout, bool object_updated)
227 /* test if we can instance or if the object is modified */
228 BL::ID b_ob_data = b_ob.data();
229 BL::ID key = (object_is_modified(b_ob) || holdout)? b_ob: b_ob_data;
231 /* find shader indices */
232 vector<uint> used_shaders;
234 BL::Object::material_slots_iterator slot;
235 for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
236 BL::Material material_override = render_layer.material_override;
239 find_shader(PointerRNA_NULL, used_shaders, scene->default_holdout);
240 else if(material_override)
241 find_shader(material_override, used_shaders, scene->default_surface);
243 find_shader(slot->material(), used_shaders, scene->default_surface);
246 if(used_shaders.size() == 0)
247 used_shaders.push_back(scene->default_surface);
249 /* test if we need to sync */
252 if(!mesh_map.sync(&mesh, key)) {
253 /* if transform was applied to mesh, need full update */
254 if(object_updated && mesh->transform_applied);
255 /* test if shaders changed, these can be object level so mesh
256 does not get tagged for recalc */
257 else if(mesh->used_shaders != used_shaders);
259 /* even if not tagged for recalc, we may need to sync anyway
260 * because the shader needs different mesh attributes */
261 bool attribute_recalc = false;
263 foreach(uint shader, mesh->used_shaders)
264 if(scene->shaders[shader]->need_update_attributes)
265 attribute_recalc = true;
267 if(!attribute_recalc)
272 /* ensure we only sync instanced meshes once */
273 if(mesh_synced.find(mesh) != mesh_synced.end())
276 mesh_synced.insert(mesh);
278 /* create derived mesh */
279 BL::Mesh b_mesh = object_to_mesh(b_ob, b_scene, true, !preview);
280 PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");
282 vector<Mesh::Triangle> oldtriangle = mesh->triangles;
285 mesh->used_shaders = used_shaders;
286 mesh->name = ustring(b_ob_data.name().c_str());
289 if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
290 create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
292 create_mesh(scene, mesh, b_mesh, used_shaders);
294 /* free derived mesh */
295 object_remove_mesh(b_data, b_mesh);
298 /* displacement method */
300 int method = RNA_enum_get(&cmesh, "displacement_method");
302 if(method == 0 || !experimental)
303 mesh->displacement_method = Mesh::DISPLACE_BUMP;
305 mesh->displacement_method = Mesh::DISPLACE_TRUE;
307 mesh->displacement_method = Mesh::DISPLACE_BOTH;
311 bool rebuild = false;
313 if(oldtriangle.size() != mesh->triangles.size())
315 else if(oldtriangle.size()) {
316 if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
320 mesh->tag_update(scene, rebuild);