]> Some of my projects - openlase-old.git/commitdiff
OpenGL-based laser simulator
authorHector Martin <hector@marcansoft.com>
Mon, 17 Jan 2011 16:58:29 +0000 (17:58 +0100)
committerHector Martin <hector@marcansoft.com>
Mon, 17 Jan 2011 16:58:29 +0000 (17:58 +0100)
tools/CMakeLists.txt
tools/simulator.c [new file with mode: 0644]

index b7327dccbf0decd47ca958e827c6c72aec477fb0..7643ab31890e64500e1a63b482326c4a0619c048 100644 (file)
@@ -1,6 +1,6 @@
 #         OpenLase - a realtime laser graphics toolkit
 #
-# Copyright (C) 2009-2010 Hector Martin "marcan" <hector@marcansoft.com>
+# Copyright (C) 2009-2011 Hector Martin "marcan" <hector@marcansoft.com>
 #
 # 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
@@ -24,3 +24,14 @@ target_link_libraries(playilda ${JACK_LIBRARIES})
 
 add_executable(playvid playvid.c trace.c)
 target_link_libraries(playvid openlase avformat avcodec)
+
+include_directories (${CMAKE_SOURCE_DIR}/include)
+link_directories (${CMAKE_BINARY_DIR}/libol)
+
+find_package(OpenGL REQUIRED)
+find_package(GLUT REQUIRED)
+
+add_executable(simulator simulator.c)
+
+include_directories(${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS})
+target_link_libraries(simulator ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${JACK_LIBRARIES})
diff --git a/tools/simulator.c b/tools/simulator.c
new file mode 100644 (file)
index 0000000..e655dbf
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+        OpenLase - a realtime laser graphics toolkit
+
+Copyright (C) 2009-2011 Hector Martin "marcan" <hector@marcansoft.com>
+
+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 or version 3.
+
+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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <jack/jack.h>
+
+#include <GL/glut.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+int window;
+
+jack_client_t *client;
+
+typedef jack_default_audio_sample_t sample_t;
+typedef jack_nframes_t nframes_t;
+
+jack_port_t *in_x;
+jack_port_t *in_y;
+jack_port_t *in_g;
+
+nframes_t rate;
+
+#define HIST_SAMPLES (48 * 50)
+#define BUF_SAMPLES (HIST_SAMPLES+48000)
+
+typedef struct {
+       float x, y, g;
+} bufsample_t;
+
+bufsample_t buffer[BUF_SAMPLES];
+
+int buf_widx = 0;
+
+static int process (nframes_t nframes, void *arg)
+{
+       sample_t *i_x = (sample_t *) jack_port_get_buffer (in_x, nframes);
+       sample_t *i_y = (sample_t *) jack_port_get_buffer (in_y, nframes);
+       sample_t *i_g = (sample_t *) jack_port_get_buffer (in_g, nframes);
+
+       nframes_t frm;
+       for (frm = 0; frm < nframes; frm++) {
+               buffer[buf_widx].x = *i_x++;
+               buffer[buf_widx].y = *i_y++;
+               buffer[buf_widx].g = *i_g++;
+
+               buf_widx++;
+               if (buf_widx >= BUF_SAMPLES)
+                       buf_widx = 0;
+       }
+
+       return 0;
+}
+
+static int bufsize (nframes_t nframes, void *arg)
+{
+       printf ("the maximum buffer size is now %u\n", nframes);
+       return 0;
+}
+
+static int srate (nframes_t nframes, void *arg)
+{
+       rate = nframes;
+       if(rate % 1000) {
+               printf("error: the sample rate should be a multiple of 1000\n");
+               exit(1);
+       }
+       printf ("Sample rate: %u/sec\n", nframes);
+       return 0;
+}
+
+static void jack_shutdown (void *arg)
+{
+       exit (1);
+}
+
+static inline void laser_color(float g, float ascale)
+{
+       float r, b;
+       r = b = 0;
+       if (g < 0)
+               g = 0;
+       if (g > 2.0)
+               g = 2.0;
+       if (g > 1.0) {
+               r = b = g - 1.0;
+               g = 1.0;
+       }
+       glColor4f(r, 1, b, g*ascale);
+}
+
+void draw_gl(void)
+{
+       int i, ridx;
+
+       static int fno=0;
+       fno++;
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+       glLoadIdentity();
+       glLineWidth(2);
+       glPointSize(2);
+
+       // horrid workaround for recordmydesktop/libtheora brokenness
+#if 0
+       glBegin(GL_POINTS);
+       glColor4f((fno&1) * (64/256.0), (fno&2) * (32/256.0), (fno&4)  * (16/256.0), 1);
+       //glColor4f(1,1,1,1);
+       glVertex3f(-0.99, -0.74, 0);
+       glVertex3f(0.99, 0.74, 0);
+       glVertex3f(-0.99, 0.74, 0);
+       glVertex3f(0.99, -0.74, 0);
+       glEnd();
+#endif
+
+       ridx = (buf_widx - HIST_SAMPLES + BUF_SAMPLES) % BUF_SAMPLES;
+
+       float lx, ly, lg;
+       lx = ly = lg = 0;
+
+       float gdelay[2] = {0,0};
+
+       for (i = 0; i<HIST_SAMPLES; i++)
+       {
+               float g;
+
+               bufsample_t s = buffer[ridx];
+               // lowpass
+               s.x = lx * 0.65 + s.x * 0.35;
+               s.y = ly * 0.65 + s.y * 0.35;
+               // delay brightness
+               gdelay[i%2] = s.g;
+               s.g = gdelay[(i+1)%2];
+
+               float d = sqrtf((s.x-lx)*(s.x-lx) + (s.y-ly)*(s.y-ly));
+               if (d == 0)
+                       d = 0.0001;
+               float dfactor = 0.01/d;
+               if (dfactor > 1.5)
+                       dfactor = 1.5;
+
+               int age = HIST_SAMPLES-i;
+               float factor;
+
+               factor = (HIST_SAMPLES-age)/(float)HIST_SAMPLES;
+
+               factor = factor*factor;
+
+               if (fabsf(s.x-lx) < 0.001 && fabsf(s.y-ly) < 0.001) {
+                       g = (s.g-0.2) * factor * 1.4;
+                       glBegin(GL_POINTS);
+                       laser_color(g, 0.08);
+                       glVertex3f(s.x, s.y, 0);
+                       glEnd();
+               } else {
+                       g = (s.g-0.2) * factor * dfactor * 1.8;
+                       glBegin(GL_LINES);
+                       laser_color(lg, 0.8);
+                       glVertex3f(lx, ly, 0);
+                       laser_color(g, 0.8);
+                       glVertex3f(s.x, s.y, 0);
+                       glEnd();
+               }
+
+               lx = s.x;
+               ly = s.y;
+               lg = g;
+
+               ridx++;
+               if (ridx >= BUF_SAMPLES)
+                       ridx = 0;
+       }
+       glEnd();
+       glutSwapBuffers();
+}
+
+void key_gl(unsigned char key, int x, int y)
+{
+       if (key == 27) {
+               jack_client_close (client);
+               glutDestroyWindow(window);
+               exit(0);
+       }
+}
+
+void resize_gl(int width, int height)
+{
+       int min = width > height ? height : width;
+       glViewport((width-min)/2, (height-min)/2, min, min);
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+       glOrtho (-1, 1, -1, 1, -1, 1);
+       glMatrixMode(GL_MODELVIEW);
+}
+
+void init_gl(int width, int height)
+{
+       glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+       glClearDepth(1.0);
+       glDepthFunc(GL_LESS);
+       glDisable(GL_DEPTH_TEST);
+       glEnable(GL_BLEND);
+       glBlendFunc (GL_SRC_ALPHA, GL_ONE);
+       glEnable(GL_POINT_SMOOTH);
+       glEnable(GL_LINE_SMOOTH);
+       resize_gl(width, height);
+}
+
+int main (int argc, char *argv[])
+{
+       if ((client = jack_client_new ("simulator")) == 0) {
+               fprintf (stderr, "jack server not running?\n");
+               return 1;
+       }
+
+       jack_set_process_callback (client, process, 0);
+       jack_set_buffer_size_callback (client, bufsize, 0);
+       jack_set_sample_rate_callback (client, srate, 0);
+       jack_on_shutdown (client, jack_shutdown, 0);
+
+       in_x = jack_port_register (client, "in_x", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+       in_y = jack_port_register (client, "in_y", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+       in_g = jack_port_register (client, "in_g", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+
+       glutInit(&argc, argv);
+
+       glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
+       glutInitWindowSize(640, 640);
+       glutInitWindowPosition(0, 0);
+
+       window = glutCreateWindow("OpenLase Simulator");
+
+       glutDisplayFunc(&draw_gl);
+       glutIdleFunc(&draw_gl);
+       glutReshapeFunc(&resize_gl);
+       glutKeyboardFunc(&key_gl);
+       init_gl(640, 640);
+
+       if (jack_activate (client)) {
+               fprintf (stderr, "cannot activate client");
+               return 1;
+       }
+
+       glutMainLoop();
+       return 0;
+}
+