|
|
deef1d |
|
|
|
deef1d |
#include "private.h"
|
|
|
deef1d |
#include "drawing.h"
|
|
|
deef1d |
|
|
|
deef1d |
|
|
|
1d641c |
HeliGLBlendFuncSeparatePtr heliGLBlendFuncSeparatePtr;
|
|
|
1d641c |
HeliGLStencilOpSeparatePtr heliGLStencilOpSeparatePtr;
|
|
|
1d641c |
HeliGLTexImage2DMultisamplePtr heliGLTexImage2DMultisamplePtr;
|
|
|
1d641c |
HeliGLGenFramebuffersPtr heliGLGenFramebuffersPtr;
|
|
|
1d641c |
HeliGLDeleteFramebuffersPtr heliGLDeleteFramebuffersPtr;
|
|
|
1d641c |
HeliGLBindFramebufferPtr heliGLBindFramebufferPtr;
|
|
|
1d641c |
HeliGLBlitFramebufferPtr heliGLBlitFramebufferPtr;
|
|
|
1d641c |
HeliGLFramebufferRenderbufferPtr heliGLFramebufferRenderbufferPtr;
|
|
|
1d641c |
HeliGLFramebufferTexture2DPtr heliGLFramebufferTexture2DPtr;
|
|
|
909bc2 |
HeliGLCheckFramebufferStatusPtr heliGLCheckFramebufferStatusPtr;
|
|
|
1d641c |
HeliGLGenRenderbuffersPtr heliGLGenRenderbuffersPtr;
|
|
|
1d641c |
HeliGLDeleteRenderbuffersPtr heliGLDeleteRenderbuffersPtr;
|
|
|
1d641c |
HeliGLBindRenderbufferPtr heliGLBindRenderbufferPtr;
|
|
|
1d641c |
HeliGLRenderbufferStoragePtr heliGLRenderbufferStoragePtr;
|
|
|
1d641c |
HeliGLRenderbufferStorageMultisamplePtr heliGLRenderbufferStorageMultisamplePtr;
|
|
|
1d641c |
|
|
|
1d641c |
unsigned int heliGLWindowFramebufferReadId = 0;
|
|
|
1d641c |
unsigned int heliGLWindowFramebufferDrawId = 0;
|
|
|
1d641c |
|
|
|
1d641c |
|
|
|
deef1d |
double heliGLGetAAResolution() {
|
|
|
deef1d |
if (!heliGLIsIntegerClipping()) return 0;
|
|
|
deef1d |
|
|
|
deef1d |
double proj[16] = {};
|
|
|
deef1d |
double model[16] = {};
|
|
|
deef1d |
glGetDoublev(GL_PROJECTION_MATRIX, proj);
|
|
|
deef1d |
glGetDoublev(GL_MODELVIEW_MATRIX, model);
|
|
|
deef1d |
|
|
|
deef1d |
double full[16] = {};
|
|
|
deef1d |
double fullinv[16] = {};
|
|
|
deef1d |
heliMatrix4Mult(full, proj, model);
|
|
|
deef1d |
|
|
|
deef1d |
full[8] = 0, full[9] = 0, full[10] = 1, full[11] = 0; // assume z is zero
|
|
|
deef1d |
if (!heliMatrix4Invert(fullinv, full)) return 0;
|
|
|
deef1d |
|
|
|
deef1d |
if (fabs(fullinv[15]) < HELI_PRECISION_SQR) return 0; // bad perspective
|
|
|
deef1d |
double k = 1/fullinv[15];
|
|
|
deef1d |
|
|
|
deef1d |
if ( fabs(fullinv[3]*k) > 1e-5
|
|
|
deef1d |
|| fabs(fullinv[7]*k) > 1e-5 ) return 0; // perspective distortion
|
|
|
deef1d |
|
|
|
deef1d |
int rect[4] = {}; // x, y, w, h
|
|
|
deef1d |
glGetIntegerv(GL_VIEWPORT, rect);
|
|
|
deef1d |
double w = rect[2], h = rect[3];
|
|
|
deef1d |
|
|
|
deef1d |
double m00 = fullinv[0]*k*2/w, m01 = fullinv[1]*k*2/w,
|
|
|
deef1d |
m10 = fullinv[4]*k*2/h, m11 = fullinv[5]*k*2/h;
|
|
|
deef1d |
double l0 = sqrt(m00*m00 + m01*m01);
|
|
|
deef1d |
double l1 = sqrt(m10*m10 + m11*m11);
|
|
|
deef1d |
if (l0 > l1) { double l = l0; l0 = l1; l1 = l; }
|
|
|
deef1d |
if (l0 < HELI_PRECISION || l1 < HELI_PRECISION) return 0;
|
|
|
deef1d |
if (l0/l1 < 0.75) return 0; // to big aspect ratio
|
|
|
deef1d |
|
|
|
deef1d |
return sqrt(l0*l1);
|
|
|
deef1d |
}
|
|
|
deef1d |
|
|
|
deef1d |
|
|
|
812e27 |
double heliGLGetPixelSize() {
|
|
|
812e27 |
double proj[16] = {};
|
|
|
812e27 |
double model[16] = {};
|
|
|
812e27 |
glGetDoublev(GL_PROJECTION_MATRIX, proj);
|
|
|
812e27 |
glGetDoublev(GL_MODELVIEW_MATRIX, model);
|
|
|
812e27 |
|
|
|
812e27 |
double full[16] = {};
|
|
|
812e27 |
double fullinv[16] = {};
|
|
|
812e27 |
heliMatrix4Mult(full, proj, model);
|
|
|
812e27 |
|
|
|
812e27 |
full[8] = 0, full[9] = 0, full[10] = 1, full[11] = 0; // assume z is zero
|
|
|
812e27 |
if (!heliMatrix4Invert(fullinv, full)) return 0;
|
|
|
812e27 |
|
|
|
812e27 |
if (fabs(fullinv[15]) <= HELI_PRECISION_SQR) return 0; // bad perspective
|
|
|
812e27 |
double k = 1/fullinv[15];
|
|
|
812e27 |
|
|
|
812e27 |
if ( fabs(fullinv[3]*k) > 1e-5
|
|
|
812e27 |
|| fabs(fullinv[7]*k) > 1e-5 ) return 0; // perspective distortion
|
|
|
812e27 |
|
|
|
812e27 |
int rect[4] = {}; // x, y, w, h
|
|
|
812e27 |
glGetIntegerv(GL_VIEWPORT, rect);
|
|
|
812e27 |
double w = rect[2], h = rect[3];
|
|
|
812e27 |
|
|
|
812e27 |
double m00 = fullinv[0]*k*2/w, m01 = fullinv[1]*k*2/w,
|
|
|
812e27 |
m10 = fullinv[4]*k*2/h, m11 = fullinv[5]*k*2/h;
|
|
|
812e27 |
double l0 = sqrt(m00*m00 + m01*m01);
|
|
|
812e27 |
double l1 = sqrt(m10*m10 + m11*m11);
|
|
|
812e27 |
if (l0 > l1) { double l = l0; l0 = l1; l1 = l; }
|
|
|
812e27 |
if (l0 <= HELI_PRECISION && l1 <= HELI_PRECISION) return 0;
|
|
|
812e27 |
|
|
|
b4b587 |
double l = sqrt(l0*l1);
|
|
|
812e27 |
return l <= HELI_PRECISION ? 0 : l;
|
|
|
812e27 |
}
|
|
|
812e27 |
|
|
|
812e27 |
|
|
|
deef1d |
static int isInteger(double x)
|
|
|
deef1d |
{ return fabs(floor(x + 0.5) - x) > 0.01; }
|
|
|
deef1d |
|
|
|
deef1d |
int heliGLIsIntegerClipping() {
|
|
|
deef1d |
double proj[16] = {};
|
|
|
deef1d |
double model[16] = {};
|
|
|
deef1d |
double viewproj[16] = {};
|
|
|
deef1d |
double viewmodel[16] = {};
|
|
|
deef1d |
|
|
|
deef1d |
int rect[4] = {}; // x, y, w, h
|
|
|
deef1d |
glGetIntegerv(GL_VIEWPORT, rect);
|
|
|
deef1d |
double hw = 0.5*rect[2], hh = 0.5*rect[3];
|
|
|
deef1d |
double view[16] = {
|
|
|
deef1d |
hw, 0, 0, 0,
|
|
|
deef1d |
0,-hh, 0, 0,
|
|
|
deef1d |
0, 0, 1, 0,
|
|
|
deef1d |
hw, hh, 0, 1 };
|
|
|
deef1d |
|
|
|
deef1d |
glGetDoublev(GL_PROJECTION_MATRIX, proj);
|
|
|
deef1d |
glGetDoublev(GL_MODELVIEW_MATRIX, model);
|
|
|
deef1d |
heliMatrix4Mult(viewproj, view, proj);
|
|
|
deef1d |
heliMatrix4Mult(viewmodel, viewproj, model);
|
|
|
deef1d |
|
|
|
deef1d |
int badMatrix = FALSE;
|
|
|
deef1d |
if (fabs(viewmodel[15]) < HELI_PRECISION_SQR) badMatrix = TRUE; // bad perspective
|
|
|
deef1d |
double k = badMatrix ? 0 : 1/viewmodel[15];
|
|
|
deef1d |
if ( fabs(viewmodel[3]*k) > 1e-5
|
|
|
deef1d |
|| fabs(viewmodel[7]*k) > 1e-5 ) badMatrix = TRUE; // perspective distortion
|
|
|
deef1d |
|
|
|
deef1d |
HeliGLCommonState s;
|
|
|
deef1d |
const int clipCount = (int)(sizeof(s.clipPlanes)/sizeof(*s.clipPlanes));
|
|
|
deef1d |
//glGetIntegerv(GL_MAX_CLIP_PLANES, &clipCount);
|
|
|
deef1d |
double eq[4] = {}, eqv[4] = {};
|
|
|
deef1d |
for(int i = 0; i < clipCount; ++i) {
|
|
|
deef1d |
if (!glIsEnabled(GL_CLIP_PLANE0 + i)) continue;
|
|
|
deef1d |
if (badMatrix) return FALSE;
|
|
|
deef1d |
|
|
|
deef1d |
glGetClipPlane(GL_CLIP_PLANE0 + i, eq);
|
|
|
deef1d |
heliMatrix4MultVec(eqv, viewproj, eq);
|
|
|
deef1d |
double a = (eqv[0] + eqv[2]*viewmodel[2])*k;
|
|
|
deef1d |
double b = (eqv[1] + eqv[2]*viewmodel[6])*k;
|
|
|
deef1d |
double c = eqv[2]*viewmodel[14]*k + 1;
|
|
|
deef1d |
|
|
|
deef1d |
if (fabs(a) > 1e-5 && fabs(b) > 1e-5) return FALSE;
|
|
|
deef1d |
if (fabs(a) > 1e-5 && !isInteger(c/a)) return FALSE;
|
|
|
deef1d |
if (fabs(b) > 1e-5 && !isInteger(b/a)) return FALSE;
|
|
|
deef1d |
}
|
|
|
deef1d |
|
|
|
deef1d |
return TRUE;
|
|
|
deef1d |
}
|
|
|
deef1d |
|
|
|
4e392e |
int heliGLTransform(double *x, double *y, int reverse) {
|
|
|
deef1d |
double proj[16] = {};
|
|
|
deef1d |
double model[16] = {};
|
|
|
deef1d |
double viewproj[16] = {};
|
|
|
deef1d |
double viewmodel[16] = {};
|
|
|
deef1d |
double inv[16] = {};
|
|
|
deef1d |
|
|
|
deef1d |
double v[2][4] = {
|
|
|
deef1d |
{ *x, *y, 0, 1 },
|
|
|
deef1d |
{ *x, *y, 1, 1 } };
|
|
|
deef1d |
double vv[2][4] = {};
|
|
|
deef1d |
*x = 0; *y = 0;
|
|
|
4e392e |
|
|
|
deef1d |
int rect[4] = {}; // x, y, w, h
|
|
|
deef1d |
glGetIntegerv(GL_VIEWPORT, rect);
|
|
|
deef1d |
double hw = 0.5*rect[2], hh = 0.5*rect[3];
|
|
|
deef1d |
double view[16] = {
|
|
|
deef1d |
hw, 0, 0, 0,
|
|
|
deef1d |
0,-hh, 0, 0,
|
|
|
deef1d |
0, 0, 1, 0,
|
|
|
deef1d |
hw, hh, 0, 1 };
|
|
|
deef1d |
|
|
|
deef1d |
glGetDoublev(GL_PROJECTION_MATRIX, proj);
|
|
|
deef1d |
glGetDoublev(GL_MODELVIEW_MATRIX, model);
|
|
|
deef1d |
heliMatrix4Mult(viewproj, view, proj);
|
|
|
deef1d |
heliMatrix4Mult(viewmodel, viewproj, model);
|
|
|
deef1d |
|
|
|
4e392e |
if (reverse) {
|
|
|
4e392e |
if (!heliMatrix4Invert(inv, viewmodel))
|
|
|
4e392e |
return FALSE;
|
|
|
4e392e |
heliMatrix4MultVec(vv[0], inv, v[0]);
|
|
|
4e392e |
heliMatrix4MultVec(vv[1], inv, v[1]);
|
|
|
4e392e |
} else {
|
|
|
4e392e |
heliMatrix4MultVec(vv[0], viewmodel, v[0]);
|
|
|
4e392e |
heliMatrix4MultVec(vv[1], viewmodel, v[1]);
|
|
|
4e392e |
}
|
|
|
deef1d |
|
|
|
deef1d |
double l = vv[0][2] - vv[1][2];
|
|
|
deef1d |
if (fabs(l) <= HELI_PRECISION) return FALSE;
|
|
|
deef1d |
l = vv[0][2]/l;
|
|
|
deef1d |
|
|
|
deef1d |
double kw = vv[0][3] + (vv[1][3] - vv[0][3])*l;
|
|
|
deef1d |
if (fabs(kw) <= HELI_PRECISION) return FALSE;
|
|
|
deef1d |
kw = 1/kw;
|
|
|
deef1d |
|
|
|
deef1d |
*x = (vv[0][0] + (vv[1][0] - vv[0][0])*l)*kw;
|
|
|
deef1d |
*y = (vv[0][1] + (vv[1][1] - vv[0][1])*l)*kw;
|
|
|
deef1d |
return TRUE;
|
|
|
deef1d |
}
|
|
|
deef1d |
|
|
|
deef1d |
|
|
|
deef1d |
void heliGLGetCommonState(HeliGLCommonState *state, unsigned int flags) {
|
|
|
deef1d |
memset(state, 0, sizeof(*state));
|
|
|
deef1d |
state->flags = flags;
|
|
|
deef1d |
|
|
|
deef1d |
if (state->flags & STATE_TRANSFORM)
|
|
|
deef1d |
glGetDoublev(GL_MODELVIEW_MATRIX, state->modelviewMatrix);
|
|
|
deef1d |
|
|
|
deef1d |
if (state->flags & STATE_CLIP) {
|
|
|
deef1d |
const int clipCount = (int)(sizeof(state->clipPlanes)/sizeof(*state->clipPlanes));
|
|
|
deef1d |
for(int i = 0; i < clipCount; ++i) {
|
|
|
deef1d |
state->clipPlanes[i].enabled = glIsEnabled(GL_CLIP_PLANE0 + i) != 0;
|
|
|
deef1d |
glGetClipPlane(GL_CLIP_PLANE0 + i, state->clipPlanes[i].equation);
|
|
|
deef1d |
}
|
|
|
deef1d |
}
|
|
|
1d641c |
|
|
|
1d641c |
if (state->flags & STATE_TARGET_FRAMEBUFFER) {
|
|
|
1d641c |
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, (int*)&state->framebuffer_read_id);
|
|
|
1d641c |
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (int*)&state->framebuffer_draw_id);
|
|
|
1d641c |
}
|
|
|
1d641c |
if (state->flags & STATE_TARGET_VIEWPORT)
|
|
|
1d641c |
glGetIntegerv(GL_VIEWPORT, state->viewport);
|
|
|
1d641c |
if (state->flags & STATE_TARGET_PROJECTION)
|
|
|
1d641c |
glGetDoublev(GL_PROJECTION_MATRIX, state->projectionMatrix);
|
|
|
d6f40c |
if (state->flags & STATE_BACKGROUND)
|
|
|
d6f40c |
glGetDoublev(GL_COLOR_CLEAR_VALUE, state->clearColor);
|
|
|
deef1d |
}
|
|
|
deef1d |
|
|
|
deef1d |
|
|
|
deef1d |
void heliGLSetCommonState(const HeliGLCommonState *state) {
|
|
|
deef1d |
int loadClip = state->flags & STATE_CLIP;
|
|
|
89ec47 |
int loadTransform = state->flags & STATE_TRANSFORM;
|
|
|
deef1d |
if (loadClip) {
|
|
|
deef1d |
unsigned int mode;
|
|
|
deef1d |
glGetIntegerv(GL_MATRIX_MODE, (int*)&mode);
|
|
|
deef1d |
glMatrixMode(GL_MODELVIEW);
|
|
|
deef1d |
if (!loadTransform) glPushMatrix();
|
|
|
cafd47 |
glLoadIdentity();
|
|
|
deef1d |
const int clipCount = (int)(sizeof(state->clipPlanes)/sizeof(*state->clipPlanes));
|
|
|
deef1d |
for(int i = 0; i < clipCount; ++i) {
|
|
|
deef1d |
if (state->clipPlanes[i].enabled) glEnable(GL_CLIP_PLANE0+i);
|
|
|
deef1d |
else glDisable(GL_CLIP_PLANE0+i);
|
|
|
deef1d |
glClipPlane(GL_CLIP_PLANE0+i, state->clipPlanes[i].equation);
|
|
|
deef1d |
}
|
|
|
deef1d |
if (!loadTransform) glPopMatrix(); else glLoadMatrixd(state->modelviewMatrix);
|
|
|
deef1d |
glMatrixMode(mode);
|
|
|
deef1d |
} else
|
|
|
deef1d |
if (loadTransform) {
|
|
|
deef1d |
unsigned int mode;
|
|
|
deef1d |
glGetIntegerv(GL_MATRIX_MODE, (int*)&mode);
|
|
|
deef1d |
glMatrixMode(GL_MODELVIEW);
|
|
|
deef1d |
glLoadMatrixd(state->modelviewMatrix);
|
|
|
deef1d |
glMatrixMode(mode);
|
|
|
deef1d |
}
|
|
|
1d641c |
|
|
|
1d641c |
if (state->flags & STATE_TARGET_FRAMEBUFFER) {
|
|
|
1d641c |
if (heliGLBindFramebufferPtr) {
|
|
|
1d641c |
heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, state->framebuffer_draw_id);
|
|
|
1d641c |
heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, state->framebuffer_read_id);
|
|
|
1d641c |
}
|
|
|
1d641c |
}
|
|
|
1d641c |
if (state->flags & STATE_TARGET_VIEWPORT)
|
|
|
1d641c |
glViewport(state->viewport[0], state->viewport[1], state->viewport[2], state->viewport[3]);
|
|
|
1d641c |
if (state->flags & STATE_TARGET_PROJECTION) {
|
|
|
1d641c |
unsigned int mode;
|
|
|
1d641c |
glGetIntegerv(GL_MATRIX_MODE, (int*)&mode);
|
|
|
1d641c |
glMatrixMode(GL_PROJECTION);
|
|
|
1d641c |
glLoadMatrixd(state->projectionMatrix);
|
|
|
1d641c |
glMatrixMode(mode);
|
|
|
1d641c |
}
|
|
|
d6f40c |
if (state->flags & STATE_BACKGROUND)
|
|
|
d6f40c |
glClearColor(state->clearColor[0], state->clearColor[1], state->clearColor[2], state->clearColor[3]);
|
|
|
deef1d |
}
|
|
|
deef1d |
|