From: Hector Martin Date: Sun, 2 Jan 2011 06:02:05 +0000 (+0100) Subject: Add the 27C3 slides (with cleaned up versions of several of the effects) X-Git-Url: https://gitweb.aptx.org/?a=commitdiff_plain;h=e5bbe1216944467557bbf2848f95d1da8fe6dbce;p=openlase-old.git Add the 27C3 slides (with cleaned up versions of several of the effects) --- diff --git a/examples/27c3_slides/27c3-logo.cfg b/examples/27c3_slides/27c3-logo.cfg new file mode 100644 index 0000000..38761de --- /dev/null +++ b/examples/27c3_slides/27c3-logo.cfg @@ -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 index 0000000..68c19e2 --- /dev/null +++ b/examples/27c3_slides/27c3-logo.svg @@ -0,0 +1,66 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/examples/27c3_slides/3ddemos.c b/examples/27c3_slides/3ddemos.c new file mode 100644 index 0000000..2c464c9 --- /dev/null +++ b/examples/27c3_slides/3ddemos.c @@ -0,0 +1,350 @@ +/* + OpenLase - a realtime laser graphics toolkit + +Copyright (C) 2009-2010 Hector Martin "marcan" + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "libol.h" +#include "ilda.h" +#include "text.h" +#include +#include + +/* 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 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 index 0000000..1960214 --- /dev/null +++ b/examples/27c3_slides/CMakeLists.txt @@ -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 index 0000000..399b33f --- /dev/null +++ b/examples/27c3_slides/avstream.c @@ -0,0 +1,250 @@ +/* + OpenLase - a realtime laser graphics toolkit + +Copyright (C) 2009-2010 Hector Martin "marcan" + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* 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; iav.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; iav.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 index 0000000..1ad43bc --- /dev/null +++ b/examples/27c3_slides/avstream.h @@ -0,0 +1,58 @@ +/* + OpenLase - a realtime laser graphics toolkit + +Copyright (C) 2009-2010 Hector Martin "marcan" + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef AVSTREAM_H +#define AVSTREAM_H + +#include +#include + +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 index 0000000..01da89a --- /dev/null +++ b/examples/27c3_slides/circlescope.c @@ -0,0 +1,156 @@ +/* + OpenLase - a realtime laser graphics toolkit + +Copyright (C) 2009-2010 Hector Martin "marcan" + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "libol.h" +#include "ilda.h" +#include "text.h" +#include +#include +#include +#include + +#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(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 + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/27c3_slides/main.c b/examples/27c3_slides/main.c new file mode 100644 index 0000000..e126960 --- /dev/null +++ b/examples/27c3_slides/main.c @@ -0,0 +1,390 @@ +/* + OpenLase - a realtime laser graphics toolkit + +Copyright (C) 2009-2010 Hector Martin "marcan" + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// 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, ¶ms); + } + olSetRenderParams(¶ms); +} + +// 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(¶ms); + 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, ¶ms); + olSetRenderParams(¶ms); + + 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 index 0000000..fcd097c --- /dev/null +++ b/examples/27c3_slides/metaballs.c @@ -0,0 +1,212 @@ +/* + OpenLase - a realtime laser graphics toolkit + +Copyright (C) 2009-2010 Hector Martin "marcan" + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "libol.h" +#include "ilda.h" +#include "text.h" +#include +#include +#include +#include + +/* 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 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 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 index 0000000..f43352e --- /dev/null +++ b/examples/27c3_slides/openlase-logo.cfg @@ -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 index 0000000..4da65ef --- /dev/null +++ b/examples/27c3_slides/openlase-logo.svg @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/27c3_slides/output.cfg b/examples/27c3_slides/output.cfg new file mode 100644 index 0000000..a7b9925 --- /dev/null +++ b/examples/27c3_slides/output.cfg @@ -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 index 0000000..740302e --- /dev/null +++ b/examples/27c3_slides/output.svg @@ -0,0 +1,185 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/27c3_slides/pong.c b/examples/27c3_slides/pong.c new file mode 100644 index 0000000..68edbb5 --- /dev/null +++ b/examples/27c3_slides/pong.c @@ -0,0 +1,186 @@ +/* + OpenLase - a realtime laser graphics toolkit + +Copyright (C) 2009-2010 Hector Martin "marcan" + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "libol.h" +#include "ilda.h" +#include "text.h" +#include +#include +#include + +/* 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 index 0000000..38761de --- /dev/null +++ b/examples/27c3_slides/slow.cfg @@ -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 index 0000000..399fb47 --- /dev/null +++ b/examples/27c3_slides/static.c @@ -0,0 +1,154 @@ +/* + OpenLase - a realtime laser graphics toolkit + +Copyright (C) 2009-2010 Hector Martin "marcan" + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "libol.h" +#include "ilda.h" +#include "text.h" +#include +#include +#include +#include + +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 index 0000000..b6e8a36 --- /dev/null +++ b/examples/27c3_slides/video.c @@ -0,0 +1,182 @@ +/* + OpenLase - a realtime laser graphics toolkit + +Copyright (C) 2009-2010 Hector Martin "marcan" + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "libol.h" +#include "ilda.h" +#include "text.h" +#include +#include +#include +#include + +#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 index 0000000..4fb58f4 --- /dev/null +++ b/examples/27c3_slides/video.h @@ -0,0 +1,44 @@ +/* + OpenLase - a realtime laser graphics toolkit + +Copyright (C) 2009-2010 Hector Martin "marcan" + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#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 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 00b9f7f..154eb16 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -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)