aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/jake2/client/CircleListener.java61
-rw-r--r--test/jake2/client/GhostMouse.java56
-rw-r--r--test/jake2/imageio/TestImage.java160
-rw-r--r--test/jake2/qcommon/TestCMD.java56
-rw-r--r--test/jake2/qcommon/TestCOM.java53
-rw-r--r--test/jake2/qcommon/TestCvar.java41
-rw-r--r--test/jake2/qcommon/TestFS.java132
-rw-r--r--test/jake2/qcommon/TestINFO.java41
-rw-r--r--test/jake2/qcommon/TestLoadGame.java42
-rw-r--r--test/jake2/qcommon/TestLoadMap.java42
-rw-r--r--test/jake2/qcommon/TestMD4.java1145
-rw-r--r--test/jake2/qcommon/TestMSG.java66
-rw-r--r--test/jake2/qcommon/TestRotatePointAroundVector.java185
-rw-r--r--test/jake2/render/DancingQueens.java320
-rw-r--r--test/jake2/render/DebugCulling.java363
-rw-r--r--test/jake2/render/TestMap.java623
-rw-r--r--test/jake2/render/TestRenderer.java829
17 files changed, 4215 insertions, 0 deletions
diff --git a/test/jake2/client/CircleListener.java b/test/jake2/client/CircleListener.java
new file mode 100644
index 0000000..35762e8
--- /dev/null
+++ b/test/jake2/client/CircleListener.java
@@ -0,0 +1,61 @@
+/*
+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 07.01.2000 by RST.
+// $Id: CircleListener.java,v 1.1 2004-07-07 19:59:56 hzi Exp $
+
+package jake2.client;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.awt.Robot;
+
+
+
+// import jake2.*;
+// import jake2.client.*;
+// import jake2.game.*;
+// import jake2.qcommon.*;
+// import jake2.render.*;
+// import jake2.server.*;
+
+class CircleListener implements ActionListener {
+ Robot robot;
+ public CircleListener(Robot robot) {
+ this.robot = robot;
+ }
+
+ public void actionPerformed(ActionEvent evt) {
+ int originx = (int)GhostMouse.size.getWidth()/2;
+ int originy = (int)GhostMouse.size.getHeight()/2;
+ double pi = 3.1457;
+
+ for(double theta = 0; theta < 4*pi; theta=theta+0.1) {
+ double radius = theta * 20;
+ double x = Math.cos(theta) * radius + originx;
+ double y = Math.sin(theta) * radius + originy;
+ robot.mouseMove((int)x,(int)y);
+ try{Thread.sleep(25);} catch (Exception ex) { }
+ }
+ }
+
+}
+
diff --git a/test/jake2/client/GhostMouse.java b/test/jake2/client/GhostMouse.java
new file mode 100644
index 0000000..33c6af8
--- /dev/null
+++ b/test/jake2/client/GhostMouse.java
@@ -0,0 +1,56 @@
+/*
+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 07.01.2000 by RST.
+// $Id: GhostMouse.java,v 1.1 2004-07-07 19:59:56 hzi Exp $
+
+package jake2.client;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.awt.Robot;
+
+
+// import jake2.*;
+// import jake2.client.*;
+// import jake2.game.*;
+// import jake2.qcommon.*;
+// import jake2.render.*;
+// import jake2.server.*;
+
+public class GhostMouse {
+ public static Dimension size;
+ public static void main(String[] args) throws Exception {
+ Robot robot = new Robot();
+ size = Toolkit.getDefaultToolkit().getScreenSize();
+
+ JFrame frame = new JFrame("Ghost Mouse (tm)!");
+ JButton button = new JButton("Gho Ghost");
+ frame.getContentPane().add(button);
+ button.addActionListener(new CircleListener(robot));
+
+ frame.pack();
+ frame.setLocation(
+ (int)(size.getWidth()-frame.getWidth())/2,
+ (int)(size.getHeight()-frame.getHeight())/2);
+ frame.show();
+ }
+}
diff --git a/test/jake2/imageio/TestImage.java b/test/jake2/imageio/TestImage.java
new file mode 100644
index 0000000..4290359
--- /dev/null
+++ b/test/jake2/imageio/TestImage.java
@@ -0,0 +1,160 @@
+/*
+ * Created on Nov 17, 2003
+ *
+ */
+package jake2.imageio;
+
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.imageio.*;
+
+/**
+ * @author cwei
+ *
+ */
+public class TestImage {
+
+ static final String TEST_FILE = "pics/colormap.pcx";
+ static final long PAUSE = 15; // ms
+ static final int ENTRIES = 2501;
+
+ File pakPath;
+ List imageFiles;
+
+ TestImage(File pakPath) {
+ this.pakPath = pakPath;
+ this.imageFiles = new ArrayList(ENTRIES);
+ }
+
+ public static void main(String[] args) throws Exception {
+
+
+ if (args == null || args.length == 0) {
+ usage();
+ }
+
+ File path = new File(args[0]);
+
+ if (!path.isDirectory()) {
+ System.err.println(path.toString() + " is not a directory");
+ usage();
+ }
+
+ if (!new File(path.getPath() + "/" + TEST_FILE).canRead()) {
+ System.err.println(
+ path.getPath() + " is not a unpacked quake2-pak file location");
+ usage();
+ }
+
+ System.out.println("*** Start Image test ***\n");
+
+ ImageIO.scanForPlugins();
+
+ TestImage test = new TestImage(path);
+ test.run();
+
+ System.gc();
+ Runtime rt = Runtime.getRuntime();
+ System.out.println(
+ "JVM total memory: " + rt.totalMemory() / 1024 + " Kbytes\n");
+
+ System.out.println("*** Image test is succeeded :-) ***\n");
+ }
+
+ static void usage() {
+ System.out.println(
+ "usage: TestImage <path to unpacked quake2-pak file>");
+ System.exit(0);
+ }
+
+ void run() {
+
+ System.out.println("begin directory scanning ...");
+ scanDirectory(pakPath);
+ System.out.println(imageFiles.size() + " graphic files found\n");
+
+ ImageFrame frame = new ImageFrame(null);
+ frame.setVisible(true);
+
+ File f = null;
+ BufferedImage image = null;
+
+ for (Iterator it = imageFiles.iterator(); it.hasNext();) {
+ f = (File) it.next();
+ try {
+ image = scale(ImageIO.read(f));
+ frame.showImage(image);
+ frame.setTitle(f.getPath());
+
+ Thread.sleep(PAUSE);
+
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
+ } catch (InterruptedException e) {
+ }
+ }
+ frame.dispose();
+ imageFiles.clear();
+ }
+
+ void scanDirectory(File dir) {
+ File[] files = dir.listFiles(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ /* matches *.pcx or *.wal files */
+ return name.matches(".*(pcx|wal)$");
+ }
+ });
+
+ if (files != null && files.length > 0) {
+ imageFiles.addAll(Arrays.asList(files));
+ }
+
+ File[] dirs = dir.listFiles(new FileFilter() {
+ public boolean accept(File pathname) {
+ return pathname.isDirectory();
+ }
+ });
+
+ if (dirs != null && dirs.length > 0) {
+ for (int i = 0; i < dirs.length; i++) {
+ System.out.println(dirs[i]);
+ // recursive directory scanning
+ scanDirectory(dirs[i]);
+ }
+ }
+ }
+
+ BufferedImage scale(BufferedImage src) {
+ BufferedImage dst = null;
+
+ int size = Math.max(src.getHeight(), src.getWidth());
+
+ double scale = 1.5;
+
+ if (size < 50) {
+ scale = 4.0;
+ } else if (size < 200) {
+ scale = 2.5;
+ } else if (size > 400) {
+ scale = 1.5;
+ }
+ BufferedImageOp op =
+ new AffineTransformOp(
+ AffineTransform.getScaleInstance(scale, scale),
+ AffineTransformOp.TYPE_NEAREST_NEIGHBOR/*TYPE_BILINEAR*/);
+ dst = op.filter(src, null);
+
+ return (dst != null) ? dst : src;
+ }
+}
diff --git a/test/jake2/qcommon/TestCMD.java b/test/jake2/qcommon/TestCMD.java
new file mode 100644
index 0000000..140f075
--- /dev/null
+++ b/test/jake2/qcommon/TestCMD.java
@@ -0,0 +1,56 @@
+/*
+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 29.12.2003 by RST.
+// $Id: TestCMD.java,v 1.1 2004-07-07 19:59:56 hzi Exp $
+
+package jake2.qcommon;
+
+import java.io.*;
+
+import jake2.*;
+import jake2.client.*;
+import jake2.game.*;
+import jake2.qcommon.*;
+import jake2.render.*;
+import jake2.server.*;
+
+public class TestCMD {
+
+ public static void main(String args[]) {
+ try {
+ Cmd.Init();
+ Cmd.RemoveCommand("exec");
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+ System.out.println("Give some commands:");
+
+ while (true) {
+ System.out.println("#");
+ String line = br.readLine();
+ Cmd.ExecuteString(line);
+ }
+ }
+ catch (Exception e) {
+ // TODO: handle exception
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/test/jake2/qcommon/TestCOM.java b/test/jake2/qcommon/TestCOM.java
new file mode 100644
index 0000000..6432fbe
--- /dev/null
+++ b/test/jake2/qcommon/TestCOM.java
@@ -0,0 +1,53 @@
+/*
+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 29.12.2003 by RST.
+// $Id: TestCOM.java,v 1.1 2004-07-07 19:59:56 hzi Exp $
+
+package jake2.qcommon;
+
+import jake2.*;
+import jake2.client.*;
+import jake2.game.*;
+import jake2.qcommon.*;
+import jake2.render.*;
+import jake2.server.*;
+
+public class TestCOM {
+
+ public static void main(String args[]) {
+ String test = "testrene = \"ein mal eins\"; a=3 ";
+ Com.ParseHelp ph = new Com.ParseHelp(test);
+
+ while (!ph.isEof())
+ System.out.println("[" + Com.Parse(ph) + "]");
+
+ System.out.println("OK!");
+
+ test = " testrene = \"ein mal eins\"; a=3";
+
+ ph = new Com.ParseHelp(test);
+
+ while (!ph.isEof())
+ System.out.println("[" + Com.Parse(ph) + "]");
+
+ System.out.println("OK!");
+ }
+}
diff --git a/test/jake2/qcommon/TestCvar.java b/test/jake2/qcommon/TestCvar.java
new file mode 100644
index 0000000..49826e8
--- /dev/null
+++ b/test/jake2/qcommon/TestCvar.java
@@ -0,0 +1,41 @@
+/*
+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 29.12.2003 by RST.
+// $Id: TestCvar.java,v 1.1 2004-07-07 19:59:56 hzi Exp $
+
+package jake2.qcommon;
+
+
+// import jake2.*;
+// import jake2.client.*;
+// import jake2.game.*;
+// import jake2.qcommon.*;
+// import jake2.render.*;
+// import jake2.server.*;
+
+public class TestCvar {
+
+ public static void main(String[] args) {
+ Cvar.Set("rene", "is cool.");
+
+ Com.Printf("rene:" + Cvar.FindVar("rene").string);
+ }
+}
diff --git a/test/jake2/qcommon/TestFS.java b/test/jake2/qcommon/TestFS.java
new file mode 100644
index 0000000..f46f43f
--- /dev/null
+++ b/test/jake2/qcommon/TestFS.java
@@ -0,0 +1,132 @@
+/*
+ * TestFS.java
+ * Copyright (C) 2003
+ *
+ * $Id: TestFS.java,v 1.1 2004-07-07 19:59:56 hzi Exp $
+ */
+/*
+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.
+
+*/
+package jake2.qcommon;
+
+import jake2.game.Cmd;
+import jake2.imageio.ImageFrame;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.TreeSet;
+import java.util.logging.*;
+
+import javax.imageio.ImageIO;
+import javax.imageio.stream.MemoryCacheImageInputStream;
+
+/**
+ * TestFS
+ *
+ * @author cwei
+ */
+public class TestFS {
+
+ public static void main(String[] args) {
+ System.out.println("*** Start FS test ***\n");
+
+ init();
+
+ FS.InitFilesystem();
+
+ Cmd.ExecuteString("link unknown.pcx ../../baseq2/space.pcx");
+ Cmd.ExecuteString("link unknown1.pcx ../../baseq2/config.cfg");
+
+ FS.Path_f();
+
+ // loescht den link
+ Cmd.ExecuteString("link unknown1.pcx");
+
+ FS.Path_f();
+
+ Cmd.ExecuteString("dir players/male/*.[a-zA-Z_0-9]?x");
+
+ // search for pack_t
+ FS.searchpath_t search;
+ Collection filenames = new TreeSet();
+ for (search = FS.fs_searchpaths; search != null; search = search.next) {
+ // is the element a pak file?
+ if (search.pack != null) {
+ // add all the pak file names
+ filenames.addAll(search.pack.files.keySet());
+ }
+ }
+
+ ImageFrame frame = new ImageFrame(null);
+ frame.setVisible(true);
+ byte[] buffer = null;
+
+ BufferedImage image = null;
+ for (Iterator it = filenames.iterator(); it.hasNext();) {
+
+ String filename = it.next().toString();
+ if (!filename.endsWith(".wal") && !filename.endsWith(".pcx")) continue;
+
+ buffer = FS.LoadFile(filename);
+
+ if (buffer != null) {
+ try {
+ image =
+ ImageIO.read(
+ new MemoryCacheImageInputStream(
+ new ByteArrayInputStream(buffer)));
+
+ frame.showImage(image);
+ frame.setTitle(filename);
+
+ Thread.sleep(15);
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e1) {
+ }
+ }
+ }
+ frame.dispose();
+
+ System.gc();
+ Runtime rt = Runtime.getRuntime();
+ System.out.println(
+ "\nJVM total memory: " + rt.totalMemory() / 1024 + " Kbytes");
+
+ System.out.println("\n*** FS test is succeeded :-) ***");
+ }
+
+ static void init() {
+ // init the global LogManager with the logging.properties file
+ try {
+ LogManager.getLogManager().readConfiguration(
+ TestFS.class.getResourceAsStream("/jake2/logging.properties"));
+ } catch (SecurityException secEx) {
+ secEx.printStackTrace();
+ } catch (IOException ioEx) {
+ System.err.println(
+ "FATAL Error: can't load /jake2/logging.properties (classpath)");
+ ioEx.printStackTrace();
+ }
+ }
+}
diff --git a/test/jake2/qcommon/TestINFO.java b/test/jake2/qcommon/TestINFO.java
new file mode 100644
index 0000000..fea3328
--- /dev/null
+++ b/test/jake2/qcommon/TestINFO.java
@@ -0,0 +1,41 @@
+/*
+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 29.12.2003 by RST.
+// $Id: TestINFO.java,v 1.1 2004-07-07 19:59:56 hzi Exp $
+
+package jake2.qcommon;
+
+import jake2.*;
+import jake2.client.*;
+import jake2.game.*;
+import jake2.qcommon.*;
+import jake2.render.*;
+import jake2.server.*;
+
+public class TestINFO {
+
+ public static void main(String args[]) {
+ String test = "\\key1\\value 1\\key 2 \\value2\\key3\\ v a l u e 3\\key4\\val ue 4";
+ Info.Print(test);
+ test = Info.Info_RemoveKey1(test, "key1");
+ Info.Print(test);
+ }
+}
diff --git a/test/jake2/qcommon/TestLoadGame.java b/test/jake2/qcommon/TestLoadGame.java
new file mode 100644
index 0000000..c6eb813
--- /dev/null
+++ b/test/jake2/qcommon/TestLoadGame.java
@@ -0,0 +1,42 @@
+/*
+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 02.01.2004 by RST.
+// $Id: TestLoadGame.java,v 1.1 2004-07-07 19:59:56 hzi Exp $
+
+package jake2.qcommon;
+
+import jake2.*;
+import jake2.client.*;
+import jake2.game.*;
+import jake2.qcommon.*;
+import jake2.render.*;
+import jake2.server.*;
+
+public class TestLoadGame {
+ public static void main(String args[]) {
+
+ Qcommon.Init(args);
+
+ System.out.println("hello!");
+ GameSave.InitGame();
+ GameSave.ReadGame("test/data/savegames/game.ssv");
+ }
+}
diff --git a/test/jake2/qcommon/TestLoadMap.java b/test/jake2/qcommon/TestLoadMap.java
new file mode 100644
index 0000000..3410ca2
--- /dev/null
+++ b/test/jake2/qcommon/TestLoadMap.java
@@ -0,0 +1,42 @@
+/*
+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 02.01.2004 by RST.
+// $Id: TestLoadMap.java,v 1.1 2004-07-07 19:59:56 hzi Exp $
+
+package jake2.qcommon;
+
+
+// import jake2.*;
+// import jake2.client.*;
+// import jake2.game.*;
+// import jake2.qcommon.*;
+// import jake2.render.*;
+// import jake2.server.*;
+
+public class TestLoadMap {
+ public static void main(String[] args) {
+ Com.DPrintf("hello!\n");
+
+ FS.InitFilesystem();
+
+ CM.CM_LoadMap("maps/base1.bsp", true, new CM.intwrap(0));
+ }
+}
diff --git a/test/jake2/qcommon/TestMD4.java b/test/jake2/qcommon/TestMD4.java
new file mode 100644
index 0000000..9b86058
--- /dev/null
+++ b/test/jake2/qcommon/TestMD4.java
@@ -0,0 +1,1145 @@
+/*
+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 02.02.2004 by RST.
+// $Id: TestMD4.java,v 1.1 2004-07-07 19:59:57 hzi Exp $
+
+package jake2.qcommon;
+
+import jake2.*;
+import jake2.client.*;
+import jake2.game.*;
+import jake2.render.*;
+import jake2.server.*;
+import jake2.util.Lib;
+
+//
+//
+//
+//
+//Network Working Group R. Rivest
+//Request for Comments: 1320 MIT Laboratory for Computer Science
+//Obsoletes: RFC 1186 and RSA Data Security, Inc.
+// April 1992
+//
+//
+// The MD4 Message-Digest Algorithm
+//
+//Status of thie Memo
+//
+// This memo provides information for the Internet community. It does
+// not specify an Internet standard. Distribution of this memo is
+// unlimited.
+//
+//Acknowlegements
+//
+// We would like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle,
+// and Noam Nisan for numerous helpful comments and suggestions.
+//
+//Table of Contents
+//
+// 1. Executive Summary 1
+// 2. Terminology and Notation 2
+// 3. MD4 Algorithm Description 2
+// 4. Summary 6
+// References 6
+// APPENDIX A - Reference Implementation 6
+// Security Considerations 20
+// Author's Address 20
+//
+//1. Executive Summary
+//
+// This document describes the MD4 message-digest algorithm [1]. The
+// algorithm takes as input a message of arbitrary length and produces
+// as output a 128-bit "fingerprint" or "message digest" of the input.
+// It is conjectured that it is computationally infeasible to produce
+// two messages having the same message digest, or to produce any
+// message having a given prespecified target message digest. The MD4
+// algorithm is intended for digital signature applications, where a
+// large file must be "compressed" in a secure manner before being
+// encrypted with a private (secret) key under a public-key cryptosystem
+// such as RSA.
+//
+// The MD4 algorithm is designed to be quite fast on 32-bit machines. In
+// addition, the MD4 algorithm does not require any large substitution
+// tables; the algorithm can be coded quite compactly.
+//
+//
+//
+//
+//
+//Rivest [Page 1]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+// The MD4 algorithm is being placed in the public domain for review and
+// possible adoption as a standard.
+//
+// This document replaces the October 1990 RFC 1186 [2]. The main
+// difference is that the reference implementation of MD4 in the
+// appendix is more portable.
+//
+// For OSI-based applications, MD4's object identifier is
+//
+// md4 OBJECT IDENTIFIER ::=
+// {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 4}
+//
+// In the X.509 type AlgorithmIdentifier [3], the parameters for MD4
+// should have type NULL.
+//
+//2. Terminology and Notation
+//
+// In this document a "word" is a 32-bit quantity and a "byte" is an
+// eight-bit quantity. A sequence of bits can be interpreted in a
+// natural manner as a sequence of bytes, where each consecutive group
+// of eight bits is interpreted as a byte with the high-order (most
+// significant) bit of each byte listed first. Similarly, a sequence of
+// bytes can be interpreted as a sequence of 32-bit words, where each
+// consecutive group of four bytes is interpreted as a word with the
+// low-order (least significant) byte given first.
+//
+// Let x_i denote "x sub i". If the subscript is an expression, we
+// surround it in braces, as in x_{i+1}. Similarly, we use ^ for
+// superscripts (exponentiation), so that x^i denotes x to the i-th
+// power.
+//
+// Let the symbol "+" denote addition of words (i.e., modulo-2^32
+// addition). Let X <<< s denote the 32-bit value obtained by circularly
+// shifting (rotating) X left by s bit positions. Let not(X) denote the
+// bit-wise complement of X, and let X v Y denote the bit-wise OR of X
+// and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY
+// denote the bit-wise AND of X and Y.
+//
+//3. MD4 Algorithm Description
+//
+// We begin by supposing that we have a b-bit message as input, and that
+// we wish to find its message digest. Here b is an arbitrary
+// nonnegative integer; b may be zero, it need not be a multiple of
+// eight, and it may be arbitrarily large. We imagine the bits of the
+// message written down as follows:
+//
+// m_0 m_1 ... m_{b-1}
+//
+//
+//
+//
+//Rivest [Page 2]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+// The following five steps are performed to compute the message digest
+// of the message.
+//
+//3.1 Step 1. Append Padding Bits
+//
+// The message is "padded" (extended) so that its length (in bits) is
+// congruent to 448, modulo 512. That is, the message is extended so
+// that it is just 64 bits shy of being a multiple of 512 bits long.
+// Padding is always performed, even if the length of the message is
+// already congruent to 448, modulo 512.
+//
+// Padding is performed as follows: a single "1" bit is appended to the
+// message, and then "0" bits are appended so that the length in bits of
+// the padded message becomes congruent to 448, modulo 512. In all, at
+// least one bit and at most 512 bits are appended.
+//
+//3.2 Step 2. Append Length
+//
+// A 64-bit representation of b (the length of the message before the
+// padding bits were added) is appended to the result of the previous
+// step. In the unlikely event that b is greater than 2^64, then only
+// the low-order 64 bits of b are used. (These bits are appended as two
+// 32-bit words and appended low-order word first in accordance with the
+// previous conventions.)
+//
+// At this point the resulting message (after padding with bits and with
+// b) has a length that is an exact multiple of 512 bits. Equivalently,
+// this message has a length that is an exact multiple of 16 (32-bit)
+// words. Let M[0 ... N-1] denote the words of the resulting message,
+// where N is a multiple of 16.
+//
+//3.3 Step 3. Initialize MD Buffer
+//
+// A four-word buffer (A,B,C,D) is used to compute the message digest.
+// Here each of A, B, C, D is a 32-bit register. These registers are
+// initialized to the following values in hexadecimal, low-order bytes
+// first):
+//
+// word A: 01 23 45 67
+// word B: 89 ab cd ef
+// word C: fe dc ba 98
+// word D: 76 54 32 10
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//Rivest [Page 3]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+//3.4 Step 4. Process Message in 16-Word Blocks
+//
+// We first define three auxiliary functions that each take as input
+// three 32-bit words and produce as output one 32-bit word.
+//
+// F(X,Y,Z) = XY v not(X) Z
+// G(X,Y,Z) = XY v XZ v YZ
+// H(X,Y,Z) = X xor Y xor Z
+//
+// In each bit position F acts as a conditional: if X then Y else Z.
+// The function F could have been defined using + instead of v since XY
+// and not(X)Z will never have "1" bits in the same bit position.) In
+// each bit position G acts as a majority function: if at least two of
+// X, Y, Z are on, then G has a "1" bit in that bit position, else G has
+// a "0" bit. It is interesting to note that if the bits of X, Y, and Z
+// are independent and unbiased, the each bit of f(X,Y,Z) will be
+// independent and unbiased, and similarly each bit of g(X,Y,Z) will be
+// independent and unbiased. The function H is the bit-wise XOR or
+// parity" function; it has properties similar to those of F and G.
+//
+// Do the following:
+//
+// Process each 16-word block. */
+// For i = 0 to N/16-1 do
+//
+// /* Copy block i into X. */
+// For j = 0 to 15 do
+// Set X[j] to M[i*16+j].
+// end /* of loop on j */
+//
+// /* Save A as AA, B as BB, C as CC, and D as DD. */
+// AA = A
+// BB = B
+// CC = C
+// DD = D
+//
+// /* Round 1. */
+// /* Let [abcd k s] denote the operation
+// a = (a + F(b,c,d) + X[k]) <<< s. */
+// /* Do the following 16 operations. */
+// [ABCD 0 3] [DABC 1 7] [CDAB 2 11] [BCDA 3 19]
+// [ABCD 4 3] [DABC 5 7] [CDAB 6 11] [BCDA 7 19]
+// [ABCD 8 3] [DABC 9 7] [CDAB 10 11] [BCDA 11 19]
+// [ABCD 12 3] [DABC 13 7] [CDAB 14 11] [BCDA 15 19]
+//
+// /* Round 2. */
+// /* Let [abcd k s] denote the operation
+// a = (a + G(b,c,d) + X[k] + 5A827999) <<< s. */
+//
+//
+//
+//Rivest [Page 4]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+// /* Do the following 16 operations. */
+// [ABCD 0 3] [DABC 4 5] [CDAB 8 9] [BCDA 12 13]
+// [ABCD 1 3] [DABC 5 5] [CDAB 9 9] [BCDA 13 13]
+// [ABCD 2 3] [DABC 6 5] [CDAB 10 9] [BCDA 14 13]
+// [ABCD 3 3] [DABC 7 5] [CDAB 11 9] [BCDA 15 13]
+//
+// /* Round 3. */
+// /* Let [abcd k s] denote the operation
+// a = (a + H(b,c,d) + X[k] + 6ED9EBA1) <<< s. */
+// /* Do the following 16 operations. */
+// [ABCD 0 3] [DABC 8 9] [CDAB 4 11] [BCDA 12 15]
+// [ABCD 2 3] [DABC 10 9] [CDAB 6 11] [BCDA 14 15]
+// [ABCD 1 3] [DABC 9 9] [CDAB 5 11] [BCDA 13 15]
+// [ABCD 3 3] [DABC 11 9] [CDAB 7 11] [BCDA 15 15]
+//
+// /* Then perform the following additions. (That is, increment each
+// of the four registers by the value it had before this block
+// was started.) */
+// A = A + AA
+// B = B + BB
+// C = C + CC
+// D = D + DD
+//
+// end /* of loop on i */
+//
+// Note. The value 5A..99 is a hexadecimal 32-bit constant, written with
+// the high-order digit first. This constant represents the square root
+// of 2. The octal value of this constant is 013240474631.
+//
+// The value 6E..A1 is a hexadecimal 32-bit constant, written with the
+// high-order digit first. This constant represents the square root of
+// 3. The octal value of this constant is 015666365641.
+//
+// See Knuth, The Art of Programming, Volume 2 (Seminumerical
+// Algorithms), Second Edition (1981), Addison-Wesley. Table 2, page
+// 660.
+//
+//3.5 Step 5. Output
+//
+// The message digest produced as output is A, B, C, D. That is, we
+// begin with the low-order byte of A, and end with the high-order byte
+// of D.
+//
+// This completes the description of MD4. A reference implementation in
+// C is given in the appendix.
+//
+//
+//
+//
+//
+//
+//Rivest [Page 5]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+//4. Summary
+//
+// The MD4 message-digest algorithm is simple to implement, and provides
+// a "fingerprint" or message digest of a message of arbitrary length.
+// It is conjectured that the difficulty of coming up with two messages
+// having the same message digest is on the order of 2^64 operations,
+// and that the difficulty of coming up with any message having a given
+// message digest is on the order of 2^128 operations. The MD4 algorithm
+// has been carefully scrutinized for weaknesses. It is, however, a
+// relatively new algorithm and further security analysis is of course
+// justified, as is the case with any new proposal of this sort.
+//
+//References
+//
+// [1] Rivest, R., "The MD4 message digest algorithm", in A.J. Menezes
+// and S.A. Vanstone, editors, Advances in Cryptology - CRYPTO '90
+// Proceedings, pages 303-311, Springer-Verlag, 1991.
+//
+// [2] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1186, MIT,
+// October 1990.
+//
+// [3] CCITT Recommendation X.509 (1988), "The Directory -
+// Authentication Framework".
+//
+// [4] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, MIT and
+// RSA Data Security, Inc, April 1992.
+//
+//APPENDIX A - Reference Implementation
+//
+// This appendix contains the following files:
+//
+// global.h -- global header file
+//
+// md4.h -- header file for MD4
+//
+// md4c.c -- source code for MD4
+//
+// mddriver.c -- test driver for MD2, MD4 and MD5
+//
+// The driver compiles for MD5 by default but can compile for MD2 or MD4
+// if the symbol MD is defined on the C compiler command line as 2 or 4.
+//
+// The implementation is portable and should work on many different
+// plaforms. However, it is not difficult to optimize the implementation
+// on particular platforms, an exercise left to the reader. For example,
+// on "little-endian" platforms where the lowest-addressed byte in a 32-
+// bit word is the least significant and there are no alignment
+// restrictions, the call to Decode in MD4Transform can be replaced with
+//
+//
+//
+//Rivest [Page 6]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+// a typecast.
+//
+//A.1 global.h
+//
+///* GLOBAL.H - RSAREF types and constants
+// */
+//
+///* PROTOTYPES should be set to one if and only if the compiler supports
+// function argument prototyping.
+// The following makes PROTOTYPES default to 0 if it has not already
+// been defined with C compiler flags.
+// */
+//#ifndef PROTOTYPES
+//#define PROTOTYPES 0
+//#endif
+//
+///* POINTER defines a generic pointer type */
+//typedef unsigned char *POINTER;
+//
+///* UINT2 defines a two byte word */
+//typedef unsigned short int UINT2;
+//
+///* UINT4 defines a four byte word */
+//typedef unsigned long int UINT4;
+//
+///* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
+// If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
+// returns an empty list.
+// */
+//
+//#if PROTOTYPES
+//#define PROTO_LIST(list) list
+//#else
+//#define PROTO_LIST(list) ()
+//#endif
+//
+//A.2 md4.h
+//
+///* MD4.H - header file for MD4C.C
+// */
+//
+///* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+// rights reserved.
+//
+// License to copy and use this software is granted provided that it
+// is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+// Algorithm" in all material mentioning or referencing this software
+// or this function.
+//
+//
+//
+//Rivest [Page 7]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+// License is also granted to make and use derivative works provided
+// that such works are identified as "derived from the RSA Data
+// Security, Inc. MD4 Message-Digest Algorithm" in all material
+// mentioning or referencing the derived work.
+//
+// RSA Data Security, Inc. makes no representations concerning either
+// the merchantability of this software or the suitability of this
+// software for any particular purpose. It is provided "as is"
+// without express or implied warranty of any kind.
+//
+// These notices must be retained in any copies of any part of this
+// documentation and/or software.
+// */
+//
+///* MD4 context. */
+//typedef struct {
+// UINT4 state[4]; /* state (ABCD) */
+// UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+// unsigned char buffer[64]; /* input buffer */
+//} MD4_CTX;
+//
+//void MD4Init PROTO_LIST ((MD4_CTX *));
+//void MD4Update PROTO_LIST
+// ((MD4_CTX *, unsigned char *, unsigned int));
+//void MD4Final PROTO_LIST ((unsigned char [16], MD4_CTX *));
+//
+//A.3 md4c.c
+//
+///* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm
+// */
+//
+///* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
+//
+// License to copy and use this software is granted provided that it
+// is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+// Algorithm" in all material mentioning or referencing this software
+// or this function.
+//
+// License is also granted to make and use derivative works provided
+// that such works are identified as "derived from the RSA Data
+// Security, Inc. MD4 Message-Digest Algorithm" in all material
+// mentioning or referencing the derived work.
+//
+// RSA Data Security, Inc. makes no representations concerning either
+// the merchantability of this software or the suitability of this
+// software for any particular purpose. It is provided "as is"
+// without express or implied warranty of any kind.
+//
+//
+//
+//
+//Rivest [Page 8]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+// These notices must be retained in any copies of any part of this
+// documentation and/or software.
+// */
+//
+//#include "global.h"
+//#include "md4.h"
+//
+///* Constants for MD4Transform routine.
+// */
+//#define S11 3
+//#define S12 7
+//#define S13 11
+//#define S14 19
+//#define S21 3
+//#define S22 5
+//#define S23 9
+//#define S24 13
+//#define S31 3
+//#define S32 9
+//#define S33 11
+//#define S34 15
+//
+//static void MD4Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
+//static void Encode PROTO_LIST
+// ((unsigned char *, UINT4 *, unsigned int));
+//static void Decode PROTO_LIST
+// ((UINT4 *, unsigned char *, unsigned int));
+//static void MD4_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
+//static void MD4_memset PROTO_LIST ((POINTER, int, unsigned int));
+//
+//static unsigned char PADDING[64] = {
+// 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+//};
+//
+///* F, G and H are basic MD4 functions.
+// */
+//#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+//#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+//#define H(x, y, z) ((x) ^ (y) ^ (z))
+//
+///* ROTATE_LEFT rotates x left n bits.
+// */
+//#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+//
+///* FF, GG and HH are transformations for rounds 1, 2 and 3 */
+///* Rotation is separate from addition to prevent recomputation */
+//
+//
+//
+//Rivest [Page 9]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+//#define FF(a, b, c, d, x, s) { \
+// (a) += F ((b), (c), (d)) + (x); \
+// (a) = ROTATE_LEFT ((a), (s)); \
+// }
+//#define GG(a, b, c, d, x, s) { \
+// (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
+// (a) = ROTATE_LEFT ((a), (s)); \
+// }
+//#define HH(a, b, c, d, x, s) { \
+// (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
+// (a) = ROTATE_LEFT ((a), (s)); \
+// }
+//
+///* MD4 initialization. Begins an MD4 operation, writing a new context.
+// */
+//void MD4Init (context)
+//MD4_CTX *context; /* context */
+//{
+// context->count[0] = context->count[1] = 0;
+//
+// /* Load magic initialization constants.
+// */
+// context->state[0] = 0x67452301;
+// context->state[1] = 0xefcdab89;
+// context->state[2] = 0x98badcfe;
+// context->state[3] = 0x10325476;
+//}
+//
+///* MD4 block update operation. Continues an MD4 message-digest
+// operation, processing another message block, and updating the
+// context.
+// */
+//void MD4Update (context, input, inputLen)
+//MD4_CTX *context; /* context */
+//unsigned char *input; /* input block */
+//unsigned int inputLen; /* length of input block */
+//{
+// unsigned int i, index, partLen;
+//
+// /* Compute number of bytes mod 64 */
+// index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+// /* Update number of bits */
+// if ((context->count[0] += ((UINT4)inputLen << 3))
+// < ((UINT4)inputLen << 3))
+// context->count[1]++;
+// context->count[1] += ((UINT4)inputLen >> 29);
+//
+// partLen = 64 - index;
+//
+//
+//
+//Rivest [Page 10]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+// /* Transform as many times as possible.
+// */
+// if (inputLen >= partLen) {
+// MD4_memcpy
+// ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+// MD4Transform (context->state, context->buffer);
+//
+// for (i = partLen; i + 63 < inputLen; i += 64)
+// MD4Transform (context->state, &input[i]);
+//
+// index = 0;
+// }
+// else
+// i = 0;
+//
+// /* Buffer remaining input */
+// MD4_memcpy
+// ((POINTER)&context->buffer[index], (POINTER)&input[i],
+// inputLen-i);
+//}
+//
+///* MD4 finalization. Ends an MD4 message-digest operation, writing the
+// the message digest and zeroizing the context.
+// */
+//void MD4Final (digest, context)
+//unsigned char digest[16]; /* message digest */
+//MD4_CTX *context; /* context */
+//{
+// unsigned char bits[8];
+// unsigned int index, padLen;
+//
+// /* Save number of bits */
+// Encode (bits, context->count, 8);
+//
+// /* Pad out to 56 mod 64.
+// */
+// index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+// padLen = (index < 56) ? (56 - index) : (120 - index);
+// MD4Update (context, PADDING, padLen);
+//
+// /* Append length (before padding) */
+// MD4Update (context, bits, 8);
+// /* Store state in digest */
+// Encode (digest, context->state, 16);
+//
+// /* Zeroize sensitive information.
+// */
+// MD4_memset ((POINTER)context, 0, sizeof (*context));
+//
+//
+//
+//Rivest [Page 11]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+//}
+//
+///* MD4 basic transformation. Transforms state based on block.
+// */
+//static void MD4Transform (state, block)
+//UINT4 state[4];
+//unsigned char block[64];
+//{
+// UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+//
+// Decode (x, block, 64);
+//
+// /* Round 1 */
+// FF (a, b, c, d, x[ 0], S11); /* 1 */
+// FF (d, a, b, c, x[ 1], S12); /* 2 */
+// FF (c, d, a, b, x[ 2], S13); /* 3 */
+// FF (b, c, d, a, x[ 3], S14); /* 4 */
+// FF (a, b, c, d, x[ 4], S11); /* 5 */
+// FF (d, a, b, c, x[ 5], S12); /* 6 */
+// FF (c, d, a, b, x[ 6], S13); /* 7 */
+// FF (b, c, d, a, x[ 7], S14); /* 8 */
+// FF (a, b, c, d, x[ 8], S11); /* 9 */
+// FF (d, a, b, c, x[ 9], S12); /* 10 */
+// FF (c, d, a, b, x[10], S13); /* 11 */
+// FF (b, c, d, a, x[11], S14); /* 12 */
+// FF (a, b, c, d, x[12], S11); /* 13 */
+// FF (d, a, b, c, x[13], S12); /* 14 */
+// FF (c, d, a, b, x[14], S13); /* 15 */
+// FF (b, c, d, a, x[15], S14); /* 16 */
+//
+// /* Round 2 */
+// GG (a, b, c, d, x[ 0], S21); /* 17 */
+// GG (d, a, b, c, x[ 4], S22); /* 18 */
+// GG (c, d, a, b, x[ 8], S23); /* 19 */
+// GG (b, c, d, a, x[12], S24); /* 20 */
+// GG (a, b, c, d, x[ 1], S21); /* 21 */
+// GG (d, a, b, c, x[ 5], S22); /* 22 */
+// GG (c, d, a, b, x[ 9], S23); /* 23 */
+// GG (b, c, d, a, x[13], S24); /* 24 */
+// GG (a, b, c, d, x[ 2], S21); /* 25 */
+// GG (d, a, b, c, x[ 6], S22); /* 26 */
+// GG (c, d, a, b, x[10], S23); /* 27 */
+// GG (b, c, d, a, x[14], S24); /* 28 */
+// GG (a, b, c, d, x[ 3], S21); /* 29 */
+// GG (d, a, b, c, x[ 7], S22); /* 30 */
+// GG (c, d, a, b, x[11], S23); /* 31 */
+// GG (b, c, d, a, x[15], S24); /* 32 */
+//
+//
+//
+//
+//Rivest [Page 12]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+// /* Round 3 */
+// HH (a, b, c, d, x[ 0], S31); /* 33 */
+// HH (d, a, b, c, x[ 8], S32); /* 34 */
+// HH (c, d, a, b, x[ 4], S33); /* 35 */
+// HH (b, c, d, a, x[12], S34); /* 36 */
+// HH (a, b, c, d, x[ 2], S31); /* 37 */
+// HH (d, a, b, c, x[10], S32); /* 38 */
+// HH (c, d, a, b, x[ 6], S33); /* 39 */
+// HH (b, c, d, a, x[14], S34); /* 40 */
+// HH (a, b, c, d, x[ 1], S31); /* 41 */
+// HH (d, a, b, c, x[ 9], S32); /* 42 */
+// HH (c, d, a, b, x[ 5], S33); /* 43 */
+// HH (b, c, d, a, x[13], S34); /* 44 */
+// HH (a, b, c, d, x[ 3], S31); /* 45 */
+// HH (d, a, b, c, x[11], S32); /* 46 */
+// HH (c, d, a, b, x[ 7], S33); /* 47 */
+// HH (b, c, d, a, x[15], S34); /* 48 */
+//
+// state[0] += a;
+// state[1] += b;
+// state[2] += c;
+// state[3] += d;
+//
+// /* Zeroize sensitive information.
+// */
+// MD4_memset ((POINTER)x, 0, sizeof (x));
+//}
+//
+///* Encodes input (UINT4) into output (unsigned char). Assumes len is
+// a multiple of 4.
+// */
+//static void Encode (output, input, len)
+//unsigned char *output;
+//UINT4 *input;
+//unsigned int len;
+//{
+// unsigned int i, j;
+//
+// for (i = 0, j = 0; j < len; i++, j += 4) {
+// output[j] = (unsigned char)(input[i] & 0xff);
+// output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+// output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+// output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+// }
+//}
+//
+///* Decodes input (unsigned char) into output (UINT4). Assumes len is
+// a multiple of 4.
+//
+//
+//
+//Rivest [Page 13]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+// */
+//static void Decode (output, input, len)
+//
+//UINT4 *output;
+//unsigned char *input;
+//unsigned int len;
+//{
+// unsigned int i, j;
+//
+// for (i = 0, j = 0; j < len; i++, j += 4)
+// output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+// (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+//}
+//
+///* Note: Replace "for loop" with standard memcpy if possible.
+// */
+//static void MD4_memcpy (output, input, len)
+//POINTER output;
+//POINTER input;
+//unsigned int len;
+//{
+// unsigned int i;
+//
+// for (i = 0; i < len; i++)
+// output[i] = input[i];
+//}
+//
+///* Note: Replace "for loop" with standard memset if possible.
+// */
+//static void MD4_memset (output, value, len)
+//POINTER output;
+//int value;
+//unsigned int len;
+//{
+// unsigned int i;
+//
+// for (i = 0; i < len; i++)
+// ((char *)output)[i] = (char)value;
+//}
+//
+//A.4 mddriver.c
+//
+///* MDDRIVER.C - test driver for MD2, MD4 and MD5
+// */
+//
+///* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+// rights reserved.
+//
+//
+//
+//
+//Rivest [Page 14]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+// RSA Data Security, Inc. makes no representations concerning either
+// the merchantability of this software or the suitability of this
+// software for any particular purpose. It is provided "as is"
+// without express or implied warranty of any kind.
+//
+// These notices must be retained in any copies of any part of this
+// documentation and/or software.
+//
+// */
+//
+///* The following makes MD default to MD5 if it has not already been
+// defined with C compiler flags.
+// */
+//#ifndef MD
+//#define MD MD5
+//#endif
+//
+//#include <stdio.h>
+//#include <time.h>
+//#include <string.h>
+//#include "global.h"
+//#if MD == 2
+//#include "md2.h"
+//#endif
+//#if MD == 4
+//#include "md4.h"
+//#endif
+//#if MD == 5
+//#include "md5.h"
+//#endif
+//
+///* Length of test block, number of test blocks.
+// */
+//#define TEST_BLOCK_LEN 1000
+//#define TEST_BLOCK_COUNT 1000
+//
+//static void MDString PROTO_LIST ((char *));
+//static void MDTimeTrial PROTO_LIST ((void));
+//static void MDTestSuite PROTO_LIST ((void));
+//static void MDFile PROTO_LIST ((char *));
+//static void MDFilter PROTO_LIST ((void));
+//static void MDPrint PROTO_LIST ((unsigned char [16]));
+//
+//#if MD == 2
+//#define MD_CTX MD2_CTX
+//#define MDInit MD2Init
+//#define MDUpdate MD2Update
+//#define MDFinal MD2Final
+//
+//
+//
+//Rivest [Page 15]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+//#endif
+//#if MD == 4
+//#define MD_CTX MD4_CTX
+//#define MDInit MD4Init
+//#define MDUpdate MD4Update
+//#define MDFinal MD4Final
+//#endif
+//#if MD == 5
+//#define MD_CTX MD5_CTX
+//#define MDInit MD5Init
+//#define MDUpdate MD5Update
+//#define MDFinal MD5Final
+//#endif
+//
+///* Main driver.
+//
+// Arguments (may be any combination):
+// -sstring - digests string
+// -t - runs time trial
+// -x - runs test script
+// filename - digests file
+// (none) - digests standard input
+// */
+//int main (argc, argv)
+//int argc;
+//char *argv[];
+//{
+// int i;
+//
+// if (argc > 1)
+// for (i = 1; i < argc; i++)
+// if (argv[i][0] == '-' && argv[i][1] == 's')
+// MDString (argv[i] + 2);
+// else if (strcmp (argv[i], "-t") == 0)
+// MDTimeTrial ();
+// else if (strcmp (argv[i], "-x") == 0)
+// MDTestSuite ();
+// else
+// MDFile (argv[i]);
+// else
+// MDFilter ();
+//
+// return (0);
+//}
+//
+///* Digests a string and prints the result.
+// */
+//static void MDString (string)
+//
+//
+//
+//Rivest [Page 16]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+//char *string;
+//{
+// MD_CTX context;
+// unsigned char digest[16];
+// unsigned int len = strlen (string);
+//
+// MDInit (&context);
+// MDUpdate (&context, string, len);
+// MDFinal (digest, &context);
+//
+// printf ("MD%d (\"%s\") = ", MD, string);
+// MDPrint (digest);
+// printf ("\n");
+//}
+//
+///* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte
+// blocks.
+// */
+//static void MDTimeTrial ()
+//{
+// MD_CTX context;
+// time_t endTime, startTime;
+// unsigned char block[TEST_BLOCK_LEN], digest[16];
+// unsigned int i;
+//
+// printf
+// ("MD%d time trial. Digesting %d %d-byte blocks ...", MD,
+// TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
+//
+// /* Initialize block */
+// for (i = 0; i < TEST_BLOCK_LEN; i++)
+// block[i] = (unsigned char)(i & 0xff);
+//
+// /* Start timer */
+// time (&startTime);
+//
+// /* Digest blocks */
+// MDInit (&context);
+// for (i = 0; i < TEST_BLOCK_COUNT; i++)
+// MDUpdate (&context, block, TEST_BLOCK_LEN);
+// MDFinal (digest, &context);
+//
+// /* Stop timer */
+// time (&endTime);
+//
+// printf (" done\n");
+// printf ("Digest = ");
+// MDPrint (digest);
+//
+//
+//
+//Rivest [Page 17]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+// printf ("\nTime = %ld seconds\n", (long)(endTime-startTime));
+// printf
+// ("Speed = %ld bytes/second\n",
+// (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime));
+//}
+//
+///* Digests a reference suite of strings and prints the results.
+// */
+//static void MDTestSuite ()
+//{
+// printf ("MD%d test suite:\n", MD);
+//
+// MDString ("");
+// MDString ("a");
+// MDString ("abc");
+// MDString ("message digest");
+// MDString ("abcdefghijklmnopqrstuvwxyz");
+// MDString
+// ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+// MDString
+//
+// ("1234567890123456789012345678901234567890\
+//1234567890123456789012345678901234567890");
+//}
+//
+///* Digests a file and prints the result.
+// */
+//static void MDFile (filename)
+//char *filename;
+//{
+// FILE *file;
+// MD_CTX context;
+// int len;
+// unsigned char buffer[1024], digest[16];
+//
+// if ((file = fopen (filename, "r")) == NULL)
+// printf ("%s can't be opened\n", filename);
+//
+// else {
+// MDInit (&context);
+// while (len = fread (buffer, 1, 1024, file))
+// MDUpdate (&context, buffer, len);
+// MDFinal (digest, &context);
+//
+// fclose (file);
+//
+// printf ("MD%d (%s) = ", MD, filename);
+// MDPrint (digest);
+//
+//
+//
+//Rivest [Page 18]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+// printf ("\n");
+// }
+//}
+//
+///* Digests the standard input and prints the result.
+// */
+//static void MDFilter ()
+//{
+// MD_CTX context;
+// int len;
+// unsigned char buffer[16], digest[16];
+//
+// MDInit (&context);
+// while (len = fread (buffer, 1, 16, stdin))
+// MDUpdate (&context, buffer, len);
+// MDFinal (digest, &context);
+//
+// MDPrint (digest);
+// printf ("\n");
+//}
+//
+///* Prints a message digest in hexadecimal.
+// */
+//static void MDPrint (digest)
+//unsigned char digest[16];
+//
+//{
+// unsigned int i;
+//
+// for (i = 0; i < 16; i++)
+// printf ("%02x", digest[i]);
+//}
+//
+//A.5 Test suite
+//
+// The MD4 test suite (driver option "-x") should print the following
+// results:
+//
+//MD4 test suite:
+//MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0
+//MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24
+//MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d
+//MD4 ("message digest") = d9130a8164549fe818874806e1c7014b
+//MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9
+//MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
+//043f8582f241db351ce627e153e7f0e4
+//MD4 ("123456789012345678901234567890123456789012345678901234567890123456
+//78901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536
+//
+//
+//
+//Rivest [Page 19]
+//
+//RFC 1320 MD4 Message-Digest Algorithm April 1992
+//
+//
+//Security Considerations
+//
+// The level of security discussed in this memo is considered to be
+// sufficient for implementing moderate security hybrid digital-
+// signature schemes based on MD4 and a public-key cryptosystem. We do
+// not know of any reason that MD4 would not be sufficient for
+// implementing very high security digital-signature schemes, but
+// because MD4 was designed to be exceptionally fast, it is "at the
+// edge" in terms of risking successful cryptanalytic attack. After
+// further critical review, it may be appropriate to consider MD4 for
+// very high security applications. For very high security applications
+// before the completion of that review, the MD5 algorithm [4] is
+// recommended.
+//
+//Author's Address
+//
+// Ronald L. Rivest
+// Massachusetts Institute of Technology
+// Laboratory for Computer Science
+// NE43-324
+// 545 Technology Square
+// Cambridge, MA 02139-1986
+//
+// Phone: (617) 253-5880
+//
+
+
+public class TestMD4 {
+ public static void main(String args[]) {
+ test("");
+ test("a");
+ test("abc");
+ test("abcdefghijklmnopqrstuvwxyz");
+ test("hi");
+ }
+
+ public static void test(String s) {
+ MD4 md4 = new MD4();
+
+ md4.engineUpdate(s.getBytes(), 0, s.length());
+ System.out.println("\"" + s + "\"");
+ System.out.print(Lib.hexDump(md4.engineDigest(), 16, false));
+ }
+}
diff --git a/test/jake2/qcommon/TestMSG.java b/test/jake2/qcommon/TestMSG.java
new file mode 100644
index 0000000..d6dee32
--- /dev/null
+++ b/test/jake2/qcommon/TestMSG.java
@@ -0,0 +1,66 @@
+/*
+ * Created on 30.01.2004
+ *
+ * To change this generated comment go to
+ * Window>Preferences>Java>Code Generation>Code Template
+ */
+package jake2.qcommon;
+
+/**
+ * @author rst
+ */
+public class TestMSG extends MSG {
+ public static void main(String[] args) {
+
+ byte buf_data[] = new byte[MAX_MSGLEN];
+ sizebuf_t buf = new sizebuf_t();
+
+ SZ.Init(buf, buf_data, MAX_MSGLEN);
+
+ MSG.WriteInt(buf, 0x80000000);
+ MSG.WriteInt(buf, 0x12345678);
+ MSG.WriteInt(buf, 0x7fffffff);
+ MSG.WriteInt(buf, 0xffffffff);
+
+
+ MSG.WriteByte(buf, 1);
+ MSG.WriteByte(buf, 2);
+ MSG.WriteByte(buf, 3);
+ MSG.WriteByte(buf, 4);
+ SZ.Print(buf, "[einz]\n");
+ SZ.Print(buf, "[zwei]...");
+
+ MSG.WriteByte(buf, 0xfe);
+ MSG.WriteByte(buf, 4);
+
+ MSG.WriteShort(buf, 32766);
+ MSG.WriteShort(buf, 16384);
+ MSG.WriteShort(buf, -32768);
+
+
+
+ MSG.WriteFloat(buf, (float) Math.PI);
+
+ System.out.println("Read:" + Integer.toHexString(MSG.ReadLong(buf)));
+ System.out.println("Read:" + Integer.toHexString(MSG.ReadLong(buf)));
+ System.out.println("Read:" + Integer.toHexString(MSG.ReadLong(buf)));
+ System.out.println("Read:" + Integer.toHexString(MSG.ReadLong(buf)));
+
+ System.out.println("Read:" + MSG.ReadByte(buf));
+ System.out.println("Read:" + MSG.ReadByte(buf));
+ System.out.println("Read:" + MSG.ReadByte(buf));
+ System.out.println("Read:" + MSG.ReadByte(buf));
+ System.out.println("Read:<" + MSG.ReadString(buf) + ">");
+
+ System.out.println("Read:" + MSG.ReadByte(buf));
+ System.out.println("Read:" + MSG.ReadByte(buf));
+
+ System.out.println("Read:" + MSG.ReadShort(buf));
+ System.out.println("Read:" + MSG.ReadShort(buf));
+ System.out.println("Read:" + MSG.ReadShort(buf));
+
+
+ System.out.println("Read:" + MSG.ReadFloat(buf));
+ }
+
+}
diff --git a/test/jake2/qcommon/TestRotatePointAroundVector.java b/test/jake2/qcommon/TestRotatePointAroundVector.java
new file mode 100644
index 0000000..37ced72
--- /dev/null
+++ b/test/jake2/qcommon/TestRotatePointAroundVector.java
@@ -0,0 +1,185 @@
+/*
+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 24.01.2004 by RST.
+// $Id: TestRotatePointAroundVector.java,v 1.1 2004-07-07 19:59:58 hzi Exp $
+
+package jake2.qcommon;
+
+import jake2.util.Lib;
+import jake2.util.Math3D;
+
+import java.util.StringTokenizer;
+
+// import jake2.*;
+// import jake2.client.*;
+// import jake2.game.*;
+// import jake2.qcommon.*;
+// import jake2.render.*;
+// import jake2.server.*;
+
+public class TestRotatePointAroundVector
+{
+
+ static String testperp[] =
+ {
+ " 0.009647 0.005551 -0.296153 == -0.006815 0.977844 0.209225",
+ "-0.758731 0.039112 0.214241 == 0.076493 0.996836 -0.021599",
+ " 0.113768 -0.311733 0.603937 == 0.939749 0.156803 -0.303783",
+ "-0.466186 0.341352 0.104305 == 0.393279 -0.287967 0.873159",
+ " 0.775436 0.779995 -0.863782 == 0.962981 -0.180665 0.200072",
+ " 0.814734 0.288255 -0.669693 == -0.170216 0.975423 0.139913",
+ "-0.667435 -0.429661 0.683953 == -0.260653 0.927747 0.267104",
+ "-0.927300 -0.585577 -0.957522 == -0.128592 0.982768 -0.132783",
+ " 0.242942 0.040065 0.092075 == -0.894528 0.291345 -0.339024",
+ " 0.646724 -0.933291 -0.948063 == 0.981161 0.135531 0.137676",
+ " 0.232663 -0.959211 0.253123 == 0.975522 0.212626 -0.056109",
+ "-0.250403 0.458914 -0.208372 == -0.424561 0.778093 0.462945",
+ " 0.194574 -0.775337 -0.556817 == 0.977607 0.170927 0.122753",
+ " 0.741328 0.476465 -0.972738 == -0.126045 0.978140 0.165391",
+ "-0.163294 -0.275933 -0.592179 == 0.858983 -0.216251 -0.464095",
+ "-0.847422 -0.768890 -0.681753 == -0.206793 -0.187629 0.960225",
+ "-0.919289 0.581288 0.198026 == 0.123803 -0.078283 0.989214",
+ "-0.541896 -0.634396 0.228633 == 0.228399 0.267386 0.936129",
+ " 0.210305 0.928218 -0.243859 == 0.975105 -0.214467 0.056344",
+ "-0.399813 -0.891607 -0.711955 == 0.974389 -0.175720 -0.140314",
+ " 0.769699 0.916032 0.251807 == -0.088408 -0.105215 0.990512",
+ " 0.262079 -0.921695 -0.297379 == 0.965746 0.246954 0.079678",
+ "-0.787958 -0.605119 -0.832105 == -0.186950 0.962327 -0.197425",
+ " 0.891434 0.839237 0.815951 == -0.175581 -0.165300 0.970488",
+ "-0.702145 -0.656422 -0.863553 == -0.186798 0.955158 -0.229739",
+ " 0.473749 -0.795161 -0.679987 == 0.950461 0.236242 0.202023",
+ "-0.756531 -0.950714 0.524613 == 0.138574 0.174143 0.974921",
+ "-0.944200 0.293208 -0.783887 == 0.111872 0.989373 0.092878",
+ "-0.380537 -0.962794 0.770586 == 0.984444 -0.137174 0.109789",
+ " 0.019079 -0.668430 0.525818 == 0.999520 0.024358 -0.019161" };
+
+ static String tests[] =
+ {
+ " 0.680375 -0.211234 0.566198 # 0.596880 0.823295 -0.604897 # 120.6802 == -0.655159 0.261707 0.743340 ",
+ " 0.536459 -0.444451 0.107940 # -0.045206 0.257742 -0.270431 # 184.8243 == -0.193460 0.038827 0.159348 ",
+ " 0.904459 0.832390 0.271423 # 0.434594 -0.716795 0.213938 # 5.8682 == 0.747359 -1.101788 0.087111 ",
+ "-0.514226 -0.725537 0.608353 # -0.686642 -0.198111 -0.740419 # 39.1712 == -0.130630 -0.727312 -0.873737 ",
+ " 0.997849 -0.563486 0.025865 # 0.678224 0.225280 -0.407937 # 229.5188 == 0.140445 -1.014774 -0.177662 ",
+ " 0.048574 -0.012834 0.945550 # -0.414966 0.542715 0.053490 # 277.1690 == 0.464477 0.459346 0.005334 ",
+ "-0.199543 0.783059 -0.433371 # -0.295083 0.615449 0.838053 # 25.1119 == 0.132556 0.605152 0.672271 ",
+ " 0.898654 0.051991 -0.827888 # -0.615572 0.326454 0.780465 # 125.6015 == -0.908882 -0.423560 1.130438 ",
+ "-0.871657 -0.959954 -0.084597 # -0.873808 -0.523440 0.941268 # 324.7949 == -0.817769 -1.385161 0.919210 ",
+ " 0.701840 -0.466668 0.079521 # -0.249586 0.520498 0.025071 # 240.3806 == -0.284741 0.143251 -0.292353 ",
+ " 0.063213 -0.921439 -0.124725 # 0.863670 0.861620 0.441905 # 102.3456 == -0.541507 0.588085 0.875724 ",
+ " 0.477069 0.279958 -0.291903 # 0.375723 -0.668052 -0.119791 # 316.8271 == 0.464398 -0.177470 -0.014007 ",
+ " 0.658402 -0.339326 -0.542064 # 0.786745 -0.299280 0.373340 # 344.3286 == 0.726676 -0.059072 0.259724 ",
+ " 0.177280 0.314608 0.717353 # -0.120880 0.847940 -0.203127 # 293.3161 == 0.546512 0.263594 -0.238898 ",
+ " 0.368437 0.821944 -0.035019 # -0.568350 0.900505 0.840257 # 53.1576 == 0.384098 0.383469 1.141096 ",
+ " 0.762124 0.282161 -0.136093 # 0.239193 -0.437881 0.572004 # 110.6848 == -0.034934 -0.356566 -0.561636 ",
+ "-0.105933 -0.547787 -0.624934 # -0.447531 0.112888 -0.166997 # 61.0586 == -0.074301 0.245476 -0.298803 ",
+ " 0.813608 -0.793658 -0.747849 # -0.009112 0.520950 0.969503 # 336.6014 == -0.120939 1.510490 1.400521 ",
+ " 0.368890 -0.233623 0.499542 # -0.262673 -0.411679 -0.535477 # 210.4159 == -0.050155 0.463231 0.348973 ",
+ "-0.511174 -0.695220 0.464297 # -0.749050 0.586941 -0.671796 # 268.2257 == 0.022772 0.925406 0.668994 ",
+ "-0.850940 0.900208 -0.894941 # 0.043127 -0.647579 -0.519875 # 287.2073 == 1.234205 -0.290291 -0.371230 ",
+ " 0.465309 0.313127 0.934810 # 0.278917 0.519470 -0.813039 # 48.5649 == -0.362583 0.755727 -0.615632 ",
+ " 0.040420 -0.843536 -0.860187 # -0.590690 -0.077159 0.639355 # 206.3947 == 0.769276 0.686703 0.210591 ",
+ " 0.511162 -0.896122 -0.684386 # 0.999987 -0.591343 0.779911 # 45.1687 == 0.096778 -1.624548 1.110771 ",
+ " 0.995598 -0.891885 0.741080 # -0.855342 -0.991677 0.846138 # 213.8012 == 2.588428 1.678911 0.857673 ",
+ "-0.639255 -0.673737 -0.216620 # 0.826053 0.639390 -0.281809 # 198.8946 == 0.277942 0.729819 0.633058 ",
+ " 0.158860 -0.094848 0.374775 # -0.800720 0.061616 0.514588 # 109.5463 == -0.113519 -0.154459 -0.215363 ",
+ " 0.984457 0.153942 0.755228 # 0.495619 0.257820 -0.929158 # 269.2090 == 0.101893 -1.323990 -0.319552 ",
+ " 0.666477 0.850753 0.746543 # 0.662075 0.958868 0.487622 # 325.2119 == 1.531004 1.350724 1.039028 ",
+ " 0.967191 0.333761 -0.005483 # -0.672064 0.660024 0.777897 # 27.7181 == -0.548955 0.246637 1.090340 " };
+
+ public static void testRotate(int i, String line)
+ {
+ StringTokenizer tk = new StringTokenizer(line);
+
+ float dir[] = { 0, 0, 0 };
+ float point[] = { 0, 0, 0 };
+ float dst[] = { 0, 0, 0 };
+ float newdst[] = { 0, 0, 0 };
+ float degrees = 0;
+
+ dir[0] = Float.parseFloat(tk.nextToken());
+ dir[1] = Float.parseFloat(tk.nextToken());
+ dir[2] = Float.parseFloat(tk.nextToken());
+
+ tk.nextToken();
+
+ point[0] = Float.parseFloat(tk.nextToken());
+ point[1] = Float.parseFloat(tk.nextToken());
+ point[2] = Float.parseFloat(tk.nextToken());
+
+ tk.nextToken();
+
+ degrees = Float.parseFloat(tk.nextToken());
+
+ tk.nextToken();
+
+ dst[0] = Float.parseFloat(tk.nextToken());
+ dst[1] = Float.parseFloat(tk.nextToken());
+ dst[2] = Float.parseFloat(tk.nextToken());
+
+ Math3D.RotatePointAroundVector(newdst, dir, point, degrees);
+
+
+ System.out.println("" + i + ":" + Lib.vtofs(dst) + " : " + Lib.vtofs(newdst));
+
+ }
+
+ public static void testPerpend(int i, String line)
+ {
+ StringTokenizer tk = new StringTokenizer(line);
+
+ float dir[] = { 0, 0, 0 };
+
+ float dst[] = { 0, 0, 0 };
+
+ float newdst[] = { 0, 0, 0 };
+
+ dir[0] = Float.parseFloat(tk.nextToken());
+ dir[1] = Float.parseFloat(tk.nextToken());
+ dir[2] = Float.parseFloat(tk.nextToken());
+
+ tk.nextToken();
+
+ dst[0] = Float.parseFloat(tk.nextToken());
+ dst[1] = Float.parseFloat(tk.nextToken());
+ dst[2] = Float.parseFloat(tk.nextToken());
+
+ Math3D.PerpendicularVector(newdst, dir);
+
+ System.out.println("" + i + ":" + Lib.vtofs(dst) + " : " + Lib.vtofs(newdst));
+
+ }
+
+ public static void main(String[] args)
+ {
+
+ System.out.println("DEG2RAD:" + Math3D.DEG2RAD(205));
+
+ System.out.println("testperpendicular...");
+ for (int n = 0; n < testperp.length; n++)
+ testPerpend(n, testperp[n]);
+
+
+ System.out.println("testrotate...");
+ for (int n = 0; n < tests.length; n++)
+ testRotate(n, tests[n]);
+ }
+
+}
diff --git a/test/jake2/render/DancingQueens.java b/test/jake2/render/DancingQueens.java
new file mode 100644
index 0000000..fbf233b
--- /dev/null
+++ b/test/jake2/render/DancingQueens.java
@@ -0,0 +1,320 @@
+/*
+ * DancingQueens.java
+ * Copyright (C) 2003
+ *
+ * $Id: DancingQueens.java,v 1.1 2004-07-07 19:59:58 hzi Exp $
+ */
+/*
+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.
+
+*/
+package jake2.render;
+
+import jake2.Defines;
+import jake2.Globals;
+import jake2.client.*;
+import jake2.game.Cmd;
+import jake2.game.cvar_t;
+import jake2.qcommon.*;
+import jake2.sys.IN;
+import jake2.sys.KBD;
+import jake2.util.Math3D;
+import jake2.util.Vargs;
+
+import java.awt.Dimension;
+import java.util.Arrays;
+
+
+/**
+ * DancingQueens
+ *
+ * @author cwei
+ */
+public class DancingQueens
+{
+ String[] args;
+
+ refexport_t re;
+ refimport_t ri;
+ viddef_t viddef;
+ int framecount = 0;
+
+ public DancingQueens(String[] args) {
+ this.args = args;
+ }
+
+ public static void main(String[] args) {
+
+ DancingQueens test = new DancingQueens(args);
+ test.init();
+ test.run();
+ }
+
+ void init() {
+
+ // only for testing
+ // a simple refimport_t implementation
+ ri = new refimport_t() {
+ public void Sys_Error(int err_level, String str) {
+ VID.Error(err_level, str, null);
+ }
+
+ public void Sys_Error(int err_level, String str, Vargs vargs) {
+ VID.Error(err_level, str, vargs);
+ }
+
+ public void Cmd_AddCommand(String name, xcommand_t cmd) {
+ Cmd.AddCommand(name, cmd);
+ }
+
+ public void Cmd_RemoveCommand(String name) {
+ Cmd.RemoveCommand(name);
+ }
+
+ public int Cmd_Argc() {
+ return Cmd.Argc();
+ }
+
+ public String Cmd_Argv(int i) {
+ return Cmd.Argv(i);
+ }
+
+ public void Cmd_ExecuteText(int exec_when, String text) {
+ Cbuf.ExecuteText(exec_when, text);
+ }
+
+ public void Con_Printf(int print_level, String str) {
+ VID.Printf(print_level, str, null);
+ }
+
+ public void Con_Printf(int print_level, String str, Vargs vargs) {
+ VID.Printf(print_level, str, vargs);
+ }
+
+ public byte[] FS_LoadFile(String name) {
+ return FS.LoadFile(name);
+ }
+
+ public int FS_FileLength(String name) {
+ return FS.FileLength(name);
+ }
+
+ public void FS_FreeFile(byte[] buf) {
+ FS.FreeFile(buf);
+ }
+
+ public String FS_Gamedir() {
+ return FS.Gamedir();
+ }
+
+ public cvar_t Cvar_Get(String name, String value, int flags) {
+ return Cvar.Get(name, value, flags);
+ }
+
+ public cvar_t Cvar_Set(String name, String value) {
+ return Cvar.Set(name, value);
+ }
+
+ public void Cvar_SetValue(String name, float value) {
+ Cvar.SetValue(name, value);
+ }
+
+ public boolean Vid_GetModeInfo(Dimension dim, int mode) {
+ return VID.GetModeInfo(dim, mode);
+ }
+
+ public void Vid_MenuInit() {
+ VID.MenuInit();
+ }
+
+ public void Vid_NewWindow(int width, int height) {
+ VID.NewWindow(width, height);
+ }
+
+ public void updateScreenCallback() {
+ DancingQueens.this.updateScreen();
+ }
+ };
+
+
+ Qcommon.InitForTestMap(new String[] {"DancingQueens"});
+ // sehr wichtig !!!
+ VID.Shutdown();
+
+ String[] names = Renderer.getDriverNames();
+ System.out.println("Registered Drivers: " + Arrays.asList(names));
+
+ this.re = Renderer.getDriver("jogl", ri);
+
+ System.out.println("Use driver: " + re);
+ System.out.println();
+
+ re.Init(0, 0);
+
+ Cmd.AddCommand("togglemouse", togglemouse);
+ Cbuf.AddText("bind t togglemouse");
+ Cbuf.Execute();
+ Globals.cls.key_dest = Defines.key_game;
+ Globals.cls.state = Defines.ca_active;
+
+ viddef = Globals.viddef;
+ fov_y = Math3D.CalcFov(fov_x, viddef.width, viddef.height);
+ }
+
+ float fps = 0.0f;
+ long start = 0;
+
+ void updateScreen()
+ {
+ re.BeginFrame(0.0f);
+
+ if (framecount % 500 == 0)
+ {
+ long time = System.currentTimeMillis();
+ fps = 500000.0f / (time - start);
+ start = time;
+ }
+ String text = fps + " fps";
+
+ testModel();
+
+ drawString(10, viddef.height - 16, text);
+
+ re.EndFrame();
+ framecount++;
+ }
+
+ long startTime;
+
+ void run()
+ {
+ startTime = System.currentTimeMillis();
+ while (true)
+ {
+ re.updateScreen(null);
+ KBD.Update();
+ Cbuf.Execute();
+ }
+ }
+
+// ===================================================================
+
+ private float yaw = 0;
+ private entity_t[] models;
+
+ private final static String[] skinNames = {
+ "players/female/athena",
+ "players/female/lotus",
+ "players/female/venus",
+ "players/female/voodoo",
+ "players/female/cobalt",
+ "players/female/lotus",
+ "players/female/brianna"
+ };
+
+ private float fov_x = 50;
+ private float fov_y;
+
+ private void testModel() {
+
+ refdef_t refdef = new refdef_t();
+
+ refdef.x = 0;
+ refdef.y = 0;
+ refdef.width = viddef.width;
+ refdef.height = viddef.height;
+ refdef.fov_x = fov_x;
+ refdef.fov_y = fov_y;
+ refdef.time = 1.0f * 0.001f;
+
+ if (models == null) {
+ models = new entity_t[12]; // model count
+ entity_t m = null;
+ for (int i = 0; i < models.length; i++)
+ {
+ m = getModel(skinNames[i % skinNames.length]);
+ m.origin[0] += 30 * i;
+ m.origin[1] += ((i % 4)) * 30 - 20;
+ models[i] = m;
+ }
+ }
+
+
+ yaw = time() * 0.1f;
+ if (yaw > 360)
+ yaw -= 360;
+ if (yaw < 0)
+ yaw += 360;
+
+ for (int i = 0; i < models.length; i++)
+ {
+ models[i].frame = (time() / 70) % models[i].model.numframes;
+ models[i].angles[1] = yaw;
+ models[i].origin[0] += KBD.my;
+ models[i].origin[1] += KBD.mx;
+
+ }
+
+ refdef.areabits = null;
+ refdef.num_entities = models.length;
+ refdef.entities = models;
+
+ refdef.lightstyles = null;
+ refdef.rdflags = Defines.RDF_NOWORLDMODEL;
+
+ re.RenderFrame(refdef);
+ }
+
+ private entity_t getModel(String name) {
+ entity_t entity = new entity_t();
+ String modelName = "players/female/tris.md2";
+ String modelSkin = name +".pcx";
+
+ entity.model = re.RegisterModel(modelName);
+ entity.skin = re.RegisterSkin(modelSkin);
+ entity.flags = Defines.RF_FULLBRIGHT;
+ entity.origin[0] = 80;
+ entity.origin[1] = 0;
+ entity.origin[2] = 0;
+ Math3D.VectorCopy(entity.origin, entity.oldorigin);
+ entity.frame = 0;
+ entity.oldframe = 0;
+ entity.backlerp = 0.0f;
+ return entity;
+ }
+
+
+ private void drawString(int x, int y, String text)
+ {
+ for (int i = 0; i < text.length(); i++)
+ {
+ re.DrawChar(x + 8 * i, y, (int) text.charAt(i));
+ }
+ }
+
+ private final int time()
+ {
+ return (int) (System.currentTimeMillis() - startTime);
+ }
+
+ static xcommand_t togglemouse = new xcommand_t() {
+ public void execute() {
+ IN.toggleMouse();
+ }
+ };
+} \ No newline at end of file
diff --git a/test/jake2/render/DebugCulling.java b/test/jake2/render/DebugCulling.java
new file mode 100644
index 0000000..b85fb45
--- /dev/null
+++ b/test/jake2/render/DebugCulling.java
@@ -0,0 +1,363 @@
+/*
+ * DebugCulling.java
+ * Copyright (C) 2003
+ *
+ * $Id: DebugCulling.java,v 1.1 2004-07-07 19:59:58 hzi Exp $
+ */
+/*
+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.
+
+*/
+package jake2.render;
+
+import jake2.Defines;
+import jake2.Globals;
+import jake2.client.VID;
+import jake2.client.cparticle_t;
+import jake2.client.entity_t;
+import jake2.client.lightstyle_t;
+import jake2.client.particle_t;
+import jake2.client.refdef_t;
+import jake2.client.refexport_t;
+import jake2.client.refimport_t;
+import jake2.client.viddef_t;
+import jake2.game.Cmd;
+import jake2.game.cvar_t;
+import jake2.qcommon.Cbuf;
+import jake2.qcommon.Cvar;
+import jake2.qcommon.FS;
+import jake2.qcommon.Qcommon;
+import jake2.qcommon.qfiles;
+import jake2.qcommon.xcommand_t;
+import jake2.sys.KBD;
+import jake2.util.Lib;
+import jake2.util.Math3D;
+import jake2.util.Vargs;
+
+import java.awt.Dimension;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Vector;
+
+/**
+ * DebugCulling
+ *
+ * @author cwei
+ */
+public class DebugCulling
+{
+
+ static final float INSTANT_PARTICLE = -10000.0f;
+ static final float PARTICLE_GRAVITY = 40.0f;
+
+ String[] args;
+
+ refexport_t re;
+ refimport_t ri;
+ viddef_t viddef;
+ int framecount = 0;
+
+ public DebugCulling(String[] args)
+ {
+ this.args = args;
+ }
+
+ public static void main(String[] args)
+ {
+
+ DebugCulling test = new DebugCulling(args);
+ test.init();
+ test.run();
+ }
+
+ void init()
+ {
+
+ // only for testing
+ // a simple refimport_t implementation
+ ri = new refimport_t()
+ {
+ public void Sys_Error(int err_level, String str)
+ {
+ VID.Error(err_level, str, null);
+ }
+
+ public void Sys_Error(int err_level, String str, Vargs vargs)
+ {
+ VID.Error(err_level, str, vargs);
+ }
+
+ public void Cmd_AddCommand(String name, xcommand_t cmd)
+ {
+ Cmd.AddCommand(name, cmd);
+ }
+
+ public void Cmd_RemoveCommand(String name)
+ {
+ Cmd.RemoveCommand(name);
+ }
+
+ public int Cmd_Argc()
+ {
+ return Cmd.Argc();
+ }
+
+ public String Cmd_Argv(int i)
+ {
+ return Cmd.Argv(i);
+ }
+
+ public void Cmd_ExecuteText(int exec_when, String text)
+ {
+ Cbuf.ExecuteText(exec_when, text);
+ }
+
+ public void Con_Printf(int print_level, String str)
+ {
+ VID.Printf(print_level, str, null);
+ }
+
+ public void Con_Printf(int print_level, String str, Vargs vargs)
+ {
+ VID.Printf(print_level, str, vargs);
+ }
+
+ public byte[] FS_LoadFile(String name)
+ {
+ return FS.LoadFile(name);
+ }
+
+ public int FS_FileLength(String name)
+ {
+ return FS.FileLength(name);
+ }
+
+ public void FS_FreeFile(byte[] buf)
+ {
+ FS.FreeFile(buf);
+ }
+
+ public String FS_Gamedir()
+ {
+ return FS.Gamedir();
+ }
+
+ public cvar_t Cvar_Get(String name, String value, int flags)
+ {
+ return Cvar.Get(name, value, flags);
+ }
+
+ public cvar_t Cvar_Set(String name, String value)
+ {
+ return Cvar.Set(name, value);
+ }
+
+ public void Cvar_SetValue(String name, float value)
+ {
+ Cvar.SetValue(name, value);
+ }
+
+ public boolean Vid_GetModeInfo(Dimension dim, int mode)
+ {
+ return VID.GetModeInfo(dim, mode);
+ }
+
+ public void Vid_MenuInit()
+ {
+ VID.MenuInit();
+ }
+
+ public void Vid_NewWindow(int width, int height)
+ {
+ VID.NewWindow(width, height);
+ }
+
+ public void updateScreenCallback()
+ {
+ DebugCulling.this.updateScreen();
+ }
+ };
+
+ Qcommon.Init(new String[] { "$Id: DebugCulling.java,v 1.1 2004-07-07 19:59:58 hzi Exp $" });
+ // sehr wichtig !!!
+ VID.Shutdown();
+
+ this.re = Renderer.getDriver("jogl", ri);
+
+ re.Init(0, 0);
+
+ viddef = Globals.viddef;
+ }
+
+ float fps = 0.0f;
+ long start = 0;
+ long startTime;
+
+ void run()
+ {
+ startTime = System.currentTimeMillis();
+ while (true)
+ {
+ re.updateScreen(null);
+ KBD.Update();
+// try {
+// Thread.sleep(5);
+// }
+// catch (InterruptedException e) {
+// }
+ }
+ }
+
+ int currentState = 0;
+
+ void updateScreen()
+ {
+ re.BeginFrame(0.0f);
+
+ switch (currentState)
+ {
+ case 0 :
+ re.DrawStretchPic(0, 0, viddef.width, viddef.height, "conback");
+ re.DrawPic(viddef.width / 2 - 50, viddef.height / 2, "loading");
+ currentState = 1;
+ break;
+ case 1 :
+ // register the map
+ re.SetSky("space1", 0, new float[]{ 0, 0, 0 });
+ re.BeginRegistration("ColorTest");
+ re.EndRegistration();
+ currentState = 2;
+ //break;
+ default :
+ if (framecount % 500 == 0)
+ {
+ long time = System.currentTimeMillis();
+ fps = 500000.0f / (time - start);
+ start = time;
+ }
+ String text = fps + " fps";
+
+ testMap();
+
+ drawString(10, viddef.height - 16, text);
+ }
+
+ re.EndFrame();
+ framecount++;
+ }
+
+ // ===================================================================
+
+ private float yaw = 0;
+
+ private float fov_x = 90;
+
+ private refdef_t refdef;
+
+ private void testMap()
+ {
+
+ if ( refdef == null ) {
+ refdef = new refdef_t();
+
+ refdef.x = 0;
+ refdef.y = 0;
+ refdef.width = viddef.width;
+ refdef.height = viddef.height;
+ refdef.fov_x = fov_x;
+ refdef.fov_y = CalcFov(fov_x, refdef.width -10, refdef.height-10);
+ refdef.vieworg = new float[] {0, 0, 0};
+
+ refdef.viewangles[0] = 0;
+ refdef.viewangles[1] = 90;
+ refdef.viewangles[2] = 0;
+
+ refdef.blend = new float[] { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ refdef.areabits = null; // draw all
+// refdef.areabits = new byte[Defines.MAX_MAP_AREAS / 8];
+// Arrays.fill(refdef.areabits, (byte) 0xFF);
+
+
+ refdef.num_entities = 0;
+ refdef.entities = null;
+
+ lightstyle_t light = new lightstyle_t();
+ light.rgb = new float[] {1.0f, 1.0f, 1.0f};
+ light.white = 3.0f;
+
+ refdef.lightstyles = new lightstyle_t[Defines.MAX_LIGHTSTYLES];
+ for (int i = 0; i < Defines.MAX_LIGHTSTYLES; i++)
+ {
+ refdef.lightstyles[i] = new lightstyle_t();
+ refdef.lightstyles[i].rgb = new float[] { 1.0f, 1.0f, 1.0f };
+ refdef.lightstyles[i].white = 3.0f; // r + g + b
+ }
+
+ }
+
+ refdef.time = time() * 0.001f;
+
+ refdef.viewangles[0] += KBD.my * 0.1f;
+ refdef.viewangles[1] -= KBD.mx * 0.1f;
+
+ refdef.vieworg[0] = 0; // + 30 * (float)Math.sin(time() * 0.0005f);
+ refdef.vieworg[1] = -79;
+ refdef.vieworg[2] = -131;
+
+ // wichtig da aufloesung 1/8
+ // --> ebenen schneiden nie genau die sicht
+ refdef.vieworg[0] += 1.0f / 16;
+ refdef.vieworg[1] += 1.0f / 16;
+ refdef.vieworg[2] += 1.0f / 16;
+
+ re.RenderFrame(refdef);
+ }
+
+ private float CalcFov(float fov_x, float width, float height)
+ {
+ double a;
+ double x;
+
+ if (fov_x < 1 || fov_x > 179)
+ ri.Sys_Error(Defines.ERR_DROP, "Bad fov: " + fov_x);
+
+ x = width / Math.tan(fov_x / 360 * Math.PI);
+
+ a = Math.atan(height / x);
+
+ a = a * 360 / Math.PI;
+
+ return (float) a;
+ }
+
+ private void drawString(int x, int y, String text)
+ {
+ for (int i = 0; i < text.length(); i++)
+ {
+ re.DrawChar(x + 8 * i, y, (int) text.charAt(i));
+ }
+ }
+
+ private final int time()
+ {
+ return (int) (System.currentTimeMillis() - startTime);
+ }
+
+} \ No newline at end of file
diff --git a/test/jake2/render/TestMap.java b/test/jake2/render/TestMap.java
new file mode 100644
index 0000000..9419fa1
--- /dev/null
+++ b/test/jake2/render/TestMap.java
@@ -0,0 +1,623 @@
+/*
+ * TestMap.java
+ * Copyright (C) 2003
+ *
+ * $Id: TestMap.java,v 1.1 2004-07-07 19:59:59 hzi Exp $
+ */
+/*
+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.
+
+*/
+package jake2.render;
+
+import jake2.Defines;
+import jake2.Globals;
+import jake2.client.*;
+import jake2.game.Cmd;
+import jake2.game.cvar_t;
+import jake2.qcommon.*;
+import jake2.sys.IN;
+import jake2.sys.KBD;
+import jake2.util.*;
+
+import java.awt.Dimension;
+import java.util.*;
+
+/**
+ * TestMap
+ *
+ * @author cwei
+ */
+public class TestMap
+{
+
+ static final float INSTANT_PARTICLE = -10000.0f;
+ static final float PARTICLE_GRAVITY = 40.0f;
+
+ String[] args;
+
+ refexport_t re;
+ refimport_t ri;
+ viddef_t viddef;
+ int framecount = 0;
+
+ public TestMap(String[] args)
+ {
+ this.args = args;
+ }
+
+ public static void main(String[] args)
+ {
+
+ TestMap test = new TestMap(args);
+ test.init();
+ test.run();
+ }
+
+ void init()
+ {
+
+ // only for testing
+ // a simple refimport_t implementation
+ ri = new refimport_t()
+ {
+ public void Sys_Error(int err_level, String str)
+ {
+ VID.Error(err_level, str, null);
+ }
+
+ public void Sys_Error(int err_level, String str, Vargs vargs)
+ {
+ VID.Error(err_level, str, vargs);
+ }
+
+ public void Cmd_AddCommand(String name, xcommand_t cmd)
+ {
+ Cmd.AddCommand(name, cmd);
+ }
+
+ public void Cmd_RemoveCommand(String name)
+ {
+ Cmd.RemoveCommand(name);
+ }
+
+ public int Cmd_Argc()
+ {
+ return Cmd.Argc();
+ }
+
+ public String Cmd_Argv(int i)
+ {
+ return Cmd.Argv(i);
+ }
+
+ public void Cmd_ExecuteText(int exec_when, String text)
+ {
+ Cbuf.ExecuteText(exec_when, text);
+ }
+
+ public void Con_Printf(int print_level, String str)
+ {
+ VID.Printf(print_level, str, null);
+ }
+
+ public void Con_Printf(int print_level, String str, Vargs vargs)
+ {
+ VID.Printf(print_level, str, vargs);
+ }
+
+ public byte[] FS_LoadFile(String name)
+ {
+ return FS.LoadFile(name);
+ }
+
+ public int FS_FileLength(String name)
+ {
+ return FS.FileLength(name);
+ }
+
+ public void FS_FreeFile(byte[] buf)
+ {
+ FS.FreeFile(buf);
+ }
+
+ public String FS_Gamedir()
+ {
+ return FS.Gamedir();
+ }
+
+ public cvar_t Cvar_Get(String name, String value, int flags)
+ {
+ return Cvar.Get(name, value, flags);
+ }
+
+ public cvar_t Cvar_Set(String name, String value)
+ {
+ return Cvar.Set(name, value);
+ }
+
+ public void Cvar_SetValue(String name, float value)
+ {
+ Cvar.SetValue(name, value);
+ }
+
+ public boolean Vid_GetModeInfo(Dimension dim, int mode)
+ {
+ return VID.GetModeInfo(dim, mode);
+ }
+
+ public void Vid_MenuInit()
+ {
+ VID.MenuInit();
+ }
+
+ public void Vid_NewWindow(int width, int height)
+ {
+ VID.NewWindow(width, height);
+ }
+
+ public void updateScreenCallback()
+ {
+ TestMap.this.updateScreen();
+ }
+ };
+
+ Qcommon.InitForTestMap(new String[] { "TestMap $Id: TestMap.java,v 1.1 2004-07-07 19:59:59 hzi Exp $" });
+ // sehr wichtig !!!
+ VID.Shutdown();
+
+ this.re = Renderer.getDriver("jogl", ri);
+
+ re.Init(0, 0);
+
+ // init keyboard
+ Cmd.AddCommand("+tforward", forward_down);
+ Cmd.AddCommand("-tforward", forward_up);
+ Cbuf.AddText("bind UPARROW +tforward");
+ Cbuf.Execute();
+ Cmd.AddCommand("+tbackward", backward_down);
+ Cmd.AddCommand("-tbackward", backward_up);
+ Cbuf.AddText("bind DOWNARROW +tbackward");
+ Cbuf.Execute();
+ Cmd.AddCommand("+tleft", left_down);
+ Cmd.AddCommand("-tleft", left_up);
+ Cbuf.AddText("bind LEFTARROW +tleft");
+ Cbuf.Execute();
+ Cmd.AddCommand("+tright", right_down);
+ Cmd.AddCommand("-tright", right_up);
+ Cbuf.AddText("bind RIGHTARROW +tright");
+ Cbuf.Execute();
+ Cmd.AddCommand("togglemouse", togglemouse);
+ Cbuf.AddText("bind t togglemouse");
+ Cbuf.Execute();
+ Globals.cls.key_dest = Defines.key_game;
+ Globals.cls.state = Defines.ca_active;
+
+ viddef = Globals.viddef;
+ }
+
+ float fps = 0.0f;
+ long start = 0;
+ long startTime;
+
+ void run()
+ {
+ startTime = System.currentTimeMillis();
+ while (true)
+ {
+ re.updateScreen(null);
+ KBD.Update();
+ Cbuf.Execute();
+ }
+ }
+
+ int currentState = 0;
+
+ void updateScreen()
+ {
+ re.BeginFrame(0.0f);
+
+ switch (currentState)
+ {
+ case 0 :
+ re.DrawStretchPic(0, 0, viddef.width, viddef.height, "conback");
+ re.DrawPic(viddef.width / 2 - 50, viddef.height / 2, "loading");
+ currentState = 1;
+ break;
+ case 1 :
+ // register the map
+ re.SetSky("space1", 0, new float[]{ 0, 0, 0 });
+ re.BeginRegistration("base1");
+ re.EndRegistration();
+ currentState = 2;
+ //break;
+ default :
+ if (framecount % 500 == 0)
+ {
+ long time = System.currentTimeMillis();
+ fps = 500000.0f / (time - start);
+ start = time;
+ }
+ String text = fps + " fps";
+
+ testMap();
+
+ drawString(10, viddef.height - 16, text);
+ }
+
+ re.EndFrame();
+ framecount++;
+ }
+
+ // ===================================================================
+
+
+ static final int FORWARD = 2;
+ static final int FORWARD_MASK = ~FORWARD;
+ static final int BACKWARD = 4;
+ static final int BACKWARD_MASK = ~BACKWARD;
+ static final int LEFT = 8;
+ static final int LEFT_MASK = ~LEFT;
+ static final int RIGHT = 16;
+ static final int RIGHT_MASK = ~RIGHT;
+
+
+ int movePlayer = 0;
+
+ // forward
+ xcommand_t forward_down = new xcommand_t() {
+ public void execute() {
+ movePlayer |= FORWARD;
+ movePlayer &= BACKWARD_MASK;
+ }
+ };
+ xcommand_t forward_up = new xcommand_t() {
+ public void execute() {
+ movePlayer &= FORWARD_MASK;
+ }
+ };
+ // backward
+ xcommand_t backward_down = new xcommand_t() {
+ public void execute() {
+ movePlayer |= BACKWARD;
+ movePlayer &= FORWARD_MASK;
+ }
+ };
+ xcommand_t backward_up = new xcommand_t() {
+ public void execute() {
+ movePlayer &= BACKWARD_MASK;
+ }
+ };
+ // left
+ xcommand_t left_down = new xcommand_t() {
+ public void execute() {
+ movePlayer |= LEFT;
+ movePlayer &= RIGHT_MASK;
+ }
+ };
+ xcommand_t left_up = new xcommand_t() {
+ public void execute() {
+ movePlayer &= LEFT_MASK;
+ }
+ };
+ // right
+ xcommand_t right_down = new xcommand_t() {
+ public void execute() {
+ movePlayer |= RIGHT;
+ movePlayer &= LEFT_MASK;
+ }
+ };
+ xcommand_t right_up = new xcommand_t() {
+ public void execute() {
+ movePlayer &= RIGHT_MASK;
+ }
+ };
+
+ private float yaw = 0;
+
+ private float fov_x = 90;
+
+ private refdef_t refdef;
+
+ private entity_t ent;
+
+ float[] vpn = {0, 0, 0};
+ float[] vright = {0, 0, 0};
+ float[] vup = {0, 0, 0};
+
+ private void testMap()
+ {
+
+ if ( refdef == null ) {
+ refdef = new refdef_t();
+
+ refdef.x = 0;
+ refdef.y = 0;
+ refdef.width = viddef.width;
+ refdef.height = viddef.height;
+ refdef.fov_x = (Globals.fov == null) ? this.fov_x : Globals.fov.value;
+ refdef.fov_x = this.fov_x;
+ refdef.fov_y = Math3D.CalcFov(refdef.fov_x, refdef.width, refdef.height);
+ refdef.vieworg = new float[] {140, -140, 50};
+ refdef.viewangles = new float[] {0, 0, 0};
+
+ refdef.blend = new float[] { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ refdef.areabits = null; // draw all
+// refdef.areabits = new byte[Defines.MAX_MAP_AREAS / 8];
+// Arrays.fill(refdef.areabits, (byte) 0xFF);
+
+ // load a monster
+ ent = new entity_t();
+
+ model_t weapon = re.RegisterModel("models/monsters/soldier/tris.md2");
+ image_t weaponSkin = re.RegisterSkin("models/monsters/soldier/skin.pcx");
+
+ ent.model = weapon;
+ ent.skin = weaponSkin;
+ ent.origin = new float[] { -60, 80, 25 };
+ Math3D.VectorCopy(ent.origin, ent.oldorigin);
+ ent.angles = new float[] { 0, 300, 0 };
+
+ refdef.num_entities = 1;
+ refdef.entities = new entity_t[] {ent};
+
+ lightstyle_t light = new lightstyle_t();
+ light.rgb = new float[] {1.0f, 1.0f, 1.0f};
+ light.white = 3.0f;
+
+ refdef.lightstyles = new lightstyle_t[Defines.MAX_LIGHTSTYLES];
+ for (int i = 0; i < Defines.MAX_LIGHTSTYLES; i++) {
+ refdef.lightstyles[i] = new lightstyle_t();
+ refdef.lightstyles[i].rgb = new float[] {1.0f, 1.0f, 1.0f};
+ refdef.lightstyles[i].white = 3.0f; // r + g + b
+ }
+
+ refdef.viewangles[1] = 130;
+ // set the start time
+ refdef.time = time() * 0.001f;
+ }
+
+ refdef.viewangles[0] += KBD.my * 0.1f;
+ refdef.viewangles[1] -= KBD.mx * 0.1f; // 90 + 180 * (float)Math.sin(time() * 0.0001f);
+
+ float dt = time() * 0.001f - refdef.time;
+
+ if (movePlayer != 0) {
+
+ float velocity = 150f * dt;
+ Math3D.AngleVectors(refdef.viewangles, vpn, vright, vup);
+
+ // forward
+ if ((movePlayer & FORWARD_MASK) != 0)
+ Math3D.VectorMA(refdef.vieworg, -velocity, vpn, refdef.vieworg);
+ // backward
+ if ((movePlayer & BACKWARD_MASK) != 0)
+ Math3D.VectorMA(refdef.vieworg, velocity, vpn, refdef.vieworg);
+ // left
+ if ((movePlayer & LEFT_MASK) != 0)
+ Math3D.VectorMA(refdef.vieworg, velocity, vright, refdef.vieworg);
+ // right
+ if ((movePlayer & RIGHT_MASK) != 0)
+ Math3D.VectorMA(refdef.vieworg, -velocity, vright, refdef.vieworg);
+
+ // wichtig da aufloesung 1/8
+ // --> ebenen schneiden nie genau die sicht
+ refdef.vieworg[0] += 1.0f / 16;
+ refdef.vieworg[1] += 1.0f / 16;
+ refdef.vieworg[2] += 1.0f / 16;
+ }
+
+ refdef.time = time() * 0.001f;
+
+ // particle init
+ particles.clear();
+
+ // check the enemy distance
+ float[] diff = {0, 0, 0};
+ Math3D.VectorSubtract( refdef.vieworg, ent.origin, diff);
+
+ if (Math3D.VectorLength(diff) < 250 && active_particles.size() == 0) {
+ RailTrail(ent.origin, refdef.vieworg);
+ } else {
+ // monster and partice animation
+ if (active_particles.size() > 0) {
+ // monster
+ ent.frame = (int)((time() * 0.013f) % 15);
+ // monster look at you :-)
+ Math3D.VectorNormalize(diff);
+ Math3D.vectoangles(diff, ent.angles);
+
+ // particles
+ animateParticles();
+
+ particle_t[] tmp = new particle_t[particles.size()];
+ particles.toArray(tmp);
+
+ refdef.particles = tmp;
+ refdef.num_particles = tmp.length;
+ }
+ else {
+ ent.frame = 0;
+ refdef.num_particles = 0;
+ }
+ }
+
+ re.RenderFrame(refdef);
+ }
+
+ private Vector particles = new Vector(1024); // = new particle_t[20];
+ private LinkedList active_particles = new LinkedList();
+ private boolean explode = false;
+ private float[] target;
+
+ private boolean initParticles = true;
+
+ private void animateParticles()
+ {
+ cparticle_t p;
+ float alpha;
+ float time, time2;
+ float[] org = {0, 0, 0};
+ int color;
+ particle_t particle;
+
+ time = 0.0f;
+
+ for (Iterator it = active_particles.iterator(); it.hasNext();)
+ {
+ p = (cparticle_t) it.next();
+
+ // PMM - added INSTANT_PARTICLE handling for heat beam
+ if (p.alphavel != INSTANT_PARTICLE)
+ {
+ time = (time() - p.time) * 0.001f;
+ alpha = p.alpha + time*p.alphavel;
+ if (alpha <= 0)
+ { // faded out
+ it.remove();
+ continue;
+ }
+ }
+ else
+ {
+ alpha = p.alpha;
+ }
+
+ if (alpha > 1.0)
+ alpha = 1;
+ color = (int)p.color;
+
+ time2 = time*time;
+
+ org[0] = p.org[0] + p.vel[0]*time + p.accel[0]*time2;
+ org[1] = p.org[1] + p.vel[1]*time + p.accel[1]*time2;
+ org[2] = p.org[2] + p.vel[2]*time + p.accel[2]*time2;
+
+ particle = new particle_t();
+ particle.alpha = alpha;
+ Math3D.VectorCopy(org, particle.origin);
+ particle.color = color;
+
+ particles.add(particle);
+
+ // PMM
+ if (p.alphavel == INSTANT_PARTICLE)
+ {
+ p.alphavel = 0.0f;
+ p.alpha = 0.0f;
+ }
+ }
+ }
+
+ private void RailTrail(float[] start, float[] end)
+ {
+ float[] move = {0, 0, 0};
+ float[] vec = {0, 0, 0};
+ float len;
+ int j;
+ cparticle_t p;
+ float dec;
+ float[] right = {0, 0, 0};
+ float[] up = {0, 0, 0};
+ int i;
+ float d, c, s;
+ float[] dir = {0, 0, 0};
+
+ Math3D.VectorCopy (start, move);
+ Math3D.VectorSubtract (end, start, vec);
+ len = Math3D.VectorNormalize(vec);
+
+ Math3D.MakeNormalVectors(vec, right, up);
+
+ for (i=0 ; i<len ; i++)
+ {
+
+ p = new cparticle_t();
+ p.time = time();
+ Math3D.VectorClear (p.accel);
+
+ d = i * 0.1f;
+ c = (float)Math.cos(d);
+ s = (float)Math.sin(d);
+
+ Math3D.VectorScale (right, c, dir);
+ Math3D.VectorMA (dir, s, up, dir);
+
+ p.alpha = 1.0f;
+ p.alphavel = -1.0f / (1 + Lib.frand() * 0.2f);
+ p.color = 0x74 + (Lib.rand() & 7);
+ for (j=0 ; j<3 ; j++)
+ {
+ p.org[j] = move[j] + dir[j]*3;
+ p.vel[j] = dir[j]*6;
+ }
+
+ Math3D.VectorAdd (move, vec, move);
+
+ active_particles.add(p);
+ }
+
+ dec = 0.75f;
+ Math3D.VectorScale (vec, dec, vec);
+ Math3D.VectorCopy (start, move);
+
+ while (len > 0)
+ {
+ len -= dec;
+
+ p = new cparticle_t();
+
+ p.time = time();
+ Math3D.VectorClear (p.accel);
+
+ p.alpha = 1.0f;
+ p.alphavel = -1.0f / (0.6f + Lib.frand() * 0.2f);
+ p.color = 0x0 + Lib.rand()&15;
+
+ for (j=0 ; j<3 ; j++)
+ {
+ p.org[j] = move[j] + Lib.crand()*3;
+ p.vel[j] = Lib.crand()*3;
+ p.accel[j] = 0;
+ }
+
+ Math3D.VectorAdd (move, vec, move);
+ active_particles.add(p);
+ }
+ }
+
+ private void drawString(int x, int y, String text)
+ {
+ for (int i = 0; i < text.length(); i++)
+ {
+ re.DrawChar(x + 8 * i, y, (int) text.charAt(i));
+ }
+ }
+
+ private final int time()
+ {
+ return (int) (System.currentTimeMillis() - startTime);
+ }
+
+ static xcommand_t togglemouse = new xcommand_t() {
+ public void execute() {
+ IN.toggleMouse();
+ }
+ };
+}
diff --git a/test/jake2/render/TestRenderer.java b/test/jake2/render/TestRenderer.java
new file mode 100644
index 0000000..976d57c
--- /dev/null
+++ b/test/jake2/render/TestRenderer.java
@@ -0,0 +1,829 @@
+/*
+ * TestRenderer.java
+ * Copyright (C) 2003
+ *
+ * $Id: TestRenderer.java,v 1.1 2004-07-07 19:59:59 hzi Exp $
+ */
+/*
+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.
+
+*/
+package jake2.render;
+
+import java.awt.Dimension;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Vector;
+
+import jake2.Defines;
+import jake2.Globals;
+import jake2.client.*;
+import jake2.game.Cmd;
+import jake2.game.cvar_t;
+import jake2.qcommon.*;
+import jake2.sys.KBD;
+import jake2.sys.Sys;
+import jake2.util.Lib;
+import jake2.util.Math3D;
+import jake2.util.Vargs;
+
+/**
+ * TestRenderer
+ *
+ * @author cwei
+ */
+public class TestRenderer {
+
+ String[] args;
+
+ refexport_t re;
+ refimport_t ri;
+ viddef_t viddef;
+ int framecount = 0;
+ static int testnr = 0;
+
+ public TestRenderer(String[] args) {
+ this.args = args;
+ }
+
+ public static void main(String[] args) {
+
+ TestRenderer test = new TestRenderer(args);
+ test.init();
+ test.run();
+ }
+
+ void init() {
+
+ // only for testing
+ // a simple refimport_t implementation
+ ri = new refimport_t() {
+ public void Sys_Error(int err_level, String str) {
+ VID.Error(err_level, str, null);
+ }
+
+ public void Sys_Error(int err_level, String str, Vargs vargs) {
+ VID.Error(err_level, str, vargs);
+ }
+
+ public void Cmd_AddCommand(String name, xcommand_t cmd) {
+ Cmd.AddCommand(name, cmd);
+ }
+
+ public void Cmd_RemoveCommand(String name) {
+ Cmd.RemoveCommand(name);
+ }
+
+ public int Cmd_Argc() {
+ return Cmd.Argc();
+ }
+
+ public String Cmd_Argv(int i) {
+ return Cmd.Argv(i);
+ }
+
+ public void Cmd_ExecuteText(int exec_when, String text) {
+ Cbuf.ExecuteText(exec_when, text);
+ }
+
+ public void Con_Printf(int print_level, String str) {
+ VID.Printf(print_level, str, null);
+ }
+
+ public void Con_Printf(int print_level, String str, Vargs vargs) {
+ VID.Printf(print_level, str, vargs);
+ }
+
+ public byte[] FS_LoadFile(String name) {
+ return FS.LoadFile(name);
+ }
+
+ public int FS_FileLength(String name) {
+ return FS.FileLength(name);
+ }
+
+ public void FS_FreeFile(byte[] buf) {
+ FS.FreeFile(buf);
+ }
+
+ public String FS_Gamedir() {
+ return FS.Gamedir();
+ }
+
+ public cvar_t Cvar_Get(String name, String value, int flags) {
+ return Cvar.Get(name, value, flags);
+ }
+
+ public cvar_t Cvar_Set(String name, String value) {
+ return Cvar.Set(name, value);
+ }
+
+ public void Cvar_SetValue(String name, float value) {
+ Cvar.SetValue(name, value);
+ }
+
+ public boolean Vid_GetModeInfo(Dimension dim, int mode) {
+ return VID.GetModeInfo(dim, mode);
+ }
+
+ public void Vid_MenuInit() {
+ VID.MenuInit();
+ }
+
+ public void Vid_NewWindow(int width, int height) {
+ VID.NewWindow(width, height);
+ }
+
+ public void updateScreenCallback() {
+ TestRenderer.this.updateScreen();
+ }
+ };
+
+
+ Qcommon.Init(new String[] {"TestRenderer"});
+ // sehr wichtig !!!
+ VID.Shutdown();
+
+ String[] names = Renderer.getDriverNames();
+ System.out.println("Registered Drivers: " + Arrays.asList(names));
+
+ this.re = Renderer.getDriver("jogl", ri);
+
+ System.out.println("Use driver: " + re);
+ System.out.println();
+
+ re.Init(0, 0);
+
+// for (int i = 0; i < raw.length; i++) {
+// raw[i] = (byte)((i % 3) + 1); //((i % 4) + 20);
+// }
+ Cmd.AddCommand("nexttest", nexttest);
+ Cbuf.AddText("bind n nexttest");
+ Cbuf.Execute();
+ Globals.cls.key_dest = Defines.key_game;
+ Globals.cls.state = Defines.ca_active;
+ }
+
+ float fps = 0.0f;
+ long start = 0;
+
+ void updateScreen() {
+ re.BeginFrame(0.0f);
+ viddef = Globals.viddef;
+ re.DrawStretchPic(0,0,viddef.width, viddef.height, "conback");
+
+ if (framecount % 500 == 0) {
+ long time = System.currentTimeMillis();
+ fps = 500000.0f / (time - start);
+ start = time;
+ }
+ String text = fps + " fps";
+
+ for (int i = 0; i < text.length(); i++) {
+ re.DrawChar(10 + 8 * i, viddef.height/2, (int)text.charAt(i));
+ }
+
+ Dimension wal = new Dimension();
+ re.DrawGetPicSize(wal, "/textures/e1u1/basemap.wal");
+
+ re.DrawPic(0, viddef.height - wal.height, "/textures/e1u1/basemap.wal");
+
+ switch (testnr) {
+ case 0 :
+ testParticles();
+ break;
+ case 1 :
+ testModel();
+ break;
+ case 2 :
+ testSprites();
+ break;
+ case 3:
+ testBeam();
+ }
+ re.EndFrame();
+ framecount++;
+ }
+
+
+ long startTime;
+
+ void run() {
+ startTime = System.currentTimeMillis();
+ while (true) {
+ re.updateScreen(null);
+ KBD.Update();
+ Cbuf.Execute();
+ try {
+ Thread.sleep(5);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+// ===================================================================
+
+ private int yaw = 0;
+
+ private void testModel() {
+
+ refdef_t refdef = new refdef_t();
+
+ refdef.x = viddef.width/ 2;
+ refdef.y = viddef.height / 2 - 72;
+ refdef.width = 144 * 2;
+ refdef.height = 168 * 2;
+ refdef.fov_x = 40;
+ refdef.fov_y = Math3D.CalcFov(refdef.fov_x, refdef.width, refdef.height);
+ refdef.time = 1.0f * 0.001f;
+
+ int maxframe = 29;
+ entity_t entity = new entity_t();
+ String modelName = "players/female/tris.md2";
+
+ String modelSkin = "players/female/athena.pcx";
+
+ String modelImage = "/players/female/athena_i.pcx";
+ String modelImage1 = "/players/female/brianna_i.pcx";
+ String modelImage2 = "/players/female/cobalt_i.pcx";
+ String modelImage3 = "/players/female/lotus_i.pcx";
+
+ entity.model = re.RegisterModel(modelName);
+
+ drawString(refdef.x, refdef.y - 20, (entity.model != null) ? modelName : "DEBUG: NullModel");
+
+ entity.skin = re.RegisterSkin(modelSkin);
+ entity.flags = Defines.RF_FULLBRIGHT;
+ entity.origin[0] = 80;
+ entity.origin[1] = 0;
+ entity.origin[2] = 0;
+ Math3D.VectorCopy(entity.origin, entity.oldorigin);
+ entity.frame = (framecount / 3) % ((qfiles.dmdl_t)entity.model.extradata).num_frames;
+ entity.oldframe = 0;
+ entity.backlerp = 0.0f;
+ yaw+=KBD.mx;
+ KBD.mx = 0;
+ if (yaw > 360)
+ yaw -= 360;
+ if (yaw < 0)
+ yaw += 360;
+ entity.angles[1] = yaw;
+
+
+ refdef.areabits = null;
+ refdef.num_entities = 1;
+ refdef.entities = new entity_t[] { entity };
+ refdef.lightstyles = null;
+ refdef.rdflags = Defines.RDF_NOWORLDMODEL;
+
+ // Menu_Draw(& s_player_config_menu);
+
+ M_DrawTextBox(
+ (int) ((refdef.x) * (320.0F / viddef.width) - 8),
+ (int) ((viddef.height / 2) * (240.0F / viddef.height) - 77),
+ refdef.width / 8,
+ refdef.height / 8);
+ refdef.height += 4;
+
+ re.RenderFrame(refdef);
+
+ re.DrawPic(refdef.x - 80, refdef.y, modelImage);
+ re.DrawPic(refdef.x - 80, refdef.y + 47, modelImage1);
+ re.DrawPic(refdef.x - 80, refdef.y + 94, modelImage2);
+ re.DrawPic(refdef.x - 80, refdef.y + 141, modelImage3);
+ }
+
+
+ private String[] sprites = {
+ "sprites/s_bfg1.sp2",
+ "sprites/s_bfg2.sp2",
+ "sprites/s_bfg3.sp2",
+ "sprites/s_explod.sp2",
+ "sprites/s_explo2.sp2",
+ "sprites/s_explo3.sp2",
+ "sprites/s_flash.sp2",
+ "sprites/s_bubble.sp2",
+ };
+
+ private int spriteCount = 0;
+ private boolean loading = true;
+
+ private void testSprites() {
+
+ if (loading) {
+
+ re.DrawPic(viddef.width / 2 - 50, viddef.height / 2, "loading");
+ String name = sprites[spriteCount];
+
+ drawString(viddef.width / 2 - 50, viddef.height / 2 + 50, name);
+
+ re.RegisterModel(name);
+ loading = ++spriteCount < sprites.length;
+ return;
+ }
+
+
+ refdef_t refdef = new refdef_t();
+
+ refdef.x = viddef.width/ 2;
+ refdef.y = viddef.height / 2 - 72;
+ refdef.width = 144 * 2;
+ refdef.height = 168 * 2;
+ refdef.fov_x = 40;
+ refdef.fov_y = Math3D.CalcFov(refdef.fov_x, refdef.width, refdef.height);
+ refdef.time = 1.0f * 0.001f;
+
+ int maxframe = 29;
+ entity_t entity = new entity_t();
+
+ String modelName = sprites[(framecount / 30) % sprites.length];
+ drawString(refdef.x, refdef.y - 20, modelName);
+
+ entity.model = re.RegisterModel(modelName);
+
+ entity.flags = Defines.RF_FULLBRIGHT;
+ entity.origin[0] = 80 - (framecount % 200) + 200;
+ entity.origin[1] = 0 + (float)(40 * Math.sin(Math.toRadians(framecount)));
+ entity.origin[2] = 0 + 20;
+ Math3D.VectorCopy(entity.origin, entity.oldorigin);
+ entity.frame = framecount / 2;
+ entity.oldframe = 0;
+ entity.backlerp = 0.0f;
+
+ refdef.areabits = null;
+ refdef.num_entities = 1;
+ refdef.entities = new entity_t[] { entity };
+ refdef.lightstyles = null;
+ refdef.rdflags = Defines.RDF_NOWORLDMODEL;
+
+ M_DrawTextBox(
+ (int) ((refdef.x) * (320.0F / viddef.width) - 8),
+ (int) ((viddef.height / 2) * (240.0F / viddef.height) - 77),
+ refdef.width / 8,
+ refdef.height / 8);
+ refdef.height += 4;
+
+ re.RenderFrame(refdef);
+
+ }
+
+ private void testBeam() {
+
+ refdef_t refdef = new refdef_t();
+
+ refdef.x = viddef.width/ 2;
+ refdef.y = viddef.height / 2 - 72;
+ refdef.width = 144 * 2;
+ refdef.height = 168 * 2;
+ refdef.fov_x = 40;
+ refdef.fov_y = Math3D.CalcFov(refdef.fov_x, refdef.width, refdef.height);
+ refdef.time = 1.0f * 0.001f;
+
+ int maxframe = 29;
+ entity_t entity = new entity_t();
+
+ drawString(refdef.x, refdef.y - 20, "Beam Test");
+
+ entity.flags = Defines.RF_BEAM;
+ entity.origin[0] = 200;
+ entity.origin[1] = 0 + (float)(80 * Math.sin(4 * Math.toRadians(framecount)));
+ entity.origin[2] = 20 + (float)(40 * Math.cos(4 * Math.toRadians(framecount)));
+
+ entity.oldorigin[0] = 20;
+ entity.oldorigin[1] = 0; // + (float)(40 * Math.sin(Math.toRadians(framecount)));
+ entity.oldorigin[2] = -20; // + 20;
+
+ entity.frame = 3;
+ entity.oldframe = 0;
+ entity.backlerp = 0.0f;
+ // the four beam colors are encoded in 32 bits of skinnum (hack)
+ entity.alpha = 0.6f;
+
+ int[] color = { 0xd0, 0xd1, 0xe0, 0xb0 };
+
+ entity.skinnum = color[framecount / 2 % 4];
+ entity.model = null;
+
+ refdef.areabits = null;
+ refdef.num_entities = 1;
+ refdef.entities = new entity_t[] { entity };
+ refdef.lightstyles = null;
+ refdef.rdflags = Defines.RDF_NOWORLDMODEL;
+
+ M_DrawTextBox(
+ (int) ((refdef.x) * (320.0F / viddef.width) - 8),
+ (int) ((viddef.height / 2) * (240.0F / viddef.height) - 77),
+ refdef.width / 8,
+ refdef.height / 8);
+ refdef.height += 4;
+
+ re.RenderFrame(refdef);
+ }
+
+ private Vector particles = new Vector(1024); // = new particle_t[20];
+ private LinkedList active_particles = new LinkedList();
+ private boolean explode = false;
+ private float[] target;
+
+ private boolean initParticles = true;
+
+ private void testParticles() {
+
+ particles.clear();
+
+ if (active_particles.size() == 0) {
+ if (explode)
+ Explosion(target);
+ else {
+ target = new float[] {150 + Lib.crand() * 80, Lib.crand() * 40, Lib.crand() * 40};
+ RailTrail(new float[]{30, -20, -20}, target);
+ //Heatbeam(new float[]{30, 20, -20}, target);
+ }
+ explode = !explode;
+ }
+ refdef_t refdef = new refdef_t();
+
+ refdef.x = viddef.width/ 2;
+ refdef.y = viddef.height / 2 - 72;
+ refdef.width = 400;
+ refdef.height = 400;
+ refdef.fov_x = 50;
+ refdef.fov_y = Math3D.CalcFov(refdef.fov_x, refdef.width, refdef.height);
+ refdef.time = 1.0f * 0.001f;
+
+ animateParticles();
+
+ drawString(refdef.x, refdef.y - 20, "active particles: " + particles.size());
+
+ particle_t[] tmp = new particle_t[particles.size()];
+
+ particles.toArray(tmp);
+
+ refdef.particles = tmp;
+ refdef.num_particles = tmp.length;
+
+ refdef.areabits = null;
+ refdef.num_entities = 0;
+ refdef.entities = null;
+ refdef.lightstyles = null;
+ refdef.rdflags = Defines.RDF_NOWORLDMODEL;
+
+ M_DrawTextBox(
+ (int) ((refdef.x) * (320.0F / viddef.width) - 8),
+ (int) ((viddef.height / 2) * (240.0F / viddef.height) - 77),
+ refdef.width / 8,
+ refdef.height / 8);
+ refdef.height += 4;
+
+ re.RenderFrame(refdef);
+ }
+
+ private void drawString(int x, int y, String text) {
+ for (int i = 0; i < text.length(); i++) {
+ re.DrawChar(x + 8 * i, y, (int)text.charAt(i));
+ }
+ }
+
+
+ private void M_DrawTextBox(int x, int y, int width, int lines) {
+ int cx, cy;
+ int n;
+
+ // draw left side
+ cx = x;
+ cy = y;
+ M_DrawCharacter(cx, cy, 1);
+ for (n = 0; n < lines; n++) {
+ cy += 8;
+ M_DrawCharacter(cx, cy, 4);
+ }
+ M_DrawCharacter(cx, cy + 8, 7);
+
+ // draw middle
+ cx += 8;
+ while (width > 0) {
+ cy = y;
+ M_DrawCharacter(cx, cy, 2);
+ for (n = 0; n < lines; n++) {
+ cy += 8;
+ M_DrawCharacter(cx, cy, 5);
+ }
+ M_DrawCharacter(cx, cy + 8, 8);
+ width -= 1;
+ cx += 8;
+ }
+
+ // draw right side
+ cy = y;
+ M_DrawCharacter(cx, cy, 3);
+ for (n = 0; n < lines; n++) {
+ cy += 8;
+ M_DrawCharacter(cx, cy, 6);
+ }
+ M_DrawCharacter(cx, cy + 8, 9);
+ }
+
+ /*
+ ================
+ M_DrawCharacter
+
+ Draws one solid graphics character
+ cx and cy are in 320*240 coordinates, and will be centered on
+ higher res screens.
+ ================
+ */
+ private void M_DrawCharacter(int cx, int cy, int num) {
+ re.DrawChar(
+ cx + ((viddef.width - 320) >> 1),
+ cy + ((viddef.height - 240) >> 1),
+ num);
+ }
+
+ long endtime;
+
+ private void Explosion(float[] org) {
+ float[] dir = {0, 0, 0};
+ int i;
+ cparticle_t p;
+
+ for(i=0; i<256; i++)
+ {
+ p = new cparticle_t();
+
+ p.time = time() * 1.0f;
+ p.color = /*0xe0*/ 223 - (Lib.rand() & 7);
+ for (int j=0 ; j<3 ; j++)
+ {
+ p.org[j] = org[j] + (float)(Lib.rand() % 32) - 16;
+ p.vel[j] = (float)(Lib.rand() % 384) - 192;
+ }
+
+ p.accel[0] = p.accel[1] = 0;
+ p.accel[2] = -PARTICLE_GRAVITY;
+ p.alpha = 1.0f;
+ p.alphavel = -0.8f / (0.5f + Lib.frand() * 0.3f);
+
+ active_particles.add(p);
+ }
+ }
+
+ static final float INSTANT_PARTICLE = -10000.0f;
+ static final float PARTICLE_GRAVITY = 40.0f;
+
+
+ /*
+ ===============
+ CL_AddParticles
+ ===============
+ */
+ private void animateParticles()
+ {
+ cparticle_t p;
+ float alpha;
+ float time, time2;
+ float[] org = {0, 0, 0};
+ int color;
+ particle_t particle;
+
+ time = 0.0f;
+
+ for (Iterator it = active_particles.iterator(); it.hasNext();)
+ {
+ p = (cparticle_t) it.next();
+
+ // PMM - added INSTANT_PARTICLE handling for heat beam
+ if (p.alphavel != INSTANT_PARTICLE)
+ {
+ time = (time() - p.time) * 0.001f;
+ alpha = p.alpha + time*p.alphavel;
+ if (alpha <= 0)
+ { // faded out
+ it.remove();
+ continue;
+ }
+ }
+ else
+ {
+ alpha = p.alpha;
+ }
+
+ if (alpha > 1.0)
+ alpha = 1;
+ color = (int)p.color;
+
+ time2 = time*time;
+
+ org[0] = p.org[0] + p.vel[0]*time + p.accel[0]*time2;
+ org[1] = p.org[1] + p.vel[1]*time + p.accel[1]*time2;
+ org[2] = p.org[2] + p.vel[2]*time + p.accel[2]*time2;
+
+ particle = new particle_t();
+ particle.alpha = alpha;
+ Math3D.VectorCopy(org, particle.origin);
+ particle.color = color;
+
+ particles.add(particle);
+
+ // PMM
+ if (p.alphavel == INSTANT_PARTICLE)
+ {
+ p.alphavel = 0.0f;
+ p.alpha = 0.0f;
+ }
+ }
+ }
+
+ private void Heatbeam (float[] start, float[] forward)
+ {
+
+ float[] v_up = {0, 0, 10};
+ float[] v_right = {0, 10, 0};
+
+
+ float[] move = {0, 0, 0};
+ float[] vec = {0, 0, 0};
+ float len;
+ int j;
+ cparticle_t p;
+ float[] right = {0, 0, 0};
+ float[] up = {0, 0, 0};
+ int i;
+ float c, s;
+ float[] dir = {0, 0, 0};
+ float ltime;
+ float step = 32.0f, rstep;
+ float start_pt;
+ float rot;
+ float variance;
+ float[] end = {0, 0, 0};
+
+ Math3D.VectorMA (start, 4096, forward, end);
+
+ Math3D.VectorCopy (start, move);
+ Math3D.VectorSubtract (end, start, vec);
+ len = Math3D.VectorNormalize (vec);
+
+ Math3D.VectorCopy (v_right, right);
+ Math3D.VectorCopy (v_up, up);
+// if (vidref_val == VIDREF_GL)
+// { // GL mode
+ Math3D.VectorMA (move, -0.5f, right, move);
+ Math3D.VectorMA (move, -0.5f, up, move);
+// }
+// // otherwise assume SOFT
+
+ ltime = (float)time()/1000.0f;
+ start_pt = (ltime*96.0f) % step;
+ Math3D.VectorMA (move, start_pt, vec, move);
+
+ Math3D.VectorScale (vec, step, vec);
+
+ rstep = (float)Math.PI / 10.0f;
+ for (i=(int)start_pt ; i<len ; i+=step)
+ {
+ if (i>step*5) // don't bother after the 5th ring
+ break;
+
+ for (rot = 0; rot < Math.PI * 2; rot += rstep)
+ {
+
+ p = new cparticle_t();
+
+ p.time = time();
+ Math3D.VectorClear (p.accel);
+ variance = 0.5f;
+ c = (float)Math.cos(rot)*variance;
+ s = (float)Math.sin(rot)*variance;
+
+ // trim it so it looks like it's starting at the origin
+ if (i < 10)
+ {
+ Math3D.VectorScale (right, c*(i/10.0f), dir);
+ Math3D.VectorMA (dir, s*(i/10.0f), up, dir);
+ }
+ else
+ {
+ Math3D.VectorScale (right, c, dir);
+ Math3D.VectorMA (dir, s, up, dir);
+ }
+
+ p.alpha = 0.8f;
+ p.alphavel = -1000.0f;
+ p.color = /* 223 */0x74 - (Lib.rand()&7);
+ for (j=0 ; j<3 ; j++)
+ {
+ p.org[j] = move[j] + dir[j]*3;
+ p.vel[j] = 0;
+ }
+
+ active_particles.add(p);
+ }
+ Math3D.VectorAdd (move, vec, move);
+ }
+ }
+
+ private void RailTrail(float[] start, float[] end)
+ {
+ float[] move = {0, 0, 0};
+ float[] vec = {0, 0, 0};
+ float len;
+ int j;
+ cparticle_t p;
+ float dec;
+ float[] right = {0, 0, 0};
+ float[] up = {0, 0, 0};
+ int i;
+ float d, c, s;
+ float[] dir = {0, 0, 0};
+
+ Math3D.VectorCopy (start, move);
+ Math3D.VectorSubtract (end, start, vec);
+ len = Math3D.VectorNormalize(vec);
+
+ Math3D.MakeNormalVectors(vec, right, up);
+
+ for (i=0 ; i<len ; i++)
+ {
+
+ p = new cparticle_t();
+ p.time = time();
+ Math3D.VectorClear (p.accel);
+
+ d = i * 0.1f;
+ c = (float)Math.cos(d);
+ s = (float)Math.sin(d);
+
+ Math3D.VectorScale (right, c, dir);
+ Math3D.VectorMA (dir, s, up, dir);
+
+ p.alpha = 1.0f;
+ p.alphavel = -1.0f / (1 + Lib.frand() * 0.2f);
+ p.color = 0x74 + (Lib.rand() & 7);
+ for (j=0 ; j<3 ; j++)
+ {
+ p.org[j] = move[j] + dir[j]*3;
+ p.vel[j] = dir[j]*6;
+ }
+
+ Math3D.VectorAdd (move, vec, move);
+
+ active_particles.add(p);
+ }
+
+ dec = 0.75f;
+ Math3D.VectorScale (vec, dec, vec);
+ Math3D.VectorCopy (start, move);
+
+ while (len > 0)
+ {
+ len -= dec;
+
+ p = new cparticle_t();
+
+ p.time = time();
+ Math3D.VectorClear (p.accel);
+
+ p.alpha = 1.0f;
+ p.alphavel = -1.0f / (0.6f + Lib.frand() * 0.2f);
+ p.color = 0x0 + Lib.rand()&15;
+
+ for (j=0 ; j<3 ; j++)
+ {
+ p.org[j] = move[j] + Lib.crand()*3;
+ p.vel[j] = Lib.crand()*3;
+ p.accel[j] = 0;
+ }
+
+ Math3D.VectorAdd (move, vec, move);
+ active_particles.add(p);
+ }
+ }
+
+ private int time() {
+ return (int)(System.currentTimeMillis() - startTime);
+ }
+
+ static xcommand_t nexttest = new xcommand_t() {
+ public void execute() {
+ testnr++;
+ testnr = testnr % 3;
+ }
+ };
+
+}