aboutsummaryrefslogtreecommitdiffstats
path: root/src/jake2/render/jogl
diff options
context:
space:
mode:
Diffstat (limited to 'src/jake2/render/jogl')
-rw-r--r--src/jake2/render/jogl/Image.java3288
-rw-r--r--src/jake2/render/jogl/Light.java1438
-rw-r--r--src/jake2/render/jogl/Mesh.java1637
-rw-r--r--src/jake2/render/jogl/Warp.java1341
4 files changed, 3776 insertions, 3928 deletions
diff --git a/src/jake2/render/jogl/Image.java b/src/jake2/render/jogl/Image.java
index 64588ef..1edb8fe 100644
--- a/src/jake2/render/jogl/Image.java
+++ b/src/jake2/render/jogl/Image.java
@@ -2,34 +2,36 @@
* Image.java
* Copyright (C) 2003
*
- * $Id: Image.java,v 1.5 2004-07-16 10:11:35 cawe Exp $
+ * $Id: Image.java,v 1.6 2004-09-22 19:22:16 salomo Exp $
*/
/*
-Copyright (C) 1997-2001 Id Software, Inc.
+ 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 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.
+ 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.
+ 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.
+ 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.jogl;
import jake2.Defines;
import jake2.client.VID;
import jake2.client.particle_t;
import jake2.game.cvar_t;
-import jake2.qcommon.*;
+import jake2.qcommon.Com;
+import jake2.qcommon.Cvar;
+import jake2.qcommon.FS;
import jake2.qcommon.longjmpException;
import jake2.qcommon.qfiles;
import jake2.render.image_t;
@@ -40,7 +42,9 @@ import java.awt.Dimension;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
-import java.nio.*;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
import java.util.Arrays;
import net.java.games.jogl.GL;
@@ -52,1643 +56,1615 @@ import net.java.games.jogl.GL;
*/
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 (!qglSelectTextureSGIS && !qglActiveTextureARB)
- return;
-
- 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;
-
- if (!qglSelectTextureSGIS && !qglActiveTextureARB)
- return;
-
- if (texture == GL_TEXTURE0) {
- tmu = 0;
- }
- else {
- tmu = 1;
- }
-
- if (tmu == gl_state.currenttmu) {
- return;
- }
-
- gl_state.currenttmu = tmu;
-
- if (qglSelectTextureSGIS) {
- // TODO handle this: gl.glSelectTextureSGIS(texture);
- gl.glActiveTexture(texture);
- }
- else if (qglActiveTextureARB) {
- 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) {
- VID.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) {
- VID.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) {
- VID.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" };
-
- VID.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 :
- VID.Printf(Defines.PRINT_ALL, "M");
- break;
- case it_sprite :
- VID.Printf(Defines.PRINT_ALL, "S");
- break;
- case it_wall :
- VID.Printf(Defines.PRINT_ALL, "W");
- break;
- case it_pic :
- VID.Printf(Defines.PRINT_ALL, "P");
- break;
- default :
- VID.Printf(Defines.PRINT_ALL, " ");
- break;
- }
-
- VID.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));
- }
- VID.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 = FS.LoadFile(filename);
-
- if (raw == null) {
- VID.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) {
-
- VID.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 = FS.LoadFile (name);
-
- if (raw == null)
- {
- VID.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)
- Com.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))
- Com.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];
- // }
- static floodfill_t[] fifo = new floodfill_t[FLOODFILL_FIFO_SIZE];
- static {
- for (int j = 0; j < fifo.length; j++) {
- fifo[j] = new floodfill_t();
- }
- }
- // 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;
- int inpt = 0, outpt = 0;
- int filledcolor = -1;
- int i;
-
- 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)
- Com.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 {
- VID.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)
- Com.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)
- Com.Error (Defines.ERR_DROP, "MAX_GLTEXTURES");
-
- numgltextures++;
- }
- image = gltextures[i];
-
- if (name.length() > Defines.MAX_QPATH)
- Com.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 = FS.LoadFile(name);
- if (raw == null) {
- VID.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; // Com.Error (ERR_DROP, "GL_FindImage: NULL name");
- // Com.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)
- Com.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 = Cvar.Get("intensity", "2", 0);
-
- if (intensity.value <= 1)
- Cvar.Set("intensity", "1");
-
- gl_state.inverse_intensity = 1 / intensity.value;
-
- Draw_GetPalette();
-
- if (qglColorTableEXT) {
- gl_state.d_16to8table = FS.LoadFile("pics/16to8.dat");
- if (gl_state.d_16to8table == null)
- Com.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();
- }
- }
-
-}
+ 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 (!qglSelectTextureSGIS && !qglActiveTextureARB)
+ return;
+
+ 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;
+
+ if (!qglSelectTextureSGIS && !qglActiveTextureARB)
+ return;
+
+ if (texture == GL_TEXTURE0) {
+ tmu = 0;
+ } else {
+ tmu = 1;
+ }
+
+ if (tmu == gl_state.currenttmu) {
+ return;
+ }
+
+ gl_state.currenttmu = tmu;
+
+ if (qglSelectTextureSGIS) {
+ // TODO handle this: gl.glSelectTextureSGIS(texture);
+ gl.glActiveTexture(texture);
+ } else if (qglActiveTextureARB) {
+ 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) {
+ VID
+ .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) {
+ VID.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) {
+ VID.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" };
+
+ VID.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:
+ VID.Printf(Defines.PRINT_ALL, "M");
+ break;
+ case it_sprite:
+ VID.Printf(Defines.PRINT_ALL, "S");
+ break;
+ case it_wall:
+ VID.Printf(Defines.PRINT_ALL, "W");
+ break;
+ case it_pic:
+ VID.Printf(Defines.PRINT_ALL, "P");
+ break;
+ default:
+ VID.Printf(Defines.PRINT_ALL, " ");
+ break;
+ }
+
+ VID.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));
+ }
+ VID.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 = FS.LoadFile(filename);
+
+ if (raw == null) {
+ VID.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) {
+
+ VID.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 = FS.LoadFile(name);
+
+ if (raw == null) {
+ VID.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)
+ Com.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))
+ Com
+ .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];
+ // }
+ static floodfill_t[] fifo = new floodfill_t[FLOODFILL_FIFO_SIZE];
+ static {
+ for (int j = 0; j < fifo.length; j++) {
+ fifo[j] = new floodfill_t();
+ }
+ }
+
+ // 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;
+ int inpt = 0, outpt = 0;
+ int filledcolor = -1;
+ int i;
+
+ 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)
+ Com.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 {
+ VID.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)
+ Com.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)
+ Com.Error(Defines.ERR_DROP, "MAX_GLTEXTURES");
+
+ numgltextures++;
+ }
+ image = gltextures[i];
+
+ if (name.length() > Defines.MAX_QPATH)
+ Com.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 = FS.LoadFile(name);
+ if (raw == null) {
+ VID.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; // Com.Error (ERR_DROP, "GL_FindImage: NULL name");
+ // Com.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)
+ Com.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 = Cvar.Get("intensity", "2", 0);
+
+ if (intensity.value <= 1)
+ Cvar.Set("intensity", "1");
+
+ gl_state.inverse_intensity = 1 / intensity.value;
+
+ Draw_GetPalette();
+
+ if (qglColorTableEXT) {
+ gl_state.d_16to8table = FS.LoadFile("pics/16to8.dat");
+ if (gl_state.d_16to8table == null)
+ Com.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();
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/jake2/render/jogl/Light.java b/src/jake2/render/jogl/Light.java
index de23629..f6b8e10 100644
--- a/src/jake2/render/jogl/Light.java
+++ b/src/jake2/render/jogl/Light.java
@@ -2,38 +2,39 @@
* Light.java
* Copyright (C) 2003
*
- * $Id: Light.java,v 1.6 2004-07-16 10:11:35 cawe Exp $
+ * $Id: Light.java,v 1.7 2004-09-22 19:22:16 salomo Exp $
*/
/*
-Copyright (C) 1997-2001 Id Software, Inc.
+ 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 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.
+ 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.
+ 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.
+ 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.jogl;
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.Com;
import jake2.qcommon.longjmpException;
-import jake2.render.*;
+import jake2.render.mnode_t;
+import jake2.render.msurface_t;
+import jake2.render.mtexinfo_t;
import jake2.util.Math3D;
import java.nio.ByteBuffer;
@@ -44,730 +45,687 @@ 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()
- {
- 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
- 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 (i=0 ; i<r_newrefdef.num_dlights ; i++)
- {
- l = r_newrefdef.dlights[i];
- R_RenderDlight (l);
- }
-
- 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)
- {
- if (node.contents != -1)
- return -1; // didn't hit anything
-
- msurface_t surf;
- int s, t, ds, dt;
- int i;
- mtexinfo_t tex;
- ByteBuffer lightmap;
- int maps;
- float[] mid = {0, 0, 0};
-
- // calculate mid point
-
- // FIXME: optimize for axial
- cplane_t plane = node.plane;
- float front = Math3D.DotProduct (start, plane.normal) - plane.dist;
- float back = Math3D.DotProduct (end, plane.normal) - plane.dist;
- boolean side = (front < 0);
- int sideIndex = (side) ? 1 : 0;
-
- if ( (back < 0) == side)
- return RecursiveLightPoint (node.children[sideIndex], start, end);
-
- float 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
- int 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;
- float[] scale = {0, 0, 0};
- 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};
- dlight_t dl;
- 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;
-
- float 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
- //
- for (int lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
- {
- dl = r_newrefdef.dlights[lnum];
-
- Math3D.VectorSubtract (currententity.origin, dl.origin, end);
- add = dl.intensity - Math3D.VectorLength(end);
- 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 )
- Com.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) )
- Com.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));
- }
- }
- }
- }
-
-}
+ // 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() {
+ 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
+ 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 (i = 0; i < r_newrefdef.num_dlights; i++) {
+ l = r_newrefdef.dlights[i];
+ R_RenderDlight(l);
+ }
+
+ 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) {
+ if (node.contents != -1)
+ return -1; // didn't hit anything
+
+ msurface_t surf;
+ int s, t, ds, dt;
+ int i;
+ mtexinfo_t tex;
+ ByteBuffer lightmap;
+ int maps;
+ float[] mid = { 0, 0, 0 };
+
+ // calculate mid point
+
+ // FIXME: optimize for axial
+ cplane_t plane = node.plane;
+ float front = Math3D.DotProduct(start, plane.normal) - plane.dist;
+ float back = Math3D.DotProduct(end, plane.normal) - plane.dist;
+ boolean side = (front < 0);
+ int sideIndex = (side) ? 1 : 0;
+
+ if ((back < 0) == side)
+ return RecursiveLightPoint(node.children[sideIndex], start, end);
+
+ float 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
+ int 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;
+ float[] scale = { 0, 0, 0 };
+ 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 };
+ dlight_t dl;
+ 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;
+
+ float r = RecursiveLightPoint(r_worldmodel.nodes[0], p, end);
+
+ if (r == -1) {
+ Math3D.VectorCopy(Globals.vec3_origin, color);
+ } else {
+ Math3D.VectorCopy(pointcolor, color);
+ }
+
+ //
+ // add dynamic lights
+ //
+ for (int lnum = 0; lnum < r_newrefdef.num_dlights; lnum++) {
+ dl = r_newrefdef.dlights[lnum];
+
+ Math3D.VectorSubtract(currententity.origin, dl.origin, end);
+ add = dl.intensity - Math3D.VectorLength(end);
+ 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)
+ Com.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))
+ Com.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));
+ }
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/jake2/render/jogl/Mesh.java b/src/jake2/render/jogl/Mesh.java
index 4a8aed3..d6dc90c 100644
--- a/src/jake2/render/jogl/Mesh.java
+++ b/src/jake2/render/jogl/Mesh.java
@@ -2,27 +2,27 @@
* Mesh.java
* Copyright (C) 2003
*
- * $Id: Mesh.java,v 1.6 2004-07-16 10:11:35 cawe Exp $
+ * $Id: Mesh.java,v 1.7 2004-09-22 19:22:16 salomo Exp $
*/
/*
-Copyright (C) 1997-2001 Id Software, Inc.
+ 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 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.
+ 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.
+ 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.
+ 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.jogl;
import jake2.Defines;
@@ -39,828 +39,795 @@ import net.java.games.jogl.util.BufferUtils;
/**
* 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[][] s_lerped = new float[qfiles.MAX_VERTS][4];
-
-
- 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, float[][] lerp, float[] move, float[] frontv, float[] backv )
- {
- int i;
- int lerpIndex = 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;
- for (i=0 ; i < nverts; i++/* , v++, ov++, lerp+=4 */)
- {
- normal = r_avertexnormals[verts[i].lightnormalindex];
-
- lerp[i][0] = move[0] + ov[i].v[0]*backv[0] + v[i].v[0]*frontv[0] + normal[0] * Defines.POWERSUIT_SCALE;
- lerp[i][1] = move[1] + ov[i].v[1]*backv[1] + v[i].v[1]*frontv[1] + normal[1] * Defines.POWERSUIT_SCALE;
- lerp[i][2] = move[2] + ov[i].v[2]*backv[2] + v[i].v[2]*frontv[2] + normal[2] * Defines.POWERSUIT_SCALE;
- }
- }
- else
- {
- for (i=0 ; i < nverts; i++ /* , v++, ov++, lerp+=4 */)
- {
- lerp[i][0] = move[0] + ov[i].v[0]*backv[0] + v[i].v[0]*frontv[0];
- lerp[i][1] = move[1] + ov[i].v[1]*backv[1] + v[i].v[1]*frontv[1];
- lerp[i][2] = move[2] + ov[i].v[2]*backv[2] + v[i].v[2]*frontv[2];
- }
- }
- }
-
- void GL_LerpVerts( int nverts, qfiles.dtrivertx_t[] v, qfiles.dtrivertx_t[] ov, qfiles.dtrivertx_t[] verts, float[] move, float[] frontv, float[] backv )
- {
- int lerpIndex = 0;
-
- int[] ovv;
- int[] vv;
- FloatBuffer lerp = vertexArrayBuf;
-
- //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 (int 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 (int 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);
- boolean isFilled = false;
- float[] tmpVec = {0, 0, 0};
-
- /*
- =============
- 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[][] vectors = {
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0} // 3 mal vec3_t
- };
-
- float[] frontv = {0, 0, 0}; // vec3_t
- float[] backv = {0, 0, 0}; // vec3_t
-
- int i;
- int index_xyz;
- //float[][] lerp;
-
- frame = paliashdr.aliasFrames[currententity.frame];
-
- verts = v = frame.verts;
-
- oldframe = paliashdr.aliasFrames[currententity.oldframe];
-
- ov = oldframe.verts;
-
- order = paliashdr.glCmds;
-
- 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, frontv);
- Math3D.AngleVectors (currententity.angles, vectors[0], vectors[1], vectors[2]);
-
- move[0] = Math3D.DotProduct(frontv, vectors[0]); // forward
- move[1] = -Math3D.DotProduct(frontv, vectors[1]); // left
- move[2] = Math3D.DotProduct(frontv, vectors[2]); // up
-
- Math3D.VectorAdd (move, oldframe.translate, move);
-
- for (i=0 ; i<3 ; i++)
- {
- move[i] = backlerp*move[i] + frontlerp*frame.translate[i];
- frontv[i] = frontlerp*frame.scale[i];
- backv[i] = backlerp*oldframe.scale[i];
- }
-
- if ( gl_vertex_arrays.value != 0.0f )
- {
- GL_LerpVerts( paliashdr.num_xyz, v, ov, verts, 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);
- }
- }
-
- if ( qglLockArraysEXT )
- gl.glLockArraysEXT( 0, paliashdr.num_xyz );
-
- 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);
- }
-
- // 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 )
- {
- do
- {
- index_xyz = order[orderIndex + 2];
- orderIndex += 3;
- /*
- vertexArrayBuf.position(4 * index_xyz);
- vertexArrayBuf.get(tmpVec);
- gl.glVertex3fv( tmpVec );
- */
- gl.glArrayElement( index_xyz );
-
- } while (--count != 0);
- }
- else
- {
- do
- {
- // texture coordinates come from the draw list
- gl.glTexCoord2f (Float.intBitsToFloat(order[orderIndex + 0]), Float.intBitsToFloat(order[orderIndex + 1]));
-
- index_xyz = order[orderIndex + 2];
- orderIndex += 3;
-
- // normals and vertexes come from the frame list
- gl.glArrayElement( index_xyz );
-
- } while (--count != 0);
- }
- gl.glEnd ();
- }
-
- 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
- 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);
- }
-
- if ( (currententity.flags & ( Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE )) != 0 )
- {
- do
- {
- index_xyz = order[orderIndex + 2];
- orderIndex += 3;
-
- gl.glColor4f( shadelight[0], shadelight[1], shadelight[2], alpha);
- tmp = s_lerped[index_xyz];
- gl.glVertex3f(tmp[0], tmp[1], tmp[2]);
-
- } while (--count != 0);
- }
- else
- {
- do
- {
- // texture coordinates come from the draw list
- // gl.glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
-
- gl.glTexCoord2f (Float.intBitsToFloat(order[orderIndex + 0]), Float.intBitsToFloat(order[orderIndex + 1]));
- index_xyz = order[orderIndex + 2];
- orderIndex += 3;
-
- // normals and vertexes come from the frame list
- l = shadedots[verts[index_xyz].lightnormalindex];
-
- gl.glColor4f (l* shadelight[0], l*shadelight[1], l*shadelight[2], alpha);
- tmp = s_lerped[index_xyz];
- gl.glVertex3f(tmp[0], tmp[1], tmp[2]);
- } while (--count != 0);
- }
- gl.glEnd ();
- }
- }
-
- // 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_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;
-
- 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
- {
- // normals and vertexes come from the frame list
- /*
- point[0] = verts[order[2]].v[0] * frame.scale[0] + frame.translate[0];
- point[1] = verts[order[2]].v[1] * frame.scale[1] + frame.translate[1];
- point[2] = verts[order[2]].v[2] * frame.scale[2] + frame.translate[2];
- */
-
- if ( gl_vertex_arrays.value != 0.0f )
- {
- index = order[orderIndex + 2] * 3;
- point[0] = vertexArrayBuf.get(index);
- point[1] = vertexArrayBuf.get(index + 1);
- point[2] = vertexArrayBuf.get(index + 2);
- }
- else
- {
- 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.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[][] vectors = {
- {0, 0, 0},
- {0, 0, 0},
- {0, 0, 0}
- };
-
- 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 ) )
- {
- VID.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 ) )
- {
- VID.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] );
-
- for ( i = 0; i < 8; i++ )
- {
- float[] tmp = {0, 0, 0};
-
- 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;
- }
- }
-
- /*
- =================
- R_DrawAliasModel
-
- =================
- */
- void R_DrawAliasModel(entity_t e)
- {
- int i;
- qfiles.dmdl_t paliashdr;
- float an;
-
- // 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}
- };
- 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) )
- {
- VID.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))
- {
- VID.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);
- }
-
-}
+ // g_mesh.c: triangle model functions
+
+ /*
+ * =============================================================
+ *
+ * ALIAS MODELS
+ *
+ * =============================================================
+ */
+
+ static final int NUMVERTEXNORMALS = 162;
+
+ float[][] r_avertexnormals = Anorms.VERTEXNORMALS;
+
+ float[][] s_lerped = new float[qfiles.MAX_VERTS][4];
+
+ 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,
+ float[][] lerp, float[] move, float[] frontv, float[] backv) {
+ int i;
+ int lerpIndex = 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;
+ for (i = 0; i < nverts; i++ /* , v++, ov++, lerp+=4 */
+ ) {
+ normal = r_avertexnormals[verts[i].lightnormalindex];
+
+ lerp[i][0] = move[0] + ov[i].v[0] * backv[0] + v[i].v[0]
+ * frontv[0] + normal[0] * Defines.POWERSUIT_SCALE;
+ lerp[i][1] = move[1] + ov[i].v[1] * backv[1] + v[i].v[1]
+ * frontv[1] + normal[1] * Defines.POWERSUIT_SCALE;
+ lerp[i][2] = move[2] + ov[i].v[2] * backv[2] + v[i].v[2]
+ * frontv[2] + normal[2] * Defines.POWERSUIT_SCALE;
+ }
+ } else {
+ for (i = 0; i < nverts; i++ /* , v++, ov++, lerp+=4 */
+ ) {
+ lerp[i][0] = move[0] + ov[i].v[0] * backv[0] + v[i].v[0]
+ * frontv[0];
+ lerp[i][1] = move[1] + ov[i].v[1] * backv[1] + v[i].v[1]
+ * frontv[1];
+ lerp[i][2] = move[2] + ov[i].v[2] * backv[2] + v[i].v[2]
+ * frontv[2];
+ }
+ }
+ }
+
+ void GL_LerpVerts(int nverts, qfiles.dtrivertx_t[] v,
+ qfiles.dtrivertx_t[] ov, qfiles.dtrivertx_t[] verts, float[] move,
+ float[] frontv, float[] backv) {
+ int lerpIndex = 0;
+
+ int[] ovv;
+ int[] vv;
+ FloatBuffer lerp = vertexArrayBuf;
+
+ //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 (int 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 (int 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);
+
+ boolean isFilled = false;
+
+ float[] tmpVec = { 0, 0, 0 };
+
+ /*
+ * ============= 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[][] vectors = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } // 3 mal
+ // vec3_t
+ };
+
+ float[] frontv = { 0, 0, 0 }; // vec3_t
+ float[] backv = { 0, 0, 0 }; // vec3_t
+
+ int i;
+ int index_xyz;
+ //float[][] lerp;
+
+ frame = paliashdr.aliasFrames[currententity.frame];
+
+ verts = v = frame.verts;
+
+ oldframe = paliashdr.aliasFrames[currententity.oldframe];
+
+ ov = oldframe.verts;
+
+ order = paliashdr.glCmds;
+
+ 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,
+ frontv);
+ Math3D.AngleVectors(currententity.angles, vectors[0], vectors[1],
+ vectors[2]);
+
+ move[0] = Math3D.DotProduct(frontv, vectors[0]); // forward
+ move[1] = -Math3D.DotProduct(frontv, vectors[1]); // left
+ move[2] = Math3D.DotProduct(frontv, vectors[2]); // up
+
+ Math3D.VectorAdd(move, oldframe.translate, move);
+
+ for (i = 0; i < 3; i++) {
+ move[i] = backlerp * move[i] + frontlerp * frame.translate[i];
+ frontv[i] = frontlerp * frame.scale[i];
+ backv[i] = backlerp * oldframe.scale[i];
+ }
+
+ if (gl_vertex_arrays.value != 0.0f) {
+ GL_LerpVerts(paliashdr.num_xyz, v, ov, verts, 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);
+ }
+ }
+
+ if (qglLockArraysEXT)
+ gl.glLockArraysEXT(0, paliashdr.num_xyz);
+
+ 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);
+ }
+
+ // 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) {
+ do {
+ index_xyz = order[orderIndex + 2];
+ orderIndex += 3;
+ /*
+ * vertexArrayBuf.position(4 * index_xyz);
+ * vertexArrayBuf.get(tmpVec); gl.glVertex3fv( tmpVec );
+ */
+ gl.glArrayElement(index_xyz);
+
+ } while (--count != 0);
+ } else {
+ do {
+ // texture coordinates come from the draw list
+ gl.glTexCoord2f(Float
+ .intBitsToFloat(order[orderIndex + 0]), Float
+ .intBitsToFloat(order[orderIndex + 1]));
+
+ index_xyz = order[orderIndex + 2];
+ orderIndex += 3;
+
+ // normals and vertexes come from the frame list
+ gl.glArrayElement(index_xyz);
+
+ } while (--count != 0);
+ }
+ gl.glEnd();
+ }
+
+ 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
+ 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);
+ }
+
+ if ((currententity.flags & (Defines.RF_SHELL_RED
+ | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE)) != 0) {
+ do {
+ index_xyz = order[orderIndex + 2];
+ orderIndex += 3;
+
+ gl.glColor4f(shadelight[0], shadelight[1],
+ shadelight[2], alpha);
+ tmp = s_lerped[index_xyz];
+ gl.glVertex3f(tmp[0], tmp[1], tmp[2]);
+
+ } while (--count != 0);
+ } else {
+ do {
+ // texture coordinates come from the draw list
+ // gl.glTexCoord2f (((float *)order)[0], ((float
+ // *)order)[1]);
+
+ gl.glTexCoord2f(Float
+ .intBitsToFloat(order[orderIndex + 0]), Float
+ .intBitsToFloat(order[orderIndex + 1]));
+ index_xyz = order[orderIndex + 2];
+ orderIndex += 3;
+
+ // normals and vertexes come from the frame list
+ l = shadedots[verts[index_xyz].lightnormalindex];
+
+ gl.glColor4f(l * shadelight[0], l * shadelight[1], l
+ * shadelight[2], alpha);
+ tmp = s_lerped[index_xyz];
+ gl.glVertex3f(tmp[0], tmp[1], tmp[2]);
+ } while (--count != 0);
+ }
+ gl.glEnd();
+ }
+ }
+
+ // 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_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;
+
+ 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 {
+ // normals and vertexes come from the frame list
+ /*
+ * point[0] = verts[order[2]].v[0] * frame.scale[0] +
+ * frame.translate[0]; point[1] = verts[order[2]].v[1] *
+ * frame.scale[1] + frame.translate[1]; point[2] =
+ * verts[order[2]].v[2] * frame.scale[2] + frame.translate[2];
+ */
+
+ if (gl_vertex_arrays.value != 0.0f) {
+ index = order[orderIndex + 2] * 3;
+ point[0] = vertexArrayBuf.get(index);
+ point[1] = vertexArrayBuf.get(index + 1);
+ point[2] = vertexArrayBuf.get(index + 2);
+ } else {
+ 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.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[][] vectors = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };
+
+ 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)) {
+ VID.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)) {
+ VID.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]);
+
+ for (i = 0; i < 8; i++) {
+ float[] tmp = { 0, 0, 0 };
+
+ 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;
+ }
+ }
+
+ /*
+ * ================= R_DrawAliasModel
+ *
+ * =================
+ */
+ void R_DrawAliasModel(entity_t e) {
+ int i;
+ qfiles.dmdl_t paliashdr;
+ float an;
+
+ // 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 } };
+ 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)) {
+ VID.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)) {
+ VID.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);
+ }
+
+} \ No newline at end of file
diff --git a/src/jake2/render/jogl/Warp.java b/src/jake2/render/jogl/Warp.java
index cd926c6..bde9697 100644
--- a/src/jake2/render/jogl/Warp.java
+++ b/src/jake2/render/jogl/Warp.java
@@ -2,720 +2,667 @@
* Warp.java
* Copyright (C) 2003
*
- * $Id: Warp.java,v 1.6 2004-07-16 10:11:35 cawe Exp $
+ * $Id: Warp.java,v 1.7 2004-09-22 19:22:16 salomo Exp $
*/
/*
-Copyright (C) 1997-2001 Id Software, Inc.
+ 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 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.
+ 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.
+ 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.
+ 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.jogl;
import jake2.Defines;
import jake2.Globals;
import jake2.qcommon.Com;
-import jake2.render.*;
+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;
- float s, t;
- float[] total = {0, 0, 0};
- float total_s, total_t;
-
- if (numverts > 60)
- Com.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
- glpoly_t 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); // :-)
- }
-
- /*
- ================
- 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;
- for (bp=fa.polys ; bp != null ; bp=bp.next)
- {
- p = bp;
-
- gl.glBegin(GL.GL_TRIANGLE_FAN);
- 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);
-
- gl.glTexCoord2f (s, t);
- gl.glVertex3f(v[0], v[1], v[2]);
- }
- gl.glEnd ();
- }
- }
-
-// ===================================================================
-
-
- 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)
- Com.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;
- }
- }
- }
-
-
-}
+
+ // 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;
+ float s, t;
+ float[] total = { 0, 0, 0 };
+ float total_s, total_t;
+
+ if (numverts > 60)
+ Com.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
+ glpoly_t 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); // :-)
+ }
+
+ /*
+ * ================ 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;
+ for (bp = fa.polys; bp != null; bp = bp.next) {
+ p = bp;
+
+ gl.glBegin(GL.GL_TRIANGLE_FAN);
+ 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);
+
+ gl.glTexCoord2f(s, t);
+ gl.glVertex3f(v[0], v[1], v[2]);
+ }
+ gl.glEnd();
+ }
+ }
+
+ // ===================================================================
+
+ 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)
+ Com.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;
+ }
+ }
+ }
+
+} \ No newline at end of file