a8098e12ef766a7e6a135eef021b4e027261efd9
[goodguy/history.git] / scenegraph.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21
22 #include "affine.h"
23 #include "clip.h"
24 #include <math.h>
25 #include "overlayframe.h"
26 #include "scenegraph.h"
27 #include <string.h>
28
29
30 #define PRINT_INDENT for(int i = 0; i < indent; i++) printf(" ");
31
32
33 SceneNode::SceneNode()
34 {
35         reset();
36 }
37
38 SceneNode::SceneNode(const char *title)
39 {
40         reset();
41         strcpy(this->title, title);
42 }
43
44 SceneNode::SceneNode(VFrame *image, int private_image, float x, float y)
45 {
46         reset();
47         this->image = image;
48         if(this->image) this->private_image = private_image;
49         this->x = x;
50         this->y = y;
51 }
52
53 SceneNode::~SceneNode()
54 {
55         nodes.remove_all_objects();
56         if(private_image) delete image;
57 }
58
59 void SceneNode::reset()
60 {
61         parent = 0;
62         scene = 0;
63         x = y = z = rx = ry = rz = 0;
64         sx = sy = sz = 1;
65         hidden = 0;
66         image = 0;
67         private_image = 0;
68         flip = 0;
69         title[0] = 0;
70 }
71
72 void SceneNode::append(SceneNode *node)
73 {
74         node->parent = this;
75         node->scene = this->scene;
76         nodes.append(node);
77 }
78
79 void SceneNode::copy_ref(SceneNode *node)
80 {
81         if(private_image) delete image;
82         private_image = 0;
83         x = node->x;
84         y = node->y;
85         z = node->z;
86         rx = node->rx;
87         ry = node->ry;
88         rz = node->rz;
89         sx = node->sx;
90         sy = node->sy;
91         sz = node->sz;
92         hidden = node->hidden;
93         image = node->image;
94         flip = node->flip;
95 }
96
97 SceneNode* SceneNode::get_node(int number)
98 {
99         return nodes.get(number);
100 }
101
102 int SceneNode::get_memory_usage()
103 {
104         if(image)
105                 return image->get_memory_usage();
106         else
107                 return 0;
108 }
109
110 void SceneNode::render(VFrame *frame, int do_camera)
111 {
112         const int debug = 0;
113         if(debug) printf("SceneNode::render %d this=%p title=%s image=%p x=%f y=%f frame=%p do_camera=%d\n",
114                 __LINE__,
115                 this,
116                 title,
117                 image,
118                 this->x,
119                 this->y,
120                 frame,
121                 do_camera);
122
123         VFrame *temp = 0;
124         VFrame *temp2 = 0;
125         if(image)
126         {
127                 float x = this->x;
128                 float y = this->y;
129                 float sx = this->sx;
130                 float sy = this->sy;
131                 float ry = this->ry;
132                 if(parent)
133                         parent->transform_coord(&x, &y, &sx, &sy, &ry);
134
135                 if(do_camera) scene->transform_camera(frame,
136                         &x,
137                         &y,
138                         &sx,
139                         &sy,
140                         get_flip());
141
142                 if(debug) printf("SceneNode::render %d at_y=%f\n",
143                         __LINE__,
144                         ((SceneCamera*)scene->cameras.get(0))->at_y);
145
146 // Render everything into a temporary, then overlay the temporary
147 //              if(!EQUIV(ry, 0) || get_flip())
148 //              {
149                 temp = new VFrame(image->get_w(),
150                         image->get_h(),
151                         image->get_color_model());
152 //              }
153                 if(debug) printf("SceneNode::render %d\n", __LINE__);
154
155
156 // 1st comes our image
157                 temp->copy_from(image);
158
159 // Then come the subnodes without camera transforms
160                 if(debug) printf("SceneNode::render %d this=%p nodes=%d\n", __LINE__, this, nodes.size());
161                 for(int i = 0; i < nodes.size(); i++)
162                         nodes.get(i)->render(temp, 0);
163
164
165
166                 if(debug) printf("SceneNode::render %d\n", __LINE__);
167
168 // Then comes rotation into temp2
169                 VFrame *src = temp;
170                 if(!EQUIV(ry, 0))
171                 {
172                         src = temp2 = new VFrame(image->get_w(),
173                                 image->get_h(),
174                                 image->get_color_model());
175                         if(!scene->affine) scene->affine =
176                                 new AffineEngine(scene->cpus, scene->cpus);
177                         scene->affine->rotate(temp2,
178                                 temp,
179                                 ry);
180                         if(debug) printf("SceneNode::render %d ry=%f\n", __LINE__, ry);
181                 }
182
183 // Then comes flipping
184                 if(get_flip())
185                         src->flip_horiz();
186
187                 if(debug) printf("SceneNode::render %d src=%p x=%f y=%f sx=%f sy=%f\n",
188                         __LINE__,
189                         src,
190                         x,
191                         y,
192                         sx,
193                         sy);
194
195 // Overlay on the output frame
196                 if(!scene->overlayer) scene->overlayer = new OverlayFrame(scene->cpus);
197
198                 if(get_flip())
199                 {
200                         scene->overlayer->overlay(frame,
201                                 src,
202                                 0,
203                                 0,
204                                 image->get_w(),
205                                 image->get_h(),
206                                 frame->get_w() - x - image->get_w() * sx,
207                                 y,
208                                 frame->get_w() - x,
209                                 y + image->get_h() * sy,
210                                 1,
211                                 TRANSFER_NORMAL,
212                                 NEAREST_NEIGHBOR);
213                 }
214                 else
215                 {
216                         if(debug) printf("SceneNode::render %d image=%p src=%p frame=%p\n",
217                                 __LINE__,
218                                 image,
219                                 src,
220                                 frame);
221                         scene->overlayer->overlay(frame,
222                                 src,
223                                 0,
224                                 0,
225                                 image->get_w(),
226                                 image->get_h(),
227                                 x,
228                                 y,
229                                 x + image->get_w() * sx,
230                                 y + image->get_h() * sy,
231                                 1,
232                                 TRANSFER_NORMAL,
233                                 NEAREST_NEIGHBOR);
234                 }
235
236                 if(debug) printf("SceneNode::render %d\n", __LINE__);
237
238         }
239         else
240         {
241                 for(int i = 0; i < nodes.size(); i++)
242                         nodes.get(i)->render(frame, 1);
243         }
244
245         if(debug) printf("SceneNode::render %d this=%p title=%s\n", __LINE__, this, title);
246
247         if(temp) delete temp;
248         if(temp2) delete temp2;
249 }
250
251 int SceneNode::get_flip()
252 {
253         if(flip) return 1;
254         if(parent && !parent->image) return parent->get_flip();
255         return 0;
256 }
257
258
259 void SceneNode::transform_coord(
260         float *x,
261         float *y,
262         float *sx,
263         float *sy,
264         float *ry)
265 {
266 // Rotate it
267 //      if(!EQUIV(this->ry, 0))
268 //      {
269 //              float pivot_x = 0;
270 //              float pivot_y = 0;
271 //              if(image)
272 //              {
273 //                      pivot_x = image->get_w() / 2;
274 //                      pivot_y = image->get_h() / 2;
275 //              }
276 //
277 //              float rel_x = *x - pivot_x;
278 //              float rel_y = *y - pivot_y;
279 //              float angle = atan2(rel_y, rel_x);
280 //              float mag = sqrt(rel_x * rel_x + rel_y * rel_y);
281 //              angle += this->ry * 2 * M_PI / 360;
282 //              *x = mag * cos(angle) + pivot_x;
283 //              *y = mag * sin(angle) + pivot_y;
284 //      }
285
286 // Nodes with images reset the transformation
287         if(!image)
288         {
289 // Scale it
290                 *x *= this->sx;
291                 *y *= this->sy;
292                 *sx *= this->sx;
293                 *sy *= this->sy;
294
295 // Translate it
296                 *x += this->x;
297                 *y += this->y;
298
299
300 // Accumulate rotation
301                 *ry += this->ry;
302
303                 if(parent)
304                 {
305                         parent->transform_coord(x, y, sx, sy, ry);
306                 }
307         }
308 }
309
310 void SceneNode::dump(int indent)
311 {
312         PRINT_INDENT
313         printf("SceneNode::dump %d this=%p title=%s\n", __LINE__, this, title);
314         PRINT_INDENT
315         printf("  image=%p private_image=%d hidden=%d flip=%d\n",
316                 image,
317                 private_image,
318                 hidden,
319                 flip);
320         PRINT_INDENT
321         printf("  x=%f y=%f z=%f sz=%f sy=%f sz=%f rx=%f ry=%f rz=%f\n",
322                 x, y, z, sz, sy, sz, rx, ry, rz);
323         PRINT_INDENT
324         printf("  nodes=%d\n", nodes.size());
325         for(int i = 0; i < nodes.size(); i++)
326         {
327                 nodes.get(i)->dump(indent + 4);
328         }
329 }
330
331
332
333
334
335 SceneGraph::SceneGraph() : VFrameScene()
336 {
337         current_camera = 0;
338         affine = 0;
339         overlayer = 0;
340 }
341
342 SceneGraph::~SceneGraph()
343 {
344         nodes.remove_all_objects();
345         cameras.remove_all_objects();
346         delete affine;
347         delete overlayer;
348 }
349
350
351 SceneNode* SceneGraph::get_node(int number)
352 {
353         return nodes.get(number);
354 }
355
356 void SceneGraph::append(SceneNode *node)
357 {
358         node->parent = 0;
359         node->scene = this;
360         nodes.append(node);
361 }
362
363 void SceneGraph::append_camera(SceneNode *node)
364 {
365         node->scene = this;
366         cameras.append(node);
367 }
368
369 void SceneGraph::render(VFrame *frame, int cpus)
370 {
371         const int debug = 0;
372         if(debug) printf("SceneGraph::render %d\n", __LINE__);
373         if(debug) dump();
374
375         this->cpus = cpus;
376
377         for(int i = 0; i < nodes.size(); i++)
378         {
379                 nodes.get(i)->render(frame, 1);
380         }
381 }
382
383 void SceneGraph::transform_camera(VFrame *frame,
384         float *x,
385         float *y,
386         float *sx,
387         float *sy,
388         int flip)
389 {
390         if(cameras.size())
391         {
392                 SceneCamera *camera = (SceneCamera*)cameras.get(current_camera);
393
394                 if(flip)
395                 {
396                         *x = frame->get_w() - *x;
397                 }
398
399                 *x -= camera->at_x;
400                 *y -= camera->at_y;
401                 *x *= camera->scale;
402                 *y *= camera->scale;
403                 *sx *= camera->scale;
404                 *sy *= camera->scale;
405
406                 if(flip)
407                 {
408                         *x = frame->get_w() - *x;
409                 }
410         }
411 }
412
413 void SceneGraph::dump()
414 {
415         int indent = 2;
416         printf("SceneGraph::dump %d cameras=%d\n", __LINE__, cameras.size());
417         for(int i = 0; i < cameras.size(); i++)
418                 cameras.get(i)->dump(indent);
419         printf("SceneGraph::dump %d nodes=%d\n", __LINE__, nodes.size());
420         for(int i = 0; i < nodes.size(); i++)
421                 nodes.get(i)->dump(indent);
422 }
423
424
425
426
427
428
429
430 SceneTransform::SceneTransform() : SceneNode()
431 {
432 }
433
434 SceneTransform::~SceneTransform()
435 {
436 }
437
438
439
440
441
442 SceneLight::SceneLight() : SceneNode()
443 {
444 }
445
446 SceneLight::~SceneLight()
447 {
448 }
449
450
451
452
453
454
455
456 SceneCamera::SceneCamera() : SceneNode()
457 {
458         at_x = at_y = at_z = 0;
459         scale = 1;
460 }
461
462 SceneCamera::~SceneCamera()
463 {
464 }
465
466 void SceneCamera::dump(int indent)
467 {
468         PRINT_INDENT
469         printf("SceneCamera::dump %d this=%p\n", __LINE__, this);
470         PRINT_INDENT
471         printf("  at_x=%f at_y=%f at_z=%f scale=%f\n",
472                 at_x,
473                 at_y,
474                 at_z,
475                 scale);
476 }
477
478
479
480
481 SceneMaterial::SceneMaterial() : SceneNode()
482 {
483         r = g = b = a = 0;
484         texture = 0;
485         s = t = 0;
486 }
487
488 SceneMaterial::~SceneMaterial()
489 {
490         delete [] texture;
491 }
492
493
494
495
496
497
498
499 SceneShape::SceneShape() : SceneNode()
500 {
501         pivot_x = pivot_y = pivot_z = 0;
502 }
503
504 SceneShape::~SceneShape()
505 {
506 }
507
508
509
510
511
512
513
514
515 SceneCylinder::SceneCylinder() : SceneShape()
516 {
517 }
518
519 SceneCylinder::~SceneCylinder()
520 {
521 }
522
523
524
525
526 SceneSphere::SceneSphere() : SceneShape()
527 {
528 }
529
530
531 SceneSphere::~SceneSphere()
532 {
533 }
534
535
536
537
538 SceneBox::SceneBox() : SceneShape()
539 {
540 }
541
542
543 SceneBox::~SceneBox()
544 {
545 }
546
547
548
549
550
551
552
553
554
555
556
557
558