package mikera.transformz;
import mikera.matrixx.AMatrix;
import mikera.matrixx.Matrix33;
import mikera.transformz.marker.ISpecialisedTransform;
import mikera.vectorz.AVector;
import mikera.vectorz.Vector3;
/**
* Specialised 3*4 affine transformation class
*
* Intended for composing 3d affine transformations.
*
* @author Mike
*/
public final class Affine34 extends AAffineTransform implements ISpecialisedTransform {
public double m00,m01,m02,tr0,
m10,m11,m12,tr1,
m20,m21,m22,tr2;
public Affine34() {
}
public Affine34(double m00, double m01, double m02, double tr0,
double m10, double m11, double m12, double tr1,
double m20, double m21, double m22, double tr2) {
this.m00=m00;
this.m01=m01;
this.m02=m02;
this.m10=m10;
this.m11=m11;
this.m12=m12;
this.m20=m20;
this.m21=m21;
this.m22=m22;
this.tr0=tr0;
this.tr1=tr1;
this.tr2=tr2;
}
public Affine34(AMatrix matrix, ATranslation trans) {
this(matrix,trans.getTranslationVector());
}
public Affine34(AMatrix m, AVector v) {
if ((v.length()!=3)||(m.columnCount()!=3)||(m.rowCount()!=3)) {
throw new IllegalArgumentException("Wrong source sizes for Affine34");
}
m00=m.unsafeGet(0,0);
m01=m.unsafeGet(0,1);
m02=m.unsafeGet(0,2);
m10=m.unsafeGet(1,0);
m11=m.unsafeGet(1,1);
m12=m.unsafeGet(1,2);
m20=m.unsafeGet(2,0);
m21=m.unsafeGet(2,1);
m22=m.unsafeGet(2,2);
tr0=v.unsafeGet(0);
tr1=v.unsafeGet(1);
tr2=v.unsafeGet(2);
}
public Affine34(Matrix33 m, AVector v) {
assert(v.length()==3);
assert(m.columnCount()==3);
assert(m.rowCount()==3);
m00=m.m00;
m01=m.m01;
m02=m.m02;
m10=m.m10;
m11=m.m11;
m12=m.m12;
m20=m.m20;
m21=m.m21;
m22=m.m22;
tr0=v.get(0);
tr1=v.get(1);
tr2=v.get(2);
}
@Override
public AMatrix getMatrix() {
return copyOfMatrix();
}
@Override
public ATranslation getTranslation() {
return Transformz.createTranslation(copyOfTranslationVector());
}
@Override
public Matrix33 copyOfMatrix() {
return new Matrix33(m00,m01,m02,m10,m11,m12,m20,m21,m22);
}
@Override
public Vector3 copyOfTranslationVector() {
return Vector3.of(tr0,tr1,tr2);
}
@Override
public void transform(AVector source, AVector dest) {
if ((source instanceof Vector3)&&(dest instanceof Vector3)) {
transform((Vector3)source,(Vector3)dest);
return;
}
double x=source.unsafeGet(0), y=source.unsafeGet(1), z=source.get(2);
dest.set(0,((m00*x)+(m01*y)+(m02*z)+tr0));
dest.set(1,((m10*x)+(m11*y)+(m12*z)+tr1));
dest.set(2,((m20*x)+(m21*y)+(m22*z)+tr2));
}
@Override
public void transformNormal(AVector source, AVector dest) {
if ((source instanceof Vector3)&&(dest instanceof Vector3)) {
transformNormal((Vector3)source,(Vector3)dest);
return;
}
transform(source, dest);
dest.normalise();
}
public void transformNormal(Vector3 source, Vector3 dest) {
double x=source.x, y=source.y, z=source.z;
dest.set(0,((m00*x)+(m01*y)+(m02*z)));
dest.set(1,((m10*x)+(m11*y)+(m12*z)));
dest.set(2,((m20*x)+(m21*y)+(m22*z)));
dest.normalise();
}
@Override
public void transformInPlace(AVector dest) {
if (dest instanceof Vector3) {
transformInPlace((Vector3)dest);
return;
}
double x=dest.unsafeGet(0), y=dest.unsafeGet(1), z=dest.get(2); // only last get needs to be safe
dest.set(0,((m00*x)+(m01*y)+(m02*z)+tr0));
dest.set(1,((m10*x)+(m11*y)+(m12*z)+tr1));
dest.set(2,((m20*x)+(m21*y)+(m22*z)+tr2));
}
public void transform(Vector3 source, Vector3 dest) {
Vector3 s=source;
dest.x=((m00*s.x)+(m01*s.y)+(m02*s.z)+tr0);
dest.y=((m10*s.x)+(m11*s.y)+(m12*s.z)+tr1);
dest.z=((m20*s.x)+(m21*s.y)+(m22*s.z)+tr2);
}
public void transformInPlace(Vector3 dest) {
Vector3 s=dest;
double tx=((m00*s.x)+(m01*s.y)+(m02*s.z)+tr0);
double ty=((m10*s.x)+(m11*s.y)+(m12*s.z)+tr1);
double tz=((m20*s.x)+(m21*s.y)+(m22*s.z)+tr2);
s.x=tx; s.y=ty; s.z=tz;
}
@Override
public int inputDimensions() {
return 3;
}
@Override
public int outputDimensions() {
return 3;
}
@Override
public void composeWith(ATransform a) {
if (a instanceof Affine34) {
composeWith((Affine34)a);
return;
} else if (a instanceof Translation3) {
composeWith((Translation3)a);
return;
}
super.composeWith(a);
}
public void composeWith(Affine34 a) {
double t00=(m00*a.m00)+(m01*a.m10)+(m02*a.m20);
double t01=(m00*a.m01)+(m01*a.m11)+(m02*a.m21);
double t02=(m00*a.m02)+(m01*a.m12)+(m02*a.m22);
double t10=(m10*a.m00)+(m11*a.m10)+(m12*a.m20);
double t11=(m10*a.m01)+(m11*a.m11)+(m12*a.m21);
double t12=(m10*a.m02)+(m11*a.m12)+(m12*a.m22);
double t20=(m20*a.m00)+(m21*a.m10)+(m22*a.m20);
double t21=(m20*a.m01)+(m21*a.m11)+(m22*a.m21);
double t22=(m20*a.m02)+(m21*a.m12)+(m22*a.m22);
double t03=(m00*a.tr0)+(m01*a.tr1)+(m02*a.tr2)+tr0;
double t13=(m10*a.tr0)+(m11*a.tr1)+(m12*a.tr2)+tr1;
double t23=(m20*a.tr0)+(m21*a.tr1)+(m22*a.tr2)+tr2;
m00=t00; m01=t01; m02=t02; tr0=t03;
m10=t10; m11=t11; m12=t12; tr1=t13;
m20=t20; m21=t21; m22=t22; tr2=t23;
}
public void composeWith(Matrix33 a) {
double t00=(m00*a.m00)+(m01*a.m10)+(m02*a.m20);
double t01=(m00*a.m01)+(m01*a.m11)+(m02*a.m21);
double t02=(m00*a.m02)+(m01*a.m12)+(m02*a.m22);
double t10=(m10*a.m00)+(m11*a.m10)+(m12*a.m20);
double t11=(m10*a.m01)+(m11*a.m11)+(m12*a.m21);
double t12=(m10*a.m02)+(m11*a.m12)+(m12*a.m22);
double t20=(m20*a.m00)+(m21*a.m10)+(m22*a.m20);
double t21=(m20*a.m01)+(m21*a.m11)+(m22*a.m21);
double t22=(m20*a.m02)+(m21*a.m12)+(m22*a.m22);
m00=t00; m01=t01; m02=t02;
m10=t10; m11=t11; m12=t12;
m20=t20; m21=t21; m22=t22;
}
public void composeWith(Translation3 a) {
tr0+=a.dx;
tr1+=a.dy;
tr2+=a.dz;
}
@Override
public boolean equals(Object o) {
if (o instanceof Affine34) {
return equals((Affine34)o);
}
return super.equals(o);
}
public boolean equals(Affine34 m) {
return
(m00==m.m00) &&
(m01==m.m01) &&
(m02==m.m02) &&
(m10==m.m10) &&
(m11==m.m11) &&
(m12==m.m12) &&
(m20==m.m20) &&
(m21==m.m21) &&
(m22==m.m22) &&
(tr0==m.tr0) &&
(tr1==m.tr1) &&
(tr2==m.tr2);
}
}