Fix various compiler warnings.
[blender.git] / source / blender / freestyle / intern / blender_interface / BlenderStrokeRenderer.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
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  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
22  *  \ingroup freestyle
23  */
24
25 #include "BlenderStrokeRenderer.h"
26
27 #include "../application/AppConfig.h"
28 #include "../stroke/Canvas.h"
29
30 extern "C" {
31 #include "MEM_guardedalloc.h"
32
33 #include "RNA_access.h"
34 #include "RNA_types.h"
35
36 #include "DNA_camera_types.h"
37 #include "DNA_listBase.h"
38 #include "DNA_linestyle_types.h"
39 #include "DNA_material_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_mesh_types.h"
42 #include "DNA_object_types.h"
43 #include "DNA_screen_types.h"
44 #include "DNA_scene_types.h"
45
46 #include "BKE_customdata.h"
47 #include "BKE_depsgraph.h"
48 #include "BKE_global.h"
49 #include "BKE_library.h" /* free_libblock */
50 #include "BKE_material.h"
51 #include "BKE_mesh.h"
52 #include "BKE_node.h"
53 #include "BKE_object.h"
54 #include "BKE_scene.h"
55
56 #include "BLI_ghash.h"
57 #include "BLI_listbase.h"
58 #include "BLI_utildefines.h"
59
60 #include "RE_pipeline.h"
61
62 #include "render_types.h"
63 }
64
65 #include <limits.h>
66
67 namespace Freestyle {
68
69 const char *BlenderStrokeRenderer::uvNames[] = {"along_stroke", "along_stroke_tips"};
70
71 BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : StrokeRenderer()
72 {
73         freestyle_bmain = re->freestyle_bmain;
74
75         // for stroke mesh generation
76         _width = re->winx;
77         _height = re->winy;
78
79         old_scene = re->scene;
80
81         char name[MAX_ID_NAME - 2];
82         BLI_snprintf(name, sizeof(name), "FRS%d_%s", render_count, re->scene->id.name + 2);
83         freestyle_scene = BKE_scene_add(freestyle_bmain, name);
84         freestyle_scene->r.cfra = old_scene->r.cfra;
85         freestyle_scene->r.mode = old_scene->r.mode &
86                                   ~(R_EDGE_FRS | R_SHADOW | R_SSS | R_PANORAMA | R_ENVMAP | R_MBLUR | R_BORDER);
87         freestyle_scene->r.xsch = re->rectx; // old_scene->r.xsch
88         freestyle_scene->r.ysch = re->recty; // old_scene->r.ysch
89         freestyle_scene->r.xasp = 1.0f; // old_scene->r.xasp;
90         freestyle_scene->r.yasp = 1.0f; // old_scene->r.yasp;
91         freestyle_scene->r.tilex = old_scene->r.tilex;
92         freestyle_scene->r.tiley = old_scene->r.tiley;
93         freestyle_scene->r.size = 100; // old_scene->r.size
94         //freestyle_scene->r.maximsize = old_scene->r.maximsize; /* DEPRECATED */
95         freestyle_scene->r.ocres = old_scene->r.ocres;
96         freestyle_scene->r.color_mgt_flag = 0; // old_scene->r.color_mgt_flag;
97         freestyle_scene->r.scemode = old_scene->r.scemode & ~(R_SINGLE_LAYER | R_NO_FRAME_UPDATE | R_MULTIVIEW);
98         freestyle_scene->r.flag = old_scene->r.flag;
99         freestyle_scene->r.threads = old_scene->r.threads;
100         freestyle_scene->r.border.xmin = old_scene->r.border.xmin;
101         freestyle_scene->r.border.ymin = old_scene->r.border.ymin;
102         freestyle_scene->r.border.xmax = old_scene->r.border.xmax;
103         freestyle_scene->r.border.ymax = old_scene->r.border.ymax;
104         strcpy(freestyle_scene->r.pic, old_scene->r.pic);
105         freestyle_scene->r.safety.xmin = old_scene->r.safety.xmin;
106         freestyle_scene->r.safety.ymin = old_scene->r.safety.ymin;
107         freestyle_scene->r.safety.xmax = old_scene->r.safety.xmax;
108         freestyle_scene->r.safety.ymax = old_scene->r.safety.ymax;
109         freestyle_scene->r.osa = old_scene->r.osa;
110         freestyle_scene->r.filtertype = old_scene->r.filtertype;
111         freestyle_scene->r.gauss = old_scene->r.gauss;
112         freestyle_scene->r.dither_intensity = old_scene->r.dither_intensity;
113         BLI_strncpy(freestyle_scene->r.engine, old_scene->r.engine, sizeof(freestyle_scene->r.engine));
114         freestyle_scene->r.im_format.planes = R_IMF_PLANES_RGBA; 
115         freestyle_scene->r.im_format.imtype = R_IMF_IMTYPE_PNG;
116         BKE_scene_disable_color_management(freestyle_scene);
117
118         if (G.debug & G_DEBUG_FREESTYLE) {
119                 printf("%s: %d thread(s)\n", __func__, BKE_render_num_threads(&freestyle_scene->r));
120         }
121
122         // Render layer
123         SceneRenderLayer *srl = (SceneRenderLayer *)freestyle_scene->r.layers.first;
124         srl->layflag = SCE_LAY_SOLID | SCE_LAY_ZTRA;
125
126         BKE_scene_set_background(freestyle_bmain, freestyle_scene);
127
128         // Camera
129         Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA, NULL);
130         DAG_relations_tag_update(freestyle_bmain);
131
132         Camera *camera = (Camera *)object_camera->data;
133         camera->type = CAM_ORTHO;
134         camera->ortho_scale = max(re->rectx, re->recty);
135         camera->clipsta = 0.1f;
136         camera->clipend = 100.0f;
137
138         _z_delta = 0.00001f;
139         _z = camera->clipsta + _z_delta;
140
141         object_camera->loc[0] = re->disprect.xmin + 0.5f * re->rectx;
142         object_camera->loc[1] = re->disprect.ymin + 0.5f * re->recty;
143         object_camera->loc[2] = 1.0f;
144
145         freestyle_scene->camera = object_camera;
146
147         // Reset serial mesh ID (used for BlenderStrokeRenderer::NewMesh())
148         _mesh_id = 0xffffffff;
149
150         // Check if the rendering engine uses new shading nodes
151         _use_shading_nodes = BKE_scene_use_new_shading_nodes(freestyle_scene);
152
153         // Create a bNodeTree-to-Material hash table
154         if (_use_shading_nodes)
155                 _nodetree_hash = BLI_ghash_ptr_new("BlenderStrokeRenderer::_nodetree_hash");
156         else
157                 _nodetree_hash = NULL;
158 }
159
160 BlenderStrokeRenderer::~BlenderStrokeRenderer()
161 {
162         // The freestyle_scene object is not released here.  Instead,
163         // the scene is released in free_all_freestyle_renders() in
164         // source/blender/render/intern/source/pipeline.c, after the
165         // compositor has finished.
166
167         // release objects and data blocks
168         for (Base *b = (Base *)freestyle_scene->base.first; b; b = b->next) {
169                 Object *ob = b->object;
170                 void *data = ob->data;
171                 char *name = ob->id.name;
172 #if 0
173                 if (G.debug & G_DEBUG_FREESTYLE) {
174                         cout << "removing " << name[0] << name[1] << ":" << (name+2) << endl;
175                 }
176 #endif
177                 switch (ob->type) {
178                 case OB_MESH:
179                         BKE_libblock_free(freestyle_bmain, ob);
180                         BKE_libblock_free(freestyle_bmain, data);
181                         break;
182                 case OB_CAMERA:
183                         BKE_libblock_free(freestyle_bmain, ob);
184                         BKE_libblock_free(freestyle_bmain, data);
185                         freestyle_scene->camera = NULL;
186                         break;
187                 default:
188                         cerr << "Warning: unexpected object in the scene: " << name[0] << name[1] << ":" << (name + 2) << endl;
189                 }
190         }
191         BLI_freelistN(&freestyle_scene->base);
192
193         // release materials
194         Link *lnk = (Link *)freestyle_bmain->mat.first;
195
196         while (lnk)
197         {
198                 Material *ma = (Material*)lnk;
199                 // We want to retain the linestyle mtexs, so let's detach them first
200                 for (int a = 0; a < MAX_MTEX; a++) {
201                         if (ma->mtex[a]) {
202                                 ma->mtex[a] = NULL;
203                         }
204                         else {
205                                 break; // Textures are ordered, no empty slots between two textures
206                         }
207                 }
208                 lnk = lnk->next;
209                 BKE_libblock_free(freestyle_bmain, ma);
210         }
211
212         if (_use_shading_nodes)
213                 BLI_ghash_free(_nodetree_hash, NULL, NULL);
214
215         FreeStrokeGroups();
216 }
217
218 float BlenderStrokeRenderer::get_stroke_vertex_z(void) const
219 {
220         float z = _z;
221         BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this);
222         if (!(_z < _z_delta * 100000.0f))
223                 self->_z_delta *= 10.0f;
224         self->_z += _z_delta;
225         return -z;
226 }
227
228 unsigned int BlenderStrokeRenderer::get_stroke_mesh_id(void) const
229 {
230         unsigned mesh_id = _mesh_id;
231         BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this);
232         self->_mesh_id--;
233         return mesh_id;
234 }
235
236 Material* BlenderStrokeRenderer::GetStrokeShader(Main *bmain, bNodeTree *iNodeTree, bool do_id_user)
237 {
238         Material *ma = BKE_material_add(bmain, "stroke_shader");
239         bNodeTree *ntree;
240         bNode *output_linestyle = NULL;
241         bNodeSocket *fromsock, *tosock;
242         PointerRNA fromptr, toptr;
243         NodeShaderAttribute *storage;
244
245         if (iNodeTree) {
246                 // make a copy of linestyle->nodetree
247                 ntree = ntreeCopyTree_ex(iNodeTree, bmain, do_id_user);
248
249                 // find the active Output Line Style node
250                 for (bNode *node = (bNode *)ntree->nodes.first; node; node = node->next) {
251                         if (node->type == SH_NODE_OUTPUT_LINESTYLE && (node->flag & NODE_DO_OUTPUT)) {
252                                 output_linestyle = node;
253                                 break;
254                         }
255                 }
256         }
257         else {
258                 ntree = ntreeAddTree(NULL, "stroke_shader", "ShaderNodeTree");
259         }
260         ma->nodetree = ntree;
261         ma->use_nodes = 1;
262
263         bNode *input_attr_color = nodeAddStaticNode(NULL, ntree, SH_NODE_ATTRIBUTE);
264         input_attr_color->locx = 0.0f;
265         input_attr_color->locy = -200.0f;
266         storage = (NodeShaderAttribute *)input_attr_color->storage;
267         BLI_strncpy(storage->name, "Color", sizeof(storage->name));
268
269         bNode *mix_rgb_color = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_RGB);
270         mix_rgb_color->custom1 = MA_RAMP_BLEND; // Mix
271         mix_rgb_color->locx = 200.0f;
272         mix_rgb_color->locy = -200.0f;
273         tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 0); // Fac
274         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr);
275         RNA_float_set(&toptr, "default_value", 0.0f);
276
277         bNode *input_attr_alpha = nodeAddStaticNode(NULL, ntree, SH_NODE_ATTRIBUTE);
278         input_attr_alpha->locx = 400.0f;
279         input_attr_alpha->locy = 300.0f;
280         storage = (NodeShaderAttribute *)input_attr_alpha->storage;
281         BLI_strncpy(storage->name, "Alpha", sizeof(storage->name));
282
283         bNode *mix_rgb_alpha = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_RGB);
284         mix_rgb_alpha->custom1 = MA_RAMP_BLEND; // Mix
285         mix_rgb_alpha->locx = 600.0f;
286         mix_rgb_alpha->locy = 300.0f;
287         tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 0); // Fac
288         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr);
289         RNA_float_set(&toptr, "default_value", 0.0f);
290
291         bNode *shader_emission = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION);
292         shader_emission->locx = 400.0f;
293         shader_emission->locy = -200.0f;
294
295         bNode *input_light_path = nodeAddStaticNode(NULL, ntree, SH_NODE_LIGHT_PATH);
296         input_light_path->locx = 400.0f;
297         input_light_path->locy = 100.0f;
298
299         bNode *mix_shader_color = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_SHADER);
300         mix_shader_color->locx = 600.0f;
301         mix_shader_color->locy = -100.0f;
302
303         bNode *shader_transparent = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_TRANSPARENT);
304         shader_transparent->locx = 600.0f;
305         shader_transparent->locy = 100.0f;
306
307         bNode *mix_shader_alpha = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_SHADER);
308         mix_shader_alpha->locx = 800.0f;
309         mix_shader_alpha->locy = 100.0f;
310
311         bNode *output_material = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
312         output_material->locx = 1000.0f;
313         output_material->locy = 100.0f;
314
315         fromsock = (bNodeSocket *)BLI_findlink(&input_attr_color->outputs, 0); // Color
316         tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 1); // Color1
317         nodeAddLink(ntree, input_attr_color, fromsock, mix_rgb_color, tosock);
318
319         fromsock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->outputs, 0); // Color
320         tosock = (bNodeSocket *)BLI_findlink(&shader_emission->inputs, 0); // Color
321         nodeAddLink(ntree, mix_rgb_color, fromsock, shader_emission, tosock);
322
323         fromsock = (bNodeSocket *)BLI_findlink(&shader_emission->outputs, 0); // Emission
324         tosock = (bNodeSocket *)BLI_findlink(&mix_shader_color->inputs, 2); // Shader (second)
325         nodeAddLink(ntree, shader_emission, fromsock, mix_shader_color, tosock);
326
327         fromsock = (bNodeSocket *)BLI_findlink(&input_light_path->outputs, 0); // In Camera Ray
328         tosock = (bNodeSocket *)BLI_findlink(&mix_shader_color->inputs, 0); // Fac
329         nodeAddLink(ntree, input_light_path, fromsock, mix_shader_color, tosock);
330
331         fromsock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->outputs, 0); // Color
332         tosock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->inputs, 0); // Fac
333         nodeAddLink(ntree, mix_rgb_alpha, fromsock, mix_shader_alpha, tosock);
334
335         fromsock = (bNodeSocket *)BLI_findlink(&input_attr_alpha->outputs, 0); // Color
336         tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 1); // Color1
337         nodeAddLink(ntree, input_attr_alpha, fromsock, mix_rgb_alpha, tosock);
338
339         fromsock = (bNodeSocket *)BLI_findlink(&shader_transparent->outputs, 0); // BSDF
340         tosock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->inputs, 1); // Shader (first)
341         nodeAddLink(ntree, shader_transparent, fromsock, mix_shader_alpha, tosock);
342
343         fromsock = (bNodeSocket *)BLI_findlink(&mix_shader_color->outputs, 0); // Shader
344         tosock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->inputs, 2); // Shader (second)
345         nodeAddLink(ntree, mix_shader_color, fromsock, mix_shader_alpha, tosock);
346
347         fromsock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->outputs, 0); // Shader
348         tosock = (bNodeSocket *)BLI_findlink(&output_material->inputs, 0); // Surface
349         nodeAddLink(ntree, mix_shader_alpha, fromsock, output_material, tosock);
350
351         if (output_linestyle) {
352                 bNodeSocket *outsock;
353                 bNodeLink *link;
354
355                 mix_rgb_color->custom1 = output_linestyle->custom1; // blend_type
356                 mix_rgb_color->custom2 = output_linestyle->custom2; // use_clamp
357
358                 outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 0); // Color
359                 tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 2); // Color2
360                 link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock));
361                 if (link) {
362                         nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_color, tosock);
363                 }
364                 else {
365                         float color[4];
366                         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr);
367                         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr);
368                         RNA_float_get_array(&fromptr, "default_value", color);
369                         RNA_float_set_array(&toptr, "default_value", color);
370                 }
371
372                 outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 1); // Color Fac
373                 tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 0); // Fac
374                 link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock));
375                 if (link) {
376                         nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_color, tosock);
377                 }
378                 else {
379                         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr);
380                         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr);
381                         RNA_float_set(&toptr, "default_value", RNA_float_get(&fromptr, "default_value"));
382                 }
383
384                 outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 2); // Alpha
385                 tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 2); // Color2
386                 link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock));
387                 if (link) {
388                         nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_alpha, tosock);
389                 }
390                 else {
391                         float color[4];
392                         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr);
393                         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr);
394                         color[0] = color[1] = color[2] = RNA_float_get(&fromptr, "default_value");
395                         color[3] = 1.0f;
396                         RNA_float_set_array(&toptr, "default_value", color);
397                 }
398
399                 outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 3); // Alpha Fac
400                 tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 0); // Fac
401                 link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock));
402                 if (link) {
403                         nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_alpha, tosock);
404                 }
405                 else {
406                         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr);
407                         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr);
408                         RNA_float_set(&toptr, "default_value", RNA_float_get(&fromptr, "default_value"));
409                 }
410
411                 for (bNode *node = (bNode *)ntree->nodes.first; node; node = node->next) {
412                         if (node->type == SH_NODE_UVALONGSTROKE) {
413                                 // UV output of the UV Along Stroke node
414                                 bNodeSocket *sock = (bNodeSocket *)BLI_findlink(&node->outputs, 0);
415
416                                 // add new UV Map node
417                                 bNode *input_uvmap = nodeAddStaticNode(NULL, ntree, SH_NODE_UVMAP);
418                                 input_uvmap->locx = node->locx - 200.0f;
419                                 input_uvmap->locy = node->locy;
420                                 NodeShaderUVMap *storage = (NodeShaderUVMap *)input_uvmap->storage;
421                                 if (node->custom1 & 1) { // use_tips
422                                         BLI_strncpy(storage->uv_map, uvNames[1], sizeof(storage->uv_map));
423                                 }
424                                 else {
425                                         BLI_strncpy(storage->uv_map, uvNames[0], sizeof(storage->uv_map));
426                                 }
427                                 fromsock = (bNodeSocket *)BLI_findlink(&input_uvmap->outputs, 0); // UV
428
429                                 // replace links from the UV Along Stroke node by links from the UV Map node
430                                 for (bNodeLink *link = (bNodeLink *)ntree->links.first; link; link = link->next) {
431                                         if (link->fromnode == node && link->fromsock == sock) {
432                                                 nodeAddLink(ntree, input_uvmap, fromsock, link->tonode, link->tosock);
433                                         }
434                                 }
435                                 nodeRemSocketLinks(ntree, sock);
436                         }
437                 }
438         }
439
440         nodeSetActive(ntree, output_material);
441         ntreeUpdateTree(bmain, ntree);
442
443         return ma;
444 }
445
446 void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
447 {
448         RenderStrokeRepBasic(iStrokeRep);
449 }
450
451 void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
452 {
453         if (_use_shading_nodes) {
454                 bNodeTree *nt = iStrokeRep->getNodeTree();
455                 Material *ma = (Material *)BLI_ghash_lookup(_nodetree_hash, nt);
456                 if (!ma) {
457                         ma = BlenderStrokeRenderer::GetStrokeShader(freestyle_bmain, nt, false);
458                         BLI_ghash_insert(_nodetree_hash, nt, ma);
459                 }
460
461                 if (STREQ(freestyle_scene->r.engine, RE_engine_id_CYCLES)) {
462                         PointerRNA scene_ptr, freestyle_scene_ptr;
463                         RNA_pointer_create(NULL, &RNA_Scene, old_scene, &scene_ptr);
464                         RNA_pointer_create(NULL, &RNA_Scene, freestyle_scene, &freestyle_scene_ptr);
465
466                         PointerRNA cycles_ptr = RNA_pointer_get(&scene_ptr, "cycles");
467                         PointerRNA freestyle_cycles_ptr = RNA_pointer_get(&freestyle_scene_ptr, "cycles");
468
469                         int flag;
470                         RNA_STRUCT_BEGIN(&freestyle_cycles_ptr, prop)
471                         {
472                                 flag = RNA_property_flag(prop);
473                                 if (flag & PROP_HIDDEN)
474                                         continue;
475                                 RNA_property_copy(&freestyle_cycles_ptr, &cycles_ptr, prop, -1);
476                         }
477                         RNA_STRUCT_END;
478
479                         RNA_boolean_set(&freestyle_cycles_ptr, "film_transparent", 1);
480                 }
481
482                 iStrokeRep->setMaterial(ma);
483         }
484         else {
485                 bool has_mat = false;
486                 int a = 0;
487
488                 // Look for a good existing material
489                 for (Link *lnk = (Link *)freestyle_bmain->mat.first; lnk; lnk = lnk->next) {
490                         Material *ma = (Material*)lnk;
491                         bool texs_are_good = true;
492                         // as soon as textures differ it's not the right one
493                         for (int a = 0; a < MAX_MTEX; a++) {
494                                 if (ma->mtex[a] != iStrokeRep->getMTex(a)) {
495                                         texs_are_good = false;
496                                         break;
497                                 }
498                         }
499
500                         if (texs_are_good) {
501                                 iStrokeRep->setMaterial(ma);
502                                 has_mat = true;
503                                 break; // if textures are good, no need to search anymore
504                         }
505                 }
506
507                 // If still no material, create one
508                 if (!has_mat) {
509                         Material *ma = BKE_material_add(freestyle_bmain, "stroke_material");
510                         DAG_relations_tag_update(freestyle_bmain);
511                         ma->mode |= MA_VERTEXCOLP;
512                         ma->mode |= MA_TRANSP;
513                         ma->mode |= MA_SHLESS;
514                         ma->vcol_alpha = 1;
515
516                         // Textures
517                         while (iStrokeRep->getMTex(a)) {
518                                 ma->mtex[a] = (MTex *)iStrokeRep->getMTex(a);
519
520                                 // We'll generate both with tips and without tips
521                                 // coordinates, on two different UV layers.
522                                 if (ma->mtex[a]->texflag & MTEX_TIPS)  {
523                                         BLI_strncpy(ma->mtex[a]->uvname, uvNames[1], sizeof(ma->mtex[a]->uvname));
524                                 }
525                                 else {
526                                         BLI_strncpy(ma->mtex[a]->uvname, uvNames[0], sizeof(ma->mtex[a]->uvname));
527                                 }
528                                 a++;
529                         }
530
531                         iStrokeRep->setMaterial(ma);
532                 }
533         }
534
535         const vector<Strip*>& strips = iStrokeRep->getStrips();
536         const bool hasTex = iStrokeRep->hasTex();
537         int totvert = 0, totedge = 0, totpoly = 0, totloop = 0;
538         int visible_faces, visible_segments;
539         for (vector<Strip*>::const_iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
540                 Strip::vertex_container& strip_vertices = (*s)->vertices();
541
542                 // count visible faces and strip segments
543                 test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
544                 if (visible_faces == 0)
545                         continue;
546
547                 totvert += visible_faces + visible_segments * 2;
548                 totedge += visible_faces * 2 + visible_segments;
549                 totpoly += visible_faces;
550                 totloop += visible_faces * 3;
551         }
552
553         BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this); // FIXME
554         vector<StrokeGroup*> *groups = hasTex ? &self->texturedStrokeGroups : &self->strokeGroups;
555         StrokeGroup *group;
556         if (groups->empty() || !(groups->back()->totvert + totvert < MESH_MAX_VERTS &&
557             groups->back()->totcol + 1 < MAXMAT))
558         {
559                 group = new StrokeGroup;
560                 groups->push_back(group);
561         }
562         else {
563                 group = groups->back();
564         }
565         group->strokes.push_back(iStrokeRep);
566         group->totvert += totvert;
567         group->totedge += totedge;
568         group->totpoly += totpoly;
569         group->totloop += totloop;
570         group->totcol++;
571 }
572
573 // Check if the triangle is visible (i.e., within the render image boundary)
574 bool BlenderStrokeRenderer::test_triangle_visibility(StrokeVertexRep *svRep[3]) const
575 {
576         int xl, xu, yl, yu;
577         Vec2r p;
578
579         xl = xu = yl = yu = 0;
580         for (int i = 0; i < 3; i++) {
581                 p = svRep[i]->point2d();
582                 if (p[0] < 0.0)
583                         xl++;
584                 else if (p[0] > _width)
585                         xu++;
586                 if (p[1] < 0.0)
587                         yl++;
588                 else if (p[1] > _height)
589                         yu++;
590         }
591         return !(xl == 3 || xu == 3 || yl == 3 || yu == 3);
592 }
593
594 // Check the visibility of faces and strip segments.
595 void BlenderStrokeRenderer::test_strip_visibility(Strip::vertex_container& strip_vertices,
596         int *visible_faces, int *visible_segments) const
597 {
598         const int strip_vertex_count = strip_vertices.size();
599         Strip::vertex_container::iterator v[3];
600         StrokeVertexRep *svRep[3];
601         bool visible;
602
603         // iterate over all vertices and count visible faces and strip segments
604         // (note: a strip segment is a series of visible faces, while two strip
605         // segments are separated by one or more invisible faces)
606         v[0] = strip_vertices.begin();
607         v[1] = v[0] + 1;
608         v[2] = v[0] + 2;
609         *visible_faces = *visible_segments = 0;
610         visible = false;
611         for (int n = 2; n < strip_vertex_count; n++, v[0]++, v[1]++, v[2]++) {
612                 svRep[0] = *(v[0]);
613                 svRep[1] = *(v[1]);
614                 svRep[2] = *(v[2]);
615                 if (test_triangle_visibility(svRep)) {
616                         (*visible_faces)++;
617                         if (!visible)
618                                 (*visible_segments)++;
619                         visible = true;
620                 }
621                 else {
622                         visible = false;
623                 }
624         }
625 }
626
627 // Release allocated memory for stroke groups
628 void BlenderStrokeRenderer::FreeStrokeGroups()
629 {
630         vector<StrokeGroup*>::const_iterator it, itend;
631
632         for (it = strokeGroups.begin(), itend = strokeGroups.end();
633              it != itend; ++it)
634         {
635                 delete (*it);
636         }
637         for (it = texturedStrokeGroups.begin(), itend = texturedStrokeGroups.end();
638              it != itend; ++it)
639         {
640                 delete (*it);
641         }
642 }
643
644 // Build a scene populated by mesh objects representing stylized strokes
645 int BlenderStrokeRenderer::GenerateScene()
646 {
647         vector<StrokeGroup*>::const_iterator it, itend;
648
649         for (it = strokeGroups.begin(), itend = strokeGroups.end();
650              it != itend; ++it)
651         {
652                 GenerateStrokeMesh(*it, false);
653         }
654         for (it = texturedStrokeGroups.begin(), itend = texturedStrokeGroups.end();
655              it != itend; ++it)
656         {
657                 GenerateStrokeMesh(*it, true);
658         }
659         return get_stroke_count();
660 }
661
662 // Return the number of strokes
663 int BlenderStrokeRenderer::get_stroke_count() const
664 {
665         return strokeGroups.size() + texturedStrokeGroups.size();
666 }
667
668 // Build a mesh object representing a group of stylized strokes
669 void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
670 {
671 #if 0
672         Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, OB_MESH);
673         DAG_relations_tag_update(freestyle_bmain);
674 #else
675         Object *object_mesh = NewMesh();
676 #endif
677         Mesh *mesh = (Mesh *)object_mesh->data;
678
679         mesh->totvert = group->totvert;
680         mesh->totedge = group->totedge;
681         mesh->totpoly = group->totpoly;
682         mesh->totloop = group->totloop;
683         mesh->totcol = group->totcol;
684
685         mesh->mvert = (MVert *)CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
686         mesh->medge = (MEdge *)CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
687         mesh->mpoly = (MPoly *)CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
688         mesh->mloop = (MLoop *)CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
689
690         MVert *vertices = mesh->mvert;
691         MEdge *edges = mesh->medge;
692         MPoly *polys = mesh->mpoly;
693         MLoop *loops = mesh->mloop;
694         MLoopUV *loopsuv[2] = { NULL };
695
696         if (hasTex) {
697                 // First UV layer
698                 CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, uvNames[0]);
699                 CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[0]);
700                 CustomData_set_layer_active(&mesh->pdata, CD_MTEXPOLY, 0);
701                 CustomData_set_layer_active(&mesh->ldata, CD_MLOOPUV, 0);
702                 BKE_mesh_update_customdata_pointers(mesh, true);
703                 loopsuv[0] = mesh->mloopuv;
704
705                 // Second UV layer
706                 CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, uvNames[1]);
707                 CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[1]);
708                 CustomData_set_layer_active(&mesh->pdata, CD_MTEXPOLY, 1);
709                 CustomData_set_layer_active(&mesh->ldata, CD_MLOOPUV, 1);
710                 BKE_mesh_update_customdata_pointers(mesh, true);
711                 loopsuv[1] = mesh->mloopuv;
712         }
713
714         // colors and transparency (the latter represented by grayscale colors)
715         MLoopCol *colors = (MLoopCol *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, mesh->totloop, "Color");
716         MLoopCol *transp = (MLoopCol *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, mesh->totloop, "Alpha");
717         mesh->mloopcol = colors;
718
719         mesh->mat = (Material **)MEM_mallocN(sizeof(Material *) * mesh->totcol, "MaterialList");
720
721         ////////////////////
722         //  Data copy
723         ////////////////////
724
725         int vertex_index = 0, edge_index = 0, loop_index = 0, material_index = 0;
726         int visible_faces, visible_segments;
727         bool visible;
728         Strip::vertex_container::iterator v[3];
729         StrokeVertexRep *svRep[3];
730         Vec2r p;
731
732         for (vector<StrokeRep*>::const_iterator it = group->strokes.begin(), itend = group->strokes.end();
733              it != itend; ++it)
734         {
735                 mesh->mat[material_index] = (*it)->getMaterial();
736
737                 vector<Strip*>& strips = (*it)->getStrips();
738                 for (vector<Strip*>::const_iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
739                         Strip::vertex_container& strip_vertices = (*s)->vertices();
740                         int strip_vertex_count = strip_vertices.size();
741
742                         // count visible faces and strip segments
743                         test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
744                         if (visible_faces == 0)
745                                 continue;
746
747                         v[0] = strip_vertices.begin();
748                         v[1] = v[0] + 1;
749                         v[2] = v[0] + 2;
750
751                         visible = false;
752
753                         // Note: Mesh generation in the following loop assumes stroke strips
754                         // to be triangle strips.
755                         for (int n = 2; n < strip_vertex_count; n++, v[0]++, v[1]++, v[2]++) {
756                                 svRep[0] = *(v[0]);
757                                 svRep[1] = *(v[1]);
758                                 svRep[2] = *(v[2]);
759                                 if (!test_triangle_visibility(svRep)) {
760                                         visible = false;
761                                 }
762                                 else {
763                                         if (!visible) {
764                                                 // first vertex
765                                                 vertices->co[0] = svRep[0]->point2d()[0];
766                                                 vertices->co[1] = svRep[0]->point2d()[1];
767                                                 vertices->co[2] = get_stroke_vertex_z();
768                                                 vertices->no[0] = 0;
769                                                 vertices->no[1] = 0;
770                                                 vertices->no[2] = SHRT_MAX;
771                                                 ++vertices;
772                                                 ++vertex_index;
773
774                                                 // second vertex
775                                                 vertices->co[0] = svRep[1]->point2d()[0];
776                                                 vertices->co[1] = svRep[1]->point2d()[1];
777                                                 vertices->co[2] = get_stroke_vertex_z();
778                                                 vertices->no[0] = 0;
779                                                 vertices->no[1] = 0;
780                                                 vertices->no[2] = SHRT_MAX;
781                                                 ++vertices;
782                                                 ++vertex_index;
783
784                                                 // first edge
785                                                 edges->v1 = vertex_index - 2;
786                                                 edges->v2 = vertex_index - 1;
787                                                 ++edges;
788                                                 ++edge_index;
789                                         }
790                                         visible = true;
791
792                                         // vertex
793                                         vertices->co[0] = svRep[2]->point2d()[0];
794                                         vertices->co[1] = svRep[2]->point2d()[1];
795                                         vertices->co[2] = get_stroke_vertex_z();
796                                         vertices->no[0] = 0;
797                                         vertices->no[1] = 0;
798                                         vertices->no[2] = SHRT_MAX;
799                                         ++vertices;
800                                         ++vertex_index;
801
802                                         // edges
803                                         edges->v1 = vertex_index - 1;
804                                         edges->v2 = vertex_index - 3;
805                                         ++edges;
806                                         ++edge_index;
807
808                                         edges->v1 = vertex_index - 1;
809                                         edges->v2 = vertex_index - 2;
810                                         ++edges;
811                                         ++edge_index;
812
813                                         // poly
814                                         polys->loopstart = loop_index;
815                                         polys->totloop = 3;
816                                         polys->mat_nr = material_index;
817                                         ++polys;
818
819                                         // Even and odd loops connect triangles vertices differently
820                                         bool is_odd = n % 2;
821                                         // loops
822                                         if (is_odd) {
823                                                 loops[0].v = vertex_index - 1;
824                                                 loops[0].e = edge_index - 2;
825
826                                                 loops[1].v = vertex_index - 3;
827                                                 loops[1].e = edge_index - 3;
828
829                                                 loops[2].v = vertex_index - 2;
830                                                 loops[2].e = edge_index - 1;
831                                         }
832                                         else {
833                                                 loops[0].v = vertex_index - 1;
834                                                 loops[0].e = edge_index - 1;
835
836                                                 loops[1].v = vertex_index - 2;
837                                                 loops[1].e = edge_index - 3;
838
839                                                 loops[2].v = vertex_index - 3;
840                                                 loops[2].e = edge_index - 2;
841                                         }
842                                         loops += 3;
843                                         loop_index += 3;
844
845                                         // UV
846                                         if (hasTex) {
847                                                 // First UV layer (loopsuv[0]) has no tips (texCoord(0)).
848                                                 // Second UV layer (loopsuv[1]) has tips:  (texCoord(1)).
849                                                 for (int L = 0; L < 2; L++) {
850                                                         if (is_odd) {
851                                                                 loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
852                                                                 loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
853
854                                                                 loopsuv[L][1].uv[0] = svRep[0]->texCoord(L).x();
855                                                                 loopsuv[L][1].uv[1] = svRep[0]->texCoord(L).y();
856
857                                                                 loopsuv[L][2].uv[0] = svRep[1]->texCoord(L).x();
858                                                                 loopsuv[L][2].uv[1] = svRep[1]->texCoord(L).y();
859                                                         }
860                                                         else {
861                                                                 loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
862                                                                 loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
863
864                                                                 loopsuv[L][1].uv[0] = svRep[1]->texCoord(L).x();
865                                                                 loopsuv[L][1].uv[1] = svRep[1]->texCoord(L).y();
866
867                                                                 loopsuv[L][2].uv[0] = svRep[0]->texCoord(L).x();
868                                                                 loopsuv[L][2].uv[1] = svRep[0]->texCoord(L).y();
869                                                         }
870                                                         loopsuv[L] += 3;
871                                                 }
872                                         }
873
874                                         // colors and alpha transparency
875                                         if (is_odd) {
876                                                 colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
877                                                 colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
878                                                 colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
879                                                 colors[0].a = (short)(255.0f * svRep[2]->alpha());
880
881                                                 colors[1].r = (short)(255.0f * svRep[0]->color()[0]);
882                                                 colors[1].g = (short)(255.0f * svRep[0]->color()[1]);
883                                                 colors[1].b = (short)(255.0f * svRep[0]->color()[2]);
884                                                 colors[1].a = (short)(255.0f * svRep[0]->alpha());
885
886                                                 colors[2].r = (short)(255.0f * svRep[1]->color()[0]);
887                                                 colors[2].g = (short)(255.0f * svRep[1]->color()[1]);
888                                                 colors[2].b = (short)(255.0f * svRep[1]->color()[2]);
889                                                 colors[2].a = (short)(255.0f * svRep[1]->alpha());
890                                         }
891                                         else {
892                                                 colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
893                                                 colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
894                                                 colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
895                                                 colors[0].a = (short)(255.0f * svRep[2]->alpha());
896
897                                                 colors[1].r = (short)(255.0f * svRep[1]->color()[0]);
898                                                 colors[1].g = (short)(255.0f * svRep[1]->color()[1]);
899                                                 colors[1].b = (short)(255.0f * svRep[1]->color()[2]);
900                                                 colors[1].a = (short)(255.0f * svRep[1]->alpha());
901
902                                                 colors[2].r = (short)(255.0f * svRep[0]->color()[0]);
903                                                 colors[2].g = (short)(255.0f * svRep[0]->color()[1]);
904                                                 colors[2].b = (short)(255.0f * svRep[0]->color()[2]);
905                                                 colors[2].a = (short)(255.0f * svRep[0]->alpha());
906                                         }
907                                         transp[0].r = transp[0].g = transp[0].b = colors[0].a;
908                                         transp[1].r = transp[1].g = transp[1].b = colors[1].a;
909                                         transp[2].r = transp[2].g = transp[2].b = colors[2].a;
910                                         colors += 3;
911                                         transp += 3;
912                                 }
913                         } // loop over strip vertices
914                 } // loop over strips
915                 material_index++;
916         } // loop over strokes
917
918         test_object_materials(freestyle_bmain, (ID *)mesh);
919
920 #if 0 // XXX
921         BLI_assert(mesh->totvert == vertex_index);
922         BLI_assert(mesh->totedge == edge_index);
923         BLI_assert(mesh->totloop == loop_index);
924         BLI_assert(mesh->totcol == material_index);
925         BKE_mesh_validate(mesh, true, true);
926 #endif
927 }
928
929 // A replacement of BKE_object_add() for better performance.
930 Object *BlenderStrokeRenderer::NewMesh() const
931 {
932         Object *ob;
933         Base *base;
934         char name[MAX_ID_NAME];
935         unsigned int mesh_id = get_stroke_mesh_id();
936
937         BLI_snprintf(name, MAX_ID_NAME, "0%08xOB", mesh_id);
938         ob = BKE_object_add_only_object(freestyle_bmain, OB_MESH, name);
939         BLI_snprintf(name, MAX_ID_NAME, "0%08xME", mesh_id);
940         ob->data = BKE_mesh_add(freestyle_bmain, name);
941         ob->lay = 1;
942
943         base = BKE_scene_base_add(freestyle_scene, ob);
944         DAG_relations_tag_update(freestyle_bmain);
945 #if 0
946         BKE_scene_base_deselect_all(scene);
947         BKE_scene_base_select(scene, base);
948 #else
949         (void)base;
950 #endif
951
952         DAG_id_tag_update_ex(freestyle_bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
953
954         return ob;
955 }
956
957 Render *BlenderStrokeRenderer::RenderScene(Render * /*re*/, bool render)
958 {
959         Camera *camera = (Camera *)freestyle_scene->camera->data;
960         if (camera->clipend < _z)
961                 camera->clipend = _z + _z_delta * 100.0f;
962 #if 0
963         if (G.debug & G_DEBUG_FREESTYLE) {
964                 cout << "clipsta " << camera->clipsta << ", clipend " << camera->clipend << endl;
965         }
966 #endif
967
968         Render *freestyle_render = RE_NewRender(freestyle_scene->id.name);
969
970         RE_RenderFreestyleStrokes(freestyle_render, freestyle_bmain, freestyle_scene,
971                                   render && get_stroke_count() > 0);
972
973         return freestyle_render;
974 }
975
976 } /* namespace Freestyle */