Files
commandergenius/project/jni/glshim/src/gl/eval.c
2016-10-22 21:12:58 +03:00

335 lines
13 KiB
C
Executable File

// TODO: glIsEnabled(), glGetMap()
// TODO: GL_AUTO_NORMAL
#include "eval.h"
#include "math/eval.h"
static inline map_state_t **get_map_pointer(GLenum target) {
switch (target) {
case GL_MAP1_COLOR_4: return &glstate->map1.color4;
case GL_MAP1_INDEX: return &glstate->map1.index;
case GL_MAP1_TEXTURE_COORD_1: return &glstate->map1.texture1;
case GL_MAP1_TEXTURE_COORD_2: return &glstate->map1.texture2;
case GL_MAP1_TEXTURE_COORD_3: return &glstate->map1.texture3;
case GL_MAP1_TEXTURE_COORD_4: return &glstate->map1.texture4;
case GL_MAP1_VERTEX_3: return &glstate->map1.vertex3;
case GL_MAP1_VERTEX_4: return &glstate->map1.vertex4;
case GL_MAP2_COLOR_4: return &glstate->map2.color4;
case GL_MAP2_INDEX: return &glstate->map2.index;
case GL_MAP2_TEXTURE_COORD_1: return &glstate->map2.texture1;
case GL_MAP2_TEXTURE_COORD_2: return &glstate->map2.texture2;
case GL_MAP2_TEXTURE_COORD_3: return &glstate->map2.texture3;
case GL_MAP2_TEXTURE_COORD_4: return &glstate->map2.texture4;
case GL_MAP2_VERTEX_3: return &glstate->map2.vertex3;
case GL_MAP2_VERTEX_4: return &glstate->map2.vertex4;
default:
printf("libGL: unknown glMap target 0x%x\n", target);
}
return NULL;
}
#define set_map_coords(n) \
map->n._1 = n##1; \
map->n._2 = n##2; \
map->n.d = 1.0/(n##2 - n##1); \
map->n.stride = n##stride; \
map->n.order = n##order;
#define case_state(dims, magic, name) \
case magic: { \
map->width = get_map_width(magic); \
map_statef_t *m = (map_statef_t *)glstate->map##dims.name; \
if (m) { \
if (m->free) \
free((void *)m->points); \
free(m); \
} \
glstate->map##dims.name = (map_state_t *)map; \
break; \
}
#define map_switch(dims) \
switch (target) { \
case_state(dims, GL_MAP##dims##_COLOR_4, color4); \
case_state(dims, GL_MAP##dims##_INDEX, index); \
case_state(dims, GL_MAP##dims##_NORMAL, normal); \
case_state(dims, GL_MAP##dims##_TEXTURE_COORD_1, texture1); \
case_state(dims, GL_MAP##dims##_TEXTURE_COORD_2, texture2); \
case_state(dims, GL_MAP##dims##_TEXTURE_COORD_3, texture3); \
case_state(dims, GL_MAP##dims##_TEXTURE_COORD_4, texture4); \
case_state(dims, GL_MAP##dims##_VERTEX_3, vertex3); \
case_state(dims, GL_MAP##dims##_VERTEX_4, vertex4); \
}
void glshim_glMap1d(GLenum target, GLdouble u1, GLdouble u2,
GLint ustride, GLint uorder, const GLdouble *points) {
noerrorShim();
map_statef_t *map = malloc(sizeof(map_statef_t));
map->type = GL_FLOAT; map->dims = 1; map->free = true;
set_map_coords(u);
map_switch(1);
map->points = copy_eval_double(target, ustride, uorder, 0, 1, points);
}
void glshim_glMap1f(GLenum target, GLfloat u1, GLfloat u2,
GLint ustride, GLint uorder, const GLfloat *points) {
noerrorShim();
map_statef_t *map = malloc(sizeof(map_statef_t));
map->type = GL_FLOAT; map->dims = 1; map->free = false;
set_map_coords(u);
map_switch(1);
map->points = points;
}
void glshim_glMap2d(GLenum target, GLdouble u1, GLdouble u2,
GLint ustride, GLint uorder, GLdouble v1, GLdouble v2,
GLint vstride, GLint vorder, const GLdouble *points) {
noerrorShim();
map_statef_t *map = malloc(sizeof(map_statef_t));
map->type = GL_FLOAT; map->dims = 2; map->free = true;
set_map_coords(u);
set_map_coords(v);
map_switch(2);
map->points = copy_eval_double(target, ustride, uorder, vstride, vorder, points);
}
void glshim_glMap2f(GLenum target, GLfloat u1, GLfloat u2,
GLint ustride, GLint uorder, GLfloat v1, GLfloat v2,
GLint vstride, GLint vorder, const GLfloat *points) {
noerrorShim();
map_statef_t *map = malloc(sizeof(map_statef_t));
map->type = GL_FLOAT; map->dims = 2; map->free = false;
set_map_coords(u);
set_map_coords(v);
map_switch(2);
map->points = points;
}
#undef set_map_coords
#undef case_state
#undef map_switch
#define p_map(d, name, func, code) { \
map_state_t *_map = glstate->map##d.name; \
if (_map) { \
if (_map->type == GL_DOUBLE) { \
map_stated_t *map = (map_stated_t *)_map; \
printf("double: not implemented\n"); \
} else if (_map->type == GL_FLOAT) { \
map_statef_t *map = (map_statef_t *)_map; \
GLfloat out[4]; \
code \
glshim_##func##v(out); \
} \
}}
#define iter_maps(d, code) \
p_map(d, color4, glColor4f, code); \
p_map(d, index, glIndexf, code); \
p_map(d, normal, glNormal3f, code); \
p_map(d, texture1, glTexCoord1f, code); \
p_map(d, texture2, glTexCoord2f, code); \
p_map(d, texture3, glTexCoord3f, code); \
p_map(d, texture4, glTexCoord4f, code); \
p_map(d, vertex3, glVertex3f, code); \
p_map(d, vertex4, glVertex4f, code);
void glshim_glEvalCoord1f(GLfloat u) {
noerrorShim();
iter_maps(1,
GLfloat uu = (u - map->u._1) * map->u.d;
_math_horner_bezier_curve(map->points, out, uu, map->width, map->u.order);
)
}
void glshim_glEvalCoord2f(GLfloat u, GLfloat v) {
noerrorShim();
iter_maps(2,
GLfloat uu = (u - map->u._1) * map->u.d;
GLfloat vv = (v - map->v._1) * map->v.d;
// TODO: GL_AUTONORMAL
_math_horner_bezier_surf((GLfloat *)map->points, out, uu, vv,
map->width, map->u.order, map->v.order);
)
}
#undef p_map
#undef iter_maps
void glshim_glMapGrid1f(GLint un, GLfloat u1, GLfloat u2) {
noerrorShim();
// TODO: double support?
map_statef_t *map;
if (! glstate->map_grid)
glstate->map_grid = malloc(sizeof(map_statef_t));
map = (map_statef_t *)glstate->map_grid;
map->dims = 1;
map->u.n = un;
map->u._1 = u1;
map->u._2 = u2;
}
void glshim_glMapGrid2f(GLint un, GLfloat u1, GLfloat u2,
GLint vn, GLfloat v1, GLfloat v2) {
noerrorShim();
// TODO: double support?
map_statef_t *map;
if (! glstate->map_grid)
glstate->map_grid = malloc(sizeof(map_statef_t));
map = (map_statef_t *)glstate->map_grid;
map->dims = 2;
map->u.n = un;
map->u._1 = u1;
map->u._2 = u2;
map->v.n = vn;
map->v._1 = v1;
map->v._2 = v2;
}
static inline GLenum eval_mesh_prep(map_statef_t **map, GLenum mode) {
if (glstate->map2.vertex4) {
*map = (map_statef_t *)glstate->map2.vertex4;
} else if (glstate->map2.vertex3) {
*map = (map_statef_t *)glstate->map2.vertex3;
} else {
return 0;
}
if ((*map)->type == GL_DOUBLE) {
printf("libGL: GL_DOUBLE map not implemented\n");
return 0;
}
switch (mode) {
case GL_POINT: return GL_POINTS;
case GL_LINE: return GL_LINE_STRIP;
case GL_FILL: return GL_TRIANGLE_STRIP;
case 0: return 1;
default:
printf("unknown glEvalMesh mode: %x\n", mode);
return 0;
}
}
void glshim_glEvalMesh1(GLenum mode, GLint i1, GLint i2) {
noerrorShim();
map_statef_t *map;
GLenum renderMode = eval_mesh_prep(&map, mode);
if (! renderMode)
return;
GLfloat u, du, u1;
du = map->u.d;
GLint i;
glshim_glBegin(renderMode);
for (u = u1, i = i1; i <= i2; i++, u += du) {
glshim_glEvalCoord1f(u);
}
glshim_glEnd();
}
void glshim_glEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) {
noerrorShim();
map_statef_t *map;
GLenum renderMode = eval_mesh_prep(&map, mode);
if (! renderMode)
return;
GLfloat u, du, u1, v, dv, v1;
du = map->u.d;
dv = map->v.d;
GLint i, j;
glshim_glBegin(renderMode);
for (v = v1, j = j1; j <= j2; j++, v += dv) {
for (u = u1, i = i1; i <= i2; i++, u += du) {
glshim_glEvalCoord2f(u, v);
if (mode == GL_FILL)
glshim_glEvalCoord2f(u, v + dv);
}
}
glshim_glEnd();
if (mode == GL_LINE) {
glshim_glBegin(renderMode);
for (u = u1, i = i1; i <= i2; i++, u += du) {
for (v = v1, j = j1; j <= j2; j++, v += dv) {
glshim_glEvalCoord2f(u, v);
}
}
glshim_glEnd();
}
}
void glshim_glEvalPoint1(GLint i) {
map_statef_t *map;
if (eval_mesh_prep(&map, 0))
glshim_glEvalCoord1f(i + map->u.d);
}
void glshim_glEvalPoint2(GLint i, GLint j) {
map_statef_t *map;
if (eval_mesh_prep(&map, 0))
glshim_glEvalCoord2f(i + map->u.d, j + map->v.d);
}
#define GL_GET_MAP(t, type) \
void glshim_glGetMap##t##v(GLenum target, GLenum query, type *v) { \
noerrorShim(); \
map_statef_t *map = *(map_statef_t **)get_map_pointer(target); \
if (map) { \
switch (query) { \
case GL_COEFF: { \
const GLfloat *points = map->points; \
for (int i = 0; i < map->u.order; i++) { \
if (map->dims == 2) { \
for (int j = 0; j < map->v.order; j++) { \
*v++ = *points++; \
} \
} else { \
*v++ = *points++; \
} \
} \
return; \
} \
case GL_ORDER: \
*v++ = map->u.order; \
if (map->dims == 2) \
*v++ = map->v.order; \
return; \
case GL_DOMAIN: \
*v++ = map->u._1; \
*v++ = map->u._2; \
if (map->dims == 2) { \
*v++ = map->u._1; \
*v++ = map->u._2; \
} \
return; \
} \
} \
}
GL_GET_MAP(i, GLint)
GL_GET_MAP(f, GLfloat)
GL_GET_MAP(d, GLdouble)
#undef GL_GET_MAP
//Direct wrapper
void glMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points) AliasExport("glshim_glMap1d");
void glMap1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points) AliasExport("glshim_glMap1f");
void glMap2d(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points) AliasExport("glshim_glMap2d");
void glMap2f(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points) AliasExport("glshim_glMap2f");
void glEvalCoord1f(GLfloat u) AliasExport("glshim_glEvalCoord1f");
void glEvalCoord2f(GLfloat u, GLfloat v) AliasExport("glshim_glEvalCoord2f");
void glEvalMesh1(GLenum mode, GLint i1, GLint i2) AliasExport("glshim_glEvalMesh1");
void glEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) AliasExport("glshim_glEvalMesh2");
void glEvalPoint1(GLint i) AliasExport("glshim_glEvalPoint1");
void glEvalPoint2(GLint i, GLint j) AliasExport("glshim_glEvalPoint2");
void glMapGrid1f(GLint un, GLfloat u1, GLfloat u2) AliasExport("glshim_glMapGrid1f");
void glMapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2) AliasExport("glshim_glMapGrid2f");
void glGetMapdv(GLenum target, GLenum query, GLdouble *v) AliasExport("glshim_glGetMapdv");
void glGetMapfv(GLenum target, GLenum query, GLfloat *v) AliasExport("glshim_glGetMapfv");
void glGetMapiv(GLenum target, GLenum query, GLint *v) AliasExport("glshim_glGetMapiv");