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) {
i = idx * (3 + c->normal_array_stride);
c->current_normal.setX(c->normal_array[i]);
c->current_normal.setY(c->normal_array[i + 1]);
c->current_normal.setZ(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.X = (c->normal_array[i]);
c->current_normal.Y = (c->normal_array[i + 1]);
c->current_normal.Z = (c->normal_array[i + 2]);
c->current_normal.W = (0.0f); // NOTE: this used to be Z but assigning Z again seemed like a bug...
}
if (states & TEXCOORD_ARRAY) {
int size = c->texcoord_array_size;
i = idx * (size + c->texcoord_array_stride);
c->current_tex_coord.setX(c->texcoord_array[i]);
c->current_tex_coord.setY(c->texcoord_array[i + 1]);
c->current_tex_coord.setZ(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.X = (c->texcoord_array[i]);
c->current_tex_coord.Y = (c->texcoord_array[i + 1]);
c->current_tex_coord.Z = (size > 2 ? c->texcoord_array[i + 2] : 0.0f);
c->current_tex_coord.W = (size > 3 ? c->texcoord_array[i + 3] : 1.0f);
}
if (states & VERTEX_ARRAY) {
GLParam p[5];

View File

@ -14,9 +14,9 @@ void glopClearDepth(GLContext *c, GLParam *p) {
void glopClear(GLContext *c, GLParam *p) {
int mask = p[1].i;
int z = 0;
int r = (int)(c->clear_color.getX() * 65535);
int g = (int)(c->clear_color.getY() * 65535);
int b = (int)(c->clear_color.getZ() * 65535);
int r = (int)(c->clear_color.X * 65535);
int g = (int)(c->clear_color.Y * 65535);
int b = (int)(c->clear_color.Z * 65535);
// TODO : correct value of Z
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;
// coordinates
winv = (float)(1.0 / v->pc.getW());
v->zp.x = (int)(v->pc.getX() * winv * c->viewport.scale.getX() + c->viewport.trans.getX());
v->zp.y = (int)(v->pc.getY() * winv * c->viewport.scale.getY() + c->viewport.trans.getY());
v->zp.z = (int)(v->pc.getZ() * winv * c->viewport.scale.getZ() + c->viewport.trans.getZ());
winv = (float)(1.0 / v->pc.W);
v->zp.x = (int)(v->pc.X * winv * c->viewport.scale.X + c->viewport.trans.X);
v->zp.y = (int)(v->pc.Y * winv * c->viewport.scale.Y + c->viewport.trans.Y);
v->zp.z = (int)(v->pc.Z * winv * c->viewport.scale.Z + c->viewport.trans.Z);
// color
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);
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);
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);
} else {
// 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
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.t = (int)(v->tex_coord.getY() * (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.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) {
return;
} else {
dx = p2->pc.getX() - p1->pc.getX();
dy = p2->pc.getY() - p1->pc.getY();
dz = p2->pc.getZ() - p1->pc.getZ();
dw = p2->pc.getW() - p1->pc.getW();
x1 = p1->pc.getX();
y1 = p1->pc.getY();
z1 = p1->pc.getZ();
w1 = p1->pc.getW();
dx = p2->pc.X - p1->pc.X;
dy = p2->pc.Y - p1->pc.Y;
dz = p2->pc.Z - p1->pc.Z;
dw = p2->pc.W - p1->pc.W;
x1 = p1->pc.X;
y1 = p1->pc.Y;
z1 = p1->pc.Z;
w1 = p1->pc.W;
tmin = 0;
tmax = 1;
@ -166,19 +166,19 @@ void gl_draw_line(GLContext *c, GLVertex *p1, GLVertex *p2) {
#define clip_func(name, sign, dir, dir1, dir2) \
static float name(Vector4 *c, Vector4 *a, Vector4 *b) { \
float t, dX, dY, dZ, dW, den;\
dX = (b->getX() - a->getX()); \
dY = (b->getY() - a->getY()); \
dZ = (b->getZ() - a->getZ()); \
dW = (b->getW() - a->getW()); \
dX = (b->X - a->X); \
dY = (b->Y - a->Y); \
dZ = (b->Z - a->Z); \
dW = (b->W - a->W); \
den = -(sign d ## dir) + dW; \
if (den == 0) \
t = 0; \
else \
t = (sign a->get ## dir () - a->getW()) / den; \
c->set ## dir1 (a->get ## dir1 () + t * d ## dir1); \
c->set ## dir2 (a->get ## dir2 () + t * d ## dir2); \
c->setW(a->getW() + t * dW); \
c->set ## dir (sign c->getW()); \
t = (sign a-> dir - a->W) / den; \
c-> dir1 = (a-> dir1 + t * d ## dir1); \
c-> dir2 = (a-> dir2 + t * d ## dir2); \
c->W = (a->W + t * dW); \
c-> dir = (sign c->W); \
return t; \
}
@ -198,23 +198,23 @@ float(*clip_proc[6])(Vector4 *, Vector4 *, Vector4 *) = {
static inline void updateTmp(GLContext *c, GLVertex *q,
GLVertex *p0, GLVertex *p1, float t) {
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.setW(a);
q->color.W = a;
} else {
q->color.setX(p0->color.getX());
q->color.setY(p0->color.getY());
q->color.setZ(p0->color.getZ());
q->color.X = (p0->color.X);
q->color.Y = (p0->color.Y);
q->color.Z = (p0->color.Z);
//q->color = p0->color;
}
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.
q->tex_coord.setX(p0->tex_coord.getX() + (p1->tex_coord.getX() - p0->tex_coord.getX()) * t);
q->tex_coord.setY(p0->tex_coord.getY() + (p1->tex_coord.getY() - p0->tex_coord.getY()) * t);
q->tex_coord.X = (p0->tex_coord.X + (p1->tex_coord.X - p0->tex_coord.X) * 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)
gl_transform_to_viewport(c, q);
}

View File

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

View File

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

View File

@ -40,13 +40,13 @@ void gl_eval_viewport(GLContext *c) {
v = &c->viewport;
v->trans.setX((float)(((v->xsize - 0.5) / 2.0) + v->xmin));
v->trans.setY((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.X = ((float)(((v->xsize - 0.5) / 2.0) + v->xmin));
v->trans.Y = ((float)(((v->ysize - 0.5) / 2.0) + v->ymin));
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.setY((float)(-(v->ysize - 0.5) / 2.0));
v->scale.setZ((float)(-((zsize - 0.5) / 2.0)));
v->scale.X = ((float)((v->xsize - 0.5) / 2.0));
v->scale.Y = ((float)(-(v->ysize - 0.5) / 2.0));
v->scale.Z = ((float)(-((zsize - 0.5) / 2.0)));
}
void glopBegin(GLContext *c, GLParam *p) {
@ -63,7 +63,9 @@ void glopBegin(GLContext *c, GLParam *p) {
if (c->matrix_model_projection_updated) {
if (c->lighting_enabled) {
// 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 {
// precompute projection matrix
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);
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) {

View File

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

View File

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