diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index b7327dc..7643ab3 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,6 +1,6 @@ # OpenLase - a realtime laser graphics toolkit # -# Copyright (C) 2009-2010 Hector Martin "marcan" +# Copyright (C) 2009-2011 Hector Martin "marcan" # # 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 index 0000000..e655dbf --- /dev/null +++ b/tools/simulator.c @@ -0,0 +1,267 @@ +/* + OpenLase - a realtime laser graphics toolkit + +Copyright (C) 2009-2011 Hector Martin "marcan" + +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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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 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; +} +