package com.glview.graphics;
public class Matrix33 {
private static ThreadLocal<Matrix33> sThreadLocal = new ThreadLocal<Matrix33>() {
protected Matrix33 initialValue() {
return new Matrix33();
};
};
private static ThreadLocal<Matrix33> sConcatTmp = new ThreadLocal<Matrix33>() {
protected Matrix33 initialValue() {
return new Matrix33();
};
};
private final float[] fMat = new float[9];
private final static int kMScaleX = 0;
private final static int kMSkewX = 1;
private final static int kMTransX = 2;
private final static int kMSkewY = 3;
private final static int kMScaleY = 4;
private final static int kMTransY = 5;
private final static int kMPersp0 = 6;
private final static int kMPersp1 = 7;
private final static int kMPersp2 = 8;
public Matrix33() {
reset();
}
private void loadIdentity() {
fMat[kMScaleX] = fMat[kMScaleY] = fMat[kMPersp2] = 1;
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMTransX] = fMat[kMTransY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0;
}
public void reset() {
loadIdentity();
}
public void load(Matrix33 v) {
System.arraycopy(v.fMat, 0, fMat, 0, fMat.length);
}
public void setConcat(Matrix33 a, Matrix33 b) {
Matrix33 tmp = sConcatTmp.get();
tmp.reset();
tmp.fMat[kMScaleX] = rowcol3(a.fMat, 0, b.fMat, 0);
tmp.fMat[kMSkewX] = rowcol3(a.fMat, 0, b.fMat, 1);
tmp.fMat[kMTransX] = rowcol3(a.fMat, 0, b.fMat, 2);
tmp.fMat[kMSkewY] = rowcol3(a.fMat, 3, b.fMat, 0);
tmp.fMat[kMScaleY] = rowcol3(a.fMat, 3, b.fMat, 1);
tmp.fMat[kMTransY] = rowcol3(a.fMat, 3, b.fMat, 2);
tmp.fMat[kMPersp0] = rowcol3(a.fMat, 6, b.fMat, 0);
tmp.fMat[kMPersp1] = rowcol3(a.fMat, 6, b.fMat, 1);
tmp.fMat[kMPersp2] = rowcol3(a.fMat, 6, b.fMat, 2);
normalize_perspective(tmp.fMat);
load(tmp);
}
public void postConcat(Matrix33 mat) {
this.setConcat(mat, this);
}
public void preConcat(Matrix33 mat) {
this.setConcat(this, mat);
}
public void setScale(float sx, float sy, float px, float py) {
if (1 == sx && 1 == sy) {
reset();
} else {
fMat[kMScaleX] = sx;
fMat[kMScaleY] = sy;
fMat[kMTransX] = px - sx * px;
fMat[kMTransY] = py - sy * py;
fMat[kMPersp2] = 1;
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0;
}
}
public void setScale(float sx, float sy) {
if (1 == sx && 1 == sy) {
reset();
} else {
fMat[kMScaleX] = sx;
fMat[kMScaleY] = sy;
fMat[kMPersp2] = 1;
fMat[kMTransX] = fMat[kMTransY] =
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0;
}
}
public void preScale(float sx, float sy) {
if (1 == sx && 1 == sy) {
return;
}
// the assumption is that these multiplies are very cheap, and that
// a full concat and/or just computing the matrix type is more expensive.
// Also, the fixed-point case checks for overflow, but the float doesn't,
// so we can get away with these blind multiplies.
fMat[kMScaleX] *= sx;
fMat[kMSkewY] *= sx;
fMat[kMPersp0] *= sx;
fMat[kMSkewX] *= sy;
fMat[kMScaleY] *= sy;
fMat[kMPersp1] *= sy;
}
public void preScale(float sx, float sy, float px, float py) {
if (1 == sx && 1 == sy) {
return;
}
Matrix33 m = sThreadLocal.get();
m.setScale(sx, sy, px, py);
preConcat(m);
}
public void postScale(float sx, float sy, float px, float py) {
if (1 == sx && 1 == sy) {
return;
}
Matrix33 m = sThreadLocal.get();
m.setScale(sx, sy, px, py);
postConcat(m);
}
public void postScale(float sx, float sy) {
if (1 == sx && 1 == sy) {
return;
}
Matrix33 m = sThreadLocal.get();
m.setScale(sx, sy);
postConcat(m);
}
public void setTranslate(float dx, float dy) {
if (dx != 0 || dy != 0) {
fMat[kMTransX] = dx;
fMat[kMTransY] = dy;
fMat[kMScaleX] = fMat[kMScaleY] = fMat[kMPersp2] = 1;
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0;
} else {
reset();
}
}
public void preTranslate(float dx, float dy) {
if (dx == 0 && dy == 0) {
return;
}
Matrix33 m = sThreadLocal.get();
m.setTranslate(dx, dy);
preConcat(m);
}
public void postTranslate(float dx, float dy) {
if (dx == 0 && dy == 0) {
return;
}
Matrix33 m = sThreadLocal.get();
m.setTranslate(dx, dy);
postConcat(m);
}
public void setSinCos(float sinV, float cosV) {
fMat[kMScaleX] = cosV;
fMat[kMSkewX] = -sinV;
fMat[kMTransX] = 0;
fMat[kMSkewY] = sinV;
fMat[kMScaleY] = cosV;
fMat[kMTransY] = 0;
fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = 1;
}
public void setSinCos(float sinV, float cosV, float px, float py) {
float oneMinusCosV = 1 - cosV;
fMat[kMScaleX] = cosV;
fMat[kMSkewX] = -sinV;
fMat[kMTransX] = sdot(sinV, py, oneMinusCosV, px);
fMat[kMSkewY] = sinV;
fMat[kMScaleY] = cosV;
fMat[kMTransY] = sdot(-sinV, px, oneMinusCosV, py);
fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = 1;
}
public void setRotate(float degrees, float px, float py) {
float a = degrees * (float) (Math.PI / 180.0f);
float sinV = (float) Math.sin(a);
float cosV = (float) Math.cos(a);
setSinCos(sinV, cosV, px, py);
}
public void setRotate(float degrees) {
float a = degrees * (float) (Math.PI / 180.0f);
float sinV = (float) Math.sin(a);
float cosV = (float) Math.cos(a);
setSinCos(sinV, cosV);
}
public void preRotate(float degrees, float px, float py) {
Matrix33 m = sThreadLocal.get();
m.setRotate(degrees, px, py);
preConcat(m);
}
public void preRotate(float degrees) {
Matrix33 m = sThreadLocal.get();
m.setRotate(degrees);
preConcat(m);
}
public void postRotate(float degrees, float px, float py) {
Matrix33 m = sThreadLocal.get();
m.setRotate(degrees, px, py);
postConcat(m);
}
public void postRotate(float degrees) {
Matrix33 m = sThreadLocal.get();
m.setRotate(degrees);
postConcat(m);
}
public void setSkew(float sx, float sy) {
fMat[kMScaleX] = 1;
fMat[kMSkewX] = sx;
fMat[kMTransX] = 0;
fMat[kMSkewY] = sy;
fMat[kMScaleY] = 1;
fMat[kMTransY] = 0;
fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = 1;
}
public void setSkew(float sx, float sy, float px, float py) {
fMat[kMScaleX] = 1;
fMat[kMSkewX] = sx;
fMat[kMTransX] = -sx * py;
fMat[kMSkewY] = sy;
fMat[kMScaleY] = 1;
fMat[kMTransY] = -sy * px;
fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = 1;
}
public void preSkew(float sx, float sy, float px, float py) {
Matrix33 m = sThreadLocal.get();
m.setSkew(sx, sy, px, py);
preConcat(m);
}
public void preSkew(float sx, float sy) {
Matrix33 m = sThreadLocal.get();
m.setSkew(sx, sy);
preConcat(m);
}
public void postSkew(float sx, float sy, float px, float py) {
Matrix33 m = sThreadLocal.get();
m.setSkew(sx, sy, px, py);
postConcat(m);
}
public void postSkew(float sx, float sy) {
Matrix33 m = sThreadLocal.get();
m.setSkew(sx, sy);
postConcat(m);
}
static float muladdmul(float a, float b, float c, float d) {
return a * b + c * d;
}
static float sdot(float a, float b, float c, float d) {
return a * b + c * d;
}
static float sdot(float a, float b, float c, float d,
float e, float f) {
return a * b + c * d + e * f;
}
static float scross(float a, float b, float c, float d) {
return a * b - c * d;
}
static float rowcol3(float row[], int rOffset, float col[], int cOffset) {
return row[rOffset + 0] * col[cOffset + 0] + row[rOffset + 1] * col[cOffset + 3] + row[rOffset + 2] * col[cOffset + 6];
}
static void normalize_perspective(float[] mat) {
if (Math.abs(mat[kMPersp2]) > 1) {
for (int i = 0; i < 9; i++)
mat[i] = mat[i] * 0.5f;
}
}
public void mapPoints(PointF[] pts, int length) {
if (pts != null) {
for (int i = 0; i < pts.length && i < length; i ++) {
PointF pt = pts[i];
mapPoint(pt, pt.x, pt.y);
}
}
}
public PointF mapPoint(PointF dst, float x, float y) {
float dx = x * fMat[kMScaleX] + y * fMat[kMSkewX] + fMat[kMTransX];
float dy = x * fMat[kMSkewY] + y * fMat[kMScaleY] + fMat[kMTransY];
float dz = x * fMat[kMPersp0] + y * fMat[kMPersp1] + fMat[kMPersp2];
if (dz != 0) dz = 1.0f / dz;
dst.x = dx * dz;
dst.y = dy * dz;
return dst;
}
}