Merging r46111 through r46136 from trunk into soc-2011-tomato
[blender-staging.git] / intern / cycles / blender / blender_mesh.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
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.
8  *
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.
13  *
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.
17  */
18
19 #include "mesh.h"
20 #include "object.h"
21 #include "scene.h"
22
23 #include "blender_sync.h"
24 #include "blender_util.h"
25
26 #include "subd_mesh.h"
27 #include "subd_patch.h"
28 #include "subd_split.h"
29
30 #include "util_foreach.h"
31
32 CCL_NAMESPACE_BEGIN
33
34 /* Find/Add */
35
36 static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
37 {
38         /* create vertices */
39         BL::Mesh::vertices_iterator v;
40
41         for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
42                 mesh->verts.push_back(get_float3(v->co()));
43
44         /* create vertex normals */
45         Attribute *attr_N = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
46         float3 *N = attr_N->data_float3();
47
48         for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
49                 *N= get_float3(v->normal());
50
51         /* create faces */
52         BL::Mesh::tessfaces_iterator f;
53         vector<int> nverts;
54
55         for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
56                 int4 vi = get_int4(f->vertices_raw());
57                 int n = (vi[3] == 0)? 3: 4;
58                 int mi = clamp(f->material_index(), 0, used_shaders.size()-1);
59                 int shader = used_shaders[mi];
60                 bool smooth = f->use_smooth();
61
62                 mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
63
64                 if(n == 4)
65                         mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
66
67                 nverts.push_back(n);
68         }
69
70         /* create generated coordinates. todo: we should actually get the orco
71            coordinates from modifiers, for now we use texspace loc/size which
72            is available in the api. */
73         if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
74                 Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
75                 float3 loc = get_float3(b_mesh.texspace_location());
76                 float3 size = get_float3(b_mesh.texspace_size());
77
78                 if(size.x != 0.0f) size.x = 0.5f/size.x;
79                 if(size.y != 0.0f) size.y = 0.5f/size.y;
80                 if(size.z != 0.0f) size.z = 0.5f/size.z;
81
82                 loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
83
84                 float3 *fdata = attr->data_float3();
85                 BL::Mesh::vertices_iterator v;
86                 size_t i = 0;
87
88                 for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
89                         fdata[i++] = get_float3(v->co())*size - loc;
90         }
91
92         /* create vertex color attributes */
93         {
94                 BL::Mesh::tessface_vertex_colors_iterator l;
95
96                 for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
97                         if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
98                                 continue;
99
100                         Attribute *attr = mesh->attributes.add(
101                                 ustring(l->name().c_str()), TypeDesc::TypeColor, Attribute::CORNER);
102
103                         BL::MeshColorLayer::data_iterator c;
104                         float3 *fdata = attr->data_float3();
105                         size_t i = 0;
106
107                         for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
108                                 fdata[0] = color_srgb_to_scene_linear(get_float3(c->color1()));
109                                 fdata[1] = color_srgb_to_scene_linear(get_float3(c->color2()));
110                                 fdata[2] = color_srgb_to_scene_linear(get_float3(c->color3()));
111
112                                 if(nverts[i] == 4) {
113                                         fdata[3] = fdata[0];
114                                         fdata[4] = fdata[2];
115                                         fdata[5] = color_srgb_to_scene_linear(get_float3(c->color4()));
116                                         fdata += 6;
117                                 }
118                                 else
119                                         fdata += 3;
120                         }
121                 }
122         }
123
124         /* create uv map attributes */
125         {
126                 BL::Mesh::tessface_uv_textures_iterator l;
127
128                 for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
129                         AttributeStandard std = (l->active_render())? ATTR_STD_UV: ATTR_STD_NONE;
130                         ustring name = ustring(l->name().c_str());
131
132                         if(!(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)))
133                                 continue;
134
135                         Attribute *attr;
136
137                         if(l->active_render())
138                                 attr = mesh->attributes.add(std, name);
139                         else
140                                 attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);
141
142                         BL::MeshTextureFaceLayer::data_iterator t;
143                         float3 *fdata = attr->data_float3();
144                         size_t i = 0;
145
146                         for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
147                                 fdata[0] =  get_float3(t->uv1());
148                                 fdata[1] =  get_float3(t->uv2());
149                                 fdata[2] =  get_float3(t->uv3());
150                                 fdata += 3;
151
152                                 if(nverts[i] == 4) {
153                                         fdata[0] =  get_float3(t->uv1());
154                                         fdata[1] =  get_float3(t->uv3());
155                                         fdata[2] =  get_float3(t->uv4());
156                                         fdata += 3;
157                                 }
158                         }
159                 }
160         }
161 }
162
163 static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
164 {
165         /* create subd mesh */
166         SubdMesh sdmesh;
167
168         /* create vertices */
169         BL::Mesh::vertices_iterator v;
170
171         for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
172                 sdmesh.add_vert(get_float3(v->co()));
173
174         /* create faces */
175         BL::Mesh::tessfaces_iterator f;
176
177         for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
178                 int4 vi = get_int4(f->vertices_raw());
179                 int n= (vi[3] == 0)? 3: 4;
180                 //int shader = used_shaders[f->material_index()];
181
182                 if(n == 4)
183                         sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]);
184                 /*else
185                         sdmesh.add_face(vi[0], vi[1], vi[2]);*/
186         }
187
188         /* finalize subd mesh */
189         sdmesh.link_boundary();
190
191         /* subdivide */
192         DiagSplit dsplit;
193         dsplit.camera = NULL;
194         dsplit.dicing_rate = RNA_float_get(cmesh, "dicing_rate");
195
196         sdmesh.tessellate(&dsplit, false, mesh, used_shaders[0], true);
197 }
198
199 /* Sync */
200
201 Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool holdout, bool object_updated)
202 {
203         /* test if we can instance or if the object is modified */
204         BL::ID b_ob_data = b_ob.data();
205         BL::ID key = (object_is_modified(b_ob) || holdout)? b_ob: b_ob_data;
206         BL::Material material_override = render_layer.material_override;
207
208         /* find shader indices */
209         vector<uint> used_shaders;
210
211         BL::Object::material_slots_iterator slot;
212         for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
213                 BL::Material material_override = render_layer.material_override;
214
215                 if(holdout)
216                         find_shader(PointerRNA_NULL, used_shaders, scene->default_holdout);
217                 else if(material_override)
218                         find_shader(material_override, used_shaders, scene->default_surface);
219                 else
220                         find_shader(slot->material(), used_shaders, scene->default_surface);
221         }
222
223         if(used_shaders.size() == 0) {
224                 if(holdout)
225                         used_shaders.push_back(scene->default_holdout);
226                 else if(material_override)
227                         find_shader(material_override, used_shaders, scene->default_surface);
228                 else
229                         used_shaders.push_back(scene->default_surface);
230         }
231         
232         /* test if we need to sync */
233         Mesh *mesh;
234
235         if(!mesh_map.sync(&mesh, key)) {
236                 /* if transform was applied to mesh, need full update */
237                 if(object_updated && mesh->transform_applied);
238                 /* test if shaders changed, these can be object level so mesh
239                    does not get tagged for recalc */
240                 else if(mesh->used_shaders != used_shaders);
241                 else {
242                         /* even if not tagged for recalc, we may need to sync anyway
243                          * because the shader needs different mesh attributes */
244                         bool attribute_recalc = false;
245
246                         foreach(uint shader, mesh->used_shaders)
247                                 if(scene->shaders[shader]->need_update_attributes)
248                                         attribute_recalc = true;
249
250                         if(!attribute_recalc)
251                                 return mesh;
252                 }
253         }
254
255         /* ensure we only sync instanced meshes once */
256         if(mesh_synced.find(mesh) != mesh_synced.end())
257                 return mesh;
258         
259         mesh_synced.insert(mesh);
260
261         /* create derived mesh */
262         BL::Mesh b_mesh = object_to_mesh(b_ob, b_scene, true, !preview);
263         PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");
264
265         vector<Mesh::Triangle> oldtriangle = mesh->triangles;
266
267         mesh->clear();
268         mesh->used_shaders = used_shaders;
269         mesh->name = ustring(b_ob_data.name().c_str());
270
271         if(b_mesh) {
272                 if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
273                         create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
274                 else
275                         create_mesh(scene, mesh, b_mesh, used_shaders);
276
277                 /* free derived mesh */
278                 object_remove_mesh(b_data, b_mesh);
279         }
280
281         /* displacement method */
282         if(cmesh.data) {
283                 int method = RNA_enum_get(&cmesh, "displacement_method");
284
285                 if(method == 0 || !experimental)
286                         mesh->displacement_method = Mesh::DISPLACE_BUMP;
287                 else if(method == 1)
288                         mesh->displacement_method = Mesh::DISPLACE_TRUE;
289                 else
290                         mesh->displacement_method = Mesh::DISPLACE_BOTH;
291         }
292
293         /* tag update */
294         bool rebuild = false;
295
296         if(oldtriangle.size() != mesh->triangles.size())
297                 rebuild = true;
298         else if(oldtriangle.size()) {
299                 if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
300                         rebuild = true;
301         }
302         
303         mesh->tag_update(scene, rebuild);
304
305         return mesh;
306 }
307
308 void BlenderSync::sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion)
309 {
310         /* todo: displacement, subdivision */
311         BL::ID b_ob_data = b_ob.data();
312         size_t size = mesh->verts.size();
313
314         /* skip objects without deforming modifiers. this is not a totally reliable,
315          * would need a more extensive check to see which objects are animated */
316         if(!size || !ccl::object_is_deform_modified(b_ob, b_scene, preview))
317                 return;
318
319         /* get derived mesh */
320         BL::Mesh b_mesh = object_to_mesh(b_ob, b_scene, true, !preview);
321
322         if(b_mesh) {
323                 BL::Mesh::vertices_iterator v;
324                 AttributeStandard std = (motion == -1)? ATTR_STD_MOTION_PRE: ATTR_STD_MOTION_POST;
325                 Attribute *attr_M = mesh->attributes.add(std);
326                 float3 *M = attr_M->data_float3();
327                 size_t i = 0, size = mesh->verts.size();
328
329                 for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < size; ++v, M++, i++)
330                         *M = get_float3(v->co());
331
332                 /* if number of vertices changed, or if coordinates stayed the same, drop it */
333                 if(i != size || memcmp(M, &mesh->verts[0], sizeof(float3)*size) == 0)
334                         mesh->attributes.remove(std);
335
336                 /* free derived mesh */
337                 object_remove_mesh(b_data, b_mesh);
338         }
339 }
340
341 CCL_NAMESPACE_END
342