]> Some of my projects - openlase-old.git/commitdiff
Add the 27C3 slides (with cleaned up versions of several of the effects)
authorHector Martin <hector@marcansoft.com>
Sun, 2 Jan 2011 06:02:05 +0000 (07:02 +0100)
committerHector Martin <hector@marcansoft.com>
Sun, 2 Jan 2011 06:16:46 +0000 (07:16 +0100)
21 files changed:
examples/27c3_slides/27c3-logo.cfg [new file with mode: 0644]
examples/27c3_slides/27c3-logo.svg [new file with mode: 0644]
examples/27c3_slides/3ddemos.c [new file with mode: 0644]
examples/27c3_slides/CMakeLists.txt [new file with mode: 0644]
examples/27c3_slides/avstream.c [new file with mode: 0644]
examples/27c3_slides/avstream.h [new file with mode: 0644]
examples/27c3_slides/circlescope.c [new file with mode: 0644]
examples/27c3_slides/jack-logo.cfg [new file with mode: 0644]
examples/27c3_slides/jack-logo.svg [new file with mode: 0644]
examples/27c3_slides/main.c [new file with mode: 0644]
examples/27c3_slides/metaballs.c [new file with mode: 0644]
examples/27c3_slides/openlase-logo.cfg [new file with mode: 0644]
examples/27c3_slides/openlase-logo.svg [new file with mode: 0644]
examples/27c3_slides/output.cfg [new file with mode: 0644]
examples/27c3_slides/output.svg [new file with mode: 0644]
examples/27c3_slides/pong.c [new file with mode: 0644]
examples/27c3_slides/slow.cfg [new file with mode: 0644]
examples/27c3_slides/static.c [new file with mode: 0644]
examples/27c3_slides/video.c [new file with mode: 0644]
examples/27c3_slides/video.h [new file with mode: 0644]
examples/CMakeLists.txt

