📄 surf.java
字号:
/* * Surf.java * Copyright (C) 2003 * * $Id: Surf.java,v 1.6 2005/01/09 22:34:21 cawe Exp $ *//*Copyright (C) 1997-2001 Id Software, Inc.This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of 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 ofMERCHANTABILITY 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 Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/package jake2.render.jogl;import jake2.Defines;import jake2.client.*;import jake2.game.cplane_t;import jake2.qcommon.Com;import jake2.render.*;import jake2.util.Lib;import jake2.util.Math3D;import java.nio.ByteOrder;import java.nio.IntBuffer;import java.util.Arrays;import net.java.games.jogl.GL;/** * Surf * * @author cwei */public abstract class Surf extends Draw { // GL_RSURF.C: surface-related refresh code float[] modelorg = {0, 0, 0}; // relative to viewpoint msurface_t r_alpha_surfaces; static final int DYNAMIC_LIGHT_WIDTH = 128; static final int DYNAMIC_LIGHT_HEIGHT = 128; static final int LIGHTMAP_BYTES = 4; static final int BLOCK_WIDTH = 128; static final int BLOCK_HEIGHT = 128; static final int MAX_LIGHTMAPS = 128; int c_visible_lightmaps; int c_visible_textures; static final int GL_LIGHTMAP_FORMAT = GL.GL_RGBA; static class gllightmapstate_t { int internal_format; int current_lightmap_texture; msurface_t[] lightmap_surfaces = new msurface_t[MAX_LIGHTMAPS]; int[] allocated = new int[BLOCK_WIDTH]; // the lightmap texture data needs to be kept in // main memory so texsubimage can update properly IntBuffer lightmap_buffer = Lib.newIntBuffer(BLOCK_WIDTH * BLOCK_HEIGHT, ByteOrder.LITTLE_ENDIAN); public gllightmapstate_t() { for (int i = 0; i < MAX_LIGHTMAPS; i++) lightmap_surfaces[i] = new msurface_t(); } public void clearLightmapSurfaces() { for (int i = 0; i < MAX_LIGHTMAPS; i++) // TODO lightmap_surfaces[i].clear(); lightmap_surfaces[i] = new msurface_t(); } } gllightmapstate_t gl_lms = new gllightmapstate_t();//// static void LM_InitBlock( void );// static void LM_UploadBlock( qboolean dynamic );// static qboolean LM_AllocBlock (int w, int h, int *x, int *y);//// extern void R_SetCacheState( msurface_t *surf );// extern void R_BuildLightMap (msurface_t *surf, byte *dest, int stride);// // Model.java abstract byte[] Mod_ClusterPVS(int cluster, model_t model); // Warp.java abstract void R_DrawSkyBox(); abstract void R_AddSkySurface(msurface_t surface); abstract void R_ClearSkyBox(); abstract void EmitWaterPolys(msurface_t fa); // Light.java abstract void R_MarkLights (dlight_t light, int bit, mnode_t node); abstract void R_SetCacheState( msurface_t surf ); abstract void R_BuildLightMap(msurface_t surf, IntBuffer dest, int stride); /* ============================================================= BRUSH MODELS ============================================================= */ /* =============== R_TextureAnimation Returns the proper texture for a given time and base texture =============== */ image_t R_TextureAnimation(mtexinfo_t tex) { int c; if (tex.next == null) return tex.image; c = currententity.frame % tex.numframes; while (c != 0) { tex = tex.next; c--; } return tex.image; } /* ================ DrawGLPoly ================ */ void DrawGLPoly(glpoly_t p) { gl.glBegin(GL.GL_POLYGON); for (int i=0 ; i<p.numverts ; i++) { gl.glTexCoord2f(p.s1(i), p.t1(i)); gl.glVertex3f(p.x(i), p.y(i), p.z(i)); } gl.glEnd(); } // ============ // PGM /* ================ DrawGLFlowingPoly -- version of DrawGLPoly that handles scrolling texture ================ */ void DrawGLFlowingPoly(msurface_t fa) { float scroll = -64 * ( (r_newrefdef.time / 40.0f) - (int)(r_newrefdef.time / 40.0f) ); if(scroll == 0.0f) scroll = -64.0f; gl.glBegin (GL.GL_POLYGON); glpoly_t p = fa.polys; for (int i=0 ; i<p.numverts ; i++) { gl.glTexCoord2f(p.s1(i) + scroll, p.t1(i)); gl.glVertex3f(p.x(i), p.y(i), p.z(i)); } gl.glEnd (); } // PGM // ============ /* ** R_DrawTriangleOutlines */ void R_DrawTriangleOutlines() { if (gl_showtris.value == 0) return; gl.glDisable (GL.GL_TEXTURE_2D); gl.glDisable (GL.GL_DEPTH_TEST); gl.glColor4f (1,1,1,1); for (int i=0 ; i<MAX_LIGHTMAPS ; i++) { msurface_t surf; for ( surf = gl_lms.lightmap_surfaces[i]; surf != null; surf = surf.lightmapchain ) { glpoly_t p = surf.polys; for ( ; p != null ; p=p.chain) { for (int j=2 ; j<p.numverts ; j++ ) { gl.glBegin (GL.GL_LINE_STRIP); gl.glVertex3f(p.x(0), p.y(0), p.z(0)); gl.glVertex3f(p.x(j-1), p.y(j-1), p.z(j-1)); gl.glVertex3f(p.x(j), p.y(j), p.z(j)); gl.glVertex3f(p.x(0), p.y(0), p.z(0)); gl.glEnd (); } } } } gl.glEnable (GL.GL_DEPTH_TEST); gl.glEnable (GL.GL_TEXTURE_2D); } /* ** DrawGLPolyChain */ void DrawGLPolyChain( glpoly_t p, float soffset, float toffset ) { if ( soffset == 0 && toffset == 0 ) { for ( ; p != null; p = p.chain ) { gl.glBegin(GL.GL_POLYGON); for (int j=0 ; j<p.numverts ; j++) { gl.glTexCoord2f (p.s2(j), p.t2(j)); gl.glVertex3f(p.x(j), p.y(j), p.z(j)); } gl.glEnd(); } } else { for ( ; p != null; p = p.chain ) { gl.glBegin(GL.GL_POLYGON); for (int j=0 ; j<p.numverts ; j++) { gl.glTexCoord2f (p.s2(j) - soffset, p.t2(j) - toffset); gl.glVertex3f(p.x(j), p.y(j), p.z(j)); } gl.glEnd(); } } } /* ** R_BlendLightMaps ** ** This routine takes all the given light mapped surfaces in the world and ** blends them into the framebuffer. */ void R_BlendLightmaps() { int i; msurface_t surf; msurface_t newdrawsurf = null; // don't bother if we're set to fullbright if (r_fullbright.value != 0) return; if (r_worldmodel.lightdata == null) return; // don't bother writing Z gl.glDepthMask( false ); /* ** set the appropriate blending mode unless we're only looking at the ** lightmaps. */ if (gl_lightmap.value == 0) { gl.glEnable(GL.GL_BLEND); if ( gl_saturatelighting.value != 0) { gl.glBlendFunc( GL.GL_ONE, GL.GL_ONE ); } else { char format = gl_monolightmap.string.toUpperCase().charAt(0); if ( format != '0' ) { switch ( format ) { case 'I': gl.glBlendFunc(GL.GL_ZERO, GL.GL_SRC_COLOR ); break; case 'L': gl.glBlendFunc(GL.GL_ZERO, GL.GL_SRC_COLOR ); break; case 'A': default: gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA ); break; } } else { gl.glBlendFunc(GL.GL_ZERO, GL.GL_SRC_COLOR ); } } } if ( currentmodel == r_worldmodel ) c_visible_lightmaps = 0; /* ** render static lightmaps first */ for ( i = 1; i < MAX_LIGHTMAPS; i++ ) { if ( gl_lms.lightmap_surfaces[i] != null ) { if (currentmodel == r_worldmodel) c_visible_lightmaps++; GL_Bind( gl_state.lightmap_textures + i); for ( surf = gl_lms.lightmap_surfaces[i]; surf != null; surf = surf.lightmapchain ) { if ( surf.polys != null ) DrawGLPolyChain( surf.polys, 0, 0 ); } } } // TODO impl: render dynamic lightmaps /* ** render dynamic lightmaps */ if ( gl_dynamic.value != 0 ) { LM_InitBlock(); GL_Bind( gl_state.lightmap_textures+0 ); if (currentmodel == r_worldmodel) c_visible_lightmaps++; newdrawsurf = gl_lms.lightmap_surfaces[0]; for ( surf = gl_lms.lightmap_surfaces[0]; surf != null; surf = surf.lightmapchain ) { int smax, tmax; IntBuffer base; smax = (surf.extents[0]>>4)+1; tmax = (surf.extents[1]>>4)+1; pos_t lightPos = new pos_t(surf.dlight_s, surf.dlight_t); if ( LM_AllocBlock( smax, tmax, lightPos) ) { // kopiere die koordinaten zurueck surf.dlight_s = lightPos.x; surf.dlight_t = lightPos.y; base = gl_lms.lightmap_buffer; base.position(surf.dlight_t * BLOCK_WIDTH + surf.dlight_s ); R_BuildLightMap (surf, base.slice(), BLOCK_WIDTH); } else { msurface_t drawsurf; // upload what we have so far LM_UploadBlock( true ); // draw all surfaces that use this lightmap for ( drawsurf = newdrawsurf; drawsurf != surf; drawsurf = drawsurf.lightmapchain ) { if ( drawsurf.polys != null ) DrawGLPolyChain( drawsurf.polys, ( drawsurf.light_s - drawsurf.dlight_s ) * ( 1.0f / 128.0f ), ( drawsurf.light_t - drawsurf.dlight_t ) * ( 1.0f / 128.0f ) ); } newdrawsurf = drawsurf; // clear the block LM_InitBlock(); // try uploading the block now if ( !LM_AllocBlock( smax, tmax, lightPos) ) { Com.Error( Defines.ERR_FATAL, "Consecutive calls to LM_AllocBlock(" + smax + "," + tmax + ") failed (dynamic)\n"); } // kopiere die koordinaten zurueck surf.dlight_s = lightPos.x; surf.dlight_t = lightPos.y; base = gl_lms.lightmap_buffer; base.position(surf.dlight_t * BLOCK_WIDTH + surf.dlight_s ); R_BuildLightMap (surf, base.slice(), BLOCK_WIDTH); } } /* ** draw remainder of dynamic lightmaps that haven't been uploaded yet */ if ( newdrawsurf != null ) LM_UploadBlock( true ); for ( surf = newdrawsurf; surf != null; surf = surf.lightmapchain ) { if ( surf.polys != null ) DrawGLPolyChain( surf.polys, ( surf.light_s - surf.dlight_s ) * ( 1.0f / 128.0f ), ( surf.light_t - surf.dlight_t ) * ( 1.0f / 128.0f ) ); } } /* ** restore state */ gl.glDisable(GL.GL_BLEND); gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); gl.glDepthMask( true ); } private IntBuffer temp2 = Lib.newIntBuffer(34 * 34, ByteOrder.LITTLE_ENDIAN); /* ================ R_RenderBrushPoly ================ */ void R_RenderBrushPoly(msurface_t fa) { int maps; image_t image; boolean is_dynamic = false; c_brush_polys++; image = R_TextureAnimation(fa.texinfo); if ((fa.flags & Defines.SURF_DRAWTURB) != 0) { GL_Bind( image.texnum ); // warp texture, no lightmaps GL_TexEnv( GL.GL_MODULATE ); gl.glColor4f( gl_state.inverse_intensity, gl_state.inverse_intensity, gl_state.inverse_intensity, 1.0F ); EmitWaterPolys (fa); GL_TexEnv( GL.GL_REPLACE ); return; } else { GL_Bind( image.texnum ); GL_TexEnv( GL.GL_REPLACE ); } // ====== // PGM if((fa.texinfo.flags & Defines.SURF_FLOWING) != 0) DrawGLFlowingPoly(fa); else DrawGLPoly (fa.polys); // PGM // ====== // ersetzt goto boolean gotoDynamic = false; /* ** check for lightmap modification */ for ( maps = 0; maps < Defines.MAXLIGHTMAPS && fa.styles[maps] != (byte)255; maps++ ) { if ( r_newrefdef.lightstyles[fa.styles[maps] & 0xFF].white != fa.cached_light[maps] ) { gotoDynamic = true; break; } } // this is a hack from cwei if (maps == 4) maps--; // dynamic this frame or dynamic previously if ( gotoDynamic || ( fa.dlightframe == r_framecount ) ) { // label dynamic: if ( gl_dynamic.value != 0 ) { if (( fa.texinfo.flags & (Defines.SURF_SKY | Defines.SURF_TRANS33 | Defines.SURF_TRANS66 | Defines.SURF_WARP ) ) == 0) { is_dynamic = true; } } } if ( is_dynamic ) { if ( ( (fa.styles[maps] & 0xFF) >= 32 || fa.styles[maps] == 0 ) && ( fa.dlightframe != r_framecount ) ) { // ist ersetzt durch temp2: unsigned temp[34*34]; int smax, tmax; smax = (fa.extents[0]>>4)+1; tmax = (fa.extents[1]>>4)+1; R_BuildLightMap( fa, temp2, smax); R_SetCacheState( fa ); GL_Bind( gl_state.lightmap_textures + fa.lightmaptexturenum ); gl.glTexSubImage2D( GL.GL_TEXTURE_2D, 0, fa.light_s, fa.light_t, smax, tmax, GL_LIGHTMAP_FORMAT, GL.GL_UNSIGNED_BYTE, temp2 ); fa.lightmapchain = gl_lms.lightmap_surfaces[fa.lightmaptexturenum]; gl_lms.lightmap_surfaces[fa.lightmaptexturenum] = fa; } else { fa.lightmapchain = gl_lms.lightmap_surfaces[0]; gl_lms.lightmap_surfaces[0] = fa; } } else { fa.lightmapchain = gl_lms.lightmap_surfaces[fa.lightmaptexturenum]; gl_lms.lightmap_surfaces[fa.lightmaptexturenum] = fa; } } /* ================ R_DrawAlphaSurfaces Draw water surfaces and windows. The BSP tree is waled front to back, so unwinding the chain of alpha_surfaces will draw back to front, giving proper ordering. ================ */ void R_DrawAlphaSurfaces() { msurface_t s;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -