first working version
authorJohn Tsiombikas <nuclear@member.fsf.org>
Fri, 8 Sep 2023 04:36:52 +0000 (07:36 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Fri, 8 Sep 2023 04:36:52 +0000 (07:36 +0300)
sdr/foo.v.glsl
src/demo.c
src/music.c [new file with mode: 0644]
src/music.h [new file with mode: 0644]

index 1e8d9b6..ce9586b 100644 (file)
@@ -1,12 +1,14 @@
 attribute vec4 attr_vertex, attr_color;
 attribute vec2 attr_texcoord;
 
+uniform mat4 matrix_modelview_projection;
+
 varying vec4 color;
 varying vec2 texcoord;
 
 void main()
 {
-       gl_Position = attr_vertex;
+       gl_Position = matrix_modelview_projection * attr_vertex;
        texcoord = attr_texcoord;
        color = attr_color;
 }
index 265e410..4e857f3 100644 (file)
@@ -1,15 +1,30 @@
 #include <stdio.h>
+#include <stdlib.h>
 #include <stdint.h>
 #include "demo.h"
 #include "opengl.h"
 #include "sanegl.h"
 #include "assman.h"
 #include "cmesh.h"
+#include "music.h"
 
+static void draw_texquad(float x, float y, float w, float h);
+static int piece_hit(int x, int y);
 static void gen_default_textures(void);
 
 static unsigned int sdr_foo;
 static unsigned int tex_logo;
+static unsigned int tex_bg, tex_piece;
+static int bg_width, bg_height;
+static float bg_aspect;
+static int piece_width, piece_height;
+static float vis_width, vis_height;
+static float xoffs, yoffs;
+static float xpos, ypos;
+static int dragging;
+static int prev_mx, prev_my;
+static int xtarg, ytarg;
+static int inplace;
 
 int demo_init(void)
 {
@@ -20,6 +35,10 @@ int demo_init(void)
                return -1;
        }
 
+       if(init_music() == -1) {
+               return -1;
+       }
+
        /* global "debug" shader which just visualizes normals */
        if(!(sdr_dbg = get_sdrprog("sdr/dbg.v.glsl", "sdr/dbg.p.glsl"))) {
                return -1;
@@ -49,13 +68,33 @@ int demo_init(void)
        gl_end();
        swap_buffers();
 
-       glEnable(GL_DEPTH_TEST);
+       if(!(tex_bg = get_tex2d("data/bunny_bg.jpg"))) {
+               return -1;
+       }
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+       bg_width = 2048;
+       bg_height = 1360;
+       bg_aspect = (float)bg_width / (float)bg_height;
+
+       if(!(tex_piece = get_tex2d("data/bunny.png"))) {
+               return -1;
+       }
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+       piece_width = piece_height = 512;
+
+       xtarg = 933;
+       ytarg = 443;
+
+       glDisable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);
        return 0;
 }
 
 void demo_cleanup(void)
 {
+       destroy_music();
        destroy_assman();
 
        glDeleteTextures(1, &deftex_white);
@@ -67,18 +106,44 @@ void demo_display(void)
 {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
-       glBindTexture(GL_TEXTURE_2D, tex_logo);
+       gl_matrix_mode(GL_MODELVIEW);
+       gl_load_identity();
+       gl_translatef(xoffs, yoffs, 0);
+
+       glBindTexture(GL_TEXTURE_2D, tex_bg);
        glUseProgram(sdr_foo);
-       gl_begin(GL_QUADS);
+
        gl_color3f(1, 1, 1);
+       draw_texquad(0, 0, bg_width, bg_height);
+
+       gl_load_identity();
+       gl_translatef(xpos, vis_height - ypos - piece_height, 0);
+
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+       glBindTexture(GL_TEXTURE_2D, tex_piece);
+       if(!inplace) {
+               gl_color4f(0, 0, 0, 0.65);
+               draw_texquad(10, -15, piece_width, piece_height);
+       }
+       gl_color3f(1, 1, 1);
+       draw_texquad(0, 0, piece_width, piece_height);
+
+       glDisable(GL_BLEND);
+}
+
+static void draw_texquad(float x, float y, float w, float h)
+{
+       gl_begin(GL_QUADS);
        gl_texcoord2f(0, 1);
-       gl_vertex2f(-1, -1);
+       gl_vertex2f(x, y);
        gl_texcoord2f(1, 1);
-       gl_vertex2f(1, -1);
+       gl_vertex2f(x + w, 0);
        gl_texcoord2f(1, 0);
-       gl_vertex2f(1, 1);
+       gl_vertex2f(x + w, y + h);
        gl_texcoord2f(0, 0);
-       gl_vertex2f(-1, 1);
+       gl_vertex2f(x, y + h);
        gl_end();
 }
 
@@ -88,18 +153,98 @@ void demo_reshape(int x, int y)
        win_width = x;
        win_height = y;
        win_aspect = (float)x / (float)y;
+
+       gl_matrix_mode(GL_PROJECTION);
+       gl_load_identity();
+       if(bg_aspect >= win_aspect) {
+               vis_width = bg_width;
+               vis_height = bg_width / win_aspect;
+               xoffs = 0;
+               yoffs = (vis_height - bg_height) * 0.5f;
+       } else {
+               vis_width = bg_height * win_aspect;
+               vis_height = bg_height;
+               xoffs = (bg_height * win_aspect - bg_width) * 0.5f;
+               yoffs = 0;
+       }
+       gl_ortho(0, vis_width, 0, vis_height, -1, 1);
 }
 
 void demo_keyboard(int key, int pressed)
 {
+       if(!pressed) return;
+
+       switch(key) {
+       case ' ':
+               xpos = xtarg + xoffs;
+               ypos = ytarg + yoffs;
+               break;
+       }
+}
+
+static void scr_to_vis(int *xp, int *yp)
+{
+       float x = (float)*xp;
+       float y = (float)*yp;
+       *xp = x / (float)win_width * (float)vis_width;
+       *yp = y / (float)win_height * (float)vis_height;
 }
 
 void demo_mouse(int bn, int pressed, int x, int y)
 {
+       if(pressed) {
+               scr_to_vis(&x, &y);
+               if(piece_hit(x, y)) {
+                       dragging = 1;
+                       prev_mx = x;
+                       prev_my = y;
+                       inplace = 0;
+               }
+       } else {
+               if(dragging) {
+                       dragging = 0;
+
+                       if(fabs(xpos - (xtarg + xoffs)) < 20 && fabs(ypos - (ytarg + yoffs)) < 20) {
+                               xpos = xtarg + xoffs;
+                               ypos = ytarg + yoffs;
+                               inplace = 1;
+                               play_music();
+                       }
+               }
+       }
 }
 
 void demo_motion(int x, int y)
 {
+       int dx, dy;
+
+       scr_to_vis(&x, &y);
+
+       dx = x - prev_mx;
+       dy = y - prev_my;
+       prev_mx = x;
+       prev_my = y;
+
+       if(!dragging || !(dx | dy)) {
+               return;
+       }
+
+       xpos += dx;
+       ypos += dy;
+
+       if(xpos < 0) xpos = 0;
+       if(ypos < 0) ypos = 0;
+       if(xpos + piece_width > vis_width) xpos = vis_width - piece_width;
+       if(ypos + piece_height > vis_height) ypos = vis_height - piece_height;
+}
+
+static int piece_hit(int x, int y)
+{
+       if(x < xpos) return 0;
+       if(x >= xpos + piece_width) return 0;
+       if(y < ypos) return 0;
+       if(y >= ypos + piece_height) return 0;
+       return 1;
 }
 
 static void gen_default_textures(void)