diff --git a/examples/27c3_slides/27c3-logo.cfg b/examples/27c3_slides/27c3-logo.cfg
new file mode 100644 (file)
index 0000000..38761de
--- /dev/null
@@ -0,0 +1,12 @@
+on_speed = 2/100.0
+off_speed = 2/25.0
+flatness = 0.000001
+start_dwell = 4
+curve_dwell = 0
+corner_dwell = 5
+end_dwell = 4
+switch_dwell = 6
+closed_overdraw = 3
+closed_start_dwell = 3
+closed_end_dwell = 3
+extra_first_dwell = 0
diff --git a/examples/27c3_slides/27c3-logo.svg b/examples/27c3_slides/27c3-logo.svg
new file mode 100644 (file)
index 0000000..68c19e2
--- /dev/null
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48+devel r"
+   width="215"
+   height="155"
+   sodipodi:docname="27c3-logo.svg">
+  <metadata
+     id="metadata8">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs6" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1912"
+     inkscape:window-height="1005"
+     id="namedview4"
+     showgrid="true"
+     inkscape:snap-global="true"
+     inkscape:zoom="2.9126781"
+     inkscape:cx="146.35732"
+     inkscape:cy="96.241399"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3071"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <path
+     style="color:#000000;fill:none;stroke:#00ff00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+     d="m 110,75 -50,0 0,-45 25,0 0,-5 -25,0 0,-20 45,0 0,25 30,0 0,-5 -25,0 0,-20 45,0 0,70 -20,0 0,-25 -55,0 0,5 50,0 0,25 25,0 0,70 -95,0 0,-70 45,0 0,45 -20,0 0,-25 -5,0 0,30 55,0 0,-5 -25,0 0,-20 25,0 0,-5 -25,0 z"
+     id="path3158"
+     inkscape:connector-curvature="0" />
+</svg>
diff --git a/examples/27c3_slides/3ddemos.c b/examples/27c3_slides/3ddemos.c
new file mode 100644 (file)
index 0000000..2c464c9
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+        OpenLase - a realtime laser graphics toolkit
+
+Copyright (C) 2009-2010 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 "libol.h"
+#include "ilda.h"
+#include "text.h"
+#include <math.h>
+#include <stdio.h>
+
+/* cubes demo */
+
+void cubes_init(void **ctx, void *arg, OLRenderParams *params)
+{
+}
+
+void cubes_deinit(void *ctx)
+{
+}
+
+void cubes_render(void *ctx, float time)
+{
+       int i;
+
+       olLoadIdentity3();
+       olLoadIdentity();
+       olPerspective(60, 1, 1, 100);
+       olTranslate3(0, 0, -3);
+
+       for(i=0; i<2; i++) {
+               olScale3(0.6, 0.6, 0.6);
+
+               olRotate3Z(time * M_PI * 0.1);
+               olRotate3Y(time * M_PI * 0.8);
+               olRotate3X(time * M_PI * 0.73);
+
+               olBegin(OL_LINESTRIP);
+               olVertex3(-1, -1, -1, C_WHITE);
+               olVertex3( 1, -1, -1, C_WHITE);
+               olVertex3( 1,  1, -1, C_WHITE);
+               olVertex3(-1,  1, -1, C_WHITE);
+               olVertex3(-1, -1, -1, C_WHITE);
+               olVertex3(-1, -1,  1, C_WHITE);
+               olEnd();
+
+               olBegin(OL_LINESTRIP);
+               olVertex3( 1,  1,  1, C_WHITE);
+               olVertex3(-1,  1,  1, C_WHITE);
+               olVertex3(-1, -1,  1, C_WHITE);
+               olVertex3( 1, -1,  1, C_WHITE);
+               olVertex3( 1,  1,  1, C_WHITE);
+               olVertex3( 1,  1, -1, C_WHITE);
+               olEnd();
+
+               olBegin(OL_LINESTRIP);
+               olVertex3( 1, -1, -1, C_WHITE);
+               olVertex3( 1, -1,  1, C_WHITE);
+               olEnd();
+
+               olBegin(OL_LINESTRIP);
+               olVertex3(-1,  1,  1, C_WHITE);
+               olVertex3(-1,  1, -1, C_WHITE);
+               olEnd();
+       }
+}
+
+/* laser scanner diagram thing */
+/* yes this is ugly stuff */
+
+static int points_left = 0;
+static int point_step = 1;
+static int delay = 0;
+static int delay_ctr = 0;
+static int include_dark_points = 0;
+
+static void cutoff(float *x, float *y, uint32_t *color)
+{
+       static float save_x, save_y;
+       static uint32_t save_color;
+       static int points_dot = 0;
+       if ((!include_dark_points) && (*color == C_BLACK)) {
+               if (points_left)
+                       return;
+               *x = save_x;
+               *y = save_y;
+       }
+       if ((points_left-delay) > 0) {
+               points_left -= point_step;
+               save_x = *x;
+               save_y = *y;
+               save_color = *color;
+               points_dot = 200;
+       } else {
+               if (points_left > delay_ctr && points_left < delay && (delay - points_left) > 20)
+                       points_dot = 0;
+               *x = save_x;
+               *y = save_y;
+               if (points_dot) {
+                       *color = C_WHITE;
+                       points_dot--;
+               } else {
+                       *color = C_BLACK;
+               }
+       }
+       if (delay > delay_ctr)
+               delay_ctr += point_step;
+}
+
+void diag_init(void **ctx, void *arg, OLRenderParams *params)
+{
+       *ctx = olLoadIlda("27c3-logo.ild");
+       if (!*ctx)
+               olLog("Failed to load 27c3-logo.ild\n");
+
+       params->off_speed = 2.0/25.0;
+       params->start_wait = 15;
+}
+
+void diag_deinit(void *ctx)
+{
+       if (ctx)
+               olFreeIlda(ctx);
+}
+
+static void draw_galvo(void)
+{
+       point_step = 10;
+
+       olBegin(OL_LINESTRIP);
+       olVertex3(-5, -10, -5, C_WHITE);
+       olVertex3(-5, 10, -5, C_WHITE);
+       olVertex3(5, 10, 5, C_WHITE);
+       olVertex3(5, -10, 5, C_WHITE);
+       olVertex3(-5, -10, -5, C_WHITE);
+       olEnd();
+
+       olBegin(OL_LINESTRIP);
+       olVertex3(2, -10, 2, C_WHITE);
+       olVertex3(2, -20, 0, C_WHITE);
+       olEnd();
+       olBegin(OL_LINESTRIP);
+       olVertex3(-2, -10, -2, C_WHITE);
+       olVertex3(-2, -20, 0, C_WHITE);
+       olEnd();
+       olBegin(OL_LINESTRIP);
+       olVertex3(-9, -50, 0, C_WHITE);
+       olVertex3(-9, -20, 0, C_WHITE);
+       olVertex3(9, -20, 0, C_WHITE);
+       olVertex3(9, -50, 0, C_WHITE);
+       olEnd();
+       olBegin(OL_LINESTRIP);
+       olVertex3(-20, -50, 0, C_WHITE);
+       olVertex3(-20, -70, 0, C_WHITE);
+       olVertex3(20, -70, 0, C_WHITE);
+       olVertex3(20, -50, 0, C_WHITE);
+       olVertex3(-20, -50, 0, C_WHITE);
+       olEnd();
+
+       point_step = 4;
+       olDrawString(olGetDefaultFont(), -15, -55, 14, C_WHITE, "Galvo");
+
+}
+
+typedef struct {
+       float time;
+       float x, y, z;
+       float rx, ry, rz;
+} campt;
+
+static campt campoints[] = {
+       {0, -140, 0, -120, 0, 0, 0},
+       {3.0, -140, 0, -120, 0, 0, 0},
+       {4.5, -100, 0, 0, 0, 0, 0},
+       {6.5, 10, -20, -70, 0, 0, 0},
+       {13, 10, -20, -70, 0, 0, 0},
+       {16, 50, 50, 10, -M_PI/2, 0, -0.5},
+       {17, 0, 140, 0, -M_PI/2, 0, 0},
+       {18, 0, 310, 0, -M_PI/2, 0, 0},
+};
+
+#define LOGO_START 14
+#define FADE_START 16
+#define FADE_END 17
+
+#define NUM_CAMPOINTS (sizeof(campoints)/sizeof(campoints[0]))
+
+void diag_render(void *ctx, float time)
+{
+       int i;
+
+       delay = 0;
+       delay_ctr = 0;
+
+       //time += 10;
+
+       //time -= 1;
+       if (time < 0)
+               time = 0;
+
+       int spl = time * 1000;
+       points_left = spl;
+
+       int maincolor = 255;
+       if (time > FADE_START)
+               maincolor = (FADE_END - time) * 255;
+
+       olSetPixelShader(NULL);
+       olLoadIdentity3();
+       olLoadIdentity();
+
+       point_step = 10;
+
+       olFrustum(-1, 1, -1, 1, 3, 100);
+       olTranslate3(0, 0, -3);
+       olScale3(0.01, 0.01, 0.01);
+
+       campt *p = &campoints[0];
+
+       for (i=0; i<NUM_CAMPOINTS; i++) {
+               if (campoints[i].time > time)
+                       break;
+               p = &campoints[i];
+       }
+
+       campt dest;
+
+       dest = *p;
+
+       if (i == NUM_CAMPOINTS) {
+               dest = *p;
+       } else {
+               float subpos = (time - p[0].time) / (p[1].time - p[0].time);
+               subpos = (sinf((subpos - 0.5) * M_PI) + 1)/2;
+               olLog("Subpos: %f\n", subpos);
+               dest.x = p[0].x * (1-subpos) + p[1].x * subpos;
+               dest.y = p[0].y * (1-subpos) + p[1].y * subpos;
+               dest.z = p[0].z * (1-subpos) + p[1].z * subpos;
+               dest.rx = p[0].rx * (1-subpos) + p[1].rx * subpos;
+               dest.ry = p[0].ry * (1-subpos) + p[1].ry * subpos;
+               dest.rz = p[0].rz * (1-subpos) + p[1].rz * subpos;
+       }
+
+       olLog("Camera @ %f: %f %f %f %f %f %f\n", time, dest.x, dest.y, dest.z, dest.rx, dest.ry, dest.rz);
+
+       olRotate3X(dest.rx);
+       olRotate3Y(dest.ry);
+       olRotate3Z(dest.rz);
+       olTranslate3(-dest.x, -dest.y, -dest.z);
+
+       int logo_points = (time - LOGO_START) * 200;
+       if (logo_points < 0)
+               logo_points = 0;
+
+       IldaFile *ild = ctx;
+       int logo_idx = logo_points;
+       if (logo_idx >= ild->count)
+               logo_idx = ild->count - 1;
+
+       if (time < FADE_END) {
+               olPushColor();
+               olMultColor(C_GREY(maincolor < 0 ? 0 : maincolor));
+               olSetPixelShader(cutoff);
+
+               olBegin(OL_LINESTRIP);
+               olVertex3(-150, 10, 0, C_WHITE);
+               olVertex3(-190, 10, 0, C_WHITE);
+               olVertex3(-190, -10, 0, C_WHITE);
+               olVertex3(-150, -10, 0, C_WHITE);
+               olVertex3(-150, 10, 0, C_WHITE);
+               olEnd();
+               olBegin(OL_LINESTRIP);
+               olVertex3(-150, 7, 0, C_WHITE);
+               olVertex3(-140, 7, 0, C_WHITE);
+               olVertex3(-140, -7, 0, C_WHITE);
+               olVertex3(-150, -7, 0, C_WHITE);
+               olEnd();
+
+               point_step = 4;
+
+               olDrawString(olGetDefaultFont(), -185, 6, 14, C_WHITE, "Laser");
+
+               point_step = 20;
+               delay += 1000;
+
+               float px = 50 * ild->points[logo_idx].x;
+               float py = 50 * ild->points[logo_idx].y;
+
+               olBegin(OL_LINESTRIP);
+               olVertex3(-140, 0, 0, C_WHITE);
+               olVertex3(0, 0, 0, C_WHITE);
+               olVertex3(px / 20, 0, 15, C_WHITE);
+               olVertex3(px, 140, py, C_WHITE);
+               olEnd();
+
+               draw_galvo();
+               olPushMatrix3();
+               olTranslate3(0, 0, 15);
+               olRotate3Z(M_PI/2);
+               delay += 200;
+               draw_galvo();
+               olPopMatrix3();
+
+               delay += 1000;
+
+               point_step = 20;
+
+               olPopColor();
+
+       }
+
+       olSetPixelShader(NULL);
+       point_step = 10;
+       olBegin(OL_LINESTRIP);
+       olVertex3(-50, 140, 37.5, C_WHITE);
+       olVertex3(50, 140, 37.5, C_WHITE);
+       olVertex3(50, 140, -37.5, C_WHITE);
+       olVertex3(-50, 140, -37.5, C_WHITE);
+       olVertex3(-50, 140, 37.5, C_WHITE);
+       olEnd();
+
+       olTranslate3(0, 140, 0);
+       olScale3(50, 50, 50);
+       olRotate3X(M_PI/2);
+
+       if (logo_points > 0) {
+               delay = delay_ctr = 0;
+               points_left = logo_points;
+               point_step = 1;
+               olSetPixelShader(cutoff);
+               olDrawIlda3D(ctx);
+       }
+       olSetPixelShader(NULL);
+}
+
+
diff --git a/examples/27c3_slides/CMakeLists.txt b/examples/27c3_slides/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1960214
--- /dev/null
@@ -0,0 +1,30 @@
+
+
+find_package(Curses REQUIRED)
+
+include_directories(${CMAKE_SOURCE_DIR}/tools ${CURSES_INCLUDE_DIR})
+
+add_executable(slides
+       main.c 3ddemos.c static.c metaballs.c circlescope.c avstream.c video.c pong.c
+       ${CMAKE_SOURCE_DIR}/tools/trace.c
+
+       ${CMAKE_CURRENT_BINARY_DIR}/openlase-logo.ild
+       ${CMAKE_CURRENT_BINARY_DIR}/27c3-logo.ild
+       ${CMAKE_CURRENT_BINARY_DIR}/jack-logo.ild
+       ${CMAKE_CURRENT_BINARY_DIR}/output.ild
+)
+
+target_link_libraries(slides openlase avformat avcodec ${CURSES_LIBRARIES})
+
+function(svg2ild NAME)
+       add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.ild
+           DEPENDS ${CMAKE_SOURCE_DIR}/tools/svg2ild.py
+           MAIN_DEPENDENCY ${NAME}.svg
+           DEPENDS ${NAME}.svg ${NAME}.cfg
+           COMMAND python ${CMAKE_SOURCE_DIR}/tools/svg2ild.py -q ${ARGN} -cfg ${CMAKE_CURRENT_SOURCE_DIR}/${NAME}.cfg ${CMAKE_CURRENT_SOURCE_DIR}/${NAME}.svg ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.ild)
+endfunction()
+
+svg2ild(openlase-logo -noopt)
+svg2ild(27c3-logo)
+svg2ild(jack-logo)
+svg2ild(output)
diff --git a/examples/27c3_slides/avstream.c b/examples/27c3_slides/avstream.c
new file mode 100644 (file)
index 0000000..399b33f
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+        OpenLase - a realtime laser graphics toolkit
+
+Copyright (C) 2009-2010 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
+*/
+
+/* Simple wrapper around libavcodec to provide audio/video streams */
+
+static int inited = 0;
+
+#include "libol.h"
+#include "avstream.h"
+
+#define AUDIO_BUF AVCODEC_MAX_AUDIO_FRAME_SIZE
+
+static void dolog(void *foo, int level, const char *fmt, va_list ap)
+{
+       char buf[1024];
+       vsnprintf(buf, 1024, fmt, ap);
+       buf[1023] = 0;
+       olLog("%s", buf);
+}
+
+static void avstream_init(void)
+{
+       av_log_set_callback(dolog);
+       av_register_all();
+       inited = 1;
+}
+
+int video_readframe(VContext *ctx, AVFrame **oFrame)
+{
+       static AVPacket packet;
+       int bytesDecoded;
+       int frameFinished = 0;
+
+       while (!frameFinished) {
+               do {
+                       if(av_read_frame(ctx->av.formatctx, &packet)<0) {
+                               *oFrame = ctx->frame;
+                               return 0;
+                       }
+               } while(packet.stream_index!=ctx->av.stream);
+
+               bytesDecoded=avcodec_decode_video2(ctx->av.codecctx, ctx->frame, &frameFinished, &packet);
+               if (bytesDecoded < 0)
+               {
+                       olLog("Error while decoding video frame\n");
+                       *oFrame = ctx->frame;
+                       return 0;
+               }
+               if (bytesDecoded != packet.size) {
+                       olLog("Multiframe packets not supported (%d != %d)\n", bytesDecoded, packet.size);
+                       exit(1);
+               }
+       }
+       *oFrame = ctx->frame;
+       return 1;
+}
+
+int audio_readsamples(AContext *ctx, float *lb, float *rb, int samples)
+{
+       AVPacket packet;
+       int bytes, bytesDecoded;
+       int input_samples;
+       int total = 0;
+       while (samples)
+       {
+               if (!ctx->buffered_samples) {
+                       do {
+                               if(av_read_frame(ctx->av.formatctx, &packet)<0) {
+                                       memset(lb, 0, samples*sizeof(float));
+                                       memset(rb, 0, samples*sizeof(float));
+                                       return total;
+                               }
+                       } while(packet.stream_index!=ctx->av.stream);
+
+                       bytes = AUDIO_BUF * sizeof(short);
+
+                       bytesDecoded = avcodec_decode_audio3(ctx->av.codecctx, ctx->iabuf, &bytes, &packet);
+                       if(bytesDecoded < 0)
+                       {
+                               olLog("Error while decoding audio frame\n");
+                               memset(lb, 0, samples*sizeof(float));
+                               memset(rb, 0, samples*sizeof(float));
+                               return -1;
+                       }
+
+                       input_samples = bytes / (sizeof(short)*ctx->av.codecctx->channels);
+
+                       ctx->buffered_samples = audio_resample(ctx->resampler, (void*)ctx->oabuf, ctx->iabuf, input_samples);
+                       ctx->poabuf = ctx->oabuf;
+               }
+
+               *lb++ = *ctx->poabuf++;
+               *rb++ = *ctx->poabuf++;
+               ctx->buffered_samples--;
+               samples--;
+               total++;
+       }
+       return total;
+}
+
+int video_open(VContext **octx, char *file)
+{
+       int i;
+       VContext *ctx;
+
+       if (!inited)
+               avstream_init();
+       
+       ctx = malloc(sizeof(VContext));
+
+       if (av_open_input_file(&ctx->av.formatctx, file, NULL, 0, NULL) != 0)
+               goto error;
+
+       if (av_find_stream_info(ctx->av.formatctx) < 0)
+               goto error;
+
+       dump_format(ctx->av.formatctx, 0, file, 0);
+
+       int stream=-1;
+       for (i=0; i<ctx->av.formatctx->nb_streams; i++) {
+               if (ctx->av.formatctx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {
+                       stream=i;
+                       break;
+               }
+       }
+       if (stream==-1)
+               goto error;
+
+       ctx->av.stream = stream;
+       ctx->av.codecctx = ctx->av.formatctx->streams[stream]->codec;
+       ctx->av.codec = avcodec_find_decoder(ctx->av.codecctx->codec_id);
+
+       if (ctx->av.codec == NULL)
+               goto error;
+
+       if (avcodec_open(ctx->av.codecctx, ctx->av.codec) < 0)
+               goto error;
+
+       ctx->frame = avcodec_alloc_frame();
+
+       *octx = ctx;
+       return 0;
+
+error:
+       // todo: cleanup avcodec stuff...
+       free(ctx);
+       *octx = NULL;
+       return -1;
+}
+
+int video_close(VContext *ctx)
+{
+       av_free(ctx->frame);
+       avcodec_close(ctx->av.codecctx);
+       av_close_input_file(ctx->av.formatctx);
+       free(ctx);
+
+       return 0;
+}
+
+int audio_open(AContext **octx, char *file)
+{
+       int i;
+       AContext *ctx;
+
+       if (!inited)
+               avstream_init();
+
+       ctx = malloc(sizeof(AContext));
+       memset(ctx, 0, sizeof(*ctx));
+       ctx->oabuf = malloc(AUDIO_BUF * sizeof(float));
+       ctx->iabuf = malloc(AUDIO_BUF * sizeof(short));
+
+       if (av_open_input_file(&ctx->av.formatctx, file, NULL, 0, NULL) != 0)
+               goto error;
+
+       if (av_find_stream_info(ctx->av.formatctx) < 0)
+               goto error;
+
+       dump_format(ctx->av.formatctx, 0, file, 0);
+
+       int stream=-1;
+       for (i=0; i<ctx->av.formatctx->nb_streams; i++) {
+               if (ctx->av.formatctx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) {
+                       stream=i;
+                       break;
+               }
+       }
+       if (stream==-1)
+               goto error;
+
+       ctx->av.stream = stream;
+       ctx->av.codecctx = ctx->av.formatctx->streams[stream]->codec;
+       ctx->av.codec = avcodec_find_decoder(ctx->av.codecctx->codec_id);
+
+       if (ctx->av.codec == NULL)
+               goto error;
+
+       if (avcodec_open(ctx->av.codecctx, ctx->av.codec) < 0)
+               goto error;
+
+       ctx->resampler = av_audio_resample_init(2, ctx->av.codecctx->channels,
+                                                                                  48000, ctx->av.codecctx->sample_rate,
+                                                                                  SAMPLE_FMT_FLT, ctx->av.codecctx->sample_fmt,
+                                                                                  16, 10, 0, 0.8);
+
+       if (!ctx->resampler)
+               goto error;
+
+       ctx->buffered_samples = 0;
+
+       *octx = ctx;
+       return 0;
+error:
+       if (ctx->oabuf)
+               free(ctx->oabuf);
+       if (ctx->iabuf)
+               free(ctx->iabuf);
+       // todo: cleanup avcodec stuff...
+       free(ctx);
+       *octx = NULL;
+       return -1;
+}
+
+int audio_close(AContext *ctx)
+{
+       avcodec_close(ctx->av.codecctx);
+       audio_resample_close(ctx->resampler);
+       av_close_input_file(ctx->av.formatctx);
+       free(ctx->oabuf);
+       free(ctx->iabuf);
+       free(ctx);
+       return 0;
+}
diff --git a/examples/27c3_slides/avstream.h b/examples/27c3_slides/avstream.h
new file mode 100644 (file)
index 0000000..1ad43bc
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+        OpenLase - a realtime laser graphics toolkit
+
+Copyright (C) 2009-2010 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
+*/
+
+#ifndef AVSTREAM_H
+#define AVSTREAM_H
+
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+
+struct avfctx {
+       AVFormatContext *formatctx;
+       AVCodecContext *codecctx;
+       AVCodec *codec;
+       int stream;
+};
+
+struct _acontext {
+       struct avfctx av;
+       ReSampleContext *resampler;
+       float *oabuf;
+       short *iabuf;
+       int buffered_samples;
+       float *poabuf;
+};
+
+struct _vcontext {
+       struct avfctx av;
+       AVFrame *frame;
+};
+
+typedef struct _acontext AContext;
+typedef struct _vcontext VContext;
+
+int video_open(VContext **ctx, char *file);
+int video_readframe(VContext *ctx, AVFrame **oFrame);
+int video_close(VContext *ctx);
+
+int audio_open(AContext **ctx, char *file);
+int audio_readsamples(AContext *ctx, float *lb, float *rb, int samples);
+int audio_close(AContext *ctx);
+
+#endif
\ No newline at end of file
diff --git a/examples/27c3_slides/circlescope.c b/examples/27c3_slides/circlescope.c
new file mode 100644 (file)
index 0000000..01da89a
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+        OpenLase - a realtime laser graphics toolkit
+
+Copyright (C) 2009-2010 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 "libol.h"
+#include "ilda.h"
+#include "text.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avstream.h"
+
+/* This is a libol version of the circlescope, rendering audio from a file.
+ * Instead of taking audio from JACK, this uses the avstream.h stuff. Since this
+ * is based on libol, the audio and video are no longer sample-synchronous
+ * (as the image is just one object in the frame) so we drop/dupe samples as
+ * needed */
+
+static AContext *actx;
+static int got_samples = 0;
+static uint64_t sample_counter;
+
+#define DRAW_SAMPLES 1024
+
+static float lbuf[DRAW_SAMPLES];
+static float rbuf[DRAW_SAMPLES];
+
+static float volume = 0.8;
+
+void circlescope_init(void **ctx, void *arg, OLRenderParams *params)
+{
+       if (audio_open(&actx, arg) != 0) {
+               olLog("Audio open/init failed\n");
+               exit(1);
+       }
+
+       got_samples = 0;
+       sample_counter = 0;
+}
+
+void circlescope_deinit(void *ctx)
+{
+       audio_close(actx);
+       olSetAudioCallback(NULL);
+}
+
+static void moreaudio(float *lb, float *rb, int samples)
+{
+       int left = samples;
+       float *plb = lb, *prb = rb;
+
+       memset(lb, 0, sizeof(float)*samples);
+       memset(rb, 0, sizeof(float)*samples);
+
+       //audio_readleft(actx, lb, rb, left);
+       if (got_samples == 0) {
+               olLog("No audio buffer?\n");
+               return;
+       }
+
+
+       int copy = samples > got_samples ? got_samples : samples;
+
+       memcpy(lb, lbuf, copy * sizeof(float));
+       memcpy(rb, rbuf, copy * sizeof(float));
+       got_samples -= copy;
+       left -= copy;
+       plb += copy;
+       prb += copy;
+
+       if (got_samples) {
+               olLog("Had %d audio samples leftover...\n", got_samples);
+               memmove(lbuf, &lbuf[copy], got_samples * sizeof(float));
+               memmove(rbuf, &rbuf[copy], got_samples * sizeof(float));
+       }
+
+       if (left) {
+               olLog("Needed %d extra audio samples\n", left);
+               if (audio_readsamples(actx, plb, prb, left) < 1) {
+                       olLog("No more audio!\n");
+               }
+       }
+
+       // unset the callback, it will be set by the render function again
+       olSetAudioCallback(NULL);
+
+       sample_counter += samples;
+
+       // adjust volume
+       int i;
+       for (i=0; i<samples; i++) {
+               lb[i] *= volume;
+               rb[i] *= volume;
+       }
+}
+
+#define MAX(a,b) (((a)<(b))?(b):(a))
+#define MIN(a,b) (((a)>(b))?(b):(a))
+
+float max_size = 0.75f;
+float min_size = 0.2f;
+float boost = 1.7;
+
+void circlescope_render(void *ctx, float time, float state)
+{
+       float pvol = (1-fabsf(state)*1.3);
+       volume = pvol < 0 ? 0 : 0.8 * pvol;
+       
+       olLoadIdentity();
+
+       if (got_samples == DRAW_SAMPLES) {
+               olLog("Already got a full buffer?\n");
+       } else {
+               if (audio_readsamples(actx, &lbuf[got_samples], &rbuf[got_samples], DRAW_SAMPLES - got_samples) < 1) {
+                       olLog("No more audio!\n");
+               }
+               got_samples = DRAW_SAMPLES;
+       }
+
+       int i;
+       
+       olBegin(OL_POINTS);
+       for (i=0; i<DRAW_SAMPLES; i++) {
+               double w = 523.251131f / 4.0f * (2*M_PI) / 48000;
+               double pos = (sample_counter+i) * w;
+
+               float val = (lbuf[i] + rbuf[i]) / 2 * boost;
+               val = MAX(MIN(val,1.0f),-1.0f);
+               val = val * 0.5f + 0.5f;
+               val *= (max_size - min_size);
+               val += min_size;
+
+               olVertex(cosf(pos) * val, sinf(pos) * val, C_WHITE);
+       }
+       olEnd();
+               
+
+       olSetAudioCallback(moreaudio);
+}
diff --git a/examples/27c3_slides/jack-logo.cfg b/examples/27c3_slides/jack-logo.cfg
new file mode 100644 (file)
index 0000000..6abae9f
--- /dev/null
@@ -0,0 +1,12 @@
+on_speed = 2/100.0
+off_speed = 2/35.0
+flatness = 0.000001
+start_dwell = 3
+curve_dwell = 0
+corner_dwell = 5
+end_dwell = 2
+switch_dwell = 10
+closed_overdraw = 3
+closed_start_dwell = 0
+closed_end_dwell = 0
+extra_first_dwell = 0
diff --git a/examples/27c3_slides/jack-logo.svg b/examples/27c3_slides/jack-logo.svg
new file mode 100644 (file)
index 0000000..7e17818
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48+devel r"
+   width="470"
+   height="91"
+   sodipodi:docname="jack-logo.svg">
+  <metadata
+     id="metadata8">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs6" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1912"
+     inkscape:window-height="1005"
+     id="namedview4"
+     showgrid="false"
+     inkscape:zoom="13.070944"
+     inkscape:cx="405.77173"
+     inkscape:cy="51.634057"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" />
+  <path
+     style="color:#000000;fill:none;stroke:#00ff00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361731999999979;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+     d="M 224.61192 18.778743 L 405.3265 18.778744 C 408.63245 18.778744 411.29393 21.440219 411.29393 24.746178 L 411.29393 61.16283 C 411.29393 64.468789 408.63245 67.130264 405.3265 67.130264 L 224.61193 67.130264 "
+     id="rect3071" />
+  <path
+     style="color:#000000;fill:none;stroke:#00ff00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+     d="m 436.54077,18.625732 25.70586,14 c 2.9033,1.581205 5.96744,3.310647 5.96744,6.616606 l 0,3.928159 c 0,3.305958 -3.19264,5.360397 -5.96744,7.157581 l -25.70586,16.649171 c -2.7748,1.797184 -5.96744,-2.661476 -5.96744,-5.967434 l 0,-36.416648 c 0,-3.305959 3.06414,-7.54864 5.96744,-5.967435 z"
+     id="rect3073"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="sssssssss" />
+  <path
+     style="color:#000000;fill:none;stroke:#00ff00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+     d="m 411.41229,58.433241 19.09646,0"
+     id="path3076"
+     inkscape:connector-curvature="0" />
+  <path
+     style="color:#000000;fill:none;stroke:#00ff00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+     d="m 411.41229,26.433241 19.09646,0"
+     id="path3076-4"
+     inkscape:connector-curvature="0" />
+  <path
+     style="color:#000000;fill:none;stroke:#00ff00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361731999999979;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+     d="M 218.81981 11.742499 C 222.04799 11.830284 224.62036 14.457523 224.62036 17.707667 L 224.62036 72.179628 C 224.62036 75.429772 222.04799 78.057011 218.81981 78.144796 "
+     id="rect3096" />
+  <path
+     style="color:#000000;fill:none;stroke:#00ff00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+     d="m 53.25701,78.912119 -40.557091,0 c -5.6794676,0 -10.2517464,-4.572279 -10.2517464,-10.251746 l 0,-45.597315 c 0,-5.679467 4.5722788,-10.251746 10.2517464,-10.251746 l 40.557091,0"
+     id="path3153"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cssssc" />
+  <path
+     style="color:#000000;fill:none;stroke:#00ff00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-dashoffset:0;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+     d="m 60.439392,1.6414981 151.174998,0 c 3.9841,0 7.19152,3.2074197 7.19152,7.191524 l 0,72.8332989 c 0,3.984104 -3.20742,7.191524 -7.19152,7.191524 l -151.174998,0 c -3.984105,0 -7.191524,-3.20742 -7.191524,-7.191524 l 0,-72.8332989 c 0,-3.9841043 3.207419,-7.191524 7.191524,-7.191524 z"
+     id="rect3096-6-5" />
+  <g
+     transform="matrix(0.94475761,0,0,1.0584726,0,10)"
+     style="font-size:58.49077225px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;color:#000000;fill:none;stroke:#00ff00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Arial;-inkscape-font-specification:Arial"
+     id="text3256">
+    <path
+       d="m 70.864573,42.036462 4.997991,-0.685438 c 0.133273,3.198723 0.733031,5.388317 1.799276,6.568787 1.066229,1.180483 2.541825,1.770721 4.426792,1.770717 1.389903,4e-6 2.58942,-0.314155 3.598553,-0.942478 1.009101,-0.647353 1.704059,-1.513671 2.084877,-2.598955 0.38078,-1.104309 0.571179,-2.855984 0.571199,-5.255031 l 0,-28.845547 5.540629,0 0,28.531388 c -2.4e-5,3.503363 -0.428423,6.216556 -1.285197,8.139585 -0.837781,1.92304 -2.180097,3.389116 -4.026953,4.398232 -1.827854,1.009118 -3.979368,1.513676 -6.454548,1.513677 -3.674722,-1e-6 -6.492634,-1.056718 -8.453744,-3.170154 -1.942079,-2.113432 -2.875037,-5.255023 -2.798875,-9.424783"
+       style="marker:none"
+       id="path3261"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 98.339242,53.9174 16.079248,-41.868883 5.96903,0 17.13597,41.868883 -6.31175,0 -4.88375,-12.680616 -17.50725,0 -4.59815,12.680616 -5.883348,0 m 12.080858,-17.193088 14.19429,0 -4.36967,-11.595339 c -1.33282,-3.522361 -2.32289,-6.416433 -2.97023,-8.682224 -0.53314,2.68467 -1.28522,5.350263 -2.25624,7.996786 l -4.59815,12.280777"
+       style="marker:none"
+       id="path3263"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 171.8811,39.237587 5.54063,1.399438 c -1.16147,4.55056 -3.25587,8.02535 -6.28318,10.424381 -3.00835,2.379996 -6.69258,3.569992 -11.0527,3.569993 -4.51249,-1e-6 -8.1872,-0.913918 -11.02414,-2.741755 -2.81793,-1.846873 -4.96944,-4.512465 -6.45455,-7.996785 -1.46608,-3.4843 -2.19912,-7.22565 -2.19912,-11.224059 0,-4.360127 0.82824,-8.158596 2.48472,-11.39542 1.67551,-3.255798 4.04598,-5.721471 7.11142,-7.397026 3.08446,-1.694515 6.47357,-2.541793 10.16735,-2.541835 4.18876,4.2e-5 7.71115,1.066279 10.56718,3.198714 2.85595,2.132513 4.84563,5.131305 5.96903,8.996383 l -5.45495,1.285198 c -0.97108,-3.046362 -2.38003,-5.264516 -4.22688,-6.654468 -1.8469,-1.38988 -4.16977,-2.084838 -6.96862,-2.084876 -3.21778,3.8e-5 -5.91193,0.771156 -8.08247,2.313356 -2.15153,1.542271 -3.6652,3.617625 -4.54103,6.226068 -0.87585,2.589462 -1.31377,5.264575 -1.31376,8.025346 -1e-5,3.560491 0.51407,6.673522 1.54224,9.339102 1.04719,2.646565 2.66558,4.626719 4.85519,5.940469 2.18958,1.313763 4.56005,1.970641 7.11143,1.970637 3.10349,4e-6 5.731,-0.894874 7.88254,-2.684635 2.15149,-1.789748 3.60804,-4.445821 4.36967,-7.968226"
+       style="marker:none"
+       id="path3265"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 183.93341,53.9174 0,-41.868883 5.54063,0 0,20.763082 20.79164,-20.763082 7.51126,0 -17.56436,16.964609 18.33548,24.904274 -7.31134,0 -14.9083,-21.191481 -6.85438,6.683028 0,14.508453 -5.54063,0"
+       style="marker:none"
+       id="path3267"
+       inkscape:connector-curvature="0" />
+  </g>
+  <path
+     id="path3197-5-1"
+     style="color:#000000;fill:none;stroke:#00ff00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+     d="m 392.34278,67.206768 0,-48.351518 0.9863,0 0,48.351518 0.98631,0 0,-48.351518 0.9863,0 0,48.351518 0.9863,0 0,-48.351518 0.9863,0 0,48.351518 0.9863,0 0,-48.351518 0.9863,0 0,48.351518 0.9863,0 0,-48.351518"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cccccccccccccccccc" />
+</svg>
diff --git a/examples/27c3_slides/main.c b/examples/27c3_slides/main.c
new file mode 100644 (file)
index 0000000..e126960
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+        OpenLase - a realtime laser graphics toolkit
+
+Copyright (C) 2009-2010 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
+*/
+
+/* Slides for the 27C3 OpenLase Lightning Talk */
+
+/* NOTE: You need to edit this file with the circlescope audio file (the Super
+ * Mario Bros music in the talk) and the tracer video file (a crop of the
+ * Bad Apple, see http://www.youtube.com/watch?v=G3C-VevI36s ). You can of
+ * course use any other files, though for the tracer you'll likely have to
+ * tweak the vparms depending on its complexity. */
+
+#include "libol.h"
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <sys/select.h>
+#include <termios.h>
+#include <unistd.h>
+#include <curses.h>
+
+// 4:3 aspect presentation
+#define ASPECT 0.75
+
+typedef void (*init_cb)(void **context, void *arg, OLRenderParams *params);
+typedef void (*render_cb)(void *context, float stime, float state);
+typedef void (*deinit_cb)(void *context);
+
+typedef struct {
+       render_cb render;
+       init_cb init;
+       deinit_cb deinit;
+       void *arg;
+       void *context;
+} slide_t;
+
+#include "video.h"
+
+video_params vparms = {
+       .file = "/home/marcansoft/dwhelper/bad_apple_crop.flv",
+       .thresh_dark = 60,
+       .thresh_light = 160,
+       .sw_dark = 100,
+       .sw_light = 160,
+       .decimate = 2,
+       .volume = 0.5,
+
+       // these just override render parameters
+       .min_length = 6,
+       .start_wait = 8,
+       .end_wait = 3,
+       .off_speed = 2.0/24,
+       .snap_pix = 4,
+       .min_framerate = 29,
+};
+
+#define DECLARE_SLIDE(name) \
+       void name##_render(void *, float, float); \
+       void name##_init(void **, void *, OLRenderParams *); \
+       void name##_deinit(void *)
+
+#define SLIDE(name, param) {name##_render, name##_init, name##_deinit, param}
+
+DECLARE_SLIDE(pong);
+DECLARE_SLIDE(videotracer);
+DECLARE_SLIDE(cubes);
+DECLARE_SLIDE(metaballs);
+DECLARE_SLIDE(showilda);
+DECLARE_SLIDE(paintilda);
+DECLARE_SLIDE(diag);
+DECLARE_SLIDE(urls);
+DECLARE_SLIDE(libol);
+DECLARE_SLIDE(circlescope);
+
+slide_t slides[] = {
+       SLIDE(paintilda, "openlase-logo.ild"),
+       SLIDE(diag, NULL),
+       SLIDE(showilda, "jack-logo.ild"),
+       SLIDE(showilda, "output.ild"),
+       SLIDE(libol, NULL),
+       SLIDE(cubes, NULL),
+       SLIDE(pong, NULL),
+       SLIDE(circlescope, "/home/marcansoft/media/midi/smb1.mp3"),
+       SLIDE(metaballs, NULL),
+       SLIDE(videotracer, &vparms),
+       SLIDE(showilda, "27c3-logo.ild"),
+       SLIDE(urls, NULL),
+};
+
+OLRenderParams master_params;
+
+#define NUM_SLIDES ((int)(sizeof(slides)/sizeof(slides[0])))
+
+WINDOW *cur_win;
+
+void logger(const char *msg)
+{
+       wprintw(cur_win, "%s", msg);
+       wrefresh(cur_win);
+}
+
+/*
+ Since we can't directly pipe 2D OpenLase output back into the 3D renderer,
+ abuse olTransformVertex3 to perform a second perspective transform.
+*/
+float cubepos = 0;
+
+// distance from observer to front face of cube (determines FOV)
+#define FACEDEPTH 3
+
+void shader_cube(float *x, float *y, uint32_t *color)
+{
+       olPushMatrix3();
+       olLoadIdentity3();
+
+       // Shrink down the entire final image a bit, to avoid cutting off the cube's
+       // left and right corners while it's rotating. On a bitmap display (PC) this
+       // doesn't matter, but on the laser without shading it looks bad if the edge
+       // suddenly scissors off.
+       olScale3( 0.9, 0.9, 0.9);
+
+       // This transform sets it up so that it's identity at the cube's front face
+       // (z = -4)
+       olFrustum(-1, 1, -1, 1, FACEDEPTH, 100);
+
+       // Now figure out the z-position depending on the rotation of the cube, to
+       // make the frontmost edge always be full-height.
+       float theta = cubepos < 0 ? -cubepos : cubepos;
+       float zdelta = -1 - FACEDEPTH + 1 * (sinf(M_PI/4) - sinf(M_PI/4 + theta));
+       olTranslate3(0, 0, zdelta);
+
+       // Perform the rotation
+       olRotate3Y(cubepos);
+
+       // And finally transform the incoming vertex
+       float z = 1;
+       olTransformVertex3(x, y, &z);
+
+       olPopMatrix3();
+}
+
+#define TRANSITION_TIME 0.75f
+
+float gtime = 0;
+int frames = 0;
+
+float cur_stime = 0;
+int cur_slide = 0;
+float next_stime = 0;
+int next_slide = -1;
+float trans_time = 0;
+
+void go(int delta)
+{
+       if (next_slide != -1) {
+               //olLog("WARNING: attempted to change slide while transition active\n");
+               return;
+       }
+       next_slide = (cur_slide + NUM_SLIDES + delta) % NUM_SLIDES;
+       next_stime = 0;
+       trans_time = 0;
+       OLRenderParams params = master_params;
+       if (slides[next_slide].init) {
+               slides[next_slide].init(&slides[next_slide].context, slides[next_slide].arg, &params);
+       }
+       olSetRenderParams(&params);
+}
+
+// this is a function of FACEDEPTH above
+#define VANISH 1.33
+#define ST_VANISH 1.45
+
+void render_slide(int num, float stime, int bcolor, float state)
+{
+       int scolor = (VANISH - fabsf(cubepos)) / VANISH * 400;
+       if (fabsf(cubepos) < VANISH) {
+               olSetPixelShader(NULL);
+               olSetVertex3Shader(NULL);
+               olLoadIdentity();
+               olLoadIdentity3();
+               olResetColor();
+               if (scolor < 255)
+                       olMultColor(C_GREY(scolor));
+               if (bcolor > 0) {
+                       // make sure the corners of the slide-rect are always nice and sharp
+                       // even when the whole frame gets resampled to maintain framerate
+                       OLRenderParams old, params;
+                       olGetRenderParams(&old);
+                       params = old;
+                       params.start_dwell = 40;
+                       params.corner_dwell = 40;
+                       params.end_dwell = 40;
+                       olSetRenderParams(&params);
+                       olRect(-1, -ASPECT, 1, ASPECT, C_GREY(bcolor > 255 ? 255 : bcolor));
+                       olSetRenderParams(&old);
+               }
+
+               slides[num].render(slides[num].context, stime, state * ST_VANISH);
+       }
+}
+
+void render_slides(void)
+{
+       int bcolor = 0;
+
+       if (next_slide == -1) {
+               cubepos = 0;
+               render_slide(cur_slide, cur_stime, bcolor, 0);
+       } else if (trans_time >= TRANSITION_TIME) {
+               if (slides[cur_slide].deinit)
+                       slides[cur_slide].deinit(slides[cur_slide].context);
+               cur_slide = next_slide;
+               cur_stime = next_stime;
+               cubepos = 0;
+               render_slide(cur_slide, cur_stime, bcolor, 0);
+               next_slide = -1;
+       } else {
+               float raw_subpos = trans_time / TRANSITION_TIME;
+               // apply a sine function to make it accelerate/delecerate smoothly
+               float subpos = (sinf((raw_subpos - 0.5) * M_PI) + 1)/2;
+
+               if (subpos < 0.5)
+                       bcolor = subpos * 1200;
+               else
+                       bcolor = (1-subpos) * 1200;
+
+               bcolor = bcolor > 0 ? bcolor + 0.3 : 0;
+
+               if (next_slide >= cur_slide)
+                       cubepos = -subpos * M_PI/2;
+               else
+                       cubepos = subpos * M_PI/2;
+               render_slide(cur_slide, cur_stime, bcolor, raw_subpos);
+
+               if (next_slide >= cur_slide)
+                       cubepos = (1-subpos) * M_PI/2;
+               else
+                       cubepos = (subpos-1) * M_PI/2;
+               render_slide(next_slide, next_stime, bcolor, raw_subpos-1);
+       }
+
+       float ftime = olRenderFrame(100);
+       frames++;
+       gtime += ftime;
+       cur_stime += ftime;
+       next_stime += ftime;
+       trans_time += ftime;
+
+       OLFrameInfo info;
+       olGetFrameInfo(&info);
+       mvprintw(3, 0, "Frame time: %f, Cur FPS: %f, Avg FPS: %f, Objects: %3d, Points: %d", ftime, 1/ftime, frames/gtime, info.objects, info.points);
+       if (info.resampled_points)
+               printw(", Rp: %4d, Bp: %4d", info.resampled_points, info.resampled_blacks);
+       if (info.padding_points)
+               printw(", Pad %4d", info.padding_points);
+       clrtoeol();
+       refresh();
+}
+
+WINDOW *misc_win, *render_win;
+
+void reset_term(void)
+{
+       delwin(misc_win);
+       delwin(render_win);
+       endwin();
+}
+
+#define WINSTART 5
+
+int main (int argc, char *argv[])
+{
+       initscr();
+       cbreak();
+       curs_set(0);
+       keypad(stdscr, TRUE);
+       nodelay(stdscr, TRUE);
+
+       int wh = (LINES - WINSTART)/2;
+       
+       attron(A_BOLD);
+       render_win = newwin(wh-1, COLS, WINSTART + 1, 0);
+       scrollok(render_win, TRUE);
+       mvprintw(WINSTART, 0, "Render messages:");
+
+       misc_win = newwin(wh-1, COLS, WINSTART + wh + 1, 0);
+       scrollok(misc_win, TRUE);
+       mvprintw(WINSTART + wh, 0, "Misc messages:");
+       attroff(A_BOLD);
+
+       mvprintw(0, 0, "Keys:  NEXT: -> or space  PREV: <-  QUIT: q\n");
+
+       refresh();
+
+       cur_win = misc_win;
+       olSetLogCallback(logger);
+
+       memset(&master_params, 0, sizeof master_params);
+       master_params.rate = 48000;
+       master_params.on_speed = 2.0/100.0;
+       master_params.off_speed = 2.0/55.0;
+       master_params.start_wait = 12;
+       master_params.start_dwell = 3;
+       master_params.curve_dwell = 0;
+       master_params.corner_dwell = 8;
+       master_params.curve_angle = cosf(30.0*(M_PI/180.0)); // 30 deg
+       master_params.end_dwell = 3;
+       master_params.end_wait = 7;
+       master_params.snap = 1/100000.0;
+       master_params.max_framelen = master_params.rate / 30;
+       master_params.flatness = 0.000001;
+       master_params.render_flags = RENDER_GRAYSCALE;
+
+       if(olInit(4, 100000) < 0)
+               return 1;
+
+       atexit(reset_term);
+
+       olSetVertexShader(shader_cube);
+
+       olSetScissor (-1, -ASPECT, 1, ASPECT);
+
+       //olLog("\e[6H");
+       OLRenderParams params = master_params;
+       if (slides[0].init)
+               slides[0].init(&slides[0].context, slides[0].arg, &params);
+       olSetRenderParams(&params);
+
+       int done = 0;
+       while (!done) {
+               if (next_slide == -1) {
+                       mvprintw(1, 0, "Slide %d/%d", cur_slide+1, NUM_SLIDES);
+               } else {
+                       mvprintw(1, 0, "Slide %d/%d -> %d/%d", cur_slide+1, NUM_SLIDES, next_slide+1, NUM_SLIDES);
+               }
+               clrtoeol();
+               refresh();
+
+               fd_set rfds;
+               struct timeval tv;
+               tv.tv_sec = tv.tv_usec = 0;
+               FD_ZERO(&rfds);
+               FD_SET(0, &rfds);
+
+               while(1) {
+                       int ch = getch();
+                       if (ch == ERR)
+                               break;
+                       switch (ch) {
+                               case KEY_LEFT:
+                                       go(-1);
+                                       break;
+                               case KEY_RIGHT:
+                               case ' ':
+                                       go(1);
+                                       break;
+                               case 'q':
+                                       done = 1;
+                       }
+                       
+               }
+
+               cur_win = render_win;
+               render_slides();
+               cur_win = misc_win;
+       }
+
+       olShutdown();
+       exit (0);
+}
+
diff --git a/examples/27c3_slides/metaballs.c b/examples/27c3_slides/metaballs.c
new file mode 100644 (file)
index 0000000..fcd097c
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+        OpenLase - a realtime laser graphics toolkit
+
+Copyright (C) 2009-2010 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 "libol.h"
+#include "ilda.h"
+#include "text.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+/* metaballs demo */
+
+/* This is the original quick&dirty metaballs tracer. The new one optimized for
+ * video is in trace.c. It's still dirty, but no longer that quick. */
+#define ABS(a) ((a)<0?(-(a)):(a))
+
+#define OVERDRAW 8
+
+static int trace(int *field, uint8_t *tmp, int thresh, int w, int h, int decimate)
+{
+       int x, y, cx, cy, px, py, i;
+       int iters = 0;
+       int objects = 0;
+       int sx[OVERDRAW], sy[OVERDRAW];
+
+       memset(tmp, 0, w*h);
+
+       for (y=1; y<h-1; y++) {
+               for (x=1; x<w-1;x++) {
+                       int idx = y*w+x;
+                       if (field[idx] > thresh && (!(field[idx-w] > thresh)
+                                                || !(field[idx+w] > thresh)
+                                                || !(field[idx-1] > thresh)
+                                                || !(field[idx+1] > thresh))) {
+                               tmp[idx] = 1;
+                       }
+               }
+       }
+
+       int total = h*w;
+       int dir = 0;
+       int minx = 0, miny = 0;
+       int maxx = w-1, maxy = h-1;
+       int div = 0;
+
+       px = 0;
+       py = 0;
+       while (total--)
+       {
+               if (tmp[py*w+px]) {
+                       x = cx = px;
+                       y = cy = py;
+                       iters = 0;
+                       olBegin(OL_POINTS);
+                       while (1)
+                       {
+                               int idx = y*w+x;
+                               if(div==0) {
+                                       if (iters < OVERDRAW) {
+                                               sx[iters] = x;
+                                               sy[iters] = y;
+                                       }
+                                       olVertex(x, y, C_WHITE);
+                                       iters++;
+                               }
+                               div = (div+1)%decimate;
+                               tmp[idx] = 0;
+                               if (tmp[idx-1]) {
+                                       x--;
+                               } else if (tmp[idx+1]) {
+                                       x++;
+                               } else if (tmp[idx-w]) {
+                                       y--;
+                               } else if (tmp[idx+w]) {
+                                       y++;
+                               } else if (tmp[idx-w-1]) {
+                                       y--; x--;
+                               } else if (tmp[idx-w+1]) {
+                                       y--; x++;
+                               } else if (tmp[idx+w-1]) {
+                                       y++; x--;
+                               } else if (tmp[idx+w+1]) {
+                                       y++; x++;
+                               } else {
+                                       break;
+                               }
+
+                       }
+                       if (iters) {
+                               objects++;
+                               if (ABS(cx-x) <= 1 && ABS(cy-y) <= 1) {
+                                       if (iters > OVERDRAW)
+                                               iters = OVERDRAW;
+                                       for (i=0; i<iters; i++)
+                                               olVertex(sx[i], sy[i], C_GREY((int)(255.0 * (OVERDRAW - 1 - i) / (float)OVERDRAW)));
+                               }
+                       }
+                       olEnd();
+               }
+               switch(dir) {
+                       case 0:
+                               px++;
+                               if (px > maxx) {
+                                       px--; py++; maxx--; dir++;
+                               }
+                               break;
+                       case 1:
+                               py++;
+                               if (py > maxy) {
+                                       py--; px--; maxy--; dir++;
+                               }
+                               break;
+                       case 2:
+                               px--;
+                               if (px < minx) {
+                                       px++; py--; minx++; dir++;
+                               }
+                               break;
+                       case 3:
+                               py--;
+                               if (py < miny) {
+                                       py++; px++; miny++; dir=0;
+                               }
+                               break;
+               }
+       }
+       return objects;
+}
+
+
+void metaballs_init(void **ctx, void *arg, OLRenderParams *params)
+{
+       params->start_wait = 8;
+       params->start_dwell = 7;
+       params->end_dwell = 7;
+}
+
+void metaballs_deinit(void *ctx)
+{
+}
+
+static int mbuf[192][256];
+static uint8_t mtmp[192][256];
+
+static void draw_metaball(float x, float y, float radius)
+{
+       int cx,cy;
+       float px,py;
+       int *p = &mbuf[0][0];
+       px = -x;
+       py = -y / 256.0 * 192.0;
+
+       radius *= 400000.0f;
+
+       for(cy=0; cy<192; cy++) {
+               for(cx=0; cx<256;cx++) {
+                       float d = px*px+py*py;
+                       *p++ += radius/(d+1);
+                       px++;
+               }
+               py++;
+               px = -x;
+       }
+}
+
+void metaballs_render(void *ctx, float time)
+{
+       float dist1 =  128 + sinf(time * M_PI * 1.0 * 0.8 * 0.8 + 0) * 95;
+       float dist2 =  128 + sinf(time * M_PI * 1.2 * 0.8 * 0.8 + 1) * 95;
+       float dist3 =  130 + sinf(time * M_PI * 1.3 * 0.8 * 0.8 + 2) * 95;
+       float dist4 =  100 + sinf(time * M_PI * 1.4 * 0.8 * 0.8 + 3) * 95;
+       float dist5 =  128 + sinf(time * M_PI * 1.5 * 0.5 * 0.8 + 4) * 95;
+       float dist6 =  128 + sinf(time * M_PI * 1.6 * 0.5 * 0.8 + 5) * 95;
+       float dist7 =  130 + sinf(time * M_PI * 1.7 * 0.5 * 0.8 + 6) * 95;
+       float dist8 =  100 + sinf(time * M_PI * 1.8 * 0.5 * 0.8 + 7) * 95;
+       float dist9 =  130 + sinf(time * M_PI * 1.9 * 0.8 * 0.8 + 6) * 95;
+       float dist10 = 100 + sinf(time * M_PI * 2.0 * 0.5 * 0.8 + 7) * 95;
+
+       memset(mbuf, 0, sizeof mbuf);
+
+       draw_metaball(dist1, dist5, 45);
+       draw_metaball(dist2, dist6, 10);
+       draw_metaball(dist7, dist3, 30);
+       draw_metaball(dist8, dist4, 70);
+       draw_metaball(dist9, dist10, 70);
+
+       olPushMatrix();
+       olTranslate(-1.0f, -0.75f);
+       olScale(2.0f/256.0f, 2.0f/256.0f);
+
+       trace(&mbuf[0][0], &mtmp[0][0], 20000, 256, 192, 1);
+
+       olPopMatrix();
+       return;
+}
diff --git a/examples/27c3_slides/openlase-logo.cfg b/examples/27c3_slides/openlase-logo.cfg
new file mode 100644 (file)
index 0000000..f43352e
--- /dev/null
@@ -0,0 +1,12 @@
+on_speed = 2/90.0
+off_speed = 2/20.0
+flatness = 1
+start_dwell = 7
+curve_dwell = 0
+corner_dwell = 8
+end_dwell = 4
+switch_dwell = 9
+closed_overdraw = 0
+closed_start_dwell = 7
+closed_end_dwell = 4
+extra_first_dwell = 10
diff --git a/examples/27c3_slides/openlase-logo.svg b/examples/27c3_slides/openlase-logo.svg
new file mode 100644 (file)
index 0000000..4da65ef
--- /dev/null
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="1640"
+   height="440"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48+devel r"
+   sodipodi:docname="openlase-logo.svg">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective10" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.35"
+     inkscape:cx="1433.287"
+     inkscape:cy="61.149503"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:window-width="1912"
+     inkscape:window-height="1005"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:snap-nodes="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showguides="true"
+     inkscape:guide-bbox="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid2816"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       spacingx="20px"
+       spacingy="20px" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(701.5,-313.86218)">
+    <path
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -681.5,333.86218 1600,0"
+       id="path2860"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -681.5,733.86218 1600,0"
+       id="path2862"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       transform="translate(-1381.5,33.862189)"
+       sodipodi:type="arc"
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path3325"
+       sodipodi:cx="800"
+       sodipodi:cy="500"
+       sodipodi:rx="100"
+       sodipodi:ry="160"
+       d="m 900,500 a 100,160 0 1 1 -200,0 100,160 0 1 1 200,0 z" />
+    <path
+       id="path3351"
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -481.5,533.86218 100,0 c 44.18278,0 80,-35.81722 80,-80 0,-44.18278 -35.81722,-80 -80,-80 l -100,0 0,320"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccsccc" />
+    <path
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -101.5,373.86218 -200,0 0,320 200,0"
+       id="path2870-3"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc" />
+    <path
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -301.5,533.86219 120,0"
+       id="path3382"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -101.5,693.86218 0,-320 200,320 0,-320"
+       id="path3386"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 118.5,373.86218 0,320 160,0 120,-320 120,320"
+       id="path2864"
+       sodipodi:nodetypes="ccccc"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path3302-9"
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 528.5,613.86218 c 0,44.18278 34.77153,80 90,80 55.22847,0 100,-35.81722 100,-80 0,-44.18278 -44.77153,-80 -100,-80 -55.22847,0 -100,-35.81722 -100,-80 0,-44.18278 44.77153,-80 100,-80 55.22847,0 120,20 90,80"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="csscssc" />
+    <path
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 918.5,373.86218 -200,0 0,320 200,0"
+       id="path2870"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc" />
+    <path
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 118.5,533.86218 760,0"
+       id="path2872"
+       sodipodi:nodetypes="cc"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 818.5,473.86218 0,120"
+       id="path2884"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 778.5,493.86218 80,80"
+       id="path2886"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="color:#000000;fill:none;stroke:#00c300;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 778.5,573.86218 80,-80"
+       id="path2888"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+  </g>
+</svg>
diff --git a/examples/27c3_slides/output.cfg b/examples/27c3_slides/output.cfg
new file mode 100644 (file)
index 0000000..a7b9925
--- /dev/null
@@ -0,0 +1,12 @@
+on_speed = 2/200.0
+off_speed = 2/25.0
+flatness = 0.0000001
+start_dwell = 10
+curve_dwell = 0
+corner_dwell = 20
+end_dwell = 10
+switch_dwell = 6
+closed_overdraw = 16
+closed_start_dwell = 10
+closed_end_dwell = 10
+extra_first_dwell = 0
diff --git a/examples/27c3_slides/output.svg b/examples/27c3_slides/output.svg
new file mode 100644 (file)
index 0000000..740302e
--- /dev/null
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="225"
+   height="165"
+   id="svg3142"
+   version="1.1"
+   inkscape:version="0.48+devel r"
+   sodipodi:docname="output.svg">
+  <defs
+     id="defs3144" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="22.4"
+     inkscape:cx="165.78848"
+     inkscape:cy="93.596254"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="1912"
+     inkscape:window-height="1005"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3158"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata3147">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-334.49938,-302.87499)">
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect3160"
+       width="85"
+       height="80"
+       x="384.49939"
+       y="322.875" />
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect3930"
+       width="25"
+       height="5"
+       x="479.49939"
+       y="322.875" />
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect3932"
+       width="135"
+       height="135"
+       x="379.49939"
+       y="317.875" />
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect3930-1"
+       width="25"
+       height="5"
+       x="479.49939"
+       y="332.875" />
+    <path
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 394.49937,387.87498 5,-55 1,0 0,1 -2,0 0,-2 2,0 0,1 -1,0 55,-5 -1,0 0,-1 2,0 0,2 -2,0 0,-1 1,0 5,55 -1,0 0,1 2,0 0,-2 -2,0 0,1 1,0 -65,5 1,0 0,-1 -2,0 0,2 2,0 0,-1 z"
+       id="path4161"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccccccccccccccccccccccccccc" />
+    <path
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 394.49937,407.87498 5,5 -10,0 5,-5 0,14 -4,0 8,0 -4,0 0,26 5,-5 -10,0 5,5"
+       id="path4167"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccc" />
+    <path
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 499.49937,407.87498 5,5 -10,0 5,-5 0,10 -4,0 8,0 -4,0 0,30 5,-5 -10,0 5,5"
+       id="path4167-9"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccc" />
+    <path
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 464.49937,407.87498 5,5 -10,0 5,-5 0,22 -4,0 8,0 -4,0 0,18 5,-5 -10,0 5,5"
+       id="path4167-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccc" />
+    <path
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 429.49937,407.87498 5,5 -10,0 5,-5 0,28 -4,0 8,0 -4,0 0,12 5,-5 -10,0 5,5"
+       id="path4167-3"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccc" />
+    <path
+       sodipodi:type="arc"
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path4201"
+       sodipodi:cx="117.5"
+       sodipodi:cy="42.5"
+       sodipodi:rx="2.5"
+       sodipodi:ry="2.5"
+       d="m 120,42.5 a 2.5,2.5 0 1 1 -5,0 2.5,2.5 0 1 1 5,0 z"
+       transform="translate(364.49937,302.87498)" />
+    <path
+       transform="translate(364.49937,312.87498)"
+       sodipodi:type="arc"
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path4201-4"
+       sodipodi:cx="117.5"
+       sodipodi:cy="42.5"
+       sodipodi:rx="2.5"
+       sodipodi:ry="2.5"
+       d="m 120,42.5 a 2.5,2.5 0 1 1 -5,0 2.5,2.5 0 1 1 5,0 z" />
+    <path
+       transform="translate(364.49937,322.87498)"
+       sodipodi:type="arc"
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path4201-9"
+       sodipodi:cx="117.5"
+       sodipodi:cy="42.5"
+       sodipodi:rx="2.5"
+       sodipodi:ry="2.5"
+       d="m 120,42.5 a 2.5,2.5 0 1 1 -5,0 2.5,2.5 0 1 1 5,0 z" />
+    <path
+       transform="translate(364.49937,342.87498)"
+       sodipodi:type="arc"
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path4201-9-5"
+       sodipodi:cx="117.5"
+       sodipodi:cy="42.5"
+       sodipodi:rx="2.5"
+       sodipodi:ry="2.5"
+       d="m 120,42.5 a 2.5,2.5 0 1 1 -5,0 2.5,2.5 0 1 1 5,0 z" />
+    <path
+       transform="translate(364.49937,352.87498)"
+       sodipodi:type="arc"
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path4201-8-5"
+       sodipodi:cx="117.5"
+       sodipodi:cy="42.5"
+       sodipodi:rx="2.5"
+       sodipodi:ry="2.5"
+       d="m 120,42.5 a 2.5,2.5 0 1 1 -5,0 2.5,2.5 0 1 1 5,0 z" />
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.97361732;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect3930-1-1"
+       width="25"
+       height="5"
+       x="479.49939"
+       y="372.875" />
+  </g>
+</svg>
diff --git a/examples/27c3_slides/pong.c b/examples/27c3_slides/pong.c
new file mode 100644 (file)
index 0000000..68edbb5
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+        OpenLase - a realtime laser graphics toolkit
+
+Copyright (C) 2009-2010 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 "libol.h"
+#include "ilda.h"
+#include "text.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* pong demo */
+
+#define TOP 0.25
+#define BOTTOM 0.85
+#define LEFT 0.07
+#define RIGHT 0.93
+#define WIDTH (RIGHT-LEFT)
+#define HEIGHT (BOTTOM-TOP)
+#define PH 0.12
+#define PW 0.03
+#define BW 0.02
+#define BH 0.02
+
+static float p1,p2,bx,by,bdx,bdy;
+int score1, score2;
+int adv;
+
+static float ltime = 0;
+
+#define BDX 0.75
+#define BDY 0.4
+
+void pong_init(void **ctx, void *arg, OLRenderParams *params)
+{
+       params->render_flags |= RENDER_NOREVERSE;
+
+       p1 = (HEIGHT-PH)/2;
+       p2 = (HEIGHT-PH)/2;
+       bx = 0;
+       by = HEIGHT/2;
+       bdx = BDX;
+       bdy = BDY;
+
+       score1 = 0;
+       score2 = 0;
+       adv = random()%2;
+
+       ltime = -1;
+}
+
+void pong_deinit(void *ctx)
+{
+}
+
+void digit(float x, float y, int d, uint32_t color)
+{
+}
+
+void pong_render(void *ctx, float time)
+{
+       float ftime = time - ltime;
+
+       if (ltime == -1)
+               ftime = 0;
+       ltime = time;
+       
+       bx += ftime*bdx;
+       by += ftime*bdy;
+
+       if (by > HEIGHT - BH) {
+               bdy = -bdy;
+               by += 2*ftime*bdy;
+       } else if (by < 0) {
+               bdy = -bdy;
+               by += 2*ftime*bdy;
+       }
+
+       float r1 = ((random()%100-50) / 10000.0);
+       float r2 = ((random()%100-50) / 10000.0);
+
+       float p1fac = powf((1-bx/WIDTH),2) * (adv?0.17:0.22) + 0.03 + r1;
+       float p2fac = powf(bx/WIDTH,2) * (adv?0.22:0.17) + 0.03 + r2;
+
+       p1 = p1 * (1-p1fac) + (by-PH/2) * p1fac;
+       p2 = p2 * (1-p2fac) + (by-PH/2) * p2fac;
+
+       if (p1 < 0)
+               p1 = 0;
+       if (p1 > HEIGHT-PH)
+               p1 = HEIGHT-PH;
+
+       if (p2 < 0)
+               p2 = 0;
+       if (p2 > HEIGHT-PH)
+               p2 = HEIGHT-PH;
+
+       olLog("%f %10f %10f %10f %10f %10f %10f\n", p1, p2, r1, r2, p1fac, p2fac, bx);
+       
+       if (bx <= 0) {
+               if (by < p1-BH || by > p1+PH) {
+                       if (bx < -BW) {
+                               by = p2 + PH/2 - BH/2;
+                               bx = WIDTH - BW;
+                               bdx = -BDX;
+                               bdy = BDY;
+                               score2++;
+                               adv = random()%2;
+                       }
+               } else {
+                       bdx = -bdx;
+                       bx += 2*ftime*bdx;
+               }
+       } else if (bx > WIDTH - BW) {
+               if (by < p2-BH || by > p2+PH) {
+                       if (bx > WIDTH) {
+                               by = p1 + PH/2 - BH/2;
+                               bx = 0;
+                               bdx = BDX;
+                               bdy = BDY;
+                               score1++;
+                               adv = random()%2;
+                       }
+               } else {
+                       bdx = -bdx;
+                       bx += 2*ftime*bdx;
+               }
+       }
+
+       bdx *= powf(1.2, ftime);
+       bdy *= powf(1.2, ftime);
+
+       
+
+       olLoadIdentity();
+
+       olTranslate(-1,1);
+       olScale(2,-2);
+       // window is now 0.0-1.0 X and Y, Y going down)
+       olRect(0, TOP, 1, BOTTOM, C_WHITE);
+       olRect(LEFT-PW, p1+TOP, LEFT, p1+TOP+PH, C_WHITE);
+       olRect(RIGHT, p2+TOP, RIGHT+PW, p2+TOP+PH, C_WHITE);
+       olRect(LEFT+bx, TOP+by, LEFT+bx+BW, TOP+by+BW, C_WHITE);
+       olLine((LEFT+RIGHT)/2, TOP, (LEFT+RIGHT)/2, BOTTOM, C_GREY(70));
+
+       olTranslate(0, TOP - 0.13);
+       olScale(1, -1);
+       
+       char buf[10];
+       sprintf(buf, "%d", score1);
+       olDrawString(olGetDefaultFont(), LEFT, 0, 0.15, C_WHITE, buf);
+
+       sprintf(buf, "%d", score2);
+       float sw = olGetStringWidth(olGetDefaultFont(), 0.15, buf);
+       olDrawString(olGetDefaultFont(), RIGHT-sw, 0, 0.15, C_WHITE, buf);
+
+       //float sw = olGetS
+
+       /*
+       if (score1 >= 100)
+               digit(0,0,score1/100,C_WHITE);
+       if (score1 >= 10)
+               digit(DIGW,0,score1/10%10,C_WHITE);
+       digit(2*DIGW,0,score1%10,C_WHITE);
+
+       if (score2 >= 100)
+               digit(1-3*DIGW,0,score2/100,C_WHITE);
+       if (score2 >= 10)
+               digit(1-2*DIGW,0,score2/10%10,C_WHITE);
+       digit(1-1*DIGW,0,score2%10,C_WHITE);*/
+}
diff --git a/examples/27c3_slides/slow.cfg b/examples/27c3_slides/slow.cfg
new file mode 100644 (file)
index 0000000..38761de
--- /dev/null
@@ -0,0 +1,12 @@
+on_speed = 2/100.0
+off_speed = 2/25.0
+flatness = 0.000001
+start_dwell = 4
+curve_dwell = 0
+corner_dwell = 5
+end_dwell = 4
+switch_dwell = 6
+closed_overdraw = 3
+closed_start_dwell = 3
+closed_end_dwell = 3
+extra_first_dwell = 0
diff --git a/examples/27c3_slides/static.c b/examples/27c3_slides/static.c
new file mode 100644 (file)
index 0000000..399fb47
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+        OpenLase - a realtime laser graphics toolkit
+
+Copyright (C) 2009-2010 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 "libol.h"
+#include "ilda.h"
+#include "text.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void showilda_init(void **ctx, void *param)
+{
+       *ctx = olLoadIlda(param);
+       if (!*ctx)
+               olLog("Failed to load %s\n", (char*)param);
+}
+
+void showilda_deinit(void *ctx)
+{
+       if (ctx)
+               olFreeIlda(ctx);
+}
+
+void showilda_render(void *ctx, float time)
+{
+       olLoadIdentity();
+       olDrawIlda(ctx);
+}
+
+int points_left = 0;
+int include_dark_points = 0;
+
+static void cutoff(float *x, float *y, uint32_t *color)
+{
+       static float save_x, save_y;
+       static uint32_t save_color;
+       static int points_dot = 0;
+       if ((!include_dark_points) && (*color == C_BLACK)) {
+               if (points_left)
+                       return;
+               *x = save_x;
+               *y = save_y;
+       }
+       if (points_left) {
+               points_left--;
+               save_x = *x;
+               save_y = *y;
+               save_color = *color;
+               points_dot = 200;
+       } else {
+               *x = save_x;
+               *y = save_y;
+               if (points_dot) {
+                       *color = C_WHITE;
+                       points_dot--;
+               } else {
+                       *color = C_BLACK;
+               }
+       }
+}
+
+void paintilda_init(void **ctx, void *param, OLRenderParams *params)
+{
+       *ctx = olLoadIlda(param);
+       if (!*ctx)
+               olLog("Failed to load %s\n", (char*)param);
+       params->render_flags |= RENDER_NOREVERSE;
+}
+
+void paintilda_deinit(void *ctx)
+{
+       if (ctx)
+               olFreeIlda(ctx);
+}
+
+void paintilda_render(void *ctx, float time)
+{
+       include_dark_points = 1;
+       points_left = time * 300;
+       olLoadIdentity();
+       olSetPixelShader(cutoff);
+       olDrawIlda(ctx);
+       olSetPixelShader(NULL);
+}
+
+
+void urls_init(void **ctx, void *param, OLRenderParams *params)
+{
+       params->on_speed = 2.0/100.0;
+       params->off_speed = 2.0/50.0;
+       params->start_wait = 7;
+       params->start_dwell = 0;
+       params->curve_dwell = 0;
+       params->corner_dwell = 8;
+       params->end_dwell = 0;
+       params->end_wait = 7;
+       params->flatness = 0.000005;
+       params->render_flags |= RENDER_NOREORDER;
+}
+
+void urls_deinit(void *ctx)
+{
+}
+
+void urls_render(void *ctx, float time)
+{
+       olLoadIdentity();
+       olLoadIdentity3();
+       olDrawString(olGetDefaultFont(), -0.99, 0.1, 0.25, C_WHITE, "marcansoft.com/openlase");
+}
+
+void libol_init(void **ctx, void *param, OLRenderParams *params)
+{
+       params->on_speed = 2.0/100.0;
+       params->off_speed = 2.0/50.0;
+       params->start_wait = 15;
+       params->start_dwell = 5;
+       params->curve_dwell = 0;
+       params->corner_dwell = 5;
+       params->end_dwell = 5;
+       params->end_wait = 2;
+       params->flatness = 0.000005;
+       params->render_flags |= RENDER_NOREORDER;
+}
+
+void libol_deinit(void *ctx)
+{
+}
+
+void libol_render(void *ctx, float time)
+{
+       olLoadIdentity();
+       olLoadIdentity3();
+       olDrawString(olGetDefaultFont(), -0.45, 0.45, 0.2, C_WHITE, "olBegin()");
+       olDrawString(olGetDefaultFont(), -0.50, 0.3, 0.8, C_WHITE, "libol");
+       olDrawString(olGetDefaultFont(), -0.45, -0.3, 0.2, C_WHITE, "olEnd()");
+}
diff --git a/examples/27c3_slides/video.c b/examples/27c3_slides/video.c
new file mode 100644 (file)
index 0000000..b6e8a36
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+        OpenLase - a realtime laser graphics toolkit
+
+Copyright (C) 2009-2010 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 "libol.h"
+#include "ilda.h"
+#include "text.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avstream.h"
+#include "video.h"
+#include "trace.h"
+
+/* This is a slide version of playvid.c, using avstream.c. */
+
+static AContext *actx;
+static VContext *vctx;
+
+static video_params *cfg;
+
+static float vidtime;
+static void *tmp;
+static int dropframes;
+static int inframes;
+static int outframes;
+static float volume = 0;
+static int bg_white = -1;
+static AVFrame *frame;
+
+static void moreaudio(float *lb, float *rb, int samples)
+{
+       audio_readsamples(actx, lb, rb, samples);
+       while (samples--) {
+               *lb++ *= volume;
+               *rb++ *= volume;
+       }
+}
+
+void videotracer_init(void **ctx, void *arg, OLRenderParams *params)
+{
+       cfg = arg;
+       if (audio_open(&actx, cfg->file) != 0) {
+               olLog("Audio open/init failed\n");
+               exit(1);
+       }
+
+       if (video_open(&vctx, cfg->file) != 0) {
+               olLog("Video open/init failed\n");
+               exit(1);
+       }
+
+       int width = vctx->av.codecctx->width;
+       int height = vctx->av.codecctx->height;
+
+       if (cfg->aspect == 0)
+               cfg->aspect = width / (float)height;
+       if (cfg->framerate == 0)
+               cfg->framerate = vctx->av.formatctx->streams[vctx->av.stream]->r_frame_rate.num / (float)vctx->av.formatctx->streams[vctx->av.stream]->r_frame_rate.den;
+
+       tmp = malloc(width * height * 2);
+       vidtime = 0;
+       dropframes = 0;
+       inframes = 0;
+       outframes = 0;
+       bg_white = -1;
+       olSetAudioCallback(moreaudio);
+
+       int maxd = width > height ? width : height;
+
+       if (cfg->min_length)
+               params->min_length = cfg->min_length;
+       if (cfg->off_speed)
+               params->off_speed = cfg->off_speed;
+       if (cfg->start_wait)
+               params->start_wait = cfg->start_wait;
+       if (cfg->end_wait)
+               params->end_wait = cfg->end_wait;
+       if (cfg->snap_pix)
+               params->snap = (cfg->snap_pix*2.0)/(float)maxd;
+       if (cfg->min_framerate)
+               params->max_framelen = params->rate / cfg->min_framerate;
+}
+
+void videotracer_deinit(void *ctx)
+{
+       audio_close(actx);
+       video_close(vctx);
+       free(tmp);
+       olSetAudioCallback(NULL);
+}
+
+#define ASPECT 0.75
+
+void videotracer_render(void *ctx, float time, float state)
+{
+       float pvol = (1-fabsf(state));
+       volume = pvol < 0 ? 0 : 0.8 * pvol * cfg->volume;
+       olLog("state=%f pvol=%f\n", state, pvol);
+
+       float iaspect = 1/cfg->aspect;
+       int width = vctx->av.codecctx->width;
+       int height = vctx->av.codecctx->height;
+
+       if (cfg->aspect > ASPECT) {
+               olScale(1, iaspect);
+       } else {
+               olScale(ASPECT * cfg->aspect, ASPECT);
+       }
+
+       olScale(1+cfg->overscan, 1+cfg->overscan);
+       olTranslate(-1.0f, 1.0f);
+       olScale(2.0f/width, -2.0f/height);
+
+       float frametime = 1.0f/cfg->framerate;
+
+       while ((time+frametime) >= vidtime) {
+               if (video_readframe(vctx, &frame) != 1) {
+                       olLog("Video EOF!\n");
+                       return;
+               }
+               if (inframes == 0)
+                       olLog("Frame stride: %d\n", frame->linesize[0]);
+
+               inframes++;
+               if (vidtime < time) {
+                       vidtime += frametime;
+                       //olLog("Frame skip!\n");
+                       dropframes++;
+                       continue;
+               }
+               vidtime += frametime;
+       }
+
+       int thresh;
+       int obj;
+       int bsum = 0;
+       int c;
+       for (c=cfg->edge_off; c<(width-cfg->edge_off); c++) {
+               bsum += frame->data[0][c+cfg->edge_off*frame->linesize[0]];
+               bsum += frame->data[0][c+(height-cfg->edge_off-1)*frame->linesize[0]];
+       }
+       for (c=cfg->edge_off; c<(height-cfg->edge_off); c++) {
+               bsum += frame->data[0][cfg->edge_off+c*frame->linesize[0]];
+               bsum += frame->data[0][(c+1)*frame->linesize[0]-1-cfg->edge_off];
+       }
+       bsum /= 2 * width * height;
+       if (bg_white == -1)
+               bg_white = bsum > 128;
+       if (bg_white && bsum < cfg->sw_dark)
+               bg_white = 0;
+       if (!bg_white && bsum > cfg->sw_light)
+               bg_white = 1;
+
+       if (bg_white)
+               thresh = cfg->thresh_light;
+       else
+               thresh = cfg->thresh_dark;
+
+       obj = trace(frame->data[0], tmp, thresh, width, height, frame->linesize[0], cfg->decimate);
+
+       outframes++;
+       olLog("Video stats: Drift %7.4f, In %4d, Out %4d, Drop %4d, Thr %3d, Bg %3d\n",
+                  time-vidtime, inframes, outframes, dropframes, thresh, bsum);
+}
diff --git a/examples/27c3_slides/video.h b/examples/27c3_slides/video.h
new file mode 100644 (file)
index 0000000..4fb58f4
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+        OpenLase - a realtime laser graphics toolkit
+
+Copyright (C) 2009-2010 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
+*/
+
+#ifndef VIDEO_H
+#define VIDEO_H
+
+typedef struct {
+       char *file;
+       int thresh_dark;
+       int thresh_light;
+       int sw_dark;
+       int sw_light;
+       int edge_off;
+       int decimate;
+       float overscan;
+       float aspect;
+       float framerate;
+       float volume;
+
+       int min_length;
+       int start_wait;
+       int end_wait;
+       int off_speed;
+       int snap_pix;
+       float min_framerate;
+} video_params;
+
+#endif
\ No newline at end of file
index 00b9f7f0571ba42a87c654e4b78aa7ae584cae64..154eb16270be7f74de5e235ced90d0d0730861a8 100644 (file)
@@ -34,3 +34,5 @@ target_link_libraries(midiview openlase ${ALSA_LIBRARIES})
 
 add_executable(harp harp.c)
 target_link_libraries(harp openlase)
+
+add_subdirectory(27c3_slides)