brutally evil... internally.. but it works. map perspective correct

now in gl engine. hooray for that. one complaint less.



SVN revision: 52566
This commit is contained in:
Carsten Haitzler 2010-09-22 06:52:28 +00:00
parent 787b09464b
commit 011b2ce822
7 changed files with 222 additions and 87 deletions

View File

@ -73,6 +73,7 @@ _evas_map_new(int count)
Evas_Map *m = calloc(1, sizeof(Evas_Map) + count * sizeof(Evas_Map_Point));
if (!m) return NULL;
m->count = count;
m->persp.foc = 0;
m->alpha = 1;
m->smooth = 1;
for (i = 0; i < count; i++)
@ -96,6 +97,7 @@ _evas_map_copy(Evas_Map *dst, const Evas_Map *src)
memcpy(dst->points, src->points, src->count * sizeof(Evas_Map_Point));
dst->smooth = src->smooth;
dst->alpha = src->alpha;
dst->persp = src->persp;
return EINA_TRUE;
}
@ -107,6 +109,7 @@ _evas_map_dup(const Evas_Map *orig)
memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point));
copy->smooth = orig->smooth;
copy->alpha = orig->alpha;
copy->persp = orig->persp;
return copy;
}
@ -648,8 +651,8 @@ evas_map_point_coord_set(Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_
if (!m) return;
if (idx >= m->count) return;
p = m->points + idx;
p->x = x;
p->y = y;
p->x = p->px = x;
p->y = p->py = y;
p->z = z;
}
@ -832,6 +835,15 @@ _evas_map_util_points_populate(Evas_Map *m, const Evas_Coord x, const Evas_Coord
p[3].z = z;
p[3].u = 0.0;
p[3].v = h;
p[0].px = p[0].x;
p[0].py = p[0].y;
p[1].px = p[1].x;
p[1].py = p[1].y;
p[2].px = p[2].x;
p[2].py = p[2].y;
p[3].px = p[3].x;
p[3].py = p[3].y;
}
/**
@ -1023,6 +1035,8 @@ evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy)
p->x = x + cx;
p->y = y + cy;
p->px = p->x;
p->py = p->y;
}
}
@ -1065,6 +1079,8 @@ evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_
p->x = x + cx;
p->y = y + cy;
p->px = p->x;
p->py = p->y;
}
}
@ -1134,6 +1150,8 @@ evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
p->x = x + cx;
p->y = y + cy;
p->z = z + cz;
p->px = p->x;
p->py = p->y;
}
}
@ -1237,7 +1255,7 @@ evas_map_util_3d_lighting(Evas_Map *m,
/**
* Apply a perspective transform to the map
*
*
* This applies a given perspective (3D) to the map coordinates. X, Y and Z
* values are used. The px and py points specify the "infinite distance" point
* in the 3D conversion (where all lines converge to like when artists draw
@ -1268,6 +1286,10 @@ evas_map_util_3d_perspective(Evas_Map *m,
p = m->points;
p_end = p + m->count;
m->persp.px = px;
m->persp.py = py;
m->persp.z0 = z0;
m->persp.foc = foc;
for (; p < p_end; p++)
{
Evas_Coord x, y, zz;

View File

@ -2442,13 +2442,19 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su
p = obj->cur.map->points;
p_end = p + 4;
pt = pts;
pts[0].px = obj->cur.map->persp.px << FP;
pts[0].py = obj->cur.map->persp.py << FP;
pts[0].foc = obj->cur.map->persp.foc << FP;
pts[0].z0 = obj->cur.map->persp.z0 << FP;
// draw geom +x +y
for (; p < p_end; p++, pt++)
{
pt->x = (p->x + x) << FP;
pt->y = (p->y + y) << FP;
pt->z = (p->z) << FP;
pt->x3 = p->px << FP;
pt->y3 = p->py << FP;
pt->u = p->u * FP1;
pt->v = p->v * FP1;
pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);

View File

@ -655,6 +655,11 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
return clean_them;
}
pts[0].px = obj->cur.map->persp.px << FP;
pts[0].py = obj->cur.map->persp.py << FP;
pts[0].foc = obj->cur.map->persp.foc << FP;
pts[0].z0 = obj->cur.map->persp.z0 << FP;
p = obj->cur.map->points;
p_end = p + 4;
pt = pts;
@ -663,6 +668,8 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
pt->x = (p->x + off_x) << FP;
pt->y = (p->y + off_y) << FP;
pt->z = (p->z) << FP;
pt->x3 = p->px << FP;
pt->y3 = p->py << FP;
pt->u = p->u * FP1;
pt->v = p->v * FP1;
pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);

View File

@ -766,9 +766,12 @@ struct _RGBA_Polygon_Point
struct _RGBA_Map_Point
{
FPc x, y; // x, y screenspace
FPc x3, y3; // x, y 3d space
FPc z; // z in world space. optional
FPc u, v; // u, v in tex coords
DATA32 col; // color at this point
// for perspective correctness - only point 0 has relevant info
FPc px, py, z0, foc;
};
// for fonts...

View File

@ -362,21 +362,24 @@ struct _Evas_Size_Hints
struct _Evas_Map_Point
{
Evas_Coord x, y, z;
Evas_Coord x, y, z, px, py;
double u, v;
unsigned char r, g, b, a;
};
struct _Evas_Map
{
int count; // num of points
Evas_Coord_Rectangle normal_geometry; // bounding box of map geom actually
void *surface; // surface holding map if needed
int surface_w, surface_h; // current surface w & h alloc
Evas_Coord mx, my; // mouse x, y after conversion to map space
Eina_Bool alpha : 1;
Eina_Bool smooth : 1;
Evas_Map_Point points[]; // actual points
int count; // num of points
Evas_Coord_Rectangle normal_geometry; // bounding box of map geom actually
void *surface; // surface holding map if needed
int surface_w, surface_h; // current surface w & h alloc
Evas_Coord mx, my; // mouse x, y after conversion to map space
struct {
Evas_Coord px, py, z0, foc;
} persp;
Eina_Bool alpha : 1;
Eina_Bool smooth : 1;
Evas_Map_Point points[]; // actual points
};
struct _Evas_Object

View File

@ -139,9 +139,11 @@ struct _Evas_GL_Shared
#define MAX_CUTOUT 512
#define DEF_CUTOUT 512
// FIXME bug with pipes > 1 right now, should default to 32
#define MAX_PIPES 128
#define DEF_PIPES 32
#define DEF_PIPES_SGX_540 32
#define DEF_PIPES 1
//#define DEF_PIPES_SGX_540 32
#define DEF_PIPES_SGX_540 1
#define DEF_PIPES_TEGRA_2 1
#define MIN_ATLAS_ALLOC 16
@ -198,6 +200,9 @@ struct _Evas_GL_Shared
int references;
int w, h;
int rot;
// persp map
int foc, z0, px, py;
int ax, ay;
};
#define RTYPE_RECT 1
@ -213,7 +218,8 @@ struct _Evas_GL_Context
int references;
int w, h;
int rot;
RGBA_Draw_Context *dc;
int foc, z0, px, py;
RGBA_Draw_Context *dc;
Evas_GL_Shared *shared;

View File

@ -133,72 +133,36 @@ glerr(int err, const char *file, const char *func, int line, const char *op)
}
static void
matrix_ident(GLfloat *m)
{
memset(m, 0, 16 * sizeof(GLfloat));
m[0] = m[5] = m[10] = m[15] = 1.0;
//------------------------
// 1 0 0 0
// 0 1 0 0
// 0 0 1 0
// 0 0 0 1
}
static void
matrix_ortho(GLfloat *m,
GLfloat l, GLfloat r,
GLfloat t, GLfloat b,
matrix_ortho(GLfloat *m,
GLfloat l, GLfloat r,
GLfloat t, GLfloat b,
GLfloat near, GLfloat far,
int rot, int w, int h)
int rot, int vw, int vh,
int foc, GLfloat orth)
{
GLfloat rotf;
GLfloat cosv, sinv;
GLfloat tx, ty;
// rot = 180;
//------------------------
m[0] = 2.0 / (r - l);
m[1] = 0.0;
m[2] = 0.0;
m[3] = 0.0;
//------------------------
m[4] = 0.0;
m[5] = 2.0 / (t - b);
m[6] = 0.0;
m[7] = 0.0;
//------------------------
m[8] = 0.0;
m[9] = 0.0;
m[10] = -(2.0 / (far - near));
m[11] = 0.0;
//------------------------
m[12] = -((r + l) / (r - l));
m[13] = -((t + b) / (t - b));
m[14] = -((near + far) / (far - near));
m[15] = 1.0;
// rot
rotf = (((rot / 90) & 0x3) * M_PI) / 2.0;
tx = 0.0;
ty = 0.0;
tx = -0.5 * (1.0 - orth);
ty = -0.5 * (1.0 - orth);
if (rot == 90)
{
tx = -(w * 1.0);
ty = -(h * 0.0);
tx += -(vw * 1.0);
ty += -(vh * 0.0);
}
if (rot == 180)
{
tx = -(w * 1.0);
ty = -(h * 1.0);
tx += -(vw * 1.0);
ty += -(vh * 1.0);
}
if (rot == 270)
{
tx = -(w * 0.0);
ty = -(h * 1.0);
tx += -(vw * 0.0);
ty += -(vh * 1.0);
}
cosv = cos(rotf);
@ -206,14 +170,23 @@ matrix_ortho(GLfloat *m,
m[0] = (2.0 / (r - l)) * ( cosv);
m[1] = (2.0 / (r - l)) * ( sinv);
m[2] = 0.0;
m[3] = 0.0;
m[4] = (2.0 / (t - b)) * (-sinv);
m[5] = (2.0 / (t - b)) * ( cosv);
m[6] = 0.0;
m[7] = 0.0;
m[12] += (m[0] * tx) + (m[4] * ty);
m[13] += (m[1] * tx) + (m[5] * ty);
m[14] += (m[2] * tx) + (m[6] * ty);
m[15] += (m[3] * tx) + (m[7] * ty);
m[8] = 0.0;
m[9] = 0.0;
m[10] = -(2.0 / (far - near));
m[11] = 1.0 / (GLfloat)foc;
m[12] = (m[0] * tx) + (m[4] * ty) - ((r + l) / (r - l));
m[13] = (m[1] * tx) + (m[5] * ty) - ((t + b) / (t - b));
m[14] = (m[2] * tx) + (m[6] * ty) - ((near + far) / (far - near));
m[15] = (m[3] * tx) + (m[7] * ty) + orth;
}
static int
@ -308,8 +281,9 @@ static void
_evas_gl_common_viewport_set(Evas_GL_Context *gc)
{
GLfloat proj[16];
int w = 1, h = 1, m = 1, rot = 1;
int w = 1, h = 1, m = 1, rot = 1, foc = 0;
foc = gc->foc;
// surface in pipe 0 will be the same as all pipes
if ((gc->pipe[0].shader.surface == gc->def_surface) ||
(!gc->pipe[0].shader.surface))
@ -328,23 +302,100 @@ _evas_gl_common_viewport_set(Evas_GL_Context *gc)
if ((!gc->change.size) ||
((gc->shared->w == w) && (gc->shared->h == h) &&
(gc->shared->rot == rot)))
(gc->shared->rot == rot) && (gc->shared->foc == gc->foc)))
return;
gc->shared->w = w;
gc->shared->h = h;
gc->shared->rot = rot;
gc->shared->foc = foc;
gc->shared->z0 = gc->z0;
gc->shared->px = gc->px;
gc->shared->py = gc->py;
gc->change.size = 0;
if ((rot == 0) || (rot == 180))
glViewport(0, 0, w, h);
if (foc == 0)
{
if ((rot == 0) || (rot == 180))
glViewport(0, 0, w, h);
else
glViewport(0, 0, h, w);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
// std matrix
if (m == 1)
matrix_ortho(proj,
0, w, 0, h,
-1000000.0, 1000000.0,
rot, w, h,
1, 1.0);
// v flipped matrix for render-to-texture
else
matrix_ortho(proj,
0, w, h, 0,
-1000000.0, 1000000.0,
rot, w, h,
1, 1.0);
}
else
glViewport(0, 0, h, w);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
matrix_ident(proj);
if (m == 1) matrix_ortho(proj, 0, w, 0, h, -1.0, 1.0, rot, w, h);
else matrix_ortho(proj, 0, w, h, 0, -1.0, 1.0, rot, w, h);
{
int px, py, vx, vy, vw = 0, vh = 0, ax = 0, ay = 0, ppx = 0, ppy = 0;
px = gc->shared->px;
py = gc->shared->py;
if ((rot == 0 ) || (rot == 90 )) ppx = px;
else if ((rot == 180) || (rot == 270)) ppx = w - px;
if ((rot == 0 ) || (rot == 270)) ppy = py;
else if ((rot == 90 ) || (rot == 180)) ppy = h - py;
vx = ((w / 2) - ppx);
if (vx >= 0)
{
vw = w + (2 * vx);
if ((rot == 0 ) || (rot == 90 )) ax = 2 * vx;
else if ((rot == 180) || (rot == 270)) ax = 0;
}
else
{
vw = w - (2 * vx);
if ((rot == 0 ) || (rot == 90 )) ax = 0;
else if ((rot == 180) || (rot == 270)) ax = ppx - px;
vx = 0;
}
vy = ((h / 2) - ppy);
if (vy < 0)
{
vh = h - (2 * vy);
if ((rot == 0 )) ay = 0;
else if ((rot == 90 ) || (rot == 180) || (rot == 270)) ay = ppy - py;
vy = -vy;
}
else
{
vh = h + (2 * vy);
if ((rot == 0 ) || (rot == 270)) ay = 2 * vy;
else if ((rot == 90 ) || (rot == 180)) ay = 0;
vy = 0;
}
if ((rot == 0) || (rot == 180))
glViewport(-2 * vx, -2 * vy, vw, vh);
else
glViewport(-2 * vy, -2 * vx, vh, vw);
if (m == 1)
matrix_ortho(proj, 0, vw, 0, vh,
-1000000.0, 1000000.0,
rot, vw, vh,
foc, 0.0);
else
matrix_ortho(proj, 0, vw, vh, 0,
-1000000.0, 1000000.0,
rot, vw, vh,
foc, 0.0);
gc->shared->ax = ax;
gc->shared->ay = ay;
}
glUseProgram(gc->shared->shader.rect.prog);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
@ -1812,7 +1863,6 @@ again:
}
}
// FIXME: we don't handle clipped maps right :(
void
evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
Evas_GL_Texture *tex,
@ -1830,6 +1880,7 @@ evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
DATA32 cmul;
GLuint prog = gc->shared->shader.img.prog;
int pn = 0;
int flat = 0;
if (!tex->alpha) blend = 0;
if (a < 255) blend = 1;
@ -1837,6 +1888,13 @@ evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
(A_VAL(&(p[2].col)) < 0xff) || (A_VAL(&(p[3].col)) < 0xff))
blend = 1;
if ((p[0].z == p[1].z) && (p[1].z == p[2].z) && (p[2].z == p[3].z))
flat = 1;
if (!flat)
{
if (p[0].foc <= 0) flat = 1;
}
if (yuv)
{
prog = gc->shared->shader.yuv.prog;
@ -1913,7 +1971,16 @@ evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
}
}
// /*xxx*/ shader_array_flush(gc);
if (!flat)
{
shader_array_flush(gc);
gc->foc = p[0].foc >> FP;
gc->z0 = p[0].z0 >> FP;
gc->px = p[0].px >> FP;
gc->py = p[0].py >> FP;
gc->change.size = 1;
_evas_gl_common_viewport_set(gc);
}
again:
vertex_array_size_check(gc, gc->state.top_pipe, 6);
pn = gc->state.top_pipe;
@ -2137,10 +2204,21 @@ again:
for (i = 0; i < 6; i++)
{
DATA32 cl = MUL4_SYM(cmul, p[points[i]].col);
PUSH_VERTEX(pn,
(p[points[i]].x >> FP),
(p[points[i]].y >> FP),
0);
if (flat)
{
PUSH_VERTEX(pn,
(p[points[i]].x >> FP),
(p[points[i]].y >> FP),
0);
}
else
{
PUSH_VERTEX(pn,
(p[points[i]].x3 >> FP) + gc->shared->ax,
(p[points[i]].y3 >> FP) + gc->shared->ay,
(p[points[i]].z >> FP)
+ (gc->shared->foc - gc->shared->z0));
}
PUSH_TEXUV(pn,
tx[points[i]],
ty[points[i]]);
@ -2160,6 +2238,16 @@ again:
B_VAL(&cl),
A_VAL(&cl));
}
if (!flat)
{
shader_array_flush(gc);
gc->foc = 0;
gc->z0 = 0;
gc->px = 0;
gc->py = 0;
gc->change.size = 1;
_evas_gl_common_viewport_set(gc);
}
}
void