aboutsummaryrefslogtreecommitdiffstats
path: root/src/jake2/util/Math3D.java
diff options
context:
space:
mode:
authorHolger Zickner <[email protected]>2004-07-07 19:59:59 +0000
committerHolger Zickner <[email protected]>2004-07-07 19:59:59 +0000
commit6e23fc1074d1f0c2c2812f4c2e663f5a21a43c20 (patch)
tree46ecc6d0255c874ba4cd26dc3d0733f785019896 /src/jake2/util/Math3D.java
import of Jake2 version sunrisesunrise
Diffstat (limited to 'src/jake2/util/Math3D.java')
-rw-r--r--src/jake2/util/Math3D.java564
1 files changed, 564 insertions, 0 deletions
diff --git a/src/jake2/util/Math3D.java b/src/jake2/util/Math3D.java
new file mode 100644
index 0000000..117487c
--- /dev/null
+++ b/src/jake2/util/Math3D.java
@@ -0,0 +1,564 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+// Created on 09.12.2003 by RST.
+// $Id: Math3D.java,v 1.1 2004-07-07 19:59:53 hzi Exp $
+
+package jake2.util;
+
+import jake2.Defines;
+import jake2.game.cplane_t;
+import jake2.qcommon.Com;
+
+public class Math3D extends Lib {
+
+ public static void set(float v1[], float v2[])
+ {
+ for (int i=0; i < v1.length; i++)
+ v1[i]=v2[i];
+ }
+
+
+ public static void VectorSubtract(float[] a, float[] b, float[] c) {
+ c[0] = a[0] - b[0];
+ c[1] = a[1] - b[1];
+ c[2] = a[2] - b[2];
+ }
+
+ public static void VectorSubtract(short[] a, short[] b, int[] c) {
+ c[0] = a[0] - b[0];
+ c[1] = a[1] - b[1];
+ c[2] = a[2] - b[2];
+ }
+
+ public static void VectorAdd(float[] a, float[] b, float[] to) {
+ to[0] = a[0] + b[0];
+ to[1] = a[1] + b[1];
+ to[2] = a[2] + b[2];
+ }
+
+ public static void VectorCopy(float[] from, float[] to) {
+ to[0] = from[0];
+ to[1] = from[1];
+ to[2] = from[2];
+ }
+
+ public static void VectorCopy(short[] from, short[] to) {
+ to[0] = from[0];
+ to[1] = from[1];
+ to[2] = from[2];
+ }
+
+ public static void VectorCopy(short[] from, float[] to) {
+ to[0] = from[0];
+ to[1] = from[1];
+ to[2] = from[2];
+ }
+
+ public static void VectorCopy(float[] from, short[] to) {
+ to[0] = (short) from[0];
+ to[1] = (short) from[1];
+ to[2] = (short) from[2];
+ }
+
+ public static void VectorClear(float[] a) {
+ a[0] = a[1] = a[2] = 0;
+ }
+ public static int VectorCompare(float[] v1, float[] v2) {
+ if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2])
+ return 0;
+
+ return 1;
+ }
+ public static void VectorNegate(float[] from, float[] to) {
+ to[0] = -from[0];
+ to[1] = -from[1];
+ to[2] = -from[2];
+ }
+ public static void VectorSet(float[] v, float x, float y, float z) {
+ v[0] = (x);
+ v[1] = (y);
+ v[2] = (z);
+ }
+ public static void VectorMA(float[] veca, float scale, float[] vecb, float[] to) {
+ to[0] = veca[0] + scale * vecb[0];
+ to[1] = veca[1] + scale * vecb[1];
+ to[2] = veca[2] + scale * vecb[2];
+ }
+ public static final float VectorNormalize(float[] v) {
+ float length, ilength;
+
+ length = VectorLength(v);
+ if (length != 0.0f) {
+ ilength = 1.0f / length;
+ v[0] *= ilength;
+ v[1] *= ilength;
+ v[2] *= ilength;
+ }
+ return length;
+ }
+ public static final float VectorNormalize2(float[] v, float[] to) {
+ float length, ilength;
+
+ length = VectorLength(v);
+ if (length != 0.0f) {
+ ilength = 1.0f / length;
+ to[0] = v[0] * length;
+ to[1] = v[1] * length;
+ to[2] = v[2] * length;
+ }
+ return length;
+ }
+ public static final float VectorLength(float v[]) {
+ return (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+ }
+ public static void VectorInverse(float[] v) {
+ v[0] = -v[0];
+ v[1] = -v[1];
+ v[2] = -v[2];
+ }
+ public static void VectorScale(float[] in, float scale, float[] out) {
+ out[0] = in[0] * scale;
+ out[1] = in[1] * scale;
+ out[2] = in[2] * scale;
+ }
+
+ public static float vectoyaw(float[] vec) {
+ float yaw;
+
+ if (/*vec[YAW] == 0 &&*/
+ vec[Defines.PITCH] == 0) {
+ yaw = 0;
+ if (vec[Defines.YAW] > 0)
+ yaw = 90;
+ else if (vec[Defines.YAW] < 0)
+ yaw = -90;
+ }
+ else {
+
+ yaw = (int) (Math.atan2(vec[Defines.YAW], vec[Defines.PITCH]) * 180 / Math.PI);
+ if (yaw < 0)
+ yaw += 360;
+ }
+
+ return yaw;
+ }
+
+ public static void vectoangles(float[] value1, float[] angles) {
+ float forward;
+ float yaw, pitch;
+
+ if (value1[1] == 0 && value1[0] == 0) {
+ yaw = 0;
+ if (value1[2] > 0)
+ pitch = 90;
+ else
+ pitch = 270;
+ }
+ else {
+ if (value1[0] != 0)
+ yaw = (int) (Math.atan2(value1[1], value1[0]) * 180 / Math.PI);
+ else if (value1[1] > 0)
+ yaw = 90;
+ else
+ yaw = -90;
+ if (yaw < 0)
+ yaw += 360;
+
+ forward = (float) Math.sqrt(value1[0] * value1[0] + value1[1] * value1[1]);
+ pitch = (int) (Math.atan2(value1[2], forward) * 180 / Math.PI);
+ if (pitch < 0)
+ pitch += 360;
+ }
+
+ angles[Defines.PITCH] = -pitch;
+ angles[Defines.YAW] = yaw;
+ angles[Defines.ROLL] = 0;
+ }
+
+ public static void RotatePointAroundVector(float[] dst, float[] dir, float[] point, float degrees) {
+ float m[][] = new float[3][3];
+ float im[][] = new float[3][3];
+ float zrot[][] = new float[3][3];
+ float tmpmat[][] = new float[3][3];
+ float rot[][] = new float[3][3];
+ int i;
+ float[] vr = { 0.0f, 0.0f, 0.0f };
+ float[] vup = { 0.0f, 0.0f, 0.0f };
+ float[] vf = { 0.0f, 0.0f, 0.0f };
+
+ vf[0] = dir[0];
+ vf[1] = dir[1];
+ vf[2] = dir[2];
+
+ Math3D.PerpendicularVector(vr, dir);
+ Math3D.CrossProduct(vr, vf, vup);
+
+ m[0][0] = vr[0];
+ m[1][0] = vr[1];
+ m[2][0] = vr[2];
+
+ m[0][1] = vup[0];
+ m[1][1] = vup[1];
+ m[2][1] = vup[2];
+
+ m[0][2] = vf[0];
+ m[1][2] = vf[1];
+ m[2][2] = vf[2];
+
+ Math3D.MatCopy(m, im); // achtung: src -> dst
+
+ im[0][1] = m[1][0];
+ im[0][2] = m[2][0];
+ im[1][0] = m[0][1];
+ im[1][2] = m[2][1];
+ im[2][0] = m[0][2];
+ im[2][1] = m[1][2];
+
+ Math3D.MatClear(zrot);
+
+ zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
+
+ zrot[0][0] = (float) Math.cos(Math3D.DEG2RAD(degrees));
+ zrot[0][1] = (float) Math.sin(Math3D.DEG2RAD(degrees));
+ zrot[1][0] = - (float) Math.sin(Math3D.DEG2RAD(degrees));
+ zrot[1][1] = (float) Math.cos(Math3D.DEG2RAD(degrees));
+
+ Math3D.R_ConcatRotations(m, zrot, tmpmat);
+ Math3D.R_ConcatRotations(tmpmat, im, rot);
+
+ for (i = 0; i < 3; i++) {
+ dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
+ }
+ }
+
+
+ public static void MakeNormalVectors(float[] forward, float[] right, float[] up) {
+ // this rotate and negat guarantees a vector
+ // not colinear with the original
+ right[1] = -forward[0];
+ right[2] = forward[1];
+ right[0] = forward[2];
+
+ float d = DotProduct(right, forward);
+ VectorMA(right, -d, forward, right);
+ VectorNormalize(right);
+ CrossProduct(right, forward, up);
+ }
+
+
+ public static float SHORT2ANGLE(int x) {
+ return ((x) * (360.0f / 65536));
+ }
+
+ /*
+ ================
+ R_ConcatTransforms
+ ================
+ */
+ public static void R_ConcatTransforms(float in1[][], float in2[][], float out[][]) {
+ out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
+ out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
+ out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
+ out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3];
+ out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
+ out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
+ out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
+ out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3];
+ out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
+ out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
+ out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
+ out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
+ }
+
+ /**
+ * concatenates 2 matrices each [3][3].
+ */
+ public static void R_ConcatRotations(float in1[][], float in2[][], float out[][]) {
+ out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
+ out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
+ out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
+ out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
+ out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
+ out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
+ out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
+ out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
+ out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
+ }
+
+ public static void ProjectPointOnPlane(float[] dst, float[] p, float[] normal) {
+ float d;
+ float[] n = { 0.0f, 0.0f, 0.0f };
+ float inv_denom;
+
+ inv_denom = 1.0F / Math3D.DotProduct(normal, normal);
+
+ d = Math3D.DotProduct(normal, p) * inv_denom;
+
+ n[0] = normal[0] * inv_denom;
+ n[1] = normal[1] * inv_denom;
+ n[2] = normal[2] * inv_denom;
+
+ dst[0] = p[0] - d * n[0];
+ dst[1] = p[1] - d * n[1];
+ dst[2] = p[2] - d * n[2];
+ }
+
+ /** assumes "src" is normalized */
+ public static void PerpendicularVector(float[] dst, float[] src) {
+ int pos;
+ int i;
+ float minelem = 1.0F;
+ float tempvec[] = { 0.0f, 0.0f, 0.0f };
+
+ // find the smallest magnitude axially aligned vector
+ for (pos = 0, i = 0; i < 3; i++) {
+ if (Math.abs(src[i]) < minelem) {
+ pos = i;
+ minelem = Math.abs(src[i]);
+ }
+ }
+ tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
+ tempvec[pos] = 1.0F;
+
+ // project the point onto the plane defined by src
+ ProjectPointOnPlane(dst, tempvec, src);
+
+ //normalize the result
+ Math3D.VectorNormalize(dst);
+ }
+
+ //=====================================================================
+ /**
+ stellt fest, auf welcher Seite sich die Kiste befindet, wenn die Ebene
+ durch Entfernung und Senkrechten-Normale gegeben ist.
+ erste Version mit vec3_t... */
+
+ public static final int BoxOnPlaneSide(float emins[], float emaxs[], cplane_t p) {
+
+ assert (emins.length == 3 && emaxs.length == 3) : "vec3_t bug";
+
+ float dist1, dist2;
+ int sides;
+
+ // fast axial cases
+ if (p.type < 3) {
+ if (p.dist <= emins[p.type])
+ return 1;
+ if (p.dist >= emaxs[p.type])
+ return 2;
+ return 3;
+ }
+
+ // general case
+ switch (p.signbits) {
+ case 0 :
+ dist1 = p.normal[0] * emaxs[0] + p.normal[1] * emaxs[1] + p.normal[2] * emaxs[2];
+ dist2 = p.normal[0] * emins[0] + p.normal[1] * emins[1] + p.normal[2] * emins[2];
+ break;
+ case 1 :
+ dist1 = p.normal[0] * emins[0] + p.normal[1] * emaxs[1] + p.normal[2] * emaxs[2];
+ dist2 = p.normal[0] * emaxs[0] + p.normal[1] * emins[1] + p.normal[2] * emins[2];
+ break;
+ case 2 :
+ dist1 = p.normal[0] * emaxs[0] + p.normal[1] * emins[1] + p.normal[2] * emaxs[2];
+ dist2 = p.normal[0] * emins[0] + p.normal[1] * emaxs[1] + p.normal[2] * emins[2];
+ break;
+ case 3 :
+ dist1 = p.normal[0] * emins[0] + p.normal[1] * emins[1] + p.normal[2] * emaxs[2];
+ dist2 = p.normal[0] * emaxs[0] + p.normal[1] * emaxs[1] + p.normal[2] * emins[2];
+ break;
+ case 4 :
+ dist1 = p.normal[0] * emaxs[0] + p.normal[1] * emaxs[1] + p.normal[2] * emins[2];
+ dist2 = p.normal[0] * emins[0] + p.normal[1] * emins[1] + p.normal[2] * emaxs[2];
+ break;
+ case 5 :
+ dist1 = p.normal[0] * emins[0] + p.normal[1] * emaxs[1] + p.normal[2] * emins[2];
+ dist2 = p.normal[0] * emaxs[0] + p.normal[1] * emins[1] + p.normal[2] * emaxs[2];
+ break;
+ case 6 :
+ dist1 = p.normal[0] * emaxs[0] + p.normal[1] * emins[1] + p.normal[2] * emins[2];
+ dist2 = p.normal[0] * emins[0] + p.normal[1] * emaxs[1] + p.normal[2] * emaxs[2];
+ break;
+ case 7 :
+ dist1 = p.normal[0] * emins[0] + p.normal[1] * emins[1] + p.normal[2] * emins[2];
+ dist2 = p.normal[0] * emaxs[0] + p.normal[1] * emaxs[1] + p.normal[2] * emaxs[2];
+ break;
+ default :
+ dist1 = dist2 = 0;
+ assert (false) : "BoxOnPlaneSide bug";
+ break;
+ }
+
+ sides = 0;
+ if (dist1 >= p.dist)
+ sides = 1;
+ if (dist2 < p.dist)
+ sides |= 2;
+
+ assert (sides != 0) : "BoxOnPlaneSide(): sides == 0 bug";
+
+ return sides;
+ }
+
+ // this is the slow, general version
+ public static final int BoxOnPlaneSide2(float[] emins, float[] emaxs, cplane_t p) {
+ int i;
+ float dist1, dist2;
+ int sides;
+ float corners[][] = new float[2][3];
+
+ for (i = 0; i < 3; i++) {
+ if (p.normal[i] < 0) {
+ corners[0][i] = emins[i];
+ corners[1][i] = emaxs[i];
+ }
+ else {
+ corners[1][i] = emins[i];
+ corners[0][i] = emaxs[i];
+ }
+ }
+ dist1 = Math3D.DotProduct(p.normal, corners[0]) - p.dist;
+ dist2 = Math3D.DotProduct(p.normal, corners[1]) - p.dist;
+ sides = 0;
+ if (dist1 >= 0)
+ sides = 1;
+ if (dist2 < 0)
+ sides |= 2;
+
+ return sides;
+ }
+
+ public static void AngleVectors(float[] angles, float[] forward, float[] right, float[] up) {
+ float angle;
+ float sr, sp, sy, cr, cp, cy;
+
+ angle = (float) (angles[Defines.YAW] * (Math.PI * 2 / 360));
+ sy = (float) Math.sin(angle);
+ cy = (float) Math.cos(angle);
+ angle = (float) (angles[Defines.PITCH] * (Math.PI * 2 / 360));
+ sp = (float) Math.sin(angle);
+ cp = (float) Math.cos(angle);
+ angle = (float) (angles[Defines.ROLL] * (Math.PI * 2 / 360));
+ sr = (float) Math.sin(angle);
+ cr = (float) Math.cos(angle);
+
+ if (forward != null) {
+ forward[0] = cp * cy;
+ forward[1] = cp * sy;
+ forward[2] = -sp;
+ }
+ if (right != null) {
+ right[0] = (-1 * sr * sp * cy + -1 * cr * -sy);
+ right[1] = (-1 * sr * sp * sy + -1 * cr * cy);
+ right[2] = -1 * sr * cp;
+ }
+ if (up != null) {
+ up[0] = (cr * sp * cy + -sr * -sy);
+ up[1] = (cr * sp * sy + -sr * cy);
+ up[2] = cr * cp;
+ }
+ }
+
+ public static void MatClear(float m[][]) {
+ m[0][0] = m[0][1] = m[0][2] = m[1][0] = m[1][1] = m[1][2] = m[2][0] = m[2][1] = m[2][2] = 0.0f;
+ }
+
+ public static final void MatCopy(float src[][], float dst[][]) {
+ for (int i = 0; i < 3; i++)
+ {
+ VectorCopy(src[i], dst[i]);
+ }
+ }
+
+ public static void G_ProjectSource(float[] point, float[] distance, float[] forward, float[] right, float[] result) {
+ result[0] = point[0] + forward[0] * distance[0] + right[0] * distance[1];
+ result[1] = point[1] + forward[1] * distance[0] + right[1] * distance[1];
+ result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] + distance[2];
+ }
+
+
+
+ public static float DotProduct(float[] x, float[] y) {
+ return x[0] * y[0] + x[1] * y[1] + x[2] * y[2];
+ }
+
+
+
+ public static void CrossProduct(float[] v1, float[] v2, float[] cross) {
+ cross[0] = v1[1] * v2[2] - v1[2] * v2[1];
+ cross[1] = v1[2] * v2[0] - v1[0] * v2[2];
+ cross[2] = v1[0] * v2[1] - v1[1] * v2[0];
+ }
+
+
+
+ public static int Q_log2(int val) {
+ int answer = 0;
+ while ((val >>= 1) > 0)
+ answer++;
+ return answer;
+ }
+
+
+
+ public static float DEG2RAD(float in) {
+ return (in * (float) Math.PI) / 180.0f;
+ }
+
+
+
+ public static float anglemod(float a) {
+ return (float) (360.0f / 65536) * ((int) (a * (65536 / 360.0f)) & 65535);
+ }
+
+
+
+ public static int ANGLE2SHORT(float x) {
+ return ((int) ((x) * 65536f / 360f) & 65535);
+ }
+
+
+
+ public static float LerpAngle(float a2, float a1, float frac) {
+ if (a1 - a2 > 180)
+ a1 -= 360;
+ if (a1 - a2 < -180)
+ a1 += 360;
+ return a2 + frac * (a1 - a2);
+ }
+
+
+ public static float CalcFov(float fov_x, float width, float height) {
+ double a = 0.0f;
+ double x;
+
+ if (fov_x < 1.0f || fov_x > 179.0f)
+ Com.Error(Defines.ERR_DROP, "Bad fov: " + fov_x);
+
+ x = width / Math.tan(fov_x / 360.0 * Math.PI);
+
+ a = Math.atan(height / x);
+
+ a = a * 360 / Math.PI;
+
+ return (float)a;
+ }
+}