diff --git a/src/music.c b/src/music.c
new file mode 100644 (file)
index 0000000..81b98d0
--- /dev/null
@@ -0,0 +1,197 @@
+#include <stdio.h>
+#include <sys/stat.h>
+#include "music.h"
+#include "assfile.h"
+#include "miniaudio/miniaudio.h"
+
+static const char *fmtname(ma_format fmt);
+static ma_result vopen(ma_vfs *vfs, const char *path, ma_uint32 mode, ma_vfs_file *fret);
+static ma_result vclose(ma_vfs *vfs, ma_vfs_file fp);
+static ma_result vread(ma_vfs *vfs, ma_vfs_file fp, void *dest, size_t sz, size_t *numread);
+static ma_result vseek(ma_vfs *vfs, ma_vfs_file fp, ma_int64 offs, ma_seek_origin from);
+static ma_result vtell(ma_vfs *vfs, ma_vfs_file fp, ma_int64 *pos);
+static ma_result vinfo(ma_vfs *vfs, ma_vfs_file fp, ma_file_info *inf);
+
+static int init_done;
+static ma_engine engine;
+static ma_sound sound;
+static ma_resource_manager resman;
+static ma_uint32 sample_rate;
+static float volume;
+
+static ma_vfs_callbacks vfs = {
+       vopen, 0,
+       vclose,
+       vread, 0,
+       vseek,
+       vtell,
+       vinfo
+};
+
+int init_music(void)
+{
+       ma_engine_config engcfg;
+       ma_resource_manager_config rescfg;
+       unsigned int flags;
+       ma_format fmt;
+       ma_uint32 nchan;
+
+       rescfg = ma_resource_manager_config_init();
+       rescfg.pVFS = &vfs;
+       if(ma_resource_manager_init(&rescfg, &resman) != 0) {
+               fprintf(stderr, "failed to initialize miniaudio resource manager\n");
+               return -1;
+       }
+
+       engcfg = ma_engine_config_init();
+       engcfg.pResourceManager = &resman;
+
+       if(ma_engine_init(&engcfg, &engine) != 0) {
+               fprintf(stderr, "failed to initialize miniaudio engine\n");
+               return -1;
+       }
+
+       flags = MA_SOUND_FLAG_STREAM;
+       if(ma_sound_init_from_file(&engine, "data/woodclick.wav", flags, 0, 0, &sound) != 0) {
+               fprintf(stderr, "failed to load music\n");
+               return -1;
+       }
+       ma_sound_get_data_format(&sound, &fmt, &nchan, &sample_rate, 0, 0);
+       printf("loaded sound: %s %u.%03u khz, %u channels\n", fmtname(fmt),
+                       (unsigned int)sample_rate / 1000, (unsigned int)sample_rate % 1000,
+                       (unsigned int)nchan);
+
+       init_done = 1;
+       volume = 1.0f;
+       return 0;
+}
+
+void destroy_music(void)
+{
+       if(init_done) {
+               ma_sound_stop(&sound);
+               ma_sound_uninit(&sound);
+               ma_engine_uninit(&engine);
+       }
+       init_done = 0;
+}
+
+void play_music(void)
+{
+       if(init_done) {
+               ma_sound_start(&sound);
+       }
+}
+
+void stop_music(void)
+{
+       if(init_done) {
+               ma_sound_stop(&sound);
+       }
+}
+
+void seek_music(long tm)
+{
+       ma_uint64 frm;
+
+       if(init_done) {
+               if(tm < 0) tm = 0;
+               frm = (ma_uint64)tm * (ma_uint64)sample_rate / 1000llu;
+               ma_sound_seek_to_pcm_frame(&sound, frm);
+       }
+}
+
+void set_music_volume(float vol)
+{
+       if(init_done) {
+               volume = vol;
+               ma_engine_set_volume(&engine, vol);
+       }
+}
+
+
+static const char *fmtname(ma_format fmt)
+{
+       switch(fmt) {
+       case ma_format_u8: return "8 bit";
+       case ma_format_s16: return "16 bit";
+       case ma_format_s24: return "24 bit";
+       case ma_format_s32: return "32 bit";
+       case ma_format_f32: return "float";
+       default:
+               return "unknown";
+       }
+}
+
+static ma_result vopen(ma_vfs *vfs, const char *path, ma_uint32 mode, ma_vfs_file *fret)
+{
+       ass_file *fp;
+
+       if(mode != MA_OPEN_MODE_READ) return -1;
+
+       if(!(fp = ass_fopen(path, "rb"))) {
+               return -1;
+       }
+       *fret = fp;
+       return 0;
+}
+
+static ma_result vclose(ma_vfs *vfs, ma_vfs_file fp)
+{
+       ass_fclose(fp);
+       return 0;
+}
+
+static ma_result vread(ma_vfs *vfs, ma_vfs_file fp, void *dest, size_t sz, size_t *numread)
+{
+       size_t res;
+
+       res = ass_fread(dest, 1, sz, fp);
+       if(numread) *numread = res;
+
+       if(res != sz) {
+               if(res == 0) return MA_AT_END;
+       }
+       return MA_SUCCESS;
+}
+
+static ma_result vseek(ma_vfs *vfs, ma_vfs_file fp, ma_int64 offs, ma_seek_origin org)
+{
+       int from;
+       switch(org) {
+       case ma_seek_origin_start:
+               from = SEEK_SET;
+               break;
+       case ma_seek_origin_current:
+               from = SEEK_CUR;
+               break;
+       case ma_seek_origin_end:
+               from = SEEK_END;
+               break;
+       }
+       return ass_fseek(fp, offs, from) == -1 ? -1 : 0;
+}
+
+static ma_result vtell(ma_vfs *vfs, ma_vfs_file fp, ma_int64 *pos)
+{
+       *pos = ass_ftell(fp);
+       return 0;
+}
+
+static ma_result vinfo(ma_vfs *vfs, ma_vfs_file fp, ma_file_info *inf)
+{
+       int fd;
+       struct stat st;
+
+#ifdef _MSC_VER
+       fd = _fileno(fp);
+#else
+       fd = fileno(fp);
+#endif
+
+       if(fstat(fd, &st) != 0) {
+               return MA_ERROR;
+       }
+       inf->sizeInBytes = st.st_size;
+       return MA_SUCCESS;
+}
diff --git a/src/music.h b/src/music.h
new file mode 100644 (file)
index 0000000..d71c7ad
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef MUSIC_H_
+#define MUSIC_H_
+
+int init_music(void);
+void destroy_music(void);
+
+void play_music(void);
+void stop_music(void);
+void seek_music(long tm);
+
+void set_music_volume(float vol);
+
+#endif /* MUSIC_H_ */