diff src/iris/theme_flash.c @ 116:a578bf9b2851 trunk

[svn] - iris vis plugin port
author nenolod
date Tue, 24 Oct 2006 21:25:31 -0700
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iris/theme_flash.c	Tue Oct 24 21:25:31 2006 -0700
@@ -0,0 +1,486 @@
+/*  Iris - visualization plugin for XMMS
+ *  Copyright (C) 2004 Marc Pompl (marc.pompl@lynorics.de)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <audacious/configdb.h>
+#include "iris.h"
+#include "particle.h"
+
+static GLuint texture[1];     /* Storage For Our Particle Texture                   */
+
+static gboolean flash_already_initialized = FALSE;
+
+static float flash_timer = 0; /* timer for flash */
+
+static struct
+{
+  gboolean flash_on_beat;
+  int flash_timer;
+  GLfloat speed;
+  GLfloat r1, r2, r3;
+  GLfloat m,n,o;
+  GLfloat f,g,h;
+  GLfloat t;
+}
+conf_private, conf_private_new;
+
+static config_theme conf = {
+  (config_global *) NULL,
+  &conf_private
+};
+
+static config_theme conf_new = {
+  (config_global *) NULL,
+  &conf_private_new
+};
+
+static char flash_flash_on_beat[] = "flashlight_flash_on_beat";
+static char flash_flash_timer[] = "flashlight_flash_timer";
+static char flash_speed[] = "flashlight_speed";
+
+static void config_read (ConfigDb *, char *);
+static void config_write (ConfigDb *, char *);
+static void config_default (void);
+static void config_create (GtkWidget *);
+static void init_draw_mode (void);
+static GLfloat get_x_angle (void);
+static void draw_one_frame (gboolean);
+
+iris_theme theme_flash = {
+  "Flash light",
+  "flash lights moving by a lissajou figure\n",
+  "Marc Pompl (marc.pompl@lynorics.de)",
+  "flashlight",
+  &conf,
+  &conf_new,
+  sizeof (conf_private),
+  config_read,
+  config_write,
+  config_default,
+  config_create,
+  NULL,
+  NULL,
+  init_draw_mode,
+  get_x_angle,
+  draw_one_frame
+};
+
+/* Create our particle structure */
+typedef struct
+{
+    GLint   active; /* Active (Yes/No) */
+    GLfloat life;   /* Particle Life   */
+    GLfloat fade;   /* Fade Speed      */
+
+    GLfloat r;      /* Red Value       */
+    GLfloat g;      /* Green Value     */
+    GLfloat b;      /* Blue Value      */
+
+    GLfloat fr;      /* Red Flash Value       */
+    GLfloat fg;      /* Green Flash Value     */
+    GLfloat fb;      /* Blue Flash Value      */
+
+    GLfloat x;      /* X Position      */
+    GLfloat y;      /* Y Position      */
+    GLfloat z;      /* Z Position      */
+
+    GLfloat xi;     /* X Direction     */
+    GLfloat yi;     /* Y Direction     */
+    GLfloat zi;     /* Z Direction     */
+
+    GLfloat xg;     /* X Gravity       */
+    GLfloat yg;     /* Y Gravity       */
+    GLfloat zg;     /* Z Gravity       */
+} particle;
+
+/* Rainbow of colors */
+static GLfloat flash_colors[16][3] =
+{
+  { 1.0f,  0.5f,  0.5f},
+	{ 1.0f,  0.75f, 0.5f},
+	{ 1.0f,  1.0f,  0.5f},
+
+	{ 0.75f, 1.0f,  0.5f},
+
+	{ 0.5f,  1.0f,  0.5f},
+	{ 0.5f,  1.0f,  0.75f},
+	{ 0.5f,  1.0f,  1.0f},
+
+	{ 0.5f,  0.75f, 1.0f},
+  { 0.5f,  0.5f,  1.0f},
+	{ 0.75f, 0.5f,  1.0f},
+
+	{ 1.0f,  0.5f,  1.0f},
+	{ 1.0f,  0.5f,  0.75f},
+	{ 0.75f, 0.5f,  0.75f},
+
+	{ 0.5f,  0.5f,  0.5f},
+	{ 0.75f, 0.75f, 0.75f},
+	{ 1.0f,  1.0f,  1.0f},
+};
+
+/* Our beloved array of particles */
+static particle particles[NUM_BANDS];
+
+void FlashColor( int num )
+{
+	GLfloat dr;
+	GLfloat dg;
+	GLfloat db;
+	dr = 1-particles[num].r;
+	dg = 1-particles[num].g;
+	db = 1-particles[num].b;
+	particles[num].fr = 1-dr*dr;
+	particles[num].fg = 1-dg*dg;
+	particles[num].fb = 1-db*db;
+}
+
+/* function to "load" a GL texture */
+void flash_loadTexture( )
+{
+	    /* Create The Texture */
+	    glGenTextures( 1, &texture[0] );
+
+	    /* Typical Texture Generation Using Data From The Bitmap */
+	    glBindTexture( GL_TEXTURE_2D, texture[0] );
+
+	    /* Generate The Texture */
+	    glTexImage2D( GL_TEXTURE_2D, 0, 3, particle_image.width,
+			  particle_image.height, 0, GL_RGBA,
+			  GL_UNSIGNED_BYTE, particle_image.pixel_data );
+
+	    /* Linear Filtering */
+	    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+	    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+}
+
+/* function to reset one particle to initial state */
+void ResetFlash( int num, GLfloat xDir, GLfloat yDir, GLfloat zDir )
+{
+    /* Make the particels active */
+    particles[num].active = TRUE;
+    /* Give the particles life */
+    particles[num].life = 1.0f;
+    /* Random Fade Speed */
+    particles[num].fade = ( GLfloat )( rand( ) *150 )/ (RAND_MAX + 1.0) / 1000.0f + 0.003f;
+    /* Select Red Rainbow Color */
+    particles[num].r = flash_colors[num][0];
+    /* Select Green Rainbow Color */
+    particles[num].g = flash_colors[num][1];
+    /* Select Blue Rainbow Color */
+    particles[num].b = flash_colors[num][2];
+    /* Set the position on the X axis */
+    particles[num].x = 0.0f;
+    /* Set the position on the Y axis */
+    particles[num].y = 0.0f;
+    /* Set the position on the Z axis */
+    particles[num].z = 0.0f;
+    /* Random Speed On X Axis */
+    particles[num].xi = xDir;
+    /* Random Speed On Y Axi */
+    particles[num].yi = yDir;
+    /* Random Speed On Z Axis */
+    particles[num].zi = zDir;
+    /* Set Horizontal Pull To Zero */
+    particles[num].xg = 0.0f;
+    /* Set Vertical Pull Downward */
+    particles[num].yg = -0.8f;
+    /* Set Pull On Z Axis To Zero */
+    particles[num].zg = 0.0f;
+		FlashColor(num);
+}
+
+static void initFlash ( int num, GLfloat value )
+{
+	GLfloat xi, yi, zi;
+	xi = num;
+	yi = 0;
+	zi = 0;
+	ResetFlash( num, xi, yi, zi );
+}
+
+static void
+init_draw_mode ()
+{
+	int loop;
+	conf.global->transparency = TRUE;
+	//conf.global->wireframe = FALSE;
+
+	flash_loadTexture();
+    /* Enable smooth shading */
+    glShadeModel( GL_SMOOTH );
+
+    /* Set the background black */
+    //glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
+
+    /* Depth buffer setup */
+    //glClearDepth( 1.0f );
+
+    /* Enables Depth Testing */
+    glDisable( GL_DEPTH_TEST );
+
+    /* Enable Blending */
+    glEnable( GL_BLEND );
+
+			glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+
+		/* Type Of Blending To Perform */
+    glBlendFunc( GL_SRC_ALPHA, GL_ONE );
+
+    /* Really Nice Perspective Calculations */
+    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
+    /* Really Nice Point Smoothing */
+    glHint( GL_POINT_SMOOTH_HINT, GL_NICEST );
+
+    /* Enable Texture Mapping */
+  glEnable( GL_TEXTURE_2D );
+    /* Select Our Texture */
+    glBindTexture( GL_TEXTURE_2D, texture[0] );
+		if (!flash_already_initialized)
+		{
+			for (loop=0; loop<NUM_BANDS; loop++)
+			{
+				initFlash(loop,0);
+			}
+			conf_private.f = 1;
+			conf_private.g = 1;
+			conf_private.h = 2;
+			conf_private.m = conf_private.n = conf_private.o = 0;
+			conf_private.t = 0.0f;
+		}
+		flash_already_initialized = TRUE;
+}
+
+
+static GLfloat
+get_x_angle ()
+{
+  return (15.0 + (int) (40.0 * rand () / (RAND_MAX + 1.0)));
+}
+
+static void
+draw_one_frame (gboolean beat)
+{
+	int loop;
+	if (beat)
+		flash_timer = conf_private.flash_timer;
+	conf_private.t += conf_private.speed;
+		/* Modify each of the particles */
+    for ( loop = 0; loop < NUM_BANDS; loop++ )
+	{
+		    GLfloat x;
+		    GLfloat y;
+		    GLfloat z;
+				/* compute the position by a lissajou */
+			GLfloat t1 = (GLfloat)((conf_private.t+loop)/2);
+			conf_private.r1 = (GLfloat)(cos(t1)*sin(t1-loop)*5.0f);
+			conf_private.r2 = (GLfloat)(sin(t1)*cos(t1)*5.0f);
+			conf_private.r3 = (GLfloat)(cos(t1+conf_private.t)*sin(t1+loop)*5.0f);
+			x = (conf_private.r1*cos(conf_private.m*t1+conf_private.f));
+			y = (conf_private.r2*sin(conf_private.n*t1+conf_private.g));
+			z = (conf_private.r3*sin(conf_private.o*t1+conf_private.h));
+
+	    if (particles[loop].active)
+		{
+				/* Draw The Particle Using Our RGB Values,
+		     * Fade The Particle Based On It's Life
+		     */
+				if ((conf_private.flash_on_beat) && (flash_timer>0))
+		    	glColor4f( particles[loop].fr,
+			       particles[loop].fg,
+			       particles[loop].fb,
+			       1.0f );
+				else
+				{
+		    	glColor4f( particles[loop].r,
+			       particles[loop].g,
+			       particles[loop].b,
+			       1.0f );
+				}
+
+				/* Build Quad From A Triangle Strip */
+		    glBegin( GL_TRIANGLE_STRIP );
+		      /* Top Right */
+		      glTexCoord2d( 1, 1 );
+		      glVertex3f( x + datas.data1[loop], y + datas.data1[loop], z );
+		      /* Top Left */
+		      glTexCoord2d( 0, 1 );
+		      glVertex3f( x - datas.data1[loop], y + datas.data1[loop], z );
+		      /* Bottom Right */
+		      glTexCoord2d( 1, 0 );
+		      glVertex3f( x + datas.data1[loop], y - datas.data1[loop], z );
+		      /* Bottom Left */
+		      glTexCoord2d( 0, 0 );
+		      glVertex3f( x - datas.data1[loop], y - datas.data1[loop], z );
+		    glEnd( );
+
+		    glBegin( GL_TRIANGLE_STRIP );
+		      /* Top Right */
+		      glTexCoord2d( 1, 1 );
+		      glVertex3f( x, y + datas.data1[loop], z+datas.data1[loop] );
+		      /* Top Left */
+		      glTexCoord2d( 0, 1 );
+		      glVertex3f( x, y + datas.data1[loop], z-datas.data1[loop] );
+		      /* Bottom Right */
+		      glTexCoord2d( 1, 0 );
+		      glVertex3f( x, y - datas.data1[loop], z+datas.data1[loop] );
+		      /* Bottom Left */
+		      glTexCoord2d( 0, 0 );
+		      glVertex3f( x, y - datas.data1[loop], z-datas.data1[loop] );
+		    glEnd( );
+
+		    glBegin( GL_TRIANGLE_STRIP );
+		      /* Top Right */
+		      glTexCoord2d( 1, 1 );
+		      glVertex3f( x+datas.data1[loop], y, z+datas.data1[loop] );
+		      /* Top Left */
+		      glTexCoord2d( 0, 1 );
+		      glVertex3f( x+datas.data1[loop], y, z-datas.data1[loop] );
+		      /* Bottom Right */
+		      glTexCoord2d( 1, 0 );
+		      glVertex3f( x-datas.data1[loop], y, z+datas.data1[loop] );
+		      /* Bottom Left */
+		      glTexCoord2d( 0, 0 );
+		      glVertex3f( x-datas.data1[loop], y, z-datas.data1[loop] );
+		    glEnd( );
+			}
+		}
+
+	if (flash_timer>0)
+		flash_timer --;
+}
+
+
+static void
+config_read (ConfigDb * db, char *section_name)
+{
+	config_default();
+  bmp_cfg_db_get_bool (db, section_name, flash_flash_on_beat, &conf_private.flash_on_beat);
+  bmp_cfg_db_get_int (db, section_name, flash_flash_timer, &conf_private.flash_timer);
+  bmp_cfg_db_get_float (db, section_name, flash_speed, &conf_private.speed);
+}
+
+
+static void
+config_write (ConfigDb * db, char *section_name)
+{
+  bmp_cfg_db_set_bool (db, section_name, flash_flash_on_beat, conf_private.flash_on_beat);
+  bmp_cfg_db_set_int (db, section_name, flash_flash_timer, conf_private.flash_timer);
+  bmp_cfg_db_set_float (db, section_name, flash_speed, conf_private.speed);
+}
+
+
+static void
+config_default ()
+{
+	conf_private.flash_on_beat = TRUE;
+	conf_private.flash_timer = 8;
+	conf_private.speed = 0.01f;
+}
+
+void
+flash_flash_toggled (GtkWidget * widget, gpointer data)
+{
+  conf_private_new.flash_on_beat = !conf_private_new.flash_on_beat;
+}
+
+static void
+flash_value_flash (GtkAdjustment * adj)
+{
+  conf_private_new.flash_timer = (int)adj->value;
+}
+
+static void
+value_speed (GtkAdjustment * adj)
+{
+  conf_private_new.speed = (GLfloat) (adj->value/1000);
+}
+
+static void
+config_create (GtkWidget * vbox)
+{
+    GtkWidget *hbox;
+  GtkWidget *button;
+  GtkWidget *label;
+  GtkObject *adjustment;
+  GtkWidget *hscale;
+
+  memcpy (&conf_private_new, &conf_private, sizeof (conf_private_new));
+
+/* flash on beat */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  button = gtk_check_button_new_with_label ("Flash on beats");
+  gtk_widget_show (button);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+				conf_private_new.flash_on_beat);
+  gtk_signal_connect (GTK_OBJECT (button), "toggled",
+		      GTK_SIGNAL_FUNC (flash_flash_toggled), NULL);
+
+  /* number of frame for the flash to propagate */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Flash propagation timer (in frames)");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.flash_timer, 1, 50, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (flash_value_flash), NULL);
+
+  /* speed */
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  label = gtk_label_new ("Speed");
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
+
+  adjustment =
+    gtk_adjustment_new (conf_private_new.speed*1000, 1, 100, 1, 5, 0);
+  hscale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+  gtk_scale_set_digits (GTK_SCALE (hscale), 0);
+  gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 25);
+  gtk_box_pack_start (GTK_BOX (hbox), hscale, FALSE, FALSE, 4);
+  gtk_widget_show (hscale);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+		      GTK_SIGNAL_FUNC (value_speed), NULL);
+}