diff --git a/demo/src/framebuffer.c b/demo/src/framebuffer.c index e118d5c..991b49b 100644 --- a/demo/src/framebuffer.c +++ b/demo/src/framebuffer.c @@ -38,6 +38,9 @@ void framebufferDraw() { saveState(); translate(1024 - 256, 256); rotate(30); + fill(colorByName("white")); + stroke(colorByName("blue")); + strokeWidth(2); rectTextured(texture, -0.5*w, -0.5*h, w, h); restoreState(); } diff --git a/src/animation.c b/src/animation.c index c9fcf9c..1ca5b76 100644 --- a/src/animation.c +++ b/src/animation.c @@ -452,7 +452,7 @@ Animation createAnimationFromImage(int width, int height, const void *pixels, in Animation createAnimationFromFramebuffer(Framebuffer framebuffer) { unsigned int texid = framebufferGetGLTexId(framebuffer); Animation animation = createAnimationFromGLTexId(texid); - //animationGLTexIdSetOwnership(texid, FALSE); + animationGLTexIdSetOwnership(texid, FALSE); return animation; } diff --git a/src/array.c b/src/array.c index f5a8b0c..bddb1a8 100644 --- a/src/array.c +++ b/src/array.c @@ -144,16 +144,25 @@ int heliMapRemove(HeliArray *a, const void *k, HeliCompareCallback cmp) { return FALSE; } +static int uintCompare(size_t a, size_t b) + { return a < b ? -1 : (a > b ? 1: 0); } +static size_t uintClone(size_t a) + { return a; } +HeliPair* heliUIntFind(HeliArray *a, size_t k, int *gtOrEqIndex) + { return heliMapFind(a, (const void*)k, (HeliCompareCallback)&uintCompare, gtOrEqIndex); } +HeliPair* heliUIntGet(HeliArray *a, size_t k) + { return heliUIntFind(a, k, NULL); } +HeliPair* heliUIntAdd(HeliArray *a, size_t k, void *v, HeliFreeCallback fv) + { return heliMapAdd(a, (const void*)k, (HeliCompareCallback)&uintCompare, (HeliCloneCallback)&uintClone, NULL, v, fv); } +int heliUIntRemove(HeliArray *a, size_t k) + { return heliMapRemove(a, (const void*)k, (HeliCompareCallback)&uintCompare); } HeliPair* heliStringmapFind(HeliArray *a, const char *k, int *gtOrEqIndex) { return heliMapFind(a, k, (HeliCompareCallback)&strcmp, gtOrEqIndex); } - HeliPair* heliStringmapGet(HeliArray *a, const char *k) { return heliStringmapFind(a, k, NULL); } - HeliPair* heliStringmapAdd(HeliArray *a, const char *k, void *v, HeliFreeCallback fv) { return heliMapAdd(a, k, (HeliCompareCallback)&strcmp, (HeliCloneCallback)&heliStringCopy, &free, v, fv); } - int heliStringmapRemove(HeliArray *a, const char *k) { return heliMapRemove(a, k, (HeliCompareCallback)&strcmp); } diff --git a/src/common.c b/src/common.c index 2feabc7..171085a 100644 --- a/src/common.c +++ b/src/common.c @@ -49,7 +49,17 @@ int randomNumber(int min, int max) double randomFloat() { return (double)rand()/(double)RAND_MAX; } +void rotateVector(double *x, double *y, double angle) { + double a = angle*PI/180.0; + double xx = x ? *x : 0.0; + double yy = y ? *y : 0.0; + double c = cos(a); + double s = sin(a); + if (x) *x = xx*c - yy*s; + if (y) *y = xx*s + yy*c; +} + Directory openDirectory(const char *path) { if (!heliInitialized) return NULL; diff --git a/src/common.h b/src/common.h index d2a2000..49d9da8 100644 --- a/src/common.h +++ b/src/common.h @@ -21,6 +21,9 @@ typedef struct _Directory *Directory; int randomNumber(int min, int max); double randomFloat(); +void rotateVector(double *x, double *y, double angle); + + Directory openDirectory(const char *path); void closeDirectory(Directory directory); int directoryGetCount(Directory directory); diff --git a/src/drawing.c b/src/drawing.c index 4a22d8e..3e1d383 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -35,6 +35,9 @@ void heliDrawingApplyTexture(double *color, HeliTextureState *state) { glColor4dv(color); unsigned int texid = state->animation ? animationGetGLTexId(state->animation) : 0; if (texid) { + HeliPair *pair = heliUIntGet(&heliDrawingFramebuffersToFlush, texid); + if (pair) framebufferFlush((Framebuffer)pair->value); + unsigned int mode = state->fixed ? GL_EYE_LINEAR : GL_OBJECT_LINEAR; unsigned int param = state->fixed ? GL_EYE_PLANE : GL_OBJECT_PLANE; @@ -173,6 +176,8 @@ void targetEx(Framebuffer framebuffer, int updateViewport, int updateProjection) unsigned int id = framebufferGetGLId(framebuffer); heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, id); heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, id); + unsigned int texid = framebufferGetGLTexId(framebuffer); + if (texid) heliUIntAdd(&heliDrawingFramebuffersToFlush, texid, framebuffer, NULL); } if (updateViewport) { viewportByFramebuffer(framebuffer); @@ -771,7 +776,7 @@ void resetState() { resetStateEx(STATE_ALL); } void resetStateEx(unsigned int flags) { - if (flags & STATE_FILL_COLOR ) fill(colorByRGBA(0.5, 0.5, 0.5, 1)); + if (flags & STATE_FILL_COLOR ) fill(colorByRGBA(1, 1, 1, 1)); if (flags & STATE_FILL_TEXTURE ) noFillTexture(); if (flags & STATE_STROKE_COLOR ) stroke(colorByRGBA(0, 0, 0, 1)); if (flags & STATE_STROKE_TEXTURE ) noStrokeTexture(); @@ -861,4 +866,5 @@ void heliDrawingFinish() { free(path); path = NULL; pathAllocated = 0; + heliArrayDestroy(&heliDrawingFramebuffersToFlush); } diff --git a/src/framebuffer.c b/src/framebuffer.c index 0cf3e21..f2b02b3 100644 --- a/src/framebuffer.c +++ b/src/framebuffer.c @@ -5,17 +5,22 @@ #include "framebuffer.h" -struct _Framebuffer { - int width; - int height; +typedef struct _HeliFramebufferDesc { unsigned int texture_id; unsigned int renderbuffer_id; unsigned int framebuffer_id; +} HeliFramebufferDesc; + +struct _Framebuffer { + int width; + int height; + HeliFramebufferDesc base; + HeliFramebufferDesc multisample; }; static void heliInitFramebuffer( - Framebuffer fb, + HeliFramebufferDesc *fbd, int width, int height, const void *pixels, @@ -25,76 +30,71 @@ static void heliInitFramebuffer( int multisample, int simple ) { - fb->width = width; - fb->height = height; - fb->texture_id = 0; - fb->renderbuffer_id = 0; - fb->framebuffer_id = 0; + fbd->texture_id = 0; + fbd->renderbuffer_id = 0; + fbd->framebuffer_id = 0; + + unsigned int texTargetBinding = multisample ? GL_TEXTURE_BINDING_2D_MULTISAMPLE : GL_TEXTURE_BINDING_2D; + unsigned int texTarget = multisample ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; unsigned int prev = 0; - glGetIntegerv(GL_TEXTURE_BINDING_2D, (int*)&prev); - glGenTextures(1, &fb->texture_id); - glBindTexture(GL_TEXTURE_2D, fb->texture_id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, smooth ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, smooth ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, horWrap ? GL_REPEAT : GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, vertWrap ? GL_REPEAT : GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.7f); - if (multisample) - heliGLTexImage2DMultisamplePtr(GL_TEXTURE_2D_MULTISAMPLE, multisample, GL_RGBA, fb->width, fb->height, GL_TRUE); - else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fb->width, fb->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - glBindTexture(GL_TEXTURE_2D, prev); + glGetIntegerv(texTargetBinding, (int*)&prev); + glGenTextures(1, &fbd->texture_id); + glBindTexture(texTarget, fbd->texture_id); + if (multisample) { + heliGLTexImage2DMultisamplePtr(texTarget, multisample, GL_RGBA, width, height, GL_TRUE); + } else { + glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, smooth ? GL_LINEAR : GL_NEAREST); + glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, smooth ? GL_LINEAR : GL_NEAREST); + glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, horWrap ? GL_REPEAT : GL_CLAMP_TO_EDGE); + glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, vertWrap ? GL_REPEAT : GL_CLAMP_TO_EDGE); + glTexImage2D(texTarget, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + } + glBindTexture(texTarget, prev); if (!simple) { glGetIntegerv(GL_RENDERBUFFER_BINDING, (int*)&prev); - heliGLGenRenderbuffersPtr(1, &fb->renderbuffer_id); - heliGLBindRenderbufferPtr(GL_RENDERBUFFER, fb->renderbuffer_id); - if (multisample) - heliGLRenderbufferStorageMultisamplePtr(GL_RENDERBUFFER, multisample, GL_STENCIL_INDEX8, fb->width, fb->height); - else - heliGLRenderbufferStoragePtr(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, fb->width, fb->height); + heliGLGenRenderbuffersPtr(1, &fbd->renderbuffer_id); + heliGLBindRenderbufferPtr(GL_RENDERBUFFER, fbd->renderbuffer_id); + if (multisample) heliGLRenderbufferStorageMultisamplePtr(GL_RENDERBUFFER, multisample, GL_DEPTH24_STENCIL8, width, height); + else heliGLRenderbufferStoragePtr(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); heliGLBindRenderbufferPtr(GL_RENDERBUFFER, prev); } glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (int*)&prev); - heliGLGenFramebuffersPtr(1, &fb->framebuffer_id); - heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, fb->framebuffer_id); - if (fb->renderbuffer_id) - heliGLFramebufferRenderbufferPtr(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->renderbuffer_id); - if (multisample) - heliGLFramebufferTexture2DPtr(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, fb->texture_id, 0); - else - heliGLFramebufferTexture2DPtr(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture_id, 0); + heliGLGenFramebuffersPtr(1, &fbd->framebuffer_id); + heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, fbd->framebuffer_id); + if (fbd->renderbuffer_id) + heliGLFramebufferRenderbufferPtr(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbd->renderbuffer_id); + heliGLFramebufferTexture2DPtr(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texTarget, fbd->texture_id, 0); heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, prev); } -static void heliDeinitFramebuffer(Framebuffer fb) { - if (fb->framebuffer_id) { +static void heliDeinitFramebuffer(HeliFramebufferDesc *fbd) { + if (fbd->framebuffer_id) { unsigned int id = 0; glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (int*)&id); - if (id == fb->framebuffer_id) heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, 0); + if (id == fbd->framebuffer_id) heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, 0); glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, (int*)&id); - if (id == fb->framebuffer_id) heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, 0); - heliGLDeleteFramebuffersPtr(1, &fb->framebuffer_id); - fb->framebuffer_id = 0; + if (id == fbd->framebuffer_id) heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, 0); + heliGLDeleteFramebuffersPtr(1, &fbd->framebuffer_id); + fbd->framebuffer_id = 0; } - if (fb->renderbuffer_id) { - heliGLDeleteRenderbuffersPtr(1, &fb->renderbuffer_id); - fb->renderbuffer_id = 0; + if (fbd->renderbuffer_id) { + heliGLDeleteRenderbuffersPtr(1, &fbd->renderbuffer_id); + fbd->renderbuffer_id = 0; } - if (fb->texture_id) { - glDeleteTextures(1, &fb->texture_id); - fb->texture_id = 0; + if (fbd->texture_id) { + glDeleteTextures(1, &fbd->texture_id); + fbd->texture_id = 0; } - fb->width = 0; - fb->height = 0; } Framebuffer createFramebufferEx(int width, int height, const void *pixels, int horWrap, int vertWrap, int smooth) { Framebuffer fb = calloc(1, sizeof(*fb)); + heliObjectRegister(fb, (HeliFreeCallback)&framebufferDestroy); if (width <= 0 || height <= 0) { fprintf(stderr, "helianthus: cannot create framebuffer, bad size: %dx%d\n", width, height); @@ -106,37 +106,56 @@ Framebuffer createFramebufferEx(int width, int height, const void *pixels, int h return fb; } - if (heliGLTexImage2DMultisamplePtr && heliGLRenderbufferStoragePtr) { + fb->width = width; + fb->height = height; + + heliInitFramebuffer(&fb->base, width, height, pixels, horWrap, vertWrap, smooth, 0, FALSE); + + unsigned int err = 0; + glGetError(); + if (heliGLTexImage2DMultisamplePtr && heliGLRenderbufferStorageMultisamplePtr) { for(int multisample = 8; multisample >= 4; multisample /= 2) { glGetError(); - heliInitFramebuffer(fb, width, height, NULL, horWrap, vertWrap, smooth, multisample, FALSE); - if (glGetError() == GL_NO_ERROR) { + heliInitFramebuffer(&fb->multisample, width, height, NULL, FALSE, FALSE, FALSE, multisample, FALSE); + err = glGetError(); + if (err == GL_NO_ERROR) { if (pixels) { - struct _Framebuffer ffb = {}; - heliInitFramebuffer(&ffb, width, height, pixels, FALSE, FALSE, FALSE, 0, TRUE); - unsigned int prevR = 0, prevD = 0; glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, (int*)&prevR); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (int*)&prevD); - heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, ffb.framebuffer_id); - heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, fb->framebuffer_id); + heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, fb->base.framebuffer_id); + heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, fb->multisample.framebuffer_id); heliGLBlitFramebufferPtr(0, 0, fb->width, fb->height, 0, 0, fb->width, fb->height, GL_COLOR_BUFFER_BIT, GL_NEAREST); heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, prevR); heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, prevD); - - heliDeinitFramebuffer(&ffb); } break; } - heliDeinitFramebuffer(fb); + heliDeinitFramebuffer(&fb->multisample); } } - if (!fb->framebuffer_id) { - fprintf(stderr, "helianthus: cannot initialize multisampling for framebuffer\n"); - heliDeinitFramebuffer(fb); - heliInitFramebuffer(fb, width, height, pixels, horWrap, vertWrap, smooth, 0, FALSE); + unsigned int prevD = 0; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (int*)&prevD); + if (!fb->multisample.framebuffer_id) { + fprintf(stderr, "helianthus: cannot initialize multisampling for framebuffer, OpenGL error code: 0x%04x\n", err); + } else { + heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, fb->multisample.framebuffer_id); + err = heliGLCheckFramebufferStatusPtr(GL_DRAW_FRAMEBUFFER); + if (err != GL_FRAMEBUFFER_COMPLETE) { + fprintf(stderr, "helianthus: multisampling framebuffer in incomplete, status: 0x%04x, OpenGL error code: 0x%04x\n", err, glGetError()); + heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, prevD); + heliDeinitFramebuffer(&fb->multisample); + } } + heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, fb->multisample.framebuffer_id); + err = heliGLCheckFramebufferStatusPtr(GL_DRAW_FRAMEBUFFER); + if (err != GL_FRAMEBUFFER_COMPLETE) { + fprintf(stderr, "helianthus: base framebuffer in incomplete, status: 0x%04x, OpenGL error code: 0x%04x", err, glGetError()); + heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, prevD); + heliDeinitFramebuffer(&fb->base); + } + heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, prevD); return fb; } @@ -157,27 +176,60 @@ Framebuffer createFramebufferFromFile(const char *path) { void framebufferDestroy(Framebuffer framebuffer) { HeliDrawingState *ss = heliDrawingGetState(); - if (framebuffer->framebuffer_id) { + if (framebuffer->base.texture_id) + heliUIntRemove(&heliDrawingFramebuffersToFlush, framebuffer->base.texture_id); + if (framebuffer->base.framebuffer_id) { for(HeliDrawingState *s = heliDrawingGetStateStack(); s <= ss; ++s) { - if (ss->glState.framebuffer_read_id == framebuffer->framebuffer_id) + if (ss->glState.framebuffer_read_id == framebuffer->base.framebuffer_id) ss->glState.framebuffer_read_id = 0; - if (ss->glState.framebuffer_draw_id == framebuffer->framebuffer_id) + if (ss->glState.framebuffer_draw_id == framebuffer->base.framebuffer_id) ss->glState.framebuffer_draw_id = 0; } } - heliDeinitFramebuffer(framebuffer); + if (framebuffer->multisample.framebuffer_id) { + for(HeliDrawingState *s = heliDrawingGetStateStack(); s <= ss; ++s) { + if (ss->glState.framebuffer_read_id == framebuffer->multisample.framebuffer_id) + ss->glState.framebuffer_read_id = 0; + if (ss->glState.framebuffer_draw_id == framebuffer->multisample.framebuffer_id) + ss->glState.framebuffer_draw_id = 0; + } + } + heliDeinitFramebuffer(&framebuffer->multisample); + heliDeinitFramebuffer(&framebuffer->base); free(framebuffer); } +void framebufferFlush(Framebuffer framebuffer) { + if (framebuffer->base.texture_id) + heliUIntRemove(&heliDrawingFramebuffersToFlush, framebuffer->base.texture_id); + if (framebuffer->base.framebuffer_id && framebuffer->multisample.framebuffer_id) { + unsigned int prevR = 0, prevD = 0; + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, (int*)&prevR); + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (int*)&prevD); + heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, framebuffer->multisample.framebuffer_id); + heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, framebuffer->base.framebuffer_id); + heliGLBlitFramebufferPtr( + 0, 0, framebuffer->width, framebuffer->height, + 0, 0, framebuffer->width, framebuffer->height, + GL_COLOR_BUFFER_BIT, GL_NEAREST ); + heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, prevR); + heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, prevD); + } +} + + int framebufferGetWidth(Framebuffer framebuffer) { return framebuffer->width; } int framebufferGetHeight(Framebuffer framebuffer) { return framebuffer->height; } unsigned int framebufferGetGLTexId(Framebuffer framebuffer) - { return framebuffer->texture_id; } -unsigned int framebufferGetGLId(Framebuffer framebuffer) - { return framebuffer->framebuffer_id; } + { return framebuffer->base.texture_id; } +unsigned int framebufferGetGLId(Framebuffer framebuffer) { + return framebuffer->multisample.framebuffer_id + ? framebuffer->multisample.framebuffer_id + : framebuffer->base.framebuffer_id; +} int imageFromViewport(int *outWidth, int *outHeight, unsigned char **outPixels) { @@ -201,20 +253,20 @@ int imageFromViewport(int *outWidth, int *outHeight, unsigned char **outPixels) } // blit multisample buffer - struct _Framebuffer ffb = {}; - heliInitFramebuffer(&ffb, vp[2], vp[3], NULL, FALSE, FALSE, FALSE, 0, TRUE); + HeliFramebufferDesc fbd = {}; + heliInitFramebuffer(&fbd, vp[2], vp[3], NULL, FALSE, FALSE, FALSE, 0, TRUE); unsigned int prevR = 0, prevD = 0; glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, (int*)&prevR); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (int*)&prevD); - heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, ffb.framebuffer_id); + heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, fbd.framebuffer_id); heliGLBlitFramebufferPtr(vp[0], vp[1], vp[2], vp[3], 0, 0, vp[2], vp[3], GL_COLOR_BUFFER_BIT, GL_NEAREST); - heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, ffb.framebuffer_id); + heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, fbd.framebuffer_id); glReadPixels(0, 0, vp[2], vp[3], GL_RGBA, GL_UNSIGNED_BYTE, buffer); heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, prevR); heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, prevD); - heliDeinitFramebuffer(&ffb); + heliDeinitFramebuffer(&fbd); } // flip image diff --git a/src/framebuffer.h b/src/framebuffer.h index 8024712..93402f4 100644 --- a/src/framebuffer.h +++ b/src/framebuffer.h @@ -12,6 +12,7 @@ Framebuffer createFramebufferEx(int width, int height, const void *pixels, int h Framebuffer createFramebufferFromFile(const char *path); void framebufferDestroy(Framebuffer framebuffer); +void framebufferFlush(Framebuffer framebuffer); int framebufferGetWidth(Framebuffer framebuffer); int framebufferGetHeight(Framebuffer framebuffer); unsigned int framebufferGetGLTexId(Framebuffer framebuffer); diff --git a/src/gl.c b/src/gl.c index ab0b92b..6ff5afe 100644 --- a/src/gl.c +++ b/src/gl.c @@ -12,6 +12,7 @@ HeliGLBindFramebufferPtr heliGLBindFramebufferPtr; HeliGLBlitFramebufferPtr heliGLBlitFramebufferPtr; HeliGLFramebufferRenderbufferPtr heliGLFramebufferRenderbufferPtr; HeliGLFramebufferTexture2DPtr heliGLFramebufferTexture2DPtr; +HeliGLCheckFramebufferStatusPtr heliGLCheckFramebufferStatusPtr; HeliGLGenRenderbuffersPtr heliGLGenRenderbuffersPtr; HeliGLDeleteRenderbuffersPtr heliGLDeleteRenderbuffersPtr; HeliGLBindRenderbufferPtr heliGLBindRenderbufferPtr; diff --git a/src/private.h b/src/private.h index dc1d0e9..54f0fc3 100644 --- a/src/private.h +++ b/src/private.h @@ -88,6 +88,11 @@ HeliPair* heliMapAdd( void *v, HeliFreeCallback fv ); int heliMapRemove(HeliArray *a, const void *k, HeliCompareCallback cmp); +HeliPair* heliUIntFind(HeliArray *a, size_t k, int *gtOrEqIndex); +HeliPair* heliUIntGet(HeliArray *a, size_t k); +HeliPair* heliUIntAdd(HeliArray *a, size_t k, void *v, HeliFreeCallback fv); +int heliUIntRemove(HeliArray *a, size_t k); + HeliPair* heliStringmapFind(HeliArray *a, const char *k, int *gtOrEqIndex); HeliPair* heliStringmapGet(HeliArray *a, const char *k); HeliPair* heliStringmapAdd(HeliArray *a, const char *k, void *v, HeliFreeCallback fv); @@ -131,6 +136,7 @@ typedef void (APIENTRY *HeliGLBindFramebufferPtr)(GLenum target, GLuint framebuf typedef void (APIENTRY *HeliGLBlitFramebufferPtr)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); typedef void (APIENTRY *HeliGLFramebufferRenderbufferPtr)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); typedef void (APIENTRY *HeliGLFramebufferTexture2DPtr)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef GLenum (APIENTRY *HeliGLCheckFramebufferStatusPtr)(GLenum target); typedef void (APIENTRY *HeliGLGenRenderbuffersPtr)(GLsizei n, GLuint *renderbuffers); typedef void (APIENTRY *HeliGLDeleteRenderbuffersPtr)(GLsizei n, const GLuint *renderbuffers); typedef void (APIENTRY *HeliGLBindRenderbufferPtr)(GLenum target, GLuint renderbuffer); @@ -146,6 +152,7 @@ extern HeliGLBindFramebufferPtr heliGLBindFramebufferPtr; extern HeliGLBlitFramebufferPtr heliGLBlitFramebufferPtr; extern HeliGLFramebufferRenderbufferPtr heliGLFramebufferRenderbufferPtr; extern HeliGLFramebufferTexture2DPtr heliGLFramebufferTexture2DPtr; +extern HeliGLCheckFramebufferStatusPtr heliGLCheckFramebufferStatusPtr; extern HeliGLGenRenderbuffersPtr heliGLGenRenderbuffersPtr; extern HeliGLDeleteRenderbuffersPtr heliGLDeleteRenderbuffersPtr; extern HeliGLBindRenderbufferPtr heliGLBindRenderbufferPtr; @@ -193,6 +200,8 @@ typedef struct _HeliDrawingState { HeliGLCommonState glState; } HeliDrawingState; +HeliArray heliDrawingFramebuffersToFlush; + HeliDrawingState *heliDrawingGetState(); HeliDrawingState *heliDrawingGetStateStack(); void heliDrawingApplyTexture(double *color, HeliTextureState *state); diff --git a/src/sprite.c b/src/sprite.c index eb68379..71a51d8 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -447,6 +447,12 @@ double spriteGetDirection(Sprite sprite) { } void spritePointTo(Sprite sprite, double x, double y) { spriteSetRotation( sprite, atan2(y - sprite->y, x - sprite->x)*(180/PI) ); } +void spriteMoveBy(Sprite sprite, double dx, double dy) + { spriteSetXY(sprite, spriteGetX(sprite) + dx, spriteGetY(sprite) + dy); } +void spriteMoveToDirection(Sprite sprite, double distance, double angle) { + double a = angle*PI/180.0; + spriteMoveBy(sprite, cos(a)*distance, sin(a)*distance); +} double spriteGetScaledWidth(Sprite sprite) { return sprite->width * sprite->scale; } diff --git a/src/sprite.h b/src/sprite.h index c2451d3..c2dbc9f 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -122,6 +122,8 @@ void spriteSetSpeedAndDirection(Sprite sprite, double speed, double angle); double spriteGetSpeed(Sprite sprite); double spriteGetDirection(Sprite sprite); void spritePointTo(Sprite sprite, double x, double y); +void spriteMoveBy(Sprite sprite, double dx, double dy); +void spriteMoveToDirection(Sprite sprite, double distance, double angle); double spriteGetScaledWidth(Sprite sprite); double spriteGetScaledHeight(Sprite sprite); diff --git a/src/world.c b/src/world.c index 1ed4331..c103935 100644 --- a/src/world.c +++ b/src/world.c @@ -392,6 +392,7 @@ static int init() { heliGLBlitFramebufferPtr = SDL_GL_GetProcAddress("glBlitFramebuffer"); heliGLFramebufferRenderbufferPtr = SDL_GL_GetProcAddress("glFramebufferRenderbuffer"); heliGLFramebufferTexture2DPtr = SDL_GL_GetProcAddress("glFramebufferTexture2D"); + heliGLCheckFramebufferStatusPtr = SDL_GL_GetProcAddress("glCheckFramebufferStatus"); heliGLGenRenderbuffersPtr = SDL_GL_GetProcAddress("glGenRenderbuffers"); heliGLDeleteRenderbuffersPtr = SDL_GL_GetProcAddress("glDeleteRenderbuffers"); heliGLBindRenderbufferPtr = SDL_GL_GetProcAddress("glBindRenderbuffer");