svn merge ^/trunk/blender -r44562:HEAD
[blender.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 bool mesh_need_attribute(Scene *scene, Mesh *mesh, Attribute::Standard std)
37 {
38         if(std == Attribute::STD_NONE)
39                 return false;
40
41         foreach(uint shader, mesh->used_shaders)
42                 if(scene->shaders[shader]->attributes.find(std))
43                         return true;
44         
45         return false;
46 }
47
48 static bool mesh_need_attribute(Scene *scene, Mesh *mesh, ustring name)
49 {
50         if(name == ustring())
51                 return false;
52
53         foreach(uint shader, mesh->used_shaders)
54                 if(scene->shaders[shader]->attributes.find(name))
55                         return true;
56         
57         return false;
58 }
59
60 static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
61 {
62         /* create vertices */
63         BL::Mesh::vertices_iterator v;
64
65         for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
66                 mesh->verts.push_back(get_float3(v->co()));
67
68         /* create vertex normals */
69         Attribute *attr_N = mesh->attributes.add(Attribute::STD_VERTEX_NORMAL);
70         float3 *N = attr_N->data_float3();
71
72         for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
73                 *N= get_float3(v->normal());
74
75         /* create faces */
76         BL::Mesh::tessfaces_iterator f;
77         vector<int> nverts;
78
79         for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.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();
85
86                 mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
87
88                 if(n == 4)
89                         mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
90
91                 nverts.push_back(n);
92         }
93
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());
101
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;
105
106                 loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
107
108                 float3 *fdata = attr->data_float3();
109                 BL::Mesh::vertices_iterator v;
110                 size_t i = 0;
111
112                 for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
113                         fdata[i++] = get_float3(v->co())*size - loc;
114         }
115
116         /* create vertex color attributes */
117         {
118                 BL::Mesh::tessface_vertex_colors_iterator l;
119
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())))
122                                 continue;
123
124                         Attribute *attr = mesh->attributes.add(
125                                 ustring(l->name().c_str()), TypeDesc::TypeColor, Attribute::CORNER);
126
127                         BL::MeshColorLayer::data_iterator c;
128                         float3 *fdata = attr->data_float3();
129                         size_t i = 0;
130
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()));
135
136                                 if(nverts[i] == 4) {
137                                         fdata[3] = fdata[0];
138                                         fdata[4] = fdata[2];
139                                         fdata[5] = color_srgb_to_scene_linear(get_float3(c->color4()));
140                                         fdata += 6;
141                                 }
142                                 else
143                                         fdata += 3;
144                         }
145                 }
146         }
147
148         /* create uv map attributes */
149         {
150                 BL::Mesh::tessface_uv_textures_iterator l;
151
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());
155
156                         if(!(mesh_need_attribute(scene, mesh, name) || mesh_need_attribute(scene, mesh, std)))
157                                 continue;
158
159                         Attribute *attr;
160
161                         if(l->active_render())
162                                 attr = mesh->attributes.add(std, name);
163                         else
164                                 attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);
165
166                         BL::MeshTextureFaceLayer::data_iterator t;
167                         float3 *fdata = attr->data_float3();
168                         size_t i = 0;
169
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());
174                                 fdata += 3;
175
176                                 if(nverts[i] == 4) {
177                                         fdata[0] =  get_float3(t->uv1());
178                                         fdata[1] =  get_float3(t->uv3());
179                                         fdata[2] =  get_float3(t->uv4());
180                                         fdata += 3;
181                                 }
182                         }
183                 }
184         }
185 }
186
187 static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
188 {
189         /* create subd mesh */
190         SubdMesh sdmesh;
191
192         /* create vertices */
193         BL::Mesh::vertices_iterator v;
194
195         for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
196                 sdmesh.add_vert(get_float3(v->co()));
197
198         /* create faces */
199         BL::Mesh::tessfaces_iterator f;
200
201         for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.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()];
205
206                 if(n == 4)
207                         sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]);
208                 /*else
209                         sdmesh.add_face(vi[0], vi[1], vi[2]);*/
210         }
211
212         /* finalize subd mesh */
213         sdmesh.link_boundary();
214
215         /* subdivide */
216         DiagSplit dsplit;
217         dsplit.camera = NULL;
218         dsplit.dicing_rate = RNA_float_get(cmesh, "dicing_rate");
219
220         sdmesh.tessellate(&dsplit, false, mesh, used_shaders[0], true);
221 }
222
223 /* Sync */
224
225 Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool holdout, bool object_updated)
226 {
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;
230         BL::Material material_override = render_layer.material_override;
231
232         /* find shader indices */
233         vector<uint> used_shaders;
234
235         BL::Object::material_slots_iterator slot;
236         for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
237                 BL::Material material_override = render_layer.material_override;
238
239                 if(holdout)
240                         find_shader(PointerRNA_NULL, used_shaders, scene->default_holdout);
241                 else if(material_override)
242                         find_shader(material_override, used_shaders, scene->default_surface);
243                 else
244                         find_shader(slot->material(), used_shaders, scene->default_surface);
245         }
246
247         if(used_shaders.size() == 0) {
248                 if(holdout)
249                         used_shaders.push_back(scene->default_holdout);
250                 else if(material_override)
251                         find_shader(material_override, used_shaders, scene->default_surface);
252                 else
253                         used_shaders.push_back(scene->default_surface);
254         }
255         
256         /* test if we need to sync */
257         Mesh *mesh;
258
259         if(!mesh_map.sync(&mesh, key)) {
260                 /* if transform was applied to mesh, need full update */
261                 if(object_updated && mesh->transform_applied);
262                 /* test if shaders changed, these can be object level so mesh
263                    does not get tagged for recalc */
264                 else if(mesh->used_shaders != used_shaders);
265                 else {
266                         /* even if not tagged for recalc, we may need to sync anyway
267                          * because the shader needs different mesh attributes */
268                         bool attribute_recalc = false;
269
270                         foreach(uint shader, mesh->used_shaders)
271                                 if(scene->shaders[shader]->need_update_attributes)
272                                         attribute_recalc = true;
273
274                         if(!attribute_recalc)
275                                 return mesh;
276                 }
277         }
278
279         /* ensure we only sync instanced meshes once */
280         if(mesh_synced.find(mesh) != mesh_synced.end())
281                 return mesh;
282         
283         mesh_synced.insert(mesh);
284
285         /* create derived mesh */
286         BL::Mesh b_mesh = object_to_mesh(b_ob, b_scene, true, !preview);
287         PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");
288
289         vector<Mesh::Triangle> oldtriangle = mesh->triangles;
290
291         mesh->clear();
292         mesh->used_shaders = used_shaders;
293         mesh->name = ustring(b_ob_data.name().c_str());
294
295         if(b_mesh) {
296                 if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
297                         create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
298                 else
299                         create_mesh(scene, mesh, b_mesh, used_shaders);
300
301                 /* free derived mesh */
302                 object_remove_mesh(b_data, b_mesh);
303         }
304
305         /* displacement method */
306         if(cmesh.data) {
307                 int method = RNA_enum_get(&cmesh, "displacement_method");
308
309                 if(method == 0 || !experimental)
310                         mesh->displacement_method = Mesh::DISPLACE_BUMP;
311                 else if(method == 1)
312                         mesh->displacement_method = Mesh::DISPLACE_TRUE;
313                 else
314                         mesh->displacement_method = Mesh::DISPLACE_BOTH;
315         }
316
317         /* tag update */
318         bool rebuild = false;
319
320         if(oldtriangle.size() != mesh->triangles.size())
321                 rebuild = true;
322         else if(oldtriangle.size()) {
323                 if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
324                         rebuild = true;
325         }
326         
327         mesh->tag_update(scene, rebuild);
328
329         return mesh;
330 }
331
332 CCL_NAMESPACE_END
333