comparison src/paranormal/xform.c @ 333:afc61c0efc05 trunk

[svn] - add Trans / Movement implementation
author nenolod
date Tue, 05 Dec 2006 02:16:09 -0800
parents a1517b09cb3a
children a9f1bd76a3e6
comparison
equal deleted inserted replaced
332:626f9f4d79a8 333:afc61c0efc05
12 #include <glib.h> 12 #include <glib.h>
13 13
14 #include "paranormal.h" 14 #include "paranormal.h"
15 #include "actuators.h" 15 #include "actuators.h"
16 #include "pn_utils.h" 16 #include "pn_utils.h"
17
18 #include "libcalc/calc.h"
17 19
18 struct xform_vector 20 struct xform_vector
19 { 21 {
20 gint32 offset; /* the offset of the top left pixel */ 22 gint32 offset; /* the offset of the top left pixel */
21 guint16 w; /* 4:4:4:4 NE, NW, SE, SW pixel weights 23 guint16 w; /* 4:4:4:4 NE, NW, SE, SW pixel weights
440 "xform_halfrender", "Halfrender Transform", 442 "xform_halfrender", "Halfrender Transform",
441 "Divides the surface in half and renders it twice.", 443 "Divides the surface in half and renders it twice.",
442 0, xform_halfrender_opts, 444 0, xform_halfrender_opts,
443 NULL, NULL, xform_halfrender_exec 445 NULL, NULL, xform_halfrender_exec
444 }; 446 };
447
448 /* **************** xform_movement **************** */
449 struct pn_actuator_option_desc xform_movement_opts[] =
450 {
451 { "formula", "The formula to evaluate.",
452 OPT_TYPE_STRING, { sval: "d = 0.15;" } },
453 { NULL }
454 };
455
456 typedef struct {
457 int width, height; /* Previous width and height. */
458 struct xform_vector *vfield;
459 } PnMovementData;
460
461 static void
462 xform_movement_init (gpointer *data)
463 {
464 *data = g_new0(PnMovementData, 1);
465 }
466
467 static void
468 xform_movement_cleanup (gpointer data)
469 {
470 PnMovementData *d = (PnMovementData *) data;
471
472 if (d)
473 {
474 if (d->vfield)
475 g_free (d->vfield);
476 g_free (d);
477 }
478 }
479
480 static void
481 xform_movement_exec (const struct pn_actuator_option *opts,
482 gpointer odata)
483 {
484 PnMovementData *d = (PnMovementData *) odata;
485
486 if (d->width != pn_image_data->width
487 || d->height != pn_image_data->height)
488 {
489 gint i, j;
490 gdouble *rf, *df;
491 gdouble xf, yf;
492 gint xn, yn;
493 expression_t *expr;
494 symbol_dict_t *dict;
495
496 d->width = pn_image_data->width;
497 d->height = pn_image_data->height;
498
499 if (d->vfield)
500 {
501 g_free (d->vfield);
502 d->vfield = NULL;
503 }
504
505 if (opts[0].val.sval == NULL)
506 return;
507
508 dict = dict_new();
509 expr = expr_compile_string(opts[0].val.sval, dict);
510 if (!expr)
511 {
512 dict_free(dict);
513 return;
514 }
515
516 rf = dict_variable(dict, "r");
517 df = dict_variable(dict, "d");
518
519 d->vfield = g_malloc (sizeof(struct xform_vector)
520 * d->width * d->height);
521
522 for (j = 0; j < pn_image_data->height; j++)
523 for (i = 0; i < pn_image_data->width; i++)
524 {
525 /* Points (xf, yf) must be in a (-1..1) square. */
526 xf = 2.0 * i / (pn_image_data->width - 1) - 1.0;
527 yf = 2.0 * j / (pn_image_data->height - 1) - 1.0;
528
529 /* Now, convert to polar coordinates r and d. */
530 *rf = hypot(xf, yf);
531 *df = atan2(yf, xf);
532
533 /* Run the script. */
534 expr_execute(expr, dict);
535
536 /* Back to (-1..1) square. */
537 xf = (*rf) * cos ((*df));
538 yf = (*rf) * sin ((*df));
539
540 /* Convert back to physical coordinates. */
541 xn = (int)(((xf + 1.0) * (pn_image_data->width - 1) / 2) + 0.5);
542 yn = (int)(((yf + 1.0) * (pn_image_data->height - 1) / 2) + 0.5);
543
544 if (xn < 0 || xn >= pn_image_data->width || yn < 0 || yn >= pn_image_data->height)
545 {
546 xn = i; yn = j;
547 }
548
549 xfvec (xn, yn, &d->vfield[PN_IMG_INDEX (i, j)]);
550 }
551 }
552
553 apply_xform (d->vfield);
554 pn_swap_surfaces ();
555 }
556
557 struct pn_actuator_desc builtin_xform_movement =
558 {
559 "xform_movement", "Movement Transform",
560 "A customizable blitter.",
561 0, xform_movement_opts,
562 xform_movement_init, xform_movement_cleanup, xform_movement_exec
563 };