diff options
Diffstat (limited to 'src')
90 files changed, 16533 insertions, 3078 deletions
diff --git a/src/META-INF/services/javax.imageio.spi.ImageReaderSpi b/src/META-INF/services/javax.imageio.spi.ImageReaderSpi deleted file mode 100644 index a0d3dae..0000000 --- a/src/META-INF/services/javax.imageio.spi.ImageReaderSpi +++ /dev/null @@ -1,2 +0,0 @@ -jake2.imageio.PCXImageReaderSpi -jake2.imageio.WALImageReaderSpi
\ No newline at end of file diff --git a/src/jake2/Defines.java b/src/jake2/Defines.java index 26984e9..f32845b 100644 --- a/src/jake2/Defines.java +++ b/src/jake2/Defines.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 31.10.2003 by RST. -// $Id: Defines.java,v 1.2 2004-07-08 15:58:46 hzi Exp $ +// $Id: Defines.java,v 1.3 2004-07-09 06:50:51 hzi Exp $ /** Contains the definitions for the game engine. */ @@ -1367,14 +1367,4 @@ public class Defines extends Math3D { public final static int MAX_LOCAL_SERVERS = 8; public final static String NO_SERVER_STRING = "<no server>"; public final static int NUM_ADDRESSBOOK_ENTRIES = 9; - - // // rserr_t - static final int rserr_ok = 0; - - static final int rserr_invalid_fullscreen = 1; - - static final int rserr_invalid_mode = 2; - - static final int rserr_unknown = 3; - } diff --git a/src/jake2/Jake2.java b/src/jake2/Jake2.java index 70649b2..65c8075 100644 --- a/src/jake2/Jake2.java +++ b/src/jake2/Jake2.java @@ -2,7 +2,7 @@ * Jake2.java * Copyright (C) 2003 * - * $Id: Jake2.java,v 1.2 2004-07-08 15:58:46 hzi Exp $ + * $Id: Jake2.java,v 1.3 2004-07-09 06:50:51 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -25,10 +25,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package jake2; -import java.io.IOException; -import java.util.logging.*; - -import jake2.qcommon.*; +import jake2.client.SCR; +import jake2.qcommon.Cvar; +import jake2.qcommon.Qcommon; import jake2.sys.Sys; /** @@ -36,23 +35,6 @@ import jake2.sys.Sys; */ public final class Jake2 { - // R I S K Y C O D E D A T A B A S E - // ------------------------------------- - // (m?gliche Fehlerursachen f?r sp?teres Debuggen) - // - sicherstellen, dass svs.clients richtig durchnummeriert wird (client_t.serverindex) - // - sicherstellen, dass SV_GAME.ge.edicts richtig durchnummeriert wird (ent.s.number der richtige index ?) - // - CM_DecompressVis() richtig portiert ? - // - NET.Net_Socket() sockarr_in.addr richtig ersetzt ? - // - - /** - * for all other classes it should be: - * <code> - * private static Logger logger = Logger.getLogger(<CLASSNAME>.class.getName()); - * </code> - * - */ - private static Logger logger; /** * main is used to start the game. Quake2 for Java supports the @@ -61,22 +43,6 @@ public final class Jake2 { */ public static void main(String[] args) { - // init the global LogManager with the logging.properties file - try { - LogManager.getLogManager().readConfiguration(Jake2.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(); - } - - logger = Logger.getLogger(Jake2.class.getName()); - - logger.log(Level.INFO, "Start Jake2 :-)"); - // in C the first arg is the filename int argc = (args == null) ? 1 : args.length + 1; String[] c_args = new String[argc]; @@ -95,17 +61,16 @@ public final class Jake2 { // find time spending rendering last frame newtime = Sys.Milliseconds(); time = newtime - oldtime; - + + // TODO this is a timer hack for Win2000 + // System.currentTimeMillis() resolution bug + if (time == 0 && (Globals.cl_timedemo.value != 0 || SCR.fps.value != 0)) { + time++; + } + if (time > 0) Qcommon.Frame(time); oldtime = newtime; - - // save cpu resources -// try { -// Thread.sleep(1); -// } -// catch (InterruptedException e) { -// } } } } diff --git a/src/jake2/client/CL.java b/src/jake2/client/CL.java index 5b30e34..125cedd 100644 --- a/src/jake2/client/CL.java +++ b/src/jake2/client/CL.java @@ -2,7 +2,7 @@ * CL.java * Copyright (C) 2004 * - * $Id: CL.java,v 1.4 2004-07-08 20:56:50 hzi Exp $ + * $Id: CL.java,v 1.5 2004-07-09 06:50:50 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -43,17 +43,6 @@ import java.nio.ByteBuffer; */ public final class CL extends CL_pred { - -// static cvar_t adr0; -// static cvar_t adr1; -// static cvar_t adr2; -// static cvar_t adr3; -// static cvar_t adr4; -// static cvar_t adr5; -// static cvar_t adr6; -// static cvar_t adr7; -// static cvar_t adr8; - /* ==================== CL_WriteDemoMessage @@ -713,7 +702,7 @@ public final class CL extends CL_pred { c = Cmd.Argv(0); - Com.Printf(NET.AdrToString(net_from) + ": " + c + " \n"); + Com.Printf(NET.AdrToString(net_from) + ": " + c + "\n"); // server connection if (c.equals("client_connect")) { @@ -1126,17 +1115,17 @@ public final class CL extends CL_pred { if (precache_check == ENV_CNT) { precache_check = ENV_CNT + 1; - CM.intwrap iw = new CM.intwrap(map_checksum); + int iw[] = {map_checksum}; CM.CM_LoadMap(cl.configstrings[CS_MODELS + 1], true, iw); - map_checksum = iw.i; -// TODO MD4 check abgeklemmt -// if ((map_checksum ^ atoi(cl.configstrings[CS_MAPCHECKSUM])) != 0) { -// Com.Error( -// ERR_DROP, -// "Local map version differs from server: " + map_checksum + " != '" + cl.configstrings[CS_MAPCHECKSUM] + "'\n"); -// return; -// } + map_checksum = iw[0]; + + if ((map_checksum ^ atoi(cl.configstrings[CS_MAPCHECKSUM])) != 0) { + Com.Error( + ERR_DROP, + "Local map version differs from server: " + map_checksum + " != '" + cl.configstrings[CS_MAPCHECKSUM] + "'\n"); + return; + } } if (precache_check > ENV_CNT && precache_check < TEXTURE_CNT) { @@ -1201,10 +1190,11 @@ public final class CL extends CL_pred { if (Cmd.Argc() < 2) { - CM.intwrap iw = new CM.intwrap(0); // for detecting cheater maps + int iw[] ={0};// for detecting cheater maps + CM.CM_LoadMap(cl.configstrings[CS_MODELS + 1], true, iw); -// int mapchecksum = iw.i ; + int mapchecksum = iw[0] ; CL.RegisterSounds(); CL.PrepRefresh(); return; @@ -1540,8 +1530,7 @@ public final class CL extends CL_pred { VID.CheckChanges(); if (!cl.refresh_prepped && cls.state == ca_active) { CL.PrepRefresh(); - // TODO force GC after level loading - System.gc(); + // force GC after level loading System.gc(); } diff --git a/src/jake2/client/CL_ents.java b/src/jake2/client/CL_ents.java index d406ff2..ae05398 100644 --- a/src/jake2/client/CL_ents.java +++ b/src/jake2/client/CL_ents.java @@ -2,7 +2,7 @@ * CL_ents.java * Copyright (C) 2004 * - * $Id: CL_ents.java,v 1.3 2004-07-08 20:56:50 hzi Exp $ + * $Id: CL_ents.java,v 1.4 2004-07-09 06:50:50 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -53,7 +53,7 @@ public class CL_ents extends CL_inv { ================= */ static int bitcounts[] = new int[32]; /// just for protocol profiling - public static int ParseEntityBits(CM.intwrap bits) { + public static int ParseEntityBits(int bits[]) { int b, total; int i; int number; @@ -82,7 +82,7 @@ public class CL_ents extends CL_inv { else number = MSG.ReadByte(net_message); - bits.i = total; + bits[0] = total; return number; } @@ -253,9 +253,9 @@ public class CL_ents extends CL_inv { } while (true) { - CM.intwrap iw = new CM.intwrap(bits); + int iw[] = {bits}; newnum = ParseEntityBits(iw); - bits = iw.i; + bits = iw[0]; if (newnum >= MAX_EDICTS) Com.Error(ERR_DROP, "CL_ParsePacketEntities: bad number:" + newnum); diff --git a/src/jake2/client/CL_input.java b/src/jake2/client/CL_input.java index b55b866..47132bb 100644 --- a/src/jake2/client/CL_input.java +++ b/src/jake2/client/CL_input.java @@ -2,7 +2,7 @@ * CL_input.java * Copyright (C) 2004 * - * $Id: CL_input.java,v 1.2 2004-07-08 15:58:43 hzi Exp $ + * $Id: CL_input.java,v 1.3 2004-07-09 06:50:50 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -549,10 +549,7 @@ public class CL_input extends CL_ents { MSG.WriteDeltaUsercmd(buf, oldcmd, cmd); // calculate a checksum over the move commands - buf.data[checksumIndex] = 0; - /*COM_BlockSequenceCRCByte( - buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1, - cls.netchan.outgoing_sequence);*/ + buf.data[checksumIndex] = Com.BlockSequenceCRCByte(buf.data, checksumIndex + 1, buf.cursize - checksumIndex - 1, cls.netchan.outgoing_sequence); // // deliver the message diff --git a/src/jake2/client/CL_parse.java b/src/jake2/client/CL_parse.java index ad19960..a36e677 100644 --- a/src/jake2/client/CL_parse.java +++ b/src/jake2/client/CL_parse.java @@ -2,7 +2,7 @@ * CL_parse.java * Copyright (C) 2004 * - * $Id: CL_parse.java,v 1.4 2004-07-08 20:56:49 hzi Exp $ + * $Id: CL_parse.java,v 1.5 2004-07-09 06:50:50 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -360,10 +360,10 @@ public class CL_parse extends CL_view { entity_state_t nullstate = new entity_state_t(null); //memset(nullstate, 0, sizeof(nullstate)); - CM.intwrap bits = new CM.intwrap(0); + int bits[] = {0}; newnum = CL_ents.ParseEntityBits(bits); es = cl_entities[newnum].baseline; - CL_ents.ParseDelta(nullstate, es, newnum, bits.i); + CL_ents.ParseDelta(nullstate, es, newnum, bits[0]); } /* diff --git a/src/jake2/client/CL_view.java b/src/jake2/client/CL_view.java index 08e55c3..ab9efa7 100644 --- a/src/jake2/client/CL_view.java +++ b/src/jake2/client/CL_view.java @@ -2,7 +2,7 @@ * CL_view.java * Copyright (C) 2004 * - * $Id: CL_view.java,v 1.2 2004-07-08 20:24:29 hzi Exp $ + * $Id: CL_view.java,v 1.3 2004-07-09 06:50:50 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -25,17 +25,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package jake2.client; -import java.util.StringTokenizer; - import jake2.qcommon.CM; import jake2.qcommon.Com; -import jake2.qcommon.xcommand_t; import jake2.sys.Sys; -import jake2.util.Vargs; - - - +import java.util.StringTokenizer; public class CL_view extends CL_input { @@ -50,18 +44,7 @@ public class CL_view extends CL_input { Call before entering a new level, or after changing dlls ================= */ - - private static xcommand_t prepRefreshCallback = new xcommand_t() { - public void execute() { - PrepRefresh2(); - } - }; - static void PrepRefresh() { - re.updateScreen(prepRefreshCallback); - } - - static void PrepRefresh2() { String mapname; int i; String name; @@ -80,13 +63,13 @@ public class CL_view extends CL_input { // register models, pics, and skins Com.Printf("Map: " + mapname + "\r"); - SCR.UpdateScreen2(); + SCR.UpdateScreen(); re.BeginRegistration(mapname); Com.Printf(" \r"); // precache status bar pics Com.Printf("pics\r"); - SCR.UpdateScreen2(); + SCR.UpdateScreen(); SCR.TouchPics(); Com.Printf(" \r"); @@ -99,11 +82,11 @@ public class CL_view extends CL_input { name = new String(cl.configstrings[CS_MODELS+i]); if (name.length() > 37) name = name.substring(0, 36); - /* + if (name.charAt(0) != '*') - Com.Printf("name" + "\r"); - */ - SCR.UpdateScreen2(); + Com.Printf(name + "\r"); + + SCR.UpdateScreen(); Sys.SendKeyEvents(); // pump message loop if (name.charAt(0) == '#') { // special player weapon model @@ -123,7 +106,7 @@ public class CL_view extends CL_input { } Com.Printf("images\r"); - SCR.UpdateScreen2(); + SCR.UpdateScreen(); for (i=1 ; i<MAX_IMAGES && cl.configstrings[CS_IMAGES+i].length() > 0 ; i++) { cl.image_precache[i] = re.RegisterPic(cl.configstrings[CS_IMAGES+i]); Sys.SendKeyEvents(); // pump message loop @@ -133,8 +116,8 @@ public class CL_view extends CL_input { for (i=0 ; i<MAX_CLIENTS ; i++) { if (cl.configstrings[CS_PLAYERSKINS+i].length() == 0) continue; - Com.Printf("client %i\r", new Vargs(1).add(i)); - SCR.UpdateScreen2(); + Com.Printf("client " + i + '\r'); + SCR.UpdateScreen(); Sys.SendKeyEvents(); // pump message loop CL.ParseClientinfo(i); Com.Printf(" \r"); @@ -144,7 +127,7 @@ public class CL_view extends CL_input { // set sky textures and speed Com.Printf("sky\r"); - SCR.UpdateScreen2(); + SCR.UpdateScreen(); rotate = Float.parseFloat(cl.configstrings[CS_SKYROTATE]); StringTokenizer st = new StringTokenizer(cl.configstrings[CS_SKYAXIS]); axis[0] = Float.parseFloat(st.nextToken()); @@ -159,7 +142,7 @@ public class CL_view extends CL_input { // clear any lines of console text Console.ClearNotify(); - SCR.UpdateScreen2(); + SCR.UpdateScreen(); cl.refresh_prepped = true; cl.force_refdef = true; // make sure we have a valid refdef } diff --git a/src/jake2/client/Key.java b/src/jake2/client/Key.java index 0b3e82a..5f7d921 100644 --- a/src/jake2/client/Key.java +++ b/src/jake2/client/Key.java @@ -2,7 +2,7 @@ * Key.java * Copyright (C) 2003 * - * $Id: Key.java,v 1.3 2004-07-08 20:24:29 hzi Exp $ + * $Id: Key.java,v 1.4 2004-07-09 06:50:50 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -119,7 +119,7 @@ public class Key extends Globals { static int history_line = 0; static boolean shift_down = false; static int[] key_repeats = new int[256]; - static int[] keyshift = new int[256]; + //static int[] keyshift = new int[256]; static boolean[] menubound = new boolean[256]; static boolean[] consolekeys = new boolean[256]; @@ -241,31 +241,31 @@ public class Key extends Globals { consolekeys['`'] = false; consolekeys['~'] = false; - for (int i = 0; i < 256; i++) - keyshift[i] = i; - for (int i = 'a'; i <= 'z'; i++) - keyshift[i] = i - 'a' + 'A'; - keyshift['1'] = '!'; - keyshift['2'] = '@'; - keyshift['3'] = '#'; - keyshift['4'] = '$'; - keyshift['5'] = '%'; - keyshift['6'] = '^'; - keyshift['7'] = '&'; - keyshift['8'] = '*'; - keyshift['9'] = '('; - keyshift['0'] = ')'; - keyshift['-'] = '_'; - keyshift['='] = '+'; - keyshift[','] = '<'; - keyshift['.'] = '>'; - keyshift['/'] = '?'; - keyshift[';'] = ':'; - keyshift['\''] = '"'; - keyshift['['] = '{'; - keyshift[']'] = '}'; - keyshift['`'] = '~'; - keyshift['\\'] = '|'; +// for (int i = 0; i < 256; i++) +// keyshift[i] = i; +// for (int i = 'a'; i <= 'z'; i++) +// keyshift[i] = i - 'a' + 'A'; +// keyshift['1'] = '!'; +// keyshift['2'] = '@'; +// keyshift['3'] = '#'; +// keyshift['4'] = '$'; +// keyshift['5'] = '%'; +// keyshift['6'] = '^'; +// keyshift['7'] = '&'; +// keyshift['8'] = '*'; +// keyshift['9'] = '('; +// keyshift['0'] = ')'; +// keyshift['-'] = '_'; +// keyshift['='] = '+'; +// keyshift[','] = '<'; +// keyshift['.'] = '>'; +// keyshift['/'] = '?'; +// keyshift[';'] = ':'; +// keyshift['\''] = '"'; +// keyshift['['] = '{'; +// keyshift[']'] = '}'; +// keyshift['`'] = '~'; +// keyshift['\\'] = '|'; menubound[K_ESCAPE] = true; for (int i = 0; i < 12; i++) @@ -386,13 +386,13 @@ public class Key extends Globals { cmd = "-" + kb.substring(1) + " " + key + " " + time + "\n"; Cbuf.AddText(cmd); } - if (keyshift[key] != key) { - kb = Globals.keybindings[keyshift[key]]; - if (kb != null && kb.length()>0 && kb.charAt(0) == '+') { - cmd = "-" + kb.substring(1) + " " + key + " " + time + "\n"; - Cbuf.AddText(cmd); - } - } +// if (keyshift[key] != key) { +// kb = Globals.keybindings[keyshift[key]]; +// if (kb != null && kb.length()>0 && kb.charAt(0) == '+') { +// cmd = "-" + kb.substring(1) + " " + key + " " + time + "\n"; +// Cbuf.AddText(cmd); +// } +// } return; } @@ -419,8 +419,8 @@ public class Key extends Globals { if (!down) return; // other systems only care about key down events - if (shift_down) - key = keyshift[key]; +// if (shift_down) +// key = keyshift[key]; switch (Globals.cls.key_dest) { case Defines.key_message : diff --git a/src/jake2/client/Menu.java b/src/jake2/client/Menu.java index 00944ed..faaf77c 100644 --- a/src/jake2/client/Menu.java +++ b/src/jake2/client/Menu.java @@ -2,7 +2,7 @@ * Menu.java * Copyright (C) 2004 * - * $Id: Menu.java,v 1.3 2004-07-08 20:56:49 hzi Exp $ + * $Id: Menu.java,v 1.4 2004-07-09 06:50:50 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -1226,7 +1226,7 @@ public final class Menu extends Key { static menulist_s s_options_joystick_box = new menulist_s(); static menulist_s s_options_cdvolume_box = new menulist_s(); static menulist_s s_options_quality_list = new menulist_s(); - static menulist_s s_options_compatibility_list = new menulist_s(); + //static menulist_s s_options_compatibility_list = new menulist_s(); static menuaction_s s_options_console_action = new menuaction_s(); static void CrosshairFunc(Object unused) { @@ -1268,7 +1268,13 @@ public final class Menu extends Key { static void ControlsSetMenuItemValues() { s_options_sfxvolume_slider.curvalue = Cvar.VariableValue("s_volume") * 10; s_options_cdvolume_box.curvalue = 1 - ((int) Cvar.VariableValue("cd_nocd")); - s_options_quality_list.curvalue = 1 - ((int) Cvar.VariableValue("s_loadas8bit")); + //s_options_quality_list.curvalue = 1 - ((int) Cvar.VariableValue("s_loadas8bit")); + if ("joal".equals(Cvar.VariableString("s_impl"))) { + s_options_quality_list.curvalue = 0; + } else { + s_options_quality_list.curvalue = 1; + } + s_options_sensitivity_slider.curvalue = (sensitivity.value) * 2; Cvar.SetValue("cl_run", ClampCvar(0, 1, cl_run.value)); @@ -1339,30 +1345,41 @@ public final class Menu extends Key { } static void UpdateSoundQualityFunc(Object unused) { + boolean driverNotChanged = false; if (s_options_quality_list.curvalue != 0) { - Cvar.SetValue("s_khz", 22); - Cvar.SetValue("s_loadas8bit", 0); +// Cvar.SetValue("s_khz", 22); +// Cvar.SetValue("s_loadas8bit", 0); + driverNotChanged = S.getDriverName().equals("dummy"); + Cvar.Set("s_impl", "dummy"); } else { - Cvar.SetValue("s_khz", 11); - Cvar.SetValue("s_loadas8bit", 1); +// Cvar.SetValue("s_khz", 11); +// Cvar.SetValue("s_loadas8bit", 1); + driverNotChanged = S.getDriverName().equals("joal"); + Cvar.Set("s_impl", "joal"); } - Cvar.SetValue("s_primary", s_options_compatibility_list.curvalue); + //Cvar.SetValue("s_primary", s_options_compatibility_list.curvalue); - DrawTextBox(8, 120 - 48, 36, 3); - Print(16 + 16, 120 - 48 + 8, "Restarting the sound system. This"); - Print(16 + 16, 120 - 48 + 16, "could take up to a minute, so"); - Print(16 + 16, 120 - 48 + 24, "please be patient."); + if (driverNotChanged) { + re.EndFrame(); + return; + } else { - // the text box won't show up unless we do a buffer swap - re.EndFrame(); + DrawTextBox(8, 120 - 48, 36, 3); + Print(16 + 16, 120 - 48 + 8, "Restarting the sound system. This"); + Print(16 + 16, 120 - 48 + 16, "could take up to a minute, so"); + Print(16 + 16, 120 - 48 + 24, "please be patient."); - CL.Snd_Restart_f.execute(); + // the text box won't show up unless we do a buffer swap + re.EndFrame(); + + CL.Snd_Restart_f.execute(); + } } static String cd_music_items[] = { "disabled", "enabled", null }; - static String quality_items[] = { "low", "high", null }; + static String soundstate_items[] = { "on", "off", null }; static String compatibility_items[] = { "max compatibility", "max performance", null }; @@ -1410,26 +1427,27 @@ public final class Menu extends Key { s_options_quality_list.x = 0; s_options_quality_list.y = 20; ; - s_options_quality_list.name = "sound quality"; + s_options_quality_list.name = "sound"; s_options_quality_list.callback = new mcallback() { public void execute(Object o) { UpdateSoundQualityFunc(o); } }; - s_options_quality_list.itemnames = quality_items; - s_options_quality_list.curvalue = 1 - (int) Cvar.VariableValue("s_loadas8bit"); - - s_options_compatibility_list.type = MTYPE_SPINCONTROL; - s_options_compatibility_list.x = 0; - s_options_compatibility_list.y = 30; - s_options_compatibility_list.name = "sound compatibility"; - s_options_compatibility_list.callback = new mcallback() { - public void execute(Object o) { - UpdateSoundQualityFunc(o); - } - }; - s_options_compatibility_list.itemnames = compatibility_items; - s_options_compatibility_list.curvalue = (int) Cvar.VariableValue("s_primary"); + s_options_quality_list.itemnames = soundstate_items; + //s_options_quality_list.curvalue = 1 - (int) Cvar.VariableValue("s_loadas8bit"); + + +// s_options_compatibility_list.type = MTYPE_SPINCONTROL; +// s_options_compatibility_list.x = 0; +// s_options_compatibility_list.y = 30; +// s_options_compatibility_list.name = "sound compatibility"; +// s_options_compatibility_list.callback = new mcallback() { +// public void execute(Object o) { +// UpdateSoundQualityFunc(o); +// } +// }; +// s_options_compatibility_list.itemnames = compatibility_items; +// s_options_compatibility_list.curvalue = (int) Cvar.VariableValue("s_primary"); s_options_sensitivity_slider.type = MTYPE_SLIDER; s_options_sensitivity_slider.x = 0; @@ -1563,7 +1581,7 @@ public final class Menu extends Key { Menu_AddItem(s_options_menu, s_options_cdvolume_box); Menu_AddItem(s_options_menu, s_options_quality_list); - Menu_AddItem(s_options_menu, s_options_compatibility_list); +// Menu_AddItem(s_options_menu, s_options_compatibility_list); Menu_AddItem(s_options_menu, s_options_sensitivity_slider); Menu_AddItem(s_options_menu, s_options_alwaysrun_box); Menu_AddItem(s_options_menu, s_options_invertmouse_box); @@ -1653,7 +1671,7 @@ public final class Menu extends Key { "John Cash", "Brian Hook", "", - "+JAVA PORT BY JTEAM", + "+JAVA PORT BY BYTONIC", "CWEI", "HOZ", "RST", @@ -2945,6 +2963,7 @@ public final class Menu extends Key { s_hostname_field.length = 12; s_hostname_field.visible_length = 12; s_hostname_field.buffer = new StringBuffer(Cvar.VariableString("hostname")); + s_hostname_field.cursor = s_hostname_field.buffer.length(); s_startserver_dmoptions_action.type = MTYPE_ACTION; s_startserver_dmoptions_action.name = " deathmatch flags"; @@ -4464,7 +4483,7 @@ public final class Menu extends Key { } Menu_DrawString(f.x + f.parent.x + 24, f.y + f.parent.y, tempbuffer); - + if (Menu_ItemAtCursor(f.parent) == f) { int offset; diff --git a/src/jake2/client/SCR.java b/src/jake2/client/SCR.java index 66b5c33..5df826c 100644 --- a/src/jake2/client/SCR.java +++ b/src/jake2/client/SCR.java @@ -2,7 +2,7 @@ * SCR.java * Copyright (C) 2003 * - * $Id: SCR.java,v 1.4 2004-07-08 20:56:49 hzi Exp $ + * $Id: SCR.java,v 1.5 2004-07-09 06:50:50 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -84,7 +84,7 @@ public final class SCR extends Globals static cvar_t scr_graphscale; static cvar_t scr_graphshift; static cvar_t scr_drawall; - static cvar_t fps; + public static cvar_t fps; static dirty_t scr_dirty = new dirty_t(); static dirty_t[] scr_old_dirty = { new dirty_t(), new dirty_t()}; @@ -98,6 +98,17 @@ public final class SCR extends Globals int x2; int y1; int y2; + + void set(dirty_t src) { + x1 = src.x1; + x2 = src.x2; + y1 = src.y1; + y2 = src.y2; + } + + void clear() { + x1 = x2 = y1 = y2 = 0; + } } /* @@ -700,11 +711,14 @@ public final class SCR extends Globals Clear any parts of the tiled background that were drawn on last frame ============== */ + + static dirty_t clear = new dirty_t(); + static void TileClear() { int i; int top, bottom, left, right; - dirty_t clear = new dirty_t(); + clear.clear(); if (scr_drawall.value != 0) DirtyScreen(); // for power vr or broken page flippers... @@ -718,7 +732,7 @@ public final class SCR extends Globals // erase rect will be the union of the past three frames // so tripple buffering works properly - clear = scr_dirty; + clear.set(scr_dirty); for (i = 0; i < 2; i++) { if (scr_old_dirty[i].x1 < clear.x1) @@ -731,8 +745,8 @@ public final class SCR extends Globals clear.y2 = scr_old_dirty[i].y2; } - scr_old_dirty[1] = scr_old_dirty[0]; - scr_old_dirty[0] = scr_dirty; + scr_old_dirty[1].set(scr_old_dirty[0]); + scr_old_dirty[0].set(scr_dirty); scr_dirty.x1 = 9999; scr_dirty.x2 = -9999; @@ -1452,10 +1466,16 @@ public final class SCR extends Globals private static int lastframes = 0; private static int lasttime = 0; private static String fpsvalue = ""; + static void DrawFPS() { if (fps.value > 0.0f) { + if (fps.modified) { + fps.modified = false; + Cvar.SetValue("cl_maxfps", 1000); + } + int diff = cls.realtime - lasttime; if (diff > (int) (fps.value * 1000)) { @@ -1469,6 +1489,9 @@ public final class SCR extends Globals re.DrawChar(x, 2, fpsvalue.charAt(i)); x += 8; } + } else if (fps.modified){ + fps.modified = false; + Cvar.SetValue("cl_maxfps", 90); } } diff --git a/src/jake2/client/V.java b/src/jake2/client/V.java index 3b9d139..2fd3005 100644 --- a/src/jake2/client/V.java +++ b/src/jake2/client/V.java @@ -2,7 +2,7 @@ * V.java * Copyright (C) 2003 * - * $Id: V.java,v 1.1 2004-07-07 19:58:52 hzi Exp $ + * $Id: V.java,v 1.2 2004-07-09 06:50:50 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -34,6 +34,7 @@ import jake2.util.Math3D; import jake2.util.Vargs; import java.io.IOException; +import java.nio.FloatBuffer; /** * V @@ -53,7 +54,7 @@ public final class V extends Globals { static entity_t[] r_entities = new entity_t[MAX_ENTITIES]; static int r_numparticles; - static particle_t[] r_particles = new particle_t[MAX_PARTICLES]; + //static particle_t[] r_particles = new particle_t[MAX_PARTICLES]; static lightstyle_t[] r_lightstyles = new lightstyle_t[MAX_LIGHTSTYLES]; static { @@ -61,8 +62,6 @@ public final class V extends Globals { r_dlights[i] = new dlight_t(); for (int i = 0; i < r_entities.length; i++) r_entities[i] = new entity_t(); - for (int i = 0; i < r_particles.length; i++) - r_particles[i] = new particle_t(); for (int i = 0; i < r_lightstyles.length; i++) r_lightstyles[i] = new lightstyle_t(); } @@ -99,16 +98,20 @@ public final class V extends Globals { ===================== */ static void AddParticle(float[] org, int color, float alpha) { - particle_t p; - if (r_numparticles >= MAX_PARTICLES) return; - p = r_particles[r_numparticles++]; + int i = r_numparticles++; - VectorCopy(org, p.origin); - p.color = color; - p.alpha = alpha; + int c = particle_t.colorTable[color]; + c |= (int)(alpha * 255) << 24; + particle_t.colorArray.put(i, c); + + i *= 3; + FloatBuffer vertexBuf = particle_t.vertexArray; + vertexBuf.put(i++, org[0]); + vertexBuf.put(i++, org[1]); + vertexBuf.put(i++, org[2]); } /* @@ -158,26 +161,25 @@ public final class V extends Globals { ================ */ static void TestParticles() { - particle_t p; int i, j; float d, r, u; - r_numparticles = MAX_PARTICLES; - for (i = 0; i < r_numparticles; i++) { + float[] origin = {0,0,0}; + + r_numparticles = 0; + for (i = 0; i < MAX_PARTICLES; i++) { d = i * 0.25f; r = 4 * ((i & 7) - 3.5f); u = 4 * (((i >> 3) & 7) - 3.5f); - p = r_particles[i]; for (j = 0; j < 3; j++) - p.origin[j] = + origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j] * d + cl.v_right[j] * r + cl.v_up[j] * u; - p.color = 8; - p.alpha = cl_testparticles.value; + AddParticle(origin, 8, cl_testparticles.value); } } @@ -356,7 +358,6 @@ public final class V extends Globals { cl.refdef.num_entities = r_numentities; cl.refdef.entities = r_entities; cl.refdef.num_particles = r_numparticles; - cl.refdef.particles = r_particles; cl.refdef.num_dlights = r_numdlights; cl.refdef.dlights = r_dlights; cl.refdef.lightstyles = r_lightstyles; diff --git a/src/jake2/client/VID.java b/src/jake2/client/VID.java index 53a943f..b18683b 100644 --- a/src/jake2/client/VID.java +++ b/src/jake2/client/VID.java @@ -2,7 +2,7 @@ * VID.java * Copyright (C) 2003 * - * $Id: VID.java,v 1.4 2004-07-08 20:56:50 hzi Exp $ + * $Id: VID.java,v 1.5 2004-07-09 06:50:50 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -370,7 +370,7 @@ public class VID extends Globals { public static void Init() { /* Create the video variables so we know how to start the graphics drivers */ - vid_ref = Cvar.Get("vid_ref", "jogl", CVAR_ARCHIVE); + vid_ref = Cvar.Get("vid_ref", "fastjogl", CVAR_ARCHIVE); vid_xpos = Cvar.Get("vid_xpos", "3", CVAR_ARCHIVE); vid_ypos = Cvar.Get("vid_ypos", "22", CVAR_ARCHIVE); vid_fullscreen = Cvar.Get("vid_fullscreen", "0", CVAR_ARCHIVE); @@ -419,6 +419,7 @@ public class VID extends Globals { // #define REF_3DFXGL 3 // #define REF_OPENGLX 4 static final int REF_OPENGL_JOGL = 0; + static final int REF_OPENGL_FASTJOGL =1; // #define REF_MESA3DGLX 5 // extern cvar_t *vid_ref; @@ -605,6 +606,12 @@ public class VID extends Globals { if (gl_driver.modified) vid_ref.modified = true; break; + case REF_OPENGL_FASTJOGL : + Cvar.Set( "vid_ref", "fastjogl" ); + Cvar.Set( "gl_driver", "fastjogl" ); + if (gl_driver.modified) + vid_ref.modified = true; + break; } Menu.ForceMenuOff(); @@ -634,6 +641,7 @@ public class VID extends Globals { // "[OpenGL glX ]", // "[Mesa 3-D glX ]", "[OpenGL jogl ]", + "[OpenGL fastjogl]", null }; static final String[] yesno_names = @@ -686,6 +694,11 @@ public class VID extends Globals { s_current_menu_index = OPENGL_MENU; s_ref_list[0].curvalue = s_ref_list[1].curvalue = REF_OPENGL_JOGL; } + else if ( vid_ref.string.equalsIgnoreCase("fastjogl")) + { + s_current_menu_index = OPENGL_MENU; + s_ref_list[0].curvalue = s_ref_list[1].curvalue = REF_OPENGL_FASTJOGL; + } // else if (strcmp( vid_ref->string, "softx" ) == 0 ) // { // s_current_menu_index = SOFTWARE_MENU; diff --git a/src/jake2/client/client_state_t.java b/src/jake2/client/client_state_t.java index ff86070..11a3af7 100644 --- a/src/jake2/client/client_state_t.java +++ b/src/jake2/client/client_state_t.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 27.11.2003 by RST. -//$Id: client_state_t.java,v 1.2 2004-07-08 20:56:51 hzi Exp $ +//$Id: client_state_t.java,v 1.3 2004-07-09 06:50:50 hzi Exp $ package jake2.client; @@ -57,7 +57,7 @@ public class client_state_t { int timedemo_start; public boolean refresh_prepped; // false if on new level or new ref dll - boolean sound_prepped; // ambient sounds can start + public boolean sound_prepped; // ambient sounds can start boolean force_refdef; // vid has changed, so we can't use a paused refdef int parse_entities; // index (not anded off) into cl_parse_entities[] @@ -129,7 +129,7 @@ public class client_state_t { model_t model_draw[] = new model_t[Defines.MAX_MODELS]; cmodel_t model_clip[] = new cmodel_t[Defines.MAX_MODELS]; - sfx_t sound_precache[] = new sfx_t[Defines.MAX_SOUNDS]; + public sfx_t sound_precache[] = new sfx_t[Defines.MAX_SOUNDS]; image_t image_precache[] = new image_t[Defines.MAX_IMAGES]; clientinfo_t clientinfo[] = new clientinfo_t[Defines.MAX_CLIENTS]; diff --git a/src/jake2/client/frame_t.java b/src/jake2/client/frame_t.java index 1e414dc..a242217 100644 --- a/src/jake2/client/frame_t.java +++ b/src/jake2/client/frame_t.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 27.11.2003 by RST. -// $Id: frame_t.java,v 1.2 2004-07-08 20:56:50 hzi Exp $ +// $Id: frame_t.java,v 1.3 2004-07-09 06:50:50 hzi Exp $ package jake2.client; @@ -27,7 +27,7 @@ import jake2.game.player_state_t; import java.util.Arrays; -public class frame_t implements Cloneable { +public class frame_t { public static final int MAX_MAP_AREAS = 256; @@ -37,8 +37,8 @@ public class frame_t implements Cloneable { int deltaframe; byte areabits[] = new byte [MAX_MAP_AREAS/8]; // portalarea visibility bits public player_state_t playerstate = new player_state_t(); // mem - int num_entities; - int parse_entities; // non-masked index into cl_parse_entities array + public int num_entities; + public int parse_entities; // non-masked index into cl_parse_entities array public void set(frame_t from) { valid = from.valid; diff --git a/src/jake2/client/particle_t.java b/src/jake2/client/particle_t.java index 2127b5d..027cadf 100644 --- a/src/jake2/client/particle_t.java +++ b/src/jake2/client/particle_t.java @@ -19,12 +19,24 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 20.11.2003 by RST. -// $Id: particle_t.java,v 1.1 2004-07-07 19:58:52 hzi Exp $ +// $Id: particle_t.java,v 1.2 2004-07-09 06:50:50 hzi Exp $ package jake2.client; +import jake2.Defines; +import jake2.util.Lib; + +import java.nio.*; + public class particle_t { - public float origin[] = { 0, 0, 0 }; - public int color; - public float alpha; + + public static FloatBuffer vertexArray = Lib.newFloatBuffer(Defines.MAX_PARTICLES * 3); + public static IntBuffer colorArray = Lib.newIntBuffer(Defines.MAX_PARTICLES, ByteOrder.LITTLE_ENDIAN); + public static int[] colorTable = new int[256]; + + public static void setColorPalette(int[] palette) { + for (int i=0; i < 256; i++) { + colorTable[i] = palette[i] & 0x00FFFFFF; + } + } } diff --git a/src/jake2/client/refdef_t.java b/src/jake2/client/refdef_t.java index a01ab06..d5c6027 100644 --- a/src/jake2/client/refdef_t.java +++ b/src/jake2/client/refdef_t.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 20.11.2003 by RST. -// $Id: refdef_t.java,v 1.1 2004-07-07 19:58:52 hzi Exp $ +// $Id: refdef_t.java,v 1.2 2004-07-09 06:50:50 hzi Exp $ package jake2.client; @@ -43,5 +43,5 @@ public class refdef_t { public dlight_t dlights[]; public int num_particles; - public particle_t particles[]; + //public particle_t particles[]; } diff --git a/src/jake2/game/Cmd.java b/src/jake2/game/Cmd.java index bbb6742..a5a0a50 100644 --- a/src/jake2/game/Cmd.java +++ b/src/jake2/game/Cmd.java @@ -2,7 +2,7 @@ * Cmd.java * Copyright (C) 2003 * - * $Id: Cmd.java,v 1.2 2004-07-08 15:58:43 hzi Exp $ + * $Id: Cmd.java,v 1.3 2004-07-09 06:50:49 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -35,32 +35,40 @@ import java.util.Arrays; /** * Cmd */ -public final class Cmd extends PlayerView { +public final class Cmd extends PlayerView +{ - static xcommand_t List_f = new xcommand_t() { - public void execute() { - cmd_function_t cmd = Cmd.cmd_functions; - int i = 0; + static xcommand_t List_f= new xcommand_t() + { + public void execute() + { + cmd_function_t cmd= Cmd.cmd_functions; + int i= 0; - while (cmd != null) { + while (cmd != null) + { Com.Printf(cmd.name + '\n'); i++; - cmd = cmd.next; + cmd= cmd.next; } Com.Printf(i + " commands\n"); } }; - static xcommand_t Exec_f = new xcommand_t() { - public void execute() { - if (Cmd.Argc() != 2) { + static xcommand_t Exec_f= new xcommand_t() + { + public void execute() + { + if (Cmd.Argc() != 2) + { Com.Printf("exec <filename> : execute a script file\n"); return; } - byte[] f = null; - f = FS.LoadFile(Cmd.Argv(1)); - if (f == null) { + byte[] f= null; + f= FS.LoadFile(Cmd.Argv(1)); + if (f == null) + { Com.Printf("couldn't exec " + Cmd.Argv(1) + "\n"); return; } @@ -71,77 +79,93 @@ public final class Cmd extends PlayerView { FS.FreeFile(f); } }; - static xcommand_t Echo_f = new xcommand_t() { - public void execute() { - for (int i = 1; i < Cmd.Argc(); i++) { + + static xcommand_t Echo_f= new xcommand_t() + { + public void execute() + { + for (int i= 1; i < Cmd.Argc(); i++) + { Com.Printf(Cmd.Argv(i) + " "); } Com.Printf("'\n"); } }; - static xcommand_t Alias_f = new xcommand_t() { - public void execute() { - cmdalias_t a = null; - if (Cmd.Argc() == 1) { + static xcommand_t Alias_f= new xcommand_t() + { + public void execute() + { + cmdalias_t a= null; + if (Cmd.Argc() == 1) + { Com.Printf("Current alias commands:\n"); - for (a = Globals.cmd_alias; a != null; a = a.next) { + for (a= Globals.cmd_alias; a != null; a= a.next) + { Com.Printf(a.name + " : " + a.value); } return; } - String s = Cmd.Argv(1); - if (s.length() > Globals.MAX_ALIAS_NAME) { + String s= Cmd.Argv(1); + if (s.length() > Globals.MAX_ALIAS_NAME) + { Com.Printf("Alias name is too long\n"); return; } // if the alias already exists, reuse it - for (a = Globals.cmd_alias; a != null; a = a.next) { - if (s.equalsIgnoreCase(a.name)) { - a.value = null; + for (a= Globals.cmd_alias; a != null; a= a.next) + { + if (s.equalsIgnoreCase(a.name)) + { + a.value= null; break; } } - if (a == null) { - a = new cmdalias_t(); - a.next = Globals.cmd_alias; - Globals.cmd_alias = a; + if (a == null) + { + a= new cmdalias_t(); + a.next= Globals.cmd_alias; + Globals.cmd_alias= a; } - a.name = s; + a.name= s; // copy the rest of the command line - String cmd = ""; - int c = Cmd.Argc(); - for (int i = 2; i < c; i++) { - cmd = cmd + Cmd.Argv(i); + String cmd= ""; + int c= Cmd.Argc(); + for (int i= 2; i < c; i++) + { + cmd= cmd + Cmd.Argv(i); if (i != (c - 1)) - cmd = cmd + " "; + cmd= cmd + " "; } - cmd = cmd + "\n"; + cmd= cmd + "\n"; - a.value = cmd; + a.value= cmd; } }; - public static xcommand_t Wait_f = new xcommand_t() { - public void execute() { - Globals.cmd_wait = true; + public static xcommand_t Wait_f= new xcommand_t() + { + public void execute() + { + Globals.cmd_wait= true; } }; - public static cmd_function_t cmd_functions = null; + public static cmd_function_t cmd_functions= null; public static int cmd_argc; - public static String[] cmd_argv = new String[Globals.MAX_STRING_TOKENS]; + public static String[] cmd_argv= new String[Globals.MAX_STRING_TOKENS]; public static String cmd_args; - public static final int ALIAS_LOOP_COUNT = 16; + public static final int ALIAS_LOOP_COUNT= 16; /** * register our commands */ - public static void Init() { + public static void Init() + { Cmd.AddCommand("exec", Exec_f); Cmd.AddCommand("echo", Echo_f); @@ -150,34 +174,37 @@ public final class Cmd extends PlayerView { Cmd.AddCommand("wait", Wait_f); } - private static char expanded[] = new char[MAX_STRING_CHARS]; - private static char temporary[] = new char[MAX_STRING_CHARS]; + private static char expanded[]= new char[MAX_STRING_CHARS]; + private static char temporary[]= new char[MAX_STRING_CHARS]; /* ====================== Cmd_MacroExpandString ====================== */ - public static char[] MacroExpandString(char text[], int len) { + public static char[] MacroExpandString(char text[], int len) + { int i, j, count; boolean inquote; char scan[]; String token; - inquote = false; + inquote= false; - scan = text; + scan= text; - if (len >= MAX_STRING_CHARS) { + if (len >= MAX_STRING_CHARS) + { Com.Printf("Line exceeded " + MAX_STRING_CHARS + " chars, discarded.\n"); return null; } - count = 0; + count= 0; - for (i = 0; i < len; i++) { + for (i= 0; i < len; i++) + { if (scan[i] == '"') - inquote = !inquote; + inquote= !inquote; if (inquote) continue; // don't expand inside quotes @@ -186,19 +213,20 @@ public final class Cmd extends PlayerView { continue; // scan out the complete macro, without $ - Com.ParseHelp ph = new Com.ParseHelp(text, i + 1); - token = Com.Parse(ph); + Com.ParseHelp ph= new Com.ParseHelp(text, i + 1); + token= Com.Parse(ph); if (ph.data == null) continue; - token = Cvar.VariableString(token); + token= Cvar.VariableString(token); - j = token.length(); + j= token.length(); len += j; - if (len >= MAX_STRING_CHARS) { + if (len >= MAX_STRING_CHARS) + { Com.Printf("Expanded line exceeded " + MAX_STRING_CHARS + " chars, discarded.\n"); return null; } @@ -214,16 +242,18 @@ public final class Cmd extends PlayerView { //strcpy(expanded, temporary); System.arraycopy(temporary, 0, expanded, 0, 0); - scan = expanded; + scan= expanded; i--; - if (++count == 100) { + if (++count == 100) + { Com.Printf("Macro expansion loop, discarded.\n"); return null; } } - if (inquote) { + if (inquote) + { Com.Printf("Line has unmatched quote, discarded.\n"); return null; } @@ -239,31 +269,34 @@ public final class Cmd extends PlayerView { $Cvars will be expanded unless they are in a quoted token ============ */ - public static void TokenizeString(char text[], boolean macroExpand) { + public static void TokenizeString(char text[], boolean macroExpand) + { String com_token; - cmd_argc = 0; + cmd_argc= 0; - int len = strlen(text); + int len= strlen(text); // macro expand the text if (macroExpand) - text = MacroExpandString(text, len); + text= MacroExpandString(text, len); if (text == null) return; - len = strlen(text); + len= strlen(text); - Com.ParseHelp ph = new Com.ParseHelp(text); + Com.ParseHelp ph= new Com.ParseHelp(text); - while (true) { + while (true) + { // skip whitespace up to a /n - char c = ph.skipwhitestoeol(); + char c= ph.skipwhitestoeol(); - if (c == '\n') { // a newline seperates commands in the buffer - c = ph.nextchar(); + if (c == '\n') + { // a newline seperates commands in the buffer + c= ph.nextchar(); break; } @@ -271,46 +304,52 @@ public final class Cmd extends PlayerView { return; // set cmd_args to everything after the first arg - if (cmd_argc == 1) { - cmd_args = new String(text, ph.index, len - ph.index); + if (cmd_argc == 1) + { + cmd_args= new String(text, ph.index, len - ph.index); cmd_args.trim(); } - com_token = Com.Parse(ph); + com_token= Com.Parse(ph); if (com_token.length() == 0) return; - if (cmd_argc < MAX_STRING_TOKENS) { - cmd_argv[cmd_argc] = com_token; + if (cmd_argc < MAX_STRING_TOKENS) + { + cmd_argv[cmd_argc]= com_token; cmd_argc++; } } } - public static void AddCommand(String cmd_name, xcommand_t function) { + public static void AddCommand(String cmd_name, xcommand_t function) + { cmd_function_t cmd; //Com.DPrintf("Cmd_AddCommand: " + cmd_name + "\n"); // fail if the command is a variable name - if ((Cvar.VariableString(cmd_name)).length() > 0) { + if ((Cvar.VariableString(cmd_name)).length() > 0) + { Com.Printf("Cmd_AddCommand: " + cmd_name + " already defined as a var\n"); return; } // fail if the command already exists - for (cmd = cmd_functions; cmd != null; cmd = cmd.next) { - if (cmd_name.equals(cmd.name)) { + for (cmd= cmd_functions; cmd != null; cmd= cmd.next) + { + if (cmd_name.equals(cmd.name)) + { Com.Printf("Cmd_AddCommand: " + cmd_name + " already defined\n"); return; } } - cmd = new cmd_function_t(); - cmd.name = cmd_name; - - cmd.function = function; - cmd.next = cmd_functions; - cmd_functions = cmd; + cmd= new cmd_function_t(); + cmd.name= cmd_name; + + cmd.function= function; + cmd.next= cmd_functions; + cmd_functions= cmd; } /* @@ -318,26 +357,30 @@ public final class Cmd extends PlayerView { Cmd_RemoveCommand ============ */ - public static void RemoveCommand(String cmd_name) { - cmd_function_t cmd, back = null; + public static void RemoveCommand(String cmd_name) + { + cmd_function_t cmd, back= null; - back = cmd = cmd_functions; + back= cmd= cmd_functions; - while (true) { + while (true) + { - if (cmd == null) { + if (cmd == null) + { Com.Printf("Cmd_RemoveCommand: " + cmd_name + " not added\n"); return; } - if (0 == strcmp(cmd_name, cmd.name)) { + if (0 == strcmp(cmd_name, cmd.name)) + { if (cmd == cmd_functions) - cmd_functions = cmd.next; + cmd_functions= cmd.next; else - back.next = cmd.next; + back.next= cmd.next; return; } - back = cmd; - cmd = cmd.next; + back= cmd; + cmd= cmd.next; } } @@ -346,10 +389,12 @@ public final class Cmd extends PlayerView { Cmd_Exists ============ */ - public static boolean Exists(String cmd_name) { + public static boolean Exists(String cmd_name) + { cmd_function_t cmd; - for (cmd = cmd_functions; cmd != null; cmd = cmd.next) { + for (cmd= cmd_functions; cmd != null; cmd= cmd.next) + { if (0 == strcmp(cmd_name, cmd.name)) return true; } @@ -357,17 +402,20 @@ public final class Cmd extends PlayerView { return false; } - public static int Argc() { + public static int Argc() + { return cmd_argc; } - public static String Argv(int i) { + public static String Argv(int i) + { if (i < 0 || i >= cmd_argc) return ""; return cmd_argv[i]; } - public static String Args() { + public static String Args() + { return new String(cmd_args); } @@ -379,48 +427,49 @@ public final class Cmd extends PlayerView { FIXME: lookupnoadd the token to speed search? ============ */ - public static void ExecuteString(String text) { + public static void ExecuteString(String text) + { cmd_function_t cmd; cmdalias_t a; TokenizeString(text.toCharArray(), true); -// if (Argc() > 0) { -// Com.DPrintf("tokenized:"); -// for (int xxx = 0; xxx < Argc(); xxx++) -// Com.DPrintf("[" + Argv(xxx) + "]"); -// -// Com.DPrintf("\n"); -// } + // if (Argc() > 0) { + // Com.DPrintf("tokenized:"); + // for (int xxx = 0; xxx < Argc(); xxx++) + // Com.DPrintf("[" + Argv(xxx) + "]"); + // + // Com.DPrintf("\n"); + // } // execute the command line if (Argc() == 0) return; // no tokens // check functions - for (cmd = cmd_functions; cmd != null; cmd = cmd.next) { - if (cmd_argv[0].equalsIgnoreCase(cmd.name)) { - if (null == cmd.function) { // forward to server command + for (cmd= cmd_functions; cmd != null; cmd= cmd.next) + { + if (cmd_argv[0].equalsIgnoreCase(cmd.name)) + { + if (null == cmd.function) + { // forward to server command Cmd.ExecuteString("cmd " + text); + } else { + cmd.function.execute(); } - else - try { - cmd.function.execute(); - } - catch (Exception e) { - System.err.println("Exception in executing a command " + cmd.name + ":"); - e.printStackTrace(); - } return; } } // check alias - for (a = cmd_alias; a != null; a = a.next) { + for (a= cmd_alias; a != null; a= a.next) + { - if (cmd_argv[0].equalsIgnoreCase(a.name)) { + if (cmd_argv[0].equalsIgnoreCase(a.name)) + { - if (++alias_count == ALIAS_LOOP_COUNT) { + if (++alias_count == ALIAS_LOOP_COUNT) + { Com.Printf("ALIAS_LOOP_COUNT\n"); return; } @@ -444,7 +493,8 @@ public final class Cmd extends PlayerView { Give items to a client ================== */ - public static void Give_f(edict_t ent) { + public static void Give_f(edict_t ent) + { String name; gitem_t it; int index; @@ -452,30 +502,34 @@ public final class Cmd extends PlayerView { boolean give_all; edict_t it_ent; - if (GameBase.deathmatch.value == 0 && GameBase.sv_cheats.value == 0) { + if (GameBase.deathmatch.value == 0 && GameBase.sv_cheats.value == 0) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } - name = GameBase.gi.args(); + name= GameBase.gi.args(); if (0 == Lib.Q_stricmp(name, "all")) - give_all = true; + give_all= true; else - give_all = false; + give_all= false; - if (give_all || 0 == Lib.Q_stricmp(GameBase.gi.argv(1), "health")) { + if (give_all || 0 == Lib.Q_stricmp(GameBase.gi.argv(1), "health")) + { if (GameBase.gi.argc() == 3) - ent.health = Lib.atoi(GameBase.gi.argv(2)); + ent.health= Lib.atoi(GameBase.gi.argv(2)); else - ent.health = ent.max_health; + ent.health= ent.max_health; if (!give_all) return; } - if (give_all || 0 == Lib.Q_stricmp(name, "weapons")) { - for (i = 1; i < GameBase.game.num_items; i++) { - it = GameAI.itemlist[i]; + if (give_all || 0 == Lib.Q_stricmp(name, "weapons")) + { + for (i= 1; i < GameBase.game.num_items; i++) + { + it= GameAI.itemlist[i]; if (null == it.pickup) continue; if (0 == (it.flags & Defines.IT_WEAPON)) @@ -486,9 +540,11 @@ public final class Cmd extends PlayerView { return; } - if (give_all || 0 == Lib.Q_stricmp(name, "ammo")) { - for (i = 1; i < GameBase.game.num_items; i++) { - it = GameAI.itemlist[i]; + if (give_all || 0 == Lib.Q_stricmp(name, "ammo")) + { + for (i= 1; i < GameBase.game.num_items; i++) + { + it= GameAI.itemlist[i]; if (null == it.pickup) continue; if (0 == (it.flags & Defines.IT_AMMO)) @@ -499,27 +555,29 @@ public final class Cmd extends PlayerView { return; } - if (give_all || Lib.Q_stricmp(name, "armor") == 0) { + if (give_all || Lib.Q_stricmp(name, "armor") == 0) + { gitem_armor_t info; - it = GameUtil.FindItem("Jacket Armor"); - ent.client.pers.inventory[GameUtil.ITEM_INDEX(it)] = 0; + it= GameUtil.FindItem("Jacket Armor"); + ent.client.pers.inventory[GameUtil.ITEM_INDEX(it)]= 0; - it = GameUtil.FindItem("Combat Armor"); - ent.client.pers.inventory[GameUtil.ITEM_INDEX(it)] = 0; + it= GameUtil.FindItem("Combat Armor"); + ent.client.pers.inventory[GameUtil.ITEM_INDEX(it)]= 0; - it = GameUtil.FindItem("Body Armor"); - info = (gitem_armor_t) it.info; - ent.client.pers.inventory[GameUtil.ITEM_INDEX(it)] = info.max_count; + it= GameUtil.FindItem("Body Armor"); + info= (gitem_armor_t) it.info; + ent.client.pers.inventory[GameUtil.ITEM_INDEX(it)]= info.max_count; if (!give_all) return; } - if (give_all || Lib.Q_stricmp(name, "Power Shield") == 0) { - it = GameUtil.FindItem("Power Shield"); - it_ent = GameUtil.G_Spawn(); - it_ent.classname = it.classname; + if (give_all || Lib.Q_stricmp(name, "Power Shield") == 0) + { + it= GameUtil.FindItem("Power Shield"); + it_ent= GameUtil.G_Spawn(); + it_ent.classname= it.classname; GameAI.SpawnItem(it_ent, it); GameAI.Touch_Item(it_ent, ent, GameBase.dummyplane, null); if (it_ent.inuse) @@ -529,44 +587,51 @@ public final class Cmd extends PlayerView { return; } - if (give_all) { - for (i = 1; i < GameBase.game.num_items; i++) { - it = GameAI.itemlist[i]; + if (give_all) + { + for (i= 1; i < GameBase.game.num_items; i++) + { + it= GameAI.itemlist[i]; if (it.pickup != null) continue; if ((it.flags & (Defines.IT_ARMOR | Defines.IT_WEAPON | Defines.IT_AMMO)) != 0) continue; - ent.client.pers.inventory[i] = 1; + ent.client.pers.inventory[i]= 1; } return; } - it = GameUtil.FindItem(name); - if (it == null) { - name = GameBase.gi.argv(1); - it = GameUtil.FindItem(name); - if (it == null) { + it= GameUtil.FindItem(name); + if (it == null) + { + name= GameBase.gi.argv(1); + it= GameUtil.FindItem(name); + if (it == null) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "unknown item\n"); return; } } - if (it.pickup == null) { + if (it.pickup == null) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "non-pickup item\n"); return; } - index = GameUtil.ITEM_INDEX(it); + index= GameUtil.ITEM_INDEX(it); - if ((it.flags & Defines.IT_AMMO) != 0) { + if ((it.flags & Defines.IT_AMMO) != 0) + { if (GameBase.gi.argc() == 3) - ent.client.pers.inventory[index] = Lib.atoi(GameBase.gi.argv(2)); + ent.client.pers.inventory[index]= Lib.atoi(GameBase.gi.argv(2)); else ent.client.pers.inventory[index] += it.quantity; } - else { - it_ent = GameUtil.G_Spawn(); - it_ent.classname = it.classname; + else + { + it_ent= GameUtil.G_Spawn(); + it_ent.classname= it.classname; GameAI.SpawnItem(it_ent, it); GameAI.Touch_Item(it_ent, ent, GameBase.dummyplane, null); if (it_ent.inuse) @@ -583,19 +648,21 @@ public final class Cmd extends PlayerView { argv(0) god ================== */ - public static void God_f(edict_t ent) { + public static void God_f(edict_t ent) + { String msg; - if (GameBase.deathmatch.value == 0 && GameBase.sv_cheats.value == 0) { + if (GameBase.deathmatch.value == 0 && GameBase.sv_cheats.value == 0) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } ent.flags ^= Defines.FL_GODMODE; if (0 == (ent.flags & Defines.FL_GODMODE)) - msg = "godmode OFF\n"; + msg= "godmode OFF\n"; else - msg = "godmode ON\n"; + msg= "godmode ON\n"; GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, msg); } @@ -609,19 +676,21 @@ public final class Cmd extends PlayerView { argv(0) notarget ================== */ - public static void Notarget_f(edict_t ent) { + public static void Notarget_f(edict_t ent) + { String msg; - if (GameBase.deathmatch.value != 0 && GameBase.sv_cheats.value == 0) { + if (GameBase.deathmatch.value != 0 && GameBase.sv_cheats.value == 0) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } ent.flags ^= Defines.FL_NOTARGET; if (0 == (ent.flags & Defines.FL_NOTARGET)) - msg = "notarget OFF\n"; + msg= "notarget OFF\n"; else - msg = "notarget ON\n"; + msg= "notarget ON\n"; GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, msg); } @@ -633,21 +702,25 @@ public final class Cmd extends PlayerView { argv(0) noclip ================== */ - public static void Noclip_f(edict_t ent) { + public static void Noclip_f(edict_t ent) + { String msg; - if (GameBase.deathmatch.value != 0 && GameBase.sv_cheats.value == 0) { + if (GameBase.deathmatch.value != 0 && GameBase.sv_cheats.value == 0) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } - if (ent.movetype == Defines.MOVETYPE_NOCLIP) { - ent.movetype = Defines.MOVETYPE_WALK; - msg = "noclip OFF\n"; + if (ent.movetype == Defines.MOVETYPE_NOCLIP) + { + ent.movetype= Defines.MOVETYPE_WALK; + msg= "noclip OFF\n"; } - else { - ent.movetype = Defines.MOVETYPE_NOCLIP; - msg = "noclip ON\n"; + else + { + ent.movetype= Defines.MOVETYPE_NOCLIP; + msg= "noclip ON\n"; } GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, msg); @@ -660,23 +733,27 @@ public final class Cmd extends PlayerView { Use an inventory item ================== */ - public static void Use_f(edict_t ent) { + public static void Use_f(edict_t ent) + { int index; gitem_t it; String s; - s = GameBase.gi.args(); - it = GameUtil.FindItem(s); - if (it == null) { + s= GameBase.gi.args(); + it= GameUtil.FindItem(s); + if (it == null) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "unknown item: " + s + "\n"); return; } - if (it.use == null) { + if (it.use == null) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "Item is not usable.\n"); return; } - index = GameUtil.ITEM_INDEX(it); - if (0 == ent.client.pers.inventory[index]) { + index= GameUtil.ITEM_INDEX(it); + if (0 == ent.client.pers.inventory[index]) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "Out of item: " + s + "\n"); return; } @@ -691,23 +768,27 @@ public final class Cmd extends PlayerView { Drop an inventory item ================== */ - public static void Drop_f(edict_t ent) { + public static void Drop_f(edict_t ent) + { int index; gitem_t it; String s; - s = GameBase.gi.args(); - it = GameUtil.FindItem(s); - if (it == null) { + s= GameBase.gi.args(); + it= GameUtil.FindItem(s); + if (it == null) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "unknown item: " + s + "\n"); return; } - if (it.drop == null) { + if (it.drop == null) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "Item is not dropable.\n"); return; } - index = GameUtil.ITEM_INDEX(it); - if (0 == ent.client.pers.inventory[index]) { + index= GameUtil.ITEM_INDEX(it); + if (0 == ent.client.pers.inventory[index]) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "Out of item: " + s + "\n"); return; } @@ -720,24 +801,27 @@ public final class Cmd extends PlayerView { Cmd_Inven_f ================= */ - public static void Inven_f(edict_t ent) { + public static void Inven_f(edict_t ent) + { int i; gclient_t cl; - cl = ent.client; + cl= ent.client; - cl.showscores = false; - cl.showhelp = false; + cl.showscores= false; + cl.showhelp= false; - if (cl.showinventory) { - cl.showinventory = false; + if (cl.showinventory) + { + cl.showinventory= false; return; } - cl.showinventory = true; + cl.showinventory= true; GameBase.gi.WriteByte(Defines.svc_inventory); - for (i = 0; i < Defines.MAX_ITEMS; i++) { + for (i= 0; i < Defines.MAX_ITEMS; i++) + { GameBase.gi.WriteShort(cl.pers.inventory[i]); } GameBase.gi.unicast(ent, true); @@ -748,18 +832,21 @@ public final class Cmd extends PlayerView { Cmd_InvUse_f ================= */ - public static void InvUse_f(edict_t ent) { + public static void InvUse_f(edict_t ent) + { gitem_t it; GameAI.ValidateSelectedItem(ent); - if (ent.client.pers.selected_item == -1) { + if (ent.client.pers.selected_item == -1) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "No item to use.\n"); return; } - it = GameAI.itemlist[ent.client.pers.selected_item]; - if (it.use == null) { + it= GameAI.itemlist[ent.client.pers.selected_item]; + if (it.use == null) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "Item is not usable.\n"); return; } @@ -771,26 +858,28 @@ public final class Cmd extends PlayerView { Cmd_WeapPrev_f ================= */ - public static void WeapPrev_f(edict_t ent) { + public static void WeapPrev_f(edict_t ent) + { gclient_t cl; int i, index; gitem_t it; int selected_weapon; - cl = ent.client; + cl= ent.client; if (cl.pers.weapon == null) return; - selected_weapon = GameUtil.ITEM_INDEX(cl.pers.weapon); + selected_weapon= GameUtil.ITEM_INDEX(cl.pers.weapon); // scan for the next valid one - for (i = 1; i <= Defines.MAX_ITEMS; i++) { - index = (selected_weapon + i) % Defines.MAX_ITEMS; + for (i= 1; i <= Defines.MAX_ITEMS; i++) + { + index= (selected_weapon + i) % Defines.MAX_ITEMS; if (0 == cl.pers.inventory[index]) continue; - it = GameAI.itemlist[index]; + it= GameAI.itemlist[index]; if (it.use == null) continue; @@ -807,27 +896,30 @@ public final class Cmd extends PlayerView { Cmd_WeapNext_f ================= */ - public static void WeapNext_f(edict_t ent) { + public static void WeapNext_f(edict_t ent) + { gclient_t cl; int i, index; gitem_t it; int selected_weapon; - cl = ent.client; + cl= ent.client; if (null == cl.pers.weapon) return; - selected_weapon = GameUtil.ITEM_INDEX(cl.pers.weapon); + selected_weapon= GameUtil.ITEM_INDEX(cl.pers.weapon); // scan for the next valid one - for (i = 1; i <= Defines.MAX_ITEMS; i++) { - index = (selected_weapon + Defines.MAX_ITEMS - i) % Defines.MAX_ITEMS; + for (i= 1; i <= Defines.MAX_ITEMS; i++) + { + index= (selected_weapon + Defines.MAX_ITEMS - i) % Defines.MAX_ITEMS; //bugfix rst - if (index == 0) index++; + if (index == 0) + index++; if (0 == cl.pers.inventory[index]) continue; - it = GameAI.itemlist[index]; + it= GameAI.itemlist[index]; if (null == it.use) continue; if (0 == (it.flags & Defines.IT_WEAPON)) @@ -843,20 +935,21 @@ public final class Cmd extends PlayerView { Cmd_WeapLast_f ================= */ - public static void WeapLast_f(edict_t ent) { + public static void WeapLast_f(edict_t ent) + { gclient_t cl; int index; gitem_t it; - cl = ent.client; + cl= ent.client; if (null == cl.pers.weapon || null == cl.pers.lastweapon) return; - index = GameUtil.ITEM_INDEX(cl.pers.lastweapon); + index= GameUtil.ITEM_INDEX(cl.pers.lastweapon); if (0 == cl.pers.inventory[index]) return; - it = GameAI.itemlist[index]; + it= GameAI.itemlist[index]; if (null == it.use) return; if (0 == (it.flags & Defines.IT_WEAPON)) @@ -869,18 +962,21 @@ public final class Cmd extends PlayerView { Cmd_InvDrop_f ================= */ - public static void InvDrop_f(edict_t ent) { + public static void InvDrop_f(edict_t ent) + { gitem_t it; GameAI.ValidateSelectedItem(ent); - if (ent.client.pers.selected_item == -1) { + if (ent.client.pers.selected_item == -1) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "No item to drop.\n"); return; } - it = GameAI.itemlist[ent.client.pers.selected_item]; - if (it.drop == null) { + it= GameAI.itemlist[ent.client.pers.selected_item]; + if (it.drop == null) + { GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "Item is not dropable.\n"); return; } @@ -894,19 +990,21 @@ public final class Cmd extends PlayerView { Display the scoreboard ================== */ - public static void Score_f(edict_t ent) { - ent.client.showinventory = false; - ent.client.showhelp = false; + public static void Score_f(edict_t ent) + { + ent.client.showinventory= false; + ent.client.showhelp= false; if (0 == GameBase.deathmatch.value && 0 == GameBase.coop.value) return; - if (ent.client.showscores) { - ent.client.showscores = false; + if (ent.client.showscores) + { + ent.client.showscores= false; return; } - ent.client.showscores = true; + ent.client.showscores= true; GameAI.DeathmatchScoreboard(ent); } @@ -917,23 +1015,26 @@ public final class Cmd extends PlayerView { Display the current help message ================== */ - public static void Help_f(edict_t ent) { + public static void Help_f(edict_t ent) + { // this is for backwards compatability - if (GameBase.deathmatch.value != 0) { + if (GameBase.deathmatch.value != 0) + { Score_f(ent); return; } - ent.client.showinventory = false; - ent.client.showscores = false; + ent.client.showinventory= false; + ent.client.showscores= false; - if (ent.client.showhelp && (ent.client.pers.game_helpchanged == GameBase.game.helpchanged)) { - ent.client.showhelp = false; + if (ent.client.showhelp && (ent.client.pers.game_helpchanged == GameBase.game.helpchanged)) + { + ent.client.showhelp= false; return; } - ent.client.showhelp = true; - ent.client.pers.helpchanged = 0; + ent.client.showhelp= true; + ent.client.pers.helpchanged= 0; GameAI.HelpComputer(ent); } @@ -944,12 +1045,13 @@ public final class Cmd extends PlayerView { Cmd_Kill_f ================= */ - public static void Kill_f(edict_t ent) { + public static void Kill_f(edict_t ent) + { if ((GameBase.level.time - ent.client.respawn_time) < 5) return; ent.flags &= ~Defines.FL_GODMODE; - ent.health = 0; - GameBase.meansOfDeath = Defines.MOD_SUICIDE; + ent.health= 0; + GameBase.meansOfDeath= Defines.MOD_SUICIDE; GameAIAdapters.player_die.die(ent, ent, ent, 100000, GameBase.vec3_origin); } @@ -958,10 +1060,11 @@ public final class Cmd extends PlayerView { Cmd_PutAway_f ================= */ - public static void PutAway_f(edict_t ent) { - ent.client.showscores = false; - ent.client.showhelp = false; - ent.client.showinventory = false; + public static void PutAway_f(edict_t ent) + { + ent.client.showscores= false; + ent.client.showhelp= false; + ent.client.showinventory= false; } @@ -970,18 +1073,21 @@ public final class Cmd extends PlayerView { Cmd_Players_f ================= */ - public static void Players_f(edict_t ent) { + public static void Players_f(edict_t ent) + { int i; int count; String small; String large; - Integer index[] = new Integer[256]; + Integer index[]= new Integer[256]; - count = 0; - for (i = 0; i < GameBase.maxclients.value; i++) { - if (GameBase.game.clients[i].pers.connected) { - index[count] = new Integer(i); + count= 0; + for (i= 0; i < GameBase.maxclients.value; i++) + { + if (GameBase.game.clients[i].pers.connected) + { + index[count]= new Integer(i); count++; } } @@ -992,16 +1098,18 @@ public final class Cmd extends PlayerView { Arrays.sort(index, 0, count - 1, GameAIAdapters.PlayerSort); // print information - large = ""; + large= ""; - for (i = 0; i < count; i++) { - small = + for (i= 0; i < count; i++) + { + small= GameBase.game.clients[index[i].intValue()].ps.stats[Defines.STAT_FRAGS] + " " + GameBase.game.clients[index[i].intValue()].pers.netname + "\n"; - if (small.length() + large.length() > 1024 - 100) { + if (small.length() + large.length() > 1024 - 100) + { // can't print all of them in one packet large += "...\n"; break; @@ -1017,10 +1125,11 @@ public final class Cmd extends PlayerView { Cmd_Wave_f ================= */ - public static void Wave_f(edict_t ent) { + public static void Wave_f(edict_t ent) + { int i; - i = Lib.atoi(GameBase.gi.argv(1)); + i= Lib.atoi(GameBase.gi.argv(1)); // can't wave when ducked if ((ent.client.ps.pmove.pm_flags & Defines.PMF_DUCKED) != 0) @@ -1029,34 +1138,35 @@ public final class Cmd extends PlayerView { if (ent.client.anim_priority > Defines.ANIM_WAVE) return; - ent.client.anim_priority = Defines.ANIM_WAVE; + ent.client.anim_priority= Defines.ANIM_WAVE; - switch (i) { + switch (i) + { case 0 : GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "flipoff\n"); - ent.s.frame = M_Player.FRAME_flip01 - 1; - ent.client.anim_end = M_Player.FRAME_flip12; + ent.s.frame= M_Player.FRAME_flip01 - 1; + ent.client.anim_end= M_Player.FRAME_flip12; break; case 1 : GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "salute\n"); - ent.s.frame = M_Player.FRAME_salute01 - 1; - ent.client.anim_end = M_Player.FRAME_salute11; + ent.s.frame= M_Player.FRAME_salute01 - 1; + ent.client.anim_end= M_Player.FRAME_salute11; break; case 2 : GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "taunt\n"); - ent.s.frame = M_Player.FRAME_taunt01 - 1; - ent.client.anim_end = M_Player.FRAME_taunt17; + ent.s.frame= M_Player.FRAME_taunt01 - 1; + ent.client.anim_end= M_Player.FRAME_taunt17; break; case 3 : GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "wave\n"); - ent.s.frame = M_Player.FRAME_wave01 - 1; - ent.client.anim_end = M_Player.FRAME_wave11; + ent.s.frame= M_Player.FRAME_wave01 - 1; + ent.client.anim_end= M_Player.FRAME_wave11; break; case 4 : default : GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "point\n"); - ent.s.frame = M_Player.FRAME_point01 - 1; - ent.client.anim_end = M_Player.FRAME_point12; + ent.s.frame= M_Player.FRAME_point01 - 1; + ent.client.anim_end= M_Player.FRAME_point12; break; } } @@ -1066,7 +1176,8 @@ public final class Cmd extends PlayerView { Cmd_Say_f ================== */ - public static void Say_f(edict_t ent, boolean team, boolean arg0) { + public static void Say_f(edict_t ent, boolean team, boolean arg0) + { int i, j; edict_t other; @@ -1077,19 +1188,21 @@ public final class Cmd extends PlayerView { return; if (0 == ((int) (dmflags.value) & (DF_MODELTEAMS | DF_SKINTEAMS))) - team = false; + team= false; if (team) - text = "(" + ent.client.pers.netname + "): "; + text= "(" + ent.client.pers.netname + "): "; else - text = "" + ent.client.pers.netname + ": "; + text= "" + ent.client.pers.netname + ": "; - if (arg0) { + if (arg0) + { strcat(text, gi.argv(0)); strcat(text, " "); strcat(text, gi.args()); } - else { + else + { if (gi.args().startsWith("\"")) text += gi.args().substring(1, gi.args().length() - 1); else @@ -1109,41 +1222,46 @@ public final class Cmd extends PlayerView { // don't let text be too long for malicious reasons if (text.length() > 150) //text[150] = 0; - text = text.substring(0, 150); + text= text.substring(0, 150); strcat(text, "\n"); - if (flood_msgs.value != 0) { - cl = ent.client; + if (flood_msgs.value != 0) + { + cl= ent.client; - if (level.time < cl.flood_locktill) { + if (level.time < cl.flood_locktill) + { gi.cprintf(ent, PRINT_HIGH, "You can't talk for " + (int) (cl.flood_locktill - level.time) + " more seconds\n"); return; } - i = (int) (cl.flood_whenhead - flood_msgs.value + 1); + i= (int) (cl.flood_whenhead - flood_msgs.value + 1); if (i < 0) //i = (sizeof(cl.flood_when) / sizeof(cl.flood_when[0])) + i; - i = (10) + i; - if (cl.flood_when[i] != 0 && level.time - cl.flood_when[i] < flood_persecond.value) { - cl.flood_locktill = level.time + flood_waitdelay.value; + i= (10) + i; + if (cl.flood_when[i] != 0 && level.time - cl.flood_when[i] < flood_persecond.value) + { + cl.flood_locktill= level.time + flood_waitdelay.value; gi.cprintf(ent, PRINT_CHAT, "Flood protection: You can't talk for " + (int) flood_waitdelay.value + " seconds.\n"); return; } //cl.flood_whenhead = (cl.flood_whenhead + 1) % (sizeof(cl.flood_when) / sizeof(cl.flood_when[0])); - cl.flood_whenhead = (cl.flood_whenhead + 1) % 10; - cl.flood_when[cl.flood_whenhead] = level.time; + cl.flood_whenhead= (cl.flood_whenhead + 1) % 10; + cl.flood_when[cl.flood_whenhead]= level.time; } if (dedicated.value != 0) gi.cprintf(null, PRINT_CHAT, "" + text + ""); - for (j = 1; j <= game.maxclients; j++) { - other = g_edicts[j]; + for (j= 1; j <= game.maxclients; j++) + { + other= g_edicts[j]; if (!other.inuse) continue; if (other.client == null) continue; - if (team) { + if (team) + { if (!OnSameTeam(ent, other)) continue; } @@ -1154,23 +1272,25 @@ public final class Cmd extends PlayerView { /** * Returns the playerlist. - * TODO: The list is badly formatted at the moment, RST. + * TODO: The list is badly formatted at the moment. */ - public static void PlayerList_f(edict_t ent) { + public static void PlayerList_f(edict_t ent) + { int i; String st; String text; edict_t e2; // connect time, ping, score, name - text = ""; + text= ""; - for (i = 0; i < GameBase.maxclients.value; i++) { - e2 = GameBase.g_edicts[1 + i]; + for (i= 0; i < GameBase.maxclients.value; i++) + { + e2= GameBase.g_edicts[1 + i]; if (!e2.inuse) continue; - st = + st= "" + (GameBase.level.framenum - e2.client.resp.enterframe) / 600 + ":" @@ -1185,7 +1305,8 @@ public final class Cmd extends PlayerView { + (e2.client.resp.spectator ? " (spectator)" : "") + "\n"; - if (text.length() + st.length() > 1024 - 50) { + if (text.length() + st.length() > 1024 - 50) + { text += "And more...\n"; GameBase.gi.cprintf(ent, Defines.PRINT_HIGH, "" + text + ""); return; @@ -1196,7 +1317,7 @@ public final class Cmd extends PlayerView { } // ====================================================================== - + /* =================== Cmd_ForwardToServer @@ -1206,18 +1327,21 @@ public final class Cmd extends PlayerView { so when they are typed in at the console, they will need to be forwarded. =================== */ - public static void ForwardToServer() { + public static void ForwardToServer() + { String cmd; - - cmd = Cmd.Argv(0); - if (Globals.cls.state <= Defines.ca_connected || cmd.charAt(0) == '-' || cmd.charAt(0) == '+') { + + cmd= Cmd.Argv(0); + if (Globals.cls.state <= Defines.ca_connected || cmd.charAt(0) == '-' || cmd.charAt(0) == '+') + { Com.Printf("Unknown command \"" + cmd + "\"\n"); return; } - + MSG.WriteByte(Globals.cls.netchan.message, Defines.clc_stringcmd); SZ.Print(Globals.cls.netchan.message, cmd); - if (Cmd.Argc() > 1) { + if (Cmd.Argc() > 1) + { SZ.Print(Globals.cls.netchan.message, " "); SZ.Print(Globals.cls.netchan.message, Cmd.Args()); } diff --git a/src/jake2/game/GameBase.java b/src/jake2/game/GameBase.java index ef1e1c9..871e084 100644 --- a/src/jake2/game/GameBase.java +++ b/src/jake2/game/GameBase.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 30.11.2003 by RST. -// $Id: GameBase.java,v 1.2 2004-07-08 15:58:44 hzi Exp $ +// $Id: GameBase.java,v 1.3 2004-07-09 06:50:49 hzi Exp $ /** Father of all Objects. */ @@ -817,24 +817,8 @@ public class GameBase extends Globals continue; } - //TODO: RST: disabled for debugging; - //if (!ent.classname.startsWith("monster") || ent.index == 312) - G_RunEntity(ent); - - // if (ent == g_edicts[307]) - // G_RunEntity(ent); - // else if (ent == g_edicts[1]) - // G_RunEntity(ent); - // - // else if (true) - // if (ent.classname.startsWith("monster") - // || ent.classname.startsWith("trigger") - // || ent.classname.startsWith("target") - // || ent.classname.startsWith( - // "misc_explo") //ent.classname.startsWith("func_door") - // ) //|| ent.classname.startsWith("monster")) - // G_RunEntity(ent); + G_RunEntity(ent); } // see if it is time to end a deathmatch diff --git a/src/jake2/game/GameFunc.java b/src/jake2/game/GameFunc.java index 8860b00..091056f 100644 --- a/src/jake2/game/GameFunc.java +++ b/src/jake2/game/GameFunc.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 18.11.2003 by RST. -// $Id: GameFunc.java,v 1.2 2004-07-08 15:58:44 hzi Exp $ +// $Id: GameFunc.java,v 1.3 2004-07-09 06:50:49 hzi Exp $ package jake2.game; @@ -38,9 +38,6 @@ public class GameFunc extends PlayerView Math3D.VectorSubtract(dest, ent.s.origin, ent.moveinfo.dir); ent.moveinfo.remaining_distance = Math3D.VectorNormalize(ent.moveinfo.dir); - //TODO: BIG HACK !!! - if (ent.moveinfo.remaining_distance == 2) - ent.moveinfo.remaining_distance = 94; ent.moveinfo.endfunc = func; if (ent.moveinfo.speed == ent.moveinfo.accel && ent.moveinfo.speed == ent.moveinfo.decel) diff --git a/src/jake2/game/GameSVCmds.java b/src/jake2/game/GameSVCmds.java index dc0b4f9..1d1c244 100644 --- a/src/jake2/game/GameSVCmds.java +++ b/src/jake2/game/GameSVCmds.java @@ -19,22 +19,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 01.02.2004 by RST. -// $Id: GameSVCmds.java,v 1.1 2004-07-07 19:59:00 hzi Exp $ +// $Id: GameSVCmds.java,v 1.2 2004-07-09 06:50:49 hzi Exp $ package jake2.game; +import jake2.qcommon.Com; + import java.io.IOException; import java.io.RandomAccessFile; import java.util.StringTokenizer; -import com.sun.corba.se.internal.ior.ByteBuffer; - -import jake2.*; -import jake2.client.*; -import jake2.qcommon.*; -import jake2.render.*; -import jake2.server.*; - public class GameSVCmds extends GameSpawn { public static void Svcmd_Test_f() { diff --git a/src/jake2/game/GameSpawn.java b/src/jake2/game/GameSpawn.java index edb8cab..34412fd 100644 --- a/src/jake2/game/GameSpawn.java +++ b/src/jake2/game/GameSpawn.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 18.11.2003 by RST. -// $Id: GameSpawn.java,v 1.2 2004-07-08 15:58:44 hzi Exp $ +// $Id: GameSpawn.java,v 1.3 2004-07-09 06:50:49 hzi Exp $ package jake2.game; @@ -305,7 +305,7 @@ public class GameSpawn extends GameSave { e.teammaster = e; c++; c2++; - Com.Printf("Team:" + e.team+" entity: " + e.index + "\n"); + //Com.Printf("Team:" + e.team+" entity: " + e.index + "\n"); for (j = i + 1; j < globals.num_edicts; j++) { e2 = g_edicts[j]; if (!e2.inuse) @@ -427,7 +427,7 @@ public class GameSpawn extends GameSave { ED_CallSpawn(ent); } //gi.dprintf("player skill level:" +skill.value + "\n"); - gi.dprintf(inhibit + " entities inhibited\n"); + //gi.dprintf(inhibit + " entities inhibited\n"); i = 1; G_FindTeams(); PlayerTrail.Init(); diff --git a/src/jake2/game/GameUtil.java b/src/jake2/game/GameUtil.java index ee52a89..a5d81ad 100644 --- a/src/jake2/game/GameUtil.java +++ b/src/jake2/game/GameUtil.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 01.11.2003 by RST. -// $Id: GameUtil.java,v 1.2 2004-07-08 15:58:44 hzi Exp $ +// $Id: GameUtil.java,v 1.3 2004-07-09 06:50:49 hzi Exp $ package jake2.game; @@ -280,7 +280,6 @@ public class GameUtil extends GameBase return false; } - /** TODO: test, / replaced the string operations. */ static String ClientTeam(edict_t ent) { String value; diff --git a/src/jake2/game/GameUtilAdapters.java b/src/jake2/game/GameUtilAdapters.java index 4a3c320..6191270 100644 --- a/src/jake2/game/GameUtilAdapters.java +++ b/src/jake2/game/GameUtilAdapters.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 26.02.2004 by RST. -// $Id: GameUtilAdapters.java,v 1.1 2004-07-08 15:58:44 hzi Exp $ +// $Id: GameUtilAdapters.java,v 1.2 2004-07-09 06:50:49 hzi Exp $ package jake2.game; @@ -310,7 +310,7 @@ public class GameUtilAdapters if (!taken) return; - Com.p("Picked up:" + ent.classname); + //Com.p("Picked up:" + ent.classname); if (!((GameBase.coop.value != 0) && (ent.item.flags & Defines.IT_STAY_COOP) != 0) || 0 != (ent.spawnflags & (Defines.DROPPED_ITEM | Defines.DROPPED_PLAYER_ITEM))) @@ -322,6 +322,7 @@ public class GameUtilAdapters } } }; + static EntTouchAdapter drop_temp_touch = new EntTouchAdapter() { public void touch(edict_t ent, edict_t other, cplane_t plane, csurface_t surf) @@ -332,6 +333,7 @@ public class GameUtilAdapters Touch_Item.touch(ent, other, plane, surf); } }; + static EntThinkAdapter drop_make_touchable = new EntThinkAdapter() { public boolean think(edict_t ent) @@ -398,7 +400,7 @@ public class GameUtilAdapters ent.client.pers.inventory[GameUtil.ITEM_INDEX(item)]--; //TODO: remove this line - ent.client.pers.inventory[GameUtil.ITEM_INDEX(item)]=0; + //ent.client.pers.inventory[GameUtil.ITEM_INDEX(item)]=0; GameUtil.ValidateSelectedItem(ent); @@ -407,7 +409,7 @@ public class GameUtilAdapters else ent.client.breather_framenum = GameBase.level.framenum + 300; - // gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage.wav"), 1, ATTN_NORM, 0); + GameBase.gi.sound(ent, Defines.CHAN_ITEM, GameBase.gi.soundindex("items/damage.wav"), 1, Defines.ATTN_NORM, 0); } }; // ====================================================================== @@ -424,7 +426,7 @@ public class GameUtilAdapters else ent.client.enviro_framenum = GameBase.level.framenum + 300; - // gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage.wav"), 1, ATTN_NORM, 0); + GameBase.gi.sound(ent, Defines.CHAN_ITEM, GameBase.gi.soundindex("items/damage.wav"), 1, Defines.ATTN_NORM, 0); } }; // ====================================================================== @@ -458,7 +460,7 @@ public class GameUtilAdapters GameUtil.ValidateSelectedItem(ent); ent.client.silencer_shots += 30; - // gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage.wav"), 1, ATTN_NORM, 0); + GameBase.gi.sound(ent, Defines.CHAN_ITEM, GameBase.gi.soundindex("items/damage.wav"), 1, Defines.ATTN_NORM, 0); } }; // ====================================================================== diff --git a/src/jake2/game/M_Actor.java b/src/jake2/game/M_Actor.java index f48ff77..24484ab 100644 --- a/src/jake2/game/M_Actor.java +++ b/src/jake2/game/M_Actor.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 11.11.2003 by RST. -// $Id: M_Actor.java,v 1.2 2004-07-08 15:58:44 hzi Exp $ +// $Id: M_Actor.java,v 1.3 2004-07-09 06:50:49 hzi Exp $ package jake2.game; @@ -731,7 +731,7 @@ public class M_Actor extends GameAI { return; self.pain_debounce_time= level.time + 3; - // gi.sound (self, CHAN_VOICE, actor.sound_pain, 1, ATTN_NORM, 0); + //GameBase.gi.sound (self, CHAN_VOICE, actor.sound_pain, 1, ATTN_NORM, 0); if ((other.client != null) && (Lib.random() < 0.4)) { float v[]= { 0, 0, 0 }; diff --git a/src/jake2/game/PlayerHud.java b/src/jake2/game/PlayerHud.java index b9622e3..244e398 100644 --- a/src/jake2/game/PlayerHud.java +++ b/src/jake2/game/PlayerHud.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 28.12.2003 by RST. -// $Id: PlayerHud.java,v 1.2 2004-07-08 15:58:44 hzi Exp $ +// $Id: PlayerHud.java,v 1.3 2004-07-09 06:50:49 hzi Exp $ package jake2.game; @@ -100,13 +100,15 @@ public class PlayerHud extends GameTarget { level.intermissiontime = level.time; // TODO: BIG HACK TO IGNORE CINEMATIC + String xxx = targ.map; int pos = xxx.indexOf(".cin"); if (pos != -1) level.changemap = xxx.substring(pos + 5); // including "+" else level.changemap = xxx; - + // ------------------------ + //level.changemap = targ.map; if (level.changemap.indexOf('*') > -1) { if (coop.value != 0) { for (i = 0; i < maxclients.value; i++) { diff --git a/src/jake2/game/game_export_t.java b/src/jake2/game/game_export_t.java index 792b785..9dabf51 100644 --- a/src/jake2/game/game_export_t.java +++ b/src/jake2/game/game_export_t.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 31.10.2003 by RST. -// $Id: game_export_t.java,v 1.2 2004-07-08 15:58:44 hzi Exp $ +// $Id: game_export_t.java,v 1.3 2004-07-09 06:50:49 hzi Exp $ package jake2.game; @@ -58,8 +58,8 @@ public class game_export_t // ReadGame is called on a loadgame. public void WriteGame(String filename, boolean autosave) { - // TODO WriteGame not implemnted! - Com.Println("WriteGame not implemnted!"); + // TODO WriteGame not implemented. + Com.Println("WriteGame not implemented."); } public void ReadGame(String filename) @@ -71,14 +71,14 @@ public class game_export_t // loaded with SpawnEntities public void WriteLevel(String filename) { - // TODO WriteLevel not implemented! - Com.Println("WriteLevel not implemented!"); + // TODO WriteLevel not implemented. + Com.Println("WriteLevel not implemented."); } public void ReadLevel(String filename) { - // TODO ReadLevel not implemnted! - Com.Println("ReadLevel not implemnted!"); + // TODO ReadLevel not implemented. + Com.Println("ReadLevel not implemented."); } public boolean ClientConnect(edict_t ent, String userinfo) diff --git a/src/jake2/game/player_state_t.java b/src/jake2/game/player_state_t.java index 3ecc17d..d4ecc72 100644 --- a/src/jake2/game/player_state_t.java +++ b/src/jake2/game/player_state_t.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 31.10.2003 by RST. -// $Id: player_state_t.java,v 1.2 2004-07-08 20:24:29 hzi Exp $ +// $Id: player_state_t.java,v 1.3 2004-07-09 06:50:49 hzi Exp $ package jake2.game; @@ -62,7 +62,6 @@ public class player_state_t { /** * */ - // TODO bugfix cwei private static player_state_t prototype = new player_state_t(); public void clear() { diff --git a/src/jake2/imageio/ImageFrame.java b/src/jake2/imageio/ImageFrame.java deleted file mode 100644 index 52cf9e4..0000000 --- a/src/jake2/imageio/ImageFrame.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Created on Apr 26, 2003 - * - */ -package jake2.imageio; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.image.BufferedImage; -import javax.swing.JFrame; - -/** - * @author cwei - * - */ -public class ImageFrame extends JFrame { - - BufferedImage image; - Component pane; - - public ImageFrame(BufferedImage image) { - super(); - this.image = image; - - pane = getContentPane(); - setIconImage(image); - setSize(640, 480); - - addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - System.exit(0); - } - }); - } - - public void paint(Graphics g) { - super.paint(g); - Graphics2D g2 = (Graphics2D) pane.getGraphics(); - if (this.image != null) { - g2.drawImage( - image, - Math.max(0, (getWidth() - image.getWidth()) / 2), - Math.max(0, (getHeight() - image.getHeight()) / 2), - Color.LIGHT_GRAY, - pane); - } else { - g2.drawString( - "EMPTY IMAGE", - this.getWidth() / 4, - this.getHeight() / 2); - } - } - - public void showImage(BufferedImage image) { - this.image = image; - this.repaint(); - } - -} diff --git a/src/jake2/imageio/PCX.java b/src/jake2/imageio/PCX.java deleted file mode 100644 index eb71465..0000000 --- a/src/jake2/imageio/PCX.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Created on Nov 18, 2003 - * - */ -package jake2.imageio; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * @author cwei - * - */ -public class PCX { - - public static final int HEADER_SIZE = 128; - - /** - * <code> - typedef struct - { - char manufacturer; - char version; - char encoding; - char bits_per_pixel; - unsigned short xmin,ymin,xmax,ymax; - unsigned short horzRes,vertRes; - unsigned char palette[48]; - char reserved; - char color_planes; - unsigned short bytes_per_line; - unsigned short palette_type; - char filler[58]; - unsigned char data; // unbounded - } pcx_t; - - </code> - */ - public static class Header { - - // size of byte arrays - static final int PALETTE_SIZE = 48; - static final int FILLER_SIZE = 58; - - byte manufacturer; - byte version; - byte encoding; - byte bitsPerPixel; - int xmin, ymin, xmax, ymax; // unsigned short - int horzRes, vertRes; // unsigned short - byte[] palette; //unsigned byte - byte reserved; - byte colorPlanes; - int bytesPerLine; // unsigned short - int paletteType; // unsigned short - byte[] filler; - - - - public Header(byte[] headerBytes) { - if (headerBytes == null || headerBytes.length != 128) { - throw new IllegalArgumentException("invalid quake2 pcx header"); - } - - ByteBuffer b = ByteBuffer.wrap(headerBytes); - // is stored as little endian - b.order(ByteOrder.LITTLE_ENDIAN); - - // fill header - manufacturer = b.get(); - version = b.get(); - encoding = b.get(); - bitsPerPixel = b.get(); - xmin = b.getShort() & 0xffff; - ymin = b.getShort() & 0xffff; - xmax = b.getShort() & 0xffff; - ymax = b.getShort() & 0xffff; - horzRes = b.getShort() & 0xffff; - vertRes = b.getShort() & 0xffff; - b.get(palette = new byte[PALETTE_SIZE]); - reserved = b.get(); - colorPlanes = b.get(); - bytesPerLine = b.getShort() & 0xffff; - paletteType = b.getShort() & 0xffff; - b.get(filler = new byte[FILLER_SIZE]); - - // check some attributes - checkHeader(); - } - - private void checkHeader() { - - if (this.getManufacturer() != 0x0a - || this.getVersion() != 5 - || this.getEncoding() != 1 - || this.getBitsPerPixel() != 8 - || this.getXmax() >= 640 - || this.getYmax() >= 480) { - throw new IllegalArgumentException("invalid quake2 pcx header"); - } - } - - /** - * @return - */ - public byte getBitsPerPixel() { - return bitsPerPixel; - } - - /** - * @return - */ - public int getBytesPerLine() { - return bytesPerLine; - } - - /** - * @return - */ - public byte getColorPlanes() { - return colorPlanes; - } - - /** - * @return - */ - public byte getEncoding() { - return encoding; - } - - /** - * @return - */ - public byte[] getFiller() { - return filler; - } - - /** - * @return - */ - public int getHeight() { - return ymax - ymin + 1; - } - - /** - * @return - */ - public byte getManufacturer() { - return manufacturer; - } - - /** - * @return - */ - public byte[] getPalette() { - return palette; - } - - /** - * @return - */ - public int getPaletteType() { - return paletteType; - } - - /** - * @return - */ - public byte getReserved() { - return reserved; - } - - /** - * @return - */ - public byte getVersion() { - return version; - } - - /** - * @return - */ - public int getWidth() { - return xmax - xmin + 1; - } - - /** - * @return - */ - public int getXmax() { - return xmax; - } - - /** - * @return - */ - public int getXmin() { - return xmin; - } - - /** - * @return - */ - public int getYmax() { - return ymax; - } - - /** - * @return - */ - public int getYmin() { - return ymin; - } - /** - * @return - */ - public int getHorzRes() { - return horzRes; - } - - /** - * @return - */ - public int getVertRes() { - return vertRes; - } - - } -}
\ No newline at end of file diff --git a/src/jake2/imageio/PCXImageReader.java b/src/jake2/imageio/PCXImageReader.java deleted file mode 100644 index c81e623..0000000 --- a/src/jake2/imageio/PCXImageReader.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Created on Nov 17, 2003 - * - */ -package jake2.imageio; - -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.image.BufferedImage; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferByte; -import java.awt.image.Raster; -import java.awt.image.WritableRaster; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.imageio.IIOException; -import javax.imageio.ImageReadParam; -import javax.imageio.ImageReader; -import javax.imageio.ImageTypeSpecifier; -import javax.imageio.metadata.IIOMetadata; -import javax.imageio.spi.ImageReaderSpi; -import javax.imageio.stream.ImageInputStream; - -/** - * @author cwei - * - */ -public class PCXImageReader extends ImageReader { - - private static Logger logger = - Logger.getLogger(PCXImageReader.class.getName()); - - ImageInputStream stream = null; - PCX.Header header = null; - - public PCXImageReader(ImageReaderSpi originatingProvider) { - super(originatingProvider); - } - - public void setInput(Object input, boolean seekForwardOnly) { - super.setInput(input, seekForwardOnly); - if (input == null) { - this.stream = null; - return; - } - if (input instanceof ImageInputStream) { - this.stream = (ImageInputStream) input; - } else { - throw new IllegalArgumentException("bad input"); - } - } - - public int getHeight(int imageIndex) throws IOException { - checkIndex(imageIndex); - readHeader(); - return header.getHeight(); - } - - public int getWidth(int imageIndex) throws IOException { - checkIndex(imageIndex); - readHeader(); - return header.getWidth(); - } - - public int getNumImages(boolean allowSearch) throws IOException { - // only 1 image - return 1; - } - - public Iterator getImageTypes(int imageIndex) throws IOException { - checkIndex(imageIndex); - readHeader(); - - ImageTypeSpecifier imageType = null; - java.util.List l = new ArrayList(1); - - imageType = - ImageTypeSpecifier.createIndexed( - Q2ColorMap.RED, - Q2ColorMap.GREEN, - Q2ColorMap.BLUE, - Q2ColorMap.ALPHA, - 8, - DataBuffer.TYPE_BYTE); - - l.add(imageType); - return l.iterator(); - } - - public IIOMetadata getStreamMetadata() throws IOException { - return null; - } - - public IIOMetadata getImageMetadata(int imageIndex) throws IOException { - return null; - } - - public BufferedImage read(int imageIndex, ImageReadParam param) - throws IOException { - - checkIndex(imageIndex); - readHeader(); - - int width = header.getWidth(); - int height = header.getHeight(); - - // Compute initial source region, clip against destination later - Rectangle sourceRegion = getSourceRegion(param, width, height); - - // Set everything to default values - int sourceXSubsampling = 1; - int sourceYSubsampling = 1; - int[] sourceBands = null; - int[] destinationBands = null; - Point destinationOffset = new Point(0, 0); - - // Get values from the ImageReadParam, if any - if (param != null) { - sourceXSubsampling = param.getSourceXSubsampling(); - sourceYSubsampling = param.getSourceYSubsampling(); - sourceBands = param.getSourceBands(); - destinationBands = param.getDestinationBands(); - destinationOffset = param.getDestinationOffset(); - } - - // Get the specified detination image or create a new one - BufferedImage dst = - getDestination(param, getImageTypes(0), width, height); - - // Enure band settings from param are compatible with images - int inputBands = 1; - checkReadParamBandSettings( - param, - inputBands, - dst.getSampleModel().getNumBands()); - - int[] bandOffsets = new int[inputBands]; - for (int i = 0; i < inputBands; i++) { - bandOffsets[i] = i; - } - int bytesPerRow = width * inputBands; - DataBufferByte rowDB = new DataBufferByte(bytesPerRow); - WritableRaster rowRas = - Raster.createInterleavedRaster( - rowDB, - width, - 1, - bytesPerRow, - inputBands, - bandOffsets, - new Point(0, 0)); - byte[] rowBuf = rowDB.getData(); - - // Create an int[] that can a single pixel - int[] pixel = rowRas.getPixel(0, 0, (int[]) null); - - WritableRaster imRas = dst.getWritableTile(0, 0); - int dstMinX = imRas.getMinX(); - int dstMaxX = dstMinX + imRas.getWidth() - 1; - int dstMinY = imRas.getMinY(); - int dstMaxY = dstMinY + imRas.getHeight() - 1; - - // Create a child raster exposing only the desired source bands - if (sourceBands != null) { - rowRas = - rowRas.createWritableChild(0, 0, width, 1, 0, 0, sourceBands); - } - - // Create a child raster exposing only the desired dest bands - if (destinationBands != null) { - imRas = - imRas.createWritableChild( - 0, - 0, - imRas.getWidth(), - imRas.getHeight(), - 0, - 0, - destinationBands); - - } - - int dataByte = 0; - int runLength = 0; - - for (int srcY = 0; srcY < height; srcY++) { - // Read the row - try { - /* - * run length decoding for PCX images - */ - int index = 0; - - while (index < rowBuf.length) { - while (runLength-- > 0 && index < rowBuf.length) { - rowBuf[index++] = (byte) (dataByte & 0xff); - } - dataByte = stream.readUnsignedByte(); - if ((dataByte & 0xc0) == 0xc0) { - runLength = dataByte & 0x3f; - dataByte = stream.readUnsignedByte(); - } else { - runLength = 1; - } - } - } catch (IOException e) { - throw new IIOException("Error reading line " + srcY, e); - } - - // Reject rows that lie outside the source region, - // or which aren't part of the subsampling - if ((srcY < sourceRegion.y) - || (srcY >= sourceRegion.y + sourceRegion.height) - || (((srcY - sourceRegion.y) % sourceYSubsampling) != 0)) { - continue; - } - - // Determine where the row will go in the destination - int dstY = - destinationOffset.y - + (srcY - sourceRegion.y) / sourceYSubsampling; - if (dstY < dstMinY) { - continue; // The row is above imRas - } - if (dstY > dstMaxY) { - break; // We're done with the image - } - - // Copy each (subsampled) source pixel into imRas - for (int srcX = sourceRegion.x; - srcX < sourceRegion.x + sourceRegion.width; - srcX++) { - if (((srcX - sourceRegion.x) % sourceXSubsampling) != 0) { - continue; - } - int dstX = - destinationOffset.x - + (srcX - sourceRegion.x) / sourceXSubsampling; - if (dstX < dstMinX) { - continue; // The pixel is to the left of imRas - } - if (dstX > dstMaxX) { - break; // We're done with the row - } - - // Copy the pixel, sub-banding is done automatically - rowRas.getPixel(srcX, 0, pixel); - imRas.setPixel(dstX, dstY, pixel); - } - } - if ((stream.readUnsignedByte()) == 0x0c) { - logger.log( - Level.FINE, - "PCX has a color palette with " - + (stream.length() - stream.getStreamPosition()) - + " Bytes, but use the default palette (quake2)"); - } - return dst; - } - - private void checkIndex(int imageIndex) { - if (imageIndex != 0) { - throw new IndexOutOfBoundsException("bad image index"); - } - } - -// buggy version -/* private void decodeRow(byte[] buffer) throws IOException { - int dataByte = 0; - int runLength = 0; - int index = 0; - - while (index < buffer.length) { - dataByte = stream.readUnsignedByte(); - if ((dataByte & 0xc0) == 0xc0) { - runLength = dataByte & 0x3f; - dataByte = stream.readUnsignedByte(); - } else { - runLength = 1; - } - - while (runLength-- > 0 && index < buffer.length) { - buffer[index++] = (byte) (dataByte & 0xff); - } - assert(runLength == -1) : "runLength decoding bug: " + runLength; - } - } -*/ - private void readHeader() throws IIOException { - - if (header != null) - return; - - logger.log(Level.FINE, "PCX read header"); - - if (stream == null) { - if (this.input == null) { - throw new IllegalStateException("No input stream"); - } - stream = (ImageInputStream) input; - } - - byte[] buffer = new byte[PCX.HEADER_SIZE]; - - try { - stream.readFully(buffer); - this.header = new PCX.Header(buffer); - logger.log( - Level.FINE, - "PCX horzRes: " - + header.getWidth() - + " height: " - + header.getHeight()); - } catch (IOException e) { - throw new IIOException("Error reading quake2 PCX header", e); - } - } -} diff --git a/src/jake2/imageio/PCXImageReaderSpi.java b/src/jake2/imageio/PCXImageReaderSpi.java deleted file mode 100644 index f4089e3..0000000 --- a/src/jake2/imageio/PCXImageReaderSpi.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Created on Nov 17, 2003 - * - */ -package jake2.imageio; - -import java.io.IOException; -import java.util.Locale; - -import javax.imageio.ImageReader; -import javax.imageio.spi.ImageReaderSpi; -import javax.imageio.stream.ImageInputStream; - -/** - * @author cwei - * - * put the own ImageReaderSpi class name in the file (relative to classpath): - * <code> - * META-INF/services/javax.imageio.spi.ImageReaderSpi - * </code> - */ -public class PCXImageReaderSpi extends ImageReaderSpi { - - static final String vendorName = "[email protected]"; - static final String version = "1.0_beta"; - static final String[] names = { "quake2 pcx" }; - static final String[] suffixes = { "pcx" }; - static final String[] MIMETypes = { "image/x-quake2-pcx" }; - static final String readerClassName = "jake2.imageio.PCXImageReader"; - static final String[] writerSpiNames = null; // { "jake2.imageio.PCXImageWriterSpi" }; - - // Metadata formats, more information below - static final boolean supportsStandardStreamMetadataFormat = false; - static final String nativeStreamMetadataFormatName = null; - - static final String nativeStreamMetadataFormatClassName = null; - static final String[] extraStreamMetadataFormatNames = null; - static final String[] extraStreamMetadataFormatClassNames = null; - static final boolean supportsStandardImageMetadataFormat = false; - static final String nativeImageMetadataFormatName = - "jake2.imageio.PCXMetaData_1.0"; - static final String nativeImageMetadataFormatClassName = null; // "jake2.imageio.PCXMetadata"; - static final String[] extraImageMetadataFormatNames = null; - static final String[] extraImageMetadataFormatClassNames = null; - - public PCXImageReaderSpi() { - - super( - vendorName, - version, - names, - suffixes, - MIMETypes, - readerClassName, - ImageReaderSpi.STANDARD_INPUT_TYPE, - // Accept ImageInputStreams - writerSpiNames, - supportsStandardStreamMetadataFormat, - nativeStreamMetadataFormatName, - nativeStreamMetadataFormatClassName, - extraStreamMetadataFormatNames, - extraStreamMetadataFormatClassNames, - supportsStandardImageMetadataFormat, - nativeImageMetadataFormatName, - nativeImageMetadataFormatClassName, - extraImageMetadataFormatNames, - extraImageMetadataFormatClassNames); - } - - public boolean canDecodeInput(Object source) throws IOException { - if (!(source instanceof ImageInputStream)) { - return false; - } - ImageInputStream stream = (ImageInputStream)source; - byte[] buffer = new byte[PCX.HEADER_SIZE]; - try { - stream.mark(); - stream.readFully(buffer); - stream.reset(); - // buffer will be converted to members and header checked - PCX.Header pcx = new PCX.Header(buffer); - } catch (IllegalArgumentException e) { - return false; - } - return true; - } - - public ImageReader createReaderInstance(Object extension) - throws IOException { - return new PCXImageReader(this); - } - - /** - * @see javax.imageio.spi.IIOServiceProvider#getDescription(java.util.Locale) - */ - public String getDescription(Locale locale) { - return "id-software's Quake2 pcx format"; - } -} diff --git a/src/jake2/imageio/Q2ColorMap.java b/src/jake2/imageio/Q2ColorMap.java deleted file mode 100644 index 6476e61..0000000 --- a/src/jake2/imageio/Q2ColorMap.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Created on Nov 18, 2003 - * - */ -package jake2.imageio; - -/** - * @author cwei - * - */ -public interface Q2ColorMap { - // Red channel - static final byte[] RED = { - 0, 15, 31, 47, 63, 75, 91, 107, 123, -117, -101, -85, -69, -53, -37, -21, - 99, 91, 83, 79, 71, 63, 59, 51, 47, 43, 39, 35, 27, 23, 19, 15, - 95, 91, 91, 87, 83, 79, 71, 63, 59, 51, 47, 39, 35, 27, 23, 19, - -113, 123, 115, 103, -49, -89, -117, 111, -21, -53, -81, -109, 119, 91, 63, 35, - -89, -97, -105, -117, 127, 115, 103, 87, 75, 67, 59, 51, 43, 35, 27, 19, - 123, 115, 107, 103, 95, 87, 83, 75, 67, 63, 55, 47, 39, 31, 23, 15, - 111, 95, 83, 67, 55, 39, 27, 15, -77, -65, -53, -41, -53, -77, -97, -121, - 115, 91, 71, 47, 23, 19, 15, 11, 7, 7, 7, 0, 0, 0, 0, 0, - -117, -125, 123, 115, 107, 99, 91, 87, 75, 63, 51, 43, 31, 19, 11, 0, - -105, -113, -121, 127, 119, 115, 107, 99, 91, 79, 67, 55, 47, 35, 23, 15, - -97, -109, -117, 127, 119, 107, 99, 87, 79, 67, 55, 43, 31, 23, 11, 0, - 119, 111, 103, 99, 91, 83, 75, 71, 63, 55, 47, 39, 35, 27, 19, 11, - -101, -113, -121, 123, 115, 103, 95, 87, 75, 63, 55, 47, 35, 27, 19, 11, - 0, 35, 63, 83, 95, 95, 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -17, -29, -45, -57, -73, -85, -101, -113, 127, 115, 95, 71, 47, 27, - -17, 55, -1, 0, 43, 27, 19, -21, -61, -97, 123, -21, -57, -89, -121, -97 - }; - - // Green channel - static final byte[] GREEN = { - 0, 15, 31, 47, 63, 75, 91, 107, 123, -117, -101, -85, -69, -53, -37, -21, - 75, 67, 63, 59, 55, 47, 43, 39, 35, 31, 27, 23, 19, 15, 15, 11, - 95, 91, 83, 79, 75, 71, 63, 59, 55, 47, 43, 39, 35, 27, 23, 19, - 119, 99, 91, 79, -105, 123, 103, 83, -97, -117, 119, 99, 79, 59, 39, 23, - 59, 47, 43, 39, 31, 23, 23, 19, 15, 15, 15, 11, 11, 11, 7, 7, - 95, 87, 83, 79, 71, 67, 63, 55, 51, 47, 39, 35, 27, 23, 15, 11, - 59, 55, 47, 43, 35, 27, 19, 11, 91, 123, -101, -69, -41, -57, -73, -89, - -105, -121, 119, 103, 83, 75, 67, 63, 55, 47, 39, 31, 23, 15, 7, 0, - 87, 79, 71, 67, 59, 51, 47, 43, 35, 31, 27, 19, 15, 11, 7, 0, - -97, -105, -117, -125, 123, 115, 107, 99, 91, 79, 67, 55, 47, 35, 23, 15, - 75, 67, 59, 55, 47, 43, 35, 31, 27, 23, 19, 15, 11, 7, 0, 0, - 123, 115, 107, 99, 91, 87, 79, 71, 63, 55, 47, 39, 31, 23, 15, 7, - -85, -97, -105, -117, -125, 119, 111, 103, 91, 79, 67, 59, 47, 35, 23, 15, - -1, -25, -45, -69, -89, -113, 123, -1, -1, -1, -1, -1, -1, -21, -41, -65, - -85, -109, 127, 107, 87, 71, 59, 43, 31, 23, 15, 7, 0, 0, 0, 0, - 0, 55, 0, 0, 43, 27, 19, -105, 115, 87, 63, -45, -85, -117, 107, 91 - }; - - // Blue channel - static final byte[] BLUE = { - 0, 15, 31, 47, 63, 75, 91, 107, 123, -117, -101, -85, -69, -53, -37, -21, - 35, 31, 31, 27, 27, 23, 23, 19, 19, 19, 15, 15, 11, 11, 7, 7, - 111, 103, 95, 91, 83, 75, 67, 59, 55, 47, 43, 39, 35, 27, 23, 19, - 83, 67, 59, 47, 75, 59, 47, 39, 39, 35, 31, 27, 23, 15, 11, 7, - 43, 35, 27, 19, 15, 11, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 75, 67, 63, 59, 55, 51, 47, 43, 39, 35, 27, 23, 19, 15, 11, 7, - 23, 23, 23, 23, 19, 15, 11, 7, 79, 111, -109, -73, -33, -45, -61, -73, - -89, -101, -117, 127, 111, 103, 91, 83, 75, 63, 51, 43, 31, 19, 11, 0, - 87, 79, 71, 67, 59, 51, 47, 43, 35, 31, 27, 19, 15, 11, 7, 0, - 123, 115, 107, 99, 95, 87, 79, 71, 67, 59, 51, 43, 35, 27, 19, 11, - 63, 55, 47, 39, 35, 27, 23, 19, 15, 11, 11, 7, 7, 0, 0, 0, - -49, -61, -73, -89, -101, -113, 127, 115, 103, 87, 75, 63, 47, 35, 23, 7, - 123, 111, 99, 87, 75, 67, 59, 51, 39, 27, 19, 11, 7, 0, 0, 0, - 0, 15, 27, 39, 47, 51, 51, -1, -45, -89, 127, 83, 39, 31, 23, 15, - 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -1, 0, -1, 35, 23, 15, 127, 83, 51, 27, -57, -101, 119, 87, 83 - }; - - // Alpha channel - static final byte[] ALPHA = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 - }; -} diff --git a/src/jake2/imageio/WAL.java b/src/jake2/imageio/WAL.java deleted file mode 100644 index 1c499ef..0000000 --- a/src/jake2/imageio/WAL.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Created on Nov 18, 2003 - * - */ -package jake2.imageio; - -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * @author cwei - * - */ -public class WAL { - - public static final int HEADER_SIZE = 100; - - /* struct wal_header - { - char name[32]; // name of the texture - - uint32 width; // width (in pixels) of the largest mipmap level - uint32 height; // height (in pixels) of the largest mipmap level - - int32 offset[4]; // byte offset of the start of each of the 4 mipmap levels - - char next_name[32]; // name of the next texture in the animation - - uint32 flags; // ? - uint32 contents; // ? - uint32 value; // ? - }; - */ - public static class Header { - - // size of byte arrays - static final int NAME_SIZE = 32; - static final int OFFSET_SIZE = 4; - - String name; - int width; - int height; - int[] offset; // file offsets for the 4 mipmap images - String nextName; - int flags; // unused - int contents; // unused - int value; // unused - - public Header(byte[] headerBytes) { - if (headerBytes == null || headerBytes.length != HEADER_SIZE) { - throw new IllegalArgumentException("invalid quake2 wal header"); - } - - ByteBuffer b = ByteBuffer.wrap(headerBytes); - // is stored as little endian - b.order(ByteOrder.LITTLE_ENDIAN); - - byte[] tmp = new byte[NAME_SIZE]; - // fill header - - // name - b.get(tmp); - try { - name = new String(tmp, "ISO-8859-1"); - } catch (UnsupportedEncodingException e) { - name = new String(tmp); - } - // width - width = b.getInt(); - assert(width >= 0) : "unsigned int bug"; // true means ok. - // height - height = b.getInt(); - assert(height >= 0) : "unsigned int bug"; // true means ok. - // 4 offsets - offset = - new int[] { b.getInt(), b.getInt(), b.getInt(), b.getInt()}; - // nextName - b.get(tmp); - try { - nextName = new String(tmp, "ISO-8859-1"); - } catch (UnsupportedEncodingException e1) { - name = new String(tmp); - } - // unused entries - flags = b.getInt(); - contents = b.getInt(); - value = b.getInt(); - - // check some attributes - checkHeader(); - } - - private void checkHeader() { - // start of mipmaps - int mipmap0 = HEADER_SIZE; - int mipmap1 = mipmap0 + getWidth() * getHeight(); - int mipmap2 = mipmap1 + getWidth() / 2 * getHeight() / 2; - int mipmap3 = mipmap2 + getWidth() / 4 * getHeight() / 4; - - if (offset[0] != mipmap0 - || offset[1] != mipmap1 - || offset[2] != mipmap2 - || offset[3] != mipmap3) { - throw new IllegalArgumentException("invalid quake2 wal header"); - } - } - - /** - * @return - */ - public int getContents() { - return contents; - } - - /** - * @return - */ - public int getFlags() { - return flags; - } - - /** - * @return - */ - public int getHeight() { - return height; - } - - /** - * @return - */ - public String getName() { - return name; - } - - /** - * @return - */ - public String getNextName() { - return nextName; - } - - /** - * @return - */ - public int getOffset(int index) { - if (index < 0 || index > 3) { - throw new ArrayIndexOutOfBoundsException("mipmap offset range is 0 to 3"); - } - return offset[index]; - } - - /** - * @return - */ - public int getValue() { - return value; - } - - /** - * @return - */ - public int getWidth() { - return width; - } - - } -}
\ No newline at end of file diff --git a/src/jake2/imageio/WALImageReader.java b/src/jake2/imageio/WALImageReader.java deleted file mode 100644 index 949b4f1..0000000 --- a/src/jake2/imageio/WALImageReader.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Created on Nov 18, 2003 - * - */ -package jake2.imageio; - -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.image.BufferedImage; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferByte; -import java.awt.image.Raster; -import java.awt.image.WritableRaster; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.imageio.IIOException; -import javax.imageio.ImageReadParam; -import javax.imageio.ImageReader; -import javax.imageio.ImageTypeSpecifier; -import javax.imageio.metadata.IIOMetadata; -import javax.imageio.spi.ImageReaderSpi; -import javax.imageio.stream.ImageInputStream; - -/** - * @author cwei - * - */ -public class WALImageReader extends ImageReader { - - private static Logger logger = - Logger.getLogger(WALImageReader.class.getName()); - - ImageInputStream stream = null; - WAL.Header header = null; - - public WALImageReader(ImageReaderSpi originatingProvider) { - super(originatingProvider); - } - - public void setInput(Object input, boolean seekForwardOnly) { - super.setInput(input, seekForwardOnly); - if (input == null) { - this.stream = null; - return; - } - if (input instanceof ImageInputStream) { - this.stream = (ImageInputStream) input; - } else { - throw new IllegalArgumentException("bad input"); - } - } - - public int getHeight(int imageIndex) throws IOException { - checkIndex(imageIndex); - readHeader(); - return header.getHeight(); - } - - public int getWidth(int imageIndex) throws IOException { - checkIndex(imageIndex); - readHeader(); - return header.getWidth(); - } - - public int getNumImages(boolean allowSearch) throws IOException { - // only 1 image - return 1; - } - - public Iterator getImageTypes(int imageIndex) throws IOException { - checkIndex(imageIndex); - readHeader(); - - ImageTypeSpecifier imageType = null; - java.util.List l = new ArrayList(1); - - imageType = - ImageTypeSpecifier.createIndexed( - Q2ColorMap.RED, - Q2ColorMap.GREEN, - Q2ColorMap.BLUE, - Q2ColorMap.ALPHA, - 8, - DataBuffer.TYPE_BYTE); - - l.add(imageType); - return l.iterator(); - } - - public IIOMetadata getStreamMetadata() throws IOException { - return null; - } - - public IIOMetadata getImageMetadata(int imageIndex) throws IOException { - return null; - } - - public BufferedImage read(int imageIndex, ImageReadParam param) - throws IOException { - - checkIndex(imageIndex); - readHeader(); - - int width = header.getWidth(); - int height = header.getHeight(); - - // Compute initial source region, clip against destination later - Rectangle sourceRegion = getSourceRegion(param, width, height); - - // Set everything to default values - int sourceXSubsampling = 1; - int sourceYSubsampling = 1; - int[] sourceBands = null; - int[] destinationBands = null; - Point destinationOffset = new Point(0, 0); - - // Get values from the ImageReadParam, if any - if (param != null) { - sourceXSubsampling = param.getSourceXSubsampling(); - sourceYSubsampling = param.getSourceYSubsampling(); - sourceBands = param.getSourceBands(); - destinationBands = param.getDestinationBands(); - destinationOffset = param.getDestinationOffset(); - } - - // Get the specified detination image or create a new one - BufferedImage dst = - getDestination(param, getImageTypes(0), width, height); - - // Enure band settings from param are compatible with images - int inputBands = 1; - checkReadParamBandSettings( - param, - inputBands, - dst.getSampleModel().getNumBands()); - - int[] bandOffsets = new int[inputBands]; - for (int i = 0; i < inputBands; i++) { - bandOffsets[i] = i; - } - int bytesPerRow = width * inputBands; - DataBufferByte rowDB = new DataBufferByte(bytesPerRow); - WritableRaster rowRas = - Raster.createInterleavedRaster( - rowDB, - width, - 1, - bytesPerRow, - inputBands, - bandOffsets, - new Point(0, 0)); - byte[] rowBuf = rowDB.getData(); - - // Create an int[] that can a single pixel - int[] pixel = rowRas.getPixel(0, 0, (int[]) null); - - WritableRaster imRas = dst.getWritableTile(0, 0); - int dstMinX = imRas.getMinX(); - int dstMaxX = dstMinX + imRas.getWidth() - 1; - int dstMinY = imRas.getMinY(); - int dstMaxY = dstMinY + imRas.getHeight() - 1; - - // Create a child raster exposing only the desired source bands - if (sourceBands != null) { - rowRas = - rowRas.createWritableChild(0, 0, width, 1, 0, 0, sourceBands); - } - - // Create a child raster exposing only the desired dest bands - if (destinationBands != null) { - imRas = - imRas.createWritableChild( - 0, - 0, - imRas.getWidth(), - imRas.getHeight(), - 0, - 0, - destinationBands); - - } - - for (int srcY = 0; srcY < height; srcY++) { - // Read the row - try { - stream.readFully(rowBuf); - } catch (IOException e) { - throw new IIOException("Error reading line " + srcY, e); - } - - // Reject rows that lie outside the source region, - // or which aren't part of the subsampling - if ((srcY < sourceRegion.y) - || (srcY >= sourceRegion.y + sourceRegion.height) - || (((srcY - sourceRegion.y) % sourceYSubsampling) != 0)) { - continue; - } - - // Determine where the row will go in the destination - int dstY = - destinationOffset.y - + (srcY - sourceRegion.y) / sourceYSubsampling; - if (dstY < dstMinY) { - continue; // The row is above imRas - } - if (dstY > dstMaxY) { - break; // We're done with the image - } - - // Copy each (subsampled) source pixel into imRas - for (int srcX = sourceRegion.x; - srcX < sourceRegion.x + sourceRegion.width; - srcX++) { - if (((srcX - sourceRegion.x) % sourceXSubsampling) != 0) { - continue; - } - int dstX = - destinationOffset.x - + (srcX - sourceRegion.x) / sourceXSubsampling; - if (dstX < dstMinX) { - continue; // The pixel is to the left of imRas - } - if (dstX > dstMaxX) { - break; // We're done with the row - } - - // Copy the pixel, sub-banding is done automatically - rowRas.getPixel(srcX, 0, pixel); - imRas.setPixel(dstX, dstY, pixel); - } - } - return dst; - } - - private void checkIndex(int imageIndex) { - if (imageIndex != 0) { - throw new IndexOutOfBoundsException("bad image index"); - } - } - - private void readHeader() throws IIOException { - - if (header != null) return; - - logger.log(Level.FINE, "WAL read header"); - - if (stream == null) { - if (this.input == null) { - throw new IllegalStateException("No input stream"); - } - stream = (ImageInputStream) input; - } - - byte[] buffer = new byte[WAL.HEADER_SIZE]; - - try { - stream.readFully(buffer); - this.header = new WAL.Header(buffer); - logger.log( - Level.FINE, - "WAL width: " - + header.getWidth() - + " height: " - + header.getHeight()); - } catch (IOException e) { - throw new IIOException("Error reading quake2 WAL header", e); - } - } -}
\ No newline at end of file diff --git a/src/jake2/imageio/WALImageReaderSpi.java b/src/jake2/imageio/WALImageReaderSpi.java deleted file mode 100644 index f731165..0000000 --- a/src/jake2/imageio/WALImageReaderSpi.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Created on Nov 18, 2003 - * - */ -package jake2.imageio; - -import java.io.IOException; -import java.util.Locale; -import javax.imageio.ImageReader; -import javax.imageio.spi.ImageReaderSpi; -import javax.imageio.stream.ImageInputStream; - -/** - * @author cwei - * - * Quake 2 stores textures in a proprietary 2D image format called WAL. - * While this isn't actually part of the BSP file format, - * it's essential information for loading Quake 2 maps. - * WAL textures are stored in a 8-bit indexed color format with a specific palette being used by all textures. - * (this palette is stored in the PAK data file that comes with Quake 2 e.g. pics/colormap.pcx). - * Four mip-map levels are stored for each texture at sizes decreasing by a factor of two. - * This is mostly for software rendering since most 3D APIs will automatically generate - * the mip-map levels when you create a texture. - * Each frame of an animated texture is stored as an individual WAL file, - * and the animation sequence is encoded by storing the name of the next texture in the sequence for each frame; - * texture names are stored with paths and without any extension. - * The format for the WAL file header is the wal_header structure: - * <code> - struct wal_header - { - char name[32]; // name of the texture - - uint32 width; // width (in pixels) of the largest mipmap level - uint32 height; // height (in pixels) of the largest mipmap level - - int32 offset[4]; // byte offset of the start of each of the 4 mipmap levels - - char next_name[32]; // name of the next texture in the animation - - uint32 flags; // ? - uint32 contents; // ? - uint32 value; // ? - }; - </code> - * The actual texture data is stored in an 8-bits-per-pixel raw format in a left-right, top-down order. - * <br> - * put the own ImageReaderSpi class name in the file (relative to classpath): - * <code>META-INF/services/javax.imageio.spi.ImageReaderSpi</code> - * - * */ -public class WALImageReaderSpi extends ImageReaderSpi { - - static final String vendorName = "[email protected]"; - static final String version = "1.0_beta"; - static final String[] names = { "quake2 wal" }; - static final String[] suffixes = { "wal" }; - static final String[] MIMETypes = { "image/x-quake2-wal" }; - static final String readerClassName = "jake2.imageio.WALImageReader"; - static final String[] writerSpiNames = null; // { "jake2.imageio.WALImageWriterSpi" }; - - // Metadata formats, more information below - static final boolean supportsStandardStreamMetadataFormat = false; - static final String nativeStreamMetadataFormatName = null; - - static final String nativeStreamMetadataFormatClassName = null; - static final String[] extraStreamMetadataFormatNames = null; - static final String[] extraStreamMetadataFormatClassNames = null; - static final boolean supportsStandardImageMetadataFormat = false; - static final String nativeImageMetadataFormatName = - "jake2.imageio.WALMetaData_1.0"; - static final String nativeImageMetadataFormatClassName = null; // "jake2.imageio.WALMetadata"; - static final String[] extraImageMetadataFormatNames = null; - static final String[] extraImageMetadataFormatClassNames = null; - - public WALImageReaderSpi() { - - super( - vendorName, - version, - names, - suffixes, - MIMETypes, - readerClassName, - ImageReaderSpi.STANDARD_INPUT_TYPE, // Accept ImageInputStreams - writerSpiNames, - supportsStandardStreamMetadataFormat, - nativeStreamMetadataFormatName, - nativeStreamMetadataFormatClassName, - extraStreamMetadataFormatNames, - extraStreamMetadataFormatClassNames, - supportsStandardImageMetadataFormat, - nativeImageMetadataFormatName, - nativeImageMetadataFormatClassName, - extraImageMetadataFormatNames, - extraImageMetadataFormatClassNames); - } - - public boolean canDecodeInput(Object source) throws IOException { - if (!(source instanceof ImageInputStream)) { - return false; - } - ImageInputStream stream = (ImageInputStream)source; - byte[] buffer = new byte[WAL.HEADER_SIZE]; - try { - stream.mark(); - stream.readFully(buffer); - stream.reset(); - // buffer will be converted to members and header checked - WAL.Header wal = new WAL.Header(buffer); - } catch (IllegalArgumentException e) { - return false; - } - return true; - } - - /** - * returns a WALImageReader - */ - public ImageReader createReaderInstance(Object extension) - throws IOException { - return new WALImageReader(this); - } - - public String getDescription(Locale locale) { - return "id-software's Quake2 wal format for textures"; - } -} diff --git a/src/jake2/logging.properties b/src/jake2/logging.properties deleted file mode 100644 index 41c2fad..0000000 --- a/src/jake2/logging.properties +++ /dev/null @@ -1,41 +0,0 @@ -# Comma separated list of log Handler classes -# These handlers will be installed during VM -# startup. -handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler - -# Default global logging level. -.level= INFO - -# Handler specific properties. -# Describes specific configuration info for -# Handlers. - -java.util.logging.FileHandler.level = ALL -# -# location is the global temp directory (linux: /tmp/jake2_0.log) -# %t means system temp dir -# %g means log file number -# -java.util.logging.FileHandler.pattern = %t/jake2_%g.log -# ca. 100KByte -java.util.logging.FileHandler.limit = 100000 -# max 1 file -java.util.logging.FileHandler.count = 1 -java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter -# java.util.logging.XMLFormatter -# java.util.logging.FileHandler.append = true - - -# Limit the message that are printed on the -# console to INFO and above. -java.util.logging.ConsoleHandler.level = ALL -java.util.logging.ConsoleHandler.formatter = - java.util.logging.SimpleFormatter - - -# For example, set the default jake2 package log level -jake2.level = INFO - -# other individual package or class configs -# jake2.imageio.level = FINEST -# jake2.qcommon.FS.level = FINEST
\ No newline at end of file diff --git a/src/jake2/qcommon/CM.java b/src/jake2/qcommon/CM.java index 8c5a203..1c3a756 100644 --- a/src/jake2/qcommon/CM.java +++ b/src/jake2/qcommon/CM.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 02.01.2004 by RST. -// $Id: CM.java,v 1.2 2004-07-08 15:58:46 hzi Exp $ +// $Id: CM.java,v 1.3 2004-07-09 06:50:50 hzi Exp $ package jake2.qcommon; @@ -189,7 +189,7 @@ public class CM extends Game { Loads in the map and all submodels ================== */ - public static cmodel_t CM_LoadMap(String name, boolean clientload, intwrap checksum) { + public static cmodel_t CM_LoadMap(String name, boolean clientload, int checksum[]) { Com.DPrintf("CM_LoadMap...\n"); byte buf[]; int i; @@ -200,7 +200,7 @@ public class CM extends Game { if (0 == strcmp(map_name, name) && (clientload || 0 == Cvar.VariableValue("flushmap"))) { - checksum.i = last_checksum; + checksum[0] = last_checksum; if (!clientload) { Arrays.fill(portalopen, false); @@ -222,7 +222,7 @@ public class CM extends Game { numleafs = 1; numclusters = 1; numareas = 1; - checksum.i = 0; + checksum[0] = 0; return map_cmodels[0]; // cinematic servers won't have anything at all } @@ -240,7 +240,7 @@ public class CM extends Game { ByteBuffer bbuf = ByteBuffer.wrap(buf); last_checksum = MD4.Com_BlockChecksum(buf, length); - checksum.i = last_checksum; + checksum[0] = last_checksum; header = new qfiles.dheader_t(bbuf.slice()); @@ -796,7 +796,6 @@ public class CM extends Game { if (l.filelen > MAX_MAP_VISIBILITY) Com.Error(ERR_DROP, "Map has too large visibility lump"); - //was: memcpy(map_visibility, cmod_base + l.fileofs, l.filelen); System.arraycopy(cmod_base, l.fileofs, map_visibility, 0, l.filelen); ByteBuffer bb = ByteBuffer.wrap(map_visibility, 0, l.filelen); @@ -1074,7 +1073,7 @@ public class CM extends Game { } } - public static int CM_BoxLeafnums_headnode(float[] mins, float[] maxs, int list[], int listsize, int headnode, intwrap topnode) { + public static int CM_BoxLeafnums_headnode(float[] mins, float[] maxs, int list[], int listsize, int headnode, int topnode[]) { leaf_list = list; leaf_count = 0; leaf_maxcount = listsize; @@ -1086,22 +1085,23 @@ public class CM extends Game { CM_BoxLeafnums_r(headnode); if (topnode != null) - topnode.i = leaf_topnode; + topnode[0] = leaf_topnode; return leaf_count; } - public static int CM_BoxLeafnums(float[] mins, float[] maxs, int list[], int listsize, intwrap topnode) { + public static int CM_BoxLeafnums(float[] mins, float[] maxs, int list[], int listsize, int topnode[]) { return CM_BoxLeafnums_headnode(mins, maxs, list, listsize, map_cmodels[0].headnode, topnode); } - public static class intwrap { + /* + public static class intwrap1 { public intwrap(int i) { this.i = i; } public int i; } - + */ /* ================== CM_PointContents @@ -1539,10 +1539,10 @@ public class CM extends Game { c2[i] += 1; } - intwrap tn = new intwrap(topnode); + int tn[] = {topnode}; numleafs = CM_BoxLeafnums_headnode(c1, c2, leafs, 1024, headnode, tn); - topnode = tn.i; + topnode = tn[0]; for (i = 0; i < numleafs; i++) { CM_TestInLeaf(leafs[i]); if (trace_trace.allsolid) diff --git a/src/jake2/qcommon/CRC.java b/src/jake2/qcommon/CRC.java new file mode 100644 index 0000000..ca22d9b --- /dev/null +++ b/src/jake2/qcommon/CRC.java @@ -0,0 +1,383 @@ +/* +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 25.01.2004 by RST. +// $Id: CRC.java,v 1.1 2004-07-09 06:50:49 hzi Exp $ +package jake2.qcommon; + +import jake2.util.Vargs; + +public class CRC +{ + + public final static short CRC_INIT_VALUE= (short) 0xffff; + public final static short CRC_XOR_VALUE= (short) 0x0000; + + private static int crctable[]= + { + 0x0000, + 0x1021, + 0x2042, + 0x3063, + 0x4084, + 0x50a5, + 0x60c6, + 0x70e7, + 0x8108, + 0x9129, + 0xa14a, + 0xb16b, + 0xc18c, + 0xd1ad, + 0xe1ce, + 0xf1ef, + 0x1231, + 0x0210, + 0x3273, + 0x2252, + 0x52b5, + 0x4294, + 0x72f7, + 0x62d6, + 0x9339, + 0x8318, + 0xb37b, + 0xa35a, + 0xd3bd, + 0xc39c, + 0xf3ff, + 0xe3de, + 0x2462, + 0x3443, + 0x0420, + 0x1401, + 0x64e6, + 0x74c7, + 0x44a4, + 0x5485, + 0xa56a, + 0xb54b, + 0x8528, + 0x9509, + 0xe5ee, + 0xf5cf, + 0xc5ac, + 0xd58d, + 0x3653, + 0x2672, + 0x1611, + 0x0630, + 0x76d7, + 0x66f6, + 0x5695, + 0x46b4, + 0xb75b, + 0xa77a, + 0x9719, + 0x8738, + 0xf7df, + 0xe7fe, + 0xd79d, + 0xc7bc, + 0x48c4, + 0x58e5, + 0x6886, + 0x78a7, + 0x0840, + 0x1861, + 0x2802, + 0x3823, + 0xc9cc, + 0xd9ed, + 0xe98e, + 0xf9af, + 0x8948, + 0x9969, + 0xa90a, + 0xb92b, + 0x5af5, + 0x4ad4, + 0x7ab7, + 0x6a96, + 0x1a71, + 0x0a50, + 0x3a33, + 0x2a12, + 0xdbfd, + 0xcbdc, + 0xfbbf, + 0xeb9e, + 0x9b79, + 0x8b58, + 0xbb3b, + 0xab1a, + 0x6ca6, + 0x7c87, + 0x4ce4, + 0x5cc5, + 0x2c22, + 0x3c03, + 0x0c60, + 0x1c41, + 0xedae, + 0xfd8f, + 0xcdec, + 0xddcd, + 0xad2a, + 0xbd0b, + 0x8d68, + 0x9d49, + 0x7e97, + 0x6eb6, + 0x5ed5, + 0x4ef4, + 0x3e13, + 0x2e32, + 0x1e51, + 0x0e70, + 0xff9f, + 0xefbe, + 0xdfdd, + 0xcffc, + 0xbf1b, + 0xaf3a, + 0x9f59, + 0x8f78, + 0x9188, + 0x81a9, + 0xb1ca, + 0xa1eb, + 0xd10c, + 0xc12d, + 0xf14e, + 0xe16f, + 0x1080, + 0x00a1, + 0x30c2, + 0x20e3, + 0x5004, + 0x4025, + 0x7046, + 0x6067, + 0x83b9, + 0x9398, + 0xa3fb, + 0xb3da, + 0xc33d, + 0xd31c, + 0xe37f, + 0xf35e, + 0x02b1, + 0x1290, + 0x22f3, + 0x32d2, + 0x4235, + 0x5214, + 0x6277, + 0x7256, + 0xb5ea, + 0xa5cb, + 0x95a8, + 0x8589, + 0xf56e, + 0xe54f, + 0xd52c, + 0xc50d, + 0x34e2, + 0x24c3, + 0x14a0, + 0x0481, + 0x7466, + 0x6447, + 0x5424, + 0x4405, + 0xa7db, + 0xb7fa, + 0x8799, + 0x97b8, + 0xe75f, + 0xf77e, + 0xc71d, + 0xd73c, + 0x26d3, + 0x36f2, + 0x0691, + 0x16b0, + 0x6657, + 0x7676, + 0x4615, + 0x5634, + 0xd94c, + 0xc96d, + 0xf90e, + 0xe92f, + 0x99c8, + 0x89e9, + 0xb98a, + 0xa9ab, + 0x5844, + 0x4865, + 0x7806, + 0x6827, + 0x18c0, + 0x08e1, + 0x3882, + 0x28a3, + 0xcb7d, + 0xdb5c, + 0xeb3f, + 0xfb1e, + 0x8bf9, + 0x9bd8, + 0xabbb, + 0xbb9a, + 0x4a75, + 0x5a54, + 0x6a37, + 0x7a16, + 0x0af1, + 0x1ad0, + 0x2ab3, + 0x3a92, + 0xfd2e, + 0xed0f, + 0xdd6c, + 0xcd4d, + 0xbdaa, + 0xad8b, + 0x9de8, + 0x8dc9, + 0x7c26, + 0x6c07, + 0x5c64, + 0x4c45, + 0x3ca2, + 0x2c83, + 0x1ce0, + 0x0cc1, + 0xef1f, + 0xff3e, + 0xcf5d, + 0xdf7c, + 0xaf9b, + 0xbfba, + 0x8fd9, + 0x9ff8, + 0x6e17, + 0x7e36, + 0x4e55, + 0x5e74, + 0x2e93, + 0x3eb2, + 0x0ed1, + 0x1ef0 }; + + static short CRC_Block(byte start[], int count) + { + short crc= CRC_INIT_VALUE; + + int ndx= 0; + + while (count-- > 0) + crc= (short) ((crc << 8) ^ crctable[0xff & ((crc >> 8) ^ start[ndx++])]); + + return crc; + } + + public static void main(String[] args) + { + byte data[]= + { + (byte) 0x71, + (byte) 0xa9, + (byte) 0x05, + (byte) 0xce, + (byte) 0x8d, + (byte) 0x75, + (byte) 0x28, + (byte) 0xc8, + (byte) 0xba, + (byte) 0x97, + + (byte) 0x45, + (byte) 0xe9, + (byte) 0x8a, + (byte) 0xe0, + (byte) 0x37, + (byte) 0xbd, + (byte) 0x6c, + (byte) 0x6d, + (byte) 0x67, + (byte) 0x4a, + (byte) 0x21 }; + System.out.println("crc:" + (CRC_Block(data, 21) & 0xffff)); + System.out.println("----"); + for (int n=0; n < 5; n++) + System.out.println("seq:" + (Com.BlockSequenceCRCByte( data,0, 21,n*10) & 0xff)); + + } + +/* c test: + * + * D:\Rene\gamesrc\quake2-3.21\qcommon>crc + * crc=-12353 + * ---- + * seq:215 + * seq:252 + * seq:164 + * seq:202 + * seq:201 + * +int main() +{ + byte data[21] = + { + 0x71, + 0xa9, + 0x05, + 0xce, + 0x8d, + 0x75, + 0x28, + 0xc8, + 0xba, + 0x97, + + 0x45, + 0xe9, + 0x8a, + 0xe0, + 0x37, + 0xbd, + 0x6c, + 0x6d, + 0x67, + 0x4a, 0x21 }; + int n=0; + + printf("crc=%d\n", (short) CRC_Block(&data, 21)); + + printf("----\n"); + for (n=0; n < 5; n++) + printf("seq:%d\n", COM_BlockSequenceCRCByte( &data,21, n*10) ); +} + */ + +} diff --git a/src/jake2/qcommon/Com.java b/src/jake2/qcommon/Com.java index c938fdb..705a009 100644 --- a/src/jake2/qcommon/Com.java +++ b/src/jake2/qcommon/Com.java @@ -2,7 +2,7 @@ * Com.java * Copyright (C) 2003 * - * $Id: Com.java,v 1.2 2004-07-08 15:58:46 hzi Exp $ + * $Id: Com.java,v 1.3 2004-07-09 06:50:50 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -38,15 +38,17 @@ import java.io.*; /** * Com - * TODO complete Com interface + * */ -public final class Com { - +public final class Com +{ + static int com_argc; - static String[] com_argv = new String[Defines.MAX_NUM_ARGVS]; - - public abstract static class RD_Flusher { - public abstract void rd_flush(int target, byte [] buffer); + static String[] com_argv= new String[Defines.MAX_NUM_ARGVS]; + + public abstract static class RD_Flusher + { + public abstract void rd_flush(int target, byte[] buffer); } static int rd_target; @@ -54,80 +56,95 @@ public final class Com { static int rd_buffersize; static RD_Flusher rd_flusher; - public static void BeginRedirect(int target, byte [] buffer, int buffersize, RD_Flusher flush) { + public static void BeginRedirect(int target, byte[] buffer, int buffersize, RD_Flusher flush) + { if (0 == target || null == buffer || 0 == buffersize || null == flush) return; - rd_target = target; - rd_buffer = buffer; - rd_buffersize = buffersize; - rd_flusher = flush; + rd_target= target; + rd_buffer= buffer; + rd_buffersize= buffersize; + rd_flusher= flush; - rd_buffer = null; + rd_buffer= null; } - public static void EndRedirect() { + public static void EndRedirect() + { rd_flusher.rd_flush(rd_target, rd_buffer); - rd_target = 0; - rd_buffer = null; - rd_buffersize = 0; - rd_flusher = null; + rd_target= 0; + rd_buffer= null; + rd_buffersize= 0; + rd_flusher= null; } - static boolean recursive = false; + static boolean recursive= false; - static String msg = ""; + static String msg= ""; // helper class to replace the pointer-pointer - public static class ParseHelp { + public static class ParseHelp + { - public ParseHelp(String in, int offset) { + public ParseHelp(String in, int offset) + { this(in.toCharArray(), offset); } - public ParseHelp(String in) { - if (in == null) { - data = null; + public ParseHelp(String in) + { + if (in == null) + { + data= null; } - else { - data = in.toCharArray(); + else + { + data= in.toCharArray(); } - index = 0; + index= 0; } - public ParseHelp(char in[]) { + public ParseHelp(char in[]) + { this(in, 0); } - public ParseHelp(char in[], int offset) { + public ParseHelp(char in[], int offset) + { if (in == null || in.length == 0) - data = null; + data= null; else - data = in; - index = offset; + data= in; + index= offset; } - public char getchar() { + public char getchar() + { // faster than if - try { + try + { return data[index]; } - catch (Exception e) { - data = null; + catch (Exception e) + { + data= null; // last char return 0; } } - public char nextchar() { + public char nextchar() + { // faster than if - try { + try + { index++; return data[index]; } - catch (Exception e) { - data = null; + catch (Exception e) + { + data= null; // avoid int wraps; index--; // last char @@ -135,144 +152,170 @@ public final class Com { } } - public boolean isEof() { + public boolean isEof() + { return data == null; } public int index; public char data[]; - public char skipwhites() { + public char skipwhites() + { char c; - while (((c = getchar()) <= ' ') && c != 0) + while (((c= getchar()) <= ' ') && c != 0) index++; return c; } - public char skipwhitestoeol() { + public char skipwhitestoeol() + { char c; - while (((c = getchar()) <= ' ') && c != '\n' && c != 0) + while (((c= getchar()) <= ' ') && c != '\n' && c != 0) index++; return c; } - public char skiptoeol() { + public char skiptoeol() + { char c; - while ((c = getchar()) != '\n' && c != 0) + while ((c= getchar()) != '\n' && c != 0) index++; return c; } } - public static char com_token[] = new char[Defines.MAX_TOKEN_CHARS]; + public static char com_token[]= new char[Defines.MAX_TOKEN_CHARS]; // See GameSpanw.ED_ParseEdict() to see how to use it now. // works perfect ! - public static String Parse(ParseHelp hlp) { + public static String Parse(ParseHelp hlp) + { int c; - int len = 0; - len = 0; + int len= 0; + len= 0; - com_token[0] = 0; + com_token[0]= 0; - if (hlp.data == null) { + if (hlp.data == null) + { return ""; } // skip whitespace hlp.skipwhites(); - if (hlp.isEof()) { + if (hlp.isEof()) + { return ""; } // skip // comments - if (hlp.getchar() == '/') { - if (hlp.nextchar() == '/') { - if ((hlp.skiptoeol() == 0) || (hlp.skipwhites() == 0)) { + if (hlp.getchar() == '/') + { + if (hlp.nextchar() == '/') + { + if ((hlp.skiptoeol() == 0) || (hlp.skipwhites() == 0)) + { return ""; } } - else { - com_token[len] = '/'; + else + { + com_token[len]= '/'; len++; } } // handle quoted strings specially - if (hlp.getchar() == '\"') { - while (true) { - c = hlp.nextchar(); - if (c == '\"' || c == 0) { + if (hlp.getchar() == '\"') + { + while (true) + { + c= hlp.nextchar(); + if (c == '\"' || c == 0) + { hlp.nextchar(); - com_token[len] = '?'; + com_token[len]= '?'; return new String(com_token, 0, len); } - if (len < Defines.MAX_TOKEN_CHARS) { - com_token[len] = hlp.getchar(); + if (len < Defines.MAX_TOKEN_CHARS) + { + com_token[len]= hlp.getchar(); len++; } } } // parse a regular word - do { - if (len < Defines.MAX_TOKEN_CHARS) { - com_token[len] = hlp.getchar(); + do + { + if (len < Defines.MAX_TOKEN_CHARS) + { + com_token[len]= hlp.getchar(); len++; } - c = hlp.nextchar(); + c= hlp.nextchar(); } while (c > 32); - if (len == Defines.MAX_TOKEN_CHARS) { + if (len == Defines.MAX_TOKEN_CHARS) + { Printf("Token exceeded " + Defines.MAX_TOKEN_CHARS + " chars, discarded.\n"); - len = 0; + len= 0; } // trigger the eof hlp.skipwhites(); - com_token[len] = 0; + com_token[len]= 0; return new String(com_token, 0, len); } - public static xcommand_t Error_f = new xcommand_t() { - public void execute() throws longjmpException { + public static xcommand_t Error_f= new xcommand_t() + { + public void execute() throws longjmpException + { Error(Globals.ERR_FATAL, Cmd.Argv(1)); } }; - public static void Error(int code, String fmt) throws longjmpException { + public static void Error(int code, String fmt) throws longjmpException + { Error(code, fmt, null); } - public static void Error(int code, String fmt, Vargs vargs) throws longjmpException { + public static void Error(int code, String fmt, Vargs vargs) throws longjmpException + { // va_list argptr; // static char msg[MAXPRINTMSG]; - if (recursive) { + if (recursive) + { Sys.Error("recursive error after: " + msg); } - recursive = true; + recursive= true; - msg = sprintf(fmt, vargs); + msg= sprintf(fmt, vargs); - if (code == Defines.ERR_DISCONNECT) { + if (code == Defines.ERR_DISCONNECT) + { CL.Drop(); - recursive = false; + recursive= false; throw new longjmpException(); } - else if (code == Defines.ERR_DROP) { + else if (code == Defines.ERR_DROP) + { Com.Printf("********************\nERROR: " + msg + "\n********************\n"); SV_MAIN.SV_Shutdown("Server crashed: " + msg + "\n", false); CL.Drop(); - recursive = false; + recursive= false; throw new longjmpException(); } - else { + else + { SV_MAIN.SV_Shutdown("Server fatal crashed: %s" + msg + "\n", false); CL.Shutdown(); } @@ -284,43 +327,51 @@ public final class Com { * Com_InitArgv checks the number of command line arguments * and copies all arguments with valid length into com_argv. */ - static void InitArgv(String[] args) throws longjmpException { + static void InitArgv(String[] args) throws longjmpException + { - if (args.length > Globals.MAX_NUM_ARGVS) { + if (args.length > Globals.MAX_NUM_ARGVS) + { Com.Error(Globals.ERR_FATAL, "argc > MAX_NUM_ARGVS"); } - Com.com_argc = args.length; - for (int i = 0; i < Com.com_argc; i++) { + Com.com_argc= args.length; + for (int i= 0; i < Com.com_argc; i++) + { if (args[i].length() >= Globals.MAX_TOKEN_CHARS) - Com.com_argv[i] = ""; + Com.com_argv[i]= ""; else - Com.com_argv[i] = args[i]; + Com.com_argv[i]= args[i]; } } - public static void DPrintf(String fmt) { + public static void DPrintf(String fmt) + { DPrintf(fmt, null); } - - public static void d(String fmt) { + + public static void d(String fmt) + { DPrintf(fmt + "\n", null); } - - public static void Printf(String fmt) { + + public static void Printf(String fmt) + { Printf(fmt, null); } - public static void DPrintf(String fmt, Vargs vargs) { + public static void DPrintf(String fmt, Vargs vargs) + { if (Globals.developer == null || Globals.developer.value == 0) return; // don't confuse non-developers with techie stuff... Printf(fmt, vargs); } - public static void Printf(String fmt, Vargs vargs) { + public static void Printf(String fmt, Vargs vargs) + { // TODO Com.Printf ist nur zum testen - String msg = sprintf(fmt, vargs); + String msg= sprintf(fmt, vargs); if (rd_target != 0) { @@ -328,7 +379,7 @@ public final class Com { { rd_flusher.rd_flush(rd_target, rd_buffer); // *rd_buffer = 0; - rd_buffer[rd_buffersize] = '\0'; + rd_buffer[rd_buffersize]= '\0'; } // TODO handle rd_buffer // strcat(rd_buffer, msg); @@ -336,7 +387,7 @@ public final class Com { } Console.Print(msg); - + // also echo to debugging console Sys.ConsoleOutput(msg); @@ -344,14 +395,14 @@ public final class Com { if (Globals.logfile_active != null && Globals.logfile_active.value != 0) { String name; - + if (Globals.logfile == null) { - name = FS.Gamedir() + "/qconsole.log"; + name= FS.Gamedir() + "/qconsole.log"; if (Globals.logfile_active.value > 2) try { - Globals.logfile = new RandomAccessFile(name, "a"); + Globals.logfile= new RandomAccessFile(name, "a"); } catch (FileNotFoundException e) { @@ -361,7 +412,7 @@ public final class Com { else try { - Globals.logfile = new RandomAccessFile(name, "rw"); + Globals.logfile= new RandomAccessFile(name, "rw"); } catch (FileNotFoundException e1) { @@ -379,58 +430,68 @@ public final class Com { // TODO: do quake2 error handling! e.printStackTrace(); } - if (Globals.logfile_active.value > 1) - ; // do nothing - // fflush (logfile); // force it to save every time + if (Globals.logfile_active.value > 1); // do nothing + // fflush (logfile); // force it to save every time } } - public static void Println(String fmt) { + public static void Println(String fmt) + { Printf(fmt); Printf("\n"); } - - public static void p(String fmt) { + + public static void p(String fmt) + { Printf(fmt); Printf("\n"); } - public static String sprintf(String fmt, Vargs vargs) { - String msg = ""; - if (vargs == null || vargs.size() == 0) { - msg = fmt; + public static String sprintf(String fmt, Vargs vargs) + { + String msg= ""; + if (vargs == null || vargs.size() == 0) + { + msg= fmt; } - else { - msg = new PrintfFormat(fmt).sprintf(vargs.toArray()); + else + { + msg= new PrintfFormat(fmt).sprintf(vargs.toArray()); } return msg; } - public static int ServerState() { + public static int ServerState() + { return Globals.server_state; } - public static int Argc() { + public static int Argc() + { return Com.com_argc; } - public static String Argv(int arg) { + public static String Argv(int arg) + { if (arg < 0 || arg >= Com.com_argc || Com.com_argv[arg].length() < 1) return ""; return Com.com_argv[arg]; } - public static void ClearArgv(int arg) { + public static void ClearArgv(int arg) + { if (arg < 0 || arg >= Com.com_argc || Com.com_argv[arg].length() < 1) return; - Com.com_argv[arg] = ""; + Com.com_argv[arg]= ""; } - public static void Quit() { + public static void Quit() + { SV_MAIN.SV_Shutdown("Server quit\n", false); CL.Shutdown(); - if (Globals.logfile != null) { + if (Globals.logfile != null) + { try { Globals.logfile.close(); @@ -438,25 +499,1036 @@ public final class Com { catch (IOException e) { } - Globals.logfile = null; + Globals.logfile= null; } Sys.Quit(); } - public static void SetServerState(int i) { - Globals.server_state = i; + Globals.server_state= i; } - public static int BlockChecksum(byte[] buf, int length) { return MD4.Com_BlockChecksum(buf, length); } - public static void StripExtension(String string, String string2) { - // TODO implement! + public static void StripExtension(String string, String string2) + { + // TODO implement StripExtension } + + /** + * CRC table. + */ + + static int chktbl[]= + { + 0x84, + 0x47, + 0x51, + 0xc1, + 0x93, + 0x22, + 0x21, + 0x24, + 0x2f, + 0x66, + 0x60, + 0x4d, + 0xb0, + 0x7c, + 0xda, + 0x88, + 0x54, + 0x15, + 0x2b, + 0xc6, + 0x6c, + 0x89, + 0xc5, + 0x9d, + 0x48, + 0xee, + 0xe6, + 0x8a, + 0xb5, + 0xf4, + 0xcb, + 0xfb, + 0xf1, + 0x0c, + 0x2e, + 0xa0, + 0xd7, + 0xc9, + 0x1f, + 0xd6, + 0x06, + 0x9a, + 0x09, + 0x41, + 0x54, + 0x67, + 0x46, + 0xc7, + 0x74, + 0xe3, + 0xc8, + 0xb6, + 0x5d, + 0xa6, + 0x36, + 0xc4, + 0xab, + 0x2c, + 0x7e, + 0x85, + 0xa8, + 0xa4, + 0xa6, + 0x4d, + 0x96, + 0x19, + 0x19, + 0x9a, + 0xcc, + 0xd8, + 0xac, + 0x39, + 0x5e, + 0x3c, + 0xf2, + 0xf5, + 0x5a, + 0x72, + 0xe5, + 0xa9, + 0xd1, + 0xb3, + 0x23, + 0x82, + 0x6f, + 0x29, + 0xcb, + 0xd1, + 0xcc, + 0x71, + 0xfb, + 0xea, + 0x92, + 0xeb, + 0x1c, + 0xca, + 0x4c, + 0x70, + 0xfe, + 0x4d, + 0xc9, + 0x67, + 0x43, + 0x47, + 0x94, + 0xb9, + 0x47, + 0xbc, + 0x3f, + 0x01, + 0xab, + 0x7b, + 0xa6, + 0xe2, + 0x76, + 0xef, + 0x5a, + 0x7a, + 0x29, + 0x0b, + 0x51, + 0x54, + 0x67, + 0xd8, + 0x1c, + 0x14, + 0x3e, + 0x29, + 0xec, + 0xe9, + 0x2d, + 0x48, + 0x67, + 0xff, + 0xed, + 0x54, + 0x4f, + 0x48, + 0xc0, + 0xaa, + 0x61, + 0xf7, + 0x78, + 0x12, + 0x03, + 0x7a, + 0x9e, + 0x8b, + 0xcf, + 0x83, + 0x7b, + 0xae, + 0xca, + 0x7b, + 0xd9, + 0xe9, + 0x53, + 0x2a, + 0xeb, + 0xd2, + 0xd8, + 0xcd, + 0xa3, + 0x10, + 0x25, + 0x78, + 0x5a, + 0xb5, + 0x23, + 0x06, + 0x93, + 0xb7, + 0x84, + 0xd2, + 0xbd, + 0x96, + 0x75, + 0xa5, + 0x5e, + 0xcf, + 0x4e, + 0xe9, + 0x50, + 0xa1, + 0xe6, + 0x9d, + 0xb1, + 0xe3, + 0x85, + 0x66, + 0x28, + 0x4e, + 0x43, + 0xdc, + 0x6e, + 0xbb, + 0x33, + 0x9e, + 0xf3, + 0x0d, + 0x00, + 0xc1, + 0xcf, + 0x67, + 0x34, + 0x06, + 0x7c, + 0x71, + 0xe3, + 0x63, + 0xb7, + 0xb7, + 0xdf, + 0x92, + 0xc4, + 0xc2, + 0x25, + 0x5c, + 0xff, + 0xc3, + 0x6e, + 0xfc, + 0xaa, + 0x1e, + 0x2a, + 0x48, + 0x11, + 0x1c, + 0x36, + 0x68, + 0x78, + 0x86, + 0x79, + 0x30, + 0xc3, + 0xd6, + 0xde, + 0xbc, + 0x3a, + 0x2a, + 0x6d, + 0x1e, + 0x46, + 0xdd, + 0xe0, + 0x80, + 0x1e, + 0x44, + 0x3b, + 0x6f, + 0xaf, + 0x31, + 0xda, + 0xa2, + 0xbd, + 0x77, + 0x06, + 0x56, + 0xc0, + 0xb7, + 0x92, + 0x4b, + 0x37, + 0xc0, + 0xfc, + 0xc2, + 0xd5, + 0xfb, + 0xa8, + 0xda, + 0xf5, + 0x57, + 0xa8, + 0x18, + 0xc0, + 0xdf, + 0xe7, + 0xaa, + 0x2a, + 0xe0, + 0x7c, + 0x6f, + 0x77, + 0xb1, + 0x26, + 0xba, + 0xf9, + 0x2e, + 0x1d, + 0x16, + 0xcb, + 0xb8, + 0xa2, + 0x44, + 0xd5, + 0x2f, + 0x1a, + 0x79, + 0x74, + 0x87, + 0x4b, + 0x00, + 0xc9, + 0x4a, + 0x3a, + 0x65, + 0x8f, + 0xe6, + 0x5d, + 0xe5, + 0x0a, + 0x77, + 0xd8, + 0x1a, + 0x14, + 0x41, + 0x75, + 0xb1, + 0xe2, + 0x50, + 0x2c, + 0x93, + 0x38, + 0x2b, + 0x6d, + 0xf3, + 0xf6, + 0xdb, + 0x1f, + 0xcd, + 0xff, + 0x14, + 0x70, + 0xe7, + 0x16, + 0xe8, + 0x3d, + 0xf0, + 0xe3, + 0xbc, + 0x5e, + 0xb6, + 0x3f, + 0xcc, + 0x81, + 0x24, + 0x67, + 0xf3, + 0x97, + 0x3b, + 0xfe, + 0x3a, + 0x96, + 0x85, + 0xdf, + 0xe4, + 0x6e, + 0x3c, + 0x85, + 0x05, + 0x0e, + 0xa3, + 0x2b, + 0x07, + 0xc8, + 0xbf, + 0xe5, + 0x13, + 0x82, + 0x62, + 0x08, + 0x61, + 0x69, + 0x4b, + 0x47, + 0x62, + 0x73, + 0x44, + 0x64, + 0x8e, + 0xe2, + 0x91, + 0xa6, + 0x9a, + 0xb7, + 0xe9, + 0x04, + 0xb6, + 0x54, + 0x0c, + 0xc5, + 0xa9, + 0x47, + 0xa6, + 0xc9, + 0x08, + 0xfe, + 0x4e, + 0xa6, + 0xcc, + 0x8a, + 0x5b, + 0x90, + 0x6f, + 0x2b, + 0x3f, + 0xb6, + 0x0a, + 0x96, + 0xc0, + 0x78, + 0x58, + 0x3c, + 0x76, + 0x6d, + 0x94, + 0x1a, + 0xe4, + 0x4e, + 0xb8, + 0x38, + 0xbb, + 0xf5, + 0xeb, + 0x29, + 0xd8, + 0xb0, + 0xf3, + 0x15, + 0x1e, + 0x99, + 0x96, + 0x3c, + 0x5d, + 0x63, + 0xd5, + 0xb1, + 0xad, + 0x52, + 0xb8, + 0x55, + 0x70, + 0x75, + 0x3e, + 0x1a, + 0xd5, + 0xda, + 0xf6, + 0x7a, + 0x48, + 0x7d, + 0x44, + 0x41, + 0xf9, + 0x11, + 0xce, + 0xd7, + 0xca, + 0xa5, + 0x3d, + 0x7a, + 0x79, + 0x7e, + 0x7d, + 0x25, + 0x1b, + 0x77, + 0xbc, + 0xf7, + 0xc7, + 0x0f, + 0x84, + 0x95, + 0x10, + 0x92, + 0x67, + 0x15, + 0x11, + 0x5a, + 0x5e, + 0x41, + 0x66, + 0x0f, + 0x38, + 0x03, + 0xb2, + 0xf1, + 0x5d, + 0xf8, + 0xab, + 0xc0, + 0x02, + 0x76, + 0x84, + 0x28, + 0xf4, + 0x9d, + 0x56, + 0x46, + 0x60, + 0x20, + 0xdb, + 0x68, + 0xa7, + 0xbb, + 0xee, + 0xac, + 0x15, + 0x01, + 0x2f, + 0x20, + 0x09, + 0xdb, + 0xc0, + 0x16, + 0xa1, + 0x89, + 0xf9, + 0x94, + 0x59, + 0x00, + 0xc1, + 0x76, + 0xbf, + 0xc1, + 0x4d, + 0x5d, + 0x2d, + 0xa9, + 0x85, + 0x2c, + 0xd6, + 0xd3, + 0x14, + 0xcc, + 0x02, + 0xc3, + 0xc2, + 0xfa, + 0x6b, + 0xb7, + 0xa6, + 0xef, + 0xdd, + 0x12, + 0x26, + 0xa4, + 0x63, + 0xe3, + 0x62, + 0xbd, + 0x56, + 0x8a, + 0x52, + 0x2b, + 0xb9, + 0xdf, + 0x09, + 0xbc, + 0x0e, + 0x97, + 0xa9, + 0xb0, + 0x82, + 0x46, + 0x08, + 0xd5, + 0x1a, + 0x8e, + 0x1b, + 0xa7, + 0x90, + 0x98, + 0xb9, + 0xbb, + 0x3c, + 0x17, + 0x9a, + 0xf2, + 0x82, + 0xba, + 0x64, + 0x0a, + 0x7f, + 0xca, + 0x5a, + 0x8c, + 0x7c, + 0xd3, + 0x79, + 0x09, + 0x5b, + 0x26, + 0xbb, + 0xbd, + 0x25, + 0xdf, + 0x3d, + 0x6f, + 0x9a, + 0x8f, + 0xee, + 0x21, + 0x66, + 0xb0, + 0x8d, + 0x84, + 0x4c, + 0x91, + 0x45, + 0xd4, + 0x77, + 0x4f, + 0xb3, + 0x8c, + 0xbc, + 0xa8, + 0x99, + 0xaa, + 0x19, + 0x53, + 0x7c, + 0x02, + 0x87, + 0xbb, + 0x0b, + 0x7c, + 0x1a, + 0x2d, + 0xdf, + 0x48, + 0x44, + 0x06, + 0xd6, + 0x7d, + 0x0c, + 0x2d, + 0x35, + 0x76, + 0xae, + 0xc4, + 0x5f, + 0x71, + 0x85, + 0x97, + 0xc4, + 0x3d, + 0xef, + 0x52, + 0xbe, + 0x00, + 0xe4, + 0xcd, + 0x49, + 0xd1, + 0xd1, + 0x1c, + 0x3c, + 0xd0, + 0x1c, + 0x42, + 0xaf, + 0xd4, + 0xbd, + 0x58, + 0x34, + 0x07, + 0x32, + 0xee, + 0xb9, + 0xb5, + 0xea, + 0xff, + 0xd7, + 0x8c, + 0x0d, + 0x2e, + 0x2f, + 0xaf, + 0x87, + 0xbb, + 0xe6, + 0x52, + 0x71, + 0x22, + 0xf5, + 0x25, + 0x17, + 0xa1, + 0x82, + 0x04, + 0xc2, + 0x4a, + 0xbd, + 0x57, + 0xc6, + 0xab, + 0xc8, + 0x35, + 0x0c, + 0x3c, + 0xd9, + 0xc2, + 0x43, + 0xdb, + 0x27, + 0x92, + 0xcf, + 0xb8, + 0x25, + 0x60, + 0xfa, + 0x21, + 0x3b, + 0x04, + 0x52, + 0xc8, + 0x96, + 0xba, + 0x74, + 0xe3, + 0x67, + 0x3e, + 0x8e, + 0x8d, + 0x61, + 0x90, + 0x92, + 0x59, + 0xb6, + 0x1a, + 0x1c, + 0x5e, + 0x21, + 0xc1, + 0x65, + 0xe5, + 0xa6, + 0x34, + 0x05, + 0x6f, + 0xc5, + 0x60, + 0xb1, + 0x83, + 0xc1, + 0xd5, + 0xd5, + 0xed, + 0xd9, + 0xc7, + 0x11, + 0x7b, + 0x49, + 0x7a, + 0xf9, + 0xf9, + 0x84, + 0x47, + 0x9b, + 0xe2, + 0xa5, + 0x82, + 0xe0, + 0xc2, + 0x88, + 0xd0, + 0xb2, + 0x58, + 0x88, + 0x7f, + 0x45, + 0x09, + 0x67, + 0x74, + 0x61, + 0xbf, + 0xe6, + 0x40, + 0xe2, + 0x9d, + 0xc2, + 0x47, + 0x05, + 0x89, + 0xed, + 0xcb, + 0xbb, + 0xb7, + 0x27, + 0xe7, + 0xdc, + 0x7a, + 0xfd, + 0xbf, + 0xa8, + 0xd0, + 0xaa, + 0x10, + 0x39, + 0x3c, + 0x20, + 0xf0, + 0xd3, + 0x6e, + 0xb1, + 0x72, + 0xf8, + 0xe6, + 0x0f, + 0xef, + 0x37, + 0xe5, + 0x09, + 0x33, + 0x5a, + 0x83, + 0x43, + 0x80, + 0x4f, + 0x65, + 0x2f, + 0x7c, + 0x8c, + 0x6a, + 0xa0, + 0x82, + 0x0c, + 0xd4, + 0xd4, + 0xfa, + 0x81, + 0x60, + 0x3d, + 0xdf, + 0x06, + 0xf1, + 0x5f, + 0x08, + 0x0d, + 0x6d, + 0x43, + 0xf2, + 0xe3, + 0x11, + 0x7d, + 0x80, + 0x32, + 0xc5, + 0xfb, + 0xc5, + 0xd9, + 0x27, + 0xec, + 0xc6, + 0x4e, + 0x65, + 0x27, + 0x76, + 0x87, + 0xa6, + 0xee, + 0xee, + 0xd7, + 0x8b, + 0xd1, + 0xa0, + 0x5c, + 0xb0, + 0x42, + 0x13, + 0x0e, + 0x95, + 0x4a, + 0xf2, + 0x06, + 0xc6, + 0x43, + 0x33, + 0xf4, + 0xc7, + 0xf8, + 0xe7, + 0x1f, + 0xdd, + 0xe4, + 0x46, + 0x4a, + 0x70, + 0x39, + 0x6c, + 0xd0, + 0xed, + 0xca, + 0xbe, + 0x60, + 0x3b, + 0xd1, + 0x7b, + 0x57, + 0x48, + 0xe5, + 0x3a, + 0x79, + 0xc1, + 0x69, + 0x33, + 0x53, + 0x1b, + 0x80, + 0xb8, + 0x91, + 0x7d, + 0xb4, + 0xf6, + 0x17, + 0x1a, + 0x1d, + 0x5a, + 0x32, + 0xd6, + 0xcc, + 0x71, + 0x29, + 0x3f, + 0x28, + 0xbb, + 0xf3, + 0x5e, + 0x71, + 0xb8, + 0x43, + 0xaf, + 0xf8, + 0xb9, + 0x64, + 0xef, + 0xc4, + 0xa5, + 0x6c, + 0x08, + 0x53, + 0xc7, + 0x00, + 0x10, + 0x39, + 0x4f, + 0xdd, + 0xe4, + 0xb6, + 0x19, + 0x27, + 0xfb, + 0xb8, + 0xf5, + 0x32, + 0x73, + 0xe5, + 0xcb, + 0x32, + 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, 0}; + + static byte chkb[] = new byte [60 + 4]; + + /** + * Calculates a crc checksum-sequence over an array. + */ + public static byte BlockSequenceCRCByte(byte base[], int offset, int length, int sequence) + { + int n; + int p_ndx; + short x; + + short crc; + + if (sequence < 0) + Sys.Error("sequence < 0, this shouldn't happen\n"); + + //p_ndx = (sequence % (sizeof(chktbl) - 4)); + p_ndx = (sequence % (1024 - 4)); + + //memcpy(chkb, base, length); + System.arraycopy(base, offset , chkb, 0, Math.max(60, length)); + + chkb[length]= (byte) chktbl[p_ndx + 0]; + chkb[length + 1]= (byte) chktbl[p_ndx + 1]; + chkb[length + 2]= (byte) chktbl[p_ndx + 2]; + chkb[length + 3]= (byte) chktbl[p_ndx + 3]; + + + length += 4; + + crc = CRC.CRC_Block(chkb, length); + + for (x= 0, n= 0; n < length; n++) + x += chkb[n]; + + crc ^= x; + + return (byte)(crc & 0xFF); + } + }
\ No newline at end of file diff --git a/src/jake2/qcommon/FS.java b/src/jake2/qcommon/FS.java index 98975a6..a99ae28 100644 --- a/src/jake2/qcommon/FS.java +++ b/src/jake2/qcommon/FS.java @@ -2,7 +2,7 @@ * FS.java * Copyright (C) 2003 * - * $Id: FS.java,v 1.2 2004-07-08 15:58:46 hzi Exp $ + * $Id: FS.java,v 1.3 2004-07-09 06:50:49 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -33,8 +33,6 @@ import jake2.sys.Sys; import java.io.*; import java.nio.ByteOrder; import java.util.*; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.imageio.stream.FileImageInputStream; @@ -45,8 +43,6 @@ import javax.imageio.stream.FileImageInputStream; */ public final class FS extends Globals { - private static Logger logger = Logger.getLogger(FS.class.getName()); - /* ============================================================================= @@ -120,7 +116,7 @@ public final class FS extends Globals { if (index > 0) { File f = new File(path.substring(0, index)); if (!f.mkdirs()) { - logger.log(Level.WARNING, "can't create path \"" + path + '"'); + Com.Printf("can't create path \"" + path + '"' + "\n" ); } } } @@ -448,12 +444,12 @@ public final class FS extends Globals { newfiles.put(entry.name.toLowerCase(), entry); - logger.log(Level.FINEST, i + ".\t" + entry); + //logger.log(Level.FINEST, i + ".\t" + entry); } } catch (IOException e) { - logger.log(Level.WARNING, e.toString()); + //logger.log(Level.WARNING, e.toString()); return null; } @@ -577,7 +573,7 @@ public final class FS extends Globals { fs_searchpaths.pack.handle.close(); } catch (IOException e) { - logger.log(Level.WARNING, e.toString()); + //logger.log(Level.WARNING, e.toString()); } // clear the hashtable fs_searchpaths.pack.files.clear(); diff --git a/src/jake2/qcommon/MD4.java b/src/jake2/qcommon/MD4.java index 45fdf7c..2c01f08 100644 --- a/src/jake2/qcommon/MD4.java +++ b/src/jake2/qcommon/MD4.java @@ -19,11 +19,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 02.02.2004 by RST. -// $Id: MD4.java,v 1.1 2004-07-07 19:59:31 hzi Exp $ +// $Id: MD4.java,v 1.2 2004-07-09 06:50:49 hzi Exp $ package jake2.qcommon; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.security.MessageDigest; import jake2.*; @@ -295,17 +296,18 @@ public class MD4 extends MessageDigest implements Cloneable { return t << s | t >>> (32 - s); } + /** + * Bugfixed, now works prima (RST). + */ public static int Com_BlockChecksum(byte[] buffer, int length) { - byte digest[] = new byte[16]; + int val; MD4 md4 = new MD4(); md4.engineUpdate(buffer, 0, length); - byte data[] = md4.engineDigest(); - Com.Printf("md4: " + Lib.hexDump(data, 16, false)); - + byte data[] = md4.engineDigest(); ByteBuffer bb = ByteBuffer.wrap(data); - //val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3]; + bb.order(ByteOrder.LITTLE_ENDIAN); val = bb.getInt() ^ bb.getInt() ^ bb.getInt() ^ bb.getInt(); return val; } diff --git a/src/jake2/qcommon/Qcommon.java b/src/jake2/qcommon/Qcommon.java index 3da48ca..9f653d4 100644 --- a/src/jake2/qcommon/Qcommon.java +++ b/src/jake2/qcommon/Qcommon.java @@ -2,7 +2,7 @@ * Qcommon.java * Copyright 2003 * - * $Id: Qcommon.java,v 1.3 2004-07-08 20:24:48 hzi Exp $ + * $Id: Qcommon.java,v 1.4 2004-07-09 06:50:49 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -28,8 +28,6 @@ package jake2.qcommon; import jake2.Globals; import jake2.client.*; import jake2.game.Cmd; -import jake2.game.EntThinkAdapter; -import jake2.game.GamePWeapon; import jake2.game.Swap; import jake2.server.SV_MAIN; import jake2.sys.NET; @@ -47,95 +45,11 @@ public final class Qcommon extends Globals { public static final String BUILDSTRING = "Java"; public static final String CPUSTRING = "jvm"; - - /** - * This function initializes the different subsystems of - * the game engine. The setjmp/longjmp mechanism of the original - * was replaced with exceptions. - * @param args the original unmodified command line arguments - */ - public static void InitForTestMap(String[] args) { - try { - - // prepare enough of the subsystems to handle - // cvar and command buffer management - Com.InitArgv(args); - - Swap.Init(); - Cbuf.Init(); - - Cmd.Init(); - Cvar.Init(); - - Key.Init(); - - // we need to add the early commands twice, because - // a basedir or cddir needs to be set before execing - // config files, but we want other parms to override - // the settings of the config files - Cbuf.AddEarlyCommands(false); - Cbuf.Execute(); - - FS.InitFilesystem(); - - Cbuf.AddText("exec default.cfg\n"); - Cbuf.AddText("exec config.cfg\n"); - - Cbuf.AddEarlyCommands(true); - Cbuf.Execute(); - - // - // init commands and vars - // - Cmd.AddCommand("error", Com.Error_f); - - Globals.host_speeds= Cvar.Get("host_speeds", "0", 0); - Globals.log_stats= Cvar.Get("log_stats", "0", 0); - Globals.developer= Cvar.Get("developer", "0", 0); - Globals.timescale= Cvar.Get("timescale", "1", 0); - Globals.fixedtime= Cvar.Get("fixedtime", "0", 0); - Globals.logfile_active= Cvar.Get("logfile", "0", 0); - Globals.showtrace= Cvar.Get("showtrace", "0", 0); - Globals.dedicated= Cvar.Get("dedicated", "0", CVAR_NOSET); - - String s = Com.sprintf("%4.2f %s %s %s", - new Vargs(4) - .add(Globals.VERSION) - .add(CPUSTRING) - .add(Globals.__DATE__) - .add(BUILDSTRING)); - - Cvar.Get("version", s, CVAR_SERVERINFO | CVAR_NOSET); - - NET.NET_Init(); - Netchan.Netchan_Init(); - - SV_MAIN.SV_Init(); - CL.Init(); - - // add + commands from command line - if (!Cbuf.AddLateCommands()) { - // if the user didn't give any commands, run default action - //Cbuf.AddText("d1\n"); - Cbuf.Execute(); - } else { - // the user asked for something explicit - // so drop the loading plaque - SCR.EndLoadingPlaque(); - } - - Com.Printf("====== Quake2 Initialized ======\n\n"); - - } catch (longjmpException e) { - Sys.Error("Error during initialization"); - } - } - /** * This function initializes the different subsystems of - * the game engine. The setjmp/longjmp mechanism of the original - * was replaced with exceptions. + * the game engine. The setjmp/longjmp mechanism of the original + * was replaced with exceptions. * @param args the original unmodified command line arguments */ public static void Init(String[] args) { @@ -147,8 +61,6 @@ public final class Qcommon extends Globals { Swap.Init(); Cbuf.Init(); - //rst bugfix - //GamePWeapon xxx = new GamePWeapon(); Cmd.Init(); Cvar.Init(); diff --git a/src/jake2/qcommon/qfiles.java b/src/jake2/qcommon/qfiles.java index ae7fdf6..8e524a5 100644 --- a/src/jake2/qcommon/qfiles.java +++ b/src/jake2/qcommon/qfiles.java @@ -2,7 +2,7 @@ * qfiles.java * Copyright (C) 2003 * - * $Id: qfiles.java,v 1.3 2004-07-08 20:24:48 hzi Exp $ + * $Id: qfiles.java,v 1.4 2004-07-09 06:50:50 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -25,14 +25,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package jake2.qcommon; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; +import jake2.Defines; -import jake2.*; -import jake2.client.*; -import jake2.game.*; -import jake2.render.*; -import jake2.server.*; +import java.nio.*; /** * qfiles @@ -292,6 +287,14 @@ public class qfiles { ofs_glcmds = b.getInt(); ofs_end = b.getInt(); // end of file } + + /* + * new members for vertex array handling + */ + public FloatBuffer textureCoordBuf = null; + public IntBuffer vertexIndexBuf = null; + public int[] counts = null; + public IntBuffer[] indexElements = null; } /* diff --git a/src/jake2/render/FastJoglRenderer.java b/src/jake2/render/FastJoglRenderer.java new file mode 100644 index 0000000..da20bfd --- /dev/null +++ b/src/jake2/render/FastJoglRenderer.java @@ -0,0 +1,306 @@ +/* + * FastJoglRenderer.java + * Copyright (C) 2003 + * + * $Id: FastJoglRenderer.java,v 1.1 2004-07-09 06:50:47 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.client.*; +import jake2.qcommon.xcommand_t; +import jake2.render.fastjogl.Impl; + +import java.awt.Dimension; + +/** + * FastJoglRenderer + * + * @author cwei + */ +final class FastJoglRenderer extends Impl implements refexport_t, Ref { + + static { + Renderer.register(new FastJoglRenderer()); + }; + + private FastJoglRenderer() { + } + + // ============================================================================ + // public interface for Renderer implementations + // + // refexport_t (ref.h) + // ============================================================================ + + /** + * @see jake2.client.refexport_t#Init() + */ + public boolean Init(int vid_xpos, int vid_ypos) { + + // pre init + if (!R_Init(vid_xpos, vid_ypos)) return false; + // calls the R_Init2() internally + updateScreen(); + // the result from R_Init2() + return post_init; + } + + /** + * @see jake2.client.refexport_t#Shutdown() + */ + public void Shutdown() { + R_Shutdown(); + } + + /** + * @see jake2.client.refexport_t#BeginRegistration(java.lang.String) + */ + public void BeginRegistration(String map) { + if (contextInUse) { + R_BeginRegistration(map); + return; + } + this.name = map; + + updateScreen(new xcommand_t() { + public void execute() { + R_BeginRegistration(FastJoglRenderer.this.name); + } + }); + } + + + private model_t model = null; + private String name = null; + + /** + * @see jake2.client.refexport_t#RegisterModel(java.lang.String) + */ + public model_t RegisterModel(String name) { + + if (contextInUse) + return R_RegisterModel(name); + + model = null; + this.name = name; + + updateScreen(new xcommand_t() { + public void execute() { + FastJoglRenderer.this.model = R_RegisterModel(FastJoglRenderer.this.name); + } + }); + return model; + } + + /** + * @see jake2.client.refexport_t#RegisterSkin(java.lang.String) + */ + public image_t RegisterSkin(String name) { + if (contextInUse) + return R_RegisterSkin(name); + + this.image = null; + this.name = name; + + updateScreen(new xcommand_t() { + public void execute() { + FastJoglRenderer.this.image = R_RegisterSkin(FastJoglRenderer.this.name); + } + }); + return image; + } + + private image_t image = null; + + /** + * @see jake2.client.refexport_t#RegisterPic(java.lang.String) + */ + public image_t RegisterPic(String name) { + if (contextInUse) + return Draw_FindPic(name); + + this.image = null; + this.name = name; + + updateScreen(new xcommand_t() { + public void execute() { + FastJoglRenderer.this.image = Draw_FindPic(FastJoglRenderer.this.name); + } + }); + return image; + } + + + private float[] axis; + private float rotate; + + /** + * @see jake2.client.refexport_t#SetSky(java.lang.String, float, float[]) + */ + public void SetSky(String name, float rotate, float[] axis) { + if (contextInUse) { + R_SetSky(name, rotate, axis); + return; + } + + this.name = name; + this.rotate = rotate; + this.axis = axis; + + updateScreen(new xcommand_t() { + public void execute() { + R_SetSky(FastJoglRenderer.this.name, FastJoglRenderer.this.rotate, FastJoglRenderer.this.axis); + } + }); + + } + + /** + * @see jake2.client.refexport_t#EndRegistration() + */ + public void EndRegistration() { + if (contextInUse) { + R_EndRegistration(); + return; + } + + updateScreen(new xcommand_t() { + public void execute() { + R_EndRegistration(); + } + }); + } + + /** + * @see jake2.client.refexport_t#RenderFrame(jake2.client.refdef_t) + */ + public void RenderFrame(refdef_t fd) { + R_RenderFrame(fd); + } + + /** + * @see jake2.client.refexport_t#DrawGetPicSize(java.awt.Dimension, java.lang.String) + */ + public void DrawGetPicSize(Dimension dim, String name) { + Draw_GetPicSize(dim, name); + } + + /** + * @see jake2.client.refexport_t#DrawPic(int, int, java.lang.String) + */ + public void DrawPic(int x, int y, String name) { + Draw_Pic(x, y, name); + } + + /** + * @see jake2.client.refexport_t#DrawStretchPic(int, int, int, int, java.lang.String) + */ + public void DrawStretchPic(int x, int y, int w, int h, String name) { + Draw_StretchPic(x, y, w, h, name); + } + + /** + * @see jake2.client.refexport_t#DrawChar(int, int, int) + */ + public void DrawChar(int x, int y, int num) { + Draw_Char(x, y, num); + } + + /** + * @see jake2.client.refexport_t#DrawTileClear(int, int, int, int, java.lang.String) + */ + public void DrawTileClear(int x, int y, int w, int h, String name) { + Draw_TileClear(x, y, w, h, name); + } + + /** + * @see jake2.client.refexport_t#DrawFill(int, int, int, int, int) + */ + public void DrawFill(int x, int y, int w, int h, int c) { + Draw_Fill(x, y, w, h, c); + } + + /** + * @see jake2.client.refexport_t#DrawFadeScreen() + */ + public void DrawFadeScreen() { + Draw_FadeScreen(); + } + + /** + * @see jake2.client.refexport_t#DrawStretchRaw(int, int, int, int, int, int, byte[]) + */ + public void DrawStretchRaw(int x, int y, int w, int h, int cols, int rows, byte[] data) { + Draw_StretchRaw(x, y, w, h, cols, rows, data); + } + + /** + * @see jake2.client.refexport_t#CinematicSetPalette(byte[]) + */ + public void CinematicSetPalette(byte[] palette) { + R_SetPalette(palette); + } + + /** + * @see jake2.client.refexport_t#BeginFrame(float) + */ + public void BeginFrame(float camera_separation) { + R_BeginFrame(camera_separation); + } + + /** + * @see jake2.client.refexport_t#EndFrame() + */ + public void EndFrame() { + GLimp_EndFrame(); + } + + /** + * @see jake2.client.refexport_t#AppActivate(boolean) + */ + public void AppActivate(boolean activate) { + GLimp_AppActivate(activate); + } + + public int apiVersion() { + return Defines.API_VERSION; + } + + // ============================================================================ + // Ref interface + // ============================================================================ + + public String getName() { + return DRIVER_NAME; + } + + public String toString() { + return DRIVER_NAME; + } + + public refexport_t GetRefAPI(refimport_t rimp) { + this.ri = rimp; + return this; + } + +}
\ No newline at end of file diff --git a/src/jake2/render/JoglRenderer.java b/src/jake2/render/JoglRenderer.java index 2829a96..97e3967 100644 --- a/src/jake2/render/JoglRenderer.java +++ b/src/jake2/render/JoglRenderer.java @@ -2,7 +2,7 @@ * JoglRenderer.java * Copyright (C) 2003 * - * $Id: JoglRenderer.java,v 1.2 2004-07-08 15:58:48 hzi Exp $ + * $Id: JoglRenderer.java,v 1.3 2004-07-09 06:50:47 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -25,15 +25,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package jake2.render; -import java.awt.Dimension; - import jake2.Defines; +import jake2.client.*; import jake2.qcommon.xcommand_t; -import jake2.render.jogl.*; +import jake2.render.jogl.Impl; -import jake2.client.refdef_t; -import jake2.client.refexport_t; -import jake2.client.refimport_t; +import java.awt.Dimension; /** * JoglRenderer @@ -59,11 +56,10 @@ final class JoglRenderer extends Impl implements refexport_t, Ref { * @see jake2.client.refexport_t#Init() */ public boolean Init(int vid_xpos, int vid_ypos) { - // pre init if (!R_Init(vid_xpos, vid_ypos)) return false; // calls the R_Init2() internally - updateScreen(null); + updateScreen(); // the result from R_Init2() return post_init; } @@ -79,7 +75,18 @@ final class JoglRenderer extends Impl implements refexport_t, Ref { * @see jake2.client.refexport_t#BeginRegistration(java.lang.String) */ public void BeginRegistration(String map) { - R_BeginRegistration(map); + if (contextInUse) { + R_BeginRegistration(map); + return; + } + + this.name = map; + + updateScreen(new xcommand_t() { + public void execute() { + R_BeginRegistration(JoglRenderer.this.name); + } + }); } @@ -143,18 +150,43 @@ final class JoglRenderer extends Impl implements refexport_t, Ref { return image; } + private float[] axis; + private float rotate; + /** * @see jake2.client.refexport_t#SetSky(java.lang.String, float, float[]) */ public void SetSky(String name, float rotate, float[] axis) { - R_SetSky(name, rotate, axis); + if (contextInUse) { + R_SetSky(name, rotate, axis); + return; + } + + this.name = name; + this.rotate = rotate; + this.axis = axis; + + updateScreen(new xcommand_t() { + public void execute() { + R_SetSky(JoglRenderer.this.name, JoglRenderer.this.rotate, JoglRenderer.this.axis); + } + }); } /** * @see jake2.client.refexport_t#EndRegistration() */ public void EndRegistration() { - R_EndRegistration(); + if (contextInUse) { + R_EndRegistration(); + return; + } + + updateScreen(new xcommand_t() { + public void execute() { + R_EndRegistration(); + } + }); } /** @@ -268,5 +300,4 @@ final class JoglRenderer extends Impl implements refexport_t, Ref { this.ri = rimp; return this; } - }
\ No newline at end of file diff --git a/src/jake2/render/Renderer.java b/src/jake2/render/Renderer.java index fbd9909..55d985c 100644 --- a/src/jake2/render/Renderer.java +++ b/src/jake2/render/Renderer.java @@ -2,7 +2,7 @@ * Renderer.java * Copyright (C) 2003 * - * $Id: Renderer.java,v 1.1 2004-07-07 19:59:34 hzi Exp $ + * $Id: Renderer.java,v 1.2 2004-07-09 06:50:47 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -26,8 +26,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. package jake2.render; import java.util.Vector; -import java.util.logging.Level; -import java.util.logging.Logger; import jake2.client.refexport_t; import jake2.client.refimport_t; @@ -39,7 +37,6 @@ import jake2.client.refimport_t; */ public class Renderer { - private static Logger logger = Logger.getLogger(Renderer.class.getName()); static Vector drivers = new Vector(3); @@ -49,8 +46,8 @@ public class Renderer { static { try { Class.forName("jake2.render.JoglRenderer"); + Class.forName("jake2.render.FastJoglRenderer"); } catch (ClassNotFoundException e) { - logger.log(Level.SEVERE, "can't found " + DEFAULT_CLASS); e.printStackTrace(); } }; @@ -74,13 +71,12 @@ public class Renderer { // find a driver Ref driver = null; int count = drivers.size(); - for (int i = 0; i < count && driver == null; i++) { + for (int i = 0; i < count; i++) { driver = (Ref) drivers.get(i); if (driver.getName().equals(driverName)) { return driver.GetRefAPI(rimp); } } - logger.log(Level.INFO, "Refresh driver \"" + driverName + "\"not found"); // null if driver not found return null; } diff --git a/src/jake2/render/fastjogl/Anorms.java b/src/jake2/render/fastjogl/Anorms.java new file mode 100644 index 0000000..552b305 --- /dev/null +++ b/src/jake2/render/fastjogl/Anorms.java @@ -0,0 +1,219 @@ +/* + * Anorms.java + * Copyright (C) 2003 + * + * $Id: Anorms.java,v 1.1 2004-07-09 06:50:49 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.fastjogl; + +/** + * Anorms + * + * @author cwei + */ +public interface Anorms { + + final float[][] VERTEXNORMALS = { + {-0.525731f, 0.000000f, 0.850651f}, + {-0.442863f, 0.238856f, 0.864188f}, + {-0.295242f, 0.000000f, 0.955423f}, + {-0.309017f, 0.500000f, 0.809017f}, + {-0.162460f, 0.262866f, 0.951056f}, + {0.000000f, 0.000000f, 1.000000f}, + {0.000000f, 0.850651f, 0.525731f}, + {-0.147621f, 0.716567f, 0.681718f}, + {0.147621f, 0.716567f, 0.681718f}, + {0.000000f, 0.525731f, 0.850651f}, + {0.309017f, 0.500000f, 0.809017f}, + {0.525731f, 0.000000f, 0.850651f}, + {0.295242f, 0.000000f, 0.955423f}, + {0.442863f, 0.238856f, 0.864188f}, + {0.162460f, 0.262866f, 0.951056f}, + {-0.681718f, 0.147621f, 0.716567f}, + {-0.809017f, 0.309017f, 0.500000f}, + {-0.587785f, 0.425325f, 0.688191f}, + {-0.850651f, 0.525731f, 0.000000f}, + {-0.864188f, 0.442863f, 0.238856f}, + {-0.716567f, 0.681718f, 0.147621f}, + {-0.688191f, 0.587785f, 0.425325f}, + {-0.500000f, 0.809017f, 0.309017f}, + {-0.238856f, 0.864188f, 0.442863f}, + {-0.425325f, 0.688191f, 0.587785f}, + {-0.716567f, 0.681718f, -0.147621f}, + {-0.500000f, 0.809017f, -0.309017f}, + {-0.525731f, 0.850651f, 0.000000f}, + {0.000000f, 0.850651f, -0.525731f}, + {-0.238856f, 0.864188f, -0.442863f}, + {0.000000f, 0.955423f, -0.295242f}, + {-0.262866f, 0.951056f, -0.162460f}, + {0.000000f, 1.000000f, 0.000000f}, + {0.000000f, 0.955423f, 0.295242f}, + {-0.262866f, 0.951056f, 0.162460f}, + {0.238856f, 0.864188f, 0.442863f}, + {0.262866f, 0.951056f, 0.162460f}, + {0.500000f, 0.809017f, 0.309017f}, + {0.238856f, 0.864188f, -0.442863f}, + {0.262866f, 0.951056f, -0.162460f}, + {0.500000f, 0.809017f, -0.309017f}, + {0.850651f, 0.525731f, 0.000000f}, + {0.716567f, 0.681718f, 0.147621f}, + {0.716567f, 0.681718f, -0.147621f}, + {0.525731f, 0.850651f, 0.000000f}, + {0.425325f, 0.688191f, 0.587785f}, + {0.864188f, 0.442863f, 0.238856f}, + {0.688191f, 0.587785f, 0.425325f}, + {0.809017f, 0.309017f, 0.500000f}, + {0.681718f, 0.147621f, 0.716567f}, + {0.587785f, 0.425325f, 0.688191f}, + {0.955423f, 0.295242f, 0.000000f}, + {1.000000f, 0.000000f, 0.000000f}, + {0.951056f, 0.162460f, 0.262866f}, + {0.850651f, -0.525731f, 0.000000f}, + {0.955423f, -0.295242f, 0.000000f}, + {0.864188f, -0.442863f, 0.238856f}, + {0.951056f, -0.162460f, 0.262866f}, + {0.809017f, -0.309017f, 0.500000f}, + {0.681718f, -0.147621f, 0.716567f}, + {0.850651f, 0.000000f, 0.525731f}, + {0.864188f, 0.442863f, -0.238856f}, + {0.809017f, 0.309017f, -0.500000f}, + {0.951056f, 0.162460f, -0.262866f}, + {0.525731f, 0.000000f, -0.850651f}, + {0.681718f, 0.147621f, -0.716567f}, + {0.681718f, -0.147621f, -0.716567f}, + {0.850651f, 0.000000f, -0.525731f}, + {0.809017f, -0.309017f, -0.500000f}, + {0.864188f, -0.442863f, -0.238856f}, + {0.951056f, -0.162460f, -0.262866f}, + {0.147621f, 0.716567f, -0.681718f}, + {0.309017f, 0.500000f, -0.809017f}, + {0.425325f, 0.688191f, -0.587785f}, + {0.442863f, 0.238856f, -0.864188f}, + {0.587785f, 0.425325f, -0.688191f}, + {0.688191f, 0.587785f, -0.425325f}, + {-0.147621f, 0.716567f, -0.681718f}, + {-0.309017f, 0.500000f, -0.809017f}, + {0.000000f, 0.525731f, -0.850651f}, + {-0.525731f, 0.000000f, -0.850651f}, + {-0.442863f, 0.238856f, -0.864188f}, + {-0.295242f, 0.000000f, -0.955423f}, + {-0.162460f, 0.262866f, -0.951056f}, + {0.000000f, 0.000000f, -1.000000f}, + {0.295242f, 0.000000f, -0.955423f}, + {0.162460f, 0.262866f, -0.951056f}, + {-0.442863f, -0.238856f, -0.864188f}, + {-0.309017f, -0.500000f, -0.809017f}, + {-0.162460f, -0.262866f, -0.951056f}, + {0.000000f, -0.850651f, -0.525731f}, + {-0.147621f, -0.716567f, -0.681718f}, + {0.147621f, -0.716567f, -0.681718f}, + {0.000000f, -0.525731f, -0.850651f}, + {0.309017f, -0.500000f, -0.809017f}, + {0.442863f, -0.238856f, -0.864188f}, + {0.162460f, -0.262866f, -0.951056f}, + {0.238856f, -0.864188f, -0.442863f}, + {0.500000f, -0.809017f, -0.309017f}, + {0.425325f, -0.688191f, -0.587785f}, + {0.716567f, -0.681718f, -0.147621f}, + {0.688191f, -0.587785f, -0.425325f}, + {0.587785f, -0.425325f, -0.688191f}, + {0.000000f, -0.955423f, -0.295242f}, + {0.000000f, -1.000000f, 0.000000f}, + {0.262866f, -0.951056f, -0.162460f}, + {0.000000f, -0.850651f, 0.525731f}, + {0.000000f, -0.955423f, 0.295242f}, + {0.238856f, -0.864188f, 0.442863f}, + {0.262866f, -0.951056f, 0.162460f}, + {0.500000f, -0.809017f, 0.309017f}, + {0.716567f, -0.681718f, 0.147621f}, + {0.525731f, -0.850651f, 0.000000f}, + {-0.238856f, -0.864188f, -0.442863f}, + {-0.500000f, -0.809017f, -0.309017f}, + {-0.262866f, -0.951056f, -0.162460f}, + {-0.850651f, -0.525731f, 0.000000f}, + {-0.716567f, -0.681718f, -0.147621f}, + {-0.716567f, -0.681718f, 0.147621f}, + {-0.525731f, -0.850651f, 0.000000f}, + {-0.500000f, -0.809017f, 0.309017f}, + {-0.238856f, -0.864188f, 0.442863f}, + {-0.262866f, -0.951056f, 0.162460f}, + {-0.864188f, -0.442863f, 0.238856f}, + {-0.809017f, -0.309017f, 0.500000f}, + {-0.688191f, -0.587785f, 0.425325f}, + {-0.681718f, -0.147621f, 0.716567f}, + {-0.442863f, -0.238856f, 0.864188f}, + {-0.587785f, -0.425325f, 0.688191f}, + {-0.309017f, -0.500000f, 0.809017f}, + {-0.147621f, -0.716567f, 0.681718f}, + {-0.425325f, -0.688191f, 0.587785f}, + {-0.162460f, -0.262866f, 0.951056f}, + {0.442863f, -0.238856f, 0.864188f}, + {0.162460f, -0.262866f, 0.951056f}, + {0.309017f, -0.500000f, 0.809017f}, + {0.147621f, -0.716567f, 0.681718f}, + {0.000000f, -0.525731f, 0.850651f}, + {0.425325f, -0.688191f, 0.587785f}, + {0.587785f, -0.425325f, 0.688191f}, + {0.688191f, -0.587785f, 0.425325f}, + {-0.955423f, 0.295242f, 0.000000f}, + {-0.951056f, 0.162460f, 0.262866f}, + {-1.000000f, 0.000000f, 0.000000f}, + {-0.850651f, 0.000000f, 0.525731f}, + {-0.955423f, -0.295242f, 0.000000f}, + {-0.951056f, -0.162460f, 0.262866f}, + {-0.864188f, 0.442863f, -0.238856f}, + {-0.951056f, 0.162460f, -0.262866f}, + {-0.809017f, 0.309017f, -0.500000f}, + {-0.864188f, -0.442863f, -0.238856f}, + {-0.951056f, -0.162460f, -0.262866f}, + {-0.809017f, -0.309017f, -0.500000f}, + {-0.681718f, 0.147621f, -0.716567f}, + {-0.681718f, -0.147621f, -0.716567f}, + {-0.850651f, 0.000000f, -0.525731f}, + {-0.688191f, 0.587785f, -0.425325f}, + {-0.587785f, 0.425325f, -0.688191f}, + {-0.425325f, 0.688191f, -0.587785f}, + {-0.425325f, -0.688191f, -0.587785f}, + {-0.587785f, -0.425325f, -0.688191f}, + {-0.688191f, -0.587785f, -0.425325f} + }; + + final float[][] VERTEXNORMAL_DOTS = { + {1.23f,1.30f,1.47f,1.35f,1.56f,1.71f,1.37f,1.38f,1.59f,1.60f,1.79f,1.97f,1.88f,1.92f,1.79f,1.02f,0.93f,1.07f,0.82f,0.87f,0.88f,0.94f,0.96f,1.14f,1.11f,0.82f,0.83f,0.89f,0.89f,0.86f,0.94f,0.91f,1.00f,1.21f,0.98f,1.48f,1.30f,1.57f,0.96f,1.07f,1.14f,1.60f,1.61f,1.40f,1.37f,1.72f,1.78f,1.79f,1.93f,1.99f,1.90f,1.68f,1.71f,1.86f,1.60f,1.68f,1.78f,1.86f,1.93f,1.99f,1.97f,1.44f,1.22f,1.49f,0.93f,0.99f,0.99f,1.23f,1.22f,1.44f,1.49f,0.89f,0.89f,0.97f,0.91f,0.98f,1.19f,0.82f,0.76f,0.82f,0.71f,0.72f,0.73f,0.76f,0.79f,0.86f,0.83f,0.72f,0.76f,0.76f,0.89f,0.82f,0.89f,0.82f,0.89f,0.91f,0.83f,0.96f,1.14f,0.97f,1.40f,1.19f,0.98f,0.94f,1.00f,1.07f,1.37f,1.21f,1.48f,1.30f,1.57f,1.61f,1.37f,0.86f,0.83f,0.91f,0.82f,0.82f,0.88f,0.89f,0.96f,1.14f,0.98f,0.87f,0.93f,0.94f,1.02f,1.30f,1.07f,1.35f,1.38f,1.11f,1.56f,1.92f,1.79f,1.79f,1.59f,1.60f,1.72f,1.90f,1.79f,0.80f,0.85f,0.79f,0.93f,0.80f,0.85f,0.77f,0.74f,0.72f,0.77f,0.74f,0.72f,0.70f,0.70f,0.71f,0.76f,0.73f,0.79f,0.79f,0.73f,0.76f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.26f,1.26f,1.48f,1.23f,1.50f,1.71f,1.14f,1.19f,1.38f,1.46f,1.64f,1.94f,1.87f,1.84f,1.71f,1.02f,0.92f,1.00f,0.79f,0.85f,0.84f,0.91f,0.90f,0.98f,0.99f,0.77f,0.77f,0.83f,0.82f,0.79f,0.86f,0.84f,0.92f,0.99f,0.91f,1.24f,1.03f,1.33f,0.88f,0.94f,0.97f,1.41f,1.39f,1.18f,1.11f,1.51f,1.61f,1.59f,1.80f,1.91f,1.76f,1.54f,1.65f,1.76f,1.70f,1.70f,1.85f,1.85f,1.97f,1.99f,1.93f,1.28f,1.09f,1.39f,0.92f,0.97f,0.99f,1.18f,1.26f,1.52f,1.48f,0.83f,0.85f,0.90f,0.88f,0.93f,1.00f,0.77f,0.73f,0.78f,0.72f,0.71f,0.74f,0.75f,0.79f,0.86f,0.81f,0.75f,0.81f,0.79f,0.96f,0.88f,0.94f,0.86f,0.93f,0.92f,0.85f,1.08f,1.33f,1.05f,1.55f,1.31f,1.01f,1.05f,1.27f,1.31f,1.60f,1.47f,1.70f,1.54f,1.76f,1.76f,1.57f,0.93f,0.90f,0.99f,0.88f,0.88f,0.95f,0.97f,1.11f,1.39f,1.20f,0.92f,0.97f,1.01f,1.10f,1.39f,1.22f,1.51f,1.58f,1.32f,1.64f,1.97f,1.85f,1.91f,1.77f,1.74f,1.88f,1.99f,1.91f,0.79f,0.86f,0.80f,0.94f,0.84f,0.88f,0.74f,0.74f,0.71f,0.82f,0.77f,0.76f,0.70f,0.73f,0.72f,0.73f,0.70f,0.74f,0.85f,0.77f,0.82f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.34f,1.27f,1.53f,1.17f,1.46f,1.71f,0.98f,1.05f,1.20f,1.34f,1.48f,1.86f,1.82f,1.71f,1.62f,1.09f,0.94f,0.99f,0.79f,0.85f,0.82f,0.90f,0.87f,0.93f,0.96f,0.76f,0.74f,0.79f,0.76f,0.74f,0.79f,0.78f,0.85f,0.92f,0.85f,1.00f,0.93f,1.06f,0.81f,0.86f,0.89f,1.16f,1.12f,0.97f,0.95f,1.28f,1.38f,1.35f,1.60f,1.77f,1.57f,1.33f,1.50f,1.58f,1.69f,1.63f,1.82f,1.74f,1.91f,1.92f,1.80f,1.04f,0.97f,1.21f,0.90f,0.93f,0.97f,1.05f,1.21f,1.48f,1.37f,0.77f,0.80f,0.84f,0.85f,0.88f,0.92f,0.73f,0.71f,0.74f,0.74f,0.71f,0.75f,0.73f,0.79f,0.84f,0.78f,0.79f,0.86f,0.81f,1.05f,0.94f,0.99f,0.90f,0.95f,0.92f,0.86f,1.24f,1.44f,1.14f,1.59f,1.34f,1.02f,1.27f,1.50f,1.49f,1.80f,1.69f,1.86f,1.72f,1.87f,1.80f,1.69f,1.00f,0.98f,1.23f,0.95f,0.96f,1.09f,1.16f,1.37f,1.63f,1.46f,0.99f,1.10f,1.25f,1.24f,1.51f,1.41f,1.67f,1.77f,1.55f,1.72f,1.95f,1.89f,1.98f,1.91f,1.86f,1.97f,1.99f,1.94f,0.81f,0.89f,0.85f,0.98f,0.90f,0.94f,0.75f,0.78f,0.73f,0.89f,0.83f,0.82f,0.72f,0.77f,0.76f,0.72f,0.70f,0.71f,0.91f,0.83f,0.89f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.46f,1.34f,1.60f,1.16f,1.46f,1.71f,0.94f,0.99f,1.05f,1.26f,1.33f,1.74f,1.76f,1.57f,1.54f,1.23f,0.98f,1.05f,0.83f,0.89f,0.84f,0.92f,0.87f,0.91f,0.96f,0.78f,0.74f,0.79f,0.72f,0.72f,0.75f,0.76f,0.80f,0.88f,0.83f,0.94f,0.87f,0.95f,0.76f,0.80f,0.82f,0.97f,0.96f,0.89f,0.88f,1.08f,1.11f,1.10f,1.37f,1.59f,1.37f,1.07f,1.27f,1.34f,1.57f,1.45f,1.69f,1.55f,1.77f,1.79f,1.60f,0.93f,0.90f,0.99f,0.86f,0.87f,0.93f,0.96f,1.07f,1.35f,1.18f,0.73f,0.76f,0.77f,0.81f,0.82f,0.85f,0.70f,0.71f,0.72f,0.78f,0.73f,0.77f,0.73f,0.79f,0.82f,0.76f,0.83f,0.90f,0.84f,1.18f,0.98f,1.03f,0.92f,0.95f,0.90f,0.86f,1.32f,1.45f,1.15f,1.53f,1.27f,0.99f,1.42f,1.65f,1.58f,1.93f,1.83f,1.94f,1.81f,1.88f,1.74f,1.70f,1.19f,1.17f,1.44f,1.11f,1.15f,1.36f,1.41f,1.61f,1.81f,1.67f,1.22f,1.34f,1.50f,1.42f,1.65f,1.61f,1.82f,1.91f,1.75f,1.80f,1.89f,1.89f,1.98f,1.99f,1.94f,1.98f,1.92f,1.87f,0.86f,0.95f,0.92f,1.14f,0.98f,1.03f,0.79f,0.84f,0.77f,0.97f,0.90f,0.89f,0.76f,0.82f,0.82f,0.74f,0.72f,0.71f,0.98f,0.89f,0.97f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.60f,1.44f,1.68f,1.22f,1.49f,1.71f,0.93f,0.99f,0.99f,1.23f,1.22f,1.60f,1.68f,1.44f,1.49f,1.40f,1.14f,1.19f,0.89f,0.96f,0.89f,0.97f,0.89f,0.91f,0.98f,0.82f,0.76f,0.82f,0.71f,0.72f,0.73f,0.76f,0.79f,0.86f,0.83f,0.91f,0.83f,0.89f,0.72f,0.76f,0.76f,0.89f,0.89f,0.82f,0.82f,0.98f,0.96f,0.97f,1.14f,1.40f,1.19f,0.94f,1.00f,1.07f,1.37f,1.21f,1.48f,1.30f,1.57f,1.61f,1.37f,0.86f,0.83f,0.91f,0.82f,0.82f,0.88f,0.89f,0.96f,1.14f,0.98f,0.70f,0.72f,0.73f,0.77f,0.76f,0.79f,0.70f,0.72f,0.71f,0.82f,0.77f,0.80f,0.74f,0.79f,0.80f,0.74f,0.87f,0.93f,0.85f,1.23f,1.02f,1.02f,0.93f,0.93f,0.87f,0.85f,1.30f,1.35f,1.07f,1.38f,1.11f,0.94f,1.47f,1.71f,1.56f,1.97f,1.88f,1.92f,1.79f,1.79f,1.59f,1.60f,1.30f,1.35f,1.56f,1.37f,1.38f,1.59f,1.60f,1.79f,1.92f,1.79f,1.48f,1.57f,1.72f,1.61f,1.78f,1.79f,1.93f,1.99f,1.90f,1.86f,1.78f,1.86f,1.93f,1.99f,1.97f,1.90f,1.79f,1.72f,0.94f,1.07f,1.00f,1.37f,1.21f,1.30f,0.86f,0.91f,0.83f,1.14f,0.98f,0.96f,0.82f,0.88f,0.89f,0.79f,0.76f,0.73f,1.07f,0.94f,1.11f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.74f,1.57f,1.76f,1.33f,1.54f,1.71f,0.94f,1.05f,0.99f,1.26f,1.16f,1.46f,1.60f,1.34f,1.46f,1.59f,1.37f,1.37f,0.97f,1.11f,0.96f,1.10f,0.95f,0.94f,1.08f,0.89f,0.82f,0.88f,0.72f,0.76f,0.75f,0.80f,0.80f,0.88f,0.87f,0.91f,0.83f,0.87f,0.72f,0.76f,0.74f,0.83f,0.84f,0.78f,0.79f,0.96f,0.89f,0.92f,0.98f,1.23f,1.05f,0.86f,0.92f,0.95f,1.11f,0.98f,1.22f,1.03f,1.34f,1.42f,1.14f,0.79f,0.77f,0.84f,0.78f,0.76f,0.82f,0.82f,0.89f,0.97f,0.90f,0.70f,0.71f,0.71f,0.73f,0.72f,0.74f,0.73f,0.76f,0.72f,0.86f,0.81f,0.82f,0.76f,0.79f,0.77f,0.73f,0.90f,0.95f,0.86f,1.18f,1.03f,0.98f,0.92f,0.90f,0.83f,0.84f,1.19f,1.17f,0.98f,1.15f,0.97f,0.89f,1.42f,1.65f,1.44f,1.93f,1.83f,1.81f,1.67f,1.61f,1.36f,1.41f,1.32f,1.45f,1.58f,1.57f,1.53f,1.74f,1.70f,1.88f,1.94f,1.81f,1.69f,1.77f,1.87f,1.79f,1.89f,1.92f,1.98f,1.99f,1.98f,1.89f,1.65f,1.80f,1.82f,1.91f,1.94f,1.75f,1.61f,1.50f,1.07f,1.34f,1.27f,1.60f,1.45f,1.55f,0.93f,0.99f,0.90f,1.35f,1.18f,1.07f,0.87f,0.93f,0.96f,0.85f,0.82f,0.77f,1.15f,0.99f,1.27f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.86f,1.71f,1.82f,1.48f,1.62f,1.71f,0.98f,1.20f,1.05f,1.34f,1.17f,1.34f,1.53f,1.27f,1.46f,1.77f,1.60f,1.57f,1.16f,1.38f,1.12f,1.35f,1.06f,1.00f,1.28f,0.97f,0.89f,0.95f,0.76f,0.81f,0.79f,0.86f,0.85f,0.92f,0.93f,0.93f,0.85f,0.87f,0.74f,0.78f,0.74f,0.79f,0.82f,0.76f,0.79f,0.96f,0.85f,0.90f,0.94f,1.09f,0.99f,0.81f,0.85f,0.89f,0.95f,0.90f,0.99f,0.94f,1.10f,1.24f,0.98f,0.75f,0.73f,0.78f,0.74f,0.72f,0.77f,0.76f,0.82f,0.89f,0.83f,0.73f,0.71f,0.71f,0.71f,0.70f,0.72f,0.77f,0.80f,0.74f,0.90f,0.85f,0.84f,0.78f,0.79f,0.75f,0.73f,0.92f,0.95f,0.86f,1.05f,0.99f,0.94f,0.90f,0.86f,0.79f,0.81f,1.00f,0.98f,0.91f,0.96f,0.89f,0.83f,1.27f,1.50f,1.23f,1.80f,1.69f,1.63f,1.46f,1.37f,1.09f,1.16f,1.24f,1.44f,1.49f,1.69f,1.59f,1.80f,1.69f,1.87f,1.86f,1.72f,1.82f,1.91f,1.94f,1.92f,1.95f,1.99f,1.98f,1.91f,1.97f,1.89f,1.51f,1.72f,1.67f,1.77f,1.86f,1.55f,1.41f,1.25f,1.33f,1.58f,1.50f,1.80f,1.63f,1.74f,1.04f,1.21f,0.97f,1.48f,1.37f,1.21f,0.93f,0.97f,1.05f,0.92f,0.88f,0.84f,1.14f,1.02f,1.34f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.94f,1.84f,1.87f,1.64f,1.71f,1.71f,1.14f,1.38f,1.19f,1.46f,1.23f,1.26f,1.48f,1.26f,1.50f,1.91f,1.80f,1.76f,1.41f,1.61f,1.39f,1.59f,1.33f,1.24f,1.51f,1.18f,0.97f,1.11f,0.82f,0.88f,0.86f,0.94f,0.92f,0.99f,1.03f,0.98f,0.91f,0.90f,0.79f,0.84f,0.77f,0.79f,0.84f,0.77f,0.83f,0.99f,0.85f,0.91f,0.92f,1.02f,1.00f,0.79f,0.80f,0.86f,0.88f,0.84f,0.92f,0.88f,0.97f,1.10f,0.94f,0.74f,0.71f,0.74f,0.72f,0.70f,0.73f,0.72f,0.76f,0.82f,0.77f,0.77f,0.73f,0.74f,0.71f,0.70f,0.73f,0.83f,0.85f,0.78f,0.92f,0.88f,0.86f,0.81f,0.79f,0.74f,0.75f,0.92f,0.93f,0.85f,0.96f,0.94f,0.88f,0.86f,0.81f,0.75f,0.79f,0.93f,0.90f,0.85f,0.88f,0.82f,0.77f,1.05f,1.27f,0.99f,1.60f,1.47f,1.39f,1.20f,1.11f,0.95f,0.97f,1.08f,1.33f,1.31f,1.70f,1.55f,1.76f,1.57f,1.76f,1.70f,1.54f,1.85f,1.97f,1.91f,1.99f,1.97f,1.99f,1.91f,1.77f,1.88f,1.85f,1.39f,1.64f,1.51f,1.58f,1.74f,1.32f,1.22f,1.01f,1.54f,1.76f,1.65f,1.93f,1.70f,1.85f,1.28f,1.39f,1.09f,1.52f,1.48f,1.26f,0.97f,0.99f,1.18f,1.00f,0.93f,0.90f,1.05f,1.01f,1.31f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.97f,1.92f,1.88f,1.79f,1.79f,1.71f,1.37f,1.59f,1.38f,1.60f,1.35f,1.23f,1.47f,1.30f,1.56f,1.99f,1.93f,1.90f,1.60f,1.78f,1.61f,1.79f,1.57f,1.48f,1.72f,1.40f,1.14f,1.37f,0.89f,0.96f,0.94f,1.07f,1.00f,1.21f,1.30f,1.14f,0.98f,0.96f,0.86f,0.91f,0.83f,0.82f,0.88f,0.82f,0.89f,1.11f,0.87f,0.94f,0.93f,1.02f,1.07f,0.80f,0.79f,0.85f,0.82f,0.80f,0.87f,0.85f,0.93f,1.02f,0.93f,0.77f,0.72f,0.74f,0.71f,0.70f,0.70f,0.71f,0.72f,0.77f,0.74f,0.82f,0.76f,0.79f,0.72f,0.73f,0.76f,0.89f,0.89f,0.82f,0.93f,0.91f,0.86f,0.83f,0.79f,0.73f,0.76f,0.91f,0.89f,0.83f,0.89f,0.89f,0.82f,0.82f,0.76f,0.72f,0.76f,0.86f,0.83f,0.79f,0.82f,0.76f,0.73f,0.94f,1.00f,0.91f,1.37f,1.21f,1.14f,0.98f,0.96f,0.88f,0.89f,0.96f,1.14f,1.07f,1.60f,1.40f,1.61f,1.37f,1.57f,1.48f,1.30f,1.78f,1.93f,1.79f,1.99f,1.92f,1.90f,1.79f,1.59f,1.72f,1.79f,1.30f,1.56f,1.35f,1.38f,1.60f,1.11f,1.07f,0.94f,1.68f,1.86f,1.71f,1.97f,1.68f,1.86f,1.44f,1.49f,1.22f,1.44f,1.49f,1.22f,0.99f,0.99f,1.23f,1.19f,0.98f,0.97f,0.97f,0.98f,1.19f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.94f,1.97f,1.87f,1.91f,1.85f,1.71f,1.60f,1.77f,1.58f,1.74f,1.51f,1.26f,1.48f,1.39f,1.64f,1.99f,1.97f,1.99f,1.70f,1.85f,1.76f,1.91f,1.76f,1.70f,1.88f,1.55f,1.33f,1.57f,0.96f,1.08f,1.05f,1.31f,1.27f,1.47f,1.54f,1.39f,1.20f,1.11f,0.93f,0.99f,0.90f,0.88f,0.95f,0.88f,0.97f,1.32f,0.92f,1.01f,0.97f,1.10f,1.22f,0.84f,0.80f,0.88f,0.79f,0.79f,0.85f,0.86f,0.92f,1.02f,0.94f,0.82f,0.76f,0.77f,0.72f,0.73f,0.70f,0.72f,0.71f,0.74f,0.74f,0.88f,0.81f,0.85f,0.75f,0.77f,0.82f,0.94f,0.93f,0.86f,0.92f,0.92f,0.86f,0.85f,0.79f,0.74f,0.79f,0.88f,0.85f,0.81f,0.82f,0.83f,0.77f,0.78f,0.73f,0.71f,0.75f,0.79f,0.77f,0.74f,0.77f,0.73f,0.70f,0.86f,0.92f,0.84f,1.14f,0.99f,0.98f,0.91f,0.90f,0.84f,0.83f,0.88f,0.97f,0.94f,1.41f,1.18f,1.39f,1.11f,1.33f,1.24f,1.03f,1.61f,1.80f,1.59f,1.91f,1.84f,1.76f,1.64f,1.38f,1.51f,1.71f,1.26f,1.50f,1.23f,1.19f,1.46f,0.99f,1.00f,0.91f,1.70f,1.85f,1.65f,1.93f,1.54f,1.76f,1.52f,1.48f,1.26f,1.28f,1.39f,1.09f,0.99f,0.97f,1.18f,1.31f,1.01f,1.05f,0.90f,0.93f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.86f,1.95f,1.82f,1.98f,1.89f,1.71f,1.80f,1.91f,1.77f,1.86f,1.67f,1.34f,1.53f,1.51f,1.72f,1.92f,1.91f,1.99f,1.69f,1.82f,1.80f,1.94f,1.87f,1.86f,1.97f,1.59f,1.44f,1.69f,1.05f,1.24f,1.27f,1.49f,1.50f,1.69f,1.72f,1.63f,1.46f,1.37f,1.00f,1.23f,0.98f,0.95f,1.09f,0.96f,1.16f,1.55f,0.99f,1.25f,1.10f,1.24f,1.41f,0.90f,0.85f,0.94f,0.79f,0.81f,0.85f,0.89f,0.94f,1.09f,0.98f,0.89f,0.82f,0.83f,0.74f,0.77f,0.72f,0.76f,0.73f,0.75f,0.78f,0.94f,0.86f,0.91f,0.79f,0.83f,0.89f,0.99f,0.95f,0.90f,0.90f,0.92f,0.84f,0.86f,0.79f,0.75f,0.81f,0.85f,0.80f,0.78f,0.76f,0.77f,0.73f,0.74f,0.71f,0.71f,0.73f,0.74f,0.74f,0.71f,0.76f,0.72f,0.70f,0.79f,0.85f,0.78f,0.98f,0.92f,0.93f,0.85f,0.87f,0.82f,0.79f,0.81f,0.89f,0.86f,1.16f,0.97f,1.12f,0.95f,1.06f,1.00f,0.93f,1.38f,1.60f,1.35f,1.77f,1.71f,1.57f,1.48f,1.20f,1.28f,1.62f,1.27f,1.46f,1.17f,1.05f,1.34f,0.96f,0.99f,0.90f,1.63f,1.74f,1.50f,1.80f,1.33f,1.58f,1.48f,1.37f,1.21f,1.04f,1.21f,0.97f,0.97f,0.93f,1.05f,1.34f,1.02f,1.14f,0.84f,0.88f,0.92f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.74f,1.89f,1.76f,1.98f,1.89f,1.71f,1.93f,1.99f,1.91f,1.94f,1.82f,1.46f,1.60f,1.65f,1.80f,1.79f,1.77f,1.92f,1.57f,1.69f,1.74f,1.87f,1.88f,1.94f,1.98f,1.53f,1.45f,1.70f,1.18f,1.32f,1.42f,1.58f,1.65f,1.83f,1.81f,1.81f,1.67f,1.61f,1.19f,1.44f,1.17f,1.11f,1.36f,1.15f,1.41f,1.75f,1.22f,1.50f,1.34f,1.42f,1.61f,0.98f,0.92f,1.03f,0.83f,0.86f,0.89f,0.95f,0.98f,1.23f,1.14f,0.97f,0.89f,0.90f,0.78f,0.82f,0.76f,0.82f,0.77f,0.79f,0.84f,0.98f,0.90f,0.98f,0.83f,0.89f,0.97f,1.03f,0.95f,0.92f,0.86f,0.90f,0.82f,0.86f,0.79f,0.77f,0.84f,0.81f,0.76f,0.76f,0.72f,0.73f,0.70f,0.72f,0.71f,0.73f,0.73f,0.72f,0.74f,0.71f,0.78f,0.74f,0.72f,0.75f,0.80f,0.76f,0.94f,0.88f,0.91f,0.83f,0.87f,0.84f,0.79f,0.76f,0.82f,0.80f,0.97f,0.89f,0.96f,0.88f,0.95f,0.94f,0.87f,1.11f,1.37f,1.10f,1.59f,1.57f,1.37f,1.33f,1.05f,1.08f,1.54f,1.34f,1.46f,1.16f,0.99f,1.26f,0.96f,1.05f,0.92f,1.45f,1.55f,1.27f,1.60f,1.07f,1.34f,1.35f,1.18f,1.07f,0.93f,0.99f,0.90f,0.93f,0.87f,0.96f,1.27f,0.99f,1.15f,0.77f,0.82f,0.85f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.60f,1.78f,1.68f,1.93f,1.86f,1.71f,1.97f,1.99f,1.99f,1.97f,1.93f,1.60f,1.68f,1.78f,1.86f,1.61f,1.57f,1.79f,1.37f,1.48f,1.59f,1.72f,1.79f,1.92f,1.90f,1.38f,1.35f,1.60f,1.23f,1.30f,1.47f,1.56f,1.71f,1.88f,1.79f,1.92f,1.79f,1.79f,1.30f,1.56f,1.35f,1.37f,1.59f,1.38f,1.60f,1.90f,1.48f,1.72f,1.57f,1.61f,1.79f,1.21f,1.00f,1.30f,0.89f,0.94f,0.96f,1.07f,1.14f,1.40f,1.37f,1.14f,0.96f,0.98f,0.82f,0.88f,0.82f,0.89f,0.83f,0.86f,0.91f,1.02f,0.93f,1.07f,0.87f,0.94f,1.11f,1.02f,0.93f,0.93f,0.82f,0.87f,0.80f,0.85f,0.79f,0.80f,0.85f,0.77f,0.72f,0.74f,0.71f,0.70f,0.70f,0.71f,0.72f,0.77f,0.74f,0.72f,0.76f,0.73f,0.82f,0.79f,0.76f,0.73f,0.79f,0.76f,0.93f,0.86f,0.91f,0.83f,0.89f,0.89f,0.82f,0.72f,0.76f,0.76f,0.89f,0.82f,0.89f,0.82f,0.89f,0.91f,0.83f,0.96f,1.14f,0.97f,1.40f,1.44f,1.19f,1.22f,0.99f,0.98f,1.49f,1.44f,1.49f,1.22f,0.99f,1.23f,0.98f,1.19f,0.97f,1.21f,1.30f,1.00f,1.37f,0.94f,1.07f,1.14f,0.98f,0.96f,0.86f,0.91f,0.83f,0.88f,0.82f,0.89f,1.11f,0.94f,1.07f,0.73f,0.76f,0.79f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.46f,1.65f,1.60f,1.82f,1.80f,1.71f,1.93f,1.91f,1.99f,1.94f,1.98f,1.74f,1.76f,1.89f,1.89f,1.42f,1.34f,1.61f,1.11f,1.22f,1.36f,1.50f,1.61f,1.81f,1.75f,1.15f,1.17f,1.41f,1.18f,1.19f,1.42f,1.44f,1.65f,1.83f,1.67f,1.94f,1.81f,1.88f,1.32f,1.58f,1.45f,1.57f,1.74f,1.53f,1.70f,1.98f,1.69f,1.87f,1.77f,1.79f,1.92f,1.45f,1.27f,1.55f,0.97f,1.07f,1.11f,1.34f,1.37f,1.59f,1.60f,1.35f,1.07f,1.18f,0.86f,0.93f,0.87f,0.96f,0.90f,0.93f,0.99f,1.03f,0.95f,1.15f,0.90f,0.99f,1.27f,0.98f,0.90f,0.92f,0.78f,0.83f,0.77f,0.84f,0.79f,0.82f,0.86f,0.73f,0.71f,0.73f,0.72f,0.70f,0.73f,0.72f,0.76f,0.81f,0.76f,0.76f,0.82f,0.77f,0.89f,0.85f,0.82f,0.75f,0.80f,0.80f,0.94f,0.88f,0.94f,0.87f,0.95f,0.96f,0.88f,0.72f,0.74f,0.76f,0.83f,0.78f,0.84f,0.79f,0.87f,0.91f,0.83f,0.89f,0.98f,0.92f,1.23f,1.34f,1.05f,1.16f,0.99f,0.96f,1.46f,1.57f,1.54f,1.33f,1.05f,1.26f,1.08f,1.37f,1.10f,0.98f,1.03f,0.92f,1.14f,0.86f,0.95f,0.97f,0.90f,0.89f,0.79f,0.84f,0.77f,0.82f,0.76f,0.82f,0.97f,0.89f,0.98f,0.71f,0.72f,0.74f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.34f,1.51f,1.53f,1.67f,1.72f,1.71f,1.80f,1.77f,1.91f,1.86f,1.98f,1.86f,1.82f,1.95f,1.89f,1.24f,1.10f,1.41f,0.95f,0.99f,1.09f,1.25f,1.37f,1.63f,1.55f,0.96f,0.98f,1.16f,1.05f,1.00f,1.27f,1.23f,1.50f,1.69f,1.46f,1.86f,1.72f,1.87f,1.24f,1.49f,1.44f,1.69f,1.80f,1.59f,1.69f,1.97f,1.82f,1.94f,1.91f,1.92f,1.99f,1.63f,1.50f,1.74f,1.16f,1.33f,1.38f,1.58f,1.60f,1.77f,1.80f,1.48f,1.21f,1.37f,0.90f,0.97f,0.93f,1.05f,0.97f,1.04f,1.21f,0.99f,0.95f,1.14f,0.92f,1.02f,1.34f,0.94f,0.86f,0.90f,0.74f,0.79f,0.75f,0.81f,0.79f,0.84f,0.86f,0.71f,0.71f,0.73f,0.76f,0.73f,0.77f,0.74f,0.80f,0.85f,0.78f,0.81f,0.89f,0.84f,0.97f,0.92f,0.88f,0.79f,0.85f,0.86f,0.98f,0.92f,1.00f,0.93f,1.06f,1.12f,0.95f,0.74f,0.74f,0.78f,0.79f,0.76f,0.82f,0.79f,0.87f,0.93f,0.85f,0.85f,0.94f,0.90f,1.09f,1.27f,0.99f,1.17f,1.05f,0.96f,1.46f,1.71f,1.62f,1.48f,1.20f,1.34f,1.28f,1.57f,1.35f,0.90f,0.94f,0.85f,0.98f,0.81f,0.89f,0.89f,0.83f,0.82f,0.75f,0.78f,0.73f,0.77f,0.72f,0.76f,0.89f,0.83f,0.91f,0.71f,0.70f,0.72f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f}, + {1.26f,1.39f,1.48f,1.51f,1.64f,1.71f,1.60f,1.58f,1.77f,1.74f,1.91f,1.94f,1.87f,1.97f,1.85f,1.10f,0.97f,1.22f,0.88f,0.92f,0.95f,1.01f,1.11f,1.39f,1.32f,0.88f,0.90f,0.97f,0.96f,0.93f,1.05f,0.99f,1.27f,1.47f,1.20f,1.70f,1.54f,1.76f,1.08f,1.31f,1.33f,1.70f,1.76f,1.55f,1.57f,1.88f,1.85f,1.91f,1.97f,1.99f,1.99f,1.70f,1.65f,1.85f,1.41f,1.54f,1.61f,1.76f,1.80f,1.91f,1.93f,1.52f,1.26f,1.48f,0.92f,0.99f,0.97f,1.18f,1.09f,1.28f,1.39f,0.94f,0.93f,1.05f,0.92f,1.01f,1.31f,0.88f,0.81f,0.86f,0.72f,0.75f,0.74f,0.79f,0.79f,0.86f,0.85f,0.71f,0.73f,0.75f,0.82f,0.77f,0.83f,0.78f,0.85f,0.88f,0.81f,0.88f,0.97f,0.90f,1.18f,1.00f,0.93f,0.86f,0.92f,0.94f,1.14f,0.99f,1.24f,1.03f,1.33f,1.39f,1.11f,0.79f,0.77f,0.84f,0.79f,0.77f,0.84f,0.83f,0.90f,0.98f,0.91f,0.85f,0.92f,0.91f,1.02f,1.26f,1.00f,1.23f,1.19f,0.99f,1.50f,1.84f,1.71f,1.64f,1.38f,1.46f,1.51f,1.76f,1.59f,0.84f,0.88f,0.80f,0.94f,0.79f,0.86f,0.82f,0.77f,0.76f,0.74f,0.74f,0.71f,0.73f,0.70f,0.72f,0.82f,0.77f,0.85f,0.74f,0.70f,0.73f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f,1.00f} + }; + +} diff --git a/src/jake2/render/fastjogl/Base.java b/src/jake2/render/fastjogl/Base.java new file mode 100644 index 0000000..c5cc690 --- /dev/null +++ b/src/jake2/render/fastjogl/Base.java @@ -0,0 +1,300 @@ +/* + * Base.java + * Copyright (C) 2003 + * + * $Id: Base.java,v 1.1 2004-07-09 06:50:49 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.fastjogl; + +import net.java.games.jogl.GL; + +/** + * Base + * + * @author cwei + */ +public class Base { + + static final int GL_COLOR_INDEX8_EXT = GL.GL_COLOR_INDEX; + static final String REF_VERSION = "GL 0.01"; + + // up / down + static final int PITCH = 0; + // left / right + static final int YAW = 1; + // fall over + static final int ROLL = 2; + + /* + skins will be outline flood filled and mip mapped + pics and sprites with alpha will be outline flood filled + pic won't be mip mapped + + model skin + sprite frame + wall texture + pic + */ + // enum imagetype_t + static final int it_skin = 0; + static final int it_sprite = 1; + static final int it_wall = 2; + static final int it_pic = 3; + static final int it_sky = 4; + + // enum modtype_t + static final int mod_bad = 0; + static final int mod_brush = 1; + static final int mod_sprite = 2; + static final int mod_alias = 3; + + static final int TEXNUM_LIGHTMAPS = 1024; + static final int TEXNUM_SCRAPS = 1152; + static final int TEXNUM_IMAGES = 1153; + + static final int MAX_GLTEXTURES = 1024; + +// =================================================================== + + // enum rserr_t + static final int rserr_ok = 0; + static final int rserr_invalid_fullscreen = 1; + static final int rserr_invalid_mode = 2; + static final int rserr_unknown = 3; + +// +// #include "gl_model.h" +// +// void GL_BeginRendering (int *x, int *y, int *width, int *height); +// void GL_EndRendering (void); +// +// void GL_SetDefaultState( void ); +// void GL_UpdateSwapInterval( void ); + + static class glvert_t { + float x, y, z; + float s, t; + float r, g, b; + } + + static final int MAX_LBM_HEIGHT = 480; + + static final float BACKFACE_EPSILON = 0.01f; + +// ==================================================== +// +// void R_TranslatePlayerSkin (int playernum); +// void GL_Bind (int texnum); +// void GL_MBind( GLenum target, int texnum ); +// void GL_TexEnv( GLenum value ); +// void GL_EnableMultitexture( qboolean enable ); +// void GL_SelectTexture( GLenum ); +// +// void R_LightPoint (vec3_t p, vec3_t color); +// void R_PushDlights (void); +// + +// ==================================================================== +// +// extern int registration_sequence; +// +// +// void V_AddBlend (float r, float g, float b, float a, float *v_blend); +// +// int R_Init( void *hinstance, void *hWnd ); +// void R_Shutdown( void ); +// +// void R_RenderView (refdef_t *fd); +// void GL_ScreenShot_f (void); +// void R_DrawAliasModel (entity_t *e); +// void R_DrawBrushModel (entity_t *e); +// void R_DrawSpriteModel (entity_t *e); +// void R_DrawBeam( entity_t *e ); +// void R_DrawWorld (void); +// void R_RenderDlights (void); +// void R_DrawAlphaSurfaces (void); +// void R_RenderBrushPoly (msurface_t *fa); +// void R_InitParticleTexture (void); +// void Draw_InitLocal (void); +// void GL_SubdivideSurface (msurface_t *fa); +// qboolean R_CullBox (vec3_t mins, vec3_t maxs); +// void R_RotateForEntity (entity_t *e); +// void R_MarkLeaves (void); +// +// glpoly_t *WaterWarpPolyVerts (glpoly_t *p); +// void EmitWaterPolys (msurface_t *fa); +// void R_AddSkySurface (msurface_t *fa); +// void R_ClearSkyBox (void); +// void R_DrawSkyBox (void); +// void R_MarkLights (dlight_t *light, int bit, mnode_t *node); +// +// +// void COM_StripExtension (char *in, char *out); +// +// void Draw_GetPicSize (int *w, int *h, char *name); +// void Draw_Pic (int x, int y, char *name); +// void Draw_StretchPic (int x, int y, int w, int h, char *name); +// void Draw_Char (int x, int y, int c); +// void Draw_TileClear (int x, int y, int w, int h, char *name); +// void Draw_Fill (int x, int y, int w, int h, int c); +// void Draw_FadeScreen (void); +// void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data); +// +// void R_BeginFrame( float camera_separation ); +// void R_SwapBuffers( int ); +// void R_SetPalette ( const unsigned char *palette); +// +// int Draw_GetPalette (void); +// +// void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight); +// +// struct image_s *R_RegisterSkin (char *name); +// +// void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height); +// image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type, int bits); +// image_t *GL_FindImage (char *name, imagetype_t type); +// void GL_TextureMode( char *string ); +// void GL_ImageList_f (void); +// +// void GL_SetTexturePalette( unsigned palette[256] ); +// +// void GL_InitImages (void); +// void GL_ShutdownImages (void); +// +// void GL_FreeUnusedImages (void); +// +// void GL_TextureAlphaMode( char *string ); +// void GL_TextureSolidMode( char *string ); +// +// /* +// ** GL extension emulation functions +// */ +// void GL_DrawParticles( int n, const particle_t particles[], const unsigned colortable[768] ); +// + + /* + ** GL config stuff + */ + static final int GL_RENDERER_VOODOO = 0x00000001; + static final int GL_RENDERER_VOODOO2 = 0x00000002; + static final int GL_RENDERER_VOODOO_RUSH = 0x00000004; + static final int GL_RENDERER_BANSHEE = 0x00000008; + static final int GL_RENDERER_3DFX = 0x0000000F; + + static final int GL_RENDERER_PCX1 = 0x00000010; + static final int GL_RENDERER_PCX2 = 0x00000020; + static final int GL_RENDERER_PMX = 0x00000040; + static final int GL_RENDERER_POWERVR = 0x00000070; + + static final int GL_RENDERER_PERMEDIA2 = 0x00000100; + static final int GL_RENDERER_GLINT_MX = 0x00000200; + static final int GL_RENDERER_GLINT_TX = 0x00000400; + static final int GL_RENDERER_3DLABS_MISC = 0x00000800; + static final int GL_RENDERER_3DLABS = 0x00000F00; + + static final int GL_RENDERER_REALIZM = 0x00001000; + static final int GL_RENDERER_REALIZM2 = 0x00002000; + static final int GL_RENDERER_INTERGRAPH = 0x00003000; + + static final int GL_RENDERER_3DPRO = 0x00004000; + static final int GL_RENDERER_REAL3D = 0x00008000; + static final int GL_RENDERER_RIVA128 = 0x00010000; + static final int GL_RENDERER_DYPIC = 0x00020000; + + static final int GL_RENDERER_V1000 = 0x00040000; + static final int GL_RENDERER_V2100 = 0x00080000; + static final int GL_RENDERER_V2200 = 0x00100000; + static final int GL_RENDERER_RENDITION = 0x001C0000; + + static final int GL_RENDERER_O2 = 0x00100000; + static final int GL_RENDERER_IMPACT = 0x00200000; + static final int GL_RENDERER_RE = 0x00400000; + static final int GL_RENDERER_IR = 0x00800000; + static final int GL_RENDERER_SGI = 0x00F00000; + + static final int GL_RENDERER_MCD = 0x01000000; + static final int GL_RENDERER_OTHER = 0x80000000; + + +// typedef struct +// { +// int renderer; +// const char *renderer_string; +// const char *vendor_string; +// const char *version_string; +// const char *extensions_string; +// +// qboolean allow_cds; +// } glconfig_t; +// +// typedef struct +// { +// float inverse_intensity; +// qboolean fullscreen; +// +// int prev_mode; +// +// unsigned char *d_16to8table; +// +// int lightmap_textures; +// +// int currenttextures[2]; +// int currenttmu; +// +// float camera_separation; +// qboolean stereo_enabled; +// +// unsigned char originalRedGammaTable[256]; +// unsigned char originalGreenGammaTable[256]; +// unsigned char originalBlueGammaTable[256]; +// } glstate_t; +// +// /* +// ==================================================================== +// +// IMPORTED FUNCTIONS +// +// ==================================================================== +// */ +// +// extern refimport_t ri; +// +// +// /* +// ==================================================================== +// +// IMPLEMENTATION SPECIFIC FUNCTIONS +// +// ==================================================================== +// */ +// +// void GLimp_BeginFrame( float camera_separation ); +// void GLimp_EndFrame( void ); +// int GLimp_Init( void *hinstance, void *hWnd ); +// void GLimp_Shutdown( void ); +// int GLimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen ); +// void GLimp_AppActivate( qboolean active ); +// void GLimp_EnableLogging( qboolean enable ); +// void GLimp_LogNewFrame( void ); +// + +} diff --git a/src/jake2/render/fastjogl/Draw.java b/src/jake2/render/fastjogl/Draw.java new file mode 100644 index 0000000..fcb48b6 --- /dev/null +++ b/src/jake2/render/fastjogl/Draw.java @@ -0,0 +1,406 @@ +/* + * Draw.java + * Copyright (C) 2003 + * + * $Id: Draw.java,v 1.1 2004-07-09 06:50:49 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.fastjogl; + +import jake2.Defines; +import jake2.Globals; +import jake2.render.image_t; + +import java.awt.Dimension; + +import net.java.games.jogl.GL; +import net.java.games.jogl.util.GLUT; + +/** + * Draw + * (gl_draw.c) + * + * @author cwei + */ +public abstract class Draw extends Image { + + /* + =============== + Draw_InitLocal + =============== + */ + void Draw_InitLocal() { + // load console characters (don't bilerp characters) + draw_chars = GL_FindImage("pics/conchars.pcx", it_pic); + GL_Bind(draw_chars.texnum); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); + } + + /* + ================ + Draw_Char + + Draws one 8*8 graphics character with 0 being transparent. + It can be clipped to the top of the screen to allow the console to be + smoothly scrolled off. + ================ + */ + protected void Draw_Char(int x, int y, int num) { + + num &= 255; + + if ( (num&127) == 32 ) return; // space + + if (y <= -8) return; // totally off screen + + int row = num>>4; + int col = num&15; + + float frow = row*0.0625f; + float fcol = col*0.0625f; + float size = 0.0625f; + + GL_Bind(draw_chars.texnum); + + gl.glBegin (GL.GL_QUADS); + gl.glTexCoord2f (fcol, frow); + gl.glVertex2f (x, y); + gl.glTexCoord2f (fcol + size, frow); + gl.glVertex2f (x+8, y); + gl.glTexCoord2f (fcol + size, frow + size); + gl.glVertex2f (x+8, y+8); + gl.glTexCoord2f (fcol, frow + size); + gl.glVertex2f (x, y+8); + gl.glEnd (); + } + + + /* + ============= + Draw_FindPic + ============= + */ + protected image_t Draw_FindPic(String name) { + image_t image = null; + String fullname; + + if (!name.startsWith("/") && !name.startsWith("\\")) + { + fullname = "pics/" + name + ".pcx"; + image = GL_FindImage(fullname, it_pic); + } else { + image = GL_FindImage(name.substring(1), it_pic); + } + return image; + } + + + /* + ============= + Draw_GetPicSize + ============= + */ + protected void Draw_GetPicSize(Dimension dim, String pic) { + + image_t image = Draw_FindPic(pic); + dim.width = (image != null) ? image.width : -1; + dim.height = (image != null) ? image.height : -1; + } + + /* + ============= + Draw_StretchPic + ============= + */ + protected void Draw_StretchPic (int x, int y, int w, int h, String pic) { + + image_t image; + + image = Draw_FindPic(pic); + if (image == null) + { + ri.Con_Printf (Defines.PRINT_ALL, "Can't find pic: " + pic +'\n'); + return; + } + + if (scrap_dirty) + Scrap_Upload(); + + if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( (gl_config.renderer & GL_RENDERER_RENDITION) != 0) ) && !image.has_alpha) + gl.glDisable(GL.GL_ALPHA_TEST); + + GL_Bind(image.texnum); + gl.glBegin (GL.GL_QUADS); + gl.glTexCoord2f (image.sl, image.tl); + gl.glVertex2f (x, y); + gl.glTexCoord2f (image.sh, image.tl); + gl.glVertex2f (x+w, y); + gl.glTexCoord2f (image.sh, image.th); + gl.glVertex2f (x+w, y+h); + gl.glTexCoord2f (image.sl, image.th); + gl.glVertex2f (x, y+h); + gl.glEnd (); + + if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( (gl_config.renderer & GL_RENDERER_RENDITION) !=0 ) ) && !image.has_alpha) + gl.glEnable(GL.GL_ALPHA_TEST); + } + + + /* + ============= + Draw_Pic + ============= + */ + protected void Draw_Pic(int x, int y, String pic) + { + image_t image; + + image = Draw_FindPic(pic); + if (image == null) + { + ri.Con_Printf(Defines.PRINT_ALL, "Can't find pic: " +pic + '\n'); + return; + } + if (scrap_dirty) + Scrap_Upload(); + + if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( (gl_config.renderer & GL_RENDERER_RENDITION) != 0 ) ) && !image.has_alpha) + gl.glDisable (GL.GL_ALPHA_TEST); + + GL_Bind(image.texnum); + + gl.glBegin (GL.GL_QUADS); + gl.glTexCoord2f (image.sl, image.tl); + gl.glVertex2f (x, y); + gl.glTexCoord2f (image.sh, image.tl); + gl.glVertex2f (x+image.width, y); + gl.glTexCoord2f (image.sh, image.th); + gl.glVertex2f (x+image.width, y+image.height); + gl.glTexCoord2f (image.sl, image.th); + gl.glVertex2f (x, y+image.height); + gl.glEnd (); + + if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( (gl_config.renderer & GL_RENDERER_RENDITION) != 0 ) ) && !image.has_alpha) + gl.glEnable (GL.GL_ALPHA_TEST); + } + + /* + ============= + Draw_TileClear + + This repeats a 64*64 tile graphic to fill the screen around a sized down + refresh window. + ============= + */ + protected void Draw_TileClear(int x, int y, int w, int h, String pic) { + image_t image; + + image = Draw_FindPic(pic); + if (image == null) + { + ri.Con_Printf(Defines.PRINT_ALL, "Can't find pic: " + pic + '\n'); + return; + } + + if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( (gl_config.renderer & GL_RENDERER_RENDITION) != 0 ) ) && !image.has_alpha) + gl.glDisable(GL.GL_ALPHA_TEST); + + GL_Bind(image.texnum); + gl.glBegin (GL.GL_QUADS); + gl.glTexCoord2f(x/64.0f, y/64.0f); + gl.glVertex2f (x, y); + gl.glTexCoord2f( (x+w)/64.0f, y/64.0f); + gl.glVertex2f(x+w, y); + gl.glTexCoord2f( (x+w)/64.0f, (y+h)/64.0f); + gl.glVertex2f(x+w, y+h); + gl.glTexCoord2f( x/64.0f, (y+h)/64.0f ); + gl.glVertex2f (x, y+h); + gl.glEnd (); + + if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( (gl_config.renderer & GL_RENDERER_RENDITION) != 0 ) ) && !image.has_alpha) + gl.glEnable(GL.GL_ALPHA_TEST); + } + + + /* + ============= + Draw_Fill + + Fills a box of pixels with a single color + ============= + */ + protected void Draw_Fill(int x, int y, int w, int h, int colorIndex) { + + if ( colorIndex > 255) + ri.Sys_Error(Defines.ERR_FATAL, "Draw_Fill: bad color"); + + gl.glDisable(GL.GL_TEXTURE_2D); + + int color = d_8to24table[colorIndex]; + + gl.glColor3ub( + (byte)((color >> 0) & 0xff), // r + (byte)((color >> 8) & 0xff), // g + (byte)((color >> 16) & 0xff) // b + ); + + gl.glBegin (GL.GL_QUADS); + + gl.glVertex2f(x,y); + gl.glVertex2f(x+w, y); + gl.glVertex2f(x+w, y+h); + gl.glVertex2f(x, y+h); + + gl.glEnd(); + gl.glColor3f(1,1,1); + gl.glEnable(GL.GL_TEXTURE_2D); + } + +// ============================================================================= + + /* + ================ + Draw_FadeScreen + ================ + */ + protected void Draw_FadeScreen() { + gl.glEnable(GL.GL_BLEND); + gl.glDisable(GL.GL_TEXTURE_2D); + gl.glColor4f(0, 0, 0, 0.8f); + gl.glBegin(GL.GL_QUADS); + + gl.glVertex2f(0,0); + gl.glVertex2f(vid.width, 0); + gl.glVertex2f(vid.width, vid.height); + gl.glVertex2f(0, vid.height); + + gl.glEnd(); + gl.glColor4f(1,1,1,1); + gl.glEnable(GL.GL_TEXTURE_2D); + gl.glDisable(GL.GL_BLEND); + } + +// ==================================================================== + + + /* + ============= + Draw_StretchRaw + ============= + */ + protected void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte[] data) + { + int i, j, trows; + int sourceIndex; + int frac, fracstep; + float hscale; + int row; + float t; + + GL_Bind(0); + + if (rows<=256) + { + hscale = 1; + trows = rows; + } + else + { + hscale = rows/256.0f; + trows = 256; + } + t = rows*hscale / 256; + + if ( !qglColorTableEXT ) + { + int[] image32 = new int[256*256]; + int destIndex = 0; + + for (i=0 ; i<trows ; i++) + { + row = (int)(i*hscale); + if (row > rows) + break; + sourceIndex = cols*row; + destIndex = i*256; + fracstep = cols*0x10000/256; + frac = fracstep >> 1; + for (j=0 ; j<256 ; j++) + { + image32[destIndex + j] = r_rawpalette[data[sourceIndex + (frac>>16)] & 0xff]; + frac += fracstep; + } + } + gl.glTexImage2D (GL.GL_TEXTURE_2D, 0, gl_tex_solid_format, 256, 256, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, image32); + } + else + { + byte[] image8 = new byte[256*256]; + int destIndex = 0;; + + for (i=0 ; i<trows ; i++) + { + row = (int)(i*hscale); + if (row > rows) + break; + sourceIndex = cols*row; + destIndex = i*256; + fracstep = cols*0x10000/256; + frac = fracstep >> 1; + for (j=0 ; j<256 ; j++) + { + image8[destIndex + j] = data[sourceIndex + (frac>>16)]; + frac += fracstep; + } + } + + gl.glTexImage2D( GL.GL_TEXTURE_2D, + 0, + GL_COLOR_INDEX8_EXT, + 256, 256, + 0, + GL.GL_COLOR_INDEX, + GL.GL_UNSIGNED_BYTE, + image8 ); + } + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + + if ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( (gl_config.renderer & GL_RENDERER_RENDITION) != 0 ) ) + gl.glDisable (GL.GL_ALPHA_TEST); + + gl.glBegin (GL.GL_QUADS); + gl.glTexCoord2f (0, 0); + gl.glVertex2f (x, y); + gl.glTexCoord2f (1, 0); + gl.glVertex2f (x+w, y); + gl.glTexCoord2f (1, t); + gl.glVertex2f (x+w, y+h); + gl.glTexCoord2f (0, t); + gl.glVertex2f (x, y+h); + gl.glEnd (); + + if ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( (gl_config.renderer & GL_RENDERER_RENDITION) != 0 ) ) + gl.glEnable (GL.GL_ALPHA_TEST); + } + +} diff --git a/src/jake2/render/fastjogl/Image.java b/src/jake2/render/fastjogl/Image.java new file mode 100644 index 0000000..de364c3 --- /dev/null +++ b/src/jake2/render/fastjogl/Image.java @@ -0,0 +1,1673 @@ +/* + * Image.java + * Copyright (C) 2003 + * + * $Id: Image.java,v 1.1 2004-07-09 06:50:49 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.fastjogl; + +import jake2.Defines; +import jake2.client.particle_t; +import jake2.game.cvar_t; +import jake2.qcommon.longjmpException; +import jake2.qcommon.qfiles; +import jake2.render.image_t; +import jake2.util.Lib; +import jake2.util.Vargs; + +import java.awt.Dimension; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.nio.*; +import java.util.Arrays; + +import net.java.games.jogl.GL; + +/** + * Image + * + * @author cwei + */ +public abstract class Image extends Main { + + image_t draw_chars; + + image_t[] gltextures = new image_t[MAX_GLTEXTURES]; + //Map gltextures = new Hashtable(MAX_GLTEXTURES); // image_t + int numgltextures; + int base_textureid; // gltextures[i] = base_textureid+i + + byte[] intensitytable = new byte[256]; + byte[] gammatable = new byte[256]; + + cvar_t intensity; + + // + // qboolean GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean is_sky ); + // qboolean GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap); + // + + int gl_solid_format = 3; + int gl_alpha_format = 4; + + int gl_tex_solid_format = 3; + int gl_tex_alpha_format = 4; + + int gl_filter_min = GL.GL_LINEAR_MIPMAP_NEAREST; + int gl_filter_max = GL.GL_LINEAR; + + Image() { + // init the texture cache + for (int i = 0; i < gltextures.length; i++) + { + gltextures[i] = new image_t(i); + } + numgltextures = 0; + } + + void GL_SetTexturePalette(int[] palette) { + + assert(palette != null && palette.length == 256) : "int palette[256] bug"; + + int i; + byte[] temptable = new byte[768]; + + if (qglColorTableEXT && gl_ext_palettedtexture.value != 0.0f) { + for (i = 0; i < 256; i++) { + temptable[i * 3 + 0] = (byte) ((palette[i] >> 0) & 0xff); + temptable[i * 3 + 1] = (byte) ((palette[i] >> 8) & 0xff); + temptable[i * 3 + 2] = (byte) ((palette[i] >> 16) & 0xff); + } + + gl.glColorTableEXT(GL.GL_SHARED_TEXTURE_PALETTE_EXT, GL.GL_RGB, 256, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, temptable); + } + } + + void GL_EnableMultitexture(boolean enable) { + if (enable) { + GL_SelectTexture(GL_TEXTURE1); + gl.glEnable(GL.GL_TEXTURE_2D); + GL_TexEnv(GL.GL_REPLACE); + } + else { + GL_SelectTexture(GL_TEXTURE1); + gl.glDisable(GL.GL_TEXTURE_2D); + GL_TexEnv(GL.GL_REPLACE); + } + GL_SelectTexture(GL_TEXTURE0); + GL_TexEnv(GL.GL_REPLACE); + } + + void GL_SelectTexture(int texture /* GLenum */) { + int tmu; + + tmu = (texture == GL_TEXTURE0) ? 0 : 1; + + if (tmu == gl_state.currenttmu) { + return; + } + + gl_state.currenttmu = tmu; + + gl.glActiveTextureARB(texture); + gl.glClientActiveTextureARB(texture); + } + + int[] lastmodes = { -1, -1 }; + + void GL_TexEnv(int mode /* GLenum */ + ) { + + if (mode != lastmodes[gl_state.currenttmu]) { + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, mode); + lastmodes[gl_state.currenttmu] = mode; + } + } + + void GL_Bind(int texnum) { + + if ((gl_nobind.value != 0) && (draw_chars != null)) { + // performance evaluation option + texnum = draw_chars.texnum; + } + if (gl_state.currenttextures[gl_state.currenttmu] == texnum) + return; + + gl_state.currenttextures[gl_state.currenttmu] = texnum; + gl.glBindTexture(GL.GL_TEXTURE_2D, texnum); + } + + void GL_MBind(int target /* GLenum */, int texnum) { + GL_SelectTexture(target); + if (target == GL_TEXTURE0) { + if (gl_state.currenttextures[0] == texnum) + return; + } + else { + if (gl_state.currenttextures[1] == texnum) + return; + } + GL_Bind(texnum); + } + + // glmode_t + static class glmode_t { + String name; + int minimize, maximize; + + glmode_t(String name, int minimize, int maximze) { + this.name = name; + this.minimize = minimize; + this.maximize = maximze; + } + } + + static final glmode_t modes[] = + { + new glmode_t("GL_NEAREST", GL.GL_NEAREST, GL.GL_NEAREST), + new glmode_t("GL_LINEAR", GL.GL_LINEAR, GL.GL_LINEAR), + new glmode_t("GL_NEAREST_MIPMAP_NEAREST", GL.GL_NEAREST_MIPMAP_NEAREST, GL.GL_NEAREST), + new glmode_t("GL_LINEAR_MIPMAP_NEAREST", GL.GL_LINEAR_MIPMAP_NEAREST, GL.GL_LINEAR), + new glmode_t("GL_NEAREST_MIPMAP_LINEAR", GL.GL_NEAREST_MIPMAP_LINEAR, GL.GL_NEAREST), + new glmode_t("GL_LINEAR_MIPMAP_LINEAR", GL.GL_LINEAR_MIPMAP_LINEAR, GL.GL_LINEAR)}; + + static final int NUM_GL_MODES = modes.length; + + // gltmode_t + static class gltmode_t { + String name; + int mode; + + gltmode_t(String name, int mode) { + this.name = name; + this.mode = mode; + } + } + + static final gltmode_t[] gl_alpha_modes = + { + new gltmode_t("default", 4), + new gltmode_t("GL_RGBA", GL.GL_RGBA), + new gltmode_t("GL_RGBA8", GL.GL_RGBA8), + new gltmode_t("GL_RGB5_A1", GL.GL_RGB5_A1), + new gltmode_t("GL_RGBA4", GL.GL_RGBA4), + new gltmode_t("GL_RGBA2", GL.GL_RGBA2), + }; + + static final int NUM_GL_ALPHA_MODES = gl_alpha_modes.length; + + static final gltmode_t[] gl_solid_modes = + { + new gltmode_t("default", 3), + new gltmode_t("GL_RGB", GL.GL_RGB), + new gltmode_t("GL_RGB8", GL.GL_RGB8), + new gltmode_t("GL_RGB5", GL.GL_RGB5), + new gltmode_t("GL_RGB4", GL.GL_RGB4), + new gltmode_t("GL_R3_G3_B2", GL.GL_R3_G3_B2), + // #ifdef GL_RGB2_EXT + new gltmode_t("GL_RGB2", GL.GL_RGB2_EXT) + // #endif + }; + + static final int NUM_GL_SOLID_MODES = gl_solid_modes.length; + + /* + =============== + GL_TextureMode + =============== + */ + void GL_TextureMode(String string) { + + int i; + for (i = 0; i < NUM_GL_MODES; i++) { + if (modes[i].name.equalsIgnoreCase(string)) + break; + } + + if (i == NUM_GL_MODES) { + ri.Con_Printf(Defines.PRINT_ALL, "bad filter name: [" + string + "]\n"); + return; + } + + gl_filter_min = modes[i].minimize; + gl_filter_max = modes[i].maximize; + + image_t glt; + // change all the existing mipmap texture objects + for (i = 0; i < numgltextures; i++) { + glt = gltextures[i]; + + if (glt.type != it_pic && glt.type != it_sky) { + GL_Bind(glt.texnum); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, gl_filter_min); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, gl_filter_max); + } + } + } + + /* + =============== + GL_TextureAlphaMode + =============== + */ + void GL_TextureAlphaMode(String string) { + + int i; + for (i = 0; i < NUM_GL_ALPHA_MODES; i++) { + if (gl_alpha_modes[i].name.equalsIgnoreCase(string)) + break; + } + + if (i == NUM_GL_ALPHA_MODES) { + ri.Con_Printf(Defines.PRINT_ALL, "bad alpha texture mode name: [" + string + "]\n"); + return; + } + + gl_tex_alpha_format = gl_alpha_modes[i].mode; + } + + /* + =============== + GL_TextureSolidMode + =============== + */ + void GL_TextureSolidMode(String string) { + int i; + for (i = 0; i < NUM_GL_SOLID_MODES; i++) { + if (gl_solid_modes[i].name.equalsIgnoreCase(string)) + break; + } + + if (i == NUM_GL_SOLID_MODES) { + ri.Con_Printf(Defines.PRINT_ALL, "bad solid texture mode name: [" + string + "]\n"); + return; + } + + gl_tex_solid_format = gl_solid_modes[i].mode; + } + + /* + =============== + GL_ImageList_f + =============== + */ + void GL_ImageList_f() { + + image_t image; + int texels; + final String[] palstrings = { "RGB", "PAL" }; + + ri.Con_Printf(Defines.PRINT_ALL, "------------------\n"); + texels = 0; + + for (int i = 0; i < numgltextures; i++) { + image = gltextures[i]; + if (image.texnum <= 0) + continue; + + texels += image.upload_width * image.upload_height; + switch (image.type) { + case it_skin : + ri.Con_Printf(Defines.PRINT_ALL, "M"); + break; + case it_sprite : + ri.Con_Printf(Defines.PRINT_ALL, "S"); + break; + case it_wall : + ri.Con_Printf(Defines.PRINT_ALL, "W"); + break; + case it_pic : + ri.Con_Printf(Defines.PRINT_ALL, "P"); + break; + default : + ri.Con_Printf(Defines.PRINT_ALL, " "); + break; + } + + ri.Con_Printf( + Defines.PRINT_ALL, + " %3i %3i %s: %s\n", + new Vargs(4).add(image.upload_width).add(image.upload_height).add(palstrings[(image.paletted) ? 1 : 0]).add( + image.name)); + } + ri.Con_Printf(Defines.PRINT_ALL, "Total texel count (not counting mipmaps): " + texels + '\n'); + } + + /* + ============================================================================= + + scrap allocation + + Allocate all the little status bar objects into a single texture + to crutch up inefficient hardware / drivers + + ============================================================================= + */ + + static final int MAX_SCRAPS = 1; + static final int BLOCK_WIDTH = 256; + static final int BLOCK_HEIGHT = 256; + + int[][] scrap_allocated = new int[MAX_SCRAPS][BLOCK_WIDTH]; + byte[][] scrap_texels = new byte[MAX_SCRAPS][BLOCK_WIDTH * BLOCK_HEIGHT]; + boolean scrap_dirty; + + static class pos_t { + int x, y; + + pos_t(int x, int y) { + this.x = x; + this.y = y; + } + } + + // returns a texture number and the position inside it + int Scrap_AllocBlock(int w, int h, pos_t pos) { + int i, j; + int best, best2; + int texnum; + + for (texnum = 0; texnum < MAX_SCRAPS; texnum++) { + best = BLOCK_HEIGHT; + + for (i = 0; i < BLOCK_WIDTH - w; i++) { + best2 = 0; + + for (j = 0; j < w; j++) { + if (scrap_allocated[texnum][i + j] >= best) + break; + if (scrap_allocated[texnum][i + j] > best2) + best2 = scrap_allocated[texnum][i + j]; + } + if (j == w) { // this is a valid spot + pos.x = i; + pos.y = best = best2; + } + } + + if (best + h > BLOCK_HEIGHT) + continue; + + for (i = 0; i < w; i++) + scrap_allocated[texnum][pos.x + i] = best + h; + + return texnum; + } + + return -1; + // Sys_Error ("Scrap_AllocBlock: full"); + } + + int scrap_uploads = 0; + + void Scrap_Upload() { + scrap_uploads++; + GL_Bind(TEXNUM_SCRAPS); + GL_Upload8(scrap_texels[0], BLOCK_WIDTH, BLOCK_HEIGHT, false, false); + scrap_dirty = false; + } + + /* + ================================================================= + + PCX LOADING + + ================================================================= + */ + + /* + ============== + LoadPCX + ============== + */ + byte[] LoadPCX(String filename, byte[][] palette, Dimension dim) { + qfiles.pcx_t pcx; + + // + // load the file + // + byte[] raw = ri.FS_LoadFile(filename); + + if (raw == null) { + ri.Con_Printf(Defines.PRINT_DEVELOPER, "Bad pcx file " + filename + '\n'); + return null; + } + + // + // parse the PCX file + // + pcx = new qfiles.pcx_t(raw); + + if (pcx.manufacturer != 0x0a + || pcx.version != 5 + || pcx.encoding != 1 + || pcx.bits_per_pixel != 8 + || pcx.xmax >= 640 + || pcx.ymax >= 480) { + + ri.Con_Printf(Defines.PRINT_ALL, "Bad pcx file " + filename + '\n'); + return null; + } + + int width = pcx.xmax - pcx.xmin + 1; + int height = pcx.ymax - pcx.ymin + 1; + + byte[] pix = new byte[width * height]; + + if (palette != null) { + palette[0] = new byte[768]; + System.arraycopy(raw, raw.length - 768, palette[0], 0, 768); + } + + if (dim != null) { + dim.width = width; + dim.height = height; + } + + // + // decode pcx + // + int count = 0; + byte dataByte = 0; + int runLength = 0; + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < width;) { + + dataByte = pcx.data.get(); + + if ((dataByte & 0xC0) == 0xC0) { + runLength = dataByte & 0x3F; + dataByte = pcx.data.get(); + // write runLength pixel + while (runLength-- > 0) { + pix[count++] = dataByte; + x++; + } + } + else { + // write one pixel + pix[count++] = dataByte; + x++; + } + } + } + return pix; + } + + // /* + // ========================================================= + // + // TARGA LOADING + // + // ========================================================= + // */ + /* + ============= + LoadTGA + ============= + */ + byte[] LoadTGA(String name, Dimension dim) { + int columns, rows, numPixels; + int pixbuf; // index into pic + int row, column; + byte[] raw; + ByteBuffer buf_p; + int length; + qfiles.tga_t targa_header; + byte[] pic = null; + + // + // load the file + // + raw = ri.FS_LoadFile (name); + + if (raw == null) + { + ri.Con_Printf(Defines.PRINT_DEVELOPER, "Bad tga file "+ name +'\n'); + return null; + } + + targa_header = new qfiles.tga_t(raw); + + if (targa_header.image_type != 2 && targa_header.image_type != 10) + ri.Sys_Error(Defines.ERR_DROP, "LoadTGA: Only type 2 and 10 targa RGB images supported\n"); + + if (targa_header.colormap_type != 0 || (targa_header.pixel_size != 32 && targa_header.pixel_size != 24)) + ri.Sys_Error (Defines.ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); + + columns = targa_header.width; + rows = targa_header.height; + numPixels = columns * rows; + + if (dim != null) { + dim.width = columns; + dim.height = rows; + } + + pic = new byte[numPixels * 4]; // targa_rgba; + + if (targa_header.id_length != 0) + targa_header.data.position(targa_header.id_length); // skip TARGA image comment + + buf_p = targa_header.data; + + byte red,green,blue,alphabyte; + red = green = blue = alphabyte = 0; + int packetHeader, packetSize, j; + + if (targa_header.image_type==2) { // Uncompressed, RGB images + for(row=rows-1; row>=0; row--) { + + pixbuf = row * columns * 4; + + for(column=0; column<columns; column++) { + switch (targa_header.pixel_size) { + case 24: + + blue = buf_p.get(); + green = buf_p.get(); + red = buf_p.get(); + pic[pixbuf++] = red; + pic[pixbuf++] = green; + pic[pixbuf++] = blue; + pic[pixbuf++] = (byte)255; + break; + case 32: + blue = buf_p.get(); + green = buf_p.get(); + red = buf_p.get(); + alphabyte = buf_p.get(); + pic[pixbuf++] = red; + pic[pixbuf++] = green; + pic[pixbuf++] = blue; + pic[pixbuf++] = alphabyte; + break; + } + } + } + } + else if (targa_header.image_type==10) { // Runlength encoded RGB images + for(row=rows-1; row>=0; row--) { + + pixbuf = row * columns * 4; + try { + + for(column=0; column<columns; ) { + + packetHeader= buf_p.get() & 0xFF; + packetSize = 1 + (packetHeader & 0x7f); + + if ((packetHeader & 0x80) != 0) { // run-length packet + switch (targa_header.pixel_size) { + case 24: + blue = buf_p.get(); + green = buf_p.get(); + red = buf_p.get(); + alphabyte = (byte)255; + break; + case 32: + blue = buf_p.get(); + green = buf_p.get(); + red = buf_p.get(); + alphabyte = buf_p.get(); + break; + } + + for(j=0;j<packetSize;j++) { + pic[pixbuf++]=red; + pic[pixbuf++]=green; + pic[pixbuf++]=blue; + pic[pixbuf++]=alphabyte; + column++; + if (column==columns) { // run spans across rows + column=0; + if (row>0) + row--; + else + // goto label breakOut; + throw new longjmpException(); + + pixbuf = row * columns * 4; + } + } + } + else { // non run-length packet + for(j=0;j<packetSize;j++) { + switch (targa_header.pixel_size) { + case 24: + blue = buf_p.get(); + green = buf_p.get(); + red = buf_p.get(); + pic[pixbuf++] = red; + pic[pixbuf++] = green; + pic[pixbuf++] = blue; + pic[pixbuf++] = (byte)255; + break; + case 32: + blue = buf_p.get(); + green = buf_p.get(); + red = buf_p.get(); + alphabyte = buf_p.get(); + pic[pixbuf++] = red; + pic[pixbuf++] = green; + pic[pixbuf++] = blue; + pic[pixbuf++] = alphabyte; + break; + } + column++; + if (column==columns) { // pixel packet run spans across rows + column=0; + if (row>0) + row--; + else + // goto label breakOut; + throw new longjmpException(); + + pixbuf = row * columns * 4; + } + } + } + } + } catch (longjmpException e){ + // label breakOut: + } + } + } + return pic; + } + + /* + ==================================================================== + + IMAGE FLOOD FILLING + + ==================================================================== + */ + + /* + ================= + Mod_FloodFillSkin + + Fill background pixels so mipmapping doesn't have haloes + ================= + */ + + static class floodfill_t { + short x, y; + } + + // must be a power of 2 + static final int FLOODFILL_FIFO_SIZE = 0x1000; + static final int FLOODFILL_FIFO_MASK = FLOODFILL_FIFO_SIZE - 1; + // + // #define FLOODFILL_STEP( off, dx, dy ) \ + // { \ + // if (pos[off] == fillcolor) \ + // { \ + // pos[off] = 255; \ + // fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \ + // inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \ + // } \ + // else if (pos[off] != 255) fdc = pos[off]; \ + // } + + // void FLOODFILL_STEP( int off, int dx, int dy ) + // { + // if (pos[off] == fillcolor) + // { + // pos[off] = 255; + // fifo[inpt].x = x + dx; fifo[inpt].y = y + dy; + // inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; + // } + // else if (pos[off] != 255) fdc = pos[off]; + // } + + // TODO check this: R_FloodFillSkin( byte[] skin, int skinwidth, int skinheight) + void R_FloodFillSkin(byte[] skin, int skinwidth, int skinheight) { + // byte fillcolor = *skin; // assume this is the pixel to fill + int fillcolor = skin[0] & 0xff; + floodfill_t[] fifo = new floodfill_t[FLOODFILL_FIFO_SIZE]; + int inpt = 0, outpt = 0; + int filledcolor = -1; + int i; + + for (int j = 0; j < fifo.length; j++) { + fifo[j] = new floodfill_t(); + } + + if (filledcolor == -1) { + filledcolor = 0; + // attempt to find opaque black + for (i = 0; i < 256; ++i) + // TODO check this + if (d_8to24table[i] == 0xFF000000) { // alpha 1.0 + //if (d_8to24table[i] == (255 << 0)) // alpha 1.0 + filledcolor = i; + break; + } + } + + // can't fill to filled color or to transparent color (used as visited marker) + if ((fillcolor == filledcolor) || (fillcolor == 255)) { + return; + } + + fifo[inpt].x = 0; + fifo[inpt].y = 0; + inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; + + while (outpt != inpt) { + int x = fifo[outpt].x; + int y = fifo[outpt].y; + int fdc = filledcolor; + // byte *pos = &skin[x + skinwidth * y]; + int pos = x + skinwidth * y; + // + outpt = (outpt + 1) & FLOODFILL_FIFO_MASK; + + int off, dx, dy; + + if (x > 0) { + // FLOODFILL_STEP( -1, -1, 0 ); + off = -1; + dx = -1; + dy = 0; + if (skin[pos + off] == (byte) fillcolor) { + skin[pos + off] = (byte) 255; + fifo[inpt].x = (short) (x + dx); + fifo[inpt].y = (short) (y + dy); + inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; + } + else if (skin[pos + off] != (byte) 255) + fdc = skin[pos + off] & 0xff; + } + + if (x < skinwidth - 1) { + // FLOODFILL_STEP( 1, 1, 0 ); + off = 1; + dx = 1; + dy = 0; + if (skin[pos + off] == (byte) fillcolor) { + skin[pos + off] = (byte) 255; + fifo[inpt].x = (short) (x + dx); + fifo[inpt].y = (short) (y + dy); + inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; + } + else if (skin[pos + off] != (byte) 255) + fdc = skin[pos + off] & 0xff; + } + + if (y > 0) { + // FLOODFILL_STEP( -skinwidth, 0, -1 ); + off = -skinwidth; + dx = 0; + dy = -1; + if (skin[pos + off] == (byte) fillcolor) { + skin[pos + off] = (byte) 255; + fifo[inpt].x = (short) (x + dx); + fifo[inpt].y = (short) (y + dy); + inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; + } + else if (skin[pos + off] != (byte) 255) + fdc = skin[pos + off] & 0xff; + } + + if (y < skinheight - 1) { + // FLOODFILL_STEP( skinwidth, 0, 1 ); + off = skinwidth; + dx = 0; + dy = 1; + if (skin[pos + off] == (byte) fillcolor) { + skin[pos + off] = (byte) 255; + fifo[inpt].x = (short) (x + dx); + fifo[inpt].y = (short) (y + dy); + inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; + } + else if (skin[pos + off] != (byte) 255) + fdc = skin[pos + off] & 0xff; + + } + + skin[x + skinwidth * y] = (byte) fdc; + } + } + + // ======================================================= + + /* + ================ + GL_ResampleTexture + ================ + */ + // cwei :-) + void GL_ResampleTexture(int[] in, int inwidth, int inheight, int[] out, int outwidth, int outheight) { + // int i, j; + // unsigned *inrow, *inrow2; + // int frac, fracstep; + // int[] p1 = new int[1024]; + // int[] p2 = new int[1024]; + // + + // *** this source do the same *** + BufferedImage image = new BufferedImage(inwidth, inheight, BufferedImage.TYPE_INT_ARGB); + + image.setRGB(0, 0, inwidth, inheight, in, 0, inwidth); + + AffineTransformOp op = + new AffineTransformOp( + AffineTransform.getScaleInstance(outwidth * 1.0 / inwidth, outheight * 1.0 / inheight), + AffineTransformOp.TYPE_NEAREST_NEIGHBOR); + BufferedImage tmp = op.filter(image, null); + + tmp.getRGB(0, 0, outwidth, outheight, out, 0, outwidth); + + // *** end *** + + // byte *pix1, *pix2, *pix3, *pix4; + // + // fracstep = inwidth*0x10000/outwidth; + // + // frac = fracstep>>2; + // for (i=0 ; i<outwidth ; i++) + // { + // p1[i] = 4*(frac>>16); + // frac += fracstep; + // } + // frac = 3*(fracstep>>2); + // for (i=0 ; i<outwidth ; i++) + // { + // p2[i] = 4*(frac>>16); + // frac += fracstep; + // } + // + // for (i=0 ; i<outheight ; i++, out += outwidth) + // { + // inrow = in + inwidth*(int)((i+0.25)*inheight/outheight); + // inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight); + // frac = fracstep >> 1; + // for (j=0 ; j<outwidth ; j++) + // { + // pix1 = (byte *)inrow + p1[j]; + // pix2 = (byte *)inrow + p2[j]; + // pix3 = (byte *)inrow2 + p1[j]; + // pix4 = (byte *)inrow2 + p2[j]; + // ((byte *)(out+j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2; + // ((byte *)(out+j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2; + // ((byte *)(out+j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2; + // ((byte *)(out+j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2; + // } + // } + } + + /* + ================ + GL_LightScaleTexture + + Scale up the pixel values in a texture to increase the + lighting range + ================ + */ + void GL_LightScaleTexture(int[] in, int inwidth, int inheight, boolean only_gamma) { + if (only_gamma) { + int i, c; + int r, g, b, color; + + c = inwidth * inheight; + for (i = 0; i < c; i++) { + color = in[i]; + r = (color >> 0) & 0xFF; + g = (color >> 8) & 0xFF; + b = (color >> 16) & 0xFF; + + r = gammatable[r] & 0xFF; + g = gammatable[g] & 0xFF; + b = gammatable[b] & 0xFF; + + in[i] = (r << 0) | (g << 8) | (b << 16) | (color & 0xFF000000); + } + } + else { + int i, c; + int r, g, b, color; + + c = inwidth * inheight; + for (i = 0; i < c; i++) { + color = in[i]; + r = (color >> 0) & 0xFF; + g = (color >> 8) & 0xFF; + b = (color >> 16) & 0xFF; + + r = gammatable[intensitytable[r] & 0xFF] & 0xFF; + g = gammatable[intensitytable[g] & 0xFF] & 0xFF; + b = gammatable[intensitytable[b] & 0xFF] & 0xFF; + + in[i] = (r << 0) | (g << 8) | (b << 16) | (color & 0xFF000000); + } + + } + } + + /* + ================ + GL_MipMap + + Operates in place, quartering the size of the texture + ================ + */ + void GL_MipMap(int[] in, int width, int height) { + int i, j; + int[] out; + + out = in; + + int inIndex = 0; + int outIndex = 0; + + int r, g, b, a; + int p1, p2, p3, p4; + + for (i = 0; i < height; i += 2, inIndex += width) { + for (j = 0; j < width; j += 2, outIndex += 1, inIndex += 2) { + + p1 = in[inIndex + 0]; + p2 = in[inIndex + 1]; + p3 = in[inIndex + width + 0]; + p4 = in[inIndex + width + 1]; + + r = (((p1 >> 0) & 0xFF) + ((p2 >> 0) & 0xFF) + ((p3 >> 0) & 0xFF) + ((p4 >> 0) & 0xFF)) >> 2; + g = (((p1 >> 8) & 0xFF) + ((p2 >> 8) & 0xFF) + ((p3 >> 8) & 0xFF) + ((p4 >> 8) & 0xFF)) >> 2; + b = (((p1 >> 16) & 0xFF) + ((p2 >> 16) & 0xFF) + ((p3 >> 16) & 0xFF) + ((p4 >> 16) & 0xFF)) >> 2; + a = (((p1 >> 24) & 0xFF) + ((p2 >> 24) & 0xFF) + ((p3 >> 24) & 0xFF) + ((p4 >> 24) & 0xFF)) >> 2; + + out[outIndex] = (r << 0) | (g << 8) | (b << 16) | (a << 24); + } + } + } + + /* + =============== + GL_Upload32 + + Returns has_alpha + =============== + */ + void GL_BuildPalettedTexture(byte[] paletted_texture, int[] scaled, int scaled_width, int scaled_height) { + + int r, g, b, c; + int size = scaled_width * scaled_height; + + for (int i = 0; i < size; i++) { + + r = (scaled[i] >> 3) & 31; + g = (scaled[i] >> 10) & 63; + b = (scaled[i] >> 19) & 31; + + c = r | (g << 5) | (b << 11); + + paletted_texture[i] = gl_state.d_16to8table[c]; + } + } + + int upload_width, upload_height; + boolean uploaded_paletted; + + /* + =============== + GL_Upload32 + + Returns has_alpha + =============== + */ + int[] scaled = new int[256 * 256]; + byte[] paletted_texture = new byte[256 * 256]; + IntBuffer tex = Lib.newIntBuffer(512 * 256, ByteOrder.LITTLE_ENDIAN); + + boolean GL_Upload32(int[] data, int width, int height, boolean mipmap) { + int samples; + int scaled_width, scaled_height; + int i, c; + int comp; + + Arrays.fill(scaled, 0); + Arrays.fill(paletted_texture, (byte)0); + + uploaded_paletted = false; + + for (scaled_width = 1; scaled_width < width; scaled_width <<= 1); + if (gl_round_down.value > 0.0f && scaled_width > width && mipmap) + scaled_width >>= 1; + for (scaled_height = 1; scaled_height < height; scaled_height <<= 1); + if (gl_round_down.value > 0.0f && scaled_height > height && mipmap) + scaled_height >>= 1; + + // let people sample down the world textures for speed + if (mipmap) { + scaled_width >>= (int) gl_picmip.value; + scaled_height >>= (int) gl_picmip.value; + } + + // don't ever bother with >256 textures + if (scaled_width > 256) + scaled_width = 256; + if (scaled_height > 256) + scaled_height = 256; + + if (scaled_width < 1) + scaled_width = 1; + if (scaled_height < 1) + scaled_height = 1; + + upload_width = scaled_width; + upload_height = scaled_height; + + if (scaled_width * scaled_height > 256 * 256) + ri.Sys_Error(Defines.ERR_DROP, "GL_Upload32: too big"); + + // scan the texture for any non-255 alpha + c = width * height; + samples = gl_solid_format; + + for (i = 0; i < c; i++) { + if ((data[i] & 0xff000000) != 0xff000000) { + samples = gl_alpha_format; + break; + } + } + + if (samples == gl_solid_format) + comp = gl_tex_solid_format; + else if (samples == gl_alpha_format) + comp = gl_tex_alpha_format; + else { + ri.Con_Printf(Defines.PRINT_ALL, "Unknown number of texture components " + samples + '\n'); + comp = samples; + } + + // simulates a goto + try { + if (scaled_width == width && scaled_height == height) { + if (!mipmap) { + if (qglColorTableEXT && gl_ext_palettedtexture.value != 0.0f && samples == gl_solid_format) { + uploaded_paletted = true; + GL_BuildPalettedTexture(paletted_texture, data, scaled_width, scaled_height); + gl.glTexImage2D( + GL.GL_TEXTURE_2D, + 0, + GL_COLOR_INDEX8_EXT, + scaled_width, + scaled_height, + 0, + GL.GL_COLOR_INDEX, + GL.GL_UNSIGNED_BYTE, + paletted_texture); + } + else { + tex.rewind(); tex.put(data); + gl.glTexImage2D( + GL.GL_TEXTURE_2D, + 0, + comp, + scaled_width, + scaled_height, + 0, + GL.GL_RGBA, + GL.GL_UNSIGNED_BYTE, + tex); + } + //goto done; + throw new longjmpException(); + } + //memcpy (scaled, data, width*height*4); were bytes + System.arraycopy(data, 0, scaled, 0, width * height); + } + else + GL_ResampleTexture(data, width, height, scaled, scaled_width, scaled_height); + + GL_LightScaleTexture(scaled, scaled_width, scaled_height, !mipmap); + + if (qglColorTableEXT && gl_ext_palettedtexture.value != 0.0f && (samples == gl_solid_format)) { + uploaded_paletted = true; + GL_BuildPalettedTexture(paletted_texture, scaled, scaled_width, scaled_height); + gl.glTexImage2D( + GL.GL_TEXTURE_2D, + 0, + GL_COLOR_INDEX8_EXT, + scaled_width, + scaled_height, + 0, + GL.GL_COLOR_INDEX, + GL.GL_UNSIGNED_BYTE, + paletted_texture); + } + else { + tex.rewind(); tex.put(scaled); + gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, tex); + } + + if (mipmap) { + int miplevel; + miplevel = 0; + while (scaled_width > 1 || scaled_height > 1) { + GL_MipMap(scaled, scaled_width, scaled_height); + scaled_width >>= 1; + scaled_height >>= 1; + if (scaled_width < 1) + scaled_width = 1; + if (scaled_height < 1) + scaled_height = 1; + + miplevel++; + if (qglColorTableEXT && gl_ext_palettedtexture.value != 0.0f && samples == gl_solid_format) { + uploaded_paletted = true; + GL_BuildPalettedTexture(paletted_texture, scaled, scaled_width, scaled_height); + gl.glTexImage2D( + GL.GL_TEXTURE_2D, + miplevel, + GL_COLOR_INDEX8_EXT, + scaled_width, + scaled_height, + 0, + GL.GL_COLOR_INDEX, + GL.GL_UNSIGNED_BYTE, + paletted_texture); + } + else { + tex.rewind(); tex.put(scaled); + gl.glTexImage2D( + GL.GL_TEXTURE_2D, + miplevel, + comp, + scaled_width, + scaled_height, + 0, + GL.GL_RGBA, + GL.GL_UNSIGNED_BYTE, + tex); + } + } + } + // label done: + } + catch (longjmpException e) { + ; // replaces label done + } + + if (mipmap) { + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, gl_filter_min); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, gl_filter_max); + } + else { + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, gl_filter_max); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, gl_filter_max); + } + + return (samples == gl_alpha_format); + } + + /* + =============== + GL_Upload8 + + Returns has_alpha + =============== + */ + + int[] trans = new int[512 * 256]; + + boolean GL_Upload8(byte[] data, int width, int height, boolean mipmap, boolean is_sky) { + + Arrays.fill(trans, 0); + + int s = width * height; + + if (s > trans.length) + ri.Sys_Error(Defines.ERR_DROP, "GL_Upload8: too large"); + + if (qglColorTableEXT && gl_ext_palettedtexture.value != 0.0f && is_sky) { + gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, width, height, 0, GL.GL_COLOR_INDEX, GL.GL_UNSIGNED_BYTE, data); + + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, gl_filter_max); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, gl_filter_max); + + // TODO check this + return false; + } + else { + int p; + int rgb; + for (int i = 0; i < s; i++) { + p = data[i] & 0xff; + trans[i] = d_8to24table[p]; + + if (p == 255) { // transparent, so scan around for another color + // to avoid alpha fringes + // FIXME: do a full flood fill so mips work... + if (i > width && (data[i - width] & 0xff) != 255) + p = data[i - width] & 0xff; + else if (i < s - width && (data[i + width] & 0xff) != 255) + p = data[i + width] & 0xff; + else if (i > 0 && (data[i - 1] & 0xff) != 255) + p = data[i - 1] & 0xff; + else if (i < s - 1 && (data[i + 1] & 0xff) != 255) + p = data[i + 1] & 0xff; + else + p = 0; + // copy rgb components + + // ((byte *)&trans[i])[0] = ((byte *)&d_8to24table[p])[0]; + // ((byte *)&trans[i])[1] = ((byte *)&d_8to24table[p])[1]; + // ((byte *)&trans[i])[2] = ((byte *)&d_8to24table[p])[2]; + + trans[i] = d_8to24table[p] & 0x00FFFFFF; // only rgb + } + } + + return GL_Upload32(trans, width, height, mipmap); + } + } + + /* + ================ + GL_LoadPic + + This is also used as an entry point for the generated r_notexture + ================ + */ + image_t GL_LoadPic(String name, byte[] pic, int width, int height, int type, int bits) { + image_t image; + int i; + + // find a free image_t + for (i = 0; i<numgltextures ; i++) + { + image = gltextures[i]; + if (image.texnum == 0) + break; + } + + if (i == numgltextures) + { + if (numgltextures == MAX_GLTEXTURES) + ri.Sys_Error (Defines.ERR_DROP, "MAX_GLTEXTURES"); + + numgltextures++; + } + image = gltextures[i]; + + if (name.length() > Defines.MAX_QPATH) + ri.Sys_Error(Defines.ERR_DROP, "Draw_LoadPic: \"" + name + "\" is too long"); + + image.name = name; + image.registration_sequence = registration_sequence; + + image.width = width; + image.height = height; + image.type = type; + + + if (type == it_skin && bits == 8) + R_FloodFillSkin(pic, width, height); + + // load little pics into the scrap + if (image.type == it_pic && bits == 8 && image.width < 64 && image.height < 64) { + pos_t pos = new pos_t(0, 0); + int j, k; + + int texnum = Scrap_AllocBlock(image.width, image.height, pos); + + if (texnum == -1) { + // replace goto nonscrap + + image.scrap = false; + + image.texnum = TEXNUM_IMAGES + image.getId(); // image pos in array + GL_Bind(image.texnum); + + if (bits == 8) { + image.has_alpha = + GL_Upload8(pic, width, height, (image.type != it_pic && image.type != it_sky), image.type == it_sky); + } + else { + int[] tmp = new int[pic.length / 4]; + + for (i = 0; i < tmp.length; i++) { + tmp[i] = ((pic[4 * i + 0] & 0xFF) << 0); // & 0x000000FF; + tmp[i] |= ((pic[4 * i + 1] & 0xFF) << 8); // & 0x0000FF00; + tmp[i] |= ((pic[4 * i + 2] & 0xFF) << 16); // & 0x00FF0000; + tmp[i] |= ((pic[4 * i + 3] & 0xFF) << 24); // & 0xFF000000; + } + + image.has_alpha = GL_Upload32(tmp, width, height, (image.type != it_pic && image.type != it_sky)); + } + + image.upload_width = upload_width; // after power of 2 and scales + image.upload_height = upload_height; + image.paletted = uploaded_paletted; + image.sl = 0; + image.sh = 1; + image.tl = 0; + image.th = 1; + + return image; + } + + scrap_dirty = true; + + // copy the texels into the scrap block + k = 0; + for (i = 0; i < image.height; i++) + for (j = 0; j < image.width; j++, k++) + scrap_texels[texnum][(pos.y + i) * BLOCK_WIDTH + pos.x + j] = pic[k]; + + image.texnum = TEXNUM_SCRAPS + texnum; + image.scrap = true; + image.has_alpha = true; + image.sl = (pos.x + 0.01f) / (float) BLOCK_WIDTH; + image.sh = (pos.x + image.width - 0.01f) / (float) BLOCK_WIDTH; + image.tl = (pos.y + 0.01f) / (float) BLOCK_WIDTH; + image.th = (pos.y + image.height - 0.01f) / (float) BLOCK_WIDTH; + + } + else { + // this was label nonscrap + + image.scrap = false; + + image.texnum = TEXNUM_IMAGES + image.getId(); //image pos in array + GL_Bind(image.texnum); + + if (bits == 8) { + image.has_alpha = GL_Upload8(pic, width, height, (image.type != it_pic && image.type != it_sky), image.type == it_sky); + } + else { + int[] tmp = new int[pic.length / 4]; + + for (i = 0; i < tmp.length; i++) { + tmp[i] = ((pic[4 * i + 0] & 0xFF) << 0); // & 0x000000FF; + tmp[i] |= ((pic[4 * i + 1] & 0xFF) << 8); // & 0x0000FF00; + tmp[i] |= ((pic[4 * i + 2] & 0xFF) << 16); // & 0x00FF0000; + tmp[i] |= ((pic[4 * i + 3] & 0xFF) << 24); // & 0xFF000000; + } + + image.has_alpha = GL_Upload32(tmp, width, height, (image.type != it_pic && image.type != it_sky)); + } + image.upload_width = upload_width; // after power of 2 and scales + image.upload_height = upload_height; + image.paletted = uploaded_paletted; + image.sl = 0; + image.sh = 1; + image.tl = 0; + image.th = 1; + } + return image; + } + + /* + ================ + GL_LoadWal + ================ + */ + image_t GL_LoadWal(String name) { + + image_t image = null; + + byte[] raw = ri.FS_LoadFile(name); + if (raw == null) { + ri.Con_Printf(Defines.PRINT_ALL, "GL_FindImage: can't load " + name + '\n'); + return r_notexture; + } + + qfiles.miptex_t mt = new qfiles.miptex_t(raw); + + byte[] pix = new byte[mt.width * mt.height]; + System.arraycopy(raw, mt.offsets[0], pix, 0, pix.length); + + image = GL_LoadPic(name, pix, mt.width, mt.height, it_wall, 8); + + return image; + } + + /* + =============== + GL_FindImage + + Finds or loads the given image + =============== + */ + image_t GL_FindImage(String name, int type) { + image_t image = null; + + // TODO loest das grossschreibungs problem + name = name.toLowerCase(); + // bughack for bad strings (fuck \0) + int index = name.indexOf('\0'); + if (index != -1) + name = name.substring(0, index); + + if (name == null || name.length() < 5) + return null; // ri.Sys_Error (ERR_DROP, "GL_FindImage: NULL name"); + // ri.Sys_Error (ERR_DROP, "GL_FindImage: bad name: %s", name); + + // look for it + for (int i = 0; i < numgltextures; i++) + { + image = gltextures[i]; + if (name.equals(image.name)) + { + image.registration_sequence = registration_sequence; + return image; + } + } + + // + // load the pic from disk + // + byte[] pic = null; + Dimension dim = new Dimension(); + + if (name.endsWith(".pcx")) { + + pic = LoadPCX(name, null, dim); + if (pic == null) + return null; + image = GL_LoadPic(name, pic, dim.width, dim.height, type, 8); + + } + else if (name.endsWith(".wal")) { + + image = GL_LoadWal(name); + + } + else if (name.endsWith(".tga")) { + + pic = LoadTGA(name, dim); + + if (pic == null) + return null; + + image = GL_LoadPic(name, pic, dim.width, dim.height, type, 32); + + } + else + return null; + + return image; + } + + /* + =============== + R_RegisterSkin + =============== + */ + protected image_t R_RegisterSkin(String name) { + return GL_FindImage(name, it_skin); + } + + /* + ================ + GL_FreeUnusedImages + + Any image that was not touched on this registration sequence + will be freed. + ================ + */ + void GL_FreeUnusedImages() { + + // never free r_notexture or particle texture + r_notexture.registration_sequence = registration_sequence; + r_particletexture.registration_sequence = registration_sequence; + + image_t image = null; + + for (int i = 0; i < numgltextures; i++) { + image = gltextures[i]; + // used this sequence + if (image.registration_sequence == registration_sequence) + continue; + // free image_t slot + if (image.registration_sequence == 0) + continue; + // don't free pics + if (image.type == it_pic) + continue; + + // free it + // TODO jogl bug + gl.glDeleteTextures(1, new int[] {image.texnum}); + image.clear(); + } + } + + /* + =============== + Draw_GetPalette + =============== + */ + protected void Draw_GetPalette() { + int r, g, b; + Dimension dim; + byte[] pic; + byte[][] palette = new byte[1][]; //new byte[768]; + + // get the palette + + pic = LoadPCX("pics/colormap.pcx", palette, dim = new Dimension()); + + if (palette[0] == null || palette[0].length != 768) + ri.Sys_Error(Defines.ERR_FATAL, "Couldn't load pics/colormap.pcx"); + + byte[] pal = palette[0]; + + int j = 0; + for (int i = 0; i < 256; i++) { + r = pal[j++] & 0xFF; + g = pal[j++] & 0xFF; + b = pal[j++] & 0xFF; + + d_8to24table[i] = (255 << 24) | (b << 16) | (g << 8) | (r << 0); + } + + d_8to24table[255] &= 0x00FFFFFF; // 255 is transparent + + particle_t.setColorPalette(d_8to24table); + } + + /* + =============== + GL_InitImages + =============== + */ + void GL_InitImages() { + int i, j; + float g = vid_gamma.value; + + registration_sequence = 1; + + // init intensity conversions + intensity = ri.Cvar_Get("intensity", "2", 0); + + if (intensity.value <= 1) + ri.Cvar_Set("intensity", "1"); + + gl_state.inverse_intensity = 1 / intensity.value; + + Draw_GetPalette(); + + if (qglColorTableEXT) { + gl_state.d_16to8table = ri.FS_LoadFile("pics/16to8.dat"); + if (gl_state.d_16to8table == null) + ri.Sys_Error(Defines.ERR_FATAL, "Couldn't load pics/16to8.pcx"); + } + + if ((gl_config.renderer & (GL_RENDERER_VOODOO | GL_RENDERER_VOODOO2)) != 0) { + g = 1.0F; + } + + for (i = 0; i < 256; i++) { + + if (g == 1.0f) { + gammatable[i] = (byte) i; + } + else { + + int inf = (int) (255.0f * Math.pow((i + 0.5) / 255.5, g) + 0.5); + if (inf < 0) + inf = 0; + if (inf > 255) + inf = 255; + gammatable[i] = (byte) inf; + } + } + + for (i = 0; i < 256; i++) { + j = (int) (i * intensity.value); + if (j > 255) + j = 255; + intensitytable[i] = (byte) j; + } + } + + /* + =============== + GL_ShutdownImages + =============== + */ + void GL_ShutdownImages() { + image_t image; + + for (int i=0; i < numgltextures ; i++) + { + image = gltextures[i]; + + if (image.registration_sequence == 0) + continue; // free image_t slot + // free it + // TODO jogl bug + gl.glDeleteTextures(1, new int[] {image.texnum}); + image.clear(); + } + } + +} diff --git a/src/jake2/render/fastjogl/Impl.java b/src/jake2/render/fastjogl/Impl.java new file mode 100644 index 0000000..03af496 --- /dev/null +++ b/src/jake2/render/fastjogl/Impl.java @@ -0,0 +1,343 @@ +/* + * Impl.java + * Copyright (C) 2003 + * + * $Id: Impl.java,v 1.1 2004-07-09 06:50:49 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.fastjogl; + +import jake2.Defines; +import jake2.Globals; +import jake2.qcommon.Com; +import jake2.qcommon.xcommand_t; +import jake2.sys.KBD; + +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JFrame; + +import net.java.games.jogl.*; + +/** + * Impl + * + * @author cwei + */ +public class Impl extends Misc implements GLEventListener { + + public static final String DRIVER_NAME = "fastjogl"; + + // handles the post initialization with JoglRenderer + protected boolean post_init = false; + + private final xcommand_t INIT_CALLBACK = new xcommand_t() { + public void execute() { + // only used for the first run (initialization) + // clear the screen + gl.glClearColor(0, 0, 0, 0); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + // + // check the post init process + // + if (!post_init) { + ri.Con_Printf(Defines.PRINT_ALL, "Missing multi-texturing for FastJOGL renderer\n"); + } + + GLimp_EndFrame(); + } + }; + + private xcommand_t callback = INIT_CALLBACK; + protected boolean contextInUse = false; + + private GraphicsDevice device; + private DisplayMode oldDisplayMode; + + GLCanvas canvas; + JFrame window; + + // window position on the screen + int window_xpos, window_ypos; + + /** + * @return true + */ + boolean GLimp_Init(int xpos, int ypos) { + // do nothing + window_xpos = xpos; + window_ypos = ypos; + return true; + } + + /** + * @param dim + * @param mode + * @param fullscreen + * @return enum rserr_t + */ + int GLimp_SetMode(Dimension dim, int mode, boolean fullscreen) { + + Dimension newDim = new Dimension(); + + ri.Cvar_Get("r_fakeFullscreen", "0", Globals.CVAR_ARCHIVE); + + ri.Con_Printf(Defines.PRINT_ALL, "Initializing OpenGL display\n"); + + ri.Con_Printf(Defines.PRINT_ALL, "...setting mode " + mode + ":"); + + if (!ri.Vid_GetModeInfo(newDim, mode)) { + ri.Con_Printf(Defines.PRINT_ALL, " invalid mode\n"); + return rserr_invalid_mode; + } + + ri.Con_Printf(Defines.PRINT_ALL, " " + newDim.width + " " + newDim.height + '\n'); + + // destroy the existing window + GLimp_Shutdown(); + + window = new JFrame("Jake2"); + + GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); + + // TODO Use debug pipeline + //canvas.setGL(new DebugGL(canvas.getGL())); + + canvas.setNoAutoRedrawMode(true); + canvas.addGLEventListener(this); + + window.getContentPane().add(canvas); + + canvas.setSize(newDim.width, newDim.height); + + // register event listener + window.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + ri.Cmd_ExecuteText(Defines.EXEC_APPEND, "quit"); + } + }); + + // D I F F E R E N T J A K E 2 E V E N T P R O C E S S I N G + window.addComponentListener(KBD.listener); + canvas.addKeyListener(KBD.listener); + canvas.addMouseListener(KBD.listener); + canvas.addMouseMotionListener(KBD.listener); + + /* + * fullscreen handling + */ + GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); + device = env.getDefaultScreenDevice(); + + if (fullscreen && !device.isFullScreenSupported()) { + ri.Con_Printf(Defines.PRINT_ALL, "...fullscreen not supported\n"); + vid_fullscreen.value = 0; + vid_fullscreen.modified = false; + } + + fullscreen = fullscreen && device.isFullScreenSupported(); + + if (oldDisplayMode == null) { + oldDisplayMode = device.getDisplayMode(); + } + + if (fullscreen) { + + DisplayMode displayMode = findDisplayMode(newDim, oldDisplayMode.getBitDepth(), oldDisplayMode.getRefreshRate()); + + if (displayMode != null) { + newDim.width = displayMode.getWidth(); + newDim.height = displayMode.getHeight(); + window.setUndecorated(true); + window.setResizable(false); + device.setFullScreenWindow(window); + device.setDisplayMode(displayMode); + window.setLocation(0, 0); + window.setSize(displayMode.getWidth(), displayMode.getHeight()); + canvas.setSize(displayMode.getWidth(), displayMode.getHeight()); + ri.Con_Printf(Defines.PRINT_ALL, "...setting fullscreen " + getModeString(displayMode) + '\n'); + } + } else { + window.setLocation(window_xpos, window_ypos); + window.pack(); + window.setResizable(false); + window.setVisible(true); + } + + while (!canvas.isDisplayable()) { + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + } + canvas.requestFocus(); + + this.canvas = canvas; + + vid.width = newDim.width; + vid.height = newDim.height; + + // let the sound and input subsystems know about the new window + ri.Vid_NewWindow(vid.width, vid.height); + + return rserr_ok; + } + + DisplayMode findDisplayMode(Dimension dim, int depth, int rate) { + DisplayMode mode = null; + DisplayMode m = null; + DisplayMode[] modes = device.getDisplayModes(); + int w = dim.width; + int h = dim.height; + + for (int i = 0; i < modes.length; i++) { + m = modes[i]; + if (m.getWidth() == w && m.getHeight() == h && m.getBitDepth() == depth && m.getRefreshRate() == rate) { + mode = m; + break; + } + } + if (mode == null) mode = oldDisplayMode; + Com.Printf(getModeString(mode) + '\n'); + return mode; + } + + String getModeString(DisplayMode m) { + StringBuffer sb = new StringBuffer(); + sb.append(m.getWidth()); + sb.append('x'); + sb.append(m.getHeight()); + sb.append('x'); + sb.append(m.getBitDepth()); + sb.append('@'); + sb.append(m.getRefreshRate()); + sb.append("Hz"); + return sb.toString(); + } + + void GLimp_BeginFrame(float camera_separation) { + // do nothing + } + + protected void GLimp_EndFrame() { + gl.glFlush(); + // swap buffer + // but jogl has no method to swap + } + + protected void GLimp_AppActivate(boolean activate) { + // do nothing + } + + boolean QGL_Init(String dll_name) { + // doesn't need libGL.so or .dll loading + return true; + } + + void QGL_Shutdown() { + // doesn't need libGL.so or .dll loading + // do nothing + } + + void GLimp_Shutdown() { + if (oldDisplayMode != null && device.getFullScreenWindow() != null) { + try { + device.setDisplayMode(oldDisplayMode); + device.setFullScreenWindow(null); + } catch (Exception e) { + e.printStackTrace(); + } + } + if (this.window != null) { + window.dispose(); + } + post_init = false; + callback = INIT_CALLBACK; + } + + void GLimp_EnableLogging(boolean enable) { + // doesn't need jogl logging + // do nothing + } + + void GLimp_LogNewFrame() { + // doesn't need jogl logging + // do nothing + } + + + + // ============================================================================ + // GLEventListener interface + // ============================================================================ + + /* + * @see net.java.games.jogl.GLEventListener#init(net.java.games.jogl.GLDrawable) + */ + public void init(GLDrawable drawable) { + this.gl = drawable.getGL(); + this.glu = drawable.getGLU(); + + // this is a hack to run R_init() in gl context + post_init = R_Init2(); + } + + /* + * @see net.java.games.jogl.GLEventListener#display(net.java.games.jogl.GLDrawable) + */ + public void display(GLDrawable drawable) { + this.gl = drawable.getGL(); + this.glu = drawable.getGLU(); + + contextInUse = true; + callback.execute(); + contextInUse = false; + } + + /* + * @see net.java.games.jogl.GLEventListener#displayChanged(net.java.games.jogl.GLDrawable, boolean, boolean) + */ + public void displayChanged(GLDrawable drawable, boolean arg1, boolean arg2) { + // do nothing + } + + /* + * @see net.java.games.jogl.GLEventListener#reshape(net.java.games.jogl.GLDrawable, int, int, int, int) + */ + public void reshape(GLDrawable drawable, int x, int y, int width, int height) { + // do nothing + } + + /* + * @see jake2.client.refexport_t#updateScreen() + */ + public void updateScreen() { + this.callback = INIT_CALLBACK; + canvas.display(); + } + + public void updateScreen(xcommand_t callback) { + this.callback = callback; + canvas.display(); + } +}
\ No newline at end of file diff --git a/src/jake2/render/fastjogl/Light.java b/src/jake2/render/fastjogl/Light.java new file mode 100644 index 0000000..b963b21 --- /dev/null +++ b/src/jake2/render/fastjogl/Light.java @@ -0,0 +1,778 @@ +/* + * Light.java + * Copyright (C) 2003 + * + * $Id: Light.java,v 1.1 2004-07-09 06:50:49 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.fastjogl; + +import jake2.Defines; +import jake2.Globals; +import jake2.client.dlight_t; +import jake2.client.lightstyle_t; +import jake2.game.GameBase; +import jake2.game.cplane_t; +import jake2.qcommon.longjmpException; +import jake2.render.*; +import jake2.util.Math3D; + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.util.Arrays; + +import net.java.games.jogl.GL; + +/** + * Light + * + * @author cwei + */ +public abstract class Light extends Warp { + // r_light.c + + int r_dlightframecount; + + static final int DLIGHT_CUTOFF = 64; + + /* + ============================================================================= + + DYNAMIC LIGHTS BLEND RENDERING + + ============================================================================= + */ + + void R_RenderDlight (dlight_t light) + { + int i, j; + float a; + float[] v = {0, 0, 0}; + float rad; + + rad = light.intensity * 0.35f; + + Math3D.VectorSubtract (light.origin, r_origin, v); + + gl.glBegin (GL.GL_TRIANGLE_FAN); + gl.glColor3f (light.color[0]*0.2f, light.color[1]*0.2f, light.color[2]*0.2f); + for (i=0 ; i<3 ; i++) + v[i] = light.origin[i] - vpn[i]*rad; + gl.glVertex3f(v[0], v[1], v[2]); + gl.glColor3f (0,0,0); + for (i=16 ; i>=0 ; i--) + { + a = (float)(i/16.0f * Math.PI*2); + for (j=0 ; j<3 ; j++) + v[j] = (float)(light.origin[j] + vright[j]*Math.cos(a)*rad + + vup[j]*Math.sin(a)*rad); + gl.glVertex3f(v[0], v[1], v[2]); + } + gl.glEnd (); + } + + /* + ============= + R_RenderDlights + ============= + */ + void R_RenderDlights() + { + if (gl_flashblend.value == 0) + return; + + r_dlightframecount = r_framecount + 1; // because the count hasn't + // advanced yet for this frame + gl.glDepthMask(false); + gl.glDisable(GL.GL_TEXTURE_2D); + gl.glShadeModel (GL.GL_SMOOTH); + gl.glEnable (GL.GL_BLEND); + gl.glBlendFunc (GL.GL_ONE, GL.GL_ONE); + + for (int i=0 ; i<r_newrefdef.num_dlights ; i++) + { + R_RenderDlight(r_newrefdef.dlights[i]); + } + + gl.glColor3f (1,1,1); + gl.glDisable(GL.GL_BLEND); + gl.glEnable(GL.GL_TEXTURE_2D); + gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); + gl.glDepthMask(true); + } + + + /* + ============================================================================= + + DYNAMIC LIGHTS + + ============================================================================= + */ + + /* + ============= + R_MarkLights + ============= + */ + void R_MarkLights (dlight_t light, int bit, mnode_t node) + { + cplane_t splitplane; + float dist; + msurface_t surf; + int i; + int sidebit; + + if (node.contents != -1) + return; + + splitplane = node.plane; + dist = Math3D.DotProduct (light.origin, splitplane.normal) - splitplane.dist; + + if (dist > light.intensity - DLIGHT_CUTOFF) + { + R_MarkLights (light, bit, node.children[0]); + return; + } + if (dist < -light.intensity + DLIGHT_CUTOFF) + { + R_MarkLights (light, bit, node.children[1]); + return; + } + + // mark the polygons + for (i=0 ; i<node.numsurfaces ; i++) + { + + surf = r_worldmodel.surfaces[node.firstsurface + i]; + + /* + * cwei + * bugfix for dlight behind the walls + */ + dist = Math3D.DotProduct (light.origin, surf.plane.normal) - surf.plane.dist; + sidebit = (dist >= 0) ? 0 : Defines.SURF_PLANEBACK; + if ( (surf.flags & Defines.SURF_PLANEBACK) != sidebit ) + continue; + /* + * cwei + * bugfix end + */ + + if (surf.dlightframe != r_dlightframecount) + { + surf.dlightbits = 0; + surf.dlightframe = r_dlightframecount; + } + surf.dlightbits |= bit; + } + + R_MarkLights (light, bit, node.children[0]); + R_MarkLights (light, bit, node.children[1]); + } + + + /* + ============= + R_PushDlights + ============= + */ + void R_PushDlights() + { + int i; + dlight_t l; + + if (gl_flashblend.value != 0) + return; + + r_dlightframecount = r_framecount + 1; // because the count hasn't + // advanced yet for this frame + for (i=0 ; i<r_newrefdef.num_dlights ; i++) { + l = r_newrefdef.dlights[i]; + R_MarkLights( l, 1<<i, r_worldmodel.nodes[0] ); + } + } + + + /* + ============================================================================= + + LIGHT SAMPLING + + ============================================================================= + */ + + float[] pointcolor = {0, 0, 0}; // vec3_t + cplane_t lightplane; // used as shadow plane + float[] lightspot = {0, 0, 0}; // vec3_t + + int RecursiveLightPoint (mnode_t node, float[] start, float[] end) + { + float front, back, frac; + boolean side; + int sideIndex; + cplane_t plane; + float[] mid = {0, 0, 0}; + msurface_t surf; + int s, t, ds, dt; + int i; + mtexinfo_t tex; + ByteBuffer lightmap; + int maps; + int r; + + if (node.contents != -1) + return -1; // didn't hit anything + + // calculate mid point + + // FIXME: optimize for axial + plane = node.plane; + front = Math3D.DotProduct (start, plane.normal) - plane.dist; + back = Math3D.DotProduct (end, plane.normal) - plane.dist; + side = (front < 0); + sideIndex = (side) ? 1 : 0; + + if ( (back < 0) == side) + return RecursiveLightPoint (node.children[sideIndex], start, end); + + frac = front / (front-back); + mid[0] = start[0] + (end[0] - start[0])*frac; + mid[1] = start[1] + (end[1] - start[1])*frac; + mid[2] = start[2] + (end[2] - start[2])*frac; + + // go down front side + r = RecursiveLightPoint (node.children[sideIndex], start, mid); + if (r >= 0) + return r; // hit something + + if ( (back < 0) == side ) + return -1; // didn't hit anuthing + + // check for impact on this node + Math3D.VectorCopy (mid, lightspot); + lightplane = plane; + + int surfIndex = node.firstsurface; + for (i=0 ; i<node.numsurfaces ; i++, surfIndex++) + { + surf = r_worldmodel.surfaces[surfIndex]; + + if ((surf.flags & (Defines.SURF_DRAWTURB | Defines.SURF_DRAWSKY)) != 0) + continue; // no lightmaps + + tex = surf.texinfo; + + s = (int)(Math3D.DotProduct (mid, tex.vecs[0]) + tex.vecs[0][3]); + t = (int)(Math3D.DotProduct (mid, tex.vecs[1]) + tex.vecs[1][3]); + + if (s < surf.texturemins[0] || t < surf.texturemins[1]) + continue; + + ds = s - surf.texturemins[0]; + dt = t - surf.texturemins[1]; + + if ( ds > surf.extents[0] || dt > surf.extents[1] ) + continue; + + if (surf.samples == null) + return 0; + + ds >>= 4; + dt >>= 4; + + lightmap = surf.samples; + int lightmapIndex = 0; + + Math3D.VectorCopy (Globals.vec3_origin, pointcolor); + if (lightmap != null) + { + float[] scale = {0, 0, 0}; + float[] rgb; + lightmapIndex += 3 * (dt * ((surf.extents[0] >> 4) + 1) + ds); + + for (maps = 0 ; maps < Defines.MAXLIGHTMAPS && surf.styles[maps] != (byte)255; maps++) + { + rgb = r_newrefdef.lightstyles[surf.styles[maps] & 0xFF].rgb; + scale[0] = gl_modulate.value * rgb[0]; + scale[1] = gl_modulate.value * rgb[1]; + scale[2] = gl_modulate.value * rgb[2]; + + pointcolor[0] += (lightmap.get(lightmapIndex + 0) & 0xFF) * scale[0] * (1.0f/255); + pointcolor[1] += (lightmap.get(lightmapIndex + 1) & 0xFF) * scale[1] * (1.0f/255); + pointcolor[2] += (lightmap.get(lightmapIndex + 2) & 0xFF) * scale[2] * (1.0f/255); + lightmapIndex += 3 * ((surf.extents[0] >> 4) + 1) * ((surf.extents[1] >> 4) + 1); + } + } + return 1; + } + + // go down back side + return RecursiveLightPoint (node.children[1 - sideIndex], mid, end); + } + + /* + =============== + R_LightPoint + =============== + */ + void R_LightPoint (float[] p, float[] color) + { + assert (p.length == 3) : "vec3_t bug"; + assert (color.length == 3) : "rgb bug"; + + float[] end = {0, 0, 0}; + float r; + int lnum; + dlight_t dl; + float light; + float[] dist = {0, 0, 0}; + float add; + + if (r_worldmodel.lightdata == null) + { + color[0] = color[1] = color[2] = 1.0f; + return; + } + + end[0] = p[0]; + end[1] = p[1]; + end[2] = p[2] - 2048; + + r = RecursiveLightPoint(r_worldmodel.nodes[0], p, end); + + if (r == -1) + { + Math3D.VectorCopy (GameBase.vec3_origin, color); + } + else + { + Math3D.VectorCopy (pointcolor, color); + } + + // + // add dynamic lights + // + light = 0; + for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++) + { + dl = r_newrefdef.dlights[lnum]; + + Math3D.VectorSubtract (currententity.origin, dl.origin, dist); + add = dl.intensity - Math3D.VectorLength(dist); + add *= (1.0f/256); + if (add > 0) + { + Math3D.VectorMA (color, add, dl.color, color); + } + } + + Math3D.VectorScale (color, gl_modulate.value, color); + } + + +// =================================================================== + + float[] s_blocklights = new float[34 * 34 * 3]; + + /* + =============== + R_AddDynamicLights + =============== + */ + void R_AddDynamicLights(msurface_t surf) + { + int lnum; + int sd, td; + float fdist, frad, fminlight; + float[] impact = {0, 0, 0}; + float[] local = {0, 0, 0}; + int s, t; + int i; + int smax, tmax; + mtexinfo_t tex; + dlight_t dl; + float[] pfBL; + float fsacc, ftacc; + + smax = (surf.extents[0]>>4)+1; + tmax = (surf.extents[1]>>4)+1; + tex = surf.texinfo; + + for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++) + { + if ( (surf.dlightbits & (1<<lnum)) == 0 ) + continue; // not lit by this light + + dl = r_newrefdef.dlights[lnum]; + frad = dl.intensity; + fdist = Math3D.DotProduct (dl.origin, surf.plane.normal) - + surf.plane.dist; + frad -= Math.abs(fdist); + // rad is now the highest intensity on the plane + + fminlight = DLIGHT_CUTOFF; // FIXME: make configurable? + if (frad < fminlight) + continue; + fminlight = frad - fminlight; + + for (i=0 ; i<3 ; i++) + { + impact[i] = dl.origin[i] - + surf.plane.normal[i]*fdist; + } + + local[0] = Math3D.DotProduct (impact, tex.vecs[0]) + tex.vecs[0][3] - surf.texturemins[0]; + local[1] = Math3D.DotProduct (impact, tex.vecs[1]) + tex.vecs[1][3] - surf.texturemins[1]; + + pfBL = s_blocklights; + int pfBLindex = 0; + for (t = 0, ftacc = 0 ; t<tmax ; t++, ftacc += 16) + { + td = (int)(local[1] - ftacc); + if ( td < 0 ) + td = -td; + + for ( s=0, fsacc = 0 ; s<smax ; s++, fsacc += 16, pfBLindex += 3) + { + sd = (int)( local[0] - fsacc ); + + if ( sd < 0 ) + sd = -sd; + + if (sd > td) + fdist = sd + (td>>1); + else + fdist = td + (sd>>1); + + if ( fdist < fminlight ) + { + pfBL[pfBLindex + 0] += ( frad - fdist ) * dl.color[0]; + pfBL[pfBLindex + 1] += ( frad - fdist ) * dl.color[1]; + pfBL[pfBLindex + 2] += ( frad - fdist ) * dl.color[2]; + } + } + } + } + } + + + /* + ** R_SetCacheState + */ + void R_SetCacheState( msurface_t surf ) + { + int maps; + + for (maps = 0 ; maps < Defines.MAXLIGHTMAPS && surf.styles[maps] != (byte)255 ; + maps++) + { + surf.cached_light[maps] = r_newrefdef.lightstyles[surf.styles[maps] & 0xFF].white; + } + } + + /* + =============== + R_BuildLightMap + + Combine and scale multiple lightmaps into the floating format in blocklights + =============== + */ + void R_BuildLightMap(msurface_t surf, IntBuffer dest, int stride) + { + int smax, tmax; + int r, g, b, a, max; + int i, j, size; + ByteBuffer lightmap; + float[] scale = {0, 0, 0, 0}; + int nummaps; + float[] bl; + lightstyle_t style; + int monolightmap; + + if ( (surf.texinfo.flags & (Defines.SURF_SKY | Defines.SURF_TRANS33 | Defines.SURF_TRANS66 | Defines.SURF_WARP)) != 0 ) + ri.Sys_Error(Defines.ERR_DROP, "R_BuildLightMap called for non-lit surface"); + + smax = (surf.extents[0] >> 4) + 1; + tmax = (surf.extents[1] >> 4) + 1; + size = smax * tmax; + if (size > ((s_blocklights.length * Defines.SIZE_OF_FLOAT) >> 4) ) + ri.Sys_Error(Defines.ERR_DROP, "Bad s_blocklights size"); + + try { + // set to full bright if no light data + if (surf.samples == null) + { + int maps; + + for (i=0 ; i<size*3 ; i++) + s_blocklights[i] = 255; + + for (maps = 0 ; maps < Defines.MAXLIGHTMAPS && surf.styles[maps] != (byte)255; maps++) + { + style = r_newrefdef.lightstyles[surf.styles[maps] & 0xFF]; + } + // goto store; + throw new longjmpException(); + } + + // count the # of maps + for ( nummaps = 0 ; nummaps < Defines.MAXLIGHTMAPS && surf.styles[nummaps] != (byte)255 ; + nummaps++) + ; + + lightmap = surf.samples; + int lightmapIndex = 0; + + // add all the lightmaps + if ( nummaps == 1 ) + { + int maps; + + for (maps = 0 ; maps < Defines.MAXLIGHTMAPS && surf.styles[maps] != (byte)255 ; + maps++) + { + bl = s_blocklights; + int blp = 0; + + for (i=0 ; i<3 ; i++) + scale[i] = gl_modulate.value * r_newrefdef.lightstyles[surf.styles[maps] & 0xFF].rgb[i]; + + if ( scale[0] == 1.0F && + scale[1] == 1.0F && + scale[2] == 1.0F ) + { + for (i=0 ; i<size ; i++) + { + bl[blp++] = lightmap.get(lightmapIndex++) & 0xFF; + bl[blp++] = lightmap.get(lightmapIndex++) & 0xFF; + bl[blp++] = lightmap.get(lightmapIndex++) & 0xFF; + } + } + else + { + for (i=0 ; i<size ; i++) + { + bl[blp++] = (lightmap.get(lightmapIndex++) & 0xFF) * scale[0]; + bl[blp++] = (lightmap.get(lightmapIndex++) & 0xFF) * scale[1]; + bl[blp++] = (lightmap.get(lightmapIndex++) & 0xFF) * scale[2]; + } + } + //lightmap += size*3; // skip to next lightmap + } + } + else + { + int maps; + + // memset( s_blocklights, 0, sizeof( s_blocklights[0] ) * size * 3 ); + + Arrays.fill(s_blocklights, 0, size * 3, 0.0f); + + for (maps = 0 ; maps < Defines.MAXLIGHTMAPS && surf.styles[maps] != (byte)255 ; + maps++) + { + bl = s_blocklights; + int blp = 0; + + for (i=0 ; i<3 ; i++) + scale[i] = gl_modulate.value*r_newrefdef.lightstyles[surf.styles[maps] & 0xFF].rgb[i]; + + if ( scale[0] == 1.0F && + scale[1] == 1.0F && + scale[2] == 1.0F ) + { + for (i=0 ; i<size ; i++) + { + bl[blp++] += lightmap.get(lightmapIndex++) & 0xFF; + bl[blp++] += lightmap.get(lightmapIndex++) & 0xFF; + bl[blp++] += lightmap.get(lightmapIndex++) & 0xFF; + } + } + else + { + for (i=0 ; i<size ; i++) + { + bl[blp++] += (lightmap.get(lightmapIndex++) & 0xFF) * scale[0]; + bl[blp++] += (lightmap.get(lightmapIndex++) & 0xFF) * scale[1]; + bl[blp++] += (lightmap.get(lightmapIndex++) & 0xFF) * scale[2]; + } + } + //lightmap += size*3; // skip to next lightmap + } + } + + // add all the dynamic lights + if (surf.dlightframe == r_framecount) + R_AddDynamicLights(surf); + + // label store: + } catch (longjmpException store) {} + + // put into texture format + stride -= smax; + bl = s_blocklights; + int blp = 0; + + monolightmap = gl_monolightmap.string.charAt(0); + + int destp = 0; + + if ( monolightmap == '0' ) + { + for (i=0 ; i<tmax ; i++, destp += stride) + { + //dest.position(destp); + + for (j=0 ; j<smax ; j++) + { + + r = (int)bl[blp++]; + g = (int)bl[blp++]; + b = (int)bl[blp++]; + + // catch negative lights + if (r < 0) + r = 0; + if (g < 0) + g = 0; + if (b < 0) + b = 0; + + /* + ** determine the brightest of the three color components + */ + if (r > g) + max = r; + else + max = g; + if (b > max) + max = b; + + /* + ** alpha is ONLY used for the mono lightmap case. For this reason + ** we set it to the brightest of the color components so that + ** things don't get too dim. + */ + a = max; + + /* + ** rescale all the color components if the intensity of the greatest + ** channel exceeds 1.0 + */ + if (max > 255) + { + float t = 255.0F / max; + + r = (int)(r*t); + g = (int)(g*t); + b = (int)(b*t); + a = (int)(a*t); + } + r &= 0xFF; g &= 0xFF; b &= 0xFF; a &= 0xFF; + dest.put(destp++, (a << 24) | (b << 16) | (g << 8) | (r << 0)); + } + } + } + else + { + for (i=0 ; i<tmax ; i++, destp += stride) + { + //dest.position(destp); + + for (j=0 ; j<smax ; j++) + { + + r = (int) bl[blp++]; + g = (int) bl[blp++]; + b = (int) bl[blp++]; + + // catch negative lights + if (r < 0) + r = 0; + if (g < 0) + g = 0; + if (b < 0) + b = 0; + + /* + ** determine the brightest of the three color components + */ + if (r > g) + max = r; + else + max = g; + if (b > max) + max = b; + + /* + ** alpha is ONLY used for the mono lightmap case. For this reason + ** we set it to the brightest of the color components so that + ** things don't get too dim. + */ + a = max; + + /* + ** rescale all the color components if the intensity of the greatest + ** channel exceeds 1.0 + */ + if (max > 255) + { + float t = 255.0F / max; + + r = (int)(r*t); + g = (int)(g*t); + b = (int)(b*t); + a = (int)(a*t); + } + + /* + ** So if we are doing alpha lightmaps we need to set the R, G, and B + ** components to 0 and we need to set alpha to 1-alpha. + */ + switch ( monolightmap ) + { + case 'L': + case 'I': + r = a; + g = b = 0; + break; + case 'C': + // try faking colored lighting + a = 255 - ((r+g+b)/3); + r *= a/255.0f; + g *= a/255.0f; + b *= a/255.0f; + break; + case 'A': + default: + r = g = b = 0; + a = 255 - a; + break; + } + r &= 0xFF; g &= 0xFF; b &= 0xFF; a &= 0xFF; + dest.put(destp++, (a << 24) | (b << 16) | (g << 8) | (r << 0)); + } + } + } + } + +} diff --git a/src/jake2/render/fastjogl/Main.java b/src/jake2/render/fastjogl/Main.java new file mode 100644 index 0000000..2363db4 --- /dev/null +++ b/src/jake2/render/fastjogl/Main.java @@ -0,0 +1,1592 @@ +/* + * Main.java + * Copyright (C) 2003 + * + * $Id: Main.java,v 1.1 2004-07-09 06:50:49 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.fastjogl; + +import jake2.*; +import jake2.client.*; +import jake2.game.cplane_t; +import jake2.game.cvar_t; +import jake2.qcommon.qfiles; +import jake2.qcommon.xcommand_t; +import jake2.render.*; +import jake2.util.Math3D; +import jake2.util.Vargs; + +import java.awt.Dimension; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +import net.java.games.jogl.GL; +import net.java.games.jogl.GLU; +import net.java.games.jogl.util.BufferUtils; +import net.java.games.jogl.util.GLUT; + +/** + * Main + * + * @author cwei + */ +public abstract class Main extends Base { + + GL gl; + GLU glu; + GLUT glut = new GLUT(); + + public static int[] d_8to24table = new int[256]; + + int c_visible_lightmaps; + int c_visible_textures; + + int registration_sequence; + + // this a hack for function pointer test + // default disabled + boolean qglColorTableEXT = false; + boolean qglActiveTextureARB = false; + boolean qglPointParameterfEXT = false; + boolean qglLockArraysEXT = false; + boolean qwglSwapIntervalEXT = false; + + // ================= + // abstract methods + // ================= + protected abstract void Draw_GetPalette(); + + abstract void GL_ImageList_f(); + abstract void GL_ScreenShot_f(); + abstract void GL_SetTexturePalette(int[] palette); + abstract void GL_Strings_f(); + + abstract void Mod_Modellist_f(); + abstract mleaf_t Mod_PointInLeaf(float[] point, model_t model); + + abstract boolean QGL_Init(String dll_name); + abstract void QGL_Shutdown(); + abstract boolean GLimp_Init(int xpos, int ypos); + abstract void GLimp_BeginFrame(float camera_separation); + abstract int GLimp_SetMode(Dimension dim, int mode, boolean fullscreen); + abstract void GLimp_Shutdown(); + abstract void GLimp_EnableLogging(boolean enable); + abstract void GLimp_LogNewFrame(); + + abstract void GL_SetDefaultState(); + + abstract void GL_InitImages(); + abstract void Mod_Init(); // Model.java + abstract void R_InitParticleTexture(); // MIsc.java + abstract void R_DrawAliasModel(entity_t e); // Mesh.java + abstract void R_DrawBrushModel(entity_t e); // Surf.java + abstract void Draw_InitLocal(); + abstract void R_LightPoint(float[] p, float[] color); + abstract void R_PushDlights(); + abstract void R_MarkLeaves(); + abstract void R_DrawWorld(); + abstract void R_RenderDlights(); + abstract void R_DrawAlphaSurfaces(); + + abstract void Mod_FreeAll(); + + abstract void GL_ShutdownImages(); + abstract void GL_Bind(int texnum); + abstract void GL_TexEnv(int mode); + abstract void GL_TextureMode(String string); + abstract void GL_TextureAlphaMode(String string); + abstract void GL_TextureSolidMode(String string); + abstract void GL_UpdateSwapInterval(); + + /* + ==================================================================== + + from gl_rmain.c + + ==================================================================== + */ + + // IMPORTED FUNCTIONS + protected refimport_t ri = null; + + int GL_TEXTURE0 = GL.GL_TEXTURE0; + int GL_TEXTURE1 = GL.GL_TEXTURE1; + + viddef_t vid = new viddef_t(); + + model_t r_worldmodel; + + float gldepthmin, gldepthmax; + + glconfig_t gl_config = new glconfig_t(); + glstate_t gl_state = new glstate_t(); + + image_t r_notexture; // use for bad textures + image_t r_particletexture; // little dot for particles + + entity_t currententity; + model_t currentmodel; + + cplane_t frustum[] = { new cplane_t(), new cplane_t(), new cplane_t(), new cplane_t()}; + + int r_visframecount; // bumped when going to a new PVS + int r_framecount; // used for dlight push checking + + int c_brush_polys, c_alias_polys; + + float v_blend[] = { 0, 0, 0, 0 }; // final blending color + + // + // view origin + // + float[] vup = { 0, 0, 0 }; + float[] vpn = { 0, 0, 0 }; + float[] vright = { 0, 0, 0 }; + float[] r_origin = { 0, 0, 0 }; + + float r_world_matrix[] = new float[16]; + float r_base_world_matrix[] = new float[16]; + + // + // screen size info + // + refdef_t r_newrefdef = new refdef_t(); + + int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2; + + cvar_t r_norefresh; + cvar_t r_drawentities; + cvar_t r_drawworld; + cvar_t r_speeds; + cvar_t r_fullbright; + cvar_t r_novis; + cvar_t r_nocull; + cvar_t r_lerpmodels; + cvar_t r_lefthand; + + cvar_t r_lightlevel; + // FIXME: This is a HACK to get the client's light level + + cvar_t gl_nosubimage; + cvar_t gl_allow_software; + + cvar_t gl_vertex_arrays; + + cvar_t gl_particle_min_size; + cvar_t gl_particle_max_size; + cvar_t gl_particle_size; + cvar_t gl_particle_att_a; + cvar_t gl_particle_att_b; + cvar_t gl_particle_att_c; + + cvar_t gl_ext_swapinterval; + cvar_t gl_ext_palettedtexture; + cvar_t gl_ext_multitexture; + cvar_t gl_ext_pointparameters; + cvar_t gl_ext_compiled_vertex_array; + + cvar_t gl_log; + cvar_t gl_bitdepth; + cvar_t gl_drawbuffer; + cvar_t gl_driver; + cvar_t gl_lightmap; + cvar_t gl_shadows; + cvar_t gl_mode; + cvar_t gl_dynamic; + cvar_t gl_monolightmap; + cvar_t gl_modulate; + cvar_t gl_nobind; + cvar_t gl_round_down; + cvar_t gl_picmip; + cvar_t gl_skymip; + cvar_t gl_showtris; + cvar_t gl_ztrick; + cvar_t gl_finish; + cvar_t gl_clear; + cvar_t gl_cull; + cvar_t gl_polyblend; + cvar_t gl_flashblend; + cvar_t gl_playermip; + cvar_t gl_saturatelighting; + cvar_t gl_swapinterval; + cvar_t gl_texturemode; + cvar_t gl_texturealphamode; + cvar_t gl_texturesolidmode; + cvar_t gl_lockpvs; + + cvar_t gl_3dlabs_broken; + + cvar_t vid_fullscreen; + cvar_t vid_gamma; + cvar_t vid_ref; + + // ============================================================================ + // to port from gl_rmain.c, ... + // ============================================================================ + + /* + ================= + R_CullBox + + Returns true if the box is completely outside the frustom + ================= + */ + final boolean R_CullBox(float[] mins, float[] maxs) { + assert(mins.length == 3 && maxs.length == 3) : "vec3_t bug"; + + if (r_nocull.value != 0) + return false; + + for (int i = 0; i < 4; i++) { + if (Math3D.BoxOnPlaneSide(mins, maxs, frustum[i]) == 2) + return true; + } + return false; + } + + final void R_RotateForEntity(entity_t e) { + + gl.glTranslatef(e.origin[0], e.origin[1], e.origin[2]); + + gl.glRotatef(e.angles[1], 0, 0, 1); + gl.glRotatef(-e.angles[0], 0, 1, 0); + gl.glRotatef(-e.angles[2], 1, 0, 0); + } + + /* + ============================================================= + + SPRITE MODELS + + ============================================================= + */ + + /* + ================= + R_DrawSpriteModel + + ================= + */ + void R_DrawSpriteModel(entity_t e) { + float alpha = 1.0F; + float[] point = { 0, 0, 0 }; + + qfiles.dsprframe_t frame; + qfiles.dsprite_t psprite; + + // don't even bother culling, because it's just a single + // polygon without a surface cache + + psprite = (qfiles.dsprite_t) currentmodel.extradata; + + e.frame %= psprite.numframes; + + frame = psprite.frames[e.frame]; + + if ((e.flags & Defines.RF_TRANSLUCENT) != 0) + alpha = e.alpha; + + if (alpha != 1.0F) + gl.glEnable(GL.GL_BLEND); + + gl.glColor4f(1, 1, 1, alpha); + + GL_Bind(currentmodel.skins[e.frame].texnum); + + GL_TexEnv(GL.GL_MODULATE); + + if (alpha == 1.0) + gl.glEnable(GL.GL_ALPHA_TEST); + else + gl.glDisable(GL.GL_ALPHA_TEST); + + gl.glBegin(GL.GL_QUADS); + + gl.glTexCoord2f(0, 1); + Math3D.VectorMA(e.origin, -frame.origin_y, vup, point); + Math3D.VectorMA(point, -frame.origin_x, vright, point); + gl.glVertex3f(point[0], point[1], point[2]); + + gl.glTexCoord2f(0, 0); + Math3D.VectorMA(e.origin, frame.height - frame.origin_y, vup, point); + Math3D.VectorMA(point, -frame.origin_x, vright, point); + gl.glVertex3f(point[0], point[1], point[2]); + + gl.glTexCoord2f(1, 0); + Math3D.VectorMA(e.origin, frame.height - frame.origin_y, vup, point); + Math3D.VectorMA(point, frame.width - frame.origin_x, vright, point); + gl.glVertex3f(point[0], point[1], point[2]); + + gl.glTexCoord2f(1, 1); + Math3D.VectorMA(e.origin, -frame.origin_y, vup, point); + Math3D.VectorMA(point, frame.width - frame.origin_x, vright, point); + gl.glVertex3f(point[0], point[1], point[2]); + + gl.glEnd(); + + gl.glDisable(GL.GL_ALPHA_TEST); + GL_TexEnv(GL.GL_REPLACE); + + if (alpha != 1.0F) + gl.glDisable(GL.GL_BLEND); + + gl.glColor4f(1, 1, 1, 1); + } + + // ================================================================================== + + /* + ============= + R_DrawNullModel + ============= + cwei :-) + */ + void R_DrawNullModel() { + float[] shadelight = { 0, 0, 0 }; + + if ((currententity.flags & Defines.RF_FULLBRIGHT) != 0) { + // cwei wollte blau: shadelight[0] = shadelight[1] = shadelight[2] = 1.0F; + shadelight[0] = shadelight[1] = shadelight[2] = 0.0F; + shadelight[2] = 0.8F; + } + else { + R_LightPoint(currententity.origin, shadelight); + } + + gl.glPushMatrix(); + R_RotateForEntity(currententity); + + gl.glDisable(GL.GL_TEXTURE_2D); + gl.glColor3f(shadelight[0], shadelight[1], shadelight[2]); + + // this replaces the TRIANGLE_FAN + glut.glutWireCube(gl, 20); + + /* + gl.glBegin(GL.GL_TRIANGLE_FAN); + gl.glVertex3f(0, 0, -16); + int i; + for (i=0 ; i<=4 ; i++) { + gl.glVertex3f((float)(16.0f * Math.cos(i * Math.PI / 2)), (float)(16.0f * Math.sin(i * Math.PI / 2)), 0.0f); + } + gl.glEnd(); + + gl.glBegin(GL.GL_TRIANGLE_FAN); + gl.glVertex3f (0, 0, 16); + for (i=4 ; i>=0 ; i--) { + gl.glVertex3f((float)(16.0f * Math.cos(i * Math.PI / 2)), (float)(16.0f * Math.sin(i * Math.PI / 2)), 0.0f); + } + gl.glEnd(); + */ + gl.glColor3f(1, 1, 1); + gl.glPopMatrix(); + gl.glEnable(GL.GL_TEXTURE_2D); + } + + /* + ============= + R_DrawEntitiesOnList + ============= + */ + void R_DrawEntitiesOnList() { + int i; + + if (r_drawentities.value == 0.0f) + return; + + // draw non-transparent first + for (i = 0; i < r_newrefdef.num_entities; i++) { + currententity = r_newrefdef.entities[i]; + if ((currententity.flags & Defines.RF_TRANSLUCENT) != 0) + continue; // solid + + if ((currententity.flags & Defines.RF_BEAM) != 0) { + R_DrawBeam(currententity); + } + else { + currentmodel = currententity.model; + if (currentmodel == null) { + R_DrawNullModel(); + continue; + } + switch (currentmodel.type) { + case mod_alias : + R_DrawAliasModel(currententity); + break; + case mod_brush : + R_DrawBrushModel(currententity); + break; + case mod_sprite : + R_DrawSpriteModel(currententity); + break; + default : + ri.Sys_Error(Defines.ERR_DROP, "Bad modeltype"); + break; + } + } + } + // draw transparent entities + // we could sort these if it ever becomes a problem... + gl.glDepthMask(false); // no z writes + for (i = 0; i < r_newrefdef.num_entities; i++) { + currententity = r_newrefdef.entities[i]; + if ((currententity.flags & Defines.RF_TRANSLUCENT) == 0) + continue; // solid + + if ((currententity.flags & Defines.RF_BEAM) != 0) { + R_DrawBeam(currententity); + } + else { + currentmodel = currententity.model; + + if (currentmodel == null) { + R_DrawNullModel(); + continue; + } + switch (currentmodel.type) { + case mod_alias : + R_DrawAliasModel(currententity); + break; + case mod_brush : + R_DrawBrushModel(currententity); + break; + case mod_sprite : + R_DrawSpriteModel(currententity); + break; + default : + ri.Sys_Error(Defines.ERR_DROP, "Bad modeltype"); + break; + } + } + } + gl.glDepthMask(true); // back to writing + } + + /* + ** GL_DrawParticles + ** + */ + void GL_DrawParticles(int num_particles) { + float[] up = { 0, 0, 0 }; + float[] right = { 0, 0, 0 }; + float scale; + int color; + + float origin_x, origin_y, origin_z; + + Math3D.VectorScale(vup, 1.5f, up); + Math3D.VectorScale(vright, 1.5f, right); + + GL_Bind(r_particletexture.texnum); + gl.glDepthMask(false); // no z buffering + gl.glEnable(GL.GL_BLEND); + GL_TexEnv(GL.GL_MODULATE); + + gl.glBegin(GL.GL_TRIANGLES); + + FloatBuffer sourceVertices = particle_t.vertexArray; + IntBuffer sourceColors = particle_t.colorArray; + for (int j = 0, i = 0; i < num_particles; i++) { + origin_x = sourceVertices.get(j++); + origin_y = sourceVertices.get(j++); + origin_z = sourceVertices.get(j++); + + // hack a scale up to keep particles from disapearing + scale = + (origin_x - r_origin[0]) * vpn[0] + + (origin_y - r_origin[1]) * vpn[1] + + (origin_z - r_origin[2]) * vpn[2]; + + scale = (scale < 20) ? 1 : 1 + scale * 0.004f; + + color = sourceColors.get(i); + gl.glColor4ub( + (byte)((color >> 0) & 0xFF), + (byte)((color >> 8) & 0xFF), + (byte)((color >> 16) & 0xFF), + (byte)((color >> 24) & 0xFF) + ); + // first vertex + gl.glTexCoord2f(0.0625f, 0.0625f); + gl.glVertex3f(origin_x, origin_y, origin_z); + // second vertex + gl.glTexCoord2f(1.0625f, 0.0625f); + gl.glVertex3f(origin_x + up[0] * scale, origin_y + up[1] * scale, origin_z + up[2] * scale); + // third vertex + gl.glTexCoord2f(0.0625f, 1.0625f); + gl.glVertex3f(origin_x + right[0] * scale, origin_y + right[1] * scale, origin_z + right[2] * scale); + } + gl.glEnd(); + + gl.glDisable(GL.GL_BLEND); + gl.glColor4f(1, 1, 1, 1); + gl.glDepthMask(true); // back to normal Z buffering + GL_TexEnv(GL.GL_REPLACE); + } + + /* + =============== + R_DrawParticles + =============== + */ + void R_DrawParticles() { + + if (gl_ext_pointparameters.value != 0.0f && qglPointParameterfEXT) { + + //gl.glEnableClientState(GL.GL_VERTEX_ARRAY); + gl.glVertexPointer(3, GL.GL_FLOAT, 0, particle_t.vertexArray); + gl.glEnableClientState(GL.GL_COLOR_ARRAY); + gl.glColorPointer(4, GL.GL_UNSIGNED_BYTE, 0, particle_t.colorArray); + + gl.glDepthMask(false); + gl.glEnable(GL.GL_BLEND); + gl.glDisable(GL.GL_TEXTURE_2D); + gl.glPointSize(gl_particle_size.value); + + gl.glDrawArrays(GL.GL_POINTS, 0, r_newrefdef.num_particles); + + gl.glDisableClientState(GL.GL_COLOR_ARRAY); + //gl.glDisableClientState(GL.GL_VERTEX_ARRAY); + + gl.glDisable(GL.GL_BLEND); + gl.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + gl.glDepthMask(true); + gl.glEnable(GL.GL_TEXTURE_2D); + + } + else { + GL_DrawParticles(r_newrefdef.num_particles); + } + } + + /* + ============ + R_PolyBlend + ============ + */ + void R_PolyBlend() { + if (gl_polyblend.value == 0.0f) + return; + + if (v_blend[3] == 0.0f) + return; + + gl.glDisable(GL.GL_ALPHA_TEST); + gl.glEnable(GL.GL_BLEND); + gl.glDisable(GL.GL_DEPTH_TEST); + gl.glDisable(GL.GL_TEXTURE_2D); + + gl.glLoadIdentity(); + + // FIXME: get rid of these + gl.glRotatef(-90, 1, 0, 0); // put Z going up + gl.glRotatef(90, 0, 0, 1); // put Z going up + + gl.glColor4f(v_blend[0], v_blend[1], v_blend[2], v_blend[3]); + + gl.glBegin(GL.GL_QUADS); + + gl.glVertex3f(10, 100, 100); + gl.glVertex3f(10, -100, 100); + gl.glVertex3f(10, -100, -100); + gl.glVertex3f(10, 100, -100); + gl.glEnd(); + + gl.glDisable(GL.GL_BLEND); + gl.glEnable(GL.GL_TEXTURE_2D); + gl.glEnable(GL.GL_ALPHA_TEST); + + gl.glColor4f(1, 1, 1, 1); + } + + // ======================================================================= + + int SignbitsForPlane(cplane_t out) { + // for fast box on planeside test + int bits = 0; + for (int j = 0; j < 3; j++) { + if (out.normal[j] < 0) + bits |= (1 << j); + } + return bits; + } + + void R_SetFrustum() { + // rotate VPN right by FOV_X/2 degrees + Math3D.RotatePointAroundVector(frustum[0].normal, vup, vpn, - (90f - r_newrefdef.fov_x / 2f)); + // rotate VPN left by FOV_X/2 degrees + Math3D.RotatePointAroundVector(frustum[1].normal, vup, vpn, 90f - r_newrefdef.fov_x / 2f); + // rotate VPN up by FOV_X/2 degrees + Math3D.RotatePointAroundVector(frustum[2].normal, vright, vpn, 90f - r_newrefdef.fov_y / 2f); + // rotate VPN down by FOV_X/2 degrees + Math3D.RotatePointAroundVector(frustum[3].normal, vright, vpn, - (90f - r_newrefdef.fov_y / 2f)); + + for (int i = 0; i < 4; i++) { + frustum[i].type = Defines.PLANE_ANYZ; + frustum[i].dist = Math3D.DotProduct(r_origin, frustum[i].normal); + frustum[i].signbits = (byte) SignbitsForPlane(frustum[i]); + } + } + + // ======================================================================= + + /* + =============== + R_SetupFrame + =============== + */ + void R_SetupFrame() { + int i; + mleaf_t leaf; + + r_framecount++; + + // build the transformation matrix for the given view angles + Math3D.VectorCopy(r_newrefdef.vieworg, r_origin); + + Math3D.AngleVectors(r_newrefdef.viewangles, vpn, vright, vup); + + // current viewcluster + if ((r_newrefdef.rdflags & Defines.RDF_NOWORLDMODEL) == 0) { + r_oldviewcluster = r_viewcluster; + r_oldviewcluster2 = r_viewcluster2; + leaf = Mod_PointInLeaf(r_origin, r_worldmodel); + r_viewcluster = r_viewcluster2 = leaf.cluster; + + // check above and below so crossing solid water doesn't draw wrong + if (leaf.contents == 0) { // look down a bit + float[] temp = { 0, 0, 0 }; + + Math3D.VectorCopy(r_origin, temp); + temp[2] -= 16; + leaf = Mod_PointInLeaf(temp, r_worldmodel); + if ((leaf.contents & Defines.CONTENTS_SOLID) == 0 && (leaf.cluster != r_viewcluster2)) + r_viewcluster2 = leaf.cluster; + } + else { // look up a bit + float[] temp = { 0, 0, 0 }; + + Math3D.VectorCopy(r_origin, temp); + temp[2] += 16; + leaf = Mod_PointInLeaf(temp, r_worldmodel); + if ((leaf.contents & Defines.CONTENTS_SOLID) == 0 && (leaf.cluster != r_viewcluster2)) + r_viewcluster2 = leaf.cluster; + } + } + + for (i = 0; i < 4; i++) + v_blend[i] = r_newrefdef.blend[i]; + + c_brush_polys = 0; + c_alias_polys = 0; + + // clear out the portion of the screen that the NOWORLDMODEL defines + if ((r_newrefdef.rdflags & Defines.RDF_NOWORLDMODEL) != 0) { + gl.glEnable(GL.GL_SCISSOR_TEST); + gl.glClearColor(0.3f, 0.3f, 0.3f, 1.0f); + gl.glScissor( + r_newrefdef.x, + vid.height - r_newrefdef.height - r_newrefdef.y, + r_newrefdef.width, + r_newrefdef.height); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + gl.glClearColor(1.0f, 0.0f, 0.5f, 0.5f); + gl.glDisable(GL.GL_SCISSOR_TEST); + } + } + + void MYgluPerspective(double fovy, double aspect, double zNear, double zFar) { + double xmin, xmax, ymin, ymax; + + ymax = zNear * Math.tan(fovy * Math.PI / 360.0); + ymin = -ymax; + + xmin = ymin * aspect; + xmax = ymax * aspect; + + xmin += - (2 * gl_state.camera_separation) / zNear; + xmax += - (2 * gl_state.camera_separation) / zNear; + + gl.glFrustum(xmin, xmax, ymin, ymax, zNear, zFar); + } + + /* + ============= + R_SetupGL + ============= + */ + void R_SetupGL() { + float screenaspect; + int x, x2, y2, y, w, h; + + // + // set up viewport + // + x = (int) Math.floor(r_newrefdef.x * vid.width / vid.width); + x2 = (int) Math.ceil((r_newrefdef.x + r_newrefdef.width) * vid.width / vid.width); + y = (int) Math.floor(vid.height - r_newrefdef.y * vid.height / vid.height); + y2 = (int) Math.ceil(vid.height - (r_newrefdef.y + r_newrefdef.height) * vid.height / vid.height); + + w = x2 - x; + h = y - y2; + + gl.glViewport(x, y2, w, h); + + // + // set up projection matrix + // + screenaspect = (float) r_newrefdef.width / r_newrefdef.height; + gl.glMatrixMode(GL.GL_PROJECTION); + gl.glLoadIdentity(); + MYgluPerspective(r_newrefdef.fov_y, screenaspect, 4, 4096); + + gl.glCullFace(GL.GL_FRONT); + + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glLoadIdentity(); + + gl.glRotatef(-90, 1, 0, 0); // put Z going up + gl.glRotatef(90, 0, 0, 1); // put Z going up + gl.glRotatef(-r_newrefdef.viewangles[2], 1, 0, 0); + gl.glRotatef(-r_newrefdef.viewangles[0], 0, 1, 0); + gl.glRotatef(-r_newrefdef.viewangles[1], 0, 0, 1); + gl.glTranslatef(-r_newrefdef.vieworg[0], -r_newrefdef.vieworg[1], -r_newrefdef.vieworg[2]); + + gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, r_world_matrix); + + // + // set drawing parms + // + if (gl_cull.value != 0.0f) + gl.glEnable(GL.GL_CULL_FACE); + else + gl.glDisable(GL.GL_CULL_FACE); + + gl.glDisable(GL.GL_BLEND); + gl.glDisable(GL.GL_ALPHA_TEST); + gl.glEnable(GL.GL_DEPTH_TEST); + } + + /* + ============= + R_Clear + ============= + */ + int trickframe = 0; + + void R_Clear() { + if (gl_ztrick.value != 0.0f) { + + if (gl_clear.value != 0.0f) { + gl.glClear(GL.GL_COLOR_BUFFER_BIT); + } + + trickframe++; + if ((trickframe & 1) != 0) { + gldepthmin = 0; + gldepthmax = 0.49999f; + gl.glDepthFunc(GL.GL_LEQUAL); + } + else { + gldepthmin = 1; + gldepthmax = 0.5f; + gl.glDepthFunc(GL.GL_GEQUAL); + } + } + else { + if (gl_clear.value != 0.0f) + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + else + gl.glClear(GL.GL_DEPTH_BUFFER_BIT); + + gldepthmin = 0; + gldepthmax = 1; + gl.glDepthFunc(GL.GL_LEQUAL); + } + gl.glDepthRange(gldepthmin, gldepthmax); + } + + void R_Flash() { + R_PolyBlend(); + } + + /* + ================ + R_RenderView + + r_newrefdef must be set before the first call + ================ + */ + void R_RenderView(refdef_t fd) { + + if (r_norefresh.value != 0.0f) + return; + + r_newrefdef = fd; + + // included by cwei + if (r_newrefdef == null) { + ri.Sys_Error(Defines.ERR_DROP, "R_RenderView: refdef_t fd is null"); + } + + if (r_worldmodel == null && (r_newrefdef.rdflags & Defines.RDF_NOWORLDMODEL) == 0) + ri.Sys_Error(Defines.ERR_DROP, "R_RenderView: NULL worldmodel"); + + if (r_speeds.value != 0.0f) { + c_brush_polys = 0; + c_alias_polys = 0; + } + + R_PushDlights(); + + if (gl_finish.value != 0.0f) + gl.glFinish(); + + R_SetupFrame(); + + R_SetFrustum(); + + R_SetupGL(); + + R_MarkLeaves(); // done here so we know if we're in water + + R_DrawWorld(); + + R_DrawEntitiesOnList(); + + R_RenderDlights(); + + R_DrawParticles(); + + R_DrawAlphaSurfaces(); + + R_Flash(); + + if (r_speeds.value != 0.0f) { + ri.Con_Printf( + Defines.PRINT_ALL, + "%4i wpoly %4i epoly %i tex %i lmaps\n", + new Vargs(4).add(c_brush_polys).add(c_alias_polys).add(c_visible_textures).add(c_visible_lightmaps)); + } + } + + void R_SetGL2D() { + // set 2D virtual screen size + gl.glViewport(0, 0, vid.width, vid.height); + gl.glMatrixMode(GL.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glOrtho(0, vid.width, vid.height, 0, -99999, 99999); + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glLoadIdentity(); + gl.glDisable(GL.GL_DEPTH_TEST); + gl.glDisable(GL.GL_CULL_FACE); + gl.glDisable(GL.GL_BLEND); + gl.glEnable(GL.GL_ALPHA_TEST); + gl.glColor4f(1, 1, 1, 1); + } + + /* + ==================== + R_SetLightLevel + + ==================== + */ + void R_SetLightLevel() { + float[] shadelight = { 0, 0, 0 }; + + if ((r_newrefdef.rdflags & Defines.RDF_NOWORLDMODEL) != 0) + return; + + // save off light value for server to look at (BIG HACK!) + + R_LightPoint(r_newrefdef.vieworg, shadelight); + + // pick the greatest component, which should be the same + // as the mono value returned by software + if (shadelight[0] > shadelight[1]) { + if (shadelight[0] > shadelight[2]) + r_lightlevel.value = 150 * shadelight[0]; + else + r_lightlevel.value = 150 * shadelight[2]; + } + else { + if (shadelight[1] > shadelight[2]) + r_lightlevel.value = 150 * shadelight[1]; + else + r_lightlevel.value = 150 * shadelight[2]; + } + } + + /* + @@@@@@@@@@@@@@@@@@@@@ + R_RenderFrame + + @@@@@@@@@@@@@@@@@@@@@ + */ + protected void R_RenderFrame(refdef_t fd) { + R_RenderView(fd); + R_SetLightLevel(); + R_SetGL2D(); + } + + protected void R_Register() { + r_lefthand = ri.Cvar_Get("hand", "0", Globals.CVAR_USERINFO | Globals.CVAR_ARCHIVE); + r_norefresh = ri.Cvar_Get("r_norefresh", "0", 0); + r_fullbright = ri.Cvar_Get("r_fullbright", "0", 0); + r_drawentities = ri.Cvar_Get("r_drawentities", "1", 0); + r_drawworld = ri.Cvar_Get("r_drawworld", "1", 0); + r_novis = ri.Cvar_Get("r_novis", "0", 0); + r_nocull = ri.Cvar_Get("r_nocull", "0", 0); + r_lerpmodels = ri.Cvar_Get("r_lerpmodels", "1", 0); + r_speeds = ri.Cvar_Get("r_speeds", "0", 0); + + r_lightlevel = ri.Cvar_Get("r_lightlevel", "1", 0); + + gl_nosubimage = ri.Cvar_Get("gl_nosubimage", "0", 0); + gl_allow_software = ri.Cvar_Get("gl_allow_software", "0", 0); + + gl_particle_min_size = ri.Cvar_Get("gl_particle_min_size", "2", Globals.CVAR_ARCHIVE); + gl_particle_max_size = ri.Cvar_Get("gl_particle_max_size", "40", Globals.CVAR_ARCHIVE); + gl_particle_size = ri.Cvar_Get("gl_particle_size", "40", Globals.CVAR_ARCHIVE); + gl_particle_att_a = ri.Cvar_Get("gl_particle_att_a", "0.01", Globals.CVAR_ARCHIVE); + gl_particle_att_b = ri.Cvar_Get("gl_particle_att_b", "0.0", Globals.CVAR_ARCHIVE); + gl_particle_att_c = ri.Cvar_Get("gl_particle_att_c", "0.01", Globals.CVAR_ARCHIVE); + + gl_modulate = ri.Cvar_Get("gl_modulate", "1", Globals.CVAR_ARCHIVE); + gl_log = ri.Cvar_Get("gl_log", "0", 0); + gl_bitdepth = ri.Cvar_Get("gl_bitdepth", "0", 0); + gl_mode = ri.Cvar_Get("gl_mode", "3", Globals.CVAR_ARCHIVE); // 640x480 + gl_lightmap = ri.Cvar_Get("gl_lightmap", "0", 0); + gl_shadows = ri.Cvar_Get("gl_shadows", "0", Globals.CVAR_ARCHIVE); + gl_dynamic = ri.Cvar_Get("gl_dynamic", "1", 0); + gl_nobind = ri.Cvar_Get("gl_nobind", "0", 0); + gl_round_down = ri.Cvar_Get("gl_round_down", "1", 0); + gl_picmip = ri.Cvar_Get("gl_picmip", "0", 0); + gl_skymip = ri.Cvar_Get("gl_skymip", "0", 0); + gl_showtris = ri.Cvar_Get("gl_showtris", "0", 0); + gl_ztrick = ri.Cvar_Get("gl_ztrick", "0", 0); + gl_finish = ri.Cvar_Get("gl_finish", "0", Globals.CVAR_ARCHIVE); + gl_clear = ri.Cvar_Get("gl_clear", "0", 0); + gl_cull = ri.Cvar_Get("gl_cull", "1", 0); + gl_polyblend = ri.Cvar_Get("gl_polyblend", "1", 0); + gl_flashblend = ri.Cvar_Get("gl_flashblend", "0", 0); + gl_playermip = ri.Cvar_Get("gl_playermip", "0", 0); + gl_monolightmap = ri.Cvar_Get("gl_monolightmap", "0", 0); + gl_driver = ri.Cvar_Get("gl_driver", "opengl32", Globals.CVAR_ARCHIVE); + gl_texturemode = ri.Cvar_Get("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", Globals.CVAR_ARCHIVE); + gl_texturealphamode = ri.Cvar_Get("gl_texturealphamode", "default", Globals.CVAR_ARCHIVE); + gl_texturesolidmode = ri.Cvar_Get("gl_texturesolidmode", "default", Globals.CVAR_ARCHIVE); + gl_lockpvs = ri.Cvar_Get("gl_lockpvs", "0", 0); + + gl_vertex_arrays = ri.Cvar_Get("gl_vertex_arrays", "1", Globals.CVAR_ARCHIVE); + + gl_ext_swapinterval = ri.Cvar_Get("gl_ext_swapinterval", "1", Globals.CVAR_ARCHIVE); + gl_ext_palettedtexture = ri.Cvar_Get("gl_ext_palettedtexture", "0", Globals.CVAR_ARCHIVE); + gl_ext_multitexture = ri.Cvar_Get("gl_ext_multitexture", "1", Globals.CVAR_ARCHIVE); + gl_ext_pointparameters = ri.Cvar_Get("gl_ext_pointparameters", "1", Globals.CVAR_ARCHIVE); + gl_ext_compiled_vertex_array = ri.Cvar_Get("gl_ext_compiled_vertex_array", "1", Globals.CVAR_ARCHIVE); + + gl_drawbuffer = ri.Cvar_Get("gl_drawbuffer", "GL_BACK", 0); + gl_swapinterval = ri.Cvar_Get("gl_swapinterval", "0", Globals.CVAR_ARCHIVE); + + gl_saturatelighting = ri.Cvar_Get("gl_saturatelighting", "0", 0); + + gl_3dlabs_broken = ri.Cvar_Get("gl_3dlabs_broken", "1", Globals.CVAR_ARCHIVE); + + vid_fullscreen = ri.Cvar_Get("vid_fullscreen", "0", Globals.CVAR_ARCHIVE); + vid_gamma = ri.Cvar_Get("vid_gamma", "1.0", Globals.CVAR_ARCHIVE); + vid_ref = ri.Cvar_Get("vid_ref", "fastjogl", Globals.CVAR_ARCHIVE); + + ri.Cmd_AddCommand("imagelist", new xcommand_t() { + public void execute() { + GL_ImageList_f(); + } + }); + + ri.Cmd_AddCommand("screenshot", new xcommand_t() { + public void execute() { + GL_ScreenShot_f(); + } + }); + ri.Cmd_AddCommand("modellist", new xcommand_t() { + public void execute() { + Mod_Modellist_f(); + } + }); + ri.Cmd_AddCommand("gl_strings", new xcommand_t() { + public void execute() { + GL_Strings_f(); + } + }); + } + + /* + ================== + R_SetMode + ================== + */ + protected boolean R_SetMode() { + + int err; // enum rserr_t + boolean fullscreen; + +// if (vid_fullscreen.modified && !gl_config.allow_cds) { +// ri.Con_Printf(Defines.PRINT_ALL, "R_SetMode() - CDS not allowed with this driver\n"); +// ri.Cvar_SetValue("vid_fullscreen", (vid_fullscreen.value > 0.0f) ? 0.0f : 1.0f); +// vid_fullscreen.modified = false; +// } + + fullscreen = (vid_fullscreen.value > 0.0f); + + vid_fullscreen.modified = false; + gl_mode.modified = false; + + Dimension dim = new Dimension(vid.width, vid.height); + + if ((err = GLimp_SetMode(dim, (int) gl_mode.value, fullscreen)) == rserr_ok) { + gl_state.prev_mode = (int) gl_mode.value; + } + else { + if (err == rserr_invalid_fullscreen) { + ri.Cvar_SetValue("vid_fullscreen", 0); + vid_fullscreen.modified = false; + ri.Con_Printf(Defines.PRINT_ALL, "ref_gl::R_SetMode() - fullscreen unavailable in this mode\n"); + if ((err = GLimp_SetMode(dim, (int) gl_mode.value, false)) == rserr_ok) + return true; + } + else if (err == rserr_invalid_mode) { + ri.Cvar_SetValue("gl_mode", gl_state.prev_mode); + gl_mode.modified = false; + ri.Con_Printf(Defines.PRINT_ALL, "ref_gl::R_SetMode() - invalid mode\n"); + } + + // try setting it back to something safe + if ((err = GLimp_SetMode(dim, gl_state.prev_mode, false)) != rserr_ok) { + ri.Con_Printf(Defines.PRINT_ALL, "ref_gl::R_SetMode() - could not revert to safe mode\n"); + return false; + } + } + return true; + } + + /* + =============== + R_Init + =============== + */ + float[] r_turbsin = new float[256]; + + protected boolean R_Init(int vid_xpos, int vid_ypos) { + + assert(Warp.SIN.length == 256) : "warpsin table bug"; + + // fill r_turbsin + for (int j = 0; j < 256; j++) { + r_turbsin[j] = Warp.SIN[j] * 0.5f; + } + + ri.Con_Printf(Defines.PRINT_ALL, "ref_gl version: " + REF_VERSION + '\n'); + + Draw_GetPalette(); + + R_Register(); + + // initialize our QGL dynamic bindings + if (!QGL_Init(gl_driver.string)) { + QGL_Shutdown(); + ri.Con_Printf(Defines.PRINT_ALL, "ref_gl::R_Init() - could not load \"" + gl_driver.string + "\"\n"); + return false; + } + + // initialize OS-specific parts of OpenGL + if (!GLimp_Init(vid_xpos, vid_ypos)) { + QGL_Shutdown(); + return false; + } + + // set our "safe" modes + gl_state.prev_mode = 3; + + // create the window and set up the context + if (!R_SetMode()) { + QGL_Shutdown(); + ri.Con_Printf(Defines.PRINT_ALL, "ref_gl::R_Init() - could not R_SetMode()\n"); + return false; + } + return true; + } + + boolean R_Init2() { + ri.Vid_MenuInit(); + + /* + ** get our various GL strings + */ + gl_config.vendor_string = gl.glGetString(GL.GL_VENDOR); + ri.Con_Printf(Defines.PRINT_ALL, "GL_VENDOR: " + gl_config.vendor_string + '\n'); + gl_config.renderer_string = gl.glGetString(GL.GL_RENDERER); + ri.Con_Printf(Defines.PRINT_ALL, "GL_RENDERER: " + gl_config.renderer_string + '\n'); + gl_config.version_string = gl.glGetString(GL.GL_VERSION); + ri.Con_Printf(Defines.PRINT_ALL, "GL_VERSION: " + gl_config.version_string + '\n'); + gl_config.extensions_string = gl.glGetString(GL.GL_EXTENSIONS); + ri.Con_Printf(Defines.PRINT_ALL, "GL_EXTENSIONS: " + gl_config.extensions_string + '\n'); + + String renderer_buffer = gl_config.renderer_string.toLowerCase(); + String vendor_buffer = gl_config.vendor_string.toLowerCase(); + + if (renderer_buffer.indexOf("voodoo") >= 0) { + if (renderer_buffer.indexOf("rush") < 0) + gl_config.renderer = GL_RENDERER_VOODOO; + else + gl_config.renderer = GL_RENDERER_VOODOO_RUSH; + } + else if (vendor_buffer.indexOf("sgi") >= 0) + gl_config.renderer = GL_RENDERER_SGI; + else if (renderer_buffer.indexOf("permedia") >= 0) + gl_config.renderer = GL_RENDERER_PERMEDIA2; + else if (renderer_buffer.indexOf("glint") >= 0) + gl_config.renderer = GL_RENDERER_GLINT_MX; + else if (renderer_buffer.indexOf("glzicd") >= 0) + gl_config.renderer = GL_RENDERER_REALIZM; + else if (renderer_buffer.indexOf("gdi") >= 0) + gl_config.renderer = GL_RENDERER_MCD; + else if (renderer_buffer.indexOf("pcx2") >= 0) + gl_config.renderer = GL_RENDERER_PCX2; + else if (renderer_buffer.indexOf("verite") >= 0) + gl_config.renderer = GL_RENDERER_RENDITION; + else + gl_config.renderer = GL_RENDERER_OTHER; + + String monolightmap = gl_monolightmap.string.toUpperCase(); + if (monolightmap.length() < 2 || monolightmap.charAt(1) != 'F') { + if (gl_config.renderer == GL_RENDERER_PERMEDIA2) { + ri.Cvar_Set("gl_monolightmap", "A"); + ri.Con_Printf(Defines.PRINT_ALL, "...using gl_monolightmap 'a'\n"); + } + else if ((gl_config.renderer & GL_RENDERER_POWERVR) != 0) { + ri.Cvar_Set("gl_monolightmap", "0"); + } + else { + ri.Cvar_Set("gl_monolightmap", "0"); + } + } + + // power vr can't have anything stay in the framebuffer, so + // the screen needs to redraw the tiled background every frame + if ((gl_config.renderer & GL_RENDERER_POWERVR) != 0) { + ri.Cvar_Set("scr_drawall", "1"); + } + else { + ri.Cvar_Set("scr_drawall", "0"); + } + + // #ifdef __linux__ + ri.Cvar_SetValue("gl_finish", 1); + // #endif + + // MCD has buffering issues + if (gl_config.renderer == GL_RENDERER_MCD) { + ri.Cvar_SetValue("gl_finish", 1); + } + + if ((gl_config.renderer & GL_RENDERER_3DLABS) != 0) { + if (gl_3dlabs_broken.value != 0.0f) + gl_config.allow_cds = false; + else + gl_config.allow_cds = true; + } + else { + gl_config.allow_cds = true; + } + + if (gl_config.allow_cds) + ri.Con_Printf(Defines.PRINT_ALL, "...allowing CDS\n"); + else + ri.Con_Printf(Defines.PRINT_ALL, "...disabling CDS\n"); + + /* + ** grab extensions + */ + if (gl_config.extensions_string.indexOf("GL_EXT_compiled_vertex_array") >= 0 + || gl_config.extensions_string.indexOf("GL_SGI_compiled_vertex_array") >= 0) { + ri.Con_Printf(Defines.PRINT_ALL, "...enabling GL_EXT_compiled_vertex_array\n"); + // qglLockArraysEXT = ( void * ) qwglGetProcAddress( "glLockArraysEXT" ); + if (gl_ext_compiled_vertex_array.value != 0.0f) + qglLockArraysEXT = true; + else + qglLockArraysEXT = false; + // qglUnlockArraysEXT = ( void * ) qwglGetProcAddress( "glUnlockArraysEXT" ); + //qglUnlockArraysEXT = true; + } + else { + ri.Con_Printf(Defines.PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n"); + qglLockArraysEXT = false; + } + + if (gl_config.extensions_string.indexOf("WGL_EXT_swap_control") >= 0) { + qwglSwapIntervalEXT = true; + ri.Con_Printf(Defines.PRINT_ALL, "...enabling WGL_EXT_swap_control\n"); + } else { + qwglSwapIntervalEXT = false; + ri.Con_Printf(Defines.PRINT_ALL, "...WGL_EXT_swap_control not found\n"); + } + + if (gl_config.extensions_string.indexOf("GL_EXT_point_parameters") >= 0) { + if (gl_ext_pointparameters.value != 0.0f) { + // qglPointParameterfEXT = ( void (APIENTRY *)( GLenum, GLfloat ) ) qwglGetProcAddress( "glPointParameterfEXT" ); + qglPointParameterfEXT = true; + // qglPointParameterfvEXT = ( void (APIENTRY *)( GLenum, const GLfloat * ) ) qwglGetProcAddress( "glPointParameterfvEXT" ); + ri.Con_Printf(Defines.PRINT_ALL, "...using GL_EXT_point_parameters\n"); + } + else { + ri.Con_Printf(Defines.PRINT_ALL, "...ignoring GL_EXT_point_parameters\n"); + } + } + else { + ri.Con_Printf(Defines.PRINT_ALL, "...GL_EXT_point_parameters not found\n"); + } + + // #ifdef __linux__ + // if ( strstr( gl_config.extensions_string, "3DFX_set_global_palette" )) + // { + // if ( gl_ext_palettedtexture->value ) + // { + // ri.Con_Printf( Defines.PRINT_ALL, "...using 3DFX_set_global_palette\n" ); + // qgl3DfxSetPaletteEXT = ( void ( APIENTRY * ) (GLuint *) )qwglGetProcAddress( "gl3DfxSetPaletteEXT" ); + //// qglColorTableEXT = Fake_glColorTableEXT; + // } + // else + // { + // ri.Con_Printf( Defines.PRINT_ALL, "...ignoring 3DFX_set_global_palette\n" ); + // } + // } + // else + // { + // ri.Con_Printf( Defines.PRINT_ALL, "...3DFX_set_global_palette not found\n" ); + // } + // #endif + + if (!qglColorTableEXT + && gl_config.extensions_string.indexOf("GL_EXT_paletted_texture") >= 0 + && gl_config.extensions_string.indexOf("GL_EXT_shared_texture_palette") >= 0) { + if (gl_ext_palettedtexture.value != 0.0f) { + ri.Con_Printf(Defines.PRINT_ALL, "...using GL_EXT_shared_texture_palette\n"); + qglColorTableEXT = false; // true; TODO jogl bug + } + else { + ri.Con_Printf(Defines.PRINT_ALL, "...ignoring GL_EXT_shared_texture_palette\n"); + qglColorTableEXT = false; + } + } + else { + ri.Con_Printf(Defines.PRINT_ALL, "...GL_EXT_shared_texture_palette not found\n"); + } + + if (gl_config.extensions_string.indexOf("GL_ARB_multitexture") >= 0) { + ri.Con_Printf(Defines.PRINT_ALL, "...using GL_ARB_multitexture\n"); + qglActiveTextureARB = true; + GL_TEXTURE0 = GL.GL_TEXTURE0_ARB; + GL_TEXTURE1 = GL.GL_TEXTURE1_ARB; + } + else { + ri.Con_Printf(Defines.PRINT_ALL, "...GL_ARB_multitexture not found\n"); + } + + if (!(qglActiveTextureARB)) + return false; + + GL_SetDefaultState(); + + GL_InitImages(); + Mod_Init(); + R_InitParticleTexture(); + Draw_InitLocal(); + + int err = gl.glGetError(); + if (err != GL.GL_NO_ERROR) + ri.Con_Printf( + Defines.PRINT_ALL, + "glGetError() = 0x%x\n\t%s\n", + new Vargs(2).add(err).add("" + gl.glGetString(err))); + + return true; + } + + /* + =============== + R_Shutdown + =============== + */ + protected void R_Shutdown() { + ri.Cmd_RemoveCommand("modellist"); + ri.Cmd_RemoveCommand("screenshot"); + ri.Cmd_RemoveCommand("imagelist"); + ri.Cmd_RemoveCommand("gl_strings"); + + Mod_FreeAll(); + + GL_ShutdownImages(); + + /* + * shut down OS specific OpenGL stuff like contexts, etc. + */ + GLimp_Shutdown(); + + /* + * shutdown our QGL subsystem + */ + QGL_Shutdown(); + } + + /* + @@@@@@@@@@@@@@@@@@@@@ + R_BeginFrame + @@@@@@@@@@@@@@@@@@@@@ + */ + protected void R_BeginFrame(float camera_separation) { + + gl_state.camera_separation = camera_separation; + + /* + ** change modes if necessary + */ + if (gl_mode.modified || vid_fullscreen.modified) { + // FIXME: only restart if CDS is required + cvar_t ref; + + ref = ri.Cvar_Get("vid_ref", "fastjogl", 0); + ref.modified = true; + } + + if (gl_log.modified) { + GLimp_EnableLogging((gl_log.value != 0.0f)); + gl_log.modified = false; + } + + if (gl_log.value != 0.0f) { + GLimp_LogNewFrame(); + } + + /* + ** update 3Dfx gamma -- it is expected that a user will do a vid_restart + ** after tweaking this value + */ + if (vid_gamma.modified) { + vid_gamma.modified = false; + + if ((gl_config.renderer & GL_RENDERER_VOODOO) != 0) { + // wird erstmal nicht gebraucht + + /* + char envbuffer[1024]; + float g; + + g = 2.00 * ( 0.8 - ( vid_gamma->value - 0.5 ) ) + 1.0F; + Com_sprintf( envbuffer, sizeof(envbuffer), "SSTV2_GAMMA=%f", g ); + putenv( envbuffer ); + Com_sprintf( envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g ); + putenv( envbuffer ); + */ + ri.Con_Printf(Defines.PRINT_DEVELOPER, "gamma anpassung fuer VOODOO nicht gesetzt"); + } + } + + GLimp_BeginFrame(camera_separation); + + /* + ** go into 2D mode + */ + gl.glViewport(0, 0, vid.width, vid.height); + gl.glMatrixMode(GL.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glOrtho(0, vid.width, vid.height, 0, -99999, 99999); + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glLoadIdentity(); + gl.glDisable(GL.GL_DEPTH_TEST); + gl.glDisable(GL.GL_CULL_FACE); + gl.glDisable(GL.GL_BLEND); + gl.glEnable(GL.GL_ALPHA_TEST); + gl.glColor4f(1, 1, 1, 1); + + /* + ** draw buffer stuff + */ + if (gl_drawbuffer.modified) { + gl_drawbuffer.modified = false; + + if (gl_state.camera_separation == 0 || !gl_state.stereo_enabled) { + if (gl_drawbuffer.string.equalsIgnoreCase("GL_FRONT")) + gl.glDrawBuffer(GL.GL_FRONT); + else + gl.glDrawBuffer(GL.GL_BACK); + } + } + + /* + ** texturemode stuff + */ + if (gl_texturemode.modified) { + GL_TextureMode(gl_texturemode.string); + gl_texturemode.modified = false; + } + + if (gl_texturealphamode.modified) { + GL_TextureAlphaMode(gl_texturealphamode.string); + gl_texturealphamode.modified = false; + } + + if (gl_texturesolidmode.modified) { + GL_TextureSolidMode(gl_texturesolidmode.string); + gl_texturesolidmode.modified = false; + } + + /* + ** swapinterval stuff + */ + GL_UpdateSwapInterval(); + + // + // clear screen if desired + // + R_Clear(); + } + + int[] r_rawpalette = new int[256]; + + /* + ============= + R_SetPalette + ============= + */ + protected void R_SetPalette(byte[] palette) { + // 256 RGB values (768 bytes) + // or null + int i; + int color = 0; + + if (palette != null) { + int j =0; + for (i = 0; i < 256; i++) { + color = (palette[j++] & 0xFF) << 0; + color |= (palette[j++] & 0xFF) << 8; + color |= (palette[j++] & 0xFF) << 16; + color |= 0xFF000000; + r_rawpalette[i] = color; + } + } + else { + for (i = 0; i < 256; i++) { + r_rawpalette[i] = d_8to24table[i] | 0xff000000; + } + } + GL_SetTexturePalette(r_rawpalette); + + gl.glClearColor(0, 0, 0, 0); + gl.glClear(GL.GL_COLOR_BUFFER_BIT); + gl.glClearColor(1f, 0f, 0.5f, 0.5f); + } + + static final int NUM_BEAM_SEGS = 6; + float[][] start_points = new float[NUM_BEAM_SEGS][3]; + // array of vec3_t + float[][] end_points = new float[NUM_BEAM_SEGS][3]; // array of vec3_t + + /* + ** R_DrawBeam + */ + void R_DrawBeam(entity_t e) { + + int i; + float r, g, b; + + float[] perpvec = { 0, 0, 0 }; // vec3_t + float[] direction = { 0, 0, 0 }; // vec3_t + float[] normalized_direction = { 0, 0, 0 }; // vec3_t + + float[] oldorigin = { 0, 0, 0 }; // vec3_t + float[] origin = { 0, 0, 0 }; // vec3_t + + oldorigin[0] = e.oldorigin[0]; + oldorigin[1] = e.oldorigin[1]; + oldorigin[2] = e.oldorigin[2]; + + origin[0] = e.origin[0]; + origin[1] = e.origin[1]; + origin[2] = e.origin[2]; + + normalized_direction[0] = direction[0] = oldorigin[0] - origin[0]; + normalized_direction[1] = direction[1] = oldorigin[1] - origin[1]; + normalized_direction[2] = direction[2] = oldorigin[2] - origin[2]; + + if (Math3D.VectorNormalize(normalized_direction) == 0.0f) + return; + + Math3D.PerpendicularVector(perpvec, normalized_direction); + Math3D.VectorScale(perpvec, e.frame / 2, perpvec); + + for (i = 0; i < 6; i++) { + Math3D.RotatePointAroundVector( + start_points[i], + normalized_direction, + perpvec, + (360.0f / NUM_BEAM_SEGS) * i); + + Math3D.VectorAdd(start_points[i], origin, start_points[i]); + Math3D.VectorAdd(start_points[i], direction, end_points[i]); + } + + gl.glDisable(GL.GL_TEXTURE_2D); + gl.glEnable(GL.GL_BLEND); + gl.glDepthMask(false); + + r = (d_8to24table[e.skinnum & 0xFF]) & 0xFF; + g = (d_8to24table[e.skinnum & 0xFF] >> 8) & 0xFF; + b = (d_8to24table[e.skinnum & 0xFF] >> 16) & 0xFF; + + r *= 1 / 255.0f; + g *= 1 / 255.0f; + b *= 1 / 255.0f; + + gl.glColor4f(r, g, b, e.alpha); + + gl.glBegin(GL.GL_TRIANGLE_STRIP); + + float[] v; + + for (i = 0; i < NUM_BEAM_SEGS; i++) { + v = start_points[i]; + gl.glVertex3f(v[0], v[1], v[2]); + v = end_points[i]; + gl.glVertex3f(v[0], v[1], v[2]); + v = start_points[(i + 1) % NUM_BEAM_SEGS]; + gl.glVertex3f(v[0], v[1], v[2]); + v = end_points[(i + 1) % NUM_BEAM_SEGS]; + gl.glVertex3f(v[0], v[1], v[2]); + } + gl.glEnd(); + + gl.glEnable(GL.GL_TEXTURE_2D); + gl.glDisable(GL.GL_BLEND); + gl.glDepthMask(true); + } + +} diff --git a/src/jake2/render/fastjogl/Mesh.java b/src/jake2/render/fastjogl/Mesh.java new file mode 100644 index 0000000..e7da997 --- /dev/null +++ b/src/jake2/render/fastjogl/Mesh.java @@ -0,0 +1,753 @@ +/* + * Mesh.java + * Copyright (C) 2003 + * + * $Id: Mesh.java,v 1.1 2004-07-09 06:50:49 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.fastjogl; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +import net.java.games.gluegen.runtime.BufferFactory; +import net.java.games.jogl.GL; +import net.java.games.jogl.util.BufferUtils; +import jake2.Defines; +import jake2.Globals; +import jake2.client.entity_t; +import jake2.qcommon.qfiles; +import jake2.render.image_t; +import jake2.util.Math3D; + +/** + * Mesh + * + * @author cwei + */ +public abstract class Mesh extends Light { + + // g_mesh.c: triangle model functions + + /* + ============================================================= + + ALIAS MODELS + + ============================================================= + */ + + static final int NUMVERTEXNORMALS = 162; + + float[][] r_avertexnormals = Anorms.VERTEXNORMALS; + float[] shadevector = {0, 0, 0}; + float[] shadelight = {0, 0, 0}; + + // precalculated dot products for quantized angles + static final int SHADEDOT_QUANT = 16; + + float[][] r_avertexnormal_dots = Anorms.VERTEXNORMAL_DOTS; + + float[] shadedots = r_avertexnormal_dots[0]; + + void GL_LerpVerts( int nverts, qfiles.dtrivertx_t[] v, qfiles.dtrivertx_t[] ov, qfiles.dtrivertx_t[] verts, FloatBuffer lerp, float[] move, float[] frontv, float[] backv ) + { + int i; + int lerpIndex = 0; + + int[] ovv; + int[] vv; + + //PMM -- added RF_SHELL_DOUBLE, RF_SHELL_HALF_DAM + if ( (currententity.flags & ( Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0 ) + { + float[] normal; + int j = 0; + for (i=0 ; i < nverts; i++/* , v++, ov++, lerp+=4 */) + { + normal = r_avertexnormals[verts[i].lightnormalindex]; + ovv = ov[i].v; + vv = v[i].v; + + lerp.put(j, move[0] + ovv[0]*backv[0] + vv[0]*frontv[0] + normal[0] * Defines.POWERSUIT_SCALE); + lerp.put(j + 1, move[1] + ovv[1]*backv[1] + vv[1]*frontv[1] + normal[1] * Defines.POWERSUIT_SCALE); + lerp.put(j + 2, move[2] + ovv[2]*backv[2] + vv[2]*frontv[2] + normal[2] * Defines.POWERSUIT_SCALE); + j+=3; + } + } + else + { + int j = 0; + for (i=0 ; i < nverts; i++ /* , v++, ov++, lerp+=4 */) + { + ovv = ov[i].v; + vv = v[i].v; + + lerp.put(j, move[0] + ovv[0]*backv[0] + vv[0]*frontv[0]); + lerp.put(j + 1, move[1] + ovv[1]*backv[1] + vv[1]*frontv[1]); + lerp.put(j + 2, move[2] + ovv[2]*backv[2] + vv[2]*frontv[2]); + j+=3; + } + } + } + + FloatBuffer colorArrayBuf = BufferUtils.newFloatBuffer(qfiles.MAX_VERTS * 4); + FloatBuffer vertexArrayBuf = BufferUtils.newFloatBuffer(qfiles.MAX_VERTS * 3); + FloatBuffer textureArrayBuf = BufferUtils.newFloatBuffer(qfiles.MAX_VERTS * 2); + boolean isFilled = false; + float[] tmpVec = {0, 0, 0}; + float[][] vectors = { + {0, 0, 0}, {0, 0, 0}, {0, 0, 0} // 3 mal vec3_t + }; + + /* + ============= + GL_DrawAliasFrameLerp + + interpolates between two frames and origins + FIXME: batch lerp all vertexes + ============= + */ + + void GL_DrawAliasFrameLerp(qfiles.dmdl_t paliashdr, float backlerp) + { + float l; + qfiles.daliasframe_t frame, oldframe; + qfiles.dtrivertx_t[] v, ov, verts; + + int[] order; + int orderIndex = 0; + int count; + + float frontlerp; + float alpha; + + float[] move = {0, 0, 0}; // vec3_t + float[] delta = {0, 0, 0}; // vec3_t + + float[] frontv = {0, 0, 0}; // vec3_t + float[] backv = {0, 0, 0}; // vec3_t + + int i; + int index_xyz; + + frame = paliashdr.aliasFrames[currententity.frame]; + + verts = v = frame.verts; + + oldframe = paliashdr.aliasFrames[currententity.oldframe]; + + ov = oldframe.verts; + + if ((currententity.flags & Defines.RF_TRANSLUCENT) != 0) + alpha = currententity.alpha; + else + alpha = 1.0f; + + // PMM - added double shell + if ( (currententity.flags & ( Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0) + gl.glDisable( GL.GL_TEXTURE_2D ); + + frontlerp = 1.0f - backlerp; + + // move should be the delta back to the previous frame * backlerp + Math3D.VectorSubtract (currententity.oldorigin, currententity.origin, delta); + Math3D.AngleVectors (currententity.angles, vectors[0], vectors[1], vectors[2]); + + move[0] = Math3D.DotProduct (delta, vectors[0]); // forward + move[1] = -Math3D.DotProduct (delta, vectors[1]); // left + move[2] = Math3D.DotProduct (delta, vectors[2]); // up + + Math3D.VectorAdd (move, oldframe.translate, move); + + for (i=0 ; i<3 ; i++) + { + move[i] = backlerp*move[i] + frontlerp*frame.translate[i]; + } + + for (i=0 ; i<3 ; i++) + { + frontv[i] = frontlerp*frame.scale[i]; + backv[i] = backlerp*oldframe.scale[i]; + } + + // ab hier wird optimiert + + GL_LerpVerts( paliashdr.num_xyz, v, ov, verts, vertexArrayBuf, move, frontv, backv ); + + //gl.glEnableClientState( GL.GL_VERTEX_ARRAY ); + gl.glVertexPointer( 3, GL.GL_FLOAT, 0, vertexArrayBuf ); + + // PMM - added double damage shell + if ( (currententity.flags & ( Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0) + { + gl.glColor4f( shadelight[0], shadelight[1], shadelight[2], alpha ); + } + else + { + gl.glEnableClientState( GL.GL_COLOR_ARRAY ); + gl.glColorPointer( 4, GL.GL_FLOAT, 0, colorArrayBuf ); + + // + // pre light everything + // + FloatBuffer color = colorArrayBuf; + int j = 0; + for ( i = 0; i < paliashdr.num_xyz; i++ ) + { + l = shadedots[verts[i].lightnormalindex]; + color.put(j++, l * shadelight[0]); + color.put(j++, l * shadelight[1]); + color.put(j++, l * shadelight[2]); + color.put(j++, alpha); + } + } + + gl.glClientActiveTextureARB(GL_TEXTURE0); + gl.glTexCoordPointer( 2, GL.GL_FLOAT, 0, textureArrayBuf); + //gl.glEnableClientState( GL.GL_TEXTURE_COORD_ARRAY); + + int pos = 0; + int[] counts = paliashdr.counts; + + IntBuffer srcIndexBuf = null; + + FloatBuffer dstTextureCoords = textureArrayBuf; + FloatBuffer srcTextureCoords = paliashdr.textureCoordBuf; + + int size = 0; + int dstIndex = 0; + int srcIndex = 0; + + for (int j = 0; j < counts.length; j++) { + + // get the vertex count and primitive type + count = counts[j]; + if (count == 0) + break; // done + + srcIndexBuf = paliashdr.indexElements[j]; + + size = (count < 0) ? -count + pos : count + pos; + for (int k = pos; k < size; k++) { + srcIndex = 2 * k; + dstIndex = 2 * srcIndexBuf.get(k-pos); + dstTextureCoords.put(dstIndex, srcTextureCoords.get(srcIndex)); + dstTextureCoords.put(dstIndex + 1, srcTextureCoords.get(srcIndex + 1)); + } + + if (count < 0) { + count = -count; + gl.glDrawElements(GL.GL_TRIANGLE_FAN, count, GL.GL_UNSIGNED_INT, srcIndexBuf); + } else { + gl.glDrawElements(GL.GL_TRIANGLE_STRIP, count, GL.GL_UNSIGNED_INT, srcIndexBuf); + } + pos += count; + } + + // PMM - added double damage shell + if ( (currententity.flags & ( Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0 ) + gl.glEnable( GL.GL_TEXTURE_2D ); + + gl.glDisableClientState( GL.GL_COLOR_ARRAY ); + + } + + /* + ============= + GL_DrawAliasShadow + ============= + */ + void GL_DrawAliasShadow(qfiles.dmdl_t paliashdr, int posenum) + { + qfiles.dtrivertx_t[] verts; + int[] order; + float[] point = {0, 0, 0}; + float height, lheight; + int count; + qfiles.daliasframe_t frame; + + lheight = currententity.origin[2] - lightspot[2]; + + frame = paliashdr.aliasFrames[currententity.frame]; + + verts = frame.verts; + + height = 0; + + order = paliashdr.glCmds; + + height = -lheight + 1.0f; + + int orderIndex = 0; + int index = 0; + + // TODO shadow drawing with vertex arrays + + while (true) + { + // get the vertex count and primitive type + count = order[orderIndex++]; + if (count == 0) + break; // done + if (count < 0) + { + count = -count; + gl.glBegin (GL.GL_TRIANGLE_FAN); + } + else + gl.glBegin (GL.GL_TRIANGLE_STRIP); + + do + { + index = order[orderIndex + 2] * 3; + point[0] = vertexArrayBuf.get(index); + point[1] = vertexArrayBuf.get(index + 1); + point[2] = vertexArrayBuf.get(index + 2); + + point[0] -= shadevector[0]*(point[2]+lheight); + point[1] -= shadevector[1]*(point[2]+lheight); + point[2] = height; + gl.glVertex3f(point[0], point[1], point[2]); + + orderIndex += 3; + + } while (--count != 0); + + gl.glEnd (); + } + } + + + /* + ** R_CullAliasModel + */ + boolean R_CullAliasModel( float[][] bbox, entity_t e ) + { + int i; + float[] mins = {0, 0, 0}; + float[] maxs = {0, 0, 0}; + + qfiles.dmdl_t paliashdr; + + float[] thismins = {0, 0, 0}; + float[] oldmins = {0, 0, 0}; + float[] thismaxs = {0, 0, 0}; + float[] oldmaxs = {0, 0, 0}; + qfiles.daliasframe_t pframe, poldframe; + float[] angles = {0, 0, 0}; + + paliashdr = (qfiles.dmdl_t)currentmodel.extradata; + + if ( ( e.frame >= paliashdr.num_frames ) || ( e.frame < 0 ) ) + { + ri.Con_Printf (Defines.PRINT_ALL, "R_CullAliasModel " + currentmodel.name +": no such frame " + e.frame + '\n'); + e.frame = 0; + } + if ( ( e.oldframe >= paliashdr.num_frames ) || ( e.oldframe < 0 ) ) + { + ri.Con_Printf (Defines.PRINT_ALL, "R_CullAliasModel " + currentmodel.name + ": no such oldframe " + e.oldframe + '\n'); + e.oldframe = 0; + } + + pframe = paliashdr.aliasFrames[e.frame]; + poldframe = paliashdr.aliasFrames[e.oldframe]; + + /* + ** compute axially aligned mins and maxs + */ + if ( pframe == poldframe ) + { + for ( i = 0; i < 3; i++ ) + { + mins[i] = pframe.translate[i]; + maxs[i] = mins[i] + pframe.scale[i]*255; + } + } + else + { + for ( i = 0; i < 3; i++ ) + { + thismins[i] = pframe.translate[i]; + thismaxs[i] = thismins[i] + pframe.scale[i]*255; + + oldmins[i] = poldframe.translate[i]; + oldmaxs[i] = oldmins[i] + poldframe.scale[i]*255; + + if ( thismins[i] < oldmins[i] ) + mins[i] = thismins[i]; + else + mins[i] = oldmins[i]; + + if ( thismaxs[i] > oldmaxs[i] ) + maxs[i] = thismaxs[i]; + else + maxs[i] = oldmaxs[i]; + } + } + + /* + ** compute a full bounding box + */ + for ( i = 0; i < 8; i++ ) + { + float[] tmp = {0, 0, 0}; + + if ( (i & 1) != 0 ) + tmp[0] = mins[0]; + else + tmp[0] = maxs[0]; + + if ( (i & 2) != 0) + tmp[1] = mins[1]; + else + tmp[1] = maxs[1]; + + if ( (i & 4) != 0) + tmp[2] = mins[2]; + else + tmp[2] = maxs[2]; + + Math3D.VectorCopy( tmp, bbox[i] ); + } + + /* + ** rotate the bounding box + */ + Math3D.VectorCopy( e.angles, angles ); + angles[YAW] = -angles[YAW]; + Math3D.AngleVectors( angles, vectors[0], vectors[1], vectors[2] ); + + float[] tmp = {0, 0, 0}; + + for ( i = 0; i < 8; i++ ) + { + Math3D.VectorCopy( bbox[i], tmp ); + + bbox[i][0] = Math3D.DotProduct( vectors[0], tmp ); + bbox[i][1] = -Math3D.DotProduct( vectors[1], tmp ); + bbox[i][2] = Math3D.DotProduct( vectors[2], tmp ); + + Math3D.VectorAdd( e.origin, bbox[i], bbox[i] ); + } + + { + int p, f; + int aggregatemask = ~0; // 0xFFFFFFFF + + for ( p = 0; p < 8; p++ ) + { + int mask = 0; + + for ( f = 0; f < 4; f++ ) + { + float dp = Math3D.DotProduct( frustum[f].normal, bbox[p] ); + + if ( ( dp - frustum[f].dist ) < 0 ) + { + mask |= ( 1 << f ); + } + } + + aggregatemask &= mask; + } + + if ( aggregatemask != 0 ) + { + return true; + } + + return false; + } + } + + + // bounding box + float[][] bbox = { + {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, + {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} + }; + + /* + ================= + R_DrawAliasModel + + ================= + */ + void R_DrawAliasModel(entity_t e) + { + int i; + qfiles.dmdl_t paliashdr; + float an; + + image_t skin; + + if ( ( e.flags & Defines.RF_WEAPONMODEL ) == 0) + { + if ( R_CullAliasModel( bbox, e ) ) + return; + } + + if ( (e.flags & Defines.RF_WEAPONMODEL) != 0 ) + { + if ( r_lefthand.value == 2.0f ) + return; + } + + paliashdr = (qfiles.dmdl_t)currentmodel.extradata; + + // + // get lighting information + // + // PMM - rewrote, reordered to handle new shells & mixing + // PMM - 3.20 code .. replaced with original way of doing it to keep mod authors happy + // + if ( (currententity.flags & ( Defines.RF_SHELL_HALF_DAM | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_RED | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE )) != 0 ) + { + Math3D.VectorClear(shadelight); + if ((currententity.flags & Defines.RF_SHELL_HALF_DAM) != 0) + { + shadelight[0] = 0.56f; + shadelight[1] = 0.59f; + shadelight[2] = 0.45f; + } + if ( (currententity.flags & Defines.RF_SHELL_DOUBLE) != 0 ) + { + shadelight[0] = 0.9f; + shadelight[1] = 0.7f; + } + if ( (currententity.flags & Defines.RF_SHELL_RED) != 0 ) + shadelight[0] = 1.0f; + if ( (currententity.flags & Defines.RF_SHELL_GREEN) != 0 ) + shadelight[1] = 1.0f; + if ( (currententity.flags & Defines.RF_SHELL_BLUE) != 0 ) + shadelight[2] = 1.0f; + } + + else if ( (currententity.flags & Defines.RF_FULLBRIGHT) != 0 ) + { + for (i=0 ; i<3 ; i++) + shadelight[i] = 1.0f; + } + else + { + R_LightPoint (currententity.origin, shadelight); + + // player lighting hack for communication back to server + // big hack! + if ( (currententity.flags & Defines.RF_WEAPONMODEL) != 0 ) + { + // pick the greatest component, which should be the same + // as the mono value returned by software + if (shadelight[0] > shadelight[1]) + { + if (shadelight[0] > shadelight[2]) + r_lightlevel.value = 150*shadelight[0]; + else + r_lightlevel.value = 150*shadelight[2]; + } + else + { + if (shadelight[1] > shadelight[2]) + r_lightlevel.value = 150*shadelight[1]; + else + r_lightlevel.value = 150*shadelight[2]; + } + } + + if ( gl_monolightmap.string.charAt(0) != '0' ) + { + float s = shadelight[0]; + + if ( s < shadelight[1] ) + s = shadelight[1]; + if ( s < shadelight[2] ) + s = shadelight[2]; + + shadelight[0] = s; + shadelight[1] = s; + shadelight[2] = s; + } + } + + if ( (currententity.flags & Defines.RF_MINLIGHT) != 0 ) + { + for (i=0 ; i<3 ; i++) + if (shadelight[i] > 0.1f) + break; + if (i == 3) + { + shadelight[0] = 0.1f; + shadelight[1] = 0.1f; + shadelight[2] = 0.1f; + } + } + + if ( (currententity.flags & Defines.RF_GLOW) != 0 ) + { // bonus items will pulse with time + float scale; + float min; + + scale = (float)(0.1f * Math.sin(r_newrefdef.time*7)); + for (i=0 ; i<3 ; i++) + { + min = shadelight[i] * 0.8f; + shadelight[i] += scale; + if (shadelight[i] < min) + shadelight[i] = min; + } + } + + // ================= + // PGM ir goggles color override + if ( (r_newrefdef.rdflags & Defines.RDF_IRGOGGLES) != 0 && (currententity.flags & Defines.RF_IR_VISIBLE) != 0) + { + shadelight[0] = 1.0f; + shadelight[1] = 0.0f; + shadelight[2] = 0.0f; + } + // PGM + // ================= + + shadedots = r_avertexnormal_dots[((int)(currententity.angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; + + an = (float)(currententity.angles[1]/180*Math.PI); + shadevector[0] = (float)Math.cos(-an); + shadevector[1] = (float)Math.sin(-an); + shadevector[2] = 1; + Math3D.VectorNormalize(shadevector); + + // + // locate the proper data + // + + c_alias_polys += paliashdr.num_tris; + + // + // draw all the triangles + // + if ( (currententity.flags & Defines.RF_DEPTHHACK) != 0) // hack the depth range to prevent view model from poking into walls + gl.glDepthRange(gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); + + if ( (currententity.flags & Defines.RF_WEAPONMODEL) != 0 && (r_lefthand.value == 1.0f) ) + { + gl.glMatrixMode( GL.GL_PROJECTION ); + gl.glPushMatrix(); + gl.glLoadIdentity(); + gl.glScalef( -1, 1, 1 ); + MYgluPerspective( r_newrefdef.fov_y, ( float ) r_newrefdef.width / r_newrefdef.height, 4, 4096); + gl.glMatrixMode( GL.GL_MODELVIEW ); + + gl.glCullFace( GL.GL_BACK ); + } + + gl.glPushMatrix (); + e.angles[PITCH] = -e.angles[PITCH]; // sigh. + R_RotateForEntity (e); + e.angles[PITCH] = -e.angles[PITCH]; // sigh. + + // select skin + if (currententity.skin != null) + skin = currententity.skin; // custom player skin + else + { + if (currententity.skinnum >= qfiles.MAX_MD2SKINS) + skin = currentmodel.skins[0]; + else + { + skin = currentmodel.skins[currententity.skinnum]; + if (skin == null) + skin = currentmodel.skins[0]; + } + } + if (skin == null) + skin = r_notexture; // fallback... + GL_Bind(skin.texnum); + + // draw it + + gl.glShadeModel (GL.GL_SMOOTH); + + GL_TexEnv( GL.GL_MODULATE ); + if ( (currententity.flags & Defines.RF_TRANSLUCENT) != 0 ) + { + gl.glEnable (GL.GL_BLEND); + } + + + if ( (currententity.frame >= paliashdr.num_frames) + || (currententity.frame < 0) ) + { + ri.Con_Printf (Defines.PRINT_ALL, "R_DrawAliasModel " + currentmodel.name +": no such frame " + currententity.frame + '\n'); + currententity.frame = 0; + currententity.oldframe = 0; + } + + if ( (currententity.oldframe >= paliashdr.num_frames) + || (currententity.oldframe < 0)) + { + ri.Con_Printf (Defines.PRINT_ALL, "R_DrawAliasModel " + currentmodel.name +": no such oldframe " + currententity.oldframe + '\n'); + currententity.frame = 0; + currententity.oldframe = 0; + } + + if ( r_lerpmodels.value == 0.0f) + currententity.backlerp = 0; + + GL_DrawAliasFrameLerp(paliashdr, currententity.backlerp); + + GL_TexEnv( GL.GL_REPLACE ); + gl.glShadeModel (GL.GL_FLAT); + + gl.glPopMatrix (); + + if ( ( currententity.flags & Defines.RF_WEAPONMODEL ) != 0 && ( r_lefthand.value == 1.0F ) ) + { + gl.glMatrixMode( GL.GL_PROJECTION ); + gl.glPopMatrix(); + gl.glMatrixMode( GL.GL_MODELVIEW ); + gl.glCullFace( GL.GL_FRONT ); + } + + if ( (currententity.flags & Defines.RF_TRANSLUCENT) != 0 ) + { + gl.glDisable (GL.GL_BLEND); + } + + if ( (currententity.flags & Defines.RF_DEPTHHACK) != 0) + gl.glDepthRange (gldepthmin, gldepthmax); + + if ( gl_shadows.value != 0.0f && (currententity.flags & (Defines.RF_TRANSLUCENT | Defines.RF_WEAPONMODEL)) == 0) + { + gl.glPushMatrix (); + R_RotateForEntity (e); + gl.glDisable (GL.GL_TEXTURE_2D); + gl.glEnable (GL.GL_BLEND); + gl.glColor4f (0,0,0,0.5f); + GL_DrawAliasShadow (paliashdr, currententity.frame ); + gl.glEnable (GL.GL_TEXTURE_2D); + gl.glDisable (GL.GL_BLEND); + gl.glPopMatrix (); + } + gl.glColor4f (1,1,1,1); + } + +} diff --git a/src/jake2/render/fastjogl/Misc.java b/src/jake2/render/fastjogl/Misc.java new file mode 100644 index 0000000..bcd2a5f --- /dev/null +++ b/src/jake2/render/fastjogl/Misc.java @@ -0,0 +1,265 @@ +/* + * Misc.java + * Copyright (C) 2003 + * + * $Id: Misc.java,v 1.1 2004-07-09 06:50:48 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.fastjogl; + +import net.java.games.jogl.GL; +import net.java.games.jogl.WGL; + +import jake2.Defines; + +/** + * Misc + * + * @author cwei + */ +public abstract class Misc extends Mesh { + + /* + ================== + R_InitParticleTexture + ================== + */ + byte[][] dottexture = + { + {0,0,0,0,0,0,0,0}, + {0,0,1,1,0,0,0,0}, + {0,1,1,1,1,0,0,0}, + {0,1,1,1,1,0,0,0}, + {0,0,1,1,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}, + }; + + void R_InitParticleTexture() + { + int x,y; + byte[] data = new byte[8 * 8 * 4]; + + // + // particle texture + // + for (x=0 ; x<8 ; x++) + { + for (y=0 ; y<8 ; y++) + { + data[y * 32 + x * 4 + 0] = (byte)255; + data[y * 32 + x * 4 + 1] = (byte)255; + data[y * 32 + x * 4 + 2] = (byte)255; + data[y * 32 + x * 4 + 3] = (byte)(dottexture[x][y]*255); + + } + } + r_particletexture = GL_LoadPic("***particle***", data, 8, 8, it_sprite, 32); + + // + // also use this for bad textures, but without alpha + // + for (x=0 ; x<8 ; x++) + { + for (y=0 ; y<8 ; y++) + { + data[y * 32 + x * 4 + 0] = (byte)(dottexture[x&3][y&3]*255); + data[y * 32 + x * 4 + 1] = 0; // dottexture[x&3][y&3]*255; + data[y * 32 + x * 4 + 2] = 0; //dottexture[x&3][y&3]*255; + data[y * 32 + x * 4 + 3] = (byte)255; + } + } + r_notexture = GL_LoadPic("***r_notexture***", data, 8, 8, it_wall, 32); + } + + +// /* +// ============================================================================== +// +// SCREEN SHOTS +// +// ============================================================================== +// */ +// +// typedef struct _TargaHeader { +// unsigned char id_length, colormap_type, image_type; +// unsigned short colormap_index, colormap_length; +// unsigned char colormap_size; +// unsigned short x_origin, y_origin, width, height; +// unsigned char pixel_size, attributes; +// } TargaHeader; + + + /* + ================== + GL_ScreenShot_f + ================== + */ + void GL_ScreenShot_f() + { +// byte *buffer; +// char picname[80]; +// char checkname[MAX_OSPATH]; +// int i, c, temp; +// FILE *f; +// +// // create the scrnshots directory if it doesn't exist +// Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot", ri.FS_Gamedir()); +// Sys_Mkdir (checkname); +// +//// +//// find a file name to save it to +//// +// strcpy(picname,"quake00.tga"); +// +// for (i=0 ; i<=99 ; i++) +// { +// picname[5] = i/10 + '0'; +// picname[6] = i%10 + '0'; +// Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/%s", ri.FS_Gamedir(), picname); +// f = fopen (checkname, "r"); +// if (!f) +// break; // file doesn't exist +// fclose (f); +// } +// if (i==100) +// { +// ri.Con_Printf (PRINT_ALL, "SCR_ScreenShot_f: Couldn't create a file\n"); +// return; +// } +// +// +// buffer = malloc(vid.width*vid.height*3 + 18); +// memset (buffer, 0, 18); +// buffer[2] = 2; // uncompressed type +// buffer[12] = vid.width&255; +// buffer[13] = vid.width>>8; +// buffer[14] = vid.height&255; +// buffer[15] = vid.height>>8; +// buffer[16] = 24; // pixel size +// +// qglReadPixels (0, 0, vid.width, vid.height, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); +// +// // swap rgb to bgr +// c = 18+vid.width*vid.height*3; +// for (i=18 ; i<c ; i+=3) +// { +// temp = buffer[i]; +// buffer[i] = buffer[i+2]; +// buffer[i+2] = temp; +// } +// +// f = fopen (checkname, "rw"); +// fwrite (buffer, 1, c, f); +// fclose (f); +// +// free (buffer); +// ri.Con_Printf (PRINT_ALL, "Wrote %s\n", picname); + } + + /* + ** GL_Strings_f + */ + void GL_Strings_f() { + ri.Con_Printf (Defines.PRINT_ALL, "GL_VENDOR: " + gl_config.vendor_string + '\n'); + ri.Con_Printf (Defines.PRINT_ALL, "GL_RENDERER: " + gl_config.renderer_string + '\n'); + ri.Con_Printf (Defines.PRINT_ALL, "GL_VERSION: " + gl_config.version_string + '\n'); + ri.Con_Printf (Defines.PRINT_ALL, "GL_EXTENSIONS: " + gl_config.extensions_string + '\n'); + } + + /* + ** GL_SetDefaultState + */ + void GL_SetDefaultState() + { + gl.glClearColor(1f,0f, 0.5f , 0.5f); // original quake2 + //gl.glClearColor(0, 0, 0, 0); // replaced with black + gl.glCullFace(GL.GL_FRONT); + gl.glEnable(GL.GL_TEXTURE_2D); + + gl.glEnable(GL.GL_ALPHA_TEST); + gl.glAlphaFunc(GL.GL_GREATER, 0.666f); + + gl.glDisable (GL.GL_DEPTH_TEST); + gl.glDisable (GL.GL_CULL_FACE); + gl.glDisable (GL.GL_BLEND); + + gl.glColor4f (1,1,1,1); + + gl.glPolygonMode (GL.GL_FRONT_AND_BACK, GL.GL_FILL); + gl.glShadeModel (GL.GL_FLAT); + + GL_TextureMode( gl_texturemode.string ); + GL_TextureAlphaMode( gl_texturealphamode.string ); + GL_TextureSolidMode( gl_texturesolidmode.string ); + + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, gl_filter_min); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, gl_filter_max); + + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT); + + gl.glBlendFunc (GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); + + GL_TexEnv( GL.GL_REPLACE ); + + if ( qglPointParameterfEXT ) + { + float[] attenuations = { gl_particle_att_a.value, gl_particle_att_b.value, gl_particle_att_c.value }; + + gl.glEnable( GL.GL_POINT_SMOOTH ); + gl.glPointParameterfEXT( GL.GL_POINT_SIZE_MIN_EXT, gl_particle_min_size.value ); + gl.glPointParameterfEXT( GL.GL_POINT_SIZE_MAX_EXT, gl_particle_max_size.value ); + gl.glPointParameterfvEXT( GL.GL_DISTANCE_ATTENUATION_EXT, attenuations ); + } + + if ( qglColorTableEXT && gl_ext_palettedtexture.value != 0.0f ) + { + gl.glEnable( GL.GL_SHARED_TEXTURE_PALETTE_EXT ); + + GL_SetTexturePalette( d_8to24table ); + } + + GL_UpdateSwapInterval(); + + /* + * vertex array extension + */ + gl.glEnableClientState(GL.GL_VERTEX_ARRAY); + gl.glClientActiveTextureARB(GL_TEXTURE0); + gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); + } + + void GL_UpdateSwapInterval() + { + if ( gl_swapinterval.modified ) + { + gl_swapinterval.modified = false; + if ( !gl_state.stereo_enabled ) + { + if (qwglSwapIntervalEXT) { + ((WGL)gl).wglSwapIntervalEXT((int)gl_swapinterval.value); + } + } + } + } +} diff --git a/src/jake2/render/fastjogl/Model.java b/src/jake2/render/fastjogl/Model.java new file mode 100644 index 0000000..4b781be --- /dev/null +++ b/src/jake2/render/fastjogl/Model.java @@ -0,0 +1,1347 @@ +/* + * Model.java + * Copyright (C) 2003 + * + * $Id: Model.java,v 1.1 2004-07-09 06:50:49 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.fastjogl; + +import jake2.Defines; +import jake2.game.cplane_t; +import jake2.game.cvar_t; +import jake2.qcommon.*; +import jake2.render.*; +import jake2.util.Math3D; +import jake2.util.Vargs; + +import java.nio.*; +import java.util.Arrays; +import java.util.Vector; + +import net.java.games.jogl.util.BufferUtils; + +/** + * Model + * + * @author cwei + */ +public abstract class Model extends Surf { + + // models.c -- model loading and caching + + model_t loadmodel; + int modfilelen; + + byte[] mod_novis = new byte[Defines.MAX_MAP_LEAFS/8]; + + static final int MAX_MOD_KNOWN = 512; + model_t[] mod_known = new model_t[MAX_MOD_KNOWN]; + int mod_numknown; + + // the inline * models from the current map are kept seperate + model_t[] mod_inline = new model_t[MAX_MOD_KNOWN]; + + abstract void GL_SubdivideSurface(msurface_t surface); // Warp.java + + /* + =============== + Mod_PointInLeaf + =============== + */ + mleaf_t Mod_PointInLeaf(float[] p, model_t model) + { + mnode_t node; + float d; + cplane_t plane; + + if (model == null || model.nodes == null) + ri.Sys_Error (Defines.ERR_DROP, "Mod_PointInLeaf: bad model"); + + node = model.nodes[0]; // root node + while (true) + { + if (node.contents != -1) + return (mleaf_t)node; + + plane = node.plane; + d = Math3D.DotProduct(p, plane.normal) - plane.dist; + if (d > 0) + node = node.children[0]; + else + node = node.children[1]; + } + // never reached + } + + + byte[] decompressed = new byte[Defines.MAX_MAP_LEAFS / 8]; + byte[] model_visibility = new byte[Defines.MAX_MAP_VISIBILITY]; + + /* + =================== + Mod_DecompressVis + =================== + */ + byte[] Mod_DecompressVis(byte[] in, int offset, model_t model) + { + int c; + byte[] out; + int outp, inp; + int row; + + row = (model.vis.numclusters+7)>>3; + out = decompressed; + outp = 0; + inp = offset; + + if (in == null) + { // no vis info, so make all visible + while (row != 0) + { + out[outp++] = (byte)0xFF; + row--; + } + return decompressed; + } + + do + { + if (in[inp] != 0) + { + out[outp++] = in[inp++]; + continue; + } + + c = in[inp + 1] & 0xFF; + inp += 2; + while (c != 0) + { + out[outp++] = 0; + c--; + } + } while (outp < row); + + return decompressed; + } + + /* + ============== + Mod_ClusterPVS + ============== + */ + byte[] Mod_ClusterPVS(int cluster, model_t model) + { + if (cluster == -1 || model.vis == null) + return mod_novis; + //return Mod_DecompressVis( (byte *)model.vis + model.vis.bitofs[cluster][Defines.DVIS_PVS], model); + return Mod_DecompressVis(model_visibility, model.vis.bitofs[cluster][Defines.DVIS_PVS], model); + } + + +// =============================================================================== + + /* + ================ + Mod_Modellist_f + ================ + */ + void Mod_Modellist_f() + { + int i; + model_t mod; + int total; + + total = 0; + ri.Con_Printf(Defines.PRINT_ALL,"Loaded models:\n"); + for (i=0; i < mod_numknown ; i++) + { + mod = mod_known[i]; + if (mod.name == "") + continue; + + ri.Con_Printf (Defines.PRINT_ALL, "%8i : %s\n", new Vargs(2).add(mod.extradatasize).add(mod.name)); + total += mod.extradatasize; + } + ri.Con_Printf (Defines.PRINT_ALL, "Total resident: " + total +'\n'); + } + + /* + =============== + Mod_Init + =============== + */ + void Mod_Init() + { + // init mod_known + for (int i=0; i < MAX_MOD_KNOWN; i++) { + mod_known[i] = new model_t(); + } + Arrays.fill(mod_novis, (byte)0xff); + } + + byte[] fileBuffer; + + /* + ================== + Mod_ForName + + Loads in a model for the given name + ================== + */ + model_t Mod_ForName(String name, boolean crash) + { + model_t mod = null; + int i; + + if (name == null || name.length() == 0) + ri.Sys_Error(Defines.ERR_DROP, "Mod_ForName: NULL name"); + + // + // inline models are grabbed only from worldmodel + // + if (name.charAt(0) == '*') + { + i = Integer.parseInt(name.substring(1)); + if (i < 1 || r_worldmodel == null || i >= r_worldmodel.numsubmodels) + ri.Sys_Error (Defines.ERR_DROP, "bad inline model number"); + return mod_inline[i]; + } + + // + // search the currently loaded models + // + for (i=0; i<mod_numknown ; i++) + { + mod = mod_known[i]; + + if (mod.name == "") + continue; + if (mod.name.equals(name) ) + return mod; + } + + // + // find a free model slot spot + // + for (i=0; i<mod_numknown ; i++) + { + mod = mod_known[i]; + + if (mod.name == "") + break; // free spot + } + if (i == mod_numknown) + { + if (mod_numknown == MAX_MOD_KNOWN) + ri.Sys_Error (Defines.ERR_DROP, "mod_numknown == MAX_MOD_KNOWN"); + mod_numknown++; + mod = mod_known[i]; + } + + mod.name = name; + + // + // load the file + // + fileBuffer = ri.FS_LoadFile(name); + + if (fileBuffer == null) + { + if (crash) + ri.Sys_Error(Defines.ERR_DROP, "Mod_NumForName: " + mod.name + " not found"); + + mod.name = ""; + return null; + } + + modfilelen = fileBuffer.length; + + loadmodel = mod; + + // + // fill it in + // + ByteBuffer bb = ByteBuffer.wrap(fileBuffer); + bb.order(ByteOrder.LITTLE_ENDIAN); + + // call the apropriate loader + + bb.mark(); + int ident = bb.getInt(); + + bb.reset(); + + switch (ident) + { + case qfiles.IDALIASHEADER: + Mod_LoadAliasModel(mod, bb); + break; + case qfiles.IDSPRITEHEADER: + Mod_LoadSpriteModel(mod, bb); + break; + case qfiles.IDBSPHEADER: + Mod_LoadBrushModel(mod, bb); + break; + default: + ri.Sys_Error(Defines.ERR_DROP,"Mod_NumForName: unknown fileid for " + mod.name); + break; + } + + this.fileBuffer = null; // free it for garbage collection + return mod; + } + + /* + =============================================================================== + + BRUSHMODEL LOADING + + =============================================================================== + */ + + byte[] mod_base; + + + /* + ================= + Mod_LoadLighting + ================= + */ + void Mod_LoadLighting(lump_t l) + { + if (l.filelen == 0) + { + loadmodel.lightdata = null; + return; + } + // memcpy (loadmodel.lightdata, mod_base + l.fileofs, l.filelen); + loadmodel.lightdata = new byte[l.filelen]; + System.arraycopy(mod_base, l.fileofs, loadmodel.lightdata, 0, l.filelen); + } + + + /* + ================= + Mod_LoadVisibility + ================= + */ + void Mod_LoadVisibility(lump_t l) + { + int i; + + if (l.filelen == 0) + { + loadmodel.vis = null; + return; + } + + System.arraycopy(mod_base, l.fileofs, model_visibility, 0, l.filelen); + + ByteBuffer bb = ByteBuffer.wrap(model_visibility, 0, l.filelen); + + loadmodel.vis = new qfiles.dvis_t(bb.order(ByteOrder.LITTLE_ENDIAN)); + + /* done: + memcpy (loadmodel.vis, mod_base + l.fileofs, l.filelen); + + loadmodel.vis.numclusters = LittleLong (loadmodel.vis.numclusters); + for (i=0 ; i<loadmodel.vis.numclusters ; i++) + { + loadmodel.vis.bitofs[i][0] = LittleLong (loadmodel.vis.bitofs[i][0]); + loadmodel.vis.bitofs[i][1] = LittleLong (loadmodel.vis.bitofs[i][1]); + } + */ + } + + + /* + ================= + Mod_LoadVertexes + ================= + */ + void Mod_LoadVertexes(lump_t l) + { + mvertex_t[] vertexes; + int i, count; + + if ( (l.filelen % mvertex_t.DISK_SIZE) != 0) + ri.Sys_Error(Defines.ERR_DROP, "MOD_LoadBmodel: funny lump size in " + loadmodel.name); + + count = l.filelen / mvertex_t.DISK_SIZE; + + vertexes = new mvertex_t[count]; + + loadmodel.vertexes = vertexes; + loadmodel.numvertexes = count; + + ByteBuffer bb = ByteBuffer.wrap(mod_base, l.fileofs, l.filelen); + bb.order(ByteOrder.LITTLE_ENDIAN); + + for ( i=0 ; i<count ; i++) + { + vertexes[i] = new mvertex_t(bb); + } + } + + /* + ================= + RadiusFromBounds + ================= + */ + float RadiusFromBounds(float[] mins, float[] maxs) + { + float[] corner = {0, 0, 0}; + + for (int i=0 ; i<3 ; i++) + { + corner[i] = Math.abs(mins[i]) > Math.abs(maxs[i]) ? Math.abs(mins[i]) : Math.abs(maxs[i]); + } + return Math3D.VectorLength(corner); + } + + + /* + ================= + Mod_LoadSubmodels + ================= + */ + void Mod_LoadSubmodels(lump_t l) + { + qfiles.dmodel_t in; + mmodel_t[] out; + int i, j, count; + + if ((l.filelen % qfiles.dmodel_t.SIZE) != 0) + ri.Sys_Error(Defines.ERR_DROP, "MOD_LoadBmodel: funny lump size in " + loadmodel.name); + + count = l.filelen / qfiles.dmodel_t.SIZE; + // out = Hunk_Alloc ( count*sizeof(*out)); + out = new mmodel_t[count]; + + loadmodel.submodels = out; + loadmodel.numsubmodels = count; + + ByteBuffer bb = ByteBuffer.wrap(mod_base, l.fileofs, l.filelen); + bb.order(ByteOrder.LITTLE_ENDIAN); + + for ( i=0 ; i<count ; i++) + { + in = new qfiles.dmodel_t(bb); + out[i] = new mmodel_t(); + for (j=0 ; j<3 ; j++) + { // spread the mins / maxs by a pixel + out[i].mins[j] = in.mins[j] - 1; + out[i].maxs[j] = in.maxs[j] + 1; + out[i].origin[j] = in.origin[j]; + } + out[i].radius = RadiusFromBounds(out[i].mins, out[i].maxs); + out[i].headnode = in.headnode; + out[i].firstface = in.firstface; + out[i].numfaces = in.numfaces; + } + } + + /* + ================= + Mod_LoadEdges + ================= + */ + void Mod_LoadEdges (lump_t l) + { + medge_t[] edges; + int i, count; + + if ( (l.filelen % medge_t.DISK_SIZE) != 0) + ri.Sys_Error(Defines.ERR_DROP, "MOD_LoadBmodel: funny lump size in " + loadmodel.name); + + count = l.filelen / medge_t.DISK_SIZE; + // out = Hunk_Alloc ( (count + 1) * sizeof(*out)); + edges = new medge_t[count + 1]; + + loadmodel.edges = edges; + loadmodel.numedges = count; + + ByteBuffer bb = ByteBuffer.wrap(mod_base, l.fileofs, l.filelen); + bb.order(ByteOrder.LITTLE_ENDIAN); + + for ( i=0 ; i<count ; i++) + { + edges[i] = new medge_t(bb); + } + } + + /* + ================= + Mod_LoadTexinfo + ================= + */ + void Mod_LoadTexinfo(lump_t l) + { + texinfo_t in; + mtexinfo_t[] out; + mtexinfo_t step; + int i, j, count; + int next; + String name; + + if ((l.filelen % texinfo_t.SIZE) != 0) + ri.Sys_Error (Defines.ERR_DROP, "MOD_LoadBmodel: funny lump size in " + loadmodel.name); + + count = l.filelen / texinfo_t.SIZE; + // out = Hunk_Alloc ( count*sizeof(*out)); + out = new mtexinfo_t[count]; + for ( i=0 ; i<count ; i++) { + out[i] = new mtexinfo_t(); + } + + loadmodel.texinfo = out; + loadmodel.numtexinfo = count; + + ByteBuffer bb = ByteBuffer.wrap(mod_base, l.fileofs, l.filelen); + bb.order(ByteOrder.LITTLE_ENDIAN); + + for ( i=0 ; i<count ; i++) { + + in = new texinfo_t(bb); + out[i].vecs = in.vecs; + out[i].flags = in.flags; + next = in.nexttexinfo; + if (next > 0) + out[i].next = loadmodel.texinfo[next]; + else + out[i].next = null; + + name = "textures/" + in.texture + ".wal"; + + out[i].image = GL_FindImage(name, it_wall); + if (out[i].image == null) { + ri.Con_Printf(Defines.PRINT_ALL, "Couldn't load " + name + '\n'); + out[i].image = r_notexture; + } + } + + // count animation frames + for (i=0 ; i<count ; i++) { + out[i].numframes = 1; + for (step = out[i].next ; (step != null) && (step != out[i]) ; step=step.next) + out[i].numframes++; + } + } + + /* + ================ + CalcSurfaceExtents + + Fills in s.texturemins[] and s.extents[] + ================ + */ + void CalcSurfaceExtents(msurface_t s) + { + float[] mins = {0, 0}; + float[] maxs = {0, 0}; + float val; + + int i, j, e; + mvertex_t v; + mtexinfo_t tex; + int[] bmins = {0, 0}; + int[] bmaxs = {0, 0}; + + mins[0] = mins[1] = 999999; + maxs[0] = maxs[1] = -99999; + + tex = s.texinfo; + + for (i=0 ; i<s.numedges ; i++) + { + e = loadmodel.surfedges[s.firstedge+i]; + if (e >= 0) + v = loadmodel.vertexes[loadmodel.edges[e].v[0]]; + else + v = loadmodel.vertexes[loadmodel.edges[-e].v[1]]; + + for (j=0 ; j<2 ; j++) + { + val = v.position[0] * tex.vecs[j][0] + + v.position[1] * tex.vecs[j][1] + + v.position[2] * tex.vecs[j][2] + + tex.vecs[j][3]; + if (val < mins[j]) + mins[j] = val; + if (val > maxs[j]) + maxs[j] = val; + } + } + + for (i=0 ; i<2 ; i++) + { + bmins[i] = (int)Math.floor(mins[i]/16); + bmaxs[i] = (int)Math.ceil(maxs[i]/16); + + s.texturemins[i] = (short)(bmins[i] * 16); + s.extents[i] = (short)((bmaxs[i] - bmins[i]) * 16); + + } + } + + /* + ================= + Mod_LoadFaces + ================= + */ + void Mod_LoadFaces (lump_t l) + { + qfiles.dface_t in; + msurface_t[] out; + int i, count, surfnum; + int planenum, side; + int ti; + + if ((l.filelen % qfiles.dface_t.SIZE) != 0) + ri.Sys_Error (Defines.ERR_DROP, "MOD_LoadBmodel: funny lump size in " + loadmodel.name); + + count = l.filelen / qfiles.dface_t.SIZE; + // out = Hunk_Alloc ( count*sizeof(*out)); + out = new msurface_t[count]; + + loadmodel.surfaces = out; + loadmodel.numsurfaces = count; + + ByteBuffer bb = ByteBuffer.wrap(mod_base, l.fileofs, l.filelen); + bb.order(ByteOrder.LITTLE_ENDIAN); + + currentmodel = loadmodel; + + GL_BeginBuildingLightmaps(loadmodel); + + for ( surfnum=0 ; surfnum<count ; surfnum++) + { + in = new qfiles.dface_t(bb); + out[surfnum] = new msurface_t(); + out[surfnum].firstedge = in.firstedge; + out[surfnum].numedges = in.numedges; + out[surfnum].flags = 0; + out[surfnum].polys = null; + + planenum = in.planenum; + side = in.side; + if (side != 0) + out[surfnum].flags |= Defines.SURF_PLANEBACK; + + out[surfnum].plane = loadmodel.planes[planenum]; + + ti = in.texinfo; + if (ti < 0 || ti >= loadmodel.numtexinfo) + ri.Sys_Error(Defines.ERR_DROP, "MOD_LoadBmodel: bad texinfo number"); + + out[surfnum].texinfo = loadmodel.texinfo[ti]; + + CalcSurfaceExtents(out[surfnum]); + + // lighting info + + for (i=0 ; i<Defines.MAXLIGHTMAPS ; i++) + out[surfnum].styles[i] = in.styles[i]; + + i = in.lightofs; + if (i == -1) + out[surfnum].samples = null; + else { + ByteBuffer pointer = ByteBuffer.wrap(loadmodel.lightdata); + pointer.position(i); + pointer = pointer.slice(); + pointer.mark(); + out[surfnum].samples = pointer; // subarray + } + + // set the drawing flags + + if ((out[surfnum].texinfo.flags & Defines.SURF_WARP) != 0) + { + out[surfnum].flags |= Defines.SURF_DRAWTURB; + for (i=0 ; i<2 ; i++) + { + out[surfnum].extents[i] = 16384; + out[surfnum].texturemins[i] = -8192; + } + GL_SubdivideSurface(out[surfnum]); // cut up polygon for warps + } + + // create lightmaps and polygons + if ((out[surfnum].texinfo.flags & (Defines.SURF_SKY | Defines.SURF_TRANS33 | Defines.SURF_TRANS66 | Defines.SURF_WARP)) == 0) + GL_CreateSurfaceLightmap(out[surfnum]); + + if ((out[surfnum].texinfo.flags & Defines.SURF_WARP) == 0) + GL_BuildPolygonFromSurface(out[surfnum]); + + } + GL_EndBuildingLightmaps (); + } + + + /* + ================= + Mod_SetParent + ================= + */ + void Mod_SetParent(mnode_t node, mnode_t parent) + { + node.parent = parent; + if (node.contents != -1) return; + Mod_SetParent(node.children[0], node); + Mod_SetParent(node.children[1], node); + } + + /* + ================= + Mod_LoadNodes + ================= + */ + void Mod_LoadNodes(lump_t l) + { + int i, j, count, p; + qfiles.dnode_t in; + mnode_t[] out; + + if ((l.filelen % qfiles.dnode_t.SIZE) != 0) + ri.Sys_Error(Defines.ERR_DROP, "MOD_LoadBmodel: funny lump size in " + loadmodel.name); + + count = l.filelen / qfiles.dnode_t.SIZE; + // out = Hunk_Alloc ( count*sizeof(*out)); + out = new mnode_t[count]; + + loadmodel.nodes = out; + loadmodel.numnodes = count; + + ByteBuffer bb = ByteBuffer.wrap(mod_base, l.fileofs, l.filelen); + bb.order(ByteOrder.LITTLE_ENDIAN); + + // initialize the tree array + for ( i=0 ; i<count ; i++) out[i] = new mnode_t(); // do first before linking + + // fill and link the nodes + for ( i=0 ; i<count ; i++) + { + in = new qfiles.dnode_t(bb); + for (j=0 ; j<3 ; j++) + { + out[i].mins[j] = in.mins[j]; + out[i].maxs[j] = in.maxs[j]; + } + + p = in.planenum; + out[i].plane = loadmodel.planes[p]; + + out[i].firstsurface = in.firstface; + out[i].numsurfaces = in.numfaces; + out[i].contents = -1; // differentiate from leafs + + for (j=0 ; j<2 ; j++) + { + p = in.children[j]; + if (p >= 0) + out[i].children[j] = loadmodel.nodes[p]; + else + out[i].children[j] = loadmodel.leafs[-1 - p]; // mleaf_t extends mnode_t + } + } + + Mod_SetParent(loadmodel.nodes[0], null); // sets nodes and leafs + } + + /* + ================= + Mod_LoadLeafs + ================= + */ + void Mod_LoadLeafs(lump_t l) + { + qfiles.dleaf_t in; + mleaf_t[] out; + int i, j, count, p; + + if ((l.filelen % qfiles.dleaf_t.SIZE) != 0) + ri.Sys_Error (Defines.ERR_DROP, "MOD_LoadBmodel: funny lump size in " + loadmodel.name); + + count = l.filelen / qfiles.dleaf_t.SIZE; + // out = Hunk_Alloc ( count*sizeof(*out)); + out = new mleaf_t[count]; + + loadmodel.leafs = out; + loadmodel.numleafs = count; + + ByteBuffer bb = ByteBuffer.wrap(mod_base, l.fileofs, l.filelen); + bb.order(ByteOrder.LITTLE_ENDIAN); + + for ( i=0 ; i<count ; i++) + { + in = new qfiles.dleaf_t(bb); + out[i] = new mleaf_t(); + for (j=0 ; j<3 ; j++) + { + out[i].mins[j] = in.mins[j]; + out[i].maxs[j] = in.maxs[j]; + + } + + out[i].contents = in.contents; + out[i].cluster = in.cluster; + out[i].area = in.area; + + out[i].setMarkSurface(in.firstleafface, loadmodel.marksurfaces); + out[i].nummarksurfaces = in.numleaffaces; + } + } + + + /* + ================= + Mod_LoadMarksurfaces + ================= + */ + void Mod_LoadMarksurfaces(lump_t l) + { + int i, j, count; + + msurface_t[] out; + + if ((l.filelen % Defines.SIZE_OF_SHORT) != 0) + ri.Sys_Error(Defines.ERR_DROP, "MOD_LoadBmodel: funny lump size in " + loadmodel.name); + count = l.filelen / Defines.SIZE_OF_SHORT; + // out = Hunk_Alloc ( count*sizeof(*out)); + out = new msurface_t[count]; + + loadmodel.marksurfaces = out; + loadmodel.nummarksurfaces = count; + + ByteBuffer bb = ByteBuffer.wrap(mod_base, l.fileofs, l.filelen); + bb.order(ByteOrder.LITTLE_ENDIAN); + + for ( i=0 ; i<count ; i++) + { + j = bb.getShort(); + if (j < 0 || j >= loadmodel.numsurfaces) + ri.Sys_Error(Defines.ERR_DROP, "Mod_ParseMarksurfaces: bad surface number"); + + out[i] = loadmodel.surfaces[j]; + } + } + + + /* + ================= + Mod_LoadSurfedges + ================= + */ + void Mod_LoadSurfedges(lump_t l) + { + int i, count; + int[] offsets; + + if ( (l.filelen % Defines.SIZE_OF_INT) != 0) + ri.Sys_Error (Defines.ERR_DROP, "MOD_LoadBmodel: funny lump size in " + loadmodel.name); + + count = l.filelen / Defines.SIZE_OF_INT; + if (count < 1 || count >= Defines.MAX_MAP_SURFEDGES) + ri.Sys_Error (Defines.ERR_DROP, "MOD_LoadBmodel: bad surfedges count in " + loadmodel.name + ": " + count); + + offsets = new int[count]; + + loadmodel.surfedges = offsets; + loadmodel.numsurfedges = count; + + ByteBuffer bb = ByteBuffer.wrap(mod_base, l.fileofs, l.filelen); + bb.order(ByteOrder.LITTLE_ENDIAN); + + for ( i=0 ; i<count ; i++) offsets[i] = bb.getInt(); + } + + + /* + ================= + Mod_LoadPlanes + ================= + */ + void Mod_LoadPlanes(lump_t l) + { + int i, j; + cplane_t[] out; + qfiles.dplane_t in; + int count; + int bits; + + if ((l.filelen % qfiles.dplane_t.SIZE) != 0) + ri.Sys_Error(Defines.ERR_DROP, "MOD_LoadBmodel: funny lump size in " + loadmodel.name); + + count = l.filelen / qfiles.dplane_t.SIZE; + // out = Hunk_Alloc ( count*2*sizeof(*out)); + out = new cplane_t[count * 2]; + + loadmodel.planes = out; + loadmodel.numplanes = count; + + ByteBuffer bb = ByteBuffer.wrap(mod_base, l.fileofs, l.filelen); + bb.order(ByteOrder.LITTLE_ENDIAN); + + for ( i=0 ; i<count ; i++) + { + bits = 0; + in = new qfiles.dplane_t(bb); + out[i] = new cplane_t(); + for (j=0 ; j<3 ; j++) + { + out[i].normal[j] = in.normal[j]; + if (out[i].normal[j] < 0) + bits |= (1<<j); + } + + out[i].dist = in.dist; + out[i].type = (byte)in.type; + out[i].signbits = (byte)bits; + } + } + + /* + ================= + Mod_LoadBrushModel + ================= + */ + void Mod_LoadBrushModel(model_t mod, ByteBuffer buffer) + { + int i; + qfiles.dheader_t header; + mmodel_t bm; + + loadmodel.type = mod_brush; + if (loadmodel != mod_known[0]) + ri.Sys_Error(Defines.ERR_DROP, "Loaded a brush model after the world"); + + header = new qfiles.dheader_t(buffer); + + i = header.version; + if (i != Defines.BSPVERSION) + ri.Sys_Error (Defines.ERR_DROP, "Mod_LoadBrushModel: " + mod.name + " has wrong version number (" + i + " should be " + Defines.BSPVERSION + ")"); + + mod_base = fileBuffer; //(byte *)header; + + // load into heap + Mod_LoadVertexes(header.lumps[Defines.LUMP_VERTEXES]); // ok + Mod_LoadEdges(header.lumps[Defines.LUMP_EDGES]); // ok + Mod_LoadSurfedges(header.lumps[Defines.LUMP_SURFEDGES]); // ok + Mod_LoadLighting(header.lumps[Defines.LUMP_LIGHTING]); // ok + Mod_LoadPlanes(header.lumps[Defines.LUMP_PLANES]); // ok + Mod_LoadTexinfo(header.lumps[Defines.LUMP_TEXINFO]); // ok + Mod_LoadFaces(header.lumps[Defines.LUMP_FACES]); // ok + Mod_LoadMarksurfaces(header.lumps[Defines.LUMP_LEAFFACES]); + Mod_LoadVisibility(header.lumps[Defines.LUMP_VISIBILITY]); // ok + Mod_LoadLeafs(header.lumps[Defines.LUMP_LEAFS]); // ok + Mod_LoadNodes(header.lumps[Defines.LUMP_NODES]); // ok + Mod_LoadSubmodels(header.lumps[Defines.LUMP_MODELS]); + mod.numframes = 2; // regular and alternate animation + + // + // set up the submodels + // + model_t starmod; + + for (i=0 ; i<mod.numsubmodels ; i++) + { + + bm = mod.submodels[i]; + starmod = mod_inline[i] = loadmodel.copy(); + + starmod.firstmodelsurface = bm.firstface; + starmod.nummodelsurfaces = bm.numfaces; + starmod.firstnode = bm.headnode; + if (starmod.firstnode >= loadmodel.numnodes) + ri.Sys_Error(Defines.ERR_DROP, "Inline model " + i + " has bad firstnode"); + + Math3D.VectorCopy(bm.maxs, starmod.maxs); + Math3D.VectorCopy(bm.mins, starmod.mins); + starmod.radius = bm.radius; + + if (i == 0) + loadmodel = starmod.copy(); + + starmod.numleafs = bm.visleafs; + } + } + + /* + ============================================================================== + + ALIAS MODELS + + ============================================================================== + */ + + /* + ================= + Mod_LoadAliasModel + ================= + */ + void Mod_LoadAliasModel (model_t mod, ByteBuffer buffer) + { + int i, j; + qfiles.dmdl_t pheader; + qfiles.dstvert_t[] poutst; + qfiles.dtriangle_t[] pouttri; + qfiles.daliasframe_t[] poutframe; + int[] poutcmd; + + pheader = new qfiles.dmdl_t(buffer); + + if (pheader.version != qfiles.ALIAS_VERSION) + ri.Sys_Error(Defines.ERR_DROP, "%s has wrong version number (%i should be %i)", + new Vargs(3).add(mod.name).add(pheader.version).add(qfiles.ALIAS_VERSION)); + + if (pheader.skinheight > MAX_LBM_HEIGHT) + ri.Sys_Error(Defines.ERR_DROP, "model "+ mod.name +" has a skin taller than " + MAX_LBM_HEIGHT); + + if (pheader.num_xyz <= 0) + ri.Sys_Error(Defines.ERR_DROP, "model " + mod.name + " has no vertices"); + + if (pheader.num_xyz > qfiles.MAX_VERTS) + ri.Sys_Error(Defines.ERR_DROP, "model " + mod.name +" has too many vertices"); + + if (pheader.num_st <= 0) + ri.Sys_Error(Defines.ERR_DROP, "model " + mod.name + " has no st vertices"); + + if (pheader.num_tris <= 0) + ri.Sys_Error(Defines.ERR_DROP, "model " + mod.name + " has no triangles"); + + if (pheader.num_frames <= 0) + ri.Sys_Error(Defines.ERR_DROP, "model " + mod.name + " has no frames"); + + // + // load base s and t vertices (not used in gl version) + // + poutst = new qfiles.dstvert_t[pheader.num_st]; + buffer.position(pheader.ofs_st); + for (i=0 ; i<pheader.num_st ; i++) + { + poutst[i] = new qfiles.dstvert_t(buffer); + } + + // + // load triangle lists + // + pouttri = new qfiles.dtriangle_t[pheader.num_tris]; + buffer.position(pheader.ofs_tris); + for (i=0 ; i<pheader.num_tris ; i++) + { + pouttri[i] = new qfiles.dtriangle_t(buffer); + } + + // + // load the frames + // + poutframe = new qfiles.daliasframe_t[pheader.num_frames]; + buffer.position(pheader.ofs_frames); + for (i=0 ; i<pheader.num_frames ; i++) + { + poutframe[i] = new qfiles.daliasframe_t(buffer); + // verts are all 8 bit, so no swapping needed + poutframe[i].verts = new qfiles.dtrivertx_t[pheader.num_xyz]; + for (int k=0; k < pheader.num_xyz; k++) { + poutframe[i].verts[k] = new qfiles.dtrivertx_t(buffer); + } + } + + mod.type = mod_alias; + + // + // load the glcmds + // + poutcmd = new int[pheader.num_glcmds]; + buffer.position(pheader.ofs_glcmds); + for (i=0 ; i<pheader.num_glcmds ; i++) + poutcmd[i] = buffer.getInt(); // LittleLong (pincmd[i]); + + // register all skins + String[] skinNames = new String[pheader.num_skins]; + byte[] nameBuf = new byte[qfiles.MAX_SKINNAME]; + buffer.position(pheader.ofs_skins); + for (i=0 ; i<pheader.num_skins ; i++) + { + buffer.get(nameBuf); + skinNames[i] = new String(nameBuf).trim(); + mod.skins[i] = GL_FindImage(skinNames[i], it_skin); + } + + // set the model arrays + pheader.skinNames = skinNames; // skin names + pheader.stVerts = poutst; // textur koordinaten + pheader.triAngles = pouttri; // dreiecke + pheader.glCmds = poutcmd; // STRIP or FAN + pheader.aliasFrames = poutframe; // frames mit vertex array + + mod.extradata = pheader; + + mod.mins[0] = -32; + mod.mins[1] = -32; + mod.mins[2] = -32; + mod.maxs[0] = 32; + mod.maxs[1] = 32; + mod.maxs[2] = 32; + + precompileGLCmds(pheader); + } + + /* + ============================================================================== + + SPRITE MODELS + + ============================================================================== + */ + + /* + ================= + Mod_LoadSpriteModel + ================= + */ + void Mod_LoadSpriteModel(model_t mod, ByteBuffer buffer) + { + qfiles.dsprite_t sprout = new qfiles.dsprite_t(buffer); + + if (sprout.version != qfiles.SPRITE_VERSION) + ri.Sys_Error(Defines.ERR_DROP, "%s has wrong version number (%i should be %i)", + new Vargs(3).add(mod.name).add(sprout.version).add(qfiles.SPRITE_VERSION)); + + if (sprout.numframes > qfiles.MAX_MD2SKINS) + ri.Sys_Error(Defines.ERR_DROP, "%s has too many frames (%i > %i)", + new Vargs(3).add(mod.name).add(sprout.numframes).add(qfiles.MAX_MD2SKINS)); + + for (int i=0 ; i<sprout.numframes ; i++) + { + mod.skins[i] = GL_FindImage(sprout.frames[i].name, it_sprite); + } + + mod.type = mod_sprite; + mod.extradata = sprout; + } + +// ============================================================================= + + /* + @@@@@@@@@@@@@@@@@@@@@ + R_BeginRegistration + + Specifies the model that will be used as the world + @@@@@@@@@@@@@@@@@@@@@ + */ + protected void R_BeginRegistration(String model) + { + resetModelArrays(); + resetPolygonArrays(); + + cvar_t flushmap; + + registration_sequence++; + r_oldviewcluster = -1; // force markleafs + + String fullname = "maps/" + model + ".bsp"; + + // explicitly free the old map if different + // this guarantees that mod_known[0] is the world map + flushmap = ri.Cvar_Get("flushmap", "0", 0); + if ( !mod_known[0].name.equals(fullname) || flushmap.value != 0.0f) + Mod_Free(mod_known[0]); + r_worldmodel = Mod_ForName(fullname, true); + + r_viewcluster = -1; + } + + + /* + @@@@@@@@@@@@@@@@@@@@@ + R_RegisterModel + + @@@@@@@@@@@@@@@@@@@@@ + */ + protected model_t R_RegisterModel(String name) + { + model_t mod = null; + int i; + qfiles.dsprite_t sprout; + qfiles.dmdl_t pheader; + + mod = Mod_ForName(name, false); + if (mod != null) + { + mod.registration_sequence = registration_sequence; + + // register any images used by the models + if (mod.type == mod_sprite) + { + sprout = (qfiles.dsprite_t)mod.extradata; + for (i=0 ; i<sprout.numframes ; i++) + mod.skins[i] = GL_FindImage(sprout.frames[i].name, it_sprite); + } + else if (mod.type == mod_alias) + { + pheader = (qfiles.dmdl_t)mod.extradata; + for (i=0 ; i<pheader.num_skins ; i++) + mod.skins[i] = GL_FindImage(pheader.skinNames[i], it_skin); + // PGM + mod.numframes = pheader.num_frames; + // PGM + } + else if (mod.type == mod_brush) + { + for (i=0 ; i<mod.numtexinfo ; i++) + mod.texinfo[i].image.registration_sequence = registration_sequence; + } + } + return mod; + } + + + /* + @@@@@@@@@@@@@@@@@@@@@ + R_EndRegistration + + @@@@@@@@@@@@@@@@@@@@@ + */ + protected void R_EndRegistration() + { + model_t mod; + + for (int i=0; i<mod_numknown ; i++) + { + mod = mod_known[i]; + if (mod.name == "") + continue; + if (mod.registration_sequence != registration_sequence) + { // don't need this model + Mod_Free(mod); + } else { + // precompile AliasModels + if (mod.type == mod_alias) + precompileGLCmds((qfiles.dmdl_t)mod.extradata); + } + } + GL_FreeUnusedImages(); + + //modelMemoryUsage(); + } + + +// ============================================================================= + + + /* + ================ + Mod_Free + ================ + */ + void Mod_Free (model_t mod) + { + mod.clear(); + } + + /* + ================ + Mod_FreeAll + ================ + */ + void Mod_FreeAll() + { + for (int i=0 ; i<mod_numknown ; i++) + { + if (mod_known[i].extradata != null) + Mod_Free(mod_known[i]); + } + } + + /* + * new functions for vertex array handling + */ + static final int MODEL_BUFFER_SIZE = 50000; + static FloatBuffer globalModelTextureCoordBuf = BufferUtils.newFloatBuffer(MODEL_BUFFER_SIZE * 2); + static IntBuffer globalModelVertexIndexBuf = BufferUtils.newIntBuffer(MODEL_BUFFER_SIZE); + + void precompileGLCmds(qfiles.dmdl_t model) { + model.textureCoordBuf = globalModelTextureCoordBuf.slice(); + model.vertexIndexBuf = globalModelVertexIndexBuf.slice(); + Vector tmp = new Vector(); + + int count = 0; + int[] order = model.glCmds; + int orderIndex = 0; + while (true) + { + // get the vertex count and primitive type + count = order[orderIndex++]; + if (count == 0) + break; // done + + tmp.addElement(new Integer(count)); + + if (count < 0) + { + count = -count; + //gl.glBegin (GL.GL_TRIANGLE_FAN); + } + else + { + //gl.glBegin (GL.GL_TRIANGLE_STRIP); + } + + do { + // texture coordinates come from the draw list + globalModelTextureCoordBuf.put(Float.intBitsToFloat(order[orderIndex + 0])); + globalModelTextureCoordBuf.put(Float.intBitsToFloat(order[orderIndex + 1])); + globalModelVertexIndexBuf.put(order[orderIndex + 2]); + + orderIndex += 3; + } while (--count != 0); + } + + int size = tmp.size(); + + model.counts = new int[size]; + model.indexElements = new IntBuffer[size]; + + count = 0; + int pos = 0; + for (int i = 0; i < model.counts.length; i++) { + count = ((Integer)tmp.get(i)).intValue(); + model.counts[i] = count; + + count = (count < 0) ? -count : count; + model.vertexIndexBuf.position(pos); + model.indexElements[i] = model.vertexIndexBuf.slice(); + pos += count; + } + } + + static void resetModelArrays() { + globalModelTextureCoordBuf.rewind(); + globalModelVertexIndexBuf.rewind(); + } + + static void modelMemoryUsage() { + System.out.println("AliasModels: globalVertexBuffer size " + globalModelVertexIndexBuf.position()); + } +} diff --git a/src/jake2/render/fastjogl/Surf.java b/src/jake2/render/fastjogl/Surf.java new file mode 100644 index 0000000..c7e7bc0 --- /dev/null +++ b/src/jake2/render/fastjogl/Surf.java @@ -0,0 +1,1464 @@ +/* + * Surf.java + * Copyright (C) 2003 + * + * $Id: Surf.java,v 1.1 2004-07-09 06:50:48 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.fastjogl; + +import jake2.Defines; +import jake2.client.*; +import jake2.game.cplane_t; +import jake2.render.*; +import jake2.util.Lib; +import jake2.util.Math3D; + +import java.nio.*; +import java.util.Arrays; + +import net.java.games.jogl.GL; +import net.java.games.jogl.util.BufferUtils; + +/** + * Surf + * + * @author cwei + */ +public abstract class Surf extends Draw { + + // GL_RSURF.C: surface-related refresh code + float[] modelorg = {0, 0, 0}; // relative to viewpoint + + msurface_t r_alpha_surfaces; + + static final int DYNAMIC_LIGHT_WIDTH = 128; + static final int DYNAMIC_LIGHT_HEIGHT = 128; + + static final int LIGHTMAP_BYTES = 4; + + static final int BLOCK_WIDTH = 128; + static final int BLOCK_HEIGHT = 128; + + static final int MAX_LIGHTMAPS = 128; + + int c_visible_lightmaps; + int c_visible_textures; + + static final int GL_LIGHTMAP_FORMAT = GL.GL_RGBA; + + static class gllightmapstate_t + { + int internal_format; + int current_lightmap_texture; + + msurface_t[] lightmap_surfaces = new msurface_t[MAX_LIGHTMAPS]; + int[] allocated = new int[BLOCK_WIDTH]; + + // the lightmap texture data needs to be kept in + // main memory so texsubimage can update properly + //byte[] lightmap_buffer = new byte[4 * BLOCK_WIDTH * BLOCK_HEIGHT]; + IntBuffer lightmap_buffer = Lib.newIntBuffer(BLOCK_WIDTH * BLOCK_HEIGHT, ByteOrder.LITTLE_ENDIAN); + + public gllightmapstate_t() { + for (int i = 0; i < MAX_LIGHTMAPS; i++) + lightmap_surfaces[i] = new msurface_t(); + } + + public void clearLightmapSurfaces() { + for (int i = 0; i < MAX_LIGHTMAPS; i++) + // TODO lightmap_surfaces[i].clear(); + lightmap_surfaces[i] = new msurface_t(); + } + + } + + gllightmapstate_t gl_lms = new gllightmapstate_t(); + + // Model.java + abstract byte[] Mod_ClusterPVS(int cluster, model_t model); + // Warp.java + abstract void R_DrawSkyBox(); + abstract void R_AddSkySurface(msurface_t surface); + abstract void R_ClearSkyBox(); + abstract void EmitWaterPolys(msurface_t fa); + // Light.java + abstract void R_MarkLights (dlight_t light, int bit, mnode_t node); + abstract void R_SetCacheState( msurface_t surf ); + abstract void R_BuildLightMap(msurface_t surf, IntBuffer dest, int stride); + + /* + ============================================================= + + BRUSH MODELS + + ============================================================= + */ + + /* + =============== + R_TextureAnimation + + Returns the proper texture for a given time and base texture + =============== + */ + image_t R_TextureAnimation(mtexinfo_t tex) + { + int c; + + if (tex.next == null) + return tex.image; + + c = currententity.frame % tex.numframes; + while (c != 0) + { + tex = tex.next; + c--; + } + + return tex.image; + } + + /* + ================ + DrawGLPoly + ================ + */ + void DrawGLPoly(glpoly_t p) + { + gl.glDrawArrays(GL.GL_POLYGON, p.pos, p.numverts); + } + + // ============ + // PGM + /* + ================ + DrawGLFlowingPoly -- version of DrawGLPoly that handles scrolling texture + ================ + */ + void DrawGLFlowingPoly(glpoly_t p) + { + int i; + float scroll; + + scroll = -64 * ( (r_newrefdef.time / 40.0f) - (int)(r_newrefdef.time / 40.0f) ); + if(scroll == 0.0f) + scroll = -64.0f; + + FloatBuffer texCoord = globalPolygonInterleavedBuf; + float[][] v = p.verts; + int index = p.pos * POLYGON_STRIDE; + for (i=0 ; i<p.numverts ; i++) { + texCoord.put(index, v[i][3] + scroll); + index += POLYGON_STRIDE; + } + gl.glDrawArrays(GL.GL_POLYGON, p.pos, p.numverts); + } + // PGM + // ============ + + /* + ** R_DrawTriangleOutlines + */ + void R_DrawTriangleOutlines() + { + int i, j; + glpoly_t p; + + if (gl_showtris.value == 0) + return; + + gl.glDisable (GL.GL_TEXTURE_2D); + gl.glDisable (GL.GL_DEPTH_TEST); + gl.glColor4f (1,1,1,1); + + for (i=0 ; i<MAX_LIGHTMAPS ; i++) + { + msurface_t surf; + + for ( surf = gl_lms.lightmap_surfaces[i]; surf != null; surf = surf.lightmapchain ) + { + p = surf.polys; + for ( ; p != null ; p=p.chain) + { + for (j=2 ; j<p.numverts ; j++ ) + { + gl.glBegin (GL.GL_LINE_STRIP); + gl.glVertex3fv (p.verts[0]); + gl.glVertex3fv (p.verts[j-1]); + gl.glVertex3fv (p.verts[j]); + gl.glVertex3fv (p.verts[0]); + gl.glEnd (); + } + } + } + } + + gl.glEnable (GL.GL_DEPTH_TEST); + gl.glEnable (GL.GL_TEXTURE_2D); + } + + private IntBuffer temp2 = Lib.newIntBuffer(34 * 34, ByteOrder.LITTLE_ENDIAN); + + /* + ================ + R_RenderBrushPoly + ================ + */ + void R_RenderBrushPoly(msurface_t fa) + { + int maps; + image_t image; + boolean is_dynamic = false; + + c_brush_polys++; + + image = R_TextureAnimation(fa.texinfo); + + if ((fa.flags & Defines.SURF_DRAWTURB) != 0) + { + GL_Bind( image.texnum ); + + // warp texture, no lightmaps + GL_TexEnv( GL.GL_MODULATE ); + gl.glColor4f( gl_state.inverse_intensity, + gl_state.inverse_intensity, + gl_state.inverse_intensity, + 1.0F ); + EmitWaterPolys (fa); + GL_TexEnv( GL.GL_REPLACE ); + + return; + } + else + { + GL_Bind( image.texnum ); + GL_TexEnv( GL.GL_REPLACE ); + } + + // ====== + // PGM + if((fa.texinfo.flags & Defines.SURF_FLOWING) != 0) + DrawGLFlowingPoly(fa.polys); + else + DrawGLPoly (fa.polys); + // PGM + // ====== + + // ersetzt goto + boolean gotoDynamic = false; + /* + ** check for lightmap modification + */ + for ( maps = 0; maps < Defines.MAXLIGHTMAPS && fa.styles[maps] != (byte)255; maps++ ) + { + if ( r_newrefdef.lightstyles[fa.styles[maps] & 0xFF].white != fa.cached_light[maps] ) { + gotoDynamic = true; + break; + } + } + + // this is a hack from cwei + if (maps == 4) maps--; + + // dynamic this frame or dynamic previously + if ( gotoDynamic || ( fa.dlightframe == r_framecount ) ) + { + // label dynamic: + if ( gl_dynamic.value != 0 ) + { + if (( fa.texinfo.flags & (Defines.SURF_SKY | Defines.SURF_TRANS33 | Defines.SURF_TRANS66 | Defines.SURF_WARP ) ) == 0) + { + is_dynamic = true; + } + } + } + + if ( is_dynamic ) + { + if ( ( (fa.styles[maps] & 0xFF) >= 32 || fa.styles[maps] == 0 ) && ( fa.dlightframe != r_framecount ) ) + { + // ist ersetzt durch temp2: unsigned temp[34*34]; + int smax, tmax; + + smax = (fa.extents[0]>>4)+1; + tmax = (fa.extents[1]>>4)+1; + + R_BuildLightMap( fa, temp2, smax); + R_SetCacheState( fa ); + + GL_Bind( gl_state.lightmap_textures + fa.lightmaptexturenum ); + + gl.glTexSubImage2D( GL.GL_TEXTURE_2D, 0, + fa.light_s, fa.light_t, + smax, tmax, + GL_LIGHTMAP_FORMAT, + GL.GL_UNSIGNED_BYTE, temp2 ); + + fa.lightmapchain = gl_lms.lightmap_surfaces[fa.lightmaptexturenum]; + gl_lms.lightmap_surfaces[fa.lightmaptexturenum] = fa; + } + else + { + fa.lightmapchain = gl_lms.lightmap_surfaces[0]; + gl_lms.lightmap_surfaces[0] = fa; + } + } + else + { + fa.lightmapchain = gl_lms.lightmap_surfaces[fa.lightmaptexturenum]; + gl_lms.lightmap_surfaces[fa.lightmaptexturenum] = fa; + } + } + + + /* + ================ + R_DrawAlphaSurfaces + + Draw water surfaces and windows. + The BSP tree is waled front to back, so unwinding the chain + of alpha_surfaces will draw back to front, giving proper ordering. + ================ + */ + void R_DrawAlphaSurfaces() + { + msurface_t s; + float intens; + + // + // go back to the world matrix + // + gl.glLoadMatrixf(r_world_matrix); + + gl.glEnable (GL.GL_BLEND); + GL_TexEnv(GL.GL_MODULATE ); + + + // the textures are prescaled up for a better lighting range, + // so scale it back down + intens = gl_state.inverse_intensity; + + gl.glInterleavedArrays(GL.GL_T2F_V3F, POLYGON_BYTE_STRIDE, globalPolygonInterleavedBuf); + + for (s=r_alpha_surfaces ; s != null ; s=s.texturechain) + { + GL_Bind(s.texinfo.image.texnum); + c_brush_polys++; + if ((s.texinfo.flags & Defines.SURF_TRANS33) != 0) + gl.glColor4f (intens, intens, intens, 0.33f); + else if ((s.texinfo.flags & Defines.SURF_TRANS66) != 0) + gl.glColor4f (intens, intens, intens, 0.66f); + else + gl.glColor4f (intens,intens,intens,1); + if ((s.flags & Defines.SURF_DRAWTURB) != 0) + EmitWaterPolys(s); + else if((s.texinfo.flags & Defines.SURF_FLOWING) != 0) // PGM 9/16/98 + DrawGLFlowingPoly(s.polys); // PGM + else + DrawGLPoly(s.polys); + } + + GL_TexEnv( GL.GL_REPLACE ); + gl.glColor4f (1,1,1,1); + gl.glDisable (GL.GL_BLEND); + + r_alpha_surfaces = null; + } + + /* + ================ + DrawTextureChains + ================ + */ + void DrawTextureChains() + { + int i; + msurface_t s; + image_t image; + + c_visible_textures = 0; + + for (i = 0; i < numgltextures ; i++) + { + image = gltextures[i]; + + if (image.registration_sequence == 0) + continue; + if (image.texturechain == null) + continue; + c_visible_textures++; + + for ( s = image.texturechain; s != null ; s=s.texturechain) + { + if ( ( s.flags & Defines.SURF_DRAWTURB) == 0 ) + R_RenderBrushPoly(s); + } + } + + GL_EnableMultitexture( false ); + for (i = 0; i < numgltextures ; i++) + { + image = gltextures[i]; + + if (image.registration_sequence == 0) + continue; + s = image.texturechain; + if (s == null) + continue; + + for ( ; s != null ; s=s.texturechain) + { + if ( (s.flags & Defines.SURF_DRAWTURB) != 0 ) + R_RenderBrushPoly(s); + } + + image.texturechain = null; + } + + GL_TexEnv( GL.GL_REPLACE ); + } + + // direct buffer + private IntBuffer temp = Lib.newIntBuffer(128 * 128, ByteOrder.LITTLE_ENDIAN); + + void GL_RenderLightmappedPoly( msurface_t surf ) + { + int i, nv = surf.polys.numverts; + int map = 0; + int index; + float[][] v; + FloatBuffer texCoord = globalPolygonInterleavedBuf; + image_t image = R_TextureAnimation( surf.texinfo ); + boolean is_dynamic = false; + int lmtex = surf.lightmaptexturenum; + glpoly_t p; + + // ersetzt goto + boolean gotoDynamic = false; + + for ( map = 0; map < Defines.MAXLIGHTMAPS && (surf.styles[map] != (byte)255); map++ ) + { + if ( r_newrefdef.lightstyles[surf.styles[map] & 0xFF].white != surf.cached_light[map] ) { + gotoDynamic = true; + break; + } + } + + // this is a hack from cwei + if (map == 4) map--; + + // dynamic this frame or dynamic previously + if ( gotoDynamic || ( surf.dlightframe == r_framecount ) ) + { + // label dynamic: + if ( gl_dynamic.value != 0 ) + { + if ( (surf.texinfo.flags & (Defines.SURF_SKY | Defines.SURF_TRANS33 | Defines.SURF_TRANS66 | Defines.SURF_WARP )) == 0 ) + { + is_dynamic = true; + } + } + } + + if ( is_dynamic ) + { + // ist raus gezogen worden int[] temp = new int[128*128]; + int smax, tmax; + + if ( ( (surf.styles[map] & 0xFF) >= 32 || surf.styles[map] == 0 ) && ( surf.dlightframe != r_framecount ) ) + { + smax = (surf.extents[0]>>4)+1; + tmax = (surf.extents[1]>>4)+1; + + R_BuildLightMap( surf, temp, smax); + R_SetCacheState( surf ); + + GL_MBind( GL_TEXTURE1, gl_state.lightmap_textures + surf.lightmaptexturenum ); + + lmtex = surf.lightmaptexturenum; + + gl.glTexSubImage2D( GL.GL_TEXTURE_2D, 0, + surf.light_s, surf.light_t, + smax, tmax, + GL_LIGHTMAP_FORMAT, + GL.GL_UNSIGNED_BYTE, temp ); + + } + else + { + smax = (surf.extents[0]>>4)+1; + tmax = (surf.extents[1]>>4)+1; + + R_BuildLightMap( surf, temp, smax); + + GL_MBind( GL_TEXTURE1, gl_state.lightmap_textures + 0 ); + + lmtex = 0; + + gl.glTexSubImage2D( GL.GL_TEXTURE_2D, 0, + surf.light_s, surf.light_t, + smax, tmax, + GL_LIGHTMAP_FORMAT, + GL.GL_UNSIGNED_BYTE, temp ); + + } + + c_brush_polys++; + + GL_MBind( GL_TEXTURE0, image.texnum ); + GL_MBind( GL_TEXTURE1, gl_state.lightmap_textures + lmtex ); + + // ========== + // PGM + if ((surf.texinfo.flags & Defines.SURF_FLOWING) != 0) + { + float scroll; + + scroll = -64 * ( (r_newrefdef.time / 40.0f) - (int)(r_newrefdef.time / 40.0f) ); + if(scroll == 0.0f) + scroll = -64.0f; + + for ( p = surf.polys; p != null; p = p.chain ) + { + v = p.verts; + index = p.pos * POLYGON_STRIDE; + for (i=0 ; i<p.numverts ; i++) { + texCoord.put(index, v[i][3] + scroll); + index += POLYGON_STRIDE; + } + gl.glDrawArrays(GL.GL_POLYGON, p.pos, p.numverts); + } + } + else + { + for ( p = surf.polys; p != null; p = p.chain ) + { + gl.glDrawArrays(GL.GL_POLYGON, p.pos, p.numverts); + } + } + // PGM + // ========== + } + else + { + c_brush_polys++; + + GL_MBind( GL_TEXTURE0, image.texnum ); + GL_MBind( GL_TEXTURE1, gl_state.lightmap_textures + lmtex); + + // ========== + // PGM + if ((surf.texinfo.flags & Defines.SURF_FLOWING) != 0) + { + float scroll; + + scroll = -64 * ( (r_newrefdef.time / 40.0f) - (int)(r_newrefdef.time / 40.0f) ); + if(scroll == 0.0) + scroll = -64.0f; + + for ( p = surf.polys; p != null; p = p.chain ) + { + v = p.verts; + index = p.pos * POLYGON_STRIDE; + for (i=0 ; i<p.numverts ; i++) { + texCoord.put(index, v[i][3] + scroll); + index += POLYGON_STRIDE; + } + gl.glDrawArrays(GL.GL_POLYGON, p.pos, p.numverts); + } + } + else + { + // PGM + // ========== + for ( p = surf.polys; p != null; p = p.chain ) + { + gl.glDrawArrays(GL.GL_POLYGON, p.pos, p.numverts); + } + + // ========== + // PGM + } + // PGM + // ========== + } + } + + /* + ================= + R_DrawInlineBModel + ================= + */ + void R_DrawInlineBModel() + { + int i, k; + cplane_t pplane; + float dot; + msurface_t psurf; + dlight_t lt; + + // calculate dynamic lighting for bmodel + if ( gl_flashblend.value == 0 ) + { + for (k=0 ; k<r_newrefdef.num_dlights ; k++) + { + lt = r_newrefdef.dlights[k]; + R_MarkLights(lt, 1<<k, currentmodel.nodes[currentmodel.firstnode]); + } + } + + // psurf = ¤tmodel->surfaces[currentmodel->firstmodelsurface]; + int psurfp = currentmodel.firstmodelsurface; + msurface_t[] surfaces; + surfaces = currentmodel.surfaces; + //psurf = surfaces[psurfp]; + + if ( (currententity.flags & Defines.RF_TRANSLUCENT) != 0 ) + { + gl.glEnable (GL.GL_BLEND); + gl.glColor4f (1,1,1,0.25f); + GL_TexEnv( GL.GL_MODULATE ); + } + + // + // draw texture + // + for (i=0 ; i<currentmodel.nummodelsurfaces ; i++) + { + psurf = surfaces[psurfp++]; + // find which side of the node we are on + pplane = psurf.plane; + + dot = Math3D.DotProduct(modelorg, pplane.normal) - pplane.dist; + + // draw the polygon + if (((psurf.flags & Defines.SURF_PLANEBACK) != 0 && (dot < -BACKFACE_EPSILON)) || + ((psurf.flags & Defines.SURF_PLANEBACK) == 0 && (dot > BACKFACE_EPSILON))) + { + if ((psurf.texinfo.flags & (Defines.SURF_TRANS33 | Defines.SURF_TRANS66)) != 0 ) + { // add to the translucent chain + psurf.texturechain = r_alpha_surfaces; + r_alpha_surfaces = psurf; + } + else if ( (psurf.flags & Defines.SURF_DRAWTURB) == 0 ) + { + GL_RenderLightmappedPoly( psurf ); + } + else + { + GL_EnableMultitexture( false ); + R_RenderBrushPoly( psurf ); + GL_EnableMultitexture( true ); + } + } + } + + if ( (currententity.flags & Defines.RF_TRANSLUCENT) != 0 ) { + gl.glDisable (GL.GL_BLEND); + gl.glColor4f (1,1,1,1); + GL_TexEnv( GL.GL_REPLACE ); + } + } + + /* + ================= + R_DrawBrushModel + ================= + */ + void R_DrawBrushModel(entity_t e) + { + float[] mins = {0, 0, 0}; + float[] maxs = {0, 0, 0}; + int i; + boolean rotated; + + if (currentmodel.nummodelsurfaces == 0) + return; + + currententity = e; + gl_state.currenttextures[0] = gl_state.currenttextures[1] = -1; + + if (e.angles[0] != 0 || e.angles[1] != 0 || e.angles[2] != 0) + { + rotated = true; + for (i=0 ; i<3 ; i++) + { + mins[i] = e.origin[i] - currentmodel.radius; + maxs[i] = e.origin[i] + currentmodel.radius; + } + } + else + { + rotated = false; + Math3D.VectorAdd(e.origin, currentmodel.mins, mins); + Math3D.VectorAdd(e.origin, currentmodel.maxs, maxs); + } + + if (R_CullBox(mins, maxs)) return; + + gl.glColor3f (1,1,1); + + // memset (gl_lms.lightmap_surfaces, 0, sizeof(gl_lms.lightmap_surfaces)); + + // TODO wird beim multitexturing nicht gebraucht + //gl_lms.clearLightmapSurfaces(); + + Math3D.VectorSubtract (r_newrefdef.vieworg, e.origin, modelorg); + if (rotated) + { + float[] temp = {0, 0, 0}; + float[] forward = {0, 0, 0}; + float[] right = {0, 0, 0}; + float[] up = {0, 0, 0}; + + Math3D.VectorCopy (modelorg, temp); + Math3D.AngleVectors (e.angles, forward, right, up); + modelorg[0] = Math3D.DotProduct (temp, forward); + modelorg[1] = -Math3D.DotProduct (temp, right); + modelorg[2] = Math3D.DotProduct (temp, up); + } + + gl.glPushMatrix(); + + e.angles[0] = -e.angles[0]; // stupid quake bug + e.angles[2] = -e.angles[2]; // stupid quake bug + R_RotateForEntity(e); + e.angles[0] = -e.angles[0]; // stupid quake bug + e.angles[2] = -e.angles[2]; // stupid quake bug + + GL_EnableMultitexture( true ); + GL_SelectTexture(GL_TEXTURE0); + GL_TexEnv( GL.GL_REPLACE ); + gl.glInterleavedArrays(GL.GL_T2F_V3F, POLYGON_BYTE_STRIDE, globalPolygonInterleavedBuf); + GL_SelectTexture(GL_TEXTURE1); + GL_TexEnv( GL.GL_MODULATE ); + gl.glTexCoordPointer(2, GL.GL_FLOAT, POLYGON_BYTE_STRIDE, globalPolygonTexCoord1Buf); + gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); + + R_DrawInlineBModel(); + + gl.glClientActiveTextureARB(GL_TEXTURE1); + gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY); + + GL_EnableMultitexture( false ); + + gl.glPopMatrix(); + } + + /* + ============================================================= + + WORLD MODEL + + ============================================================= + */ + + /* + ================ + R_RecursiveWorldNode + ================ + */ + void R_RecursiveWorldNode (mnode_t node) + { + int c, side, sidebit; + cplane_t plane; + msurface_t surf; + msurface_t mark; + mleaf_t pleaf; + float dot = 0; + image_t image; + + if (node.contents == Defines.CONTENTS_SOLID) + return; // solid + + if (node.visframe != r_visframecount) + return; + + if (R_CullBox(node.mins, node.maxs)) + return; + + // if a leaf node, draw stuff + if (node.contents != -1) + { + pleaf = (mleaf_t)node; + + // check for door connected areas + if (r_newrefdef.areabits != null) + { + if ( ((r_newrefdef.areabits[pleaf.area >> 3] & 0xFF) & (1 << (pleaf.area & 7)) ) == 0 ) + return; // not visible + } + + int markp = 0; + + mark = pleaf.getMarkSurface(markp); // first marked surface + c = pleaf.nummarksurfaces; + + if (c != 0) + { + do + { + mark.visframe = r_framecount; + mark = pleaf.getMarkSurface(++markp); // next surface + } while (--c != 0); + } + + return; + } + + // node is just a decision point, so go down the apropriate sides + + // find which side of the node we are on + plane = node.plane; + + switch (plane.type) + { + case Defines.PLANE_X: + dot = modelorg[0] - plane.dist; + break; + case Defines.PLANE_Y: + dot = modelorg[1] - plane.dist; + break; + case Defines.PLANE_Z: + dot = modelorg[2] - plane.dist; + break; + default: + dot = Math3D.DotProduct(modelorg, plane.normal) - plane.dist; + break; + } + + if (dot >= 0.0f) + { + side = 0; + sidebit = 0; + } + else + { + side = 1; + sidebit = Defines.SURF_PLANEBACK; + } + + // recurse down the children, front side first + R_RecursiveWorldNode(node.children[side]); + + // draw stuff + //for ( c = node.numsurfaces, surf = r_worldmodel.surfaces[node.firstsurface]; c != 0 ; c--, surf++) + for ( c = 0; c < node.numsurfaces; c++) + { + surf = r_worldmodel.surfaces[node.firstsurface + c]; + if (surf.visframe != r_framecount) + continue; + + if ( (surf.flags & Defines.SURF_PLANEBACK) != sidebit ) + continue; // wrong side + + if ((surf.texinfo.flags & Defines.SURF_SKY) != 0) + { // just adds to visible sky bounds + R_AddSkySurface(surf); + } + else if ((surf.texinfo.flags & (Defines.SURF_TRANS33 | Defines.SURF_TRANS66)) != 0) + { // add to the translucent chain + surf.texturechain = r_alpha_surfaces; + r_alpha_surfaces = surf; + } + else + { + if ( ( surf.flags & Defines.SURF_DRAWTURB) == 0 ) + { + GL_RenderLightmappedPoly( surf ); + } + else + { + // the polygon is visible, so add it to the texture + // sorted chain + // FIXME: this is a hack for animation + image = R_TextureAnimation(surf.texinfo); + surf.texturechain = image.texturechain; + image.texturechain = surf; + } + } + } + + // recurse down the back side + R_RecursiveWorldNode(node.children[1 - side]); + } + + + /* + ============= + R_DrawWorld + ============= + */ + void R_DrawWorld() + { + entity_t ent = new entity_t(); + + if (r_drawworld.value == 0) + return; + + if ( (r_newrefdef.rdflags & Defines.RDF_NOWORLDMODEL) != 0 ) + return; + + currentmodel = r_worldmodel; + + Math3D.VectorCopy(r_newrefdef.vieworg, modelorg); + + // auto cycle the world frame for texture animation + // memset (&ent, 0, sizeof(ent)); + ent.frame = (int)(r_newrefdef.time*2); + currententity = ent; + + gl_state.currenttextures[0] = gl_state.currenttextures[1] = -1; + + gl.glColor3f (1,1,1); + // memset (gl_lms.lightmap_surfaces, 0, sizeof(gl_lms.lightmap_surfaces)); + // TODO wird bei multitexture nicht gebraucht + //gl_lms.clearLightmapSurfaces(); + + R_ClearSkyBox(); + + GL_EnableMultitexture( true ); + + GL_SelectTexture( GL_TEXTURE0); + GL_TexEnv( GL.GL_REPLACE ); + gl.glInterleavedArrays(GL.GL_T2F_V3F, POLYGON_BYTE_STRIDE, globalPolygonInterleavedBuf); + GL_SelectTexture( GL_TEXTURE1); + gl.glTexCoordPointer(2, GL.GL_FLOAT, POLYGON_BYTE_STRIDE, globalPolygonTexCoord1Buf); + gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); + + if ( gl_lightmap.value != 0) + GL_TexEnv( GL.GL_REPLACE ); + else + GL_TexEnv( GL.GL_MODULATE ); + + R_RecursiveWorldNode(r_worldmodel.nodes[0]); // root node + + gl.glClientActiveTextureARB(GL_TEXTURE1); + gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY); + + GL_EnableMultitexture( false ); + + DrawTextureChains(); + R_DrawSkyBox(); + R_DrawTriangleOutlines(); + } + + byte[] fatvis = new byte[Defines.MAX_MAP_LEAFS / 8]; + + /* + =============== + R_MarkLeaves + + Mark the leaves and nodes that are in the PVS for the current + cluster + =============== + */ + void R_MarkLeaves() + { + byte[] vis; + //byte[] fatvis = new byte[Defines.MAX_MAP_LEAFS / 8]; + + Arrays.fill(fatvis, (byte)0); + + mnode_t node; + int i, c; + mleaf_t leaf; + int cluster; + + if (r_oldviewcluster == r_viewcluster && r_oldviewcluster2 == r_viewcluster2 && r_novis.value == 0 && r_viewcluster != -1) + return; + + // development aid to let you run around and see exactly where + // the pvs ends + if (gl_lockpvs.value != 0) + return; + + r_visframecount++; + r_oldviewcluster = r_viewcluster; + r_oldviewcluster2 = r_viewcluster2; + + if (r_novis.value != 0 || r_viewcluster == -1 || r_worldmodel.vis == null) + { + // mark everything + for (i=0 ; i<r_worldmodel.numleafs ; i++) + r_worldmodel.leafs[i].visframe = r_visframecount; + for (i=0 ; i<r_worldmodel.numnodes ; i++) + r_worldmodel.nodes[i].visframe = r_visframecount; + return; + } + + vis = Mod_ClusterPVS(r_viewcluster, r_worldmodel); + // may have to combine two clusters because of solid water boundaries + if (r_viewcluster2 != r_viewcluster) + { + // memcpy (fatvis, vis, (r_worldmodel.numleafs+7)/8); + System.arraycopy(vis, 0, fatvis, 0, (r_worldmodel.numleafs+7) / 8); + vis = Mod_ClusterPVS(r_viewcluster2, r_worldmodel); + c = (r_worldmodel.numleafs + 31) / 32; + int k = 0; + for (i=0 ; i<c ; i++) { + fatvis[k] |= vis[k++]; + fatvis[k] |= vis[k++]; + fatvis[k] |= vis[k++]; + fatvis[k] |= vis[k++]; + } + + vis = fatvis; + } + + for ( i=0; i < r_worldmodel.numleafs; i++) + { + leaf = r_worldmodel.leafs[i]; + cluster = leaf.cluster; + if (cluster == -1) + continue; + if (((vis[cluster>>3] & 0xFF) & (1 << (cluster & 7))) != 0) + { + node = (mnode_t)leaf; + do + { + if (node.visframe == r_visframecount) + break; + node.visframe = r_visframecount; + node = node.parent; + } while (node != null); + } + } + } + + + + /* + ============================================================================= + + LIGHTMAP ALLOCATION + + ============================================================================= + */ + + void LM_InitBlock() + { + Arrays.fill(gl_lms.allocated, 0); + } + + void LM_UploadBlock( boolean dynamic ) + { + int texture; + int height = 0; + + if ( dynamic ) + { + texture = 0; + } + else + { + texture = gl_lms.current_lightmap_texture; + } + + GL_Bind( gl_state.lightmap_textures + texture ); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + + if ( dynamic ) + { + int i; + + for ( i = 0; i < BLOCK_WIDTH; i++ ) + { + if ( gl_lms.allocated[i] > height ) + height = gl_lms.allocated[i]; + } + + gl.glTexSubImage2D( GL.GL_TEXTURE_2D, + 0, + 0, 0, + BLOCK_WIDTH, height, + GL_LIGHTMAP_FORMAT, + GL.GL_UNSIGNED_BYTE, + gl_lms.lightmap_buffer ); + } + else + { + gl.glTexImage2D( GL.GL_TEXTURE_2D, + 0, + gl_lms.internal_format, + BLOCK_WIDTH, BLOCK_HEIGHT, + 0, + GL_LIGHTMAP_FORMAT, + GL.GL_UNSIGNED_BYTE, + gl_lms.lightmap_buffer ); + if ( ++gl_lms.current_lightmap_texture == MAX_LIGHTMAPS ) + ri.Sys_Error( Defines.ERR_DROP, "LM_UploadBlock() - MAX_LIGHTMAPS exceeded\n" ); + + + //debugLightmap(gl_lms.lightmap_buffer, 128, 128, 4); + + } + } + + // returns a texture number and the position inside it + boolean LM_AllocBlock (int w, int h, pos_t pos) + { + int x = pos.x; + int y = pos.y; + int i, j; + int best, best2; + + best = BLOCK_HEIGHT; + + for (i=0 ; i<BLOCK_WIDTH-w ; i++) + { + best2 = 0; + + for (j=0 ; j<w ; j++) + { + if (gl_lms.allocated[i+j] >= best) + break; + if (gl_lms.allocated[i+j] > best2) + best2 = gl_lms.allocated[i+j]; + } + if (j == w) + { // this is a valid spot + pos.x = x = i; + pos.y = y = best = best2; + } + } + + if (best + h > BLOCK_HEIGHT) + return false; + + for (i=0 ; i<w ; i++) + gl_lms.allocated[x + i] = best + h; + + return true; + } + + /* + ================ + GL_BuildPolygonFromSurface + ================ + */ + void GL_BuildPolygonFromSurface(msurface_t fa) + { + int i, lindex, lnumverts; + medge_t[] pedges; + medge_t r_pedge; + int vertpage; + float[] vec; + float s, t; + glpoly_t poly; + float[] total = {0, 0, 0}; + + // reconstruct the polygon + pedges = currentmodel.edges; + lnumverts = fa.numedges; + vertpage = 0; + + Math3D.VectorClear(total); + // + // draw texture + // + // poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float)); + poly = new glpoly_t(lnumverts); + + poly.next = fa.polys; + poly.flags = fa.flags; + fa.polys = poly; + poly.numverts = lnumverts; + + for (i=0 ; i<lnumverts ; i++) + { + lindex = currentmodel.surfedges[fa.firstedge + i]; + + if (lindex > 0) + { + r_pedge = pedges[lindex]; + vec = currentmodel.vertexes[r_pedge.v[0]].position; + } + else + { + r_pedge = pedges[-lindex]; + vec = currentmodel.vertexes[r_pedge.v[1]].position; + } + s = Math3D.DotProduct (vec, fa.texinfo.vecs[0]) + fa.texinfo.vecs[0][3]; + s /= fa.texinfo.image.width; + + t = Math3D.DotProduct (vec, fa.texinfo.vecs[1]) + fa.texinfo.vecs[1][3]; + t /= fa.texinfo.image.height; + + Math3D.VectorAdd (total, vec, total); + Math3D.VectorCopy (vec, poly.verts[i]); + poly.verts[i][3] = s; + poly.verts[i][4] = t; + + // + // lightmap texture coordinates + // + s = Math3D.DotProduct (vec, fa.texinfo.vecs[0]) + fa.texinfo.vecs[0][3]; + s -= fa.texturemins[0]; + s += fa.light_s*16; + s += 8; + s /= BLOCK_WIDTH*16; //fa.texinfo.texture.width; + + t = Math3D.DotProduct (vec, fa.texinfo.vecs[1]) + fa.texinfo.vecs[1][3]; + t -= fa.texturemins[1]; + t += fa.light_t*16; + t += 8; + t /= BLOCK_HEIGHT*16; //fa.texinfo.texture.height; + + poly.verts[i][5] = s; + poly.verts[i][6] = t; + } + + poly.numverts = lnumverts; + + precompilePolygon(poly); + + } + + /* + ======================== + GL_CreateSurfaceLightmap + ======================== + */ + void GL_CreateSurfaceLightmap(msurface_t surf) + { + int smax, tmax; + IntBuffer base; + + if ( (surf.flags & (Defines.SURF_DRAWSKY | Defines.SURF_DRAWTURB)) != 0) + return; + + smax = (surf.extents[0]>>4)+1; + tmax = (surf.extents[1]>>4)+1; + + pos_t lightPos = new pos_t(surf.light_s, surf.light_t); + + if ( !LM_AllocBlock( smax, tmax, lightPos ) ) + { + LM_UploadBlock( false ); + LM_InitBlock(); + lightPos = new pos_t(surf.light_s, surf.light_t); + if ( !LM_AllocBlock( smax, tmax, lightPos ) ) + { + ri.Sys_Error( Defines.ERR_FATAL, "Consecutive calls to LM_AllocBlock(" + smax +"," + tmax +") failed\n"); + } + } + + // kopiere die koordinaten zurueck + surf.light_s = lightPos.x; + surf.light_t = lightPos.y; + + surf.lightmaptexturenum = gl_lms.current_lightmap_texture; + + base = gl_lms.lightmap_buffer; + base.position(surf.light_t * BLOCK_WIDTH + surf.light_s); + + R_SetCacheState( surf ); + R_BuildLightMap(surf, base.slice(), BLOCK_WIDTH); + } + + lightstyle_t[] lightstyles; + IntBuffer dummy = BufferUtils.newIntBuffer(128*128); + + /* + ================== + GL_BeginBuildingLightmaps + + ================== + */ + void GL_BeginBuildingLightmaps(model_t m) + { + // static lightstyle_t lightstyles[MAX_LIGHTSTYLES]; + int i; + + // init lightstyles + if ( lightstyles == null ) { + lightstyles = new lightstyle_t[Defines.MAX_LIGHTSTYLES]; + for (i = 0; i < lightstyles.length; i++) + { + lightstyles[i] = new lightstyle_t(); + } + } + + // memset( gl_lms.allocated, 0, sizeof(gl_lms.allocated) ); + Arrays.fill(gl_lms.allocated, 0); + + r_framecount = 1; // no dlightcache + + GL_EnableMultitexture( true ); + GL_SelectTexture( GL_TEXTURE1); + + /* + ** setup the base lightstyles so the lightmaps won't have to be regenerated + ** the first time they're seen + */ + for (i=0 ; i < Defines.MAX_LIGHTSTYLES ; i++) + { + lightstyles[i].rgb[0] = 1; + lightstyles[i].rgb[1] = 1; + lightstyles[i].rgb[2] = 1; + lightstyles[i].white = 3; + } + r_newrefdef.lightstyles = lightstyles; + + if (gl_state.lightmap_textures == 0) + { + gl_state.lightmap_textures = TEXNUM_LIGHTMAPS; + } + + gl_lms.current_lightmap_texture = 1; + + /* + ** if mono lightmaps are enabled and we want to use alpha + ** blending (a,1-a) then we're likely running on a 3DLabs + ** Permedia2. In a perfect world we'd use a GL_ALPHA lightmap + ** in order to conserve space and maximize bandwidth, however + ** this isn't a perfect world. + ** + ** So we have to use alpha lightmaps, but stored in GL_RGBA format, + ** which means we only get 1/16th the color resolution we should when + ** using alpha lightmaps. If we find another board that supports + ** only alpha lightmaps but that can at least support the GL_ALPHA + ** format then we should change this code to use real alpha maps. + */ + + char format = gl_monolightmap.string.toUpperCase().charAt(0); + + if ( format == 'A' ) + { + gl_lms.internal_format = gl_tex_alpha_format; + } + /* + ** try to do hacked colored lighting with a blended texture + */ + else if ( format == 'C' ) + { + gl_lms.internal_format = gl_tex_alpha_format; + } + else if ( format == 'I' ) + { + gl_lms.internal_format = GL.GL_INTENSITY8; + } + else if ( format == 'L' ) + { + gl_lms.internal_format = GL.GL_LUMINANCE8; + } + else + { + gl_lms.internal_format = gl_tex_solid_format; + } + + /* + ** initialize the dynamic lightmap texture + */ + GL_Bind( gl_state.lightmap_textures + 0 ); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); + gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + gl.glTexImage2D( GL.GL_TEXTURE_2D, + 0, + gl_lms.internal_format, + BLOCK_WIDTH, BLOCK_HEIGHT, + 0, + GL_LIGHTMAP_FORMAT, + GL.GL_UNSIGNED_BYTE, + dummy ); + } + + /* + ======================= + GL_EndBuildingLightmaps + ======================= + */ + void GL_EndBuildingLightmaps() + { + LM_UploadBlock( false ); + GL_EnableMultitexture( false ); + } + + /* + * new functions for vertex array handling + */ + static final int POLYGON_BUFFER_SIZE = 120000; + static final int POLYGON_STRIDE = 7; + static final int POLYGON_BYTE_STRIDE = POLYGON_STRIDE * BufferUtils.SIZEOF_FLOAT; + + static FloatBuffer globalPolygonInterleavedBuf = BufferUtils.newFloatBuffer(POLYGON_BUFFER_SIZE * 7); + static FloatBuffer globalPolygonTexCoord1Buf = null; + + static { + globalPolygonInterleavedBuf.position(POLYGON_STRIDE - 2); + globalPolygonTexCoord1Buf = globalPolygonInterleavedBuf.slice(); + globalPolygonInterleavedBuf.position(0); + }; + + void precompilePolygon(glpoly_t p) { + + p.pos = globalPolygonInterleavedBuf.position() / POLYGON_STRIDE; + + float[] v; + FloatBuffer buffer = globalPolygonInterleavedBuf; + + for (int i = 0; i < p.verts.length; i++) { + v = p.verts[i]; + // textureCoord0 + buffer.put(v[3]); + buffer.put(v[4]); + + // vertex + buffer.put(v[0]); + buffer.put(v[1]); + buffer.put(v[2]); + + // textureCoord1 + buffer.put(v[5]); + buffer.put(v[6]); + } + } + + public static void resetPolygonArrays() { + globalPolygonInterleavedBuf.rewind(); + } + + //ImageFrame frame; + +// void debugLightmap(byte[] buf, int w, int h, float scale) { +// IntBuffer pix = ByteBuffer.wrap(buf).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer(); +// +// int[] pixel = new int[w * h]; +// +// pix.get(pixel); +// +// BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR); +// image.setRGB(0, 0, w, h, pixel, 0, w); +// AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(scale, scale), AffineTransformOp.TYPE_NEAREST_NEIGHBOR); +// BufferedImage tmp = op.filter(image, null); +// +// if (frame == null) { +// frame = new ImageFrame(null); +// frame.show(); +// } +// frame.showImage(tmp); +// +// } + +} diff --git a/src/jake2/render/fastjogl/Warp.java b/src/jake2/render/fastjogl/Warp.java new file mode 100644 index 0000000..f9a5b07 --- /dev/null +++ b/src/jake2/render/fastjogl/Warp.java @@ -0,0 +1,732 @@ +/* + * Warp.java + * Copyright (C) 2003 + * + * $Id: Warp.java,v 1.1 2004-07-09 06:50:49 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.fastjogl; + +import java.nio.FloatBuffer; + +import jake2.Defines; +import jake2.Globals; +import jake2.game.GameBase; +import jake2.render.glpoly_t; +import jake2.render.image_t; +import jake2.render.msurface_t; +import jake2.util.Math3D; +import net.java.games.jogl.GL; + +/** + * Warp + * + * @author cwei + */ +public abstract class Warp extends Model { + + + // warpsin.h + public static final float[] SIN = { + 0f, 0.19633f, 0.392541f, 0.588517f, 0.784137f, 0.979285f, 1.17384f, 1.3677f, + 1.56072f, 1.75281f, 1.94384f, 2.1337f, 2.32228f, 2.50945f, 2.69512f, 2.87916f, + 3.06147f, 3.24193f, 3.42044f, 3.59689f, 3.77117f, 3.94319f, 4.11282f, 4.27998f, + 4.44456f, 4.60647f, 4.76559f, 4.92185f, 5.07515f, 5.22538f, 5.37247f, 5.51632f, + 5.65685f, 5.79398f, 5.92761f, 6.05767f, 6.18408f, 6.30677f, 6.42566f, 6.54068f, + 6.65176f, 6.75883f, 6.86183f, 6.9607f, 7.05537f, 7.14579f, 7.23191f, 7.31368f, + 7.39104f, 7.46394f, 7.53235f, 7.59623f, 7.65552f, 7.71021f, 7.76025f, 7.80562f, + 7.84628f, 7.88222f, 7.91341f, 7.93984f, 7.96148f, 7.97832f, 7.99036f, 7.99759f, + 8f, 7.99759f, 7.99036f, 7.97832f, 7.96148f, 7.93984f, 7.91341f, 7.88222f, + 7.84628f, 7.80562f, 7.76025f, 7.71021f, 7.65552f, 7.59623f, 7.53235f, 7.46394f, + 7.39104f, 7.31368f, 7.23191f, 7.14579f, 7.05537f, 6.9607f, 6.86183f, 6.75883f, + 6.65176f, 6.54068f, 6.42566f, 6.30677f, 6.18408f, 6.05767f, 5.92761f, 5.79398f, + 5.65685f, 5.51632f, 5.37247f, 5.22538f, 5.07515f, 4.92185f, 4.76559f, 4.60647f, + 4.44456f, 4.27998f, 4.11282f, 3.94319f, 3.77117f, 3.59689f, 3.42044f, 3.24193f, + 3.06147f, 2.87916f, 2.69512f, 2.50945f, 2.32228f, 2.1337f, 1.94384f, 1.75281f, + 1.56072f, 1.3677f, 1.17384f, 0.979285f, 0.784137f, 0.588517f, 0.392541f, 0.19633f, + 9.79717e-16f, -0.19633f, -0.392541f, -0.588517f, -0.784137f, -0.979285f, -1.17384f, -1.3677f, + -1.56072f, -1.75281f, -1.94384f, -2.1337f, -2.32228f, -2.50945f, -2.69512f, -2.87916f, + -3.06147f, -3.24193f, -3.42044f, -3.59689f, -3.77117f, -3.94319f, -4.11282f, -4.27998f, + -4.44456f, -4.60647f, -4.76559f, -4.92185f, -5.07515f, -5.22538f, -5.37247f, -5.51632f, + -5.65685f, -5.79398f, -5.92761f, -6.05767f, -6.18408f, -6.30677f, -6.42566f, -6.54068f, + -6.65176f, -6.75883f, -6.86183f, -6.9607f, -7.05537f, -7.14579f, -7.23191f, -7.31368f, + -7.39104f, -7.46394f, -7.53235f, -7.59623f, -7.65552f, -7.71021f, -7.76025f, -7.80562f, + -7.84628f, -7.88222f, -7.91341f, -7.93984f, -7.96148f, -7.97832f, -7.99036f, -7.99759f, + -8f, -7.99759f, -7.99036f, -7.97832f, -7.96148f, -7.93984f, -7.91341f, -7.88222f, + -7.84628f, -7.80562f, -7.76025f, -7.71021f, -7.65552f, -7.59623f, -7.53235f, -7.46394f, + -7.39104f, -7.31368f, -7.23191f, -7.14579f, -7.05537f, -6.9607f, -6.86183f, -6.75883f, + -6.65176f, -6.54068f, -6.42566f, -6.30677f, -6.18408f, -6.05767f, -5.92761f, -5.79398f, + -5.65685f, -5.51632f, -5.37247f, -5.22538f, -5.07515f, -4.92185f, -4.76559f, -4.60647f, + -4.44456f, -4.27998f, -4.11282f, -3.94319f, -3.77117f, -3.59689f, -3.42044f, -3.24193f, + -3.06147f, -2.87916f, -2.69512f, -2.50945f, -2.32228f, -2.1337f, -1.94384f, -1.75281f, + -1.56072f, -1.3677f, -1.17384f, -0.979285f, -0.784137f, -0.588517f, -0.392541f, -0.19633f + }; + + // gl_warp.c -- sky and water polygons + //extern model_t *loadmodel; // Model.java + + String skyname; + float skyrotate; + float[] skyaxis = {0, 0, 0}; + image_t[] sky_images = new image_t[6]; + + msurface_t warpface; + + static final int SUBDIVIDE_SIZE = 64; + + void BoundPoly(int numverts, float[][] verts, float[] mins, float[] maxs) + { + int i, j; + float[] v; + + mins[0] = mins[1] = mins[2] = 9999; + maxs[0] = maxs[1] = maxs[2] = -9999; + for (i=0 ; i<numverts ; i++) + { + v = verts[i]; + for (j=0 ; j<3 ; j++) + { + if (v[j] < mins[j]) + mins[j] = v[j]; + if (v[j] > maxs[j]) + maxs[j] = v[j]; + } + } + } + + void SubdividePolygon(int numverts, float[][] verts) + { + int i, j, k; + float[] mins = {0, 0, 0}; + float[] maxs = {0, 0, 0}; + float m; + float[] v = {0, 0, 0}; + float[][] front = new float[64][3]; + float[][] back = new float[64][3]; + + int f, b; + float[] dist = new float[64]; + float frac; + glpoly_t poly; + float s, t; + float[] total = {0, 0, 0}; + float total_s, total_t; + + if (numverts > 60) + ri.Sys_Error(Defines.ERR_DROP, "numverts = " + numverts); + + BoundPoly(numverts, verts, mins, maxs); + + // x,y und z + for (i=0 ; i<3 ; i++) + { + m = (mins[i] + maxs[i]) * 0.5f; + m = SUBDIVIDE_SIZE * (float)Math.floor(m / SUBDIVIDE_SIZE + 0.5f); + if (maxs[i] - m < 8) + continue; + if (m - mins[i] < 8) + continue; + + // cut it + for (j=0 ; j<numverts ; j++) { + dist[j] = verts[j][i] - m; + } + + // wrap cases + dist[j] = dist[0]; + + Math3D.VectorCopy(verts[0], verts[numverts]); + + f = b = 0; + for (j=0 ; j<numverts ; j++) + { + v = verts[j]; + if (dist[j] >= 0) + { + Math3D.VectorCopy(v, front[f]); + f++; + } + if (dist[j] <= 0) + { + Math3D.VectorCopy(v, back[b]); + b++; + } + if (dist[j] == 0 || dist[j+1] == 0) continue; + + if ( (dist[j] > 0) != (dist[j+1] > 0) ) + { + // clip point + frac = dist[j] / (dist[j] - dist[j+1]); + for (k=0 ; k<3 ; k++) + front[f][k] = back[b][k] = v[k] + frac*(verts[j+1][k] - v[k]); + + f++; + b++; + } + } + + SubdividePolygon(f, front); + SubdividePolygon(b, back); + return; + } + + // add a point in the center to help keep warp valid + + // wird im Konstruktor erschlagen + // poly = Hunk_Alloc (sizeof(glpoly_t) + ((numverts-4)+2) * VERTEXSIZE*sizeof(float)); + + // init polys + poly = new glpoly_t(numverts + 2); + + poly.next = warpface.polys; + warpface.polys = poly; + poly.numverts = numverts + 2; + Math3D.VectorClear(total); + total_s = 0; + total_t = 0; + for (i=0 ; i<numverts ; i++) + { + Math3D.VectorCopy(verts[i], poly.verts[i+1]); + s = Math3D.DotProduct(verts[i], warpface.texinfo.vecs[0]); + t = Math3D.DotProduct(verts[i], warpface.texinfo.vecs[1]); + + total_s += s; + total_t += t; + Math3D.VectorAdd(total, verts[i], total); + + poly.verts[i+1][3] = s; + poly.verts[i+1][4] = t; + } + + Math3D.VectorScale(total, (1.0f/numverts), poly.verts[0]); + poly.verts[0][3] = total_s/numverts; + poly.verts[0][4] = total_t/numverts; + + // memcpy (poly.verts[i+1], poly.verts[1], sizeof(poly.verts[0])); + System.arraycopy(poly.verts[1], 0, poly.verts[i+1], 0, poly.verts[1].length); // :-) + + precompilePolygon(poly); + } + + /* + ================ + GL_SubdivideSurface + + Breaks a polygon up along axial 64 unit + boundaries so that turbulent and sky warps + can be done reasonably. + ================ + */ + void GL_SubdivideSurface(msurface_t fa) + { + float[][] verts = new float[64][3]; + + int numverts; + int i; + int lindex; + float[] vec; + + warpface = fa; + + // + // convert edges back to a normal polygon + // + numverts = 0; + for (i=0 ; i < fa.numedges ; i++) + { + lindex = loadmodel.surfedges[fa.firstedge + i]; + + if (lindex > 0) + vec = loadmodel.vertexes[loadmodel.edges[lindex].v[0]].position; + else + vec = loadmodel.vertexes[loadmodel.edges[-lindex].v[1]].position; + Math3D.VectorCopy(vec, verts[numverts]); + numverts++; + } + + SubdividePolygon(numverts, verts); + } + +// ========================================================= + + + +//// speed up sin calculations - Ed +// float r_turbsin[] = +// { +// #include "warpsin.h" +// }; + static final float TURBSCALE = (float)(256.0f / (2 * Math.PI)); + + /* + ============= + EmitWaterPolys + + Does a water warp on the pre-fragmented glpoly_t chain + ============= + */ + void EmitWaterPolys(msurface_t fa) + { + glpoly_t p, bp; + float[] v; + int i; + float s = 0; + float t = 0; + float os, ot; + float scroll; + float rdt = r_newrefdef.time; + + if ((fa.texinfo.flags & Defines.SURF_FLOWING) != 0) + scroll = -64 * ( (r_newrefdef.time*0.5f) - (int)(r_newrefdef.time*0.5f) ); + else + scroll = 0; + + int index; + FloatBuffer texCoord = globalPolygonInterleavedBuf; + for (bp=fa.polys ; bp != null ; bp=bp.next) + { + p = bp; + + index = p.pos * POLYGON_STRIDE; + for (i=0; i<p.numverts ; i++) + { + v = p.verts[i]; + os = v[3]; + ot = v[4]; + + s = os + Warp.SIN[(int)((ot * 0.125f + r_newrefdef.time) * TURBSCALE) & 255]; + s += scroll; + s *= (1.0f/64); + + t = ot + Warp.SIN[(int)((os * 0.125f + rdt) * TURBSCALE) & 255]; + t *= (1.0f/64); + + texCoord.put(index, s); + texCoord.put(index + 1, t); + index += POLYGON_STRIDE; + } + gl.glDrawArrays(GL.GL_TRIANGLE_FAN, p.pos, p.numverts); + } + } + +// =================================================================== + + + float[][] skyclip = { + { 1, 1, 0}, + { 1, -1, 0}, + { 0, -1, 1}, + { 0, 1, 1}, + { 1, 0, 1}, + {-1, 0, 1} + }; + + int c_sky; + + // 1 = s, 2 = t, 3 = 2048 + int[][] st_to_vec = + { + {3,-1,2}, + {-3,1,2}, + + {1,3,2}, + {-1,-3,2}, + + {-2,-1,3}, // 0 degrees yaw, look straight up + {2,-1,-3} // look straight down + + }; + + int[][] vec_to_st = + { + {-2,3,1}, + {2,3,-1}, + + {1,3,2}, + {-1,3,-2}, + + {-2,-1,3}, + {-2,1,-3} + + }; + + float[][] skymins = new float[2][6]; + float[][] skymaxs = new float[2][6]; + float sky_min, sky_max; + + void DrawSkyPolygon (int nump, float[][] vecs) + { + int i,j; + float[] v = {0, 0, 0}; + float[] av = {0, 0, 0}; + float s, t, dv; + int axis; + float[] vp; + + c_sky++; + // decide which face it maps to + Math3D.VectorCopy(Globals.vec3_origin, v); + for (i=0; i<nump ; i++) + { + Math3D.VectorAdd(vecs[i], v, v); + } + av[0] = Math.abs(v[0]); + av[1] = Math.abs(v[1]); + av[2] = Math.abs(v[2]); + if (av[0] > av[1] && av[0] > av[2]) + { + if (v[0] < 0) + axis = 1; + else + axis = 0; + } + else if (av[1] > av[2] && av[1] > av[0]) + { + if (v[1] < 0) + axis = 3; + else + axis = 2; + } + else + { + if (v[2] < 0) + axis = 5; + else + axis = 4; + } + + // project new texture coords + for (i=0 ; i<nump ; i++) + { + j = vec_to_st[axis][2]; + if (j > 0) + dv = vecs[i][j - 1]; + else + dv = -vecs[i][-j - 1]; + if (dv < 0.001f) + continue; // don't divide by zero + j = vec_to_st[axis][0]; + if (j < 0) + s = -vecs[i][-j -1] / dv; + else + s = vecs[i][j-1] / dv; + j = vec_to_st[axis][1]; + if (j < 0) + t = -vecs[i][-j -1] / dv; + else + t = vecs[i][j-1] / dv; + + if (s < skymins[0][axis]) + skymins[0][axis] = s; + if (t < skymins[1][axis]) + skymins[1][axis] = t; + if (s > skymaxs[0][axis]) + skymaxs[0][axis] = s; + if (t > skymaxs[1][axis]) + skymaxs[1][axis] = t; + } + } + + static final float ON_EPSILON = 0.1f; // point on plane side epsilon + static final int MAX_CLIP_VERTS = 64; + + static final int SIDE_BACK = 1; + static final int SIDE_FRONT = 0; + static final int SIDE_ON = 2; + + float[] dists = new float[MAX_CLIP_VERTS]; + int[] sides = new int[MAX_CLIP_VERTS]; + float[][][][] newv = new float[6][2][MAX_CLIP_VERTS][3]; + + void ClipSkyPolygon(int nump, float[][] vecs, int stage) + { + float[] norm; + float[] v; + boolean front, back; + float d, e; + int[] newc = { 0, 0 }; + int i, j; + + if (nump > MAX_CLIP_VERTS-2) + ri.Sys_Error(Defines.ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS"); + if (stage == 6) + { // fully clipped, so draw it + DrawSkyPolygon(nump, vecs); + return; + } + + front = back = false; + norm = skyclip[stage]; + for (i=0 ; i<nump ; i++) + { + d = Math3D.DotProduct(vecs[i], norm); + if (d > ON_EPSILON) + { + front = true; + sides[i] = SIDE_FRONT; + } + else if (d < -ON_EPSILON) + { + back = true; + sides[i] = SIDE_BACK; + } + else + sides[i] = SIDE_ON; + dists[i] = d; + } + + if (!front || !back) + { // not clipped + ClipSkyPolygon (nump, vecs, stage+1); + return; + } + + // clip it + sides[i] = sides[0]; + dists[i] = dists[0]; + Math3D.VectorCopy(vecs[0], vecs[i]); + newc[0] = newc[1] = 0; + + for (i=0; i<nump ; i++) + { + v = vecs[i]; + switch (sides[i]) + { + case SIDE_FRONT: + Math3D.VectorCopy(v, newv[stage][0][newc[0]]); + newc[0]++; + break; + case SIDE_BACK: + Math3D.VectorCopy(v, newv[stage][1][newc[1]]); + newc[1]++; + break; + case SIDE_ON: + Math3D.VectorCopy(v, newv[stage][0][newc[0]]); + newc[0]++; + Math3D.VectorCopy (v, newv[stage][1][newc[1]]); + newc[1]++; + break; + } + + if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + d = dists[i] / (dists[i] - dists[i+1]); + for (j=0 ; j<3 ; j++) + { + e = v[j] + d * (vecs[i + 1][j] - v[j]); + newv[stage][0][newc[0]][j] = e; + newv[stage][1][newc[1]][j] = e; + } + newc[0]++; + newc[1]++; + } + + // continue + ClipSkyPolygon(newc[0], newv[stage][0], stage+1); + ClipSkyPolygon(newc[1], newv[stage][1], stage+1); + } + + float[][] verts = new float[MAX_CLIP_VERTS][3]; + + /* + ================= + R_AddSkySurface + ================= + */ + void R_AddSkySurface(msurface_t fa) + { + int i; + glpoly_t p; + + // calculate vertex values for sky box + for (p=fa.polys ; p != null ; p=p.next) + { + for (i=0 ; i < p.numverts ; i++) + { + Math3D.VectorSubtract(p.verts[i], r_origin, verts[i]); + } + ClipSkyPolygon (p.numverts, verts, 0); + } + } + + + /* + ============== + R_ClearSkyBox + ============== + */ + void R_ClearSkyBox() + { + int i; + + for (i=0 ; i<6 ; i++) + { + skymins[0][i] = skymins[1][i] = 9999; + skymaxs[0][i] = skymaxs[1][i] = -9999; + } + } + + + void MakeSkyVec (float s, float t, int axis) + { + float[] v = {0, 0, 0}; + float[] b = {0, 0, 0}; + int j, k; + + b[0] = s*2300; + b[1] = t*2300; + b[2] = 2300; + + for (j=0 ; j<3 ; j++) + { + k = st_to_vec[axis][j]; + if (k < 0) + v[j] = -b[-k - 1]; + else + v[j] = b[k - 1]; + } + + // avoid bilerp seam + s = (s + 1) * 0.5f; + t = (t + 1) * 0.5f; + + if (s < sky_min) + s = sky_min; + else if (s > sky_max) + s = sky_max; + if (t < sky_min) + t = sky_min; + else if (t > sky_max) + t = sky_max; + + t = 1.0f - t; + gl.glTexCoord2f (s, t); + gl.glVertex3f(v[0], v[1], v[2]); + } + + /* + ============== + R_DrawSkyBox + ============== + */ + int[] skytexorder = {0,2,1,3,4,5}; + + void R_DrawSkyBox() + { + int i; + + if (skyrotate != 0) + { // check for no sky at all + for (i=0 ; i<6 ; i++) + if (skymins[0][i] < skymaxs[0][i] + && skymins[1][i] < skymaxs[1][i]) + break; + if (i == 6) + return; // nothing visible + } + + gl.glPushMatrix (); + gl.glTranslatef (r_origin[0], r_origin[1], r_origin[2]); + gl.glRotatef (r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]); + + for (i=0 ; i<6 ; i++) + { + if (skyrotate != 0) + { // hack, forces full sky to draw when rotating + skymins[0][i] = -1; + skymins[1][i] = -1; + skymaxs[0][i] = 1; + skymaxs[1][i] = 1; + } + + if (skymins[0][i] >= skymaxs[0][i] + || skymins[1][i] >= skymaxs[1][i]) + continue; + + GL_Bind(sky_images[skytexorder[i]].texnum); + + gl.glBegin(GL.GL_QUADS); + MakeSkyVec(skymins[0][i], skymins[1][i], i); + MakeSkyVec(skymins[0][i], skymaxs[1][i], i); + MakeSkyVec(skymaxs[0][i], skymaxs[1][i], i); + MakeSkyVec(skymaxs[0][i], skymins[1][i], i); + gl.glEnd (); + } + gl.glPopMatrix (); + } + + + /* + ============ + R_SetSky + ============ + */ + // 3dstudio environment map names + String[] suf = {"rt", "bk", "lf", "ft", "up", "dn"}; + + protected void R_SetSky(String name, float rotate, float[] axis) + { + assert (axis.length == 3) : "vec3_t bug"; + int i; + String pathname; + +// strncpy (skyname, name, sizeof(skyname)-1); + skyname = name; + + skyrotate = rotate; + Math3D.VectorCopy(axis, skyaxis); + + for (i=0 ; i<6 ; i++) + { + // chop down rotating skies for less memory + if (gl_skymip.value != 0 || skyrotate != 0) + gl_picmip.value++; + + if ( qglColorTableEXT && gl_ext_palettedtexture.value != 0) { + // Com_sprintf (pathname, sizeof(pathname), "env/%s%s.pcx", skyname, suf[i]); + pathname = "env/" + skyname + suf[i] + ".pcx"; + } else { + // Com_sprintf (pathname, sizeof(pathname), "env/%s%s.tga", skyname, suf[i]); + pathname = "env/" + skyname + suf[i] + ".tga"; + } + + sky_images[i] = GL_FindImage(pathname, it_sky); + + if (sky_images[i] == null) + sky_images[i] = r_notexture; + + if (gl_skymip.value != 0 || skyrotate != 0) + { // take less memory + gl_picmip.value--; + sky_min = 1.0f / 256; + sky_max = 255.0f / 256; + } + else + { + sky_min = 1.0f / 512; + sky_max = 511.0f / 512; + } + } + } + + +} diff --git a/src/jake2/render/glpoly_t.java b/src/jake2/render/glpoly_t.java index 25cff9c..85b1fd0 100644 --- a/src/jake2/render/glpoly_t.java +++ b/src/jake2/render/glpoly_t.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 20.11.2003 by RST. -// $Id: glpoly_t.java,v 1.1 2004-07-07 19:59:35 hzi Exp $ +// $Id: glpoly_t.java,v 1.2 2004-07-09 06:50:47 hzi Exp $ package jake2.render; @@ -35,4 +35,12 @@ public class glpoly_t { public glpoly_t(int numverts) { this.verts = new float[numverts][VERTEXSIZE]; } + + /* + * vertex array extension + */ + + // the array position (glDrawArrays) + public int pos = 0; + } diff --git a/src/jake2/render/jogl/Draw.java b/src/jake2/render/jogl/Draw.java index eac0a1e..3251b0e 100644 --- a/src/jake2/render/jogl/Draw.java +++ b/src/jake2/render/jogl/Draw.java @@ -2,7 +2,7 @@ * Draw.java * Copyright (C) 2003 * - * $Id: Draw.java,v 1.2 2004-07-08 15:58:45 hzi Exp $ + * $Id: Draw.java,v 1.3 2004-07-09 06:50:48 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -257,10 +257,10 @@ public abstract class Draw extends Image { int color = d_8to24table[colorIndex]; - gl.glColor3f( - ((color >> 0) & 0xff)/255.0f, // r - ((color >> 8) & 0xff)/255.0f, // g - ((color >> 16) & 0xff)/255.0f // b + gl.glColor3ub( + (byte)((color >> 0) & 0xff), // r + (byte)((color >> 8) & 0xff), // g + (byte)((color >> 16) & 0xff) // b ); gl.glBegin (GL.GL_QUADS); diff --git a/src/jake2/render/jogl/Image.java b/src/jake2/render/jogl/Image.java index 4e65481..f0034fe 100644 --- a/src/jake2/render/jogl/Image.java +++ b/src/jake2/render/jogl/Image.java @@ -2,7 +2,7 @@ * Image.java * Copyright (C) 2003 * - * $Id: Image.java,v 1.2 2004-07-08 20:24:30 hzi Exp $ + * $Id: Image.java,v 1.3 2004-07-09 06:50:48 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -26,27 +26,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. package jake2.render.jogl; import jake2.Defines; +import jake2.client.particle_t; import jake2.game.cvar_t; import jake2.qcommon.longjmpException; import jake2.qcommon.qfiles; import jake2.render.image_t; +import jake2.util.Lib; import jake2.util.Vargs; import java.awt.Dimension; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; -import java.awt.image.BufferedImageOp; -import java.awt.image.Raster; -import java.awt.image.SampleModel; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.IntBuffer; +import java.nio.*; import java.util.Arrays; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.Map; -import java.util.TreeMap; import net.java.games.jogl.GL; @@ -128,8 +121,7 @@ public abstract class Image extends Main { GL_TexEnv(GL.GL_REPLACE); } - void GL_SelectTexture(int texture /* GLenum */ - ) { + void GL_SelectTexture(int texture /* GLenum */) { int tmu; if (!qglSelectTextureSGIS && !qglActiveTextureARB) @@ -787,9 +779,9 @@ public abstract class Image extends Main { filledcolor = 0; // attempt to find opaque black for (i = 0; i < 256; ++i) - if (d_8to24table[i] == (255 << 0)) // alpha 1.0 - // TODO check this: if ((d_8to24table[i] & 0xFF000000) == 0xFF000000) // alpha 1.0 - { + // TODO check this + if (d_8to24table[i] == 0xFF000000) { // alpha 1.0 + //if (d_8to24table[i] == (255 << 0)) // alpha 1.0 filledcolor = i; break; } @@ -1068,6 +1060,7 @@ public abstract class Image extends Main { */ int[] scaled = new int[256 * 256]; byte[] paletted_texture = new byte[256 * 256]; + IntBuffer tex = Lib.newIntBuffer(512 * 256, ByteOrder.LITTLE_ENDIAN); boolean GL_Upload32(int[] data, int width, int height, boolean mipmap) { int samples; @@ -1149,6 +1142,7 @@ public abstract class Image extends Main { paletted_texture); } else { + tex.rewind(); tex.put(data); gl.glTexImage2D( GL.GL_TEXTURE_2D, 0, @@ -1158,13 +1152,13 @@ public abstract class Image extends Main { 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, - data); + tex); } //goto done; throw new longjmpException(); } //memcpy (scaled, data, width*height*4); were bytes - IntBuffer.wrap(data).get(scaled, 0, width * height); + System.arraycopy(data, 0, scaled, 0, width * height); } else @@ -1187,7 +1181,8 @@ public abstract class Image extends Main { paletted_texture); } else { - gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, scaled); + tex.rewind(); tex.put(scaled); + gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, tex); } if (mipmap) { @@ -1218,6 +1213,7 @@ public abstract class Image extends Main { paletted_texture); } else { + tex.rewind(); tex.put(scaled); gl.glTexImage2D( GL.GL_TEXTURE_2D, miplevel, @@ -1227,14 +1223,14 @@ public abstract class Image extends Main { 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, - scaled); + tex); } } } // label done: } catch (longjmpException e) { - ; // replaces labe done + ; // replaces label done } if (mipmap) { @@ -1578,7 +1574,7 @@ public abstract class Image extends Main { // free it // TODO jogl bug - //gl.glDeleteTextures(1, new int[] {image.texnum}); + gl.glDeleteTextures(1, new int[] {image.texnum}); image.clear(); } } @@ -1590,7 +1586,6 @@ public abstract class Image extends Main { */ protected void Draw_GetPalette() { int r, g, b; - int v; Dimension dim; byte[] pic; byte[][] palette = new byte[1][]; //new byte[768]; @@ -1604,15 +1599,18 @@ public abstract class Image extends Main { byte[] pal = palette[0]; + int j = 0; for (int i = 0; i < 256; i++) { - r = pal[i * 3 + 0]; - g = pal[i * 3 + 1]; - b = pal[i * 3 + 2]; + r = pal[j++] & 0xFF; + g = pal[j++] & 0xFF; + b = pal[j++] & 0xFF; - d_8to24table[i] = (255 << 24) + (r << 0) + (g << 8) + (b << 16); + d_8to24table[i] = (255 << 24) | (b << 16) | (g << 8) | (r << 0); } - d_8to24table[255] &= 0x00ffffff; // 255 is transparent + d_8to24table[255] &= 0x00FFFFFF; // 255 is transparent + + particle_t.setColorPalette(d_8to24table); } /* @@ -1686,7 +1684,7 @@ public abstract class Image extends Main { continue; // free image_t slot // free it // TODO jogl bug - //gl.glDeleteTextures(1, new int[] {image.texnum}); + gl.glDeleteTextures(1, new int[] {image.texnum}); image.clear(); } } diff --git a/src/jake2/render/jogl/Impl.java b/src/jake2/render/jogl/Impl.java index 991c349..cfaec7e 100644 --- a/src/jake2/render/jogl/Impl.java +++ b/src/jake2/render/jogl/Impl.java @@ -2,7 +2,7 @@ * Impl.java * Copyright (C) 2003 * - * $Id: Impl.java,v 1.4 2004-07-08 20:56:55 hzi Exp $ + * $Id: Impl.java,v 1.5 2004-07-09 06:50:48 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -27,13 +27,11 @@ package jake2.render.jogl; import jake2.Defines; import jake2.Globals; -import jake2.client.CL; import jake2.qcommon.Com; import jake2.qcommon.xcommand_t; -import jake2.server.SV; import jake2.sys.KBD; -import java.awt.Dimension; +import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; @@ -48,17 +46,34 @@ import net.java.games.jogl.*; */ public class Impl extends Misc implements GLEventListener { - - public static final String DRIVER_NAME = "jogl"; // handles the post initialization with JoglRenderer protected boolean post_init = false; - // switch to updateScreen callback - private boolean switchToCallback = false; - private xcommand_t callback = null; + private final xcommand_t INIT_CALLBACK = new xcommand_t() { + public void execute() { + // only used for the first run (initialization) + // clear the screen + gl.glClearColor(0, 0, 0, 0); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + // + // check the post init process + // + if (!post_init) { + ri.Con_Printf(Defines.PRINT_ALL, "Missing multi-texturing for FastJOGL renderer\n"); + } + + GLimp_EndFrame(); + } + }; + + private xcommand_t callback = INIT_CALLBACK; protected boolean contextInUse = false; + + private GraphicsDevice device; + private DisplayMode oldDisplayMode; GLCanvas canvas; JFrame window; @@ -88,13 +103,9 @@ public class Impl extends Misc implements GLEventListener { ri.Cvar_Get("r_fakeFullscreen", "0", Globals.CVAR_ARCHIVE); - ri.Con_Printf(Defines.PRINT_ALL, "Initializing OpenGL display\n", null); + ri.Con_Printf(Defines.PRINT_ALL, "Initializing OpenGL display\n"); - if (fullscreen) { - ri.Con_Printf(Defines.PRINT_ALL, "...setting fullscreen mode " + mode + ":"); - } - else - ri.Con_Printf(Defines.PRINT_ALL, "...setting mode " + mode + ":"); + ri.Con_Printf(Defines.PRINT_ALL, "...setting mode " + mode + ":"); if (!ri.Vid_GetModeInfo(newDim, mode)) { ri.Con_Printf(Defines.PRINT_ALL, " invalid mode\n"); @@ -113,18 +124,12 @@ public class Impl extends Misc implements GLEventListener { // TODO Use debug pipeline //canvas.setGL(new DebugGL(canvas.getGL())); - //canvas.setRenderingThread(Thread.currentThread()); - canvas.setNoAutoRedrawMode(true); canvas.addGLEventListener(this); - window.getContentPane().add(canvas); - + window.getContentPane().add(canvas); canvas.setSize(newDim.width, newDim.height); - window.setLocation(window_xpos, window_ypos); - //window.setUndecorated(true); - window.setResizable(false); // register event listener window.addWindowListener(new WindowAdapter() { @@ -134,14 +139,57 @@ public class Impl extends Misc implements GLEventListener { }); // D I F F E R E N T J A K E 2 E V E N T P R O C E S S I N G + window.addComponentListener(KBD.listener); canvas.addKeyListener(KBD.listener); canvas.addMouseListener(KBD.listener); canvas.addMouseMotionListener(KBD.listener); - window.addComponentListener(KBD.listener); - canvas.requestFocus(); - window.pack(); - window.show(); + /* + * fullscreen handling + */ + GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); + device = env.getDefaultScreenDevice(); + + if (fullscreen && !device.isFullScreenSupported()) { + ri.Con_Printf(Defines.PRINT_ALL, "...fullscreen not supported\n"); + vid_fullscreen.value = 0; + vid_fullscreen.modified = false; + } + + fullscreen = fullscreen && device.isFullScreenSupported(); + + if (oldDisplayMode == null) { + oldDisplayMode = device.getDisplayMode(); + } + + if (fullscreen) { + + DisplayMode displayMode = findDisplayMode(newDim, oldDisplayMode.getBitDepth(), oldDisplayMode.getRefreshRate()); + + if (displayMode != null) { + newDim.width = displayMode.getWidth(); + newDim.height = displayMode.getHeight(); + window.setUndecorated(true); + window.setResizable(false); + device.setFullScreenWindow(window); + device.setDisplayMode(displayMode); + window.setLocation(0, 0); + window.setSize(displayMode.getWidth(), displayMode.getHeight()); + canvas.setSize(displayMode.getWidth(), displayMode.getHeight()); + ri.Con_Printf(Defines.PRINT_ALL, "...setting fullscreen " + getModeString(displayMode) + '\n'); + } + } else { + window.setLocation(window_xpos, window_ypos); + window.pack(); + window.setResizable(false); + window.setVisible(true); + } + + while (!canvas.isDisplayable()) { + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + } canvas.requestFocus(); this.canvas = canvas; @@ -154,6 +202,38 @@ public class Impl extends Misc implements GLEventListener { return rserr_ok; } + + DisplayMode findDisplayMode(Dimension dim, int depth, int rate) { + DisplayMode mode = null; + DisplayMode m = null; + DisplayMode[] modes = device.getDisplayModes(); + int w = dim.width; + int h = dim.height; + + for (int i = 0; i < modes.length; i++) { + m = modes[i]; + if (m.getWidth() == w && m.getHeight() == h && m.getBitDepth() == depth && m.getRefreshRate() == rate) { + mode = m; + break; + } + } + if (mode == null) mode = oldDisplayMode; + Com.Printf(getModeString(mode) + '\n'); + return mode; + } + + String getModeString(DisplayMode m) { + StringBuffer sb = new StringBuffer(); + sb.append(m.getWidth()); + sb.append('x'); + sb.append(m.getHeight()); + sb.append('x'); + sb.append(m.getBitDepth()); + sb.append('@'); + sb.append(m.getRefreshRate()); + sb.append("Hz"); + return sb.toString(); + } void GLimp_BeginFrame(float camera_separation) { // do nothing @@ -180,11 +260,19 @@ public class Impl extends Misc implements GLEventListener { } void GLimp_Shutdown() { + if (oldDisplayMode != null && device.getFullScreenWindow() != null) { + try { + device.setDisplayMode(oldDisplayMode); + device.setFullScreenWindow(null); + } catch (Exception e) { + e.printStackTrace(); + } + } if (this.window != null) { window.dispose(); } post_init = false; - switchToCallback = false; + callback = INIT_CALLBACK; } void GLimp_EnableLogging(boolean enable) { @@ -221,31 +309,8 @@ public class Impl extends Misc implements GLEventListener { this.gl = drawable.getGL(); this.glu = drawable.getGLU(); - this.contextInUse = true; - - if (switchToCallback) { - callback.execute(); - } - else - { - - // after the first run (initialization) switch to callback - switchToCallback = true; - - // clear the screen - gl.glClearColor(0, 0, 0, 0); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - // - // check the post init process - // - if (!post_init) { - ri.Sys_Error(Defines.ERR_FATAL, "Error: can't init JOGL renderer"); - } - - GLimp_EndFrame(); - } - + contextInUse = true; + callback.execute(); contextInUse = false; } @@ -260,20 +325,18 @@ public class Impl extends Misc implements GLEventListener { * @see net.java.games.jogl.GLEventListener#reshape(net.java.games.jogl.GLDrawable, int, int, int, int) */ public void reshape(GLDrawable drawable, int x, int y, int width, int height) { - - vid.height = height; - vid.width = width; - - ri.Vid_NewWindow(width, height); + // do nothing } /* * @see jake2.client.refexport_t#updateScreen() */ + public void updateScreen() { + this.callback = INIT_CALLBACK; + canvas.display(); + } + public void updateScreen(xcommand_t callback) { -// if (canvas == null) { -// throw new IllegalStateException("Refresh modul \"" + DRIVER_NAME + "\" have to be initialized."); -// } this.callback = callback; canvas.display(); } diff --git a/src/jake2/render/jogl/Light.java b/src/jake2/render/jogl/Light.java index 686884a..851f4e6 100644 --- a/src/jake2/render/jogl/Light.java +++ b/src/jake2/render/jogl/Light.java @@ -2,7 +2,7 @@ * Light.java * Copyright (C) 2003 * - * $Id: Light.java,v 1.3 2004-07-08 20:56:55 hzi Exp $ + * $Id: Light.java,v 1.4 2004-07-09 06:50:48 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -25,12 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package jake2.render.jogl; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.util.Arrays; - -import net.java.games.jogl.GL; - import jake2.Defines; import jake2.Globals; import jake2.client.dlight_t; @@ -38,12 +32,15 @@ import jake2.client.lightstyle_t; import jake2.game.GameBase; import jake2.game.cplane_t; import jake2.qcommon.longjmpException; -import jake2.render.mnode_t; -import jake2.render.msurface_t; -import jake2.render.mtexinfo_t; -import jake2.util.Lib; +import jake2.render.*; import jake2.util.Math3D; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.util.Arrays; + +import net.java.games.jogl.GL; + /** * Light * @@ -79,7 +76,7 @@ public abstract class Light extends Warp { gl.glColor3f (light.color[0]*0.2f, light.color[1]*0.2f, light.color[2]*0.2f); for (i=0 ; i<3 ; i++) v[i] = light.origin[i] - vpn[i]*rad; - gl.glVertex3fv (v); + gl.glVertex3f(v[0], v[1], v[2]); gl.glColor3f (0,0,0); for (i=16 ; i>=0 ; i--) { @@ -87,7 +84,7 @@ public abstract class Light extends Warp { for (j=0 ; j<3 ; j++) v[j] = (float)(light.origin[j] + vright[j]*Math.cos(a)*rad + vup[j]*Math.sin(a)*rad); - gl.glVertex3fv (v); + gl.glVertex3f(v[0], v[1], v[2]); } gl.glEnd (); } @@ -306,16 +303,13 @@ public abstract class Light extends Warp { ds >>= 4; dt >>= 4; - //surf.samples.reset(); - lightmap = surf.samples.slice(); - + lightmap = surf.samples; int lightmapIndex = 0; + Math3D.VectorCopy (Globals.vec3_origin, pointcolor); if (lightmap != null) { float[] scale = {0, 0, 0}; - -// lightmap += 3*(dt * ((surf.extents[0]>>4)+1) + ds); lightmapIndex += 3 * (dt * ((surf.extents[0] >> 4) + 1) + ds); for (maps = 0 ; maps < Defines.MAXLIGHTMAPS && surf.styles[maps] != (byte)255; maps++) @@ -326,15 +320,11 @@ public abstract class Light extends Warp { pointcolor[0] += (lightmap.get(lightmapIndex + 0) & 0xFF) * scale[0] * (1.0f/255); pointcolor[1] += (lightmap.get(lightmapIndex + 1) & 0xFF) * scale[1] * (1.0f/255); pointcolor[2] += (lightmap.get(lightmapIndex + 2) & 0xFF) * scale[2] * (1.0f/255); -// lightmap += 3*((surf.extents[0]>>4)+1) * -// ((surf.extents[1]>>4)+1); lightmapIndex += 3 * ((surf.extents[0] >> 4) + 1) * ((surf.extents[1] >> 4) + 1); } } - return 1; } - // go down back side return RecursiveLightPoint (node.children[1 - sideIndex], mid, end); } @@ -506,7 +496,7 @@ public abstract class Light extends Warp { Combine and scale multiple lightmaps into the floating format in blocklights =============== */ - void R_BuildLightMap(msurface_t surf, ByteBuffer dest, int stride) + void R_BuildLightMap(msurface_t surf, IntBuffer dest, int stride) { int smax, tmax; int r, g, b, a, max; @@ -549,8 +539,8 @@ public abstract class Light extends Warp { nummaps++) ; - //surf.samples.reset(); - lightmap = surf.samples.slice(); + lightmap = surf.samples; + int lightmapIndex = 0; // add all the lightmaps if ( nummaps == 1 ) @@ -572,18 +562,18 @@ public abstract class Light extends Warp { { for (i=0 ; i<size ; i++) { - bl[blp++] = lightmap.get() & 0xFF; - bl[blp++] = lightmap.get() & 0xFF; - bl[blp++] = lightmap.get() & 0xFF; + bl[blp++] = lightmap.get(lightmapIndex++) & 0xFF; + bl[blp++] = lightmap.get(lightmapIndex++) & 0xFF; + bl[blp++] = lightmap.get(lightmapIndex++) & 0xFF; } } else { for (i=0 ; i<size ; i++) { - bl[blp++] = (lightmap.get() & 0xFF) * scale[0]; - bl[blp++] = (lightmap.get() & 0xFF) * scale[1]; - bl[blp++] = (lightmap.get() & 0xFF) * scale[2]; + bl[blp++] = (lightmap.get(lightmapIndex++) & 0xFF) * scale[0]; + bl[blp++] = (lightmap.get(lightmapIndex++) & 0xFF) * scale[1]; + bl[blp++] = (lightmap.get(lightmapIndex++) & 0xFF) * scale[2]; } } //lightmap += size*3; // skip to next lightmap @@ -612,18 +602,18 @@ public abstract class Light extends Warp { { for (i=0 ; i<size ; i++) { - bl[blp++] += lightmap.get() & 0xFF; - bl[blp++] += lightmap.get() & 0xFF; - bl[blp++] += lightmap.get() & 0xFF; + bl[blp++] += lightmap.get(lightmapIndex++) & 0xFF; + bl[blp++] += lightmap.get(lightmapIndex++) & 0xFF; + bl[blp++] += lightmap.get(lightmapIndex++) & 0xFF; } } else { for (i=0 ; i<size ; i++) { - bl[blp++] += (lightmap.get() & 0xFF) * scale[0]; - bl[blp++] += (lightmap.get() & 0xFF) * scale[1]; - bl[blp++] += (lightmap.get() & 0xFF) * scale[2]; + bl[blp++] += (lightmap.get(lightmapIndex++) & 0xFF) * scale[0]; + bl[blp++] += (lightmap.get(lightmapIndex++) & 0xFF) * scale[1]; + bl[blp++] += (lightmap.get(lightmapIndex++) & 0xFF) * scale[2]; } } //lightmap += size*3; // skip to next lightmap @@ -638,7 +628,7 @@ public abstract class Light extends Warp { } catch (longjmpException store) {} // put into texture format - stride -= (smax<<2); + stride -= smax; bl = s_blocklights; int blp = 0; @@ -697,8 +687,8 @@ public abstract class Light extends Warp { b = (int)(b*t); a = (int)(a*t); } - dest.put((byte)r).put((byte)g).put((byte)b).put((byte)a); - destp += 4; + r &= 0xFF; g &= 0xFF; b &= 0xFF; a &= 0xFF; + dest.put(destp++, (a << 24) | (b << 16) | (g << 8) | (r << 0)); } } } @@ -778,9 +768,8 @@ public abstract class Light extends Warp { a = 255 - a; break; } - - dest.put((byte)r).put((byte)g).put((byte)b).put((byte)a); - destp += 4; + r &= 0xFF; g &= 0xFF; b &= 0xFF; a &= 0xFF; + dest.put(destp++, (a << 24) | (b << 16) | (g << 8) | (r << 0)); } } } diff --git a/src/jake2/render/jogl/Main.java b/src/jake2/render/jogl/Main.java index 32442ba..2b46501 100644 --- a/src/jake2/render/jogl/Main.java +++ b/src/jake2/render/jogl/Main.java @@ -2,7 +2,7 @@ * Main.java * Copyright (C) 2003 * - * $Id: Main.java,v 1.2 2004-07-08 15:58:44 hzi Exp $ + * $Id: Main.java,v 1.3 2004-07-09 06:50:47 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -29,6 +29,7 @@ import jake2.*; import jake2.client.*; import jake2.game.cplane_t; import jake2.game.cvar_t; +import jake2.qcommon.Cvar; import jake2.qcommon.qfiles; import jake2.qcommon.xcommand_t; import jake2.render.*; @@ -36,9 +37,12 @@ import jake2.util.Math3D; import jake2.util.Vargs; import java.awt.Dimension; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; import net.java.games.jogl.GL; import net.java.games.jogl.GLU; +import net.java.games.jogl.util.BufferUtils; import net.java.games.jogl.util.GLUT; /** @@ -52,7 +56,7 @@ public abstract class Main extends Base { GLU glu; GLUT glut = new GLUT(); - int[] d_8to24table = new int[256]; + public static int[] d_8to24table = new int[256]; int c_visible_lightmaps; int c_visible_textures; @@ -66,8 +70,8 @@ public abstract class Main extends Base { boolean qglActiveTextureARB = false; boolean qglPointParameterfEXT = false; boolean qglLockArraysEXT = false; - boolean qglUnlockArraysEXT = false; boolean qglMTexCoord2fSGIS = false; + boolean qwglSwapIntervalEXT = false; // ================= // abstract methods @@ -323,22 +327,22 @@ public abstract class Main extends Base { gl.glTexCoord2f(0, 1); Math3D.VectorMA(e.origin, -frame.origin_y, vup, point); Math3D.VectorMA(point, -frame.origin_x, vright, point); - gl.glVertex3fv(point); + gl.glVertex3f(point[0], point[1], point[2]); gl.glTexCoord2f(0, 0); Math3D.VectorMA(e.origin, frame.height - frame.origin_y, vup, point); Math3D.VectorMA(point, -frame.origin_x, vright, point); - gl.glVertex3fv(point); + gl.glVertex3f(point[0], point[1], point[2]); gl.glTexCoord2f(1, 0); Math3D.VectorMA(e.origin, frame.height - frame.origin_y, vup, point); Math3D.VectorMA(point, frame.width - frame.origin_x, vright, point); - gl.glVertex3fv(point); + gl.glVertex3f(point[0], point[1], point[2]); gl.glTexCoord2f(1, 1); Math3D.VectorMA(e.origin, -frame.origin_y, vup, point); Math3D.VectorMA(point, frame.width - frame.origin_x, vright, point); - gl.glVertex3fv(point); + gl.glVertex3f(point[0], point[1], point[2]); gl.glEnd(); @@ -375,7 +379,7 @@ public abstract class Main extends Base { R_RotateForEntity(currententity); gl.glDisable(GL.GL_TEXTURE_2D); - gl.glColor3fv(shadelight); + gl.glColor3f(shadelight[0], shadelight[1], shadelight[2]); // this replaces the TRIANGLE_FAN glut.glutWireCube(gl, 20); @@ -479,63 +483,63 @@ public abstract class Main extends Base { } gl.glDepthMask(true); // back to writing } - + /* ** GL_DrawParticles ** */ - void GL_DrawParticles(int num_particles, particle_t[] particles) { - particle_t p; - int i; + void GL_DrawParticles(int num_particles) { float[] up = { 0, 0, 0 }; float[] right = { 0, 0, 0 }; float scale; int color; + float origin_x, origin_y, origin_z; + + Math3D.VectorScale(vup, 1.5f, up); + Math3D.VectorScale(vright, 1.5f, right); + GL_Bind(r_particletexture.texnum); gl.glDepthMask(false); // no z buffering gl.glEnable(GL.GL_BLEND); GL_TexEnv(GL.GL_MODULATE); + gl.glBegin(GL.GL_TRIANGLES); - Math3D.VectorScale(vup, 1.5f, up); - Math3D.VectorScale(vright, 1.5f, right); + FloatBuffer sourceVertices = particle_t.vertexArray; + IntBuffer sourceColors = particle_t.colorArray; + for (int j = 0, i = 0; i < num_particles; i++) { + origin_x = sourceVertices.get(j++); + origin_y = sourceVertices.get(j++); + origin_z = sourceVertices.get(j++); - for (i = 0; i < num_particles; i++) { - p = particles[i]; // hack a scale up to keep particles from disapearing scale = - (p.origin[0] - r_origin[0]) * vpn[0] - + (p.origin[1] - r_origin[1]) * vpn[1] - + (p.origin[2] - r_origin[2]) * vpn[2]; + (origin_x - r_origin[0]) * vpn[0] + + (origin_y - r_origin[1]) * vpn[1] + + (origin_z - r_origin[2]) * vpn[2]; - if (scale < 20) - scale = 1; - else - scale = 1 + scale * 0.004f; - - color = d_8to24table[p.color]; + scale = (scale < 20) ? 1 : 1 + scale * 0.004f; + color = sourceColors.get(i); gl.glColor4ub( - (byte) ((color >> 0) & 0xff), - (byte) ((color >> 8) & 0xff), - (byte) ((color >> 16) & 0xff), - (byte) (p.alpha * 255)); - + (byte)((color >> 0) & 0xFF), + (byte)((color >> 8) & 0xFF), + (byte)((color >> 16) & 0xFF), + (byte)((color >> 24) & 0xFF) + ); + // first vertex gl.glTexCoord2f(0.0625f, 0.0625f); - gl.glVertex3fv(p.origin); - + gl.glVertex3f(origin_x, origin_y, origin_z); + // second vertex gl.glTexCoord2f(1.0625f, 0.0625f); - gl.glVertex3f(p.origin[0] + up[0] * scale, p.origin[1] + up[1] * scale, p.origin[2] + up[2] * scale); - + gl.glVertex3f(origin_x + up[0] * scale, origin_y + up[1] * scale, origin_z + up[2] * scale); + // third vertex gl.glTexCoord2f(0.0625f, 1.0625f); - gl.glVertex3f( - p.origin[0] + right[0] * scale, - p.origin[1] + right[1] * scale, - p.origin[2] + right[2] * scale); + gl.glVertex3f(origin_x + right[0] * scale, origin_y + right[1] * scale, origin_z + right[2] * scale); } - gl.glEnd(); + gl.glDisable(GL.GL_BLEND); gl.glColor4f(1, 1, 1, 1); gl.glDepthMask(true); // back to normal Z buffering @@ -550,29 +554,21 @@ public abstract class Main extends Base { void R_DrawParticles() { if (gl_ext_pointparameters.value != 0.0f && qglPointParameterfEXT) { - int color; - particle_t p; + gl.glEnableClientState(GL.GL_VERTEX_ARRAY); + gl.glVertexPointer(3, GL.GL_FLOAT, 0, particle_t.vertexArray); + gl.glEnableClientState(GL.GL_COLOR_ARRAY); + gl.glColorPointer(4, GL.GL_UNSIGNED_BYTE, 0, particle_t.colorArray); + gl.glDepthMask(false); gl.glEnable(GL.GL_BLEND); gl.glDisable(GL.GL_TEXTURE_2D); - gl.glPointSize(gl_particle_size.value); - - gl.glBegin(GL.GL_POINTS); - for (int i = 0; i < r_newrefdef.num_particles; i++) { - p = r_newrefdef.particles[i]; - color = d_8to24table[p.color]; - - gl.glColor4ub( - (byte) ((color >> 0) & 0xff), - (byte) ((color >> 8) & 0xff), - (byte) ((color >> 16) & 0xff), - (byte) (p.alpha * 255)); - - gl.glVertex3fv(p.origin); - } - gl.glEnd(); + + gl.glDrawArrays(GL.GL_POINTS, 0, r_newrefdef.num_particles); + + gl.glDisableClientState(GL.GL_COLOR_ARRAY); + gl.glDisableClientState(GL.GL_VERTEX_ARRAY); gl.glDisable(GL.GL_BLEND); gl.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); @@ -581,7 +577,7 @@ public abstract class Main extends Base { } else { - GL_DrawParticles(r_newrefdef.num_particles, r_newrefdef.particles); + GL_DrawParticles(r_newrefdef.num_particles); } } @@ -608,7 +604,7 @@ public abstract class Main extends Base { gl.glRotatef(-90, 1, 0, 0); // put Z going up gl.glRotatef(90, 0, 0, 1); // put Z going up - gl.glColor4fv(v_blend); + gl.glColor4f(v_blend[0], v_blend[1], v_blend[2], v_blend[3]); gl.glBegin(GL.GL_QUADS); @@ -958,7 +954,7 @@ public abstract class Main extends Base { protected void R_Register() { r_lefthand = ri.Cvar_Get("hand", "0", Globals.CVAR_USERINFO | Globals.CVAR_ARCHIVE); r_norefresh = ri.Cvar_Get("r_norefresh", "0", 0); - r_fullbright = ri.Cvar_Get("r_fullbright", "1", 0); + r_fullbright = ri.Cvar_Get("r_fullbright", "0", 0); r_drawentities = ri.Cvar_Get("r_drawentities", "1", 0); r_drawworld = ri.Cvar_Get("r_drawworld", "1", 0); r_novis = ri.Cvar_Get("r_novis", "0", 0); @@ -1007,7 +1003,7 @@ public abstract class Main extends Base { gl_vertex_arrays = ri.Cvar_Get("gl_vertex_arrays", "0", Globals.CVAR_ARCHIVE); gl_ext_swapinterval = ri.Cvar_Get("gl_ext_swapinterval", "1", Globals.CVAR_ARCHIVE); - gl_ext_palettedtexture = ri.Cvar_Get("gl_ext_palettedtexture", "1", Globals.CVAR_ARCHIVE); + gl_ext_palettedtexture = ri.Cvar_Get("gl_ext_palettedtexture", "0", Globals.CVAR_ARCHIVE); gl_ext_multitexture = ri.Cvar_Get("gl_ext_multitexture", "1", Globals.CVAR_ARCHIVE); gl_ext_pointparameters = ri.Cvar_Get("gl_ext_pointparameters", "1", Globals.CVAR_ARCHIVE); gl_ext_compiled_vertex_array = ri.Cvar_Get("gl_ext_compiled_vertex_array", "1", Globals.CVAR_ARCHIVE); @@ -1056,11 +1052,11 @@ public abstract class Main extends Base { int err; // enum rserr_t boolean fullscreen; - if (vid_fullscreen.modified && !gl_config.allow_cds) { - ri.Con_Printf(Defines.PRINT_ALL, "R_SetMode() - CDS not allowed with this driver\n"); - ri.Cvar_SetValue("vid_fullscreen", (vid_fullscreen.value > 0.0f) ? 0.0f : 1.0f); - vid_fullscreen.modified = false; - } +// if (vid_fullscreen.modified && !gl_config.allow_cds) { +// ri.Con_Printf(Defines.PRINT_ALL, "R_SetMode() - CDS not allowed with this driver\n"); +// ri.Cvar_SetValue("vid_fullscreen", (vid_fullscreen.value > 0.0f) ? 0.0f : 1.0f); +// vid_fullscreen.modified = false; +// } fullscreen = (vid_fullscreen.value > 0.0f); @@ -1237,25 +1233,24 @@ public abstract class Main extends Base { || gl_config.extensions_string.indexOf("GL_SGI_compiled_vertex_array") >= 0) { ri.Con_Printf(Defines.PRINT_ALL, "...enabling GL_EXT_compiled_vertex_array\n"); // qglLockArraysEXT = ( void * ) qwglGetProcAddress( "glLockArraysEXT" ); - qglLockArraysEXT = true; + if (gl_ext_compiled_vertex_array.value != 0.0f) + qglLockArraysEXT = true; + else + qglLockArraysEXT = false; // qglUnlockArraysEXT = ( void * ) qwglGetProcAddress( "glUnlockArraysEXT" ); - qglUnlockArraysEXT = true; + //qglUnlockArraysEXT = true; } else { ri.Con_Printf(Defines.PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n"); } - // #ifdef _WIN32 - // if ( strstr( gl_config.extensions_string, "WGL_EXT_swap_control" ) ) - // { - // qwglSwapIntervalEXT = ( BOOL (WINAPI *)(int)) qwglGetProcAddress( "wglSwapIntervalEXT" ); - // ri.Con_Printf( Defines.PRINT_ALL, "...enabling WGL_EXT_swap_control\n" ); - // } - // else - // { - // ri.Con_Printf( Defines.PRINT_ALL, "...WGL_EXT_swap_control not found\n" ); - // } - // #endif + if (gl_config.extensions_string.indexOf("WGL_EXT_swap_control") >= 0) { + qwglSwapIntervalEXT = true; + ri.Con_Printf(Defines.PRINT_ALL, "...enabling WGL_EXT_swap_control\n"); + } else { + qwglSwapIntervalEXT = false; + ri.Con_Printf(Defines.PRINT_ALL, "...WGL_EXT_swap_control not found\n"); + } if (gl_config.extensions_string.indexOf("GL_EXT_point_parameters") >= 0) { if (gl_ext_pointparameters.value != 0.0f) { @@ -1301,6 +1296,7 @@ public abstract class Main extends Base { } else { ri.Con_Printf(Defines.PRINT_ALL, "...ignoring GL_EXT_shared_texture_palette\n"); + qglColorTableEXT = false; } } else { @@ -1317,34 +1313,40 @@ public abstract class Main extends Base { qglMTexCoord2fSGIS = true; GL_TEXTURE0 = GL.GL_TEXTURE0_ARB; GL_TEXTURE1 = GL.GL_TEXTURE1_ARB; + Cvar.SetValue("r_fullbright", 1); } else { ri.Con_Printf(Defines.PRINT_ALL, "...ignoring GL_ARB_multitexture\n"); + Cvar.SetValue("r_fullbright", 0); } } else { ri.Con_Printf(Defines.PRINT_ALL, "...GL_ARB_multitexture not found\n"); + Cvar.SetValue("r_fullbright", 0); } if (gl_config.extensions_string.indexOf("GL_SGIS_multitexture") >= 0) { if (qglActiveTextureARB) { ri.Con_Printf(Defines.PRINT_ALL, "...GL_SGIS_multitexture deprecated in favor of ARB_multitexture\n"); - } - else if (gl_ext_multitexture.value != 0.0f) { + Cvar.SetValue("r_fullbright", 1); + } else if (gl_ext_multitexture.value != 0.0f) { ri.Con_Printf(Defines.PRINT_ALL, "...using GL_SGIS_multitexture\n"); // qglMTexCoord2fSGIS = ( void * ) qwglGetProcAddress( "glMTexCoord2fSGIS" ); // qglSelectTextureSGIS = ( void * ) qwglGetProcAddress( "glSelectTextureSGIS" ); qglSelectTextureSGIS = true; qglMTexCoord2fSGIS = true; + Cvar.SetValue("r_fullbright", 1); // //GL_TEXTURE0 = GL.GL_TEXTURE0_SGIS; // //GL_TEXTURE1 = GL.GL_TEXTURE1_SGIS; - } - else { + } else { ri.Con_Printf(Defines.PRINT_ALL, "...ignoring GL_SGIS_multitexture\n"); + Cvar.SetValue("r_fullbright", 0); } } else { ri.Con_Printf(Defines.PRINT_ALL, "...GL_SGIS_multitexture not found\n"); + if (!qglActiveTextureARB) + Cvar.SetValue("r_fullbright", 0); } GL_SetDefaultState(); @@ -1359,7 +1361,7 @@ public abstract class Main extends Base { ri.Con_Printf( Defines.PRINT_ALL, "glGetError() = 0x%x\n\t%s\n", - new Vargs(2).add(err).add(gl.glGetString(err))); + new Vargs(2).add(err).add("" + gl.glGetString(err))); return true; } @@ -1406,7 +1408,7 @@ public abstract class Main extends Base { // FIXME: only restart if CDS is required cvar_t ref; - ref = ri.Cvar_Get("vid_ref", "gl", 0); + ref = ri.Cvar_Get("vid_ref", "jogl", 0); ref.modified = true; } @@ -1511,26 +1513,22 @@ public abstract class Main extends Base { ============= */ protected void R_SetPalette(byte[] palette) { - - //assert(palette != null && palette.length == 768) : "byte palette[768] bug"; - // es darf auch null sein - + // 256 RGB values (768 bytes) + // or null int i; int color = 0; if (palette != null) { - + int j =0; for (i = 0; i < 256; i++) { - color = (palette[i * 3 + 0] << 0) & 0x000000FF; - color |= (palette[i * 3 + 1] << 8) & 0x0000FF00; - color |= (palette[i * 3 + 2] << 8) & 0x00FF0000; + color = (palette[j++] & 0xFF) << 0; + color |= (palette[j++] & 0xFF) << 8; + color |= (palette[j++] & 0xFF) << 16; color |= 0xFF000000; r_rawpalette[i] = color; } - } else { - for (i = 0; i < 256; i++) { r_rawpalette[i] = d_8to24table[i] | 0xff000000; } @@ -1543,6 +1541,9 @@ public abstract class Main extends Base { } static final int NUM_BEAM_SEGS = 6; + float[][] start_points = new float[NUM_BEAM_SEGS][3]; + // array of vec3_t + float[][] end_points = new float[NUM_BEAM_SEGS][3]; // array of vec3_t /* ** R_DrawBeam @@ -1556,10 +1557,6 @@ public abstract class Main extends Base { float[] direction = { 0, 0, 0 }; // vec3_t float[] normalized_direction = { 0, 0, 0 }; // vec3_t - float[][] start_points = new float[NUM_BEAM_SEGS][3]; - // array of vec3_t - float[][] end_points = new float[NUM_BEAM_SEGS][3]; // array of vec3_t - float[] oldorigin = { 0, 0, 0 }; // vec3_t float[] origin = { 0, 0, 0 }; // vec3_t @@ -1607,11 +1604,18 @@ public abstract class Main extends Base { gl.glColor4f(r, g, b, e.alpha); gl.glBegin(GL.GL_TRIANGLE_STRIP); + + float[] v; + for (i = 0; i < NUM_BEAM_SEGS; i++) { - gl.glVertex3fv(start_points[i]); - gl.glVertex3fv(end_points[i]); - gl.glVertex3fv(start_points[(i + 1) % NUM_BEAM_SEGS]); - gl.glVertex3fv(end_points[(i + 1) % NUM_BEAM_SEGS]); + v = start_points[i]; + gl.glVertex3f(v[0], v[1], v[2]); + v = end_points[i]; + gl.glVertex3f(v[0], v[1], v[2]); + v = start_points[(i + 1) % NUM_BEAM_SEGS]; + gl.glVertex3f(v[0], v[1], v[2]); + v = end_points[(i + 1) % NUM_BEAM_SEGS]; + gl.glVertex3f(v[0], v[1], v[2]); } gl.glEnd(); diff --git a/src/jake2/render/jogl/Mesh.java b/src/jake2/render/jogl/Mesh.java index 37e4445..991bf37 100644 --- a/src/jake2/render/jogl/Mesh.java +++ b/src/jake2/render/jogl/Mesh.java @@ -2,7 +2,7 @@ * Mesh.java * Copyright (C) 2003 * - * $Id: Mesh.java,v 1.3 2004-07-08 20:24:30 hzi Exp $ + * $Id: Mesh.java,v 1.4 2004-07-09 06:50:48 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -104,36 +104,36 @@ public abstract class Mesh extends Light { { int i; int lerpIndex = 0; - lerp.position(0); //PMM -- added RF_SHELL_DOUBLE, RF_SHELL_HALF_DAM if ( (currententity.flags & ( Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0 ) { float[] normal; + int j = 0; for (i=0 ; i < nverts; i++/* , v++, ov++, lerp+=4 */) { normal = r_avertexnormals[verts[i].lightnormalindex]; - lerp.put(move[0] + ov[i].v[0]*backv[0] + v[i].v[0]*frontv[0] + normal[0] * Defines.POWERSUIT_SCALE); - lerp.put(move[1] + ov[i].v[1]*backv[1] + v[i].v[1]*frontv[1] + normal[1] * Defines.POWERSUIT_SCALE); - lerp.put(move[2] + ov[i].v[2]*backv[2] + v[i].v[2]*frontv[2] + normal[2] * Defines.POWERSUIT_SCALE); - lerp.get(); + lerp.put(j++, move[0] + ov[i].v[0]*backv[0] + v[i].v[0]*frontv[0] + normal[0] * Defines.POWERSUIT_SCALE); + lerp.put(j++, move[1] + ov[i].v[1]*backv[1] + v[i].v[1]*frontv[1] + normal[1] * Defines.POWERSUIT_SCALE); + lerp.put(j++, move[2] + ov[i].v[2]*backv[2] + v[i].v[2]*frontv[2] + normal[2] * Defines.POWERSUIT_SCALE); } } else { + int j = 0; for (i=0 ; i < nverts; i++ /* , v++, ov++, lerp+=4 */) { - lerp.put(move[0] + ov[i].v[0]*backv[0] + v[i].v[0]*frontv[0]); - lerp.put(move[1] + ov[i].v[1]*backv[1] + v[i].v[1]*frontv[1]); - lerp.put(move[2] + ov[i].v[2]*backv[2] + v[i].v[2]*frontv[2]); - lerp.get(); + + lerp.put(j++, move[0] + ov[i].v[0]*backv[0] + v[i].v[0]*frontv[0]); + lerp.put(j++, move[1] + ov[i].v[1]*backv[1] + v[i].v[1]*frontv[1]); + lerp.put(j++, move[2] + ov[i].v[2]*backv[2] + v[i].v[2]*frontv[2]); } } } FloatBuffer colorArrayBuf = BufferUtils.newFloatBuffer(qfiles.MAX_VERTS * 4); - FloatBuffer vertexArrayBuf = BufferUtils.newFloatBuffer(qfiles.MAX_VERTS * 4); + FloatBuffer vertexArrayBuf = BufferUtils.newFloatBuffer(qfiles.MAX_VERTS * 3); boolean isFilled = false; float[] tmpVec = {0, 0, 0}; @@ -218,7 +218,7 @@ public abstract class Mesh extends Light { GL_LerpVerts( paliashdr.num_xyz, v, ov, verts, vertexArrayBuf, move, frontv, backv ); gl.glEnableClientState( GL.GL_VERTEX_ARRAY ); - gl.glVertexPointer( 3, GL.GL_FLOAT, 16, vertexArrayBuf ); // padded for SIMD + gl.glVertexPointer( 3, GL.GL_FLOAT, 0, vertexArrayBuf ); // PMM - added double damage shell if ( (currententity.flags & ( Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0) @@ -233,11 +233,15 @@ public abstract class Mesh extends Light { // // pre light everything // - colorArrayBuf.position(0); + FloatBuffer color = colorArrayBuf; + int j = 0; for ( i = 0; i < paliashdr.num_xyz; i++ ) { l = shadedots[verts[i].lightnormalindex]; - colorArrayBuf.put(l * shadelight[0]).put(l * shadelight[1]).put(l * shadelight[2]).put(alpha); + color.put(j++, l * shadelight[0]); + color.put(j++, l * shadelight[1]); + color.put(j++, l * shadelight[2]); + color.put(j++, alpha); } } @@ -294,13 +298,15 @@ public abstract class Mesh extends Light { gl.glEnd (); } - if ( qglUnlockArraysEXT ) + if ( qglLockArraysEXT ) gl.glUnlockArraysEXT(); } else { GL_LerpVerts( paliashdr.num_xyz, v, ov, verts, s_lerped, move, frontv, backv ); + float[] tmp; + while (true) { // get the vertex count and primitive type @@ -325,7 +331,8 @@ public abstract class Mesh extends Light { orderIndex += 3; gl.glColor4f( shadelight[0], shadelight[1], shadelight[2], alpha); - gl.glVertex3fv (s_lerped[index_xyz]); + tmp = s_lerped[index_xyz]; + gl.glVertex3f(tmp[0], tmp[1], tmp[2]); } while (--count != 0); } @@ -344,7 +351,8 @@ public abstract class Mesh extends Light { l = shadedots[verts[index_xyz].lightnormalindex]; gl.glColor4f (l* shadelight[0], l*shadelight[1], l*shadelight[2], alpha); - gl.glVertex3fv (s_lerped[index_xyz]); + tmp = s_lerped[index_xyz]; + gl.glVertex3f(tmp[0], tmp[1], tmp[2]); } while (--count != 0); } gl.glEnd (); @@ -384,6 +392,7 @@ public abstract class Mesh extends Light { height = -lheight + 1.0f; int orderIndex = 0; + int index = 0; while (true) { @@ -410,18 +419,20 @@ public abstract class Mesh extends Light { if ( gl_vertex_arrays.value != 0.0f ) { - vertexArrayBuf.position(order[orderIndex + 2] * 4); - vertexArrayBuf.get(point); + index = order[orderIndex + 2] * 3; + point[0] = vertexArrayBuf.get(index); + point[1] = vertexArrayBuf.get(index + 1); + point[2] = vertexArrayBuf.get(index + 2); } else { - System.arraycopy(s_lerped[order[orderIndex + 2]], 0, point, 0, 3); + Math3D.VectorCopy(s_lerped[order[orderIndex + 2]], point); } point[0] -= shadevector[0]*(point[2]+lheight); point[1] -= shadevector[1]*(point[2]+lheight); point[2] = height; - gl.glVertex3fv (point); + gl.glVertex3f(point[0], point[1], point[2]); orderIndex += 3; diff --git a/src/jake2/render/jogl/Misc.java b/src/jake2/render/jogl/Misc.java index 8f04a84..a1d2e70 100644 --- a/src/jake2/render/jogl/Misc.java +++ b/src/jake2/render/jogl/Misc.java @@ -2,7 +2,7 @@ * Misc.java * Copyright (C) 2003 * - * $Id: Misc.java,v 1.1 2004-07-07 19:59:41 hzi Exp $ + * $Id: Misc.java,v 1.2 2004-07-09 06:50:48 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -25,9 +25,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package jake2.render.jogl; -import net.java.games.jogl.GL; - import jake2.Defines; +import net.java.games.jogl.GL; +import net.java.games.jogl.WGL; /** * Misc @@ -249,13 +249,11 @@ public abstract class Misc extends Mesh { if ( gl_swapinterval.modified ) { gl_swapinterval.modified = false; - if ( !gl_state.stereo_enabled ) { -// #ifdef _WIN32 -// if ( qwglSwapIntervalEXT ) -// qwglSwapIntervalEXT( gl_swapinterval->value ); -// #endif + if (qwglSwapIntervalEXT) { + ((WGL)gl).wglSwapIntervalEXT((int)gl_swapinterval.value); + } } } } diff --git a/src/jake2/render/jogl/Model.java b/src/jake2/render/jogl/Model.java index 8c2cfc8..75357c3 100644 --- a/src/jake2/render/jogl/Model.java +++ b/src/jake2/render/jogl/Model.java @@ -2,7 +2,7 @@ * Model.java * Copyright (C) 2003 * - * $Id: Model.java,v 1.1 2004-07-07 19:59:42 hzi Exp $ + * $Id: Model.java,v 1.2 2004-07-09 06:50:48 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -517,6 +517,9 @@ public abstract class Model extends Surf { count = l.filelen / texinfo_t.SIZE; // out = Hunk_Alloc ( count*sizeof(*out)); out = new mtexinfo_t[count]; + for ( i=0 ; i<count ; i++) { + out[i] = new mtexinfo_t(); + } loadmodel.texinfo = out; loadmodel.numtexinfo = count; @@ -524,13 +527,10 @@ public abstract class Model extends Surf { ByteBuffer bb = ByteBuffer.wrap(mod_base, l.fileofs, l.filelen); bb.order(ByteOrder.LITTLE_ENDIAN); - for ( i=0 ; i<count ; i++) - { - in = new texinfo_t(bb); - out[i] = new mtexinfo_t(); - //for (j=0 ; j<8 ; j++) - out[i].vecs = in.vecs; + for ( i=0 ; i<count ; i++) { + in = new texinfo_t(bb); + out[i].vecs = in.vecs; out[i].flags = in.flags; next = in.nexttexinfo; if (next > 0) @@ -541,17 +541,14 @@ public abstract class Model extends Surf { name = "textures/" + in.texture + ".wal"; out[i].image = GL_FindImage(name, it_wall); - if (out[i].image == null) - { + if (out[i].image == null) { ri.Con_Printf(Defines.PRINT_ALL, "Couldn't load " + name + '\n'); out[i].image = r_notexture; } } // count animation frames - for (i=0 ; i<count ; i++) - { - // out = &loadmodel.texinfo[i]; + for (i=0 ; i<count ; i++) { out[i].numframes = 1; for (step = out[i].next ; (step != null) && (step != out[i]) ; step=step.next) out[i].numframes++; diff --git a/src/jake2/render/jogl/Surf.java b/src/jake2/render/jogl/Surf.java index 7f05332..54e0e77 100644 --- a/src/jake2/render/jogl/Surf.java +++ b/src/jake2/render/jogl/Surf.java @@ -2,7 +2,7 @@ * Surf.java * Copyright (C) 2003 * - * $Id: Surf.java,v 1.2 2004-07-08 20:24:30 hzi Exp $ + * $Id: Surf.java,v 1.3 2004-07-09 06:50:48 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -25,35 +25,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package jake2.render.jogl; -import java.awt.geom.AffineTransform; -import java.awt.image.AffineTransformOp; -import java.awt.image.BufferedImage; -import java.nio.ByteBuffer; +import jake2.Defines; +import jake2.client.*; +import jake2.game.cplane_t; +import jake2.render.*; +import jake2.util.Lib; +import jake2.util.Math3D; + import java.nio.ByteOrder; import java.nio.IntBuffer; import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; import net.java.games.jogl.GL; -import net.java.games.jogl.util.BufferUtils; - -import jake2.Defines; -import jake2.client.dlight_t; -import jake2.client.entity_t; -import jake2.client.lightstyle_t; -import jake2.game.cplane_t; -import jake2.imageio.ImageFrame; -import jake2.render.glpoly_t; -import jake2.render.image_t; -import jake2.render.medge_t; -import jake2.render.mleaf_t; -import jake2.render.mnode_t; -import jake2.render.model_t; -import jake2.render.msurface_t; -import jake2.render.mtexinfo_t; -import jake2.util.Lib; -import jake2.util.Math3D; /** * Surf @@ -92,7 +75,7 @@ public abstract class Surf extends Draw { // the lightmap texture data needs to be kept in // main memory so texsubimage can update properly - byte[] lightmap_buffer = new byte[4 * BLOCK_WIDTH * BLOCK_HEIGHT]; + IntBuffer lightmap_buffer = Lib.newIntBuffer(BLOCK_WIDTH * BLOCK_HEIGHT, ByteOrder.LITTLE_ENDIAN); public gllightmapstate_t() { @@ -129,7 +112,7 @@ public abstract class Surf extends Draw { // Light.java abstract void R_MarkLights (dlight_t light, int bit, mnode_t node); abstract void R_SetCacheState( msurface_t surf ); - abstract void R_BuildLightMap(msurface_t surf, ByteBuffer dest, int stride); + abstract void R_BuildLightMap(msurface_t surf, IntBuffer dest, int stride); /* ============================================================= @@ -178,7 +161,7 @@ public abstract class Surf extends Draw { { v = p.verts[i]; gl.glTexCoord2f(v[3], v[4]); - gl.glVertex3fv(v); + gl.glVertex3f(v[0], v[1], v[2]); } gl.glEnd(); } @@ -208,7 +191,7 @@ public abstract class Surf extends Draw { { v = p.verts[i]; gl.glTexCoord2f ((v[3] + scroll), v[4]); - gl.glVertex3fv( v ); + gl.glVertex3f(v[0], v[1], v[2]); } gl.glEnd (); } @@ -273,7 +256,7 @@ public abstract class Surf extends Draw { { v = p.verts[j]; gl.glTexCoord2f (v[5], v[6] ); - gl.glVertex3fv( v ); + gl.glVertex3f(v[0], v[1], v[2]); } gl.glEnd(); } @@ -290,7 +273,7 @@ public abstract class Surf extends Draw { { v = p.verts[j]; gl.glTexCoord2f (v[5] - soffset, v[6] - toffset ); - gl.glVertex3fv( v ); + gl.glVertex3f(v[0], v[1], v[2]); } gl.glEnd(); } @@ -399,7 +382,7 @@ public abstract class Surf extends Draw { for ( surf = gl_lms.lightmap_surfaces[0]; surf != null; surf = surf.lightmapchain ) { int smax, tmax; - ByteBuffer base; + IntBuffer base; smax = (surf.extents[0]>>4)+1; tmax = (surf.extents[1]>>4)+1; @@ -412,10 +395,10 @@ public abstract class Surf extends Draw { surf.dlight_s = lightPos.x; surf.dlight_t = lightPos.y; - base = ByteBuffer.wrap(gl_lms.lightmap_buffer); - base.position( ( surf.dlight_t * BLOCK_WIDTH + surf.dlight_s ) * LIGHTMAP_BYTES); + base = gl_lms.lightmap_buffer; + base.position(surf.dlight_t * BLOCK_WIDTH + surf.dlight_s ); - R_BuildLightMap (surf, base, BLOCK_WIDTH*LIGHTMAP_BYTES); + R_BuildLightMap (surf, base.slice(), BLOCK_WIDTH); } else { @@ -448,10 +431,10 @@ public abstract class Surf extends Draw { surf.dlight_s = lightPos.x; surf.dlight_t = lightPos.y; - base = ByteBuffer.wrap(gl_lms.lightmap_buffer); - base.position( ( surf.dlight_t * BLOCK_WIDTH + surf.dlight_s ) * LIGHTMAP_BYTES); + base = gl_lms.lightmap_buffer; + base.position(surf.dlight_t * BLOCK_WIDTH + surf.dlight_s ); - R_BuildLightMap (surf, base, BLOCK_WIDTH*LIGHTMAP_BYTES); + R_BuildLightMap (surf, base.slice(), BLOCK_WIDTH); } } @@ -476,7 +459,7 @@ public abstract class Surf extends Draw { gl.glDepthMask( true ); } - private ByteBuffer temp2 = BufferUtils.newByteBuffer(34 * 34 * 4); + private IntBuffer temp2 = Lib.newIntBuffer(34 * 34, ByteOrder.LITTLE_ENDIAN); /* ================ @@ -562,7 +545,7 @@ public abstract class Surf extends Draw { smax = (fa.extents[0]>>4)+1; tmax = (fa.extents[1]>>4)+1; - R_BuildLightMap( fa, temp2, smax*4 ); + R_BuildLightMap( fa, temp2, smax); R_SetCacheState( fa ); GL_Bind( gl_state.lightmap_textures + fa.lightmaptexturenum ); @@ -717,7 +700,7 @@ public abstract class Surf extends Draw { } // direct buffer - ByteBuffer temp = BufferUtils.newByteBuffer(128 * 128 * 4); + private IntBuffer temp = Lib.newIntBuffer(128 * 128, ByteOrder.LITTLE_ENDIAN); void GL_RenderLightmappedPoly( msurface_t surf ) { @@ -766,7 +749,7 @@ public abstract class Surf extends Draw { smax = (surf.extents[0]>>4)+1; tmax = (surf.extents[1]>>4)+1; - R_BuildLightMap( surf, temp, smax*4 ); + R_BuildLightMap( surf, temp, smax); R_SetCacheState( surf ); GL_MBind( GL_TEXTURE1, gl_state.lightmap_textures + surf.lightmaptexturenum ); @@ -785,7 +768,7 @@ public abstract class Surf extends Draw { smax = (surf.extents[0]>>4)+1; tmax = (surf.extents[1]>>4)+1; - R_BuildLightMap( surf, temp, smax*4 ); + R_BuildLightMap( surf, temp, smax); GL_MBind( GL_TEXTURE1, gl_state.lightmap_textures + 0 ); @@ -825,7 +808,7 @@ public abstract class Surf extends Draw { gl.glMultiTexCoord2fARB(GL_TEXTURE1, v[5], v[6]); //gglMTexCoord2fSGIS( GL_TEXTURE0, v[3], v[4]); //gglMTexCoord2fSGIS( GL_TEXTURE1, v[5], v[6]); - gl.glVertex3fv(v); + gl.glVertex3f(v[0], v[1], v[2]); } gl.glEnd (); } @@ -843,7 +826,7 @@ public abstract class Surf extends Draw { gl.glMultiTexCoord2fARB(GL_TEXTURE1, v[5], v[6]); //gglMTexCoord2fSGIS( GL_TEXTURE0, v[3], v[4]); //gglMTexCoord2fSGIS( GL_TEXTURE1, v[5], v[6]); - gl.glVertex3fv(v); + gl.glVertex3f(v[0], v[1], v[2]); } gl.glEnd (); } @@ -879,7 +862,7 @@ public abstract class Surf extends Draw { gl.glMultiTexCoord2fARB(GL_TEXTURE1, v[5], v[6]); // qglMTexCoord2fSGIS( GL_TEXTURE0, (v[3]+scroll), v[4]); // qglMTexCoord2fSGIS( GL_TEXTURE1, v[5], v[6]); - gl.glVertex3fv(v); + gl.glVertex3f(v[0], v[1], v[2]); } gl.glEnd(); } @@ -899,7 +882,7 @@ public abstract class Surf extends Draw { gl.glMultiTexCoord2fARB(GL_TEXTURE1, v[5], v[6]); //gglMTexCoord2fSGIS( GL_TEXTURE0, v[3], v[4]); //gglMTexCoord2fSGIS( GL_TEXTURE1, v[5], v[6]); - gl.glVertex3fv(v); + gl.glVertex3f(v[0], v[1], v[2]); } gl.glEnd (); } @@ -1558,7 +1541,7 @@ public abstract class Surf extends Draw { void GL_CreateSurfaceLightmap(msurface_t surf) { int smax, tmax; - ByteBuffer base; + IntBuffer base; if ( (surf.flags & (Defines.SURF_DRAWSKY | Defines.SURF_DRAWTURB)) != 0) return; @@ -1585,13 +1568,12 @@ public abstract class Surf extends Draw { surf.lightmaptexturenum = gl_lms.current_lightmap_texture; - // base = gl_lms.lightmap_buffer; - base = ByteBuffer.wrap(gl_lms.lightmap_buffer); - int basep = (surf.light_t * BLOCK_WIDTH + surf.light_s) * LIGHTMAP_BYTES; + int basep = (surf.light_t * BLOCK_WIDTH + surf.light_s);// * LIGHTMAP_BYTES; + base = gl_lms.lightmap_buffer; base.position(basep); R_SetCacheState( surf ); - R_BuildLightMap(surf, base.slice(), BLOCK_WIDTH * LIGHTMAP_BYTES); + R_BuildLightMap(surf, base.slice(), BLOCK_WIDTH); } lightstyle_t[] lightstyles; @@ -1713,26 +1695,26 @@ public abstract class Surf extends Draw { } - ImageFrame frame; + //ImageFrame frame; - void debugLightmap(byte[] buf, int w, int h, float scale) { - IntBuffer pix = ByteBuffer.wrap(buf).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer(); - - int[] pixel = new int[w * h]; - - pix.get(pixel); - - BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR); - image.setRGB(0, 0, w, h, pixel, 0, w); - AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(scale, scale), AffineTransformOp.TYPE_NEAREST_NEIGHBOR); - BufferedImage tmp = op.filter(image, null); - - if (frame == null) { - frame = new ImageFrame(null); - frame.show(); - } - frame.showImage(tmp); - - } +// void debugLightmap(byte[] buf, int w, int h, float scale) { +// IntBuffer pix = ByteBuffer.wrap(buf).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer(); +// +// int[] pixel = new int[w * h]; +// +// pix.get(pixel); +// +// BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR); +// image.setRGB(0, 0, w, h, pixel, 0, w); +// AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(scale, scale), AffineTransformOp.TYPE_NEAREST_NEIGHBOR); +// BufferedImage tmp = op.filter(image, null); +// +// if (frame == null) { +// frame = new ImageFrame(null); +// frame.show(); +// } +// frame.showImage(tmp); +// +// } } diff --git a/src/jake2/render/jogl/Warp.java b/src/jake2/render/jogl/Warp.java index 8ccb93a..6dc5145 100644 --- a/src/jake2/render/jogl/Warp.java +++ b/src/jake2/render/jogl/Warp.java @@ -2,7 +2,7 @@ * Warp.java * Copyright (C) 2003 * - * $Id: Warp.java,v 1.3 2004-07-08 20:24:30 hzi Exp $ + * $Id: Warp.java,v 1.4 2004-07-09 06:50:48 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -313,7 +313,7 @@ public abstract class Warp extends Model { t *= (1.0f/64); gl.glTexCoord2f (s, t); - gl.glVertex3fv( v ); + gl.glVertex3f(v[0], v[1], v[2]); } gl.glEnd (); } @@ -612,7 +612,7 @@ public abstract class Warp extends Model { t = 1.0f - t; gl.glTexCoord2f (s, t); - gl.glVertex3fv( v ); + gl.glVertex3f(v[0], v[1], v[2]); } /* diff --git a/src/jake2/render/model_t.java b/src/jake2/render/model_t.java index 5807568..5ee824c 100644 --- a/src/jake2/render/model_t.java +++ b/src/jake2/render/model_t.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 20.11.2003 by RST. -// $Id: model_t.java,v 1.2 2004-07-08 15:58:48 hzi Exp $ +// $Id: model_t.java,v 1.3 2004-07-09 06:50:47 hzi Exp $ package jake2.render; @@ -119,7 +119,7 @@ public class model_t implements Cloneable { // Math3D.VectorClear(mins); Math3D.VectorClear(maxs); - radius = 0;; + radius = 0; // // solid volume for clipping diff --git a/src/jake2/render/msurface_t.java b/src/jake2/render/msurface_t.java index c6247d9..9a64c88 100644 --- a/src/jake2/render/msurface_t.java +++ b/src/jake2/render/msurface_t.java @@ -19,11 +19,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 20.11.2003 by RST. -// $Id: msurface_t.java,v 1.2 2004-07-08 20:24:29 hzi Exp $ +// $Id: msurface_t.java,v 1.3 2004-07-09 06:50:47 hzi Exp $ package jake2.render; import java.nio.ByteBuffer; +import java.util.Arrays; import jake2.game.*; import jake2.qcommon.texinfo_t; @@ -67,23 +68,25 @@ public class msurface_t public void clear() { visframe = 0; - //plane = null; + plane = null; + plane = new cplane_t(); flags = 0; firstedge = 0; numedges = 0; - texturemins[0] = texturemins[1] = 0; + texturemins[0] = texturemins[1] = -1; extents[0] = extents[1] = 0; light_s = light_t = 0; dlight_s = dlight_t = 0; - //polys = null; + polys = null; texturechain = null; lightmapchain = null; - //texinfo = null; + //texinfo = new mtexinfo_t(); + texinfo.clear(); dlightframe = 0; dlightbits = 0; @@ -98,6 +101,6 @@ public class msurface_t { cached_light[i] = 0; } - //samples = null; + if (samples != null) samples.clear(); } } diff --git a/src/jake2/render/mtexinfo_t.java b/src/jake2/render/mtexinfo_t.java index a78af9f..d545210 100644 --- a/src/jake2/render/mtexinfo_t.java +++ b/src/jake2/render/mtexinfo_t.java @@ -19,10 +19,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 20.11.2003 by RST. -// $Id: mtexinfo_t.java,v 1.1 2004-07-07 19:59:35 hzi Exp $ +// $Id: mtexinfo_t.java,v 1.2 2004-07-09 06:50:47 hzi Exp $ package jake2.render; +import java.util.Arrays; + public class mtexinfo_t { // [s/t][xyz offset] public float vecs[][] = { @@ -33,4 +35,15 @@ public class mtexinfo_t { public int numframes; public mtexinfo_t next; // animation chain public image_t image; + + public void clear() { + Arrays.fill(vecs[0], 0); + Arrays.fill(vecs[1], 0); + + flags = 0; + numframes = 0; + next = null; + image = null; + } + } diff --git a/src/jake2/server/SV_CCMDS.java b/src/jake2/server/SV_CCMDS.java index 6c71224..76e348d 100644 --- a/src/jake2/server/SV_CCMDS.java +++ b/src/jake2/server/SV_CCMDS.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 18.01.2004 by RST. -// $Id: SV_CCMDS.java,v 1.2 2004-07-08 15:58:45 hzi Exp $ +// $Id: SV_CCMDS.java,v 1.3 2004-07-09 06:50:49 hzi Exp $ package jake2.server; @@ -228,7 +228,6 @@ public class SV_CCMDS extends SV_ENTS { f1.close(); } catch (IOException e1) { - // TODO Auto-generated catch block e1.printStackTrace(); } return; @@ -627,7 +626,7 @@ public class SV_CCMDS extends SV_ENTS { // copy off the level to the autosave slot if (0 == dedicated.value) { - //TODO: SV_WriteServerFile! + //TODO: SV_WriteServerFile. //SV_WriteServerFile(true); //SV_CopySaveGame("current", "save0"); @@ -658,7 +657,7 @@ public class SV_CCMDS extends SV_ENTS { } sv.state = ss_dead; // don't save current level when changing - //TODO: RST: disabled for debugging + //TODO: savegame //SV_WipeSavegame("current"); SV_GameMap_f(); } diff --git a/src/jake2/server/SV_GAME.java b/src/jake2/server/SV_GAME.java index 8f6eec4..9e3d8d2 100644 --- a/src/jake2/server/SV_GAME.java +++ b/src/jake2/server/SV_GAME.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 14.01.2004 by RST. -// $Id: SV_GAME.java,v 1.4 2004-07-08 20:56:54 hzi Exp $ +// $Id: SV_GAME.java,v 1.5 2004-07-09 06:50:49 hzi Exp $ package jake2.server; @@ -308,11 +308,11 @@ public class SV_GAME extends SV_INIT { } public static void PF_StartSound(edict_t entity, int channel, int sound_num, float volume, float attenuation, float timeofs) { + if (null == entity) return; - - //TODO: impl SV_StartSound SV_SEND.SV_StartSound (null, entity, channel, sound_num, volume, attenuation, timeofs); + } //============================================== diff --git a/src/jake2/server/SV_INIT.java b/src/jake2/server/SV_INIT.java index b4b4ee6..631e898 100644 --- a/src/jake2/server/SV_INIT.java +++ b/src/jake2/server/SV_INIT.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 14.01.2004 by RST. -// $Id: SV_INIT.java,v 1.3 2004-07-08 20:24:30 hzi Exp $ +// $Id: SV_INIT.java,v 1.4 2004-07-09 06:50:49 hzi Exp $ package jake2.server; @@ -250,16 +250,16 @@ public class SV_INIT extends Globals { sv.name=server; sv.configstrings[CS_NAME] = server; - CM.intwrap checksum_iw = new CM.intwrap(checksum); + int iw[] = {checksum}; if (serverstate != ss_game) { - sv.models[1] = CM.CM_LoadMap("", false, checksum_iw); // no real map + sv.models[1] = CM.CM_LoadMap("", false, iw); // no real map } else { - sv.configstrings[CS_MODELS + 1] = "maps/" + server + ".bsp"; - sv.models[1] = CM.CM_LoadMap(sv.configstrings[CS_MODELS + 1], false, checksum_iw); + sv.configstrings[CS_MODELS + 1] = "maps/" + server + ".bsp"; + sv.models[1] = CM.CM_LoadMap(sv.configstrings[CS_MODELS + 1], false, iw); } - checksum = checksum_iw.i; + checksum = iw[0]; sv.configstrings[CS_MAPCHECKSUM] = "" + checksum; // @@ -302,7 +302,7 @@ public class SV_INIT extends Globals { // set serverinfo variable Cvar.FullSet("mapname", sv.name, CVAR_SERVERINFO | CVAR_NOSET); - Com.Printf("-------------------------------------\n"); + //Com.Printf("-------------------------------------\n"); } /* diff --git a/src/jake2/server/SV_MAIN.java b/src/jake2/server/SV_MAIN.java index 464b056..510decc 100644 --- a/src/jake2/server/SV_MAIN.java +++ b/src/jake2/server/SV_MAIN.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 13.01.2004 by RST. -// $Id: SV_MAIN.java,v 1.2 2004-07-08 15:58:45 hzi Exp $ +// $Id: SV_MAIN.java,v 1.3 2004-07-09 06:50:49 hzi Exp $ package jake2.server; @@ -476,7 +476,7 @@ public class SV_MAIN extends SV_GAME { Cmd.TokenizeString(s.toCharArray(), false); c = Cmd.Argv(0); - Com.Printf("Packet " + NET.AdrToString(Netchan.net_from) + " : " + c + "\n"); + //Com.Printf("Packet " + NET.AdrToString(Netchan.net_from) + " : " + c + "\n"); //Com.Printf(Lib.hexDump(net_message.data, 64, false) + "\n"); if (0 == strcmp(c, "ping")) diff --git a/src/jake2/server/SV_USER.java b/src/jake2/server/SV_USER.java index c6e355e..65e5262 100644 --- a/src/jake2/server/SV_USER.java +++ b/src/jake2/server/SV_USER.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 17.01.2004 by RST. -// $Id: SV_USER.java,v 1.3 2004-07-08 20:24:30 hzi Exp $ +// $Id: SV_USER.java,v 1.4 2004-07-09 06:50:49 hzi Exp $ package jake2.server; @@ -29,7 +29,8 @@ import jake2.util.Lib; import java.io.IOException; -public class SV_USER extends SV_SEND { +public class SV_USER extends SV_SEND +{ static edict_t sv_player; @@ -47,14 +48,17 @@ public class SV_USER extends SV_SEND { SV_BeginDemoServer ================== */ - public static void SV_BeginDemoserver() { + public static void SV_BeginDemoserver() + { String name; - name = "demos/" + sv.name; - try { - sv.demofile = FS.FOpenFile(name); + name= "demos/" + sv.name; + try + { + sv.demofile= FS.FOpenFile(name); } - catch (IOException e) { + catch (IOException e) + { Com.Error(ERR_DROP, "Couldn't open " + name + "\n"); } if (sv.demofile == null) @@ -69,20 +73,23 @@ public class SV_USER extends SV_SEND { This will be sent on the initial connection and upon each server load. ================ */ - public static void SV_New_f() { + public static void SV_New_f() + { String gamedir; int playernum; edict_t ent; Com.DPrintf("New() from " + sv_client.name + "\n"); - if (sv_client.state != cs_connected) { + if (sv_client.state != cs_connected) + { Com.Printf("New not valid -- already spawned\n"); return; } // demo servers just dump the file message - if (sv.state == ss_demo) { + if (sv.state == ss_demo) + { SV_BeginDemoserver(); return; } @@ -91,7 +98,7 @@ public class SV_USER extends SV_SEND { // serverdata needs to go over for all types of servers // to make sure the protocol is right, and to set the gamedir // - gamedir = Cvar.VariableString("gamedir"); + gamedir= Cvar.VariableString("gamedir"); // send the serverdata MSG.WriteByte(sv_client.netchan.message, svc_serverdata); @@ -101,10 +108,10 @@ public class SV_USER extends SV_SEND { MSG.WriteString(sv_client.netchan.message, gamedir); if (sv.state == ss_cinematic || sv.state == ss_pic) - playernum = -1; + playernum= -1; else //playernum = sv_client - svs.clients; - playernum = sv_client.serverindex; + playernum= sv_client.serverindex; MSG.WriteShort(sv_client.netchan.message, playernum); @@ -114,12 +121,13 @@ public class SV_USER extends SV_SEND { // // game server // - if (sv.state == ss_game) { + if (sv.state == ss_game) + { // set up the entity for the client - ent = SV_GAME.ge.edicts[playernum + 1]; - ent.s.number = playernum + 1; - sv_client.edict = ent; - sv_client.lastcmd = new usercmd_t(); + ent= SV_GAME.ge.edicts[playernum + 1]; + ent.s.number= playernum + 1; + sv_client.edict= ent; + sv_client.lastcmd= new usercmd_t(); // begin fetching configstrings MSG.WriteByte(sv_client.netchan.message, svc_stufftext); @@ -133,29 +141,34 @@ public class SV_USER extends SV_SEND { SV_Configstrings_f ================== */ - public static void SV_Configstrings_f() { + public static void SV_Configstrings_f() + { int start; Com.DPrintf("Configstrings() from " + sv_client.name + "\n"); - if (sv_client.state != cs_connected) { + if (sv_client.state != cs_connected) + { Com.Printf("configstrings not valid -- already spawned\n"); return; } // handle the case of a level changing while a client was connecting - if (atoi(Cmd.Argv(1)) != svs.spawncount) { + if (atoi(Cmd.Argv(1)) != svs.spawncount) + { Com.Printf("SV_Configstrings_f from different level\n"); SV_New_f(); return; } - start = atoi(Cmd.Argv(2)); + start= atoi(Cmd.Argv(2)); // write a packet full of data - while (sv_client.netchan.message.cursize < MAX_MSGLEN / 2 && start < MAX_CONFIGSTRINGS) { - if (sv.configstrings[start] != null && sv.configstrings[start].length() != 0) { + while (sv_client.netchan.message.cursize < MAX_MSGLEN / 2 && start < MAX_CONFIGSTRINGS) + { + if (sv.configstrings[start] != null && sv.configstrings[start].length() != 0) + { MSG.WriteByte(sv_client.netchan.message, svc_configstring); MSG.WriteShort(sv_client.netchan.message, start); MSG.WriteString(sv_client.netchan.message, sv.configstrings[start]); @@ -165,11 +178,13 @@ public class SV_USER extends SV_SEND { // send next command - if (start == MAX_CONFIGSTRINGS) { + if (start == MAX_CONFIGSTRINGS) + { MSG.WriteByte(sv_client.netchan.message, svc_stufftext); MSG.WriteString(sv_client.netchan.message, "cmd baselines " + svs.spawncount + " 0\n"); } - else { + else + { MSG.WriteByte(sv_client.netchan.message, svc_stufftext); MSG.WriteString(sv_client.netchan.message, "cmd configstrings " + svs.spawncount + " " + start + "\n"); } @@ -180,35 +195,40 @@ public class SV_USER extends SV_SEND { SV_Baselines_f ================== */ - public static void SV_Baselines_f() { + public static void SV_Baselines_f() + { int start; entity_state_t nullstate; entity_state_t base; Com.DPrintf("Baselines() from " + sv_client.name + "\n"); - if (sv_client.state != cs_connected) { + if (sv_client.state != cs_connected) + { Com.Printf("baselines not valid -- already spawned\n"); return; } // handle the case of a level changing while a client was connecting - if (atoi(Cmd.Argv(1)) != svs.spawncount) { + if (atoi(Cmd.Argv(1)) != svs.spawncount) + { Com.Printf("SV_Baselines_f from different level\n"); SV_New_f(); return; } - start = atoi(Cmd.Argv(2)); + start= atoi(Cmd.Argv(2)); //memset (&nullstate, 0, sizeof(nullstate)); - nullstate = new entity_state_t(null); + nullstate= new entity_state_t(null); // write a packet full of data - while (sv_client.netchan.message.cursize < MAX_MSGLEN / 2 && start < MAX_EDICTS) { - base = sv.baselines[start]; - if (base.modelindex != 0 || base.sound != 0 || base.effects != 0) { + while (sv_client.netchan.message.cursize < MAX_MSGLEN / 2 && start < MAX_EDICTS) + { + base= sv.baselines[start]; + if (base.modelindex != 0 || base.sound != 0 || base.effects != 0) + { MSG.WriteByte(sv_client.netchan.message, svc_spawnbaseline); MSG.WriteDeltaEntity(nullstate, base, sv_client.netchan.message, true, true); } @@ -217,11 +237,13 @@ public class SV_USER extends SV_SEND { // send next command - if (start == MAX_EDICTS) { + if (start == MAX_EDICTS) + { MSG.WriteByte(sv_client.netchan.message, svc_stufftext); MSG.WriteString(sv_client.netchan.message, "precache " + svs.spawncount + "\n"); } - else { + else + { MSG.WriteByte(sv_client.netchan.message, svc_stufftext); MSG.WriteString(sv_client.netchan.message, "cmd baselines " + svs.spawncount + " " + start + "\n"); } @@ -232,17 +254,19 @@ public class SV_USER extends SV_SEND { SV_Begin_f ================== */ - public static void SV_Begin_f() { + public static void SV_Begin_f() + { Com.DPrintf("Begin() from " + sv_client.name + "\n"); // handle the case of a level changing while a client was connecting - if (atoi(Cmd.Argv(1)) != svs.spawncount) { + if (atoi(Cmd.Argv(1)) != svs.spawncount) + { Com.Printf("SV_Begin_f from different level\n"); SV_New_f(); return; } - sv_client.state = cs_spawned; + sv_client.state= cs_spawned; // call the game begin function SV_GAME.ge.ClientBegin(sv_player); @@ -257,7 +281,8 @@ public class SV_USER extends SV_SEND { SV_NextDownload_f ================== */ - public static void SV_NextDownload_f() { + public static void SV_NextDownload_f() + { int r; int percent; int size; @@ -265,18 +290,18 @@ public class SV_USER extends SV_SEND { if (sv_client.download == null) return; - r = sv_client.downloadsize - sv_client.downloadcount; + r= sv_client.downloadsize - sv_client.downloadcount; if (r > 1024) - r = 1024; + r= 1024; MSG.WriteByte(sv_client.netchan.message, svc_download); MSG.WriteShort(sv_client.netchan.message, r); sv_client.downloadcount += r; - size = sv_client.downloadsize; + size= sv_client.downloadsize; if (size == 0) - size = 1; - percent = sv_client.downloadcount * 100 / size; + size= 1; + percent= sv_client.downloadcount * 100 / size; MSG.WriteByte(sv_client.netchan.message, percent); SZ.Write(sv_client.netchan.message, sv_client.download, sv_client.downloadcount - r, r); @@ -284,7 +309,7 @@ public class SV_USER extends SV_SEND { return; FS.FreeFile(sv_client.download); - sv_client.download = null; + sv_client.download= null; } /* @@ -292,14 +317,15 @@ public class SV_USER extends SV_SEND { SV_BeginDownload_f ================== */ - public static void SV_BeginDownload_f() { + public static void SV_BeginDownload_f() + { String name; - int offset = 0; + int offset= 0; - name = Cmd.Argv(1); + name= Cmd.Argv(1); if (Cmd.Argc() > 2) - offset = atoi(Cmd.Argv(2)); // downloaded offset + offset= atoi(Cmd.Argv(2)); // downloaded offset // hacked by zoid to allow more conrol over download // first off, no .. or global allow check @@ -310,9 +336,11 @@ public class SV_USER extends SV_SEND { || name.charAt(0) == '/' // next up, skin check || (name.startsWith("players/") && 0 == allow_download_players.value) // now models || (name.startsWith("models/") && 0 == allow_download_models.value) // now sounds - || (name.startsWith("sound/") && 0 == allow_download_sounds.value) // now maps (note special case for maps, must not be in pak) + || (name.startsWith("sound/") + && 0 == allow_download_sounds.value) // now maps (note special case for maps, must not be in pak) || (name.startsWith("maps/") && 0 == allow_download_maps.value) // MUST be in a subdirectory - || name.indexOf('/') == -1) { // don't allow anything with .. path + || name.indexOf('/') == -1) + { // don't allow anything with .. path MSG.WriteByte(sv_client.netchan.message, svc_download); MSG.WriteShort(sv_client.netchan.message, -1); MSG.WriteByte(sv_client.netchan.message, 0); @@ -322,20 +350,22 @@ public class SV_USER extends SV_SEND { if (sv_client.download != null) FS.FreeFile(sv_client.download); - sv_client.download = FS.LoadFile(name); - sv_client.downloadsize = sv_client.download.length; - sv_client.downloadcount = offset; + sv_client.download= FS.LoadFile(name); + sv_client.downloadsize= sv_client.download.length; + sv_client.downloadcount= offset; if (offset > sv_client.downloadsize) - sv_client.downloadcount = sv_client.downloadsize; + sv_client.downloadcount= sv_client.downloadsize; if (sv_client.download == null // special check for maps, if it came from a pak file, don't allow // download ZOID - || (name.startsWith("maps/") && FS.file_from_pak != 0)) { + || (name.startsWith("maps/") && FS.file_from_pak != 0)) + { Com.DPrintf("Couldn't download " + name + " to " + sv_client.name + "\n"); - if (sv_client.download != null) { + if (sv_client.download != null) + { FS.FreeFile(sv_client.download); - sv_client.download = null; + sv_client.download= null; } MSG.WriteByte(sv_client.netchan.message, svc_download); @@ -357,7 +387,8 @@ public class SV_USER extends SV_SEND { The client is going to disconnect, so remove the connection immediately ================= */ - public static void SV_Disconnect_f() { + public static void SV_Disconnect_f() + { // SV_EndRedirect (); SV_DropClient(sv_client); } @@ -369,11 +400,13 @@ public class SV_USER extends SV_SEND { Dumps the serverinfo info string ================== */ - public static void SV_ShowServerinfo_f() { + public static void SV_ShowServerinfo_f() + { Info.Print(Cvar.Serverinfo()); } - public static void SV_Nextserver() { + public static void SV_Nextserver() + { String v; //ZOID, ss_pic can be nextserver'd in coop mode @@ -381,11 +414,12 @@ public class SV_USER extends SV_SEND { return; // can't nextserver while playing a normal game svs.spawncount++; // make sure another doesn't sneak in - v = Cvar.VariableString("nextserver"); + v= Cvar.VariableString("nextserver"); //if (!v[0]) if (v.length() == 0) Cbuf.AddText("killserver\n"); - else { + else + { Cbuf.AddText(v); Cbuf.AddText("\n"); } @@ -400,8 +434,10 @@ public class SV_USER extends SV_SEND { to the next server, ================== */ - public static void SV_Nextserver_f() { - if (Lib.atoi(Cmd.Argv(1)) != svs.spawncount) { + public static void SV_Nextserver_f() + { + if (Lib.atoi(Cmd.Argv(1)) != svs.spawncount) + { Com.DPrintf("Nextserver() from wrong level, from " + sv_client.name + "\n"); return; // leftover from last server } @@ -411,58 +447,80 @@ public class SV_USER extends SV_SEND { SV_Nextserver(); } - public static class ucmd_t { - public ucmd_t(String n, Runnable r) { - name = n; - this.r = r; + public static class ucmd_t + { + public ucmd_t(String n, Runnable r) + { + name= n; + this.r= r; } String name; Runnable r; } - static ucmd_t u1 = new ucmd_t("new", new Runnable() { - public void run() { + static ucmd_t u1= new ucmd_t("new", new Runnable() + { + public void run() + { SV_New_f(); } }); - static ucmd_t ucmds[] = { + static ucmd_t ucmds[]= { // auto issued - new ucmd_t("new", new Runnable() { public void run() { SV_New_f(); + new ucmd_t("new", new Runnable() + { public void run() + { SV_New_f(); } - }), new ucmd_t("configstrings", new Runnable() { - public void run() { + }), new ucmd_t("configstrings", new Runnable() + { + public void run() + { SV_Configstrings_f(); } - }), new ucmd_t("baselines", new Runnable() { - public void run() { + }), new ucmd_t("baselines", new Runnable() + { + public void run() + { SV_Baselines_f(); } - }), new ucmd_t("begin", new Runnable() { - public void run() { + }), new ucmd_t("begin", new Runnable() + { + public void run() + { SV_Begin_f(); } - }), new ucmd_t("nextserver", new Runnable() { - public void run() { + }), new ucmd_t("nextserver", new Runnable() + { + public void run() + { SV_Nextserver_f(); } - }), new ucmd_t("disconnect", new Runnable() { - public void run() { + }), new ucmd_t("disconnect", new Runnable() + { + public void run() + { SV_Disconnect_f(); } }), // issued by hand at client consoles - new ucmd_t("info", new Runnable() { - public void run() { + new ucmd_t("info", new Runnable() + { + public void run() + { SV_ShowServerinfo_f(); } - }), new ucmd_t("download", new Runnable() { - public void run() { + }), new ucmd_t("download", new Runnable() + { + public void run() + { SV_BeginDownload_f(); } - }), new ucmd_t("nextdl", new Runnable() { - public void run() { + }), new ucmd_t("nextdl", new Runnable() + { + public void run() + { SV_NextDownload_f(); } }) @@ -473,23 +531,26 @@ public class SV_USER extends SV_SEND { SV_ExecuteUserCommand ================== */ - public static void SV_ExecuteUserCommand(String s) { - ucmd_t u = null; + public static void SV_ExecuteUserCommand(String s) + { + ucmd_t u= null; Cmd.TokenizeString(s.toCharArray(), true); - sv_player = sv_client.edict; + sv_player= sv_client.edict; // SV_BeginRedirect (RD_CLIENT); - int i=0; - for (; i < ucmds.length; i++) { - u = ucmds[i]; - if (0 == strcmp(Cmd.Argv(0), u.name)) { + int i= 0; + for (; i < ucmds.length; i++) + { + u= ucmds[i]; + if (0 == strcmp(Cmd.Argv(0), u.name)) + { u.r.run(); break; } } - + if (i == ucmds.length && sv.state == ss_game) SV_GAME.ge.ClientCommand(sv_player); @@ -504,10 +565,12 @@ public class SV_USER extends SV_SEND { =========================================================================== */ - public static void SV_ClientThink(client_t cl, usercmd_t cmd) { + public static void SV_ClientThink(client_t cl, usercmd_t cmd) + { cl.commandMsec -= cmd.msec & 0xFF; - if (cl.commandMsec < 0 && sv_enforcetime.value != 0) { + if (cl.commandMsec < 0 && sv_enforcetime.value != 0) + { Com.DPrintf("commandMsec underflow from " + cl.name + "\n"); return; } @@ -515,7 +578,7 @@ public class SV_USER extends SV_SEND { SV_GAME.ge.ClientThink(cl.edict, cmd); } - public static final int MAX_STRINGCMDS = 8; + public static final int MAX_STRINGCMDS= 8; /* =================== SV_ExecuteClientMessage @@ -523,12 +586,13 @@ public class SV_USER extends SV_SEND { The current net_message is parsed for the given client =================== */ - public static void SV_ExecuteClientMessage(client_t cl) { + public static void SV_ExecuteClientMessage(client_t cl) + { int c; String s; - usercmd_t nullcmd = new usercmd_t(); - usercmd_t oldest = new usercmd_t(), oldcmd = new usercmd_t(), newcmd = new usercmd_t(); + usercmd_t nullcmd= new usercmd_t(); + usercmd_t oldest= new usercmd_t(), oldcmd= new usercmd_t(), newcmd= new usercmd_t(); int net_drop; int stringCmdCount; int checksum, calculatedChecksum; @@ -536,26 +600,29 @@ public class SV_USER extends SV_SEND { boolean move_issued; int lastframe; - sv_client = cl; - sv_player = sv_client.edict; + sv_client= cl; + sv_player= sv_client.edict; // only allow one move command - move_issued = false; - stringCmdCount = 0; + move_issued= false; + stringCmdCount= 0; - while (true) { - if (net_message.readcount > net_message.cursize) { + while (true) + { + if (net_message.readcount > net_message.cursize) + { Com.Printf("SV_ReadClientMessage: bad read:\n"); Com.Printf(Lib.hexDump(net_message.data, 32, false)); SV_DropClient(cl); return; } - c = MSG.ReadByte(net_message); + c= MSG.ReadByte(net_message); if (c == -1) break; - switch (c) { + switch (c) + { default : Com.Printf("SV_ReadClientMessage: unknown command char\n"); SV_DropClient(cl); @@ -565,7 +632,7 @@ public class SV_USER extends SV_SEND { break; case clc_userinfo : - cl.userinfo = MSG.ReadString(net_message); + cl.userinfo= MSG.ReadString(net_message); SV_MAIN.SV_UserinfoChanged(cl); break; @@ -573,41 +640,43 @@ public class SV_USER extends SV_SEND { if (move_issued) return; // someone is trying to cheat... - move_issued = true; - checksumIndex = net_message.readcount; - checksum = MSG.ReadByte(net_message); - lastframe = MSG.ReadLong(net_message); - - if (lastframe != cl.lastframe) { - cl.lastframe = lastframe; - if (cl.lastframe > 0) { - cl.frame_latency[cl.lastframe & (LATENCY_COUNTS - 1)] = + move_issued= true; + checksumIndex= net_message.readcount; + checksum= MSG.ReadByte(net_message); + lastframe= MSG.ReadLong(net_message); + + if (lastframe != cl.lastframe) + { + cl.lastframe= lastframe; + if (cl.lastframe > 0) + { + cl.frame_latency[cl.lastframe & (LATENCY_COUNTS - 1)]= svs.realtime - cl.frames[cl.lastframe & UPDATE_MASK].senttime; } } //memset (nullcmd, 0, sizeof(nullcmd)); - nullcmd = new usercmd_t(); + nullcmd= new usercmd_t(); MSG.ReadDeltaUsercmd(net_message, nullcmd, oldest); MSG.ReadDeltaUsercmd(net_message, oldest, oldcmd); MSG.ReadDeltaUsercmd(net_message, oldcmd, newcmd); - if (cl.state != cs_spawned) { - cl.lastframe = -1; + if (cl.state != cs_spawned) + { + cl.lastframe= -1; break; } // if the checksum fails, ignore the rest of the packet - calculatedChecksum = 0; - /* - = Com.BlockSequenceCRCByte( - net_message.data + checksumIndex + 1, + calculatedChecksum= + Com.BlockSequenceCRCByte( + net_message.data, checksumIndex + 1, net_message.readcount - checksumIndex - 1, cl.netchan.incoming_sequence); - */ - if (calculatedChecksum != checksum) { + if ((calculatedChecksum &0xff) != checksum) + { Com.DPrintf( "Failed command checksum for " + cl.name @@ -621,14 +690,17 @@ public class SV_USER extends SV_SEND { return; } - if (0 == sv_paused.value) { - net_drop = cl.netchan.dropped; - if (net_drop < 20) { + if (0 == sv_paused.value) + { + net_drop= cl.netchan.dropped; + if (net_drop < 20) + { //if (net_drop > 2) // Com.Printf ("drop %i\n", net_drop); - while (net_drop > 2) { + while (net_drop > 2) + { SV_ClientThink(cl, cl.lastcmd); net_drop--; @@ -648,7 +720,7 @@ public class SV_USER extends SV_SEND { break; case clc_stringcmd : - s = MSG.ReadString(net_message); + s= MSG.ReadString(net_message); // malicious users may try using too many string commands if (++stringCmdCount < MAX_STRINGCMDS) diff --git a/src/jake2/server/SV_WORLD.java b/src/jake2/server/SV_WORLD.java index 4e78084..2eb2ca6 100644 --- a/src/jake2/server/SV_WORLD.java +++ b/src/jake2/server/SV_WORLD.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 07.01.2000 by RST. -// $Id: SV_WORLD.java,v 1.3 2004-07-08 20:24:30 hzi Exp $ +// $Id: SV_WORLD.java,v 1.4 2004-07-09 06:50:49 hzi Exp $ package jake2.server; @@ -48,14 +48,13 @@ public class SV_WORLD extends SV_CCMDS //=============================================================================== // - public static void initNodes() { - for (int n = 0; n < AREA_NODES; n++) - sv_areanodes[n] = new areanode_t(); + for (int n= 0; n < AREA_NODES; n++) + sv_areanodes[n]= new areanode_t(); } - public static areanode_t sv_areanodes[] = new areanode_t[AREA_NODES]; + public static areanode_t sv_areanodes[]= new areanode_t[AREA_NODES]; static { initNodes(); @@ -70,21 +69,21 @@ public class SV_WORLD extends SV_CCMDS // ClearLink is used for new headnodes public static void ClearLink(link_t l) { - l.prev = l.next = l; + l.prev= l.next= l; } public static void RemoveLink(link_t l) { - l.next.prev = l.prev; - l.prev.next = l.next; + l.next.prev= l.prev; + l.prev.next= l.next; } public static void InsertLinkBefore(link_t l, link_t before) { - l.next = before; - l.prev = before.prev; - l.prev.next = l; - l.next.prev = l; + l.next= before; + l.prev= before.prev; + l.prev.next= l; + l.next.prev= l; } /* @@ -97,10 +96,10 @@ public class SV_WORLD extends SV_CCMDS public static areanode_t SV_CreateAreaNode(int depth, float[] mins, float[] maxs) { areanode_t anode; - float[] size = { 0, 0, 0 }; - float[] mins1 = { 0, 0, 0 }, maxs1 = { 0, 0, 0 }, mins2 = { 0, 0, 0 }, maxs2 = { 0, 0, 0 }; + float[] size= { 0, 0, 0 }; + float[] mins1= { 0, 0, 0 }, maxs1= { 0, 0, 0 }, mins2= { 0, 0, 0 }, maxs2= { 0, 0, 0 }; - anode = sv_areanodes[sv_numareanodes]; + anode= sv_areanodes[sv_numareanodes]; // just for debugging (rst) VectorCopy(mins, anode.mins_rst); @@ -113,27 +112,27 @@ public class SV_WORLD extends SV_CCMDS if (depth == AREA_DEPTH) { - anode.axis = -1; - anode.children[0] = anode.children[1] = null; + anode.axis= -1; + anode.children[0]= anode.children[1]= null; return anode; } VectorSubtract(maxs, mins, size); if (size[0] > size[1]) - anode.axis = 0; + anode.axis= 0; else - anode.axis = 1; + anode.axis= 1; - anode.dist = 0.5f * (maxs[anode.axis] + mins[anode.axis]); + anode.dist= 0.5f * (maxs[anode.axis] + mins[anode.axis]); VectorCopy(mins, mins1); VectorCopy(mins, mins2); VectorCopy(maxs, maxs1); VectorCopy(maxs, maxs2); - maxs1[anode.axis] = mins2[anode.axis] = anode.dist; + maxs1[anode.axis]= mins2[anode.axis]= anode.dist; - anode.children[0] = SV_CreateAreaNode(depth + 1, mins2, maxs2); - anode.children[1] = SV_CreateAreaNode(depth + 1, mins1, maxs1); + anode.children[0]= SV_CreateAreaNode(depth + 1, mins2, maxs2); + anode.children[1]= SV_CreateAreaNode(depth + 1, mins1, maxs1); return anode; } @@ -147,7 +146,7 @@ public class SV_WORLD extends SV_CCMDS public static void SV_ClearWorld() { initNodes(); - sv_numareanodes = 0; + sv_numareanodes= 0; SV_CreateAreaNode(0, sv.models[1].mins, sv.models[1].maxs); /* @@ -178,7 +177,7 @@ public class SV_WORLD extends SV_CCMDS if (null == ent.area.prev) return; // not linked in anywhere RemoveLink(ent.area); - ent.area.prev = ent.area.next = null; + ent.area.prev= ent.area.next= null; } /* @@ -186,18 +185,18 @@ public class SV_WORLD extends SV_CCMDS SV_LinkEdict =============== */ - public static final int MAX_TOTAL_ENT_LEAFS = 128; - + public static final int MAX_TOTAL_ENT_LEAFS= 128; + private static int leafs[]= new int[MAX_TOTAL_ENT_LEAFS]; + private static int clusters[]= new int[MAX_TOTAL_ENT_LEAFS]; + public static void SV_LinkEdict(edict_t ent) { areanode_t node; - // TODO: make static instead of new - int leafs[] = new int[MAX_TOTAL_ENT_LEAFS]; - int clusters[] = new int[MAX_TOTAL_ENT_LEAFS]; + int num_leafs; int j, k; int area; - int topnode = 0; + int topnode= 0; if (ent.area.prev != null) SV_UnlinkEdict(ent); // unlink from old position @@ -214,54 +213,54 @@ public class SV_WORLD extends SV_CCMDS // encode the size into the entity_state for client prediction if (ent.solid == SOLID_BBOX && 0 == (ent.svflags & SVF_DEADMONSTER)) { // assume that x/y are equal and symetric - int i = (int) (ent.maxs[0] / 8); + int i= (int) (ent.maxs[0] / 8); if (i < 1) - i = 1; + i= 1; if (i > 31) - i = 31; + i= 31; // z is not symetric - j = (int) ((-ent.mins[2]) / 8); + j= (int) ((-ent.mins[2]) / 8); if (j < 1) - j = 1; + j= 1; if (j > 31) - j = 31; + j= 31; // and z maxs can be negative... - k = (int) ((ent.maxs[2] + 32) / 8); + k= (int) ((ent.maxs[2] + 32) / 8); if (k < 1) - k = 1; + k= 1; if (k > 63) - k = 63; + k= 63; - ent.s.solid = (k << 10) | (j << 5) | i; + ent.s.solid= (k << 10) | (j << 5) | i; } else if (ent.solid == SOLID_BSP) { - ent.s.solid = 31; // a solid_bbox will never create this value + ent.s.solid= 31; // a solid_bbox will never create this value } else - ent.s.solid = 0; + ent.s.solid= 0; // set the abs box if (ent.solid == SOLID_BSP && (ent.s.angles[0] != 0 || ent.s.angles[1] != 0 || ent.s.angles[2] != 0)) { // expand for rotation float max, v; - max = 0; - for (int i = 0; i < 3; i++) + max= 0; + for (int i= 0; i < 3; i++) { - v = Math.abs(ent.mins[i]); + v= Math.abs(ent.mins[i]); if (v > max) - max = v; - v = Math.abs(ent.maxs[i]); + max= v; + v= Math.abs(ent.maxs[i]); if (v > max) - max = v; + max= v; } - for (int i = 0; i < 3; i++) + for (int i= 0; i < 3; i++) { - ent.absmin[i] = ent.s.origin[i] - max; - ent.absmax[i] = ent.s.origin[i] + max; + ent.absmin[i]= ent.s.origin[i] - max; + ent.absmax[i]= ent.s.origin[i] + max; } } else @@ -281,62 +280,65 @@ public class SV_WORLD extends SV_CCMDS ent.absmax[2]++; // link to PVS leafs - ent.num_clusters = 0; - ent.areanum = 0; - ent.areanum2 = 0; + ent.num_clusters= 0; + ent.areanum= 0; + ent.areanum2= 0; //get all leafs, including solids - CM.intwrap iw = new CM.intwrap(topnode); + int iw[] = {topnode}; - num_leafs = CM.CM_BoxLeafnums(ent.absmin, ent.absmax, leafs, MAX_TOTAL_ENT_LEAFS, iw); + num_leafs= CM.CM_BoxLeafnums(ent.absmin, ent.absmax, leafs, MAX_TOTAL_ENT_LEAFS, iw); - topnode = iw.i; + topnode= iw[0]; // set areas - for (int i = 0; i < num_leafs; i++) + for (int i= 0; i < num_leafs; i++) { - clusters[i] = CM.CM_LeafCluster(leafs[i]); - area = CM.CM_LeafArea(leafs[i]); + clusters[i]= CM.CM_LeafCluster(leafs[i]); + area= CM.CM_LeafArea(leafs[i]); if (area != 0) - { // doors may legally straggle two areas, + { + // doors may legally straggle two areas, // but nothing should evern need more than that if (ent.areanum != 0 && ent.areanum != area) { if (ent.areanum2 != 0 && ent.areanum2 != area && sv.state == ss_loading) Com.DPrintf("Object touching 3 areas at " + ent.absmin[0] + " " + ent.absmin[1] + " " + ent.absmin[2] + "\n"); - ent.areanum2 = area; + ent.areanum2= area; } else - ent.areanum = area; + ent.areanum= area; } } if (num_leafs >= MAX_TOTAL_ENT_LEAFS) - { // assume we missed some leafs, and mark by headnode - ent.num_clusters = -1; - ent.headnode = topnode; + { + // assume we missed some leafs, and mark by headnode + ent.num_clusters= -1; + ent.headnode= topnode; } else { - ent.num_clusters = 0; - for (int i = 0; i < num_leafs; i++) + ent.num_clusters= 0; + for (int i= 0; i < num_leafs; i++) { if (clusters[i] == -1) continue; // not a visible leaf - for (j = 0; j < i; j++) + for (j= 0; j < i; j++) if (clusters[j] == clusters[i]) break; if (j == i) { if (ent.num_clusters == MAX_ENT_CLUSTERS) - { // assume we missed some leafs, and mark by headnode - ent.num_clusters = -1; - ent.headnode = topnode; + { + // assume we missed some leafs, and mark by headnode + ent.num_clusters= -1; + ent.headnode= topnode; break; } - ent.clusternums[ent.num_clusters++] = clusters[i]; + ent.clusternums[ent.num_clusters++]= clusters[i]; } } } @@ -352,16 +354,16 @@ public class SV_WORLD extends SV_CCMDS return; // find the first node that the ent's box crosses - node = sv_areanodes[0]; + node= sv_areanodes[0]; while (true) { if (node.axis == -1) break; if (ent.absmin[node.axis] > node.dist) - node = node.children[0]; + node= node.children[0]; else if (ent.absmax[node.axis] < node.dist) - node = node.children[1]; + node= node.children[1]; else break; // crosses the node } @@ -386,19 +388,18 @@ public class SV_WORLD extends SV_CCMDS edict_t check; int count; - count = 0; + count= 0; // touch linked edicts if (area_type == AREA_SOLID) - start = node.solid_edicts; + start= node.solid_edicts; else - start = node.trigger_edicts; + start= node.trigger_edicts; - for (l = start.next; l != start; l = next) + for (l= start.next; l != start; l= next) { - next = l.next; - check = //EDICT_FROM_AREA(l); - (edict_t) l.o; + next= l.next; + check= (edict_t) l.o; if (check.solid == SOLID_NOT) continue; // deactivated @@ -416,7 +417,7 @@ public class SV_WORLD extends SV_CCMDS return; } - area_list[area_count] = check; + area_list[area_count]= check; area_count++; } @@ -438,57 +439,53 @@ public class SV_WORLD extends SV_CCMDS */ public static int SV_AreaEdicts(float[] mins, float[] maxs, edict_t list[], int maxcount, int areatype) { - area_mins = mins; - area_maxs = maxs; - area_list = list; - area_count = 0; - area_maxcount = maxcount; - area_type = areatype; + area_mins= mins; + area_maxs= maxs; + area_list= list; + area_count= 0; + area_maxcount= maxcount; + area_type= areatype; SV_AreaEdicts_r(sv_areanodes[0]); - /* - Com.Printf("found edicts in area:" + area_count + "\n"); - for (int n = 0; n < area_count; n++) { - Com.Printf("%4i : %25s", new Vargs().add(n).add(list[n].classname)); - } - */ return area_count; } //=========================================================================== + private static edict_t touch[]= new edict_t[MAX_EDICTS]; /* ============= SV_PointContents ============= */ + public static int SV_PointContents(float[] p) { - // TODO: make static instead new - edict_t touch[] = new edict_t[MAX_EDICTS], hit; + edict_t hit; + int i, num; int contents, c2; int headnode; float angles[]; // get base contents from world - contents = CM.PointContents(p, sv.models[1].headnode); + contents= CM.PointContents(p, sv.models[1].headnode); // or in contents from all the other entities - num = SV_AreaEdicts(p, p, touch, MAX_EDICTS, AREA_SOLID); + num= SV_AreaEdicts(p, p, touch, MAX_EDICTS, AREA_SOLID); - for (i = 0; i < num; i++) + for (i= 0; i < num; i++) { - hit = touch[i]; + hit= touch[i]; // might intersect, so do an exact clip - headnode = SV_HullForEntity(hit); - angles = hit.s.angles; + headnode= SV_HullForEntity(hit); + angles= hit.s.angles; if (hit.solid != SOLID_BSP) - angles = vec3_origin; // boxes don't rotate + angles= vec3_origin; // boxes don't rotate - c2 = CM.TransformedPointContents(p, headnode, hit.s.origin, hit.s.angles); + c2= CM.TransformedPointContents(p, headnode, hit.s.origin, hit.s.angles); contents |= c2; } @@ -514,7 +511,7 @@ public class SV_WORLD extends SV_CCMDS // decide which clipping hull to use, based on the size if (ent.solid == SOLID_BSP) { // explicit hulls in the BSP model - model = sv.models[ent.s.modelindex]; + model= sv.models[ent.s.modelindex]; if (null == model) Com.Error(ERR_FATAL, "MOVETYPE_PUSH with a non bsp model"); @@ -535,23 +532,23 @@ public class SV_WORLD extends SV_CCMDS ==================== */ + private static edict_t touchlist[]= new edict_t[MAX_EDICTS]; public static void SV_ClipMoveToEntities(moveclip_t clip) { int i, num; - // TODO: make static instead of new - edict_t touchlist[] = new edict_t[MAX_EDICTS]; + edict_t touch; trace_t trace; int headnode; float angles[]; - num = SV_AreaEdicts(clip.boxmins, clip.boxmaxs, touchlist, MAX_EDICTS, AREA_SOLID); + num= SV_AreaEdicts(clip.boxmins, clip.boxmaxs, touchlist, MAX_EDICTS, AREA_SOLID); // be careful, it is possible to have an entity in this // list removed before we get to it (killtriggered) - for (i = 0; i < num; i++) + for (i= 0; i < num; i++) { - touch = touchlist[i]; + touch= touchlist[i]; if (touch.solid == SOLID_NOT) continue; if (touch == clip.passedict) @@ -570,13 +567,13 @@ public class SV_WORLD extends SV_CCMDS continue; // might intersect, so do an exact clip - headnode = SV_HullForEntity(touch); - angles = touch.s.angles; + headnode= SV_HullForEntity(touch); + angles= touch.s.angles; if (touch.solid != SOLID_BSP) - angles = vec3_origin; // boxes don't rotate + angles= vec3_origin; // boxes don't rotate if ((touch.svflags & SVF_MONSTER) != 0) - trace = + trace= CM.TransformedBoxTrace( clip.start, clip.end, @@ -587,7 +584,7 @@ public class SV_WORLD extends SV_CCMDS touch.s.origin, angles); else - trace = + trace= CM.TransformedBoxTrace( clip.start, clip.end, @@ -600,17 +597,17 @@ public class SV_WORLD extends SV_CCMDS if (trace.allsolid || trace.startsolid || trace.fraction < clip.trace.fraction) { - trace.ent = touch; + trace.ent= touch; if (clip.trace.startsolid) { - clip.trace = trace; - clip.trace.startsolid = true; + clip.trace= trace; + clip.trace.startsolid= true; } else clip.trace.set(trace); } else if (trace.startsolid) - clip.trace.startsolid = true; + clip.trace.startsolid= true; } } @@ -623,17 +620,17 @@ public class SV_WORLD extends SV_CCMDS { int i; - for (i = 0; i < 3; i++) + for (i= 0; i < 3; i++) { if (end[i] > start[i]) { - boxmins[i] = start[i] + mins[i] - 1; - boxmaxs[i] = end[i] + maxs[i] + 1; + boxmins[i]= start[i] + mins[i] - 1; + boxmaxs[i]= end[i] + maxs[i] + 1; } else { - boxmins[i] = end[i] + mins[i] - 1; - boxmaxs[i] = start[i] + maxs[i] + 1; + boxmins[i]= end[i] + mins[i] - 1; + boxmaxs[i]= start[i] + maxs[i] + 1; } } @@ -651,27 +648,27 @@ public class SV_WORLD extends SV_CCMDS */ public static trace_t SV_Trace(float[] start, float[] mins, float[] maxs, float[] end, edict_t passedict, int contentmask) { - moveclip_t clip = new moveclip_t(); + moveclip_t clip= new moveclip_t(); if (mins == null) - mins = vec3_origin; + mins= vec3_origin; if (maxs == null) - maxs = vec3_origin; + maxs= vec3_origin; //memset ( clip, 0, sizeof ( moveclip_t ) ); // clip to world - clip.trace = CM.BoxTrace(start, end, mins, maxs, 0, contentmask); - clip.trace.ent = ge.edicts[0]; + clip.trace= CM.BoxTrace(start, end, mins, maxs, 0, contentmask); + clip.trace.ent= ge.edicts[0]; if (clip.trace.fraction == 0) return clip.trace; // blocked by the world - clip.contentmask = contentmask; - clip.start = start; - clip.end = end; - clip.mins = mins; - clip.maxs = maxs; - clip.passedict = passedict; + clip.contentmask= contentmask; + clip.start= start; + clip.end= end; + clip.mins= mins; + clip.maxs= maxs; + clip.passedict= passedict; VectorCopy(mins, clip.mins2); VectorCopy(maxs, clip.maxs2); diff --git a/src/jake2/sound/S.java b/src/jake2/sound/S.java index c696501..55588b5 100644 --- a/src/jake2/sound/S.java +++ b/src/jake2/sound/S.java @@ -2,7 +2,7 @@ * S.java * Copyright (C) 2003 * - * $Id: S.java,v 1.1 2004-07-08 20:56:49 hzi Exp $ + * $Id: S.java,v 1.2 2004-07-09 06:50:48 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -184,4 +184,8 @@ public class S { public static void StopAllSounds() { impl.StopAllSounds(); } + + public static String getDriverName() { + return impl.getName(); + } } diff --git a/src/jake2/sound/WaveLoader.java b/src/jake2/sound/WaveLoader.java new file mode 100644 index 0000000..020ab52 --- /dev/null +++ b/src/jake2/sound/WaveLoader.java @@ -0,0 +1,302 @@ +/* + * SND_MEM.java + * Copyright (C) 2004 + * + * $Id: WaveLoader.java,v 1.1 2004-07-09 06:50:48 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.sound; + +import jake2.Defines; +import jake2.qcommon.Com; +import jake2.qcommon.FS; +import jake2.sys.Sys; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +/** + * SND_MEM + */ +public class WaveLoader { + + private static final AudioFormat sampleFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 22050, 16, 1, 2, 22050, false); + + /* + ============== + S_LoadSound + ============== + */ + public static sfxcache_t LoadSound(sfx_t s) { + String namebuffer; + byte[] data; + wavinfo_t info; + int len; + float stepscale; + sfxcache_t sc = null; + int size; + String name; + + if (s.name.charAt(0) == '*') + return null; + + // see if still in memory + sc = s.cache; + if (sc != null) + return sc; + + // load it in + if (s.truename != null) + name = s.truename; + else + name = s.name; + + if (name.charAt(0) == '#') + namebuffer = name.substring(1); + + else + namebuffer = "sound/" + name; + + data = FS.LoadFile(namebuffer); + + if (data == null) { + Com.DPrintf("Couldn't load " + namebuffer + "\n"); + return null; + } + size = data.length; + + info = GetWavinfo(s.name, data, size); + + AudioInputStream in = null; + AudioInputStream out = null; + try { + in = AudioSystem.getAudioInputStream(new ByteArrayInputStream(data)); + if (in.getFormat().getSampleSizeInBits() == 8) { + in = convertTo16bit(in); + } + out = AudioSystem.getAudioInputStream(sampleFormat, in); + int l = (int)out.getFrameLength(); + sc = s.cache = new sfxcache_t(l*2); + sc.length = l; + int c = out.read(sc.data, 0, l * 2); + out.close(); + in.close(); + } catch (Exception e) { + Com.Printf("Couldn't load " + namebuffer + "\n"); + return null; + } + + sc.loopstart = info.loopstart * ((int)sampleFormat.getSampleRate() / info.rate); + sc.speed = (int)sampleFormat.getSampleRate(); + sc.width = sampleFormat.getSampleSizeInBits() / 8; + sc.stereo = 0; + + data = null; + + return sc; + } + + static AudioInputStream convertTo16bit(AudioInputStream in) throws IOException { + AudioFormat format = in.getFormat(); + int length = (int)in.getFrameLength(); + byte[] samples = new byte[2*length]; + + for (int i = 0; i < length; i++) { + in.read(samples, 2*i+1, 1); + samples[2*i+1] -= 128; + } + in.close(); + + AudioFormat newformat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, format.getSampleRate(), 16, format.getChannels(), 2, format.getFrameRate(), false); + return new AudioInputStream(new ByteArrayInputStream(samples), newformat, length); + } + + /* + =============================================================================== + + WAV loading + + =============================================================================== + */ + + static byte[] data_b; + static int data_p; + static int iff_end; + static int last_chunk; + static int iff_data; + static int iff_chunk_len; + + + static short GetLittleShort() { + int val = 0; + val = data_b[data_p] & 0xFF; + data_p++; + val |= ((data_b[data_p] & 0xFF) << 8); + data_p++; + return (short)val; + } + + static int GetLittleLong() { + int val = 0; + val = data_b[data_p] & 0xFF; + data_p++; + val |= ((data_b[data_p] & 0xFF) << 8); + data_p++; + val |= ((data_b[data_p] & 0xFF) << 16); + data_p++; + val |= ((data_b[data_p] & 0xFF) << 24); + data_p++; + return val; + } + + static void FindNextChunk(String name) { + while (true) { + data_p = last_chunk; + + if (data_p >= iff_end) { // didn't find the chunk + data_p = 0; + return; + } + + data_p += 4; + + iff_chunk_len = GetLittleLong(); + + if (iff_chunk_len < 0) { + data_p = 0; + return; + } + if (iff_chunk_len > 1024*1024) + Sys.Error("FindNextChunk: length is past the 1 meg sanity limit"); + + data_p -= 8; + last_chunk = data_p + 8 + ((iff_chunk_len + 1) & ~1); + String s = new String(data_b, data_p, 4); + if (s.equals(name)) + return; + } + } + + static void FindChunk(String name) { + last_chunk = iff_data; + FindNextChunk(name); + } + + /* + ============ + GetWavinfo + ============ + */ + static wavinfo_t GetWavinfo(String name, byte[] wav, int wavlength) { + wavinfo_t info = new wavinfo_t(); + int i; + int format; + int samples; + + if (wav == null) + return info; + + iff_data = 0; + iff_end = wavlength; + data_b = wav; + + // find "RIFF" chunk + FindChunk("RIFF"); + String s = new String(data_b, data_p + 8, 4); + if (!s.equals("WAVE")) { + Com.Printf("Missing RIFF/WAVE chunks\n"); + return info; + } + + // get "fmt " chunk + iff_data = data_p + 12; + // DumpChunks (); + + FindChunk("fmt "); + if (data_p == 0) { + Com.Printf("Missing fmt chunk\n"); + return info; + } + data_p += 8; + format = GetLittleShort(); + if (format != 1) { + Com.Printf("Microsoft PCM format only\n"); + return info; + } + + info.channels = GetLittleShort(); + info.rate = GetLittleLong(); + data_p += 4 + 2; + info.width = GetLittleShort() / 8; + + // get cue chunk + FindChunk("cue "); + if (data_p != 0) { + data_p += 32; + info.loopstart = GetLittleLong(); + // Com_Printf("loopstart=%d\n", sfx->loopstart); + + // if the next chunk is a LIST chunk, look for a cue length marker + FindNextChunk("LIST"); + if (data_p != 0) { + s = new String(data_b, data_p + 28, 4); + if (s.equals("MARK")) { // this is not a proper parse, but it works with cooledit... + data_p += 24; + i = GetLittleLong(); // samples in loop + info.samples = info.loopstart + i; + // Com_Printf("looped length: %i\n", i); + } + } + } else + info.loopstart = -1; + + // find data chunk + FindChunk("data"); + if (data_p == 0) { + Com.Printf("Missing data chunk\n"); + return info; + } + + data_p += 4; + samples = GetLittleLong() / info.width; + + if (info.samples != 0) { + if (samples < info.samples) + Com.Error(Defines.ERR_DROP, "Sound " + name + " has a bad loop length"); + } else + info.samples = samples; + + info.dataofs = data_p; + + return info; + } + + static class wavinfo_t { + int rate; + int width; + int channels; + int loopstart; + int samples; + int dataofs; // chunk starts this many bytes from file start + } +} diff --git a/src/jake2/sound/joal/Channel.java b/src/jake2/sound/joal/Channel.java new file mode 100644 index 0000000..ced496f --- /dev/null +++ b/src/jake2/sound/joal/Channel.java @@ -0,0 +1,84 @@ +/* + * Created on Jun 19, 2004 + * + * Copyright (C) 2003 + * + * $Id: Channel.java,v 1.1 2004-07-09 06:50:52 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.sound.joal; + +/** + * Channel + * + * @author cwei + */ +public class Channel { + + final static int LISTENER = 0; + final static int FIXED = 1; + final static int DYNAMIC = 2; + + int entnum; + int entchannel; + int bufferId; + float rolloff; + boolean autosound = false; + int sourceId; + boolean active = false; + boolean modified = false; + boolean bufferChanged = false; + + // sound attributes + int type; + int entity; + float[] origin = {0, 0, 0}; + + Channel(int sourceId) { + this.sourceId = sourceId; + clear(); + } + + void addListener() { + type = LISTENER; + } + + void addFixed(float[] origin) { + type = FIXED; + this.origin = origin; + } + + void addDynamic(int entity) { + type = DYNAMIC; + this.entity = entity; + } + + void clear() { + entnum = -1; + entchannel = -1; + bufferId = -1; + bufferChanged = false; + rolloff = 0; + autosound = false; + active = false; + modified = false; + } +} diff --git a/src/jake2/sound/joal/JOALSoundImpl.java b/src/jake2/sound/joal/JOALSoundImpl.java new file mode 100644 index 0000000..8a005ce --- /dev/null +++ b/src/jake2/sound/joal/JOALSoundImpl.java @@ -0,0 +1,793 @@ +/* + * JOALSoundImpl.java + * Copyright (C) 2004 + * + * $Id: JOALSoundImpl.java,v 1.1 2004-07-09 06:50:52 hzi Exp $ + */ +package jake2.sound.joal; + + +import jake2.Defines; +import jake2.Globals; +import jake2.client.CL; +import jake2.game.*; +import jake2.qcommon.*; +import jake2.sound.*; +import jake2.util.Math3D; +import jake2.util.Vargs; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.*; + +import net.java.games.joal.*; + +/** + * JOALSoundImpl + */ +public final class JOALSoundImpl implements Sound { + + static { + S.register(new JOALSoundImpl()); + }; + + static AL al; + static ALC alc; + + cvar_t s_volume; + + private static final int MAX_SFX = Defines.MAX_SOUNDS * 2; + private static final int MAX_CHANNELS = 32; + + private int[] buffers = new int[MAX_SFX]; + private int[] sources = new int[MAX_CHANNELS]; + private Channel[] channels = null; + + private JOALSoundImpl() { + } + + + /* (non-Javadoc) + * @see jake2.sound.SoundImpl#Init() + */ + public boolean Init() { + + try { + initOpenAL(); + al = ALFactory.getAL(); + checkError(); + } catch (OpenALException e) { + Com.Printf(e.getMessage() + '\n'); + return false; + } + + checkError(); + al.alGenBuffers(MAX_SFX, buffers); + al.alGenSources(MAX_CHANNELS, sources); + checkError(); + s_volume = Cvar.Get("s_volume", "0.7", Defines.CVAR_ARCHIVE); + initChannels(); + al.alDistanceModel(AL.AL_INVERSE_DISTANCE_CLAMPED); +// al.alDistanceModel(AL.AL_INVERSE_DISTANCE); + Cmd.AddCommand("play", new xcommand_t() { + public void execute() { + Play(); + } + }); + Cmd.AddCommand("stopsound", new xcommand_t() { + public void execute() { + StopAllSounds(); + } + }); + Cmd.AddCommand("soundlist", new xcommand_t() { + public void execute() { + SoundList(); + } + }); + Cmd.AddCommand("soundinfo", new xcommand_t() { + public void execute() { + SoundInfo_f(); + } + }); + + num_sfx = 0; + + + Com.Printf("sound sampling rate: 44100Hz\n"); + + StopAllSounds(); + Com.Printf("------------------------------------\n"); + return true; + } + + + private void initOpenAL() throws OpenALException { + ALFactory.initialize(); + alc = ALFactory.getALC(); + String deviceName = null; + + String os = System.getProperty("os.name"); + if (os.startsWith("Windows")) { + deviceName = "DirectSound3D"; + } + ALC.Device device = alc.alcOpenDevice(deviceName); + String deviceSpecifier = alc.alcGetString(device, ALC.ALC_DEVICE_SPECIFIER); + String defaultSpecifier = alc.alcGetString(device, ALC.ALC_DEFAULT_DEVICE_SPECIFIER); + + Com.Printf(os + " using " + ((deviceName == null) ? defaultSpecifier : deviceName) + '\n'); + + ALC.Context context = alc.alcCreateContext(device, new int[] {0}); + alc.alcMakeContextCurrent(context); + // Check for an error. + if (alc.alcGetError(device) != ALC.ALC_NO_ERROR) { + Com.DPrintf("Error with SoundDevice"); + } + } + + void exitOpenAL() { + // Get the current context. + ALC.Context curContext = alc.alcGetCurrentContext(); + // Get the device used by that context. + ALC.Device curDevice = alc.alcGetContextsDevice(curContext); + // Reset the current context to NULL. + alc.alcMakeContextCurrent(null); + // Release the context and the device. + alc.alcDestroyContext(curContext); + alc.alcCloseDevice(curDevice); + } + + private void initChannels() { + + // create channels + channels = new Channel[MAX_CHANNELS]; + + int sourceId; + for (int i = 0; i < MAX_CHANNELS; i++) { + sourceId = sources[i]; + channels[i] = new Channel(sourceId); + + // set default values for AL sources + al.alSourcef (sourceId, AL.AL_GAIN, s_volume.value); + al.alSourcef (sourceId, AL.AL_PITCH, 1.0f); + al.alSourcei (sourceId, AL.AL_SOURCE_ABSOLUTE, AL.AL_TRUE); + al.alSourcefv(sourceId, AL.AL_VELOCITY, NULLVECTOR); + al.alSourcei (sourceId, AL.AL_LOOPING, AL.AL_FALSE); + al.alSourcef (sourceId, AL.AL_REFERENCE_DISTANCE, 300.0f); + al.alSourcef (sourceId, AL.AL_MIN_GAIN, 0.0005f); + al.alSourcef (sourceId, AL.AL_MAX_GAIN, 1.0f); + } + } + + + /* (non-Javadoc) + * @see jake2.sound.SoundImpl#RegisterSound(jake2.sound.sfx_t) + */ + private void initBuffer(sfx_t sfx) + { + if (sfx.cache == null ) { + //System.out.println(sfx.name + " " + sfx.cache.length+ " " + sfx.cache.loopstart + " " + sfx.cache.speed + " " + sfx.cache.stereo + " " + sfx.cache.width); + return; + } + + int format = AL.AL_FORMAT_MONO16; + byte[] data = sfx.cache.data; + int freq = sfx.cache.speed; + int size = data.length; + +// if (buffers[sfx.id] != 0) +// al.alDeleteBuffers(1, new int[] {buffers[sfx.id] }); +// +// int[] bid = new int[1]; +// al.alBufferData( bid[0], format, data, size, freq); +// buffers[sfx.id] = bid[0]; +// al.alBufferData( bid[0], format, data, size, freq); + + al.alBufferData( buffers[sfx.id], format, data, size, freq); +// int error; +// if ((error = al.alGetError()) != AL.AL_NO_ERROR) { +// String message; +// switch(error) { +// case AL.AL_INVALID_OPERATION: message = "invalid operation"; break; +// case AL.AL_INVALID_VALUE: message = "invalid value"; break; +// case AL.AL_INVALID_ENUM: message = "invalid enum"; break; +// case AL.AL_INVALID_NAME: message = "invalid name"; break; +// default: message = "" + error; +// } +// Com.DPrintf("Error Buffer " + sfx.id + ": " + sfx.name + " (" + size + ") --> " + message + '\n'); +// } + } + + private void checkError() { + int error; + if ((error = al.alGetError()) != AL.AL_NO_ERROR) { + String message; + switch(error) { + case AL.AL_INVALID_OPERATION: message = "invalid operation"; break; + case AL.AL_INVALID_VALUE: message = "invalid value"; break; + case AL.AL_INVALID_ENUM: message = "invalid enum"; break; + case AL.AL_INVALID_NAME: message = "invalid name"; break; + default: message = "" + error; + } + Com.DPrintf("AL Error: " + message +'\n'); + } + } + + + /* (non-Javadoc) + * @see jake2.sound.SoundImpl#Shutdown() + */ + public void Shutdown() { + StopAllSounds(); + al.alDeleteSources(sources.length, sources); + al.alDeleteBuffers(buffers.length, buffers); + exitOpenAL(); + //ALut.alutExit(); + Cmd.RemoveCommand("play"); + Cmd.RemoveCommand("stopsound"); + Cmd.RemoveCommand("soundlist"); + Cmd.RemoveCommand("soundinfo"); + + // free all sounds + for (int i = 0; i < num_sfx; i++) { + if (known_sfx[i].name == null) + continue; + known_sfx[i].clear(); + } + num_sfx = 0; + } + + private final static float[] NULLVECTOR = {0, 0, 0}; + private float[] entityOrigin = {0, 0, 0}; + private float[] sourceOrigin = {0, 0, 0}; + + /* (non-Javadoc) + * @see jake2.sound.SoundImpl#StartSound(float[], int, int, jake2.sound.sfx_t, float, float, float) + */ + public void StartSound(float[] origin, int entnum, int entchannel, sfx_t sfx, float fvol, float attenuation, float timeofs) { + + if (sfx == null) + return; + + if (sfx.name.charAt(0) == '*') + sfx = RegisterSexedSound(Globals.cl_entities[entnum].current, sfx.name); + + if (LoadSound(sfx) == null) + return; // can't load sound + + if (attenuation != Defines.ATTN_STATIC) + attenuation *= 0.5f; + + Channel ch = pickChannel(entnum, entchannel, buffers[sfx.id], attenuation); + + if (ch == null) return; + + if (entnum == Globals.cl.playernum + 1) { + ch.addListener(); + } else if (origin != null) { + ch.addFixed(origin); + } else { + ch.addDynamic(entnum); + } + } + + Channel pickChannel(int entnum, int entchannel, int bufferId, float rolloff) { + + Channel ch = null; + int state; + int i; + + for (i = 0; i < MAX_CHANNELS; i++) { + ch = channels[i]; + + if (entchannel != 0 && ch.entnum == entnum && ch.entchannel == entchannel) { + // always override sound from same entity + break; + } + + // don't let monster sounds override player sounds + if ((ch.entnum == Globals.cl.playernum+1) && (entnum != Globals.cl.playernum+1) && ch.bufferId != -1) + continue; + + // looking for a free AL source + if (!ch.active) { + break; + } + } + + if (i == MAX_CHANNELS) + return null; + + ch.entnum = entnum; + ch.entchannel = entchannel; + if (ch.bufferId != bufferId) { + ch.bufferId = bufferId; + ch.bufferChanged = true; + } + ch.rolloff = rolloff * 2; + ch.active = true; + ch.modified = true; + + return ch; + } + + private float[] listenerOrigin = {0, 0, 0}; + private float[] listenerOrientation = {0, 0, 0, 0, 0, 0}; + + /* (non-Javadoc) + * @see jake2.sound.SoundImpl#Update(float[], float[], float[], float[]) + */ + public void Update(float[] origin, float[] forward, float[] right, float[] up) { + + convertVector(origin, listenerOrigin); + al.alListenerfv(AL.AL_POSITION, listenerOrigin); + + convertOrientation(forward, up, listenerOrientation); + al.alListenerfv(AL.AL_ORIENTATION, listenerOrientation); + + AddLoopSounds(origin); + playChannels(listenerOrigin); + } + + Map looptable = new Hashtable(2 * MAX_CHANNELS); + + /* + ================== + S_AddLoopSounds + + Entities with a ->sound field will generated looped sounds + that are automatically started, stopped, and merged together + as the entities are sent to the client + ================== + */ + void AddLoopSounds(float[] listener) { + + if (Globals.cl_paused.value != 0.0f) { + removeUnusedLoopSounds(); + return; + } + + if (Globals.cls.state != Globals.ca_active) { + removeUnusedLoopSounds(); + return; + } + + if (!Globals.cl.sound_prepped) { + removeUnusedLoopSounds(); + return; + } + + Channel ch; + sfx_t sfx; + sfxcache_t sc; + int num; + entity_state_t ent; + Object key; + int sound = 0; + + for (int i=0 ; i<Globals.cl.frame.num_entities ; i++) { + num = (Globals.cl.frame.parse_entities + i)&(Defines.MAX_PARSE_ENTITIES-1); + ent = Globals.cl_parse_entities[num]; + sound = ent.sound; + + if (sound == 0) continue; + + key = new Integer(ent.number); + ch = (Channel)looptable.get(key); + + if (ch != null) { + // keep on looping + ch.autosound = true; + ch.origin = ent.origin; + continue; + } + + sfx = Globals.cl.sound_precache[sound]; + if (sfx == null) + continue; // bad sound effect + + sc = sfx.cache; + if (sc == null) + continue; + + // allocate a channel + ch = pickChannel(0, 0, buffers[sfx.id], 6); + if (ch == null) + break; + + ch.addFixed(ent.origin); + ch.autosound = true; + + looptable.put(key, ch); + al.alSourcei(ch.sourceId, AL.AL_LOOPING, AL.AL_TRUE); + } + + removeUnusedLoopSounds(); + + } + + void removeUnusedLoopSounds() { + Channel ch; + // stop unused loopsounds + for (Iterator iter = looptable.values().iterator(); iter.hasNext();) { + ch = (Channel)iter.next(); + if (!ch.autosound) { + al.alSourceStop(ch.sourceId); + al.alSourcei(ch.sourceId, AL.AL_LOOPING, AL.AL_FALSE); + iter.remove(); + ch.clear(); + } + } + } + + void playChannels(float[] listenerOrigin) { + + float[] sourceOrigin = {0, 0, 0}; + float[] entityOrigin = {0, 0, 0}; + Channel ch; + int sourceId; + int state; + + for (int i = 0; i < MAX_CHANNELS; i++) { + ch = channels[i]; + if (ch.active) { + sourceId = ch.sourceId; + + switch (ch.type) { + case Channel.LISTENER: + Math3D.VectorCopy(listenerOrigin, sourceOrigin); + break; + case Channel.DYNAMIC: + CL.GetEntitySoundOrigin(ch.entity, entityOrigin); + convertVector(entityOrigin, sourceOrigin); + break; + case Channel.FIXED: + convertVector(ch.origin, sourceOrigin); + break; + } + + if (ch.modified) { + if (ch.bufferChanged) + al.alSourcei (sourceId, AL.AL_BUFFER, ch.bufferId); + + al.alSourcef (sourceId, AL.AL_GAIN, s_volume.value); + al.alSourcef (sourceId, AL.AL_ROLLOFF_FACTOR, ch.rolloff); + al.alSourcefv(sourceId, AL.AL_POSITION, sourceOrigin); + al.alSourcePlay(sourceId); + ch.modified = false; + } else { + state = al.alGetSourcei(ch.sourceId, AL.AL_SOURCE_STATE); + if (state == AL.AL_PLAYING) { + al.alSourcefv(sourceId, AL.AL_POSITION, sourceOrigin); + } else { + ch.clear(); + } + } + ch.autosound = false; + } + } + } + + + /* (non-Javadoc) + * @see jake2.sound.SoundImpl#StopAllSounds() + */ + public void StopAllSounds() { + for (int i = 0; i < MAX_CHANNELS; i++) { + al.alSourceStop(sources[i]); + al.alSourcei(sources[i], AL.AL_BUFFER, 0); + channels[i].clear(); + } + } + + static void convertVector(float[] from, float[] to) { + to[0] = from[0]; + to[1] = from[2]; + to[2] = -from[1]; + } + + static void convertOrientation(float[] forward, float[] up, float[] orientation) { + orientation[0] = forward[0]; + orientation[1] = forward[2]; + orientation[2] = -forward[1]; + orientation[3] = up[0]; + orientation[4] = up[2]; + orientation[5] = -up[1]; + } + + /* (non-Javadoc) + * @see jake2.sound.Sound#getName() + */ + public String getName() { + return "joal"; + } + + + int s_registration_sequence; + boolean s_registering; + + /* (non-Javadoc) + * @see jake2.sound.Sound#BeginRegistration() + */ + public void BeginRegistration() { + s_registration_sequence++; + s_registering = true; + } + + /* (non-Javadoc) + * @see jake2.sound.Sound#RegisterSound(java.lang.String) + */ + public sfx_t RegisterSound(String name) { + sfx_t sfx = FindName(name, true); + sfx.registration_sequence = s_registration_sequence; + + if (!s_registering) + LoadSound(sfx); + + return sfx; + } + + /* (non-Javadoc) + * @see jake2.sound.Sound#EndRegistration() + */ + public void EndRegistration() { + int i; + sfx_t sfx; + int size; + + // free any sounds not from this registration sequence + for (i = 0; i < num_sfx; i++) { + sfx = known_sfx[i]; + if (sfx.name == null) + continue; + if (sfx.registration_sequence != s_registration_sequence) { + // don't need this sound + sfx.clear(); + } + } + + // load everything in + for (i = 0; i < num_sfx; i++) { + sfx = known_sfx[i]; + if (sfx.name == null) + continue; + LoadSound(sfx); + } + + s_registering = false; + } + + sfx_t RegisterSexedSound(entity_state_t ent, String base) { + + sfx_t sfx = null; + + // determine what model the client is using + String model = "male"; + int n = Globals.CS_PLAYERSKINS + ent.number - 1; + if (Globals.cl.configstrings[n] != null) { + int p = Globals.cl.configstrings[n].indexOf('\\'); + if (p >= 0) { + p++; + model = Globals.cl.configstrings[n].substring(p); + //strcpy(model, p); + p = model.indexOf('/'); + if (p > 0) + model = model.substring(0, p); + } + } + // if we can't figure it out, they're male + if (model == null || model.length() == 0) + model = "male"; + + // see if we already know of the model specific sound + String sexedFilename = "#players/" + model + "/" + base.substring(1); + //Com_sprintf (sexedFilename, sizeof(sexedFilename), "#players/%s/%s", model, base+1); + sfx = FindName(sexedFilename, false); + + if (sfx == null) { + // no, so see if it exists + RandomAccessFile f = null; + try { + f = FS.FOpenFile(sexedFilename.substring(1)); + } catch (IOException e) {} + if (f != null) { + // yes, close the file and register it + try { + FS.FCloseFile(f); + } catch (IOException e1) {} + sfx = RegisterSound(sexedFilename); + } else { + // no, revert to the male sound in the pak0.pak + //Com_sprintf (maleFilename, sizeof(maleFilename), "player/%s/%s", "male", base+1); + String maleFilename = "player/male/" + base.substring(1); + sfx = AliasName(sexedFilename, maleFilename); + } + } + + //System.out.println(sfx.name); + return sfx; + } + + + static sfx_t[] known_sfx = new sfx_t[MAX_SFX]; + static { + for (int i = 0; i< known_sfx.length; i++) + known_sfx[i] = new sfx_t(); + } + static int num_sfx; + + sfx_t FindName(String name, boolean create) { + int i; + sfx_t sfx = null; + + if (name == null) + Com.Error(Defines.ERR_FATAL, "S_FindName: NULL\n"); + if (name.length() == 0) + Com.Error(Defines.ERR_FATAL, "S_FindName: empty name\n"); + + if (name.length() >= Defines.MAX_QPATH) + Com.Error(Defines.ERR_FATAL, "Sound name too long: " + name); + + // see if already loaded + for (i = 0; i < num_sfx; i++) + if (name.equals(known_sfx[i].name)) { + return known_sfx[i]; + } + + if (!create) + return null; + + // find a free sfx + for (i = 0; i < num_sfx; i++) + if (known_sfx[i].name == null) + // registration_sequence < s_registration_sequence) + break; + + if (i == num_sfx) { + if (num_sfx == MAX_SFX) + Com.Error(Defines.ERR_FATAL, "S_FindName: out of sfx_t"); + num_sfx++; + } + + sfx = known_sfx[i]; + sfx.clear(); + sfx.name = name; + sfx.registration_sequence = s_registration_sequence; + // cwei + sfx.id = i; + + return sfx; + } + + /* + ================== + S_AliasName + + ================== + */ + sfx_t AliasName(String aliasname, String truename) + { + sfx_t sfx = null; + String s; + int i; + + s = new String(truename); + + // find a free sfx + for (i=0 ; i < num_sfx ; i++) + if (known_sfx[i].name == null) + break; + + if (i == num_sfx) + { + if (num_sfx == MAX_SFX) + Com.Error(Defines.ERR_FATAL, "S_FindName: out of sfx_t"); + num_sfx++; + } + + sfx = known_sfx[i]; + sfx.clear(); + sfx.name = new String(aliasname); + sfx.registration_sequence = s_registration_sequence; + sfx.truename = s; + // cwei + sfx.id = i; + + return sfx; + } + + /* + ============== + S_LoadSound + ============== + */ + public sfxcache_t LoadSound(sfx_t s) { + sfxcache_t sc = WaveLoader.LoadSound(s); + initBuffer(s); + return sc; + } + + /* (non-Javadoc) + * @see jake2.sound.Sound#StartLocalSound(java.lang.String) + */ + public void StartLocalSound(String sound) { + sfx_t sfx; + + sfx = RegisterSound(sound); + if (sfx == null) { + Com.Printf("S_StartLocalSound: can't cache " + sound + "\n"); + return; + } + StartSound(null, Globals.cl.playernum + 1, 0, sfx, 1, 1, 0); + } + + /* (non-Javadoc) + * @see jake2.sound.Sound#RawSamples(int, int, int, int, byte[]) + */ + public void RawSamples(int samples, int rate, int width, int channels, byte[] data) { + // TODO implement RawSamples + } + + /* + =============================================================================== + + console functions + + =============================================================================== + */ + + void Play() { + int i; + String name; + sfx_t sfx; + + i = 1; + while (i < Cmd.Argc()) { + name = new String(Cmd.Argv(i)); + if (name.indexOf('.') == -1) + name += ".wav"; + + sfx = RegisterSound(name); + StartSound(null, Globals.cl.playernum + 1, 0, sfx, 1.0f, 1.0f, 0.0f); + i++; + } + } + + void SoundList() { + int i; + sfx_t sfx; + sfxcache_t sc; + int size, total; + + total = 0; + for (i = 0; i < num_sfx; i++) { + sfx = known_sfx[i]; + if (sfx.registration_sequence == 0) + continue; + sc = sfx.cache; + if (sc != null) { + size = sc.length * sc.width * (sc.stereo + 1); + total += size; + if (sc.loopstart >= 0) + Com.Printf("L"); + else + Com.Printf(" "); + Com.Printf("(%2db) %6i : %s\n", new Vargs(3).add(sc.width * 8).add(size).add(sfx.name)); + } else { + if (sfx.name.charAt(0) == '*') + Com.Printf(" placeholder : " + sfx.name + "\n"); + else + Com.Printf(" not loaded : " + sfx.name + "\n"); + } + } + Com.Printf("Total resident: " + total + "\n"); + } + + void SoundInfo_f() { + + Com.Printf("%5d stereo\n", new Vargs(1).add(1)); + Com.Printf("%5d samples\n", new Vargs(1).add(22050)); + Com.Printf("%5d samplebits\n", new Vargs(1).add(16)); + Com.Printf("%5d speed\n", new Vargs(1).add(44100)); + } + +} diff --git a/src/jake2/sound/jsound/JSoundImpl.java b/src/jake2/sound/jsound/JSoundImpl.java new file mode 100644 index 0000000..3a3cc46 --- /dev/null +++ b/src/jake2/sound/jsound/JSoundImpl.java @@ -0,0 +1,98 @@ +/* + * JSoundImpl.java + * Copyright (C) 2004 + * + * $Id: JSoundImpl.java,v 1.1 2004-07-09 06:50:48 hzi Exp $ + */ +package jake2.sound.jsound; + +import jake2.sound.*; +import jake2.sound.Sound; +import jake2.sound.sfx_t; + +/** + * JSoundImpl + */ +public class JSoundImpl implements Sound { + + static { + S.register(new JSoundImpl()); + }; + + public boolean Init() { + SND_DMA.Init(); + if (SND_DMA.sound_started) return true; + return false; + } + + /* (non-Javadoc) + * @see jake2.sound.SoundImpl#Shutdown() + */ + public void Shutdown() { + SND_DMA.Shutdown(); + } + + /* (non-Javadoc) + * @see jake2.sound.SoundImpl#StartSound(float[], int, int, jake2.sound.sfx_t, float, float, float) + */ + public void StartSound(float[] origin, int entnum, int entchannel, sfx_t sfx, float fvol, float attenuation, float timeofs) { + SND_DMA.StartSound(origin, entnum, entchannel, sfx, fvol, attenuation, timeofs); + } + + /* (non-Javadoc) + * @see jake2.sound.SoundImpl#StopAllSounds() + */ + public void StopAllSounds() { + SND_DMA.StopAllSounds(); + } + + /* (non-Javadoc) + * @see jake2.sound.SoundImpl#Update(float[], float[], float[], float[]) + */ + public void Update(float[] origin, float[] forward, float[] right, float[] up) { + SND_DMA.Update(origin, forward, right, up); + } + + /* (non-Javadoc) + * @see jake2.sound.Sound#getName() + */ + public String getName() { + return "jsound"; + } + + /* (non-Javadoc) + * @see jake2.sound.Sound#BeginRegistration() + */ + public void BeginRegistration() { + SND_DMA.BeginRegistration(); + } + + /* (non-Javadoc) + * @see jake2.sound.Sound#RegisterSound(java.lang.String) + */ + public sfx_t RegisterSound(String sample) { + return SND_DMA.RegisterSound(sample); + } + + /* (non-Javadoc) + * @see jake2.sound.Sound#EndRegistration() + */ + public void EndRegistration() { + SND_DMA.EndRegistration(); + } + + /* (non-Javadoc) + * @see jake2.sound.Sound#StartLocalSound(java.lang.String) + */ + public void StartLocalSound(String sound) { + SND_DMA.StartLocalSound(sound); + } + + /* (non-Javadoc) + * @see jake2.sound.Sound#RawSamples(int, int, int, int, byte[]) + */ + public void RawSamples(int samples, int rate, int width, int channels, byte[] data) { + SND_DMA.RawSamples(samples, rate, width, channels, data); + } + +} diff --git a/src/jake2/sound/jsound/SND_DMA.java b/src/jake2/sound/jsound/SND_DMA.java new file mode 100644 index 0000000..9fe7930 --- /dev/null +++ b/src/jake2/sound/jsound/SND_DMA.java @@ -0,0 +1,1197 @@ +/* + * S_DMA.java + * Copyright (C) 2004 + * + * $Id: SND_DMA.java,v 1.1 2004-07-09 06:50:48 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. + +*/ + +// Created on 26.01.2004 by RST. + +package jake2.sound.jsound; + +import jake2.Defines; +import jake2.client.CL; +import jake2.game.*; +import jake2.qcommon.*; +import jake2.sound.*; +import jake2.util.Vargs; + +import java.io.IOException; +import java.io.RandomAccessFile; + + + +/** + * SND_DMA + * TODO implement sound system + */ +public class SND_DMA extends SND_MIX { + +//// ======================================================================= +//// Internal sound data & structures +//// ======================================================================= +// +//// only begin attenuating sound volumes when outside the FULLVOLUME range + static final int SOUND_FULLVOLUME = 80; + static final float SOUND_LOOPATTENUATE = 0.003f; + static int s_registration_sequence; + + static boolean sound_started = false; + + static float[] listener_origin = {0, 0, 0}; + static float[] listener_forward = {0, 0, 0}; + static float[] listener_right = {0, 0, 0}; + static float[] listener_up = {0, 0, 0}; + + static boolean s_registering; + + static int soundtime; // sample PAIRS + + // during registration it is possible to have more sounds + // than could actually be referenced during gameplay, + // because we don't want to free anything until we are + // sure we won't need it. + static final int MAX_SFX = (MAX_SOUNDS*2); + static sfx_t[] known_sfx = new sfx_t[MAX_SFX]; + static { + for (int i = 0; i< known_sfx.length; i++) + known_sfx[i] = new sfx_t(); + } + static int num_sfx; + + static final int MAX_PLAYSOUNDS = 128; + static playsound_t[] s_playsounds = new playsound_t[MAX_PLAYSOUNDS]; + static { + for( int i = 0; i < MAX_PLAYSOUNDS; i++) { + s_playsounds[i] = new playsound_t(); + } + } + static playsound_t s_freeplays = new playsound_t(); + + static int s_beginofs; + + static cvar_t s_testsound; + static cvar_t s_loadas8bit; + static cvar_t s_khz; + static cvar_t s_show; + static cvar_t s_mixahead; + static cvar_t s_primary; +// +// +// int s_rawend; +// portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES]; +// +// +// ==================================================================== +// User-setable variables +// ==================================================================== + + + static void SoundInfo_f() { + if (!sound_started) { + Com.Printf("sound system not started\n"); + return; + } + + Com.Printf("%5d stereo\n", new Vargs(1).add(dma.channels - 1)); + Com.Printf("%5d samples\n", new Vargs(1).add(dma.samples)); + //Com.Printf("%5d samplepos\n", new Vargs(1).add(dma.samplepos)); + Com.Printf("%5d samplebits\n", new Vargs(1).add(dma.samplebits)); + Com.Printf("%5d submission_chunk\n", new Vargs(1).add(dma.submission_chunk)); + Com.Printf("%5d speed\n", new Vargs(1).add(dma.speed)); + } + + /* + ================ + S_Init + ================ + */ + public static void Init() { + cvar_t cv; + + Com.Printf("\n------- sound initialization -------\n"); + + cv = Cvar.Get("s_initsound", "0", 0); + if (cv.value == 0.0f) + Com.Printf("not initializing.\n"); + else { + s_volume = Cvar.Get("s_volume", "0.7", CVAR_ARCHIVE); + s_khz = Cvar.Get("s_khz", "11", CVAR_ARCHIVE); + s_loadas8bit = Cvar.Get("s_loadas8bit", "1", CVAR_ARCHIVE); + s_mixahead = Cvar.Get("s_mixahead", "0.2", CVAR_ARCHIVE); + s_show = Cvar.Get("s_show", "0", 0); + s_testsound = Cvar.Get("s_testsound", "0", 0); + s_primary = Cvar.Get("s_primary", "0", CVAR_ARCHIVE); // win32 specific + + Cmd.AddCommand("play", new xcommand_t() { + public void execute() { + Play(); + } + }); + Cmd.AddCommand("stopsound", new xcommand_t() { + public void execute() { + StopAllSounds(); + } + }); + Cmd.AddCommand("soundlist", new xcommand_t() { + public void execute() { + SoundList(); + } + }); + Cmd.AddCommand("soundinfo", new xcommand_t() { + public void execute() { + SoundInfo_f(); + } + }); + + if (!SNDDMA_Init()) + return; + + InitScaletable(); + + sound_started = true; + num_sfx = 0; + + soundtime = 0; + paintedtime = 0; + + Com.Printf("sound sampling rate: " + dma.speed + "\n"); + + StopAllSounds(); + } + Com.Printf("------------------------------------\n"); + } + + +// ======================================================================= +// Shutdown sound engine +// ======================================================================= + + public static void Shutdown() { + int i; + sfx_t[] sfx; + + if (!sound_started) + return; + + SNDDMA_Shutdown(); + + sound_started = false; + + Cmd.RemoveCommand("play"); + Cmd.RemoveCommand("stopsound"); + Cmd.RemoveCommand("soundlist"); + Cmd.RemoveCommand("soundinfo"); + + // free all sounds + for (i = 0, sfx = known_sfx; i < num_sfx; i++) { + if (sfx[i].name == null) + continue; + + //memset (sfx, 0, sizeof(*sfx)); + sfx[i].clear(); + } + + num_sfx = 0; + } + +// ======================================================================= +// Load a sound +// ======================================================================= + + /* + ================== + S_FindName + + ================== + */ + static sfx_t FindName(String name, boolean create) { + int i; + sfx_t sfx = null; + + if (name == null) + Com.Error(ERR_FATAL, "S_FindName: NULL\n"); + if (name.length() == 0) + Com.Error(ERR_FATAL, "S_FindName: empty name\n"); + + if (name.length() >= MAX_QPATH) + Com.Error(ERR_FATAL, "Sound name too long: " + name); + + // see if already loaded + for (i = 0; i < num_sfx; i++) + if (name.equals(known_sfx[i].name)) { + return known_sfx[i]; + } + + if (!create) + return null; + + // find a free sfx + for (i = 0; i < num_sfx; i++) + if (known_sfx[i].name == null) + // registration_sequence < s_registration_sequence) + break; + + if (i == num_sfx) { + if (num_sfx == MAX_SFX) + Com.Error(ERR_FATAL, "S_FindName: out of sfx_t"); + num_sfx++; + } + + sfx = known_sfx[i]; + //memset (sfx, 0, sizeof(*sfx)); + sfx.clear(); + sfx.name = name; + sfx.registration_sequence = s_registration_sequence; + + return sfx; + } + + /* + ================== + S_AliasName + + ================== + */ + static sfx_t AliasName(String aliasname, String truename) + { + sfx_t sfx = null; +// char *s; + int i; + +// s = Z_Malloc (MAX_QPATH); +// strcpy (s, truename); + + // find a free sfx + for (i=0 ; i < num_sfx ; i++) + if (known_sfx[i].name == null) + break; + + if (i == num_sfx) + { + if (num_sfx == MAX_SFX) + Com.Error(ERR_FATAL, "S_FindName: out of sfx_t"); + num_sfx++; + } + + sfx = known_sfx[i]; + //memset (sfx, 0, sizeof(*sfx)); + //strcpy (sfx->name, aliasname); + sfx.name = aliasname; + sfx.registration_sequence = s_registration_sequence; + sfx.truename = truename; + + return sfx; + } + + + /* + ===================== + S_BeginRegistration + + ===================== + */ + public static void BeginRegistration() { + s_registration_sequence++; + s_registering = true; + } + + /* + ================== + S_RegisterSound + + ================== + */ + public static sfx_t RegisterSound(String name) { + sfx_t sfx = null; + + if (!sound_started) + return null; + + sfx = FindName(name, true); + sfx.registration_sequence = s_registration_sequence; + + if (!s_registering) + WaveLoader.LoadSound(sfx); + + return sfx; + } + + + /* + ===================== + S_EndRegistration + + ===================== + */ + public static void EndRegistration() { + int i; + sfx_t sfx; + int size; + + // free any sounds not from this registration sequence + for (i = 0; i < num_sfx; i++) { + sfx = known_sfx[i]; + if (sfx.name == null) + continue; + if (sfx.registration_sequence != s_registration_sequence) { // don't need this sound + //memset (sfx, 0, sizeof(*sfx)); + sfx.clear(); + } else { + // make sure it is paged in + // if (sfx->cache) + // { + // size = sfx->cache->length*sfx->cache->width; + // Com_PageInMemory ((byte *)sfx->cache, size); + // } + } + + } + + // load everything in + for (i = 0; i < num_sfx; i++) { + sfx = known_sfx[i]; + if (sfx.name == null) + continue; + WaveLoader.LoadSound(sfx); + } + + s_registering = false; + } + + +// ============================================================================= + + /* + ================= + S_PickChannel + ================= + */ + static channel_t PickChannel(int entnum, int entchannel) + { + int ch_idx; + int first_to_die; + int life_left; + channel_t ch; + + if (entchannel<0) + Com.Error(ERR_DROP, "S_PickChannel: entchannel<0"); + + // Check for replacement sound, or find the best one to replace + first_to_die = -1; + life_left = 0x7fffffff; + for (ch_idx=0 ; ch_idx < MAX_CHANNELS ; ch_idx++) + { + if (entchannel != 0 // channel 0 never overrides + && channels[ch_idx].entnum == entnum + && channels[ch_idx].entchannel == entchannel) + { // always override sound from same entity + first_to_die = ch_idx; + break; + } + + // don't let monster sounds override player sounds + if ((channels[ch_idx].entnum == cl.playernum+1) && (entnum != cl.playernum+1) && channels[ch_idx].sfx != null) + continue; + + if (channels[ch_idx].end - paintedtime < life_left) + { + life_left = channels[ch_idx].end - paintedtime; + first_to_die = ch_idx; + } + } + + if (first_to_die == -1) + return null; + + ch = channels[first_to_die]; + //memset (ch, 0, sizeof(*ch)); + ch.clear(); + + return ch; + } + + /* + ================= + S_SpatializeOrigin + + Used for spatializing channels and autosounds + ================= + */ + static void SpatializeOrigin(float[] origin, float master_vol, float dist_mult, channel_t ch) + { + float dot; + float dist; + float lscale, rscale, scale; + float[] source_vec = {0, 0, 0}; + + if (cls.state != ca_active) + { + ch.leftvol = ch.rightvol = 255; + return; + } + +// calculate stereo seperation and distance attenuation + VectorSubtract(origin, listener_origin, source_vec); + + dist = VectorNormalize(source_vec); + dist -= SOUND_FULLVOLUME; + if (dist < 0) + dist = 0; // close enough to be at full volume + dist *= dist_mult; // different attenuation levels + + dot = DotProduct(listener_right, source_vec); + + if (dma.channels == 1 || dist_mult == 0.0f) + { // no attenuation = no spatialization + rscale = 1.0f; + lscale = 1.0f; + } + else + { + rscale = 0.5f * (1.0f + dot); + lscale = 0.5f * (1.0f - dot); + } + + // add in distance effect + scale = (1.0f - dist) * rscale; + ch.rightvol = (int) (master_vol * scale); + if (ch.rightvol < 0) + ch.rightvol = 0; + + scale = (1.0f - dist) * lscale; + ch.leftvol = (int) (master_vol * scale); + if (ch.leftvol < 0) + ch.leftvol = 0; + } + + /* + ================= + S_Spatialize + ================= + */ + static void Spatialize(channel_t ch) + { + float[] origin = {0, 0, 0}; + + // anything coming from the view entity will always be full volume + if (ch.entnum == cl.playernum+1) + { + ch.leftvol = ch.master_vol; + ch.rightvol = ch.master_vol; + return; + } + + if (ch.fixed_origin) + { + VectorCopy(ch.origin, origin); + } + else + CL.GetEntitySoundOrigin(ch.entnum, origin); + + SpatializeOrigin(origin, (float)ch.master_vol, ch.dist_mult, ch); + } + + /* + ================= + S_AllocPlaysound + ================= + */ + static playsound_t AllocPlaysound () + { + playsound_t ps; + + ps = s_freeplays.next; + if (ps == s_freeplays) + return null; // no free playsounds + + // unlink from freelist + ps.prev.next = ps.next; + ps.next.prev = ps.prev; + + return ps; + } + + + /* + ================= + S_FreePlaysound + ================= + */ + static void FreePlaysound(playsound_t ps) + { + // unlink from channel + ps.prev.next = ps.next; + ps.next.prev = ps.prev; + + // add to free list + ps.next = s_freeplays.next; + s_freeplays.next.prev = ps; + ps.prev = s_freeplays; + s_freeplays.next = ps; + } + + /* + =============== + S_IssuePlaysound + + Take the next playsound and begin it on the channel + This is never called directly by S_Play*, but only + by the update loop. + =============== + */ + static void IssuePlaysound (playsound_t ps) + { + channel_t ch; + sfxcache_t sc; + + if (s_show.value != 0.0f) + Com.Printf("Issue " + ps.begin + "\n"); + // pick a channel to play on + ch = PickChannel(ps.entnum, ps.entchannel); + if (ch == null) + { + FreePlaysound(ps); + return; + } + + // spatialize + if (ps.attenuation == ATTN_STATIC) + ch.dist_mult = ps.attenuation * 0.001f; + else + ch.dist_mult = ps.attenuation * 0.0005f; + ch.master_vol = (int)ps.volume; + ch.entnum = ps.entnum; + ch.entchannel = ps.entchannel; + ch.sfx = ps.sfx; + VectorCopy (ps.origin, ch.origin); + ch.fixed_origin = ps.fixed_origin; + + Spatialize(ch); + + ch.pos = 0; + sc = WaveLoader.LoadSound(ch.sfx); + ch.end = paintedtime + sc.length; + + // free the playsound + FreePlaysound(ps); + } + + static sfx_t RegisterSexedSound(entity_state_t ent, String base) { + sfx_t sfx = null; + + // determine what model the client is using + String model = "male"; + int n = CS_PLAYERSKINS + ent.number - 1; + if (cl.configstrings[n] != null) { + int p = cl.configstrings[n].indexOf('\\'); + if (p >= 0) { + p++; + model = cl.configstrings[n].substring(p); + //strcpy(model, p); + p = model.indexOf('/'); + if (p > 0) + model = model.substring(0, p - 1); + } + } + // if we can't figure it out, they're male + if (model == null || model.length() == 0) + model = "male"; + + // see if we already know of the model specific sound + String sexedFilename = "#players/" + model + "/" + base.substring(1); + //Com_sprintf (sexedFilename, sizeof(sexedFilename), "#players/%s/%s", model, base+1); + sfx = FindName(sexedFilename, false); + + if (sfx == null) { + // no, so see if it exists + RandomAccessFile f = null; + try { + f = FS.FOpenFile(sexedFilename.substring(1)); + } catch (IOException e) {} + if (f != null) { + // yes, close the file and register it + try { + FS.FCloseFile(f); + } catch (IOException e1) {} + sfx = RegisterSound(sexedFilename); + } else { + // no, revert to the male sound in the pak0.pak + //Com_sprintf (maleFilename, sizeof(maleFilename), "player/%s/%s", "male", base+1); + String maleFilename = "player/male/" + base.substring(1); + sfx = AliasName(sexedFilename, maleFilename); + } + } + + return sfx; + } + + +// ======================================================================= +// Start a sound effect +// ======================================================================= + + /* + ==================== + S_StartSound + + Validates the parms and ques the sound up + if pos is NULL, the sound will be dynamically sourced from the entity + Entchannel 0 will never override a playing sound + ==================== + */ + public static void StartSound(float[] origin, int entnum, int entchannel, sfx_t sfx, float fvol, float attenuation, float timeofs) { + + if (!sound_started) + return; + + if (sfx == null) + return; + + if (sfx.name.charAt(0) == '*') + sfx = RegisterSexedSound(cl_entities[entnum].current, sfx.name); + + // make sure the sound is loaded + sfxcache_t sc = WaveLoader.LoadSound(sfx); + if (sc == null) + return; // couldn't load the sound's data + + int vol = (int) (fvol * 255); + + // make the playsound_t + playsound_t ps = AllocPlaysound(); + if (ps == null) + return; + + if (origin != null) { + VectorCopy(origin, ps.origin); + ps.fixed_origin = true; + } else + ps.fixed_origin = false; + + ps.entnum = entnum; + ps.entchannel = entchannel; + ps.attenuation = attenuation; + ps.volume = vol; + ps.sfx = sfx; + + // drift s_beginofs + int start = (int) (cl.frame.servertime * 0.001f * dma.speed + s_beginofs); + if (start < paintedtime) { + start = paintedtime; + s_beginofs = (int) (start - (cl.frame.servertime * 0.001f * dma.speed)); + } else if (start > paintedtime + 0.3f * dma.speed) { + start = (int) (paintedtime + 0.1f * dma.speed); + s_beginofs = (int) (start - (cl.frame.servertime * 0.001f * dma.speed)); + } else { + s_beginofs -= 10; + } + + if (timeofs == 0.0f) + ps.begin = paintedtime; + else + ps.begin = (long) (start + timeofs * dma.speed); + + // sort into the pending sound list + playsound_t sort; + for (sort = s_pendingplays.next; sort != s_pendingplays && sort.begin < ps.begin; sort = sort.next); + + ps.next = sort; + ps.prev = sort.prev; + + ps.next.prev = ps; + ps.prev.next = ps; + } + + /* + ================== + S_StartLocalSound + ================== + */ + public static void StartLocalSound(String sound) { + sfx_t sfx; + + if (!sound_started) + return; + + sfx = RegisterSound(sound); + if (sfx == null) { + Com.Printf("S_StartLocalSound: can't cache " + sound + "\n"); + return; + } + StartSound(null, cl.playernum + 1, 0, sfx, 1, 1, 0); + } + + + /* + ================== + S_ClearBuffer + ================== + */ + static void ClearBuffer() + { + int clear; + + if (!sound_started) + return; + + s_rawend = 0; + + if (dma.samplebits == 8) + clear = 0x80; + else + clear = 0; + + SNDDMA_BeginPainting (); + if (dma.buffer != null) + //memset(dma.buffer, clear, dma.samples * dma.samplebits/8); + //Arrays.fill(dma.buffer, (byte)clear); + SNDDMA_Submit (); + } + + /* + ================== + S_StopAllSounds + ================== + */ + public static void StopAllSounds() + { + int i; + + if (!sound_started) + return; + + // clear all the playsounds + //memset(s_playsounds, 0, sizeof(s_playsounds)); + s_freeplays.next = s_freeplays.prev = s_freeplays; + s_pendingplays.next = s_pendingplays.prev = s_pendingplays; + + for (i=0 ; i<MAX_PLAYSOUNDS ; i++) + { + s_playsounds[i].clear(); + s_playsounds[i].prev = s_freeplays; + s_playsounds[i].next = s_freeplays.next; + s_playsounds[i].prev.next = s_playsounds[i]; + s_playsounds[i].next.prev = s_playsounds[i]; + } + + // clear all the channels + //memset(channels, 0, sizeof(channels)); + for (i = 0; i < MAX_CHANNELS; i++) + channels[i].clear(); + + ClearBuffer(); + } + + /* + ================== + S_AddLoopSounds + + Entities with a ->sound field will generated looped sounds + that are automatically started, stopped, and merged together + as the entities are sent to the client + ================== + */ + static void AddLoopSounds() + { + int i, j; + int[] sounds = new int[Defines.MAX_EDICTS]; + int left, right, left_total, right_total; + channel_t ch; + sfx_t sfx; + sfxcache_t sc; + int num; + entity_state_t ent; + + if (cl_paused.value != 0.0f) + return; + + if (cls.state != ca_active) + return; + + if (!cl.sound_prepped) + return; + + for (i=0 ; i<cl.frame.num_entities ; i++) + { + num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1); + ent = cl_parse_entities[num]; + sounds[i] = ent.sound; + } + + for (i=0 ; i<cl.frame.num_entities ; i++) + { + if (sounds[i] == 0) + continue; + + sfx = cl.sound_precache[sounds[i]]; + if (sfx == null) + continue; // bad sound effect + sc = sfx.cache; + if (sc == null) + continue; + + num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1); + ent = cl_parse_entities[num]; + + channel_t tch = new channel_t(); + // find the total contribution of all sounds of this type + SpatializeOrigin(ent.origin, 255.0f, SOUND_LOOPATTENUATE, tch); + left_total = tch.leftvol; + right_total = tch.rightvol; + for (j=i+1 ; j<cl.frame.num_entities ; j++) + { + if (sounds[j] != sounds[i]) + continue; + sounds[j] = 0; // don't check this again later + + num = (cl.frame.parse_entities + j)&(MAX_PARSE_ENTITIES-1); + ent = cl_parse_entities[num]; + + SpatializeOrigin(ent.origin, 255.0f, SOUND_LOOPATTENUATE, tch); + left_total += tch.leftvol; + right_total += tch.rightvol; + } + + if (left_total == 0 && right_total == 0) + continue; // not audible + + // allocate a channel + ch = PickChannel(0, 0); + if (ch == null) + return; + + if (left_total > 255) + left_total = 255; + if (right_total > 255) + right_total = 255; + ch.leftvol = left_total; + ch.rightvol = right_total; + ch.autosound = true; // remove next frame + ch.sfx = sfx; + ch.pos = paintedtime % sc.length; + ch.end = paintedtime + sc.length - ch.pos; + } + } + +// ============================================================================= + + /* + ============ + S_RawSamples + + Cinematic streaming and voice over network + ============ + */ + static void RawSamples(int samples, int rate, int width, int channels, byte[] data) + { + //TODO RawSamples + int i; + int src, dst; + float scale; + + if (!sound_started) + return; + + if (s_rawend < paintedtime) + s_rawend = paintedtime; + scale = (float)rate / dma.speed; + +// Com_Printf ("%i < %i < %i\n", soundtime, paintedtime, s_rawend); + if (channels == 2 && width == 2) + { + if (scale == 1.0) + { // optimized case +// for (i=0 ; i<samples ; i++) +// { +// dst = s_rawend&(MAX_RAW_SAMPLES-1); +// s_rawend++; +// s_rawsamples[dst].left = +// LittleShort(((short *)data)[i*2]) << 8; +// s_rawsamples[dst].right = +// LittleShort(((short *)data)[i*2+1]) << 8; +// } + } + else + { + for (i=0 ; ; i++) + { +// src = i*scale; +// if (src >= samples) +// break; +// dst = s_rawend&(MAX_RAW_SAMPLES-1); +// s_rawend++; +// s_rawsamples[dst].left = +// LittleShort(((short *)data)[src*2]) << 8; +// s_rawsamples[dst].right = +// LittleShort(((short *)data)[src*2+1]) << 8; + } + } + } + else if (channels == 1 && width == 2) + { + for (i=0 ; ; i++) + { +// src = i*scale; +// if (src >= samples) +// break; +// dst = s_rawend&(MAX_RAW_SAMPLES-1); +// s_rawend++; +// s_rawsamples[dst].left = +// LittleShort(((short *)data)[src]) << 8; +// s_rawsamples[dst].right = +// LittleShort(((short *)data)[src]) << 8; + } + } + else if (channels == 2 && width == 1) + { + for (i=0 ; ; i++) + { +// src = i*scale; +// if (src >= samples) +// break; +// dst = s_rawend&(MAX_RAW_SAMPLES-1); +// s_rawend++; +// s_rawsamples[dst].left = +// ((char *)data)[src*2] << 16; +// s_rawsamples[dst].right = +// ((char *)data)[src*2+1] << 16; + } + } + else if (channels == 1 && width == 1) + { + for (i=0 ; ; i++) + { +// src = i*scale; +// if (src >= samples) +// break; +// dst = s_rawend&(MAX_RAW_SAMPLES-1); +// s_rawend++; +// s_rawsamples[dst].left = +// (((byte *)data)[src]-128) << 16; +// s_rawsamples[dst].right = (((byte *)data)[src]-128) << 16; + } + } + } + +//// ============================================================================= + + /* + ============ + S_Update + + Called once each time through the main loop + ============ + */ + public static void Update(float[] origin, float[] forward, float[] right, float[] up) { + + if (!sound_started) + return; + + // if the laoding plaque is up, clear everything + // out to make sure we aren't looping a dirty + // dma buffer while loading + if (cls.disable_screen != 0.0f) { + ClearBuffer(); + return; + } + + // rebuild scale tables if volume is modified + if (s_volume.modified) + InitScaletable(); + + VectorCopy(origin, listener_origin); + VectorCopy(forward, listener_forward); + VectorCopy(right, listener_right); + VectorCopy(up, listener_up); + + channel_t combine = null; + + // update spatialization for dynamic sounds + channel_t ch; + for (int i = 0; i < MAX_CHANNELS; i++) { + ch = channels[i]; + if (ch.sfx == null) + continue; + if (ch.autosound) { // autosounds are regenerated fresh each frame + //memset (ch, 0, sizeof(*ch)); + ch.clear(); + continue; + } + Spatialize(ch); // respatialize channel + if (ch.leftvol == 0 && ch.rightvol == 0) { + //memset (ch, 0, sizeof(*ch)); + ch.clear(); + continue; + } + } + + // add loopsounds + AddLoopSounds(); + + // + // debugging output + // + if (s_show.value != 0.0f) { + int total = 0; + + for (int i = 0; i < MAX_CHANNELS; i++) { + ch = channels[i]; + if (ch.sfx != null && (ch.leftvol != 0 || ch.rightvol != 0)) { + Com.Printf(ch.leftvol + " " + ch.rightvol + " " + ch.sfx.name + "\n"); + total++; + } + } + + //Com.Printf("----(" + total + ")---- painted: " + paintedtime + "\n"); + } + + // mix some sound + Update_(); + } + + static int buffers = 0; + static int oldsamplepos = 0; + static void GetSoundtime() + { + int samplepos; + //static int buffers; + //static int oldsamplepos; + int fullsamples; + + fullsamples = dma.samples / dma.channels; + +// it is possible to miscount buffers if it has wrapped twice between +// calls to S_Update. Oh well. + samplepos = SNDDMA_GetDMAPos(); + + if (samplepos < oldsamplepos) + { + buffers++; // buffer wrapped + + if (paintedtime > 0x40000000) + { // time to chop things off to avoid 32 bit limits + buffers = 0; + paintedtime = fullsamples; + StopAllSounds(); + } + } + oldsamplepos = samplepos; + + soundtime = buffers*fullsamples + samplepos/dma.channels; + } + + static void Update_() + { + int endtime; + int samps; + + if (!sound_started) + return; + + SNDDMA_BeginPainting(); + + if (dma.buffer == null) + return; + + // Updates DMA time + GetSoundtime(); + + // check to make sure that we haven't overshot + if (paintedtime < soundtime) + { + Com.DPrintf("S_Update_ : overflow\n"); + paintedtime = soundtime; + } + + // mix ahead of current position + endtime = (int)(soundtime + s_mixahead.value * dma.speed); + // endtime = (soundtime + 4096) & ~4095; + + // mix to an even submission block size + endtime = (endtime + dma.submission_chunk-1) + & ~(dma.submission_chunk-1); + samps = dma.samples >> (dma.channels-1); + if (endtime - soundtime > samps) + endtime = soundtime + samps; + + PaintChannels(endtime); + + SNDDMA_Submit(); + } + + /* + =============================================================================== + + console functions + + =============================================================================== + */ + + static void Play() { + int i; + String name; + sfx_t sfx; + + i = 1; + while (i < Cmd.Argc()) { + name = new String(Cmd.Argv(i)); + if (name.indexOf('.') == -1) + name += ".wav"; + + sfx = RegisterSound(name); + StartSound(null, cl.playernum + 1, 0, sfx, 1.0f, 1.0f, 0.0f); + i++; + } + } + + static void SoundList() { + int i; + sfx_t sfx; + sfxcache_t sc; + int size, total; + + total = 0; + for (i = 0; i < num_sfx; i++) { + sfx = known_sfx[i]; + if (sfx.registration_sequence == 0) + continue; + sc = sfx.cache; + if (sc != null) { + size = sc.length * sc.width * (sc.stereo + 1); + total += size; + if (sc.loopstart >= 0) + Com.Printf("L"); + else + Com.Printf(" "); + Com.Printf("(%2db) %6i : %s\n", new Vargs(3).add(sc.width * 8).add(size).add(sfx.name)); + } else { + if (sfx.name.charAt(0) == '*') + Com.Printf(" placeholder : " + sfx.name + "\n"); + else + Com.Printf(" not loaded : " + sfx.name + "\n"); + } + } + Com.Printf("Total resident: " + total + "\n"); + } + +} diff --git a/src/jake2/sound/jsound/SND_JAVA.java b/src/jake2/sound/jsound/SND_JAVA.java new file mode 100644 index 0000000..679c64e --- /dev/null +++ b/src/jake2/sound/jsound/SND_JAVA.java @@ -0,0 +1,181 @@ +/* + * SND_JAVA.java + * Copyright (C) 2004 + * + * $Id: SND_JAVA.java,v 1.1 2004-07-09 06:50:48 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.sound.jsound; + +import jake2.Globals; +import jake2.game.cvar_t; +import jake2.qcommon.Cvar; + +import javax.sound.sampled.*; + +/** + * SND_JAVA + */ +public class SND_JAVA extends Globals { + + static boolean snd_inited= false; + + static cvar_t sndbits; + static cvar_t sndspeed; + static cvar_t sndchannels; + + static class dma_t { + int channels; + int samples; // mono samples in buffer + int submission_chunk; // don't mix less than this # + //int samplepos; // in mono samples + int samplebits; + int speed; + byte[] buffer; + } + static SND_DMA.dma_t dma = new dma_t(); + + static class SoundThread extends Thread { + byte[] b; + SourceDataLine l; + int pos = 0; + boolean running = false; + public SoundThread(byte[] buffer, SourceDataLine line) { + b = buffer; + l = line; + } + public void run() { + running = true; + while (running) { + line.write(b, pos, 512); + pos = (pos+512) % b.length; + } + } + public synchronized void stopLoop() { + running = false; + } + public int getSamplePos() { + return pos >> 1; + } + } + static SoundThread thread; + static SourceDataLine line; + static AudioFormat format; + + + static boolean SNDDMA_Init() { + + if (snd_inited) + return true; + + if (sndbits == null) { + sndbits = Cvar.Get("sndbits", "16", CVAR_ARCHIVE); + sndspeed = Cvar.Get("sndspeed", "0", CVAR_ARCHIVE); + sndchannels = Cvar.Get("sndchannels", "1", CVAR_ARCHIVE); + } + +// byte[] sound = FS.LoadFile("sound/misc/menu1.wav"); +// AudioInputStream stream; +// try { +// stream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(sound)); +// } catch (UnsupportedAudioFileException e) { +// return false; +// } catch (IOException e) { +// return false; +// } + //format = stream.getFormat(); + format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 22050, 16, 1, 2, 22050, false); + DataLine.Info dinfo = new DataLine.Info(SourceDataLine.class, format); + + try { + line = (SourceDataLine)AudioSystem.getLine(dinfo); + } catch (LineUnavailableException e4) { + return false; + } + + dma.buffer = new byte[65536]; + dma.channels = format.getChannels(); + dma.samplebits = format.getSampleSizeInBits(); + dma.samples = dma.buffer.length / format.getFrameSize(); + dma.speed = (int)format.getSampleRate(); + //dma.samplepos = 0; + dma.submission_chunk = 1; + + try { + line.open(format, 4096); + } catch (LineUnavailableException e5) { + return false; + } + + line.start(); + thread = new SoundThread(dma.buffer, line); + //thread.setPriority(Thread.MAX_PRIORITY); + thread.start(); + + snd_inited = true; + return true; + + } + + static int SNDDMA_GetDMAPos() { + //dma.samplepos = line.getFramePosition() % dma.samples; + return thread.getSamplePos(); //dma.samplepos; + } + + static void SNDDMA_Shutdown() { + thread.stopLoop(); + line.stop(); + line.flush(); + line.close(); + line=null; + snd_inited = false; + } + + /* + ============== + SNDDMA_Submit + + Send sound to device if buffer isn't really the dma buffer + =============== + */ + public static void SNDDMA_Submit() { +// runLine(); + } + + static void SNDDMA_BeginPainting() {} + +// private static int pos = 0; +// static void runLine() { +// +// int p = line.getFramePosition() * format.getFrameSize() % dma.buffer.length; +// if (p == 0) { +// writeLine(); +// } +// else if (pos - p < 4096 ) writeLine(); +// } +// +// static void writeLine() { +// line.write(dma.buffer, pos, 4096); +// pos+=4096; +// if (pos>=dma.buffer.length) pos = 0; +// } + +} diff --git a/src/jake2/sound/jsound/SND_MIX.java b/src/jake2/sound/jsound/SND_MIX.java new file mode 100644 index 0000000..c3aae2c --- /dev/null +++ b/src/jake2/sound/jsound/SND_MIX.java @@ -0,0 +1,491 @@ +/* + * SND_MIX.java + * Copyright (C) 2004 + * + * $Id: SND_MIX.java,v 1.1 2004-07-09 06:50:48 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.sound.jsound; + +import java.nio.*; +import java.nio.ByteBuffer; +import java.nio.ShortBuffer; + +import jake2.game.cvar_t; +import jake2.sound.*; +import jake2.sound.sfx_t; +import jake2.sound.sfxcache_t; +import jake2.util.Math3D; + +/** + * SND_MIX + */ +public class SND_MIX extends SND_JAVA { + + static final int MAX_CHANNELS = 32; + static final int MAX_RAW_SAMPLES = 8192; + + static class playsound_t { + playsound_t prev, next; + sfx_t sfx; + float volume; + float attenuation; + int entnum; + int entchannel; + boolean fixed_origin; // use origin field instead of entnum's origin + float[] origin = { 0, 0, 0 }; + long begin; // begin on this sample + + public void clear() { + prev = next = null; + sfx = null; + volume = attenuation = begin = entnum = entchannel = 0; + fixed_origin = false; + Math3D.VectorClear(origin); + } + }; + + static class channel_t { + sfx_t sfx; // sfx number + int leftvol; // 0-255 volume + int rightvol; // 0-255 volume + int end; // end time in global paintsamples + int pos; // sample position in sfx + int looping; // where to loop, -1 = no looping OBSOLETE? + int entnum; // to allow overriding a specific sound + int entchannel; // + float[] origin = { 0, 0, 0 }; // only use if fixed_origin is set + float dist_mult; // distance multiplier (attenuation/clipK) + int master_vol; // 0-255 master volume + boolean fixed_origin; // use origin instead of fetching entnum's origin + boolean autosound; // from an entity->sound, cleared each frame + + void clear() { + sfx = null; + dist_mult = leftvol = rightvol = end = pos = looping = entnum = entchannel = master_vol = 0; + Math3D.VectorClear(origin); + fixed_origin = autosound = false; + } + }; + + static class portable_samplepair_t { + int left; + int right; + }; + + static cvar_t s_volume; + static int s_rawend; +//// snd_mix.c -- portable code to mix sounds for snd_dma.c +// +// #include "client.h" +// #include "snd_loc.h" +// + static final int PAINTBUFFER_SIZE = 2048; + //static portable_samplepair_t[] paintbuffer = new portable_samplepair_t[PAINTBUFFER_SIZE]; + static IntBuffer paintbuffer = IntBuffer.allocate(PAINTBUFFER_SIZE*2); + static int[][] snd_scaletable = new int[32][256]; +// int *snd_p, snd_linear_count, snd_vol; +// short *snd_out; + static IntBuffer snd_p; + static ShortBuffer snd_out; + static int snd_linear_count; + static int snd_vol; + + static int paintedtime; // sample PAIRS + static playsound_t s_pendingplays = new playsound_t(); + + //static portable_samplepair_t[] s_rawsamples = new portable_samplepair_t[MAX_RAW_SAMPLES]; + static IntBuffer s_rawsamples = IntBuffer.allocate(MAX_RAW_SAMPLES*2); + static channel_t[] channels = new channel_t[MAX_CHANNELS]; + static { + for(int i=0; i < MAX_CHANNELS; i++) + channels[i] = new channel_t(); + } + + static void WriteLinearBlastStereo16() + { + int i; + int val; + + for (i=0 ; i<snd_linear_count ; i+=2) + { + val = snd_p.get(i)>>8; + if (val > 0x7fff) + snd_out.put(i, (short)0x7fff); + else if (val < (short)0x8000) + snd_out.put(i,(short)0x8000); + else + snd_out.put(i, (short)val); + + val = snd_p.get(i+1)>>8; + if (val > 0x7fff) + snd_out.put(i+1, (short)0x7fff); + else if (val < (short)0x8000) + snd_out.put(i+1, (short)0x8000); + else + snd_out.put(i+1, (short)val); + } + } + + static void TransferStereo16(ByteBuffer pbuf, int endtime) + { + int lpos; + int lpaintedtime; + + snd_p = paintbuffer; + lpaintedtime = paintedtime; + + while (lpaintedtime < endtime) + { + // handle recirculating buffer issues + lpos = lpaintedtime & ((dma.samples>>1)-1); + +// snd_out = (short *) pbuf + (lpos<<1); + snd_out = pbuf.asShortBuffer(); + snd_out.position(lpos<<1); + snd_out = snd_out.slice(); + + snd_linear_count = (dma.samples>>1) - lpos; + if (lpaintedtime + snd_linear_count > endtime) + snd_linear_count = endtime - lpaintedtime; + + snd_linear_count <<= 1; + + // write a linear blast of samples + WriteLinearBlastStereo16(); + + //snd_p += snd_linear_count; + paintbuffer.position(snd_linear_count); + snd_p = paintbuffer.slice(); + + lpaintedtime += (snd_linear_count>>1); + } + } + + /* + =================== + S_TransferPaintBuffer + + =================== + */ + static void TransferPaintBuffer(int endtime) + { + int out_idx; + int count; + int out_mask; + int p; + int step; + int val; + //unsigned long *pbuf; + + ByteBuffer pbuf = ByteBuffer.wrap(dma.buffer); + pbuf.order(ByteOrder.LITTLE_ENDIAN); + + if (SND_DMA.s_testsound.value != 0.0f) + { + int i; + int count2; + + // write a fixed sine wave + count2 = (endtime - paintedtime)*2; + int v; + for (i=0 ; i<count2 ; i+=2) { + v = (int)(Math.sin((paintedtime+i)*0.1)*20000*256); + paintbuffer.put(i, v); + paintbuffer.put(i+1, v); + } + } + + + if (dma.samplebits == 16 && dma.channels == 2) + { // optimized case + TransferStereo16(pbuf, endtime); + } + else + { // general case + p = 0; + count = (endtime - paintedtime) * dma.channels; + out_mask = dma.samples - 1; + out_idx = paintedtime * dma.channels & out_mask; + step = 3 - dma.channels; + + if (dma.samplebits == 16) + { +// short *out = (short *) pbuf; + ShortBuffer out = pbuf.asShortBuffer(); + while (count-- > 0) + { + val = paintbuffer.get(p) >> 8; + p+= step; + if (val > 0x7fff) + val = 0x7fff; + else if (val < (short)0x8000) + val = (short)0x8000; + out.put(out_idx, (short)val); +//System.out.println(out_idx + " " + val); + out_idx = (out_idx + 1) & out_mask; + } + } + else if (dma.samplebits == 8) + { +// unsigned char *out = (unsigned char *) pbuf; + ByteBuffer out = pbuf; + while (count-- > 0) + { + val = paintbuffer.get(p) >> 8; + p += step; + if (val > 0x7fff) + val = 0x7fff; + else if (val < (short)0x8000) + val = (short)0x8000; + out.put(out_idx,(byte)(val>>>8)); + out_idx = (out_idx + 1) & out_mask; + } + } + } + } + + + /* + =============================================================================== + + CHANNEL MIXING + + =============================================================================== + */ + static void PaintChannels(int endtime) + { + int i; + int end; + channel_t ch; + sfxcache_t sc; + int ltime, count; + playsound_t ps; + + snd_vol = (int)(s_volume.value*256); + +// Com_Printf ("%i to %i\n", paintedtime, endtime); + while (paintedtime < endtime) + { + // if paintbuffer is smaller than DMA buffer + end = endtime; + if (endtime - paintedtime > PAINTBUFFER_SIZE) + end = paintedtime + PAINTBUFFER_SIZE; + + // start any playsounds + while (true) + { + ps = s_pendingplays.next; + if (ps == s_pendingplays) + break; // no more pending sounds + if (ps.begin <= paintedtime) + { + SND_DMA.IssuePlaysound(ps); + continue; + } + + if (ps.begin < end) + end = (int)ps.begin; // stop here + break; + } + + // clear the paint buffer + if (s_rawend < paintedtime) + { +// Com_Printf ("clear\n"); + for (i = 0; i < (end-paintedtime)*2; i++) { + paintbuffer.put(i, 0); + } + //memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t)); + } + else + { // copy from the streaming sound source + int s; + int stop; + + stop = (end < s_rawend) ? end : s_rawend; + + for (i=paintedtime ; i<stop ; i++) + { + s = i&(MAX_RAW_SAMPLES-1); + //paintbuffer[i-paintedtime] = s_rawsamples[s]; + paintbuffer.put((i-paintedtime)*2, s_rawsamples.get(2*s)); + paintbuffer.put((i-paintedtime)*2+1, s_rawsamples.get(2*s)+1); + } +// if (i != end) +// Com_Printf ("partial stream\n"); +// else +// Com_Printf ("full stream\n"); + for ( ; i<end ; i++) + { + //paintbuffer[i-paintedtime].left = + //paintbuffer[i-paintedtime].right = 0; + paintbuffer.put((i-paintedtime)*2, 0); + paintbuffer.put((i-paintedtime)*2+1, 0); + } + } + + + // paint in the channels. + //ch = channels; + for (i=0; i<MAX_CHANNELS ; i++) + { + ch = channels[i]; + ltime = paintedtime; + + while (ltime < end) + { + if (ch.sfx == null || (ch.leftvol == 0 && ch.rightvol == 0)) + break; + + // max painting is to the end of the buffer + count = end - ltime; + + // might be stopped by running out of data + if (ch.end - ltime < count) + count = ch.end - ltime; + + sc = WaveLoader.LoadSound(ch.sfx); + if (sc == null) + break; + + if (count > 0 && ch.sfx != null) + { + if (sc.width == 1)// FIXME; 8 bit asm is wrong now + PaintChannelFrom8(ch, sc, count, ltime - paintedtime); + else + PaintChannelFrom16(ch, sc, count, ltime - paintedtime); + + ltime += count; + } + + // if at end of loop, restart + if (ltime >= ch.end) + { + if (ch.autosound) + { // autolooping sounds always go back to start + ch.pos = 0; + ch.end = ltime + sc.length; + } + else if (sc.loopstart >= 0) + { + ch.pos = sc.loopstart; + ch.end = ltime + sc.length - ch.pos; + } + else + { // channel just stopped + ch.sfx = null; + } + } + } + + } + + // transfer out according to DMA format + TransferPaintBuffer(end); + paintedtime = end; + } + } + + static void InitScaletable () + { + int i, j; + int scale; + + s_volume.modified = false; + for (i=0 ; i<32 ; i++) + { + scale = (int)(i * 8 * 256 * s_volume.value); + for (j=0 ; j<256 ; j++) + snd_scaletable[i][j] = ((byte)j) * scale; + } + } + + static void PaintChannelFrom8(channel_t ch, sfxcache_t sc, int count, int offset) + { + int data; + int[] lscale; + int[] rscale; + int sfx; + int i; + portable_samplepair_t samp; + + if (ch.leftvol > 255) + ch.leftvol = 255; + if (ch.rightvol > 255) + ch.rightvol = 255; + + //ZOID-- >>11 has been changed to >>3, >>11 didn't make much sense + //as it would always be zero. + lscale = snd_scaletable[ ch.leftvol >> 3]; + rscale = snd_scaletable[ ch.rightvol >> 3]; + sfx = ch.pos; + + //samp = paintbuffer[offset]; + + for (i=0 ; i<count ; i++, offset++) + { + int left = paintbuffer.get(offset*2); + int right = paintbuffer.get(offset*2+1); + data = sc.data[sfx+i]; + left += lscale[data]; + right += rscale[data]; + paintbuffer.put(offset*2, left); + paintbuffer.put(offset*2+1, right); + } + + ch.pos += count; + } + + private static ByteBuffer bb; + private static ShortBuffer sb; + static void PaintChannelFrom16(channel_t ch, sfxcache_t sc, int count, int offset) + { + int data; + int left, right; + int leftvol, rightvol; + int sfx; + int i; + portable_samplepair_t samp; + + leftvol = ch.leftvol*snd_vol; + rightvol = ch.rightvol*snd_vol; + ByteBuffer bb = ByteBuffer.wrap(sc.data); + bb.order(ByteOrder.LITTLE_ENDIAN); + sb = bb.asShortBuffer(); + sfx = ch.pos; + + //samp = paintbuffer[offset]; + for (i=0 ; i<count ; i++, offset++) + { + left = paintbuffer.get(offset*2); + right = paintbuffer.get(offset*2+1); + data = sb.get(sfx+i); + left += (data * leftvol)>>8; + right += (data * rightvol)>>8; + paintbuffer.put(offset*2, left); + paintbuffer.put(offset*2+1, right); + } + + ch.pos += count; + } + +}
\ No newline at end of file diff --git a/src/jake2/sys/NET.java b/src/jake2/sys/NET.java index 19a3a59..50f7ceb 100644 --- a/src/jake2/sys/NET.java +++ b/src/jake2/sys/NET.java @@ -2,7 +2,7 @@ * NET.java * Copyright (C) 2003 * - * $Id: NET.java,v 1.1 2004-07-07 19:59:51 hzi Exp $ + * $Id: NET.java,v 1.2 2004-07-09 06:50:47 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -686,8 +686,8 @@ public final class NET extends Defines { ==================== */ public static String NET_ErrorString() { + int code; - //code = errno; //return strerror (code); return "errno can not yet resolved in java"; @@ -700,7 +700,7 @@ public final class NET extends Defines { return; // we're not a server, just run full speed try { - //TODO: check for + //TODO: check for timeout Thread.sleep(msec); } catch (InterruptedException e) { diff --git a/src/jake2/sys/Sys.java b/src/jake2/sys/Sys.java index 8a08956..b65098c 100644 --- a/src/jake2/sys/Sys.java +++ b/src/jake2/sys/Sys.java @@ -2,7 +2,7 @@ * Sys.java * Copyright (C) 2003 * - * $Id: Sys.java,v 1.3 2004-07-08 20:24:30 hzi Exp $ + * $Id: Sys.java,v 1.4 2004-07-09 06:50:47 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -44,14 +44,6 @@ import jake2.util.Lib; */ public final class Sys extends Defines { - public static void StackTrace() { - - StackTraceElement trace[] = new Throwable().getStackTrace(); - Com.Println("StackTrace:"); - for (int i = 0; i < trace.length; i++) - Com.Println("" + trace[i]); - } - public static void Error(String error) { CL.Shutdown(); @@ -259,11 +251,6 @@ public final class Sys extends Defines { Globals.sys_frame_time = Sys.Milliseconds(); } - public static game_export_t GetGameAPI(game_import_t gimport) - { - return Game.GetGameApi(gimport); - } - public static String GetClipboardData() { // TODO: implement GetClipboardData return null; diff --git a/src/jake2/util/Lib.java b/src/jake2/util/Lib.java index bab5ff0..8a965ab 100644 --- a/src/jake2/util/Lib.java +++ b/src/jake2/util/Lib.java @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Created on 09.12.2003 by RST. -// $Id: Lib.java,v 1.2 2004-07-08 15:58:48 hzi Exp $ +// $Id: Lib.java,v 1.3 2004-07-09 06:50:51 hzi Exp $ package jake2.util; @@ -28,37 +28,17 @@ import jake2.qcommon.Com; import jake2.qcommon.FS; import java.io.*; +import java.nio.*; import java.nio.ByteBuffer; +import java.nio.FloatBuffer; import java.util.Arrays; import java.util.StringTokenizer; -public class Lib { - - /* - ============= - TempVector - - This is just a convenience function - for making temporary vectors for function calls - ============= - */ - public static float tv_vecs[][] = new float[8][3]; - public static int tv_index; - public static float[] tv(float x, float y, float z) { +import net.java.games.jogl.util.BufferUtils; - float[] v; - - // use an array so that multiple tempvectors won't collide - // for a while - v = tv_vecs[tv_index]; - tv_index = (tv_index++) & 7; +public class Lib { - v[0] = x; - v[1] = y; - v[2] = z; - return v; - } /* ============= VectorToString @@ -92,9 +72,6 @@ public class Lib { public static float crand() { return (Globals.rnd.nextFloat() - 0.5f) * 2.0f; } - public static float frand() { - return Globals.rnd.nextFloat(); - } public static int strcmp(String in1, String in2) { return in1.compareTo(in2); @@ -108,25 +85,6 @@ public class Lib { return (i1.indexOf(i2) != -1); } - public static int strncmp(String in1, String in2, int len) { - int i1 = Math.min(len, in1.length()); - int i2 = Math.min(len, in2.length()); - - if (i1 < i2) - return -1; - if (i1 > i2) - return 1; - - for (int n = 0; n < i1; n++) { - char c1 = in1.charAt(n); - char c2 = in2.charAt(n); - if (c1 < c2) - return -1; - if (c1 > c2) - return 1; - } - return 0; - } public static float atof(String in) { float res = 0; @@ -189,17 +147,6 @@ public class Lib { in += i; } - public static void strcpy(char dest[], char src[]) { - for (int i = 0; i < dest.length && i < src.length; i++) - if (src[i] == 0) { - dest[i] = 0; - return; - } - else - dest[i] = src[i]; - - } - public static void strcpy(byte dest[], byte src[]) { for (int i = 0; i < dest.length && i < src.length; i++) if (src[i] == 0) { @@ -385,33 +332,6 @@ public class Lib { return result; } - public static void main(String[] args) { - System.out.println("testing Lib..."); - - String linetest = "line 1\r\n line zwo\nline drei\n\r line4\n.line5"; - - String line[] = linesplit(linetest); - - for (int n = 0; n < line.length; n++) { - System.out.println("[" + line[n] + "]"); - } - - String v = "0.234 1.23423 7.23423"; - - int i1 = v.indexOf(" "); - int i2 = v.indexOf(" ", i1 + 1); - - System.out.println("testing substring..."); - - System.out.println("[" + v.substring(0, i1) + "]"); - System.out.println("[" + v.substring(i1 + 1, i2) + "]"); - System.out.println("[" + v.substring(i2 + 1, v.length()) + "]"); - - System.out.println("rightfrom[" + rightFrom("abcdefg#hijklm", '#') + "]"); - System.out.println("leftfrom[" + leftFrom("abcdefghijk#12", '#') + "]"); - System.out.println("leftfrom[" + leftFrom("abcdefghi", '#') + "]"); - } - public static int rename(String oldn, String newn) { try { File f1 = new File(oldn); @@ -436,23 +356,6 @@ public class Lib { public static int getInt(byte b[]) { return (b[0] & 0xff) | ((b[1] & 0xff) << 8) | ((b[2] & 0xff) << 16) | ((b[3] & 0xff) << 24); } - - public static void sleep(int sec) { - try { - Thread.sleep(sec * 1000); - } - catch (InterruptedException e) { - } - } - - public static byte[] clone(byte in[]) { - byte out[] = new byte[in.length]; - - if (in.length != 0) - System.arraycopy(in, 0, out, 0, in.length); - - return out; - } public static float[] clone(float in[]) { float out[] = new float[in.length]; @@ -463,15 +366,6 @@ public class Lib { return out; } - public static short[] clone(short in[]) { - short out[] = new short[in.length]; - - if (in.length != 0) - System.arraycopy(in, 0, out, 0, in.length); - - return out; - } - public static long[] clone(long in[]) { long out[] = new long[in.length]; @@ -516,4 +410,44 @@ public class Lib { return out; } + + /* + * java.nio.* Buffer util functions + */ + + public static final int SIZEOF_FLOAT = BufferUtils.SIZEOF_FLOAT; + public static final int SIZEOF_INT = BufferUtils.SIZEOF_INT; + + public static FloatBuffer newFloatBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_FLOAT); + return bb.asFloatBuffer(); + } + + public static FloatBuffer newFloatBuffer(int numElements, ByteOrder order) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_FLOAT, order); + return bb.asFloatBuffer(); + } + + public static IntBuffer newIntBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_INT); + return bb.asIntBuffer(); + } + + public static IntBuffer newIntBuffer(int numElements, ByteOrder order) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_INT, order); + return bb.asIntBuffer(); + } + + public static ByteBuffer newByteBuffer(int numElements) { + ByteBuffer bb = ByteBuffer.allocateDirect(numElements); + bb.order(ByteOrder.nativeOrder()); + return bb; + } + + public static ByteBuffer newByteBuffer(int numElements, ByteOrder order) { + ByteBuffer bb = ByteBuffer.allocateDirect(numElements); + bb.order(order); + return bb; + } + } |