/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Modifications
Copyright 2003-2004 Bytonic Software
Copyright 2010 Google Inc.
*/
package com.googlecode.gwtquake.shared.render;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Arrays;
import com.googlecode.gwtquake.shared.common.Com;
import com.googlecode.gwtquake.shared.common.Constants;
import com.googlecode.gwtquake.shared.game.*;
import com.googlecode.gwtquake.shared.util.Math3D;
public class Surface {
public int visframe; // should be drawn when node is crossed
public Plane plane;
public int flags;
public int firstedge; // look up in model->surfedges[], negative numbers
public int numedges; // are backwards edges
public short texturemins[] = { 0, 0 };
public short extents[] = { 0, 0 };
public int light_s, light_t; // gl lightmap coordinates
public int dlight_s, dlight_t;
// gl lightmap coordinates for dynamic lightmaps
public Polygon polys; // multiple if warped
public Surface texturechain;
public Surface lightmapchain;
// TODO check this
public Texture texinfo = new Texture();
// lighting info
public int dlightframe;
public int dlightbits;
public int lightmaptexturenum;
public byte styles[] = new byte[Constants.MAXLIGHTMAPS];
public float cached_light[] = new float[Constants.MAXLIGHTMAPS];
// values currently used in lightmap
// public byte samples[]; // [numstyles*surfsize]
public ByteBuffer samples; // [numstyles*surfsize]
/**
* R_BuildLightMap
*
* Combine and scale multiple lightmaps into the floating format in
* blocklights
*/
public void R_BuildLightMap(IntBuffer dest, int stride) {
int r, g, b, a, max;
int i, j;
int nummaps;
float[] bl;
// lightstyle_t style;
if ((texinfo.flags & (Constants.SURF_SKY | Constants.SURF_TRANS33
| Constants.SURF_TRANS66 | Constants.SURF_WARP)) != 0)
Com.Error(Constants.ERR_DROP,
"R_BuildLightMap called for non-lit surface");
int smax = (extents[0] >> 4) + 1;
int tmax = (extents[1] >> 4) + 1;
int size = smax * tmax;
if (size > ((Surfaces.s_blocklights.length * Constants.SIZE_OF_FLOAT) >> 4))
Com.Error(Constants.ERR_DROP, "Bad s_blocklights size");
// try {
// set to full bright if no light data
if (samples == null) {
// int maps;
for (i = 0; i < size * 3; i++)
Surfaces.s_blocklights[i] = 255;
// TODO useless? hoz
// for (maps = 0 ; maps < Defines.MAXLIGHTMAPS &&
// surf.styles[maps] != (byte)255; maps++)
// {
// style = r_newrefdef.lightstyles[surf.styles[maps] & 0xFF];
// }
// goto store;
// throw gotoStore;
} else {
// count the # of maps
for (nummaps = 0; nummaps < Constants.MAXLIGHTMAPS
&& styles[nummaps] != (byte) 255; nummaps++)
;
ByteBuffer lightmap = samples;
int lightmapIndex = 0;
// add all the lightmaps
float scale0;
float scale1;
float scale2;
if (nummaps == 1) {
int maps;
for (maps = 0; maps < Constants.MAXLIGHTMAPS
&& styles[maps] != (byte) 255; maps++) {
bl = Surfaces.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];
scale0 = GlConfig.gl_modulate.value
* GlState.r_newrefdef.lightstyles[styles[maps] & 0xFF].rgb[0];
scale1 = GlConfig.gl_modulate.value
* GlState.r_newrefdef.lightstyles[styles[maps] & 0xFF].rgb[1];
scale2 = GlConfig.gl_modulate.value
* GlState.r_newrefdef.lightstyles[styles[maps] & 0xFF].rgb[2];
if (scale0 == 1.0F && scale1 == 1.0F && scale2 == 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) * scale0;
bl[blp++] = (lightmap.get(lightmapIndex++) & 0xFF) * scale1;
bl[blp++] = (lightmap.get(lightmapIndex++) & 0xFF) * scale2;
}
}
// lightmap += size*3; // skip to next lightmap
}
} else {
int maps;
// memset( s_blocklights, 0, sizeof( s_blocklights[0] ) * size *
// 3 );
Arrays.fill(Surfaces.s_blocklights, 0, size * 3, 0.0f);
for (maps = 0; maps < Constants.MAXLIGHTMAPS
&& styles[maps] != (byte) 255; maps++) {
bl = Surfaces.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];
scale0 = GlConfig.gl_modulate.value
* GlState.r_newrefdef.lightstyles[styles[maps] & 0xFF].rgb[0];
scale1 = GlConfig.gl_modulate.value
* GlState.r_newrefdef.lightstyles[styles[maps] & 0xFF].rgb[1];
scale2 = GlConfig.gl_modulate.value
* GlState.r_newrefdef.lightstyles[styles[maps] & 0xFF].rgb[2];
if (scale0 == 1.0F && scale1 == 1.0F && scale2 == 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) * scale0;
bl[blp++] += (lightmap.get(lightmapIndex++) & 0xFF) * scale1;
bl[blp++] += (lightmap.get(lightmapIndex++) & 0xFF) * scale2;
}
}
// lightmap += size*3; // skip to next lightmap
}
}
// add all the dynamic lights
if (dlightframe == GlState.r_framecount) {
R_AddDynamicLights(this);
}
// label store:
// } catch (Throwable store) {
}
// put into texture format
stride -= smax;
bl = Surfaces.s_blocklights;
int blp = 0;
int monolightmap = GlConfig.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);
}
// if (j == 0 || i == 0 || j == smax-1 || i == tmax-1) {
// r = g = b = a = 0;
// }
// r &= 0xFF; g &= 0xFF; b &= 0xFF; a &= 0xFF;
dest.put(destp++, (a << 24) | (b << 16) | (g << 8) | r);
}
}
} 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);
float af = a / 255.0f;
r *= af;
g *= af;
b *= af;
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);
}
}
}
}
/*
* ================ CalcSurfaceExtents
*
* Fills in s.texturemins[] and s.extents[] ================
*/
void CalcSurfaceExtents() {
float[] mins = { 0, 0 };
float[] maxs = { 0, 0 };
float val;
int j, e;
Vertex v;
int[] bmins = { 0, 0 };
int[] bmaxs = { 0, 0 };
mins[0] = mins[1] = 999999;
maxs[0] = maxs[1] = -99999;
Texture tex = texinfo;
for (int i = 0; i < numedges; i++) {
e = Models.loadmodel.surfedges[firstedge + i];
if (e >= 0)
v = Models.loadmodel.vertexes[Models.loadmodel.edges[e].v[0]];
else
v = Models.loadmodel.vertexes[Models.loadmodel.edges[-e].v[1]];
for (j = 0; j < 2; j++) {
val = v.position[0] * tex.vecs[j][0] + v.position[1] * tex.vecs[j][1]
+ v.position[2] * tex.vecs[j][2] + tex.vecs[j][3];
if (val < mins[j])
mins[j] = val;
if (val > maxs[j])
maxs[j] = val;
}
}
for (int i = 0; i < 2; i++) {
bmins[i] = (int) Math.floor(mins[i] / 16);
bmaxs[i] = (int) Math.ceil(maxs[i] / 16);
texturemins[i] = (short) (bmins[i] * 16);
extents[i] = (short) ((bmaxs[i] - bmins[i]) * 16);
}
}
/**
* GL_SubdivideSurface Breaks a polygon up along axial 64 unit boundaries so
* that turbulent and sky warps can be done reasonably.
*/
void GL_SubdivideSurface() {
float[][] verts = tmpVerts;
float[] vec;
//
// convert edges back to a normal polygon
//
int numverts = 0;
for (int i = 0; i < numedges; i++) {
int lindex = Models.loadmodel.surfedges[firstedge + i];
if (lindex > 0) {
vec = Models.loadmodel.vertexes[Models.loadmodel.edges[lindex].v[0]].position;
} else {
vec = Models.loadmodel.vertexes[Models.loadmodel.edges[-lindex].v[1]].position;
}
Math3D.VectorCopy(vec, verts[numverts]);
numverts++;
}
Surfaces.SubdividePolygon(this, numverts, verts);
}
public void clear() {
visframe = 0;
plane.clear();
flags = 0;
firstedge = 0;
numedges = 0;
texturemins[0] = texturemins[1] = -1;
extents[0] = extents[1] = 0;
light_s = light_t = 0;
dlight_s = dlight_t = 0;
polys = null;
texturechain = null;
lightmapchain = null;
// texinfo = new mtexinfo_t();
texinfo.clear();
dlightframe = 0;
dlightbits = 0;
lightmaptexturenum = 0;
for (int i = 0; i < styles.length; i++) {
styles[i] = 0;
}
for (int i = 0; i < cached_light.length; i++) {
cached_light[i] = 0;
}
if (samples != null)
samples.clear();
}
static final float[][] tmpVerts = new float[64][3];
// TODO sync with jogl renderer. hoz
/**
* R_SetCacheState
*/
public static void R_SetCacheState(Surface surf) {
for (int maps = 0; maps < Constants.MAXLIGHTMAPS
&& surf.styles[maps] != (byte) 255; maps++) {
surf.cached_light[maps] = GlState.r_newrefdef.lightstyles[surf.styles[maps] & 0xFF].white;
}
}
/**
* R_AddDynamicLights
*/
static void R_AddDynamicLights(Surface surf) {
int sd, td;
float fdist, frad, fminlight;
int s, t;
DynamicLight dl;
float[] pfBL;
float fsacc, ftacc;
int smax = (surf.extents[0] >> 4) + 1;
int tmax = (surf.extents[1] >> 4) + 1;
Texture tex = surf.texinfo;
float local0, local1;
for (int lnum = 0; lnum < GlState.r_newrefdef.num_dlights; lnum++) {
if ((surf.dlightbits & (1 << lnum)) == 0)
continue; // not lit by this light
dl = GlState.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 = GlConstants.DLIGHT_CUTOFF; // FIXME: make configurable?
if (frad < fminlight)
continue;
fminlight = frad - fminlight;
for (int i = 0; i < 3; i++) {
DynamicLights.impact[i] = dl.origin[i] - surf.plane.normal[i] * fdist;
}
local0 = Math3D.DotProduct(DynamicLights.impact, tex.vecs[0])
+ tex.vecs[0][3] - surf.texturemins[0];
local1 = Math3D.DotProduct(DynamicLights.impact, tex.vecs[1])
+ tex.vecs[1][3] - surf.texturemins[1];
pfBL = Surfaces.s_blocklights;
int pfBLindex = 0;
for (t = 0, ftacc = 0; t < tmax; t++, ftacc += 16) {
td = (int) (local1 - ftacc);
if (td < 0)
td = -td;
for (s = 0, fsacc = 0; s < smax; s++, fsacc += 16, pfBLindex += 3) {
sd = (int) (local0 - 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];
}
}
}
}
}
/**
* EmitWaterPolys Does a water warp on the pre-fragmented glpoly_t chain
*/
public static void EmitWaterPolys(Surface fa) {
float rdt = GlState.r_newrefdef.time;
float scroll;
if ((fa.texinfo.flags & Constants.SURF_FLOWING) != 0)
scroll = -64
* ((GlState.r_newrefdef.time * 0.5f) - (int) (GlState.r_newrefdef.time * 0.5f));
else
scroll = 0;
int i;
float s, t, os, ot;
Polygon p, bp;
for (bp = fa.polys; bp != null; bp = bp.next) {
p = bp;
GlState.gl.glBegin(Gl1Context.GL_TRIANGLE_FAN);
for (i = 0; i < p.numverts; i++) {
os = p.getS1(i);
ot = p.getT1(i);
s = os
+ GlConstants.SIN[(int) ((ot * 0.125f + GlState.r_newrefdef.time) * GlConstants.TURBSCALE) & 255];
s += scroll;
s *= (1.0f / 64);
t = ot
+ GlConstants.SIN[(int) ((os * 0.125f + rdt) * GlConstants.TURBSCALE) & 255];
t *= (1.0f / 64);
GlState.gl.glTexCoord2f(s, t);
GlState.gl.glVertex3f(p.getX(i), p.getY(i), p.getZ(i));
}
GlState.gl.glEnd();
}
}
/**
* GL_CreateSurfaceLightmap
*/
static void GL_CreateSurfaceLightmap(Surface surf) {
if ((surf.flags & (Constants.SURF_DRAWSKY | Constants.SURF_DRAWTURB)) != 0)
return;
int smax = (surf.extents[0] >> 4) + 1;
int tmax = (surf.extents[1] >> 4) + 1;
Images.pos_t lightPos = new Images.pos_t(surf.light_s, surf.light_t);
if (!Surfaces.LM_AllocBlock(smax, tmax, lightPos)) {
Surfaces.LM_UploadBlock(false);
Surfaces.LM_InitBlock();
lightPos = new Images.pos_t(surf.light_s, surf.light_t);
if (!Surfaces.LM_AllocBlock(smax, tmax, lightPos)) {
Com.Error(Constants.ERR_FATAL, "Consecutive calls to LM_AllocBlock("
+ smax + "," + tmax + ") failed\n");
}
}
// kopiere die koordinaten zurueck
surf.light_s = lightPos.x;
surf.light_t = lightPos.y;
surf.lightmaptexturenum = Surfaces.gl_lms.current_lightmap_texture;
IntBuffer base = Surfaces.gl_lms.lightmap_buffer;
base.position(surf.light_t * Surfaces.BLOCK_WIDTH + surf.light_s);
Surface.R_SetCacheState(surf);
surf.R_BuildLightMap(base.slice(), Surfaces.BLOCK_WIDTH);
}
/**
* GL_BuildPolygonFromSurface
*/
static void GL_BuildPolygonFromSurface(Surface fa) {
// reconstruct the polygon
Edge[] pedges = GlState.currentmodel.edges;
int lnumverts = fa.numedges;
//
// draw texture
//
// poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) *
// VERTEXSIZE*sizeof(float));
Polygon poly = Polygons.create(lnumverts);
poly.next = fa.polys;
poly.flags = fa.flags;
fa.polys = poly;
int lindex;
float[] vec;
Edge r_pedge;
float s, t;
for (int i = 0; i < lnumverts; i++) {
lindex = GlState.currentmodel.surfedges[fa.firstedge + i];
if (lindex > 0) {
r_pedge = pedges[lindex];
vec = GlState.currentmodel.vertexes[r_pedge.v[0]].position;
} else {
r_pedge = pedges[-lindex];
vec = GlState.currentmodel.vertexes[r_pedge.v[1]].position;
}
// if(!fa.texinfo.image.complete) {
// gl.log("building surface with bad texture coordinates");
// }
s = Math3D.DotProduct(vec, fa.texinfo.vecs[0]) + fa.texinfo.vecs[0][3];
s /= fa.texinfo.image.width;
t = Math3D.DotProduct(vec, fa.texinfo.vecs[1]) + fa.texinfo.vecs[1][3];
t /= fa.texinfo.image.height;
poly.setX(i, vec[0]);
poly.setY(i, vec[1]);
poly.setZ(i, vec[2]);
poly.setS1(i, s);
poly.setT1(i, t);
//
// lightmap texture coordinates
//
s = Math3D.DotProduct(vec, fa.texinfo.vecs[0]) + fa.texinfo.vecs[0][3];
s -= fa.texturemins[0];
s += fa.light_s * 16;
s += 8;
s /= Surfaces.BLOCK_WIDTH * 16; // fa.texinfo.texture.width;
t = Math3D.DotProduct(vec, fa.texinfo.vecs[1]) + fa.texinfo.vecs[1][3];
t -= fa.texturemins[1];
t += fa.light_t * 16;
t += 8;
t /= Surfaces.BLOCK_HEIGHT * 16; // fa.texinfo.texture.height;
poly.setS2(i, s);
poly.setT2(i, t);
}
}
/**
* GL_RenderLightmappedPoly
*
* @param surf
*/
static void GL_RenderLightmappedPoly(Surface surf) {
// ersetzt goto
boolean gotoDynamic = false;
int map;
for (map = 0; map < Constants.MAXLIGHTMAPS
&& (surf.styles[map] != (byte) 255); map++) {
if (GlState.r_newrefdef.lightstyles[surf.styles[map] & 0xFF].white != surf.cached_light[map]) {
gotoDynamic = true;
break;
}
}
// this is a hack from cwei
if (map == 4)
map--;
// dynamic this frame or dynamic previously
boolean is_dynamic = false;
if (gotoDynamic || (surf.dlightframe == GlState.r_framecount)) {
// label dynamic:
if (GlConfig.gl_dynamic.value != 0) {
if ((surf.texinfo.flags & (Constants.SURF_SKY | Constants.SURF_TRANS33
| Constants.SURF_TRANS66 | Constants.SURF_WARP)) == 0) {
is_dynamic = true;
}
}
}
Polygon p;
Image image = Texture.R_TextureAnimation(surf.texinfo);
int lmtex = surf.lightmaptexturenum;
if (is_dynamic) {
// ist raus gezogen worden int[] temp = new int[128*128];
int smax = (surf.extents[0] >> 4) + 1;
int tmax = (surf.extents[1] >> 4) + 1;
surf.R_BuildLightMap(Surfaces.temp, smax);
if (((surf.styles[map] & 0xFF) >= 32 || surf.styles[map] == 0)
&& (surf.dlightframe != GlState.r_framecount)) {
Surface.R_SetCacheState(surf);
lmtex = surf.lightmaptexturenum;
} else {
lmtex = 0;
}
Images.GL_MBind(Gl1Context.GL_TEXTURE1,
GlConfig.gl_state.lightmap_textures + lmtex);
GlState.gl.glTexSubImage2D(Gl1Context.GL_TEXTURE_2D, 0, surf.light_s,
surf.light_t, smax, tmax, Surfaces.GL_LIGHTMAP_FORMAT,
Gl1Context.GL_UNSIGNED_BYTE, Surfaces.temp);
}
GlState.c_brush_polys++;
Images.GL_MBind(Gl1Context.GL_TEXTURE0, image.texnum);
Images.GL_MBind(Gl1Context.GL_TEXTURE1, GlConfig.gl_state.lightmap_textures
+ lmtex);
// ==========
// PGM
if ((surf.texinfo.flags & Constants.SURF_FLOWING) != 0) {
float scroll;
scroll = -64
* ((GlState.r_newrefdef.time / 40.0f) - (int) (GlState.r_newrefdef.time / 40.0f));
if (scroll == 0.0f)
scroll = -64.0f;
for (p = surf.polys; p != null; p = p.chain) {
p.beginScrolling(scroll);
GlState.gl.glDrawArrays(Gl1Context._GL_POLYGON, p.pos, p.numverts);
p.endScrolling();
}
} else {
for (p = surf.polys; p != null; p = p.chain) {
GlState.gl.glDrawArrays(Gl1Context._GL_POLYGON, p.pos, p.numverts);
}
}
// PGM
// ==========
// }
// else
// {
// c_brush_polys++;
//
// GL_MBind( GL_TEXTURE0, image.texnum );
// GL_MBind( GL_TEXTURE1, gl_state.lightmap_textures + lmtex);
//
// // ==========
// // PGM
// if ((surf.texinfo.flags & Defines.SURF_FLOWING) != 0)
// {
// float scroll;
//
// scroll = -64 * ( (r_newrefdef.time / 40.0f) - (int)(r_newrefdef.time /
// 40.0f) );
// if(scroll == 0.0)
// scroll = -64.0f;
//
// for ( p = surf.polys; p != null; p = p.chain )
// {
// p.beginScrolling(scroll);
// gl.glDrawArrays(GLAdapter._GL_POLYGON, p.pos, p.numverts);
// p.endScrolling();
// }
// }
// else
// {
// // PGM
// // ==========
// for ( p = surf.polys; p != null; p = p.chain )
// {
// gl.glDrawArrays(GLAdapter._GL_POLYGON, p.pos, p.numverts);
// }
//
// // ==========
// // PGM
// }
// // PGM
// // ==========
// }
}
/**
* R_RenderBrushPoly
*/
public static void R_RenderBrushPoly(Surface fa) {
GlState.c_brush_polys++;
Image image = Texture.R_TextureAnimation(fa.texinfo);
if ((fa.flags & Constants.SURF_DRAWTURB) != 0) {
Images.GL_Bind(image.texnum);
// warp texture, no lightmaps
Images.GL_TexEnv(Gl1Context.GL_MODULATE);
GlState.gl.glColor4f(GlState.inverse_intensity,
GlState.inverse_intensity, GlState.inverse_intensity, 1.0F);
Surface.EmitWaterPolys(fa);
Images.GL_TexEnv(Gl1Context.GL_REPLACE);
return;
} else {
Images.GL_Bind(image.texnum);
Images.GL_TexEnv(Gl1Context.GL_REPLACE);
}
// ======
// PGM
if ((fa.texinfo.flags & Constants.SURF_FLOWING) != 0)
fa.polys.drawFlowing();
else
fa.polys.draw();
// PGM
// ======
// ersetzt goto
boolean gotoDynamic = false;
/*
* * check for lightmap modification
*/
int maps;
for (maps = 0; maps < Constants.MAXLIGHTMAPS
&& fa.styles[maps] != (byte) 255; maps++) {
if (GlState.r_newrefdef.lightstyles[fa.styles[maps] & 0xFF].white != fa.cached_light[maps]) {
gotoDynamic = true;
break;
}
}
// this is a hack from cwei
if (maps == 4)
maps--;
// dynamic this frame or dynamic previously
boolean is_dynamic = false;
if (gotoDynamic || (fa.dlightframe == GlState.r_framecount)) {
// label dynamic:
if (GlConfig.gl_dynamic.value != 0) {
if ((fa.texinfo.flags & (Constants.SURF_SKY | Constants.SURF_TRANS33
| Constants.SURF_TRANS66 | Constants.SURF_WARP)) == 0) {
is_dynamic = true;
}
}
}
if (is_dynamic) {
if (((fa.styles[maps] & 0xFF) >= 32 || fa.styles[maps] == 0)
&& (fa.dlightframe != GlState.r_framecount)) {
// ist ersetzt durch temp2: unsigned temp[34*34];
int smax, tmax;
smax = (fa.extents[0] >> 4) + 1;
tmax = (fa.extents[1] >> 4) + 1;
fa.R_BuildLightMap(Surfaces.temp2, smax);
Surface.R_SetCacheState(fa);
Images.GL_Bind(GlState.lightmap_textures + fa.lightmaptexturenum);
GlState.gl.glTexSubImage2D(Gl1Context.GL_TEXTURE_2D, 0, fa.light_s,
fa.light_t, smax, tmax, Surfaces.GL_LIGHTMAP_FORMAT,
Gl1Context.GL_UNSIGNED_BYTE, Surfaces.temp2);
fa.lightmapchain = Surfaces.gl_lms.lightmap_surfaces[fa.lightmaptexturenum];
Surfaces.gl_lms.lightmap_surfaces[fa.lightmaptexturenum] = fa;
} else {
fa.lightmapchain = Surfaces.gl_lms.lightmap_surfaces[0];
Surfaces.gl_lms.lightmap_surfaces[0] = fa;
}
} else {
fa.lightmapchain = Surfaces.gl_lms.lightmap_surfaces[fa.lightmaptexturenum];
Surfaces.gl_lms.lightmap_surfaces[fa.lightmaptexturenum] = fa;
}
}
}