TINYGL: Done several optimizations to the maths code.

This commit is contained in:
Stefano Musumeci 2014-06-07 00:55:08 +02:00
parent 9be1423802
commit 4fbb2d0dc3
9 changed files with 333 additions and 254 deletions

View file

@ -25,18 +25,18 @@ void glopArrayElement(GLContext *c, GLParam *param) {
} }
if (states & NORMAL_ARRAY) { if (states & NORMAL_ARRAY) {
i = idx * (3 + c->normal_array_stride); i = idx * (3 + c->normal_array_stride);
c->current_normal.setX(c->normal_array[i]); c->current_normal.X = (c->normal_array[i]);
c->current_normal.setY(c->normal_array[i + 1]); c->current_normal.Y = (c->normal_array[i + 1]);
c->current_normal.setZ(c->normal_array[i + 2]); c->current_normal.Z = (c->normal_array[i + 2]);
c->current_normal.setW(0.0f); // NOTE: this used to be Z but assigning Z again seemed like a bug... c->current_normal.W = (0.0f); // NOTE: this used to be Z but assigning Z again seemed like a bug...
} }
if (states & TEXCOORD_ARRAY) { if (states & TEXCOORD_ARRAY) {
int size = c->texcoord_array_size; int size = c->texcoord_array_size;
i = idx * (size + c->texcoord_array_stride); i = idx * (size + c->texcoord_array_stride);
c->current_tex_coord.setX(c->texcoord_array[i]); c->current_tex_coord.X = (c->texcoord_array[i]);
c->current_tex_coord.setY(c->texcoord_array[i + 1]); c->current_tex_coord.Y = (c->texcoord_array[i + 1]);
c->current_tex_coord.setZ(size > 2 ? c->texcoord_array[i + 2] : 0.0f); c->current_tex_coord.Z = (size > 2 ? c->texcoord_array[i + 2] : 0.0f);
c->current_tex_coord.setW(size > 3 ? c->texcoord_array[i + 3] : 1.0f); c->current_tex_coord.W = (size > 3 ? c->texcoord_array[i + 3] : 1.0f);
} }
if (states & VERTEX_ARRAY) { if (states & VERTEX_ARRAY) {
GLParam p[5]; GLParam p[5];

View file

@ -14,9 +14,9 @@ void glopClearDepth(GLContext *c, GLParam *p) {
void glopClear(GLContext *c, GLParam *p) { void glopClear(GLContext *c, GLParam *p) {
int mask = p[1].i; int mask = p[1].i;
int z = 0; int z = 0;
int r = (int)(c->clear_color.getX() * 65535); int r = (int)(c->clear_color.X * 65535);
int g = (int)(c->clear_color.getY() * 65535); int g = (int)(c->clear_color.Y * 65535);
int b = (int)(c->clear_color.getZ() * 65535); int b = (int)(c->clear_color.Z * 65535);
// TODO : correct value of Z // TODO : correct value of Z
ZB_clear(c->zb, mask & TGL_DEPTH_BUFFER_BIT, z, mask & TGL_COLOR_BUFFER_BIT, r, g, b); ZB_clear(c->zb, mask & TGL_DEPTH_BUFFER_BIT, z, mask & TGL_COLOR_BUFFER_BIT, r, g, b);

View file

@ -17,17 +17,17 @@ void gl_transform_to_viewport(GLContext *c, GLVertex *v) {
float winv; float winv;
// coordinates // coordinates
winv = (float)(1.0 / v->pc.getW()); winv = (float)(1.0 / v->pc.W);
v->zp.x = (int)(v->pc.getX() * winv * c->viewport.scale.getX() + c->viewport.trans.getX()); v->zp.x = (int)(v->pc.X * winv * c->viewport.scale.X + c->viewport.trans.X);
v->zp.y = (int)(v->pc.getY() * winv * c->viewport.scale.getY() + c->viewport.trans.getY()); v->zp.y = (int)(v->pc.Y * winv * c->viewport.scale.Y + c->viewport.trans.Y);
v->zp.z = (int)(v->pc.getZ() * winv * c->viewport.scale.getZ() + c->viewport.trans.getZ()); v->zp.z = (int)(v->pc.Z * winv * c->viewport.scale.Z + c->viewport.trans.Z);
// color // color
if (c->lighting_enabled) { if (c->lighting_enabled) {
v->zp.r = (int)(v->color.getX() * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN) v->zp.r = (int)(v->color.X * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN)
+ ZB_POINT_RED_MIN); + ZB_POINT_RED_MIN);
v->zp.g = (int)(v->color.getY() * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN) v->zp.g = (int)(v->color.Y * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN)
+ ZB_POINT_GREEN_MIN); + ZB_POINT_GREEN_MIN);
v->zp.b = (int)(v->color.getZ() * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN) v->zp.b = (int)(v->color.Z * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN)
+ ZB_POINT_BLUE_MIN); + ZB_POINT_BLUE_MIN);
} else { } else {
// no need to convert to integer if no lighting : take current color // no need to convert to integer if no lighting : take current color
@ -38,8 +38,8 @@ void gl_transform_to_viewport(GLContext *c, GLVertex *v) {
// texture // texture
if (c->texture_2d_enabled) { if (c->texture_2d_enabled) {
v->zp.s = (int)(v->tex_coord.getX() * (ZB_POINT_S_MAX - ZB_POINT_S_MIN) + ZB_POINT_S_MIN); v->zp.s = (int)(v->tex_coord.X * (ZB_POINT_S_MAX - ZB_POINT_S_MIN) + ZB_POINT_S_MIN);
v->zp.t = (int)(v->tex_coord.getY() * (ZB_POINT_S_MAX - ZB_POINT_S_MIN) + ZB_POINT_S_MIN); v->zp.t = (int)(v->tex_coord.Y * (ZB_POINT_S_MAX - ZB_POINT_S_MIN) + ZB_POINT_S_MIN);
} }
} }
@ -125,14 +125,14 @@ void gl_draw_line(GLContext *c, GLVertex *p1, GLVertex *p2) {
} else if ((cc1 & cc2) != 0) { } else if ((cc1 & cc2) != 0) {
return; return;
} else { } else {
dx = p2->pc.getX() - p1->pc.getX(); dx = p2->pc.X - p1->pc.X;
dy = p2->pc.getY() - p1->pc.getY(); dy = p2->pc.Y - p1->pc.Y;
dz = p2->pc.getZ() - p1->pc.getZ(); dz = p2->pc.Z - p1->pc.Z;
dw = p2->pc.getW() - p1->pc.getW(); dw = p2->pc.W - p1->pc.W;
x1 = p1->pc.getX(); x1 = p1->pc.X;
y1 = p1->pc.getY(); y1 = p1->pc.Y;
z1 = p1->pc.getZ(); z1 = p1->pc.Z;
w1 = p1->pc.getW(); w1 = p1->pc.W;
tmin = 0; tmin = 0;
tmax = 1; tmax = 1;
@ -166,19 +166,19 @@ void gl_draw_line(GLContext *c, GLVertex *p1, GLVertex *p2) {
#define clip_func(name, sign, dir, dir1, dir2) \ #define clip_func(name, sign, dir, dir1, dir2) \
static float name(Vector4 *c, Vector4 *a, Vector4 *b) { \ static float name(Vector4 *c, Vector4 *a, Vector4 *b) { \
float t, dX, dY, dZ, dW, den;\ float t, dX, dY, dZ, dW, den;\
dX = (b->getX() - a->getX()); \ dX = (b->X - a->X); \
dY = (b->getY() - a->getY()); \ dY = (b->Y - a->Y); \
dZ = (b->getZ() - a->getZ()); \ dZ = (b->Z - a->Z); \
dW = (b->getW() - a->getW()); \ dW = (b->W - a->W); \
den = -(sign d ## dir) + dW; \ den = -(sign d ## dir) + dW; \
if (den == 0) \ if (den == 0) \
t = 0; \ t = 0; \
else \ else \
t = (sign a->get ## dir () - a->getW()) / den; \ t = (sign a-> dir - a->W) / den; \
c->set ## dir1 (a->get ## dir1 () + t * d ## dir1); \ c-> dir1 = (a-> dir1 + t * d ## dir1); \
c->set ## dir2 (a->get ## dir2 () + t * d ## dir2); \ c-> dir2 = (a-> dir2 + t * d ## dir2); \
c->setW(a->getW() + t * dW); \ c->W = (a->W + t * dW); \
c->set ## dir (sign c->getW()); \ c-> dir = (sign c->W); \
return t; \ return t; \
} }
@ -198,23 +198,23 @@ float(*clip_proc[6])(Vector4 *, Vector4 *, Vector4 *) = {
static inline void updateTmp(GLContext *c, GLVertex *q, static inline void updateTmp(GLContext *c, GLVertex *q,
GLVertex *p0, GLVertex *p1, float t) { GLVertex *p0, GLVertex *p1, float t) {
if (c->current_shade_model == TGL_SMOOTH) { if (c->current_shade_model == TGL_SMOOTH) {
float a = q->color.getW(); float a = q->color.W;
q->color = p0->color + (p1->color - p0->color) * t; q->color = p0->color + (p1->color - p0->color) * t;
q->color.setW(a); q->color.W = a;
} else { } else {
q->color.setX(p0->color.getX()); q->color.X = (p0->color.X);
q->color.setY(p0->color.getY()); q->color.Y = (p0->color.Y);
q->color.setZ(p0->color.getZ()); q->color.Z = (p0->color.Z);
//q->color = p0->color; //q->color = p0->color;
} }
if (c->texture_2d_enabled) { if (c->texture_2d_enabled) {
//NOTE: This could be implemented with operator overloading, but i'm not 100% sure that we can completely disregard Z and W components so I'm leaving it like this for now. //NOTE: This could be implemented with operator overloading, but i'm not 100% sure that we can completely disregard Z and W components so I'm leaving it like this for now.
q->tex_coord.setX(p0->tex_coord.getX() + (p1->tex_coord.getX() - p0->tex_coord.getX()) * t); q->tex_coord.X = (p0->tex_coord.X + (p1->tex_coord.X - p0->tex_coord.X) * t);
q->tex_coord.setY(p0->tex_coord.getY() + (p1->tex_coord.getY() - p0->tex_coord.getY()) * t); q->tex_coord.Y = (p0->tex_coord.Y + (p1->tex_coord.Y - p0->tex_coord.Y) * t);
} }
q->clip_code = gl_clipcode(q->pc.getX(), q->pc.getY(), q->pc.getZ(), q->pc.getW()); q->clip_code = gl_clipcode(q->pc.X, q->pc.Y, q->pc.Z, q->pc.W);
if (q->clip_code == 0) if (q->clip_code == 0)
gl_transform_to_viewport(c, q); gl_transform_to_viewport(c, q);
} }

View file

@ -35,7 +35,6 @@ void tglGetIntegerv(int pname, int *params) {
} }
void tglGetFloatv(int pname, float *v) { void tglGetFloatv(int pname, float *v) {
TinyGL::Matrix4* m;
int i; int i;
int mnr = 0; // just a trick to return the correct matrix int mnr = 0; // just a trick to return the correct matrix
TinyGL::GLContext *c = TinyGL::gl_get_context(); TinyGL::GLContext *c = TinyGL::gl_get_context();

View file

@ -33,8 +33,8 @@ void glopMaterial(GLContext *c, GLParam *p) {
m->specular = v; m->specular = v;
break; break;
case TGL_SHININESS: case TGL_SHININESS:
m->shininess = v.getX(); m->shininess = v.X;
m->shininess_i = (int)(v.getX() / 128.0f) * SPECULAR_BUFFER_RESOLUTION; m->shininess_i = (int)(v.X / 128.0f) * SPECULAR_BUFFER_RESOLUTION;
break; break;
case TGL_AMBIENT_AND_DIFFUSE: case TGL_AMBIENT_AND_DIFFUSE:
m->diffuse = v; m->diffuse = v;
@ -78,7 +78,7 @@ void glopLight(GLContext *c, GLParam *p) {
l->position = pos; l->position = pos;
if (l->position.getW() == 0) { if (l->position.W == 0) {
l->norm_position = pos.toVector3(); l->norm_position = pos.toVector3();
l->norm_position.normalize(); l->norm_position.normalize();
} }
@ -90,10 +90,10 @@ void glopLight(GLContext *c, GLParam *p) {
l->norm_spot_direction.normalize(); l->norm_spot_direction.normalize();
break; break;
case TGL_SPOT_EXPONENT: case TGL_SPOT_EXPONENT:
l->spot_exponent = v.getX(); l->spot_exponent = v.X;
break; break;
case TGL_SPOT_CUTOFF: { case TGL_SPOT_CUTOFF: {
float a = v.getX(); float a = v.X;
assert(a == 180 || (a >= 0 && a <= 90)); assert(a == 180 || (a >= 0 && a <= 90));
l->spot_cutoff = a; l->spot_cutoff = a;
if (a != 180) if (a != 180)
@ -101,13 +101,13 @@ void glopLight(GLContext *c, GLParam *p) {
} }
break; break;
case TGL_CONSTANT_ATTENUATION: case TGL_CONSTANT_ATTENUATION:
l->attenuation[0] = v.getX(); l->attenuation[0] = v.X;
break; break;
case TGL_LINEAR_ATTENUATION: case TGL_LINEAR_ATTENUATION:
l->attenuation[1] = v.getX(); l->attenuation[1] = v.X;
break; break;
case TGL_QUADRATIC_ATTENUATION: case TGL_QUADRATIC_ATTENUATION:
l->attenuation[2] = v.getX(); l->attenuation[2] = v.X;
break; break;
default: default:
assert(0); assert(0);
@ -178,26 +178,26 @@ void gl_shade_vertex(GLContext *c, GLVertex *v) {
n = v->normal; n = v->normal;
R = m->emission.getX() + m->ambient.getX() * c->ambient_light_model.getX(); R = m->emission.X + m->ambient.X * c->ambient_light_model.X;
G = m->emission.getY() + m->ambient.getY() * c->ambient_light_model.getY(); G = m->emission.Y + m->ambient.Y * c->ambient_light_model.Y;
B = m->emission.getZ() + m->ambient.getZ() * c->ambient_light_model.getZ(); B = m->emission.Z + m->ambient.Z * c->ambient_light_model.Z;
A = clampf(m->diffuse.getW(), 0, 1); A = clampf(m->diffuse.W, 0, 1);
for (l = c->first_light; l != NULL; l = l->next) { for (l = c->first_light; l != NULL; l = l->next) {
float lR, lB, lG; float lR, lB, lG;
// ambient // ambient
lR = l->ambient.getX() * m->ambient.getX(); lR = l->ambient.X * m->ambient.X;
lG = l->ambient.getY() * m->ambient.getY(); lG = l->ambient.Y * m->ambient.Y;
lB = l->ambient.getZ() * m->ambient.getZ(); lB = l->ambient.Z * m->ambient.Z;
if (l->position.getW() == 0) { if (l->position.W == 0) {
// light at infinity // light at infinity
d = l->position.toVector3(); d = l->position.toVector3();
att = 1; att = 1;
} else { } else {
// distance attenuation // distance attenuation
d = l->position.toVector3() - v->ec.toVector3(); d = (l->position - v->ec).toVector3();
dist = d.getLength(); dist = d.getLength();
if (dist > 1E-3) { if (dist > 1E-3) {
tmp = 1 / dist; tmp = 1 / dist;
@ -211,9 +211,9 @@ void gl_shade_vertex(GLContext *c, GLVertex *v) {
dot = -dot; dot = -dot;
if (dot > 0) { if (dot > 0) {
// diffuse light // diffuse light
lR += dot * l->diffuse.getX() * m->diffuse.getX(); lR += dot * l->diffuse.X * m->diffuse.X;
lG += dot * l->diffuse.getY() * m->diffuse.getY(); lG += dot * l->diffuse.Y * m->diffuse.Y;
lB += dot * l->diffuse.getZ() * m->diffuse.getZ(); lB += dot * l->diffuse.Z * m->diffuse.Z;
// spot light // spot light
if (l->spot_cutoff != 180) { if (l->spot_cutoff != 180) {
@ -237,13 +237,13 @@ void gl_shade_vertex(GLContext *c, GLVertex *v) {
Vector3 vcoord; Vector3 vcoord;
vcoord = v->ec.toVector3(); vcoord = v->ec.toVector3();
vcoord.normalize(); vcoord.normalize();
s.setX(d.getX() - vcoord.getX()); s.X = (d.X - vcoord.X);
s.setY(d.getY() - vcoord.getX()); s.Y = (d.Y - vcoord.X);
s.setZ(d.getZ() - vcoord.getX()); s.Z = (d.Z - vcoord.X);
//NOTE: this operation is rather suspicious, this code should be tested. //NOTE: this operation is rather suspicious, this code should be tested.
} else { } else {
s = d; s = d;
s.setZ(s.getZ() + 1.0); s.Z = (s.Z + 1.0);
} }
dot_spec = Vector3::dot(n, s); dot_spec = Vector3::dot(n, s);
if (twoside && dot_spec < 0) if (twoside && dot_spec < 0)
@ -267,9 +267,9 @@ void gl_shade_vertex(GLContext *c, GLVertex *v) {
idx = (int)tmp; idx = (int)tmp;
dot_spec = specbuf->buf[idx]; dot_spec = specbuf->buf[idx];
lR += dot_spec * l->specular.getX() * m->specular.getX(); lR += dot_spec * l->specular.X * m->specular.X;
lG += dot_spec * l->specular.getY() * m->specular.getY(); lG += dot_spec * l->specular.Y * m->specular.Y;
lB += dot_spec * l->specular.getZ() * m->specular.getZ(); lB += dot_spec * l->specular.Z * m->specular.Z;
} }
} }

View file

@ -172,26 +172,25 @@ void glopRotate(GLContext *c, GLParam *p) {
void glopScale(GLContext *c, GLParam *p) { void glopScale(GLContext *c, GLParam *p) {
float x = p[1].f, y = p[2].f, z = p[3].f; float x = p[1].f, y = p[2].f, z = p[3].f;
Matrix4 m = Matrix4::identity(); Matrix4 *m = c->matrix_stack_ptr[c->matrix_mode];
m.set(0, 0, x); m->set(0, 0, m->get(0, 0) * x); m->set(0, 1, m->get(0, 1) * y); m->set(0, 2, m->get(0, 2) * z);
m.set(1, 1, y); m->set(1, 0, m->get(1, 0) * x); m->set(1, 1, m->get(1, 1) * y); m->set(1, 2, m->get(1, 2) * z);
m.set(2, 2, z); m->set(2, 0, m->get(2, 0) * x); m->set(2, 1, m->get(2, 1) * y); m->set(2, 2, m->get(2, 2) * z);
m->set(3, 0, m->get(3, 0) * x); m->set(3, 1, m->get(3, 1) * y); m->set(3, 2, m->get(3, 2) * z);
*c->matrix_stack_ptr[c->matrix_mode] *= m;
gl_matrix_update(c); gl_matrix_update(c);
} }
void glopTranslate(GLContext *c, GLParam *p) { void glopTranslate(GLContext *c, GLParam *p) {
Matrix4 m = Matrix4::identity();
float x = p[1].f, y = p[2].f, z = p[3].f; float x = p[1].f, y = p[2].f, z = p[3].f;
m.set(0, 3, x); Matrix4 *m = c->matrix_stack_ptr[c->matrix_mode];
m.set(1, 3, y);
m.set(2, 3, z);
*c->matrix_stack_ptr[c->matrix_mode] *= m; m->set(0, 3, m->get(0,0) * x + m->get(0,1) * y + m->get(0,2) * z + m->get(0,3));
m->set(1, 3, m->get(1,0) * x + m->get(1,1) * y + m->get(1,2) * z + m->get(1,3));
m->set(2, 3, m->get(2,0) * x + m->get(2,1) * y + m->get(2,2) * z + m->get(2,3));
m->set(3, 3, m->get(3,0) * x + m->get(3,1) * y + m->get(3,2) * z + m->get(3,3));
gl_matrix_update(c); gl_matrix_update(c);
} }

View file

@ -40,13 +40,13 @@ void gl_eval_viewport(GLContext *c) {
v = &c->viewport; v = &c->viewport;
v->trans.setX((float)(((v->xsize - 0.5) / 2.0) + v->xmin)); v->trans.X = ((float)(((v->xsize - 0.5) / 2.0) + v->xmin));
v->trans.setY((float)(((v->ysize - 0.5) / 2.0) + v->ymin)); v->trans.Y = ((float)(((v->ysize - 0.5) / 2.0) + v->ymin));
v->trans.setZ((float)(((zsize - 0.5) / 2.0) + ((1 << ZB_POINT_Z_FRAC_BITS)) / 2)); v->trans.Z = ((float)(((zsize - 0.5) / 2.0) + ((1 << ZB_POINT_Z_FRAC_BITS)) / 2));
v->scale.setX((float)((v->xsize - 0.5) / 2.0)); v->scale.X = ((float)((v->xsize - 0.5) / 2.0));
v->scale.setY((float)(-(v->ysize - 0.5) / 2.0)); v->scale.Y = ((float)(-(v->ysize - 0.5) / 2.0));
v->scale.setZ((float)(-((zsize - 0.5) / 2.0))); v->scale.Z = ((float)(-((zsize - 0.5) / 2.0)));
} }
void glopBegin(GLContext *c, GLParam *p) { void glopBegin(GLContext *c, GLParam *p) {
@ -63,7 +63,9 @@ void glopBegin(GLContext *c, GLParam *p) {
if (c->matrix_model_projection_updated) { if (c->matrix_model_projection_updated) {
if (c->lighting_enabled) { if (c->lighting_enabled) {
// precompute inverse modelview // precompute inverse modelview
c->matrix_model_view_inv = c->matrix_stack_ptr[0]->inverse().transpose(); c->matrix_model_view_inv = *c->matrix_stack_ptr[0];
c->matrix_model_view_inv.invert();
c->matrix_model_view_inv.transpose();
} else { } else {
// precompute projection matrix // precompute projection matrix
c->matrix_model_projection = (*c->matrix_stack_ptr[1]) * (*c->matrix_stack_ptr[0]); c->matrix_model_projection = (*c->matrix_stack_ptr[1]) * (*c->matrix_stack_ptr[0]);
@ -153,11 +155,11 @@ static inline void gl_vertex_transform(GLContext *c, GLVertex *v) {
v->pc = m->transform3x4(v->coord); v->pc = m->transform3x4(v->coord);
if (c->matrix_model_projection_no_w_transform) { if (c->matrix_model_projection_no_w_transform) {
v->pc.setW(m->get(3,3)); v->pc.W = (m->get(3,3));
} }
} }
v->clip_code = gl_clipcode(v->pc.getX(), v->pc.getY(), v->pc.getZ(), v->pc.getW()); v->clip_code = gl_clipcode(v->pc.X, v->pc.Y, v->pc.Z, v->pc.W);
} }
void glopVertex(GLContext *c, GLParam *p) { void glopVertex(GLContext *c, GLParam *p) {

View file

@ -8,67 +8,132 @@ namespace TinyGL {
// Inversion of a general nxn matrix. // Inversion of a general nxn matrix.
// Note : m is destroyed // Note : m is destroyed
int Matrix_Inv(float *r, float *m, int n) { int Matrix_Inv(float *r, float *m, int n) {
int k; double inv[16], det;
float max, tmp, t; int i;
// identitée dans r inv[0] = m[5] * m[10] * m[15] -
for (int i = 0; i < n * n; i++) m[5] * m[11] * m[14] -
r[i] = 0; m[9] * m[6] * m[15] +
for (int i = 0; i < n; i++) m[9] * m[7] * m[14] +
r[i * n + i] = 1; m[13] * m[6] * m[11] -
m[13] * m[7] * m[10];
for (int j = 0; j < n; j++) { inv[4] = -m[4] * m[10] * m[15] +
max = m[j * n + j]; m[4] * m[11] * m[14] +
k = j; m[8] * m[6] * m[15] -
for (int i = j + 1; i < n; i++) { m[8] * m[7] * m[14] -
if (fabs(m[i * n + j]) > fabs(max)) { m[12] * m[6] * m[11] +
k = i; m[12] * m[7] * m[10];
max = m[i * n + j];
}
}
// non intersible matrix
if (max == 0)
return 1;
if (k != j) { inv[8] = m[4] * m[9] * m[15] -
for (int i = 0; i < n; i++) { m[4] * m[11] * m[13] -
tmp = m[j * n + i]; m[8] * m[5] * m[15] +
m[j * n + i] = m[k * n + i]; m[8] * m[7] * m[13] +
m[k * n + i] = tmp; m[12] * m[5] * m[11] -
m[12] * m[7] * m[9];
tmp = r[j * n + i]; inv[12] = -m[4] * m[9] * m[14] +
r[j * n + i] = r[k * n + i]; m[4] * m[10] * m[13] +
r[k * n + i] = tmp; m[8] * m[5] * m[14] -
} m[8] * m[6] * m[13] -
} m[12] * m[5] * m[10] +
m[12] * m[6] * m[9];
max = 1 / max; inv[1] = -m[1] * m[10] * m[15] +
for (int i = 0; i < n; i++) { m[1] * m[11] * m[14] +
m[j * n + i] *= max; m[9] * m[2] * m[15] -
r[j * n + i] *= max; m[9] * m[3] * m[14] -
} m[13] * m[2] * m[11] +
m[13] * m[3] * m[10];
inv[5] = m[0] * m[10] * m[15] -
m[0] * m[11] * m[14] -
m[8] * m[2] * m[15] +
m[8] * m[3] * m[14] +
m[12] * m[2] * m[11] -
m[12] * m[3] * m[10];
for (int l = 0; l < n; l++) { inv[9] = -m[0] * m[9] * m[15] +
if (l != j) { m[0] * m[11] * m[13] +
t = m[l * n + j]; m[8] * m[1] * m[15] -
for (int i = 0; i < n; i++) { m[8] * m[3] * m[13] -
m[l * n + i] -= m[j * n + i] * t; m[12] * m[1] * m[11] +
r[l * n + i] -= r[j * n + i] * t; m[12] * m[3] * m[9];
}
}
}
}
return 0; inv[13] = m[0] * m[9] * m[14] -
} m[0] * m[10] * m[13] -
m[8] * m[1] * m[14] +
m[8] * m[2] * m[13] +
m[12] * m[1] * m[10] -
m[12] * m[2] * m[9];
Vector3::Vector3() { inv[2] = m[1] * m[6] * m[15] -
// Empty constructor, no overhead m[1] * m[7] * m[14] -
} m[5] * m[2] * m[15] +
m[5] * m[3] * m[14] +
m[13] * m[2] * m[7] -
m[13] * m[3] * m[6];
Vector3::Vector3(const Vector3 &other) { inv[6] = -m[0] * m[6] * m[15] +
memcpy(_v, other._v, sizeof(_v)); m[0] * m[7] * m[14] +
m[4] * m[2] * m[15] -
m[4] * m[3] * m[14] -
m[12] * m[2] * m[7] +
m[12] * m[3] * m[6];
inv[10] = m[0] * m[5] * m[15] -
m[0] * m[7] * m[13] -
m[4] * m[1] * m[15] +
m[4] * m[3] * m[13] +
m[12] * m[1] * m[7] -
m[12] * m[3] * m[5];
inv[14] = -m[0] * m[5] * m[14] +
m[0] * m[6] * m[13] +
m[4] * m[1] * m[14] -
m[4] * m[2] * m[13] -
m[12] * m[1] * m[6] +
m[12] * m[2] * m[5];
inv[3] = -m[1] * m[6] * m[11] +
m[1] * m[7] * m[10] +
m[5] * m[2] * m[11] -
m[5] * m[3] * m[10] -
m[9] * m[2] * m[7] +
m[9] * m[3] * m[6];
inv[7] = m[0] * m[6] * m[11] -
m[0] * m[7] * m[10] -
m[4] * m[2] * m[11] +
m[4] * m[3] * m[10] +
m[8] * m[2] * m[7] -
m[8] * m[3] * m[6];
inv[11] = -m[0] * m[5] * m[11] +
m[0] * m[7] * m[9] +
m[4] * m[1] * m[11] -
m[4] * m[3] * m[9] -
m[8] * m[1] * m[7] +
m[8] * m[3] * m[5];
inv[15] = m[0] * m[5] * m[10] -
m[0] * m[6] * m[9] -
m[4] * m[1] * m[10] +
m[4] * m[2] * m[9] +
m[8] * m[1] * m[6] -
m[8] * m[2] * m[5];
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
if (det == 0)
return false;
det = 1.0 / det;
for (i = 0; i < 16; i++)
r[i] = inv[i] * det;
return true;
} }
Vector3::Vector3(float x, float y, float z) { Vector3::Vector3(float x, float y, float z) {
@ -87,10 +152,6 @@ void Vector3::normalize() {
} }
} }
Vector4::Vector4() {
// Empty constructor, no overhead
}
Vector4::Vector4(float x, float y, float z, float w) { Vector4::Vector4(float x, float y, float z, float w) {
_v[0] = x; _v[0] = x;
_v[1] = y; _v[1] = y;
@ -99,20 +160,12 @@ Vector4::Vector4(float x, float y, float z, float w) {
} }
Vector4::Vector4(const Vector3 &vec, float w) { Vector4::Vector4(const Vector3 &vec, float w) {
_v[0] = vec.getX(); _v[0] = vec.X;
_v[1] = vec.getY(); _v[1] = vec.Y;
_v[2] = vec.getZ(); _v[2] = vec.Z;
_v[3] = w; _v[3] = w;
} }
Matrix4::Matrix4() {
// Empty constructor, no overhead
}
Matrix4::Matrix4(const Matrix4 &other) {
memcpy(_m, other._m, sizeof(_m));
}
TinyGL::Matrix4 Matrix4::identity() { TinyGL::Matrix4 Matrix4::identity() {
Matrix4 a; Matrix4 a;
a.fill(0); a.fill(0);
@ -126,29 +179,53 @@ TinyGL::Matrix4 Matrix4::identity() {
TinyGL::Matrix4 Matrix4::transpose() const { TinyGL::Matrix4 Matrix4::transpose() const {
Matrix4 a; Matrix4 a;
a.set(0, 0, this->get(0, 0)); a.set(0, 0, this->_m[0][0]);
a.set(0, 1, this->get(1, 0)); a.set(0, 1, this->_m[1][0]);
a.set(0, 2, this->get(2, 0)); a.set(0, 2, this->_m[2][0]);
a.set(0, 3, this->get(3, 0)); a.set(0, 3, this->_m[3][0]);
a.set(1, 0, this->get(0, 1)); a.set(1, 0, this->_m[0][1]);
a.set(1, 1, this->get(1, 1)); a.set(1, 1, this->_m[1][1]);
a.set(1, 2, this->get(2, 1)); a.set(1, 2, this->_m[2][1]);
a.set(1, 3, this->get(3, 1)); a.set(1, 3, this->_m[3][1]);
a.set(2, 0, this->get(0, 2)); a.set(2, 0, this->_m[0][2]);
a.set(2, 1, this->get(1, 2)); a.set(2, 1, this->_m[1][2]);
a.set(2, 2, this->get(2, 2)); a.set(2, 2, this->_m[2][2]);
a.set(2, 3, this->get(3, 2)); a.set(2, 3, this->_m[3][2]);
a.set(3, 0, this->get(0, 3)); a.set(3, 0, this->_m[0][3]);
a.set(3, 1, this->get(1, 3)); a.set(3, 1, this->_m[1][3]);
a.set(3, 2, this->get(2, 3)); a.set(3, 2, this->_m[2][3]);
a.set(3, 3, this->get(3, 3)); a.set(3, 3, this->_m[3][3]);
return a; return a;
} }
void Matrix4::transpose()
{
Matrix4 tmp = *this;
this->set(0, 0, tmp._m[0][0]);
this->set(0, 1, tmp._m[1][0]);
this->set(0, 2, tmp._m[2][0]);
this->set(0, 3, tmp._m[3][0]);
this->set(1, 0, tmp._m[0][1]);
this->set(1, 1, tmp._m[1][1]);
this->set(1, 2, tmp._m[2][1]);
this->set(1, 3, tmp._m[3][1]);
this->set(2, 0, tmp._m[0][2]);
this->set(2, 1, tmp._m[1][2]);
this->set(2, 2, tmp._m[2][2]);
this->set(2, 3, tmp._m[3][2]);
this->set(3, 0, tmp._m[0][3]);
this->set(3, 1, tmp._m[1][3]);
this->set(3, 2, tmp._m[2][3]);
this->set(3, 3, tmp._m[3][3]);
}
Matrix4 Matrix4::inverseOrtho() const { Matrix4 Matrix4::inverseOrtho() const {
Matrix4 a; Matrix4 a;
@ -198,36 +275,6 @@ Matrix4 Matrix4::rotation(float t, int u) {
return a; return a;
} }
Vector3 Matrix4::transform(const Vector3 &vector) const {
return Vector3(
vector.getX() * get(0, 0) + vector.getY() * get(0, 1) + vector.getZ() * get(0, 2) + get(0, 3),
vector.getX() * get(1, 0) + vector.getY() * get(1, 1) + vector.getZ() * get(1, 2) + get(1, 3),
vector.getX() * get(2, 0) + vector.getY() * get(2, 1) + vector.getZ() * get(2, 2) + get(2, 3));
}
Vector3 Matrix4::transform3x3(const Vector3 &vector) const {
return Vector3(
vector.getX() * get(0, 0) + vector.getY() * get(0, 1) + vector.getZ() * get(0, 2),
vector.getX() * get(1, 0) + vector.getY() * get(1, 1) + vector.getZ() * get(1, 2),
vector.getX() * get(2, 0) + vector.getY() * get(2, 1) + vector.getZ() * get(2, 2));
}
TinyGL::Vector4 Matrix4::transform3x4(const Vector4 &vector) const {
return Vector4(
vector.getX() * get(0, 0) + vector.getY() * get(0, 1) + vector.getZ() * get(0, 2) + get(0, 3),
vector.getX() * get(1, 0) + vector.getY() * get(1, 1) + vector.getZ() * get(1, 2) + get(1, 3),
vector.getX() * get(2, 0) + vector.getY() * get(2, 1) + vector.getZ() * get(2, 2) + get(2, 3),
vector.getX() * get(3, 0) + vector.getY() * get(3, 1) + vector.getZ() * get(3, 2) + get(3, 3));
}
Vector4 Matrix4::transform(const Vector4 &vector) const {
return Vector4(
vector.getX() * get(0, 0) + vector.getY() * get(0, 1) + vector.getZ() * get(0, 2) + vector.getW() * get(0, 3),
vector.getX() * get(1, 0) + vector.getY() * get(1, 1) + vector.getZ() * get(1, 2) + vector.getW() * get(1, 3),
vector.getX() * get(2, 0) + vector.getY() * get(2, 1) + vector.getZ() * get(2, 2) + vector.getW() * get(2, 3),
vector.getX() * get(3, 0) + vector.getY() * get(3, 1) + vector.getZ() * get(3, 2) + vector.getW() * get(3, 3));
}
bool Matrix4::IsIdentity() const { bool Matrix4::IsIdentity() const {
//NOTE: This might need to be implemented in a fault-tolerant way. //NOTE: This might need to be implemented in a fault-tolerant way.
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
@ -242,4 +289,10 @@ bool Matrix4::IsIdentity() const {
return true; return true;
} }
void Matrix4::invert()
{
Matrix4 source = *this;
Matrix_Inv((float *)this->_m, (float *)source._m, 4);
}
} // end of namespace TinyGL } // end of namespace TinyGL

View file

@ -3,26 +3,30 @@
namespace TinyGL { namespace TinyGL {
#define X _v[0]
#define Y _v[1]
#define Z _v[2]
#define W _v[3]
// Matrix & Vertex // Matrix & Vertex
class Vector3 { class Vector3 {
public: public:
Vector3(); Vector3() { }
Vector3(const Vector3 &other);
Vector3(float x, float y, float z); Vector3(float x, float y, float z);
float getX() const { return _v[0]; } //float getX() const { return _v[0]; }
float getY() const { return _v[1]; } //float getY() const { return _v[1]; }
float getZ() const { return _v[2]; } //float getZ() const { return _v[2]; }
void setX(float val) { _v[0] = val; } //void setX(float val) { _v[0] = val; }
void setY(float val) { _v[1] = val; } //void setY(float val) { _v[1] = val; }
void setZ(float val) { _v[2] = val; } //void setZ(float val) { _v[2] = val; }
void normalize(); void normalize();
inline float getLength() const { return sqrt(_v[0] * _v[0] + _v[1] * _v[1] + _v[2] * _v[2]); } float getLength() const { return sqrt(_v[0] * _v[0] + _v[1] * _v[1] + _v[2] * _v[2]); }
inline static float dot(const Vector3 &a, const Vector3 &b) { static float dot(const Vector3 &a, const Vector3 &b) {
return a._v[0] * b._v[0] + a._v[1] * b._v[1] + a._v[2] * b._v[2]; return a._v[0] * b._v[0] + a._v[1] * b._v[1] + a._v[2] * b._v[2];
} }
@ -34,11 +38,6 @@ public:
return _v[0] != other._v[0] || _v[1] != other._v[1] || _v[2] != other._v[2]; return _v[0] != other._v[0] || _v[1] != other._v[1] || _v[2] != other._v[2];
} }
Vector3 &operator=(const Vector3 &other) {
memcpy(_v,other._v,sizeof(_v));
return *this;
}
Vector3 operator-() const { Vector3 operator-() const {
return Vector3(-_v[0],-_v[1],-_v[2]); return Vector3(-_v[0],-_v[1],-_v[2]);
} }
@ -75,21 +74,16 @@ public:
_v[2] -= value; _v[2] -= value;
return *this; return *this;
} }
private:
float _v[3]; float _v[3];
}; };
class Vector4 { class Vector4 {
public: public:
Vector4(); Vector4() { }
Vector4(const Vector3 &vec, float w); Vector4(const Vector3 &vec, float w);
Vector4(float x, float y, float z, float w); Vector4(float x, float y, float z, float w);
Vector4 &operator=(const Vector4 &other) {
memcpy(_v,other._v,sizeof(_v));
return *this;
}
bool operator==(const Vector4 &other) const { bool operator==(const Vector4 &other) const {
return _v[0] == other._v[0] && _v[1] == other._v[1] && _v[2] == other._v[2] && _v[3] == other._v[3]; return _v[0] == other._v[0] && _v[1] == other._v[1] && _v[2] == other._v[2] && _v[3] == other._v[3];
} }
@ -142,33 +136,26 @@ public:
return Vector3(_v[0],_v[1],_v[2]); return Vector3(_v[0],_v[1],_v[2]);
} }
float getX() const { return _v[0]; } //float getX() const { return _v[0]; }
float getY() const { return _v[1]; } //float getY() const { return _v[1]; }
float getZ() const { return _v[2]; } //float getZ() const { return _v[2]; }
float getW() const { return _v[3]; } //float getW() const { return _v[3]; }
void setX(float val) { _v[0] = val; } //void setX(float val) { _v[0] = val; }
void setY(float val) { _v[1] = val; } //void setY(float val) { _v[1] = val; }
void setZ(float val) { _v[2] = val; } //void setZ(float val) { _v[2] = val; }
void setW(float val) { _v[3] = val; } //void setW(float val) { _v[3] = val; }
private:
float _v[4]; float _v[4];
}; };
class Matrix4 { class Matrix4 {
public: public:
Matrix4(); Matrix4() { }
Matrix4(const Matrix4 &other);
bool IsIdentity() const; bool IsIdentity() const;
Matrix4 &operator=(const Matrix4 &other) { inline Matrix4 operator+(const Matrix4 &b) const {
memcpy(_m,other._m,sizeof(_m));
return *this;
}
Matrix4 operator+(const Matrix4 &b) const {
Matrix4 result; Matrix4 result;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
@ -178,7 +165,7 @@ public:
return result; return result;
} }
Matrix4 operator-(const Matrix4 &b) const { inline Matrix4 operator-(const Matrix4 &b) const {
Matrix4 result; Matrix4 result;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
@ -188,12 +175,11 @@ public:
return result; return result;
} }
Matrix4 operator*(const Matrix4 &b) const { inline Matrix4 operator*(const Matrix4 &b) const {
Matrix4 result; Matrix4 result;
float s;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
s = 0.0; float s = 0.0;
for (int k = 0; k < 4; k++) for (int k = 0; k < 4; k++)
s += this->get(i,k) * b.get(k,j); s += this->get(i,k) * b.get(k,j);
result.set(i,j,s); result.set(i,j,s);
@ -202,8 +188,17 @@ public:
return result; return result;
} }
Matrix4 &operator*=(const Matrix4 &b) { inline Matrix4 &operator*=(const Matrix4 &b) {
*this = *this * b; Matrix4 a = *this;
float s;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
s = 0.0;
for (int k = 0; k < 4; k++)
s += a.get(i,k) * b.get(k,j);
this->set(i,j,s);
}
}
return *this; return *this;
} }
@ -226,14 +221,45 @@ public:
return _m[x][y]; return _m[x][y];
} }
void invert();
void transpose();
Matrix4 transpose() const; Matrix4 transpose() const;
Matrix4 inverseOrtho() const; Matrix4 inverseOrtho() const;
Matrix4 inverse() const; Matrix4 inverse() const;
Vector3 transform(const Vector3 &vector) const; inline Vector3 transform(const Vector3 &vector) const {
Vector3 transform3x3(const Vector3 &vector) const; // Transform the vector as if this were a 3x3 matrix. return Vector3(
Vector4 transform3x4(const Vector4 &vector) const; // Transform the vector as if this were a 3x4 matrix. vector.X * _m[0][0] + vector.Y * _m[0][1] + vector.Z * _m[0][2] + _m[0][3],
Vector4 transform(const Vector4 &vector) const; vector.X * _m[1][0] + vector.Y * _m[1][1] + vector.Z * _m[1][2] + _m[1][3],
vector.X * _m[2][0] + vector.Y * _m[2][1] + vector.Z * _m[2][2] + _m[2][3]);
}
// Transform the vector as if this were a 3x3 matrix.
inline Vector3 transform3x3(const Vector3 &vector) const {
return Vector3(
vector.X * _m[0][0] + vector.Y * _m[0][1] + vector.Z * _m[0][2],
vector.X * _m[1][0] + vector.Y * _m[1][1] + vector.Z * _m[1][2],
vector.X * _m[2][0] + vector.Y * _m[2][1] + vector.Z * _m[2][2]);
}
// Transform the vector as if this were a 3x4 matrix.
inline Vector4 transform3x4(const Vector4 &vector) const {
return Vector4(
vector.X * _m[0][0] + vector.Y * _m[0][1] + vector.Z * _m[0][2] + _m[0][3],
vector.X * _m[1][0] + vector.Y * _m[1][1] + vector.Z * _m[1][2] + _m[1][3],
vector.X * _m[2][0] + vector.Y * _m[2][1] + vector.Z * _m[2][2] + _m[2][3],
vector.X * _m[3][0] + vector.Y * _m[3][1] + vector.Z * _m[3][2] + _m[3][3]);
}
inline Vector4 transform(const Vector4 &vector) const {
return Vector4(
vector.X * _m[0][0] + vector.Y * _m[0][1] + vector.Z * _m[0][2] + vector.W * _m[0][3],
vector.X * _m[1][0] + vector.Y * _m[1][1] + vector.Z * _m[1][2] + vector.W * _m[1][3],
vector.X * _m[2][0] + vector.Y * _m[2][1] + vector.Z * _m[2][2] + vector.W * _m[2][3],
vector.X * _m[3][0] + vector.Y * _m[3][1] + vector.Z * _m[3][2] + vector.W * _m[3][3]);
}
private: private:
float _m[4][4]; float _m[4][4];
}; };