comparison src/paranormal/xform.c @ 336:8554beb862c0 trunk

[svn] - implement AVS-like Trans / Dynamic Movement
author nenolod
date Tue, 05 Dec 2006 14:10:31 -0800
parents a9f1bd76a3e6
children 5d12ef0b97a5
comparison
equal deleted inserted replaced
335:015513ad27d2 336:8554beb862c0
562 "xform_movement", "Movement Transform", 562 "xform_movement", "Movement Transform",
563 "A customizable blitter.", 563 "A customizable blitter.",
564 0, xform_movement_opts, 564 0, xform_movement_opts,
565 xform_movement_init, xform_movement_cleanup, xform_movement_exec 565 xform_movement_init, xform_movement_cleanup, xform_movement_exec
566 }; 566 };
567
568 /* **************** xform_dynmovement **************** */
569 struct pn_actuator_option_desc xform_dynmovement_opts[] =
570 {
571 { "init_script", "The formula to evaluate on init.",
572 OPT_TYPE_STRING, { sval: "" } },
573 { "frame_script", "The formula to evaluate on each frame.",
574 OPT_TYPE_STRING, { sval: "" } },
575 { "point_script", "The formula to evaluate.",
576 OPT_TYPE_STRING, { sval: "d = 0.15;" } },
577 { NULL }
578 };
579
580 typedef struct {
581 int width, height; /* Previous width and height. */
582 expression_t *expr_init;
583 expression_t *expr_frame;
584 expression_t *expr_point;
585 symbol_dict_t *dict;
586 struct xform_vector *vfield;
587 } PnDynMovementData;
588
589 static void
590 xform_dynmovement_init (gpointer *data)
591 {
592 *data = g_new0(PnDynMovementData, 1);
593 }
594
595 static void
596 xform_dynmovement_cleanup (gpointer data)
597 {
598 PnDynMovementData *d = (PnDynMovementData *) data;
599
600 if (d)
601 {
602 if (d->expr_init)
603 expression_free (d->expr_init);
604 if (d->expr_frame)
605 expression_free (d->expr_frame);
606 if (d->expr_point)
607 expression_free (d->expr_point);
608 if (d->dict)
609 dict_free (d->dict);
610 if (d->vfield)
611 g_free (d->vfield);
612 g_free (d);
613 }
614 }
615
616 static void
617 xform_dynmovement_exec (const struct pn_actuator_option *opts,
618 gpointer odata)
619 {
620 PnDynMovementData *d = (PnDynMovementData *) odata;
621 gint i, j;
622 gdouble *rf, *df;
623 gdouble xf, yf;
624 gint xn, yn;
625
626 if (d->width != pn_image_data->width
627 || d->height != pn_image_data->height)
628 {
629 d->width = pn_image_data->width;
630 d->height = pn_image_data->height;
631
632 if (d->vfield)
633 {
634 g_free (d->vfield);
635 d->vfield = NULL;
636 }
637
638 if (opts[2].val.sval == NULL)
639 return;
640
641 if (!d->dict)
642 d->dict = dict_new();
643 else
644 {
645 dict_free(d->dict);
646 d->dict = dict_new();
647 }
648
649 rf = dict_variable(d->dict, "r");
650 df = dict_variable(d->dict, "d");
651
652 if (d->expr_init)
653 {
654 expression_free(d->expr_init);
655 d->expr_init = NULL;
656 }
657
658 /* initialize */
659 d->expr_init = expr_compile_string(opts[0].val.sval, d->dict);
660
661 if (d->expr_init != NULL)
662 {
663 expr_execute(d->expr_init, d->dict);
664 }
665
666 d->expr_frame = expr_compile_string(opts[1].val.sval, d->dict);
667 d->expr_point = expr_compile_string(opts[2].val.sval, d->dict);
668
669 d->vfield = g_malloc (sizeof(struct xform_vector)
670 * d->width * d->height);
671 }
672
673 /* run the on-frame script. */
674 if (d->expr_frame != NULL)
675 expr_execute(d->expr_frame, d->dict);
676
677 for (j = 0; j < pn_image_data->height; j++)
678 for (i = 0; i < pn_image_data->width; i++)
679 {
680 /* Points (xf, yf) must be in a (-1..1) square. */
681 xf = 2.0 * i / (pn_image_data->width - 1) - 1.0;
682 yf = 2.0 * j / (pn_image_data->height - 1) - 1.0;
683
684 /* Now, convert to polar coordinates r and d. */
685 *rf = hypot(xf, yf);
686 *df = atan2(yf, xf);
687
688 /* Run the script. */
689 if (d->expr_point != NULL)
690 expr_execute(d->expr_point, d->dict);
691
692 /* Back to (-1..1) square. */
693 xf = (*rf) * cos ((*df));
694 yf = (*rf) * sin ((*df));
695
696 /* Convert back to physical coordinates. */
697 xn = (int)(((xf + 1.0) * (pn_image_data->width - 1) / 2) + 0.5);
698 yn = (int)(((yf + 1.0) * (pn_image_data->height - 1) / 2) + 0.5);
699
700 if (xn < 0 || xn >= pn_image_data->width || yn < 0 || yn >= pn_image_data->height)
701 {
702 xn = i; yn = j;
703 }
704
705 xfvec (xn, yn, &d->vfield[PN_IMG_INDEX (i, j)]);
706 }
707
708 apply_xform (d->vfield);
709 pn_swap_surfaces ();
710 }
711
712 struct pn_actuator_desc builtin_xform_dynmovement =
713 {
714 "xform_dynmovement", "Dynamic Movement Transform",
715 "A customizable blitter.",
716 0, xform_dynmovement_opts,
717 xform_dynmovement_init, xform_dynmovement_cleanup, xform_dynmovement_exec
718 };