Further consolidation of the view map creation.
[blender-staging.git] / source / blender / freestyle / intern / blender_interface / BlenderStrokeRenderer.cpp
1 # include "BlenderStrokeRenderer.h"
2 # include "../stroke/Canvas.h"
3 # include "../application/AppConfig.h"
4
5 # include "BlenderTextureManager.h"
6
7 #ifdef __cplusplus
8 extern "C" {
9 #endif
10
11 #include "MEM_guardedalloc.h"
12
13 #include "DNA_camera_types.h"
14 #include "DNA_customdata_types.h"
15 #include "DNA_listBase.h"
16 #include "DNA_mesh_types.h"
17 #include "DNA_meshdata_types.h"
18 #include "DNA_screen_types.h"
19
20 #include "BKE_customdata.h"
21 #include "BKE_global.h"
22 #include "BKE_library.h" /* free_libblock */
23 #include "BKE_material.h"
24 #include "BKE_main.h" /* struct Main */
25 #include "BKE_object.h"
26 #include "BKE_scene.h"
27
28 #include "RE_pipeline.h"
29
30 #include "renderpipeline.h"
31
32 #ifdef __cplusplus
33 }
34 #endif
35
36
37 BlenderStrokeRenderer::BlenderStrokeRenderer(Render* re)
38 :StrokeRenderer(){
39         
40         // TEMPORARY - need a  texture manager
41         _textureManager = new BlenderTextureManager;
42         _textureManager->load();
43
44         // Scene.New("FreestyleStrokes")
45         old_scene = re->scene;
46
47         objects.first = objects.last = NULL;
48         
49         ListBase lb;
50         freestyle_scene = add_scene("freestyle_strokes");
51         lb = freestyle_scene->r.layers;
52         freestyle_scene->r= old_scene->r;
53         freestyle_scene->r.layers= lb;
54         set_scene_bg( freestyle_scene );
55
56         // image dimensions
57         float ycor = ((float)re->r.yasp) / ((float)re->r.xasp);
58         float width = freestyle_scene->r.xsch;
59         float height = freestyle_scene->r.ysch * ycor;
60
61         // Camera
62         Object* object_camera = add_object(freestyle_scene, OB_CAMERA);
63         
64         Camera* camera = (Camera *) object_camera->data;
65         camera->type = CAM_ORTHO;
66         camera->ortho_scale = max(width,height);
67         
68         object_camera->loc[0] = 0.5 * width;
69         object_camera->loc[1] = 0.5 * height;
70         object_camera->loc[2] = 1.0;
71         
72         freestyle_scene->camera = object_camera;
73
74         store_object(object_camera);
75         
76         // Material
77         material = add_material("stroke_material");
78         material->mode |= MA_VERTEXCOLP;
79         material->mode |= MA_SHLESS;
80 }
81
82 BlenderStrokeRenderer::~BlenderStrokeRenderer(){
83         
84           if(0 != _textureManager)
85           {
86             delete _textureManager;
87             _textureManager = 0;
88           }
89
90         // release scene
91         free_libblock( &G.main->scene, freestyle_scene );
92
93         // release objects and data blocks
94         LinkData *link = (LinkData *)objects.first;
95         while(link) {
96                 Object *ob = (Object *)link->data;
97                 void *data = ob->data;
98                 char name[24];
99                 strcpy(name, ob->id.name);
100                 //cout << "removing " << name[0] << name[1] << ":" << (name+2) << endl;
101                 switch (ob->type) {
102                 case OB_MESH:
103                         free_libblock( &G.main->object, ob );
104                         free_libblock( &G.main->mesh, data );
105                         break;
106                 case OB_CAMERA:
107                         free_libblock( &G.main->object, ob );
108                         free_libblock( &G.main->camera, data );
109                         break;
110                 default:
111                         cerr << "Warning: unexpected object in the scene: " << name[0] << name[1] << ":" << (name+2) << endl;
112                 }
113                 link = link->next;
114         }
115         BLI_freelistN( &objects );
116
117         // release material
118         free_libblock( &G.main->mat, material );
119         
120         set_scene_bg( old_scene );
121 }
122
123 void BlenderStrokeRenderer::store_object(Object *ob) const {
124
125         LinkData *link = (LinkData *)MEM_callocN(sizeof(LinkData), "temporary object" );
126         link->data = ob;
127         BLI_addhead(const_cast<ListBase *>(&objects), link);
128 }
129
130 void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const{
131   RenderStrokeRepBasic(iStrokeRep);
132 }
133
134 void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const{
135         
136         ////////////////////
137         //  Build up scene
138         ////////////////////
139         
140           vector<Strip*>& strips = iStrokeRep->getStrips();
141           Strip::vertex_container::iterator v[3];
142           StrokeVertexRep *svRep[3];
143           Vec3r color[3];
144           unsigned int vertex_index;
145           float ycor = ((float)freestyle_scene->r.yasp) / ((float)freestyle_scene->r.xasp);
146           float width = freestyle_scene->r.xsch;
147           float height = freestyle_scene->r.ysch * ycor;
148           Vec2r p;
149         
150           for(vector<Strip*>::iterator s=strips.begin(), send=strips.end();
151           s!=send;
152           ++s){         
153                 
154             Strip::vertex_container& strip_vertices = (*s)->vertices();
155                 int strip_vertex_count = (*s)->sizeStrip();
156                 int m, n, visible_faces, visible_segments;
157                 bool visible;
158
159                 // iterate over all vertices and count visible faces and strip segments
160                 // (note: a strip segment is a series of visible faces, while two strip
161                 // segments are separated by one or more invisible faces)
162                 v[0] = strip_vertices.begin();
163             v[1] = v[0]; ++(v[1]);
164             v[2] = v[1]; ++(v[2]);
165                 visible_faces = visible_segments = 0;
166                 visible = false;
167             for (n = 2; n < strip_vertex_count; n++)
168                 {
169                         svRep[0] = *(v[0]);
170                         svRep[1] = *(v[1]);
171                         svRep[2] = *(v[2]);
172                         m = 0;
173                         for (int j = 0; j < 3; j++) {
174                                 p = svRep[j]->point2d();
175                                 if (p[0] < 0.0 || p[0] > width || p[1] < 0.0 || p[1] > height)
176                                         m++;
177                         }
178                         if (m == 3) {
179                                 visible = false;
180                         } else {
181                                 visible_faces++;
182                                 if (!visible)
183                                         visible_segments++;
184                                 visible = true;
185                         }
186                         ++v[0]; ++v[1]; ++v[2];
187                 }
188                 if (visible_faces == 0)
189                         continue;
190
191                 // me = Mesh.New()
192                 Object* object_mesh = add_object(freestyle_scene, OB_MESH);
193                 Mesh* mesh = (Mesh *) object_mesh->data;
194                 MEM_freeN(mesh->bb);
195                 mesh->bb= NULL;
196                 mesh->id.us = 0;
197
198                 store_object(object_mesh);
199                 
200 #if 1
201                 // me.materials = [mat]
202                 mesh->mat = ( Material ** ) MEM_mallocN( 1 * sizeof( Material * ), "MaterialList" );
203                 mesh->mat[0] = material;
204                 mesh->totcol = 1;
205                 test_object_materials( (ID*) mesh );
206 #else
207                 assign_material(object_mesh, material, object_mesh->totcol+1);
208                 object_mesh->actcol= object_mesh->totcol;
209 #endif
210                 
211                 // vertices allocation
212                 mesh->totvert = visible_faces + visible_segments * 2;
213                 mesh->mvert = (MVert*) CustomData_add_layer( &mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
214                         
215                 // faces allocation
216                 mesh->totface = visible_faces;
217                 mesh->mface = (MFace*) CustomData_add_layer( &mesh->fdata, CD_MFACE, CD_CALLOC, NULL, mesh->totface);
218                 
219                 // colors allocation  - me.vertexColors = True
220                 MCol* alphas = (MCol *) CustomData_add_layer_named( &mesh->fdata, CD_MCOL, CD_CALLOC, NULL, mesh->totface, "A" );
221                 MCol* colors = (MCol *) CustomData_add_layer_named( &mesh->fdata, CD_MCOL, CD_CALLOC, NULL, mesh->totface, "RGB" );
222                 mesh->mcol = alphas;
223
224                 ////////////////////
225                 //  Data copy
226                 ////////////////////
227                 
228                 MVert* vertices = mesh->mvert;
229                 MFace* faces = mesh->mface;
230                 
231             v[0] = strip_vertices.begin();
232             v[1] = v[0]; ++(v[1]);
233             v[2] = v[1]; ++(v[2]);
234
235                 vertex_index = 0;
236                 visible = false;
237                 
238             for (n = 2; n < strip_vertex_count; n++)
239                 {
240                         svRep[0] = *(v[0]);
241                         svRep[1] = *(v[1]);
242                         svRep[2] = *(v[2]);
243                         m = 0;
244                         for (int j = 0; j < 3; j++) {
245                                 p = svRep[j]->point2d();
246                                 if (p[0] < 0.0 || p[0] > width || p[1] < 0.0 || p[1] > height)
247                                         m++;
248                         }
249                         if (m == 3) {
250                                 visible = false;
251                         } else {
252                                 if (!visible) {
253                                         vertex_index += 2;
254
255                                         // first vertex
256                                         vertices->co[0] = svRep[0]->point2d()[0];
257                                         vertices->co[1] = svRep[0]->point2d()[1];
258                                         vertices->co[2] = 0.0;
259                                         ++vertices;
260                                         
261                                         // second vertex
262                                         vertices->co[0] = svRep[1]->point2d()[0];
263                                         vertices->co[1] = svRep[1]->point2d()[1];
264                                         vertices->co[2] = 0.0;
265                                         ++vertices;
266                                 }
267                                 visible = true;
268
269                                 // vertex
270                                 vertices->co[0] = svRep[2]->point2d()[0];
271                                 vertices->co[1] = svRep[2]->point2d()[1];
272                                 vertices->co[2] = 0.0;
273                                 
274                                 // faces
275                                 faces->v1 = vertex_index - 2;
276                                 faces->v2 = vertex_index - 1;
277                                 faces->v3 = vertex_index;
278                                 faces->v4 = 0;
279                                 
280                                 // colors
281                                 // red and blue are swapped - cf DNA_meshdata_types.h : MCol    
282                                 color[0] = svRep[0]->color();
283                                 color[1] = svRep[1]->color();
284                                 color[2] = svRep[2]->color();
285
286                                 colors->a = 0;
287                                 colors->r = (short)(255.0f*(color[0])[2]);
288                                 colors->g = (short)(255.0f*(color[0])[1]);
289                                 colors->b = (short)(255.0f*(color[0])[0]);
290                                 alphas->a = 0;
291                                 alphas->r = 0;
292                                 alphas->g = 0;
293                                 alphas->b = (short)(255.0f*svRep[0]->alpha());
294                                 ++colors; ++alphas;
295                                 
296                                 colors->a = 0;
297                                 colors->r = (short)(255.0f*(color[1])[2]);
298                                 colors->g = (short)(255.0f*(color[1])[1]);
299                                 colors->b = (short)(255.0f*(color[1])[0]);
300                                 alphas->a = 0;
301                                 alphas->r = 0;
302                                 alphas->g = 0;
303                                 alphas->b = (short)(255.0f*svRep[1]->alpha());
304                                 ++colors; ++alphas;
305                                 
306                                 colors->a = 0;
307                                 colors->r = (short)(255.0f*(color[2])[2]);
308                                 colors->g = (short)(255.0f*(color[2])[1]);
309                                 colors->b = (short)(255.0f*(color[2])[0]);
310                                 alphas->a = 0;
311                                 alphas->r = 0;
312                                 alphas->g = 0;
313                                 alphas->b = (short)(255.0f*svRep[2]->alpha());
314                                 ++colors; ++alphas;
315
316                                 ++faces; ++vertices; ++colors; ++alphas;
317                                 ++vertex_index;
318                         }
319                         ++v[0]; ++v[1]; ++v[2];
320
321                 } // loop over strip vertices 
322         
323         } // loop over strips   
324
325 }
326
327 Render* BlenderStrokeRenderer::RenderScene( Render *re ) {
328     Render* freestyle_render;
329     RenderLayer *rl;
330     float *rectf, *alpha;
331         int x, y, rectx, recty;
332         
333         freestyle_scene->r.mode &= ~( R_EDGE_FRS | R_SHADOW | R_SSS | R_PANORAMA | R_ENVMAP | R_MBLUR );
334         freestyle_scene->r.scemode &= ~( R_SINGLE_LAYER );
335         freestyle_scene->r.planes = R_PLANES32;
336         freestyle_scene->r.imtype = R_PNG;
337         
338     // Pass 1 - render only the alpha component
339         freestyle_render = RE_NewRender(freestyle_scene->id.name);
340         RE_BlenderFrame( freestyle_render, freestyle_scene, NULL, 1);
341
342     // save the alpha component of the render into a buffer
343         rl = render_get_active_layer( freestyle_render, freestyle_render->result );
344     if (!rl || rl->rectf == NULL) {
345         cout << "Cannot find Freestyle result image" << endl;
346         RE_FreeRender(freestyle_render);
347         return NULL;
348     }
349         rectf = rl->rectf;
350         rectx = re->rectx;
351         recty = re->recty;
352     alpha = new float[rectx * recty];
353     for (y = 0; y < recty; y++)
354         for (x = 0; x < rectx; x++)
355             alpha[rectx * y + x] = rectf[4 * (rectx * y + x)];
356
357         RE_FreeRender(freestyle_render);
358
359     // replace the mesh vertex colors
360     LinkData *link = (LinkData *)objects.first;
361     while (link) {
362                 Object *ob = (Object *)link->data;
363         if (ob->type == OB_MESH) {
364                 Mesh *mesh = (Mesh *)ob->data;
365             int index = CustomData_get_named_layer_index(&mesh->fdata, CD_MCOL, "A");
366             if (index < 0) {
367                 cout << "Cannot find mesh MCol layer (A)" << endl;
368                 goto error;
369             }
370             CustomData_free_layer(&mesh->fdata, CD_MCOL, mesh->totface, index);
371                 mesh->mcol = (MCol *)CustomData_get_layer_named(&mesh->fdata, CD_MCOL, "RGB");
372             if (!mesh->mcol) {
373                 cout << "Cannot find mesh MCol layer (RGB)" << endl;
374                 goto error;
375             }
376                 }
377         link = link->next;
378         }
379
380     // Pass 2 - render the RGB components
381         freestyle_render = RE_NewRender(freestyle_scene->id.name);
382     RE_BlenderFrame( freestyle_render, freestyle_scene, NULL, 1);
383
384     // merge the saved alpha component into the 2nd render
385         rl = render_get_active_layer( freestyle_render, freestyle_render->result );
386     if (!rl || rl->rectf == NULL) {
387         cout << "Cannot find Freestyle result image" << endl;
388         RE_FreeRender(freestyle_render);
389         goto error;
390     }
391         rectf = rl->rectf;
392     for (y = 0; y < recty; y++)
393         for (x = 0; x < rectx; x++)
394             rectf[4 * (rectx * y + x) + 3] = alpha[rectx * y + x];
395
396     delete [] alpha;
397
398     return freestyle_render;
399
400 error:
401     delete [] alpha;
402
403     return NULL;
404 }