diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/jake2/client/CircleListener.java | 61 | ||||
-rw-r--r-- | test/jake2/client/GhostMouse.java | 56 | ||||
-rw-r--r-- | test/jake2/imageio/TestImage.java | 160 | ||||
-rw-r--r-- | test/jake2/qcommon/TestCMD.java | 56 | ||||
-rw-r--r-- | test/jake2/qcommon/TestCOM.java | 53 | ||||
-rw-r--r-- | test/jake2/qcommon/TestCvar.java | 41 | ||||
-rw-r--r-- | test/jake2/qcommon/TestFS.java | 132 | ||||
-rw-r--r-- | test/jake2/qcommon/TestINFO.java | 41 | ||||
-rw-r--r-- | test/jake2/qcommon/TestLoadGame.java | 42 | ||||
-rw-r--r-- | test/jake2/qcommon/TestLoadMap.java | 42 | ||||
-rw-r--r-- | test/jake2/qcommon/TestMD4.java | 1145 | ||||
-rw-r--r-- | test/jake2/qcommon/TestMSG.java | 66 | ||||
-rw-r--r-- | test/jake2/qcommon/TestRotatePointAroundVector.java | 185 | ||||
-rw-r--r-- | test/jake2/render/DancingQueens.java | 320 | ||||
-rw-r--r-- | test/jake2/render/DebugCulling.java | 363 | ||||
-rw-r--r-- | test/jake2/render/TestMap.java | 623 | ||||
-rw-r--r-- | test/jake2/render/TestRenderer.java | 829 |
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 +// EMail: [email protected] +// + + +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; + } + }; + +} |