+long double SarrusDetScalar(long double a1, long double b1, long double c1, long double a2, long double b2, long double c2, long double a3, long double b3, long double c3)
+{
+ return a1 * b2 * c3 + a2 * b3 * c1 + a3 * b1 * c2
+ - a1 * c2 * b3 - a2 * c3 * b1 - a3 * c1 * b2;
+}
+
+void SarrusSolve(long double a1, long double b1, long double c1, long double d1, long double a2, long double b2, long double c2, long double d2, long double a3, long double b3, long double c3, long double d3, long double *a, long double *b, long double *c)
+{
+ long double det;
+ det = SarrusDetScalar(a1, b1, c1,
+ a2, b2, c2,
+ a3, b3, c3);
+ *a = SarrusDetScalar(d1, b1, c1,
+ d2, b2, c2,
+ d3, b3, c3) / det;
+ *b = SarrusDetScalar(a1, d1, c1,
+ a2, d2, c2,
+ a3, d3, c3) / det;
+ *c = SarrusDetScalar(a1, b1, d1,
+ a2, b2, d2,
+ a3, b3, d3) / det;
+}
+
+void Face_TexdefFromTextureCoordinates ( float *xyzst1, float *xyzst2, float *xyzst3, qtexture_t *q, face_t *f)
+{
+ vec3_t pvecs[2];
+ int sv, tv, uv;
+
+ long double STfromXYZ[2][4];
+
+ // get natural texture axis
+ TextureAxisFromPlane(&f->plane, pvecs[0], pvecs[1]);
+
+ if (pvecs[0][0])
+ sv = 0;
+ else if (pvecs[0][1])
+ sv = 1;
+ else
+ sv = 2;
+
+ if (pvecs[1][0])
+ tv = 0;
+ else if (pvecs[1][1])
+ tv = 1;
+ else
+ tv = 2;
+
+ uv = 3 - sv - tv; // the "other one"
+
+ // find the STfromXYZ 4-vectors
+ /*
+ SARRUS-SOLVE:
+ xyzst1[3] == xyzst1[sv] * STfromXYZ[0][sv] + xyzst1[tv] * STfromXYZ[0][tv] + STfromXYZ[0][3];
+ xyzst2[3] == xyzst2[sv] * STfromXYZ[0][sv] + xyzst2[tv] * STfromXYZ[0][tv] + STfromXYZ[0][3];
+ xyzst3[3] == xyzst3[sv] * STfromXYZ[0][sv] + xyzst3[tv] * STfromXYZ[0][tv] + STfromXYZ[0][3];
+ FOR: STfromXYZ[0]
+ GIVEN: one coord of them (uv) is empty (see Face_TextureVectors)
+ SARRUS-SOLVE:
+ xyzst1[4] == xyzst1[sv] * STfromXYZ[1][sv] + xyzst1[tv] * STfromXYZ[1][tv] + STfromXYZ[1][3];
+ xyzst2[4] == xyzst2[sv] * STfromXYZ[1][sv] + xyzst2[tv] * STfromXYZ[1][tv] + STfromXYZ[1][3];
+ xyzst3[4] == xyzst3[sv] * STfromXYZ[1][sv] + xyzst3[tv] * STfromXYZ[1][tv] + STfromXYZ[1][3];
+ FOR: STfromXYZ[1]
+ GIVEN: one coord of them (uv) is empty (see Face_TextureVectors)
+ */
+
+ STfromXYZ[0][uv] = 0;
+ SarrusSolve(
+ xyzst1[sv], xyzst1[tv], 1, xyzst1[3],
+ xyzst2[sv], xyzst2[tv], 1, xyzst2[3],
+ xyzst3[sv], xyzst3[tv], 1, xyzst3[3],
+ &STfromXYZ[0][sv], &STfromXYZ[0][tv], &STfromXYZ[0][3]
+ );
+
+ STfromXYZ[1][uv] = 0;
+ SarrusSolve(
+ xyzst1[sv], xyzst1[tv], 1, xyzst1[4],
+ xyzst2[sv], xyzst2[tv], 1, xyzst2[4],
+ xyzst3[sv], xyzst3[tv], 1, xyzst3[4],
+ &STfromXYZ[1][sv], &STfromXYZ[1][tv], &STfromXYZ[1][3]
+ );
+
+ /*
+ printf("%s\n", q->name);
+
+ printf("%f == %Lf\n", xyzst1[3], DotProduct (xyzst1, STfromXYZ[0]) + STfromXYZ[0][3]);
+ printf("%f == %Lf\n", xyzst2[3], DotProduct (xyzst2, STfromXYZ[0]) + STfromXYZ[0][3]);
+ printf("%f == %Lf\n", xyzst3[3], DotProduct (xyzst3, STfromXYZ[0]) + STfromXYZ[0][3]);
+ printf("%f == %Lf\n", xyzst1[4], DotProduct (xyzst1, STfromXYZ[1]) + STfromXYZ[1][3]);
+ printf("%f == %Lf\n", xyzst2[4], DotProduct (xyzst2, STfromXYZ[1]) + STfromXYZ[1][3]);
+ printf("%f == %Lf\n", xyzst3[4], DotProduct (xyzst3, STfromXYZ[1]) + STfromXYZ[1][3]);
+
+ float newSTfromXYZ[2][4];
+
+ printf("old: %Lf,%Lf,%Lf,%Lf %Lf,%Lf,%Lf,%Lf\n",
+ STfromXYZ[0][0], STfromXYZ[0][1], STfromXYZ[0][2], STfromXYZ[0][3],
+ STfromXYZ[1][0], STfromXYZ[1][1], STfromXYZ[1][2], STfromXYZ[1][3]);
+ */
+
+ Face_TexdefFromTextureVectors (f, STfromXYZ, pvecs, sv, tv);
+
+ /*
+ Face_TextureVectors(f, newSTfromXYZ);
+
+ printf("new: %f,%f,%f,%f %f,%f,%f,%f\n",
+ newSTfromXYZ[0][0], newSTfromXYZ[0][1], newSTfromXYZ[0][2], newSTfromXYZ[0][3],
+ newSTfromXYZ[1][0], newSTfromXYZ[1][1], newSTfromXYZ[1][2], newSTfromXYZ[1][3]);
+
+ float newxyzst1[5];
+ float newxyzst2[5];
+ float newxyzst3[5];
+ VectorCopy(xyzst1, newxyzst1);
+ VectorCopy(xyzst2, newxyzst2);
+ VectorCopy(xyzst3, newxyzst3);
+ EmitTextureCoordinates (newxyzst1, q, f);
+ EmitTextureCoordinates (newxyzst2, q, f);
+ EmitTextureCoordinates (newxyzst3, q, f);
+ printf("Face_TexdefFromTextureCoordinates: %f,%f %f,%f %f,%f -> %f,%f %f,%f %f,%f\n",
+ xyzst1[3], xyzst1[4],
+ xyzst2[3], xyzst2[4],
+ xyzst3[3], xyzst3[4],
+ newxyzst1[3], newxyzst1[4],
+ newxyzst2[3], newxyzst2[4],
+ newxyzst3[3], newxyzst3[4]);
+ // TODO why do these differ, but not the previous ones? this makes no sense whatsoever
+ */
+}
+
+
+