|
import java.io.PrintStream;
|
|
class LA
|
{
|
|
static cVector newVector(double x, double y, double z)
|
{
|
cVector temp = new cVector();
|
temp.x = x;
|
temp.y = y;
|
temp.z = z;
|
return temp;
|
}
|
|
static void setVector(cVector v, double x, double y, double z)
|
{
|
v.x = x;
|
v.y = y;
|
v.z = z;
|
}
|
|
static String toPOVRay(cVector v)
|
{
|
StringBuffer buf = new StringBuffer(50);
|
toPOVRay(v, buf);
|
return buf.toString();
|
}
|
|
static void toPOVRay(cVector v, StringBuffer buf)
|
{
|
buf.append('<');
|
buf.append(v.x);
|
buf.append(',');
|
buf.append(v.y);
|
buf.append(',');
|
buf.append(v.z);
|
buf.append('>');
|
}
|
|
static boolean vecEqual(cVector a, cVector b)
|
{
|
return a.x == b.x && a.y == b.y && a.z == b.z;
|
}
|
|
static double distance(cVector a, cVector b)
|
{
|
return Math.sqrt(distance2(a, b));
|
}
|
|
static double distance2(cVector a, cVector b)
|
{
|
double x = b.x - a.x;
|
double y = b.y - a.y;
|
double z = b.z - a.z;
|
|
return x * x + y * y + z * z;
|
}
|
|
static void vecNegate(cVector v)
|
{
|
v.x *= -1;
|
v.y *= -1;
|
v.z *= -1;
|
}
|
|
static void vecScale(cVector v, double s)
|
{
|
v.x *= s;
|
v.y *= s;
|
v.z *= s;
|
}
|
|
static double vecDot(cVector a, cVector b)
|
{
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
}
|
|
static double vecLen(cVector v)
|
{
|
return (double) Math.sqrt(vecDot(v, v));
|
}
|
|
static double vecLen2(cVector v)
|
{
|
return vecDot(v, v);
|
}
|
|
static void vecCopy(cVector a, cVector b)
|
{
|
Grafreed.Assert (a != null);
|
assert (b != null);
|
|
b.x = a.x;
|
b.y = a.y;
|
b.z = a.z;
|
}
|
|
static void vecAdd(cVector a, cVector b, cVector c)
|
{
|
c.x = a.x + b.x;
|
c.y = a.y + b.y;
|
c.z = a.z + b.z;
|
}
|
|
static void vecSub(cVector a, cVector b, cVector c)
|
{
|
c.x = a.x - b.x;
|
c.y = a.y - b.y;
|
c.z = a.z - b.z;
|
}
|
|
static void vecCross(cVector a, cVector b, cVector c)
|
{
|
c.x = a.y * b.z - a.z * b.y;
|
c.y = a.z * b.x - a.x * b.z;
|
c.z = a.x * b.y - a.y * b.x;
|
}
|
|
static boolean vecNormalize(cVector v)
|
{
|
double len = v.x * v.x + v.y * v.y + v.z * v.z; // vecLen(v);
|
|
if (len <= 0) // 0.0001)
|
{
|
return false;
|
}
|
|
len = Math.sqrt(len);
|
|
//vecScale(v, 1 / Math.sqrt(len));
|
v.x /= len;
|
v.y /= len;
|
v.z /= len;
|
return true;
|
}
|
|
static cVector xformPos(cVector v, double mat[][])
|
{
|
new Exception().printStackTrace();
|
cVector temp = new cVector();
|
xformPos(v, mat, temp);
|
return temp;
|
}
|
|
static void xformPos(cVector in, double mat[][], cVector out)
|
{
|
//assert (mat != null);
|
if (mat == null)
|
{
|
out.set(in);
|
return;
|
}
|
|
assert (in != null);
|
for (int i = 0; i < 3; i++)
|
{
|
xfpTemp.set(i, in.x * mat[0][i] + in.y * mat[1][i] + in.z * mat[2][i] + mat[3][i]);
|
}
|
|
vecCopy(xfpTemp, out);
|
}
|
|
static cVector xformDir(cVector v, double mat[][])
|
{
|
new Exception().printStackTrace();
|
System.exit(0);
|
cVector temp = new cVector();
|
xformDir(v, mat, temp);
|
return temp;
|
}
|
|
static void xformDir(cVector in, double mat[][], cVector out)
|
{
|
//xfdTemp.x = xfdTemp.y = xfdTemp.z = 0;
|
//xformPos(xfdTemp, mat, xfdTemp);
|
//xformPos(in, mat, out);
|
//vecSub(out, xfdTemp, out);
|
if (mat == null)
|
{
|
out.set(in);
|
return;
|
}
|
|
for (int i = 0; i < 3; i++)
|
{
|
xfpTemp.set(i, in.x * mat[0][i] + in.y * mat[1][i] + in.z * mat[2][i]);
|
}
|
|
vecCopy(xfpTemp, out);
|
}
|
|
static double[][] newMatrix()
|
{
|
double temp[][] = new double[4][4];
|
matIdentity(temp);
|
return temp;
|
}
|
|
static void matPrint(double mat[][])
|
{
|
for (int i = 0; i < 4; i++)
|
{
|
for (int j = 0; j < 4; j++)
|
{
|
System.out.print(mat[i][j]);
|
if (j < 3)
|
{
|
System.out.print(", ");
|
}
|
}
|
System.out.println();
|
}
|
}
|
|
static void matIdentity(double mat[][])
|
{
|
// matIdentity(mat, false);
|
int s = 4;
|
|
for (int i = 0; i < s; i++)
|
{
|
double[] mati = mat[i];
|
for (int j = 0; j < s; j++)
|
{
|
mati[j] = i != j ? 0 : 1;
|
}
|
}
|
}
|
|
static void matIdentity(double mat[][], boolean rotationonly)
|
{
|
int s = 4;
|
|
if (rotationonly)
|
{
|
s = 3;
|
|
for (int i = 0; i < s; i++)
|
{
|
double[] mati = mat[i];
|
for (int j = 0; j < s; j++)
|
{
|
mati[j] = i != j ? 0 : 1;
|
}
|
}
|
}
|
else
|
{
|
mat[3][0] = 0;
|
mat[3][1] = 0;
|
mat[3][2] = 0;
|
}
|
}
|
|
static boolean isIdentity(double mat[][])
|
{
|
if (mat == null)
|
return true;
|
|
//new Exception().printStackTrace();
|
//LA.matPrint(mat);
|
for (int i = 0; i < 4; i++)
|
{
|
double[] mati = mat[i];
|
for (int j = 0; j < 4; j++)
|
{
|
if (mati[j] != (i != j ? 0 : 1))
|
{
|
return false;
|
}
|
}
|
}
|
|
return true;
|
}
|
|
static boolean isIdentityEps(double mat[][])
|
{
|
if (mat == null)
|
return true;
|
|
//new Exception().printStackTrace();
|
//LA.matPrint(mat);
|
for (int i = 0; i < 4; i++)
|
{
|
double[] mati = mat[i];
|
for (int j = 0; j < 4; j++)
|
{
|
if ((mati[j] - ((i != j) ? 0 : 1)) > 0.00001)
|
{
|
return false;
|
}
|
}
|
}
|
|
return true;
|
}
|
|
static void matCopy(double src[][], double dst[][])
|
{
|
for (int i = 0; i < 4; i++)
|
{
|
double[] dsti = dst[i];
|
double[] srci = src[i];
|
for (int j = 0; j < 4; j++)
|
{
|
dsti[j] = srci[j];
|
}
|
|
}
|
|
// Last row should always be 0 0 0 1
|
Grafreed.Assert(Math.abs(src[0][3]) <= 1E-15);
|
Grafreed.Assert(Math.abs(src[1][3]) <= 1E-15);
|
Grafreed.Assert(Math.abs(src[2][3]) <= 1E-15);
|
Grafreed.Assert(Math.abs(src[3][3] - 1) <= 1E-15);
|
Grafreed.Assert(Math.abs(dst[0][3]) <= 1E-15);
|
Grafreed.Assert(Math.abs(dst[1][3]) <= 1E-15);
|
Grafreed.Assert(Math.abs(dst[2][3]) <= 1E-15);
|
Grafreed.Assert(Math.abs(dst[3][3] - 1) <= 1E-15);
|
}
|
|
static double toRadians(double degrees)
|
{
|
return (degrees * Math.PI) / 180;
|
}
|
|
static void matConcat(double left[][], double right[][], double product[][])
|
{
|
//double tmp[][] = left;
|
//left = right;
|
//right = tmp;
|
|
for (int j = 0; j < 4; j++)
|
{
|
double[] rightj = right[j];
|
double[] concat = concatTemp[j];
|
for (int i = 0; i < 4; i++)
|
{
|
concat[i] = 0;
|
for (int k = 0; k < 4; k++)
|
{
|
concat[i] += left[k][i] * rightj[k];
|
}
|
}
|
}
|
|
matCopy(concatTemp, product);
|
}
|
|
static void matTranslate(double mat[][], double dx, double dy, double dz)
|
{
|
matIdentity(xlateTemp);
|
xlateTemp[3][0] = dx;
|
xlateTemp[3][1] = dy;
|
xlateTemp[3][2] = dz;
|
//xlateTemp[0][3] = dx;
|
//xlateTemp[1][3] = dy;
|
//xlateTemp[2][3] = dz;
|
matConcat(xlateTemp, mat, mat);
|
}
|
|
static void matHomogene(double mat[][], double dx, double dy, double dz)
|
{
|
matIdentity(xlateTemp);
|
xlateTemp[0][3] = dx;
|
xlateTemp[1][3] = dy;
|
xlateTemp[2][3] = dz;
|
//xlateTemp[0][3] = dx;
|
//xlateTemp[1][3] = dy;
|
//xlateTemp[2][3] = dz;
|
matConcat(xlateTemp, mat, mat);
|
}
|
|
static void matTranslateInv(double mat[][], double dx, double dy, double dz)
|
{
|
matIdentity(xlateTemp);
|
xlateTemp[3][0] = dx;
|
xlateTemp[3][1] = dy;
|
xlateTemp[3][2] = dz;
|
//xlateTemp[0][3] = dx;
|
//xlateTemp[1][3] = dy;
|
//xlateTemp[2][3] = dz;
|
matConcat(mat, xlateTemp, mat);
|
}
|
|
static void matScale(double mat[][], double sx, double sy, double sz)
|
{
|
matIdentity(xlateTemp);
|
xlateTemp[0][0] = sx;
|
xlateTemp[1][1] = sy;
|
xlateTemp[2][2] = sz;
|
matConcat(xlateTemp, mat, mat);
|
//matConcat(mat, xlateTemp, mat);
|
}
|
|
static void matXRotate(double mat[][], double radians)
|
{
|
matIdentity(rotTemp);
|
rotTemp[1][1] = rotTemp[2][2] = (double) Math.cos(radians);
|
rotTemp[2][1] = -(rotTemp[1][2] = (double) Math.sin(radians));
|
// if (CameraPane.LOCALTRANSFORM)
|
matConcat(rotTemp, mat, mat);
|
// else
|
// matConcat(mat, rotTemp, mat);
|
}
|
|
static void matYRotate(double mat[][], double radians)
|
{
|
matIdentity(rotTemp);
|
rotTemp[0][0] = rotTemp[2][2] = (double) Math.cos(-radians);
|
rotTemp[2][0] = -(rotTemp[0][2] = (double) Math.sin(-radians));
|
// if (CameraPane.LOCALTRANSFORM)
|
matConcat(rotTemp, mat, mat);
|
// else
|
// matConcat(mat, rotTemp, mat);
|
}
|
|
static void matZRotate(double mat[][], double radians)
|
{
|
matIdentity(rotTemp);
|
rotTemp[0][0] = rotTemp[1][1] = (double) Math.cos(radians);
|
rotTemp[1][0] = -(rotTemp[0][1] = (double) Math.sin(radians));
|
// if (CameraPane.LOCALTRANSFORM)
|
matConcat(rotTemp, mat, mat);
|
// else
|
// matConcat(mat, rotTemp, mat);
|
}
|
|
// Project A onto B
|
static void matRotate(double mat[][], cVector pA, cVector pB)
|
{
|
matIdentity(mat);
|
|
double x, y, z, w;
|
|
/*
|
if (pA == null || pB == null)
|
{
|
x = y = z = 0.0D;
|
w = 1.0D;
|
return;
|
}
|
*/
|
cVector lA = cStatic.point1; // new cVector(pA);
|
lA.set(pA);
|
cVector lB = cStatic.point2; // new cVector(pB);
|
lB.set(pB);
|
if (lA.length2() > 0.0F)
|
{
|
lA.normalize();
|
}
|
if (lB.length2() > 0.0F)
|
{
|
lB.normalize();
|
}
|
double lDot = lA.dot(lB);
|
cVector lCP = cStatic.point3; // new cVector();
|
lCP.cross(lA, lB);
|
if (lCP.length2() > 0.0F)
|
{
|
lCP.normalize();
|
} else if (lDot < 0.0D)
|
{
|
lCP.cross(lA, cVector.Y);
|
if (lCP.length2() > 0.0F)
|
{
|
lCP.normalize();
|
} else
|
{
|
lCP.cross(lA, cVector.X);
|
lCP.normalize();
|
}
|
}
|
double lTmp = (lDot + 1.0D) / 2D;
|
double lCos = Math.sqrt(lTmp);
|
double lSin = Math.sqrt(1.0D - lTmp);
|
x = lCP.x * lSin;
|
y = lCP.y * lSin;
|
z = lCP.z * lSin;
|
w = lCos;
|
|
/*
|
| 2 2 |
|
| 1 - 2Y - 2Z 2XY - 2ZW 2XZ + 2YW |
|
| |
|
| 2 2 |
|
M = | 2XY + 2ZW 1 - 2X - 2Z 2YZ - 2XW |
|
| |
|
| 2 2 |
|
| 2XZ - 2YW 2YZ + 2XW 1 - 2X - 2Y |
|
| |
|
*/
|
mat[0][0] = 1 - 2 * (y*y + z*z);
|
mat[1][1] = 1 - 2 * (x*x + z*z);
|
mat[2][2] = 1 - 2 * (x*x + y*y);
|
mat[0][1] = 2 * (x*y - z*w);
|
mat[0][2] = 2 * (x*z + y*w);
|
mat[1][0] = 2 * (x*y + z*w);
|
mat[1][2] = 2 * (y*z - x*w);
|
mat[2][0] = 2 * (x*z - y*w);
|
mat[2][1] = 2 * (y*z + x*w);
|
}
|
|
static void matTranspose(double input[][], double output[][])
|
{
|
matCopy(input, output);
|
|
for (int i = 1; i < 4; i++)
|
{
|
for (int j = 0; j < i; j++)
|
{
|
double t = output[i][j];
|
output[i][j] = output[j][i];
|
output[j][i] = t;
|
}
|
}
|
}
|
|
static void matInvert(double input[][], double output[][])
|
{
|
int irow = 0;
|
int icol = 0;
|
matCopy(input, output);
|
for (int i = 0; i < 4; i++)
|
{
|
ipiv[i] = -1;
|
}
|
|
for (int i = 0; i < 4; i++)
|
{
|
double big = 0;
|
for (int j = 0; j < 4; j++)
|
{
|
if (ipiv[j] != 0)
|
{
|
double[] cj = output[j];
|
for (int k = 0; k < 4; k++)
|
{
|
if (ipiv[k] == -1)
|
{
|
double piv = Math.abs(cj[k]);
|
if (piv >= big)
|
{
|
big = piv;
|
irow = j;
|
icol = k;
|
}
|
} else if (ipiv[k] > 0)
|
{
|
System.out.println("singular matrix");
|
//new Exception().printStackTrace();
|
return;
|
}
|
}
|
|
}
|
}
|
|
ipiv[icol]++;
|
double[] col = output[icol];
|
if (irow != icol)
|
{
|
double[] row = output[irow];
|
for (int j = 0; j < 4; j++)
|
{
|
double dum = row[j];
|
row[j] = col[j];
|
col[j] = dum;
|
}
|
|
}
|
|
indxr[i] = irow;
|
indxc[i] = icol;
|
/*
|
if (Math.abs(output[icol][icol]) < 1E-20)
|
{
|
System.out.println("singular matrix II");
|
new Exception().printStackTrace();
|
return;
|
}
|
*/
|
double pivinv = 1 / col[icol];
|
col[icol] = 1;
|
for (int j = 0; j < 4; j++)
|
{
|
col[j] *= pivinv;
|
}
|
|
for (int j = 0; j < 4; j++)
|
{
|
if (j != icol)
|
{
|
double[] cj = output[j];
|
double dum = cj[icol];
|
cj[icol] = 0;
|
for (int k = 0; k < 4; k++)
|
{
|
cj[k] -= col[k] * dum;
|
}
|
}
|
}
|
}
|
|
for (int i = 3; i >= 0; i--)
|
{
|
if (indxr[i] != indxc[i])
|
{
|
for (int j = 0; j < 4; j++)
|
{
|
double[] cj = output[j];
|
double dum = cj[indxr[i]];
|
cj[indxr[i]] = cj[indxc[i]];
|
cj[indxc[i]] = dum;
|
}
|
}
|
}
|
}
|
|
private static cVector xfpTemp = new cVector();
|
private static cVector xfdTemp = new cVector();
|
private static double concatTemp[][] = new double[4][4];
|
private static double xlateTemp[][] = new double[4][4];
|
private static double rotTemp[][] = new double[4][4];
|
private static int ipiv[] = new int[4];
|
private static int indxr[] = new int[4];
|
private static int indxc[] = new int[4];
|
|
static double[][] Identity = new double[4][4];
|
|
static int SIZE = 0; // 65536*64;
|
|
static double[] costable = new double[SIZE];
|
static double[] sintable = new double[SIZE];
|
|
static double PI2 = 2 * Math.PI;
|
|
static
|
{
|
for (int i=SIZE; --i>=0;)
|
{
|
costable[i] = Math.cos(PI2 * i/SIZE);
|
sintable[i] = Math.sin(PI2 * i*i/SIZE/SIZE);
|
}
|
|
LA.matIdentity(Identity);
|
}
|
|
static double cos(double x0)
|
{
|
if (true)
|
return Math.cos(x0);
|
|
double x = x0;
|
|
while (x < 0)
|
{
|
x += PI2;
|
}
|
|
while (x > PI2)
|
{
|
x -= PI2;
|
}
|
|
x /= PI2;
|
|
int modi = (int)(x*(SIZE-1));
|
|
// double real = Math.cos(x0);
|
// double test = costable[modi];
|
//
|
// if (Math.abs(real - test) > 0.000001)
|
// x = x;
|
|
return costable[modi];
|
}
|
|
static double sin(double x0)
|
{
|
if (true)
|
return Math.sin(x0);
|
|
double x = x0;
|
|
while (x < 0)
|
{
|
x += PI2;
|
}
|
|
while (x > PI2)
|
{
|
x -= PI2;
|
}
|
|
x /= PI2;
|
|
x = Math.sqrt(x);
|
|
int modi = (int)(x*(SIZE-1));
|
|
// double real = Math.sin(x0);
|
// double test = sintable[modi];
|
//
|
// if (Math.abs(real - test) > 0.000001)
|
// x = x;
|
|
return sintable[modi];
|
}
|
}
|