diff options
Diffstat (limited to 'ioq3-r437/src/renderer')
28 files changed, 0 insertions, 25577 deletions
diff --git a/ioq3-r437/src/renderer/qgl.h b/ioq3-r437/src/renderer/qgl.h deleted file mode 100644 index c1a2b1d8..00000000 --- a/ioq3-r437/src/renderer/qgl.h +++ /dev/null @@ -1,590 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -/* -** QGL.H -*/ - -#ifndef __QGL_H__ -#define __QGL_H__ - -#if defined( __LINT__ ) - -#include <GL/gl.h> - -#elif defined( _WIN32 ) - -#if _MSC_VER -#pragma warning (disable: 4201) -#pragma warning (disable: 4214) -#pragma warning (disable: 4514) -#pragma warning (disable: 4032) -#pragma warning (disable: 4201) -#pragma warning (disable: 4214) -#endif - -#include <windows.h> -#include <gl/gl.h> - -#elif defined(MACOS_X) - -#include <OpenGL/OpenGL.h> -#include <OpenGL/gl.h> -#include <OpenGL/glu.h> -#ifndef GL_EXT_abgr -#include <OpenGL/glext.h> -#endif - -// This can be defined to use the CGLMacro.h support which avoids looking up -// the current context. -//#define USE_CGLMACROS - -#ifdef USE_CGLMACROS -#include "macosx_local.h" -#define cgl_ctx glw_state._cgl_ctx -#include <OpenGL/CGLMacro.h> -#endif - -#elif defined( __linux__ ) || defined(__FreeBSD__) - -#include <GL/gl.h> -#include <GL/glx.h> -// bk001129 - from cvs1.17 (mkv) -#if defined(__FX__) -#include <GL/fxmesa.h> -#endif - -#elif defined( __sun ) -#include <GL/gl.h> -#include <GL/glx.h> - -#else - -#include <gl.h> - -#endif - -#ifndef APIENTRY -#define APIENTRY -#endif -#ifndef WINAPI -#define WINAPI -#endif - - -//=========================================================================== - -/* -** multitexture extension definitions -*/ -#if !defined(__sun) -#define GL_ACTIVE_TEXTURE_ARB               0x84E0 -#define GL_CLIENT_ACTIVE_TEXTURE_ARB        0x84E1 -#define GL_MAX_ACTIVE_TEXTURES_ARB          0x84E2 - -#define GL_TEXTURE0_ARB                     0x84C0 -#define GL_TEXTURE1_ARB                     0x84C1 -#define GL_TEXTURE2_ARB                     0x84C2 -#define GL_TEXTURE3_ARB                     0x84C3 -#else -#define GL_MAX_ACTIVE_TEXTURES_ARB          0x84E2 -#endif /* defined(__sun) */ - -// NOTE: some Linux platforms would need those prototypes -#if defined(MACOS_X) || ( defined(__sun) && defined(__sparc) ) -typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); -typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum target); -typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum target); -#endif - -// TTimo - VC7 / XP ? -#ifdef WIN32 -typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); -typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum target); -typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum target); -#endif - -/* -** extension constants -*/ - - -// S3TC compression constants -#define GL_RGB_S3TC							0x83A0 -#define GL_RGB4_S3TC						0x83A1 - - -// extensions will be function pointers on all platforms - -extern	void ( APIENTRY * qglMultiTexCoord2fARB )( GLenum texture, GLfloat s, GLfloat t ); -extern	void ( APIENTRY * qglActiveTextureARB )( GLenum texture ); -extern	void ( APIENTRY * qglClientActiveTextureARB )( GLenum texture ); - -extern	void ( APIENTRY * qglLockArraysEXT) (GLint, GLint); -extern	void ( APIENTRY * qglUnlockArraysEXT) (void); - -//=========================================================================== - -// non-windows systems will just redefine qgl* to gl* -#if !defined( _WIN32 ) && !defined(MACOS_X) && !defined( __linux__ ) && !defined( __FreeBSD__ ) && !defined(__sun) // rb010123 - -#include "qgl_linked.h" - -#elif (defined(MACOS_X) && !defined(USE_SDL_VIDEO)) -// This includes #ifdefs for optional logging and GL error checking after every GL call as well as #defines to prevent incorrect usage of the non-'qgl' versions of the GL API. -#include "macosx_qgl.h" - -#else - -// windows systems use a function pointer for each call so we can load minidrivers - -extern  void ( APIENTRY * qglAccum )(GLenum op, GLfloat value); -extern  void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref); -extern  GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences); -extern  void ( APIENTRY * qglArrayElement )(GLint i); -extern  void ( APIENTRY * qglBegin )(GLenum mode); -extern  void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture); -extern  void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); -extern  void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor); -extern  void ( APIENTRY * qglCallList )(GLuint list); -extern  void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists); -extern  void ( APIENTRY * qglClear )(GLbitfield mask); -extern  void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -extern  void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -extern  void ( APIENTRY * qglClearDepth )(GLclampd depth); -extern  void ( APIENTRY * qglClearIndex )(GLfloat c); -extern  void ( APIENTRY * qglClearStencil )(GLint s); -extern  void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation); -extern  void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue); -extern  void ( APIENTRY * qglColor3bv )(const GLbyte *v); -extern  void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue); -extern  void ( APIENTRY * qglColor3dv )(const GLdouble *v); -extern  void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue); -extern  void ( APIENTRY * qglColor3fv )(const GLfloat *v); -extern  void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue); -extern  void ( APIENTRY * qglColor3iv )(const GLint *v); -extern  void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue); -extern  void ( APIENTRY * qglColor3sv )(const GLshort *v); -extern  void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue); -extern  void ( APIENTRY * qglColor3ubv )(const GLubyte *v); -extern  void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue); -extern  void ( APIENTRY * qglColor3uiv )(const GLuint *v); -extern  void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue); -extern  void ( APIENTRY * qglColor3usv )(const GLushort *v); -extern  void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); -extern  void ( APIENTRY * qglColor4bv )(const GLbyte *v); -extern  void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); -extern  void ( APIENTRY * qglColor4dv )(const GLdouble *v); -extern  void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -extern  void ( APIENTRY * qglColor4fv )(const GLfloat *v); -extern  void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha); -extern  void ( APIENTRY * qglColor4iv )(const GLint *v); -extern  void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha); -extern  void ( APIENTRY * qglColor4sv )(const GLshort *v); -extern  void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); -extern  void ( APIENTRY * qglColor4ubv )(const GLubyte *v); -extern  void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha); -extern  void ( APIENTRY * qglColor4uiv )(const GLuint *v); -extern  void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha); -extern  void ( APIENTRY * qglColor4usv )(const GLushort *v); -extern  void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -extern  void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode); -extern  void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -extern  void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); -extern  void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); -extern  void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -extern  void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -extern  void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -extern  void ( APIENTRY * qglCullFace )(GLenum mode); -extern  void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range); -extern  void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures); -extern  void ( APIENTRY * qglDepthFunc )(GLenum func); -extern  void ( APIENTRY * qglDepthMask )(GLboolean flag); -extern  void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar); -extern  void ( APIENTRY * qglDisable )(GLenum cap); -extern  void ( APIENTRY * qglDisableClientState )(GLenum array); -extern  void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count); -extern  void ( APIENTRY * qglDrawBuffer )(GLenum mode); -extern  void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -extern  void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -extern  void ( APIENTRY * qglEdgeFlag )(GLboolean flag); -extern  void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer); -extern  void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag); -extern  void ( APIENTRY * qglEnable )(GLenum cap); -extern  void ( APIENTRY * qglEnableClientState )(GLenum array); -extern  void ( APIENTRY * qglEnd )(void); -extern  void ( APIENTRY * qglEndList )(void); -extern  void ( APIENTRY * qglEvalCoord1d )(GLdouble u); -extern  void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u); -extern  void ( APIENTRY * qglEvalCoord1f )(GLfloat u); -extern  void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u); -extern  void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v); -extern  void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u); -extern  void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v); -extern  void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u); -extern  void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2); -extern  void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); -extern  void ( APIENTRY * qglEvalPoint1 )(GLint i); -extern  void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j); -extern  void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer); -extern  void ( APIENTRY * qglFinish )(void); -extern  void ( APIENTRY * qglFlush )(void); -extern  void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param); -extern  void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params); -extern  void ( APIENTRY * qglFogi )(GLenum pname, GLint param); -extern  void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params); -extern  void ( APIENTRY * qglFrontFace )(GLenum mode); -extern  void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -extern  GLuint ( APIENTRY * qglGenLists )(GLsizei range); -extern  void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures); -extern  void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params); -extern  void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation); -extern  void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params); -extern  GLenum ( APIENTRY * qglGetError )(void); -extern  void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params); -extern  void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params); -extern  void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params); -extern  void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params); -extern  void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v); -extern  void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v); -extern  void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v); -extern  void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params); -extern  void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params); -extern  void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values); -extern  void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values); -extern  void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values); -extern  void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params); -extern  void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask); -extern  const GLubyte * ( APIENTRY * qglGetString )(GLenum name); -extern  void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params); -extern  void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params); -extern  void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params); -extern  void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params); -extern  void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params); -extern  void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); -extern  void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params); -extern  void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params); -extern  void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params); -extern  void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params); -extern  void ( APIENTRY * qglHint )(GLenum target, GLenum mode); -extern  void ( APIENTRY * qglIndexMask )(GLuint mask); -extern  void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); -extern  void ( APIENTRY * qglIndexd )(GLdouble c); -extern  void ( APIENTRY * qglIndexdv )(const GLdouble *c); -extern  void ( APIENTRY * qglIndexf )(GLfloat c); -extern  void ( APIENTRY * qglIndexfv )(const GLfloat *c); -extern  void ( APIENTRY * qglIndexi )(GLint c); -extern  void ( APIENTRY * qglIndexiv )(const GLint *c); -extern  void ( APIENTRY * qglIndexs )(GLshort c); -extern  void ( APIENTRY * qglIndexsv )(const GLshort *c); -extern  void ( APIENTRY * qglIndexub )(GLubyte c); -extern  void ( APIENTRY * qglIndexubv )(const GLubyte *c); -extern  void ( APIENTRY * qglInitNames )(void); -extern  void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer); -extern  GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap); -extern  GLboolean ( APIENTRY * qglIsList )(GLuint list); -extern  GLboolean ( APIENTRY * qglIsTexture )(GLuint texture); -extern  void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param); -extern  void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params); -extern  void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param); -extern  void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params); -extern  void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param); -extern  void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params); -extern  void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param); -extern  void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params); -extern  void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern); -extern  void ( APIENTRY * qglLineWidth )(GLfloat width); -extern  void ( APIENTRY * qglListBase )(GLuint base); -extern  void ( APIENTRY * qglLoadIdentity )(void); -extern  void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m); -extern  void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m); -extern  void ( APIENTRY * qglLoadName )(GLuint name); -extern  void ( APIENTRY * qglLogicOp )(GLenum opcode); -extern  void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); -extern  void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); -extern  void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); -extern  void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); -extern  void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2); -extern  void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2); -extern  void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); -extern  void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); -extern  void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param); -extern  void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params); -extern  void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param); -extern  void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params); -extern  void ( APIENTRY * qglMatrixMode )(GLenum mode); -extern  void ( APIENTRY * qglMultMatrixd )(const GLdouble *m); -extern  void ( APIENTRY * qglMultMatrixf )(const GLfloat *m); -extern  void ( APIENTRY * qglNewList )(GLuint list, GLenum mode); -extern  void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz); -extern  void ( APIENTRY * qglNormal3bv )(const GLbyte *v); -extern  void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz); -extern  void ( APIENTRY * qglNormal3dv )(const GLdouble *v); -extern  void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz); -extern  void ( APIENTRY * qglNormal3fv )(const GLfloat *v); -extern  void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz); -extern  void ( APIENTRY * qglNormal3iv )(const GLint *v); -extern  void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz); -extern  void ( APIENTRY * qglNormal3sv )(const GLshort *v); -extern  void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); -extern  void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -extern  void ( APIENTRY * qglPassThrough )(GLfloat token); -extern  void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values); -extern  void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values); -extern  void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values); -extern  void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param); -extern  void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param); -extern  void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param); -extern  void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param); -extern  void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor); -extern  void ( APIENTRY * qglPointSize )(GLfloat size); -extern  void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode); -extern  void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units); -extern  void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask); -extern  void ( APIENTRY * qglPopAttrib )(void); -extern  void ( APIENTRY * qglPopClientAttrib )(void); -extern  void ( APIENTRY * qglPopMatrix )(void); -extern  void ( APIENTRY * qglPopName )(void); -extern  void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities); -extern  void ( APIENTRY * qglPushAttrib )(GLbitfield mask); -extern  void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask); -extern  void ( APIENTRY * qglPushMatrix )(void); -extern  void ( APIENTRY * qglPushName )(GLuint name); -extern  void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y); -extern  void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v); -extern  void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y); -extern  void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v); -extern  void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y); -extern  void ( APIENTRY * qglRasterPos2iv )(const GLint *v); -extern  void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y); -extern  void ( APIENTRY * qglRasterPos2sv )(const GLshort *v); -extern  void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z); -extern  void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v); -extern  void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z); -extern  void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v); -extern  void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z); -extern  void ( APIENTRY * qglRasterPos3iv )(const GLint *v); -extern  void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z); -extern  void ( APIENTRY * qglRasterPos3sv )(const GLshort *v); -extern  void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); -extern  void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v); -extern  void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); -extern  void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v); -extern  void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w); -extern  void ( APIENTRY * qglRasterPos4iv )(const GLint *v); -extern  void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w); -extern  void ( APIENTRY * qglRasterPos4sv )(const GLshort *v); -extern  void ( APIENTRY * qglReadBuffer )(GLenum mode); -extern  void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); -extern  void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); -extern  void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2); -extern  void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); -extern  void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2); -extern  void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2); -extern  void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2); -extern  void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2); -extern  void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2); -extern  GLint ( APIENTRY * qglRenderMode )(GLenum mode); -extern  void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); -extern  void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -extern  void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z); -extern  void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z); -extern  void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height); -extern  void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer); -extern  void ( APIENTRY * qglShadeModel )(GLenum mode); -extern  void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask); -extern  void ( APIENTRY * qglStencilMask )(GLuint mask); -extern  void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass); -extern  void ( APIENTRY * qglTexCoord1d )(GLdouble s); -extern  void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v); -extern  void ( APIENTRY * qglTexCoord1f )(GLfloat s); -extern  void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v); -extern  void ( APIENTRY * qglTexCoord1i )(GLint s); -extern  void ( APIENTRY * qglTexCoord1iv )(const GLint *v); -extern  void ( APIENTRY * qglTexCoord1s )(GLshort s); -extern  void ( APIENTRY * qglTexCoord1sv )(const GLshort *v); -extern  void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t); -extern  void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v); -extern  void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t); -extern  void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v); -extern  void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t); -extern  void ( APIENTRY * qglTexCoord2iv )(const GLint *v); -extern  void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t); -extern  void ( APIENTRY * qglTexCoord2sv )(const GLshort *v); -extern  void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r); -extern  void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v); -extern  void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r); -extern  void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v); -extern  void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r); -extern  void ( APIENTRY * qglTexCoord3iv )(const GLint *v); -extern  void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r); -extern  void ( APIENTRY * qglTexCoord3sv )(const GLshort *v); -extern  void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q); -extern  void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v); -extern  void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q); -extern  void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v); -extern  void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q); -extern  void ( APIENTRY * qglTexCoord4iv )(const GLint *v); -extern  void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q); -extern  void ( APIENTRY * qglTexCoord4sv )(const GLshort *v); -extern  void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -extern  void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param); -extern  void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params); -extern  void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param); -extern  void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params); -extern  void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param); -extern  void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params); -extern  void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param); -extern  void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params); -extern  void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param); -extern  void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params); -extern  void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -extern  void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -extern  void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param); -extern  void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params); -extern  void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param); -extern  void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params); -extern  void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -extern  void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -extern  void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z); -extern  void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z); -extern  void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y); -extern  void ( APIENTRY * qglVertex2dv )(const GLdouble *v); -extern  void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y); -extern  void ( APIENTRY * qglVertex2fv )(const GLfloat *v); -extern  void ( APIENTRY * qglVertex2i )(GLint x, GLint y); -extern  void ( APIENTRY * qglVertex2iv )(const GLint *v); -extern  void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y); -extern  void ( APIENTRY * qglVertex2sv )(const GLshort *v); -extern  void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z); -extern  void ( APIENTRY * qglVertex3dv )(const GLdouble *v); -extern  void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z); -extern  void ( APIENTRY * qglVertex3fv )(const GLfloat *v); -extern  void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z); -extern  void ( APIENTRY * qglVertex3iv )(const GLint *v); -extern  void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z); -extern  void ( APIENTRY * qglVertex3sv )(const GLshort *v); -extern  void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); -extern  void ( APIENTRY * qglVertex4dv )(const GLdouble *v); -extern  void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); -extern  void ( APIENTRY * qglVertex4fv )(const GLfloat *v); -extern  void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w); -extern  void ( APIENTRY * qglVertex4iv )(const GLint *v); -extern  void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w); -extern  void ( APIENTRY * qglVertex4sv )(const GLshort *v); -extern  void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -extern  void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height); - -#if defined( _WIN32 ) - -extern  int   ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *); -extern  int   ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); -extern  int   ( WINAPI * qwglGetPixelFormat)(HDC); -extern  BOOL  ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *); -extern  BOOL  ( WINAPI * qwglSwapBuffers)(HDC); - -extern	BOOL  ( WINAPI * qwglGetDeviceGammaRamp3DFX)( HDC, LPVOID ); -extern	BOOL  ( WINAPI * qwglSetDeviceGammaRamp3DFX)( HDC, LPVOID ); - -extern BOOL  ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT); -extern HGLRC ( WINAPI * qwglCreateContext)(HDC); -extern HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int); -extern BOOL  ( WINAPI * qwglDeleteContext)(HGLRC); -extern HGLRC ( WINAPI * qwglGetCurrentContext)(VOID); -extern HDC   ( WINAPI * qwglGetCurrentDC)(VOID); -extern PROC  ( WINAPI * qwglGetProcAddress)(LPCSTR); -extern BOOL  ( WINAPI * qwglMakeCurrent)(HDC, HGLRC); -extern BOOL  ( WINAPI * qwglShareLists)(HGLRC, HGLRC); -extern BOOL  ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD); - -extern BOOL  ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT, -                                           FLOAT, int, LPGLYPHMETRICSFLOAT); - -extern BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT, -                                            LPLAYERPLANEDESCRIPTOR); -extern int  ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int, -                                                CONST COLORREF *); -extern int  ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int, -                                                COLORREF *); -extern BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL); -extern BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT); - -extern BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval ); - -#endif	// _WIN32 - -#if ( (defined __linux__ )  || (defined __FreeBSD__ ) || (defined __sun) ) // rb010123 - -//FX Mesa Functions -// bk001129 - from cvs1.17 (mkv) -#if defined (__FX__) -extern fxMesaContext (*qfxMesaCreateContext)(GLuint win, GrScreenResolution_t, GrScreenRefresh_t, const GLint attribList[]); -extern fxMesaContext (*qfxMesaCreateBestContext)(GLuint win, GLint width, GLint height, const GLint attribList[]); -extern void (*qfxMesaDestroyContext)(fxMesaContext ctx); -extern void (*qfxMesaMakeCurrent)(fxMesaContext ctx); -extern fxMesaContext (*qfxMesaGetCurrentContext)(void); -extern void (*qfxMesaSwapBuffers)(void); -#endif - -//GLX Functions -extern XVisualInfo * (*qglXChooseVisual)( Display *dpy, int screen, int *attribList ); -extern GLXContext (*qglXCreateContext)( Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct ); -extern void (*qglXDestroyContext)( Display *dpy, GLXContext ctx ); -extern Bool (*qglXMakeCurrent)( Display *dpy, GLXDrawable drawable, GLXContext ctx); -extern void (*qglXCopyContext)( Display *dpy, GLXContext src, GLXContext dst, GLuint mask ); -extern void (*qglXSwapBuffers)( Display *dpy, GLXDrawable drawable ); - -#endif // __linux__ || __FreeBSD__ || __sun // rb010123 - -#endif	// _WIN32 && __linux__ - -#endif diff --git a/ioq3-r437/src/renderer/qgl_linked.h b/ioq3-r437/src/renderer/qgl_linked.h deleted file mode 100644 index 3d11f4a8..00000000 --- a/ioq3-r437/src/renderer/qgl_linked.h +++ /dev/null @@ -1,357 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ - -#define qglAccum glAccum -#define qglAlphaFunc glAlphaFunc -#define qglAreTexturesResident glAreTexturesResident -#define qglArrayElement glArrayElement -#define qglBegin glBegin -#define qglBindTexture glBindTexture -#define qglBitmap glBitmap -#define qglBlendFunc glBlendFunc -#define qglCallList glCallList -#define qglCallLists glCallLists -#define qglClear glClear -#define qglClearAccum glClearAccum -#define qglClearColor glClearColor -#define qglClearDepth glClearDepth -#define qglClearIndex glClearIndex -#define qglClearStencil glClearStencil -#define qglClipPlane glClipPlane -#define qglColor3b glColor3b -#define qglColor3bv glColor3bv -#define qglColor3d glColor3d -#define qglColor3dv glColor3dv -#define qglColor3f glColor3f -#define qglColor3fv glColor3fv -#define qglColor3i glColor3i -#define qglColor3iv glColor3iv -#define qglColor3s glColor3s -#define qglColor3sv glColor3sv -#define qglColor3ub glColor3ub -#define qglColor3ubv glColor3ubv -#define qglColor3ui glColor3ui -#define qglColor3uiv glColor3uiv -#define qglColor3us glColor3us -#define qglColor3usv glColor3usv -#define qglColor4b glColor4b -#define qglColor4bv glColor4bv -#define qglColor4d glColor4d -#define qglColor4dv glColor4dv -#define qglColor4f glColor4f -#define qglColor4fv glColor4fv -#define qglColor4i glColor4i -#define qglColor4iv glColor4iv -#define qglColor4s glColor4s -#define qglColor4sv glColor4sv -#define qglColor4ub glColor4ub -#define qglColor4ubv glColor4ubv -#define qglColor4ui glColor4ui -#define qglColor4uiv glColor4uiv -#define qglColor4us glColor4us -#define qglColor4usv glColor4usv -#define qglColorMask glColorMask -#define qglColorMaterial glColorMaterial -#define qglColorPointer glColorPointer -#define qglCopyPixels glCopyPixels -#define qglCopyTexImage1D glCopyTexImage1D -#define qglCopyTexImage2D glCopyTexImage2D -#define qglCopyTexSubImage1D glCopyTexSubImage1D -#define qglCopyTexSubImage2D glCopyTexSubImage2D -#define qglCullFace glCullFace -#define qglDeleteLists glDeleteLists -#define qglDeleteTextures glDeleteTextures -#define qglDepthFunc glDepthFunc -#define qglDepthMask glDepthMask -#define qglDepthRange glDepthRange -#define qglDisable glDisable -#define qglDisableClientState glDisableClientState -#define qglDrawArrays glDrawArrays -#define qglDrawBuffer glDrawBuffer -#define qglDrawElements glDrawElements -#define qglDrawPixels glDrawPixels -#define qglEdgeFlag glEdgeFlag -#define qglEdgeFlagPointer glEdgeFlagPointer -#define qglEdgeFlagv glEdgeFlagv -#define qglEnable glEnable -#define qglEnableClientState glEnableClientState -#define qglEnd glEnd -#define qglEndList glEndList -#define qglEvalCoord1d glEvalCoord1d -#define qglEvalCoord1dv glEvalCoord1dv -#define qglEvalCoord1f glEvalCoord1f -#define qglEvalCoord1fv glEvalCoord1fv -#define qglEvalCoord2d glEvalCoord2d -#define qglEvalCoord2dv glEvalCoord2dv -#define qglEvalCoord2f glEvalCoord2f -#define qglEvalCoord2fv glEvalCoord2fv -#define qglEvalMesh1 glEvalMesh1 -#define qglEvalMesh2 glEvalMesh2 -#define qglEvalPoint1 glEvalPoint1 -#define qglEvalPoint2 glEvalPoint2 -#define qglFeedbackBuffer glFeedbackBuffer -#define qglFinish glFinish -#define qglFlush glFlush -#define qglFogf glFogf -#define qglFogfv glFogfv -#define qglFogi glFogi -#define qglFogiv glFogiv -#define qglFrontFace glFrontFace -#define qglFrustum glFrustum -#define qglGenLists glGenLists -#define qglGenTextures glGenTextures -#define qglGetBooleanv glGetBooleanv -#define qglGetClipPlane glGetClipPlane -#define qglGetDoublev glGetDoublev -#define qglGetError glGetError -#define qglGetFloatv glGetFloatv -#define qglGetIntegerv glGetIntegerv -#define qglGetLightfv glGetLightfv -#define qglGetLightiv glGetLightiv -#define qglGetMapdv glGetMapdv -#define qglGetMapfv glGetMapfv -#define qglGetMapiv glGetMapiv -#define qglGetMaterialfv glGetMaterialfv -#define qglGetMaterialiv glGetMaterialiv -#define qglGetPixelMapfv glGetPixelMapfv -#define qglGetPixelMapuiv glGetPixelMapuiv -#define qglGetPixelMapusv glGetPixelMapusv -#define qglGetPointerv glGetPointerv -#define qglGetPolygonStipple glGetPolygonStipple -#define qglGetString glGetString -#define qglGetTexGendv glGetTexGendv -#define qglGetTexGenfv glGetTexGenfv -#define qglGetTexGeniv glGetTexGeniv -#define qglGetTexImage glGetTexImage -#define qglGetTexLevelParameterfv glGetTexLevelParameterfv -#define qglGetTexLevelParameteriv glGetTexLevelParameteriv -#define qglGetTexParameterfv glGetTexParameterfv -#define qglGetTexParameteriv glGetTexParameteriv -#define qglHint glHint -#define qglIndexMask glIndexMask -#define qglIndexPointer glIndexPointer -#define qglIndexd glIndexd -#define qglIndexdv glIndexdv -#define qglIndexf glIndexf -#define qglIndexfv glIndexfv -#define qglIndexi glIndexi -#define qglIndexiv glIndexiv -#define qglIndexs glIndexs -#define qglIndexsv glIndexsv -#define qglIndexub glIndexub -#define qglIndexubv glIndexubv -#define qglInitNames glInitNames -#define qglInterleavedArrays glInterleavedArrays -#define qglIsEnabled glIsEnabled -#define qglIsList glIsList -#define qglIsTexture glIsTexture -#define qglLightModelf glLightModelf -#define qglLightModelfv glLightModelfv -#define qglLightModeli glLightModeli -#define qglLightModeliv glLightModeliv -#define qglLightf glLightf -#define qglLightfv glLightfv -#define qglLighti glLighti -#define qglLightiv glLightiv -#define qglLineStipple glLineStipple -#define qglLineWidth glLineWidth -#define qglListBase glListBase -#define qglLoadIdentity glLoadIdentity -#define qglLoadMatrixd glLoadMatrixd -#define qglLoadMatrixf glLoadMatrixf -#define qglLoadName glLoadName -#define qglLogicOp glLogicOp -#define qglMap1d glMap1d -#define qglMap1f glMap1f -#define qglMap2d glMap2d -#define qglMap2f glMap2f -#define qglMapGrid1d glMapGrid1d -#define qglMapGrid1f glMapGrid1f -#define qglMapGrid2d glMapGrid2d -#define qglMapGrid2f glMapGrid2f -#define qglMaterialf glMaterialf -#define qglMaterialfv glMaterialfv -#define qglMateriali glMateriali -#define qglMaterialiv glMaterialiv -#define qglMatrixMode glMatrixMode -#define qglMultMatrixd glMultMatrixd -#define qglMultMatrixf glMultMatrixf -#define qglNewList glNewList -#define qglNormal3b glNormal3b -#define qglNormal3bv glNormal3bv -#define qglNormal3d glNormal3d -#define qglNormal3dv glNormal3dv -#define qglNormal3f glNormal3f -#define qglNormal3fv glNormal3fv -#define qglNormal3i glNormal3i -#define qglNormal3iv glNormal3iv -#define qglNormal3s glNormal3s -#define qglNormal3sv glNormal3sv -#define qglNormalPointer glNormalPointer -#define qglOrtho glOrtho -#define qglPassThrough glPassThrough -#define qglPixelMapfv glPixelMapfv -#define qglPixelMapuiv glPixelMapuiv -#define qglPixelMapusv glPixelMapusv -#define qglPixelStoref glPixelStoref -#define qglPixelStorei glPixelStorei -#define qglPixelTransferf glPixelTransferf -#define qglPixelTransferi glPixelTransferi -#define qglPixelZoom glPixelZoom -#define qglPointSize glPointSize -#define qglPolygonMode glPolygonMode -#define qglPolygonOffset glPolygonOffset -#define qglPolygonStipple glPolygonStipple -#define qglPopAttrib glPopAttrib -#define qglPopClientAttrib glPopClientAttrib -#define qglPopMatrix glPopMatrix -#define qglPopName glPopName -#define qglPrioritizeTextures glPrioritizeTextures -#define qglPushAttrib glPushAttrib -#define qglPushClientAttrib glPushClientAttrib -#define qglPushMatrix glPushMatrix -#define qglPushName glPushName -#define qglRasterPos2d glRasterPos2d -#define qglRasterPos2dv glRasterPos2dv -#define qglRasterPos2f glRasterPos2f -#define qglRasterPos2fv glRasterPos2fv -#define qglRasterPos2i glRasterPos2i -#define qglRasterPos2iv glRasterPos2iv -#define qglRasterPos2s glRasterPos2s -#define qglRasterPos2sv glRasterPos2sv -#define qglRasterPos3d glRasterPos3d -#define qglRasterPos3dv glRasterPos3dv -#define qglRasterPos3f glRasterPos3f -#define qglRasterPos3fv glRasterPos3fv -#define qglRasterPos3i glRasterPos3i -#define qglRasterPos3iv glRasterPos3iv -#define qglRasterPos3s glRasterPos3s -#define qglRasterPos3sv glRasterPos3sv -#define qglRasterPos4d glRasterPos4d -#define qglRasterPos4dv glRasterPos4dv -#define qglRasterPos4f glRasterPos4f -#define qglRasterPos4fv glRasterPos4fv -#define qglRasterPos4i glRasterPos4i -#define qglRasterPos4iv glRasterPos4iv -#define qglRasterPos4s glRasterPos4s -#define qglRasterPos4sv glRasterPos4sv -#define qglReadBuffer glReadBuffer -#define qglReadPixels glReadPixels -#define qglRectd glRectd -#define qglRectdv glRectdv -#define qglRectf glRectf -#define qglRectfv glRectfv -#define qglRecti glRecti -#define qglRectiv glRectiv -#define qglRects glRects -#define qglRectsv glRectsv -#define qglRenderMode glRenderMode -#define qglRotated glRotated -#define qglRotatef glRotatef -#define qglScaled glScaled -#define qglScalef glScalef -#define qglScissor glScissor -#define qglSelectBuffer glSelectBuffer -#define qglShadeModel glShadeModel -#define qglStencilFunc glStencilFunc -#define qglStencilMask glStencilMask -#define qglStencilOp glStencilOp -#define qglTexCoord1d glTexCoord1d -#define qglTexCoord1dv glTexCoord1dv -#define qglTexCoord1f glTexCoord1f -#define qglTexCoord1fv glTexCoord1fv -#define qglTexCoord1i glTexCoord1i -#define qglTexCoord1iv glTexCoord1iv -#define qglTexCoord1s glTexCoord1s -#define qglTexCoord1sv glTexCoord1sv -#define qglTexCoord2d glTexCoord2d -#define qglTexCoord2dv glTexCoord2dv -#define qglTexCoord2f glTexCoord2f -#define qglTexCoord2fv glTexCoord2fv -#define qglTexCoord2i glTexCoord2i -#define qglTexCoord2iv glTexCoord2iv -#define qglTexCoord2s glTexCoord2s -#define qglTexCoord2sv glTexCoord2sv -#define qglTexCoord3d glTexCoord3d -#define qglTexCoord3dv glTexCoord3dv -#define qglTexCoord3f glTexCoord3f -#define qglTexCoord3fv glTexCoord3fv -#define qglTexCoord3i glTexCoord3i -#define qglTexCoord3iv glTexCoord3iv -#define qglTexCoord3s glTexCoord3s -#define qglTexCoord3sv glTexCoord3sv -#define qglTexCoord4d glTexCoord4d -#define qglTexCoord4dv glTexCoord4dv -#define qglTexCoord4f glTexCoord4f -#define qglTexCoord4fv glTexCoord4fv -#define qglTexCoord4i glTexCoord4i -#define qglTexCoord4iv glTexCoord4iv -#define qglTexCoord4s glTexCoord4s -#define qglTexCoord4sv glTexCoord4sv -#define qglTexCoordPointer glTexCoordPointer -#define	qglTexEnvf glTexEnvf -#define	qglTexEnvfv glTexEnvfv -#define	qglTexEnvi glTexEnvi -#define	qglTexEnviv glTexEnviv -#define qglTexGend glTexGend -#define qglTexGendv glTexGendv -#define qglTexGenf glTexGenf -#define qglTexGenfv glTexGenfv -#define qglTexGeni glTexGeni -#define qglTexGeniv glTexGeniv -#define qglTexImage1D glTexImage1D -#define qglTexImage2D glTexImage2D -#define qglTexParameterf glTexParameterf -#define qglTexParameterfv glTexParameterfv -#define qglTexParameteri glTexParameteri -#define qglTexParameteriv glTexParameteriv -#define qglTexSubImage1D glTexSubImage1D -#define qglTexSubImage2D glTexSubImage2D -#define qglTranslated glTranslated -#define qglTranslatef glTranslatef -#define qglVertex2d glVertex2d -#define qglVertex2dv glVertex2dv -#define qglVertex2f glVertex2f -#define qglVertex2fv glVertex2fv -#define qglVertex2i glVertex2i -#define qglVertex2iv glVertex2iv -#define qglVertex2s glVertex2s -#define qglVertex2sv glVertex2sv -#define qglVertex3d glVertex3d -#define qglVertex3dv glVertex3dv -#define qglVertex3f glVertex3f -#define qglVertex3fv glVertex3fv -#define qglVertex3i glVertex3i -#define qglVertex3iv glVertex3iv -#define qglVertex3s glVertex3s -#define qglVertex3sv glVertex3sv -#define qglVertex4d glVertex4d -#define qglVertex4dv glVertex4dv -#define qglVertex4f glVertex4f -#define qglVertex4fv glVertex4fv -#define qglVertex4i glVertex4i -#define qglVertex4iv glVertex4iv -#define qglVertex4s glVertex4s -#define qglVertex4sv glVertex4sv -#define qglVertexPointer glVertexPointer -#define qglViewport glViewport - diff --git a/ioq3-r437/src/renderer/tr_animation.c b/ioq3-r437/src/renderer/tr_animation.c deleted file mode 100644 index 8f424569..00000000 --- a/ioq3-r437/src/renderer/tr_animation.c +++ /dev/null @@ -1,658 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ - -#include "tr_local.h" - -/* - -All bones should be an identity orientation to display the mesh exactly -as it is specified. - -For all other frames, the bones represent the transformation from the  -orientation of the bone in the base frame to the orientation in this -frame. - -*/ - -/* -============== -R_AddAnimSurfaces -============== -*/ -void R_AddAnimSurfaces( trRefEntity_t *ent ) { -	md4Header_t		*header; -	md4Surface_t	*surface; -	md4LOD_t		*lod; -	shader_t		*shader; -	int				i; - -	header = (md4Header_t *) tr.currentModel->md4; -	lod = (md4LOD_t *)( (byte *)header + header->ofsLODs ); - -	surface = (md4Surface_t *)( (byte *)lod + lod->ofsSurfaces ); -	for ( i = 0 ; i < lod->numSurfaces ; i++ ) { -		shader = R_GetShaderByHandle( surface->shaderIndex ); -		R_AddDrawSurf( (void *)surface, shader, 0 /*fogNum*/, qfalse ); -		surface = (md4Surface_t *)( (byte *)surface + surface->ofsEnd ); -	} -} - -/* -============== -RB_SurfaceAnim -============== -*/ -void RB_SurfaceAnim( md4Surface_t *surface ) { -	int				i, j, k; -	float			frontlerp, backlerp; -	int				*triangles; -	int				indexes; -	int				baseIndex, baseVertex; -	int				numVerts; -	md4Vertex_t		*v; -	md4Bone_t		bones[MD4_MAX_BONES]; -	md4Bone_t		*bonePtr, *bone; -	md4Header_t		*header; -	md4Frame_t		*frame; -	md4Frame_t		*oldFrame; -	int				frameSize; - - -	if (  backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) { -		backlerp = 0; -		frontlerp = 1; -	} else  { -		backlerp = backEnd.currentEntity->e.backlerp; -		frontlerp = 1.0f - backlerp; -	} -	header = (md4Header_t *)((byte *)surface + surface->ofsHeader); - -	frameSize = (size_t)( &((md4Frame_t *)0)->bones[ header->numBones ] ); - -	frame = (md4Frame_t *)((byte *)header + header->ofsFrames +  -			backEnd.currentEntity->e.frame * frameSize ); -	oldFrame = (md4Frame_t *)((byte *)header + header->ofsFrames +  -			backEnd.currentEntity->e.oldframe * frameSize ); - -	RB_CheckOverflow( surface->numVerts, surface->numTriangles * 3 ); - -	triangles = (int *) ((byte *)surface + surface->ofsTriangles); -	indexes = surface->numTriangles * 3; -	baseIndex = tess.numIndexes; -	baseVertex = tess.numVertexes; -	for (j = 0 ; j < indexes ; j++) { -		tess.indexes[baseIndex + j] = baseIndex + triangles[j]; -	} -	tess.numIndexes += indexes; - -	// -	// lerp all the needed bones -	// -	if ( !backlerp ) { -		// no lerping needed -		bonePtr = frame->bones; -	} else { -		bonePtr = bones; -		for ( i = 0 ; i < header->numBones*12 ; i++ ) { -			((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i] -					+ backlerp * ((float *)oldFrame->bones)[i]; -		} -	} - -	// -	// deform the vertexes by the lerped bones -	// -	numVerts = surface->numVerts; -	// FIXME -	// This makes TFC's skeletons work.  Shouldn't be necessary anymore, but left -	// in for reference. -	//v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts + 12); -	v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts); -	for ( j = 0; j < numVerts; j++ ) { -		vec3_t	tempVert, tempNormal; -		md4Weight_t	*w; - -		VectorClear( tempVert ); -		VectorClear( tempNormal ); -		w = v->weights; -		for ( k = 0 ; k < v->numWeights ; k++, w++ ) { -			bone = bonePtr + w->boneIndex; - -			tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] ); -			tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] ); -			tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] ); - -			tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal ); -			tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal ); -			tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal ); -		} - -		tess.xyz[baseVertex + j][0] = tempVert[0]; -		tess.xyz[baseVertex + j][1] = tempVert[1]; -		tess.xyz[baseVertex + j][2] = tempVert[2]; - -		tess.normal[baseVertex + j][0] = tempNormal[0]; -		tess.normal[baseVertex + j][1] = tempNormal[1]; -		tess.normal[baseVertex + j][2] = tempNormal[2]; - -		tess.texCoords[baseVertex + j][0][0] = v->texCoords[0]; -		tess.texCoords[baseVertex + j][0][1] = v->texCoords[1]; - -		// FIXME -		// This makes TFC's skeletons work.  Shouldn't be necessary anymore, but left -		// in for reference. -		//v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 ); -		v = (md4Vertex_t *)&v->weights[v->numWeights]; -	} - -	tess.numVertexes += surface->numVerts; -} - - -#ifdef RAVENMD4 - -// copied and adapted from tr_mesh.c - -/* -============= -R_MDRCullModel -============= -*/ - -static int R_MDRCullModel( mdrHeader_t *header, trRefEntity_t *ent ) { -	vec3_t		bounds[2]; -	mdrFrame_t	*oldFrame, *newFrame; -	int			i, frameSize; - -	frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] ); -	 -	// compute frame pointers -	newFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame); -	oldFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.oldframe); - -	// cull bounding sphere ONLY if this is not an upscaled entity -	if ( !ent->e.nonNormalizedAxes ) -	{ -		if ( ent->e.frame == ent->e.oldframe ) -		{ -			switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) ) -			{ -				// Ummm... yeah yeah I know we don't really have an md3 here.. but we pretend -				// we do. After all, the purpose of md4s are not that different, are they? -				 -				case CULL_OUT: -					tr.pc.c_sphere_cull_md3_out++; -					return CULL_OUT; - -				case CULL_IN: -					tr.pc.c_sphere_cull_md3_in++; -					return CULL_IN; - -				case CULL_CLIP: -					tr.pc.c_sphere_cull_md3_clip++; -					break; -			} -		} -		else -		{ -			int sphereCull, sphereCullB; - -			sphereCull  = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ); -			if ( newFrame == oldFrame ) { -				sphereCullB = sphereCull; -			} else { -				sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius ); -			} - -			if ( sphereCull == sphereCullB ) -			{ -				if ( sphereCull == CULL_OUT ) -				{ -					tr.pc.c_sphere_cull_md3_out++; -					return CULL_OUT; -				} -				else if ( sphereCull == CULL_IN ) -				{ -					tr.pc.c_sphere_cull_md3_in++; -					return CULL_IN; -				} -				else -				{ -					tr.pc.c_sphere_cull_md3_clip++; -				} -			} -		} -	} -	 -	// calculate a bounding box in the current coordinate system -	for (i = 0 ; i < 3 ; i++) { -		bounds[0][i] = oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i]; -		bounds[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i]; -	} - -	switch ( R_CullLocalBox( bounds ) ) -	{ -		case CULL_IN: -			tr.pc.c_box_cull_md3_in++; -			return CULL_IN; -		case CULL_CLIP: -			tr.pc.c_box_cull_md3_clip++; -			return CULL_CLIP; -		case CULL_OUT: -		default: -			tr.pc.c_box_cull_md3_out++; -			return CULL_OUT; -	} -} - -/* -================= -R_MDRComputeFogNum - -================= -*/ - -int R_MDRComputeFogNum( mdrHeader_t *header, trRefEntity_t *ent ) { -	int				i, j; -	fog_t			*fog; -	mdrFrame_t		*mdrFrame; -	vec3_t			localOrigin; -	int frameSize; - -	if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { -		return 0; -	} -	 -	frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] ); - -	// FIXME: non-normalized axis issues -	mdrFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame); -	VectorAdd( ent->e.origin, mdrFrame->localOrigin, localOrigin ); -	for ( i = 1 ; i < tr.world->numfogs ; i++ ) { -		fog = &tr.world->fogs[i]; -		for ( j = 0 ; j < 3 ; j++ ) { -			if ( localOrigin[j] - mdrFrame->radius >= fog->bounds[1][j] ) { -				break; -			} -			if ( localOrigin[j] + mdrFrame->radius <= fog->bounds[0][j] ) { -				break; -			} -		} -		if ( j == 3 ) { -			return i; -		} -	} - -	return 0; -} - - -/* -============== -R_MDRAddAnimSurfaces -============== -*/ - -// much stuff in there is just copied from R_AddMd3Surfaces in tr_mesh.c - -void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) { -	mdrHeader_t		*header; -	mdrSurface_t	*surface; -	mdrLOD_t		*lod; -	shader_t		*shader; -	skin_t		*skin; -	int				i, j; -	int				lodnum = 0; -	int				fogNum = 0; -	int				cull; -	qboolean	personalModel; - -	header = (mdrHeader_t *) tr.currentModel->md4; -	 -	personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal; -	 -	if ( ent->e.renderfx & RF_WRAP_FRAMES ) -	{ -		ent->e.frame %= header->numFrames; -		ent->e.oldframe %= header->numFrames; -	}	 -	 -	// -	// Validate the frames so there is no chance of a crash. -	// This will write directly into the entity structure, so -	// when the surfaces are rendered, they don't need to be -	// range checked again. -	// -	if ((ent->e.frame >= header->numFrames)  -		|| (ent->e.frame < 0) -		|| (ent->e.oldframe >= header->numFrames) -		|| (ent->e.oldframe < 0) ) -	{ -		ri.Printf( PRINT_DEVELOPER, "R_MDRAddAnimSurfaces: no such frame %d to %d for '%s'\n", -			   ent->e.oldframe, ent->e.frame, tr.currentModel->name ); -		ent->e.frame = 0; -		ent->e.oldframe = 0; -	} - -	// -	// cull the entire model if merged bounding box of both frames -	// is outside the view frustum. -	// -	cull = R_MDRCullModel (header, ent); -	if ( cull == CULL_OUT ) { -		return; -	}	 - -	// figure out the current LOD of the model we're rendering, and set the lod pointer respectively. -	lodnum = R_ComputeLOD(ent); -	// check whether this model has as that many LODs at all. If not, try the closest thing we got. -	if(header->numLODs <= 0) -		return; -	if(header->numLODs <= lodnum) -		lodnum = header->numLODs - 1; - -	lod = (mdrLOD_t *)( (byte *)header + header->ofsLODs); -	for(i = 0; i < lodnum; i++) -	{ -		lod = (mdrLOD_t *) ((byte *) lod + lod->ofsEnd); -	} -	 -	// set up lighting -	if ( !personalModel || r_shadows->integer > 1 ) -	{ -		R_SetupEntityLighting( &tr.refdef, ent ); -	} - -	// fogNum? -	fogNum = R_MDRComputeFogNum( header, ent ); - -	surface = (mdrSurface_t *)( (byte *)lod + lod->ofsSurfaces ); - -	for ( i = 0 ; i < lod->numSurfaces ; i++ ) -	{ -		 -		if(ent->e.customShader) -			shader = R_GetShaderByHandle(ent->e.customShader); -		else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins) -		{ -			skin = R_GetSkinByHandle(ent->e.customSkin); -			shader = tr.defaultShader; -			 -			for(j = 0; j < skin->numSurfaces; j++) -			{ -				if (!strcmp(skin->surfaces[j]->name, surface->name)) -				{ -					shader = skin->surfaces[j]->shader; -					break; -				} -			} -		} -		else if(surface->shaderIndex > 0) -			shader = R_GetShaderByHandle( surface->shaderIndex ); -		else -			shader = tr.defaultShader; - -		// we will add shadows even if the main object isn't visible in the view - -		// stencil shadows can't do personal models unless I polyhedron clip -		if ( !personalModel -		        && r_shadows->integer == 2 -			&& fogNum == 0 -			&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) ) -			&& shader->sort == SS_OPAQUE ) -		{ -			R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse ); -		} - -		// projection shadows work fine with personal models -		if ( r_shadows->integer == 3 -			&& fogNum == 0 -			&& (ent->e.renderfx & RF_SHADOW_PLANE ) -			&& shader->sort == SS_OPAQUE ) -		{ -			R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse ); -		} - -		if (!personalModel) -			R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse ); - -		surface = (mdrSurface_t *)( (byte *)surface + surface->ofsEnd ); -	} -} - -/* -============== -RB_MDRSurfaceAnim -============== -*/ -void RB_MDRSurfaceAnim( md4Surface_t *surface ) -{ -	int				i, j, k; -	float			frontlerp, backlerp; -	int				*triangles; -	int				indexes; -	int				baseIndex, baseVertex; -	int				numVerts; -	mdrVertex_t		*v; -	mdrHeader_t		*header; -	mdrFrame_t		*frame; -	mdrFrame_t		*oldFrame; -	mdrBone_t		bones[MD4_MAX_BONES], *bonePtr, *bone; - -	int			frameSize; - -	// don't lerp if lerping off, or this is the only frame, or the last frame... -	// -	if (backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame)  -	{ -		backlerp	= 0;	// if backlerp is 0, lerping is off and frontlerp is never used -		frontlerp	= 1; -	}  -	else   -	{ -		backlerp	= backEnd.currentEntity->e.backlerp; -		frontlerp	= 1.0f - backlerp; -	} - -	header = (mdrHeader_t *)((byte *)surface + surface->ofsHeader); - -	frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] ); - -	frame = (mdrFrame_t *)((byte *)header + header->ofsFrames + -		backEnd.currentEntity->e.frame * frameSize ); -	oldFrame = (mdrFrame_t *)((byte *)header + header->ofsFrames + -		backEnd.currentEntity->e.oldframe * frameSize ); - -	RB_CheckOverflow( surface->numVerts, surface->numTriangles ); - -	triangles	= (int *) ((byte *)surface + surface->ofsTriangles); -	indexes		= surface->numTriangles * 3; -	baseIndex	= tess.numIndexes; -	baseVertex	= tess.numVertexes; -	 -	// Set up all triangles. -	for (j = 0 ; j < indexes ; j++)  -	{ -		tess.indexes[baseIndex + j] = baseVertex + triangles[j]; -	} -	tess.numIndexes += indexes; - -	// -	// lerp all the needed bones -	// -	if ( !backlerp )  -	{ -		// no lerping needed -		bonePtr = frame->bones; -	}  -	else  -	{ -		bonePtr = bones; -		 -		for ( i = 0 ; i < header->numBones*12 ; i++ )  -		{ -			((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i] + backlerp * ((float *)oldFrame->bones)[i]; -		} -	} - -	// -	// deform the vertexes by the lerped bones -	// -	numVerts = surface->numVerts; -	v = (mdrVertex_t *) ((byte *)surface + surface->ofsVerts); -	for ( j = 0; j < numVerts; j++ )  -	{ -		vec3_t	tempVert, tempNormal; -		mdrWeight_t	*w; - -		VectorClear( tempVert ); -		VectorClear( tempNormal ); -		w = v->weights; -		for ( k = 0 ; k < v->numWeights ; k++, w++ )  -		{ -			bone = bonePtr + w->boneIndex; -			 -			tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] ); -			tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] ); -			tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] ); -			 -			tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal ); -			tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal ); -			tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal ); -		} - -		tess.xyz[baseVertex + j][0] = tempVert[0]; -		tess.xyz[baseVertex + j][1] = tempVert[1]; -		tess.xyz[baseVertex + j][2] = tempVert[2]; - -		tess.normal[baseVertex + j][0] = tempNormal[0]; -		tess.normal[baseVertex + j][1] = tempNormal[1]; -		tess.normal[baseVertex + j][2] = tempNormal[2]; - -		tess.texCoords[baseVertex + j][0][0] = v->texCoords[0]; -		tess.texCoords[baseVertex + j][0][1] = v->texCoords[1]; - -		v = (mdrVertex_t *)&v->weights[v->numWeights]; -	} - -	tess.numVertexes += surface->numVerts; -} - - -#define MC_MASK_X ((1<<(MC_BITS_X))-1) -#define MC_MASK_Y ((1<<(MC_BITS_Y))-1) -#define MC_MASK_Z ((1<<(MC_BITS_Z))-1) -#define MC_MASK_VECT ((1<<(MC_BITS_VECT))-1) - -#define MC_SCALE_VECT (1.0f/(float)((1<<(MC_BITS_VECT-1))-2)) - -#define MC_POS_X (0) -#define MC_SHIFT_X (0) - -#define MC_POS_Y ((((MC_BITS_X))/8)) -#define MC_SHIFT_Y ((((MC_BITS_X)%8))) - -#define MC_POS_Z ((((MC_BITS_X+MC_BITS_Y))/8)) -#define MC_SHIFT_Z ((((MC_BITS_X+MC_BITS_Y)%8))) - -#define MC_POS_V11 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z))/8)) -#define MC_SHIFT_V11 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z)%8))) - -#define MC_POS_V12 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT))/8)) -#define MC_SHIFT_V12 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT)%8))) - -#define MC_POS_V13 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*2))/8)) -#define MC_SHIFT_V13 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*2)%8))) - -#define MC_POS_V21 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*3))/8)) -#define MC_SHIFT_V21 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*3)%8))) - -#define MC_POS_V22 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*4))/8)) -#define MC_SHIFT_V22 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*4)%8))) - -#define MC_POS_V23 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*5))/8)) -#define MC_SHIFT_V23 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*5)%8))) - -#define MC_POS_V31 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*6))/8)) -#define MC_SHIFT_V31 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*6)%8))) - -#define MC_POS_V32 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*7))/8)) -#define MC_SHIFT_V32 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*7)%8))) - -#define MC_POS_V33 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*8))/8)) -#define MC_SHIFT_V33 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*8)%8))) - -void MC_UnCompress(float mat[3][4],const unsigned char * comp) -{ -	int val; - -	val=(int)((unsigned short *)(comp))[0]; -	val-=1<<(MC_BITS_X-1); -	mat[0][3]=((float)(val))*MC_SCALE_X; - -	val=(int)((unsigned short *)(comp))[1]; -	val-=1<<(MC_BITS_Y-1); -	mat[1][3]=((float)(val))*MC_SCALE_Y; - -	val=(int)((unsigned short *)(comp))[2]; -	val-=1<<(MC_BITS_Z-1); -	mat[2][3]=((float)(val))*MC_SCALE_Z; - -	val=(int)((unsigned short *)(comp))[3]; -	val-=1<<(MC_BITS_VECT-1); -	mat[0][0]=((float)(val))*MC_SCALE_VECT; - -	val=(int)((unsigned short *)(comp))[4]; -	val-=1<<(MC_BITS_VECT-1); -	mat[0][1]=((float)(val))*MC_SCALE_VECT; - -	val=(int)((unsigned short *)(comp))[5]; -	val-=1<<(MC_BITS_VECT-1); -	mat[0][2]=((float)(val))*MC_SCALE_VECT; - - -	val=(int)((unsigned short *)(comp))[6]; -	val-=1<<(MC_BITS_VECT-1); -	mat[1][0]=((float)(val))*MC_SCALE_VECT; - -	val=(int)((unsigned short *)(comp))[7]; -	val-=1<<(MC_BITS_VECT-1); -	mat[1][1]=((float)(val))*MC_SCALE_VECT; - -	val=(int)((unsigned short *)(comp))[8]; -	val-=1<<(MC_BITS_VECT-1); -	mat[1][2]=((float)(val))*MC_SCALE_VECT; - - -	val=(int)((unsigned short *)(comp))[9]; -	val-=1<<(MC_BITS_VECT-1); -	mat[2][0]=((float)(val))*MC_SCALE_VECT; - -	val=(int)((unsigned short *)(comp))[10]; -	val-=1<<(MC_BITS_VECT-1); -	mat[2][1]=((float)(val))*MC_SCALE_VECT; - -	val=(int)((unsigned short *)(comp))[11]; -	val-=1<<(MC_BITS_VECT-1); -	mat[2][2]=((float)(val))*MC_SCALE_VECT; -} -#endif diff --git a/ioq3-r437/src/renderer/tr_backend.c b/ioq3-r437/src/renderer/tr_backend.c deleted file mode 100644 index 6c93c14c..00000000 --- a/ioq3-r437/src/renderer/tr_backend.c +++ /dev/null @@ -1,1121 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -#include "tr_local.h" - -backEndData_t	*backEndData[SMP_FRAMES]; -backEndState_t	backEnd; - - -static float	s_flipMatrix[16] = { -	// convert from our coordinate system (looking down X) -	// to OpenGL's coordinate system (looking down -Z) -	0, 0, -1, 0, -	-1, 0, 0, 0, -	0, 1, 0, 0, -	0, 0, 0, 1 -}; - - -/* -** GL_Bind -*/ -void GL_Bind( image_t *image ) { -	int texnum; - -	if ( !image ) { -		ri.Printf( PRINT_WARNING, "GL_Bind: NULL image\n" ); -		texnum = tr.defaultImage->texnum; -	} else { -		texnum = image->texnum; -	} - -	if ( r_nobind->integer && tr.dlightImage ) {		// performance evaluation option -		texnum = tr.dlightImage->texnum; -	} - -	if ( glState.currenttextures[glState.currenttmu] != texnum ) { -		image->frameUsed = tr.frameCount; -		glState.currenttextures[glState.currenttmu] = texnum; -		qglBindTexture (GL_TEXTURE_2D, texnum); -	} -} - -/* -** GL_SelectTexture -*/ -void GL_SelectTexture( int unit ) -{ -	if ( glState.currenttmu == unit ) -	{ -		return; -	} - -	if ( unit == 0 ) -	{ -		qglActiveTextureARB( GL_TEXTURE0_ARB ); -		GLimp_LogComment( "glActiveTextureARB( GL_TEXTURE0_ARB )\n" ); -		qglClientActiveTextureARB( GL_TEXTURE0_ARB ); -		GLimp_LogComment( "glClientActiveTextureARB( GL_TEXTURE0_ARB )\n" ); -	} -	else if ( unit == 1 ) -	{ -		qglActiveTextureARB( GL_TEXTURE1_ARB ); -		GLimp_LogComment( "glActiveTextureARB( GL_TEXTURE1_ARB )\n" ); -		qglClientActiveTextureARB( GL_TEXTURE1_ARB ); -		GLimp_LogComment( "glClientActiveTextureARB( GL_TEXTURE1_ARB )\n" ); -	} else { -		ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit ); -	} - -	glState.currenttmu = unit; -} - - -/* -** GL_BindMultitexture -*/ -void GL_BindMultitexture( image_t *image0, GLuint env0, image_t *image1, GLuint env1 ) { -	int		texnum0, texnum1; - -	texnum0 = image0->texnum; -	texnum1 = image1->texnum; - -	if ( r_nobind->integer && tr.dlightImage ) {		// performance evaluation option -		texnum0 = texnum1 = tr.dlightImage->texnum; -	} - -	if ( glState.currenttextures[1] != texnum1 ) { -		GL_SelectTexture( 1 ); -		image1->frameUsed = tr.frameCount; -		glState.currenttextures[1] = texnum1; -		qglBindTexture( GL_TEXTURE_2D, texnum1 ); -	} -	if ( glState.currenttextures[0] != texnum0 ) { -		GL_SelectTexture( 0 ); -		image0->frameUsed = tr.frameCount; -		glState.currenttextures[0] = texnum0; -		qglBindTexture( GL_TEXTURE_2D, texnum0 ); -	} -} - - -/* -** GL_Cull -*/ -void GL_Cull( int cullType ) { -	if ( glState.faceCulling == cullType ) { -		return; -	} - -	glState.faceCulling = cullType; - -	if ( cullType == CT_TWO_SIDED )  -	{ -		qglDisable( GL_CULL_FACE ); -	}  -	else  -	{ -		qglEnable( GL_CULL_FACE ); - -		if ( cullType == CT_BACK_SIDED ) -		{ -			if ( backEnd.viewParms.isMirror ) -			{ -				qglCullFace( GL_FRONT ); -			} -			else -			{ -				qglCullFace( GL_BACK ); -			} -		} -		else -		{ -			if ( backEnd.viewParms.isMirror ) -			{ -				qglCullFace( GL_BACK ); -			} -			else -			{ -				qglCullFace( GL_FRONT ); -			} -		} -	} -} - -/* -** GL_TexEnv -*/ -void GL_TexEnv( int env ) -{ -	if ( env == glState.texEnv[glState.currenttmu] ) -	{ -		return; -	} - -	glState.texEnv[glState.currenttmu] = env; - - -	switch ( env ) -	{ -	case GL_MODULATE: -		qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); -		break; -	case GL_REPLACE: -		qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); -		break; -	case GL_DECAL: -		qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); -		break; -	case GL_ADD: -		qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD ); -		break; -	default: -		ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed\n", env ); -		break; -	} -} - -/* -** GL_State -** -** This routine is responsible for setting the most commonly changed state -** in Q3. -*/ -void GL_State( unsigned long stateBits ) -{ -	unsigned long diff = stateBits ^ glState.glStateBits; - -	if ( !diff ) -	{ -		return; -	} - -	// -	// check depthFunc bits -	// -	if ( diff & GLS_DEPTHFUNC_EQUAL ) -	{ -		if ( stateBits & GLS_DEPTHFUNC_EQUAL ) -		{ -			qglDepthFunc( GL_EQUAL ); -		} -		else -		{ -			qglDepthFunc( GL_LEQUAL ); -		} -	} - -	// -	// check blend bits -	// -	if ( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) -	{ -		GLenum srcFactor, dstFactor; - -		if ( stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) -		{ -			switch ( stateBits & GLS_SRCBLEND_BITS ) -			{ -			case GLS_SRCBLEND_ZERO: -				srcFactor = GL_ZERO; -				break; -			case GLS_SRCBLEND_ONE: -				srcFactor = GL_ONE; -				break; -			case GLS_SRCBLEND_DST_COLOR: -				srcFactor = GL_DST_COLOR; -				break; -			case GLS_SRCBLEND_ONE_MINUS_DST_COLOR: -				srcFactor = GL_ONE_MINUS_DST_COLOR; -				break; -			case GLS_SRCBLEND_SRC_ALPHA: -				srcFactor = GL_SRC_ALPHA; -				break; -			case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA: -				srcFactor = GL_ONE_MINUS_SRC_ALPHA; -				break; -			case GLS_SRCBLEND_DST_ALPHA: -				srcFactor = GL_DST_ALPHA; -				break; -			case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA: -				srcFactor = GL_ONE_MINUS_DST_ALPHA; -				break; -			case GLS_SRCBLEND_ALPHA_SATURATE: -				srcFactor = GL_SRC_ALPHA_SATURATE; -				break; -			default: -				srcFactor = GL_ONE;		// to get warning to shut up -				ri.Error( ERR_DROP, "GL_State: invalid src blend state bits\n" ); -				break; -			} - -			switch ( stateBits & GLS_DSTBLEND_BITS ) -			{ -			case GLS_DSTBLEND_ZERO: -				dstFactor = GL_ZERO; -				break; -			case GLS_DSTBLEND_ONE: -				dstFactor = GL_ONE; -				break; -			case GLS_DSTBLEND_SRC_COLOR: -				dstFactor = GL_SRC_COLOR; -				break; -			case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR: -				dstFactor = GL_ONE_MINUS_SRC_COLOR; -				break; -			case GLS_DSTBLEND_SRC_ALPHA: -				dstFactor = GL_SRC_ALPHA; -				break; -			case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA: -				dstFactor = GL_ONE_MINUS_SRC_ALPHA; -				break; -			case GLS_DSTBLEND_DST_ALPHA: -				dstFactor = GL_DST_ALPHA; -				break; -			case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA: -				dstFactor = GL_ONE_MINUS_DST_ALPHA; -				break; -			default: -				dstFactor = GL_ONE;		// to get warning to shut up -				ri.Error( ERR_DROP, "GL_State: invalid dst blend state bits\n" ); -				break; -			} - -			qglEnable( GL_BLEND ); -			qglBlendFunc( srcFactor, dstFactor ); -		} -		else -		{ -			qglDisable( GL_BLEND ); -		} -	} - -	// -	// check depthmask -	// -	if ( diff & GLS_DEPTHMASK_TRUE ) -	{ -		if ( stateBits & GLS_DEPTHMASK_TRUE ) -		{ -			qglDepthMask( GL_TRUE ); -		} -		else -		{ -			qglDepthMask( GL_FALSE ); -		} -	} - -	// -	// fill/line mode -	// -	if ( diff & GLS_POLYMODE_LINE ) -	{ -		if ( stateBits & GLS_POLYMODE_LINE ) -		{ -			qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); -		} -		else -		{ -			qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); -		} -	} - -	// -	// depthtest -	// -	if ( diff & GLS_DEPTHTEST_DISABLE ) -	{ -		if ( stateBits & GLS_DEPTHTEST_DISABLE ) -		{ -			qglDisable( GL_DEPTH_TEST ); -		} -		else -		{ -			qglEnable( GL_DEPTH_TEST ); -		} -	} - -	// -	// alpha test -	// -	if ( diff & GLS_ATEST_BITS ) -	{ -		switch ( stateBits & GLS_ATEST_BITS ) -		{ -		case 0: -			qglDisable( GL_ALPHA_TEST ); -			break; -		case GLS_ATEST_GT_0: -			qglEnable( GL_ALPHA_TEST ); -			qglAlphaFunc( GL_GREATER, 0.0f ); -			break; -		case GLS_ATEST_LT_80: -			qglEnable( GL_ALPHA_TEST ); -			qglAlphaFunc( GL_LESS, 0.5f ); -			break; -		case GLS_ATEST_GE_80: -			qglEnable( GL_ALPHA_TEST ); -			qglAlphaFunc( GL_GEQUAL, 0.5f ); -			break; -		default: -			assert( 0 ); -			break; -		} -	} - -	glState.glStateBits = stateBits; -} - - - -/* -================ -RB_Hyperspace - -A player has predicted a teleport, but hasn't arrived yet -================ -*/ -static void RB_Hyperspace( void ) { -	float		c; - -	if ( !backEnd.isHyperspace ) { -		// do initialization shit -	} - -	c = ( backEnd.refdef.time & 255 ) / 255.0f; -	qglClearColor( c, c, c, 1 ); -	qglClear( GL_COLOR_BUFFER_BIT ); - -	backEnd.isHyperspace = qtrue; -} - - -static void SetViewportAndScissor( void ) { -	qglMatrixMode(GL_PROJECTION); -	qglLoadMatrixf( backEnd.viewParms.projectionMatrix ); -	qglMatrixMode(GL_MODELVIEW); - -	// set the window clipping -	qglViewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,  -		backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); -	qglScissor( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,  -		backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); -} - -/* -================= -RB_BeginDrawingView - -Any mirrored or portaled views have already been drawn, so prepare -to actually render the visible surfaces for this view -================= -*/ -void RB_BeginDrawingView (void) { -	int clearBits = 0; - -	// sync with gl if needed -	if ( r_finish->integer == 1 && !glState.finishCalled ) { -		qglFinish (); -		glState.finishCalled = qtrue; -	} -	if ( r_finish->integer == 0 ) { -		glState.finishCalled = qtrue; -	} - -	// we will need to change the projection matrix before drawing -	// 2D images again -	backEnd.projection2D = qfalse; - -	// -	// set the modelview matrix for the viewer -	// -	SetViewportAndScissor(); - -	// ensures that depth writes are enabled for the depth clear -	GL_State( GLS_DEFAULT ); -	// clear relevant buffers -	clearBits = GL_DEPTH_BUFFER_BIT; - -	if ( r_measureOverdraw->integer || r_shadows->integer == 2 ) -	{ -		clearBits |= GL_STENCIL_BUFFER_BIT; -	} -	if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) ) -	{ -		clearBits |= GL_COLOR_BUFFER_BIT;	// FIXME: only if sky shaders have been used -#ifdef _DEBUG -		qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f );	// FIXME: get color of sky -#else -		qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );	// FIXME: get color of sky -#endif -	} -	qglClear( clearBits ); - -	if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) ) -	{ -		RB_Hyperspace(); -		return; -	} -	else -	{ -		backEnd.isHyperspace = qfalse; -	} - -	glState.faceCulling = -1;		// force face culling to set next time - -	// we will only draw a sun if there was sky rendered in this view -	backEnd.skyRenderedThisView = qfalse; - -	// clip to the plane of the portal -	if ( backEnd.viewParms.isPortal ) { -		float	plane[4]; -		double	plane2[4]; - -		plane[0] = backEnd.viewParms.portalPlane.normal[0]; -		plane[1] = backEnd.viewParms.portalPlane.normal[1]; -		plane[2] = backEnd.viewParms.portalPlane.normal[2]; -		plane[3] = backEnd.viewParms.portalPlane.dist; - -		plane2[0] = DotProduct (backEnd.viewParms.or.axis[0], plane); -		plane2[1] = DotProduct (backEnd.viewParms.or.axis[1], plane); -		plane2[2] = DotProduct (backEnd.viewParms.or.axis[2], plane); -		plane2[3] = DotProduct (plane, backEnd.viewParms.or.origin) - plane[3]; - -		qglLoadMatrixf( s_flipMatrix ); -		qglClipPlane (GL_CLIP_PLANE0, plane2); -		qglEnable (GL_CLIP_PLANE0); -	} else { -		qglDisable (GL_CLIP_PLANE0); -	} -} - - -#define	MAC_EVENT_PUMP_MSEC		5 - -/* -================== -RB_RenderDrawSurfList -================== -*/ -void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { -	shader_t		*shader, *oldShader; -	int				fogNum, oldFogNum; -	int				entityNum, oldEntityNum; -	int				dlighted, oldDlighted; -	qboolean		depthRange, oldDepthRange; -	int				i; -	drawSurf_t		*drawSurf; -	int				oldSort; -	float			originalTime; - -	// save original time for entity shader offsets -	originalTime = backEnd.refdef.floatTime; - -	// clear the z buffer, set the modelview, etc -	RB_BeginDrawingView (); - -	// draw everything -	oldEntityNum = -1; -	backEnd.currentEntity = &tr.worldEntity; -	oldShader = NULL; -	oldFogNum = -1; -	oldDepthRange = qfalse; -	oldDlighted = qfalse; -	oldSort = -1; -	depthRange = qfalse; - -	backEnd.pc.c_surfaces += numDrawSurfs; - -	for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) { -		if ( drawSurf->sort == oldSort ) { -			// fast path, same as previous sort -			rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface ); -			continue; -		} -		oldSort = drawSurf->sort; -		R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted ); - -		// -		// change the tess parameters if needed -		// a "entityMergable" shader is a shader that can have surfaces from seperate -		// entities merged into a single batch, like smoke and blood puff sprites -		if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted  -			|| ( entityNum != oldEntityNum && !shader->entityMergable ) ) { -			if (oldShader != NULL) { -				RB_EndSurface(); -			} -			RB_BeginSurface( shader, fogNum ); -			oldShader = shader; -			oldFogNum = fogNum; -			oldDlighted = dlighted; -		} - -		// -		// change the modelview matrix if needed -		// -		if ( entityNum != oldEntityNum ) { -			depthRange = qfalse; - -			if ( entityNum != ENTITYNUM_WORLD ) { -				backEnd.currentEntity = &backEnd.refdef.entities[entityNum]; -				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime; -				// we have to reset the shaderTime as well otherwise image animations start -				// from the wrong frame -				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; - -				// set up the transformation matrix -				R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or ); - -				// set up the dynamic lighting if needed -				if ( backEnd.currentEntity->needDlights ) { -					R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or ); -				} - -				if ( backEnd.currentEntity->e.renderfx & RF_DEPTHHACK ) { -					// hack the depth range to prevent view model from poking into walls -					depthRange = qtrue; -				} -			} else { -				backEnd.currentEntity = &tr.worldEntity; -				backEnd.refdef.floatTime = originalTime; -				backEnd.or = backEnd.viewParms.world; -				// we have to reset the shaderTime as well otherwise image animations on -				// the world (like water) continue with the wrong frame -				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; -				R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or ); -			} - -			qglLoadMatrixf( backEnd.or.modelMatrix ); - -			// -			// change depthrange if needed -			// -			if ( oldDepthRange != depthRange ) { -				if ( depthRange ) { -					qglDepthRange (0, 0.3); -				} else { -					qglDepthRange (0, 1); -				} -				oldDepthRange = depthRange; -			} - -			oldEntityNum = entityNum; -		} - -		// add the triangles for this surface -		rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface ); -	} - -	backEnd.refdef.floatTime = originalTime; - -	// draw the contents of the last shader batch -	if (oldShader != NULL) { -		RB_EndSurface(); -	} - -	// go back to the world modelview matrix -	qglLoadMatrixf( backEnd.viewParms.world.modelMatrix ); -	if ( depthRange ) { -		qglDepthRange (0, 1); -	} - -#if 0 -	RB_DrawSun(); -#endif -	// darken down any stencil shadows -	RB_ShadowFinish();		 - -	// add light flares on lights that aren't obscured -	RB_RenderFlares(); -} - - -/* -============================================================================ - -RENDER BACK END THREAD FUNCTIONS - -============================================================================ -*/ - -/* -================ -RB_SetGL2D - -================ -*/ -void	RB_SetGL2D (void) { -	backEnd.projection2D = qtrue; - -	// set 2D virtual screen size -	qglViewport( 0, 0, glConfig.vidWidth, glConfig.vidHeight ); -	qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight ); -	qglMatrixMode(GL_PROJECTION); -    qglLoadIdentity (); -	qglOrtho (0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1); -	qglMatrixMode(GL_MODELVIEW); -    qglLoadIdentity (); - -	GL_State( GLS_DEPTHTEST_DISABLE | -			  GLS_SRCBLEND_SRC_ALPHA | -			  GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); - -	qglDisable( GL_CULL_FACE ); -	qglDisable( GL_CLIP_PLANE0 ); - -	// set time for 2D shaders -	backEnd.refdef.time = ri.Milliseconds(); -	backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f; -} - - -/* -============= -RE_StretchRaw - -FIXME: not exactly backend -Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle. -Used for cinematics. -============= -*/ -void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) { -	int			i, j; -	int			start, end; - -	if ( !tr.registered ) { -		return; -	} -	R_SyncRenderThread(); - -	// we definately want to sync every frame for the cinematics -	qglFinish(); - -	start = end = 0; -	if ( r_speeds->integer ) { -		start = ri.Milliseconds(); -	} - -	// make sure rows and cols are powers of 2 -	for ( i = 0 ; ( 1 << i ) < cols ; i++ ) { -	} -	for ( j = 0 ; ( 1 << j ) < rows ; j++ ) { -	} -	if ( ( 1 << i ) != cols || ( 1 << j ) != rows) { -		ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows); -	} - -	GL_Bind( tr.scratchImage[client] ); - -	// if the scratchImage isn't in the format we want, specify it as a new texture -	if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) { -		tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols; -		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows; -		qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );	 -	} else { -		if (dirty) { -			// otherwise, just subimage upload it so that drivers can tell we are going to be changing -			// it and don't try and do a texture compression -			qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data ); -		} -	} - -	if ( r_speeds->integer ) { -		end = ri.Milliseconds(); -		ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start ); -	} - -	RB_SetGL2D(); - -	qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight ); - -	qglBegin (GL_QUADS); -	qglTexCoord2f ( 0.5f / cols,  0.5f / rows ); -	qglVertex2f (x, y); -	qglTexCoord2f ( ( cols - 0.5f ) / cols ,  0.5f / rows ); -	qglVertex2f (x+w, y); -	qglTexCoord2f ( ( cols - 0.5f ) / cols, ( rows - 0.5f ) / rows ); -	qglVertex2f (x+w, y+h); -	qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows ); -	qglVertex2f (x, y+h); -	qglEnd (); -} - -void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) { - -	GL_Bind( tr.scratchImage[client] ); - -	// if the scratchImage isn't in the format we want, specify it as a new texture -	if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) { -		tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols; -		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows; -		qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );	 -	} else { -		if (dirty) { -			// otherwise, just subimage upload it so that drivers can tell we are going to be changing -			// it and don't try and do a texture compression -			qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data ); -		} -	} -} - - -/* -============= -RB_SetColor - -============= -*/ -const void	*RB_SetColor( const void *data ) { -	const setColorCommand_t	*cmd; - -	cmd = (const setColorCommand_t *)data; - -	backEnd.color2D[0] = cmd->color[0] * 255; -	backEnd.color2D[1] = cmd->color[1] * 255; -	backEnd.color2D[2] = cmd->color[2] * 255; -	backEnd.color2D[3] = cmd->color[3] * 255; - -	return (const void *)(cmd + 1); -} - -/* -============= -RB_StretchPic -============= -*/ -const void *RB_StretchPic ( const void *data ) { -	const stretchPicCommand_t	*cmd; -	shader_t *shader; -	int		numVerts, numIndexes; - -	cmd = (const stretchPicCommand_t *)data; - -	if ( !backEnd.projection2D ) { -		RB_SetGL2D(); -	} - -	shader = cmd->shader; -	if ( shader != tess.shader ) { -		if ( tess.numIndexes ) { -			RB_EndSurface(); -		} -		backEnd.currentEntity = &backEnd.entity2D; -		RB_BeginSurface( shader, 0 ); -	} - -	RB_CHECKOVERFLOW( 4, 6 ); -	numVerts = tess.numVertexes; -	numIndexes = tess.numIndexes; - -	tess.numVertexes += 4; -	tess.numIndexes += 6; - -	tess.indexes[ numIndexes ] = numVerts + 3; -	tess.indexes[ numIndexes + 1 ] = numVerts + 0; -	tess.indexes[ numIndexes + 2 ] = numVerts + 2; -	tess.indexes[ numIndexes + 3 ] = numVerts + 2; -	tess.indexes[ numIndexes + 4 ] = numVerts + 0; -	tess.indexes[ numIndexes + 5 ] = numVerts + 1; - -	*(int *)tess.vertexColors[ numVerts ] = -		*(int *)tess.vertexColors[ numVerts + 1 ] = -		*(int *)tess.vertexColors[ numVerts + 2 ] = -		*(int *)tess.vertexColors[ numVerts + 3 ] = *(int *)backEnd.color2D; - -	tess.xyz[ numVerts ][0] = cmd->x; -	tess.xyz[ numVerts ][1] = cmd->y; -	tess.xyz[ numVerts ][2] = 0; - -	tess.texCoords[ numVerts ][0][0] = cmd->s1; -	tess.texCoords[ numVerts ][0][1] = cmd->t1; - -	tess.xyz[ numVerts + 1 ][0] = cmd->x + cmd->w; -	tess.xyz[ numVerts + 1 ][1] = cmd->y; -	tess.xyz[ numVerts + 1 ][2] = 0; - -	tess.texCoords[ numVerts + 1 ][0][0] = cmd->s2; -	tess.texCoords[ numVerts + 1 ][0][1] = cmd->t1; - -	tess.xyz[ numVerts + 2 ][0] = cmd->x + cmd->w; -	tess.xyz[ numVerts + 2 ][1] = cmd->y + cmd->h; -	tess.xyz[ numVerts + 2 ][2] = 0; - -	tess.texCoords[ numVerts + 2 ][0][0] = cmd->s2; -	tess.texCoords[ numVerts + 2 ][0][1] = cmd->t2; - -	tess.xyz[ numVerts + 3 ][0] = cmd->x; -	tess.xyz[ numVerts + 3 ][1] = cmd->y + cmd->h; -	tess.xyz[ numVerts + 3 ][2] = 0; - -	tess.texCoords[ numVerts + 3 ][0][0] = cmd->s1; -	tess.texCoords[ numVerts + 3 ][0][1] = cmd->t2; - -	return (const void *)(cmd + 1); -} - - -/* -============= -RB_DrawSurfs - -============= -*/ -const void	*RB_DrawSurfs( const void *data ) { -	const drawSurfsCommand_t	*cmd; - -	// finish any 2D drawing if needed -	if ( tess.numIndexes ) { -		RB_EndSurface(); -	} - -	cmd = (const drawSurfsCommand_t *)data; - -	backEnd.refdef = cmd->refdef; -	backEnd.viewParms = cmd->viewParms; - -	RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs ); - -	return (const void *)(cmd + 1); -} - - -/* -============= -RB_DrawBuffer - -============= -*/ -const void	*RB_DrawBuffer( const void *data ) { -	const drawBufferCommand_t	*cmd; - -	cmd = (const drawBufferCommand_t *)data; - -	qglDrawBuffer( cmd->buffer ); - -	// clear screen for debugging -	if ( r_clear->integer ) { -		qglClearColor( 1, 0, 0.5, 1 ); -		qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); -	} - -	return (const void *)(cmd + 1); -} - -/* -=============== -RB_ShowImages - -Draw all the images to the screen, on top of whatever -was there.  This is used to test for texture thrashing. - -Also called by RE_EndRegistration -=============== -*/ -void RB_ShowImages( void ) { -	int		i; -	image_t	*image; -	float	x, y, w, h; -	int		start, end; - -	if ( !backEnd.projection2D ) { -		RB_SetGL2D(); -	} - -	qglClear( GL_COLOR_BUFFER_BIT ); - -	qglFinish(); - -	start = ri.Milliseconds(); - -	for ( i=0 ; i<tr.numImages ; i++ ) { -		image = tr.images[i]; - -		w = glConfig.vidWidth / 20; -		h = glConfig.vidHeight / 15; -		x = i % 20 * w; -		y = i / 20 * h; - -		// show in proportional size in mode 2 -		if ( r_showImages->integer == 2 ) { -			w *= image->uploadWidth / 512.0f; -			h *= image->uploadHeight / 512.0f; -		} - -		GL_Bind( image ); -		qglBegin (GL_QUADS); -		qglTexCoord2f( 0, 0 ); -		qglVertex2f( x, y ); -		qglTexCoord2f( 1, 0 ); -		qglVertex2f( x + w, y ); -		qglTexCoord2f( 1, 1 ); -		qglVertex2f( x + w, y + h ); -		qglTexCoord2f( 0, 1 ); -		qglVertex2f( x, y + h ); -		qglEnd(); -	} - -	qglFinish(); - -	end = ri.Milliseconds(); -	ri.Printf( PRINT_ALL, "%i msec to draw all images\n", end - start ); - -} - - -/* -============= -RB_SwapBuffers - -============= -*/ -const void	*RB_SwapBuffers( const void *data ) { -	const swapBuffersCommand_t	*cmd; - -	// finish any 2D drawing if needed -	if ( tess.numIndexes ) { -		RB_EndSurface(); -	} - -	// texture swapping test -	if ( r_showImages->integer ) { -		RB_ShowImages(); -	} - -	cmd = (const swapBuffersCommand_t *)data; - -	// we measure overdraw by reading back the stencil buffer and -	// counting up the number of increments that have happened -	if ( r_measureOverdraw->integer ) { -		int i; -		long sum = 0; -		unsigned char *stencilReadback; - -		stencilReadback = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight ); -		qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback ); - -		for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) { -			sum += stencilReadback[i]; -		} - -		backEnd.pc.c_overDraw += sum; -		ri.Hunk_FreeTempMemory( stencilReadback ); -	} - - -	if ( !glState.finishCalled ) { -		qglFinish(); -	} - -	GLimp_LogComment( "***************** RB_SwapBuffers *****************\n\n\n" ); - -	GLimp_EndFrame(); - -	backEnd.projection2D = qfalse; - -	return (const void *)(cmd + 1); -} - -/* -==================== -RB_ExecuteRenderCommands - -This function will be called synchronously if running without -smp extensions, or asynchronously by another thread. -==================== -*/ -void RB_ExecuteRenderCommands( const void *data ) { -	int		t1, t2; - -	t1 = ri.Milliseconds (); - -	if ( !r_smp->integer || data == backEndData[0]->commands.cmds ) { -		backEnd.smpFrame = 0; -	} else { -		backEnd.smpFrame = 1; -	} - -	while ( 1 ) { -		switch ( *(const int *)data ) { -		case RC_SET_COLOR: -			data = RB_SetColor( data ); -			break; -		case RC_STRETCH_PIC: -			data = RB_StretchPic( data ); -			break; -		case RC_DRAW_SURFS: -			data = RB_DrawSurfs( data ); -			break; -		case RC_DRAW_BUFFER: -			data = RB_DrawBuffer( data ); -			break; -		case RC_SWAP_BUFFERS: -			data = RB_SwapBuffers( data ); -			break; -		case RC_SCREENSHOT: -			data = RB_TakeScreenshotCmd( data ); -			break; - -		case RC_END_OF_LIST: -		default: -			// stop rendering on this thread -			t2 = ri.Milliseconds (); -			backEnd.pc.msec = t2 - t1; -			return; -		} -	} - -} - - -/* -================ -RB_RenderThread -================ -*/ -void RB_RenderThread( void ) { -	const void	*data; - -	// wait for either a rendering command or a quit command -	while ( 1 ) { -		// sleep until we have work to do -		data = GLimp_RendererSleep(); - -		if ( !data ) { -			return;	// all done, renderer is shutting down -		} - -		renderThreadActive = qtrue; - -		RB_ExecuteRenderCommands( data ); - -		renderThreadActive = qfalse; -	} -} - diff --git a/ioq3-r437/src/renderer/tr_bsp.c b/ioq3-r437/src/renderer/tr_bsp.c deleted file mode 100644 index b0cbe50d..00000000 --- a/ioq3-r437/src/renderer/tr_bsp.c +++ /dev/null @@ -1,1865 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_map.c - -#include "tr_local.h" - -/* - -Loads and prepares a map file for scene rendering. - -A single entry point: - -void RE_LoadWorldMap( const char *name ); - -*/ - -static	world_t		s_worldData; -static	byte		*fileBase; - -int			c_subdivisions; -int			c_gridVerts; - -//=============================================================================== - -static void HSVtoRGB( float h, float s, float v, float rgb[3] ) -{ -	int i; -	float f; -	float p, q, t; - -	h *= 5; - -	i = floor( h ); -	f = h - i; - -	p = v * ( 1 - s ); -	q = v * ( 1 - s * f ); -	t = v * ( 1 - s * ( 1 - f ) ); - -	switch ( i ) -	{ -	case 0: -		rgb[0] = v; -		rgb[1] = t; -		rgb[2] = p; -		break; -	case 1: -		rgb[0] = q; -		rgb[1] = v; -		rgb[2] = p; -		break; -	case 2: -		rgb[0] = p; -		rgb[1] = v; -		rgb[2] = t; -		break; -	case 3: -		rgb[0] = p; -		rgb[1] = q; -		rgb[2] = v; -		break; -	case 4: -		rgb[0] = t; -		rgb[1] = p; -		rgb[2] = v; -		break; -	case 5: -		rgb[0] = v; -		rgb[1] = p; -		rgb[2] = q; -		break; -	} -} - -/* -=============== -R_ColorShiftLightingBytes - -=============== -*/ -static	void R_ColorShiftLightingBytes( byte in[4], byte out[4] ) { -	int		shift, r, g, b; - -	// shift the color data based on overbright range -	shift = r_mapOverBrightBits->integer - tr.overbrightBits; - -	// shift the data based on overbright range -	r = in[0] << shift; -	g = in[1] << shift; -	b = in[2] << shift; -	 -	// normalize by color instead of saturating to white -	if ( ( r | g | b ) > 255 ) { -		int		max; - -		max = r > g ? r : g; -		max = max > b ? max : b; -		r = r * 255 / max; -		g = g * 255 / max; -		b = b * 255 / max; -	} - -	out[0] = r; -	out[1] = g; -	out[2] = b; -	out[3] = in[3]; -} - -/* -=============== -R_LoadLightmaps - -=============== -*/ -#define	LIGHTMAP_SIZE	128 -static	void R_LoadLightmaps( lump_t *l ) { -	byte		*buf, *buf_p; -	int			len; -	byte		image[LIGHTMAP_SIZE*LIGHTMAP_SIZE*4]; -	int			i, j; -	float maxIntensity = 0; -	double sumIntensity = 0; - -	len = l->filelen; -	if ( !len ) { -		return; -	} -	buf = fileBase + l->fileofs; - -	// we are about to upload textures -	R_SyncRenderThread(); - -	// create all the lightmaps -	tr.numLightmaps = len / (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3); -	if ( tr.numLightmaps == 1 ) { -		//FIXME: HACK: maps with only one lightmap turn up fullbright for some reason. -		//this avoids this, but isn't the correct solution. -		tr.numLightmaps++; -	} else if ( tr.numLightmaps >= MAX_LIGHTMAPS ) { // 20051020 misantropia -		ri.Printf( PRINT_WARNING, "WARNING: number of lightmaps > MAX_LIGHTMAPS\n" ); -		tr.numLightmaps = MAX_LIGHTMAPS; -	} - -	// if we are in r_vertexLight mode, we don't need the lightmaps at all -	if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) { -		return; -	} - -	for ( i = 0 ; i < tr.numLightmaps ; i++ ) { -		// expand the 24 bit on-disk to 32 bit -		buf_p = buf + i * LIGHTMAP_SIZE*LIGHTMAP_SIZE * 3; - -		if ( r_lightmap->integer == 2 ) -		{	// color code by intensity as development tool	(FIXME: check range) -			for ( j = 0; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) -			{ -				float r = buf_p[j*3+0]; -				float g = buf_p[j*3+1]; -				float b = buf_p[j*3+2]; -				float intensity; -				float out[3] = {0.0, 0.0, 0.0}; - -				intensity = 0.33f * r + 0.685f * g + 0.063f * b; - -				if ( intensity > 255 ) -					intensity = 1.0f; -				else -					intensity /= 255.0f; - -				if ( intensity > maxIntensity ) -					maxIntensity = intensity; - -				HSVtoRGB( intensity, 1.00, 0.50, out ); - -				image[j*4+0] = out[0] * 255; -				image[j*4+1] = out[1] * 255; -				image[j*4+2] = out[2] * 255; -				image[j*4+3] = 255; - -				sumIntensity += intensity; -			} -		} else { -			for ( j = 0 ; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) { -				R_ColorShiftLightingBytes( &buf_p[j*3], &image[j*4] ); -				image[j*4+3] = 255; -			} -		} -		tr.lightmaps[i] = R_CreateImage( va("*lightmap%d",i), image,  -			LIGHTMAP_SIZE, LIGHTMAP_SIZE, qfalse, qfalse, GL_CLAMP ); -	} - -	if ( r_lightmap->integer == 2 )	{ -		ri.Printf( PRINT_ALL, "Brightest lightmap value: %d\n", ( int ) ( maxIntensity * 255 ) ); -	} -} - - -/* -================= -RE_SetWorldVisData - -This is called by the clipmodel subsystem so we can share the 1.8 megs of -space in big maps... -================= -*/ -void		RE_SetWorldVisData( const byte *vis ) { -	tr.externalVisData = vis; -} - - -/* -================= -R_LoadVisibility -================= -*/ -static	void R_LoadVisibility( lump_t *l ) { -	int		len; -	byte	*buf; - -	len = ( s_worldData.numClusters + 63 ) & ~63; -	s_worldData.novis = ri.Hunk_Alloc( len, h_low ); -	Com_Memset( s_worldData.novis, 0xff, len ); - -    len = l->filelen; -	if ( !len ) { -		return; -	} -	buf = fileBase + l->fileofs; - -	s_worldData.numClusters = LittleLong( ((int *)buf)[0] ); -	s_worldData.clusterBytes = LittleLong( ((int *)buf)[1] ); - -	// CM_Load should have given us the vis data to share, so -	// we don't need to allocate another copy -	if ( tr.externalVisData ) { -		s_worldData.vis = tr.externalVisData; -	} else { -		byte	*dest; - -		dest = ri.Hunk_Alloc( len - 8, h_low ); -		Com_Memcpy( dest, buf + 8, len - 8 ); -		s_worldData.vis = dest; -	} -} - -//=============================================================================== - - -/* -=============== -ShaderForShaderNum -=============== -*/ -static shader_t *ShaderForShaderNum( int shaderNum, int lightmapNum ) { -	shader_t	*shader; -	dshader_t	*dsh; - -	shaderNum = LittleLong( shaderNum ); -	if ( shaderNum < 0 || shaderNum >= s_worldData.numShaders ) { -		ri.Error( ERR_DROP, "ShaderForShaderNum: bad num %i", shaderNum ); -	} -	dsh = &s_worldData.shaders[ shaderNum ]; - -	if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) { -		lightmapNum = LIGHTMAP_BY_VERTEX; -	} - -	if ( r_fullbright->integer ) { -		lightmapNum = LIGHTMAP_WHITEIMAGE; -	} - -	shader = R_FindShader( dsh->shader, lightmapNum, qtrue ); - -	// if the shader had errors, just use default shader -	if ( shader->defaultShader ) { -		return tr.defaultShader; -	} - -	return shader; -} - -/* -=============== -ParseFace -=============== -*/ -static void ParseFace( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int *indexes  ) { -	int			i, j; -	srfSurfaceFace_t	*cv; -	int			numPoints, numIndexes; -	int			lightmapNum; -	int			sfaceSize, ofsIndexes; - -	lightmapNum = LittleLong( ds->lightmapNum ); - -	// get fog volume -	surf->fogIndex = LittleLong( ds->fogNum ) + 1; - -	// get shader value -	surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapNum ); -	if ( r_singleShader->integer && !surf->shader->isSky ) { -		surf->shader = tr.defaultShader; -	} - -	numPoints = LittleLong( ds->numVerts ); -	if (numPoints > MAX_FACE_POINTS) { -		ri.Printf( PRINT_WARNING, "WARNING: MAX_FACE_POINTS exceeded: %i\n", numPoints); -    numPoints = MAX_FACE_POINTS; -    surf->shader = tr.defaultShader; -	} - -	numIndexes = LittleLong( ds->numIndexes ); - -	// create the srfSurfaceFace_t -	sfaceSize = ( size_t ) &((srfSurfaceFace_t *)0)->points[numPoints]; -	ofsIndexes = sfaceSize; -	sfaceSize += sizeof( int ) * numIndexes; - -	cv = ri.Hunk_Alloc( sfaceSize, h_low ); -	cv->surfaceType = SF_FACE; -	cv->numPoints = numPoints; -	cv->numIndices = numIndexes; -	cv->ofsIndices = ofsIndexes; - -	verts += LittleLong( ds->firstVert ); -	for ( i = 0 ; i < numPoints ; i++ ) { -		for ( j = 0 ; j < 3 ; j++ ) { -			cv->points[i][j] = LittleFloat( verts[i].xyz[j] ); -		} -		for ( j = 0 ; j < 2 ; j++ ) { -			cv->points[i][3+j] = LittleFloat( verts[i].st[j] ); -			cv->points[i][5+j] = LittleFloat( verts[i].lightmap[j] ); -		} -		R_ColorShiftLightingBytes( verts[i].color, (byte *)&cv->points[i][7] ); -	} - -	indexes += LittleLong( ds->firstIndex ); -	for ( i = 0 ; i < numIndexes ; i++ ) { -		((int *)((byte *)cv + cv->ofsIndices ))[i] = LittleLong( indexes[ i ] ); -	} - -	// take the plane information from the lightmap vector -	for ( i = 0 ; i < 3 ; i++ ) { -		cv->plane.normal[i] = LittleFloat( ds->lightmapVecs[2][i] ); -	} -	cv->plane.dist = DotProduct( cv->points[0], cv->plane.normal ); -	SetPlaneSignbits( &cv->plane ); -	cv->plane.type = PlaneTypeForNormal( cv->plane.normal ); - -	surf->data = (surfaceType_t *)cv; -} - - -/* -=============== -ParseMesh -=============== -*/ -static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, msurface_t *surf ) { -	srfGridMesh_t	*grid; -	int				i, j; -	int				width, height, numPoints; -	drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE]; -	int				lightmapNum; -	vec3_t			bounds[2]; -	vec3_t			tmpVec; -	static surfaceType_t	skipData = SF_SKIP; - -	lightmapNum = LittleLong( ds->lightmapNum ); - -	// get fog volume -	surf->fogIndex = LittleLong( ds->fogNum ) + 1; - -	// get shader value -	surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapNum ); -	if ( r_singleShader->integer && !surf->shader->isSky ) { -		surf->shader = tr.defaultShader; -	} - -	// we may have a nodraw surface, because they might still need to -	// be around for movement clipping -	if ( s_worldData.shaders[ LittleLong( ds->shaderNum ) ].surfaceFlags & SURF_NODRAW ) { -		surf->data = &skipData; -		return; -	} - -	width = LittleLong( ds->patchWidth ); -	height = LittleLong( ds->patchHeight ); - -	verts += LittleLong( ds->firstVert ); -	numPoints = width * height; -	for ( i = 0 ; i < numPoints ; i++ ) { -		for ( j = 0 ; j < 3 ; j++ ) { -			points[i].xyz[j] = LittleFloat( verts[i].xyz[j] ); -			points[i].normal[j] = LittleFloat( verts[i].normal[j] ); -		} -		for ( j = 0 ; j < 2 ; j++ ) { -			points[i].st[j] = LittleFloat( verts[i].st[j] ); -			points[i].lightmap[j] = LittleFloat( verts[i].lightmap[j] ); -		} -		R_ColorShiftLightingBytes( verts[i].color, points[i].color ); -	} - -	// pre-tesseleate -	grid = R_SubdividePatchToGrid( width, height, points ); -	surf->data = (surfaceType_t *)grid; - -	// copy the level of detail origin, which is the center -	// of the group of all curves that must subdivide the same -	// to avoid cracking -	for ( i = 0 ; i < 3 ; i++ ) { -		bounds[0][i] = LittleFloat( ds->lightmapVecs[0][i] ); -		bounds[1][i] = LittleFloat( ds->lightmapVecs[1][i] ); -	} -	VectorAdd( bounds[0], bounds[1], bounds[1] ); -	VectorScale( bounds[1], 0.5f, grid->lodOrigin ); -	VectorSubtract( bounds[0], grid->lodOrigin, tmpVec ); -	grid->lodRadius = VectorLength( tmpVec ); -} - -/* -=============== -ParseTriSurf -=============== -*/ -static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int *indexes ) { -	srfTriangles_t	*tri; -	int				i, j; -	int				numVerts, numIndexes; - -	// get fog volume -	surf->fogIndex = LittleLong( ds->fogNum ) + 1; - -	// get shader -	surf->shader = ShaderForShaderNum( ds->shaderNum, LIGHTMAP_BY_VERTEX ); -	if ( r_singleShader->integer && !surf->shader->isSky ) { -		surf->shader = tr.defaultShader; -	} - -	numVerts = LittleLong( ds->numVerts ); -	numIndexes = LittleLong( ds->numIndexes ); - -	tri = ri.Hunk_Alloc( sizeof( *tri ) + numVerts * sizeof( tri->verts[0] )  -		+ numIndexes * sizeof( tri->indexes[0] ), h_low ); -	tri->surfaceType = SF_TRIANGLES; -	tri->numVerts = numVerts; -	tri->numIndexes = numIndexes; -	tri->verts = (drawVert_t *)(tri + 1); -	tri->indexes = (int *)(tri->verts + tri->numVerts ); - -	surf->data = (surfaceType_t *)tri; - -	// copy vertexes -	ClearBounds( tri->bounds[0], tri->bounds[1] ); -	verts += LittleLong( ds->firstVert ); -	for ( i = 0 ; i < numVerts ; i++ ) { -		for ( j = 0 ; j < 3 ; j++ ) { -			tri->verts[i].xyz[j] = LittleFloat( verts[i].xyz[j] ); -			tri->verts[i].normal[j] = LittleFloat( verts[i].normal[j] ); -		} -		AddPointToBounds( tri->verts[i].xyz, tri->bounds[0], tri->bounds[1] ); -		for ( j = 0 ; j < 2 ; j++ ) { -			tri->verts[i].st[j] = LittleFloat( verts[i].st[j] ); -			tri->verts[i].lightmap[j] = LittleFloat( verts[i].lightmap[j] ); -		} - -		R_ColorShiftLightingBytes( verts[i].color, tri->verts[i].color ); -	} - -	// copy indexes -	indexes += LittleLong( ds->firstIndex ); -	for ( i = 0 ; i < numIndexes ; i++ ) { -		tri->indexes[i] = LittleLong( indexes[i] ); -		if ( tri->indexes[i] < 0 || tri->indexes[i] >= numVerts ) { -			ri.Error( ERR_DROP, "Bad index in triangle surface" ); -		} -	} -} - -/* -=============== -ParseFlare -=============== -*/ -static void ParseFlare( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int *indexes ) { -	srfFlare_t		*flare; -	int				i; - -	// get fog volume -	surf->fogIndex = LittleLong( ds->fogNum ) + 1; - -	// get shader -	surf->shader = ShaderForShaderNum( ds->shaderNum, LIGHTMAP_BY_VERTEX ); -	if ( r_singleShader->integer && !surf->shader->isSky ) { -		surf->shader = tr.defaultShader; -	} - -	flare = ri.Hunk_Alloc( sizeof( *flare ), h_low ); -	flare->surfaceType = SF_FLARE; - -	surf->data = (surfaceType_t *)flare; - -	for ( i = 0 ; i < 3 ; i++ ) { -		flare->origin[i] = LittleFloat( ds->lightmapOrigin[i] ); -		flare->color[i] = LittleFloat( ds->lightmapVecs[0][i] ); -		flare->normal[i] = LittleFloat( ds->lightmapVecs[2][i] ); -	} -} - - -/* -================= -R_MergedWidthPoints - -returns true if there are grid points merged on a width edge -================= -*/ -int R_MergedWidthPoints(srfGridMesh_t *grid, int offset) { -	int i, j; - -	for (i = 1; i < grid->width-1; i++) { -		for (j = i + 1; j < grid->width-1; j++) { -			if ( fabs(grid->verts[i + offset].xyz[0] - grid->verts[j + offset].xyz[0]) > .1) continue; -			if ( fabs(grid->verts[i + offset].xyz[1] - grid->verts[j + offset].xyz[1]) > .1) continue; -			if ( fabs(grid->verts[i + offset].xyz[2] - grid->verts[j + offset].xyz[2]) > .1) continue; -			return qtrue; -		} -	} -	return qfalse; -} - -/* -================= -R_MergedHeightPoints - -returns true if there are grid points merged on a height edge -================= -*/ -int R_MergedHeightPoints(srfGridMesh_t *grid, int offset) { -	int i, j; - -	for (i = 1; i < grid->height-1; i++) { -		for (j = i + 1; j < grid->height-1; j++) { -			if ( fabs(grid->verts[grid->width * i + offset].xyz[0] - grid->verts[grid->width * j + offset].xyz[0]) > .1) continue; -			if ( fabs(grid->verts[grid->width * i + offset].xyz[1] - grid->verts[grid->width * j + offset].xyz[1]) > .1) continue; -			if ( fabs(grid->verts[grid->width * i + offset].xyz[2] - grid->verts[grid->width * j + offset].xyz[2]) > .1) continue; -			return qtrue; -		} -	} -	return qfalse; -} - -/* -================= -R_FixSharedVertexLodError_r - -NOTE: never sync LoD through grid edges with merged points! - -FIXME: write generalized version that also avoids cracks between a patch and one that meets half way? -================= -*/ -void R_FixSharedVertexLodError_r( int start, srfGridMesh_t *grid1 ) { -	int j, k, l, m, n, offset1, offset2, touch; -	srfGridMesh_t *grid2; - -	for ( j = start; j < s_worldData.numsurfaces; j++ ) { -		// -		grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data; -		// if this surface is not a grid -		if ( grid2->surfaceType != SF_GRID ) continue; -		// if the LOD errors are already fixed for this patch -		if ( grid2->lodFixed == 2 ) continue; -		// grids in the same LOD group should have the exact same lod radius -		if ( grid1->lodRadius != grid2->lodRadius ) continue; -		// grids in the same LOD group should have the exact same lod origin -		if ( grid1->lodOrigin[0] != grid2->lodOrigin[0] ) continue; -		if ( grid1->lodOrigin[1] != grid2->lodOrigin[1] ) continue; -		if ( grid1->lodOrigin[2] != grid2->lodOrigin[2] ) continue; -		// -		touch = qfalse; -		for (n = 0; n < 2; n++) { -			// -			if (n) offset1 = (grid1->height-1) * grid1->width; -			else offset1 = 0; -			if (R_MergedWidthPoints(grid1, offset1)) continue; -			for (k = 1; k < grid1->width-1; k++) { -				for (m = 0; m < 2; m++) { - -					if (m) offset2 = (grid2->height-1) * grid2->width; -					else offset2 = 0; -					if (R_MergedWidthPoints(grid2, offset2)) continue; -					for ( l = 1; l < grid2->width-1; l++) { -					// -						if ( fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1) continue; -						if ( fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1) continue; -						if ( fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1) continue; -						// ok the points are equal and should have the same lod error -						grid2->widthLodError[l] = grid1->widthLodError[k]; -						touch = qtrue; -					} -				} -				for (m = 0; m < 2; m++) { - -					if (m) offset2 = grid2->width-1; -					else offset2 = 0; -					if (R_MergedHeightPoints(grid2, offset2)) continue; -					for ( l = 1; l < grid2->height-1; l++) { -					// -						if ( fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1) continue; -						if ( fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1) continue; -						if ( fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1) continue; -						// ok the points are equal and should have the same lod error -						grid2->heightLodError[l] = grid1->widthLodError[k]; -						touch = qtrue; -					} -				} -			} -		} -		for (n = 0; n < 2; n++) { -			// -			if (n) offset1 = grid1->width-1; -			else offset1 = 0; -			if (R_MergedHeightPoints(grid1, offset1)) continue; -			for (k = 1; k < grid1->height-1; k++) { -				for (m = 0; m < 2; m++) { - -					if (m) offset2 = (grid2->height-1) * grid2->width; -					else offset2 = 0; -					if (R_MergedWidthPoints(grid2, offset2)) continue; -					for ( l = 1; l < grid2->width-1; l++) { -					// -						if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1) continue; -						if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1) continue; -						if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1) continue; -						// ok the points are equal and should have the same lod error -						grid2->widthLodError[l] = grid1->heightLodError[k]; -						touch = qtrue; -					} -				} -				for (m = 0; m < 2; m++) { - -					if (m) offset2 = grid2->width-1; -					else offset2 = 0; -					if (R_MergedHeightPoints(grid2, offset2)) continue; -					for ( l = 1; l < grid2->height-1; l++) { -					// -						if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1) continue; -						if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1) continue; -						if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1) continue; -						// ok the points are equal and should have the same lod error -						grid2->heightLodError[l] = grid1->heightLodError[k]; -						touch = qtrue; -					} -				} -			} -		} -		if (touch) { -			grid2->lodFixed = 2; -			R_FixSharedVertexLodError_r ( start, grid2 ); -			//NOTE: this would be correct but makes things really slow -			//grid2->lodFixed = 1; -		} -	} -} - -/* -================= -R_FixSharedVertexLodError - -This function assumes that all patches in one group are nicely stitched together for the highest LoD. -If this is not the case this function will still do its job but won't fix the highest LoD cracks. -================= -*/ -void R_FixSharedVertexLodError( void ) { -	int i; -	srfGridMesh_t *grid1; - -	for ( i = 0; i < s_worldData.numsurfaces; i++ ) { -		// -		grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data; -		// if this surface is not a grid -		if ( grid1->surfaceType != SF_GRID ) -			continue; -		// -		if ( grid1->lodFixed ) -			continue; -		// -		grid1->lodFixed = 2; -		// recursively fix other patches in the same LOD group -		R_FixSharedVertexLodError_r( i + 1, grid1); -	} -} - - -/* -=============== -R_StitchPatches -=============== -*/ -int R_StitchPatches( int grid1num, int grid2num ) { -	float *v1, *v2; -	srfGridMesh_t *grid1, *grid2; -	int k, l, m, n, offset1, offset2, row, column; - -	grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data; -	grid2 = (srfGridMesh_t *) s_worldData.surfaces[grid2num].data; -	for (n = 0; n < 2; n++) { -		// -		if (n) offset1 = (grid1->height-1) * grid1->width; -		else offset1 = 0; -		if (R_MergedWidthPoints(grid1, offset1)) -			continue; -		for (k = 0; k < grid1->width-2; k += 2) { - -			for (m = 0; m < 2; m++) { - -				if ( grid2->width >= MAX_GRID_SIZE ) -					break; -				if (m) offset2 = (grid2->height-1) * grid2->width; -				else offset2 = 0; -				for ( l = 0; l < grid2->width-1; l++) { -				// -					v1 = grid1->verts[k + offset1].xyz; -					v2 = grid2->verts[l + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; - -					v1 = grid1->verts[k + 2 + offset1].xyz; -					v2 = grid2->verts[l + 1 + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; -					// -					v1 = grid2->verts[l + offset2].xyz; -					v2 = grid2->verts[l + 1 + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) < .01 && -							fabs(v1[1] - v2[1]) < .01 && -							fabs(v1[2] - v2[2]) < .01) -						continue; -					// -					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); -					// insert column into grid2 right after after column l -					if (m) row = grid2->height-1; -					else row = 0; -					grid2 = R_GridInsertColumn( grid2, l+1, row, -									grid1->verts[k + 1 + offset1].xyz, grid1->widthLodError[k+1]); -					grid2->lodStitched = qfalse; -					s_worldData.surfaces[grid2num].data = (void *) grid2; -					return qtrue; -				} -			} -			for (m = 0; m < 2; m++) { - -				if (grid2->height >= MAX_GRID_SIZE) -					break; -				if (m) offset2 = grid2->width-1; -				else offset2 = 0; -				for ( l = 0; l < grid2->height-1; l++) { -					// -					v1 = grid1->verts[k + offset1].xyz; -					v2 = grid2->verts[grid2->width * l + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; - -					v1 = grid1->verts[k + 2 + offset1].xyz; -					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; -					// -					v1 = grid2->verts[grid2->width * l + offset2].xyz; -					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) < .01 && -							fabs(v1[1] - v2[1]) < .01 && -							fabs(v1[2] - v2[2]) < .01) -						continue; -					// -					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); -					// insert row into grid2 right after after row l -					if (m) column = grid2->width-1; -					else column = 0; -					grid2 = R_GridInsertRow( grid2, l+1, column, -										grid1->verts[k + 1 + offset1].xyz, grid1->widthLodError[k+1]); -					grid2->lodStitched = qfalse; -					s_worldData.surfaces[grid2num].data = (void *) grid2; -					return qtrue; -				} -			} -		} -	} -	for (n = 0; n < 2; n++) { -		// -		if (n) offset1 = grid1->width-1; -		else offset1 = 0; -		if (R_MergedHeightPoints(grid1, offset1)) -			continue; -		for (k = 0; k < grid1->height-2; k += 2) { -			for (m = 0; m < 2; m++) { - -				if ( grid2->width >= MAX_GRID_SIZE ) -					break; -				if (m) offset2 = (grid2->height-1) * grid2->width; -				else offset2 = 0; -				for ( l = 0; l < grid2->width-1; l++) { -				// -					v1 = grid1->verts[grid1->width * k + offset1].xyz; -					v2 = grid2->verts[l + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; - -					v1 = grid1->verts[grid1->width * (k + 2) + offset1].xyz; -					v2 = grid2->verts[l + 1 + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; -					// -					v1 = grid2->verts[l + offset2].xyz; -					v2 = grid2->verts[(l + 1) + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) < .01 && -							fabs(v1[1] - v2[1]) < .01 && -							fabs(v1[2] - v2[2]) < .01) -						continue; -					// -					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); -					// insert column into grid2 right after after column l -					if (m) row = grid2->height-1; -					else row = 0; -					grid2 = R_GridInsertColumn( grid2, l+1, row, -									grid1->verts[grid1->width * (k + 1) + offset1].xyz, grid1->heightLodError[k+1]); -					grid2->lodStitched = qfalse; -					s_worldData.surfaces[grid2num].data = (void *) grid2; -					return qtrue; -				} -			} -			for (m = 0; m < 2; m++) { - -				if (grid2->height >= MAX_GRID_SIZE) -					break; -				if (m) offset2 = grid2->width-1; -				else offset2 = 0; -				for ( l = 0; l < grid2->height-1; l++) { -				// -					v1 = grid1->verts[grid1->width * k + offset1].xyz; -					v2 = grid2->verts[grid2->width * l + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; - -					v1 = grid1->verts[grid1->width * (k + 2) + offset1].xyz; -					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; -					// -					v1 = grid2->verts[grid2->width * l + offset2].xyz; -					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) < .01 && -							fabs(v1[1] - v2[1]) < .01 && -							fabs(v1[2] - v2[2]) < .01) -						continue; -					// -					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); -					// insert row into grid2 right after after row l -					if (m) column = grid2->width-1; -					else column = 0; -					grid2 = R_GridInsertRow( grid2, l+1, column, -									grid1->verts[grid1->width * (k + 1) + offset1].xyz, grid1->heightLodError[k+1]); -					grid2->lodStitched = qfalse; -					s_worldData.surfaces[grid2num].data = (void *) grid2; -					return qtrue; -				} -			} -		} -	} -	for (n = 0; n < 2; n++) { -		// -		if (n) offset1 = (grid1->height-1) * grid1->width; -		else offset1 = 0; -		if (R_MergedWidthPoints(grid1, offset1)) -			continue; -		for (k = grid1->width-1; k > 1; k -= 2) { - -			for (m = 0; m < 2; m++) { - -				if ( grid2->width >= MAX_GRID_SIZE ) -					break; -				if (m) offset2 = (grid2->height-1) * grid2->width; -				else offset2 = 0; -				for ( l = 0; l < grid2->width-1; l++) { -				// -					v1 = grid1->verts[k + offset1].xyz; -					v2 = grid2->verts[l + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; - -					v1 = grid1->verts[k - 2 + offset1].xyz; -					v2 = grid2->verts[l + 1 + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; -					// -					v1 = grid2->verts[l + offset2].xyz; -					v2 = grid2->verts[(l + 1) + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) < .01 && -							fabs(v1[1] - v2[1]) < .01 && -							fabs(v1[2] - v2[2]) < .01) -						continue; -					// -					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); -					// insert column into grid2 right after after column l -					if (m) row = grid2->height-1; -					else row = 0; -					grid2 = R_GridInsertColumn( grid2, l+1, row, -										grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k+1]); -					grid2->lodStitched = qfalse; -					s_worldData.surfaces[grid2num].data = (void *) grid2; -					return qtrue; -				} -			} -			for (m = 0; m < 2; m++) { - -				if (grid2->height >= MAX_GRID_SIZE) -					break; -				if (m) offset2 = grid2->width-1; -				else offset2 = 0; -				for ( l = 0; l < grid2->height-1; l++) { -				// -					v1 = grid1->verts[k + offset1].xyz; -					v2 = grid2->verts[grid2->width * l + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; - -					v1 = grid1->verts[k - 2 + offset1].xyz; -					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; -					// -					v1 = grid2->verts[grid2->width * l + offset2].xyz; -					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) < .01 && -							fabs(v1[1] - v2[1]) < .01 && -							fabs(v1[2] - v2[2]) < .01) -						continue; -					// -					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); -					// insert row into grid2 right after after row l -					if (m) column = grid2->width-1; -					else column = 0; -					grid2 = R_GridInsertRow( grid2, l+1, column, -										grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k+1]); -					if (!grid2) -						break; -					grid2->lodStitched = qfalse; -					s_worldData.surfaces[grid2num].data = (void *) grid2; -					return qtrue; -				} -			} -		} -	} -	for (n = 0; n < 2; n++) { -		// -		if (n) offset1 = grid1->width-1; -		else offset1 = 0; -		if (R_MergedHeightPoints(grid1, offset1)) -			continue; -		for (k = grid1->height-1; k > 1; k -= 2) { -			for (m = 0; m < 2; m++) { - -				if ( grid2->width >= MAX_GRID_SIZE ) -					break; -				if (m) offset2 = (grid2->height-1) * grid2->width; -				else offset2 = 0; -				for ( l = 0; l < grid2->width-1; l++) { -				// -					v1 = grid1->verts[grid1->width * k + offset1].xyz; -					v2 = grid2->verts[l + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; - -					v1 = grid1->verts[grid1->width * (k - 2) + offset1].xyz; -					v2 = grid2->verts[l + 1 + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; -					// -					v1 = grid2->verts[l + offset2].xyz; -					v2 = grid2->verts[(l + 1) + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) < .01 && -							fabs(v1[1] - v2[1]) < .01 && -							fabs(v1[2] - v2[2]) < .01) -						continue; -					// -					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); -					// insert column into grid2 right after after column l -					if (m) row = grid2->height-1; -					else row = 0; -					grid2 = R_GridInsertColumn( grid2, l+1, row, -										grid1->verts[grid1->width * (k - 1) + offset1].xyz, grid1->heightLodError[k+1]); -					grid2->lodStitched = qfalse; -					s_worldData.surfaces[grid2num].data = (void *) grid2; -					return qtrue; -				} -			} -			for (m = 0; m < 2; m++) { - -				if (grid2->height >= MAX_GRID_SIZE) -					break; -				if (m) offset2 = grid2->width-1; -				else offset2 = 0; -				for ( l = 0; l < grid2->height-1; l++) { -				// -					v1 = grid1->verts[grid1->width * k + offset1].xyz; -					v2 = grid2->verts[grid2->width * l + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; - -					v1 = grid1->verts[grid1->width * (k - 2) + offset1].xyz; -					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) > .1) -						continue; -					if ( fabs(v1[1] - v2[1]) > .1) -						continue; -					if ( fabs(v1[2] - v2[2]) > .1) -						continue; -					// -					v1 = grid2->verts[grid2->width * l + offset2].xyz; -					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; -					if ( fabs(v1[0] - v2[0]) < .01 && -							fabs(v1[1] - v2[1]) < .01 && -							fabs(v1[2] - v2[2]) < .01) -						continue; -					// -					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); -					// insert row into grid2 right after after row l -					if (m) column = grid2->width-1; -					else column = 0; -					grid2 = R_GridInsertRow( grid2, l+1, column, -										grid1->verts[grid1->width * (k - 1) + offset1].xyz, grid1->heightLodError[k+1]); -					grid2->lodStitched = qfalse; -					s_worldData.surfaces[grid2num].data = (void *) grid2; -					return qtrue; -				} -			} -		} -	} -	return qfalse; -} - -/* -=============== -R_TryStitchPatch - -This function will try to stitch patches in the same LoD group together for the highest LoD. - -Only single missing vertice cracks will be fixed. - -Vertices will be joined at the patch side a crack is first found, at the other side -of the patch (on the same row or column) the vertices will not be joined and cracks -might still appear at that side. -=============== -*/ -int R_TryStitchingPatch( int grid1num ) { -	int j, numstitches; -	srfGridMesh_t *grid1, *grid2; - -	numstitches = 0; -	grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data; -	for ( j = 0; j < s_worldData.numsurfaces; j++ ) { -		// -		grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data; -		// if this surface is not a grid -		if ( grid2->surfaceType != SF_GRID ) continue; -		// grids in the same LOD group should have the exact same lod radius -		if ( grid1->lodRadius != grid2->lodRadius ) continue; -		// grids in the same LOD group should have the exact same lod origin -		if ( grid1->lodOrigin[0] != grid2->lodOrigin[0] ) continue; -		if ( grid1->lodOrigin[1] != grid2->lodOrigin[1] ) continue; -		if ( grid1->lodOrigin[2] != grid2->lodOrigin[2] ) continue; -		// -		while (R_StitchPatches(grid1num, j)) -		{ -			numstitches++; -		} -	} -	return numstitches; -} - -/* -=============== -R_StitchAllPatches -=============== -*/ -void R_StitchAllPatches( void ) { -	int i, stitched, numstitches; -	srfGridMesh_t *grid1; - -	numstitches = 0; -	do -	{ -		stitched = qfalse; -		for ( i = 0; i < s_worldData.numsurfaces; i++ ) { -			// -			grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data; -			// if this surface is not a grid -			if ( grid1->surfaceType != SF_GRID ) -				continue; -			// -			if ( grid1->lodStitched ) -				continue; -			// -			grid1->lodStitched = qtrue; -			stitched = qtrue; -			// -			numstitches += R_TryStitchingPatch( i ); -		} -	} -	while (stitched); -	ri.Printf( PRINT_ALL, "stitched %d LoD cracks\n", numstitches ); -} - -/* -=============== -R_MovePatchSurfacesToHunk -=============== -*/ -void R_MovePatchSurfacesToHunk(void) { -	int i, size; -	srfGridMesh_t *grid, *hunkgrid; - -	for ( i = 0; i < s_worldData.numsurfaces; i++ ) { -		// -		grid = (srfGridMesh_t *) s_worldData.surfaces[i].data; -		// if this surface is not a grid -		if ( grid->surfaceType != SF_GRID ) -			continue; -		// -		size = (grid->width * grid->height - 1) * sizeof( drawVert_t ) + sizeof( *grid ); -		hunkgrid = ri.Hunk_Alloc( size, h_low ); -		Com_Memcpy(hunkgrid, grid, size); - -		hunkgrid->widthLodError = ri.Hunk_Alloc( grid->width * 4, h_low ); -		Com_Memcpy( hunkgrid->widthLodError, grid->widthLodError, grid->width * 4 ); - -		hunkgrid->heightLodError = ri.Hunk_Alloc( grid->height * 4, h_low ); -		Com_Memcpy( grid->heightLodError, grid->heightLodError, grid->height * 4 ); - -		R_FreeSurfaceGridMesh( grid ); - -		s_worldData.surfaces[i].data = (void *) hunkgrid; -	} -} - -/* -=============== -R_LoadSurfaces -=============== -*/ -static	void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) { -	dsurface_t	*in; -	msurface_t	*out; -	drawVert_t	*dv; -	int			*indexes; -	int			count; -	int			numFaces, numMeshes, numTriSurfs, numFlares; -	int			i; - -	numFaces = 0; -	numMeshes = 0; -	numTriSurfs = 0; -	numFlares = 0; - -	in = (void *)(fileBase + surfs->fileofs); -	if (surfs->filelen % sizeof(*in)) -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); -	count = surfs->filelen / sizeof(*in); - -	dv = (void *)(fileBase + verts->fileofs); -	if (verts->filelen % sizeof(*dv)) -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - -	indexes = (void *)(fileBase + indexLump->fileofs); -	if ( indexLump->filelen % sizeof(*indexes)) -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - -	out = ri.Hunk_Alloc ( count * sizeof(*out), h_low );	 - -	s_worldData.surfaces = out; -	s_worldData.numsurfaces = count; - -	for ( i = 0 ; i < count ; i++, in++, out++ ) { -		switch ( LittleLong( in->surfaceType ) ) { -		case MST_PATCH: -			ParseMesh ( in, dv, out ); -			numMeshes++; -			break; -		case MST_TRIANGLE_SOUP: -			ParseTriSurf( in, dv, out, indexes ); -			numTriSurfs++; -			break; -		case MST_PLANAR: -			ParseFace( in, dv, out, indexes ); -			numFaces++; -			break; -		case MST_FLARE: -			ParseFlare( in, dv, out, indexes ); -			numFlares++; -			break; -		default: -			ri.Error( ERR_DROP, "Bad surfaceType" ); -		} -	} - -#ifdef PATCH_STITCHING -	R_StitchAllPatches(); -#endif - -	R_FixSharedVertexLodError(); - -#ifdef PATCH_STITCHING -	R_MovePatchSurfacesToHunk(); -#endif - -	ri.Printf( PRINT_ALL, "...loaded %d faces, %i meshes, %i trisurfs, %i flares\n",  -		numFaces, numMeshes, numTriSurfs, numFlares ); -} - - - -/* -================= -R_LoadSubmodels -================= -*/ -static	void R_LoadSubmodels( lump_t *l ) { -	dmodel_t	*in; -	bmodel_t	*out; -	int			i, j, count; - -	in = (void *)(fileBase + l->fileofs); -	if (l->filelen % sizeof(*in)) -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); -	count = l->filelen / sizeof(*in); - -	s_worldData.bmodels = out = ri.Hunk_Alloc( count * sizeof(*out), h_low ); - -	for ( i=0 ; i<count ; i++, in++, out++ ) { -		model_t *model; - -		model = R_AllocModel(); - -		assert( model != NULL );			// this should never happen - -		model->type = MOD_BRUSH; -		model->bmodel = out; -		Com_sprintf( model->name, sizeof( model->name ), "*%d", i ); - -		for (j=0 ; j<3 ; j++) { -			out->bounds[0][j] = LittleFloat (in->mins[j]); -			out->bounds[1][j] = LittleFloat (in->maxs[j]); -		} - -		out->firstSurface = s_worldData.surfaces + LittleLong( in->firstSurface ); -		out->numSurfaces = LittleLong( in->numSurfaces ); -	} -} - - - -//================================================================== - -/* -================= -R_SetParent -================= -*/ -static	void R_SetParent (mnode_t *node, mnode_t *parent) -{ -	node->parent = parent; -	if (node->contents != -1) -		return; -	R_SetParent (node->children[0], node); -	R_SetParent (node->children[1], node); -} - -/* -================= -R_LoadNodesAndLeafs -================= -*/ -static	void R_LoadNodesAndLeafs (lump_t *nodeLump, lump_t *leafLump) { -	int			i, j, p; -	dnode_t		*in; -	dleaf_t		*inLeaf; -	mnode_t 	*out; -	int			numNodes, numLeafs; - -	in = (void *)(fileBase + nodeLump->fileofs); -	if (nodeLump->filelen % sizeof(dnode_t) || -		leafLump->filelen % sizeof(dleaf_t) ) { -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); -	} -	numNodes = nodeLump->filelen / sizeof(dnode_t); -	numLeafs = leafLump->filelen / sizeof(dleaf_t); - -	out = ri.Hunk_Alloc ( (numNodes + numLeafs) * sizeof(*out), h_low);	 - -	s_worldData.nodes = out; -	s_worldData.numnodes = numNodes + numLeafs; -	s_worldData.numDecisionNodes = numNodes; - -	// load nodes -	for ( i=0 ; i<numNodes; i++, in++, out++) -	{ -		for (j=0 ; j<3 ; j++) -		{ -			out->mins[j] = LittleLong (in->mins[j]); -			out->maxs[j] = LittleLong (in->maxs[j]); -		} -	 -		p = LittleLong(in->planeNum); -		out->plane = s_worldData.planes + p; - -		out->contents = CONTENTS_NODE;	// differentiate from leafs - -		for (j=0 ; j<2 ; j++) -		{ -			p = LittleLong (in->children[j]); -			if (p >= 0) -				out->children[j] = s_worldData.nodes + p; -			else -				out->children[j] = s_worldData.nodes + numNodes + (-1 - p); -		} -	} -	 -	// load leafs -	inLeaf = (void *)(fileBase + leafLump->fileofs); -	for ( i=0 ; i<numLeafs ; i++, inLeaf++, out++) -	{ -		for (j=0 ; j<3 ; j++) -		{ -			out->mins[j] = LittleLong (inLeaf->mins[j]); -			out->maxs[j] = LittleLong (inLeaf->maxs[j]); -		} - -		out->cluster = LittleLong(inLeaf->cluster); -		out->area = LittleLong(inLeaf->area); - -		if ( out->cluster >= s_worldData.numClusters ) { -			s_worldData.numClusters = out->cluster + 1; -		} - -		out->firstmarksurface = s_worldData.marksurfaces + -			LittleLong(inLeaf->firstLeafSurface); -		out->nummarksurfaces = LittleLong(inLeaf->numLeafSurfaces); -	}	 - -	// chain decendants -	R_SetParent (s_worldData.nodes, NULL); -} - -//============================================================================= - -/* -================= -R_LoadShaders -================= -*/ -static	void R_LoadShaders( lump_t *l ) {	 -	int		i, count; -	dshader_t	*in, *out; -	 -	in = (void *)(fileBase + l->fileofs); -	if (l->filelen % sizeof(*in)) -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); -	count = l->filelen / sizeof(*in); -	out = ri.Hunk_Alloc ( count*sizeof(*out), h_low ); - -	s_worldData.shaders = out; -	s_worldData.numShaders = count; - -	Com_Memcpy( out, in, count*sizeof(*out) ); - -	for ( i=0 ; i<count ; i++ ) { -		out[i].surfaceFlags = LittleLong( out[i].surfaceFlags ); -		out[i].contentFlags = LittleLong( out[i].contentFlags ); -	} -} - - -/* -================= -R_LoadMarksurfaces -================= -*/ -static	void R_LoadMarksurfaces (lump_t *l) -{	 -	int		i, j, count; -	int		*in; -	msurface_t **out; -	 -	in = (void *)(fileBase + l->fileofs); -	if (l->filelen % sizeof(*in)) -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); -	count = l->filelen / sizeof(*in); -	out = ri.Hunk_Alloc ( count*sizeof(*out), h_low);	 - -	s_worldData.marksurfaces = out; -	s_worldData.nummarksurfaces = count; - -	for ( i=0 ; i<count ; i++) -	{ -		j = LittleLong(in[i]); -		out[i] = s_worldData.surfaces + j; -	} -} - - -/* -================= -R_LoadPlanes -================= -*/ -static	void R_LoadPlanes( lump_t *l ) { -	int			i, j; -	cplane_t	*out; -	dplane_t 	*in; -	int			count; -	int			bits; -	 -	in = (void *)(fileBase + l->fileofs); -	if (l->filelen % sizeof(*in)) -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); -	count = l->filelen / sizeof(*in); -	out = ri.Hunk_Alloc ( count*2*sizeof(*out), h_low);	 -	 -	s_worldData.planes = out; -	s_worldData.numplanes = count; - -	for ( i=0 ; i<count ; i++, in++, out++) { -		bits = 0; -		for (j=0 ; j<3 ; j++) { -			out->normal[j] = LittleFloat (in->normal[j]); -			if (out->normal[j] < 0) { -				bits |= 1<<j; -			} -		} - -		out->dist = LittleFloat (in->dist); -		out->type = PlaneTypeForNormal( out->normal ); -		out->signbits = bits; -	} -} - -/* -================= -R_LoadFogs - -================= -*/ -static	void R_LoadFogs( lump_t *l, lump_t *brushesLump, lump_t *sidesLump ) { -	int			i; -	fog_t		*out; -	dfog_t		*fogs; -	dbrush_t 	*brushes, *brush; -	dbrushside_t	*sides; -	int			count, brushesCount, sidesCount; -	int			sideNum; -	int			planeNum; -	shader_t	*shader; -	float		d; -	int			firstSide; - -	fogs = (void *)(fileBase + l->fileofs); -	if (l->filelen % sizeof(*fogs)) { -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); -	} -	count = l->filelen / sizeof(*fogs); - -	// create fog strucutres for them -	s_worldData.numfogs = count + 1; -	s_worldData.fogs = ri.Hunk_Alloc ( s_worldData.numfogs*sizeof(*out), h_low); -	out = s_worldData.fogs + 1; - -	if ( !count ) { -		return; -	} - -	brushes = (void *)(fileBase + brushesLump->fileofs); -	if (brushesLump->filelen % sizeof(*brushes)) { -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); -	} -	brushesCount = brushesLump->filelen / sizeof(*brushes); - -	sides = (void *)(fileBase + sidesLump->fileofs); -	if (sidesLump->filelen % sizeof(*sides)) { -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); -	} -	sidesCount = sidesLump->filelen / sizeof(*sides); - -	for ( i=0 ; i<count ; i++, fogs++) { -		out->originalBrushNumber = LittleLong( fogs->brushNum ); - -		if ( (unsigned)out->originalBrushNumber >= brushesCount ) { -			ri.Error( ERR_DROP, "fog brushNumber out of range" ); -		} -		brush = brushes + out->originalBrushNumber; - -		firstSide = LittleLong( brush->firstSide ); - -			if ( (unsigned)firstSide > sidesCount - 6 ) { -			ri.Error( ERR_DROP, "fog brush sideNumber out of range" ); -		} - -		// brushes are always sorted with the axial sides first -		sideNum = firstSide + 0; -		planeNum = LittleLong( sides[ sideNum ].planeNum ); -		out->bounds[0][0] = -s_worldData.planes[ planeNum ].dist; - -		sideNum = firstSide + 1; -		planeNum = LittleLong( sides[ sideNum ].planeNum ); -		out->bounds[1][0] = s_worldData.planes[ planeNum ].dist; - -		sideNum = firstSide + 2; -		planeNum = LittleLong( sides[ sideNum ].planeNum ); -		out->bounds[0][1] = -s_worldData.planes[ planeNum ].dist; - -		sideNum = firstSide + 3; -		planeNum = LittleLong( sides[ sideNum ].planeNum ); -		out->bounds[1][1] = s_worldData.planes[ planeNum ].dist; - -		sideNum = firstSide + 4; -		planeNum = LittleLong( sides[ sideNum ].planeNum ); -		out->bounds[0][2] = -s_worldData.planes[ planeNum ].dist; - -		sideNum = firstSide + 5; -		planeNum = LittleLong( sides[ sideNum ].planeNum ); -		out->bounds[1][2] = s_worldData.planes[ planeNum ].dist; - -		// get information from the shader for fog parameters -		shader = R_FindShader( fogs->shader, LIGHTMAP_NONE, qtrue ); - -		out->parms = shader->fogParms; - -		out->colorInt = ColorBytes4 ( shader->fogParms.color[0] * tr.identityLight,  -			                          shader->fogParms.color[1] * tr.identityLight,  -			                          shader->fogParms.color[2] * tr.identityLight, 1.0 ); - -		d = shader->fogParms.depthForOpaque < 1 ? 1 : shader->fogParms.depthForOpaque; -		out->tcScale = 1.0f / ( d * 8 ); - -		// set the gradient vector -		sideNum = LittleLong( fogs->visibleSide ); - -		if ( sideNum == -1 ) { -			out->hasSurface = qfalse; -		} else { -			out->hasSurface = qtrue; -			planeNum = LittleLong( sides[ firstSide + sideNum ].planeNum ); -			VectorSubtract( vec3_origin, s_worldData.planes[ planeNum ].normal, out->surface ); -			out->surface[3] = -s_worldData.planes[ planeNum ].dist; -		} - -		out++; -	} - -} - - -/* -================ -R_LoadLightGrid - -================ -*/ -void R_LoadLightGrid( lump_t *l ) { -	int		i; -	vec3_t	maxs; -	int		numGridPoints; -	world_t	*w; -	float	*wMins, *wMaxs; - -	w = &s_worldData; - -	w->lightGridInverseSize[0] = 1.0f / w->lightGridSize[0]; -	w->lightGridInverseSize[1] = 1.0f / w->lightGridSize[1]; -	w->lightGridInverseSize[2] = 1.0f / w->lightGridSize[2]; - -	wMins = w->bmodels[0].bounds[0]; -	wMaxs = w->bmodels[0].bounds[1]; - -	for ( i = 0 ; i < 3 ; i++ ) { -		w->lightGridOrigin[i] = w->lightGridSize[i] * ceil( wMins[i] / w->lightGridSize[i] ); -		maxs[i] = w->lightGridSize[i] * floor( wMaxs[i] / w->lightGridSize[i] ); -		w->lightGridBounds[i] = (maxs[i] - w->lightGridOrigin[i])/w->lightGridSize[i] + 1; -	} - -	numGridPoints = w->lightGridBounds[0] * w->lightGridBounds[1] * w->lightGridBounds[2]; - -	if ( l->filelen != numGridPoints * 8 ) { -		ri.Printf( PRINT_WARNING, "WARNING: light grid mismatch\n" ); -		w->lightGridData = NULL; -		return; -	} - -	w->lightGridData = ri.Hunk_Alloc( l->filelen, h_low ); -	Com_Memcpy( w->lightGridData, (void *)(fileBase + l->fileofs), l->filelen ); - -	// deal with overbright bits -	for ( i = 0 ; i < numGridPoints ; i++ ) { -		R_ColorShiftLightingBytes( &w->lightGridData[i*8], &w->lightGridData[i*8] ); -		R_ColorShiftLightingBytes( &w->lightGridData[i*8+3], &w->lightGridData[i*8+3] ); -	} -} - -/* -================ -R_LoadEntities -================ -*/ -void R_LoadEntities( lump_t *l ) { -	char *p, *token, *s; -	char keyname[MAX_TOKEN_CHARS]; -	char value[MAX_TOKEN_CHARS]; -	world_t	*w; - -	w = &s_worldData; -	w->lightGridSize[0] = 64; -	w->lightGridSize[1] = 64; -	w->lightGridSize[2] = 128; - -	p = (char *)(fileBase + l->fileofs); - -	// store for reference by the cgame -	w->entityString = ri.Hunk_Alloc( l->filelen + 1, h_low ); -	strcpy( w->entityString, p ); -	w->entityParsePoint = w->entityString; - -	token = COM_ParseExt( &p, qtrue ); -	if (!*token || *token != '{') { -		return; -	} - -	// only parse the world spawn -	while ( 1 ) {	 -		// parse key -		token = COM_ParseExt( &p, qtrue ); - -		if ( !*token || *token == '}' ) { -			break; -		} -		Q_strncpyz(keyname, token, sizeof(keyname)); - -		// parse value -		token = COM_ParseExt( &p, qtrue ); - -		if ( !*token || *token == '}' ) { -			break; -		} -		Q_strncpyz(value, token, sizeof(value)); - -		// check for remapping of shaders for vertex lighting -		s = "vertexremapshader"; -		if (!Q_strncmp(keyname, s, strlen(s)) ) { -			s = strchr(value, ';'); -			if (!s) { -				ri.Printf( PRINT_WARNING, "WARNING: no semi colon in vertexshaderremap '%s'\n", value ); -				break; -			} -			*s++ = 0; -			if (r_vertexLight->integer) { -				R_RemapShader(value, s, "0"); -			} -			continue; -		} -		// check for remapping of shaders -		s = "remapshader"; -		if (!Q_strncmp(keyname, s, strlen(s)) ) { -			s = strchr(value, ';'); -			if (!s) { -				ri.Printf( PRINT_WARNING, "WARNING: no semi colon in shaderremap '%s'\n", value ); -				break; -			} -			*s++ = 0; -			R_RemapShader(value, s, "0"); -			continue; -		} -		// check for a different grid size -		if (!Q_stricmp(keyname, "gridsize")) { -			sscanf(value, "%f %f %f", &w->lightGridSize[0], &w->lightGridSize[1], &w->lightGridSize[2] ); -			continue; -		} -	} -} - -/* -================= -R_GetEntityToken -================= -*/ -qboolean R_GetEntityToken( char *buffer, int size ) { -	const char	*s; - -	s = COM_Parse( &s_worldData.entityParsePoint ); -	Q_strncpyz( buffer, s, size ); -	if ( !s_worldData.entityParsePoint || !s[0] ) { -		s_worldData.entityParsePoint = s_worldData.entityString; -		return qfalse; -	} else { -		return qtrue; -	} -} - -/* -================= -RE_LoadWorldMap - -Called directly from cgame -================= -*/ -void RE_LoadWorldMap( const char *name ) { -	int			i; -	dheader_t	*header; -	byte		*buffer; -	byte		*startMarker; - -	if ( tr.worldMapLoaded ) { -		ri.Error( ERR_DROP, "ERROR: attempted to redundantly load world map\n" ); -	} - -	// set default sun direction to be used if it isn't -	// overridden by a shader -	tr.sunDirection[0] = 0.45f; -	tr.sunDirection[1] = 0.3f; -	tr.sunDirection[2] = 0.9f; - -	VectorNormalize( tr.sunDirection ); - -	tr.worldMapLoaded = qtrue; - -	// load it -    ri.FS_ReadFile( name, (void **)&buffer ); -	if ( !buffer ) { -		ri.Error (ERR_DROP, "RE_LoadWorldMap: %s not found", name); -	} - -	// clear tr.world so if the level fails to load, the next -	// try will not look at the partially loaded version -	tr.world = NULL; - -	Com_Memset( &s_worldData, 0, sizeof( s_worldData ) ); -	Q_strncpyz( s_worldData.name, name, sizeof( s_worldData.name ) ); - -	Q_strncpyz( s_worldData.baseName, COM_SkipPath( s_worldData.name ), sizeof( s_worldData.name ) ); -	COM_StripExtension( s_worldData.baseName, s_worldData.baseName ); - -	startMarker = ri.Hunk_Alloc(0, h_low); -	c_gridVerts = 0; - -	header = (dheader_t *)buffer; -	fileBase = (byte *)header; - -	i = LittleLong (header->version); -	if ( i != BSP_VERSION ) { -		ri.Error (ERR_DROP, "RE_LoadWorldMap: %s has wrong version number (%i should be %i)",  -			name, i, BSP_VERSION); -	} - -	// swap all the lumps -	for (i=0 ; i<sizeof(dheader_t)/4 ; i++) { -		((int *)header)[i] = LittleLong ( ((int *)header)[i]); -	} - -	// load into heap -	R_LoadShaders( &header->lumps[LUMP_SHADERS] ); -	R_LoadLightmaps( &header->lumps[LUMP_LIGHTMAPS] ); -	R_LoadPlanes (&header->lumps[LUMP_PLANES]); -	R_LoadFogs( &header->lumps[LUMP_FOGS], &header->lumps[LUMP_BRUSHES], &header->lumps[LUMP_BRUSHSIDES] ); -	R_LoadSurfaces( &header->lumps[LUMP_SURFACES], &header->lumps[LUMP_DRAWVERTS], &header->lumps[LUMP_DRAWINDEXES] ); -	R_LoadMarksurfaces (&header->lumps[LUMP_LEAFSURFACES]); -	R_LoadNodesAndLeafs (&header->lumps[LUMP_NODES], &header->lumps[LUMP_LEAFS]); -	R_LoadSubmodels (&header->lumps[LUMP_MODELS]); -	R_LoadVisibility( &header->lumps[LUMP_VISIBILITY] ); -	R_LoadEntities( &header->lumps[LUMP_ENTITIES] ); -	R_LoadLightGrid( &header->lumps[LUMP_LIGHTGRID] ); - -	s_worldData.dataSize = (byte *)ri.Hunk_Alloc(0, h_low) - startMarker; - -	// only set tr.world now that we know the entire level has loaded properly -	tr.world = &s_worldData; - -    ri.FS_FreeFile( buffer ); -} - diff --git a/ioq3-r437/src/renderer/tr_cmds.c b/ioq3-r437/src/renderer/tr_cmds.c deleted file mode 100644 index 54f81505..00000000 --- a/ioq3-r437/src/renderer/tr_cmds.c +++ /dev/null @@ -1,447 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -#include "tr_local.h" - -volatile renderCommandList_t	*renderCommandList; - -volatile qboolean	renderThreadActive; - - -/* -===================== -R_PerformanceCounters -===================== -*/ -void R_PerformanceCounters( void ) { -	if ( !r_speeds->integer ) { -		// clear the counters even if we aren't printing -		Com_Memset( &tr.pc, 0, sizeof( tr.pc ) ); -		Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) ); -		return; -	} - -	if (r_speeds->integer == 1) { -		ri.Printf (PRINT_ALL, "%i/%i shaders/surfs %i leafs %i verts %i/%i tris %.2f mtex %.2f dc\n", -			backEnd.pc.c_shaders, backEnd.pc.c_surfaces, tr.pc.c_leafs, backEnd.pc.c_vertexes,  -			backEnd.pc.c_indexes/3, backEnd.pc.c_totalIndexes/3,  -			R_SumOfUsedImages()/(1000000.0f), backEnd.pc.c_overDraw / (float)(glConfig.vidWidth * glConfig.vidHeight) );  -	} else if (r_speeds->integer == 2) { -		ri.Printf (PRINT_ALL, "(patch) %i sin %i sclip  %i sout %i bin %i bclip %i bout\n", -			tr.pc.c_sphere_cull_patch_in, tr.pc.c_sphere_cull_patch_clip, tr.pc.c_sphere_cull_patch_out,  -			tr.pc.c_box_cull_patch_in, tr.pc.c_box_cull_patch_clip, tr.pc.c_box_cull_patch_out ); -		ri.Printf (PRINT_ALL, "(md3) %i sin %i sclip  %i sout %i bin %i bclip %i bout\n", -			tr.pc.c_sphere_cull_md3_in, tr.pc.c_sphere_cull_md3_clip, tr.pc.c_sphere_cull_md3_out,  -			tr.pc.c_box_cull_md3_in, tr.pc.c_box_cull_md3_clip, tr.pc.c_box_cull_md3_out ); -	} else if (r_speeds->integer == 3) { -		ri.Printf (PRINT_ALL, "viewcluster: %i\n", tr.viewCluster ); -	} else if (r_speeds->integer == 4) { -		if ( backEnd.pc.c_dlightVertexes ) { -			ri.Printf (PRINT_ALL, "dlight srf:%i  culled:%i  verts:%i  tris:%i\n",  -				tr.pc.c_dlightSurfaces, tr.pc.c_dlightSurfacesCulled, -				backEnd.pc.c_dlightVertexes, backEnd.pc.c_dlightIndexes / 3 ); -		} -	}  -	else if (r_speeds->integer == 5 ) -	{ -		ri.Printf( PRINT_ALL, "zFar: %.0f\n", tr.viewParms.zFar ); -	} -	else if (r_speeds->integer == 6 ) -	{ -		ri.Printf( PRINT_ALL, "flare adds:%i tests:%i renders:%i\n",  -			backEnd.pc.c_flareAdds, backEnd.pc.c_flareTests, backEnd.pc.c_flareRenders ); -	} - -	Com_Memset( &tr.pc, 0, sizeof( tr.pc ) ); -	Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) ); -} - - -/* -==================== -R_InitCommandBuffers -==================== -*/ -void R_InitCommandBuffers( void ) { -	glConfig.smpActive = qfalse; -	if ( r_smp->integer ) { -		ri.Printf( PRINT_ALL, "Trying SMP acceleration...\n" ); -		if ( GLimp_SpawnRenderThread( RB_RenderThread ) ) { -			ri.Printf( PRINT_ALL, "...succeeded.\n" ); -			glConfig.smpActive = qtrue; -		} else { -			ri.Printf( PRINT_ALL, "...failed.\n" ); -		} -	} -} - -/* -==================== -R_ShutdownCommandBuffers -==================== -*/ -void R_ShutdownCommandBuffers( void ) { -	// kill the rendering thread -	if ( glConfig.smpActive ) { -		GLimp_WakeRenderer( NULL ); -		glConfig.smpActive = qfalse; -	} -} - -/* -==================== -R_IssueRenderCommands -==================== -*/ -int	c_blockedOnRender; -int	c_blockedOnMain; - -void R_IssueRenderCommands( qboolean runPerformanceCounters ) { -	renderCommandList_t	*cmdList; - -	cmdList = &backEndData[tr.smpFrame]->commands; -	assert(cmdList); // bk001205 -	// add an end-of-list command -	*(int *)(cmdList->cmds + cmdList->used) = RC_END_OF_LIST; - -	// clear it out, in case this is a sync and not a buffer flip -	cmdList->used = 0; - -	if ( glConfig.smpActive ) { -		// if the render thread is not idle, wait for it -		if ( renderThreadActive ) { -			c_blockedOnRender++; -			if ( r_showSmp->integer ) { -				ri.Printf( PRINT_ALL, "R" ); -			} -		} else { -			c_blockedOnMain++; -			if ( r_showSmp->integer ) { -				ri.Printf( PRINT_ALL, "." ); -			} -		} - -		// sleep until the renderer has completed -		GLimp_FrontEndSleep(); -	} - -	// at this point, the back end thread is idle, so it is ok -	// to look at it's performance counters -	if ( runPerformanceCounters ) { -		R_PerformanceCounters(); -	} - -	// actually start the commands going -	if ( !r_skipBackEnd->integer ) { -		// let it start on the new batch -		if ( !glConfig.smpActive ) { -			RB_ExecuteRenderCommands( cmdList->cmds ); -		} else { -			GLimp_WakeRenderer( cmdList ); -		} -	} -} - - -/* -==================== -R_SyncRenderThread - -Issue any pending commands and wait for them to complete. -After exiting, the render thread will have completed its work -and will remain idle and the main thread is free to issue -OpenGL calls until R_IssueRenderCommands is called. -==================== -*/ -void R_SyncRenderThread( void ) { -	if ( !tr.registered ) { -		return; -	} -	R_IssueRenderCommands( qfalse ); - -	if ( !glConfig.smpActive ) { -		return; -	} -	GLimp_FrontEndSleep(); -} - -/* -============ -R_GetCommandBuffer - -make sure there is enough command space, waiting on the -render thread if needed. -============ -*/ -void *R_GetCommandBuffer( int bytes ) { -	renderCommandList_t	*cmdList; - -	cmdList = &backEndData[tr.smpFrame]->commands; - -	// always leave room for the end of list command -	if ( cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS ) { -		if ( bytes > MAX_RENDER_COMMANDS - 4 ) { -			ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes ); -		} -		// if we run out of room, just start dropping commands -		return NULL; -	} - -	cmdList->used += bytes; - -	return cmdList->cmds + cmdList->used - bytes; -} - - -/* -============= -R_AddDrawSurfCmd - -============= -*/ -void	R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs ) { -	drawSurfsCommand_t	*cmd; - -	cmd = R_GetCommandBuffer( sizeof( *cmd ) ); -	if ( !cmd ) { -		return; -	} -	cmd->commandId = RC_DRAW_SURFS; - -	cmd->drawSurfs = drawSurfs; -	cmd->numDrawSurfs = numDrawSurfs; - -	cmd->refdef = tr.refdef; -	cmd->viewParms = tr.viewParms; -} - - -/* -============= -RE_SetColor - -Passing NULL will set the color to white -============= -*/ -void	RE_SetColor( const float *rgba ) { -	setColorCommand_t	*cmd; - -  if ( !tr.registered ) { -    return; -  } -	cmd = R_GetCommandBuffer( sizeof( *cmd ) ); -	if ( !cmd ) { -		return; -	} -	cmd->commandId = RC_SET_COLOR; -	if ( !rgba ) { -		static float colorWhite[4] = { 1, 1, 1, 1 }; - -		rgba = colorWhite; -	} - -	cmd->color[0] = rgba[0]; -	cmd->color[1] = rgba[1]; -	cmd->color[2] = rgba[2]; -	cmd->color[3] = rgba[3]; -} - - -/* -============= -RE_StretchPic -============= -*/ -void RE_StretchPic ( float x, float y, float w, float h,  -					  float s1, float t1, float s2, float t2, qhandle_t hShader ) { -	stretchPicCommand_t	*cmd; - -  if (!tr.registered) { -    return; -  } -	cmd = R_GetCommandBuffer( sizeof( *cmd ) ); -	if ( !cmd ) { -		return; -	} -	cmd->commandId = RC_STRETCH_PIC; -	cmd->shader = R_GetShaderByHandle( hShader ); -	cmd->x = x; -	cmd->y = y; -	cmd->w = w; -	cmd->h = h; -	cmd->s1 = s1; -	cmd->t1 = t1; -	cmd->s2 = s2; -	cmd->t2 = t2; -} - - -/* -==================== -RE_BeginFrame - -If running in stereo, RE_BeginFrame will be called twice -for each RE_EndFrame -==================== -*/ -void RE_BeginFrame( stereoFrame_t stereoFrame ) { -	drawBufferCommand_t	*cmd; - -	if ( !tr.registered ) { -		return; -	} -	glState.finishCalled = qfalse; - -	tr.frameCount++; -	tr.frameSceneNum = 0; - -	// -	// do overdraw measurement -	// -	if ( r_measureOverdraw->integer ) -	{ -		if ( glConfig.stencilBits < 4 ) -		{ -			ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits ); -			ri.Cvar_Set( "r_measureOverdraw", "0" ); -			r_measureOverdraw->modified = qfalse; -		} -		else if ( r_shadows->integer == 2 ) -		{ -			ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" ); -			ri.Cvar_Set( "r_measureOverdraw", "0" ); -			r_measureOverdraw->modified = qfalse; -		} -		else -		{ -			R_SyncRenderThread(); -			qglEnable( GL_STENCIL_TEST ); -			qglStencilMask( ~0U ); -			qglClearStencil( 0U ); -			qglStencilFunc( GL_ALWAYS, 0U, ~0U ); -			qglStencilOp( GL_KEEP, GL_INCR, GL_INCR ); -		} -		r_measureOverdraw->modified = qfalse; -	} -	else -	{ -		// this is only reached if it was on and is now off -		if ( r_measureOverdraw->modified ) { -			R_SyncRenderThread(); -			qglDisable( GL_STENCIL_TEST ); -		} -		r_measureOverdraw->modified = qfalse; -	} - -	// -	// texturemode stuff -	// -	if ( r_textureMode->modified ) { -		R_SyncRenderThread(); -		GL_TextureMode( r_textureMode->string ); -		r_textureMode->modified = qfalse; -	} - -	// -	// gamma stuff -	// -	if ( r_gamma->modified ) { -		r_gamma->modified = qfalse; - -		R_SyncRenderThread(); -		R_SetColorMappings(); -	} - -    // check for errors -    if ( !r_ignoreGLErrors->integer ) { -        int	err; - -		R_SyncRenderThread(); -        if ( ( err = qglGetError() ) != GL_NO_ERROR ) { -            ri.Error( ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!\n", err ); -        } -    } - -	// -	// draw buffer stuff -	// -	cmd = R_GetCommandBuffer( sizeof( *cmd ) ); -	if ( !cmd ) { -		return; -	} -	cmd->commandId = RC_DRAW_BUFFER; - -	if ( glConfig.stereoEnabled ) { -		if ( stereoFrame == STEREO_LEFT ) { -			cmd->buffer = (int)GL_BACK_LEFT; -		} else if ( stereoFrame == STEREO_RIGHT ) { -			cmd->buffer = (int)GL_BACK_RIGHT; -		} else { -			ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); -		} -	} else { -		if ( stereoFrame != STEREO_CENTER ) { -			ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); -		} -		if ( !Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) ) { -			cmd->buffer = (int)GL_FRONT; -		} else { -			cmd->buffer = (int)GL_BACK; -		} -	} -} - - -/* -============= -RE_EndFrame - -Returns the number of msec spent in the back end -============= -*/ -void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) { -	swapBuffersCommand_t	*cmd; - -	if ( !tr.registered ) { -		return; -	} -	cmd = R_GetCommandBuffer( sizeof( *cmd ) ); -	if ( !cmd ) { -		return; -	} -	cmd->commandId = RC_SWAP_BUFFERS; - -	R_IssueRenderCommands( qtrue ); - -	// use the other buffers next frame, because another CPU -	// may still be rendering into the current ones -	R_ToggleSmpFrame(); - -	if ( frontEndMsec ) { -		*frontEndMsec = tr.frontEndMsec; -	} -	tr.frontEndMsec = 0; -	if ( backEndMsec ) { -		*backEndMsec = backEnd.pc.msec; -	} -	backEnd.pc.msec = 0; -} - diff --git a/ioq3-r437/src/renderer/tr_curve.c b/ioq3-r437/src/renderer/tr_curve.c deleted file mode 100644 index 7eb1b4c5..00000000 --- a/ioq3-r437/src/renderer/tr_curve.c +++ /dev/null @@ -1,626 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ - -#include "tr_local.h" - -/* - -This file does all of the processing necessary to turn a raw grid of points -read from the map file into a srfGridMesh_t ready for rendering. - -The level of detail solution is direction independent, based only on subdivided -distance from the true curve. - -Only a single entry point: - -srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, -								drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) { - -*/ - - -/* -============ -LerpDrawVert -============ -*/ -static void LerpDrawVert( drawVert_t *a, drawVert_t *b, drawVert_t *out ) { -	out->xyz[0] = 0.5f * (a->xyz[0] + b->xyz[0]); -	out->xyz[1] = 0.5f * (a->xyz[1] + b->xyz[1]); -	out->xyz[2] = 0.5f * (a->xyz[2] + b->xyz[2]); - -	out->st[0] = 0.5f * (a->st[0] + b->st[0]); -	out->st[1] = 0.5f * (a->st[1] + b->st[1]); - -	out->lightmap[0] = 0.5f * (a->lightmap[0] + b->lightmap[0]); -	out->lightmap[1] = 0.5f * (a->lightmap[1] + b->lightmap[1]); - -	out->color[0] = (a->color[0] + b->color[0]) >> 1; -	out->color[1] = (a->color[1] + b->color[1]) >> 1; -	out->color[2] = (a->color[2] + b->color[2]) >> 1; -	out->color[3] = (a->color[3] + b->color[3]) >> 1; -} - -/* -============ -Transpose -============ -*/ -static void Transpose( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) { -	int		i, j; -	drawVert_t	temp; - -	if ( width > height ) { -		for ( i = 0 ; i < height ; i++ ) { -			for ( j = i + 1 ; j < width ; j++ ) { -				if ( j < height ) { -					// swap the value -					temp = ctrl[j][i]; -					ctrl[j][i] = ctrl[i][j]; -					ctrl[i][j] = temp; -				} else { -					// just copy -					ctrl[j][i] = ctrl[i][j]; -				} -			} -		} -	} else { -		for ( i = 0 ; i < width ; i++ ) { -			for ( j = i + 1 ; j < height ; j++ ) { -				if ( j < width ) { -					// swap the value -					temp = ctrl[i][j]; -					ctrl[i][j] = ctrl[j][i]; -					ctrl[j][i] = temp; -				} else { -					// just copy -					ctrl[i][j] = ctrl[j][i]; -				} -			} -		} -	} - -} - - -/* -================= -MakeMeshNormals - -Handles all the complicated wrapping and degenerate cases -================= -*/ -static void MakeMeshNormals( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) { -	int		i, j, k, dist; -	vec3_t	normal; -	vec3_t	sum; -	int		count = 0; -	vec3_t	base; -	vec3_t	delta; -	int		x, y; -	drawVert_t	*dv; -	vec3_t		around[8], temp; -	qboolean	good[8]; -	qboolean	wrapWidth, wrapHeight; -	float		len; -static	int	neighbors[8][2] = { -	{0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1} -	}; - -	wrapWidth = qfalse; -	for ( i = 0 ; i < height ; i++ ) { -		VectorSubtract( ctrl[i][0].xyz, ctrl[i][width-1].xyz, delta ); -		len = VectorLengthSquared( delta ); -		if ( len > 1.0 ) { -			break; -		} -	} -	if ( i == height ) { -		wrapWidth = qtrue; -	} - -	wrapHeight = qfalse; -	for ( i = 0 ; i < width ; i++ ) { -		VectorSubtract( ctrl[0][i].xyz, ctrl[height-1][i].xyz, delta ); -		len = VectorLengthSquared( delta ); -		if ( len > 1.0 ) { -			break; -		} -	} -	if ( i == width) { -		wrapHeight = qtrue; -	} - - -	for ( i = 0 ; i < width ; i++ ) { -		for ( j = 0 ; j < height ; j++ ) { -			count = 0; -			dv = &ctrl[j][i]; -			VectorCopy( dv->xyz, base ); -			for ( k = 0 ; k < 8 ; k++ ) { -				VectorClear( around[k] ); -				good[k] = qfalse; - -				for ( dist = 1 ; dist <= 3 ; dist++ ) { -					x = i + neighbors[k][0] * dist; -					y = j + neighbors[k][1] * dist; -					if ( wrapWidth ) { -						if ( x < 0 ) { -							x = width - 1 + x; -						} else if ( x >= width ) { -							x = 1 + x - width; -						} -					} -					if ( wrapHeight ) { -						if ( y < 0 ) { -							y = height - 1 + y; -						} else if ( y >= height ) { -							y = 1 + y - height; -						} -					} - -					if ( x < 0 || x >= width || y < 0 || y >= height ) { -						break;					// edge of patch -					} -					VectorSubtract( ctrl[y][x].xyz, base, temp ); -					if ( VectorNormalize2( temp, temp ) == 0 ) { -						continue;				// degenerate edge, get more dist -					} else { -						good[k] = qtrue; -						VectorCopy( temp, around[k] ); -						break;					// good edge -					} -				} -			} - -			VectorClear( sum ); -			for ( k = 0 ; k < 8 ; k++ ) { -				if ( !good[k] || !good[(k+1)&7] ) { -					continue;	// didn't get two points -				} -				CrossProduct( around[(k+1)&7], around[k], normal ); -				if ( VectorNormalize2( normal, normal ) == 0 ) { -					continue; -				} -				VectorAdd( normal, sum, sum ); -				count++; -			} -			if ( count == 0 ) { -//printf("bad normal\n"); -				count = 1; -			} -			VectorNormalize2( sum, dv->normal ); -		} -	} -} - - -/* -============ -InvertCtrl -============ -*/ -static void InvertCtrl( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) { -	int		i, j; -	drawVert_t	temp; - -	for ( i = 0 ; i < height ; i++ ) { -		for ( j = 0 ; j < width/2 ; j++ ) { -			temp = ctrl[i][j]; -			ctrl[i][j] = ctrl[i][width-1-j]; -			ctrl[i][width-1-j] = temp; -		} -	} -} - - -/* -================= -InvertErrorTable -================= -*/ -static void InvertErrorTable( float errorTable[2][MAX_GRID_SIZE], int width, int height ) { -	int		i; -	float	copy[2][MAX_GRID_SIZE]; - -	Com_Memcpy( copy, errorTable, sizeof( copy ) ); - -	for ( i = 0 ; i < width ; i++ ) { -		errorTable[1][i] = copy[0][i];	//[width-1-i]; -	} - -	for ( i = 0 ; i < height ; i++ ) { -		errorTable[0][i] = copy[1][height-1-i]; -	} - -} - -/* -================== -PutPointsOnCurve -================== -*/ -static void PutPointsOnCurve( drawVert_t	ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],  -							 int width, int height ) { -	int			i, j; -	drawVert_t	prev, next; - -	for ( i = 0 ; i < width ; i++ ) { -		for ( j = 1 ; j < height ; j += 2 ) { -			LerpDrawVert( &ctrl[j][i], &ctrl[j+1][i], &prev ); -			LerpDrawVert( &ctrl[j][i], &ctrl[j-1][i], &next ); -			LerpDrawVert( &prev, &next, &ctrl[j][i] ); -		} -	} - - -	for ( j = 0 ; j < height ; j++ ) { -		for ( i = 1 ; i < width ; i += 2 ) { -			LerpDrawVert( &ctrl[j][i], &ctrl[j][i+1], &prev ); -			LerpDrawVert( &ctrl[j][i], &ctrl[j][i-1], &next ); -			LerpDrawVert( &prev, &next, &ctrl[j][i] ); -		} -	} -} - -/* -================= -R_CreateSurfaceGridMesh -================= -*/ -srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height, -								drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE] ) { -	int i, j, size; -	drawVert_t	*vert; -	vec3_t		tmpVec; -	srfGridMesh_t *grid; - -	// copy the results out to a grid -	size = (width * height - 1) * sizeof( drawVert_t ) + sizeof( *grid ); - -#ifdef PATCH_STITCHING -	grid = /*ri.Hunk_Alloc*/ ri.Malloc( size ); -	Com_Memset(grid, 0, size); - -	grid->widthLodError = /*ri.Hunk_Alloc*/ ri.Malloc( width * 4 ); -	Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 ); - -	grid->heightLodError = /*ri.Hunk_Alloc*/ ri.Malloc( height * 4 ); -	Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 ); -#else -	grid = ri.Hunk_Alloc( size ); -	Com_Memset(grid, 0, size); - -	grid->widthLodError = ri.Hunk_Alloc( width * 4 ); -	Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 ); - -	grid->heightLodError = ri.Hunk_Alloc( height * 4 ); -	Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 ); -#endif - -	grid->width = width; -	grid->height = height; -	grid->surfaceType = SF_GRID; -	ClearBounds( grid->meshBounds[0], grid->meshBounds[1] ); -	for ( i = 0 ; i < width ; i++ ) { -		for ( j = 0 ; j < height ; j++ ) { -			vert = &grid->verts[j*width+i]; -			*vert = ctrl[j][i]; -			AddPointToBounds( vert->xyz, grid->meshBounds[0], grid->meshBounds[1] ); -		} -	} - -	// compute local origin and bounds -	VectorAdd( grid->meshBounds[0], grid->meshBounds[1], grid->localOrigin ); -	VectorScale( grid->localOrigin, 0.5f, grid->localOrigin ); -	VectorSubtract( grid->meshBounds[0], grid->localOrigin, tmpVec ); -	grid->meshRadius = VectorLength( tmpVec ); - -	VectorCopy( grid->localOrigin, grid->lodOrigin ); -	grid->lodRadius = grid->meshRadius; -	// -	return grid; -} - -/* -================= -R_FreeSurfaceGridMesh -================= -*/ -void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) { -	ri.Free(grid->widthLodError); -	ri.Free(grid->heightLodError); -	ri.Free(grid); -} - -/* -================= -R_SubdividePatchToGrid -================= -*/ -srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, -								drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) { -	int			i, j, k, l; -	drawVert_t_cleared( prev ); -	drawVert_t_cleared( next ); -	drawVert_t_cleared( mid ); -	float		len, maxLen; -	int			dir; -	int			t; -	drawVert_t	ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; -	float		errorTable[2][MAX_GRID_SIZE]; - -	for ( i = 0 ; i < width ; i++ ) { -		for ( j = 0 ; j < height ; j++ ) { -			ctrl[j][i] = points[j*width+i]; -		} -	} - -	for ( dir = 0 ; dir < 2 ; dir++ ) { - -		for ( j = 0 ; j < MAX_GRID_SIZE ; j++ ) { -			errorTable[dir][j] = 0; -		} - -		// horizontal subdivisions -		for ( j = 0 ; j + 2 < width ; j += 2 ) { -			// check subdivided midpoints against control points - -			// FIXME: also check midpoints of adjacent patches against the control points -			// this would basically stitch all patches in the same LOD group together. - -			maxLen = 0; -			for ( i = 0 ; i < height ; i++ ) { -				vec3_t		midxyz; -				vec3_t		midxyz2; -				vec3_t		dir; -				vec3_t		projected; -				float		d; - -				// calculate the point on the curve -				for ( l = 0 ; l < 3 ; l++ ) { -					midxyz[l] = (ctrl[i][j].xyz[l] + ctrl[i][j+1].xyz[l] * 2 -							+ ctrl[i][j+2].xyz[l] ) * 0.25f; -				} - -				// see how far off the line it is -				// using dist-from-line will not account for internal -				// texture warping, but it gives a lot less polygons than -				// dist-from-midpoint -				VectorSubtract( midxyz, ctrl[i][j].xyz, midxyz ); -				VectorSubtract( ctrl[i][j+2].xyz, ctrl[i][j].xyz, dir ); -				VectorNormalize( dir ); - -				d = DotProduct( midxyz, dir ); -				VectorScale( dir, d, projected ); -				VectorSubtract( midxyz, projected, midxyz2); -				len = VectorLengthSquared( midxyz2 );			// we will do the sqrt later -				if ( len > maxLen ) { -					maxLen = len; -				} -			} - -			maxLen = sqrt(maxLen); - -			// if all the points are on the lines, remove the entire columns -			if ( maxLen < 0.1f ) { -				errorTable[dir][j+1] = 999; -				continue; -			} - -			// see if we want to insert subdivided columns -			if ( width + 2 > MAX_GRID_SIZE ) { -				errorTable[dir][j+1] = 1.0f/maxLen; -				continue;	// can't subdivide any more -			} - -			if ( maxLen <= r_subdivisions->value ) { -				errorTable[dir][j+1] = 1.0f/maxLen; -				continue;	// didn't need subdivision -			} - -			errorTable[dir][j+2] = 1.0f/maxLen; - -			// insert two columns and replace the peak -			width += 2; -			for ( i = 0 ; i < height ; i++ ) { -				LerpDrawVert( &ctrl[i][j], &ctrl[i][j+1], &prev ); -				LerpDrawVert( &ctrl[i][j+1], &ctrl[i][j+2], &next ); -				LerpDrawVert( &prev, &next, &mid ); - -				for ( k = width - 1 ; k > j + 3 ; k-- ) { -					ctrl[i][k] = ctrl[i][k-2]; -				} -				ctrl[i][j + 1] = prev; -				ctrl[i][j + 2] = mid; -				ctrl[i][j + 3] = next; -			} - -			// back up and recheck this set again, it may need more subdivision -			j -= 2; - -		} - -		Transpose( width, height, ctrl ); -		t = width; -		width = height; -		height = t; -	} - - -	// put all the aproximating points on the curve -	PutPointsOnCurve( ctrl, width, height ); - -	// cull out any rows or columns that are colinear -	for ( i = 1 ; i < width-1 ; i++ ) { -		if ( errorTable[0][i] != 999 ) { -			continue; -		} -		for ( j = i+1 ; j < width ; j++ ) { -			for ( k = 0 ; k < height ; k++ ) { -				ctrl[k][j-1] = ctrl[k][j]; -			} -			errorTable[0][j-1] = errorTable[0][j]; -		} -		width--; -	} - -	for ( i = 1 ; i < height-1 ; i++ ) { -		if ( errorTable[1][i] != 999 ) { -			continue; -		} -		for ( j = i+1 ; j < height ; j++ ) { -			for ( k = 0 ; k < width ; k++ ) { -				ctrl[j-1][k] = ctrl[j][k]; -			} -			errorTable[1][j-1] = errorTable[1][j]; -		} -		height--; -	} - -#if 1 -	// flip for longest tristrips as an optimization -	// the results should be visually identical with or -	// without this step -	if ( height > width ) { -		Transpose( width, height, ctrl ); -		InvertErrorTable( errorTable, width, height ); -		t = width; -		width = height; -		height = t; -		InvertCtrl( width, height, ctrl ); -	} -#endif - -	// calculate normals -	MakeMeshNormals( width, height, ctrl ); - -	return R_CreateSurfaceGridMesh( width, height, ctrl, errorTable ); -} - -/* -=============== -R_GridInsertColumn -=============== -*/ -srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) { -	int i, j; -	int width, height, oldwidth; -	drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; -	float errorTable[2][MAX_GRID_SIZE]; -	float lodRadius; -	vec3_t lodOrigin; - -	oldwidth = 0; -	width = grid->width + 1; -	if (width > MAX_GRID_SIZE) -		return NULL; -	height = grid->height; -	for (i = 0; i < width; i++) { -		if (i == column) { -			//insert new column -			for (j = 0; j < grid->height; j++) { -				LerpDrawVert( &grid->verts[j * grid->width + i-1], &grid->verts[j * grid->width + i], &ctrl[j][i] ); -				if (j == row) -					VectorCopy(point, ctrl[j][i].xyz); -			} -			errorTable[0][i] = loderror; -			continue; -		} -		errorTable[0][i] = grid->widthLodError[oldwidth]; -		for (j = 0; j < grid->height; j++) { -			ctrl[j][i] = grid->verts[j * grid->width + oldwidth]; -		} -		oldwidth++; -	} -	for (j = 0; j < grid->height; j++) { -		errorTable[1][j] = grid->heightLodError[j]; -	} -	// put all the aproximating points on the curve -	//PutPointsOnCurve( ctrl, width, height ); -	// calculate normals -	MakeMeshNormals( width, height, ctrl ); - -	VectorCopy(grid->lodOrigin, lodOrigin); -	lodRadius = grid->lodRadius; -	// free the old grid -	R_FreeSurfaceGridMesh(grid); -	// create a new grid -	grid = R_CreateSurfaceGridMesh( width, height, ctrl, errorTable ); -	grid->lodRadius = lodRadius; -	VectorCopy(lodOrigin, grid->lodOrigin); -	return grid; -} - -/* -=============== -R_GridInsertRow -=============== -*/ -srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) { -	int i, j; -	int width, height, oldheight; -	drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; -	float errorTable[2][MAX_GRID_SIZE]; -	float lodRadius; -	vec3_t lodOrigin; - -	oldheight = 0; -	width = grid->width; -	height = grid->height + 1; -	if (height > MAX_GRID_SIZE) -		return NULL; -	for (i = 0; i < height; i++) { -		if (i == row) { -			//insert new row -			for (j = 0; j < grid->width; j++) { -				LerpDrawVert( &grid->verts[(i-1) * grid->width + j], &grid->verts[i * grid->width + j], &ctrl[i][j] ); -				if (j == column) -					VectorCopy(point, ctrl[i][j].xyz); -			} -			errorTable[1][i] = loderror; -			continue; -		} -		errorTable[1][i] = grid->heightLodError[oldheight]; -		for (j = 0; j < grid->width; j++) { -			ctrl[i][j] = grid->verts[oldheight * grid->width + j]; -		} -		oldheight++; -	} -	for (j = 0; j < grid->width; j++) { -		errorTable[0][j] = grid->widthLodError[j]; -	} -	// put all the aproximating points on the curve -	//PutPointsOnCurve( ctrl, width, height ); -	// calculate normals -	MakeMeshNormals( width, height, ctrl ); - -	VectorCopy(grid->lodOrigin, lodOrigin); -	lodRadius = grid->lodRadius; -	// free the old grid -	R_FreeSurfaceGridMesh(grid); -	// create a new grid -	grid = R_CreateSurfaceGridMesh( width, height, ctrl, errorTable ); -	grid->lodRadius = lodRadius; -	VectorCopy(lodOrigin, grid->lodOrigin); -	return grid; -} diff --git a/ioq3-r437/src/renderer/tr_flares.c b/ioq3-r437/src/renderer/tr_flares.c deleted file mode 100644 index 65fb2ba7..00000000 --- a/ioq3-r437/src/renderer/tr_flares.c +++ /dev/null @@ -1,447 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_flares.c - -#include "tr_local.h" - -/* -============================================================================= - -LIGHT FLARES - -A light flare is an effect that takes place inside the eye when bright light -sources are visible.  The size of the flare reletive to the screen is nearly -constant, irrespective of distance, but the intensity should be proportional to the -projected area of the light source. - -A surface that has been flagged as having a light flare will calculate the depth -buffer value that it's midpoint should have when the surface is added. - -After all opaque surfaces have been rendered, the depth buffer is read back for -each flare in view.  If the point has not been obscured by a closer surface, the -flare should be drawn. - -Surfaces that have a repeated texture should never be flagged as flaring, because -there will only be a single flare added at the midpoint of the polygon. - -To prevent abrupt popping, the intensity of the flare is interpolated up and -down as it changes visibility.  This involves scene to scene state, unlike almost -all other aspects of the renderer, and is complicated by the fact that a single -frame may have multiple scenes. - -RB_RenderFlares() will be called once per view (twice in a mirrored scene, potentially -up to five or more times in a frame with 3D status bar icons). - -============================================================================= -*/ - - -// flare states maintain visibility over multiple frames for fading -// layers: view, mirror, menu -typedef struct flare_s { -	struct		flare_s	*next;		// for active chain - -	int			addedFrame; - -	qboolean	inPortal;				// true if in a portal view of the scene -	int			frameSceneNum; -	void		*surface; -	int			fogNum; - -	int			fadeTime; - -	qboolean	visible;			// state of last test -	float		drawIntensity;		// may be non 0 even if !visible due to fading - -	int			windowX, windowY; -	float		eyeZ; - -	vec3_t		color; -} flare_t; - -#define		MAX_FLARES		128 - -flare_t		r_flareStructs[MAX_FLARES]; -flare_t		*r_activeFlares, *r_inactiveFlares; - -/* -================== -R_ClearFlares -================== -*/ -void R_ClearFlares( void ) { -	int		i; - -	Com_Memset( r_flareStructs, 0, sizeof( r_flareStructs ) ); -	r_activeFlares = NULL; -	r_inactiveFlares = NULL; - -	for ( i = 0 ; i < MAX_FLARES ; i++ ) { -		r_flareStructs[i].next = r_inactiveFlares; -		r_inactiveFlares = &r_flareStructs[i]; -	} -} - - -/* -================== -RB_AddFlare - -This is called at surface tesselation time -================== -*/ -void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t normal ) { -	int				i; -	flare_t			*f, *oldest; -	vec3_t			local; -	float			d; -	vec4_t			eye, clip, normalized, window; - -	backEnd.pc.c_flareAdds++; - -	// if the point is off the screen, don't bother adding it -	// calculate screen coordinates and depth -	R_TransformModelToClip( point, backEnd.or.modelMatrix,  -		backEnd.viewParms.projectionMatrix, eye, clip ); - -	// check to see if the point is completely off screen -	for ( i = 0 ; i < 3 ; i++ ) { -		if ( clip[i] >= clip[3] || clip[i] <= -clip[3] ) { -			return; -		} -	} - -	R_TransformClipToWindow( clip, &backEnd.viewParms, normalized, window ); - -	if ( window[0] < 0 || window[0] >= backEnd.viewParms.viewportWidth -		|| window[1] < 0 || window[1] >= backEnd.viewParms.viewportHeight ) { -		return;	// shouldn't happen, since we check the clip[] above, except for FP rounding -	} - -	// see if a flare with a matching surface, scene, and view exists -	oldest = r_flareStructs; -	for ( f = r_activeFlares ; f ; f = f->next ) { -		if ( f->surface == surface && f->frameSceneNum == backEnd.viewParms.frameSceneNum -			&& f->inPortal == backEnd.viewParms.isPortal ) { -			break; -		} -	} - -	// allocate a new one -	if (!f ) { -		if ( !r_inactiveFlares ) { -			// the list is completely full -			return; -		} -		f = r_inactiveFlares; -		r_inactiveFlares = r_inactiveFlares->next; -		f->next = r_activeFlares; -		r_activeFlares = f; - -		f->surface = surface; -		f->frameSceneNum = backEnd.viewParms.frameSceneNum; -		f->inPortal = backEnd.viewParms.isPortal; -		f->addedFrame = -1; -	} - -	if ( f->addedFrame != backEnd.viewParms.frameCount - 1 ) { -		f->visible = qfalse; -		f->fadeTime = backEnd.refdef.time - 2000; -	} - -	f->addedFrame = backEnd.viewParms.frameCount; -	f->fogNum = fogNum; - -	VectorCopy( color, f->color ); - -	// fade the intensity of the flare down as the -	// light surface turns away from the viewer -	if ( normal ) { -		VectorSubtract( backEnd.viewParms.or.origin, point, local ); -		VectorNormalizeFast( local ); -		d = DotProduct( local, normal ); -		VectorScale( f->color, d, f->color );  -	} - -	// save info needed to test -	f->windowX = backEnd.viewParms.viewportX + window[0]; -	f->windowY = backEnd.viewParms.viewportY + window[1]; - -	f->eyeZ = eye[2]; -} - -/* -================== -RB_AddDlightFlares -================== -*/ -void RB_AddDlightFlares( void ) { -	dlight_t		*l; -	int				i, j, k; -	fog_t			*fog; - -	if ( !r_flares->integer ) { -		return; -	} - -	l = backEnd.refdef.dlights; -	fog = tr.world->fogs; -	for (i=0 ; i<backEnd.refdef.num_dlights ; i++, l++) { - -		// find which fog volume the light is in  -		for ( j = 1 ; j < tr.world->numfogs ; j++ ) { -			fog = &tr.world->fogs[j]; -			for ( k = 0 ; k < 3 ; k++ ) { -				if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) { -					break; -				} -			} -			if ( k == 3 ) { -				break; -			} -		} -		if ( j == tr.world->numfogs ) { -			j = 0; -		} - -		RB_AddFlare( (void *)l, j, l->origin, l->color, NULL ); -	} -} - -/* -=============================================================================== - -FLARE BACK END - -=============================================================================== -*/ - -/* -================== -RB_TestFlare -================== -*/ -void RB_TestFlare( flare_t *f ) { -	float			depth; -	qboolean		visible; -	float			fade; -	float			screenZ; - -	backEnd.pc.c_flareTests++; - -	// doing a readpixels is as good as doing a glFinish(), so -	// don't bother with another sync -	glState.finishCalled = qfalse; - -	// read back the z buffer contents -	qglReadPixels( f->windowX, f->windowY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth ); - -	screenZ = backEnd.viewParms.projectionMatrix[14] /  -		( ( 2*depth - 1 ) * backEnd.viewParms.projectionMatrix[11] - backEnd.viewParms.projectionMatrix[10] ); - -	visible = ( -f->eyeZ - -screenZ ) < 24; - -	if ( visible ) { -		if ( !f->visible ) { -			f->visible = qtrue; -			f->fadeTime = backEnd.refdef.time - 1; -		} -		fade = ( ( backEnd.refdef.time - f->fadeTime ) /1000.0f ) * r_flareFade->value; -	} else { -		if ( f->visible ) { -			f->visible = qfalse; -			f->fadeTime = backEnd.refdef.time - 1; -		} -		fade = 1.0f - ( ( backEnd.refdef.time - f->fadeTime ) / 1000.0f ) * r_flareFade->value; -	} - -	if ( fade < 0 ) { -		fade = 0; -	} -	if ( fade > 1 ) { -		fade = 1; -	} - -	f->drawIntensity = fade; -} - - -/* -================== -RB_RenderFlare -================== -*/ -void RB_RenderFlare( flare_t *f ) { -	float			size; -	vec3_t			color; -	int				iColor[3]; - -	backEnd.pc.c_flareRenders++; - -	VectorScale( f->color, f->drawIntensity*tr.identityLight, color ); -	iColor[0] = color[0] * 255; -	iColor[1] = color[1] * 255; -	iColor[2] = color[2] * 255; - -	size = backEnd.viewParms.viewportWidth * ( r_flareSize->value/640.0f + 8 / -f->eyeZ ); - -	RB_BeginSurface( tr.flareShader, f->fogNum ); - -	// FIXME: use quadstamp? -	tess.xyz[tess.numVertexes][0] = f->windowX - size; -	tess.xyz[tess.numVertexes][1] = f->windowY - size; -	tess.texCoords[tess.numVertexes][0][0] = 0; -	tess.texCoords[tess.numVertexes][0][1] = 0; -	tess.vertexColors[tess.numVertexes][0] = iColor[0]; -	tess.vertexColors[tess.numVertexes][1] = iColor[1]; -	tess.vertexColors[tess.numVertexes][2] = iColor[2]; -	tess.vertexColors[tess.numVertexes][3] = 255; -	tess.numVertexes++; - -	tess.xyz[tess.numVertexes][0] = f->windowX - size; -	tess.xyz[tess.numVertexes][1] = f->windowY + size; -	tess.texCoords[tess.numVertexes][0][0] = 0; -	tess.texCoords[tess.numVertexes][0][1] = 1; -	tess.vertexColors[tess.numVertexes][0] = iColor[0]; -	tess.vertexColors[tess.numVertexes][1] = iColor[1]; -	tess.vertexColors[tess.numVertexes][2] = iColor[2]; -	tess.vertexColors[tess.numVertexes][3] = 255; -	tess.numVertexes++; - -	tess.xyz[tess.numVertexes][0] = f->windowX + size; -	tess.xyz[tess.numVertexes][1] = f->windowY + size; -	tess.texCoords[tess.numVertexes][0][0] = 1; -	tess.texCoords[tess.numVertexes][0][1] = 1; -	tess.vertexColors[tess.numVertexes][0] = iColor[0]; -	tess.vertexColors[tess.numVertexes][1] = iColor[1]; -	tess.vertexColors[tess.numVertexes][2] = iColor[2]; -	tess.vertexColors[tess.numVertexes][3] = 255; -	tess.numVertexes++; - -	tess.xyz[tess.numVertexes][0] = f->windowX + size; -	tess.xyz[tess.numVertexes][1] = f->windowY - size; -	tess.texCoords[tess.numVertexes][0][0] = 1; -	tess.texCoords[tess.numVertexes][0][1] = 0; -	tess.vertexColors[tess.numVertexes][0] = iColor[0]; -	tess.vertexColors[tess.numVertexes][1] = iColor[1]; -	tess.vertexColors[tess.numVertexes][2] = iColor[2]; -	tess.vertexColors[tess.numVertexes][3] = 255; -	tess.numVertexes++; - -	tess.indexes[tess.numIndexes++] = 0; -	tess.indexes[tess.numIndexes++] = 1; -	tess.indexes[tess.numIndexes++] = 2; -	tess.indexes[tess.numIndexes++] = 0; -	tess.indexes[tess.numIndexes++] = 2; -	tess.indexes[tess.numIndexes++] = 3; - -	RB_EndSurface(); -} - -/* -================== -RB_RenderFlares - -Because flares are simulating an occular effect, they should be drawn after -everything (all views) in the entire frame has been drawn. - -Because of the way portals use the depth buffer to mark off areas, the -needed information would be lost after each view, so we are forced to draw -flares after each view. - -The resulting artifact is that flares in mirrors or portals don't dim properly -when occluded by something in the main view, and portal flares that should -extend past the portal edge will be overwritten. -================== -*/ -void RB_RenderFlares (void) { -	flare_t		*f; -	flare_t		**prev; -	qboolean	draw; - -	if ( !r_flares->integer ) { -		return; -	} - -//	RB_AddDlightFlares(); - -	// perform z buffer readback on each flare in this view -	draw = qfalse; -	prev = &r_activeFlares; -	while ( ( f = *prev ) != NULL ) { -		// throw out any flares that weren't added last frame -		if ( f->addedFrame < backEnd.viewParms.frameCount - 1 ) { -			*prev = f->next; -			f->next = r_inactiveFlares; -			r_inactiveFlares = f; -			continue; -		} - -		// don't draw any here that aren't from this scene / portal -		f->drawIntensity = 0; -		if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum -			&& f->inPortal == backEnd.viewParms.isPortal ) { -			RB_TestFlare( f ); -			if ( f->drawIntensity ) { -				draw = qtrue; -			} else { -				// this flare has completely faded out, so remove it from the chain -				*prev = f->next; -				f->next = r_inactiveFlares; -				r_inactiveFlares = f; -				continue; -			} -		} - -		prev = &f->next; -	} - -	if ( !draw ) { -		return;		// none visible -	} - -	if ( backEnd.viewParms.isPortal ) { -		qglDisable (GL_CLIP_PLANE0); -	} - -	qglPushMatrix(); -    qglLoadIdentity(); -	qglMatrixMode( GL_PROJECTION ); -	qglPushMatrix(); -    qglLoadIdentity(); -	qglOrtho( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, -			  backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, -			  -99999, 99999 ); - -	for ( f = r_activeFlares ; f ; f = f->next ) { -		if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum -			&& f->inPortal == backEnd.viewParms.isPortal -			&& f->drawIntensity ) { -			RB_RenderFlare( f ); -		} -	} - -	qglPopMatrix(); -	qglMatrixMode( GL_MODELVIEW ); -	qglPopMatrix(); -} - diff --git a/ioq3-r437/src/renderer/tr_font.c b/ioq3-r437/src/renderer/tr_font.c deleted file mode 100644 index 383108fb..00000000 --- a/ioq3-r437/src/renderer/tr_font.c +++ /dev/null @@ -1,549 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_font.c -//  -// -// The font system uses FreeType 2.x to render TrueType fonts for use within the game. -// As of this writing ( Nov, 2000 ) Team Arena uses these fonts for all of the ui and  -// about 90% of the cgame presentation. A few areas of the CGAME were left uses the old  -// fonts since the code is shared with standard Q3A. -// -// If you include this font rendering code in a commercial product you MUST include the -// following somewhere with your product, see www.freetype.org for specifics or changes. -// The Freetype code also uses some hinting techniques that MIGHT infringe on patents  -// held by apple so be aware of that also. -// -// As of Q3A 1.25+ and Team Arena, we are shipping the game with the font rendering code -// disabled. This removes any potential patent issues and it keeps us from having to  -// distribute an actual TrueTrype font which is 1. expensive to do and 2. seems to require -// an act of god to accomplish.  -// -// What we did was pre-render the fonts using FreeType ( which is why we leave the FreeType -// credit in the credits ) and then saved off the glyph data and then hand touched up the  -// font bitmaps so they scale a bit better in GL. -// -// There are limitations in the way fonts are saved and reloaded in that it is based on  -// point size and not name. So if you pre-render Helvetica in 18 point and Impact in 18 point -// you will end up with a single 18 point data file and image set. Typically you will want to  -// choose 3 sizes to best approximate the scaling you will be doing in the ui scripting system -//  -// In the UI Scripting code, a scale of 1.0 is equal to a 48 point font. In Team Arena, we -// use three or four scales, most of them exactly equaling the specific rendered size. We  -// rendered three sizes in Team Arena, 12, 16, and 20.  -// -// To generate new font data you need to go through the following steps. -// 1. delete the fontImage_x_xx.tga files and fontImage_xx.dat files from the fonts path. -// 2. in a ui script, specificy a font, smallFont, and bigFont keyword with font name and  -//    point size. the original TrueType fonts must exist in fonts at this point. -// 3. run the game, you should see things normally. -// 4. Exit the game and there will be three dat files and at least three tga files. The  -//    tga's are in 256x256 pages so if it takes three images to render a 24 point font you  -//    will end up with fontImage_0_24.tga through fontImage_2_24.tga -// 5. You will need to flip the tga's in Photoshop as the tga output code writes them upside -//    down. -// 6. In future runs of the game, the system looks for these images and data files when a s -//    specific point sized font is rendered and loads them for use.  -// 7. Because of the original beta nature of the FreeType code you will probably want to hand -//    touch the font bitmaps. -//  -// Currently a define in the project turns on or off the FreeType code which is currently  -// defined out. To pre-render new fonts you need enable the define ( BUILD_FREETYPE ) and  -// uncheck the exclude from build check box in the FreeType2 area of the Renderer project.  - - -#include "tr_local.h" -#include "../qcommon/qcommon.h" - -#ifdef BUILD_FREETYPE -#include <ft2build.h> -#include <freetype/fterrors.h> -#include <freetype/ftsystem.h> -#include <freetype/ftimage.h> -#include <freetype/freetype.h> -#include <freetype/ftoutln.h> - -#define _FLOOR(x)  ((x) & -64) -#define _CEIL(x)   (((x)+63) & -64) -#define _TRUNC(x)  ((x) >> 6) - -FT_Library ftLibrary = NULL;   -#endif - -#define MAX_FONTS 6 -static int registeredFontCount = 0; -static fontInfo_t registeredFont[MAX_FONTS]; - -#ifdef BUILD_FREETYPE -void R_GetGlyphInfo(FT_GlyphSlot glyph, int *left, int *right, int *width, int *top, int *bottom, int *height, int *pitch) { - -  *left  = _FLOOR( glyph->metrics.horiBearingX ); -  *right = _CEIL( glyph->metrics.horiBearingX + glyph->metrics.width ); -  *width = _TRUNC(*right - *left); -     -  *top    = _CEIL( glyph->metrics.horiBearingY ); -  *bottom = _FLOOR( glyph->metrics.horiBearingY - glyph->metrics.height ); -  *height = _TRUNC( *top - *bottom ); -  *pitch  = ( qtrue ? (*width+3) & -4 : (*width+7) >> 3 ); -} - - -FT_Bitmap *R_RenderGlyph(FT_GlyphSlot glyph, glyphInfo_t* glyphOut) { - -  FT_Bitmap  *bit2; -  int left, right, width, top, bottom, height, pitch, size; - -  R_GetGlyphInfo(glyph, &left, &right, &width, &top, &bottom, &height, &pitch); - -  if ( glyph->format == ft_glyph_format_outline ) { -    size   = pitch*height;  - -    bit2 = Z_Malloc(sizeof(FT_Bitmap)); - -    bit2->width      = width; -    bit2->rows       = height; -    bit2->pitch      = pitch; -    bit2->pixel_mode = ft_pixel_mode_grays; -    //bit2->pixel_mode = ft_pixel_mode_mono; -    bit2->buffer     = Z_Malloc(pitch*height); -    bit2->num_grays = 256; - -    Com_Memset( bit2->buffer, 0, size ); - -    FT_Outline_Translate( &glyph->outline, -left, -bottom ); - -    FT_Outline_Get_Bitmap( ftLibrary, &glyph->outline, bit2 ); - -    glyphOut->height = height; -    glyphOut->pitch = pitch; -    glyphOut->top = (glyph->metrics.horiBearingY >> 6) + 1; -    glyphOut->bottom = bottom; -     -    return bit2; -  } -  else { -    ri.Printf(PRINT_ALL, "Non-outline fonts are not supported\n"); -  } -  return NULL; -} - -void WriteTGA (char *filename, byte *data, int width, int height) { -	byte	*buffer; -	int		i, c; - -	buffer = Z_Malloc(width*height*4 + 18); -	Com_Memset (buffer, 0, 18); -	buffer[2] = 2;		// uncompressed type -	buffer[12] = width&255; -	buffer[13] = width>>8; -	buffer[14] = height&255; -	buffer[15] = height>>8; -	buffer[16] = 32;	// pixel size - -	// swap rgb to bgr -	c = 18 + width * height * 4; -	for (i=18 ; i<c ; i+=4) -	{ -		buffer[i] = data[i-18+2];		// blue -		buffer[i+1] = data[i-18+1];		// green -		buffer[i+2] = data[i-18+0];		// red -		buffer[i+3] = data[i-18+3];		// alpha -	} - -	ri.FS_WriteFile(filename, buffer, c); - -	//f = fopen (filename, "wb"); -	//fwrite (buffer, 1, c, f); -	//fclose (f); - -	Z_Free (buffer); -} - -static glyphInfo_t *RE_ConstructGlyphInfo(unsigned char *imageOut, int *xOut, int *yOut, int *maxHeight, FT_Face face, const unsigned char c, qboolean calcHeight) { -  int i; -  static glyphInfo_t glyph; -  unsigned char *src, *dst; -  float scaled_width, scaled_height; -  FT_Bitmap *bitmap = NULL; - -  Com_Memset(&glyph, 0, sizeof(glyphInfo_t)); -  // make sure everything is here -  if (face != NULL) { -    FT_Load_Glyph(face, FT_Get_Char_Index( face, c), FT_LOAD_DEFAULT ); -    bitmap = R_RenderGlyph(face->glyph, &glyph); -    if (bitmap) { -      glyph.xSkip = (face->glyph->metrics.horiAdvance >> 6) + 1; -    } else { -      return &glyph; -    } - -    if (glyph.height > *maxHeight) { -      *maxHeight = glyph.height; -    } - -    if (calcHeight) { -      Z_Free(bitmap->buffer); -      Z_Free(bitmap); -      return &glyph; -    } - -/* -    // need to convert to power of 2 sizes so we do not get  -    // any scaling from the gl upload -  	for (scaled_width = 1 ; scaled_width < glyph.pitch ; scaled_width<<=1) -	  	; -  	for (scaled_height = 1 ; scaled_height < glyph.height ; scaled_height<<=1) -	  	; -*/ - -    scaled_width = glyph.pitch; -    scaled_height = glyph.height; - -    // we need to make sure we fit -    if (*xOut + scaled_width + 1 >= 255) { -      if (*yOut + *maxHeight + 1 >= 255) { -        *yOut = -1; -        *xOut = -1; -        Z_Free(bitmap->buffer); -        Z_Free(bitmap); -        return &glyph; -      } else { -        *xOut = 0; -        *yOut += *maxHeight + 1; -      } -    } else if (*yOut + *maxHeight + 1 >= 255) { -      *yOut = -1; -      *xOut = -1; -      Z_Free(bitmap->buffer); -      Z_Free(bitmap); -      return &glyph; -    } - - -    src = bitmap->buffer; -    dst = imageOut + (*yOut * 256) + *xOut; - -		if (bitmap->pixel_mode == ft_pixel_mode_mono) { -			for (i = 0; i < glyph.height; i++) { -				int j; -				unsigned char *_src = src; -				unsigned char *_dst = dst; -				unsigned char mask = 0x80; -				unsigned char val = *_src; -				for (j = 0; j < glyph.pitch; j++) { -					if (mask == 0x80) { -						val = *_src++; -					} -					if (val & mask) { -						*_dst = 0xff; -					} -					mask >>= 1; -         -					if ( mask == 0 ) { -						mask = 0x80; -					} -					_dst++; -				} - -				src += glyph.pitch; -				dst += 256; - -			} -		} else { -	    for (i = 0; i < glyph.height; i++) { -		    Com_Memcpy(dst, src, glyph.pitch); -			  src += glyph.pitch; -				dst += 256; -	    } -		} - -    // we now have an 8 bit per pixel grey scale bitmap  -    // that is width wide and pf->ftSize->metrics.y_ppem tall - -    glyph.imageHeight = scaled_height; -    glyph.imageWidth = scaled_width; -    glyph.s = (float)*xOut / 256; -    glyph.t = (float)*yOut / 256; -    glyph.s2 = glyph.s + (float)scaled_width / 256; -    glyph.t2 = glyph.t + (float)scaled_height / 256; - -    *xOut += scaled_width + 1; -  } - -  Z_Free(bitmap->buffer); -  Z_Free(bitmap); - -  return &glyph; -} -#endif - -static int fdOffset; -static byte	*fdFile; - -int readInt( void ) { -	int i = fdFile[fdOffset]+(fdFile[fdOffset+1]<<8)+(fdFile[fdOffset+2]<<16)+(fdFile[fdOffset+3]<<24); -	fdOffset += 4; -	return i; -} - -typedef union { -	byte	fred[4]; -	float	ffred; -} poor; - -float readFloat( void ) { -	poor	me; -#if defined Q3_BIG_ENDIAN -	me.fred[0] = fdFile[fdOffset+3]; -	me.fred[1] = fdFile[fdOffset+2]; -	me.fred[2] = fdFile[fdOffset+1]; -	me.fred[3] = fdFile[fdOffset+0]; -#elif defined Q3_LITTLE_ENDIAN -	me.fred[0] = fdFile[fdOffset+0]; -	me.fred[1] = fdFile[fdOffset+1]; -	me.fred[2] = fdFile[fdOffset+2]; -	me.fred[3] = fdFile[fdOffset+3]; -#endif -	fdOffset += 4; -	return me.ffred; -} - -void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) { -#ifdef BUILD_FREETYPE -  FT_Face face; -  int j, k, xOut, yOut, lastStart, imageNumber; -  int scaledSize, newSize, maxHeight, left, satLevels; -  unsigned char *out, *imageBuff; -  glyphInfo_t *glyph; -  image_t *image; -  qhandle_t h; -	float max; -#endif -  void *faceData; -	int i, len; -  char name[1024]; -	float dpi = 72;											// -	float glyphScale =  72.0f / dpi; 		// change the scale to be relative to 1 based on 72 dpi ( so dpi of 144 means a scale of .5 ) - - -  if (!fontName) { -    ri.Printf(PRINT_ALL, "RE_RegisterFont: called with empty name\n"); -    return; -  } - -	if (pointSize <= 0) { -		pointSize = 12; -	} -	// we also need to adjust the scale based on point size relative to 48 points as the ui scaling is based on a 48 point font -	glyphScale *= 48.0f / pointSize; - -	// make sure the render thread is stopped -	R_SyncRenderThread(); - -  if (registeredFontCount >= MAX_FONTS) { -    ri.Printf(PRINT_ALL, "RE_RegisterFont: Too many fonts registered already.\n"); -    return; -  } - -	Com_sprintf(name, sizeof(name), "fonts/fontImage_%i.dat",pointSize); -	for (i = 0; i < registeredFontCount; i++) { -		if (Q_stricmp(name, registeredFont[i].name) == 0) { -			Com_Memcpy(font, ®isteredFont[i], sizeof(fontInfo_t)); -			return; -		} -	} - -	len = ri.FS_ReadFile(name, NULL); -	if (len == sizeof(fontInfo_t)) { -		ri.FS_ReadFile(name, &faceData); -		fdOffset = 0; -		fdFile = faceData; -		for(i=0; i<GLYPHS_PER_FONT; i++) { -			font->glyphs[i].height		= readInt(); -			font->glyphs[i].top			= readInt(); -			font->glyphs[i].bottom		= readInt(); -			font->glyphs[i].pitch		= readInt(); -			font->glyphs[i].xSkip		= readInt(); -			font->glyphs[i].imageWidth	= readInt(); -			font->glyphs[i].imageHeight = readInt(); -			font->glyphs[i].s			= readFloat(); -			font->glyphs[i].t			= readFloat(); -			font->glyphs[i].s2			= readFloat(); -			font->glyphs[i].t2			= readFloat(); -			font->glyphs[i].glyph		= readInt(); -			Com_Memcpy(font->glyphs[i].shaderName, &fdFile[fdOffset], 32); -			fdOffset += 32; -		} -		font->glyphScale = readFloat(); -		Com_Memcpy(font->name, &fdFile[fdOffset], MAX_QPATH); - -//		Com_Memcpy(font, faceData, sizeof(fontInfo_t)); -		Q_strncpyz(font->name, name, sizeof(font->name)); -		for (i = GLYPH_START; i < GLYPH_END; i++) { -			font->glyphs[i].glyph = RE_RegisterShaderNoMip(font->glyphs[i].shaderName); -		} -	  Com_Memcpy(®isteredFont[registeredFontCount++], font, sizeof(fontInfo_t)); -		return; -	} - -#ifndef BUILD_FREETYPE -    ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType code not available\n"); -#else -  if (ftLibrary == NULL) { -    ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType not initialized.\n"); -    return; -  } - -  len = ri.FS_ReadFile(fontName, &faceData); -  if (len <= 0) { -    ri.Printf(PRINT_ALL, "RE_RegisterFont: Unable to read font file\n"); -    return; -  } - -  // allocate on the stack first in case we fail -  if (FT_New_Memory_Face( ftLibrary, faceData, len, 0, &face )) { -    ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType2, unable to allocate new face.\n"); -    return; -  } - - -  if (FT_Set_Char_Size( face, pointSize << 6, pointSize << 6, dpi, dpi)) { -    ri.Printf(PRINT_ALL, "RE_RegisterFont: FreeType2, Unable to set face char size.\n"); -    return; -  } - -  //*font = ®isteredFonts[registeredFontCount++]; - -  // make a 256x256 image buffer, once it is full, register it, clean it and keep going  -  // until all glyphs are rendered - -  out = Z_Malloc(1024*1024); -  if (out == NULL) { -    ri.Printf(PRINT_ALL, "RE_RegisterFont: Z_Malloc failure during output image creation.\n"); -    return; -  } -  Com_Memset(out, 0, 1024*1024); - -  maxHeight = 0; - -  for (i = GLYPH_START; i < GLYPH_END; i++) { -    glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qtrue); -  } - -  xOut = 0; -  yOut = 0; -  i = GLYPH_START; -  lastStart = i; -  imageNumber = 0; - -  while ( i <= GLYPH_END ) { - -    glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qfalse); - -    if (xOut == -1 || yOut == -1 || i == GLYPH_END)  { -      // ran out of room -      // we need to create an image from the bitmap, set all the handles in the glyphs to this point -      //  - -      scaledSize = 256*256; -      newSize = scaledSize * 4; -      imageBuff = Z_Malloc(newSize); -      left = 0; -      max = 0; -      satLevels = 255; -      for ( k = 0; k < (scaledSize) ; k++ ) { -        if (max < out[k]) { -          max = out[k]; -        } -      } - -			if (max > 0) { -				max = 255/max; -			} - -      for ( k = 0; k < (scaledSize) ; k++ ) { -        imageBuff[left++] = 255; -        imageBuff[left++] = 255; -        imageBuff[left++] = 255; - -        imageBuff[left++] = ((float)out[k] * max); -      } - -			Com_sprintf (name, sizeof(name), "fonts/fontImage_%i_%i.tga", imageNumber++, pointSize); -			if (r_saveFontData->integer) {  -			  WriteTGA(name, imageBuff, 256, 256); -			} - -    	//Com_sprintf (name, sizeof(name), "fonts/fontImage_%i_%i", imageNumber++, pointSize); -      image = R_CreateImage(name, imageBuff, 256, 256, qfalse, qfalse, GL_CLAMP); -      h = RE_RegisterShaderFromImage(name, LIGHTMAP_2D, image, qfalse); -      for (j = lastStart; j < i; j++) { -        font->glyphs[j].glyph = h; -				Q_strncpyz(font->glyphs[j].shaderName, name, sizeof(font->glyphs[j].shaderName)); -      } -      lastStart = i; -		  Com_Memset(out, 0, 1024*1024); -      xOut = 0; -      yOut = 0; -      Z_Free(imageBuff); -			i++; -    } else { -      Com_Memcpy(&font->glyphs[i], glyph, sizeof(glyphInfo_t)); -      i++; -    } -  } - -	registeredFont[registeredFontCount].glyphScale = glyphScale; -	font->glyphScale = glyphScale; -  Com_Memcpy(®isteredFont[registeredFontCount++], font, sizeof(fontInfo_t)); - -	if (r_saveFontData->integer) {  -		ri.FS_WriteFile(va("fonts/fontImage_%i.dat", pointSize), font, sizeof(fontInfo_t)); -	} - -  Z_Free(out); -   -  ri.FS_FreeFile(faceData); -#endif -} - - - -void R_InitFreeType(void) { -#ifdef BUILD_FREETYPE -  if (FT_Init_FreeType( &ftLibrary )) { -    ri.Printf(PRINT_ALL, "R_InitFreeType: Unable to initialize FreeType.\n"); -  } -#endif -  registeredFontCount = 0; -} - - -void R_DoneFreeType(void) { -#ifdef BUILD_FREETYPE -  if (ftLibrary) { -    FT_Done_FreeType( ftLibrary ); -    ftLibrary = NULL; -  } -#endif -	registeredFontCount = 0; -} - diff --git a/ioq3-r437/src/renderer/tr_image.c b/ioq3-r437/src/renderer/tr_image.c deleted file mode 100644 index 15d6c7ec..00000000 --- a/ioq3-r437/src/renderer/tr_image.c +++ /dev/null @@ -1,2570 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_image.c -#include "tr_local.h" - -/* - * Include file for users of JPEG library. - * You will need to have included system headers that define at least - * the typedefs FILE and size_t before you can include jpeglib.h. - * (stdio.h is sufficient on ANSI-conforming systems.) - * You may also wish to include "jerror.h". - */ - -#define JPEG_INTERNALS -#include "../jpeg-6/jpeglib.h" - - -static void LoadBMP( const char *name, byte **pic, int *width, int *height ); -static void LoadTGA( const char *name, byte **pic, int *width, int *height ); -static void LoadJPG( const char *name, byte **pic, int *width, int *height ); - -static byte			 s_intensitytable[256]; -static unsigned char s_gammatable[256]; - -int		gl_filter_min = GL_LINEAR_MIPMAP_NEAREST; -int		gl_filter_max = GL_LINEAR; - -#define FILE_HASH_SIZE		1024 -static	image_t*		hashTable[FILE_HASH_SIZE]; - -/* -** R_GammaCorrect -*/ -void R_GammaCorrect( byte *buffer, int bufSize ) { -	int i; - -	for ( i = 0; i < bufSize; i++ ) { -		buffer[i] = s_gammatable[buffer[i]]; -	} -} - -typedef struct { -	char *name; -	int	minimize, maximize; -} textureMode_t; - -textureMode_t modes[] = { -	{"GL_NEAREST", GL_NEAREST, GL_NEAREST}, -	{"GL_LINEAR", GL_LINEAR, GL_LINEAR}, -	{"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, -	{"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR}, -	{"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST}, -	{"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} -}; - -/* -================ -return a hash value for the filename -================ -*/ -static long generateHashValue( const char *fname ) { -	int		i; -	long	hash; -	char	letter; - -	hash = 0; -	i = 0; -	while (fname[i] != '\0') { -		letter = tolower(fname[i]); -		if (letter =='.') break;				// don't include extension -		if (letter =='\\') letter = '/';		// damn path names -		hash+=(long)(letter)*(i+119); -		i++; -	} -	hash &= (FILE_HASH_SIZE-1); -	return hash; -} - -/* -=============== -GL_TextureMode -=============== -*/ -void GL_TextureMode( const char *string ) { -	int		i; -	image_t	*glt; - -	for ( i=0 ; i< 6 ; i++ ) { -		if ( !Q_stricmp( modes[i].name, string ) ) { -			break; -		} -	} - -	// hack to prevent trilinear from being set on voodoo, -	// because their driver freaks... -	if ( i == 5 && glConfig.hardwareType == GLHW_3DFX_2D3D ) { -		ri.Printf( PRINT_ALL, "Refusing to set trilinear on a voodoo.\n" ); -		i = 3; -	} - - -	if ( i == 6 ) { -		ri.Printf (PRINT_ALL, "bad filter name\n"); -		return; -	} - -	gl_filter_min = modes[i].minimize; -	gl_filter_max = modes[i].maximize; - -	// change all the existing mipmap texture objects -	for ( i = 0 ; i < tr.numImages ; i++ ) { -		glt = tr.images[ i ]; -		if ( glt->mipmap ) { -			GL_Bind (glt); -			qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); -			qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); -		} -	} -} - -/* -=============== -R_SumOfUsedImages -=============== -*/ -int R_SumOfUsedImages( void ) { -	int	total; -	int i; - -	total = 0; -	for ( i = 0; i < tr.numImages; i++ ) { -		if ( tr.images[i]->frameUsed == tr.frameCount ) { -			total += tr.images[i]->uploadWidth * tr.images[i]->uploadHeight; -		} -	} - -	return total; -} - -/* -=============== -R_ImageList_f -=============== -*/ -void R_ImageList_f( void ) { -	int		i; -	image_t	*image; -	int		texels; -	const char *yesno[] = { -		"no ", "yes" -	}; - -	ri.Printf (PRINT_ALL, "\n      -w-- -h-- -mm- -TMU- -if-- wrap --name-------\n"); -	texels = 0; - -	for ( i = 0 ; i < tr.numImages ; i++ ) { -		image = tr.images[ i ]; - -		texels += image->uploadWidth*image->uploadHeight; -		ri.Printf (PRINT_ALL,  "%4i: %4i %4i  %s   %d   ", -			i, image->uploadWidth, image->uploadHeight, yesno[image->mipmap], image->TMU ); -		switch ( image->internalFormat ) { -		case 1: -			ri.Printf( PRINT_ALL, "I    " ); -			break; -		case 2: -			ri.Printf( PRINT_ALL, "IA   " ); -			break; -		case 3: -			ri.Printf( PRINT_ALL, "RGB  " ); -			break; -		case 4: -			ri.Printf( PRINT_ALL, "RGBA " ); -			break; -		case GL_RGBA8: -			ri.Printf( PRINT_ALL, "RGBA8" ); -			break; -		case GL_RGB8: -			ri.Printf( PRINT_ALL, "RGB8" ); -			break; -		case GL_RGB4_S3TC: -			ri.Printf( PRINT_ALL, "S3TC " ); -			break; -		case GL_RGBA4: -			ri.Printf( PRINT_ALL, "RGBA4" ); -			break; -		case GL_RGB5: -			ri.Printf( PRINT_ALL, "RGB5 " ); -			break; -		default: -			ri.Printf( PRINT_ALL, "???? " ); -		} - -		switch ( image->wrapClampMode ) { -		case GL_REPEAT: -			ri.Printf( PRINT_ALL, "rept " ); -			break; -		case GL_CLAMP: -			ri.Printf( PRINT_ALL, "clmp " ); -			break; -		default: -			ri.Printf( PRINT_ALL, "%4i ", image->wrapClampMode ); -			break; -		} -		 -		ri.Printf( PRINT_ALL, " %s\n", image->imgName ); -	} -	ri.Printf (PRINT_ALL, " ---------\n"); -	ri.Printf (PRINT_ALL, " %i total texels (not including mipmaps)\n", texels); -	ri.Printf (PRINT_ALL, " %i total images\n\n", tr.numImages ); -} - -//======================================================================= - -/* -================ -ResampleTexture - -Used to resample images in a more general than quartering fashion. - -This will only be filtered properly if the resampled size -is greater than half the original size. - -If a larger shrinking is needed, use the mipmap function  -before or after. -================ -*/ -static void ResampleTexture( unsigned *in, int inwidth, int inheight, unsigned *out,   -							int outwidth, int outheight ) { -	int		i, j; -	unsigned	*inrow, *inrow2; -	unsigned	frac, fracstep; -	unsigned	p1[2048], p2[2048]; -	byte		*pix1, *pix2, *pix3, *pix4; - -	if (outwidth>2048) -		ri.Error(ERR_DROP, "ResampleTexture: max width"); -								 -	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; -		} -	} -} - -/* -================ -R_LightScaleTexture - -Scale up the pixel values in a texture to increase the -lighting range -================ -*/ -void R_LightScaleTexture (unsigned *in, int inwidth, int inheight, qboolean only_gamma ) -{ -	if ( only_gamma ) -	{ -		if ( !glConfig.deviceSupportsGamma ) -		{ -			int		i, c; -			byte	*p; - -			p = (byte *)in; - -			c = inwidth*inheight; -			for (i=0 ; i<c ; i++, p+=4) -			{ -				p[0] = s_gammatable[p[0]]; -				p[1] = s_gammatable[p[1]]; -				p[2] = s_gammatable[p[2]]; -			} -		} -	} -	else -	{ -		int		i, c; -		byte	*p; - -		p = (byte *)in; - -		c = inwidth*inheight; - -		if ( glConfig.deviceSupportsGamma ) -		{ -			for (i=0 ; i<c ; i++, p+=4) -			{ -				p[0] = s_intensitytable[p[0]]; -				p[1] = s_intensitytable[p[1]]; -				p[2] = s_intensitytable[p[2]]; -			} -		} -		else -		{ -			for (i=0 ; i<c ; i++, p+=4) -			{ -				p[0] = s_gammatable[s_intensitytable[p[0]]]; -				p[1] = s_gammatable[s_intensitytable[p[1]]]; -				p[2] = s_gammatable[s_intensitytable[p[2]]]; -			} -		} -	} -} - - -/* -================ -R_MipMap2 - -Operates in place, quartering the size of the texture -Proper linear filter -================ -*/ -static void R_MipMap2( unsigned *in, int inWidth, int inHeight ) { -	int			i, j, k; -	byte		*outpix; -	int			inWidthMask, inHeightMask; -	int			total; -	int			outWidth, outHeight; -	unsigned	*temp; - -	outWidth = inWidth >> 1; -	outHeight = inHeight >> 1; -	temp = ri.Hunk_AllocateTempMemory( outWidth * outHeight * 4 ); - -	inWidthMask = inWidth - 1; -	inHeightMask = inHeight - 1; - -	for ( i = 0 ; i < outHeight ; i++ ) { -		for ( j = 0 ; j < outWidth ; j++ ) { -			outpix = (byte *) ( temp + i * outWidth + j ); -			for ( k = 0 ; k < 4 ; k++ ) { -				total =  -					1 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] + -					2 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] + -					2 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] + -					1 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] + - -					2 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] + -					4 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] + -					4 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] + -					2 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] + - -					2 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] + -					4 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] + -					4 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] + -					2 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] + - -					1 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] + -					2 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] + -					2 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] + -					1 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k]; -				outpix[k] = total / 36; -			} -		} -	} - -	Com_Memcpy( in, temp, outWidth * outHeight * 4 ); -	ri.Hunk_FreeTempMemory( temp ); -} - -/* -================ -R_MipMap - -Operates in place, quartering the size of the texture -================ -*/ -static void R_MipMap (byte *in, int width, int height) { -	int		i, j; -	byte	*out; -	int		row; - -	if ( !r_simpleMipMaps->integer ) { -		R_MipMap2( (unsigned *)in, width, height ); -		return; -	} - -	if ( width == 1 && height == 1 ) { -		return; -	} - -	row = width * 4; -	out = in; -	width >>= 1; -	height >>= 1; - -	if ( width == 0 || height == 0 ) { -		width += height;	// get largest -		for (i=0 ; i<width ; i++, out+=4, in+=8 ) { -			out[0] = ( in[0] + in[4] )>>1; -			out[1] = ( in[1] + in[5] )>>1; -			out[2] = ( in[2] + in[6] )>>1; -			out[3] = ( in[3] + in[7] )>>1; -		} -		return; -	} - -	for (i=0 ; i<height ; i++, in+=row) { -		for (j=0 ; j<width ; j++, out+=4, in+=8) { -			out[0] = (in[0] + in[4] + in[row+0] + in[row+4])>>2; -			out[1] = (in[1] + in[5] + in[row+1] + in[row+5])>>2; -			out[2] = (in[2] + in[6] + in[row+2] + in[row+6])>>2; -			out[3] = (in[3] + in[7] + in[row+3] + in[row+7])>>2; -		} -	} -} - - -/* -================== -R_BlendOverTexture - -Apply a color blend over a set of pixels -================== -*/ -static void R_BlendOverTexture( byte *data, int pixelCount, byte blend[4] ) { -	int		i; -	int		inverseAlpha; -	int		premult[3]; - -	inverseAlpha = 255 - blend[3]; -	premult[0] = blend[0] * blend[3]; -	premult[1] = blend[1] * blend[3]; -	premult[2] = blend[2] * blend[3]; - -	for ( i = 0 ; i < pixelCount ; i++, data+=4 ) { -		data[0] = ( data[0] * inverseAlpha + premult[0] ) >> 9; -		data[1] = ( data[1] * inverseAlpha + premult[1] ) >> 9; -		data[2] = ( data[2] * inverseAlpha + premult[2] ) >> 9; -	} -} - -byte	mipBlendColors[16][4] = { -	{0,0,0,0}, -	{255,0,0,128}, -	{0,255,0,128}, -	{0,0,255,128}, -	{255,0,0,128}, -	{0,255,0,128}, -	{0,0,255,128}, -	{255,0,0,128}, -	{0,255,0,128}, -	{0,0,255,128}, -	{255,0,0,128}, -	{0,255,0,128}, -	{0,0,255,128}, -	{255,0,0,128}, -	{0,255,0,128}, -	{0,0,255,128}, -}; - - -/* -=============== -Upload32 - -=============== -*/ -extern qboolean charSet; -static void Upload32( unsigned *data,  -						  int width, int height,  -						  qboolean mipmap,  -						  qboolean picmip,  -							qboolean lightMap, -						  int *format,  -						  int *pUploadWidth, int *pUploadHeight ) -{ -	int			samples; -	unsigned	*scaledBuffer = NULL; -	unsigned	*resampledBuffer = NULL; -	int			scaled_width, scaled_height; -	int			i, c; -	byte		*scan; -	GLenum		internalFormat = GL_RGB; -	float		rMax = 0, gMax = 0, bMax = 0; - -	// -	// convert to exact power of 2 sizes -	// -	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) -		; -	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) -		; -	if ( r_roundImagesDown->integer && scaled_width > width ) -		scaled_width >>= 1; -	if ( r_roundImagesDown->integer && scaled_height > height ) -		scaled_height >>= 1; - -	if ( scaled_width != width || scaled_height != height ) { -		resampledBuffer = ri.Hunk_AllocateTempMemory( scaled_width * scaled_height * 4 ); -		ResampleTexture (data, width, height, resampledBuffer, scaled_width, scaled_height); -		data = resampledBuffer; -		width = scaled_width; -		height = scaled_height; -	} - -	// -	// perform optional picmip operation -	// -	if ( picmip ) { -		scaled_width >>= r_picmip->integer; -		scaled_height >>= r_picmip->integer; -	} - -	// -	// clamp to minimum size -	// -	if (scaled_width < 1) { -		scaled_width = 1; -	} -	if (scaled_height < 1) { -		scaled_height = 1; -	} - -	// -	// clamp to the current upper OpenGL limit -	// scale both axis down equally so we don't have to -	// deal with a half mip resampling -	// -	while ( scaled_width > glConfig.maxTextureSize -		|| scaled_height > glConfig.maxTextureSize ) { -		scaled_width >>= 1; -		scaled_height >>= 1; -	} - -	scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); - -	// -	// scan the texture for each channel's max values -	// and verify if the alpha channel is being used or not -	// -	c = width*height; -	scan = ((byte *)data); -	samples = 3; -	if (!lightMap) { -		for ( i = 0; i < c; i++ ) -		{ -			if ( scan[i*4+0] > rMax ) -			{ -				rMax = scan[i*4+0]; -			} -			if ( scan[i*4+1] > gMax ) -			{ -				gMax = scan[i*4+1]; -			} -			if ( scan[i*4+2] > bMax ) -			{ -				bMax = scan[i*4+2]; -			} -			if ( scan[i*4 + 3] != 255 )  -			{ -				samples = 4; -				break; -			} -		} -		// select proper internal format -		if ( samples == 3 ) -		{ -			if ( glConfig.textureCompression == TC_S3TC ) -			{ -				internalFormat = GL_RGB4_S3TC; -			} -			else if ( r_texturebits->integer == 16 ) -			{ -				internalFormat = GL_RGB5; -			} -			else if ( r_texturebits->integer == 32 ) -			{ -				internalFormat = GL_RGB8; -			} -			else -			{ -				internalFormat = 3; -			} -		} -		else if ( samples == 4 ) -		{ -			if ( r_texturebits->integer == 16 ) -			{ -				internalFormat = GL_RGBA4; -			} -			else if ( r_texturebits->integer == 32 ) -			{ -				internalFormat = GL_RGBA8; -			} -			else -			{ -				internalFormat = 4; -			} -		} -	} else { -		internalFormat = 3; -	} -	// copy or resample data as appropriate for first MIP level -	if ( ( scaled_width == width ) &&  -		( scaled_height == height ) ) { -		if (!mipmap) -		{ -			qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); -			*pUploadWidth = scaled_width; -			*pUploadHeight = scaled_height; -			*format = internalFormat; - -			goto done; -		} -		Com_Memcpy (scaledBuffer, data, width*height*4); -	} -	else -	{ -		// use the normal mip-mapping function to go down from here -		while ( width > scaled_width || height > scaled_height ) { -			R_MipMap( (byte *)data, width, height ); -			width >>= 1; -			height >>= 1; -			if ( width < 1 ) { -				width = 1; -			} -			if ( height < 1 ) { -				height = 1; -			} -		} -		Com_Memcpy( scaledBuffer, data, width * height * 4 ); -	} - -	R_LightScaleTexture (scaledBuffer, scaled_width, scaled_height, !mipmap ); - -	*pUploadWidth = scaled_width; -	*pUploadHeight = scaled_height; -	*format = internalFormat; - -	qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer ); - -	if (mipmap) -	{ -		int		miplevel; - -		miplevel = 0; -		while (scaled_width > 1 || scaled_height > 1) -		{ -			R_MipMap( (byte *)scaledBuffer, 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 ( r_colorMipLevels->integer ) { -				R_BlendOverTexture( (byte *)scaledBuffer, scaled_width * scaled_height, mipBlendColors[miplevel] ); -			} - -			qglTexImage2D (GL_TEXTURE_2D, miplevel, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer ); -		} -	} -done: - -	if (mipmap) -	{ -		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); -		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); -	} -	else -	{ -		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); -		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); -	} - -	GL_CheckErrors(); - -	if ( scaledBuffer != 0 ) -		ri.Hunk_FreeTempMemory( scaledBuffer ); -	if ( resampledBuffer != 0 ) -		ri.Hunk_FreeTempMemory( resampledBuffer ); -} - - -/* -================ -R_CreateImage - -This is the only way any image_t are created -================ -*/ -image_t *R_CreateImage( const char *name, const byte *pic, int width, int height,  -					   qboolean mipmap, qboolean allowPicmip, int glWrapClampMode ) { -	image_t		*image; -	qboolean	isLightmap = qfalse; -	long		hash; - -	if (strlen(name) >= MAX_QPATH ) { -		ri.Error (ERR_DROP, "R_CreateImage: \"%s\" is too long\n", name); -	} -	if ( !strncmp( name, "*lightmap", 9 ) ) { -		isLightmap = qtrue; -	} - -	if ( tr.numImages == MAX_DRAWIMAGES ) { -		ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit\n"); -	} - -	image = tr.images[tr.numImages] = ri.Hunk_Alloc( sizeof( image_t ), h_low ); -	image->texnum = 1024 + tr.numImages; -	tr.numImages++; - -	image->mipmap = mipmap; -	image->allowPicmip = allowPicmip; - -	strcpy (image->imgName, name); - -	image->width = width; -	image->height = height; -	image->wrapClampMode = glWrapClampMode; - -	// lightmaps are always allocated on TMU 1 -	if ( qglActiveTextureARB && isLightmap ) { -		image->TMU = 1; -	} else { -		image->TMU = 0; -	} - -	if ( qglActiveTextureARB ) { -		GL_SelectTexture( image->TMU ); -	} - -	GL_Bind(image); - -	Upload32( (unsigned *)pic, image->width, image->height,  -								image->mipmap, -								allowPicmip, -								isLightmap, -								&image->internalFormat, -								&image->uploadWidth, -								&image->uploadHeight ); - -	qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode ); -	qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode ); - -	qglBindTexture( GL_TEXTURE_2D, 0 ); - -	if ( image->TMU == 1 ) { -		GL_SelectTexture( 0 ); -	} - -	hash = generateHashValue(name); -	image->next = hashTable[hash]; -	hashTable[hash] = image; - -	return image; -} - - -/* -========================================================= - -BMP LOADING - -========================================================= -*/ -typedef struct -{ -	char id[2]; -	unsigned long fileSize; -	unsigned long reserved0; -	unsigned long bitmapDataOffset; -	unsigned long bitmapHeaderSize; -	unsigned long width; -	unsigned long height; -	unsigned short planes; -	unsigned short bitsPerPixel; -	unsigned long compression; -	unsigned long bitmapDataSize; -	unsigned long hRes; -	unsigned long vRes; -	unsigned long colors; -	unsigned long importantColors; -	unsigned char palette[256][4]; -} BMPHeader_t; - -static void LoadBMP( const char *name, byte **pic, int *width, int *height ) -{ -	int		columns, rows; -	unsigned	numPixels; -	byte	*pixbuf; -	int		row, column; -	byte	*buf_p; -	byte	*buffer; -	int		length; -	BMPHeader_t bmpHeader; -	byte		*bmpRGBA; - -	*pic = NULL; - -	// -	// load the file -	// -	length = ri.FS_ReadFile( ( char * ) name, (void **)&buffer); -	if (!buffer) { -		return; -	} - -	buf_p = buffer; - -	bmpHeader.id[0] = *buf_p++; -	bmpHeader.id[1] = *buf_p++; -	bmpHeader.fileSize = LittleLong( * ( long * ) buf_p ); -	buf_p += 4; -	bmpHeader.reserved0 = LittleLong( * ( long * ) buf_p ); -	buf_p += 4; -	bmpHeader.bitmapDataOffset = LittleLong( * ( long * ) buf_p ); -	buf_p += 4; -	bmpHeader.bitmapHeaderSize = LittleLong( * ( long * ) buf_p ); -	buf_p += 4; -	bmpHeader.width = LittleLong( * ( long * ) buf_p ); -	buf_p += 4; -	bmpHeader.height = LittleLong( * ( long * ) buf_p ); -	buf_p += 4; -	bmpHeader.planes = LittleShort( * ( short * ) buf_p ); -	buf_p += 2; -	bmpHeader.bitsPerPixel = LittleShort( * ( short * ) buf_p ); -	buf_p += 2; -	bmpHeader.compression = LittleLong( * ( long * ) buf_p ); -	buf_p += 4; -	bmpHeader.bitmapDataSize = LittleLong( * ( long * ) buf_p ); -	buf_p += 4; -	bmpHeader.hRes = LittleLong( * ( long * ) buf_p ); -	buf_p += 4; -	bmpHeader.vRes = LittleLong( * ( long * ) buf_p ); -	buf_p += 4; -	bmpHeader.colors = LittleLong( * ( long * ) buf_p ); -	buf_p += 4; -	bmpHeader.importantColors = LittleLong( * ( long * ) buf_p ); -	buf_p += 4; - -	Com_Memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) ); - -	if ( bmpHeader.bitsPerPixel == 8 ) -		buf_p += 1024; - -	if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' )  -	{ -		ri.Error( ERR_DROP, "LoadBMP: only Windows-style BMP files supported (%s)\n", name ); -	} -	if ( bmpHeader.fileSize != length ) -	{ -		ri.Error( ERR_DROP, "LoadBMP: header size does not match file size (%d vs. %d) (%s)\n", bmpHeader.fileSize, length, name ); -	} -	if ( bmpHeader.compression != 0 ) -	{ -		ri.Error( ERR_DROP, "LoadBMP: only uncompressed BMP files supported (%s)\n", name ); -	} -	if ( bmpHeader.bitsPerPixel < 8 ) -	{ -		ri.Error( ERR_DROP, "LoadBMP: monochrome and 4-bit BMP files not supported (%s)\n", name ); -	} - -	columns = bmpHeader.width; -	rows = bmpHeader.height; -	if ( rows < 0 ) -		rows = -rows; -	numPixels = columns * rows; - -	if(columns <= 0 || !rows || numPixels > 0x1FFFFFFF // 4*1FFFFFFF == 0x7FFFFFFC < 0x7FFFFFFF -	    || ((numPixels * 4) / columns) / 4 != rows) -	{ -	  ri.Error (ERR_DROP, "LoadBMP: %s has an invalid image size\n", name); -	} - -	if ( width )  -		*width = columns; -	if ( height ) -		*height = rows; - -	bmpRGBA = ri.Malloc( numPixels * 4 ); -	*pic = bmpRGBA; - - -	for ( row = rows-1; row >= 0; row-- ) -	{ -		pixbuf = bmpRGBA + row*columns*4; - -		for ( column = 0; column < columns; column++ ) -		{ -			unsigned char red, green, blue, alpha; -			int palIndex; -			unsigned short shortPixel; - -			switch ( bmpHeader.bitsPerPixel ) -			{ -			case 8: -				palIndex = *buf_p++; -				*pixbuf++ = bmpHeader.palette[palIndex][2]; -				*pixbuf++ = bmpHeader.palette[palIndex][1]; -				*pixbuf++ = bmpHeader.palette[palIndex][0]; -				*pixbuf++ = 0xff; -				break; -			case 16: -				shortPixel = * ( unsigned short * ) pixbuf; -				pixbuf += 2; -				*pixbuf++ = ( shortPixel & ( 31 << 10 ) ) >> 7; -				*pixbuf++ = ( shortPixel & ( 31 << 5 ) ) >> 2; -				*pixbuf++ = ( shortPixel & ( 31 ) ) << 3; -				*pixbuf++ = 0xff; -				break; - -			case 24: -				blue = *buf_p++; -				green = *buf_p++; -				red = *buf_p++; -				*pixbuf++ = red; -				*pixbuf++ = green; -				*pixbuf++ = blue; -				*pixbuf++ = 255; -				break; -			case 32: -				blue = *buf_p++; -				green = *buf_p++; -				red = *buf_p++; -				alpha = *buf_p++; -				*pixbuf++ = red; -				*pixbuf++ = green; -				*pixbuf++ = blue; -				*pixbuf++ = alpha; -				break; -			default: -				ri.Error( ERR_DROP, "LoadBMP: illegal pixel_size '%d' in file '%s'\n", bmpHeader.bitsPerPixel, name ); -				break; -			} -		} -	} - -	ri.FS_FreeFile( buffer ); - -} - - -/* -================================================================= - -PCX LOADING - -================================================================= -*/ - - -/* -============== -LoadPCX -============== -*/ -static void LoadPCX ( const char *filename, byte **pic, byte **palette, int *width, int *height) -{ -	byte	*raw; -	pcx_t	*pcx; -	int		x, y; -	int		len; -	int		dataByte, runLength; -	byte	*out, *pix; -	unsigned		xmax, ymax; - -	*pic = NULL; -	*palette = NULL; - -	// -	// load the file -	// -	len = ri.FS_ReadFile( ( char * ) filename, (void **)&raw); -	if (!raw) { -		return; -	} - -	// -	// parse the PCX file -	// -	pcx = (pcx_t *)raw; -	raw = &pcx->data; - -  	xmax = LittleShort(pcx->xmax); -    ymax = LittleShort(pcx->ymax); - -	if (pcx->manufacturer != 0x0a -		|| pcx->version != 5 -		|| pcx->encoding != 1 -		|| pcx->bits_per_pixel != 8 -		|| xmax >= 1024 -		|| ymax >= 1024) -	{ -		ri.Printf (PRINT_ALL, "Bad pcx file %s (%i x %i) (%i x %i)\n", filename, xmax+1, ymax+1, pcx->xmax, pcx->ymax); -		return; -	} - -	out = ri.Malloc ( (ymax+1) * (xmax+1) ); - -	*pic = out; - -	pix = out; - -	if (palette) -	{ -		*palette = ri.Malloc(768); -		Com_Memcpy (*palette, (byte *)pcx + len - 768, 768); -	} - -	if (width) -		*width = xmax+1; -	if (height) -		*height = ymax+1; -// FIXME: use bytes_per_line here? - -	for (y=0 ; y<=ymax ; y++, pix += xmax+1) -	{ -		for (x=0 ; x<=xmax ; ) -		{ -			dataByte = *raw++; - -			if((dataByte & 0xC0) == 0xC0) -			{ -				runLength = dataByte & 0x3F; -				dataByte = *raw++; -			} -			else -				runLength = 1; - -			while(runLength-- > 0) -				pix[x++] = dataByte; -		} - -	} - -	if ( raw - (byte *)pcx > len) -	{ -		ri.Printf (PRINT_DEVELOPER, "PCX file %s was malformed", filename); -		ri.Free (*pic); -		*pic = NULL; -	} - -	ri.FS_FreeFile (pcx); -} - - -/* -============== -LoadPCX32 -============== -*/ -static void LoadPCX32 ( const char *filename, byte **pic, int *width, int *height) { -	byte	*palette; -	byte	*pic8; -	int		i, c, p; -	byte	*pic32; - -	LoadPCX (filename, &pic8, &palette, width, height); -	if (!pic8) { -		*pic = NULL; -		return; -	} - -	// LoadPCX32 ensures width, height < 1024 -	c = (*width) * (*height); -	pic32 = *pic = ri.Malloc(4 * c ); -	for (i = 0 ; i < c ; i++) { -		p = pic8[i]; -		pic32[0] = palette[p*3]; -		pic32[1] = palette[p*3 + 1]; -		pic32[2] = palette[p*3 + 2]; -		pic32[3] = 255; -		pic32 += 4; -	} - -	ri.Free (pic8); -	ri.Free (palette); -} - -/* -========================================================= - -TARGA LOADING - -========================================================= -*/ - -/* -============= -LoadTGA -============= -*/ -static void LoadTGA ( const char *name, byte **pic, int *width, int *height) -{ -	unsigned	columns, rows, numPixels; -	byte	*pixbuf; -	int		row, column; -	byte	*buf_p; -	byte	*buffer; -	TargaHeader	targa_header; -	byte		*targa_rgba; - -	*pic = NULL; - -	// -	// load the file -	// -	ri.FS_ReadFile ( ( char * ) name, (void **)&buffer); -	if (!buffer) { -		return; -	} - -	buf_p = buffer; - -	targa_header.id_length = buf_p[0]; -	targa_header.colormap_type = buf_p[1]; -	targa_header.image_type = buf_p[2]; -	 -	memcpy(&targa_header.colormap_index, &buf_p[3], 2); -	memcpy(&targa_header.colormap_length, &buf_p[5], 2); -	targa_header.colormap_size = buf_p[7]; -	memcpy(&targa_header.x_origin, &buf_p[8], 2); -	memcpy(&targa_header.y_origin, &buf_p[10], 2); -	memcpy(&targa_header.width, &buf_p[12], 2); -	memcpy(&targa_header.height, &buf_p[14], 2); -	targa_header.pixel_size = buf_p[16]; -	targa_header.attributes = buf_p[17]; - -	targa_header.colormap_index = LittleShort(targa_header.colormap_index); -	targa_header.colormap_length = LittleShort(targa_header.colormap_length); -	targa_header.x_origin = LittleShort(targa_header.x_origin); -	targa_header.y_origin = LittleShort(targa_header.y_origin); -	targa_header.width = LittleShort(targa_header.width); -	targa_header.height = LittleShort(targa_header.height); - -	buf_p += 18; - -	if (targa_header.image_type!=2  -		&& targa_header.image_type!=10 -		&& targa_header.image_type != 3 )  -	{ -		ri.Error (ERR_DROP, "LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n"); -	} - -	if ( targa_header.colormap_type != 0 ) -	{ -		ri.Error( ERR_DROP, "LoadTGA: colormaps not supported\n" ); -	} - -	if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 ) -	{ -		ri.Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); -	} - -	columns = targa_header.width; -	rows = targa_header.height; -	numPixels = columns * rows * 4; - -	if (width) -		*width = columns; -	if (height) -		*height = rows; - -	if(!columns || !rows || numPixels > 0x7FFFFFFF || numPixels / columns / 4 != rows) -	{ -		ri.Error (ERR_DROP, "LoadTGA: %s has an invalid image size\n", name); -	} - -	targa_rgba = ri.Malloc (numPixels); -	*pic = targa_rgba; - -	if (targa_header.id_length != 0) -		buf_p += targa_header.id_length;  // skip TARGA image comment -	 -	if ( targa_header.image_type==2 || targa_header.image_type == 3 ) -	{  -		// Uncompressed RGB or gray scale image -		for(row=rows-1; row>=0; row--)  -		{ -			pixbuf = targa_rgba + row*columns*4; -			for(column=0; column<columns; column++)  -			{ -				unsigned char red,green,blue,alphabyte; -				switch (targa_header.pixel_size)  -				{ -					 -				case 8: -					blue = *buf_p++; -					green = blue; -					red = blue; -					*pixbuf++ = red; -					*pixbuf++ = green; -					*pixbuf++ = blue; -					*pixbuf++ = 255; -					break; - -				case 24: -					blue = *buf_p++; -					green = *buf_p++; -					red = *buf_p++; -					*pixbuf++ = red; -					*pixbuf++ = green; -					*pixbuf++ = blue; -					*pixbuf++ = 255; -					break; -				case 32: -					blue = *buf_p++; -					green = *buf_p++; -					red = *buf_p++; -					alphabyte = *buf_p++; -					*pixbuf++ = red; -					*pixbuf++ = green; -					*pixbuf++ = blue; -					*pixbuf++ = alphabyte; -					break; -				default: -					ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); -					break; -				} -			} -		} -	} -	else if (targa_header.image_type==10) {   // Runlength encoded RGB images -		unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j; - -		red = 0; -		green = 0; -		blue = 0; -		alphabyte = 0xff; - -		for(row=rows-1; row>=0; row--) { -			pixbuf = targa_rgba + row*columns*4; -			for(column=0; column<columns; ) { -				packetHeader= *buf_p++; -				packetSize = 1 + (packetHeader & 0x7f); -				if (packetHeader & 0x80) {        // run-length packet -					switch (targa_header.pixel_size) { -						case 24: -								blue = *buf_p++; -								green = *buf_p++; -								red = *buf_p++; -								alphabyte = 255; -								break; -						case 32: -								blue = *buf_p++; -								green = *buf_p++; -								red = *buf_p++; -								alphabyte = *buf_p++; -								break; -						default: -							ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); -							break; -					} -	 -					for(j=0;j<packetSize;j++) { -						*pixbuf++=red; -						*pixbuf++=green; -						*pixbuf++=blue; -						*pixbuf++=alphabyte; -						column++; -						if (column==columns) { // run spans across rows -							column=0; -							if (row>0) -								row--; -							else -								goto breakOut; -							pixbuf = targa_rgba + row*columns*4; -						} -					} -				} -				else {                            // non run-length packet -					for(j=0;j<packetSize;j++) { -						switch (targa_header.pixel_size) { -							case 24: -									blue = *buf_p++; -									green = *buf_p++; -									red = *buf_p++; -									*pixbuf++ = red; -									*pixbuf++ = green; -									*pixbuf++ = blue; -									*pixbuf++ = 255; -									break; -							case 32: -									blue = *buf_p++; -									green = *buf_p++; -									red = *buf_p++; -									alphabyte = *buf_p++; -									*pixbuf++ = red; -									*pixbuf++ = green; -									*pixbuf++ = blue; -									*pixbuf++ = alphabyte; -									break; -							default: -								ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); -								break; -						} -						column++; -						if (column==columns) { // pixel packet run spans across rows -							column=0; -							if (row>0) -								row--; -							else -								goto breakOut; -							pixbuf = targa_rgba + row*columns*4; -						}						 -					} -				} -			} -			breakOut:; -		} -	} - -#if 0  -  // TTimo: this is the chunk of code to ensure a behavior that meets TGA specs  -  // bk0101024 - fix from Leonardo -  // bit 5 set => top-down -  if (targa_header.attributes & 0x20) { -    unsigned char *flip = (unsigned char*)malloc (columns*4); -    unsigned char *src, *dst; - -    for (row = 0; row < rows/2; row++) { -      src = targa_rgba + row * 4 * columns; -      dst = targa_rgba + (rows - row - 1) * 4 * columns; - -      memcpy (flip, src, columns*4); -      memcpy (src, dst, columns*4); -      memcpy (dst, flip, columns*4); -    } -    free (flip); -  } -#endif -  // instead we just print a warning -  if (targa_header.attributes & 0x20) { -    ri.Printf( PRINT_WARNING, "WARNING: '%s' TGA file header declares top-down image, ignoring\n", name); -  } - -  ri.FS_FreeFile (buffer); -} - -static void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height ) { -  /* This struct contains the JPEG decompression parameters and pointers to -   * working space (which is allocated as needed by the JPEG library). -   */ -  struct jpeg_decompress_struct cinfo = {NULL}; -  /* We use our private extension JPEG error handler. -   * Note that this struct must live as long as the main JPEG parameter -   * struct, to avoid dangling-pointer problems. -   */ -  /* This struct represents a JPEG error handler.  It is declared separately -   * because applications often want to supply a specialized error handler -   * (see the second half of this file for an example).  But here we just -   * take the easy way out and use the standard error handler, which will -   * print a message on stderr and call exit() if compression fails. -   * Note that this struct must live as long as the main JPEG parameter -   * struct, to avoid dangling-pointer problems. -   */ -  struct jpeg_error_mgr jerr; -  /* More stuff */ -  JSAMPARRAY buffer;		/* Output row buffer */ -  unsigned row_stride;		/* physical row width in output buffer */ -  unsigned pixelcount, memcount; -  unsigned char *out; -  byte	*fbuffer; -  byte  *buf; - -  /* In this example we want to open the input file before doing anything else, -   * so that the setjmp() error recovery below can assume the file is open. -   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that -   * requires it in order to read binary files. -   */ - -  ri.FS_ReadFile ( ( char * ) filename, (void **)&fbuffer); -  if (!fbuffer) { -	return; -  } - -  /* Step 1: allocate and initialize JPEG decompression object */ - -  /* We have to set up the error handler first, in case the initialization -   * step fails.  (Unlikely, but it could happen if you are out of memory.) -   * This routine fills in the contents of struct jerr, and returns jerr's -   * address which we place into the link field in cinfo. -   */ -  cinfo.err = jpeg_std_error(&jerr); - -  /* Now we can initialize the JPEG decompression object. */ -  jpeg_create_decompress(&cinfo); - -  /* Step 2: specify data source (eg, a file) */ - -  jpeg_stdio_src(&cinfo, fbuffer); - -  /* Step 3: read file parameters with jpeg_read_header() */ - -  (void) jpeg_read_header(&cinfo, TRUE); -  /* We can ignore the return value from jpeg_read_header since -   *   (a) suspension is not possible with the stdio data source, and -   *   (b) we passed TRUE to reject a tables-only JPEG file as an error. -   * See libjpeg.doc for more info. -   */ - -  /* Step 4: set parameters for decompression */ - -  /* In this example, we don't need to change any of the defaults set by -   * jpeg_read_header(), so we do nothing here. -   */ - -  /* Step 5: Start decompressor */ - -  (void) jpeg_start_decompress(&cinfo); -  /* We can ignore the return value since suspension is not possible -   * with the stdio data source. -   */ - -  /* We may need to do some setup of our own at this point before reading -   * the data.  After jpeg_start_decompress() we have the correct scaled -   * output image dimensions available, as well as the output colormap -   * if we asked for color quantization. -   * In this example, we need to make an output work buffer of the right size. -   */  -  /* JSAMPLEs per row in output buffer */ - -  pixelcount = cinfo.output_width * cinfo.output_height; - -  if(!cinfo.output_width || !cinfo.output_height -      || ((pixelcount * 4) / cinfo.output_width) / 4 != cinfo.output_height -      || pixelcount > 0x1FFFFFFF || cinfo.output_components > 4) // 4*1FFFFFFF == 0x7FFFFFFC < 0x7FFFFFFF -  { -    ri.Error (ERR_DROP, "LoadJPG: %s has an invalid image size: %dx%d*4=%d, components: %d\n", filename, -		    cinfo.output_width, cinfo.output_height, pixelcount * 4, cinfo.output_components); -  } - -  memcount = pixelcount * 4; -  row_stride = cinfo.output_width * cinfo.output_components; - -  out = ri.Malloc(memcount); - -  *width = cinfo.output_width; -  *height = cinfo.output_height; - -  /* Step 6: while (scan lines remain to be read) */ -  /*           jpeg_read_scanlines(...); */ - -  /* Here we use the library's state variable cinfo.output_scanline as the -   * loop counter, so that we don't have to keep track ourselves. -   */ -  while (cinfo.output_scanline < cinfo.output_height) { -    /* jpeg_read_scanlines expects an array of pointers to scanlines. -     * Here the array is only one element long, but you could ask for -     * more than one scanline at a time if that's more convenient. -     */ -	buf = ((out+(row_stride*cinfo.output_scanline))); -	buffer = &buf; -    (void) jpeg_read_scanlines(&cinfo, buffer, 1); -  } -   -  buf = out; - -  // If we are processing an 8-bit JPEG (greyscale), we'll have to convert -  // the greyscale values to RGBA. -  if(cinfo.output_components == 1) -  { -  	int sindex = pixelcount, dindex = memcount; -	unsigned char greyshade; - -	// Only pixelcount number of bytes have been written. -	// Expand the color values over the rest of the buffer, starting -	// from the end. -	do -	{ -		greyshade = buf[--sindex]; - -		buf[--dindex] = 255; -		buf[--dindex] = greyshade; -		buf[--dindex] = greyshade; -		buf[--dindex] = greyshade; -	} while(sindex); -  } -  else -  { -	// clear all the alphas to 255 -	int	i; - -	for ( i = 3 ; i < memcount ; i+=4 ) -	{ -		buf[i] = 255; -	} -  } - -  *pic = out; - -  /* Step 7: Finish decompression */ - -  (void) jpeg_finish_decompress(&cinfo); -  /* We can ignore the return value since suspension is not possible -   * with the stdio data source. -   */ - -  /* Step 8: Release JPEG decompression object */ - -  /* This is an important step since it will release a good deal of memory. */ -  jpeg_destroy_decompress(&cinfo); - -  /* After finish_decompress, we can close the input file. -   * Here we postpone it until after no more JPEG errors are possible, -   * so as to simplify the setjmp error logic above.  (Actually, I don't -   * think that jpeg_destroy can do an error exit, but why assume anything...) -   */ -  ri.FS_FreeFile (fbuffer); - -  /* At this point you may want to check to see whether any corrupt-data -   * warnings occurred (test whether jerr.pub.num_warnings is nonzero). -   */ - -  /* And we're done! */ -} - - -/* Expanded data destination object for stdio output */ - -typedef struct { -  struct jpeg_destination_mgr pub; /* public fields */ - -  byte* outfile;		/* target stream */ -  int	size; -} my_destination_mgr; - -typedef my_destination_mgr * my_dest_ptr; - - -/* - * Initialize destination --- called by jpeg_start_compress - * before any data is actually written. - */ - -void init_destination (j_compress_ptr cinfo) -{ -  my_dest_ptr dest = (my_dest_ptr) cinfo->dest; - -  dest->pub.next_output_byte = dest->outfile; -  dest->pub.free_in_buffer = dest->size; -} - - -/* - * Empty the output buffer --- called whenever buffer fills up. - * - * In typical applications, this should write the entire output buffer - * (ignoring the current state of next_output_byte & free_in_buffer), - * reset the pointer & count to the start of the buffer, and return TRUE - * indicating that the buffer has been dumped. - * - * In applications that need to be able to suspend compression due to output - * overrun, a FALSE return indicates that the buffer cannot be emptied now. - * In this situation, the compressor will return to its caller (possibly with - * an indication that it has not accepted all the supplied scanlines).  The - * application should resume compression after it has made more room in the - * output buffer.  Note that there are substantial restrictions on the use of - * suspension --- see the documentation. - * - * When suspending, the compressor will back up to a convenient restart point - * (typically the start of the current MCU). next_output_byte & free_in_buffer - * indicate where the restart point will be if the current call returns FALSE. - * Data beyond this point will be regenerated after resumption, so do not - * write it out when emptying the buffer externally. - */ - -boolean empty_output_buffer (j_compress_ptr cinfo) -{ -  return TRUE; -} - - -/* - * Compression initialization. - * Before calling this, all parameters and a data destination must be set up. - * - * We require a write_all_tables parameter as a failsafe check when writing - * multiple datastreams from the same compression object.  Since prior runs - * will have left all the tables marked sent_table=TRUE, a subsequent run - * would emit an abbreviated stream (no tables) by default.  This may be what - * is wanted, but for safety's sake it should not be the default behavior: - * programmers should have to make a deliberate choice to emit abbreviated - * images.  Therefore the documentation and examples should encourage people - * to pass write_all_tables=TRUE; then it will take active thought to do the - * wrong thing. - */ - -GLOBAL void -jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) -{ -  if (cinfo->global_state != CSTATE_START) -    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - -  if (write_all_tables) -    jpeg_suppress_tables(cinfo, FALSE);	/* mark all tables to be written */ - -  /* (Re)initialize error mgr and destination modules */ -  (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); -  (*cinfo->dest->init_destination) (cinfo); -  /* Perform master selection of active modules */ -  jinit_compress_master(cinfo); -  /* Set up for the first pass */ -  (*cinfo->master->prepare_for_pass) (cinfo); -  /* Ready for application to drive first pass through jpeg_write_scanlines -   * or jpeg_write_raw_data. -   */ -  cinfo->next_scanline = 0; -  cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); -} - - -/* - * Write some scanlines of data to the JPEG compressor. - * - * The return value will be the number of lines actually written. - * This should be less than the supplied num_lines only in case that - * the data destination module has requested suspension of the compressor, - * or if more than image_height scanlines are passed in. - * - * Note: we warn about excess calls to jpeg_write_scanlines() since - * this likely signals an application programmer error.  However, - * excess scanlines passed in the last valid call are *silently* ignored, - * so that the application need not adjust num_lines for end-of-image - * when using a multiple-scanline buffer. - */ - -GLOBAL JDIMENSION -jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, -		      JDIMENSION num_lines) -{ -  JDIMENSION row_ctr, rows_left; - -  if (cinfo->global_state != CSTATE_SCANNING) -    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); -  if (cinfo->next_scanline >= cinfo->image_height) -    WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - -  /* Call progress monitor hook if present */ -  if (cinfo->progress != NULL) { -    cinfo->progress->pass_counter = (long) cinfo->next_scanline; -    cinfo->progress->pass_limit = (long) cinfo->image_height; -    (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); -  } - -  /* Give master control module another chance if this is first call to -   * jpeg_write_scanlines.  This lets output of the frame/scan headers be -   * delayed so that application can write COM, etc, markers between -   * jpeg_start_compress and jpeg_write_scanlines. -   */ -  if (cinfo->master->call_pass_startup) -    (*cinfo->master->pass_startup) (cinfo); - -  /* Ignore any extra scanlines at bottom of image. */ -  rows_left = cinfo->image_height - cinfo->next_scanline; -  if (num_lines > rows_left) -    num_lines = rows_left; - -  row_ctr = 0; -  (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); -  cinfo->next_scanline += row_ctr; -  return row_ctr; -} - -/* - * Terminate destination --- called by jpeg_finish_compress - * after all data has been written.  Usually needs to flush buffer. - * - * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding - * application must deal with any cleanup that should happen even - * for error exit. - */ - -static int hackSize; - -void term_destination (j_compress_ptr cinfo) -{ -  my_dest_ptr dest = (my_dest_ptr) cinfo->dest; -  size_t datacount = dest->size - dest->pub.free_in_buffer; -  hackSize = datacount; -} - - -/* - * Prepare for output to a stdio stream. - * The caller must have already opened the stream, and is responsible - * for closing it after finishing compression. - */ - -void jpegDest (j_compress_ptr cinfo, byte* outfile, int size) -{ -  my_dest_ptr dest; - -  /* The destination object is made permanent so that multiple JPEG images -   * can be written to the same file without re-executing jpeg_stdio_dest. -   * This makes it dangerous to use this manager and a different destination -   * manager serially with the same JPEG object, because their private object -   * sizes may be different.  Caveat programmer. -   */ -  if (cinfo->dest == NULL) {	/* first time for this JPEG object? */ -    cinfo->dest = (struct jpeg_destination_mgr *) -      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, -				  sizeof(my_destination_mgr)); -  } - -  dest = (my_dest_ptr) cinfo->dest; -  dest->pub.init_destination = init_destination; -  dest->pub.empty_output_buffer = empty_output_buffer; -  dest->pub.term_destination = term_destination; -  dest->outfile = outfile; -  dest->size = size; -} - -void SaveJPG(char * filename, int quality, int image_width, int image_height, unsigned char *image_buffer) { -  /* This struct contains the JPEG compression parameters and pointers to -   * working space (which is allocated as needed by the JPEG library). -   * It is possible to have several such structures, representing multiple -   * compression/decompression processes, in existence at once.  We refer -   * to any one struct (and its associated working data) as a "JPEG object". -   */ -  struct jpeg_compress_struct cinfo; -  /* This struct represents a JPEG error handler.  It is declared separately -   * because applications often want to supply a specialized error handler -   * (see the second half of this file for an example).  But here we just -   * take the easy way out and use the standard error handler, which will -   * print a message on stderr and call exit() if compression fails. -   * Note that this struct must live as long as the main JPEG parameter -   * struct, to avoid dangling-pointer problems. -   */ -  struct jpeg_error_mgr jerr; -  /* More stuff */ -  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */ -  int row_stride;		/* physical row width in image buffer */ -  unsigned char *out; - -  /* Step 1: allocate and initialize JPEG compression object */ - -  /* We have to set up the error handler first, in case the initialization -   * step fails.  (Unlikely, but it could happen if you are out of memory.) -   * This routine fills in the contents of struct jerr, and returns jerr's -   * address which we place into the link field in cinfo. -   */ -  cinfo.err = jpeg_std_error(&jerr); -  /* Now we can initialize the JPEG compression object. */ -  jpeg_create_compress(&cinfo); - -  /* Step 2: specify data destination (eg, a file) */ -  /* Note: steps 2 and 3 can be done in either order. */ - -  /* Here we use the library-supplied code to send compressed data to a -   * stdio stream.  You can also write your own code to do something else. -   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that -   * requires it in order to write binary files. -   */ -  out = ri.Hunk_AllocateTempMemory(image_width*image_height*4); -  jpegDest(&cinfo, out, image_width*image_height*4); - -  /* Step 3: set parameters for compression */ - -  /* First we supply a description of the input image. -   * Four fields of the cinfo struct must be filled in: -   */ -  cinfo.image_width = image_width; 	/* image width and height, in pixels */ -  cinfo.image_height = image_height; -  cinfo.input_components = 4;		/* # of color components per pixel */ -  cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */ -  /* Now use the library's routine to set default compression parameters. -   * (You must set at least cinfo.in_color_space before calling this, -   * since the defaults depend on the source color space.) -   */ -  jpeg_set_defaults(&cinfo); -  /* Now you can set any non-default parameters you wish to. -   * Here we just illustrate the use of quality (quantization table) scaling: -   */ -  jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); - -  /* Step 4: Start compressor */ - -  /* TRUE ensures that we will write a complete interchange-JPEG file. -   * Pass TRUE unless you are very sure of what you're doing. -   */ -  jpeg_start_compress(&cinfo, TRUE); - -  /* Step 5: while (scan lines remain to be written) */ -  /*           jpeg_write_scanlines(...); */ - -  /* Here we use the library's state variable cinfo.next_scanline as the -   * loop counter, so that we don't have to keep track ourselves. -   * To keep things simple, we pass one scanline per call; you can pass -   * more if you wish, though. -   */ -  row_stride = image_width * 4;	/* JSAMPLEs per row in image_buffer */ - -  while (cinfo.next_scanline < cinfo.image_height) { -    /* jpeg_write_scanlines expects an array of pointers to scanlines. -     * Here the array is only one element long, but you could pass -     * more than one scanline at a time if that's more convenient. -     */ -    row_pointer[0] = & image_buffer[((cinfo.image_height-1)*row_stride)-cinfo.next_scanline * row_stride]; -    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); -  } - -  /* Step 6: Finish compression */ - -  jpeg_finish_compress(&cinfo); -  /* After finish_compress, we can close the output file. */ -  ri.FS_WriteFile( filename, out, hackSize ); - -  ri.Hunk_FreeTempMemory(out); - -  /* Step 7: release JPEG compression object */ - -  /* This is an important step since it will release a good deal of memory. */ -  jpeg_destroy_compress(&cinfo); - -  /* And we're done! */ -} - -//=================================================================== - -/* -================= -R_LoadImage - -Loads any of the supported image types into a cannonical -32 bit format. -================= -*/ -void R_LoadImage( const char *name, byte **pic, int *width, int *height ) { -	int		len; - -	*pic = NULL; -	*width = 0; -	*height = 0; - -	len = strlen(name); -	if (len<5) { -		return; -	} - -	if ( !Q_stricmp( name+len-4, ".tga" ) ) { -	  LoadTGA( name, pic, width, height );            // try tga first -    if (!*pic) {                                    // -		  char altname[MAX_QPATH];                      // try jpg in place of tga  -      strcpy( altname, name );                       -      len = strlen( altname );                   -      altname[len-3] = 'j'; -      altname[len-2] = 'p'; -      altname[len-1] = 'g'; -			LoadJPG( altname, pic, width, height ); -		} -  } else if ( !Q_stricmp(name+len-4, ".pcx") ) { -    LoadPCX32( name, pic, width, height ); -	} else if ( !Q_stricmp( name+len-4, ".bmp" ) ) { -		LoadBMP( name, pic, width, height ); -	} else if ( !Q_stricmp( name+len-4, ".jpg" ) ) { -		LoadJPG( name, pic, width, height ); -	} -} - - -/* -=============== -R_FindImageFile - -Finds or loads the given image. -Returns NULL if it fails, not a default image. -============== -*/ -image_t	*R_FindImageFile( const char *name, qboolean mipmap, qboolean allowPicmip, int glWrapClampMode ) { -	image_t	*image; -	int		width, height; -	byte	*pic; -	long	hash; - -	if (!name) { -		return NULL; -	} - -	hash = generateHashValue(name); - -	// -	// see if the image is already loaded -	// -	for (image=hashTable[hash]; image; image=image->next) { -		if ( !strcmp( name, image->imgName ) ) { -			// the white image can be used with any set of parms, but other mismatches are errors -			if ( strcmp( name, "*white" ) ) { -				if ( image->mipmap != mipmap ) { -					ri.Printf( PRINT_DEVELOPER, "WARNING: reused image %s with mixed mipmap parm\n", name ); -				} -				if ( image->allowPicmip != allowPicmip ) { -					ri.Printf( PRINT_DEVELOPER, "WARNING: reused image %s with mixed allowPicmip parm\n", name ); -				} -				if ( image->wrapClampMode != glWrapClampMode ) { -					ri.Printf( PRINT_ALL, "WARNING: reused image %s with mixed glWrapClampMode parm\n", name ); -				} -			} -			return image; -		} -	} - -	// -	// load the pic from disk -	// -	R_LoadImage( name, &pic, &width, &height ); -	if ( pic == NULL ) {                                    // if we dont get a successful load -	  char altname[MAX_QPATH];                              // copy the name -    int len;                                              //   -    strcpy( altname, name );                              // -    len = strlen( altname );                              //  -    altname[len-3] = toupper(altname[len-3]);             // and try upper case extension for unix systems -    altname[len-2] = toupper(altname[len-2]);             // -    altname[len-1] = toupper(altname[len-1]);             // -		ri.Printf( PRINT_ALL, "trying %s...\n", altname );    //  -	  R_LoadImage( altname, &pic, &width, &height );        // -    if (pic == NULL) {                                    // if that fails -      return NULL;                                        // bail -    } -	} - -	image = R_CreateImage( ( char * ) name, pic, width, height, mipmap, allowPicmip, glWrapClampMode ); -	ri.Free( pic ); -	return image; -} - - -/* -================ -R_CreateDlightImage -================ -*/ -#define	DLIGHT_SIZE	16 -static void R_CreateDlightImage( void ) { -	int		x,y; -	byte	data[DLIGHT_SIZE][DLIGHT_SIZE][4]; -	int		b; - -	// make a centered inverse-square falloff blob for dynamic lighting -	for (x=0 ; x<DLIGHT_SIZE ; x++) { -		for (y=0 ; y<DLIGHT_SIZE ; y++) { -			float	d; - -			d = ( DLIGHT_SIZE/2 - 0.5f - x ) * ( DLIGHT_SIZE/2 - 0.5f - x ) + -				( DLIGHT_SIZE/2 - 0.5f - y ) * ( DLIGHT_SIZE/2 - 0.5f - y ); -			b = 4000 / d; -			if (b > 255) { -				b = 255; -			} else if ( b < 75 ) { -				b = 0; -			} -			data[y][x][0] =  -			data[y][x][1] =  -			data[y][x][2] = b; -			data[y][x][3] = 255;			 -		} -	} -	tr.dlightImage = R_CreateImage("*dlight", (byte *)data, DLIGHT_SIZE, DLIGHT_SIZE, qfalse, qfalse, GL_CLAMP ); -} - - -/* -================= -R_InitFogTable -================= -*/ -void R_InitFogTable( void ) { -	int		i; -	float	d; -	float	exp; -	 -	exp = 0.5; - -	for ( i = 0 ; i < FOG_TABLE_SIZE ; i++ ) { -		d = pow ( (float)i/(FOG_TABLE_SIZE-1), exp ); - -		tr.fogTable[i] = d; -	} -} - -/* -================ -R_FogFactor - -Returns a 0.0 to 1.0 fog density value -This is called for each texel of the fog texture on startup -and for each vertex of transparent shaders in fog dynamically -================ -*/ -float	R_FogFactor( float s, float t ) { -	float	d; - -	s -= 1.0/512; -	if ( s < 0 ) { -		return 0; -	} -	if ( t < 1.0/32 ) { -		return 0; -	} -	if ( t < 31.0/32 ) { -		s *= (t - 1.0f/32.0f) / (30.0f/32.0f); -	} - -	// we need to leave a lot of clamp range -	s *= 8; - -	if ( s > 1.0 ) { -		s = 1.0; -	} - -	d = tr.fogTable[ (int)(s * (FOG_TABLE_SIZE-1)) ]; - -	return d; -} - -/* -================ -R_CreateFogImage -================ -*/ -#define	FOG_S	256 -#define	FOG_T	32 -static void R_CreateFogImage( void ) { -	int		x,y; -	byte	*data; -	float	g; -	float	d; -	float	borderColor[4]; - -	data = ri.Hunk_AllocateTempMemory( FOG_S * FOG_T * 4 ); - -	g = 2.0; - -	// S is distance, T is depth -	for (x=0 ; x<FOG_S ; x++) { -		for (y=0 ; y<FOG_T ; y++) { -			d = R_FogFactor( ( x + 0.5f ) / FOG_S, ( y + 0.5f ) / FOG_T ); - -			data[(y*FOG_S+x)*4+0] =  -			data[(y*FOG_S+x)*4+1] =  -			data[(y*FOG_S+x)*4+2] = 255; -			data[(y*FOG_S+x)*4+3] = 255*d; -		} -	} -	// standard openGL clamping doesn't really do what we want -- it includes -	// the border color at the edges.  OpenGL 1.2 has clamp-to-edge, which does -	// what we want. -	tr.fogImage = R_CreateImage("*fog", (byte *)data, FOG_S, FOG_T, qfalse, qfalse, GL_CLAMP ); -	ri.Hunk_FreeTempMemory( data ); - -	borderColor[0] = 1.0; -	borderColor[1] = 1.0; -	borderColor[2] = 1.0; -	borderColor[3] = 1; - -	qglTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor ); -} - -/* -================== -R_CreateDefaultImage -================== -*/ -#define	DEFAULT_SIZE	16 -static void R_CreateDefaultImage( void ) { -	int		x; -	byte	data[DEFAULT_SIZE][DEFAULT_SIZE][4]; - -	// the default image will be a box, to allow you to see the mapping coordinates -	Com_Memset( data, 32, sizeof( data ) ); -	for ( x = 0 ; x < DEFAULT_SIZE ; x++ ) { -		data[0][x][0] = -		data[0][x][1] = -		data[0][x][2] = -		data[0][x][3] = 255; - -		data[x][0][0] = -		data[x][0][1] = -		data[x][0][2] = -		data[x][0][3] = 255; - -		data[DEFAULT_SIZE-1][x][0] = -		data[DEFAULT_SIZE-1][x][1] = -		data[DEFAULT_SIZE-1][x][2] = -		data[DEFAULT_SIZE-1][x][3] = 255; - -		data[x][DEFAULT_SIZE-1][0] = -		data[x][DEFAULT_SIZE-1][1] = -		data[x][DEFAULT_SIZE-1][2] = -		data[x][DEFAULT_SIZE-1][3] = 255; -	} -	tr.defaultImage = R_CreateImage("*default", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, qtrue, qfalse, GL_REPEAT ); -} - -/* -================== -R_CreateBuiltinImages -================== -*/ -void R_CreateBuiltinImages( void ) { -	int		x,y; -	byte	data[DEFAULT_SIZE][DEFAULT_SIZE][4]; - -	R_CreateDefaultImage(); - -	// we use a solid white image instead of disabling texturing -	Com_Memset( data, 255, sizeof( data ) ); -	tr.whiteImage = R_CreateImage("*white", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT ); - -	// with overbright bits active, we need an image which is some fraction of full color, -	// for default lightmaps, etc -	for (x=0 ; x<DEFAULT_SIZE ; x++) { -		for (y=0 ; y<DEFAULT_SIZE ; y++) { -			data[y][x][0] =  -			data[y][x][1] =  -			data[y][x][2] = tr.identityLightByte; -			data[y][x][3] = 255;			 -		} -	} - -	tr.identityLightImage = R_CreateImage("*identityLight", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT ); - - -	for(x=0;x<32;x++) { -		// scratchimage is usually used for cinematic drawing -		tr.scratchImage[x] = R_CreateImage("*scratch", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, qfalse, qtrue, GL_CLAMP ); -	} - -	R_CreateDlightImage(); -	R_CreateFogImage(); -} - - -/* -=============== -R_SetColorMappings -=============== -*/ -void R_SetColorMappings( void ) { -	int		i, j; -	float	g; -	int		inf; -	int		shift; - -	// setup the overbright lighting -	tr.overbrightBits = r_overBrightBits->integer; -	if ( !glConfig.deviceSupportsGamma ) { -		tr.overbrightBits = 0;		// need hardware gamma for overbright -	} - -	// never overbright in windowed mode -	if ( !glConfig.isFullscreen )  -	{ -		tr.overbrightBits = 0; -	} - -	// allow 2 overbright bits in 24 bit, but only 1 in 16 bit -	if ( glConfig.colorBits > 16 ) { -		if ( tr.overbrightBits > 2 ) { -			tr.overbrightBits = 2; -		} -	} else { -		if ( tr.overbrightBits > 1 ) { -			tr.overbrightBits = 1; -		} -	} -	if ( tr.overbrightBits < 0 ) { -		tr.overbrightBits = 0; -	} - -	tr.identityLight = 1.0f / ( 1 << tr.overbrightBits ); -	tr.identityLightByte = 255 * tr.identityLight; - - -	if ( r_intensity->value <= 1 ) { -		ri.Cvar_Set( "r_intensity", "1" ); -	} - -	if ( r_gamma->value < 0.5f ) { -		ri.Cvar_Set( "r_gamma", "0.5" ); -	} else if ( r_gamma->value > 3.0f ) { -		ri.Cvar_Set( "r_gamma", "3.0" ); -	} - -	g = r_gamma->value; - -	shift = tr.overbrightBits; - -	for ( i = 0; i < 256; i++ ) { -		if ( g == 1 ) { -			inf = i; -		} else { -			inf = 255 * pow ( i/255.0f, 1.0f / g ) + 0.5f; -		} -		inf <<= shift; -		if (inf < 0) { -			inf = 0; -		} -		if (inf > 255) { -			inf = 255; -		} -		s_gammatable[i] = inf; -	} - -	for (i=0 ; i<256 ; i++) { -		j = i * r_intensity->value; -		if (j > 255) { -			j = 255; -		} -		s_intensitytable[i] = j; -	} - -	if ( glConfig.deviceSupportsGamma ) -	{ -		GLimp_SetGamma( s_gammatable, s_gammatable, s_gammatable ); -	} -} - -/* -=============== -R_InitImages -=============== -*/ -void	R_InitImages( void ) { -	Com_Memset(hashTable, 0, sizeof(hashTable)); -	// build brightness translation tables -	R_SetColorMappings(); - -	// create default texture and white texture -	R_CreateBuiltinImages(); -} - -/* -=============== -R_DeleteTextures -=============== -*/ -void R_DeleteTextures( void ) { -	int		i; - -	for ( i=0; i<tr.numImages ; i++ ) { -		qglDeleteTextures( 1, &tr.images[i]->texnum ); -	} -	Com_Memset( tr.images, 0, sizeof( tr.images ) ); - -	tr.numImages = 0; - -	Com_Memset( glState.currenttextures, 0, sizeof( glState.currenttextures ) ); -	if ( qglBindTexture ) { -		if ( qglActiveTextureARB ) { -			GL_SelectTexture( 1 ); -			qglBindTexture( GL_TEXTURE_2D, 0 ); -			GL_SelectTexture( 0 ); -			qglBindTexture( GL_TEXTURE_2D, 0 ); -		} else { -			qglBindTexture( GL_TEXTURE_2D, 0 ); -		} -	} -} - -/* -============================================================================ - -SKINS - -============================================================================ -*/ - -/* -================== -CommaParse - -This is unfortunate, but the skin files aren't -compatable with our normal parsing rules. -================== -*/ -static char *CommaParse( char **data_p ) { -	int c = 0, len; -	char *data; -	static	char	com_token[MAX_TOKEN_CHARS]; - -	data = *data_p; -	len = 0; -	com_token[0] = 0; - -	// make sure incoming data is valid -	if ( !data ) { -		*data_p = NULL; -		return com_token; -	} - -	while ( 1 ) { -		// skip whitespace -		while( (c = *data) <= ' ') { -			if( !c ) { -				break; -			} -			data++; -		} - - -		c = *data; - -		// skip double slash comments -		if ( c == '/' && data[1] == '/' ) -		{ -			while (*data && *data != '\n') -				data++; -		} -		// skip /* */ comments -		else if ( c=='/' && data[1] == '*' )  -		{ -			while ( *data && ( *data != '*' || data[1] != '/' ) )  -			{ -				data++; -			} -			if ( *data )  -			{ -				data += 2; -			} -		} -		else -		{ -			break; -		} -	} - -	if ( c == 0 ) { -		return ""; -	} - -	// handle quoted strings -	if (c == '\"') -	{ -		data++; -		while (1) -		{ -			c = *data++; -			if (c=='\"' || !c) -			{ -				com_token[len] = 0; -				*data_p = ( char * ) data; -				return com_token; -			} -			if (len < MAX_TOKEN_CHARS) -			{ -				com_token[len] = c; -				len++; -			} -		} -	} - -	// parse a regular word -	do -	{ -		if (len < MAX_TOKEN_CHARS) -		{ -			com_token[len] = c; -			len++; -		} -		data++; -		c = *data; -	} while (c>32 && c != ',' ); - -	if (len == MAX_TOKEN_CHARS) -	{ -//		Com_Printf ("Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS); -		len = 0; -	} -	com_token[len] = 0; - -	*data_p = ( char * ) data; -	return com_token; -} - - -/* -=============== -RE_RegisterSkin - -=============== -*/ -qhandle_t RE_RegisterSkin( const char *name ) { -	qhandle_t	hSkin; -	skin_t		*skin; -	skinSurface_t	*surf; -	char		*text, *text_p; -	char		*token; -	char		surfName[MAX_QPATH]; - -	if ( !name || !name[0] ) { -		Com_Printf( "Empty name passed to RE_RegisterSkin\n" ); -		return 0; -	} - -	if ( strlen( name ) >= MAX_QPATH ) { -		Com_Printf( "Skin name exceeds MAX_QPATH\n" ); -		return 0; -	} - - -	// see if the skin is already loaded -	for ( hSkin = 1; hSkin < tr.numSkins ; hSkin++ ) { -		skin = tr.skins[hSkin]; -		if ( !Q_stricmp( skin->name, name ) ) { -			if( skin->numSurfaces == 0 ) { -				return 0;		// default skin -			} -			return hSkin; -		} -	} - -	// allocate a new skin -	if ( tr.numSkins == MAX_SKINS ) { -		ri.Printf( PRINT_WARNING, "WARNING: RE_RegisterSkin( '%s' ) MAX_SKINS hit\n", name ); -		return 0; -	} -	tr.numSkins++; -	skin = ri.Hunk_Alloc( sizeof( skin_t ), h_low ); -	tr.skins[hSkin] = skin; -	Q_strncpyz( skin->name, name, sizeof( skin->name ) ); -	skin->numSurfaces = 0; - -	// make sure the render thread is stopped -	R_SyncRenderThread(); - -	// If not a .skin file, load as a single shader -	if ( strcmp( name + strlen( name ) - 5, ".skin" ) ) { -		skin->numSurfaces = 1; -		skin->surfaces[0] = ri.Hunk_Alloc( sizeof(skin->surfaces[0]), h_low ); -		skin->surfaces[0]->shader = R_FindShader( name, LIGHTMAP_NONE, qtrue ); -		return hSkin; -	} - -	// load and parse the skin file -    ri.FS_ReadFile( name, (void **)&text ); -	if ( !text ) { -		return 0; -	} - -	text_p = text; -	while ( text_p && *text_p ) { -		// get surface name -		token = CommaParse( &text_p ); -		Q_strncpyz( surfName, token, sizeof( surfName ) ); - -		if ( !token[0] ) { -			break; -		} -		// lowercase the surface name so skin compares are faster -		Q_strlwr( surfName ); - -		if ( *text_p == ',' ) { -			text_p++; -		} - -		if ( strstr( token, "tag_" ) ) { -			continue; -		} -		 -		// parse the shader name -		token = CommaParse( &text_p ); - -		surf = skin->surfaces[ skin->numSurfaces ] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); -		Q_strncpyz( surf->name, surfName, sizeof( surf->name ) ); -		surf->shader = R_FindShader( token, LIGHTMAP_NONE, qtrue ); -		skin->numSurfaces++; -	} - -	ri.FS_FreeFile( text ); - - -	// never let a skin have 0 shaders -	if ( skin->numSurfaces == 0 ) { -		return 0;		// use default skin -	} - -	return hSkin; -} - - -/* -=============== -R_InitSkins -=============== -*/ -void	R_InitSkins( void ) { -	skin_t		*skin; - -	tr.numSkins = 1; - -	// make the default skin have all default shaders -	skin = tr.skins[0] = ri.Hunk_Alloc( sizeof( skin_t ), h_low ); -	Q_strncpyz( skin->name, "<default skin>", sizeof( skin->name )  ); -	skin->numSurfaces = 1; -	skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces ), h_low ); -	skin->surfaces[0]->shader = tr.defaultShader; -} - -/* -=============== -R_GetSkinByHandle -=============== -*/ -skin_t	*R_GetSkinByHandle( qhandle_t hSkin ) { -	if ( hSkin < 1 || hSkin >= tr.numSkins ) { -		return tr.skins[0]; -	} -	return tr.skins[ hSkin ]; -} - -/* -=============== -R_SkinList_f -=============== -*/ -void	R_SkinList_f( void ) { -	int			i, j; -	skin_t		*skin; - -	ri.Printf (PRINT_ALL, "------------------\n"); - -	for ( i = 0 ; i < tr.numSkins ; i++ ) { -		skin = tr.skins[i]; - -		ri.Printf( PRINT_ALL, "%3i:%s\n", i, skin->name ); -		for ( j = 0 ; j < skin->numSurfaces ; j++ ) { -			ri.Printf( PRINT_ALL, "       %s = %s\n",  -				skin->surfaces[j]->name, skin->surfaces[j]->shader->name ); -		} -	} -	ri.Printf (PRINT_ALL, "------------------\n"); -} - diff --git a/ioq3-r437/src/renderer/tr_init.c b/ioq3-r437/src/renderer/tr_init.c deleted file mode 100644 index ffdd9974..00000000 --- a/ioq3-r437/src/renderer/tr_init.c +++ /dev/null @@ -1,1205 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_init.c -- functions that are not called every frame - -#include "tr_local.h" - -glconfig_t	glConfig; -glstate_t	glState; - -static void GfxInfo_f( void ); - -cvar_t	*r_flareSize; -cvar_t	*r_flareFade; - -cvar_t	*r_railWidth; -cvar_t	*r_railCoreWidth; -cvar_t	*r_railSegmentLength; - -cvar_t	*r_ignoreFastPath; - -cvar_t	*r_verbose; -cvar_t	*r_ignore; - -cvar_t	*r_displayRefresh; - -cvar_t	*r_detailTextures; - -cvar_t	*r_znear; - -cvar_t	*r_smp; -cvar_t	*r_showSmp; -cvar_t	*r_skipBackEnd; - -cvar_t	*r_ignorehwgamma; -cvar_t	*r_measureOverdraw; - -cvar_t	*r_inGameVideo; -cvar_t	*r_fastsky; -cvar_t	*r_drawSun; -cvar_t	*r_dynamiclight; -cvar_t	*r_dlightBacks; - -cvar_t	*r_lodbias; -cvar_t	*r_lodscale; - -cvar_t	*r_norefresh; -cvar_t	*r_drawentities; -cvar_t	*r_drawworld; -cvar_t	*r_speeds; -cvar_t	*r_fullbright; -cvar_t	*r_novis; -cvar_t	*r_nocull; -cvar_t	*r_facePlaneCull; -cvar_t	*r_showcluster; -cvar_t	*r_nocurves; - -cvar_t	*r_allowExtensions; - -cvar_t	*r_ext_compressed_textures; -cvar_t	*r_ext_gamma_control; -cvar_t	*r_ext_multitexture; -cvar_t	*r_ext_compiled_vertex_array; -cvar_t	*r_ext_texture_env_add; - -cvar_t	*r_ignoreGLErrors; -cvar_t	*r_logFile; - -cvar_t	*r_stencilbits; -cvar_t	*r_depthbits; -cvar_t	*r_colorbits; -cvar_t	*r_stereo; -cvar_t	*r_primitives; -cvar_t	*r_texturebits; - -cvar_t	*r_drawBuffer; -cvar_t  *r_glDriver; -cvar_t	*r_lightmap; -cvar_t	*r_vertexLight; -cvar_t	*r_uiFullScreen; -cvar_t	*r_shadows; -cvar_t	*r_flares; -cvar_t	*r_mode; -cvar_t	*r_nobind; -cvar_t	*r_singleShader; -cvar_t	*r_roundImagesDown; -cvar_t	*r_colorMipLevels; -cvar_t	*r_picmip; -cvar_t	*r_showtris; -cvar_t	*r_showsky; -cvar_t	*r_shownormals; -cvar_t	*r_finish; -cvar_t	*r_clear; -cvar_t	*r_swapInterval; -cvar_t	*r_textureMode; -cvar_t	*r_offsetFactor; -cvar_t	*r_offsetUnits; -cvar_t	*r_gamma; -cvar_t	*r_intensity; -cvar_t	*r_lockpvs; -cvar_t	*r_noportals; -cvar_t	*r_portalOnly; - -cvar_t	*r_subdivisions; -cvar_t	*r_lodCurveError; - -cvar_t	*r_fullscreen; - -cvar_t	*r_customwidth; -cvar_t	*r_customheight; -cvar_t	*r_customaspect; - -cvar_t	*r_overBrightBits; -cvar_t	*r_mapOverBrightBits; - -cvar_t	*r_debugSurface; -cvar_t	*r_simpleMipMaps; - -cvar_t	*r_showImages; - -cvar_t	*r_ambientScale; -cvar_t	*r_directedScale; -cvar_t	*r_debugLight; -cvar_t	*r_debugSort; -cvar_t	*r_printShaders; -cvar_t	*r_saveFontData; - -cvar_t	*r_GLlibCoolDownMsec; - -cvar_t	*r_maxpolys; -int		max_polys; -cvar_t	*r_maxpolyverts; -int		max_polyverts; - -static void AssertCvarRange( cvar_t *cv, float minVal, float maxVal, qboolean shouldBeIntegral ) -{ -	if ( shouldBeIntegral ) -	{ -		if ( ( int ) cv->value != cv->integer ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' must be integral (%f)\n", cv->name, cv->value ); -			ri.Cvar_Set( cv->name, va( "%d", cv->integer ) ); -		} -	} - -	if ( cv->value < minVal ) -	{ -		ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' out of range (%f < %f)\n", cv->name, cv->value, minVal ); -		ri.Cvar_Set( cv->name, va( "%f", minVal ) ); -	} -	else if ( cv->value > maxVal ) -	{ -		ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' out of range (%f > %f)\n", cv->name, cv->value, maxVal ); -		ri.Cvar_Set( cv->name, va( "%f", maxVal ) ); -	} -} - - -/* -** InitOpenGL -** -** This function is responsible for initializing a valid OpenGL subsystem.  This -** is done by calling GLimp_Init (which gives us a working OGL subsystem) then -** setting variables, checking GL constants, and reporting the gfx system config -** to the user. -*/ -static void InitOpenGL( void ) -{ -	char renderer_buffer[1024]; - -	// -	// initialize OS specific portions of the renderer -	// -	// GLimp_Init directly or indirectly references the following cvars: -	//		- r_fullscreen -	//		- r_glDriver -	//		- r_mode -	//		- r_(color|depth|stencil)bits -	//		- r_ignorehwgamma -	//		- r_gamma -	// -	 -	if ( glConfig.vidWidth == 0 ) -	{ -		GLint		temp; -		 -		GLimp_Init(); - -		strcpy( renderer_buffer, glConfig.renderer_string ); -		Q_strlwr( renderer_buffer ); - -		// OpenGL driver constants -		qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp ); -		glConfig.maxTextureSize = temp; - -		// stubbed or broken drivers may have reported 0... -		if ( glConfig.maxTextureSize <= 0 )  -		{ -			glConfig.maxTextureSize = 0; -		} -	} - -	// init command buffers and SMP -	R_InitCommandBuffers(); - -	// print info -	GfxInfo_f(); - -	// set default state -	GL_SetDefaultState(); -} - -/* -================== -GL_CheckErrors -================== -*/ -void GL_CheckErrors( void ) { -    int		err; -    char	s[64]; - -    err = qglGetError(); -    if ( err == GL_NO_ERROR ) { -        return; -    } -    if ( r_ignoreGLErrors->integer ) { -        return; -    } -    switch( err ) { -        case GL_INVALID_ENUM: -            strcpy( s, "GL_INVALID_ENUM" ); -            break; -        case GL_INVALID_VALUE: -            strcpy( s, "GL_INVALID_VALUE" ); -            break; -        case GL_INVALID_OPERATION: -            strcpy( s, "GL_INVALID_OPERATION" ); -            break; -        case GL_STACK_OVERFLOW: -            strcpy( s, "GL_STACK_OVERFLOW" ); -            break; -        case GL_STACK_UNDERFLOW: -            strcpy( s, "GL_STACK_UNDERFLOW" ); -            break; -        case GL_OUT_OF_MEMORY: -            strcpy( s, "GL_OUT_OF_MEMORY" ); -            break; -        default: -            Com_sprintf( s, sizeof(s), "%i", err); -            break; -    } - -    ri.Error( ERR_FATAL, "GL_CheckErrors: %s", s ); -} - - -/* -** R_GetModeInfo -*/ -typedef struct vidmode_s -{ -    const char *description; -    int         width, height; -	float		pixelAspect;		// pixel width / height -} vidmode_t; - -vidmode_t r_vidModes[] = -{ -    { "Mode  0: 320x240",		320,	240,	1 }, -    { "Mode  1: 400x300",		400,	300,	1 }, -    { "Mode  2: 512x384",		512,	384,	1 }, -    { "Mode  3: 640x480",		640,	480,	1 }, -    { "Mode  4: 800x600",		800,	600,	1 }, -    { "Mode  5: 960x720",		960,	720,	1 }, -    { "Mode  6: 1024x768",		1024,	768,	1 }, -    { "Mode  7: 1152x864",		1152,	864,	1 }, -    { "Mode  8: 1280x1024",		1280,	1024,	1 }, -    { "Mode  9: 1600x1200",		1600,	1200,	1 }, -    { "Mode 10: 2048x1536",		2048,	1536,	1 }, -    { "Mode 11: 856x480 (wide)",856,	480,	1 } -}; -static int	s_numVidModes = ( sizeof( r_vidModes ) / sizeof( r_vidModes[0] ) ); - -qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode ) { -	vidmode_t	*vm; - -    if ( mode < -1 ) { -        return qfalse; -	} -	if ( mode >= s_numVidModes ) { -		return qfalse; -	} - -	if ( mode == -1 ) { -		*width = r_customwidth->integer; -		*height = r_customheight->integer; -		*windowAspect = r_customaspect->value; -		return qtrue; -	} - -	vm = &r_vidModes[mode]; - -    *width  = vm->width; -    *height = vm->height; -    *windowAspect = (float)vm->width / ( vm->height * vm->pixelAspect ); - -    return qtrue; -} - -/* -** R_ModeList_f -*/ -static void R_ModeList_f( void ) -{ -	int i; - -	ri.Printf( PRINT_ALL, "\n" ); -	for ( i = 0; i < s_numVidModes; i++ ) -	{ -		ri.Printf( PRINT_ALL, "%s\n", r_vidModes[i].description ); -	} -	ri.Printf( PRINT_ALL, "\n" ); -} - - -/*  -==============================================================================  -  -						SCREEN SHOTS  - -NOTE TTimo -some thoughts about the screenshots system: -screenshots get written in fs_homepath + fs_gamedir -vanilla q3 .. baseq3/screenshots/ *.tga -team arena .. missionpack/screenshots/ *.tga - -two commands: "screenshot" and "screenshotJPEG" -we use statics to store a count and start writing the first screenshot/screenshot????.tga (.jpg) available -(with FS_FileExists / FS_FOpenFileWrite calls) -FIXME: the statics don't get a reinit between fs_game changes - -==============================================================================  -*/  - -/*  -==================  -RB_TakeScreenshot -==================  -*/   -void RB_TakeScreenshot( int x, int y, int width, int height, char *fileName ) { -	byte		*buffer; -	int			i, c, temp; -		 -	buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*3+18); - -	Com_Memset (buffer, 0, 18); -	buffer[2] = 2;		// uncompressed type -	buffer[12] = width & 255; -	buffer[13] = width >> 8; -	buffer[14] = height & 255; -	buffer[15] = height >> 8; -	buffer[16] = 24;	// pixel size - -	qglReadPixels( x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 );  - -	// swap rgb to bgr -	c = 18 + width * height * 3; -	for (i=18 ; i<c ; i+=3) { -		temp = buffer[i]; -		buffer[i] = buffer[i+2]; -		buffer[i+2] = temp; -	} - -	// gamma correct -	if ( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma ) { -		R_GammaCorrect( buffer + 18, glConfig.vidWidth * glConfig.vidHeight * 3 ); -	} - -	ri.FS_WriteFile( fileName, buffer, c ); - -	ri.Hunk_FreeTempMemory( buffer ); -} - -/*  -==================  -RB_TakeScreenshotJPEG -==================  -*/   -void RB_TakeScreenshotJPEG( int x, int y, int width, int height, char *fileName ) { -	byte		*buffer; - -	buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*4); - -	qglReadPixels( x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer );  - -	// gamma correct -	if ( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma ) { -		R_GammaCorrect( buffer, glConfig.vidWidth * glConfig.vidHeight * 4 ); -	} - -	ri.FS_WriteFile( fileName, buffer, 1 );		// create path -	SaveJPG( fileName, 95, glConfig.vidWidth, glConfig.vidHeight, buffer); - -	ri.Hunk_FreeTempMemory( buffer ); -} - -/* -================== -RB_TakeScreenshotCmd -================== -*/ -const void *RB_TakeScreenshotCmd( const void *data ) { -	const screenshotCommand_t	*cmd; -	 -	cmd = (const screenshotCommand_t *)data; -	 -	if (cmd->jpeg) -		RB_TakeScreenshotJPEG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName); -	else -		RB_TakeScreenshot( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName); -	 -	return (const void *)(cmd + 1);	 -} - -/* -================== -R_TakeScreenshot -================== -*/ -void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean jpeg ) { -	static char	fileName[MAX_OSPATH]; // bad things if two screenshots per frame? -	screenshotCommand_t	*cmd; - -	cmd = R_GetCommandBuffer( sizeof( *cmd ) ); -	if ( !cmd ) { -		return; -	} -	cmd->commandId = RC_SCREENSHOT; - -	cmd->x = x; -	cmd->y = y; -	cmd->width = width; -	cmd->height = height; -	Q_strncpyz( fileName, name, sizeof(fileName) ); -	cmd->fileName = fileName; -	cmd->jpeg = jpeg; -} - -/*  -==================  -R_ScreenshotFilename -==================  -*/   -void R_ScreenshotFilename( int lastNumber, char *fileName ) { -	int		a,b,c,d; - -	if ( lastNumber < 0 || lastNumber > 9999 ) { -		Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.tga" ); -		return; -	} - -	a = lastNumber / 1000; -	lastNumber -= a*1000; -	b = lastNumber / 100; -	lastNumber -= b*100; -	c = lastNumber / 10; -	lastNumber -= c*10; -	d = lastNumber; - -	Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.tga" -		, a, b, c, d ); -} - -/*  -==================  -R_ScreenshotFilename -==================  -*/   -void R_ScreenshotFilenameJPEG( int lastNumber, char *fileName ) { -	int		a,b,c,d; - -	if ( lastNumber < 0 || lastNumber > 9999 ) { -		Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.jpg" ); -		return; -	} - -	a = lastNumber / 1000; -	lastNumber -= a*1000; -	b = lastNumber / 100; -	lastNumber -= b*100; -	c = lastNumber / 10; -	lastNumber -= c*10; -	d = lastNumber; - -	Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.jpg" -		, a, b, c, d ); -} - -/* -==================== -R_LevelShot - -levelshots are specialized 128*128 thumbnails for -the menu system, sampled down from full screen distorted images -==================== -*/ -void R_LevelShot( void ) { -	char		checkname[MAX_OSPATH]; -	byte		*buffer; -	byte		*source; -	byte		*src, *dst; -	int			x, y; -	int			r, g, b; -	float		xScale, yScale; -	int			xx, yy; - -	sprintf( checkname, "levelshots/%s.tga", tr.world->baseName ); - -	source = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight * 3 ); - -	buffer = ri.Hunk_AllocateTempMemory( 128 * 128*3 + 18); -	Com_Memset (buffer, 0, 18); -	buffer[2] = 2;		// uncompressed type -	buffer[12] = 128; -	buffer[14] = 128; -	buffer[16] = 24;	// pixel size - -	qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGB, GL_UNSIGNED_BYTE, source );  - -	// resample from source -	xScale = glConfig.vidWidth / 512.0f; -	yScale = glConfig.vidHeight / 384.0f; -	for ( y = 0 ; y < 128 ; y++ ) { -		for ( x = 0 ; x < 128 ; x++ ) { -			r = g = b = 0; -			for ( yy = 0 ; yy < 3 ; yy++ ) { -				for ( xx = 0 ; xx < 4 ; xx++ ) { -					src = source + 3 * ( glConfig.vidWidth * (int)( (y*3+yy)*yScale ) + (int)( (x*4+xx)*xScale ) ); -					r += src[0]; -					g += src[1]; -					b += src[2]; -				} -			} -			dst = buffer + 18 + 3 * ( y * 128 + x ); -			dst[0] = b / 12; -			dst[1] = g / 12; -			dst[2] = r / 12; -		} -	} - -	// gamma correct -	if ( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma ) { -		R_GammaCorrect( buffer + 18, 128 * 128 * 3 ); -	} - -	ri.FS_WriteFile( checkname, buffer, 128 * 128*3 + 18 ); - -	ri.Hunk_FreeTempMemory( buffer ); -	ri.Hunk_FreeTempMemory( source ); - -	ri.Printf( PRINT_ALL, "Wrote %s\n", checkname ); -} - -/*  -==================  -R_ScreenShot_f - -screenshot -screenshot [silent] -screenshot [levelshot] -screenshot [filename] - -Doesn't print the pacifier message if there is a second arg -==================  -*/   -void R_ScreenShot_f (void) { -	char	checkname[MAX_OSPATH]; -	static	int	lastNumber = -1; -	qboolean	silent; - -	if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) { -		R_LevelShot(); -		return; -	} - -	if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) { -		silent = qtrue; -	} else { -		silent = qfalse; -	} - -	if ( ri.Cmd_Argc() == 2 && !silent ) { -		// explicit filename -		Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.tga", ri.Cmd_Argv( 1 ) ); -	} else { -		// scan for a free filename - -		// if we have saved a previous screenshot, don't scan -		// again, because recording demo avis can involve -		// thousands of shots -		if ( lastNumber == -1 ) { -			lastNumber = 0; -		} -		// scan for a free number -		for ( ; lastNumber <= 9999 ; lastNumber++ ) { -			R_ScreenshotFilename( lastNumber, checkname ); - -      if (!ri.FS_FileExists( checkname )) -      { -        break; // file doesn't exist -      } -		} - -		if ( lastNumber >= 9999 ) { -			ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n");  -			return; - 		} - -		lastNumber++; -	} - -	R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qfalse ); - -	if ( !silent ) { -		ri.Printf (PRINT_ALL, "Wrote %s\n", checkname); -	} -}  - -void R_ScreenShotJPEG_f (void) { -	char		checkname[MAX_OSPATH]; -	static	int	lastNumber = -1; -	qboolean	silent; - -	if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) { -		R_LevelShot(); -		return; -	} - -	if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) { -		silent = qtrue; -	} else { -		silent = qfalse; -	} - -	if ( ri.Cmd_Argc() == 2 && !silent ) { -		// explicit filename -		Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.jpg", ri.Cmd_Argv( 1 ) ); -	} else { -		// scan for a free filename - -		// if we have saved a previous screenshot, don't scan -		// again, because recording demo avis can involve -		// thousands of shots -		if ( lastNumber == -1 ) { -			lastNumber = 0; -		} -		// scan for a free number -		for ( ; lastNumber <= 9999 ; lastNumber++ ) { -			R_ScreenshotFilenameJPEG( lastNumber, checkname ); - -      if (!ri.FS_FileExists( checkname )) -      { -        break; // file doesn't exist -      } -		} - -		if ( lastNumber == 10000 ) { -			ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n");  -			return; - 		} - -		lastNumber++; -	} - -	R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qtrue ); - -	if ( !silent ) { -		ri.Printf (PRINT_ALL, "Wrote %s\n", checkname); -	} -}  - -//============================================================================ - -/* -** GL_SetDefaultState -*/ -void GL_SetDefaultState( void ) -{ -	qglClearDepth( 1.0f ); - -	qglCullFace(GL_FRONT); - -	qglColor4f (1,1,1,1); - -	// initialize downstream texture unit if we're running -	// in a multitexture environment -	if ( qglActiveTextureARB ) { -		GL_SelectTexture( 1 ); -		GL_TextureMode( r_textureMode->string ); -		GL_TexEnv( GL_MODULATE ); -		qglDisable( GL_TEXTURE_2D ); -		GL_SelectTexture( 0 ); -	} - -	qglEnable(GL_TEXTURE_2D); -	GL_TextureMode( r_textureMode->string ); -	GL_TexEnv( GL_MODULATE ); - -	qglShadeModel( GL_SMOOTH ); -	qglDepthFunc( GL_LEQUAL ); - -	// the vertex array is always enabled, but the color and texture -	// arrays are enabled and disabled around the compiled vertex array call -	qglEnableClientState (GL_VERTEX_ARRAY); - -	// -	// make sure our GL state vector is set correctly -	// -	glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE; - -	qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); -	qglDepthMask( GL_TRUE ); -	qglDisable( GL_DEPTH_TEST ); -	qglEnable( GL_SCISSOR_TEST ); -	qglDisable( GL_CULL_FACE ); -	qglDisable( GL_BLEND ); -} - - -/* -================ -GfxInfo_f -================ -*/ -void GfxInfo_f( void )  -{ -	cvar_t *sys_cpustring = ri.Cvar_Get( "sys_cpustring", "", 0 ); -	const char *enablestrings[] = -	{ -		"disabled", -		"enabled" -	}; -	const char *fsstrings[] = -	{ -		"windowed", -		"fullscreen" -	}; - -	ri.Printf( PRINT_ALL, "\nGL_VENDOR: %s\n", glConfig.vendor_string ); -	ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string ); -	ri.Printf( PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string ); -	ri.Printf( PRINT_ALL, "GL_EXTENSIONS: %s\n", glConfig.extensions_string ); -	ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize ); -	ri.Printf( PRINT_ALL, "GL_MAX_ACTIVE_TEXTURES_ARB: %d\n", glConfig.maxActiveTextures ); -	ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits ); -	ri.Printf( PRINT_ALL, "MODE: %d, %d x %d %s hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1] ); -	if ( glConfig.displayFrequency ) -	{ -		ri.Printf( PRINT_ALL, "%d\n", glConfig.displayFrequency ); -	} -	else -	{ -		ri.Printf( PRINT_ALL, "N/A\n" ); -	} -	if ( glConfig.deviceSupportsGamma ) -	{ -		ri.Printf( PRINT_ALL, "GAMMA: hardware w/ %d overbright bits\n", tr.overbrightBits ); -	} -	else -	{ -		ri.Printf( PRINT_ALL, "GAMMA: software w/ %d overbright bits\n", tr.overbrightBits ); -	} -	ri.Printf( PRINT_ALL, "CPU: %s\n", sys_cpustring->string ); - -	// rendering primitives -	{ -		int		primitives; - -		// default is to use triangles if compiled vertex arrays are present -		ri.Printf( PRINT_ALL, "rendering primitives: " ); -		primitives = r_primitives->integer; -		if ( primitives == 0 ) { -			if ( qglLockArraysEXT ) { -				primitives = 2; -			} else { -				primitives = 1; -			} -		} -		if ( primitives == -1 ) { -			ri.Printf( PRINT_ALL, "none\n" ); -		} else if ( primitives == 2 ) { -			ri.Printf( PRINT_ALL, "single glDrawElements\n" ); -		} else if ( primitives == 1 ) { -			ri.Printf( PRINT_ALL, "multiple glArrayElement\n" ); -		} else if ( primitives == 3 ) { -			ri.Printf( PRINT_ALL, "multiple glColor4ubv + glTexCoord2fv + glVertex3fv\n" ); -		} -	} - -	ri.Printf( PRINT_ALL, "texturemode: %s\n", r_textureMode->string ); -	ri.Printf( PRINT_ALL, "picmip: %d\n", r_picmip->integer ); -	ri.Printf( PRINT_ALL, "texture bits: %d\n", r_texturebits->integer ); -	ri.Printf( PRINT_ALL, "multitexture: %s\n", enablestrings[qglActiveTextureARB != 0] ); -	ri.Printf( PRINT_ALL, "compiled vertex arrays: %s\n", enablestrings[qglLockArraysEXT != 0 ] ); -	ri.Printf( PRINT_ALL, "texenv add: %s\n", enablestrings[glConfig.textureEnvAddAvailable != 0] ); -	ri.Printf( PRINT_ALL, "compressed textures: %s\n", enablestrings[glConfig.textureCompression!=TC_NONE] ); -	if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) -	{ -		ri.Printf( PRINT_ALL, "HACK: using vertex lightmap approximation\n" ); -	} -	if ( glConfig.hardwareType == GLHW_RAGEPRO ) -	{ -		ri.Printf( PRINT_ALL, "HACK: ragePro approximations\n" ); -	} -	if ( glConfig.hardwareType == GLHW_RIVA128 ) -	{ -		ri.Printf( PRINT_ALL, "HACK: riva128 approximations\n" ); -	} -	if ( glConfig.smpActive ) { -		ri.Printf( PRINT_ALL, "Using dual processor acceleration\n" ); -	} -	if ( r_finish->integer ) { -		ri.Printf( PRINT_ALL, "Forcing glFinish\n" ); -	} -} - -/* -=============== -R_Register -=============== -*/ -void R_Register( void )  -{ -	// -	// latched and archived variables -	// -	r_glDriver = ri.Cvar_Get( "r_glDriver", OPENGL_DRIVER_NAME, CVAR_ARCHIVE | CVAR_LATCH ); -	r_allowExtensions = ri.Cvar_Get( "r_allowExtensions", "1", CVAR_ARCHIVE | CVAR_LATCH ); -	r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compressed_textures", "0", CVAR_ARCHIVE | CVAR_LATCH ); -	r_ext_gamma_control = ri.Cvar_Get( "r_ext_gamma_control", "1", CVAR_ARCHIVE | CVAR_LATCH ); -	r_ext_multitexture = ri.Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE | CVAR_LATCH ); -	r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH); -#ifdef __linux__ // broken on linux -	r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "0", CVAR_ARCHIVE | CVAR_LATCH); -#else -	r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH); -#endif - -	r_picmip = ri.Cvar_Get ("r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH ); -	r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH ); -	r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH ); -	AssertCvarRange( r_picmip, 0, 16, qtrue ); -	r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH ); -	r_texturebits = ri.Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH ); -	r_colorbits = ri.Cvar_Get( "r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH ); -	r_stereo = ri.Cvar_Get( "r_stereo", "0", CVAR_ARCHIVE | CVAR_LATCH ); -#ifdef __linux__ -	r_stencilbits = ri.Cvar_Get( "r_stencilbits", "0", CVAR_ARCHIVE | CVAR_LATCH ); -#else -	r_stencilbits = ri.Cvar_Get( "r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH ); -#endif -	r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH ); -	r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH ); -	r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH); -	r_mode = ri.Cvar_Get( "r_mode", "3", CVAR_ARCHIVE | CVAR_LATCH ); -	r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH ); -	r_customwidth = ri.Cvar_Get( "r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH ); -	r_customheight = ri.Cvar_Get( "r_customheight", "1024", CVAR_ARCHIVE | CVAR_LATCH ); -	r_customaspect = ri.Cvar_Get( "r_customaspect", "1", CVAR_ARCHIVE | CVAR_LATCH ); -	r_simpleMipMaps = ri.Cvar_Get( "r_simpleMipMaps", "1", CVAR_ARCHIVE | CVAR_LATCH ); -	r_vertexLight = ri.Cvar_Get( "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH ); -	r_uiFullScreen = ri.Cvar_Get( "r_uifullscreen", "0", 0); -	r_subdivisions = ri.Cvar_Get ("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH); -	r_smp = ri.Cvar_Get( "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH); -	r_ignoreFastPath = ri.Cvar_Get( "r_ignoreFastPath", "1", CVAR_ARCHIVE | CVAR_LATCH ); - -	// -	// temporary latched variables that can only change over a restart -	// -	r_displayRefresh = ri.Cvar_Get( "r_displayRefresh", "0", CVAR_LATCH ); -	AssertCvarRange( r_displayRefresh, 0, 200, qtrue ); -	r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT ); -	r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH ); -	r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH ); -	r_singleShader = ri.Cvar_Get ("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH ); - -	// -	// archived variables that can change at any time -	// -	r_lodCurveError = ri.Cvar_Get( "r_lodCurveError", "250", CVAR_ARCHIVE|CVAR_CHEAT ); -	r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE ); -	r_flares = ri.Cvar_Get ("r_flares", "0", CVAR_ARCHIVE ); -	r_znear = ri.Cvar_Get( "r_znear", "4", CVAR_CHEAT ); -	AssertCvarRange( r_znear, 0.001f, 200, qtrue ); -	r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE ); -	r_fastsky = ri.Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE ); -	r_inGameVideo = ri.Cvar_Get( "r_inGameVideo", "1", CVAR_ARCHIVE ); -	r_drawSun = ri.Cvar_Get( "r_drawSun", "0", CVAR_ARCHIVE ); -	r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE ); -	r_dlightBacks = ri.Cvar_Get( "r_dlightBacks", "1", CVAR_ARCHIVE ); -	r_finish = ri.Cvar_Get ("r_finish", "0", CVAR_ARCHIVE); -	r_textureMode = ri.Cvar_Get( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE ); -	r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0", CVAR_ARCHIVE ); -	r_gamma = ri.Cvar_Get( "r_gamma", "1", CVAR_ARCHIVE ); -	r_facePlaneCull = ri.Cvar_Get ("r_facePlaneCull", "1", CVAR_ARCHIVE ); - -	r_railWidth = ri.Cvar_Get( "r_railWidth", "16", CVAR_ARCHIVE ); -	r_railCoreWidth = ri.Cvar_Get( "r_railCoreWidth", "6", CVAR_ARCHIVE ); -	r_railSegmentLength = ri.Cvar_Get( "r_railSegmentLength", "32", CVAR_ARCHIVE ); - -	r_primitives = ri.Cvar_Get( "r_primitives", "0", CVAR_ARCHIVE ); - -	r_ambientScale = ri.Cvar_Get( "r_ambientScale", "0.6", CVAR_CHEAT ); -	r_directedScale = ri.Cvar_Get( "r_directedScale", "1", CVAR_CHEAT ); - -	// -	// temporary variables that can change at any time -	// -	r_showImages = ri.Cvar_Get( "r_showImages", "0", CVAR_TEMP ); - -	r_debugLight = ri.Cvar_Get( "r_debuglight", "0", CVAR_TEMP ); -	r_debugSort = ri.Cvar_Get( "r_debugSort", "0", CVAR_CHEAT ); -	r_printShaders = ri.Cvar_Get( "r_printShaders", "0", 0 ); -	r_saveFontData = ri.Cvar_Get( "r_saveFontData", "0", 0 ); - -	r_nocurves = ri.Cvar_Get ("r_nocurves", "0", CVAR_CHEAT ); -	r_drawworld = ri.Cvar_Get ("r_drawworld", "1", CVAR_CHEAT ); -	r_lightmap = ri.Cvar_Get ("r_lightmap", "0", 0 ); -	r_portalOnly = ri.Cvar_Get ("r_portalOnly", "0", CVAR_CHEAT ); - -	r_flareSize = ri.Cvar_Get ("r_flareSize", "40", CVAR_CHEAT); -	r_flareFade = ri.Cvar_Get ("r_flareFade", "7", CVAR_CHEAT); - -	r_showSmp = ri.Cvar_Get ("r_showSmp", "0", CVAR_CHEAT); -	r_skipBackEnd = ri.Cvar_Get ("r_skipBackEnd", "0", CVAR_CHEAT); - -	r_measureOverdraw = ri.Cvar_Get( "r_measureOverdraw", "0", CVAR_CHEAT ); -	r_lodscale = ri.Cvar_Get( "r_lodscale", "5", CVAR_CHEAT ); -	r_norefresh = ri.Cvar_Get ("r_norefresh", "0", CVAR_CHEAT); -	r_drawentities = ri.Cvar_Get ("r_drawentities", "1", CVAR_CHEAT ); -	r_ignore = ri.Cvar_Get( "r_ignore", "1", CVAR_CHEAT ); -	r_nocull = ri.Cvar_Get ("r_nocull", "0", CVAR_CHEAT); -	r_novis = ri.Cvar_Get ("r_novis", "0", CVAR_CHEAT); -	r_showcluster = ri.Cvar_Get ("r_showcluster", "0", CVAR_CHEAT); -	r_speeds = ri.Cvar_Get ("r_speeds", "0", CVAR_CHEAT); -	r_verbose = ri.Cvar_Get( "r_verbose", "0", CVAR_CHEAT ); -	r_logFile = ri.Cvar_Get( "r_logFile", "0", CVAR_CHEAT ); -	r_debugSurface = ri.Cvar_Get ("r_debugSurface", "0", CVAR_CHEAT); -	r_nobind = ri.Cvar_Get ("r_nobind", "0", CVAR_CHEAT); -	r_showtris = ri.Cvar_Get ("r_showtris", "0", CVAR_CHEAT); -	r_showsky = ri.Cvar_Get ("r_showsky", "0", CVAR_CHEAT); -	r_shownormals = ri.Cvar_Get ("r_shownormals", "0", CVAR_CHEAT); -	r_clear = ri.Cvar_Get ("r_clear", "0", CVAR_CHEAT); -	r_offsetFactor = ri.Cvar_Get( "r_offsetfactor", "-1", CVAR_CHEAT ); -	r_offsetUnits = ri.Cvar_Get( "r_offsetunits", "-2", CVAR_CHEAT ); -	r_drawBuffer = ri.Cvar_Get( "r_drawBuffer", "GL_BACK", CVAR_CHEAT ); -	r_lockpvs = ri.Cvar_Get ("r_lockpvs", "0", CVAR_CHEAT); -	r_noportals = ri.Cvar_Get ("r_noportals", "0", CVAR_CHEAT); -	r_shadows = ri.Cvar_Get( "cg_shadows", "1", 0 ); - -	r_maxpolys = ri.Cvar_Get( "r_maxpolys", va("%d", MAX_POLYS), 0); -	r_maxpolyverts = ri.Cvar_Get( "r_maxpolyverts", va("%d", MAX_POLYVERTS), 0); - -	r_GLlibCoolDownMsec = ri.Cvar_Get( "r_GLlibCoolDownMsec", "0", CVAR_ARCHIVE ); -   -	// make sure all the commands added here are also -	// removed in R_Shutdown -	ri.Cmd_AddCommand( "imagelist", R_ImageList_f ); -	ri.Cmd_AddCommand( "shaderlist", R_ShaderList_f ); -	ri.Cmd_AddCommand( "skinlist", R_SkinList_f ); -	ri.Cmd_AddCommand( "modellist", R_Modellist_f ); -	ri.Cmd_AddCommand( "modelist", R_ModeList_f ); -	ri.Cmd_AddCommand( "screenshot", R_ScreenShot_f ); -	ri.Cmd_AddCommand( "screenshotJPEG", R_ScreenShotJPEG_f ); -	ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f ); -} - -/* -=============== -R_Init -=============== -*/ -void R_Init( void ) {	 -	int	err; -	int i; -	byte *ptr; - -	ri.Printf( PRINT_ALL, "----- R_Init -----\n" ); - -	// clear all our internal state -	Com_Memset( &tr, 0, sizeof( tr ) ); -	Com_Memset( &backEnd, 0, sizeof( backEnd ) ); -	Com_Memset( &tess, 0, sizeof( tess ) ); - -//	Swap_Init(); - -	if ( (int)tess.xyz & 15 ) { -		Com_Printf( "WARNING: tess.xyz not 16 byte aligned\n" ); -	} -	Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) ); - -	// -	// init function tables -	// -	for ( i = 0; i < FUNCTABLE_SIZE; i++ ) -	{ -		tr.sinTable[i]		= sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); -		tr.squareTable[i]	= ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f; -		tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; -		tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; - -		if ( i < FUNCTABLE_SIZE / 2 ) -		{ -			if ( i < FUNCTABLE_SIZE / 4 ) -			{ -				tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); -			} -			else -			{ -				tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4]; -			} -		} -		else -		{ -			tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2]; -		} -	} - -	R_InitFogTable(); - -	R_NoiseInit(); - -	R_Register(); - -	max_polys = r_maxpolys->integer; -	if (max_polys < MAX_POLYS) -		max_polys = MAX_POLYS; - -	max_polyverts = r_maxpolyverts->integer; -	if (max_polyverts < MAX_POLYVERTS) -		max_polyverts = MAX_POLYVERTS; - -	ptr = ri.Hunk_Alloc( sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low); -	backEndData[0] = (backEndData_t *) ptr; -	backEndData[0]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[0] )); -	backEndData[0]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys); -	if ( r_smp->integer ) { -		ptr = ri.Hunk_Alloc( sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low); -		backEndData[1] = (backEndData_t *) ptr; -		backEndData[1]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[1] )); -		backEndData[1]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys); -	} else { -		backEndData[1] = NULL; -	} -	R_ToggleSmpFrame(); - -	InitOpenGL(); - -	R_InitImages(); - -	R_InitShaders(); - -	R_InitSkins(); - -	R_ModelInit(); - -	R_InitFreeType(); - - -	err = qglGetError(); -	if ( err != GL_NO_ERROR ) -		ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err); - -	ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" ); -} - -/* -=============== -RE_Shutdown -=============== -*/ -void RE_Shutdown( qboolean destroyWindow ) {	 - -	ri.Printf( PRINT_ALL, "RE_Shutdown( %i )\n", destroyWindow ); - -	ri.Cmd_RemoveCommand ("modellist"); -	ri.Cmd_RemoveCommand ("screenshotJPEG"); -	ri.Cmd_RemoveCommand ("screenshot"); -	ri.Cmd_RemoveCommand ("imagelist"); -	ri.Cmd_RemoveCommand ("shaderlist"); -	ri.Cmd_RemoveCommand ("skinlist"); -	ri.Cmd_RemoveCommand ("gfxinfo"); -	ri.Cmd_RemoveCommand( "modelist" ); -	ri.Cmd_RemoveCommand( "shaderstate" ); - - -	if ( tr.registered ) { -		R_SyncRenderThread(); -		R_ShutdownCommandBuffers(); -		R_DeleteTextures(); -	} - -	R_DoneFreeType(); - -	// shut down platform specific OpenGL stuff -	if ( destroyWindow ) { -		GLimp_Shutdown(); -	} - -	tr.registered = qfalse; -} - - -/* -============= -RE_EndRegistration - -Touch all images to make sure they are resident -============= -*/ -void RE_EndRegistration( void ) { -	R_SyncRenderThread(); -	if (!Sys_LowPhysicalMemory()) { -		RB_ShowImages(); -	} -} - - -/* -@@@@@@@@@@@@@@@@@@@@@ -GetRefAPI - -@@@@@@@@@@@@@@@@@@@@@ -*/ -refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) { -	static refexport_t	re; - -	ri = *rimp; - -	Com_Memset( &re, 0, sizeof( re ) ); - -	if ( apiVersion != REF_API_VERSION ) { -		ri.Printf(PRINT_ALL, "Mismatched REF_API_VERSION: expected %i, got %i\n",  -			REF_API_VERSION, apiVersion ); -		return NULL; -	} - -	// the RE_ functions are Renderer Entry points - -	re.Shutdown = RE_Shutdown; - -	re.BeginRegistration = RE_BeginRegistration; -	re.RegisterModel = RE_RegisterModel; -	re.RegisterSkin = RE_RegisterSkin; -	re.RegisterShader = RE_RegisterShader; -	re.RegisterShaderNoMip = RE_RegisterShaderNoMip; -	re.LoadWorld = RE_LoadWorldMap; -	re.SetWorldVisData = RE_SetWorldVisData; -	re.EndRegistration = RE_EndRegistration; - -	re.BeginFrame = RE_BeginFrame; -	re.EndFrame = RE_EndFrame; - -	re.MarkFragments = R_MarkFragments; -	re.LerpTag = R_LerpTag; -	re.ModelBounds = R_ModelBounds; - -	re.ClearScene = RE_ClearScene; -	re.AddRefEntityToScene = RE_AddRefEntityToScene; -	re.AddPolyToScene = RE_AddPolyToScene; -	re.LightForPoint = R_LightForPoint; -	re.AddLightToScene = RE_AddLightToScene; -	re.AddAdditiveLightToScene = RE_AddAdditiveLightToScene; -	re.RenderScene = RE_RenderScene; - -	re.SetColor = RE_SetColor; -	re.DrawStretchPic = RE_StretchPic; -	re.DrawStretchRaw = RE_StretchRaw; -	re.UploadCinematic = RE_UploadCinematic; - -	re.RegisterFont = RE_RegisterFont; -	re.RemapShader = R_RemapShader; -	re.GetEntityToken = R_GetEntityToken; -	re.inPVS = R_inPVS; - -	return &re; -} diff --git a/ioq3-r437/src/renderer/tr_light.c b/ioq3-r437/src/renderer/tr_light.c deleted file mode 100644 index c21ade73..00000000 --- a/ioq3-r437/src/renderer/tr_light.c +++ /dev/null @@ -1,395 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_light.c - -#include "tr_local.h" - -#define	DLIGHT_AT_RADIUS		16 -// at the edge of a dlight's influence, this amount of light will be added - -#define	DLIGHT_MINIMUM_RADIUS	16		 -// never calculate a range less than this to prevent huge light numbers - - -/* -=============== -R_TransformDlights - -Transforms the origins of an array of dlights. -Used by both the front end (for DlightBmodel) and -the back end (before doing the lighting calculation) -=============== -*/ -void R_TransformDlights( int count, dlight_t *dl, orientationr_t *or) { -	int		i; -	vec3_t	temp; - -	for ( i = 0 ; i < count ; i++, dl++ ) { -		VectorSubtract( dl->origin, or->origin, temp ); -		dl->transformed[0] = DotProduct( temp, or->axis[0] ); -		dl->transformed[1] = DotProduct( temp, or->axis[1] ); -		dl->transformed[2] = DotProduct( temp, or->axis[2] ); -	} -} - -/* -============= -R_DlightBmodel - -Determine which dynamic lights may effect this bmodel -============= -*/ -void R_DlightBmodel( bmodel_t *bmodel ) { -	int			i, j; -	dlight_t	*dl; -	int			mask; -	msurface_t	*surf; - -	// transform all the lights -	R_TransformDlights( tr.refdef.num_dlights, tr.refdef.dlights, &tr.or ); - -	mask = 0; -	for ( i=0 ; i<tr.refdef.num_dlights ; i++ ) { -		dl = &tr.refdef.dlights[i]; - -		// see if the point is close enough to the bounds to matter -		for ( j = 0 ; j < 3 ; j++ ) { -			if ( dl->transformed[j] - bmodel->bounds[1][j] > dl->radius ) { -				break; -			} -			if ( bmodel->bounds[0][j] - dl->transformed[j] > dl->radius ) { -				break; -			} -		} -		if ( j < 3 ) { -			continue; -		} - -		// we need to check this light -		mask |= 1 << i; -	} - -	tr.currentEntity->needDlights = (mask != 0); - -	// set the dlight bits in all the surfaces -	for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) { -		surf = bmodel->firstSurface + i; - -		if ( *surf->data == SF_FACE ) { -			((srfSurfaceFace_t *)surf->data)->dlightBits[ tr.smpFrame ] = mask; -		} else if ( *surf->data == SF_GRID ) { -			((srfGridMesh_t *)surf->data)->dlightBits[ tr.smpFrame ] = mask; -		} else if ( *surf->data == SF_TRIANGLES ) { -			((srfTriangles_t *)surf->data)->dlightBits[ tr.smpFrame ] = mask; -		} -	} -} - - -/* -============================================================================= - -LIGHT SAMPLING - -============================================================================= -*/ - -extern	cvar_t	*r_ambientScale; -extern	cvar_t	*r_directedScale; -extern	cvar_t	*r_debugLight; - -/* -================= -R_SetupEntityLightingGrid - -================= -*/ -static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) { -	vec3_t	lightOrigin; -	int		pos[3]; -	int		i, j; -	byte	*gridData; -	float	frac[3]; -	int		gridStep[3]; -	vec3_t	direction; -	float	totalFactor; - -	if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) { -		// seperate lightOrigins are needed so an object that is -		// sinking into the ground can still be lit, and so -		// multi-part models can be lit identically -		VectorCopy( ent->e.lightingOrigin, lightOrigin ); -	} else { -		VectorCopy( ent->e.origin, lightOrigin ); -	} - -	VectorSubtract( lightOrigin, tr.world->lightGridOrigin, lightOrigin ); -	for ( i = 0 ; i < 3 ; i++ ) { -		float	v; - -		v = lightOrigin[i]*tr.world->lightGridInverseSize[i]; -		pos[i] = floor( v ); -		frac[i] = v - pos[i]; -		if ( pos[i] < 0 ) { -			pos[i] = 0; -		} else if ( pos[i] >= tr.world->lightGridBounds[i] - 1 ) { -			pos[i] = tr.world->lightGridBounds[i] - 1; -		} -	} - -	VectorClear( ent->ambientLight ); -	VectorClear( ent->directedLight ); -	VectorClear( direction ); - -	assert( tr.world->lightGridData ); // bk010103 - NULL with -nolight maps - -	// trilerp the light value -	gridStep[0] = 8; -	gridStep[1] = 8 * tr.world->lightGridBounds[0]; -	gridStep[2] = 8 * tr.world->lightGridBounds[0] * tr.world->lightGridBounds[1]; -	gridData = tr.world->lightGridData + pos[0] * gridStep[0] -		+ pos[1] * gridStep[1] + pos[2] * gridStep[2]; - -	totalFactor = 0; -	for ( i = 0 ; i < 8 ; i++ ) { -		float	factor; -		byte	*data; -		int		lat, lng; -		vec3_t	normal; -		#if idppc -		float d0, d1, d2, d3, d4, d5; -		#endif -		factor = 1.0; -		data = gridData; -		for ( j = 0 ; j < 3 ; j++ ) { -			if ( i & (1<<j) ) { -				factor *= frac[j]; -				data += gridStep[j]; -			} else { -				factor *= (1.0f - frac[j]); -			} -		} - -		if ( !(data[0]+data[1]+data[2]) ) { -			continue;	// ignore samples in walls -		} -		totalFactor += factor; -		#if idppc -		d0 = data[0]; d1 = data[1]; d2 = data[2]; -		d3 = data[3]; d4 = data[4]; d5 = data[5]; - -		ent->ambientLight[0] += factor * d0; -		ent->ambientLight[1] += factor * d1; -		ent->ambientLight[2] += factor * d2; - -		ent->directedLight[0] += factor * d3; -		ent->directedLight[1] += factor * d4; -		ent->directedLight[2] += factor * d5; -		#else -		ent->ambientLight[0] += factor * data[0]; -		ent->ambientLight[1] += factor * data[1]; -		ent->ambientLight[2] += factor * data[2]; - -		ent->directedLight[0] += factor * data[3]; -		ent->directedLight[1] += factor * data[4]; -		ent->directedLight[2] += factor * data[5]; -		#endif -		lat = data[7]; -		lng = data[6]; -		lat *= (FUNCTABLE_SIZE/256); -		lng *= (FUNCTABLE_SIZE/256); - -		// decode X as cos( lat ) * sin( long ) -		// decode Y as sin( lat ) * sin( long ) -		// decode Z as cos( long ) - -		normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; -		normal[1] = tr.sinTable[lat] * tr.sinTable[lng]; -		normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - -		VectorMA( direction, factor, normal, direction ); -	} - -	if ( totalFactor > 0 && totalFactor < 0.99 ) { -		totalFactor = 1.0f / totalFactor; -		VectorScale( ent->ambientLight, totalFactor, ent->ambientLight ); -		VectorScale( ent->directedLight, totalFactor, ent->directedLight ); -	} - -	VectorScale( ent->ambientLight, r_ambientScale->value, ent->ambientLight ); -	VectorScale( ent->directedLight, r_directedScale->value, ent->directedLight ); - -	VectorNormalize2( direction, ent->lightDir ); -} - - -/* -=============== -LogLight -=============== -*/ -static void LogLight( trRefEntity_t *ent ) { -	int	max1, max2; - -	if ( !(ent->e.renderfx & RF_FIRST_PERSON ) ) { -		return; -	} - -	max1 = ent->ambientLight[0]; -	if ( ent->ambientLight[1] > max1 ) { -		max1 = ent->ambientLight[1]; -	} else if ( ent->ambientLight[2] > max1 ) { -		max1 = ent->ambientLight[2]; -	} - -	max2 = ent->directedLight[0]; -	if ( ent->directedLight[1] > max2 ) { -		max2 = ent->directedLight[1]; -	} else if ( ent->directedLight[2] > max2 ) { -		max2 = ent->directedLight[2]; -	} - -	ri.Printf( PRINT_ALL, "amb:%i  dir:%i\n", max1, max2 ); -} - -/* -================= -R_SetupEntityLighting - -Calculates all the lighting values that will be used -by the Calc_* functions -================= -*/ -void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) { -	int				i; -	dlight_t		*dl; -	float			power; -	vec3_t			dir; -	float			d; -	vec3_t			lightDir; -	vec3_t			lightOrigin; - -	// lighting calculations  -	if ( ent->lightingCalculated ) { -		return; -	} -	ent->lightingCalculated = qtrue; - -	// -	// trace a sample point down to find ambient light -	// -	if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) { -		// seperate lightOrigins are needed so an object that is -		// sinking into the ground can still be lit, and so -		// multi-part models can be lit identically -		VectorCopy( ent->e.lightingOrigin, lightOrigin ); -	} else { -		VectorCopy( ent->e.origin, lightOrigin ); -	} - -	// if NOWORLDMODEL, only use dynamic lights (menu system, etc) -	if ( !(refdef->rdflags & RDF_NOWORLDMODEL )  -		&& tr.world->lightGridData ) { -		R_SetupEntityLightingGrid( ent ); -	} else { -		ent->ambientLight[0] = ent->ambientLight[1] =  -			ent->ambientLight[2] = tr.identityLight * 150; -		ent->directedLight[0] = ent->directedLight[1] =  -			ent->directedLight[2] = tr.identityLight * 150; -		VectorCopy( tr.sunDirection, ent->lightDir ); -	} - -	// bonus items and view weapons have a fixed minimum add -	if ( 1 /* ent->e.renderfx & RF_MINLIGHT */ ) { -		// give everything a minimum light add -		ent->ambientLight[0] += tr.identityLight * 32; -		ent->ambientLight[1] += tr.identityLight * 32; -		ent->ambientLight[2] += tr.identityLight * 32; -	} - -	// -	// modify the light by dynamic lights -	// -	d = VectorLength( ent->directedLight ); -	VectorScale( ent->lightDir, d, lightDir ); - -	for ( i = 0 ; i < refdef->num_dlights ; i++ ) { -		dl = &refdef->dlights[i]; -		VectorSubtract( dl->origin, lightOrigin, dir ); -		d = VectorNormalize( dir ); - -		power = DLIGHT_AT_RADIUS * ( dl->radius * dl->radius ); -		if ( d < DLIGHT_MINIMUM_RADIUS ) { -			d = DLIGHT_MINIMUM_RADIUS; -		} -		d = power / ( d * d ); - -		VectorMA( ent->directedLight, d, dl->color, ent->directedLight ); -		VectorMA( lightDir, d, dir, lightDir ); -	} - -	// clamp ambient -	for ( i = 0 ; i < 3 ; i++ ) { -		if ( ent->ambientLight[i] > tr.identityLightByte ) { -			ent->ambientLight[i] = tr.identityLightByte; -		} -	} - -	if ( r_debugLight->integer ) { -		LogLight( ent ); -	} - -	// save out the byte packet version -	((byte *)&ent->ambientLightInt)[0] = myftol( ent->ambientLight[0] ); -	((byte *)&ent->ambientLightInt)[1] = myftol( ent->ambientLight[1] ); -	((byte *)&ent->ambientLightInt)[2] = myftol( ent->ambientLight[2] ); -	((byte *)&ent->ambientLightInt)[3] = 0xff; -	 -	// transform the direction to local space -	VectorNormalize( lightDir ); -	ent->lightDir[0] = DotProduct( lightDir, ent->e.axis[0] ); -	ent->lightDir[1] = DotProduct( lightDir, ent->e.axis[1] ); -	ent->lightDir[2] = DotProduct( lightDir, ent->e.axis[2] ); -} - -/* -================= -R_LightForPoint -================= -*/ -int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ) -{ -	trRefEntity_t ent; -	 -	// bk010103 - this segfaults with -nolight maps -	if ( tr.world->lightGridData == NULL ) -	  return qfalse; - -	Com_Memset(&ent, 0, sizeof(ent)); -	VectorCopy( point, ent.e.origin ); -	R_SetupEntityLightingGrid( &ent ); -	VectorCopy(ent.ambientLight, ambientLight); -	VectorCopy(ent.directedLight, directedLight); -	VectorCopy(ent.lightDir, lightDir); - -	return qtrue; -} diff --git a/ioq3-r437/src/renderer/tr_local.h b/ioq3-r437/src/renderer/tr_local.h deleted file mode 100644 index 865128f5..00000000 --- a/ioq3-r437/src/renderer/tr_local.h +++ /dev/null @@ -1,1645 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ - - -#ifndef TR_LOCAL_H -#define TR_LOCAL_H - -#include "../qcommon/q_shared.h" -#include "../qcommon/qfiles.h" -#include "../qcommon/qcommon.h" -#include "tr_public.h" -#include "qgl.h" - -#define GL_INDEX_TYPE		GL_UNSIGNED_INT -typedef unsigned int glIndex_t; - -// fast float to int conversion -#if id386 && !defined(__GNUC__) -long myftol( float f ); -#else -#define	myftol(x) ((int)(x)) -#endif - - -// everything that is needed by the backend needs -// to be double buffered to allow it to run in -// parallel on a dual cpu machine -#define	SMP_FRAMES		2 - -// 12 bits -// see QSORT_SHADERNUM_SHIFT -#define	MAX_SHADERS				16384 - -//#define MAX_SHADER_STATES 2048 -#define MAX_STATES_PER_SHADER 32 -#define MAX_STATE_NAME 32 - -// can't be increased without changing bit packing for drawsurfs - - -typedef struct dlight_s { -	vec3_t	origin; -	vec3_t	color;				// range from 0.0 to 1.0, should be color normalized -	float	radius; - -	vec3_t	transformed;		// origin in local coordinate system -	int		additive;			// texture detail is lost tho when the lightmap is dark -} dlight_t; - - -// a trRefEntity_t has all the information passed in by -// the client game, as well as some locally derived info -typedef struct { -	refEntity_t	e; - -	float		axisLength;		// compensate for non-normalized axis - -	qboolean	needDlights;	// true for bmodels that touch a dlight -	qboolean	lightingCalculated; -	vec3_t		lightDir;		// normalized direction towards light -	vec3_t		ambientLight;	// color normalized to 0-255 -	int			ambientLightInt;	// 32 bit rgba packed -	vec3_t		directedLight; -} trRefEntity_t; - - -typedef struct { -	vec3_t		origin;			// in world coordinates -	vec3_t		axis[3];		// orientation in world -	vec3_t		viewOrigin;		// viewParms->or.origin in local coordinates -	float		modelMatrix[16]; -} orientationr_t; - -typedef struct image_s { -	char		imgName[MAX_QPATH];		// game path, including extension -	int			width, height;				// source image -	int			uploadWidth, uploadHeight;	// after power of two and picmip but not including clamp to MAX_TEXTURE_SIZE -	GLuint		texnum;					// gl texture binding - -	int			frameUsed;			// for texture usage in frame statistics - -	int			internalFormat; -	int			TMU;				// only needed for voodoo2 - -	qboolean	mipmap; -	qboolean	allowPicmip; -	int			wrapClampMode;		// GL_CLAMP or GL_REPEAT - -	struct image_s*	next; -} image_t; - -//=============================================================================== - -typedef enum { -	SS_BAD, -	SS_PORTAL,			// mirrors, portals, viewscreens -	SS_ENVIRONMENT,		// sky box -	SS_OPAQUE,			// opaque - -	SS_DECAL,			// scorch marks, etc. -	SS_SEE_THROUGH,		// ladders, grates, grills that may have small blended edges -						// in addition to alpha test -	SS_BANNER, - -	SS_FOG, - -	SS_UNDERWATER,		// for items that should be drawn in front of the water plane - -	SS_BLEND0,			// regular transparency and filters -	SS_BLEND1,			// generally only used for additive type effects -	SS_BLEND2, -	SS_BLEND3, - -	SS_BLEND6, -	SS_STENCIL_SHADOW, -	SS_ALMOST_NEAREST,	// gun smoke puffs - -	SS_NEAREST			// blood blobs -} shaderSort_t; - - -#define MAX_SHADER_STAGES 8 - -typedef enum { -	GF_NONE, - -	GF_SIN, -	GF_SQUARE, -	GF_TRIANGLE, -	GF_SAWTOOTH,  -	GF_INVERSE_SAWTOOTH,  - -	GF_NOISE - -} genFunc_t; - - -typedef enum { -	DEFORM_NONE, -	DEFORM_WAVE, -	DEFORM_NORMALS, -	DEFORM_BULGE, -	DEFORM_MOVE, -	DEFORM_PROJECTION_SHADOW, -	DEFORM_AUTOSPRITE, -	DEFORM_AUTOSPRITE2, -	DEFORM_TEXT0, -	DEFORM_TEXT1, -	DEFORM_TEXT2, -	DEFORM_TEXT3, -	DEFORM_TEXT4, -	DEFORM_TEXT5, -	DEFORM_TEXT6, -	DEFORM_TEXT7 -} deform_t; - -typedef enum { -	AGEN_IDENTITY, -	AGEN_SKIP, -	AGEN_ENTITY, -	AGEN_ONE_MINUS_ENTITY, -	AGEN_VERTEX, -	AGEN_ONE_MINUS_VERTEX, -	AGEN_LIGHTING_SPECULAR, -	AGEN_WAVEFORM, -	AGEN_PORTAL, -	AGEN_CONST -} alphaGen_t; - -typedef enum { -	CGEN_BAD, -	CGEN_IDENTITY_LIGHTING,	// tr.identityLight -	CGEN_IDENTITY,			// always (1,1,1,1) -	CGEN_ENTITY,			// grabbed from entity's modulate field -	CGEN_ONE_MINUS_ENTITY,	// grabbed from 1 - entity.modulate -	CGEN_EXACT_VERTEX,		// tess.vertexColors -	CGEN_VERTEX,			// tess.vertexColors * tr.identityLight -	CGEN_ONE_MINUS_VERTEX, -	CGEN_WAVEFORM,			// programmatically generated -	CGEN_LIGHTING_DIFFUSE, -	CGEN_FOG,				// standard fog -	CGEN_CONST				// fixed color -} colorGen_t; - -typedef enum { -	TCGEN_BAD, -	TCGEN_IDENTITY,			// clear to 0,0 -	TCGEN_LIGHTMAP, -	TCGEN_TEXTURE, -	TCGEN_ENVIRONMENT_MAPPED, -	TCGEN_FOG, -	TCGEN_VECTOR			// S and T from world coordinates -} texCoordGen_t; - -typedef enum { -	ACFF_NONE, -	ACFF_MODULATE_RGB, -	ACFF_MODULATE_RGBA, -	ACFF_MODULATE_ALPHA -} acff_t; - -typedef struct { -	genFunc_t	func; - -	float base; -	float amplitude; -	float phase; -	float frequency; -} waveForm_t; - -#define TR_MAX_TEXMODS 4 - -typedef enum { -	TMOD_NONE, -	TMOD_TRANSFORM, -	TMOD_TURBULENT, -	TMOD_SCROLL, -	TMOD_SCALE, -	TMOD_STRETCH, -	TMOD_ROTATE, -	TMOD_ENTITY_TRANSLATE -} texMod_t; - -#define	MAX_SHADER_DEFORMS	3 -typedef struct { -	deform_t	deformation;			// vertex coordinate modification type - -	vec3_t		moveVector; -	waveForm_t	deformationWave; -	float		deformationSpread; - -	float		bulgeWidth; -	float		bulgeHeight; -	float		bulgeSpeed; -} deformStage_t; - - -typedef struct { -	texMod_t		type; - -	// used for TMOD_TURBULENT and TMOD_STRETCH -	waveForm_t		wave; - -	// used for TMOD_TRANSFORM -	float			matrix[2][2];		// s' = s * m[0][0] + t * m[1][0] + trans[0] -	float			translate[2];		// t' = s * m[0][1] + t * m[0][1] + trans[1] - -	// used for TMOD_SCALE -	float			scale[2];			// s *= scale[0] -	                                    // t *= scale[1] - -	// used for TMOD_SCROLL -	float			scroll[2];			// s' = s + scroll[0] * time -										// t' = t + scroll[1] * time - -	// + = clockwise -	// - = counterclockwise -	float			rotateSpeed; - -} texModInfo_t; - - -#define	MAX_IMAGE_ANIMATIONS	8 - -typedef struct { -	image_t			*image[MAX_IMAGE_ANIMATIONS]; -	int				numImageAnimations; -	float			imageAnimationSpeed; - -	texCoordGen_t	tcGen; -	vec3_t			tcGenVectors[2]; - -	int				numTexMods; -	texModInfo_t	*texMods; - -	int				videoMapHandle; -	qboolean		isLightmap; -	qboolean		vertexLightmap; -	qboolean		isVideoMap; -} textureBundle_t; - -#define NUM_TEXTURE_BUNDLES 2 - -typedef struct { -	qboolean		active; -	 -	textureBundle_t	bundle[NUM_TEXTURE_BUNDLES]; - -	waveForm_t		rgbWave; -	colorGen_t		rgbGen; - -	waveForm_t		alphaWave; -	alphaGen_t		alphaGen; - -	byte			constantColor[4];			// for CGEN_CONST and AGEN_CONST - -	unsigned		stateBits;					// GLS_xxxx mask - -	acff_t			adjustColorsForFog; - -	qboolean		isDetail; -} shaderStage_t; - -struct shaderCommands_s; - -#define LIGHTMAP_2D			-4		// shader is for 2D rendering -#define LIGHTMAP_BY_VERTEX	-3		// pre-lit triangle models -#define LIGHTMAP_WHITEIMAGE	-2 -#define	LIGHTMAP_NONE		-1 - -typedef enum { -	CT_FRONT_SIDED, -	CT_BACK_SIDED, -	CT_TWO_SIDED -} cullType_t; - -typedef enum { -	FP_NONE,		// surface is translucent and will just be adjusted properly -	FP_EQUAL,		// surface is opaque but possibly alpha tested -	FP_LE			// surface is trnaslucent, but still needs a fog pass (fog surface) -} fogPass_t; - -typedef struct { -	float		cloudHeight; -	image_t		*outerbox[6], *innerbox[6]; -} skyParms_t; - -typedef struct { -	vec3_t	color; -	float	depthForOpaque; -} fogParms_t; - - -typedef struct shader_s { -	char		name[MAX_QPATH];		// game path, including extension -	int			lightmapIndex;			// for a shader to match, both name and lightmapIndex must match - -	int			index;					// this shader == tr.shaders[index] -	int			sortedIndex;			// this shader == tr.sortedShaders[sortedIndex] - -	float		sort;					// lower numbered shaders draw before higher numbered - -	qboolean	defaultShader;			// we want to return index 0 if the shader failed to -										// load for some reason, but R_FindShader should -										// still keep a name allocated for it, so if -										// something calls RE_RegisterShader again with -										// the same name, we don't try looking for it again - -	qboolean	explicitlyDefined;		// found in a .shader file - -	int			surfaceFlags;			// if explicitlyDefined, this will have SURF_* flags -	int			contentFlags; - -	qboolean	entityMergable;			// merge across entites optimizable (smoke, blood) - -	qboolean	isSky; -	skyParms_t	sky; -	fogParms_t	fogParms; - -	float		portalRange;			// distance to fog out at - -	int			multitextureEnv;		// 0, GL_MODULATE, GL_ADD (FIXME: put in stage) - -	cullType_t	cullType;				// CT_FRONT_SIDED, CT_BACK_SIDED, or CT_TWO_SIDED -	qboolean	polygonOffset;			// set for decals and other items that must be offset  -	qboolean	noMipMaps;				// for console fonts, 2D elements, etc. -	qboolean	noPicMip;				// for images that must always be full resolution - -	fogPass_t	fogPass;				// draw a blended pass, possibly with depth test equals - -	qboolean	needsNormal;			// not all shaders will need all data to be gathered -	qboolean	needsST1; -	qboolean	needsST2; -	qboolean	needsColor; - -	int			numDeforms; -	deformStage_t	deforms[MAX_SHADER_DEFORMS]; - -	int			numUnfoggedPasses; -	shaderStage_t	*stages[MAX_SHADER_STAGES];		 - -	void		(*optimalStageIteratorFunc)( void ); - -  float clampTime;                                  // time this shader is clamped to -  float timeOffset;                                 // current time offset for this shader - -  int numStates;                                    // if non-zero this is a state shader -  struct shader_s *currentShader;                   // current state if this is a state shader -  struct shader_s *parentShader;                    // current state if this is a state shader -  int currentState;                                 // current state index for cycle purposes -  long expireTime;                                  // time in milliseconds this expires - -  struct shader_s *remappedShader;                  // current shader this one is remapped too - -  int shaderStates[MAX_STATES_PER_SHADER];          // index to valid shader states - -	struct	shader_s	*next; -} shader_t; - -typedef struct shaderState_s { -  char shaderName[MAX_QPATH];     // name of shader this state belongs to -  char name[MAX_STATE_NAME];      // name of this state -  char stateShader[MAX_QPATH];    // shader this name invokes -  int cycleTime;                  // time this cycle lasts, <= 0 is forever -  shader_t *shader; -} shaderState_t; - - -// trRefdef_t holds everything that comes in refdef_t, -// as well as the locally generated scene information -typedef struct { -	int			x, y, width, height; -	float		fov_x, fov_y; -	vec3_t		vieworg; -	vec3_t		viewaxis[3];		// transformation matrix - -	int			time;				// time in milliseconds for shader effects and other time dependent rendering issues -	int			rdflags;			// RDF_NOWORLDMODEL, etc - -	// 1 bits will prevent the associated area from rendering at all -	byte		areamask[MAX_MAP_AREA_BYTES]; -	qboolean	areamaskModified;	// qtrue if areamask changed since last scene - -	float		floatTime;			// tr.refdef.time / 1000.0 - -	// text messages for deform text shaders -	char		text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH]; - -	int			num_entities; -	trRefEntity_t	*entities; - -	int			num_dlights; -	struct dlight_s	*dlights; - -	int			numPolys; -	struct srfPoly_s	*polys; - -	int			numDrawSurfs; -	struct drawSurf_s	*drawSurfs; - - -} trRefdef_t; - - -//================================================================================= - -// skins allow models to be retextured without modifying the model file -typedef struct { -	char		name[MAX_QPATH]; -	shader_t	*shader; -} skinSurface_t; - -typedef struct skin_s { -	char		name[MAX_QPATH];		// game path, including extension -	int			numSurfaces; -	skinSurface_t	*surfaces[MD3_MAX_SURFACES]; -} skin_t; - - -typedef struct { -	int			originalBrushNumber; -	vec3_t		bounds[2]; - -	unsigned	colorInt;				// in packed byte format -	float		tcScale;				// texture coordinate vector scales -	fogParms_t	parms; - -	// for clipping distance in fog when outside -	qboolean	hasSurface; -	float		surface[4]; -} fog_t; - -typedef struct { -	orientationr_t	or; -	orientationr_t	world; -	vec3_t		pvsOrigin;			// may be different than or.origin for portals -	qboolean	isPortal;			// true if this view is through a portal -	qboolean	isMirror;			// the portal is a mirror, invert the face culling -	int			frameSceneNum;		// copied from tr.frameSceneNum -	int			frameCount;			// copied from tr.frameCount -	cplane_t	portalPlane;		// clip anything behind this if mirroring -	int			viewportX, viewportY, viewportWidth, viewportHeight; -	float		fovX, fovY; -	float		projectionMatrix[16]; -	cplane_t	frustum[4]; -	vec3_t		visBounds[2]; -	float		zFar; -} viewParms_t; - - -/* -============================================================================== - -SURFACES - -============================================================================== -*/ - -// any changes in surfaceType must be mirrored in rb_surfaceTable[] -typedef enum { -	SF_BAD, -	SF_SKIP,				// ignore -	SF_FACE, -	SF_GRID, -	SF_TRIANGLES, -	SF_POLY, -	SF_MD3, -	SF_MD4, -#ifdef RAVENMD4 -	SF_MDR, -#endif -	SF_FLARE, -	SF_ENTITY,				// beams, rails, lightning, etc that can be determined by entity -	SF_DISPLAY_LIST, - -	SF_NUM_SURFACE_TYPES, -	SF_MAX = 0x7fffffff			// ensures that sizeof( surfaceType_t ) == sizeof( int ) -} surfaceType_t; - -typedef struct drawSurf_s { -	unsigned			sort;			// bit combination for fast compares -	surfaceType_t		*surface;		// any of surface*_t -} drawSurf_t; - -#define	MAX_FACE_POINTS		64 - -#define	MAX_PATCH_SIZE		32			// max dimensions of a patch mesh in map file -#define	MAX_GRID_SIZE		65			// max dimensions of a grid mesh in memory - -// when cgame directly specifies a polygon, it becomes a srfPoly_t -// as soon as it is called -typedef struct srfPoly_s { -	surfaceType_t	surfaceType; -	qhandle_t		hShader; -	int				fogIndex; -	int				numVerts; -	polyVert_t		*verts; -} srfPoly_t; - -typedef struct srfDisplayList_s { -	surfaceType_t	surfaceType; -	int				listNum; -} srfDisplayList_t; - - -typedef struct srfFlare_s { -	surfaceType_t	surfaceType; -	vec3_t			origin; -	vec3_t			normal; -	vec3_t			color; -} srfFlare_t; - -typedef struct srfGridMesh_s { -	surfaceType_t	surfaceType; - -	// dynamic lighting information -	int				dlightBits[SMP_FRAMES]; - -	// culling information -	vec3_t			meshBounds[2]; -	vec3_t			localOrigin; -	float			meshRadius; - -	// lod information, which may be different -	// than the culling information to allow for -	// groups of curves that LOD as a unit -	vec3_t			lodOrigin; -	float			lodRadius; -	int				lodFixed; -	int				lodStitched; - -	// vertexes -	int				width, height; -	float			*widthLodError; -	float			*heightLodError; -	drawVert_t		verts[1];		// variable sized -} srfGridMesh_t; - - - -#define	VERTEXSIZE	8 -typedef struct { -	surfaceType_t	surfaceType; -	cplane_t	plane; - -	// dynamic lighting information -	int			dlightBits[SMP_FRAMES]; - -	// triangle definitions (no normals at points) -	int			numPoints; -	int			numIndices; -	int			ofsIndices; -	float		points[1][VERTEXSIZE];	// variable sized -										// there is a variable length list of indices here also -} srfSurfaceFace_t; - - -// misc_models in maps are turned into direct geometry by q3map -typedef struct { -	surfaceType_t	surfaceType; - -	// dynamic lighting information -	int				dlightBits[SMP_FRAMES]; - -	// culling information (FIXME: use this!) -	vec3_t			bounds[2]; -	vec3_t			localOrigin; -	float			radius; - -	// triangle definitions -	int				numIndexes; -	int				*indexes; - -	int				numVerts; -	drawVert_t		*verts; -} srfTriangles_t; - - -extern	void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void *); - -/* -============================================================================== - -BRUSH MODELS - -============================================================================== -*/ - - -// -// in memory representation -// - -#define	SIDE_FRONT	0 -#define	SIDE_BACK	1 -#define	SIDE_ON		2 - -typedef struct msurface_s { -	int					viewCount;		// if == tr.viewCount, already added -	struct shader_s		*shader; -	int					fogIndex; - -	surfaceType_t		*data;			// any of srf*_t -} msurface_t; - - - -#define	CONTENTS_NODE		-1 -typedef struct mnode_s { -	// common with leaf and node -	int			contents;		// -1 for nodes, to differentiate from leafs -	int			visframe;		// node needs to be traversed if current -	vec3_t		mins, maxs;		// for bounding box culling -	struct mnode_s	*parent; - -	// node specific -	cplane_t	*plane; -	struct mnode_s	*children[2];	 - -	// leaf specific -	int			cluster; -	int			area; - -	msurface_t	**firstmarksurface; -	int			nummarksurfaces; -} mnode_t; - -typedef struct { -	vec3_t		bounds[2];		// for culling -	msurface_t	*firstSurface; -	int			numSurfaces; -} bmodel_t; - -typedef struct { -	char		name[MAX_QPATH];		// ie: maps/tim_dm2.bsp -	char		baseName[MAX_QPATH];	// ie: tim_dm2 - -	int			dataSize; - -	int			numShaders; -	dshader_t	*shaders; - -	bmodel_t	*bmodels; - -	int			numplanes; -	cplane_t	*planes; - -	int			numnodes;		// includes leafs -	int			numDecisionNodes; -	mnode_t		*nodes; - -	int			numsurfaces; -	msurface_t	*surfaces; - -	int			nummarksurfaces; -	msurface_t	**marksurfaces; - -	int			numfogs; -	fog_t		*fogs; - -	vec3_t		lightGridOrigin; -	vec3_t		lightGridSize; -	vec3_t		lightGridInverseSize; -	int			lightGridBounds[3]; -	byte		*lightGridData; - - -	int			numClusters; -	int			clusterBytes; -	const byte	*vis;			// may be passed in by CM_LoadMap to save space - -	byte		*novis;			// clusterBytes of 0xff - -	char		*entityString; -	char		*entityParsePoint; -} world_t; - -//====================================================================== - -typedef enum { -	MOD_BAD, -	MOD_BRUSH, -	MOD_MESH, -	MOD_MD4, -#ifdef RAVENMD4 -	MOD_MDR -#endif -} modtype_t; - -typedef struct model_s { -	char		name[MAX_QPATH]; -	modtype_t	type; -	int			index;				// model = tr.models[model->index] - -	int			dataSize;			// just for listing purposes -	bmodel_t	*bmodel;			// only if type == MOD_BRUSH -	md3Header_t	*md3[MD3_MAX_LODS];	// only if type == MOD_MESH -	void	*md4;				// only if type == (MOD_MD4 | MOD_MDR) - -	int			 numLods; -} model_t; - - -#define	MAX_MOD_KNOWN	1024 - -void		R_ModelInit (void); -model_t		*R_GetModelByHandle( qhandle_t hModel ); -int			R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame,  -					 float frac, const char *tagName ); -void		R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ); - -void		R_Modellist_f (void); - -//==================================================== -extern	refimport_t		ri; - -#define	MAX_DRAWIMAGES			2048 -#define	MAX_LIGHTMAPS			256 -#define	MAX_SKINS				1024 - - -#define	MAX_DRAWSURFS			0x10000 -#define	DRAWSURF_MASK			(MAX_DRAWSURFS-1) - -/* - -the drawsurf sort data is packed into a single 32 bit value so it can be -compared quickly during the qsorting process - -the bits are allocated as follows: - -21 - 31	: sorted shader index -11 - 20	: entity index -2 - 6	: fog index -//2		: used to be clipped flag REMOVED - 03.21.00 rad -0 - 1	: dlightmap index - -	TTimo - 1.32 -17-31 : sorted shader index -7-16  : entity index -2-6   : fog index -0-1   : dlightmap index -*/ -#define	QSORT_SHADERNUM_SHIFT	17 -#define	QSORT_ENTITYNUM_SHIFT	7 -#define	QSORT_FOGNUM_SHIFT		2 - -extern	int			gl_filter_min, gl_filter_max; - -/* -** performanceCounters_t -*/ -typedef struct { -	int		c_sphere_cull_patch_in, c_sphere_cull_patch_clip, c_sphere_cull_patch_out; -	int		c_box_cull_patch_in, c_box_cull_patch_clip, c_box_cull_patch_out; -	int		c_sphere_cull_md3_in, c_sphere_cull_md3_clip, c_sphere_cull_md3_out; -	int		c_box_cull_md3_in, c_box_cull_md3_clip, c_box_cull_md3_out; - -	int		c_leafs; -	int		c_dlightSurfaces; -	int		c_dlightSurfacesCulled; -} frontEndCounters_t; - -#define	FOG_TABLE_SIZE		256 -#define FUNCTABLE_SIZE		1024 -#define FUNCTABLE_SIZE2		10 -#define FUNCTABLE_MASK		(FUNCTABLE_SIZE-1) - - -// the renderer front end should never modify glstate_t -typedef struct { -	int			currenttextures[2]; -	int			currenttmu; -	qboolean	finishCalled; -	int			texEnv[2]; -	int			faceCulling; -	unsigned long	glStateBits; -} glstate_t; - - -typedef struct { -	int		c_surfaces, c_shaders, c_vertexes, c_indexes, c_totalIndexes; -	float	c_overDraw; -	 -	int		c_dlightVertexes; -	int		c_dlightIndexes; - -	int		c_flareAdds; -	int		c_flareTests; -	int		c_flareRenders; - -	int		msec;			// total msec for backend run -} backEndCounters_t; - -// all state modified by the back end is seperated -// from the front end state -typedef struct { -	int			smpFrame; -	trRefdef_t	refdef; -	viewParms_t	viewParms; -	orientationr_t	or; -	backEndCounters_t	pc; -	qboolean	isHyperspace; -	trRefEntity_t	*currentEntity; -	qboolean	skyRenderedThisView;	// flag for drawing sun - -	qboolean	projection2D;	// if qtrue, drawstretchpic doesn't need to change modes -	byte		color2D[4]; -	qboolean	vertexes2D;		// shader needs to be finished -	trRefEntity_t	entity2D;	// currentEntity will point at this when doing 2D rendering -} backEndState_t; - -/* -** trGlobals_t  -** -** Most renderer globals are defined here. -** backend functions should never modify any of these fields, -** but may read fields that aren't dynamically modified -** by the frontend. -*/ -typedef struct { -	qboolean				registered;		// cleared at shutdown, set at beginRegistration - -	int						visCount;		// incremented every time a new vis cluster is entered -	int						frameCount;		// incremented every frame -	int						sceneCount;		// incremented every scene -	int						viewCount;		// incremented every view (twice a scene if portaled) -											// and every R_MarkFragments call - -	int						smpFrame;		// toggles from 0 to 1 every endFrame - -	int						frameSceneNum;	// zeroed at RE_BeginFrame - -	qboolean				worldMapLoaded; -	world_t					*world; - -	const byte				*externalVisData;	// from RE_SetWorldVisData, shared with CM_Load - -	image_t					*defaultImage; -	image_t					*scratchImage[32]; -	image_t					*fogImage; -	image_t					*dlightImage;	// inverse-quare highlight for projective adding -	image_t					*flareImage; -	image_t					*whiteImage;			// full of 0xff -	image_t					*identityLightImage;	// full of tr.identityLightByte - -	shader_t				*defaultShader; -	shader_t				*shadowShader; -	shader_t				*projectionShadowShader; - -	shader_t				*flareShader; -	shader_t				*sunShader; - -	int						numLightmaps; -	image_t					*lightmaps[MAX_LIGHTMAPS]; - -	trRefEntity_t			*currentEntity; -	trRefEntity_t			worldEntity;		// point currentEntity at this when rendering world -	int						currentEntityNum; -	int						shiftedEntityNum;	// currentEntityNum << QSORT_ENTITYNUM_SHIFT -	model_t					*currentModel; - -	viewParms_t				viewParms; - -	float					identityLight;		// 1.0 / ( 1 << overbrightBits ) -	int						identityLightByte;	// identityLight * 255 -	int						overbrightBits;		// r_overbrightBits->integer, but set to 0 if no hw gamma - -	orientationr_t			or;					// for current entity - -	trRefdef_t				refdef; - -	int						viewCluster; - -	vec3_t					sunLight;			// from the sky shader for this level -	vec3_t					sunDirection; - -	frontEndCounters_t		pc; -	int						frontEndMsec;		// not in pc due to clearing issue - -	// -	// put large tables at the end, so most elements will be -	// within the +/32K indexed range on risc processors -	// -	model_t					*models[MAX_MOD_KNOWN]; -	int						numModels; - -	int						numImages; -	image_t					*images[MAX_DRAWIMAGES]; - -	// shader indexes from other modules will be looked up in tr.shaders[] -	// shader indexes from drawsurfs will be looked up in sortedShaders[] -	// lower indexed sortedShaders must be rendered first (opaque surfaces before translucent) -	int						numShaders; -	shader_t				*shaders[MAX_SHADERS]; -	shader_t				*sortedShaders[MAX_SHADERS]; - -	int						numSkins; -	skin_t					*skins[MAX_SKINS]; - -	float					sinTable[FUNCTABLE_SIZE]; -	float					squareTable[FUNCTABLE_SIZE]; -	float					triangleTable[FUNCTABLE_SIZE]; -	float					sawToothTable[FUNCTABLE_SIZE]; -	float					inverseSawToothTable[FUNCTABLE_SIZE]; -	float					fogTable[FOG_TABLE_SIZE]; -} trGlobals_t; - -extern backEndState_t	backEnd; -extern trGlobals_t	tr; -extern glconfig_t	glConfig;		// outside of TR since it shouldn't be cleared during ref re-init -extern glstate_t	glState;		// outside of TR since it shouldn't be cleared during ref re-init - - -// -// cvars -// -extern cvar_t	*r_flareSize; -extern cvar_t	*r_flareFade; - -extern cvar_t	*r_railWidth; -extern cvar_t	*r_railCoreWidth; -extern cvar_t	*r_railSegmentLength; - -extern cvar_t	*r_ignore;				// used for debugging anything -extern cvar_t	*r_verbose;				// used for verbose debug spew -extern cvar_t	*r_ignoreFastPath;		// allows us to ignore our Tess fast paths - -extern cvar_t	*r_znear;				// near Z clip plane - -extern cvar_t	*r_stencilbits;			// number of desired stencil bits -extern cvar_t	*r_depthbits;			// number of desired depth bits -extern cvar_t	*r_colorbits;			// number of desired color bits, only relevant for fullscreen -extern cvar_t	*r_stereo;				// desired pixelformat stereo flag -extern cvar_t	*r_texturebits;			// number of desired texture bits -										// 0 = use framebuffer depth -										// 16 = use 16-bit textures -										// 32 = use 32-bit textures -										// all else = error - -extern cvar_t	*r_measureOverdraw;		// enables stencil buffer overdraw measurement - -extern cvar_t	*r_lodbias;				// push/pull LOD transitions -extern cvar_t	*r_lodscale; - -extern cvar_t	*r_primitives;			// "0" = based on compiled vertex array existance -										// "1" = glDrawElemet tristrips -										// "2" = glDrawElements triangles -										// "-1" = no drawing - -extern cvar_t	*r_inGameVideo;				// controls whether in game video should be draw -extern cvar_t	*r_fastsky;				// controls whether sky should be cleared or drawn -extern cvar_t	*r_drawSun;				// controls drawing of sun quad -extern cvar_t	*r_dynamiclight;		// dynamic lights enabled/disabled -extern cvar_t	*r_dlightBacks;			// dlight non-facing surfaces for continuity - -extern	cvar_t	*r_norefresh;			// bypasses the ref rendering -extern	cvar_t	*r_drawentities;		// disable/enable entity rendering -extern	cvar_t	*r_drawworld;			// disable/enable world rendering -extern	cvar_t	*r_speeds;				// various levels of information display -extern  cvar_t	*r_detailTextures;		// enables/disables detail texturing stages -extern	cvar_t	*r_novis;				// disable/enable usage of PVS -extern	cvar_t	*r_nocull; -extern	cvar_t	*r_facePlaneCull;		// enables culling of planar surfaces with back side test -extern	cvar_t	*r_nocurves; -extern	cvar_t	*r_showcluster; - -extern cvar_t	*r_mode;				// video mode -extern cvar_t	*r_fullscreen; -extern cvar_t	*r_gamma; -extern cvar_t	*r_displayRefresh;		// optional display refresh option -extern cvar_t	*r_ignorehwgamma;		// overrides hardware gamma capabilities - -extern cvar_t	*r_allowExtensions;				// global enable/disable of OpenGL extensions -extern cvar_t	*r_ext_compressed_textures;		// these control use of specific extensions -extern cvar_t	*r_ext_gamma_control; -extern cvar_t	*r_ext_texenv_op; -extern cvar_t	*r_ext_multitexture; -extern cvar_t	*r_ext_compiled_vertex_array; -extern cvar_t	*r_ext_texture_env_add; - -extern	cvar_t	*r_nobind;						// turns off binding to appropriate textures -extern	cvar_t	*r_singleShader;				// make most world faces use default shader -extern	cvar_t	*r_roundImagesDown; -extern	cvar_t	*r_colorMipLevels;				// development aid to see texture mip usage -extern	cvar_t	*r_picmip;						// controls picmip values -extern	cvar_t	*r_finish; -extern	cvar_t	*r_drawBuffer; -extern  cvar_t  *r_glDriver; -extern	cvar_t	*r_swapInterval; -extern	cvar_t	*r_textureMode; -extern	cvar_t	*r_offsetFactor; -extern	cvar_t	*r_offsetUnits; - -extern	cvar_t	*r_fullbright;					// avoid lightmap pass -extern	cvar_t	*r_lightmap;					// render lightmaps only -extern	cvar_t	*r_vertexLight;					// vertex lighting mode for better performance -extern	cvar_t	*r_uiFullScreen;				// ui is running fullscreen - -extern	cvar_t	*r_logFile;						// number of frames to emit GL logs -extern	cvar_t	*r_showtris;					// enables wireframe rendering of the world -extern	cvar_t	*r_showsky;						// forces sky in front of all surfaces -extern	cvar_t	*r_shownormals;					// draws wireframe normals -extern	cvar_t	*r_clear;						// force screen clear every frame - -extern	cvar_t	*r_shadows;						// controls shadows: 0 = none, 1 = blur, 2 = stencil, 3 = black planar projection -extern	cvar_t	*r_flares;						// light flares - -extern	cvar_t	*r_intensity; - -extern	cvar_t	*r_lockpvs; -extern	cvar_t	*r_noportals; -extern	cvar_t	*r_portalOnly; - -extern	cvar_t	*r_subdivisions; -extern	cvar_t	*r_lodCurveError; -extern	cvar_t	*r_smp; -extern	cvar_t	*r_showSmp; -extern	cvar_t	*r_skipBackEnd; - -extern	cvar_t	*r_ignoreGLErrors; - -extern	cvar_t	*r_overBrightBits; -extern	cvar_t	*r_mapOverBrightBits; - -extern	cvar_t	*r_debugSurface; -extern	cvar_t	*r_simpleMipMaps; - -extern	cvar_t	*r_showImages; -extern	cvar_t	*r_debugSort; - -extern	cvar_t	*r_printShaders; -extern	cvar_t	*r_saveFontData; - -extern	cvar_t	*r_GLlibCoolDownMsec; - -//==================================================================== - -float R_NoiseGet4f( float x, float y, float z, float t ); -void  R_NoiseInit( void ); - -void R_SwapBuffers( int ); - -void R_RenderView( viewParms_t *parms ); - -void R_AddMD3Surfaces( trRefEntity_t *e ); -void R_AddNullModelSurfaces( trRefEntity_t *e ); -void R_AddBeamSurfaces( trRefEntity_t *e ); -void R_AddRailSurfaces( trRefEntity_t *e, qboolean isUnderwater ); -void R_AddLightningBoltSurfaces( trRefEntity_t *e ); - -void R_AddPolygonSurfaces( void ); - -void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,  -					 int *fogNum, int *dlightMap ); - -void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int fogIndex, int dlightMap ); - - -#define	CULL_IN		0		// completely unclipped -#define	CULL_CLIP	1		// clipped by one or more planes -#define	CULL_OUT	2		// completely outside the clipping planes -void R_LocalNormalToWorld (vec3_t local, vec3_t world); -void R_LocalPointToWorld (vec3_t local, vec3_t world); -int R_CullLocalBox (vec3_t bounds[2]); -int R_CullPointAndRadius( vec3_t origin, float radius ); -int R_CullLocalPointAndRadius( vec3_t origin, float radius ); - -void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms, orientationr_t *or ); - -/* -** GL wrapper/helper functions -*/ -void	GL_Bind( image_t *image ); -void	GL_SetDefaultState (void); -void	GL_SelectTexture( int unit ); -void	GL_TextureMode( const char *string ); -void	GL_CheckErrors( void ); -void	GL_State( unsigned long stateVector ); -void	GL_TexEnv( int env ); -void	GL_Cull( int cullType ); - -#define GLS_SRCBLEND_ZERO						0x00000001 -#define GLS_SRCBLEND_ONE						0x00000002 -#define GLS_SRCBLEND_DST_COLOR					0x00000003 -#define GLS_SRCBLEND_ONE_MINUS_DST_COLOR		0x00000004 -#define GLS_SRCBLEND_SRC_ALPHA					0x00000005 -#define GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA		0x00000006 -#define GLS_SRCBLEND_DST_ALPHA					0x00000007 -#define GLS_SRCBLEND_ONE_MINUS_DST_ALPHA		0x00000008 -#define GLS_SRCBLEND_ALPHA_SATURATE				0x00000009 -#define		GLS_SRCBLEND_BITS					0x0000000f - -#define GLS_DSTBLEND_ZERO						0x00000010 -#define GLS_DSTBLEND_ONE						0x00000020 -#define GLS_DSTBLEND_SRC_COLOR					0x00000030 -#define GLS_DSTBLEND_ONE_MINUS_SRC_COLOR		0x00000040 -#define GLS_DSTBLEND_SRC_ALPHA					0x00000050 -#define GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA		0x00000060 -#define GLS_DSTBLEND_DST_ALPHA					0x00000070 -#define GLS_DSTBLEND_ONE_MINUS_DST_ALPHA		0x00000080 -#define		GLS_DSTBLEND_BITS					0x000000f0 - -#define GLS_DEPTHMASK_TRUE						0x00000100 - -#define GLS_POLYMODE_LINE						0x00001000 - -#define GLS_DEPTHTEST_DISABLE					0x00010000 -#define GLS_DEPTHFUNC_EQUAL						0x00020000 - -#define GLS_ATEST_GT_0							0x10000000 -#define GLS_ATEST_LT_80							0x20000000 -#define GLS_ATEST_GE_80							0x40000000 -#define		GLS_ATEST_BITS						0x70000000 - -#define GLS_DEFAULT			GLS_DEPTHMASK_TRUE - -void	RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty); -void	RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty); - -void		RE_BeginFrame( stereoFrame_t stereoFrame ); -void		RE_BeginRegistration( glconfig_t *glconfig ); -void		RE_LoadWorldMap( const char *mapname ); -void		RE_SetWorldVisData( const byte *vis ); -qhandle_t	RE_RegisterModel( const char *name ); -qhandle_t	RE_RegisterSkin( const char *name ); -void		RE_Shutdown( qboolean destroyWindow ); - -qboolean	R_GetEntityToken( char *buffer, int size ); - -model_t		*R_AllocModel( void ); - -void    	R_Init( void ); -image_t		*R_FindImageFile( const char *name, qboolean mipmap, qboolean allowPicmip, int glWrapClampMode ); - -image_t		*R_CreateImage( const char *name, const byte *pic, int width, int height, qboolean mipmap -					, qboolean allowPicmip, int wrapClampMode ); -qboolean	R_GetModeInfo( int *width, int *height, float *windowAspect, int mode ); - -void		R_SetColorMappings( void ); -void		R_GammaCorrect( byte *buffer, int bufSize ); - -void	R_ImageList_f( void ); -void	R_SkinList_f( void ); -// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=516 -const void *RB_TakeScreenshotCmd( const void *data ); -void	R_ScreenShot_f( void ); - -void	R_InitFogTable( void ); -float	R_FogFactor( float s, float t ); -void	R_InitImages( void ); -void	R_DeleteTextures( void ); -int		R_SumOfUsedImages( void ); -void	R_InitSkins( void ); -skin_t	*R_GetSkinByHandle( qhandle_t hSkin ); - -int R_ComputeLOD( trRefEntity_t *ent ); - - -// -// tr_shader.c -// -qhandle_t		 RE_RegisterShaderLightMap( const char *name, int lightmapIndex ); -qhandle_t		 RE_RegisterShader( const char *name ); -qhandle_t		 RE_RegisterShaderNoMip( const char *name ); -qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage); - -shader_t	*R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ); -shader_t	*R_GetShaderByHandle( qhandle_t hShader ); -shader_t	*R_GetShaderByState( int index, long *cycleTime ); -shader_t *R_FindShaderByName( const char *name ); -void		R_InitShaders( void ); -void		R_ShaderList_f( void ); -void    R_RemapShader(const char *oldShader, const char *newShader, const char *timeOffset); - -/* -==================================================================== - -IMPLEMENTATION SPECIFIC FUNCTIONS - -==================================================================== -*/ - -void		GLimp_Init( void ); -void		GLimp_Shutdown( void ); -void		GLimp_EndFrame( void ); - -qboolean	GLimp_SpawnRenderThread( void (*function)( void ) ); -void		*GLimp_RendererSleep( void ); -void		GLimp_FrontEndSleep( void ); -void		GLimp_WakeRenderer( void *data ); - -void		GLimp_LogComment( char *comment ); - -// NOTE TTimo linux works with float gamma value, not the gamma table -//   the params won't be used, getting the r_gamma cvar directly -void		GLimp_SetGamma( unsigned char red[256],  -						    unsigned char green[256], -							unsigned char blue[256] ); - - -/* -==================================================================== - -TESSELATOR/SHADER DECLARATIONS - -==================================================================== -*/ -typedef byte color4ub_t[4]; - -typedef struct stageVars -{ -	color4ub_t	colors[SHADER_MAX_VERTEXES]; -	vec2_t		texcoords[NUM_TEXTURE_BUNDLES][SHADER_MAX_VERTEXES]; -} stageVars_t; - - -typedef struct shaderCommands_s  -{ -	glIndex_t	indexes[SHADER_MAX_INDEXES] ALIGN(16); -	vec4_t		xyz[SHADER_MAX_VERTEXES] ALIGN(16); -	vec4_t		normal[SHADER_MAX_VERTEXES] ALIGN(16); -	vec2_t		texCoords[SHADER_MAX_VERTEXES][2] ALIGN(16); -	color4ub_t	vertexColors[SHADER_MAX_VERTEXES] ALIGN(16); -	int			vertexDlightBits[SHADER_MAX_VERTEXES] ALIGN(16); - -	stageVars_t	svars ALIGN(16); - -	color4ub_t	constantColor255[SHADER_MAX_VERTEXES] ALIGN(16); - -	shader_t	*shader; -  float   shaderTime; -	int			fogNum; - -	int			dlightBits;	// or together of all vertexDlightBits - -	int			numIndexes; -	int			numVertexes; - -	// info extracted from current shader -	int			numPasses; -	void		(*currentStageIteratorFunc)( void ); -	shaderStage_t	**xstages; -} shaderCommands_t; - -extern	shaderCommands_t	tess; - -void RB_BeginSurface(shader_t *shader, int fogNum ); -void RB_EndSurface(void); -void RB_CheckOverflow( int verts, int indexes ); -#define RB_CHECKOVERFLOW(v,i) if (tess.numVertexes + (v) >= SHADER_MAX_VERTEXES || tess.numIndexes + (i) >= SHADER_MAX_INDEXES ) {RB_CheckOverflow(v,i);} - -void RB_StageIteratorGeneric( void ); -void RB_StageIteratorSky( void ); -void RB_StageIteratorVertexLitTexture( void ); -void RB_StageIteratorLightmappedMultitexture( void ); - -void RB_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, byte *color ); -void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, byte *color, float s1, float t1, float s2, float t2 ); - -void RB_ShowImages( void ); - - -/* -============================================================ - -WORLD MAP - -============================================================ -*/ - -void R_AddBrushModelSurfaces( trRefEntity_t *e ); -void R_AddWorldSurfaces( void ); -qboolean R_inPVS( const vec3_t p1, const vec3_t p2 ); - - -/* -============================================================ - -FLARES - -============================================================ -*/ - -void R_ClearFlares( void ); - -void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t normal ); -void RB_AddDlightFlares( void ); -void RB_RenderFlares (void); - -/* -============================================================ - -LIGHTS - -============================================================ -*/ - -void R_DlightBmodel( bmodel_t *bmodel ); -void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ); -void R_TransformDlights( int count, dlight_t *dl, orientationr_t *or ); -int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ); - - -/* -============================================================ - -SHADOWS - -============================================================ -*/ - -void RB_ShadowTessEnd( void ); -void RB_ShadowFinish( void ); -void RB_ProjectionShadowDeform( void ); - -/* -============================================================ - -SKIES - -============================================================ -*/ - -void R_BuildCloudData( shaderCommands_t *shader ); -void R_InitSkyTexCoords( float cloudLayerHeight ); -void R_DrawSkyBox( shaderCommands_t *shader ); -void RB_DrawSun( void ); -void RB_ClipSkyPolygons( shaderCommands_t *shader ); - -/* -============================================================ - -CURVE TESSELATION - -============================================================ -*/ - -#define PATCH_STITCHING - -srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, -								drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ); -srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ); -srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ); -void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ); - -/* -============================================================ - -MARKERS, POLYGON PROJECTION ON WORLD POLYGONS - -============================================================ -*/ - -int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection, -				   int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ); - - -/* -============================================================ - -SCENE GENERATION - -============================================================ -*/ - -void R_ToggleSmpFrame( void ); - -void RE_ClearScene( void ); -void RE_AddRefEntityToScene( const refEntity_t *ent ); -void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num ); -void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ); -void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ); -void RE_RenderScene( const refdef_t *fd ); - -#ifdef RAVENMD4 -/* -============================================================= - -UNCOMPRESSING BONES - -============================================================= -*/ - -#define MC_BITS_X (16) -#define MC_BITS_Y (16) -#define MC_BITS_Z (16) -#define MC_BITS_VECT (16) - -#define MC_SCALE_X (1.0f/64) -#define MC_SCALE_Y (1.0f/64) -#define MC_SCALE_Z (1.0f/64) - -void MC_UnCompress(float mat[3][4],const unsigned char * comp); -#endif - -/* -============================================================= - -ANIMATED MODELS - -============================================================= -*/ - -// void R_MakeAnimModel( model_t *model );      haven't seen this one really, so not needed I guess. -void R_AddAnimSurfaces( trRefEntity_t *ent ); -void RB_SurfaceAnim( md4Surface_t *surfType ); -#ifdef RAVENMD4 -void R_MDRAddAnimSurfaces( trRefEntity_t *ent ); -void RB_MDRSurfaceAnim( md4Surface_t *surface ); -#endif - -/* -============================================================= -============================================================= -*/ -void	R_TransformModelToClip( const vec3_t src, const float *modelMatrix, const float *projectionMatrix, -							vec4_t eye, vec4_t dst ); -void	R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t normalized, vec4_t window ); - -void	RB_DeformTessGeometry( void ); - -void	RB_CalcEnvironmentTexCoords( float *dstTexCoords ); -void	RB_CalcFogTexCoords( float *dstTexCoords ); -void	RB_CalcScrollTexCoords( const float scroll[2], float *dstTexCoords ); -void	RB_CalcRotateTexCoords( float rotSpeed, float *dstTexCoords ); -void	RB_CalcScaleTexCoords( const float scale[2], float *dstTexCoords ); -void	RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *dstTexCoords ); -void	RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *dstTexCoords ); -void	RB_CalcModulateColorsByFog( unsigned char *dstColors ); -void	RB_CalcModulateAlphasByFog( unsigned char *dstColors ); -void	RB_CalcModulateRGBAsByFog( unsigned char *dstColors ); -void	RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors ); -void	RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors ); -void	RB_CalcAlphaFromEntity( unsigned char *dstColors ); -void	RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors ); -void	RB_CalcStretchTexCoords( const waveForm_t *wf, float *texCoords ); -void	RB_CalcColorFromEntity( unsigned char *dstColors ); -void	RB_CalcColorFromOneMinusEntity( unsigned char *dstColors ); -void	RB_CalcSpecularAlpha( unsigned char *alphas ); -void	RB_CalcDiffuseColor( unsigned char *colors ); - -/* -============================================================= - -RENDERER BACK END FUNCTIONS - -============================================================= -*/ - -void RB_RenderThread( void ); -void RB_ExecuteRenderCommands( const void *data ); - -/* -============================================================= - -RENDERER BACK END COMMAND QUEUE - -============================================================= -*/ - -#define	MAX_RENDER_COMMANDS	0x40000 - -typedef struct { -	byte	cmds[MAX_RENDER_COMMANDS]; -	int		used; -} renderCommandList_t; - -typedef struct { -	int		commandId; -	float	color[4]; -} setColorCommand_t; - -typedef struct { -	int		commandId; -	int		buffer; -} drawBufferCommand_t; - -typedef struct { -	int		commandId; -	image_t	*image; -	int		width; -	int		height; -	void	*data; -} subImageCommand_t; - -typedef struct { -	int		commandId; -} swapBuffersCommand_t; - -typedef struct { -	int		commandId; -	int		buffer; -} endFrameCommand_t; - -typedef struct { -	int		commandId; -	shader_t	*shader; -	float	x, y; -	float	w, h; -	float	s1, t1; -	float	s2, t2; -} stretchPicCommand_t; - -typedef struct { -	int		commandId; -	trRefdef_t	refdef; -	viewParms_t	viewParms; -	drawSurf_t *drawSurfs; -	int		numDrawSurfs; -} drawSurfsCommand_t; - -typedef struct { -	int commandId; -	int x; -	int y; -	int width; -	int height; -	char *fileName; -	qboolean jpeg; -} screenshotCommand_t; - -typedef enum { -	RC_END_OF_LIST, -	RC_SET_COLOR, -	RC_STRETCH_PIC, -	RC_DRAW_SURFS, -	RC_DRAW_BUFFER, -	RC_SWAP_BUFFERS, -	RC_SCREENSHOT -} renderCommand_t; - - -// these are sort of arbitrary limits. -// the limits apply to the sum of all scenes in a frame -- -// the main view, all the 3D icons, etc -#define	MAX_POLYS		600 -#define	MAX_POLYVERTS	3000 - -// all of the information needed by the back end must be -// contained in a backEndData_t.  This entire structure is -// duplicated so the front and back end can run in parallel -// on an SMP machine -typedef struct { -	drawSurf_t	drawSurfs[MAX_DRAWSURFS]; -	dlight_t	dlights[MAX_DLIGHTS]; -	trRefEntity_t	entities[MAX_ENTITIES]; -	srfPoly_t	*polys;//[MAX_POLYS]; -	polyVert_t	*polyVerts;//[MAX_POLYVERTS]; -	renderCommandList_t	commands; -} backEndData_t; - -extern	int		max_polys; -extern	int		max_polyverts; - -extern	backEndData_t	*backEndData[SMP_FRAMES];	// the second one may not be allocated - -extern	volatile renderCommandList_t	*renderCommandList; - -extern	volatile qboolean	renderThreadActive; - - -void *R_GetCommandBuffer( int bytes ); -void RB_ExecuteRenderCommands( const void *data ); - -void R_InitCommandBuffers( void ); -void R_ShutdownCommandBuffers( void ); - -void R_SyncRenderThread( void ); - -void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs ); - -void RE_SetColor( const float *rgba ); -void RE_StretchPic ( float x, float y, float w, float h,  -					  float s1, float t1, float s2, float t2, qhandle_t hShader ); -void RE_BeginFrame( stereoFrame_t stereoFrame ); -void RE_EndFrame( int *frontEndMsec, int *backEndMsec ); -void SaveJPG(char * filename, int quality, int image_width, int image_height, unsigned char *image_buffer); - -// font stuff -void R_InitFreeType( void ); -void R_DoneFreeType( void ); -void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font); - - -#endif //TR_LOCAL_H diff --git a/ioq3-r437/src/renderer/tr_main.c b/ioq3-r437/src/renderer/tr_main.c deleted file mode 100644 index 61112484..00000000 --- a/ioq3-r437/src/renderer/tr_main.c +++ /dev/null @@ -1,1344 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_main.c -- main control flow for each frame - -#include "tr_local.h" - -#include <string.h> // memcpy - -trGlobals_t		tr; - -static float	s_flipMatrix[16] = { -	// convert from our coordinate system (looking down X) -	// to OpenGL's coordinate system (looking down -Z) -	0, 0, -1, 0, -	-1, 0, 0, 0, -	0, 1, 0, 0, -	0, 0, 0, 1 -}; - - -refimport_t	ri; - -// entities that will have procedurally generated surfaces will just -// point at this for their sorting surface -surfaceType_t	entitySurface = SF_ENTITY; - -/* -================= -R_CullLocalBox - -Returns CULL_IN, CULL_CLIP, or CULL_OUT -================= -*/ -int R_CullLocalBox (vec3_t bounds[2]) { -	int		i, j; -	vec3_t	transformed[8]; -	float	dists[8]; -	vec3_t	v; -	cplane_t	*frust; -	int			anyBack; -	int			front, back; - -	if ( r_nocull->integer ) { -		return CULL_CLIP; -	} - -	// transform into world space -	for (i = 0 ; i < 8 ; i++) { -		v[0] = bounds[i&1][0]; -		v[1] = bounds[(i>>1)&1][1]; -		v[2] = bounds[(i>>2)&1][2]; - -		VectorCopy( tr.or.origin, transformed[i] ); -		VectorMA( transformed[i], v[0], tr.or.axis[0], transformed[i] ); -		VectorMA( transformed[i], v[1], tr.or.axis[1], transformed[i] ); -		VectorMA( transformed[i], v[2], tr.or.axis[2], transformed[i] ); -	} - -	// check against frustum planes -	anyBack = 0; -	for (i = 0 ; i < 4 ; i++) { -		frust = &tr.viewParms.frustum[i]; - -		front = back = 0; -		for (j = 0 ; j < 8 ; j++) { -			dists[j] = DotProduct(transformed[j], frust->normal); -			if ( dists[j] > frust->dist ) { -				front = 1; -				if ( back ) { -					break;		// a point is in front -				} -			} else { -				back = 1; -			} -		} -		if ( !front ) { -			// all points were behind one of the planes -			return CULL_OUT; -		} -		anyBack |= back; -	} - -	if ( !anyBack ) { -		return CULL_IN;		// completely inside frustum -	} - -	return CULL_CLIP;		// partially clipped -} - -/* -** R_CullLocalPointAndRadius -*/ -int R_CullLocalPointAndRadius( vec3_t pt, float radius ) -{ -	vec3_t transformed; - -	R_LocalPointToWorld( pt, transformed ); - -	return R_CullPointAndRadius( transformed, radius ); -} - -/* -** R_CullPointAndRadius -*/ -int R_CullPointAndRadius( vec3_t pt, float radius ) -{ -	int		i; -	float	dist; -	cplane_t	*frust; -	qboolean mightBeClipped = qfalse; - -	if ( r_nocull->integer ) { -		return CULL_CLIP; -	} - -	// check against frustum planes -	for (i = 0 ; i < 4 ; i++)  -	{ -		frust = &tr.viewParms.frustum[i]; - -		dist = DotProduct( pt, frust->normal) - frust->dist; -		if ( dist < -radius ) -		{ -			return CULL_OUT; -		} -		else if ( dist <= radius )  -		{ -			mightBeClipped = qtrue; -		} -	} - -	if ( mightBeClipped ) -	{ -		return CULL_CLIP; -	} - -	return CULL_IN;		// completely inside frustum -} - - -/* -================= -R_LocalNormalToWorld - -================= -*/ -void R_LocalNormalToWorld (vec3_t local, vec3_t world) { -	world[0] = local[0] * tr.or.axis[0][0] + local[1] * tr.or.axis[1][0] + local[2] * tr.or.axis[2][0]; -	world[1] = local[0] * tr.or.axis[0][1] + local[1] * tr.or.axis[1][1] + local[2] * tr.or.axis[2][1]; -	world[2] = local[0] * tr.or.axis[0][2] + local[1] * tr.or.axis[1][2] + local[2] * tr.or.axis[2][2]; -} - -/* -================= -R_LocalPointToWorld - -================= -*/ -void R_LocalPointToWorld (vec3_t local, vec3_t world) { -	world[0] = local[0] * tr.or.axis[0][0] + local[1] * tr.or.axis[1][0] + local[2] * tr.or.axis[2][0] + tr.or.origin[0]; -	world[1] = local[0] * tr.or.axis[0][1] + local[1] * tr.or.axis[1][1] + local[2] * tr.or.axis[2][1] + tr.or.origin[1]; -	world[2] = local[0] * tr.or.axis[0][2] + local[1] * tr.or.axis[1][2] + local[2] * tr.or.axis[2][2] + tr.or.origin[2]; -} - -/* -================= -R_WorldToLocal - -================= -*/ -void R_WorldToLocal (vec3_t world, vec3_t local) { -	local[0] = DotProduct(world, tr.or.axis[0]); -	local[1] = DotProduct(world, tr.or.axis[1]); -	local[2] = DotProduct(world, tr.or.axis[2]); -} - -/* -========================== -R_TransformModelToClip - -========================== -*/ -void R_TransformModelToClip( const vec3_t src, const float *modelMatrix, const float *projectionMatrix, -							vec4_t eye, vec4_t dst ) { -	int i; - -	for ( i = 0 ; i < 4 ; i++ ) { -		eye[i] =  -			src[0] * modelMatrix[ i + 0 * 4 ] + -			src[1] * modelMatrix[ i + 1 * 4 ] + -			src[2] * modelMatrix[ i + 2 * 4 ] + -			1 * modelMatrix[ i + 3 * 4 ]; -	} - -	for ( i = 0 ; i < 4 ; i++ ) { -		dst[i] =  -			eye[0] * projectionMatrix[ i + 0 * 4 ] + -			eye[1] * projectionMatrix[ i + 1 * 4 ] + -			eye[2] * projectionMatrix[ i + 2 * 4 ] + -			eye[3] * projectionMatrix[ i + 3 * 4 ]; -	} -} - -/* -========================== -R_TransformClipToWindow - -========================== -*/ -void R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t normalized, vec4_t window ) { -	normalized[0] = clip[0] / clip[3]; -	normalized[1] = clip[1] / clip[3]; -	normalized[2] = ( clip[2] + clip[3] ) / ( 2 * clip[3] ); - -	window[0] = 0.5f * ( 1.0f + normalized[0] ) * view->viewportWidth; -	window[1] = 0.5f * ( 1.0f + normalized[1] ) * view->viewportHeight; -	window[2] = normalized[2]; - -	window[0] = (int) ( window[0] + 0.5 ); -	window[1] = (int) ( window[1] + 0.5 ); -} - - -/* -========================== -myGlMultMatrix - -========================== -*/ -void myGlMultMatrix( const float *a, const float *b, float *out ) { -	int		i, j; - -	for ( i = 0 ; i < 4 ; i++ ) { -		for ( j = 0 ; j < 4 ; j++ ) { -			out[ i * 4 + j ] = -				a [ i * 4 + 0 ] * b [ 0 * 4 + j ] -				+ a [ i * 4 + 1 ] * b [ 1 * 4 + j ] -				+ a [ i * 4 + 2 ] * b [ 2 * 4 + j ] -				+ a [ i * 4 + 3 ] * b [ 3 * 4 + j ]; -		} -	} -} - -/* -================= -R_RotateForEntity - -Generates an orientation for an entity and viewParms -Does NOT produce any GL calls -Called by both the front end and the back end -================= -*/ -void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms, -					   orientationr_t *or ) { -	float	glMatrix[16]; -	vec3_t	delta; -	float	axisLength; - -	if ( ent->e.reType != RT_MODEL ) { -		*or = viewParms->world; -		return; -	} - -	VectorCopy( ent->e.origin, or->origin ); - -	VectorCopy( ent->e.axis[0], or->axis[0] ); -	VectorCopy( ent->e.axis[1], or->axis[1] ); -	VectorCopy( ent->e.axis[2], or->axis[2] ); - -	glMatrix[0] = or->axis[0][0]; -	glMatrix[4] = or->axis[1][0]; -	glMatrix[8] = or->axis[2][0]; -	glMatrix[12] = or->origin[0]; - -	glMatrix[1] = or->axis[0][1]; -	glMatrix[5] = or->axis[1][1]; -	glMatrix[9] = or->axis[2][1]; -	glMatrix[13] = or->origin[1]; - -	glMatrix[2] = or->axis[0][2]; -	glMatrix[6] = or->axis[1][2]; -	glMatrix[10] = or->axis[2][2]; -	glMatrix[14] = or->origin[2]; - -	glMatrix[3] = 0; -	glMatrix[7] = 0; -	glMatrix[11] = 0; -	glMatrix[15] = 1; - -	myGlMultMatrix( glMatrix, viewParms->world.modelMatrix, or->modelMatrix ); - -	// calculate the viewer origin in the model's space -	// needed for fog, specular, and environment mapping -	VectorSubtract( viewParms->or.origin, or->origin, delta ); - -	// compensate for scale in the axes if necessary -	if ( ent->e.nonNormalizedAxes ) { -		axisLength = VectorLength( ent->e.axis[0] ); -		if ( !axisLength ) { -			axisLength = 0; -		} else { -			axisLength = 1.0f / axisLength; -		} -	} else { -		axisLength = 1.0f; -	} - -	or->viewOrigin[0] = DotProduct( delta, or->axis[0] ) * axisLength; -	or->viewOrigin[1] = DotProduct( delta, or->axis[1] ) * axisLength; -	or->viewOrigin[2] = DotProduct( delta, or->axis[2] ) * axisLength; -} - -/* -================= -R_RotateForViewer - -Sets up the modelview matrix for a given viewParm -================= -*/ -void R_RotateForViewer (void)  -{ -	float	viewerMatrix[16]; -	vec3_t	origin; - -	Com_Memset (&tr.or, 0, sizeof(tr.or)); -	tr.or.axis[0][0] = 1; -	tr.or.axis[1][1] = 1; -	tr.or.axis[2][2] = 1; -	VectorCopy (tr.viewParms.or.origin, tr.or.viewOrigin); - -	// transform by the camera placement -	VectorCopy( tr.viewParms.or.origin, origin ); - -	viewerMatrix[0] = tr.viewParms.or.axis[0][0]; -	viewerMatrix[4] = tr.viewParms.or.axis[0][1]; -	viewerMatrix[8] = tr.viewParms.or.axis[0][2]; -	viewerMatrix[12] = -origin[0] * viewerMatrix[0] + -origin[1] * viewerMatrix[4] + -origin[2] * viewerMatrix[8]; - -	viewerMatrix[1] = tr.viewParms.or.axis[1][0]; -	viewerMatrix[5] = tr.viewParms.or.axis[1][1]; -	viewerMatrix[9] = tr.viewParms.or.axis[1][2]; -	viewerMatrix[13] = -origin[0] * viewerMatrix[1] + -origin[1] * viewerMatrix[5] + -origin[2] * viewerMatrix[9]; - -	viewerMatrix[2] = tr.viewParms.or.axis[2][0]; -	viewerMatrix[6] = tr.viewParms.or.axis[2][1]; -	viewerMatrix[10] = tr.viewParms.or.axis[2][2]; -	viewerMatrix[14] = -origin[0] * viewerMatrix[2] + -origin[1] * viewerMatrix[6] + -origin[2] * viewerMatrix[10]; - -	viewerMatrix[3] = 0; -	viewerMatrix[7] = 0; -	viewerMatrix[11] = 0; -	viewerMatrix[15] = 1; - -	// convert from our coordinate system (looking down X) -	// to OpenGL's coordinate system (looking down -Z) -	myGlMultMatrix( viewerMatrix, s_flipMatrix, tr.or.modelMatrix ); - -	tr.viewParms.world = tr.or; - -} - -/* -** SetFarClip -*/ -static void SetFarClip( void ) -{ -	float	farthestCornerDistance = 0; -	int		i; - -	// if not rendering the world (icons, menus, etc) -	// set a 2k far clip plane -	if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { -		tr.viewParms.zFar = 2048; -		return; -	} - -	// -	// set far clipping planes dynamically -	// -	farthestCornerDistance = 0; -	for ( i = 0; i < 8; i++ ) -	{ -		vec3_t v; -		vec3_t vecTo; -		float distance; - -		if ( i & 1 ) -		{ -			v[0] = tr.viewParms.visBounds[0][0]; -		} -		else -		{ -			v[0] = tr.viewParms.visBounds[1][0]; -		} - -		if ( i & 2 ) -		{ -			v[1] = tr.viewParms.visBounds[0][1]; -		} -		else -		{ -			v[1] = tr.viewParms.visBounds[1][1]; -		} - -		if ( i & 4 ) -		{ -			v[2] = tr.viewParms.visBounds[0][2]; -		} -		else -		{ -			v[2] = tr.viewParms.visBounds[1][2]; -		} - -		VectorSubtract( v, tr.viewParms.or.origin, vecTo ); - -		distance = vecTo[0] * vecTo[0] + vecTo[1] * vecTo[1] + vecTo[2] * vecTo[2]; - -		if ( distance > farthestCornerDistance ) -		{ -			farthestCornerDistance = distance; -		} -	} -	tr.viewParms.zFar = sqrt( farthestCornerDistance ); -} - - -/* -=============== -R_SetupProjection -=============== -*/ -void R_SetupProjection( void ) { -	float	xmin, xmax, ymin, ymax; -	float	width, height, depth; -	float	zNear, zFar; - -	// dynamically compute far clip plane distance -	SetFarClip(); - -	// -	// set up projection matrix -	// -	zNear	= r_znear->value; -	zFar	= tr.viewParms.zFar; - -	ymax = zNear * tan( tr.refdef.fov_y * M_PI / 360.0f ); -	ymin = -ymax; - -	xmax = zNear * tan( tr.refdef.fov_x * M_PI / 360.0f ); -	xmin = -xmax; - -	width = xmax - xmin; -	height = ymax - ymin; -	depth = zFar - zNear; - -	tr.viewParms.projectionMatrix[0] = 2 * zNear / width; -	tr.viewParms.projectionMatrix[4] = 0; -	tr.viewParms.projectionMatrix[8] = ( xmax + xmin ) / width;	// normally 0 -	tr.viewParms.projectionMatrix[12] = 0; - -	tr.viewParms.projectionMatrix[1] = 0; -	tr.viewParms.projectionMatrix[5] = 2 * zNear / height; -	tr.viewParms.projectionMatrix[9] = ( ymax + ymin ) / height;	// normally 0 -	tr.viewParms.projectionMatrix[13] = 0; - -	tr.viewParms.projectionMatrix[2] = 0; -	tr.viewParms.projectionMatrix[6] = 0; -	tr.viewParms.projectionMatrix[10] = -( zFar + zNear ) / depth; -	tr.viewParms.projectionMatrix[14] = -2 * zFar * zNear / depth; - -	tr.viewParms.projectionMatrix[3] = 0; -	tr.viewParms.projectionMatrix[7] = 0; -	tr.viewParms.projectionMatrix[11] = -1; -	tr.viewParms.projectionMatrix[15] = 0; -} - -/* -================= -R_SetupFrustum - -Setup that culling frustum planes for the current view -================= -*/ -void R_SetupFrustum (void) { -	int		i; -	float	xs, xc; -	float	ang; - -	ang = tr.viewParms.fovX / 180 * M_PI * 0.5f; -	xs = sin( ang ); -	xc = cos( ang ); - -	VectorScale( tr.viewParms.or.axis[0], xs, tr.viewParms.frustum[0].normal ); -	VectorMA( tr.viewParms.frustum[0].normal, xc, tr.viewParms.or.axis[1], tr.viewParms.frustum[0].normal ); - -	VectorScale( tr.viewParms.or.axis[0], xs, tr.viewParms.frustum[1].normal ); -	VectorMA( tr.viewParms.frustum[1].normal, -xc, tr.viewParms.or.axis[1], tr.viewParms.frustum[1].normal ); - -	ang = tr.viewParms.fovY / 180 * M_PI * 0.5f; -	xs = sin( ang ); -	xc = cos( ang ); - -	VectorScale( tr.viewParms.or.axis[0], xs, tr.viewParms.frustum[2].normal ); -	VectorMA( tr.viewParms.frustum[2].normal, xc, tr.viewParms.or.axis[2], tr.viewParms.frustum[2].normal ); - -	VectorScale( tr.viewParms.or.axis[0], xs, tr.viewParms.frustum[3].normal ); -	VectorMA( tr.viewParms.frustum[3].normal, -xc, tr.viewParms.or.axis[2], tr.viewParms.frustum[3].normal ); - -	for (i=0 ; i<4 ; i++) { -		tr.viewParms.frustum[i].type = PLANE_NON_AXIAL; -		tr.viewParms.frustum[i].dist = DotProduct (tr.viewParms.or.origin, tr.viewParms.frustum[i].normal); -		SetPlaneSignbits( &tr.viewParms.frustum[i] ); -	} -} - - -/* -================= -R_MirrorPoint -================= -*/ -void R_MirrorPoint (vec3_t in, orientation_t *surface, orientation_t *camera, vec3_t out) { -	int		i; -	vec3_t	local; -	vec3_t	transformed; -	float	d; - -	VectorSubtract( in, surface->origin, local ); - -	VectorClear( transformed ); -	for ( i = 0 ; i < 3 ; i++ ) { -		d = DotProduct(local, surface->axis[i]); -		VectorMA( transformed, d, camera->axis[i], transformed ); -	} - -	VectorAdd( transformed, camera->origin, out ); -} - -void R_MirrorVector (vec3_t in, orientation_t *surface, orientation_t *camera, vec3_t out) { -	int		i; -	float	d; - -	VectorClear( out ); -	for ( i = 0 ; i < 3 ; i++ ) { -		d = DotProduct(in, surface->axis[i]); -		VectorMA( out, d, camera->axis[i], out ); -	} -} - - -/* -============= -R_PlaneForSurface -============= -*/ -void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) { -	srfTriangles_t	*tri; -	srfPoly_t		*poly; -	drawVert_t		*v1, *v2, *v3; -	vec4_t			plane4; - -	if (!surfType) { -		Com_Memset (plane, 0, sizeof(*plane)); -		plane->normal[0] = 1; -		return; -	} -	switch (*surfType) { -	case SF_FACE: -		*plane = ((srfSurfaceFace_t *)surfType)->plane; -		return; -	case SF_TRIANGLES: -		tri = (srfTriangles_t *)surfType; -		v1 = tri->verts + tri->indexes[0]; -		v2 = tri->verts + tri->indexes[1]; -		v3 = tri->verts + tri->indexes[2]; -		PlaneFromPoints( plane4, v1->xyz, v2->xyz, v3->xyz ); -		VectorCopy( plane4, plane->normal );  -		plane->dist = plane4[3]; -		return; -	case SF_POLY: -		poly = (srfPoly_t *)surfType; -		PlaneFromPoints( plane4, poly->verts[0].xyz, poly->verts[1].xyz, poly->verts[2].xyz ); -		VectorCopy( plane4, plane->normal );  -		plane->dist = plane4[3]; -		return; -	default: -		Com_Memset (plane, 0, sizeof(*plane)); -		plane->normal[0] = 1;		 -		return; -	} -} - -/* -================= -R_GetPortalOrientation - -entityNum is the entity that the portal surface is a part of, which may -be moving and rotating. - -Returns qtrue if it should be mirrored -================= -*/ -qboolean R_GetPortalOrientations( drawSurf_t *drawSurf, int entityNum,  -							 orientation_t *surface, orientation_t *camera, -							 vec3_t pvsOrigin, qboolean *mirror ) { -	int			i; -	cplane_t	originalPlane, plane; -	trRefEntity_t	*e; -	float		d; -	vec3_t		transformed; - -	// create plane axis for the portal we are seeing -	R_PlaneForSurface( drawSurf->surface, &originalPlane ); - -	// rotate the plane if necessary -	if ( entityNum != ENTITYNUM_WORLD ) { -		tr.currentEntityNum = entityNum; -		tr.currentEntity = &tr.refdef.entities[entityNum]; - -		// get the orientation of the entity -		R_RotateForEntity( tr.currentEntity, &tr.viewParms, &tr.or ); - -		// rotate the plane, but keep the non-rotated version for matching -		// against the portalSurface entities -		R_LocalNormalToWorld( originalPlane.normal, plane.normal ); -		plane.dist = originalPlane.dist + DotProduct( plane.normal, tr.or.origin ); - -		// translate the original plane -		originalPlane.dist = originalPlane.dist + DotProduct( originalPlane.normal, tr.or.origin ); -	} else { -		plane = originalPlane; -	} - -	VectorCopy( plane.normal, surface->axis[0] ); -	PerpendicularVector( surface->axis[1], surface->axis[0] ); -	CrossProduct( surface->axis[0], surface->axis[1], surface->axis[2] ); - -	// locate the portal entity closest to this plane. -	// origin will be the origin of the portal, origin2 will be -	// the origin of the camera -	for ( i = 0 ; i < tr.refdef.num_entities ; i++ ) { -		e = &tr.refdef.entities[i]; -		if ( e->e.reType != RT_PORTALSURFACE ) { -			continue; -		} - -		d = DotProduct( e->e.origin, originalPlane.normal ) - originalPlane.dist; -		if ( d > 64 || d < -64) { -			continue; -		} - -		// get the pvsOrigin from the entity -		VectorCopy( e->e.oldorigin, pvsOrigin ); - -		// if the entity is just a mirror, don't use as a camera point -		if ( e->e.oldorigin[0] == e->e.origin[0] &&  -			e->e.oldorigin[1] == e->e.origin[1] &&  -			e->e.oldorigin[2] == e->e.origin[2] ) { -			VectorScale( plane.normal, plane.dist, surface->origin ); -			VectorCopy( surface->origin, camera->origin ); -			VectorSubtract( vec3_origin, surface->axis[0], camera->axis[0] ); -			VectorCopy( surface->axis[1], camera->axis[1] ); -			VectorCopy( surface->axis[2], camera->axis[2] ); - -			*mirror = qtrue; -			return qtrue; -		} - -		// project the origin onto the surface plane to get -		// an origin point we can rotate around -		d = DotProduct( e->e.origin, plane.normal ) - plane.dist; -		VectorMA( e->e.origin, -d, surface->axis[0], surface->origin ); -			 -		// now get the camera origin and orientation -		VectorCopy( e->e.oldorigin, camera->origin ); -		AxisCopy( e->e.axis, camera->axis ); -		VectorSubtract( vec3_origin, camera->axis[0], camera->axis[0] ); -		VectorSubtract( vec3_origin, camera->axis[1], camera->axis[1] ); - -		// optionally rotate -		if ( e->e.oldframe ) { -			// if a speed is specified -			if ( e->e.frame ) { -				// continuous rotate -				d = (tr.refdef.time/1000.0f) * e->e.frame; -				VectorCopy( camera->axis[1], transformed ); -				RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d ); -				CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] ); -			} else { -				// bobbing rotate, with skinNum being the rotation offset -				d = sin( tr.refdef.time * 0.003f ); -				d = e->e.skinNum + d * 4; -				VectorCopy( camera->axis[1], transformed ); -				RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d ); -				CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] ); -			} -		} -		else if ( e->e.skinNum ) { -			d = e->e.skinNum; -			VectorCopy( camera->axis[1], transformed ); -			RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d ); -			CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] ); -		} -		*mirror = qfalse; -		return qtrue; -	} - -	// if we didn't locate a portal entity, don't render anything. -	// We don't want to just treat it as a mirror, because without a -	// portal entity the server won't have communicated a proper entity set -	// in the snapshot - -	// unfortunately, with local movement prediction it is easily possible -	// to see a surface before the server has communicated the matching -	// portal surface entity, so we don't want to print anything here... - -	//ri.Printf( PRINT_ALL, "Portal surface without a portal entity\n" ); - -	return qfalse; -} - -static qboolean IsMirror( const drawSurf_t *drawSurf, int entityNum ) -{ -	int			i; -	cplane_t	originalPlane, plane; -	trRefEntity_t	*e; -	float		d; - -	// create plane axis for the portal we are seeing -	R_PlaneForSurface( drawSurf->surface, &originalPlane ); - -	// rotate the plane if necessary -	if ( entityNum != ENTITYNUM_WORLD )  -	{ -		tr.currentEntityNum = entityNum; -		tr.currentEntity = &tr.refdef.entities[entityNum]; - -		// get the orientation of the entity -		R_RotateForEntity( tr.currentEntity, &tr.viewParms, &tr.or ); - -		// rotate the plane, but keep the non-rotated version for matching -		// against the portalSurface entities -		R_LocalNormalToWorld( originalPlane.normal, plane.normal ); -		plane.dist = originalPlane.dist + DotProduct( plane.normal, tr.or.origin ); - -		// translate the original plane -		originalPlane.dist = originalPlane.dist + DotProduct( originalPlane.normal, tr.or.origin ); -	}  -	else  -	{ -		plane = originalPlane; -	} - -	// locate the portal entity closest to this plane. -	// origin will be the origin of the portal, origin2 will be -	// the origin of the camera -	for ( i = 0 ; i < tr.refdef.num_entities ; i++ )  -	{ -		e = &tr.refdef.entities[i]; -		if ( e->e.reType != RT_PORTALSURFACE ) { -			continue; -		} - -		d = DotProduct( e->e.origin, originalPlane.normal ) - originalPlane.dist; -		if ( d > 64 || d < -64) { -			continue; -		} - -		// if the entity is just a mirror, don't use as a camera point -		if ( e->e.oldorigin[0] == e->e.origin[0] &&  -			e->e.oldorigin[1] == e->e.origin[1] &&  -			e->e.oldorigin[2] == e->e.origin[2] )  -		{ -			return qtrue; -		} - -		return qfalse; -	} -	return qfalse; -} - -/* -** SurfIsOffscreen -** -** Determines if a surface is completely offscreen. -*/ -static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128] ) { -	float shortest = 100000000; -	int entityNum; -	int numTriangles; -	shader_t *shader; -	int		fogNum; -	int dlighted; -	vec4_t clip, eye; -	int i; -	unsigned int pointOr = 0; -	unsigned int pointAnd = (unsigned int)~0; - -	if ( glConfig.smpActive ) {		// FIXME!  we can't do RB_BeginSurface/RB_EndSurface stuff with smp! -		return qfalse; -	} - -	R_RotateForViewer(); - -	R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted ); -	RB_BeginSurface( shader, fogNum ); -	rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface ); - -	assert( tess.numVertexes < 128 ); - -	for ( i = 0; i < tess.numVertexes; i++ ) -	{ -		int j; -		unsigned int pointFlags = 0; - -		R_TransformModelToClip( tess.xyz[i], tr.or.modelMatrix, tr.viewParms.projectionMatrix, eye, clip ); - -		for ( j = 0; j < 3; j++ ) -		{ -			if ( clip[j] >= clip[3] ) -			{ -				pointFlags |= (1 << (j*2)); -			} -			else if ( clip[j] <= -clip[3] ) -			{ -				pointFlags |= ( 1 << (j*2+1)); -			} -		} -		pointAnd &= pointFlags; -		pointOr |= pointFlags; -	} - -	// trivially reject -	if ( pointAnd ) -	{ -		return qtrue; -	} - -	// determine if this surface is backfaced and also determine the distance -	// to the nearest vertex so we can cull based on portal range.  Culling -	// based on vertex distance isn't 100% correct (we should be checking for -	// range to the surface), but it's good enough for the types of portals -	// we have in the game right now. -	numTriangles = tess.numIndexes / 3; - -	for ( i = 0; i < tess.numIndexes; i += 3 ) -	{ -		vec3_t normal; -		float dot; -		float len; - -		VectorSubtract( tess.xyz[tess.indexes[i]], tr.viewParms.or.origin, normal ); - -		len = VectorLengthSquared( normal );			// lose the sqrt -		if ( len < shortest ) -		{ -			shortest = len; -		} - -		if ( ( dot = DotProduct( normal, tess.normal[tess.indexes[i]] ) ) >= 0 ) -		{ -			numTriangles--; -		} -	} -	if ( !numTriangles ) -	{ -		return qtrue; -	} - -	// mirrors can early out at this point, since we don't do a fade over distance -	// with them (although we could) -	if ( IsMirror( drawSurf, entityNum ) ) -	{ -		return qfalse; -	} - -	if ( shortest > (tess.shader->portalRange*tess.shader->portalRange) ) -	{ -		return qtrue; -	} - -	return qfalse; -} - -/* -======================== -R_MirrorViewBySurface - -Returns qtrue if another view has been rendered -======================== -*/ -qboolean R_MirrorViewBySurface (drawSurf_t *drawSurf, int entityNum) { -	vec4_t			clipDest[128]; -	viewParms_t		newParms; -	viewParms_t		oldParms; -	orientation_t	surface, camera; - -	// don't recursively mirror -	if (tr.viewParms.isPortal) { -		ri.Printf( PRINT_DEVELOPER, "WARNING: recursive mirror/portal found\n" ); -		return qfalse; -	} - -	if ( r_noportals->integer || (r_fastsky->integer == 1) ) { -		return qfalse; -	} - -	// trivially reject portal/mirror -	if ( SurfIsOffscreen( drawSurf, clipDest ) ) { -		return qfalse; -	} - -	// save old viewParms so we can return to it after the mirror view -	oldParms = tr.viewParms; - -	newParms = tr.viewParms; -	newParms.isPortal = qtrue; -	if ( !R_GetPortalOrientations( drawSurf, entityNum, &surface, &camera,  -		newParms.pvsOrigin, &newParms.isMirror ) ) { -		return qfalse;		// bad portal, no portalentity -	} - -	R_MirrorPoint (oldParms.or.origin, &surface, &camera, newParms.or.origin ); - -	VectorSubtract( vec3_origin, camera.axis[0], newParms.portalPlane.normal ); -	newParms.portalPlane.dist = DotProduct( camera.origin, newParms.portalPlane.normal ); -	 -	R_MirrorVector (oldParms.or.axis[0], &surface, &camera, newParms.or.axis[0]); -	R_MirrorVector (oldParms.or.axis[1], &surface, &camera, newParms.or.axis[1]); -	R_MirrorVector (oldParms.or.axis[2], &surface, &camera, newParms.or.axis[2]); - -	// OPTIMIZE: restrict the viewport on the mirrored view - -	// render the mirror view -	R_RenderView (&newParms); - -	tr.viewParms = oldParms; - -	return qtrue; -} - -/* -================= -R_SpriteFogNum - -See if a sprite is inside a fog volume -================= -*/ -int R_SpriteFogNum( trRefEntity_t *ent ) { -	int				i, j; -	fog_t			*fog; - -	if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { -		return 0; -	} - -	for ( i = 1 ; i < tr.world->numfogs ; i++ ) { -		fog = &tr.world->fogs[i]; -		for ( j = 0 ; j < 3 ; j++ ) { -			if ( ent->e.origin[j] - ent->e.radius >= fog->bounds[1][j] ) { -				break; -			} -			if ( ent->e.origin[j] + ent->e.radius <= fog->bounds[0][j] ) { -				break; -			} -		} -		if ( j == 3 ) { -			return i; -		} -	} - -	return 0; -} - -/* -========================================================================================== - -DRAWSURF SORTING - -========================================================================================== -*/ - -/* -=============== -R_Radix -=============== -*/ -static ID_INLINE void R_Radix( int byte, int size, drawSurf_t *source, drawSurf_t *dest ) -{ -  int           count[ 256 ] = { 0 }; -  int           index[ 256 ]; -  int           i; -  unsigned char *sortKey = NULL; -  unsigned char *end = NULL; - -  sortKey = ( (unsigned char *)&source[ 0 ].sort ) + byte; -  end = sortKey + ( size * sizeof( drawSurf_t ) ); -  for( ; sortKey < end; sortKey += sizeof( drawSurf_t ) ) -    ++count[ *sortKey ]; - -  index[ 0 ] = 0; - -  for( i = 1; i < 256; ++i ) -    index[ i ] = index[ i - 1 ] + count[ i - 1 ]; - -  sortKey = ( (unsigned char *)&source[ 0 ].sort ) + byte; -  for( i = 0; i < size; ++i, sortKey += sizeof( drawSurf_t ) ) -    dest[ index[ *sortKey ]++ ] = source[ i ]; -} - -/* -=============== -R_RadixSort - -Radix sort with 4 byte size buckets -=============== -*/ -static void R_RadixSort( drawSurf_t *source, int size ) -{ -  static drawSurf_t scratch[ MAX_DRAWSURFS ]; - -  R_Radix( 0, size, source, scratch ); -  R_Radix( 1, size, scratch, source ); -  R_Radix( 2, size, source, scratch ); -  R_Radix( 3, size, scratch, source ); -} - -//========================================================================================== - -/* -================= -R_AddDrawSurf -================= -*/ -void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader,  -				   int fogIndex, int dlightMap ) { -	int			index; - -	// instead of checking for overflow, we just mask the index -	// so it wraps around -	index = tr.refdef.numDrawSurfs & DRAWSURF_MASK; -	// the sort data is packed into a single 32 bit value so it can be -	// compared quickly during the qsorting process -	tr.refdef.drawSurfs[index].sort = (shader->sortedIndex << QSORT_SHADERNUM_SHIFT)  -		| tr.shiftedEntityNum | ( fogIndex << QSORT_FOGNUM_SHIFT ) | (int)dlightMap; -	tr.refdef.drawSurfs[index].surface = surface; -	tr.refdef.numDrawSurfs++; -} - -/* -================= -R_DecomposeSort -================= -*/ -void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,  -					 int *fogNum, int *dlightMap ) { -	*fogNum = ( sort >> QSORT_FOGNUM_SHIFT ) & 31; -	*shader = tr.sortedShaders[ ( sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1) ]; -	*entityNum = ( sort >> QSORT_ENTITYNUM_SHIFT ) & 1023; -	*dlightMap = sort & 3; -} - -/* -================= -R_SortDrawSurfs -================= -*/ -void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) { -	shader_t		*shader; -	int				fogNum; -	int				entityNum; -	int				dlighted; -	int				i; - -	// it is possible for some views to not have any surfaces -	if ( numDrawSurfs < 1 ) { -		// we still need to add it for hyperspace cases -		R_AddDrawSurfCmd( drawSurfs, numDrawSurfs ); -		return; -	} - -	// if we overflowed MAX_DRAWSURFS, the drawsurfs -	// wrapped around in the buffer and we will be missing -	// the first surfaces, not the last ones -	if ( numDrawSurfs > MAX_DRAWSURFS ) { -		numDrawSurfs = MAX_DRAWSURFS; -	} - -	// sort the drawsurfs by sort type, then orientation, then shader -	R_RadixSort( drawSurfs, numDrawSurfs ); - -	// check for any pass through drawing, which -	// may cause another view to be rendered first -	for ( i = 0 ; i < numDrawSurfs ; i++ ) { -		R_DecomposeSort( (drawSurfs+i)->sort, &entityNum, &shader, &fogNum, &dlighted ); - -		if ( shader->sort > SS_PORTAL ) { -			break; -		} - -		// no shader should ever have this sort type -		if ( shader->sort == SS_BAD ) { -			ri.Error (ERR_DROP, "Shader '%s'with sort == SS_BAD", shader->name ); -		} - -		// if the mirror was completely clipped away, we may need to check another surface -		if ( R_MirrorViewBySurface( (drawSurfs+i), entityNum) ) { -			// this is a debug option to see exactly what is being mirrored -			if ( r_portalOnly->integer ) { -				return; -			} -			break;		// only one mirror view at a time -		} -	} - -	R_AddDrawSurfCmd( drawSurfs, numDrawSurfs ); -} - -/* -============= -R_AddEntitySurfaces -============= -*/ -void R_AddEntitySurfaces (void) { -	trRefEntity_t	*ent; -	shader_t		*shader; - -	if ( !r_drawentities->integer ) { -		return; -	} - -	for ( tr.currentEntityNum = 0;  -	      tr.currentEntityNum < tr.refdef.num_entities;  -		  tr.currentEntityNum++ ) { -		ent = tr.currentEntity = &tr.refdef.entities[tr.currentEntityNum]; - -		ent->needDlights = qfalse; - -		// preshift the value we are going to OR into the drawsurf sort -		tr.shiftedEntityNum = tr.currentEntityNum << QSORT_ENTITYNUM_SHIFT; - -		// -		// the weapon model must be handled special -- -		// we don't want the hacked weapon position showing in  -		// mirrors, because the true body position will already be drawn -		// -		if ( (ent->e.renderfx & RF_FIRST_PERSON) && tr.viewParms.isPortal) { -			continue; -		} - -		// simple generated models, like sprites and beams, are not culled -		switch ( ent->e.reType ) { -		case RT_PORTALSURFACE: -			break;		// don't draw anything -		case RT_SPRITE: -		case RT_BEAM: -		case RT_LIGHTNING: -		case RT_RAIL_CORE: -		case RT_RAIL_RINGS: -			// self blood sprites, talk balloons, etc should not be drawn in the primary -			// view.  We can't just do this check for all entities, because md3 -			// entities may still want to cast shadows from them -			if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal) { -				continue; -			} -			shader = R_GetShaderByHandle( ent->e.customShader ); -			R_AddDrawSurf( &entitySurface, shader, R_SpriteFogNum( ent ), 0 ); -			break; - -		case RT_MODEL: -			// we must set up parts of tr.or for model culling -			R_RotateForEntity( ent, &tr.viewParms, &tr.or ); - -			tr.currentModel = R_GetModelByHandle( ent->e.hModel ); -			if (!tr.currentModel) { -				R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0 ); -			} else { -				switch ( tr.currentModel->type ) { -				case MOD_MESH: -					R_AddMD3Surfaces( ent ); -					break; -				case MOD_MD4: -					R_AddAnimSurfaces( ent ); -					break; -#ifdef RAVENMD4 -				case MOD_MDR: -					R_MDRAddAnimSurfaces( ent ); -					break; -#endif -				case MOD_BRUSH: -					R_AddBrushModelSurfaces( ent ); -					break; -				case MOD_BAD:		// null model axis -					if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal) { -						break; -					} -					shader = R_GetShaderByHandle( ent->e.customShader ); -					R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0 ); -					break; -				default: -					ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad modeltype" ); -					break; -				} -			} -			break; -		default: -			ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad reType" ); -		} -	} - -} - - -/* -==================== -R_GenerateDrawSurfs -==================== -*/ -void R_GenerateDrawSurfs( void ) { -	R_AddWorldSurfaces (); - -	R_AddPolygonSurfaces(); - -	// set the projection matrix with the minimum zfar -	// now that we have the world bounded -	// this needs to be done before entities are -	// added, because they use the projection -	// matrix for lod calculation -	R_SetupProjection (); - -	R_AddEntitySurfaces (); -} - -/* -================ -R_DebugPolygon -================ -*/ -void R_DebugPolygon( int color, int numPoints, float *points ) { -	int		i; - -	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - -	// draw solid shade - -	qglColor3f( color&1, (color>>1)&1, (color>>2)&1 ); -	qglBegin( GL_POLYGON ); -	for ( i = 0 ; i < numPoints ; i++ ) { -		qglVertex3fv( points + i * 3 ); -	} -	qglEnd(); - -	// draw wireframe outline -	GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); -	qglDepthRange( 0, 0 ); -	qglColor3f( 1, 1, 1 ); -	qglBegin( GL_POLYGON ); -	for ( i = 0 ; i < numPoints ; i++ ) { -		qglVertex3fv( points + i * 3 ); -	} -	qglEnd(); -	qglDepthRange( 0, 1 ); -} - -/* -==================== -R_DebugGraphics - -Visualization aid for movement clipping debugging -==================== -*/ -void R_DebugGraphics( void ) { -	if ( !r_debugSurface->integer ) { -		return; -	} - -	// the render thread can't make callbacks to the main thread -	R_SyncRenderThread(); - -	GL_Bind( tr.whiteImage); -	GL_Cull( CT_FRONT_SIDED ); -	ri.CM_DrawDebugSurface( R_DebugPolygon ); -} - - -/* -================ -R_RenderView - -A view may be either the actual camera view, -or a mirror / remote location -================ -*/ -void R_RenderView (viewParms_t *parms) { -	int		firstDrawSurf; - -	if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) { -		return; -	} - -	tr.viewCount++; - -	tr.viewParms = *parms; -	tr.viewParms.frameSceneNum = tr.frameSceneNum; -	tr.viewParms.frameCount = tr.frameCount; - -	firstDrawSurf = tr.refdef.numDrawSurfs; - -	tr.viewCount++; - -	// set viewParms.world -	R_RotateForViewer (); - -	R_SetupFrustum (); - -	R_GenerateDrawSurfs(); - -	R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf ); - -	// draw main system development information (surface outlines, etc) -	R_DebugGraphics(); -} - - - diff --git a/ioq3-r437/src/renderer/tr_marks.c b/ioq3-r437/src/renderer/tr_marks.c deleted file mode 100644 index a283815b..00000000 --- a/ioq3-r437/src/renderer/tr_marks.c +++ /dev/null @@ -1,443 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_marks.c -- polygon projection on the world polygons - -#include "tr_local.h" -//#include "assert.h" - -#define MAX_VERTS_ON_POLY		64 - -#define MARKER_OFFSET			0	// 1 - -/* -============= -R_ChopPolyBehindPlane - -Out must have space for two more vertexes than in -============= -*/ -#define	SIDE_FRONT	0 -#define	SIDE_BACK	1 -#define	SIDE_ON		2 -static void R_ChopPolyBehindPlane( int numInPoints, vec3_t inPoints[MAX_VERTS_ON_POLY], -								   int *numOutPoints, vec3_t outPoints[MAX_VERTS_ON_POLY],  -							vec3_t normal, vec_t dist, vec_t epsilon) { -	float		dists[MAX_VERTS_ON_POLY+4]; -	int			sides[MAX_VERTS_ON_POLY+4]; -	int			counts[3]; -	float		dot; -	int			i, j; -	float		*p1, *p2, *clip; -	float		d; - -	// don't clip if it might overflow -	if ( numInPoints >= MAX_VERTS_ON_POLY - 2 ) { -		*numOutPoints = 0; -		return; -	} - -	counts[0] = counts[1] = counts[2] = 0; - -	// determine sides for each point -	for ( i = 0 ; i < numInPoints ; i++ ) { -		dot = DotProduct( inPoints[i], normal ); -		dot -= dist; -		dists[i] = dot; -		if ( dot > epsilon ) { -			sides[i] = SIDE_FRONT; -		} else if ( dot < -epsilon ) { -			sides[i] = SIDE_BACK; -		} else { -			sides[i] = SIDE_ON; -		} -		counts[sides[i]]++; -	} -	sides[i] = sides[0]; -	dists[i] = dists[0]; - -	*numOutPoints = 0; - -	if ( !counts[0] ) { -		return; -	} -	if ( !counts[1] ) { -		*numOutPoints = numInPoints; -		Com_Memcpy( outPoints, inPoints, numInPoints * sizeof(vec3_t) ); -		return; -	} - -	for ( i = 0 ; i < numInPoints ; i++ ) { -		p1 = inPoints[i]; -		clip = outPoints[ *numOutPoints ]; -		 -		if ( sides[i] == SIDE_ON ) { -			VectorCopy( p1, clip ); -			(*numOutPoints)++; -			continue; -		} -	 -		if ( sides[i] == SIDE_FRONT ) { -			VectorCopy( p1, clip ); -			(*numOutPoints)++; -			clip = outPoints[ *numOutPoints ]; -		} - -		if ( sides[i+1] == SIDE_ON || sides[i+1] == sides[i] ) { -			continue; -		} -			 -		// generate a split point -		p2 = inPoints[ (i+1) % numInPoints ]; - -		d = dists[i] - dists[i+1]; -		if ( d == 0 ) { -			dot = 0; -		} else { -			dot = dists[i] / d; -		} - -		// clip xyz - -		for (j=0 ; j<3 ; j++) { -			clip[j] = p1[j] + dot * ( p2[j] - p1[j] ); -		} - -		(*numOutPoints)++; -	} -} - -/* -================= -R_BoxSurfaces_r - -================= -*/ -void R_BoxSurfaces_r(mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **list, int listsize, int *listlength, vec3_t dir) { - -	int			s, c; -	msurface_t	*surf, **mark; - -	// do the tail recursion in a loop -	while ( node->contents == -1 ) { -		s = BoxOnPlaneSide( mins, maxs, node->plane ); -		if (s == 1) { -			node = node->children[0]; -		} else if (s == 2) { -			node = node->children[1]; -		} else { -			R_BoxSurfaces_r(node->children[0], mins, maxs, list, listsize, listlength, dir); -			node = node->children[1]; -		} -	} - -	// add the individual surfaces -	mark = node->firstmarksurface; -	c = node->nummarksurfaces; -	while (c--) { -		// -		if (*listlength >= listsize) break; -		// -		surf = *mark; -		// check if the surface has NOIMPACT or NOMARKS set -		if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) ) -			|| ( surf->shader->contentFlags & CONTENTS_FOG ) ) { -			surf->viewCount = tr.viewCount; -		} -		// extra check for surfaces to avoid list overflows -		else if (*(surf->data) == SF_FACE) { -			// the face plane should go through the box -			s = BoxOnPlaneSide( mins, maxs, &(( srfSurfaceFace_t * ) surf->data)->plane ); -			if (s == 1 || s == 2) { -				surf->viewCount = tr.viewCount; -			} else if (DotProduct((( srfSurfaceFace_t * ) surf->data)->plane.normal, dir) > -0.5) { -			// don't add faces that make sharp angles with the projection direction -				surf->viewCount = tr.viewCount; -			} -		} -		else if (*(surfaceType_t *) (surf->data) != SF_GRID) surf->viewCount = tr.viewCount; -		// check the viewCount because the surface may have -		// already been added if it spans multiple leafs -		if (surf->viewCount != tr.viewCount) { -			surf->viewCount = tr.viewCount; -			list[*listlength] = (surfaceType_t *) surf->data; -			(*listlength)++; -		} -		mark++; -	} -} - -/* -================= -R_AddMarkFragments - -================= -*/ -void R_AddMarkFragments(int numClipPoints, vec3_t clipPoints[2][MAX_VERTS_ON_POLY], -				   int numPlanes, vec3_t *normals, float *dists, -				   int maxPoints, vec3_t pointBuffer, -				   int maxFragments, markFragment_t *fragmentBuffer, -				   int *returnedPoints, int *returnedFragments, -				   vec3_t mins, vec3_t maxs) { -	int pingPong, i; -	markFragment_t	*mf; - -	// chop the surface by all the bounding planes of the to be projected polygon -	pingPong = 0; - -	for ( i = 0 ; i < numPlanes ; i++ ) { - -		R_ChopPolyBehindPlane( numClipPoints, clipPoints[pingPong], -						   &numClipPoints, clipPoints[!pingPong], -							normals[i], dists[i], 0.5 ); -		pingPong ^= 1; -		if ( numClipPoints == 0 ) { -			break; -		} -	} -	// completely clipped away? -	if ( numClipPoints == 0 ) { -		return; -	} - -	// add this fragment to the returned list -	if ( numClipPoints + (*returnedPoints) > maxPoints ) { -		return;	// not enough space for this polygon -	} -	/* -	// all the clip points should be within the bounding box -	for ( i = 0 ; i < numClipPoints ; i++ ) { -		int j; -		for ( j = 0 ; j < 3 ; j++ ) { -			if (clipPoints[pingPong][i][j] < mins[j] - 0.5) break; -			if (clipPoints[pingPong][i][j] > maxs[j] + 0.5) break; -		} -		if (j < 3) break; -	} -	if (i < numClipPoints) return; -	*/ - -	mf = fragmentBuffer + (*returnedFragments); -	mf->firstPoint = (*returnedPoints); -	mf->numPoints = numClipPoints; -	Com_Memcpy( pointBuffer + (*returnedPoints) * 3, clipPoints[pingPong], numClipPoints * sizeof(vec3_t) ); - -	(*returnedPoints) += numClipPoints; -	(*returnedFragments)++; -} - -/* -================= -R_MarkFragments - -================= -*/ -int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection, -				   int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ) { -	int				numsurfaces, numPlanes; -	int				i, j, k, m, n; -	surfaceType_t	*surfaces[64]; -	vec3_t			mins, maxs; -	int				returnedFragments; -	int				returnedPoints; -	vec3_t			normals[MAX_VERTS_ON_POLY+2]; -	float			dists[MAX_VERTS_ON_POLY+2]; -	vec3_t			clipPoints[2][MAX_VERTS_ON_POLY]; -	int				numClipPoints; -	float			*v; -	srfSurfaceFace_t *surf; -	srfGridMesh_t	*cv; -	drawVert_t		*dv; -	vec3_t			normal; -	vec3_t			projectionDir; -	vec3_t			v1, v2; -	int				*indexes; - -	//increment view count for double check prevention -	tr.viewCount++; - -	// -	VectorNormalize2( projection, projectionDir ); -	// find all the brushes that are to be considered -	ClearBounds( mins, maxs ); -	for ( i = 0 ; i < numPoints ; i++ ) { -		vec3_t	temp; - -		AddPointToBounds( points[i], mins, maxs ); -		VectorAdd( points[i], projection, temp ); -		AddPointToBounds( temp, mins, maxs ); -		// make sure we get all the leafs (also the one(s) in front of the hit surface) -		VectorMA( points[i], -20, projectionDir, temp ); -		AddPointToBounds( temp, mins, maxs ); -	} - -	if (numPoints > MAX_VERTS_ON_POLY) numPoints = MAX_VERTS_ON_POLY; -	// create the bounding planes for the to be projected polygon -	for ( i = 0 ; i < numPoints ; i++ ) { -		VectorSubtract(points[(i+1)%numPoints], points[i], v1); -		VectorAdd(points[i], projection, v2); -		VectorSubtract(points[i], v2, v2); -		CrossProduct(v1, v2, normals[i]); -		VectorNormalizeFast(normals[i]); -		dists[i] = DotProduct(normals[i], points[i]); -	} -	// add near and far clipping planes for projection -	VectorCopy(projectionDir, normals[numPoints]); -	dists[numPoints] = DotProduct(normals[numPoints], points[0]) - 32; -	VectorCopy(projectionDir, normals[numPoints+1]); -	VectorInverse(normals[numPoints+1]); -	dists[numPoints+1] = DotProduct(normals[numPoints+1], points[0]) - 20; -	numPlanes = numPoints + 2; - -	numsurfaces = 0; -	R_BoxSurfaces_r(tr.world->nodes, mins, maxs, surfaces, 64, &numsurfaces, projectionDir); -	//assert(numsurfaces <= 64); -	//assert(numsurfaces != 64); - -	returnedPoints = 0; -	returnedFragments = 0; - -	for ( i = 0 ; i < numsurfaces ; i++ ) { - -		if (*surfaces[i] == SF_GRID) { - -			cv = (srfGridMesh_t *) surfaces[i]; -			for ( m = 0 ; m < cv->height - 1 ; m++ ) { -				for ( n = 0 ; n < cv->width - 1 ; n++ ) { -					// We triangulate the grid and chop all triangles within -					// the bounding planes of the to be projected polygon. -					// LOD is not taken into account, not such a big deal though. -					// -					// It's probably much nicer to chop the grid itself and deal -					// with this grid as a normal SF_GRID surface so LOD will -					// be applied. However the LOD of that chopped grid must -					// be synced with the LOD of the original curve. -					// One way to do this; the chopped grid shares vertices with -					// the original curve. When LOD is applied to the original -					// curve the unused vertices are flagged. Now the chopped curve -					// should skip the flagged vertices. This still leaves the -					// problems with the vertices at the chopped grid edges. -					// -					// To avoid issues when LOD applied to "hollow curves" (like -					// the ones around many jump pads) we now just add a 2 unit -					// offset to the triangle vertices. -					// The offset is added in the vertex normal vector direction -					// so all triangles will still fit together. -					// The 2 unit offset should avoid pretty much all LOD problems. - -					numClipPoints = 3; - -					dv = cv->verts + m * cv->width + n; - -					VectorCopy(dv[0].xyz, clipPoints[0][0]); -					VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]); -					VectorCopy(dv[cv->width].xyz, clipPoints[0][1]); -					VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]); -					VectorCopy(dv[1].xyz, clipPoints[0][2]); -					VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]); -					// check the normal of this triangle -					VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1); -					VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2); -					CrossProduct(v1, v2, normal); -					VectorNormalizeFast(normal); -					if (DotProduct(normal, projectionDir) < -0.1) { -						// add the fragments of this triangle -						R_AddMarkFragments(numClipPoints, clipPoints, -										   numPlanes, normals, dists, -										   maxPoints, pointBuffer, -										   maxFragments, fragmentBuffer, -										   &returnedPoints, &returnedFragments, mins, maxs); - -						if ( returnedFragments == maxFragments ) { -							return returnedFragments;	// not enough space for more fragments -						} -					} - -					VectorCopy(dv[1].xyz, clipPoints[0][0]); -					VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]); -					VectorCopy(dv[cv->width].xyz, clipPoints[0][1]); -					VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]); -					VectorCopy(dv[cv->width+1].xyz, clipPoints[0][2]); -					VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width+1].normal, clipPoints[0][2]); -					// check the normal of this triangle -					VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1); -					VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2); -					CrossProduct(v1, v2, normal); -					VectorNormalizeFast(normal); -					if (DotProduct(normal, projectionDir) < -0.05) { -						// add the fragments of this triangle -						R_AddMarkFragments(numClipPoints, clipPoints, -										   numPlanes, normals, dists, -										   maxPoints, pointBuffer, -										   maxFragments, fragmentBuffer, -										   &returnedPoints, &returnedFragments, mins, maxs); - -						if ( returnedFragments == maxFragments ) { -							return returnedFragments;	// not enough space for more fragments -						} -					} -				} -			} -		} -		else if (*surfaces[i] == SF_FACE) { - -			surf = ( srfSurfaceFace_t * ) surfaces[i]; -			// check the normal of this face -			if (DotProduct(surf->plane.normal, projectionDir) > -0.5) { -				continue; -			} - -			/* -			VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1); -			VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2); -			CrossProduct(v1, v2, normal); -			VectorNormalize(normal); -			if (DotProduct(normal, projectionDir) > -0.5) continue; -			*/ -			indexes = (int *)( (byte *)surf + surf->ofsIndices ); -			for ( k = 0 ; k < surf->numIndices ; k += 3 ) { -				for ( j = 0 ; j < 3 ; j++ ) { -					v = surf->points[0] + VERTEXSIZE * indexes[k+j];; -					VectorMA( v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] ); -				} -				// add the fragments of this face -				R_AddMarkFragments( 3 , clipPoints, -								   numPlanes, normals, dists, -								   maxPoints, pointBuffer, -								   maxFragments, fragmentBuffer, -								   &returnedPoints, &returnedFragments, mins, maxs); -				if ( returnedFragments == maxFragments ) { -					return returnedFragments;	// not enough space for more fragments -				} -			} -			continue; -		} -		else { -			// ignore all other world surfaces -			// might be cool to also project polygons on a triangle soup -			// however this will probably create huge amounts of extra polys -			// even more than the projection onto curves -			continue; -		} -	} -	return returnedFragments; -} - diff --git a/ioq3-r437/src/renderer/tr_mesh.c b/ioq3-r437/src/renderer/tr_mesh.c deleted file mode 100644 index 9b60348b..00000000 --- a/ioq3-r437/src/renderer/tr_mesh.c +++ /dev/null @@ -1,418 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_mesh.c: triangle model functions - -#include "tr_local.h" - -static float ProjectRadius( float r, vec3_t location ) -{ -	float pr; -	float dist; -	float c; -	vec3_t	p; -	float	projected[4]; - -	c = DotProduct( tr.viewParms.or.axis[0], tr.viewParms.or.origin ); -	dist = DotProduct( tr.viewParms.or.axis[0], location ) - c; - -	if ( dist <= 0 ) -		return 0; - -	p[0] = 0; -	p[1] = fabs( r ); -	p[2] = -dist; - -	projected[0] = p[0] * tr.viewParms.projectionMatrix[0] +  -		           p[1] * tr.viewParms.projectionMatrix[4] + -				   p[2] * tr.viewParms.projectionMatrix[8] + -				   tr.viewParms.projectionMatrix[12]; - -	projected[1] = p[0] * tr.viewParms.projectionMatrix[1] +  -		           p[1] * tr.viewParms.projectionMatrix[5] + -				   p[2] * tr.viewParms.projectionMatrix[9] + -				   tr.viewParms.projectionMatrix[13]; - -	projected[2] = p[0] * tr.viewParms.projectionMatrix[2] +  -		           p[1] * tr.viewParms.projectionMatrix[6] + -				   p[2] * tr.viewParms.projectionMatrix[10] + -				   tr.viewParms.projectionMatrix[14]; - -	projected[3] = p[0] * tr.viewParms.projectionMatrix[3] +  -		           p[1] * tr.viewParms.projectionMatrix[7] + -				   p[2] * tr.viewParms.projectionMatrix[11] + -				   tr.viewParms.projectionMatrix[15]; - - -	pr = projected[1] / projected[3]; - -	if ( pr > 1.0f ) -		pr = 1.0f; - -	return pr; -} - -/* -============= -R_CullModel -============= -*/ -static int R_CullModel( md3Header_t *header, trRefEntity_t *ent ) { -	vec3_t		bounds[2]; -	md3Frame_t	*oldFrame, *newFrame; -	int			i; - -	// compute frame pointers -	newFrame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.frame; -	oldFrame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.oldframe; - -	// cull bounding sphere ONLY if this is not an upscaled entity -	if ( !ent->e.nonNormalizedAxes ) -	{ -		if ( ent->e.frame == ent->e.oldframe ) -		{ -			switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) ) -			{ -			case CULL_OUT: -				tr.pc.c_sphere_cull_md3_out++; -				return CULL_OUT; - -			case CULL_IN: -				tr.pc.c_sphere_cull_md3_in++; -				return CULL_IN; - -			case CULL_CLIP: -				tr.pc.c_sphere_cull_md3_clip++; -				break; -			} -		} -		else -		{ -			int sphereCull, sphereCullB; - -			sphereCull  = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ); -			if ( newFrame == oldFrame ) { -				sphereCullB = sphereCull; -			} else { -				sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius ); -			} - -			if ( sphereCull == sphereCullB ) -			{ -				if ( sphereCull == CULL_OUT ) -				{ -					tr.pc.c_sphere_cull_md3_out++; -					return CULL_OUT; -				} -				else if ( sphereCull == CULL_IN ) -				{ -					tr.pc.c_sphere_cull_md3_in++; -					return CULL_IN; -				} -				else -				{ -					tr.pc.c_sphere_cull_md3_clip++; -				} -			} -		} -	} -	 -	// calculate a bounding box in the current coordinate system -	for (i = 0 ; i < 3 ; i++) { -		bounds[0][i] = oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i]; -		bounds[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i]; -	} - -	switch ( R_CullLocalBox( bounds ) ) -	{ -	case CULL_IN: -		tr.pc.c_box_cull_md3_in++; -		return CULL_IN; -	case CULL_CLIP: -		tr.pc.c_box_cull_md3_clip++; -		return CULL_CLIP; -	case CULL_OUT: -	default: -		tr.pc.c_box_cull_md3_out++; -		return CULL_OUT; -	} -} - - -/* -================= -R_ComputeLOD - -================= -*/ -int R_ComputeLOD( trRefEntity_t *ent ) { -	float radius; -	float flod, lodscale; -	float projectedRadius; -	md3Frame_t *frame; -#ifdef RAVENMD4 -	mdrHeader_t *mdr; -	mdrFrame_t *mdrframe; -#endif -	int lod; - -	if ( tr.currentModel->numLods < 2 ) -	{ -		// model has only 1 LOD level, skip computations and bias -		lod = 0; -	} -	else -	{ -		// multiple LODs exist, so compute projected bounding sphere -		// and use that as a criteria for selecting LOD - -#ifdef RAVENMD4 -		// This is an MDR model. -		 -		if(tr.currentModel->md4) -		{ -			int frameSize; -			mdr = (mdrHeader_t *) tr.currentModel->md4; -			frameSize = (size_t) (&((mdrFrame_t *)0)->bones[mdr->numBones]); -			 -			mdrframe = (mdrFrame_t *) ((byte *) mdr + mdr->ofsFrames + frameSize * ent->e.frame); -			 -			radius = RadiusFromBounds(mdrframe->bounds[0], mdrframe->bounds[1]); -		} -		else -#endif -		{ -			frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames ); - -			frame += ent->e.frame; - -			radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] ); -		} - -		if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 ) -		{ -			lodscale = r_lodscale->value; -			if (lodscale > 20) lodscale = 20; -			flod = 1.0f - projectedRadius * lodscale; -		} -		else -		{ -			// object intersects near view plane, e.g. view weapon -			flod = 0; -		} - -		flod *= tr.currentModel->numLods; -		lod = myftol( flod ); - -		if ( lod < 0 ) -		{ -			lod = 0; -		} -		else if ( lod >= tr.currentModel->numLods ) -		{ -			lod = tr.currentModel->numLods - 1; -		} -	} - -	lod += r_lodbias->integer; -	 -	if ( lod >= tr.currentModel->numLods ) -		lod = tr.currentModel->numLods - 1; -	if ( lod < 0 ) -		lod = 0; - -	return lod; -} - -/* -================= -R_ComputeFogNum - -================= -*/ -int R_ComputeFogNum( md3Header_t *header, trRefEntity_t *ent ) { -	int				i, j; -	fog_t			*fog; -	md3Frame_t		*md3Frame; -	vec3_t			localOrigin; - -	if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { -		return 0; -	} - -	// FIXME: non-normalized axis issues -	md3Frame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.frame; -	VectorAdd( ent->e.origin, md3Frame->localOrigin, localOrigin ); -	for ( i = 1 ; i < tr.world->numfogs ; i++ ) { -		fog = &tr.world->fogs[i]; -		for ( j = 0 ; j < 3 ; j++ ) { -			if ( localOrigin[j] - md3Frame->radius >= fog->bounds[1][j] ) { -				break; -			} -			if ( localOrigin[j] + md3Frame->radius <= fog->bounds[0][j] ) { -				break; -			} -		} -		if ( j == 3 ) { -			return i; -		} -	} - -	return 0; -} - -/* -================= -R_AddMD3Surfaces - -================= -*/ -void R_AddMD3Surfaces( trRefEntity_t *ent ) { -	int				i; -	md3Header_t		*header = NULL; -	md3Surface_t	*surface = NULL; -	md3Shader_t		*md3Shader = NULL; -	shader_t		*shader = NULL; -	int				cull; -	int				lod; -	int				fogNum; -	qboolean		personalModel; - -	// don't add third_person objects if not in a portal -	personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal; - -	if ( ent->e.renderfx & RF_WRAP_FRAMES ) { -		ent->e.frame %= tr.currentModel->md3[0]->numFrames; -		ent->e.oldframe %= tr.currentModel->md3[0]->numFrames; -	} - -	// -	// Validate the frames so there is no chance of a crash. -	// This will write directly into the entity structure, so -	// when the surfaces are rendered, they don't need to be -	// range checked again. -	// -	if ( (ent->e.frame >= tr.currentModel->md3[0]->numFrames)  -		|| (ent->e.frame < 0) -		|| (ent->e.oldframe >= tr.currentModel->md3[0]->numFrames) -		|| (ent->e.oldframe < 0) ) { -			ri.Printf( PRINT_DEVELOPER, "R_AddMD3Surfaces: no such frame %d to %d for '%s'\n", -				ent->e.oldframe, ent->e.frame, -				tr.currentModel->name ); -			ent->e.frame = 0; -			ent->e.oldframe = 0; -	} - -	// -	// compute LOD -	// -	lod = R_ComputeLOD( ent ); - -	header = tr.currentModel->md3[lod]; - -	// -	// cull the entire model if merged bounding box of both frames -	// is outside the view frustum. -	// -	cull = R_CullModel ( header, ent ); -	if ( cull == CULL_OUT ) { -		return; -	} - -	// -	// set up lighting now that we know we aren't culled -	// -	if ( !personalModel || r_shadows->integer > 1 ) { -		R_SetupEntityLighting( &tr.refdef, ent ); -	} - -	// -	// see if we are in a fog volume -	// -	fogNum = R_ComputeFogNum( header, ent ); - -	// -	// draw all surfaces -	// -	surface = (md3Surface_t *)( (byte *)header + header->ofsSurfaces ); -	for ( i = 0 ; i < header->numSurfaces ; i++ ) { - -		if ( ent->e.customShader ) { -			shader = R_GetShaderByHandle( ent->e.customShader ); -		} else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) { -			skin_t *skin; -			int		j; - -			skin = R_GetSkinByHandle( ent->e.customSkin ); - -			// match the surface name to something in the skin file -			shader = tr.defaultShader; -			for ( j = 0 ; j < skin->numSurfaces ; j++ ) { -				// the names have both been lowercased -				if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) { -					shader = skin->surfaces[j]->shader; -					break; -				} -			} -			if (shader == tr.defaultShader) { -				ri.Printf( PRINT_DEVELOPER, "WARNING: no shader for surface %s in skin %s\n", surface->name, skin->name); -			} -			else if (shader->defaultShader) { -				ri.Printf( PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name); -			} -		} else if ( surface->numShaders <= 0 ) { -			shader = tr.defaultShader; -		} else { -			md3Shader = (md3Shader_t *) ( (byte *)surface + surface->ofsShaders ); -			md3Shader += ent->e.skinNum % surface->numShaders; -			shader = tr.shaders[ md3Shader->shaderIndex ]; -		} - - -		// we will add shadows even if the main object isn't visible in the view - -		// stencil shadows can't do personal models unless I polyhedron clip -		if ( !personalModel -			&& r_shadows->integer == 2  -			&& fogNum == 0 -			&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )  -			&& shader->sort == SS_OPAQUE ) { -			R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse ); -		} - -		// projection shadows work fine with personal models -		if ( r_shadows->integer == 3 -			&& fogNum == 0 -			&& (ent->e.renderfx & RF_SHADOW_PLANE ) -			&& shader->sort == SS_OPAQUE ) { -			R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse ); -		} - -		// don't add third_person objects if not viewing through a portal -		if ( !personalModel ) { -			R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse ); -		} - -		surface = (md3Surface_t *)( (byte *)surface + surface->ofsEnd ); -	} - -} - diff --git a/ioq3-r437/src/renderer/tr_model.c b/ioq3-r437/src/renderer/tr_model.c deleted file mode 100644 index a6bfb5db..00000000 --- a/ioq3-r437/src/renderer/tr_model.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_models.c -- model loading and caching - -#include "tr_local.h" - -#define	LL(x) x=LittleLong(x) - -static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *name ); -static qboolean R_LoadMD4 (model_t *mod, void *buffer, const char *name ); -#ifdef RAVENMD4 -static qboolean R_LoadMDR (model_t *mod, void *buffer, int filesize, const char *name ); -#endif - -model_t	*loadmodel; - -/* -** R_GetModelByHandle -*/ -model_t	*R_GetModelByHandle( qhandle_t index ) { -	model_t		*mod; - -	// out of range gets the defualt model -	if ( index < 1 || index >= tr.numModels ) { -		return tr.models[0]; -	} - -	mod = tr.models[index]; - -	return mod; -} - -//=============================================================================== - -/* -** R_AllocModel -*/ -model_t *R_AllocModel( void ) { -	model_t		*mod; - -	if ( tr.numModels == MAX_MOD_KNOWN ) { -		return NULL; -	} - -	mod = ri.Hunk_Alloc( sizeof( *tr.models[tr.numModels] ), h_low ); -	mod->index = tr.numModels; -	tr.models[tr.numModels] = mod; -	tr.numModels++; - -	return mod; -} - -/* -==================== -RE_RegisterModel - -Loads in a model for the given name - -Zero will be returned if the model fails to load. -An entry will be retained for failed models as an -optimization to prevent disk rescanning if they are -asked for again. -==================== -*/ -qhandle_t RE_RegisterModel( const char *name ) { -	model_t		*mod; -	unsigned	*buf; -	int			lod; -	int			ident; -	qboolean	loaded = qfalse; -	qhandle_t	hModel; -	int			numLoaded; -	char		*fext, defex[] = "md3", filename[MAX_QPATH], namebuf[MAX_QPATH+20]; - -	if ( !name || !name[0] ) { -		ri.Printf( PRINT_ALL, "RE_RegisterModel: NULL name\n" ); -		return 0; -	} - -	if ( strlen( name ) >= MAX_QPATH ) { -		Com_Printf( "Model name exceeds MAX_QPATH\n" ); -		return 0; -	} - -	// -	// search the currently loaded models -	// -	for ( hModel = 1 ; hModel < tr.numModels; hModel++ ) { -		mod = tr.models[hModel]; -		if ( !strcmp( mod->name, name ) ) { -			if( mod->type == MOD_BAD ) { -				return 0; -			} -			return hModel; -		} -	} - -	// allocate a new model_t - -	if ( ( mod = R_AllocModel() ) == NULL ) { -		ri.Printf( PRINT_WARNING, "RE_RegisterModel: R_AllocModel() failed for '%s'\n", name); -		return 0; -	} - -	// only set the name after the model has been successfully loaded -	Q_strncpyz( mod->name, name, sizeof( mod->name ) ); - - -	// make sure the render thread is stopped -	R_SyncRenderThread(); - -	mod->numLods = 0; - -	// -	// load the files -	// -	numLoaded = 0; - -	strcpy(filename, name); - -	fext = strchr(filename, '.'); -	if(!fext) -		fext = defex; -	else -	{ -		*fext = '\0'; -		fext++; -	} - -#ifdef RAVENMD4 -	if(!Q_stricmp(fext, "mdr")) -	{ -		int filesize; -		 -		filesize = ri.FS_ReadFile(name, (void **) &buf); -		if(!buf) -		{ -			ri.Printf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name); -			mod->type = MOD_BAD; -			return 0; -		} -		 -		ident = LittleLong(*(unsigned *)buf); -		if(ident == MDR_IDENT) -			loaded = R_LoadMDR(mod, buf, filesize, name); - -		ri.FS_FreeFile (buf); -		 -		if(!loaded) -		{ -			ri.Printf(PRINT_WARNING,"RE_RegisterModel: couldn't load mdr file %s\n", name); -			mod->type = MOD_BAD; -			return 0; -		} -		 -		return mod->index; -	} -#endif - -	fext = defex; - -	for ( lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod-- ) { -		if ( lod ) -			Com_sprintf(namebuf, sizeof(namebuf), "%s_%d.%s", filename, lod, fext); -		else -			Com_sprintf(namebuf, sizeof(namebuf), "%s.%s", filename, fext); - -		ri.FS_ReadFile( namebuf, (void **)&buf ); -		if ( !buf ) { -			continue; -		} -		 -		loadmodel = mod; -		 -		ident = LittleLong(*(unsigned *)buf); -		if ( ident == MD4_IDENT ) { -			loaded = R_LoadMD4( mod, buf, name ); -		} else { -			if ( ident != MD3_IDENT ) { -				ri.Printf (PRINT_WARNING,"RE_RegisterModel: unknown fileid for %s\n", name); -				goto fail; -			} - -			loaded = R_LoadMD3( mod, lod, buf, name ); -		} -		 -		ri.FS_FreeFile (buf); - -		if ( !loaded ) { -			if ( lod == 0 ) { -				goto fail; -			} else { -				break; -			} -		} else { -			mod->numLods++; -			numLoaded++; -			// if we have a valid model and are biased -			// so that we won't see any higher detail ones, -			// stop loading them -//			if ( lod <= r_lodbias->integer ) { -//				break; -//			} -		} -	} - -	if ( numLoaded ) { -		// duplicate into higher lod spots that weren't -		// loaded, in case the user changes r_lodbias on the fly -		for ( lod-- ; lod >= 0 ; lod-- ) { -			mod->numLods++; -			mod->md3[lod] = mod->md3[lod+1]; -		} - -		return mod->index; -	} -#ifdef _DEBUG -	else { -		ri.Printf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name); -	} -#endif - -fail: -	// we still keep the model_t around, so if the model name is asked for -	// again, we won't bother scanning the filesystem -	mod->type = MOD_BAD; -	return 0; -} - - -/* -================= -R_LoadMD3 -================= -*/ -static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *mod_name ) { -	int					i, j; -	md3Header_t			*pinmodel; -    md3Frame_t			*frame; -	md3Surface_t		*surf; -	md3Shader_t			*shader; -	md3Triangle_t		*tri; -	md3St_t				*st; -	md3XyzNormal_t		*xyz; -	md3Tag_t			*tag; -	int					version; -	int					size; - -	pinmodel = (md3Header_t *)buffer; - -	version = LittleLong (pinmodel->version); -	if (version != MD3_VERSION) { -		ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n", -				 mod_name, version, MD3_VERSION); -		return qfalse; -	} - -	mod->type = MOD_MESH; -	size = LittleLong(pinmodel->ofsEnd); -	mod->dataSize += size; -	mod->md3[lod] = ri.Hunk_Alloc( size, h_low ); - -	Com_Memcpy (mod->md3[lod], buffer, LittleLong(pinmodel->ofsEnd) ); - -    LL(mod->md3[lod]->ident); -    LL(mod->md3[lod]->version); -    LL(mod->md3[lod]->numFrames); -    LL(mod->md3[lod]->numTags); -    LL(mod->md3[lod]->numSurfaces); -    LL(mod->md3[lod]->ofsFrames); -    LL(mod->md3[lod]->ofsTags); -    LL(mod->md3[lod]->ofsSurfaces); -    LL(mod->md3[lod]->ofsEnd); - -	if ( mod->md3[lod]->numFrames < 1 ) { -		ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has no frames\n", mod_name ); -		return qfalse; -	} -     -	// swap all the frames -    frame = (md3Frame_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsFrames ); -    for ( i = 0 ; i < mod->md3[lod]->numFrames ; i++, frame++) { -    	frame->radius = LittleFloat( frame->radius ); -        for ( j = 0 ; j < 3 ; j++ ) { -            frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] ); -            frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] ); -	    	frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] ); -        } -	} - -	// swap all the tags -    tag = (md3Tag_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsTags ); -    for ( i = 0 ; i < mod->md3[lod]->numTags * mod->md3[lod]->numFrames ; i++, tag++) { -        for ( j = 0 ; j < 3 ; j++ ) { -			tag->origin[j] = LittleFloat( tag->origin[j] ); -			tag->axis[0][j] = LittleFloat( tag->axis[0][j] ); -			tag->axis[1][j] = LittleFloat( tag->axis[1][j] ); -			tag->axis[2][j] = LittleFloat( tag->axis[2][j] ); -        } -	} - -	// swap all the surfaces -	surf = (md3Surface_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsSurfaces ); -	for ( i = 0 ; i < mod->md3[lod]->numSurfaces ; i++) { - -        LL(surf->ident); -        LL(surf->flags); -        LL(surf->numFrames); -        LL(surf->numShaders); -        LL(surf->numTriangles); -        LL(surf->ofsTriangles); -        LL(surf->numVerts); -        LL(surf->ofsShaders); -        LL(surf->ofsSt); -        LL(surf->ofsXyzNormals); -        LL(surf->ofsEnd); -		 -		if ( surf->numVerts > SHADER_MAX_VERTEXES ) { -			ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)", -				mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); -		} -		if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { -			ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)", -				mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); -		} -	 -		// change to surface identifier -		surf->ident = SF_MD3; - -		// lowercase the surface name so skin compares are faster -		Q_strlwr( surf->name ); - -		// strip off a trailing _1 or _2 -		// this is a crutch for q3data being a mess -		j = strlen( surf->name ); -		if ( j > 2 && surf->name[j-2] == '_' ) { -			surf->name[j-2] = 0; -		} - -        // register the shaders -        shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders ); -        for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) { -            shader_t	*sh; - -            sh = R_FindShader( shader->name, LIGHTMAP_NONE, qtrue ); -			if ( sh->defaultShader ) { -				shader->shaderIndex = 0; -			} else { -				shader->shaderIndex = sh->index; -			} -        } - -		// swap all the triangles -		tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); -		for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { -			LL(tri->indexes[0]); -			LL(tri->indexes[1]); -			LL(tri->indexes[2]); -		} - -		// swap all the ST -        st = (md3St_t *) ( (byte *)surf + surf->ofsSt ); -        for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { -            st->st[0] = LittleFloat( st->st[0] ); -            st->st[1] = LittleFloat( st->st[1] ); -        } - -		// swap all the XyzNormals -        xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals ); -        for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ )  -		{ -            xyz->xyz[0] = LittleShort( xyz->xyz[0] ); -            xyz->xyz[1] = LittleShort( xyz->xyz[1] ); -            xyz->xyz[2] = LittleShort( xyz->xyz[2] ); - -            xyz->normal = LittleShort( xyz->normal ); -        } - - -		// find the next surface -		surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd ); -	} -     -	return qtrue; -} - - - -/* -================= -R_LoadMDR -================= -*/ -#ifdef RAVENMD4 -static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char *mod_name )  -{ -	int					i, j, k, l; -	mdrHeader_t			*pinmodel, *mdr; -        mdrFrame_t			*frame; -	mdrLOD_t			*lod, *curlod; -	mdrSurface_t			*surf, *cursurf; -	mdrTriangle_t			*tri, *curtri; -	mdrVertex_t			*v, *curv; -	mdrWeight_t			*weight, *curweight; -	mdrTag_t			*tag, *curtag; -	int					size; -	shader_t			*sh; - -	pinmodel = (mdrHeader_t *)buffer; - -	pinmodel->version = LittleLong(pinmodel->version); -	if (pinmodel->version != MDR_VERSION)  -	{ -		ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has wrong version (%i should be %i)\n", mod_name, pinmodel->version, MDR_VERSION); -		return qfalse; -	} - -	size = LittleLong(pinmodel->ofsEnd); -	 -	if(size > filesize) -	{ -		ri.Printf(PRINT_WARNING, "R_LoadMDR: Header of %s is broken. Wrong filesize declared!\n", mod_name); -		return qfalse; -	} -	 -	mod->type = MOD_MDR; - -	pinmodel->numFrames = LittleLong(pinmodel->numFrames); -	pinmodel->numBones = LittleLong(pinmodel->numBones); -	pinmodel->ofsFrames = LittleLong(pinmodel->ofsFrames); -	 -	// This is a model that uses some type of compressed Bones. We don't want to uncompress every bone for each rendered frame -	// over and over again, we'll uncompress it in this function already, so we must adjust the size of the target md4. -	if(pinmodel->ofsFrames < 0) -	{ -		// mdrFrame_t is larger than mdrCompFrame_t: -		size += pinmodel->numFrames * sizeof(frame->name); -		// now add enough space for the uncompressed bones. -		size += pinmodel->numFrames * pinmodel->numBones * ((sizeof(mdrBone_t) - sizeof(mdrCompBone_t))); -	} -	 -	mod->dataSize += size; -	mod->md4 = mdr = ri.Hunk_Alloc( size, h_low ); - -	// Copy all the values over from the file and fix endian issues in the process, if necessary. -	 -	mdr->ident = LittleLong(pinmodel->ident); -	mdr->version = pinmodel->version;	// Don't need to swap byte order on this one, we already did above. -	Q_strncpyz(mdr->name, pinmodel->name, sizeof(mdr->name)); -	mdr->numFrames = pinmodel->numFrames; -	mdr->numBones = pinmodel->numBones; -	mdr->numLODs = LittleLong(pinmodel->numLODs); -	mdr->numTags = LittleLong(pinmodel->numTags); -	// We don't care about offset values, we'll generate them ourselves while loading. -	 -	mod->numLods = mdr->numLODs; - -	if ( mdr->numFrames < 1 )  -	{ -		ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has no frames\n", mod_name); -		return qfalse; -	} - -	/* The first frame will be put into the first free space after the header */ -	frame = (mdrFrame_t *)(mdr + 1); -	mdr->ofsFrames = (int)((byte *) frame - (byte *) mdr); -		 -	if (pinmodel->ofsFrames < 0) -	{ -		mdrCompFrame_t *cframe; -				 -		// compressed model...				 -		cframe = (mdrCompFrame_t *)((byte *) pinmodel - pinmodel->ofsFrames); - -		for(i = 0; i < mdr->numFrames; i++) -		{ -			for(j = 0; j < 3; j++) -			{ -				frame->bounds[0][j] = LittleFloat(cframe->bounds[0][j]); -				frame->bounds[1][j] = LittleFloat(cframe->bounds[1][j]); -				frame->localOrigin[j] = LittleFloat(cframe->localOrigin[j]); -			} - -			frame->radius = LittleFloat(cframe->radius); -			frame->name[0] = '\0';	// No name supplied in the compressed version. -			 -			for(j = 0; j < mdr->numBones; j++) -			{ -				for(k = 0; k < (sizeof(cframe->bones[j].Comp) / 2); k++) -				{ -					// Do swapping for the uncompressing functions. They seem to use shorts -					// values only, so I assume this will work. Never tested it on other -					// platforms, though. -					 -					((unsigned short *)(cframe->bones[j].Comp))[k] = -						LittleShort( ((unsigned short *)(cframe->bones[j].Comp))[k] ); -				} -				 -				/* Now do the actual uncompressing */ -				MC_UnCompress(frame->bones[j].matrix, cframe->bones[j].Comp); -			} -			 -			// Next Frame... -			cframe = (mdrCompFrame_t *) &cframe->bones[j]; -			frame = (mdrFrame_t *) &frame->bones[j]; -		} -	} -	else -	{ -		mdrFrame_t *curframe; -		 -		// uncompressed model... -		// -     -		curframe = (mdrFrame_t *)((byte *) pinmodel + pinmodel->ofsFrames); -		 -		// swap all the frames -		for ( i = 0 ; i < mdr->numFrames ; i++)  -		{ -			for(j = 0; j < 3; j++) -			{ -				frame->bounds[0][j] = LittleFloat(curframe->bounds[0][j]); -				frame->bounds[1][j] = LittleFloat(curframe->bounds[1][j]); -				frame->localOrigin[j] = LittleFloat(curframe->localOrigin[j]); -			} -			 -			frame->radius = LittleFloat(curframe->radius); -			Q_strncpyz(frame->name, curframe->name, sizeof(frame->name)); -			 -			for (j = 0; j < (int) (mdr->numBones * sizeof(mdrBone_t) / 4); j++)  -			{ -				((float *)frame->bones)[j] = LittleFloat( ((float *)curframe->bones)[j] ); -			} -			 -			curframe++; -			frame++; -		} -	} -	 -	// frame should now point to the first free address after all frames. -	lod = (mdrLOD_t *) frame; -	mdr->ofsLODs = (int) ((byte *) lod - (byte *)mdr); -	 -	curlod = (mdrLOD_t *)((byte *) pinmodel + LittleLong(pinmodel->ofsLODs)); -		 -	// swap all the LOD's -	for ( l = 0 ; l < mdr->numLODs ; l++) -	{ -		lod->numSurfaces = LittleLong(curlod->numSurfaces); -		 -		// swap all the surfaces -		surf = (mdrSurface_t *) (lod + 1); -		lod->ofsSurfaces = (int)((byte *) surf - (byte *) lod); -		cursurf = (mdrSurface_t *) ((byte *)curlod + LittleLong(curlod->ofsSurfaces)); -		 -		for ( i = 0 ; i < lod->numSurfaces ; i++) { -			// first do some copying stuff -			 -			surf->ident = SF_MDR; -			Q_strncpyz(surf->name, cursurf->name, sizeof(surf->name)); -			Q_strncpyz(surf->shader, cursurf->shader, sizeof(surf->shader)); -			 -			surf->ofsHeader = (byte *) mdr - (byte *) surf; -			 -			surf->numVerts = LittleLong(cursurf->numVerts); -			surf->numTriangles = LittleLong(cursurf->numTriangles); -			// numBoneReferences and BoneReferences generally seem to be unused -			 -			// now do the checks that may fail. -			if ( surf->numVerts > SHADER_MAX_VERTEXES )  -			{ -				ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i verts on a surface (%i)", -					  mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); -				return qfalse; -			} -			if ( surf->numTriangles*3 > SHADER_MAX_INDEXES )  -			{ -				ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i triangles on a surface (%i)", -					  mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); -				return qfalse; -			} -			// lowercase the surface name so skin compares are faster -			Q_strlwr( surf->name ); - -			// register the shaders -			sh = R_FindShader(surf->shader, LIGHTMAP_NONE, qtrue); -			if ( sh->defaultShader ) { -				surf->shaderIndex = 0; -			} else { -				surf->shaderIndex = sh->index; -			} -			 -			// now copy the vertexes. -			v = (mdrVertex_t *) (surf + 1); -			surf->ofsVerts = (int)((byte *) v - (byte *) surf); -			curv = (mdrVertex_t *) ((byte *)cursurf + LittleLong(cursurf->ofsVerts)); -			 -			for(j = 0; j < surf->numVerts; j++) -			{ -				v->normal[0] = LittleFloat(curv->normal[0]); -				v->normal[1] = LittleFloat(curv->normal[1]); -				v->normal[2] = LittleFloat(curv->normal[2]); -				 -				v->texCoords[0] = LittleFloat(curv->texCoords[0]); -				v->texCoords[1] = LittleFloat(curv->texCoords[1]); -				 -				v->numWeights = LittleLong(curv->numWeights); -				weight = &v->weights[0]; -				curweight = &curv->weights[0]; -				 -				// Now copy all the weights -				for(k = 0; k < v->numWeights; k++) -				{ -					weight->boneIndex = LittleLong(curweight->boneIndex); -					weight->boneWeight = LittleFloat(curweight->boneWeight); -					 -					weight->offset[0] = LittleFloat(curweight->offset[0]); -					weight->offset[1] = LittleFloat(curweight->offset[1]); -					weight->offset[2] = LittleFloat(curweight->offset[2]); -					 -					weight++; -					curweight++; -				} -				 -				v = (mdrVertex_t *) weight; -				curv = (mdrVertex_t *) curweight; -			} -						 -			// we know the offset to the triangles now: -			tri = (mdrTriangle_t *) v; -			surf->ofsTriangles = (int)((byte *) tri - (byte *) surf); -			curtri = (mdrTriangle_t *)((byte *) cursurf + LittleLong(cursurf->ofsTriangles)); -			 -			for(j = 0; j < surf->numTriangles; j++) -			{ -				tri->indexes[0] = curtri->indexes[0]; -				tri->indexes[1] = curtri->indexes[1]; -				tri->indexes[2] = curtri->indexes[2]; -				 -				tri++; -				curtri++; -			} -			 -			// tri and curtri now point to the end of their surfaces. -			surf->ofsEnd = (byte *) tri - (byte *) surf; - -			// find the next surface -			surf = (mdrSurface_t *) tri; -			cursurf = (mdrSurface_t *) curtri; -		} - -		// surf points to the next lod now. -		lod->ofsEnd = (int)((byte *) surf - (byte *) lod); -				 -		lod = (mdrLOD_t *) surf; -		curlod = (mdrLOD_t *) cursurf; -	} -	 -	// lod points to the first tag now, so update the offset too. -	tag = (mdrTag_t *) lod; -	mdr->ofsTags = (int)((byte *) tag - (byte *) mdr); -	curtag = (mdrTag_t *) ((byte *)pinmodel + LittleLong(pinmodel->ofsTags)); -	 -	for (i = 0 ; i < mdr->numTags ; i++) -	{ -		tag->boneIndex = LittleLong(curtag->boneIndex); -		Q_strncpyz(tag->name, curtag->name, sizeof(tag->name)); -		 -		tag++; -		curtag++; -	} -	 -	// And finally we know the offset to the end. -	mdr->ofsEnd = (int)((byte *) tag - (byte *) mdr); - -	// phew! we're done. -	 -	return qtrue; -} -#endif - -/* -================= -R_LoadMD4 -================= -*/ - -static qboolean R_LoadMD4( model_t *mod, void *buffer, const char *mod_name ) { -	int					i, j, k, lodindex; -	md4Header_t			*pinmodel, *md4; -    md4Frame_t			*frame; -	md4LOD_t			*lod; -	md4Surface_t		*surf; -	md4Triangle_t		*tri; -	md4Vertex_t			*v; -	int					version; -	int					size; -	shader_t			*sh; -	int					frameSize; - -	pinmodel = (md4Header_t *)buffer; - -	version = LittleLong (pinmodel->version); -	if (version != MD4_VERSION) { -		ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has wrong version (%i should be %i)\n", -				 mod_name, version, MD4_VERSION); -		return qfalse; -	} - -	mod->type = MOD_MD4; -	size = LittleLong(pinmodel->ofsEnd); -	mod->dataSize += size; -	md4 = mod->md4 = ri.Hunk_Alloc( size, h_low ); - -	Com_Memcpy(md4, buffer, size); - -    LL(md4->ident); -    LL(md4->version); -    LL(md4->numFrames); -    LL(md4->numBones); -    LL(md4->numLODs); -    LL(md4->ofsFrames); -    LL(md4->ofsLODs); -    md4->ofsEnd = size; - -	if ( md4->numFrames < 1 ) { -		ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has no frames\n", mod_name ); -		return qfalse; -	} - -    // we don't need to swap tags in the renderer, they aren't used -     -	// swap all the frames -	frameSize = (size_t)( &((md4Frame_t *)0)->bones[ md4->numBones ] ); -    for ( i = 0 ; i < md4->numFrames ; i++, frame++) { -	    frame = (md4Frame_t *) ( (byte *)md4 + md4->ofsFrames + i * frameSize ); -    	frame->radius = LittleFloat( frame->radius ); -        for ( j = 0 ; j < 3 ; j++ ) { -            frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] ); -            frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] ); -	    	frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] ); -        } -		for ( j = 0 ; j < md4->numBones * sizeof( md4Bone_t ) / 4 ; j++ ) { -			((float *)frame->bones)[j] = LittleFloat( ((float *)frame->bones)[j] ); -		} -	} - -	// swap all the LOD's -	lod = (md4LOD_t *) ( (byte *)md4 + md4->ofsLODs ); -	for ( lodindex = 0 ; lodindex < md4->numLODs ; lodindex++ ) { - -		// swap all the surfaces -		surf = (md4Surface_t *) ( (byte *)lod + lod->ofsSurfaces ); -		for ( i = 0 ; i < lod->numSurfaces ; i++) { -			LL(surf->ident); -			LL(surf->numTriangles); -			LL(surf->ofsTriangles); -			LL(surf->numVerts); -			LL(surf->ofsVerts); -			LL(surf->ofsEnd); -			 -			if ( surf->numVerts > SHADER_MAX_VERTEXES ) { -				ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)", -					mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); -			} -			if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { -				ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)", -					mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); -			} - -			// change to surface identifier -			surf->ident = SF_MD4; - -			// lowercase the surface name so skin compares are faster -			Q_strlwr( surf->name ); -		 -			// register the shaders -			sh = R_FindShader( surf->shader, LIGHTMAP_NONE, qtrue ); -			if ( sh->defaultShader ) { -				surf->shaderIndex = 0; -			} else { -				surf->shaderIndex = sh->index; -			} - -			// swap all the triangles -			tri = (md4Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); -			for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { -				LL(tri->indexes[0]); -				LL(tri->indexes[1]); -				LL(tri->indexes[2]); -			} - -			// swap all the vertexes -			// FIXME -			// This makes TFC's skeletons work.  Shouldn't be necessary anymore, but left -			// in for reference. -			//v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts + 12); -			v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts); -			for ( j = 0 ; j < surf->numVerts ; j++ ) { -				v->normal[0] = LittleFloat( v->normal[0] ); -				v->normal[1] = LittleFloat( v->normal[1] ); -				v->normal[2] = LittleFloat( v->normal[2] ); - -				v->texCoords[0] = LittleFloat( v->texCoords[0] ); -				v->texCoords[1] = LittleFloat( v->texCoords[1] ); - -				v->numWeights = LittleLong( v->numWeights ); - -				for ( k = 0 ; k < v->numWeights ; k++ ) { -					v->weights[k].boneIndex = LittleLong( v->weights[k].boneIndex ); -					v->weights[k].boneWeight = LittleFloat( v->weights[k].boneWeight ); -				   v->weights[k].offset[0] = LittleFloat( v->weights[k].offset[0] ); -				   v->weights[k].offset[1] = LittleFloat( v->weights[k].offset[1] ); -				   v->weights[k].offset[2] = LittleFloat( v->weights[k].offset[2] ); -				} -				// FIXME -				// This makes TFC's skeletons work.  Shouldn't be necessary anymore, but left -				// in for reference. -				//v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 ); -				v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights]); -			} - -			// find the next surface -			surf = (md4Surface_t *)( (byte *)surf + surf->ofsEnd ); -		} - -		// find the next LOD -		lod = (md4LOD_t *)( (byte *)lod + lod->ofsEnd ); -	} - -	return qtrue; -} - - - -//============================================================================= - -/* -** RE_BeginRegistration -*/ -void RE_BeginRegistration( glconfig_t *glconfigOut ) { - -	R_Init(); - -	*glconfigOut = glConfig; - -	R_SyncRenderThread(); - -	tr.viewCluster = -1;		// force markleafs to regenerate -	R_ClearFlares(); -	RE_ClearScene(); - -	tr.registered = qtrue; - -	// NOTE: this sucks, for some reason the first stretch pic is never drawn -	// without this we'd see a white flash on a level load because the very -	// first time the level shot would not be drawn -	RE_StretchPic(0, 0, 0, 0, 0, 0, 1, 1, 0); -} - -//============================================================================= - -/* -=============== -R_ModelInit -=============== -*/ -void R_ModelInit( void ) { -	model_t		*mod; - -	// leave a space for NULL model -	tr.numModels = 0; - -	mod = R_AllocModel(); -	mod->type = MOD_BAD; -} - - -/* -================ -R_Modellist_f -================ -*/ -void R_Modellist_f( void ) { -	int		i, j; -	model_t	*mod; -	int		total; -	int		lods; - -	total = 0; -	for ( i = 1 ; i < tr.numModels; i++ ) { -		mod = tr.models[i]; -		lods = 1; -		for ( j = 1 ; j < MD3_MAX_LODS ; j++ ) { -			if ( mod->md3[j] && mod->md3[j] != mod->md3[j-1] ) { -				lods++; -			} -		} -		ri.Printf( PRINT_ALL, "%8i : (%i) %s\n",mod->dataSize, lods, mod->name ); -		total += mod->dataSize; -	} -	ri.Printf( PRINT_ALL, "%8i : Total models\n", total ); - -#if	0		// not working right with new hunk -	if ( tr.world ) { -		ri.Printf( PRINT_ALL, "\n%8i : %s\n", tr.world->dataSize, tr.world->name ); -	} -#endif -} - - -//============================================================================= - - -/* -================ -R_GetTag -================ -*/ -static md3Tag_t *R_GetTag( md3Header_t *mod, int frame, const char *tagName ) { -	md3Tag_t		*tag; -	int				i; - -	if ( frame >= mod->numFrames ) { -		// it is possible to have a bad frame while changing models, so don't error -		frame = mod->numFrames - 1; -	} - -	tag = (md3Tag_t *)((byte *)mod + mod->ofsTags) + frame * mod->numTags; -	for ( i = 0 ; i < mod->numTags ; i++, tag++ ) { -		if ( !strcmp( tag->name, tagName ) ) { -			return tag;	// found it -		} -	} - -	return NULL; -} - -#ifdef RAVENMD4 -void R_GetAnimTag( mdrHeader_t *mod, int framenum, const char *tagName, md3Tag_t * dest)  -{ -	int				i; -	int				frameSize; -	mdrFrame_t		*frame; -	mdrTag_t		*tag; - -	if ( framenum >= mod->numFrames )  -	{ -		// it is possible to have a bad frame while changing models, so don't error -		framenum = mod->numFrames - 1; -	} - -	tag = (mdrTag_t *)((byte *)mod + mod->ofsTags); -	for ( i = 0 ; i < mod->numTags ; i++, tag++ ) -	{ -		if ( !strcmp( tag->name, tagName ) ) -		{ -			Q_strncpyz(dest->name, tag->name, sizeof(dest->name)); - -			// uncompressed model... -			// -			frameSize = (long)( &((mdrFrame_t *)0)->bones[ mod->numBones ] ); -			frame = (mdrFrame_t *)((byte *)mod + mod->ofsFrames + framenum * frameSize ); -	#if 1 -			VectorCopy(&frame->bones[tag->boneIndex].matrix[0][0], dest->axis[0] ); -			VectorCopy(&frame->bones[tag->boneIndex].matrix[1][0], dest->axis[1] ); -			VectorCopy(&frame->bones[tag->boneIndex].matrix[2][0], dest->axis[2] ); -	#else -			{ -				int j,k; -				for (j=0;j<3;j++) -				{ -					for (k=0;k<3;k++) -						dest->axis[j][k]=frame->bones[tag->boneIndex].matrix[k][j]; -				} -			} -	#endif -			dest->origin[0]=frame->bones[tag->boneIndex].matrix[0][3]; -			dest->origin[1]=frame->bones[tag->boneIndex].matrix[1][3]; -			dest->origin[2]=frame->bones[tag->boneIndex].matrix[2][3];				 - -			return; -		} -	} - -	AxisClear( dest->axis ); -	VectorClear( dest->origin ); -	strcpy(dest->name,""); -} -#endif - -/* -================ -R_LerpTag -================ -*/ -int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame,  -					 float frac, const char *tagName ) { -	md3Tag_t	*start, *end; -#ifdef RAVENMD4 -	md3Tag_t	start_space, end_space; -#endif -	int		i; -	float		frontLerp, backLerp; -	model_t		*model; - -	model = R_GetModelByHandle( handle ); -	if ( !model->md3[0] ) -	{ -#ifdef RAVENMD4 -		if(model->md4) -		{ -			start = &start_space; -			end = &end_space; -			R_GetAnimTag((mdrHeader_t *) model->md4, startFrame, tagName, start); -			R_GetAnimTag((mdrHeader_t *) model->md4, endFrame, tagName, end); -		} -		else -#endif -		{ - -			AxisClear( tag->axis ); -			VectorClear( tag->origin ); -			return qfalse; - -		} -	} -	else -	{ -		start = R_GetTag( model->md3[0], startFrame, tagName ); -		end = R_GetTag( model->md3[0], endFrame, tagName ); -		if ( !start || !end ) { -			AxisClear( tag->axis ); -			VectorClear( tag->origin ); -			return qfalse; -		} -	} -	 -	frontLerp = frac; -	backLerp = 1.0f - frac; - -	for ( i = 0 ; i < 3 ; i++ ) { -		tag->origin[i] = start->origin[i] * backLerp +  end->origin[i] * frontLerp; -		tag->axis[0][i] = start->axis[0][i] * backLerp +  end->axis[0][i] * frontLerp; -		tag->axis[1][i] = start->axis[1][i] * backLerp +  end->axis[1][i] * frontLerp; -		tag->axis[2][i] = start->axis[2][i] * backLerp +  end->axis[2][i] * frontLerp; -	} -	VectorNormalize( tag->axis[0] ); -	VectorNormalize( tag->axis[1] ); -	VectorNormalize( tag->axis[2] ); -	return qtrue; -} - - -/* -==================== -R_ModelBounds -==================== -*/ -void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) { -	model_t		*model; -	md3Header_t	*header; -	md3Frame_t	*frame; - -	model = R_GetModelByHandle( handle ); - -	if ( model->bmodel ) { -		VectorCopy( model->bmodel->bounds[0], mins ); -		VectorCopy( model->bmodel->bounds[1], maxs ); -		return; -	} - -	if ( !model->md3[0] ) { -		VectorClear( mins ); -		VectorClear( maxs ); -		return; -	} - -	header = model->md3[0]; - -	frame = (md3Frame_t *)( (byte *)header + header->ofsFrames ); - -	VectorCopy( frame->bounds[0], mins ); -	VectorCopy( frame->bounds[1], maxs ); -} - diff --git a/ioq3-r437/src/renderer/tr_noise.c b/ioq3-r437/src/renderer/tr_noise.c deleted file mode 100644 index 5d550a3f..00000000 --- a/ioq3-r437/src/renderer/tr_noise.c +++ /dev/null @@ -1,95 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_noise.c -#include "tr_local.h" - -#define NOISE_SIZE 256 -#define NOISE_MASK ( NOISE_SIZE - 1 ) - -#define VAL( a ) s_noise_perm[ ( a ) & ( NOISE_MASK )] -#define INDEX( x, y, z, t ) VAL( x + VAL( y + VAL( z + VAL( t ) ) ) ) - -static float s_noise_table[NOISE_SIZE]; -static int s_noise_perm[NOISE_SIZE]; - -#define LERP( a, b, w ) ( a * ( 1.0f - w ) + b * w ) - -static float GetNoiseValue( int x, int y, int z, int t ) -{ -	int index = INDEX( ( int ) x, ( int ) y, ( int ) z, ( int ) t ); - -	return s_noise_table[index]; -} - -void R_NoiseInit( void ) -{ -	int i; - -	srand( 1001 ); - -	for ( i = 0; i < NOISE_SIZE; i++ ) -	{ -		s_noise_table[i] = ( float ) ( ( ( rand() / ( float ) RAND_MAX ) * 2.0 - 1.0 ) ); -		s_noise_perm[i] = ( unsigned char ) ( rand() / ( float ) RAND_MAX * 255 ); -	} -} - -float R_NoiseGet4f( float x, float y, float z, float t ) -{ -	int i; -	int ix, iy, iz, it; -	float fx, fy, fz, ft; -	float front[4]; -	float back[4]; -	float fvalue, bvalue, value[2], finalvalue; - -	ix = ( int ) floor( x ); -	fx = x - ix; -	iy = ( int ) floor( y ); -	fy = y - iy; -	iz = ( int ) floor( z ); -	fz = z - iz; -	it = ( int ) floor( t ); -	ft = t - it; - -	for ( i = 0; i < 2; i++ ) -	{ -		front[0] = GetNoiseValue( ix, iy, iz, it + i ); -		front[1] = GetNoiseValue( ix+1, iy, iz, it + i ); -		front[2] = GetNoiseValue( ix, iy+1, iz, it + i ); -		front[3] = GetNoiseValue( ix+1, iy+1, iz, it + i ); - -		back[0] = GetNoiseValue( ix, iy, iz + 1, it + i ); -		back[1] = GetNoiseValue( ix+1, iy, iz + 1, it + i ); -		back[2] = GetNoiseValue( ix, iy+1, iz + 1, it + i ); -		back[3] = GetNoiseValue( ix+1, iy+1, iz + 1, it + i ); - -		fvalue = LERP( LERP( front[0], front[1], fx ), LERP( front[2], front[3], fx ), fy ); -		bvalue = LERP( LERP( back[0], back[1], fx ), LERP( back[2], back[3], fx ), fy ); - -		value[i] = LERP( fvalue, bvalue, fz ); -	} - -	finalvalue = LERP( value[0], value[1], ft ); - -	return finalvalue; -} diff --git a/ioq3-r437/src/renderer/tr_public.h b/ioq3-r437/src/renderer/tr_public.h deleted file mode 100644 index 97523054..00000000 --- a/ioq3-r437/src/renderer/tr_public.h +++ /dev/null @@ -1,167 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -#ifndef __TR_PUBLIC_H -#define __TR_PUBLIC_H - -#include "tr_types.h" - -#define	REF_API_VERSION		8 - -// -// these are the functions exported by the refresh module -// -typedef struct { -	// called before the library is unloaded -	// if the system is just reconfiguring, pass destroyWindow = qfalse, -	// which will keep the screen from flashing to the desktop. -	void	(*Shutdown)( qboolean destroyWindow ); - -	// All data that will be used in a level should be -	// registered before rendering any frames to prevent disk hits, -	// but they can still be registered at a later time -	// if necessary. -	// -	// BeginRegistration makes any existing media pointers invalid -	// and returns the current gl configuration, including screen width -	// and height, which can be used by the client to intelligently -	// size display elements -	void	(*BeginRegistration)( glconfig_t *config ); -	qhandle_t (*RegisterModel)( const char *name ); -	qhandle_t (*RegisterSkin)( const char *name ); -	qhandle_t (*RegisterShader)( const char *name ); -	qhandle_t (*RegisterShaderNoMip)( const char *name ); -	void	(*LoadWorld)( const char *name ); - -	// the vis data is a large enough block of data that we go to the trouble -	// of sharing it with the clipmodel subsystem -	void	(*SetWorldVisData)( const byte *vis ); - -	// EndRegistration will draw a tiny polygon with each texture, forcing -	// them to be loaded into card memory -	void	(*EndRegistration)( void ); - -	// a scene is built up by calls to R_ClearScene and the various R_Add functions. -	// Nothing is drawn until R_RenderScene is called. -	void	(*ClearScene)( void ); -	void	(*AddRefEntityToScene)( const refEntity_t *re ); -	void	(*AddPolyToScene)( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num ); -	int		(*LightForPoint)( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ); -	void	(*AddLightToScene)( const vec3_t org, float intensity, float r, float g, float b ); -	void	(*AddAdditiveLightToScene)( const vec3_t org, float intensity, float r, float g, float b ); -	void	(*RenderScene)( const refdef_t *fd ); - -	void	(*SetColor)( const float *rgba );	// NULL = 1,1,1,1 -	void	(*DrawStretchPic) ( float x, float y, float w, float h,  -		float s1, float t1, float s2, float t2, qhandle_t hShader );	// 0 = white - -	// Draw images for cinematic rendering, pass as 32 bit rgba -	void	(*DrawStretchRaw) (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty); -	void	(*UploadCinematic) (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty); - -	void	(*BeginFrame)( stereoFrame_t stereoFrame ); - -	// if the pointers are not NULL, timing info will be returned -	void	(*EndFrame)( int *frontEndMsec, int *backEndMsec ); - - -	int		(*MarkFragments)( int numPoints, const vec3_t *points, const vec3_t projection, -				   int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ); - -	int		(*LerpTag)( orientation_t *tag,  qhandle_t model, int startFrame, int endFrame,  -					 float frac, const char *tagName ); -	void	(*ModelBounds)( qhandle_t model, vec3_t mins, vec3_t maxs ); - -#ifdef __USEA3D -	void    (*A3D_RenderGeometry) (void *pVoidA3D, void *pVoidGeom, void *pVoidMat, void *pVoidGeomStatus); -#endif -	void	(*RegisterFont)(const char *fontName, int pointSize, fontInfo_t *font); -	void	(*RemapShader)(const char *oldShader, const char *newShader, const char *offsetTime); -	qboolean (*GetEntityToken)( char *buffer, int size ); -	qboolean (*inPVS)( const vec3_t p1, const vec3_t p2 ); -} refexport_t; - -// -// these are the functions imported by the refresh module -// -typedef struct { -	// print message on the local console -	void	(QDECL *Printf)( int printLevel, const char *fmt, ...); - -	// abort the game -	void	(QDECL *Error)( int errorLevel, const char *fmt, ...); - -	// milliseconds should only be used for profiling, never -	// for anything game related.  Get time from the refdef -	int		(*Milliseconds)( void ); - -	// stack based memory allocation for per-level things that -	// won't be freed -#ifdef HUNK_DEBUG -	void	*(*Hunk_AllocDebug)( int size, ha_pref pref, char *label, char *file, int line ); -#else -	void	*(*Hunk_Alloc)( int size, ha_pref pref ); -#endif -	void	*(*Hunk_AllocateTempMemory)( int size ); -	void	(*Hunk_FreeTempMemory)( void *block ); - -	// dynamic memory allocator for things that need to be freed -	void	*(*Malloc)( int bytes ); -	void	(*Free)( void *buf ); - -	cvar_t	*(*Cvar_Get)( const char *name, const char *value, int flags ); -	void	(*Cvar_Set)( const char *name, const char *value ); - -	void	(*Cmd_AddCommand)( const char *name, void(*cmd)(void) ); -	void	(*Cmd_RemoveCommand)( const char *name ); - -	int		(*Cmd_Argc) (void); -	char	*(*Cmd_Argv) (int i); - -	void	(*Cmd_ExecuteText) (int exec_when, const char *text); - -	// visualization for debugging collision detection -	void	(*CM_DrawDebugSurface)( void (*drawPoly)(int color, int numPoints, float *points) ); - -	// a -1 return means the file does not exist -	// NULL can be passed for buf to just determine existance -	int		(*FS_FileIsInPAK)( const char *name, int *pCheckSum ); -	int		(*FS_ReadFile)( const char *name, void **buf ); -	void	(*FS_FreeFile)( void *buf ); -	char **	(*FS_ListFiles)( const char *name, const char *extension, int *numfilesfound ); -	void	(*FS_FreeFileList)( char **filelist ); -	void	(*FS_WriteFile)( const char *qpath, const void *buffer, int size ); -	qboolean (*FS_FileExists)( const char *file ); - -	// cinematic stuff -	void	(*CIN_UploadCinematic)(int handle); -	int		(*CIN_PlayCinematic)( const char *arg0, int xpos, int ypos, int width, int height, int bits); -	e_status (*CIN_RunCinematic) (int handle); - -} refimport_t; - - -// this is the only function actually exported at the linker level -// If the module can't init to a valid rendering state, NULL will be -// returned. -refexport_t*GetRefAPI( int apiVersion, refimport_t *rimp ); - -#endif	// __TR_PUBLIC_H diff --git a/ioq3-r437/src/renderer/tr_scene.c b/ioq3-r437/src/renderer/tr_scene.c deleted file mode 100644 index 515a629b..00000000 --- a/ioq3-r437/src/renderer/tr_scene.c +++ /dev/null @@ -1,409 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ - -#include "tr_local.h" - -int			r_firstSceneDrawSurf; - -int			r_numdlights; -int			r_firstSceneDlight; - -int			r_numentities; -int			r_firstSceneEntity; - -int			r_numpolys; -int			r_firstScenePoly; - -int			r_numpolyverts; - - -/* -==================== -R_ToggleSmpFrame - -==================== -*/ -void R_ToggleSmpFrame( void ) { -	if ( r_smp->integer ) { -		// use the other buffers next frame, because another CPU -		// may still be rendering into the current ones -		tr.smpFrame ^= 1; -	} else { -		tr.smpFrame = 0; -	} - -	backEndData[tr.smpFrame]->commands.used = 0; - -	r_firstSceneDrawSurf = 0; - -	r_numdlights = 0; -	r_firstSceneDlight = 0; - -	r_numentities = 0; -	r_firstSceneEntity = 0; - -	r_numpolys = 0; -	r_firstScenePoly = 0; - -	r_numpolyverts = 0; -} - - -/* -==================== -RE_ClearScene - -==================== -*/ -void RE_ClearScene( void ) { -	r_firstSceneDlight = r_numdlights; -	r_firstSceneEntity = r_numentities; -	r_firstScenePoly = r_numpolys; -} - -/* -=========================================================================== - -DISCRETE POLYS - -=========================================================================== -*/ - -/* -===================== -R_AddPolygonSurfaces - -Adds all the scene's polys into this view's drawsurf list -===================== -*/ -void R_AddPolygonSurfaces( void ) { -	int			i; -	shader_t	*sh; -	srfPoly_t	*poly; - -	tr.currentEntityNum = ENTITYNUM_WORLD; -	tr.shiftedEntityNum = tr.currentEntityNum << QSORT_ENTITYNUM_SHIFT; - -	for ( i = 0, poly = tr.refdef.polys; i < tr.refdef.numPolys ; i++, poly++ ) { -		sh = R_GetShaderByHandle( poly->hShader ); -		R_AddDrawSurf( ( void * )poly, sh, poly->fogIndex, qfalse ); -	} -} - -/* -===================== -RE_AddPolyToScene - -===================== -*/ -void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) { -	srfPoly_t	*poly; -	int			i, j; -	int			fogIndex; -	fog_t		*fog; -	vec3_t		bounds[2]; - -	if ( !tr.registered ) { -		return; -	} - -	if ( !hShader ) { -		ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolyToScene: NULL poly shader\n"); -		return; -	} - -	for ( j = 0; j < numPolys; j++ ) { -		if ( r_numpolyverts + numVerts > max_polyverts || r_numpolys >= max_polys ) { -      /* -      NOTE TTimo this was initially a PRINT_WARNING -      but it happens a lot with high fighting scenes and particles -      since we don't plan on changing the const and making for room for those effects -      simply cut this message to developer only -      */ -			ri.Printf( PRINT_DEVELOPER, "WARNING: RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n"); -			return; -		} - -		poly = &backEndData[tr.smpFrame]->polys[r_numpolys]; -		poly->surfaceType = SF_POLY; -		poly->hShader = hShader; -		poly->numVerts = numVerts; -		poly->verts = &backEndData[tr.smpFrame]->polyVerts[r_numpolyverts]; -		 -		Com_Memcpy( poly->verts, &verts[numVerts*j], numVerts * sizeof( *verts ) ); - -		if ( glConfig.hardwareType == GLHW_RAGEPRO ) { -			poly->verts->modulate[0] = 255; -			poly->verts->modulate[1] = 255; -			poly->verts->modulate[2] = 255; -			poly->verts->modulate[3] = 255; -		} -		// done. -		r_numpolys++; -		r_numpolyverts += numVerts; - -		// if no world is loaded -		if ( tr.world == NULL ) { -			fogIndex = 0; -		} -		// see if it is in a fog volume -		else if ( tr.world->numfogs == 1 ) { -			fogIndex = 0; -		} else { -			// find which fog volume the poly is in -			VectorCopy( poly->verts[0].xyz, bounds[0] ); -			VectorCopy( poly->verts[0].xyz, bounds[1] ); -			for ( i = 1 ; i < poly->numVerts ; i++ ) { -				AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] ); -			} -			for ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) { -				fog = &tr.world->fogs[fogIndex];  -				if ( bounds[1][0] >= fog->bounds[0][0] -					&& bounds[1][1] >= fog->bounds[0][1] -					&& bounds[1][2] >= fog->bounds[0][2] -					&& bounds[0][0] <= fog->bounds[1][0] -					&& bounds[0][1] <= fog->bounds[1][1] -					&& bounds[0][2] <= fog->bounds[1][2] ) { -					break; -				} -			} -			if ( fogIndex == tr.world->numfogs ) { -				fogIndex = 0; -			} -		} -		poly->fogIndex = fogIndex; -	} -} - - -//================================================================================= - - -/* -===================== -RE_AddRefEntityToScene - -===================== -*/ -void RE_AddRefEntityToScene( const refEntity_t *ent ) { -	if ( !tr.registered ) { -		return; -	} -  // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=402 -	if ( r_numentities >= ENTITYNUM_WORLD ) { -		return; -	} -	if ( ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) { -		ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType ); -	} - -	backEndData[tr.smpFrame]->entities[r_numentities].e = *ent; -	backEndData[tr.smpFrame]->entities[r_numentities].lightingCalculated = qfalse; - -	r_numentities++; -} - - -/* -===================== -RE_AddDynamicLightToScene - -===================== -*/ -void RE_AddDynamicLightToScene( const vec3_t org, float intensity, float r, float g, float b, int additive ) { -	dlight_t	*dl; - -	if ( !tr.registered ) { -		return; -	} -	if ( r_numdlights >= MAX_DLIGHTS ) { -		return; -	} -	if ( intensity <= 0 ) { -		return; -	} -	// these cards don't have the correct blend mode -	if ( glConfig.hardwareType == GLHW_RIVA128 || glConfig.hardwareType == GLHW_PERMEDIA2 ) { -		return; -	} -	dl = &backEndData[tr.smpFrame]->dlights[r_numdlights++]; -	VectorCopy (org, dl->origin); -	dl->radius = intensity; -	dl->color[0] = r; -	dl->color[1] = g; -	dl->color[2] = b; -	dl->additive = additive; -} - -/* -===================== -RE_AddLightToScene - -===================== -*/ -void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) { -	RE_AddDynamicLightToScene( org, intensity, r, g, b, qfalse ); -} - -/* -===================== -RE_AddAdditiveLightToScene - -===================== -*/ -void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ) { -	RE_AddDynamicLightToScene( org, intensity, r, g, b, qtrue ); -} - -/* -@@@@@@@@@@@@@@@@@@@@@ -RE_RenderScene - -Draw a 3D view into a part of the window, then return -to 2D drawing. - -Rendering a scene may require multiple views to be rendered -to handle mirrors, -@@@@@@@@@@@@@@@@@@@@@ -*/ -void RE_RenderScene( const refdef_t *fd ) { -	viewParms_t		parms; -	int				startTime; - -	if ( !tr.registered ) { -		return; -	} -	GLimp_LogComment( "====== RE_RenderScene =====\n" ); - -	if ( r_norefresh->integer ) { -		return; -	} - -	startTime = ri.Milliseconds(); - -	if (!tr.world && !( fd->rdflags & RDF_NOWORLDMODEL ) ) { -		ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel"); -	} - -	Com_Memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) ); - -	tr.refdef.x = fd->x; -	tr.refdef.y = fd->y; -	tr.refdef.width = fd->width; -	tr.refdef.height = fd->height; -	tr.refdef.fov_x = fd->fov_x; -	tr.refdef.fov_y = fd->fov_y; - -	VectorCopy( fd->vieworg, tr.refdef.vieworg ); -	VectorCopy( fd->viewaxis[0], tr.refdef.viewaxis[0] ); -	VectorCopy( fd->viewaxis[1], tr.refdef.viewaxis[1] ); -	VectorCopy( fd->viewaxis[2], tr.refdef.viewaxis[2] ); - -	tr.refdef.time = fd->time; -	tr.refdef.rdflags = fd->rdflags; - -	// copy the areamask data over and note if it has changed, which -	// will force a reset of the visible leafs even if the view hasn't moved -	tr.refdef.areamaskModified = qfalse; -	if ( ! (tr.refdef.rdflags & RDF_NOWORLDMODEL) ) { -		int		areaDiff; -		int		i; - -		// compare the area bits -		areaDiff = 0; -		for (i = 0 ; i < MAX_MAP_AREA_BYTES/4 ; i++) { -			areaDiff |= ((int *)tr.refdef.areamask)[i] ^ ((int *)fd->areamask)[i]; -			((int *)tr.refdef.areamask)[i] = ((int *)fd->areamask)[i]; -		} - -		if ( areaDiff ) { -			// a door just opened or something -			tr.refdef.areamaskModified = qtrue; -		} -	} - - -	// derived info - -	tr.refdef.floatTime = tr.refdef.time * 0.001f; - -	tr.refdef.numDrawSurfs = r_firstSceneDrawSurf; -	tr.refdef.drawSurfs = backEndData[tr.smpFrame]->drawSurfs; - -	tr.refdef.num_entities = r_numentities - r_firstSceneEntity; -	tr.refdef.entities = &backEndData[tr.smpFrame]->entities[r_firstSceneEntity]; - -	tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight; -	tr.refdef.dlights = &backEndData[tr.smpFrame]->dlights[r_firstSceneDlight]; - -	tr.refdef.numPolys = r_numpolys - r_firstScenePoly; -	tr.refdef.polys = &backEndData[tr.smpFrame]->polys[r_firstScenePoly]; - -	// turn off dynamic lighting globally by clearing all the -	// dlights if it needs to be disabled or if vertex lighting is enabled -	if ( r_dynamiclight->integer == 0 || -		 r_vertexLight->integer == 1 || -		 glConfig.hardwareType == GLHW_PERMEDIA2 ) { -		tr.refdef.num_dlights = 0; -	} - -	// a single frame may have multiple scenes draw inside it -- -	// a 3D game view, 3D status bar renderings, 3D menus, etc. -	// They need to be distinguished by the light flare code, because -	// the visibility state for a given surface may be different in -	// each scene / view. -	tr.frameSceneNum++; -	tr.sceneCount++; - -	// setup view parms for the initial view -	// -	// set up viewport -	// The refdef takes 0-at-the-top y coordinates, so -	// convert to GL's 0-at-the-bottom space -	// -	Com_Memset( &parms, 0, sizeof( parms ) ); -	parms.viewportX = tr.refdef.x; -	parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height ); -	parms.viewportWidth = tr.refdef.width; -	parms.viewportHeight = tr.refdef.height; -	parms.isPortal = qfalse; - -	parms.fovX = tr.refdef.fov_x; -	parms.fovY = tr.refdef.fov_y; - -	VectorCopy( fd->vieworg, parms.or.origin ); -	VectorCopy( fd->viewaxis[0], parms.or.axis[0] ); -	VectorCopy( fd->viewaxis[1], parms.or.axis[1] ); -	VectorCopy( fd->viewaxis[2], parms.or.axis[2] ); - -	VectorCopy( fd->vieworg, parms.pvsOrigin ); - -	R_RenderView( &parms ); - -	// the next scene rendered in this frame will tack on after this one -	r_firstSceneDrawSurf = tr.refdef.numDrawSurfs; -	r_firstSceneEntity = r_numentities; -	r_firstSceneDlight = r_numdlights; -	r_firstScenePoly = r_numpolys; - -	tr.frontEndMsec += ri.Milliseconds() - startTime; -} diff --git a/ioq3-r437/src/renderer/tr_shade.c b/ioq3-r437/src/renderer/tr_shade.c deleted file mode 100644 index 6f22b7c2..00000000 --- a/ioq3-r437/src/renderer/tr_shade.c +++ /dev/null @@ -1,1462 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_shade.c - -#include "tr_local.h"  -#if idppc_altivec && !defined(MACOS_X) -#include <altivec.h> -#endif - -/* - -  THIS ENTIRE FILE IS BACK END - -  This file deals with applying shaders to surface data in the tess struct. -*/ - -/* -================ -R_ArrayElementDiscrete - -This is just for OpenGL conformance testing, it should never be the fastest -================ -*/ -static void APIENTRY R_ArrayElementDiscrete( GLint index ) { -	qglColor4ubv( tess.svars.colors[ index ] ); -	if ( glState.currenttmu ) { -		qglMultiTexCoord2fARB( 0, tess.svars.texcoords[ 0 ][ index ][0], tess.svars.texcoords[ 0 ][ index ][1] ); -		qglMultiTexCoord2fARB( 1, tess.svars.texcoords[ 1 ][ index ][0], tess.svars.texcoords[ 1 ][ index ][1] ); -	} else { -		qglTexCoord2fv( tess.svars.texcoords[ 0 ][ index ] ); -	} -	qglVertex3fv( tess.xyz[ index ] ); -} - -/* -=================== -R_DrawStripElements - -=================== -*/ -static int		c_vertexes;		// for seeing how long our average strips are -static int		c_begins; -static void R_DrawStripElements( int numIndexes, const glIndex_t *indexes, void ( APIENTRY *element )(GLint) ) { -	int i; -	int last[3] = { -1, -1, -1 }; -	qboolean even; - -	c_begins++; - -	if ( numIndexes <= 0 ) { -		return; -	} - -	qglBegin( GL_TRIANGLE_STRIP ); - -	// prime the strip -	element( indexes[0] ); -	element( indexes[1] ); -	element( indexes[2] ); -	c_vertexes += 3; - -	last[0] = indexes[0]; -	last[1] = indexes[1]; -	last[2] = indexes[2]; - -	even = qfalse; - -	for ( i = 3; i < numIndexes; i += 3 ) -	{ -		// odd numbered triangle in potential strip -		if ( !even ) -		{ -			// check previous triangle to see if we're continuing a strip -			if ( ( indexes[i+0] == last[2] ) && ( indexes[i+1] == last[1] ) ) -			{ -				element( indexes[i+2] ); -				c_vertexes++; -				assert( indexes[i+2] < tess.numVertexes ); -				even = qtrue; -			} -			// otherwise we're done with this strip so finish it and start -			// a new one -			else -			{ -				qglEnd(); - -				qglBegin( GL_TRIANGLE_STRIP ); -				c_begins++; - -				element( indexes[i+0] ); -				element( indexes[i+1] ); -				element( indexes[i+2] ); - -				c_vertexes += 3; - -				even = qfalse; -			} -		} -		else -		{ -			// check previous triangle to see if we're continuing a strip -			if ( ( last[2] == indexes[i+1] ) && ( last[0] == indexes[i+0] ) ) -			{ -				element( indexes[i+2] ); -				c_vertexes++; - -				even = qfalse; -			} -			// otherwise we're done with this strip so finish it and start -			// a new one -			else -			{ -				qglEnd(); - -				qglBegin( GL_TRIANGLE_STRIP ); -				c_begins++; - -				element( indexes[i+0] ); -				element( indexes[i+1] ); -				element( indexes[i+2] ); -				c_vertexes += 3; - -				even = qfalse; -			} -		} - -		// cache the last three vertices -		last[0] = indexes[i+0]; -		last[1] = indexes[i+1]; -		last[2] = indexes[i+2]; -	} - -	qglEnd(); -} - - - -/* -================== -R_DrawElements - -Optionally performs our own glDrawElements that looks for strip conditions -instead of using the single glDrawElements call that may be inefficient -without compiled vertex arrays. -================== -*/ -static void R_DrawElements( int numIndexes, const glIndex_t *indexes ) { -	int		primitives; - -	primitives = r_primitives->integer; - -	// default is to use triangles if compiled vertex arrays are present -	if ( primitives == 0 ) { -		if ( qglLockArraysEXT ) { -			primitives = 2; -		} else { -			primitives = 1; -		} -	} - - -	if ( primitives == 2 ) { -		qglDrawElements( GL_TRIANGLES,  -						numIndexes, -						GL_INDEX_TYPE, -						indexes ); -		return; -	} - -	if ( primitives == 1 ) { -		R_DrawStripElements( numIndexes,  indexes, qglArrayElement ); -		return; -	} -	 -	if ( primitives == 3 ) { -		R_DrawStripElements( numIndexes,  indexes, R_ArrayElementDiscrete ); -		return; -	} - -	// anything else will cause no drawing -} - - -/* -============================================================= - -SURFACE SHADERS - -============================================================= -*/ - -shaderCommands_t	tess; -static qboolean	setArraysOnce; - -/* -================= -R_BindAnimatedImage - -================= -*/ -static void R_BindAnimatedImage( textureBundle_t *bundle ) { -	int		index; - -	if ( bundle->isVideoMap ) { -		ri.CIN_RunCinematic(bundle->videoMapHandle); -		ri.CIN_UploadCinematic(bundle->videoMapHandle); -		return; -	} - -	if ( bundle->numImageAnimations <= 1 ) { -		GL_Bind( bundle->image[0] ); -		return; -	} - -	// it is necessary to do this messy calc to make sure animations line up -	// exactly with waveforms of the same frequency -	index = myftol( tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE ); -	index >>= FUNCTABLE_SIZE2; - -	if ( index < 0 ) { -		index = 0;	// may happen with shader time offsets -	} -	index %= bundle->numImageAnimations; - -	GL_Bind( bundle->image[ index ] ); -} - -/* -================ -DrawTris - -Draws triangle outlines for debugging -================ -*/ -static void DrawTris (shaderCommands_t *input) { -	GL_Bind( tr.whiteImage ); -	qglColor3f (1,1,1); - -	GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); -	qglDepthRange( 0, 0 ); - -	qglDisableClientState (GL_COLOR_ARRAY); -	qglDisableClientState (GL_TEXTURE_COORD_ARRAY); - -	qglVertexPointer (3, GL_FLOAT, 16, input->xyz);	// padded for SIMD - -	if (qglLockArraysEXT) { -		qglLockArraysEXT(0, input->numVertexes); -		GLimp_LogComment( "glLockArraysEXT\n" ); -	} - -	R_DrawElements( input->numIndexes, input->indexes ); - -	if (qglUnlockArraysEXT) { -		qglUnlockArraysEXT(); -		GLimp_LogComment( "glUnlockArraysEXT\n" ); -	} -	qglDepthRange( 0, 1 ); -} - - -/* -================ -DrawNormals - -Draws vertex normals for debugging -================ -*/ -static void DrawNormals (shaderCommands_t *input) { -	int		i; -	vec3_t	temp; - -	GL_Bind( tr.whiteImage ); -	qglColor3f (1,1,1); -	qglDepthRange( 0, 0 );	// never occluded -	GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); - -	qglBegin (GL_LINES); -	for (i = 0 ; i < input->numVertexes ; i++) { -		qglVertex3fv (input->xyz[i]); -		VectorMA (input->xyz[i], 2, input->normal[i], temp); -		qglVertex3fv (temp); -	} -	qglEnd (); - -	qglDepthRange( 0, 1 ); -} - -/* -============== -RB_BeginSurface - -We must set some things up before beginning any tesselation, -because a surface may be forced to perform a RB_End due -to overflow. -============== -*/ -void RB_BeginSurface( shader_t *shader, int fogNum ) { - -	shader_t *state = (shader->remappedShader) ? shader->remappedShader : shader; - -	tess.numIndexes = 0; -	tess.numVertexes = 0; -	tess.shader = state; -	tess.fogNum = fogNum; -	tess.dlightBits = 0;		// will be OR'd in by surface functions -	tess.xstages = state->stages; -	tess.numPasses = state->numUnfoggedPasses; -	tess.currentStageIteratorFunc = state->optimalStageIteratorFunc; - -	tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; -	if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) { -		tess.shaderTime = tess.shader->clampTime; -	} - - -} - -/* -=================== -DrawMultitextured - -output = t0 * t1 or t0 + t1 - -t0 = most upstream according to spec -t1 = most downstream according to spec -=================== -*/ -static void DrawMultitextured( shaderCommands_t *input, int stage ) { -	shaderStage_t	*pStage; - -	pStage = tess.xstages[stage]; - -	GL_State( pStage->stateBits ); - -	// this is an ugly hack to work around a GeForce driver -	// bug with multitexture and clip planes -	if ( backEnd.viewParms.isPortal ) { -		qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); -	} - -	// -	// base -	// -	GL_SelectTexture( 0 ); -	qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] ); -	R_BindAnimatedImage( &pStage->bundle[0] ); - -	// -	// lightmap/secondary pass -	// -	GL_SelectTexture( 1 ); -	qglEnable( GL_TEXTURE_2D ); -	qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - -	if ( r_lightmap->integer ) { -		GL_TexEnv( GL_REPLACE ); -	} else { -		GL_TexEnv( tess.shader->multitextureEnv ); -	} - -	qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[1] ); - -	R_BindAnimatedImage( &pStage->bundle[1] ); - -	R_DrawElements( input->numIndexes, input->indexes ); - -	// -	// disable texturing on TEXTURE1, then select TEXTURE0 -	// -	//qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); -	qglDisable( GL_TEXTURE_2D ); - -	GL_SelectTexture( 0 ); -} - - - -/* -=================== -ProjectDlightTexture - -Perform dynamic lighting with another rendering pass -=================== -*/ -#if idppc_altivec -static void ProjectDlightTexture_altivec( void ) { -	int		i, l; -	vec_t	origin0, origin1, origin2; -	float   texCoords0, texCoords1; -	vector float floatColorVec0, floatColorVec1; -	vector float modulateVec, colorVec, zero; -	vector short colorShort; -	vector signed int colorInt; -	vector unsigned char floatColorVecPerm, modulatePerm, colorChar; -	vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff, -                                               0x00, 0x00, 0x00, 0xff, -                                               0x00, 0x00, 0x00, 0xff, -                                               0x00, 0x00, 0x00, 0xff); -	float	*texCoords; -	byte	*colors; -	byte	clipBits[SHADER_MAX_VERTEXES]; -	float	texCoordsArray[SHADER_MAX_VERTEXES][2]; -	byte	colorArray[SHADER_MAX_VERTEXES][4]; -	unsigned	hitIndexes[SHADER_MAX_INDEXES]; -	int		numIndexes; -	float	scale; -	float	radius; -	vec3_t	floatColor; -	float	modulate = 0.0f; - -	if ( !backEnd.refdef.num_dlights ) { -		return; -	} - -	// There has to be a better way to do this so that floatColor -	// and/or modulate are already 16-byte aligned. -	floatColorVecPerm = vec_lvsl(0,(float *)floatColor); -	modulatePerm = vec_lvsl(0,(float *)&modulate); -	modulatePerm = (vector unsigned char)vec_splat((vector unsigned int)modulatePerm,0); -	zero = (vector float)vec_splat_s8(0); - -	for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { -		dlight_t	*dl; - -		if ( !( tess.dlightBits & ( 1 << l ) ) ) { -			continue;	// this surface definately doesn't have any of this light -		} -		texCoords = texCoordsArray[0]; -		colors = colorArray[0]; - -		dl = &backEnd.refdef.dlights[l]; -		origin0 = dl->transformed[0]; -		origin1 = dl->transformed[1]; -		origin2 = dl->transformed[2]; -		radius = dl->radius; -		scale = 1.0f / radius; - -		floatColor[0] = dl->color[0] * 255.0f; -		floatColor[1] = dl->color[1] * 255.0f; -		floatColor[2] = dl->color[2] * 255.0f; -		floatColorVec0 = vec_ld(0, floatColor); -		floatColorVec1 = vec_ld(11, floatColor); -		floatColorVec0 = vec_perm(floatColorVec0,floatColorVec0,floatColorVecPerm); -		for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) { -			int		clip = 0; -			vec_t dist0, dist1, dist2; -			 -			dist0 = origin0 - tess.xyz[i][0]; -			dist1 = origin1 - tess.xyz[i][1]; -			dist2 = origin2 - tess.xyz[i][2]; - -			backEnd.pc.c_dlightVertexes++; - -			texCoords0 = 0.5f + dist0 * scale; -			texCoords1 = 0.5f + dist1 * scale; - -			if( !r_dlightBacks->integer && -					// dist . tess.normal[i] -					( dist0 * tess.normal[i][0] + -					dist1 * tess.normal[i][1] + -					dist2 * tess.normal[i][2] ) < 0.0f ) { -				clip = 63; -			} else { -				if ( texCoords0 < 0.0f ) { -					clip |= 1; -				} else if ( texCoords0 > 1.0f ) { -					clip |= 2; -				} -				if ( texCoords1 < 0.0f ) { -					clip |= 4; -				} else if ( texCoords1 > 1.0f ) { -					clip |= 8; -				} -				texCoords[0] = texCoords0; -				texCoords[1] = texCoords1; - -				// modulate the strength based on the height and color -				if ( dist2 > radius ) { -					clip |= 16; -					modulate = 0.0f; -				} else if ( dist2 < -radius ) { -					clip |= 32; -					modulate = 0.0f; -				} else { -					dist2 = Q_fabs(dist2); -					if ( dist2 < radius * 0.5f ) { -						modulate = 1.0f; -					} else { -						modulate = 2.0f * (radius - dist2) * scale; -					} -				} -			} -			clipBits[i] = clip; - -			modulateVec = vec_ld(0,(float *)&modulate); -			modulateVec = vec_perm(modulateVec,modulateVec,modulatePerm); -			colorVec = vec_madd(floatColorVec0,modulateVec,zero); -			colorInt = vec_cts(colorVec,0);	// RGBx -			colorShort = vec_pack(colorInt,colorInt);		// RGBxRGBx -			colorChar = vec_packsu(colorShort,colorShort);	// RGBxRGBxRGBxRGBx -			colorChar = vec_sel(colorChar,vSel,vSel);		// RGBARGBARGBARGBA replace alpha with 255 -			vec_ste((vector unsigned int)colorChar,0,(unsigned int *)colors);	// store color -		} - -		// build a list of triangles that need light -		numIndexes = 0; -		for ( i = 0 ; i < tess.numIndexes ; i += 3 ) { -			int		a, b, c; - -			a = tess.indexes[i]; -			b = tess.indexes[i+1]; -			c = tess.indexes[i+2]; -			if ( clipBits[a] & clipBits[b] & clipBits[c] ) { -				continue;	// not lighted -			} -			hitIndexes[numIndexes] = a; -			hitIndexes[numIndexes+1] = b; -			hitIndexes[numIndexes+2] = c; -			numIndexes += 3; -		} - -		if ( !numIndexes ) { -			continue; -		} - -		qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); -		qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] ); - -		qglEnableClientState( GL_COLOR_ARRAY ); -		qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); - -		GL_Bind( tr.dlightImage ); -		// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light -		// where they aren't rendered -		if ( dl->additive ) { -			GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); -		} -		else { -			GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); -		} -		R_DrawElements( numIndexes, hitIndexes ); -		backEnd.pc.c_totalIndexes += numIndexes; -		backEnd.pc.c_dlightIndexes += numIndexes; -	} -} -#endif - - -static void ProjectDlightTexture_scalar( void ) { -	int		i, l; -	vec3_t	origin; -	float	*texCoords; -	byte	*colors; -	byte	clipBits[SHADER_MAX_VERTEXES]; -	float	texCoordsArray[SHADER_MAX_VERTEXES][2]; -	byte	colorArray[SHADER_MAX_VERTEXES][4]; -	unsigned	hitIndexes[SHADER_MAX_INDEXES]; -	int		numIndexes; -	float	scale; -	float	radius; -	vec3_t	floatColor; -	float	modulate = 0.0f; - -	if ( !backEnd.refdef.num_dlights ) { -		return; -	} - -	for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { -		dlight_t	*dl; - -		if ( !( tess.dlightBits & ( 1 << l ) ) ) { -			continue;	// this surface definately doesn't have any of this light -		} -		texCoords = texCoordsArray[0]; -		colors = colorArray[0]; - -		dl = &backEnd.refdef.dlights[l]; -		VectorCopy( dl->transformed, origin ); -		radius = dl->radius; -		scale = 1.0f / radius; - -		floatColor[0] = dl->color[0] * 255.0f; -		floatColor[1] = dl->color[1] * 255.0f; -		floatColor[2] = dl->color[2] * 255.0f; -		for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) { -			int		clip = 0; -			vec3_t	dist; -			 -			VectorSubtract( origin, tess.xyz[i], dist ); - -			backEnd.pc.c_dlightVertexes++; - -			texCoords[0] = 0.5f + dist[0] * scale; -			texCoords[1] = 0.5f + dist[1] * scale; - -			if( !r_dlightBacks->integer && -					// dist . tess.normal[i] -					( dist[0] * tess.normal[i][0] + -					dist[1] * tess.normal[i][1] + -					dist[2] * tess.normal[i][2] ) < 0.0f ) { -				clip = 63; -			} else { -				if ( texCoords[0] < 0.0f ) { -					clip |= 1; -				} else if ( texCoords[0] > 1.0f ) { -					clip |= 2; -				} -				if ( texCoords[1] < 0.0f ) { -					clip |= 4; -				} else if ( texCoords[1] > 1.0f ) { -					clip |= 8; -				} -				texCoords[0] = texCoords[0]; -				texCoords[1] = texCoords[1]; - -				// modulate the strength based on the height and color -				if ( dist[2] > radius ) { -					clip |= 16; -					modulate = 0.0f; -				} else if ( dist[2] < -radius ) { -					clip |= 32; -					modulate = 0.0f; -				} else { -					dist[2] = Q_fabs(dist[2]); -					if ( dist[2] < radius * 0.5f ) { -						modulate = 1.0f; -					} else { -						modulate = 2.0f * (radius - dist[2]) * scale; -					} -				} -			} -			clipBits[i] = clip; -			colors[0] = myftol(floatColor[0] * modulate); -			colors[1] = myftol(floatColor[1] * modulate); -			colors[2] = myftol(floatColor[2] * modulate); -			colors[3] = 255; -		} - -		// build a list of triangles that need light -		numIndexes = 0; -		for ( i = 0 ; i < tess.numIndexes ; i += 3 ) { -			int		a, b, c; - -			a = tess.indexes[i]; -			b = tess.indexes[i+1]; -			c = tess.indexes[i+2]; -			if ( clipBits[a] & clipBits[b] & clipBits[c] ) { -				continue;	// not lighted -			} -			hitIndexes[numIndexes] = a; -			hitIndexes[numIndexes+1] = b; -			hitIndexes[numIndexes+2] = c; -			numIndexes += 3; -		} - -		if ( !numIndexes ) { -			continue; -		} - -		qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); -		qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] ); - -		qglEnableClientState( GL_COLOR_ARRAY ); -		qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); - -		GL_Bind( tr.dlightImage ); -		// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light -		// where they aren't rendered -		if ( dl->additive ) { -			GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); -		} -		else { -			GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); -		} -		R_DrawElements( numIndexes, hitIndexes ); -		backEnd.pc.c_totalIndexes += numIndexes; -		backEnd.pc.c_dlightIndexes += numIndexes; -	} -} - -static void ProjectDlightTexture( void ) { -#if idppc_altivec -	if (com_altivec->integer) { -		// must be in a seperate function or G3 systems will crash. -		ProjectDlightTexture_altivec(); -		return; -	} -#endif -	ProjectDlightTexture_scalar(); -} - - -/* -=================== -RB_FogPass - -Blends a fog texture on top of everything else -=================== -*/ -static void RB_FogPass( void ) { -	fog_t		*fog; -	int			i; - -	qglEnableClientState( GL_COLOR_ARRAY ); -	qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors ); - -	qglEnableClientState( GL_TEXTURE_COORD_ARRAY); -	qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] ); - -	fog = tr.world->fogs + tess.fogNum; - -	for ( i = 0; i < tess.numVertexes; i++ ) { -		* ( int * )&tess.svars.colors[i] = fog->colorInt; -	} - -	RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[0] ); - -	GL_Bind( tr.fogImage ); - -	if ( tess.shader->fogPass == FP_EQUAL ) { -		GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL ); -	} else { -		GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); -	} - -	R_DrawElements( tess.numIndexes, tess.indexes ); -} - -/* -=============== -ComputeColors -=============== -*/ -static void ComputeColors( shaderStage_t *pStage ) -{ -	int		i; - -	// -	// rgbGen -	// -	switch ( pStage->rgbGen ) -	{ -		case CGEN_IDENTITY: -			Com_Memset( tess.svars.colors, 0xff, tess.numVertexes * 4 ); -			break; -		default: -		case CGEN_IDENTITY_LIGHTING: -			Com_Memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 ); -			break; -		case CGEN_LIGHTING_DIFFUSE: -			RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors ); -			break; -		case CGEN_EXACT_VERTEX: -			Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) ); -			break; -		case CGEN_CONST: -			for ( i = 0; i < tess.numVertexes; i++ ) { -				*(int *)tess.svars.colors[i] = *(int *)pStage->constantColor; -			} -			break; -		case CGEN_VERTEX: -			if ( tr.identityLight == 1 ) -			{ -				Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) ); -			} -			else -			{ -				for ( i = 0; i < tess.numVertexes; i++ ) -				{ -					tess.svars.colors[i][0] = tess.vertexColors[i][0] * tr.identityLight; -					tess.svars.colors[i][1] = tess.vertexColors[i][1] * tr.identityLight; -					tess.svars.colors[i][2] = tess.vertexColors[i][2] * tr.identityLight; -					tess.svars.colors[i][3] = tess.vertexColors[i][3]; -				} -			} -			break; -		case CGEN_ONE_MINUS_VERTEX: -			if ( tr.identityLight == 1 ) -			{ -				for ( i = 0; i < tess.numVertexes; i++ ) -				{ -					tess.svars.colors[i][0] = 255 - tess.vertexColors[i][0]; -					tess.svars.colors[i][1] = 255 - tess.vertexColors[i][1]; -					tess.svars.colors[i][2] = 255 - tess.vertexColors[i][2]; -				} -			} -			else -			{ -				for ( i = 0; i < tess.numVertexes; i++ ) -				{ -					tess.svars.colors[i][0] = ( 255 - tess.vertexColors[i][0] ) * tr.identityLight; -					tess.svars.colors[i][1] = ( 255 - tess.vertexColors[i][1] ) * tr.identityLight; -					tess.svars.colors[i][2] = ( 255 - tess.vertexColors[i][2] ) * tr.identityLight; -				} -			} -			break; -		case CGEN_FOG: -			{ -				fog_t		*fog; - -				fog = tr.world->fogs + tess.fogNum; - -				for ( i = 0; i < tess.numVertexes; i++ ) { -					* ( int * )&tess.svars.colors[i] = fog->colorInt; -				} -			} -			break; -		case CGEN_WAVEFORM: -			RB_CalcWaveColor( &pStage->rgbWave, ( unsigned char * ) tess.svars.colors ); -			break; -		case CGEN_ENTITY: -			RB_CalcColorFromEntity( ( unsigned char * ) tess.svars.colors ); -			break; -		case CGEN_ONE_MINUS_ENTITY: -			RB_CalcColorFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); -			break; -	} - -	// -	// alphaGen -	// -	switch ( pStage->alphaGen ) -	{ -	case AGEN_SKIP: -		break; -	case AGEN_IDENTITY: -		if ( pStage->rgbGen != CGEN_IDENTITY ) { -			if ( ( pStage->rgbGen == CGEN_VERTEX && tr.identityLight != 1 ) || -				 pStage->rgbGen != CGEN_VERTEX ) { -				for ( i = 0; i < tess.numVertexes; i++ ) { -					tess.svars.colors[i][3] = 0xff; -				} -			} -		} -		break; -	case AGEN_CONST: -		if ( pStage->rgbGen != CGEN_CONST ) { -			for ( i = 0; i < tess.numVertexes; i++ ) { -				tess.svars.colors[i][3] = pStage->constantColor[3]; -			} -		} -		break; -	case AGEN_WAVEFORM: -		RB_CalcWaveAlpha( &pStage->alphaWave, ( unsigned char * ) tess.svars.colors ); -		break; -	case AGEN_LIGHTING_SPECULAR: -		RB_CalcSpecularAlpha( ( unsigned char * ) tess.svars.colors ); -		break; -	case AGEN_ENTITY: -		RB_CalcAlphaFromEntity( ( unsigned char * ) tess.svars.colors ); -		break; -	case AGEN_ONE_MINUS_ENTITY: -		RB_CalcAlphaFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); -		break; -    case AGEN_VERTEX: -		if ( pStage->rgbGen != CGEN_VERTEX ) { -			for ( i = 0; i < tess.numVertexes; i++ ) { -				tess.svars.colors[i][3] = tess.vertexColors[i][3]; -			} -		} -        break; -    case AGEN_ONE_MINUS_VERTEX: -        for ( i = 0; i < tess.numVertexes; i++ ) -        { -			tess.svars.colors[i][3] = 255 - tess.vertexColors[i][3]; -        } -        break; -	case AGEN_PORTAL: -		{ -			unsigned char alpha; - -			for ( i = 0; i < tess.numVertexes; i++ ) -			{ -				float len; -				vec3_t v; - -				VectorSubtract( tess.xyz[i], backEnd.viewParms.or.origin, v ); -				len = VectorLength( v ); - -				len /= tess.shader->portalRange; - -				if ( len < 0 ) -				{ -					alpha = 0; -				} -				else if ( len > 1 ) -				{ -					alpha = 0xff; -				} -				else -				{ -					alpha = len * 0xff; -				} - -				tess.svars.colors[i][3] = alpha; -			} -		} -		break; -	} - -	// -	// fog adjustment for colors to fade out as fog increases -	// -	if ( tess.fogNum ) -	{ -		switch ( pStage->adjustColorsForFog ) -		{ -		case ACFF_MODULATE_RGB: -			RB_CalcModulateColorsByFog( ( unsigned char * ) tess.svars.colors ); -			break; -		case ACFF_MODULATE_ALPHA: -			RB_CalcModulateAlphasByFog( ( unsigned char * ) tess.svars.colors ); -			break; -		case ACFF_MODULATE_RGBA: -			RB_CalcModulateRGBAsByFog( ( unsigned char * ) tess.svars.colors ); -			break; -		case ACFF_NONE: -			break; -		} -	} -} - -/* -=============== -ComputeTexCoords -=============== -*/ -static void ComputeTexCoords( shaderStage_t *pStage ) { -	int		i; -	int		b; - -	for ( b = 0; b < NUM_TEXTURE_BUNDLES; b++ ) { -		int tm; - -		// -		// generate the texture coordinates -		// -		switch ( pStage->bundle[b].tcGen ) -		{ -		case TCGEN_IDENTITY: -			Com_Memset( tess.svars.texcoords[b], 0, sizeof( float ) * 2 * tess.numVertexes ); -			break; -		case TCGEN_TEXTURE: -			for ( i = 0 ; i < tess.numVertexes ; i++ ) { -				tess.svars.texcoords[b][i][0] = tess.texCoords[i][0][0]; -				tess.svars.texcoords[b][i][1] = tess.texCoords[i][0][1]; -			} -			break; -		case TCGEN_LIGHTMAP: -			for ( i = 0 ; i < tess.numVertexes ; i++ ) { -				tess.svars.texcoords[b][i][0] = tess.texCoords[i][1][0]; -				tess.svars.texcoords[b][i][1] = tess.texCoords[i][1][1]; -			} -			break; -		case TCGEN_VECTOR: -			for ( i = 0 ; i < tess.numVertexes ; i++ ) { -				tess.svars.texcoords[b][i][0] = DotProduct( tess.xyz[i], pStage->bundle[b].tcGenVectors[0] ); -				tess.svars.texcoords[b][i][1] = DotProduct( tess.xyz[i], pStage->bundle[b].tcGenVectors[1] ); -			} -			break; -		case TCGEN_FOG: -			RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[b] ); -			break; -		case TCGEN_ENVIRONMENT_MAPPED: -			RB_CalcEnvironmentTexCoords( ( float * ) tess.svars.texcoords[b] ); -			break; -		case TCGEN_BAD: -			return; -		} - -		// -		// alter texture coordinates -		// -		for ( tm = 0; tm < pStage->bundle[b].numTexMods ; tm++ ) { -			switch ( pStage->bundle[b].texMods[tm].type ) -			{ -			case TMOD_NONE: -				tm = TR_MAX_TEXMODS;		// break out of for loop -				break; - -			case TMOD_TURBULENT: -				RB_CalcTurbulentTexCoords( &pStage->bundle[b].texMods[tm].wave,  -						                 ( float * ) tess.svars.texcoords[b] ); -				break; - -			case TMOD_ENTITY_TRANSLATE: -				RB_CalcScrollTexCoords( backEnd.currentEntity->e.shaderTexCoord, -									 ( float * ) tess.svars.texcoords[b] ); -				break; - -			case TMOD_SCROLL: -				RB_CalcScrollTexCoords( pStage->bundle[b].texMods[tm].scroll, -										 ( float * ) tess.svars.texcoords[b] ); -				break; - -			case TMOD_SCALE: -				RB_CalcScaleTexCoords( pStage->bundle[b].texMods[tm].scale, -									 ( float * ) tess.svars.texcoords[b] ); -				break; -			 -			case TMOD_STRETCH: -				RB_CalcStretchTexCoords( &pStage->bundle[b].texMods[tm].wave,  -						               ( float * ) tess.svars.texcoords[b] ); -				break; - -			case TMOD_TRANSFORM: -				RB_CalcTransformTexCoords( &pStage->bundle[b].texMods[tm], -						                 ( float * ) tess.svars.texcoords[b] ); -				break; - -			case TMOD_ROTATE: -				RB_CalcRotateTexCoords( pStage->bundle[b].texMods[tm].rotateSpeed, -										( float * ) tess.svars.texcoords[b] ); -				break; - -			default: -				ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'\n", pStage->bundle[b].texMods[tm].type, tess.shader->name ); -				break; -			} -		} -	} -} - -/* -** RB_IterateStagesGeneric -*/ -static void RB_IterateStagesGeneric( shaderCommands_t *input ) -{ -	int stage; - -	for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) -	{ -		shaderStage_t *pStage = tess.xstages[stage]; - -		if ( !pStage ) -		{ -			break; -		} - -		ComputeColors( pStage ); -		ComputeTexCoords( pStage ); - -		if ( !setArraysOnce ) -		{ -			qglEnableClientState( GL_COLOR_ARRAY ); -			qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, input->svars.colors ); -		} - -		// -		// do multitexture -		// -		if ( pStage->bundle[1].image[0] != 0 ) -		{ -			DrawMultitextured( input, stage ); -		} -		else -		{ -			if ( !setArraysOnce ) -			{ -				qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] ); -			} - -			// -			// set state -			// -			if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer ) -			{ -				GL_Bind( tr.whiteImage ); -			} -			else  -				R_BindAnimatedImage( &pStage->bundle[0] ); - -			GL_State( pStage->stateBits ); - -			// -			// draw -			// -			R_DrawElements( input->numIndexes, input->indexes ); -		} -		// allow skipping out to show just lightmaps during development -		if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) ) -		{ -			break; -		} -	} -} - - -/* -** RB_StageIteratorGeneric -*/ -void RB_StageIteratorGeneric( void ) -{ -	shaderCommands_t *input; - -	input = &tess; - -	RB_DeformTessGeometry(); - -	// -	// log this call -	// -	if ( r_logFile->integer )  -	{ -		// don't just call LogComment, or we will get -		// a call to va() every frame! -		GLimp_LogComment( va("--- RB_StageIteratorGeneric( %s ) ---\n", tess.shader->name) ); -	} - -	// -	// set face culling appropriately -	// -	GL_Cull( input->shader->cullType ); - -	// set polygon offset if necessary -	if ( input->shader->polygonOffset ) -	{ -		qglEnable( GL_POLYGON_OFFSET_FILL ); -		qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); -	} - -	// -	// if there is only a single pass then we can enable color -	// and texture arrays before we compile, otherwise we need -	// to avoid compiling those arrays since they will change -	// during multipass rendering -	// -	if ( tess.numPasses > 1 || input->shader->multitextureEnv ) -	{ -		setArraysOnce = qfalse; -		qglDisableClientState (GL_COLOR_ARRAY); -		qglDisableClientState (GL_TEXTURE_COORD_ARRAY); -	} -	else -	{ -		setArraysOnce = qtrue; - -		qglEnableClientState( GL_COLOR_ARRAY); -		qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors ); - -		qglEnableClientState( GL_TEXTURE_COORD_ARRAY); -		qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] ); -	} - -	// -	// lock XYZ -	// -	qglVertexPointer (3, GL_FLOAT, 16, input->xyz);	// padded for SIMD -	if (qglLockArraysEXT) -	{ -		qglLockArraysEXT(0, input->numVertexes); -		GLimp_LogComment( "glLockArraysEXT\n" ); -	} - -	// -	// enable color and texcoord arrays after the lock if necessary -	// -	if ( !setArraysOnce ) -	{ -		qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); -		qglEnableClientState( GL_COLOR_ARRAY ); -	} - -	// -	// call shader function -	// -	RB_IterateStagesGeneric( input ); - -	//  -	// now do any dynamic lighting needed -	// -	if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE -		&& !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) { -		ProjectDlightTexture(); -	} - -	// -	// now do fog -	// -	if ( tess.fogNum && tess.shader->fogPass ) { -		RB_FogPass(); -	} - -	//  -	// unlock arrays -	// -	if (qglUnlockArraysEXT)  -	{ -		qglUnlockArraysEXT(); -		GLimp_LogComment( "glUnlockArraysEXT\n" ); -	} - -	// -	// reset polygon offset -	// -	if ( input->shader->polygonOffset ) -	{ -		qglDisable( GL_POLYGON_OFFSET_FILL ); -	} -} - - -/* -** RB_StageIteratorVertexLitTexture -*/ -void RB_StageIteratorVertexLitTexture( void ) -{ -	shaderCommands_t *input; -	shader_t		*shader; - -	input = &tess; - -	shader = input->shader; - -	// -	// compute colors -	// -	RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors ); - -	// -	// log this call -	// -	if ( r_logFile->integer )  -	{ -		// don't just call LogComment, or we will get -		// a call to va() every frame! -		GLimp_LogComment( va("--- RB_StageIteratorVertexLitTexturedUnfogged( %s ) ---\n", tess.shader->name) ); -	} - -	// -	// set face culling appropriately -	// -	GL_Cull( input->shader->cullType ); - -	// -	// set arrays and lock -	// -	qglEnableClientState( GL_COLOR_ARRAY); -	qglEnableClientState( GL_TEXTURE_COORD_ARRAY); - -	qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors ); -	qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] ); -	qglVertexPointer (3, GL_FLOAT, 16, input->xyz); - -	if ( qglLockArraysEXT ) -	{ -		qglLockArraysEXT(0, input->numVertexes); -		GLimp_LogComment( "glLockArraysEXT\n" ); -	} - -	// -	// call special shade routine -	// -	R_BindAnimatedImage( &tess.xstages[0]->bundle[0] ); -	GL_State( tess.xstages[0]->stateBits ); -	R_DrawElements( input->numIndexes, input->indexes ); - -	//  -	// now do any dynamic lighting needed -	// -	if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) { -		ProjectDlightTexture(); -	} - -	// -	// now do fog -	// -	if ( tess.fogNum && tess.shader->fogPass ) { -		RB_FogPass(); -	} - -	//  -	// unlock arrays -	// -	if (qglUnlockArraysEXT)  -	{ -		qglUnlockArraysEXT(); -		GLimp_LogComment( "glUnlockArraysEXT\n" ); -	} -} - -//define	REPLACE_MODE - -void RB_StageIteratorLightmappedMultitexture( void ) { -	shaderCommands_t *input; - -	input = &tess; - -	// -	// log this call -	// -	if ( r_logFile->integer ) { -		// don't just call LogComment, or we will get -		// a call to va() every frame! -		GLimp_LogComment( va("--- RB_StageIteratorLightmappedMultitexture( %s ) ---\n", tess.shader->name) ); -	} - -	// -	// set face culling appropriately -	// -	GL_Cull( input->shader->cullType ); - -	// -	// set color, pointers, and lock -	// -	GL_State( GLS_DEFAULT ); -	qglVertexPointer( 3, GL_FLOAT, 16, input->xyz ); - -#ifdef REPLACE_MODE -	qglDisableClientState( GL_COLOR_ARRAY ); -	qglColor3f( 1, 1, 1 ); -	qglShadeModel( GL_FLAT ); -#else -	qglEnableClientState( GL_COLOR_ARRAY ); -	qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.constantColor255 ); -#endif - -	// -	// select base stage -	// -	GL_SelectTexture( 0 ); - -	qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); -	R_BindAnimatedImage( &tess.xstages[0]->bundle[0] ); -	qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] ); - -	// -	// configure second stage -	// -	GL_SelectTexture( 1 ); -	qglEnable( GL_TEXTURE_2D ); -	if ( r_lightmap->integer ) { -		GL_TexEnv( GL_REPLACE ); -	} else { -		GL_TexEnv( GL_MODULATE ); -	} -	R_BindAnimatedImage( &tess.xstages[0]->bundle[1] ); -	qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); -	qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][1] ); - -	// -	// lock arrays -	// -	if ( qglLockArraysEXT ) { -		qglLockArraysEXT(0, input->numVertexes); -		GLimp_LogComment( "glLockArraysEXT\n" ); -	} - -	R_DrawElements( input->numIndexes, input->indexes ); - -	// -	// disable texturing on TEXTURE1, then select TEXTURE0 -	// -	qglDisable( GL_TEXTURE_2D ); -	qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); - -	GL_SelectTexture( 0 ); -#ifdef REPLACE_MODE -	GL_TexEnv( GL_MODULATE ); -	qglShadeModel( GL_SMOOTH ); -#endif - -	//  -	// now do any dynamic lighting needed -	// -	if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) { -		ProjectDlightTexture(); -	} - -	// -	// now do fog -	// -	if ( tess.fogNum && tess.shader->fogPass ) { -		RB_FogPass(); -	} - -	// -	// unlock arrays -	// -	if ( qglUnlockArraysEXT ) { -		qglUnlockArraysEXT(); -		GLimp_LogComment( "glUnlockArraysEXT\n" ); -	} -} - -/* -** RB_EndSurface -*/ -void RB_EndSurface( void ) { -	shaderCommands_t *input; - -	input = &tess; - -	if (input->numIndexes == 0) { -		return; -	} - -	if (input->indexes[SHADER_MAX_INDEXES-1] != 0) { -		ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_INDEXES hit"); -	}	 -	if (input->xyz[SHADER_MAX_VERTEXES-1][0] != 0) { -		ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_VERTEXES hit"); -	} - -	if ( tess.shader == tr.shadowShader ) { -		RB_ShadowTessEnd(); -		return; -	} - -	// for debugging of sort order issues, stop rendering after a given sort value -	if ( r_debugSort->integer && r_debugSort->integer < tess.shader->sort ) { -		return; -	} - -	// -	// update performance counters -	// -	backEnd.pc.c_shaders++; -	backEnd.pc.c_vertexes += tess.numVertexes; -	backEnd.pc.c_indexes += tess.numIndexes; -	backEnd.pc.c_totalIndexes += tess.numIndexes * tess.numPasses; - -	// -	// call off to shader specific tess end function -	// -	tess.currentStageIteratorFunc(); - -	// -	// draw debugging stuff -	// -	if ( r_showtris->integer ) { -		DrawTris (input); -	} -	if ( r_shownormals->integer ) { -		DrawNormals (input); -	} -	// clear shader so we can tell we don't have any unclosed surfaces -	tess.numIndexes = 0; - -	GLimp_LogComment( "----------\n" ); -} - diff --git a/ioq3-r437/src/renderer/tr_shade_calc.c b/ioq3-r437/src/renderer/tr_shade_calc.c deleted file mode 100644 index 15fbe77a..00000000 --- a/ioq3-r437/src/renderer/tr_shade_calc.c +++ /dev/null @@ -1,1231 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_shade_calc.c - -#include "tr_local.h" -#if idppc_altivec && !defined(MACOS_X) -#include <altivec.h> -#endif - - -#define	WAVEVALUE( table, base, amplitude, phase, freq )  ((base) + table[ myftol( ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude)) - -static float *TableForFunc( genFunc_t func )  -{ -	switch ( func ) -	{ -	case GF_SIN: -		return tr.sinTable; -	case GF_TRIANGLE: -		return tr.triangleTable; -	case GF_SQUARE: -		return tr.squareTable; -	case GF_SAWTOOTH: -		return tr.sawToothTable; -	case GF_INVERSE_SAWTOOTH: -		return tr.inverseSawToothTable; -	case GF_NONE: -	default: -		break; -	} - -	ri.Error( ERR_DROP, "TableForFunc called with invalid function '%d' in shader '%s'\n", func, tess.shader->name ); -	return NULL; -} - -/* -** EvalWaveForm -** -** Evaluates a given waveForm_t, referencing backEnd.refdef.time directly -*/ -static float EvalWaveForm( const waveForm_t *wf )  -{ -	float	*table; - -	table = TableForFunc( wf->func ); - -	return WAVEVALUE( table, wf->base, wf->amplitude, wf->phase, wf->frequency ); -} - -static float EvalWaveFormClamped( const waveForm_t *wf ) -{ -	float glow  = EvalWaveForm( wf ); - -	if ( glow < 0 ) -	{ -		return 0; -	} - -	if ( glow > 1 ) -	{ -		return 1; -	} - -	return glow; -} - -/* -** RB_CalcStretchTexCoords -*/ -void RB_CalcStretchTexCoords( const waveForm_t *wf, float *st ) -{ -	float p; -	texModInfo_t tmi; - -	p = 1.0f / EvalWaveForm( wf ); - -	tmi.matrix[0][0] = p; -	tmi.matrix[1][0] = 0; -	tmi.translate[0] = 0.5f - 0.5f * p; - -	tmi.matrix[0][1] = 0; -	tmi.matrix[1][1] = p; -	tmi.translate[1] = 0.5f - 0.5f * p; - -	RB_CalcTransformTexCoords( &tmi, st ); -} - -/* -==================================================================== - -DEFORMATIONS - -==================================================================== -*/ - -/* -======================== -RB_CalcDeformVertexes - -======================== -*/ -void RB_CalcDeformVertexes( deformStage_t *ds ) -{ -	int i; -	vec3_t	offset; -	float	scale; -	float	*xyz = ( float * ) tess.xyz; -	float	*normal = ( float * ) tess.normal; -	float	*table; - -	if ( ds->deformationWave.frequency == 0 ) -	{ -		scale = EvalWaveForm( &ds->deformationWave ); - -		for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) -		{ -			VectorScale( normal, scale, offset ); -			 -			xyz[0] += offset[0]; -			xyz[1] += offset[1]; -			xyz[2] += offset[2]; -		} -	} -	else -	{ -		table = TableForFunc( ds->deformationWave.func ); - -		for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) -		{ -			float off = ( xyz[0] + xyz[1] + xyz[2] ) * ds->deformationSpread; - -			scale = WAVEVALUE( table, ds->deformationWave.base,  -				ds->deformationWave.amplitude, -				ds->deformationWave.phase + off, -				ds->deformationWave.frequency ); - -			VectorScale( normal, scale, offset ); -			 -			xyz[0] += offset[0]; -			xyz[1] += offset[1]; -			xyz[2] += offset[2]; -		} -	} -} - -/* -========================= -RB_CalcDeformNormals - -Wiggle the normals for wavy environment mapping -========================= -*/ -void RB_CalcDeformNormals( deformStage_t *ds ) { -	int i; -	float	scale; -	float	*xyz = ( float * ) tess.xyz; -	float	*normal = ( float * ) tess.normal; - -	for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) { -		scale = 0.98f; -		scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale, -			tess.shaderTime * ds->deformationWave.frequency ); -		normal[ 0 ] += ds->deformationWave.amplitude * scale; - -		scale = 0.98f; -		scale = R_NoiseGet4f( 100 + xyz[0] * scale, xyz[1] * scale, xyz[2] * scale, -			tess.shaderTime * ds->deformationWave.frequency ); -		normal[ 1 ] += ds->deformationWave.amplitude * scale; - -		scale = 0.98f; -		scale = R_NoiseGet4f( 200 + xyz[0] * scale, xyz[1] * scale, xyz[2] * scale, -			tess.shaderTime * ds->deformationWave.frequency ); -		normal[ 2 ] += ds->deformationWave.amplitude * scale; - -		VectorNormalizeFast( normal ); -	} -} - -/* -======================== -RB_CalcBulgeVertexes - -======================== -*/ -void RB_CalcBulgeVertexes( deformStage_t *ds ) { -	int i; -	const float *st = ( const float * ) tess.texCoords[0]; -	float		*xyz = ( float * ) tess.xyz; -	float		*normal = ( float * ) tess.normal; -	float		now; - -	now = backEnd.refdef.time * ds->bulgeSpeed * 0.001f; - -	for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 4, normal += 4 ) { -		int		off; -		float scale; - -		off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now ); - -		scale = tr.sinTable[ off & FUNCTABLE_MASK ] * ds->bulgeHeight; -			 -		xyz[0] += normal[0] * scale; -		xyz[1] += normal[1] * scale; -		xyz[2] += normal[2] * scale; -	} -} - - -/* -====================== -RB_CalcMoveVertexes - -A deformation that can move an entire surface along a wave path -====================== -*/ -void RB_CalcMoveVertexes( deformStage_t *ds ) { -	int			i; -	float		*xyz; -	float		*table; -	float		scale; -	vec3_t		offset; - -	table = TableForFunc( ds->deformationWave.func ); - -	scale = WAVEVALUE( table, ds->deformationWave.base,  -		ds->deformationWave.amplitude, -		ds->deformationWave.phase, -		ds->deformationWave.frequency ); - -	VectorScale( ds->moveVector, scale, offset ); - -	xyz = ( float * ) tess.xyz; -	for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) { -		VectorAdd( xyz, offset, xyz ); -	} -} - - -/* -============= -DeformText - -Change a polygon into a bunch of text polygons -============= -*/ -void DeformText( const char *text ) { -	int		i; -	vec3_t	origin, width, height; -	int		len; -	int		ch; -	byte	color[4]; -	float	bottom, top; -	vec3_t	mid; - -	height[0] = 0; -	height[1] = 0; -	height[2] = -1; -	CrossProduct( tess.normal[0], height, width ); - -	// find the midpoint of the box -	VectorClear( mid ); -	bottom = 999999; -	top = -999999; -	for ( i = 0 ; i < 4 ; i++ ) { -		VectorAdd( tess.xyz[i], mid, mid ); -		if ( tess.xyz[i][2] < bottom ) { -			bottom = tess.xyz[i][2]; -		} -		if ( tess.xyz[i][2] > top ) { -			top = tess.xyz[i][2]; -		} -	} -	VectorScale( mid, 0.25f, origin ); - -	// determine the individual character size -	height[0] = 0; -	height[1] = 0; -	height[2] = ( top - bottom ) * 0.5f; - -	VectorScale( width, height[2] * -0.75f, width ); - -	// determine the starting position -	len = strlen( text ); -	VectorMA( origin, (len-1), width, origin ); - -	// clear the shader indexes -	tess.numIndexes = 0; -	tess.numVertexes = 0; - -	color[0] = color[1] = color[2] = color[3] = 255; - -	// draw each character -	for ( i = 0 ; i < len ; i++ ) { -		ch = text[i]; -		ch &= 255; - -		if ( ch != ' ' ) { -			int		row, col; -			float	frow, fcol, size; - -			row = ch>>4; -			col = ch&15; - -			frow = row*0.0625f; -			fcol = col*0.0625f; -			size = 0.0625f; - -			RB_AddQuadStampExt( origin, width, height, color, fcol, frow, fcol + size, frow + size ); -		} -		VectorMA( origin, -2, width, origin ); -	} -} - -/* -================== -GlobalVectorToLocal -================== -*/ -static void GlobalVectorToLocal( const vec3_t in, vec3_t out ) { -	out[0] = DotProduct( in, backEnd.or.axis[0] ); -	out[1] = DotProduct( in, backEnd.or.axis[1] ); -	out[2] = DotProduct( in, backEnd.or.axis[2] ); -} - -/* -===================== -AutospriteDeform - -Assuming all the triangles for this shader are independant -quads, rebuild them as forward facing sprites -===================== -*/ -static void AutospriteDeform( void ) { -	int		i; -	int		oldVerts; -	float	*xyz; -	vec3_t	mid, delta; -	float	radius; -	vec3_t	left, up; -	vec3_t	leftDir, upDir; - -	if ( tess.numVertexes & 3 ) { -		ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd vertex count", tess.shader->name ); -	} -	if ( tess.numIndexes != ( tess.numVertexes >> 2 ) * 6 ) { -		ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd index count", tess.shader->name ); -	} - -	oldVerts = tess.numVertexes; -	tess.numVertexes = 0; -	tess.numIndexes = 0; - -	if ( backEnd.currentEntity != &tr.worldEntity ) { -		GlobalVectorToLocal( backEnd.viewParms.or.axis[1], leftDir ); -		GlobalVectorToLocal( backEnd.viewParms.or.axis[2], upDir ); -	} else { -		VectorCopy( backEnd.viewParms.or.axis[1], leftDir ); -		VectorCopy( backEnd.viewParms.or.axis[2], upDir ); -	} - -	for ( i = 0 ; i < oldVerts ; i+=4 ) { -		// find the midpoint -		xyz = tess.xyz[i]; - -		mid[0] = 0.25f * (xyz[0] + xyz[4] + xyz[8] + xyz[12]); -		mid[1] = 0.25f * (xyz[1] + xyz[5] + xyz[9] + xyz[13]); -		mid[2] = 0.25f * (xyz[2] + xyz[6] + xyz[10] + xyz[14]); - -		VectorSubtract( xyz, mid, delta ); -		radius = VectorLength( delta ) * 0.707f;		// / sqrt(2) - -		VectorScale( leftDir, radius, left ); -		VectorScale( upDir, radius, up ); - -		if ( backEnd.viewParms.isMirror ) { -			VectorSubtract( vec3_origin, left, left ); -		} - -	  // compensate for scale in the axes if necessary -  	if ( backEnd.currentEntity->e.nonNormalizedAxes ) { -      float axisLength; -		  axisLength = VectorLength( backEnd.currentEntity->e.axis[0] ); -  		if ( !axisLength ) { -	  		axisLength = 0; -  		} else { -	  		axisLength = 1.0f / axisLength; -  		} -      VectorScale(left, axisLength, left); -      VectorScale(up, axisLength, up); -    } - -		RB_AddQuadStamp( mid, left, up, tess.vertexColors[i] ); -	} -} - - -/* -===================== -Autosprite2Deform - -Autosprite2 will pivot a rectangular quad along the center of its long axis -===================== -*/ -int edgeVerts[6][2] = { -	{ 0, 1 }, -	{ 0, 2 }, -	{ 0, 3 }, -	{ 1, 2 }, -	{ 1, 3 }, -	{ 2, 3 } -}; - -static void Autosprite2Deform( void ) { -	int		i, j, k; -	int		indexes; -	float	*xyz; -	vec3_t	forward; - -	if ( tess.numVertexes & 3 ) { -		ri.Printf( PRINT_WARNING, "Autosprite2 shader %s had odd vertex count", tess.shader->name ); -	} -	if ( tess.numIndexes != ( tess.numVertexes >> 2 ) * 6 ) { -		ri.Printf( PRINT_WARNING, "Autosprite2 shader %s had odd index count", tess.shader->name ); -	} - -	if ( backEnd.currentEntity != &tr.worldEntity ) { -		GlobalVectorToLocal( backEnd.viewParms.or.axis[0], forward ); -	} else { -		VectorCopy( backEnd.viewParms.or.axis[0], forward ); -	} - -	// this is a lot of work for two triangles... -	// we could precalculate a lot of it is an issue, but it would mess up -	// the shader abstraction -	for ( i = 0, indexes = 0 ; i < tess.numVertexes ; i+=4, indexes+=6 ) { -		float	lengths[2]; -		int		nums[2]; -		vec3_t	mid[2]; -		vec3_t	major, minor; -		float	*v1, *v2; - -		// find the midpoint -		xyz = tess.xyz[i]; - -		// identify the two shortest edges -		nums[0] = nums[1] = 0; -		lengths[0] = lengths[1] = 999999; - -		for ( j = 0 ; j < 6 ; j++ ) { -			float	l; -			vec3_t	temp; - -			v1 = xyz + 4 * edgeVerts[j][0]; -			v2 = xyz + 4 * edgeVerts[j][1]; - -			VectorSubtract( v1, v2, temp ); -			 -			l = DotProduct( temp, temp ); -			if ( l < lengths[0] ) { -				nums[1] = nums[0]; -				lengths[1] = lengths[0]; -				nums[0] = j; -				lengths[0] = l; -			} else if ( l < lengths[1] ) { -				nums[1] = j; -				lengths[1] = l; -			} -		} - -		for ( j = 0 ; j < 2 ; j++ ) { -			v1 = xyz + 4 * edgeVerts[nums[j]][0]; -			v2 = xyz + 4 * edgeVerts[nums[j]][1]; - -			mid[j][0] = 0.5f * (v1[0] + v2[0]); -			mid[j][1] = 0.5f * (v1[1] + v2[1]); -			mid[j][2] = 0.5f * (v1[2] + v2[2]); -		} - -		// find the vector of the major axis -		VectorSubtract( mid[1], mid[0], major ); - -		// cross this with the view direction to get minor axis -		CrossProduct( major, forward, minor ); -		VectorNormalize( minor ); -		 -		// re-project the points -		for ( j = 0 ; j < 2 ; j++ ) { -			float	l; - -			v1 = xyz + 4 * edgeVerts[nums[j]][0]; -			v2 = xyz + 4 * edgeVerts[nums[j]][1]; - -			l = 0.5 * sqrt( lengths[j] ); -			 -			// we need to see which direction this edge -			// is used to determine direction of projection -			for ( k = 0 ; k < 5 ; k++ ) { -				if ( tess.indexes[ indexes + k ] == i + edgeVerts[nums[j]][0] -					&& tess.indexes[ indexes + k + 1 ] == i + edgeVerts[nums[j]][1] ) { -					break; -				} -			} - -			if ( k == 5 ) { -				VectorMA( mid[j], l, minor, v1 ); -				VectorMA( mid[j], -l, minor, v2 ); -			} else { -				VectorMA( mid[j], -l, minor, v1 ); -				VectorMA( mid[j], l, minor, v2 ); -			} -		} -	} -} - - -/* -===================== -RB_DeformTessGeometry - -===================== -*/ -void RB_DeformTessGeometry( void ) { -	int		i; -	deformStage_t	*ds; - -	for ( i = 0 ; i < tess.shader->numDeforms ; i++ ) { -		ds = &tess.shader->deforms[ i ]; - -		switch ( ds->deformation ) { -        case DEFORM_NONE: -            break; -		case DEFORM_NORMALS: -			RB_CalcDeformNormals( ds ); -			break; -		case DEFORM_WAVE: -			RB_CalcDeformVertexes( ds ); -			break; -		case DEFORM_BULGE: -			RB_CalcBulgeVertexes( ds ); -			break; -		case DEFORM_MOVE: -			RB_CalcMoveVertexes( ds ); -			break; -		case DEFORM_PROJECTION_SHADOW: -			RB_ProjectionShadowDeform(); -			break; -		case DEFORM_AUTOSPRITE: -			AutospriteDeform(); -			break; -		case DEFORM_AUTOSPRITE2: -			Autosprite2Deform(); -			break; -		case DEFORM_TEXT0: -		case DEFORM_TEXT1: -		case DEFORM_TEXT2: -		case DEFORM_TEXT3: -		case DEFORM_TEXT4: -		case DEFORM_TEXT5: -		case DEFORM_TEXT6: -		case DEFORM_TEXT7: -			DeformText( backEnd.refdef.text[ds->deformation - DEFORM_TEXT0] ); -			break; -		} -	} -} - -/* -==================================================================== - -COLORS - -==================================================================== -*/ - - -/* -** RB_CalcColorFromEntity -*/ -void RB_CalcColorFromEntity( unsigned char *dstColors ) -{ -	int	i; -	int *pColors = ( int * ) dstColors; -	int c; - -	if ( !backEnd.currentEntity ) -		return; - -	c = * ( int * ) backEnd.currentEntity->e.shaderRGBA; - -	for ( i = 0; i < tess.numVertexes; i++, pColors++ ) -	{ -		*pColors = c; -	} -} - -/* -** RB_CalcColorFromOneMinusEntity -*/ -void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors ) -{ -	int	i; -	int *pColors = ( int * ) dstColors; -	unsigned char invModulate[3]; -	int c; - -	if ( !backEnd.currentEntity ) -		return; - -	invModulate[0] = 255 - backEnd.currentEntity->e.shaderRGBA[0]; -	invModulate[1] = 255 - backEnd.currentEntity->e.shaderRGBA[1]; -	invModulate[2] = 255 - backEnd.currentEntity->e.shaderRGBA[2]; -	invModulate[3] = 255 - backEnd.currentEntity->e.shaderRGBA[3];	// this trashes alpha, but the AGEN block fixes it - -	c = * ( int * ) invModulate; - -	for ( i = 0; i < tess.numVertexes; i++, pColors++ ) -	{ -		*pColors = * ( int * ) invModulate; -	} -} - -/* -** RB_CalcAlphaFromEntity -*/ -void RB_CalcAlphaFromEntity( unsigned char *dstColors ) -{ -	int	i; - -	if ( !backEnd.currentEntity ) -		return; - -	dstColors += 3; - -	for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 ) -	{ -		*dstColors = backEnd.currentEntity->e.shaderRGBA[3]; -	} -} - -/* -** RB_CalcAlphaFromOneMinusEntity -*/ -void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors ) -{ -	int	i; - -	if ( !backEnd.currentEntity ) -		return; - -	dstColors += 3; - -	for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 ) -	{ -		*dstColors = 0xff - backEnd.currentEntity->e.shaderRGBA[3]; -	} -} - -/* -** RB_CalcWaveColor -*/ -void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors ) -{ -	int i; -	int v; -	float glow; -	int *colors = ( int * ) dstColors; -	byte	color[4]; - - -  if ( wf->func == GF_NOISE ) { -		glow = wf->base + R_NoiseGet4f( 0, 0, 0, ( tess.shaderTime + wf->phase ) * wf->frequency ) * wf->amplitude; -	} else { -		glow = EvalWaveForm( wf ) * tr.identityLight; -	} -	 -	if ( glow < 0 ) { -		glow = 0; -	} -	else if ( glow > 1 ) { -		glow = 1; -	} - -	v = myftol( 255 * glow ); -	color[0] = color[1] = color[2] = v; -	color[3] = 255; -	v = *(int *)color; -	 -	for ( i = 0; i < tess.numVertexes; i++, colors++ ) { -		*colors = v; -	} -} - -/* -** RB_CalcWaveAlpha -*/ -void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors ) -{ -	int i; -	int v; -	float glow; - -	glow = EvalWaveFormClamped( wf ); - -	v = 255 * glow; - -	for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 ) -	{ -		dstColors[3] = v; -	} -} - -/* -** RB_CalcModulateColorsByFog -*/ -void RB_CalcModulateColorsByFog( unsigned char *colors ) { -	int		i; -	float	texCoords[SHADER_MAX_VERTEXES][2]; - -	// calculate texcoords so we can derive density -	// this is not wasted, because it would only have -	// been previously called if the surface was opaque -	RB_CalcFogTexCoords( texCoords[0] ); - -	for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) { -		float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] ); -		colors[0] *= f; -		colors[1] *= f; -		colors[2] *= f; -	} -} - -/* -** RB_CalcModulateAlphasByFog -*/ -void RB_CalcModulateAlphasByFog( unsigned char *colors ) { -	int		i; -	float	texCoords[SHADER_MAX_VERTEXES][2]; - -	// calculate texcoords so we can derive density -	// this is not wasted, because it would only have -	// been previously called if the surface was opaque -	RB_CalcFogTexCoords( texCoords[0] ); - -	for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) { -		float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] ); -		colors[3] *= f; -	} -} - -/* -** RB_CalcModulateRGBAsByFog -*/ -void RB_CalcModulateRGBAsByFog( unsigned char *colors ) { -	int		i; -	float	texCoords[SHADER_MAX_VERTEXES][2]; - -	// calculate texcoords so we can derive density -	// this is not wasted, because it would only have -	// been previously called if the surface was opaque -	RB_CalcFogTexCoords( texCoords[0] ); - -	for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) { -		float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] ); -		colors[0] *= f; -		colors[1] *= f; -		colors[2] *= f; -		colors[3] *= f; -	} -} - - -/* -==================================================================== - -TEX COORDS - -==================================================================== -*/ - -/* -======================== -RB_CalcFogTexCoords - -To do the clipped fog plane really correctly, we should use -projected textures, but I don't trust the drivers and it -doesn't fit our shader data. -======================== -*/ -void RB_CalcFogTexCoords( float *st ) { -	int			i; -	float		*v; -	float		s, t; -	float		eyeT; -	qboolean	eyeOutside; -	fog_t		*fog; -	vec3_t		local; -	vec4_t		fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; - -	fog = tr.world->fogs + tess.fogNum; - -	// all fogging distance is based on world Z units -	VectorSubtract( backEnd.or.origin, backEnd.viewParms.or.origin, local ); -	fogDistanceVector[0] = -backEnd.or.modelMatrix[2]; -	fogDistanceVector[1] = -backEnd.or.modelMatrix[6]; -	fogDistanceVector[2] = -backEnd.or.modelMatrix[10]; -	fogDistanceVector[3] = DotProduct( local, backEnd.viewParms.or.axis[0] ); - -	// scale the fog vectors based on the fog's thickness -	fogDistanceVector[0] *= fog->tcScale; -	fogDistanceVector[1] *= fog->tcScale; -	fogDistanceVector[2] *= fog->tcScale; -	fogDistanceVector[3] *= fog->tcScale; - -	// rotate the gradient vector for this orientation -	if ( fog->hasSurface ) { -		fogDepthVector[0] = fog->surface[0] * backEnd.or.axis[0][0] +  -			fog->surface[1] * backEnd.or.axis[0][1] + fog->surface[2] * backEnd.or.axis[0][2]; -		fogDepthVector[1] = fog->surface[0] * backEnd.or.axis[1][0] +  -			fog->surface[1] * backEnd.or.axis[1][1] + fog->surface[2] * backEnd.or.axis[1][2]; -		fogDepthVector[2] = fog->surface[0] * backEnd.or.axis[2][0] +  -			fog->surface[1] * backEnd.or.axis[2][1] + fog->surface[2] * backEnd.or.axis[2][2]; -		fogDepthVector[3] = -fog->surface[3] + DotProduct( backEnd.or.origin, fog->surface ); - -		eyeT = DotProduct( backEnd.or.viewOrigin, fogDepthVector ) + fogDepthVector[3]; -	} else { -		eyeT = 1;	// non-surface fog always has eye inside -	} - -	// see if the viewpoint is outside -	// this is needed for clipping distance even for constant fog - -	if ( eyeT < 0 ) { -		eyeOutside = qtrue; -	} else { -		eyeOutside = qfalse; -	} - -	fogDistanceVector[3] += 1.0/512; - -	// calculate density for each point -	for (i = 0, v = tess.xyz[0] ; i < tess.numVertexes ; i++, v += 4) { -		// calculate the length in fog -		s = DotProduct( v, fogDistanceVector ) + fogDistanceVector[3]; -		t = DotProduct( v, fogDepthVector ) + fogDepthVector[3]; - -		// partially clipped fogs use the T axis		 -		if ( eyeOutside ) { -			if ( t < 1.0 ) { -				t = 1.0/32;	// point is outside, so no fogging -			} else { -				t = 1.0/32 + 30.0/32 * t / ( t - eyeT );	// cut the distance at the fog plane -			} -		} else { -			if ( t < 0 ) { -				t = 1.0/32;	// point is outside, so no fogging -			} else { -				t = 31.0/32; -			} -		} - -		st[0] = s; -		st[1] = t; -		st += 2; -	} -} - - - -/* -** RB_CalcEnvironmentTexCoords -*/ -void RB_CalcEnvironmentTexCoords( float *st )  -{ -	int			i; -	float		*v, *normal; -	vec3_t		viewer, reflected; -	float		d; - -	v = tess.xyz[0]; -	normal = tess.normal[0]; - -	for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 )  -	{ -		VectorSubtract (backEnd.or.viewOrigin, v, viewer); -		VectorNormalizeFast (viewer); - -		d = DotProduct (normal, viewer); - -		reflected[0] = normal[0]*2*d - viewer[0]; -		reflected[1] = normal[1]*2*d - viewer[1]; -		reflected[2] = normal[2]*2*d - viewer[2]; - -		st[0] = 0.5 + reflected[1] * 0.5; -		st[1] = 0.5 - reflected[2] * 0.5; -	} -} - -/* -** RB_CalcTurbulentTexCoords -*/ -void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st ) -{ -	int i; -	float now; - -	now = ( wf->phase + tess.shaderTime * wf->frequency ); - -	for ( i = 0; i < tess.numVertexes; i++, st += 2 ) -	{ -		float s = st[0]; -		float t = st[1]; - -		st[0] = s + tr.sinTable[ ( ( int ) ( ( ( tess.xyz[i][0] + tess.xyz[i][2] )* 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude; -		st[1] = t + tr.sinTable[ ( ( int ) ( ( tess.xyz[i][1] * 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude; -	} -} - -/* -** RB_CalcScaleTexCoords -*/ -void RB_CalcScaleTexCoords( const float scale[2], float *st ) -{ -	int i; - -	for ( i = 0; i < tess.numVertexes; i++, st += 2 ) -	{ -		st[0] *= scale[0]; -		st[1] *= scale[1]; -	} -} - -/* -** RB_CalcScrollTexCoords -*/ -void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st ) -{ -	int i; -	float timeScale = tess.shaderTime; -	float adjustedScrollS, adjustedScrollT; - -	adjustedScrollS = scrollSpeed[0] * timeScale; -	adjustedScrollT = scrollSpeed[1] * timeScale; - -	// clamp so coordinates don't continuously get larger, causing problems -	// with hardware limits -	adjustedScrollS = adjustedScrollS - floor( adjustedScrollS ); -	adjustedScrollT = adjustedScrollT - floor( adjustedScrollT ); - -	for ( i = 0; i < tess.numVertexes; i++, st += 2 ) -	{ -		st[0] += adjustedScrollS; -		st[1] += adjustedScrollT; -	} -} - -/* -** RB_CalcTransformTexCoords -*/ -void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *st  ) -{ -	int i; - -	for ( i = 0; i < tess.numVertexes; i++, st += 2 ) -	{ -		float s = st[0]; -		float t = st[1]; - -		st[0] = s * tmi->matrix[0][0] + t * tmi->matrix[1][0] + tmi->translate[0]; -		st[1] = s * tmi->matrix[0][1] + t * tmi->matrix[1][1] + tmi->translate[1]; -	} -} - -/* -** RB_CalcRotateTexCoords -*/ -void RB_CalcRotateTexCoords( float degsPerSecond, float *st ) -{ -	float timeScale = tess.shaderTime; -	float degs; -	int index; -	float sinValue, cosValue; -	texModInfo_t tmi; - -	degs = -degsPerSecond * timeScale; -	index = degs * ( FUNCTABLE_SIZE / 360.0f ); - -	sinValue = tr.sinTable[ index & FUNCTABLE_MASK ]; -	cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ]; - -	tmi.matrix[0][0] = cosValue; -	tmi.matrix[1][0] = -sinValue; -	tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue; - -	tmi.matrix[0][1] = sinValue; -	tmi.matrix[1][1] = cosValue; -	tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue; - -	RB_CalcTransformTexCoords( &tmi, st ); -} - - - - - - -#if id386 && !defined(__GNUC__) - -long myftol( float f ) { -	static int tmp; -	__asm fld f -	__asm fistp tmp -	__asm mov eax, tmp -} - -#endif - -/* -** RB_CalcSpecularAlpha -** -** Calculates specular coefficient and places it in the alpha channel -*/ -vec3_t lightOrigin = { -960, 1980, 96 };		// FIXME: track dynamically - -void RB_CalcSpecularAlpha( unsigned char *alphas ) { -	int			i; -	float		*v, *normal; -	vec3_t		viewer,  reflected; -	float		l, d; -	int			b; -	vec3_t		lightDir; -	int			numVertexes; - -	v = tess.xyz[0]; -	normal = tess.normal[0]; - -	alphas += 3; - -	numVertexes = tess.numVertexes; -	for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4, alphas += 4) { -		float ilength; - -		VectorSubtract( lightOrigin, v, lightDir ); -//		ilength = Q_rsqrt( DotProduct( lightDir, lightDir ) ); -		VectorNormalizeFast( lightDir ); - -		// calculate the specular color -		d = DotProduct (normal, lightDir); -//		d *= ilength; - -		// we don't optimize for the d < 0 case since this tends to -		// cause visual artifacts such as faceted "snapping" -		reflected[0] = normal[0]*2*d - lightDir[0]; -		reflected[1] = normal[1]*2*d - lightDir[1]; -		reflected[2] = normal[2]*2*d - lightDir[2]; - -		VectorSubtract (backEnd.or.viewOrigin, v, viewer); -		ilength = Q_rsqrt( DotProduct( viewer, viewer ) ); -		l = DotProduct (reflected, viewer); -		l *= ilength; - -		if (l < 0) { -			b = 0; -		} else { -			l = l*l; -			l = l*l; -			b = l * 255; -			if (b > 255) { -				b = 255; -			} -		} - -		*alphas = b; -	} -} - -/* -** RB_CalcDiffuseColor -** -** The basic vertex lighting calc -*/ -#if idppc_altivec -static void RB_CalcDiffuseColor_altivec( unsigned char *colors ) -{ -	int				i; -	float			*v, *normal; -	trRefEntity_t	*ent; -	int				ambientLightInt; -	vec3_t			lightDir; -	int				numVertexes; -	vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff, -                                               0x00, 0x00, 0x00, 0xff, -                                               0x00, 0x00, 0x00, 0xff, -                                               0x00, 0x00, 0x00, 0xff); -	vector float ambientLightVec; -	vector float directedLightVec; -	vector float lightDirVec; -	vector float normalVec0, normalVec1; -	vector float incomingVec0, incomingVec1, incomingVec2; -	vector float zero, jVec; -	vector signed int jVecInt; -	vector signed short jVecShort; -	vector unsigned char jVecChar, normalPerm; -	ent = backEnd.currentEntity; -	ambientLightInt = ent->ambientLightInt; -	// A lot of this could be simplified if we made sure -	// entities light info was 16-byte aligned. -	jVecChar = vec_lvsl(0, ent->ambientLight); -	ambientLightVec = vec_ld(0, (vector float *)ent->ambientLight); -	jVec = vec_ld(11, (vector float *)ent->ambientLight); -	ambientLightVec = vec_perm(ambientLightVec,jVec,jVecChar); - -	jVecChar = vec_lvsl(0, ent->directedLight); -	directedLightVec = vec_ld(0,(vector float *)ent->directedLight); -	jVec = vec_ld(11,(vector float *)ent->directedLight); -	directedLightVec = vec_perm(directedLightVec,jVec,jVecChar);	  - -	jVecChar = vec_lvsl(0, ent->lightDir); -	lightDirVec = vec_ld(0,(vector float *)ent->lightDir); -	jVec = vec_ld(11,(vector float *)ent->lightDir); -	lightDirVec = vec_perm(lightDirVec,jVec,jVecChar);	  - -	zero = (vector float)vec_splat_s8(0); -	VectorCopy( ent->lightDir, lightDir ); - -	v = tess.xyz[0]; -	normal = tess.normal[0]; - -	normalPerm = vec_lvsl(0,normal); -	numVertexes = tess.numVertexes; -	for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { -		normalVec0 = vec_ld(0,(vector float *)normal); -		normalVec1 = vec_ld(11,(vector float *)normal); -		normalVec0 = vec_perm(normalVec0,normalVec1,normalPerm); -		incomingVec0 = vec_madd(normalVec0, lightDirVec, zero); -		incomingVec1 = vec_sld(incomingVec0,incomingVec0,4); -		incomingVec2 = vec_add(incomingVec0,incomingVec1); -		incomingVec1 = vec_sld(incomingVec1,incomingVec1,4); -		incomingVec2 = vec_add(incomingVec2,incomingVec1); -		incomingVec0 = vec_splat(incomingVec2,0); -		incomingVec0 = vec_max(incomingVec0,zero); -		normalPerm = vec_lvsl(12,normal); -		jVec = vec_madd(incomingVec0, directedLightVec, ambientLightVec); -		jVecInt = vec_cts(jVec,0);	// RGBx -		jVecShort = vec_pack(jVecInt,jVecInt);		// RGBxRGBx -		jVecChar = vec_packsu(jVecShort,jVecShort);	// RGBxRGBxRGBxRGBx -		jVecChar = vec_sel(jVecChar,vSel,vSel);		// RGBARGBARGBARGBA replace alpha with 255 -		vec_ste((vector unsigned int)jVecChar,0,(unsigned int *)&colors[i*4]);	// store color -	} -} -#endif - -static void RB_CalcDiffuseColor_scalar( unsigned char *colors ) -{ -	int				i, j; -	float			*v, *normal; -	float			incoming; -	trRefEntity_t	*ent; -	int				ambientLightInt; -	vec3_t			ambientLight; -	vec3_t			lightDir; -	vec3_t			directedLight; -	int				numVertexes; -	ent = backEnd.currentEntity; -	ambientLightInt = ent->ambientLightInt; -	VectorCopy( ent->ambientLight, ambientLight ); -	VectorCopy( ent->directedLight, directedLight ); -	VectorCopy( ent->lightDir, lightDir ); - -	v = tess.xyz[0]; -	normal = tess.normal[0]; - -	numVertexes = tess.numVertexes; -	for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { -		incoming = DotProduct (normal, lightDir); -		if ( incoming <= 0 ) { -			*(int *)&colors[i*4] = ambientLightInt; -			continue; -		}  -		j = myftol( ambientLight[0] + incoming * directedLight[0] ); -		if ( j > 255 ) { -			j = 255; -		} -		colors[i*4+0] = j; - -		j = myftol( ambientLight[1] + incoming * directedLight[1] ); -		if ( j > 255 ) { -			j = 255; -		} -		colors[i*4+1] = j; - -		j = myftol( ambientLight[2] + incoming * directedLight[2] ); -		if ( j > 255 ) { -			j = 255; -		} -		colors[i*4+2] = j; - -		colors[i*4+3] = 255; -	} -} - -void RB_CalcDiffuseColor( unsigned char *colors ) -{ -#if idppc_altivec -	if (com_altivec->integer) { -		// must be in a seperate function or G3 systems will crash. -		RB_CalcDiffuseColor_altivec( colors ); -		return; -	} -#endif -	RB_CalcDiffuseColor_scalar( colors ); -} - diff --git a/ioq3-r437/src/renderer/tr_shader.c b/ioq3-r437/src/renderer/tr_shader.c deleted file mode 100644 index ddcbfca5..00000000 --- a/ioq3-r437/src/renderer/tr_shader.c +++ /dev/null @@ -1,3033 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -#include "tr_local.h" - -// tr_shader.c -- this file deals with the parsing and definition of shaders - -static char *s_shaderText; - -// the shader is parsed into these global variables, then copied into -// dynamically allocated memory if it is valid. -static	shaderStage_t	stages[MAX_SHADER_STAGES];		 -static	shader_t		shader; -static	texModInfo_t	texMods[MAX_SHADER_STAGES][TR_MAX_TEXMODS]; -static	qboolean		deferLoad; - -#define FILE_HASH_SIZE		1024 -static	shader_t*		hashTable[FILE_HASH_SIZE]; - -#define MAX_SHADERTEXT_HASH		2048 -static char **shaderTextHashTable[MAX_SHADERTEXT_HASH]; - -/* -================ -return a hash value for the filename -================ -*/ -#ifdef __GNUCC__ -  #warning TODO: check if long is ok here  -#endif -static long generateHashValue( const char *fname, const int size ) { -	int		i; -	long	hash; -	char	letter; - -	hash = 0; -	i = 0; -	while (fname[i] != '\0') { -		letter = tolower(fname[i]); -		if (letter =='.') break;				// don't include extension -		if (letter =='\\') letter = '/';		// damn path names -		if (letter == PATH_SEP) letter = '/';		// damn path names -		hash+=(long)(letter)*(i+119); -		i++; -	} -	hash = (hash ^ (hash >> 10) ^ (hash >> 20)); -	hash &= (size-1); -	return hash; -} - -void R_RemapShader(const char *shaderName, const char *newShaderName, const char *timeOffset) { -	char		strippedName[MAX_QPATH]; -	int			hash; -	shader_t	*sh, *sh2; -	qhandle_t	h; - -	sh = R_FindShaderByName( shaderName ); -	if (sh == NULL || sh == tr.defaultShader) { -		h = RE_RegisterShaderLightMap(shaderName, 0); -		sh = R_GetShaderByHandle(h); -	} -	if (sh == NULL || sh == tr.defaultShader) { -		ri.Printf( PRINT_WARNING, "WARNING: R_RemapShader: shader %s not found\n", shaderName ); -		return; -	} - -	sh2 = R_FindShaderByName( newShaderName ); -	if (sh2 == NULL || sh2 == tr.defaultShader) { -		h = RE_RegisterShaderLightMap(newShaderName, 0); -		sh2 = R_GetShaderByHandle(h); -	} - -	if (sh2 == NULL || sh2 == tr.defaultShader) { -		ri.Printf( PRINT_WARNING, "WARNING: R_RemapShader: new shader %s not found\n", newShaderName ); -		return; -	} - -	// remap all the shaders with the given name -	// even tho they might have different lightmaps -	COM_StripExtension( shaderName, strippedName ); -	hash = generateHashValue(strippedName, FILE_HASH_SIZE); -	for (sh = hashTable[hash]; sh; sh = sh->next) { -		if (Q_stricmp(sh->name, strippedName) == 0) { -			if (sh != sh2) { -				sh->remappedShader = sh2; -			} else { -				sh->remappedShader = NULL; -			} -		} -	} -	if (timeOffset) { -		sh2->timeOffset = atof(timeOffset); -	} -} - -/* -=============== -ParseVector -=============== -*/ -static qboolean ParseVector( char **text, int count, float *v ) { -	char	*token; -	int		i; - -	// FIXME: spaces are currently required after parens, should change parseext... -	token = COM_ParseExt( text, qfalse ); -	if ( strcmp( token, "(" ) ) { -		ri.Printf( PRINT_WARNING, "WARNING: missing parenthesis in shader '%s'\n", shader.name ); -		return qfalse; -	} - -	for ( i = 0 ; i < count ; i++ ) { -		token = COM_ParseExt( text, qfalse ); -		if ( !token[0] ) { -			ri.Printf( PRINT_WARNING, "WARNING: missing vector element in shader '%s'\n", shader.name ); -			return qfalse; -		} -		v[i] = atof( token ); -	} - -	token = COM_ParseExt( text, qfalse ); -	if ( strcmp( token, ")" ) ) { -		ri.Printf( PRINT_WARNING, "WARNING: missing parenthesis in shader '%s'\n", shader.name ); -		return qfalse; -	} - -	return qtrue; -} - - -/* -=============== -NameToAFunc -=============== -*/ -static unsigned NameToAFunc( const char *funcname ) -{	 -	if ( !Q_stricmp( funcname, "GT0" ) ) -	{ -		return GLS_ATEST_GT_0; -	} -	else if ( !Q_stricmp( funcname, "LT128" ) ) -	{ -		return GLS_ATEST_LT_80; -	} -	else if ( !Q_stricmp( funcname, "GE128" ) ) -	{ -		return GLS_ATEST_GE_80; -	} - -	ri.Printf( PRINT_WARNING, "WARNING: invalid alphaFunc name '%s' in shader '%s'\n", funcname, shader.name ); -	return 0; -} - - -/* -=============== -NameToSrcBlendMode -=============== -*/ -static int NameToSrcBlendMode( const char *name ) -{ -	if ( !Q_stricmp( name, "GL_ONE" ) ) -	{ -		return GLS_SRCBLEND_ONE; -	} -	else if ( !Q_stricmp( name, "GL_ZERO" ) ) -	{ -		return GLS_SRCBLEND_ZERO; -	} -	else if ( !Q_stricmp( name, "GL_DST_COLOR" ) ) -	{ -		return GLS_SRCBLEND_DST_COLOR; -	} -	else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_COLOR" ) ) -	{ -		return GLS_SRCBLEND_ONE_MINUS_DST_COLOR; -	} -	else if ( !Q_stricmp( name, "GL_SRC_ALPHA" ) ) -	{ -		return GLS_SRCBLEND_SRC_ALPHA; -	} -	else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_ALPHA" ) ) -	{ -		return GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA; -	} -	else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) ) -	{ -		return GLS_SRCBLEND_DST_ALPHA; -	} -	else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) ) -	{ -		return GLS_SRCBLEND_ONE_MINUS_DST_ALPHA; -	} -	else if ( !Q_stricmp( name, "GL_SRC_ALPHA_SATURATE" ) ) -	{ -		return GLS_SRCBLEND_ALPHA_SATURATE; -	} - -	ri.Printf( PRINT_WARNING, "WARNING: unknown blend mode '%s' in shader '%s', substituting GL_ONE\n", name, shader.name ); -	return GLS_SRCBLEND_ONE; -} - -/* -=============== -NameToDstBlendMode -=============== -*/ -static int NameToDstBlendMode( const char *name ) -{ -	if ( !Q_stricmp( name, "GL_ONE" ) ) -	{ -		return GLS_DSTBLEND_ONE; -	} -	else if ( !Q_stricmp( name, "GL_ZERO" ) ) -	{ -		return GLS_DSTBLEND_ZERO; -	} -	else if ( !Q_stricmp( name, "GL_SRC_ALPHA" ) ) -	{ -		return GLS_DSTBLEND_SRC_ALPHA; -	} -	else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_ALPHA" ) ) -	{ -		return GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; -	} -	else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) ) -	{ -		return GLS_DSTBLEND_DST_ALPHA; -	} -	else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) ) -	{ -		return GLS_DSTBLEND_ONE_MINUS_DST_ALPHA; -	} -	else if ( !Q_stricmp( name, "GL_SRC_COLOR" ) ) -	{ -		return GLS_DSTBLEND_SRC_COLOR; -	} -	else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_COLOR" ) ) -	{ -		return GLS_DSTBLEND_ONE_MINUS_SRC_COLOR; -	} - -	ri.Printf( PRINT_WARNING, "WARNING: unknown blend mode '%s' in shader '%s', substituting GL_ONE\n", name, shader.name ); -	return GLS_DSTBLEND_ONE; -} - -/* -=============== -NameToGenFunc -=============== -*/ -static genFunc_t NameToGenFunc( const char *funcname ) -{ -	if ( !Q_stricmp( funcname, "sin" ) ) -	{ -		return GF_SIN; -	} -	else if ( !Q_stricmp( funcname, "square" ) ) -	{ -		return GF_SQUARE; -	} -	else if ( !Q_stricmp( funcname, "triangle" ) ) -	{ -		return GF_TRIANGLE; -	} -	else if ( !Q_stricmp( funcname, "sawtooth" ) ) -	{ -		return GF_SAWTOOTH; -	} -	else if ( !Q_stricmp( funcname, "inversesawtooth" ) ) -	{ -		return GF_INVERSE_SAWTOOTH; -	} -	else if ( !Q_stricmp( funcname, "noise" ) ) -	{ -		return GF_NOISE; -	} - -	ri.Printf( PRINT_WARNING, "WARNING: invalid genfunc name '%s' in shader '%s'\n", funcname, shader.name ); -	return GF_SIN; -} - - -/* -=================== -ParseWaveForm -=================== -*/ -static void ParseWaveForm( char **text, waveForm_t *wave ) -{ -	char *token; - -	token = COM_ParseExt( text, qfalse ); -	if ( token[0] == 0 ) -	{ -		ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name ); -		return; -	} -	wave->func = NameToGenFunc( token ); - -	// BASE, AMP, PHASE, FREQ -	token = COM_ParseExt( text, qfalse ); -	if ( token[0] == 0 ) -	{ -		ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name ); -		return; -	} -	wave->base = atof( token ); - -	token = COM_ParseExt( text, qfalse ); -	if ( token[0] == 0 ) -	{ -		ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name ); -		return; -	} -	wave->amplitude = atof( token ); - -	token = COM_ParseExt( text, qfalse ); -	if ( token[0] == 0 ) -	{ -		ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name ); -		return; -	} -	wave->phase = atof( token ); - -	token = COM_ParseExt( text, qfalse ); -	if ( token[0] == 0 ) -	{ -		ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name ); -		return; -	} -	wave->frequency = atof( token ); -} - - -/* -=================== -ParseTexMod -=================== -*/ -static void ParseTexMod( char *_text, shaderStage_t *stage ) -{ -	const char *token; -	char **text = &_text; -	texModInfo_t *tmi; - -	if ( stage->bundle[0].numTexMods == TR_MAX_TEXMODS ) { -		ri.Error( ERR_DROP, "ERROR: too many tcMod stages in shader '%s'\n", shader.name ); -		return; -	} - -	tmi = &stage->bundle[0].texMods[stage->bundle[0].numTexMods]; -	stage->bundle[0].numTexMods++; - -	token = COM_ParseExt( text, qfalse ); - -	// -	// turb -	// -	if ( !Q_stricmp( token, "turb" ) ) -	{ -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->wave.base = atof( token ); -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name ); -			return; -		} -		tmi->wave.amplitude = atof( token ); -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name ); -			return; -		} -		tmi->wave.phase = atof( token ); -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name ); -			return; -		} -		tmi->wave.frequency = atof( token ); - -		tmi->type = TMOD_TURBULENT; -	} -	// -	// scale -	// -	else if ( !Q_stricmp( token, "scale" ) ) -	{ -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing scale parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->scale[0] = atof( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing scale parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->scale[1] = atof( token ); -		tmi->type = TMOD_SCALE; -	} -	// -	// scroll -	// -	else if ( !Q_stricmp( token, "scroll" ) ) -	{ -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing scale scroll parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->scroll[0] = atof( token ); -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing scale scroll parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->scroll[1] = atof( token ); -		tmi->type = TMOD_SCROLL; -	} -	// -	// stretch -	// -	else if ( !Q_stricmp( token, "stretch" ) ) -	{ -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->wave.func = NameToGenFunc( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->wave.base = atof( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->wave.amplitude = atof( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->wave.phase = atof( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->wave.frequency = atof( token ); -		 -		tmi->type = TMOD_STRETCH; -	} -	// -	// transform -	// -	else if ( !Q_stricmp( token, "transform" ) ) -	{ -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->matrix[0][0] = atof( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->matrix[0][1] = atof( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->matrix[1][0] = atof( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->matrix[1][1] = atof( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->translate[0] = atof( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->translate[1] = atof( token ); - -		tmi->type = TMOD_TRANSFORM; -	} -	// -	// rotate -	// -	else if ( !Q_stricmp( token, "rotate" ) ) -	{ -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing tcMod rotate parms in shader '%s'\n", shader.name ); -			return; -		} -		tmi->rotateSpeed = atof( token ); -		tmi->type = TMOD_ROTATE; -	} -	// -	// entityTranslate -	// -	else if ( !Q_stricmp( token, "entityTranslate" ) ) -	{ -		tmi->type = TMOD_ENTITY_TRANSLATE; -	} -	else -	{ -		ri.Printf( PRINT_WARNING, "WARNING: unknown tcMod '%s' in shader '%s'\n", token, shader.name ); -	} -} - - -/* -=================== -ParseStage -=================== -*/ -static qboolean ParseStage( shaderStage_t *stage, char **text ) -{ -	char *token; -	int depthMaskBits = GLS_DEPTHMASK_TRUE, blendSrcBits = 0, blendDstBits = 0, atestBits = 0, depthFuncBits = 0; -	qboolean depthMaskExplicit = qfalse; - -	stage->active = qtrue; - -	while ( 1 ) -	{ -		token = COM_ParseExt( text, qtrue ); -		if ( !token[0] ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: no matching '}' found\n" ); -			return qfalse; -		} - -		if ( token[0] == '}' ) -		{ -			break; -		} -		// -		// map <name> -		// -		else if ( !Q_stricmp( token, "map" ) ) -		{ -			token = COM_ParseExt( text, qfalse ); -			if ( !token[0] ) -			{ -				ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'map' keyword in shader '%s'\n", shader.name ); -				return qfalse; -			} - -			if ( !Q_stricmp( token, "$whiteimage" ) ) -			{ -				stage->bundle[0].image[0] = tr.whiteImage; -				continue; -			} -			else if ( !Q_stricmp( token, "$lightmap" ) ) -			{ -				stage->bundle[0].isLightmap = qtrue; -				if ( shader.lightmapIndex < 0 ) { -					stage->bundle[0].image[0] = tr.whiteImage; -				} else { -					stage->bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex]; -				} -				continue; -			} -			else -			{ -				stage->bundle[0].image[0] = R_FindImageFile( token, !shader.noMipMaps, !shader.noPicMip, GL_REPEAT ); -				if ( !stage->bundle[0].image[0] ) -				{ -					ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); -					return qfalse; -				} -			} -		} -		// -		// clampmap <name> -		// -		else if ( !Q_stricmp( token, "clampmap" ) ) -		{ -			token = COM_ParseExt( text, qfalse ); -			if ( !token[0] ) -			{ -				ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'clampmap' keyword in shader '%s'\n", shader.name ); -				return qfalse; -			} - -			stage->bundle[0].image[0] = R_FindImageFile( token, !shader.noMipMaps, !shader.noPicMip, GL_CLAMP ); -			if ( !stage->bundle[0].image[0] ) -			{ -				ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); -				return qfalse; -			} -		} -		// -		// animMap <frequency> <image1> .... <imageN> -		// -		else if ( !Q_stricmp( token, "animMap" ) ) -		{ -			token = COM_ParseExt( text, qfalse ); -			if ( !token[0] ) -			{ -				ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'animMmap' keyword in shader '%s'\n", shader.name ); -				return qfalse; -			} -			stage->bundle[0].imageAnimationSpeed = atof( token ); - -			// parse up to MAX_IMAGE_ANIMATIONS animations -			while ( 1 ) { -				int		num; - -				token = COM_ParseExt( text, qfalse ); -				if ( !token[0] ) { -					break; -				} -				num = stage->bundle[0].numImageAnimations; -				if ( num < MAX_IMAGE_ANIMATIONS ) { -					stage->bundle[0].image[num] = R_FindImageFile( token, !shader.noMipMaps, !shader.noPicMip, GL_REPEAT ); -					if ( !stage->bundle[0].image[num] ) -					{ -						ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); -						return qfalse; -					} -					stage->bundle[0].numImageAnimations++; -				} -			} -		} -		else if ( !Q_stricmp( token, "videoMap" ) ) -		{ -			token = COM_ParseExt( text, qfalse ); -			if ( !token[0] ) -			{ -				ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'videoMmap' keyword in shader '%s'\n", shader.name ); -				return qfalse; -			} -			stage->bundle[0].videoMapHandle = ri.CIN_PlayCinematic( token, 0, 0, 256, 256, (CIN_loop | CIN_silent | CIN_shader)); -			if (stage->bundle[0].videoMapHandle != -1) { -				stage->bundle[0].isVideoMap = qtrue; -				stage->bundle[0].image[0] = tr.scratchImage[stage->bundle[0].videoMapHandle]; -			} -		} -		// -		// alphafunc <func> -		// -		else if ( !Q_stricmp( token, "alphaFunc" ) ) -		{ -			token = COM_ParseExt( text, qfalse ); -			if ( !token[0] ) -			{ -				ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'alphaFunc' keyword in shader '%s'\n", shader.name ); -				return qfalse; -			} - -			atestBits = NameToAFunc( token ); -		} -		// -		// depthFunc <func> -		// -		else if ( !Q_stricmp( token, "depthfunc" ) ) -		{ -			token = COM_ParseExt( text, qfalse ); - -			if ( !token[0] ) -			{ -				ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'depthfunc' keyword in shader '%s'\n", shader.name ); -				return qfalse; -			} - -			if ( !Q_stricmp( token, "lequal" ) ) -			{ -				depthFuncBits = 0; -			} -			else if ( !Q_stricmp( token, "equal" ) ) -			{ -				depthFuncBits = GLS_DEPTHFUNC_EQUAL; -			} -			else -			{ -				ri.Printf( PRINT_WARNING, "WARNING: unknown depthfunc '%s' in shader '%s'\n", token, shader.name ); -				continue; -			} -		} -		// -		// detail -		// -		else if ( !Q_stricmp( token, "detail" ) ) -		{ -			stage->isDetail = qtrue; -		} -		// -		// blendfunc <srcFactor> <dstFactor> -		// or blendfunc <add|filter|blend> -		// -		else if ( !Q_stricmp( token, "blendfunc" ) ) -		{ -			token = COM_ParseExt( text, qfalse ); -			if ( token[0] == 0 ) -			{ -				ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name ); -				continue; -			} -			// check for "simple" blends first -			if ( !Q_stricmp( token, "add" ) ) { -				blendSrcBits = GLS_SRCBLEND_ONE; -				blendDstBits = GLS_DSTBLEND_ONE; -			} else if ( !Q_stricmp( token, "filter" ) ) { -				blendSrcBits = GLS_SRCBLEND_DST_COLOR; -				blendDstBits = GLS_DSTBLEND_ZERO; -			} else if ( !Q_stricmp( token, "blend" ) ) { -				blendSrcBits = GLS_SRCBLEND_SRC_ALPHA; -				blendDstBits = GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; -			} else { -				// complex double blends -				blendSrcBits = NameToSrcBlendMode( token ); - -				token = COM_ParseExt( text, qfalse ); -				if ( token[0] == 0 ) -				{ -					ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name ); -					continue; -				} -				blendDstBits = NameToDstBlendMode( token ); -			} - -			// clear depth mask for blended surfaces -			if ( !depthMaskExplicit ) -			{ -				depthMaskBits = 0; -			} -		} -		// -		// rgbGen -		// -		else if ( !Q_stricmp( token, "rgbGen" ) ) -		{ -			token = COM_ParseExt( text, qfalse ); -			if ( token[0] == 0 ) -			{ -				ri.Printf( PRINT_WARNING, "WARNING: missing parameters for rgbGen in shader '%s'\n", shader.name ); -				continue; -			} - -			if ( !Q_stricmp( token, "wave" ) ) -			{ -				ParseWaveForm( text, &stage->rgbWave ); -				stage->rgbGen = CGEN_WAVEFORM; -			} -			else if ( !Q_stricmp( token, "const" ) ) -			{ -				vec3_t	color; - -				ParseVector( text, 3, color ); -				stage->constantColor[0] = 255 * color[0]; -				stage->constantColor[1] = 255 * color[1]; -				stage->constantColor[2] = 255 * color[2]; - -				stage->rgbGen = CGEN_CONST; -			} -			else if ( !Q_stricmp( token, "identity" ) ) -			{ -				stage->rgbGen = CGEN_IDENTITY; -			} -			else if ( !Q_stricmp( token, "identityLighting" ) ) -			{ -				stage->rgbGen = CGEN_IDENTITY_LIGHTING; -			} -			else if ( !Q_stricmp( token, "entity" ) ) -			{ -				stage->rgbGen = CGEN_ENTITY; -			} -			else if ( !Q_stricmp( token, "oneMinusEntity" ) ) -			{ -				stage->rgbGen = CGEN_ONE_MINUS_ENTITY; -			} -			else if ( !Q_stricmp( token, "vertex" ) ) -			{ -				stage->rgbGen = CGEN_VERTEX; -				if ( stage->alphaGen == 0 ) { -					stage->alphaGen = AGEN_VERTEX; -				} -			} -			else if ( !Q_stricmp( token, "exactVertex" ) ) -			{ -				stage->rgbGen = CGEN_EXACT_VERTEX; -			} -			else if ( !Q_stricmp( token, "lightingDiffuse" ) ) -			{ -				stage->rgbGen = CGEN_LIGHTING_DIFFUSE; -			} -			else if ( !Q_stricmp( token, "oneMinusVertex" ) ) -			{ -				stage->rgbGen = CGEN_ONE_MINUS_VERTEX; -			} -			else -			{ -				ri.Printf( PRINT_WARNING, "WARNING: unknown rgbGen parameter '%s' in shader '%s'\n", token, shader.name ); -				continue; -			} -		} -		// -		// alphaGen  -		// -		else if ( !Q_stricmp( token, "alphaGen" ) ) -		{ -			token = COM_ParseExt( text, qfalse ); -			if ( token[0] == 0 ) -			{ -				ri.Printf( PRINT_WARNING, "WARNING: missing parameters for alphaGen in shader '%s'\n", shader.name ); -				continue; -			} - -			if ( !Q_stricmp( token, "wave" ) ) -			{ -				ParseWaveForm( text, &stage->alphaWave ); -				stage->alphaGen = AGEN_WAVEFORM; -			} -			else if ( !Q_stricmp( token, "const" ) ) -			{ -				token = COM_ParseExt( text, qfalse ); -				stage->constantColor[3] = 255 * atof( token ); -				stage->alphaGen = AGEN_CONST; -			} -			else if ( !Q_stricmp( token, "identity" ) ) -			{ -				stage->alphaGen = AGEN_IDENTITY; -			} -			else if ( !Q_stricmp( token, "entity" ) ) -			{ -				stage->alphaGen = AGEN_ENTITY; -			} -			else if ( !Q_stricmp( token, "oneMinusEntity" ) ) -			{ -				stage->alphaGen = AGEN_ONE_MINUS_ENTITY; -			} -			else if ( !Q_stricmp( token, "vertex" ) ) -			{ -				stage->alphaGen = AGEN_VERTEX; -			} -			else if ( !Q_stricmp( token, "lightingSpecular" ) ) -			{ -				stage->alphaGen = AGEN_LIGHTING_SPECULAR; -			} -			else if ( !Q_stricmp( token, "oneMinusVertex" ) ) -			{ -				stage->alphaGen = AGEN_ONE_MINUS_VERTEX; -			} -			else if ( !Q_stricmp( token, "portal" ) ) -			{ -				stage->alphaGen = AGEN_PORTAL; -				token = COM_ParseExt( text, qfalse ); -				if ( token[0] == 0 ) -				{ -					shader.portalRange = 256; -					ri.Printf( PRINT_WARNING, "WARNING: missing range parameter for alphaGen portal in shader '%s', defaulting to 256\n", shader.name ); -				} -				else -				{ -					shader.portalRange = atof( token ); -				} -			} -			else -			{ -				ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name ); -				continue; -			} -		} -		// -		// tcGen <function> -		// -		else if ( !Q_stricmp(token, "texgen") || !Q_stricmp( token, "tcGen" ) )  -		{ -			token = COM_ParseExt( text, qfalse ); -			if ( token[0] == 0 ) -			{ -				ri.Printf( PRINT_WARNING, "WARNING: missing texgen parm in shader '%s'\n", shader.name ); -				continue; -			} - -			if ( !Q_stricmp( token, "environment" ) ) -			{ -				stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED; -			} -			else if ( !Q_stricmp( token, "lightmap" ) ) -			{ -				stage->bundle[0].tcGen = TCGEN_LIGHTMAP; -			} -			else if ( !Q_stricmp( token, "texture" ) || !Q_stricmp( token, "base" ) ) -			{ -				stage->bundle[0].tcGen = TCGEN_TEXTURE; -			} -			else if ( !Q_stricmp( token, "vector" ) ) -			{ -				ParseVector( text, 3, stage->bundle[0].tcGenVectors[0] ); -				ParseVector( text, 3, stage->bundle[0].tcGenVectors[1] ); - -				stage->bundle[0].tcGen = TCGEN_VECTOR; -			} -			else  -			{ -				ri.Printf( PRINT_WARNING, "WARNING: unknown texgen parm in shader '%s'\n", shader.name ); -			} -		} -		// -		// tcMod <type> <...> -		// -		else if ( !Q_stricmp( token, "tcMod" ) ) -		{ -			char buffer[1024] = ""; - -			while ( 1 ) -			{ -				token = COM_ParseExt( text, qfalse ); -				if ( token[0] == 0 ) -					break; -				strcat( buffer, token ); -				strcat( buffer, " " ); -			} - -			ParseTexMod( buffer, stage ); - -			continue; -		} -		// -		// depthmask -		// -		else if ( !Q_stricmp( token, "depthwrite" ) ) -		{ -			depthMaskBits = GLS_DEPTHMASK_TRUE; -			depthMaskExplicit = qtrue; - -			continue; -		} -		else -		{ -			ri.Printf( PRINT_WARNING, "WARNING: unknown parameter '%s' in shader '%s'\n", token, shader.name ); -			return qfalse; -		} -	} - -	// -	// if cgen isn't explicitly specified, use either identity or identitylighting -	// -	if ( stage->rgbGen == CGEN_BAD ) { -		if ( blendSrcBits == 0 || -			blendSrcBits == GLS_SRCBLEND_ONE ||  -			blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) { -			stage->rgbGen = CGEN_IDENTITY_LIGHTING; -		} else { -			stage->rgbGen = CGEN_IDENTITY; -		} -	} - - -	// -	// implicitly assume that a GL_ONE GL_ZERO blend mask disables blending -	// -	if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) &&  -		 ( blendDstBits == GLS_DSTBLEND_ZERO ) ) -	{ -		blendDstBits = blendSrcBits = 0; -		depthMaskBits = GLS_DEPTHMASK_TRUE; -	} - -	// decide which agens we can skip -	if ( stage->alphaGen == CGEN_IDENTITY ) { -		if ( stage->rgbGen == CGEN_IDENTITY -			|| stage->rgbGen == CGEN_LIGHTING_DIFFUSE ) { -			stage->alphaGen = AGEN_SKIP; -		} -	} - -	// -	// compute state bits -	// -	stage->stateBits = depthMaskBits |  -		               blendSrcBits | blendDstBits |  -					   atestBits |  -					   depthFuncBits; - -	return qtrue; -} - -/* -=============== -ParseDeform - -deformVertexes wave <spread> <waveform> <base> <amplitude> <phase> <frequency> -deformVertexes normal <frequency> <amplitude> -deformVertexes move <vector> <waveform> <base> <amplitude> <phase> <frequency> -deformVertexes bulge <bulgeWidth> <bulgeHeight> <bulgeSpeed> -deformVertexes projectionShadow -deformVertexes autoSprite -deformVertexes autoSprite2 -deformVertexes text[0-7] -=============== -*/ -static void ParseDeform( char **text ) { -	char	*token; -	deformStage_t	*ds; - -	token = COM_ParseExt( text, qfalse ); -	if ( token[0] == 0 ) -	{ -		ri.Printf( PRINT_WARNING, "WARNING: missing deform parm in shader '%s'\n", shader.name ); -		return; -	} - -	if ( shader.numDeforms == MAX_SHADER_DEFORMS ) { -		ri.Printf( PRINT_WARNING, "WARNING: MAX_SHADER_DEFORMS in '%s'\n", shader.name ); -		return; -	} - -	ds = &shader.deforms[ shader.numDeforms ]; -	shader.numDeforms++; - -	if ( !Q_stricmp( token, "projectionShadow" ) ) { -		ds->deformation = DEFORM_PROJECTION_SHADOW; -		return; -	} - -	if ( !Q_stricmp( token, "autosprite" ) ) { -		ds->deformation = DEFORM_AUTOSPRITE; -		return; -	} - -	if ( !Q_stricmp( token, "autosprite2" ) ) { -		ds->deformation = DEFORM_AUTOSPRITE2; -		return; -	} - -	if ( !Q_stricmpn( token, "text", 4 ) ) { -		int		n; -		 -		n = token[4] - '0'; -		if ( n < 0 || n > 7 ) { -			n = 0; -		} -		ds->deformation = DEFORM_TEXT0 + n; -		return; -	} - -	if ( !Q_stricmp( token, "bulge" ) )	{ -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name ); -			return; -		} -		ds->bulgeWidth = atof( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name ); -			return; -		} -		ds->bulgeHeight = atof( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name ); -			return; -		} -		ds->bulgeSpeed = atof( token ); - -		ds->deformation = DEFORM_BULGE; -		return; -	} - -	if ( !Q_stricmp( token, "wave" ) ) -	{ -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name ); -			return; -		} - -		if ( atof( token ) != 0 ) -		{ -			ds->deformationSpread = 1.0f / atof( token ); -		} -		else -		{ -			ds->deformationSpread = 100.0f; -			ri.Printf( PRINT_WARNING, "WARNING: illegal div value of 0 in deformVertexes command for shader '%s'\n", shader.name ); -		} - -		ParseWaveForm( text, &ds->deformationWave ); -		ds->deformation = DEFORM_WAVE; -		return; -	} - -	if ( !Q_stricmp( token, "normal" ) ) -	{ -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name ); -			return; -		} -		ds->deformationWave.amplitude = atof( token ); - -		token = COM_ParseExt( text, qfalse ); -		if ( token[0] == 0 ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name ); -			return; -		} -		ds->deformationWave.frequency = atof( token ); - -		ds->deformation = DEFORM_NORMALS; -		return; -	} - -	if ( !Q_stricmp( token, "move" ) ) { -		int		i; - -		for ( i = 0 ; i < 3 ; i++ ) { -			token = COM_ParseExt( text, qfalse ); -			if ( token[0] == 0 ) { -				ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name ); -				return; -			} -			ds->moveVector[i] = atof( token ); -		} - -		ParseWaveForm( text, &ds->deformationWave ); -		ds->deformation = DEFORM_MOVE; -		return; -	} - -	ri.Printf( PRINT_WARNING, "WARNING: unknown deformVertexes subtype '%s' found in shader '%s'\n", token, shader.name ); -} - - -/* -=============== -ParseSkyParms - -skyParms <outerbox> <cloudheight> <innerbox> -=============== -*/ -static void ParseSkyParms( char **text ) { -	char		*token; -	static char	*suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; -	char		pathname[MAX_QPATH]; -	int			i; - -	// outerbox -	token = COM_ParseExt( text, qfalse ); -	if ( token[0] == 0 ) { -		ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name ); -		return; -	} -	if ( strcmp( token, "-" ) ) { -		for (i=0 ; i<6 ; i++) { -			Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga" -				, token, suf[i] ); -#ifdef GL_CLAMP_TO_EDGE -			shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, qtrue, qtrue, GL_CLAMP_TO_EDGE ); -#else -			shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, qtrue, qtrue, GL_CLAMP ); -#endif -			if ( !shader.sky.outerbox[i] ) { -				shader.sky.outerbox[i] = tr.defaultImage; -			} -		} -	} - -	// cloudheight -	token = COM_ParseExt( text, qfalse ); -	if ( token[0] == 0 ) { -		ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name ); -		return; -	} -	shader.sky.cloudHeight = atof( token ); -	if ( !shader.sky.cloudHeight ) { -		shader.sky.cloudHeight = 512; -	} -	R_InitSkyTexCoords( shader.sky.cloudHeight ); - - -	// innerbox -	token = COM_ParseExt( text, qfalse ); -	if ( token[0] == 0 ) { -		ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name ); -		return; -	} -	if ( strcmp( token, "-" ) ) { -		for (i=0 ; i<6 ; i++) { -			Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga" -				, token, suf[i] ); -			shader.sky.innerbox[i] = R_FindImageFile( ( char * ) pathname, qtrue, qtrue, GL_REPEAT ); -			if ( !shader.sky.innerbox[i] ) { -				shader.sky.innerbox[i] = tr.defaultImage; -			} -		} -	} - -	shader.isSky = qtrue; -} - - -/* -================= -ParseSort -================= -*/ -void ParseSort( char **text ) { -	char	*token; - -	token = COM_ParseExt( text, qfalse ); -	if ( token[0] == 0 ) { -		ri.Printf( PRINT_WARNING, "WARNING: missing sort parameter in shader '%s'\n", shader.name ); -		return; -	} - -	if ( !Q_stricmp( token, "portal" ) ) { -		shader.sort = SS_PORTAL; -	} else if ( !Q_stricmp( token, "sky" ) ) { -		shader.sort = SS_ENVIRONMENT; -	} else if ( !Q_stricmp( token, "opaque" ) ) { -		shader.sort = SS_OPAQUE; -	}else if ( !Q_stricmp( token, "decal" ) ) { -		shader.sort = SS_DECAL; -	} else if ( !Q_stricmp( token, "seeThrough" ) ) { -		shader.sort = SS_SEE_THROUGH; -	} else if ( !Q_stricmp( token, "banner" ) ) { -		shader.sort = SS_BANNER; -	} else if ( !Q_stricmp( token, "additive" ) ) { -		shader.sort = SS_BLEND1; -	} else if ( !Q_stricmp( token, "nearest" ) ) { -		shader.sort = SS_NEAREST; -	} else if ( !Q_stricmp( token, "underwater" ) ) { -		shader.sort = SS_UNDERWATER; -	} else { -		shader.sort = atof( token ); -	} -} - - - -// this table is also present in q3map - -typedef struct { -	char	*name; -	int		clearSolid, surfaceFlags, contents; -} infoParm_t; - -infoParm_t	infoParms[] = { -	// server relevant contents -	{"water",		1,	0,	CONTENTS_WATER }, -	{"slime",		1,	0,	CONTENTS_SLIME },		// mildly damaging -	{"lava",		1,	0,	CONTENTS_LAVA },		// very damaging -	{"playerclip",	1,	0,	CONTENTS_PLAYERCLIP }, -	{"monsterclip",	1,	0,	CONTENTS_MONSTERCLIP }, -	{"nodrop",		1,	0,	CONTENTS_NODROP },		// don't drop items or leave bodies (death fog, lava, etc) -	{"nonsolid",	1,	SURF_NONSOLID,	0},						// clears the solid flag - -	// utility relevant attributes -	{"origin",		1,	0,	CONTENTS_ORIGIN },		// center of rotating brushes -	{"trans",		0,	0,	CONTENTS_TRANSLUCENT },	// don't eat contained surfaces -	{"detail",		0,	0,	CONTENTS_DETAIL },		// don't include in structural bsp -	{"structural",	0,	0,	CONTENTS_STRUCTURAL },	// force into structural bsp even if trnas -	{"areaportal",	1,	0,	CONTENTS_AREAPORTAL },	// divides areas -	{"clusterportal", 1,0,  CONTENTS_CLUSTERPORTAL },	// for bots -	{"donotenter",  1,  0,  CONTENTS_DONOTENTER },		// for bots - -	{"fog",			1,	0,	CONTENTS_FOG},			// carves surfaces entering -	{"sky",			0,	SURF_SKY,		0 },		// emit light from an environment map -	{"lightfilter",	0,	SURF_LIGHTFILTER, 0 },		// filter light going through it -	{"alphashadow",	0,	SURF_ALPHASHADOW, 0 },		// test light on a per-pixel basis -	{"hint",		0,	SURF_HINT,		0 },		// use as a primary splitter - -	// server attributes -	{"slick",		0,	SURF_SLICK,		0 }, -	{"noimpact",	0,	SURF_NOIMPACT,	0 },		// don't make impact explosions or marks -	{"nomarks",		0,	SURF_NOMARKS,	0 },		// don't make impact marks, but still explode -	{"ladder",		0,	SURF_LADDER,	0 }, -	{"nodamage",	0,	SURF_NODAMAGE,	0 }, -	{"metalsteps",	0,	SURF_METALSTEPS,0 }, -	{"flesh",		0,	SURF_FLESH,		0 }, -	{"nosteps",		0,	SURF_NOSTEPS,	0 }, - -	// drawsurf attributes -	{"nodraw",		0,	SURF_NODRAW,	0 },	// don't generate a drawsurface (or a lightmap) -	{"pointlight",	0,	SURF_POINTLIGHT, 0 },	// sample lighting at vertexes -	{"nolightmap",	0,	SURF_NOLIGHTMAP,0 },	// don't generate a lightmap -	{"nodlight",	0,	SURF_NODLIGHT, 0 },		// don't ever add dynamic lights -	{"dust",		0,	SURF_DUST, 0}			// leave a dust trail when walking on this surface -}; - - -/* -=============== -ParseSurfaceParm - -surfaceparm <name> -=============== -*/ -static void ParseSurfaceParm( char **text ) { -	char	*token; -	int		numInfoParms = sizeof(infoParms) / sizeof(infoParms[0]); -	int		i; - -	token = COM_ParseExt( text, qfalse ); -	for ( i = 0 ; i < numInfoParms ; i++ ) { -		if ( !Q_stricmp( token, infoParms[i].name ) ) { -			shader.surfaceFlags |= infoParms[i].surfaceFlags; -			shader.contentFlags |= infoParms[i].contents; -#if 0 -			if ( infoParms[i].clearSolid ) { -				si->contents &= ~CONTENTS_SOLID; -			} -#endif -			break; -		} -	} -} - -/* -================= -ParseShader - -The current text pointer is at the explicit text definition of the -shader.  Parse it into the global shader variable.  Later functions -will optimize it. -================= -*/ -static qboolean ParseShader( char **text ) -{ -	char *token; -	int s; - -	s = 0; - -	token = COM_ParseExt( text, qtrue ); -	if ( token[0] != '{' ) -	{ -		ri.Printf( PRINT_WARNING, "WARNING: expecting '{', found '%s' instead in shader '%s'\n", token, shader.name ); -		return qfalse; -	} - -	while ( 1 ) -	{ -		token = COM_ParseExt( text, qtrue ); -		if ( !token[0] ) -		{ -			ri.Printf( PRINT_WARNING, "WARNING: no concluding '}' in shader %s\n", shader.name ); -			return qfalse; -		} - -		// end of shader definition -		if ( token[0] == '}' ) -		{ -			break; -		} -		// stage definition -		else if ( token[0] == '{' ) -		{ -			// 20051019 misantropia -- fix buffer overrun. -			if ( s >= MAX_SHADER_STAGES ) { -				ri.Printf( PRINT_WARNING, "WARNING: too many stages in shader %s\n", shader.name ); -				return qfalse; -			} - -			if ( !ParseStage( &stages[s], text ) ) -			{ -				return qfalse; -			} -			stages[s].active = qtrue; -			s++; - -			continue; -		} -		// skip stuff that only the QuakeEdRadient needs -		else if ( !Q_stricmpn( token, "qer", 3 ) ) { -			SkipRestOfLine( text ); -			continue; -		} -		// sun parms -		else if ( !Q_stricmp( token, "q3map_sun" ) ) { -			float	a, b; - -			token = COM_ParseExt( text, qfalse ); -			tr.sunLight[0] = atof( token ); -			token = COM_ParseExt( text, qfalse ); -			tr.sunLight[1] = atof( token ); -			token = COM_ParseExt( text, qfalse ); -			tr.sunLight[2] = atof( token ); -			 -			VectorNormalize( tr.sunLight ); - -			token = COM_ParseExt( text, qfalse ); -			a = atof( token ); -			VectorScale( tr.sunLight, a, tr.sunLight); - -			token = COM_ParseExt( text, qfalse ); -			a = atof( token ); -			a = a / 180 * M_PI; - -			token = COM_ParseExt( text, qfalse ); -			b = atof( token ); -			b = b / 180 * M_PI; - -			tr.sunDirection[0] = cos( a ) * cos( b ); -			tr.sunDirection[1] = sin( a ) * cos( b ); -			tr.sunDirection[2] = sin( b ); -		} -		else if ( !Q_stricmp( token, "deformVertexes" ) ) { -			ParseDeform( text ); -			continue; -		} -		else if ( !Q_stricmp( token, "tesssize" ) ) { -			SkipRestOfLine( text ); -			continue; -		} -		else if ( !Q_stricmp( token, "clampTime" ) ) { -			token = COM_ParseExt( text, qfalse ); -      if (token[0]) { -        shader.clampTime = atof(token); -      } -    } -		// skip stuff that only the q3map needs -		else if ( !Q_stricmpn( token, "q3map", 5 ) ) { -			SkipRestOfLine( text ); -			continue; -		} -		// skip stuff that only q3map or the server needs -		else if ( !Q_stricmp( token, "surfaceParm" ) ) { -			ParseSurfaceParm( text ); -			continue; -		} -		// no mip maps -		else if ( !Q_stricmp( token, "nomipmaps" ) ) -		{ -			shader.noMipMaps = qtrue; -			shader.noPicMip = qtrue; -			continue; -		} -		// no picmip adjustment -		else if ( !Q_stricmp( token, "nopicmip" ) ) -		{ -			shader.noPicMip = qtrue; -			continue; -		} -		// polygonOffset -		else if ( !Q_stricmp( token, "polygonOffset" ) ) -		{ -			shader.polygonOffset = qtrue; -			continue; -		} -		// entityMergable, allowing sprite surfaces from multiple entities -		// to be merged into one batch.  This is a savings for smoke -		// puffs and blood, but can't be used for anything where the -		// shader calcs (not the surface function) reference the entity color or scroll -		else if ( !Q_stricmp( token, "entityMergable" ) ) -		{ -			shader.entityMergable = qtrue; -			continue; -		} -		// fogParms -		else if ( !Q_stricmp( token, "fogParms" ) )  -		{ -			if ( !ParseVector( text, 3, shader.fogParms.color ) ) { -				return qfalse; -			} - -			token = COM_ParseExt( text, qfalse ); -			if ( !token[0] )  -			{ -				ri.Printf( PRINT_WARNING, "WARNING: missing parm for 'fogParms' keyword in shader '%s'\n", shader.name ); -				continue; -			} -			shader.fogParms.depthForOpaque = atof( token ); - -			// skip any old gradient directions -			SkipRestOfLine( text ); -			continue; -		} -		// portal -		else if ( !Q_stricmp(token, "portal") ) -		{ -			shader.sort = SS_PORTAL; -			continue; -		} -		// skyparms <cloudheight> <outerbox> <innerbox> -		else if ( !Q_stricmp( token, "skyparms" ) ) -		{ -			ParseSkyParms( text ); -			continue; -		} -		// light <value> determines flaring in q3map, not needed here -		else if ( !Q_stricmp(token, "light") )  -		{ -			token = COM_ParseExt( text, qfalse ); -			continue; -		} -		// cull <face> -		else if ( !Q_stricmp( token, "cull") )  -		{ -			token = COM_ParseExt( text, qfalse ); -			if ( token[0] == 0 ) -			{ -				ri.Printf( PRINT_WARNING, "WARNING: missing cull parms in shader '%s'\n", shader.name ); -				continue; -			} - -			if ( !Q_stricmp( token, "none" ) || !Q_stricmp( token, "twosided" ) || !Q_stricmp( token, "disable" ) ) -			{ -				shader.cullType = CT_TWO_SIDED; -			} -			else if ( !Q_stricmp( token, "back" ) || !Q_stricmp( token, "backside" ) || !Q_stricmp( token, "backsided" ) ) -			{ -				shader.cullType = CT_BACK_SIDED; -			} -			else -			{ -				ri.Printf( PRINT_WARNING, "WARNING: invalid cull parm '%s' in shader '%s'\n", token, shader.name ); -			} -			continue; -		} -		// sort -		else if ( !Q_stricmp( token, "sort" ) ) -		{ -			ParseSort( text ); -			continue; -		} -		else -		{ -			ri.Printf( PRINT_WARNING, "WARNING: unknown general shader parameter '%s' in '%s'\n", token, shader.name ); -			return qfalse; -		} -	} - -	// -	// ignore shaders that don't have any stages, unless it is a sky or fog -	// -	if ( s == 0 && !shader.isSky && !(shader.contentFlags & CONTENTS_FOG ) ) { -		return qfalse; -	} - -	shader.explicitlyDefined = qtrue; - -	return qtrue; -} - -/* -======================================================================================== - -SHADER OPTIMIZATION AND FOGGING - -======================================================================================== -*/ - -/* -=================== -ComputeStageIteratorFunc - -See if we can use on of the simple fastpath stage functions, -otherwise set to the generic stage function -=================== -*/ -static void ComputeStageIteratorFunc( void ) -{ -	shader.optimalStageIteratorFunc = RB_StageIteratorGeneric; - -	// -	// see if this should go into the sky path -	// -	if ( shader.isSky ) -	{ -		shader.optimalStageIteratorFunc = RB_StageIteratorSky; -		goto done; -	} - -	if ( r_ignoreFastPath->integer ) -	{ -		return; -	} - -	// -	// see if this can go into the vertex lit fast path -	// -	if ( shader.numUnfoggedPasses == 1 ) -	{ -		if ( stages[0].rgbGen == CGEN_LIGHTING_DIFFUSE ) -		{ -			if ( stages[0].alphaGen == AGEN_IDENTITY ) -			{ -				if ( stages[0].bundle[0].tcGen == TCGEN_TEXTURE ) -				{ -					if ( !shader.polygonOffset ) -					{ -						if ( !shader.multitextureEnv ) -						{ -							if ( !shader.numDeforms ) -							{ -								shader.optimalStageIteratorFunc = RB_StageIteratorVertexLitTexture; -								goto done; -							} -						} -					} -				} -			} -		} -	} - -	// -	// see if this can go into an optimized LM, multitextured path -	// -	if ( shader.numUnfoggedPasses == 1 ) -	{ -		if ( ( stages[0].rgbGen == CGEN_IDENTITY ) && ( stages[0].alphaGen == AGEN_IDENTITY ) ) -		{ -			if ( stages[0].bundle[0].tcGen == TCGEN_TEXTURE &&  -				stages[0].bundle[1].tcGen == TCGEN_LIGHTMAP ) -			{ -				if ( !shader.polygonOffset ) -				{ -					if ( !shader.numDeforms ) -					{ -						if ( shader.multitextureEnv ) -						{ -							shader.optimalStageIteratorFunc = RB_StageIteratorLightmappedMultitexture; -							goto done; -						} -					} -				} -			} -		} -	} - -done: -	return; -} - -typedef struct { -	int		blendA; -	int		blendB; - -	int		multitextureEnv; -	int		multitextureBlend; -} collapse_t; - -static collapse_t	collapse[] = { -	{ 0, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO,	 -		GL_MODULATE, 0 }, - -	{ 0, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, -		GL_MODULATE, 0 }, - -	{ GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, -		GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR }, - -	{ GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, -		GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR }, - -	{ GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, -		GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR }, - -	{ GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, -		GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR }, - -	{ 0, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE, -		GL_ADD, 0 }, - -	{ GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE, -		GL_ADD, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE }, -#if 0 -	{ 0, GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_SRCBLEND_SRC_ALPHA, -		GL_DECAL, 0 }, -#endif -	{ -1 } -}; - -/* -================ -CollapseMultitexture - -Attempt to combine two stages into a single multitexture stage -FIXME: I think modulated add + modulated add collapses incorrectly -================= -*/ -static qboolean CollapseMultitexture( void ) { -	int abits, bbits; -	int i; -	textureBundle_t tmpBundle; - -	if ( !qglActiveTextureARB ) { -		return qfalse; -	} - -	// make sure both stages are active -	if ( !stages[0].active || !stages[1].active ) { -		return qfalse; -	} - -	// on voodoo2, don't combine different tmus -	if ( glConfig.driverType == GLDRV_VOODOO ) { -		if ( stages[0].bundle[0].image[0]->TMU == -			 stages[1].bundle[0].image[0]->TMU ) { -			return qfalse; -		} -	} - -	abits = stages[0].stateBits; -	bbits = stages[1].stateBits; - -	// make sure that both stages have identical state other than blend modes -	if ( ( abits & ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS | GLS_DEPTHMASK_TRUE ) ) != -		( bbits & ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS | GLS_DEPTHMASK_TRUE ) ) ) { -		return qfalse; -	} - -	abits &= ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); -	bbits &= ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); - -	// search for a valid multitexture blend function -	for ( i = 0; collapse[i].blendA != -1 ; i++ ) { -		if ( abits == collapse[i].blendA -			&& bbits == collapse[i].blendB ) { -			break; -		} -	} - -	// nothing found -	if ( collapse[i].blendA == -1 ) { -		return qfalse; -	} - -	// GL_ADD is a separate extension -	if ( collapse[i].multitextureEnv == GL_ADD && !glConfig.textureEnvAddAvailable ) { -		return qfalse; -	} - -	// make sure waveforms have identical parameters -	if ( ( stages[0].rgbGen != stages[1].rgbGen ) || -		( stages[0].alphaGen != stages[1].alphaGen ) )  { -		return qfalse; -	} - -	// an add collapse can only have identity colors -	if ( collapse[i].multitextureEnv == GL_ADD && stages[0].rgbGen != CGEN_IDENTITY ) { -		return qfalse; -	} - -	if ( stages[0].rgbGen == CGEN_WAVEFORM ) -	{ -		if ( memcmp( &stages[0].rgbWave, -					 &stages[1].rgbWave, -					 sizeof( stages[0].rgbWave ) ) ) -		{ -			return qfalse; -		} -	} -	if ( stages[0].alphaGen == CGEN_WAVEFORM ) -	{ -		if ( memcmp( &stages[0].alphaWave, -					 &stages[1].alphaWave, -					 sizeof( stages[0].alphaWave ) ) ) -		{ -			return qfalse; -		} -	} - - -	// make sure that lightmaps are in bundle 1 for 3dfx -	if ( stages[0].bundle[0].isLightmap ) -	{ -		tmpBundle = stages[0].bundle[0]; -		stages[0].bundle[0] = stages[1].bundle[0]; -		stages[0].bundle[1] = tmpBundle; -	} -	else -	{ -		stages[0].bundle[1] = stages[1].bundle[0]; -	} - -	// set the new blend state bits -	shader.multitextureEnv = collapse[i].multitextureEnv; -	stages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); -	stages[0].stateBits |= collapse[i].multitextureBlend; - -	// -	// move down subsequent shaders -	// -	memmove( &stages[1], &stages[2], sizeof( stages[0] ) * ( MAX_SHADER_STAGES - 2 ) ); -	Com_Memset( &stages[MAX_SHADER_STAGES-1], 0, sizeof( stages[0] ) ); - -	return qtrue; -} - -/* -============= - -FixRenderCommandList -https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=493 -Arnout: this is a nasty issue. Shaders can be registered after drawsurfaces are generated -but before the frame is rendered. This will, for the duration of one frame, cause drawsurfaces -to be rendered with bad shaders. To fix this, need to go through all render commands and fix -sortedIndex. -============== -*/ -static void FixRenderCommandList( int newShader ) { -	renderCommandList_t	*cmdList = &backEndData[tr.smpFrame]->commands; - -	if( cmdList ) { -		const void *curCmd = cmdList->cmds; - -		while ( 1 ) { -			switch ( *(const int *)curCmd ) { -			case RC_SET_COLOR: -				{ -				const setColorCommand_t *sc_cmd = (const setColorCommand_t *)curCmd; -				curCmd = (const void *)(sc_cmd + 1); -				break; -				} -			case RC_STRETCH_PIC: -				{ -				const stretchPicCommand_t *sp_cmd = (const stretchPicCommand_t *)curCmd; -				curCmd = (const void *)(sp_cmd + 1); -				break; -				} -			case RC_DRAW_SURFS: -				{ -				int i; -				drawSurf_t	*drawSurf; -				shader_t	*shader; -				int			fogNum; -				int			entityNum; -				int			dlightMap; -				int			sortedIndex; -				const drawSurfsCommand_t *ds_cmd =  (const drawSurfsCommand_t *)curCmd; - -				for( i = 0, drawSurf = ds_cmd->drawSurfs; i < ds_cmd->numDrawSurfs; i++, drawSurf++ ) { -					R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlightMap ); -                    sortedIndex = (( drawSurf->sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1)); -					if( sortedIndex >= newShader ) { -						sortedIndex++; -						drawSurf->sort = (sortedIndex << QSORT_SHADERNUM_SHIFT) | entityNum | ( fogNum << QSORT_FOGNUM_SHIFT ) | (int)dlightMap; -					} -				} -				curCmd = (const void *)(ds_cmd + 1); -				break; -				} -			case RC_DRAW_BUFFER: -				{ -				const drawBufferCommand_t *db_cmd = (const drawBufferCommand_t *)curCmd; -				curCmd = (const void *)(db_cmd + 1); -				break; -				} -			case RC_SWAP_BUFFERS: -				{ -				const swapBuffersCommand_t *sb_cmd = (const swapBuffersCommand_t *)curCmd; -				curCmd = (const void *)(sb_cmd + 1); -				break; -				} -			case RC_END_OF_LIST: -			default: -				return; -			} -		} -	} -} - -/* -============== -SortNewShader - -Positions the most recently created shader in the tr.sortedShaders[] -array so that the shader->sort key is sorted reletive to the other -shaders. - -Sets shader->sortedIndex -============== -*/ -static void SortNewShader( void ) { -	int		i; -	float	sort; -	shader_t	*newShader; - -	newShader = tr.shaders[ tr.numShaders - 1 ]; -	sort = newShader->sort; - -	for ( i = tr.numShaders - 2 ; i >= 0 ; i-- ) { -		if ( tr.sortedShaders[ i ]->sort <= sort ) { -			break; -		} -		tr.sortedShaders[i+1] = tr.sortedShaders[i]; -		tr.sortedShaders[i+1]->sortedIndex++; -	} - -	// Arnout: fix rendercommandlist -	// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=493 -	FixRenderCommandList( i+1 ); - -	newShader->sortedIndex = i+1; -	tr.sortedShaders[i+1] = newShader; -} - - -/* -==================== -GeneratePermanentShader -==================== -*/ -static shader_t *GeneratePermanentShader( void ) { -	shader_t	*newShader; -	int			i, b; -	int			size, hash; - -	if ( tr.numShaders == MAX_SHADERS ) { -		ri.Printf( PRINT_WARNING, "WARNING: GeneratePermanentShader - MAX_SHADERS hit\n"); -		return tr.defaultShader; -	} - -	newShader = ri.Hunk_Alloc( sizeof( shader_t ), h_low ); - -	*newShader = shader; - -	if ( shader.sort <= SS_OPAQUE ) { -		newShader->fogPass = FP_EQUAL; -	} else if ( shader.contentFlags & CONTENTS_FOG ) { -		newShader->fogPass = FP_LE; -	} - -	tr.shaders[ tr.numShaders ] = newShader; -	newShader->index = tr.numShaders; -	 -	tr.sortedShaders[ tr.numShaders ] = newShader; -	newShader->sortedIndex = tr.numShaders; - -	tr.numShaders++; - -	for ( i = 0 ; i < newShader->numUnfoggedPasses ; i++ ) { -		if ( !stages[i].active ) { -			break; -		} -		newShader->stages[i] = ri.Hunk_Alloc( sizeof( stages[i] ), h_low ); -		*newShader->stages[i] = stages[i]; - -		for ( b = 0 ; b < NUM_TEXTURE_BUNDLES ; b++ ) { -			size = newShader->stages[i]->bundle[b].numTexMods * sizeof( texModInfo_t ); -			newShader->stages[i]->bundle[b].texMods = ri.Hunk_Alloc( size, h_low ); -			Com_Memcpy( newShader->stages[i]->bundle[b].texMods, stages[i].bundle[b].texMods, size ); -		} -	} - -	SortNewShader(); - -	hash = generateHashValue(newShader->name, FILE_HASH_SIZE); -	newShader->next = hashTable[hash]; -	hashTable[hash] = newShader; - -	return newShader; -} - -/* -================= -VertexLightingCollapse - -If vertex lighting is enabled, only render a single -pass, trying to guess which is the correct one to best aproximate -what it is supposed to look like. -================= -*/ -static void VertexLightingCollapse( void ) { -	int		stage; -	shaderStage_t	*bestStage; -	int		bestImageRank; -	int		rank; - -	// if we aren't opaque, just use the first pass -	if ( shader.sort == SS_OPAQUE ) { - -		// pick the best texture for the single pass -		bestStage = &stages[0]; -		bestImageRank = -999999; - -		for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { -			shaderStage_t *pStage = &stages[stage]; - -			if ( !pStage->active ) { -				break; -			} -			rank = 0; - -			if ( pStage->bundle[0].isLightmap ) { -				rank -= 100; -			} -			if ( pStage->bundle[0].tcGen != TCGEN_TEXTURE ) { -				rank -= 5; -			} -			if ( pStage->bundle[0].numTexMods ) { -				rank -= 5; -			} -			if ( pStage->rgbGen != CGEN_IDENTITY && pStage->rgbGen != CGEN_IDENTITY_LIGHTING ) { -				rank -= 3; -			} - -			if ( rank > bestImageRank  ) { -				bestImageRank = rank; -				bestStage = pStage; -			} -		} - -		stages[0].bundle[0] = bestStage->bundle[0]; -		stages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); -		stages[0].stateBits |= GLS_DEPTHMASK_TRUE; -		if ( shader.lightmapIndex == LIGHTMAP_NONE ) { -			stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE; -		} else { -			stages[0].rgbGen = CGEN_EXACT_VERTEX; -		} -		stages[0].alphaGen = AGEN_SKIP;		 -	} else { -		// don't use a lightmap (tesla coils) -		if ( stages[0].bundle[0].isLightmap ) { -			stages[0] = stages[1]; -		} - -		// if we were in a cross-fade cgen, hack it to normal -		if ( stages[0].rgbGen == CGEN_ONE_MINUS_ENTITY || stages[1].rgbGen == CGEN_ONE_MINUS_ENTITY ) { -			stages[0].rgbGen = CGEN_IDENTITY_LIGHTING; -		} -		if ( ( stages[0].rgbGen == CGEN_WAVEFORM && stages[0].rgbWave.func == GF_SAWTOOTH ) -			&& ( stages[1].rgbGen == CGEN_WAVEFORM && stages[1].rgbWave.func == GF_INVERSE_SAWTOOTH ) ) { -			stages[0].rgbGen = CGEN_IDENTITY_LIGHTING; -		} -		if ( ( stages[0].rgbGen == CGEN_WAVEFORM && stages[0].rgbWave.func == GF_INVERSE_SAWTOOTH ) -			&& ( stages[1].rgbGen == CGEN_WAVEFORM && stages[1].rgbWave.func == GF_SAWTOOTH ) ) { -			stages[0].rgbGen = CGEN_IDENTITY_LIGHTING; -		} -	} - -	for ( stage = 1; stage < MAX_SHADER_STAGES; stage++ ) { -		shaderStage_t *pStage = &stages[stage]; - -		if ( !pStage->active ) { -			break; -		} - -		Com_Memset( pStage, 0, sizeof( *pStage ) ); -	} -} - -/* -========================= -FinishShader - -Returns a freshly allocated shader with all the needed info -from the current global working shader -========================= -*/ -static shader_t *FinishShader( void ) { -	int stage; -	qboolean		hasLightmapStage; -	qboolean		vertexLightmap; - -	hasLightmapStage = qfalse; -	vertexLightmap = qfalse; - -	// -	// set sky stuff appropriate -	// -	if ( shader.isSky ) { -		shader.sort = SS_ENVIRONMENT; -	} - -	// -	// set polygon offset -	// -	if ( shader.polygonOffset && !shader.sort ) { -		shader.sort = SS_DECAL; -	} - -	// -	// set appropriate stage information -	// -	for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { -		shaderStage_t *pStage = &stages[stage]; - -		if ( !pStage->active ) { -			break; -		} - -    // check for a missing texture -		if ( !pStage->bundle[0].image[0] ) { -			ri.Printf( PRINT_WARNING, "Shader %s has a stage with no image\n", shader.name ); -			pStage->active = qfalse; -			continue; -		} - -		// -		// ditch this stage if it's detail and detail textures are disabled -		// -		if ( pStage->isDetail && !r_detailTextures->integer ) { -			if ( stage < ( MAX_SHADER_STAGES - 1 ) ) { -				memmove( pStage, pStage + 1, sizeof( *pStage ) * ( MAX_SHADER_STAGES - stage - 1 ) ); -				Com_Memset(  pStage + 1, 0, sizeof( *pStage ) ); -			} -			continue; -		} - -		// -		// default texture coordinate generation -		// -		if ( pStage->bundle[0].isLightmap ) { -			if ( pStage->bundle[0].tcGen == TCGEN_BAD ) { -				pStage->bundle[0].tcGen = TCGEN_LIGHTMAP; -			} -			hasLightmapStage = qtrue; -		} else { -			if ( pStage->bundle[0].tcGen == TCGEN_BAD ) { -				pStage->bundle[0].tcGen = TCGEN_TEXTURE; -			} -		} - - -    // not a true lightmap but we want to leave existing  -    // behaviour in place and not print out a warning -    //if (pStage->rgbGen == CGEN_VERTEX) { -    //  vertexLightmap = qtrue; -    //} - - - -		// -		// determine sort order and fog color adjustment -		// -		if ( ( pStage->stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) && -			 ( stages[0].stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) ) { -			int blendSrcBits = pStage->stateBits & GLS_SRCBLEND_BITS; -			int blendDstBits = pStage->stateBits & GLS_DSTBLEND_BITS; - -			// fog color adjustment only works for blend modes that have a contribution -			// that aproaches 0 as the modulate values aproach 0 -- -			// GL_ONE, GL_ONE -			// GL_ZERO, GL_ONE_MINUS_SRC_COLOR -			// GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA - -			// modulate, additive -			if ( ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && ( blendDstBits == GLS_DSTBLEND_ONE ) ) || -				( ( blendSrcBits == GLS_SRCBLEND_ZERO ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR ) ) ) { -				pStage->adjustColorsForFog = ACFF_MODULATE_RGB; -			} -			// strict blend -			else if ( ( blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) ) -			{ -				pStage->adjustColorsForFog = ACFF_MODULATE_ALPHA; -			} -			// premultiplied alpha -			else if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) ) -			{ -				pStage->adjustColorsForFog = ACFF_MODULATE_RGBA; -			} else { -				// we can't adjust this one correctly, so it won't be exactly correct in fog -			} - -			// don't screw with sort order if this is a portal or environment -			if ( !shader.sort ) { -				// see through item, like a grill or grate -				if ( pStage->stateBits & GLS_DEPTHMASK_TRUE ) { -					shader.sort = SS_SEE_THROUGH; -				} else { -					shader.sort = SS_BLEND0; -				} -			} -		} -	} - -	// there are times when you will need to manually apply a sort to -	// opaque alpha tested shaders that have later blend passes -	if ( !shader.sort ) { -		shader.sort = SS_OPAQUE; -	} - -	// -	// if we are in r_vertexLight mode, never use a lightmap texture -	// -	if ( stage > 1 && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) ) { -		VertexLightingCollapse(); -		stage = 1; -		hasLightmapStage = qfalse; -	} - -	// -	// look for multitexture potential -	// -	if ( stage > 1 && CollapseMultitexture() ) { -		stage--; -	} - -	if ( shader.lightmapIndex >= 0 && !hasLightmapStage ) { -		if (vertexLightmap) { -			ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has VERTEX forced lightmap!\n", shader.name ); -		} else { -			ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has lightmap but no lightmap stage!\n", shader.name ); -  			shader.lightmapIndex = LIGHTMAP_NONE; -		} -	} - - -	// -	// compute number of passes -	// -	shader.numUnfoggedPasses = stage; - -	// fogonly shaders don't have any normal passes -	if ( stage == 0 ) { -		shader.sort = SS_FOG; -	} - -	// determine which stage iterator function is appropriate -	ComputeStageIteratorFunc(); - -	return GeneratePermanentShader(); -} - -//======================================================================================== - -/* -==================== -FindShaderInShaderText - -Scans the combined text description of all the shader files for -the given shader name. - -return NULL if not found - -If found, it will return a valid shader -===================== -*/ -static char *FindShaderInShaderText( const char *shadername ) { - -	char *token, *p; - -	int i, hash; - -	hash = generateHashValue(shadername, MAX_SHADERTEXT_HASH); - -	for (i = 0; shaderTextHashTable[hash][i]; i++) { -		p = shaderTextHashTable[hash][i]; -		token = COM_ParseExt(&p, qtrue); -		if ( !Q_stricmp( token, shadername ) ) { -			return p; -		} -	} - -	p = s_shaderText; - -	if ( !p ) { -		return NULL; -	} - -	// look for label -	while ( 1 ) { -		token = COM_ParseExt( &p, qtrue ); -		if ( token[0] == 0 ) { -			break; -		} - -		if ( !Q_stricmp( token, shadername ) ) { -			return p; -		} -		else { -			// skip the definition -			SkipBracedSection( &p ); -		} -	} - -	return NULL; -} - - -/* -================== -R_FindShaderByName - -Will always return a valid shader, but it might be the -default shader if the real one can't be found. -================== -*/ -shader_t *R_FindShaderByName( const char *name ) { -	char		strippedName[MAX_QPATH]; -	int			hash; -	shader_t	*sh; - -	if ( (name==NULL) || (name[0] == 0) ) {  // bk001205 -		return tr.defaultShader; -	} - -	COM_StripExtension( name, strippedName ); - -	hash = generateHashValue(strippedName, FILE_HASH_SIZE); - -	// -	// see if the shader is already loaded -	// -	for (sh=hashTable[hash]; sh; sh=sh->next) { -		// NOTE: if there was no shader or image available with the name strippedName -		// then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we -		// have to check all default shaders otherwise for every call to R_FindShader -		// with that same strippedName a new default shader is created. -		if (Q_stricmp(sh->name, strippedName) == 0) { -			// match found -			return sh; -		} -	} - -	return tr.defaultShader; -} - - -/* -=============== -R_FindShader - -Will always return a valid shader, but it might be the -default shader if the real one can't be found. - -In the interest of not requiring an explicit shader text entry to -be defined for every single image used in the game, three default -shader behaviors can be auto-created for any image: - -If lightmapIndex == LIGHTMAP_NONE, then the image will have -dynamic diffuse lighting applied to it, as apropriate for most -entity skin surfaces. - -If lightmapIndex == LIGHTMAP_2D, then the image will be used -for 2D rendering unless an explicit shader is found - -If lightmapIndex == LIGHTMAP_BY_VERTEX, then the image will use -the vertex rgba modulate values, as apropriate for misc_model -pre-lit surfaces. - -Other lightmapIndex values will have a lightmap stage created -and src*dest blending applied with the texture, as apropriate for -most world construction surfaces. - -=============== -*/ -shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ) { -	char		strippedName[MAX_QPATH]; -	char		fileName[MAX_QPATH]; -	int			i, hash; -	char		*shaderText; -	image_t		*image; -	shader_t	*sh; - -	if ( name[0] == 0 ) { -		return tr.defaultShader; -	} - -	// use (fullbright) vertex lighting if the bsp file doesn't have -	// lightmaps -	if ( lightmapIndex >= 0 && lightmapIndex >= tr.numLightmaps ) { -		lightmapIndex = LIGHTMAP_BY_VERTEX; -	} - -	COM_StripExtension( name, strippedName ); - -	hash = generateHashValue(strippedName, FILE_HASH_SIZE); - -	// -	// see if the shader is already loaded -	// -	for (sh = hashTable[hash]; sh; sh = sh->next) { -		// NOTE: if there was no shader or image available with the name strippedName -		// then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we -		// have to check all default shaders otherwise for every call to R_FindShader -		// with that same strippedName a new default shader is created. -		if ( (sh->lightmapIndex == lightmapIndex || sh->defaultShader) && -		     !Q_stricmp(sh->name, strippedName)) { -			// match found -			return sh; -		} -	} - -	// make sure the render thread is stopped, because we are probably -	// going to have to upload an image -	if (r_smp->integer) { -		R_SyncRenderThread(); -	} - -	// clear the global shader -	Com_Memset( &shader, 0, sizeof( shader ) ); -	Com_Memset( &stages, 0, sizeof( stages ) ); -	Q_strncpyz(shader.name, strippedName, sizeof(shader.name)); -	shader.lightmapIndex = lightmapIndex; -	for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) { -		stages[i].bundle[0].texMods = texMods[i]; -	} - -	// FIXME: set these "need" values apropriately -	shader.needsNormal = qtrue; -	shader.needsST1 = qtrue; -	shader.needsST2 = qtrue; -	shader.needsColor = qtrue; - -	// -	// attempt to define shader from an explicit parameter file -	// -	shaderText = FindShaderInShaderText( strippedName ); -	if ( shaderText ) { -		// enable this when building a pak file to get a global list -		// of all explicit shaders -		if ( r_printShaders->integer ) { -			ri.Printf( PRINT_ALL, "*SHADER* %s\n", name ); -		} - -		if ( !ParseShader( &shaderText ) ) { -			// had errors, so use default shader -			shader.defaultShader = qtrue; -		} -		sh = FinishShader(); -		return sh; -	} - - -	// -	// if not defined in the in-memory shader descriptions, -	// look for a single TGA, BMP, or PCX -	// -	Q_strncpyz( fileName, name, sizeof( fileName ) ); -	COM_DefaultExtension( fileName, sizeof( fileName ), ".tga" ); -	image = R_FindImageFile( fileName, mipRawImage, mipRawImage, mipRawImage ? GL_REPEAT : GL_CLAMP ); -	if ( !image ) { -		ri.Printf( PRINT_DEVELOPER, "Couldn't find image for shader %s\n", name ); -		shader.defaultShader = qtrue; -		return FinishShader(); -	} - -	// -	// create the default shading commands -	// -	if ( shader.lightmapIndex == LIGHTMAP_NONE ) { -		// dynamic colors at vertexes -		stages[0].bundle[0].image[0] = image; -		stages[0].active = qtrue; -		stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE; -		stages[0].stateBits = GLS_DEFAULT; -	} else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) { -		// explicit colors at vertexes -		stages[0].bundle[0].image[0] = image; -		stages[0].active = qtrue; -		stages[0].rgbGen = CGEN_EXACT_VERTEX; -		stages[0].alphaGen = AGEN_SKIP; -		stages[0].stateBits = GLS_DEFAULT; -	} else if ( shader.lightmapIndex == LIGHTMAP_2D ) { -		// GUI elements -		stages[0].bundle[0].image[0] = image; -		stages[0].active = qtrue; -		stages[0].rgbGen = CGEN_VERTEX; -		stages[0].alphaGen = AGEN_VERTEX; -		stages[0].stateBits = GLS_DEPTHTEST_DISABLE | -			  GLS_SRCBLEND_SRC_ALPHA | -			  GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; -	} else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) { -		// fullbright level -		stages[0].bundle[0].image[0] = tr.whiteImage; -		stages[0].active = qtrue; -		stages[0].rgbGen = CGEN_IDENTITY_LIGHTING; -		stages[0].stateBits = GLS_DEFAULT; - -		stages[1].bundle[0].image[0] = image; -		stages[1].active = qtrue; -		stages[1].rgbGen = CGEN_IDENTITY; -		stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO; -	} else { -		// two pass lightmap -		stages[0].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex]; -		stages[0].bundle[0].isLightmap = qtrue; -		stages[0].active = qtrue; -		stages[0].rgbGen = CGEN_IDENTITY;	// lightmaps are scaled on creation -													// for identitylight -		stages[0].stateBits = GLS_DEFAULT; - -		stages[1].bundle[0].image[0] = image; -		stages[1].active = qtrue; -		stages[1].rgbGen = CGEN_IDENTITY; -		stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO; -	} - -	return FinishShader(); -} - - -qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage) { -	int			i, hash; -	shader_t	*sh; - -	hash = generateHashValue(name, FILE_HASH_SIZE); - -	// 20051020 misantropia -- probably not necessary since this function -	// only gets called from tr_font.c with lightmapIndex == LIGHTMAP_2D -	// but better safe than sorry. -	if ( lightmapIndex >= tr.numLightmaps ) { -		lightmapIndex = LIGHTMAP_WHITEIMAGE; -	} - -	// -	// see if the shader is already loaded -	// -	for (sh=hashTable[hash]; sh; sh=sh->next) { -		// NOTE: if there was no shader or image available with the name strippedName -		// then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we -		// have to check all default shaders otherwise for every call to R_FindShader -		// with that same strippedName a new default shader is created. -		if ( (sh->lightmapIndex == lightmapIndex || sh->defaultShader) && -			// index by name -			!Q_stricmp(sh->name, name)) { -			// match found -			return sh->index; -		} -	} - -	// make sure the render thread is stopped, because we are probably -	// going to have to upload an image -	if (r_smp->integer) { -		R_SyncRenderThread(); -	} - -	// clear the global shader -	Com_Memset( &shader, 0, sizeof( shader ) ); -	Com_Memset( &stages, 0, sizeof( stages ) ); -	Q_strncpyz(shader.name, name, sizeof(shader.name)); -	shader.lightmapIndex = lightmapIndex; -	for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) { -		stages[i].bundle[0].texMods = texMods[i]; -	} - -	// FIXME: set these "need" values apropriately -	shader.needsNormal = qtrue; -	shader.needsST1 = qtrue; -	shader.needsST2 = qtrue; -	shader.needsColor = qtrue; - -	// -	// create the default shading commands -	// -	if ( shader.lightmapIndex == LIGHTMAP_NONE ) { -		// dynamic colors at vertexes -		stages[0].bundle[0].image[0] = image; -		stages[0].active = qtrue; -		stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE; -		stages[0].stateBits = GLS_DEFAULT; -	} else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) { -		// explicit colors at vertexes -		stages[0].bundle[0].image[0] = image; -		stages[0].active = qtrue; -		stages[0].rgbGen = CGEN_EXACT_VERTEX; -		stages[0].alphaGen = AGEN_SKIP; -		stages[0].stateBits = GLS_DEFAULT; -	} else if ( shader.lightmapIndex == LIGHTMAP_2D ) { -		// GUI elements -		stages[0].bundle[0].image[0] = image; -		stages[0].active = qtrue; -		stages[0].rgbGen = CGEN_VERTEX; -		stages[0].alphaGen = AGEN_VERTEX; -		stages[0].stateBits = GLS_DEPTHTEST_DISABLE | -			  GLS_SRCBLEND_SRC_ALPHA | -			  GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; -	} else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) { -		// fullbright level -		stages[0].bundle[0].image[0] = tr.whiteImage; -		stages[0].active = qtrue; -		stages[0].rgbGen = CGEN_IDENTITY_LIGHTING; -		stages[0].stateBits = GLS_DEFAULT; - -		stages[1].bundle[0].image[0] = image; -		stages[1].active = qtrue; -		stages[1].rgbGen = CGEN_IDENTITY; -		stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO; -	} else { -		// two pass lightmap -		stages[0].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex]; -		stages[0].bundle[0].isLightmap = qtrue; -		stages[0].active = qtrue; -		stages[0].rgbGen = CGEN_IDENTITY;	// lightmaps are scaled on creation -													// for identitylight -		stages[0].stateBits = GLS_DEFAULT; - -		stages[1].bundle[0].image[0] = image; -		stages[1].active = qtrue; -		stages[1].rgbGen = CGEN_IDENTITY; -		stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO; -	} - -	sh = FinishShader(); -  return sh->index;  -} - - -/*  -==================== -RE_RegisterShader - -This is the exported shader entry point for the rest of the system -It will always return an index that will be valid. - -This should really only be used for explicit shaders, because there is no -way to ask for different implicit lighting modes (vertex, lightmap, etc) -==================== -*/ -qhandle_t RE_RegisterShaderLightMap( const char *name, int lightmapIndex ) { -	shader_t	*sh; - -	if ( strlen( name ) >= MAX_QPATH ) { -		Com_Printf( "Shader name exceeds MAX_QPATH\n" ); -		return 0; -	} - -	sh = R_FindShader( name, lightmapIndex, qtrue ); - -	// we want to return 0 if the shader failed to -	// load for some reason, but R_FindShader should -	// still keep a name allocated for it, so if -	// something calls RE_RegisterShader again with -	// the same name, we don't try looking for it again -	if ( sh->defaultShader ) { -		return 0; -	} - -	return sh->index; -} - - -/*  -==================== -RE_RegisterShader - -This is the exported shader entry point for the rest of the system -It will always return an index that will be valid. - -This should really only be used for explicit shaders, because there is no -way to ask for different implicit lighting modes (vertex, lightmap, etc) -==================== -*/ -qhandle_t RE_RegisterShader( const char *name ) { -	shader_t	*sh; - -	if ( strlen( name ) >= MAX_QPATH ) { -		Com_Printf( "Shader name exceeds MAX_QPATH\n" ); -		return 0; -	} - -	sh = R_FindShader( name, LIGHTMAP_2D, qtrue ); - -	// we want to return 0 if the shader failed to -	// load for some reason, but R_FindShader should -	// still keep a name allocated for it, so if -	// something calls RE_RegisterShader again with -	// the same name, we don't try looking for it again -	if ( sh->defaultShader ) { -		return 0; -	} - -	return sh->index; -} - - -/* -==================== -RE_RegisterShaderNoMip - -For menu graphics that should never be picmiped -==================== -*/ -qhandle_t RE_RegisterShaderNoMip( const char *name ) { -	shader_t	*sh; - -	if ( strlen( name ) >= MAX_QPATH ) { -		Com_Printf( "Shader name exceeds MAX_QPATH\n" ); -		return 0; -	} - -	sh = R_FindShader( name, LIGHTMAP_2D, qfalse ); - -	// we want to return 0 if the shader failed to -	// load for some reason, but R_FindShader should -	// still keep a name allocated for it, so if -	// something calls RE_RegisterShader again with -	// the same name, we don't try looking for it again -	if ( sh->defaultShader ) { -		return 0; -	} - -	return sh->index; -} - -/* -==================== -R_GetShaderByHandle - -When a handle is passed in by another module, this range checks -it and returns a valid (possibly default) shader_t to be used internally. -==================== -*/ -shader_t *R_GetShaderByHandle( qhandle_t hShader ) { -	if ( hShader < 0 ) { -	  ri.Printf( PRINT_WARNING, "R_GetShaderByHandle: out of range hShader '%d'\n", hShader ); // bk: FIXME name -		return tr.defaultShader; -	} -	if ( hShader >= tr.numShaders ) { -		ri.Printf( PRINT_WARNING, "R_GetShaderByHandle: out of range hShader '%d'\n", hShader ); -		return tr.defaultShader; -	} -	return tr.shaders[hShader]; -} - -/* -=============== -R_ShaderList_f - -Dump information on all valid shaders to the console -A second parameter will cause it to print in sorted order -=============== -*/ -void	R_ShaderList_f (void) { -	int			i; -	int			count; -	shader_t	*shader; - -	ri.Printf (PRINT_ALL, "-----------------------\n"); - -	count = 0; -	for ( i = 0 ; i < tr.numShaders ; i++ ) { -		if ( ri.Cmd_Argc() > 1 ) { -			shader = tr.sortedShaders[i]; -		} else { -			shader = tr.shaders[i]; -		} - -		ri.Printf( PRINT_ALL, "%i ", shader->numUnfoggedPasses ); - -		if (shader->lightmapIndex >= 0 ) { -			ri.Printf (PRINT_ALL, "L "); -		} else { -			ri.Printf (PRINT_ALL, "  "); -		} -		if ( shader->multitextureEnv == GL_ADD ) { -			ri.Printf( PRINT_ALL, "MT(a) " ); -		} else if ( shader->multitextureEnv == GL_MODULATE ) { -			ri.Printf( PRINT_ALL, "MT(m) " ); -		} else if ( shader->multitextureEnv == GL_DECAL ) { -			ri.Printf( PRINT_ALL, "MT(d) " ); -		} else { -			ri.Printf( PRINT_ALL, "      " ); -		} -		if ( shader->explicitlyDefined ) { -			ri.Printf( PRINT_ALL, "E " ); -		} else { -			ri.Printf( PRINT_ALL, "  " ); -		} - -		if ( shader->optimalStageIteratorFunc == RB_StageIteratorGeneric ) { -			ri.Printf( PRINT_ALL, "gen " ); -		} else if ( shader->optimalStageIteratorFunc == RB_StageIteratorSky ) { -			ri.Printf( PRINT_ALL, "sky " ); -		} else if ( shader->optimalStageIteratorFunc == RB_StageIteratorLightmappedMultitexture ) { -			ri.Printf( PRINT_ALL, "lmmt" ); -		} else if ( shader->optimalStageIteratorFunc == RB_StageIteratorVertexLitTexture ) { -			ri.Printf( PRINT_ALL, "vlt " ); -		} else { -			ri.Printf( PRINT_ALL, "    " ); -		} - -		if ( shader->defaultShader ) { -			ri.Printf (PRINT_ALL,  ": %s (DEFAULTED)\n", shader->name); -		} else { -			ri.Printf (PRINT_ALL,  ": %s\n", shader->name); -		} -		count++; -	} -	ri.Printf (PRINT_ALL, "%i total shaders\n", count); -	ri.Printf (PRINT_ALL, "------------------\n"); -} - - -/* -==================== -ScanAndLoadShaderFiles - -Finds and loads all .shader files, combining them into -a single large text block that can be scanned for shader names -===================== -*/ -#define	MAX_SHADER_FILES	4096 -static void ScanAndLoadShaderFiles( void ) -{ -	char **shaderFiles; -	char *buffers[MAX_SHADER_FILES]; -	char *p; -	int numShaders; -	int i; -	char *oldp, *token, *hashMem; -	int shaderTextHashTableSizes[MAX_SHADERTEXT_HASH], hash, size; - -	long sum = 0; -	// scan for shader files -	shaderFiles = ri.FS_ListFiles( "scripts", ".shader", &numShaders ); - -	if ( !shaderFiles || !numShaders ) -	{ -		ri.Printf( PRINT_WARNING, "WARNING: no shader files found\n" ); -		return; -	} - -	if ( numShaders > MAX_SHADER_FILES ) { -		numShaders = MAX_SHADER_FILES; -	} - -	// load and parse shader files -	for ( i = 0; i < numShaders; i++ ) -	{ -		char filename[MAX_QPATH]; - -		Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] ); -		ri.Printf( PRINT_ALL, "...loading '%s'\n", filename ); -		sum += ri.FS_ReadFile( filename, (void **)&buffers[i] ); -		if ( !buffers[i] ) { -			ri.Error( ERR_DROP, "Couldn't load %s", filename ); -		} -	} - -	// build single large buffer -	s_shaderText = ri.Hunk_Alloc( sum + numShaders*2, h_low ); - -	// free in reverse order, so the temp files are all dumped -	for ( i = numShaders - 1; i >= 0 ; i-- ) { -		strcat( s_shaderText, "\n" ); -		p = &s_shaderText[strlen(s_shaderText)]; -		strcat( s_shaderText, buffers[i] ); -		ri.FS_FreeFile( buffers[i] ); -		buffers[i] = p; -		COM_Compress(p); -	} - -	// free up memory -	ri.FS_FreeFileList( shaderFiles ); - -	Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes)); -	size = 0; -	// -	for ( i = 0; i < numShaders; i++ ) { -		// pointer to the first shader file -		p = buffers[i]; -		// look for label -		while ( 1 ) { -			token = COM_ParseExt( &p, qtrue ); -			if ( token[0] == 0 ) { -				break; -			} - -			hash = generateHashValue(token, MAX_SHADERTEXT_HASH); -			shaderTextHashTableSizes[hash]++; -			size++; -			SkipBracedSection(&p); -			// if we passed the pointer to the next shader file -			if ( i < numShaders - 1 ) { -				if ( p > buffers[i+1] ) { -					break; -				} -			} -		} -	} - -	size += MAX_SHADERTEXT_HASH; - -	hashMem = ri.Hunk_Alloc( size * sizeof(char *), h_low ); - -	for (i = 0; i < MAX_SHADERTEXT_HASH; i++) { -		shaderTextHashTable[i] = (char **) hashMem; -		hashMem = ((char *) hashMem) + ((shaderTextHashTableSizes[i] + 1) * sizeof(char *)); -	} - -	Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes)); -	// -	for ( i = 0; i < numShaders; i++ ) { -		// pointer to the first shader file -		p = buffers[i]; -		// look for label -		while ( 1 ) { -			oldp = p; -			token = COM_ParseExt( &p, qtrue ); -			if ( token[0] == 0 ) { -				break; -			} - -			hash = generateHashValue(token, MAX_SHADERTEXT_HASH); -			shaderTextHashTable[hash][shaderTextHashTableSizes[hash]++] = oldp; - -			SkipBracedSection(&p); -			// if we passed the pointer to the next shader file -			if ( i < numShaders - 1 ) { -				if ( p > buffers[i+1] ) { -					break; -				} -			} -		} -	} - -	return; - -} - - -/* -==================== -CreateInternalShaders -==================== -*/ -static void CreateInternalShaders( void ) { -	tr.numShaders = 0; - -	// init the default shader -	Com_Memset( &shader, 0, sizeof( shader ) ); -	Com_Memset( &stages, 0, sizeof( stages ) ); - -	Q_strncpyz( shader.name, "<default>", sizeof( shader.name ) ); - -	shader.lightmapIndex = LIGHTMAP_NONE; -	stages[0].bundle[0].image[0] = tr.defaultImage; -	stages[0].active = qtrue; -	stages[0].stateBits = GLS_DEFAULT; -	tr.defaultShader = FinishShader(); - -	// shadow shader is just a marker -	Q_strncpyz( shader.name, "<stencil shadow>", sizeof( shader.name ) ); -	shader.sort = SS_STENCIL_SHADOW; -	tr.shadowShader = FinishShader(); -} - -static void CreateExternalShaders( void ) { -	tr.projectionShadowShader = R_FindShader( "projectionShadow", LIGHTMAP_NONE, qtrue ); -	tr.flareShader = R_FindShader( "flareShader", LIGHTMAP_NONE, qtrue ); -	tr.sunShader = R_FindShader( "sun", LIGHTMAP_NONE, qtrue ); -} - -/* -================== -R_InitShaders -================== -*/ -void R_InitShaders( void ) { -	ri.Printf( PRINT_ALL, "Initializing Shaders\n" ); - -	Com_Memset(hashTable, 0, sizeof(hashTable)); - -	deferLoad = qfalse; - -	CreateInternalShaders(); - -	ScanAndLoadShaderFiles(); - -	CreateExternalShaders(); -} diff --git a/ioq3-r437/src/renderer/tr_shadows.c b/ioq3-r437/src/renderer/tr_shadows.c deleted file mode 100644 index 1162c8fd..00000000 --- a/ioq3-r437/src/renderer/tr_shadows.c +++ /dev/null @@ -1,341 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -#include "tr_local.h" - - -/* - -  for a projection shadow: - -  point[x] += light vector * ( z - shadow plane ) -  point[y] += -  point[z] = shadow plane - -  1 0 light[x] / light[z] - -*/ - -typedef struct { -	int		i2; -	int		facing; -} edgeDef_t; - -#define	MAX_EDGE_DEFS	32 - -static	edgeDef_t	edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS]; -static	int			numEdgeDefs[SHADER_MAX_VERTEXES]; -static	int			facing[SHADER_MAX_INDEXES/3]; - -void R_AddEdgeDef( int i1, int i2, int facing ) { -	int		c; - -	c = numEdgeDefs[ i1 ]; -	if ( c == MAX_EDGE_DEFS ) { -		return;		// overflow -	} -	edgeDefs[ i1 ][ c ].i2 = i2; -	edgeDefs[ i1 ][ c ].facing = facing; - -	numEdgeDefs[ i1 ]++; -} - -void R_RenderShadowEdges( void ) { -	int		i; - -#if 0 -	int		numTris; - -	// dumb way -- render every triangle's edges -	numTris = tess.numIndexes / 3; - -	for ( i = 0 ; i < numTris ; i++ ) { -		int		i1, i2, i3; - -		if ( !facing[i] ) { -			continue; -		} - -		i1 = tess.indexes[ i*3 + 0 ]; -		i2 = tess.indexes[ i*3 + 1 ]; -		i3 = tess.indexes[ i*3 + 2 ]; - -		qglBegin( GL_TRIANGLE_STRIP ); -		qglVertex3fv( tess.xyz[ i1 ] ); -		qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); -		qglVertex3fv( tess.xyz[ i2 ] ); -		qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); -		qglVertex3fv( tess.xyz[ i3 ] ); -		qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] ); -		qglVertex3fv( tess.xyz[ i1 ] ); -		qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); -		qglEnd(); -	} -#else -	int		c, c2; -	int		j, k; -	int		i2; -	int		c_edges, c_rejected; -	int		hit[2]; - -	// an edge is NOT a silhouette edge if its face doesn't face the light, -	// or if it has a reverse paired edge that also faces the light. -	// A well behaved polyhedron would have exactly two faces for each edge, -	// but lots of models have dangling edges or overfanned edges -	c_edges = 0; -	c_rejected = 0; - -	for ( i = 0 ; i < tess.numVertexes ; i++ ) { -		c = numEdgeDefs[ i ]; -		for ( j = 0 ; j < c ; j++ ) { -			if ( !edgeDefs[ i ][ j ].facing ) { -				continue; -			} - -			hit[0] = 0; -			hit[1] = 0; - -			i2 = edgeDefs[ i ][ j ].i2; -			c2 = numEdgeDefs[ i2 ]; -			for ( k = 0 ; k < c2 ; k++ ) { -				if ( edgeDefs[ i2 ][ k ].i2 == i ) { -					hit[ edgeDefs[ i2 ][ k ].facing ]++; -				} -			} - -			// if it doesn't share the edge with another front facing -			// triangle, it is a sil edge -			if ( hit[ 1 ] == 0 ) { -				qglBegin( GL_TRIANGLE_STRIP ); -				qglVertex3fv( tess.xyz[ i ] ); -				qglVertex3fv( tess.xyz[ i + tess.numVertexes ] ); -				qglVertex3fv( tess.xyz[ i2 ] ); -				qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); -				qglEnd(); -				c_edges++; -			} else { -				c_rejected++; -			} -		} -	} -#endif -} - -/* -================= -RB_ShadowTessEnd - -triangleFromEdge[ v1 ][ v2 ] - - -  set triangle from edge( v1, v2, tri ) -  if ( facing[ triangleFromEdge[ v1 ][ v2 ] ] && !facing[ triangleFromEdge[ v2 ][ v1 ] ) { -  } -================= -*/ -void RB_ShadowTessEnd( void ) { -	int		i; -	int		numTris; -	vec3_t	lightDir; - -	// we can only do this if we have enough space in the vertex buffers -	if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) { -		return; -	} - -	if ( glConfig.stencilBits < 4 ) { -		return; -	} - -	VectorCopy( backEnd.currentEntity->lightDir, lightDir ); - -	// project vertexes away from light direction -	for ( i = 0 ; i < tess.numVertexes ; i++ ) { -		VectorMA( tess.xyz[i], -512, lightDir, tess.xyz[i+tess.numVertexes] ); -	} - -	// decide which triangles face the light -	Com_Memset( numEdgeDefs, 0, 4 * tess.numVertexes ); - -	numTris = tess.numIndexes / 3; -	for ( i = 0 ; i < numTris ; i++ ) { -		int		i1, i2, i3; -		vec3_t	d1, d2, normal; -		float	*v1, *v2, *v3; -		float	d; - -		i1 = tess.indexes[ i*3 + 0 ]; -		i2 = tess.indexes[ i*3 + 1 ]; -		i3 = tess.indexes[ i*3 + 2 ]; - -		v1 = tess.xyz[ i1 ]; -		v2 = tess.xyz[ i2 ]; -		v3 = tess.xyz[ i3 ]; - -		VectorSubtract( v2, v1, d1 ); -		VectorSubtract( v3, v1, d2 ); -		CrossProduct( d1, d2, normal ); - -		d = DotProduct( normal, lightDir ); -		if ( d > 0 ) { -			facing[ i ] = 1; -		} else { -			facing[ i ] = 0; -		} - -		// create the edges -		R_AddEdgeDef( i1, i2, facing[ i ] ); -		R_AddEdgeDef( i2, i3, facing[ i ] ); -		R_AddEdgeDef( i3, i1, facing[ i ] ); -	} - -	// draw the silhouette edges - -	GL_Bind( tr.whiteImage ); -	qglEnable( GL_CULL_FACE ); -	GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); -	qglColor3f( 0.2f, 0.2f, 0.2f ); - -	// don't write to the color buffer -	qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); - -	qglEnable( GL_STENCIL_TEST ); -	qglStencilFunc( GL_ALWAYS, 1, 255 ); - -	// mirrors have the culling order reversed -	if ( backEnd.viewParms.isMirror ) { -		qglCullFace( GL_FRONT ); -		qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); - -		R_RenderShadowEdges(); - -		qglCullFace( GL_BACK ); -		qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); - -		R_RenderShadowEdges(); -	} else { -		qglCullFace( GL_BACK ); -		qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); - -		R_RenderShadowEdges(); - -		qglCullFace( GL_FRONT ); -		qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); - -		R_RenderShadowEdges(); -	} - - -	// reenable writing to the color buffer -	qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); -} - - -/* -================= -RB_ShadowFinish - -Darken everything that is is a shadow volume. -We have to delay this until everything has been shadowed, -because otherwise shadows from different body parts would -overlap and double darken. -================= -*/ -void RB_ShadowFinish( void ) { -	if ( r_shadows->integer != 2 ) { -		return; -	} -	if ( glConfig.stencilBits < 4 ) { -		return; -	} -	qglEnable( GL_STENCIL_TEST ); -	qglStencilFunc( GL_NOTEQUAL, 0, 255 ); - -	qglDisable (GL_CLIP_PLANE0); -	qglDisable (GL_CULL_FACE); - -	GL_Bind( tr.whiteImage ); - -    qglLoadIdentity (); - -	qglColor3f( 0.6f, 0.6f, 0.6f ); -	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO ); - -//	qglColor3f( 1, 0, 0 ); -//	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - -	qglBegin( GL_QUADS ); -	qglVertex3f( -100, 100, -10 ); -	qglVertex3f( 100, 100, -10 ); -	qglVertex3f( 100, -100, -10 ); -	qglVertex3f( -100, -100, -10 ); -	qglEnd (); - -	qglColor4f(1,1,1,1); -	qglDisable( GL_STENCIL_TEST ); -} - - -/* -================= -RB_ProjectionShadowDeform - -================= -*/ -void RB_ProjectionShadowDeform( void ) { -	float	*xyz; -	int		i; -	float	h; -	vec3_t	ground; -	vec3_t	light; -	float	groundDist; -	float	d; -	vec3_t	lightDir; - -	xyz = ( float * ) tess.xyz; - -	ground[0] = backEnd.or.axis[0][2]; -	ground[1] = backEnd.or.axis[1][2]; -	ground[2] = backEnd.or.axis[2][2]; - -	groundDist = backEnd.or.origin[2] - backEnd.currentEntity->e.shadowPlane; - -	VectorCopy( backEnd.currentEntity->lightDir, lightDir ); -	d = DotProduct( lightDir, ground ); -	// don't let the shadows get too long or go negative -	if ( d < 0.5 ) { -		VectorMA( lightDir, (0.5 - d), ground, lightDir ); -		d = DotProduct( lightDir, ground ); -	} -	d = 1.0 / d; - -	light[0] = lightDir[0] * d; -	light[1] = lightDir[1] * d; -	light[2] = lightDir[2] * d; - -	for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) { -		h = DotProduct( xyz, ground ) + groundDist; - -		xyz[0] -= light[0] * h; -		xyz[1] -= light[1] * h; -		xyz[2] -= light[2] * h; -	} -} diff --git a/ioq3-r437/src/renderer/tr_sky.c b/ioq3-r437/src/renderer/tr_sky.c deleted file mode 100644 index 02624f3d..00000000 --- a/ioq3-r437/src/renderer/tr_sky.c +++ /dev/null @@ -1,845 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_sky.c -#include "tr_local.h" - -#define SKY_SUBDIVISIONS		8 -#define HALF_SKY_SUBDIVISIONS	(SKY_SUBDIVISIONS/2) - -static float s_cloudTexCoords[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2]; -static float s_cloudTexP[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1]; - -/* -=================================================================================== - -POLYGON TO BOX SIDE PROJECTION - -=================================================================================== -*/ - -static vec3_t sky_clip[6] =  -{ -	{1,1,0}, -	{1,-1,0}, -	{0,-1,1}, -	{0,1,1}, -	{1,0,1}, -	{-1,0,1}  -}; - -static float	sky_mins[2][6], sky_maxs[2][6]; -static float	sky_min, sky_max; - -/* -================ -AddSkyPolygon -================ -*/ -static void AddSkyPolygon (int nump, vec3_t vecs)  -{ -	int		i,j; -	vec3_t	v, av; -	float	s, t, dv; -	int		axis; -	float	*vp; -	// s = [0]/[2], t = [1]/[2] -	static int	vec_to_st[6][3] = -	{ -		{-2,3,1}, -		{2,3,-1}, - -		{1,3,2}, -		{-1,3,-2}, - -		{-2,-1,3}, -		{-2,1,-3} - -	//	{-1,2,3}, -	//	{1,2,-3} -	}; - -	// decide which face it maps to -	VectorCopy (vec3_origin, v); -	for (i=0, vp=vecs ; i<nump ; i++, vp+=3) -	{ -		VectorAdd (vp, v, v); -	} -	av[0] = fabs(v[0]); -	av[1] = fabs(v[1]); -	av[2] = fabs(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++, vecs+=3) -	{ -		j = vec_to_st[axis][2]; -		if (j > 0) -			dv = vecs[j - 1]; -		else -			dv = -vecs[-j - 1]; -		if (dv < 0.001) -			continue;	// don't divide by zero -		j = vec_to_st[axis][0]; -		if (j < 0) -			s = -vecs[-j -1] / dv; -		else -			s = vecs[j-1] / dv; -		j = vec_to_st[axis][1]; -		if (j < 0) -			t = -vecs[-j -1] / dv; -		else -			t = vecs[j-1] / dv; - -		if (s < sky_mins[0][axis]) -			sky_mins[0][axis] = s; -		if (t < sky_mins[1][axis]) -			sky_mins[1][axis] = t; -		if (s > sky_maxs[0][axis]) -			sky_maxs[0][axis] = s; -		if (t > sky_maxs[1][axis]) -			sky_maxs[1][axis] = t; -	} -} - -#define	ON_EPSILON		0.1f			// point on plane side epsilon -#define	MAX_CLIP_VERTS	64 -/* -================ -ClipSkyPolygon -================ -*/ -static void ClipSkyPolygon (int nump, vec3_t vecs, int stage)  -{ -	float	*norm; -	float	*v; -	qboolean	front, back; -	float	d, e; -	float	dists[MAX_CLIP_VERTS]; -	int		sides[MAX_CLIP_VERTS]; -	vec3_t	newv[2][MAX_CLIP_VERTS]; -	int		newc[2]; -	int		i, j; - -	if (nump > MAX_CLIP_VERTS-2) -		ri.Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS"); -	if (stage == 6) -	{	// fully clipped, so draw it -		AddSkyPolygon (nump, vecs); -		return; -	} - -	front = back = qfalse; -	norm = sky_clip[stage]; -	for (i=0, v = vecs ; i<nump ; i++, v+=3) -	{ -		d = DotProduct (v, norm); -		if (d > ON_EPSILON) -		{ -			front = qtrue; -			sides[i] = SIDE_FRONT; -		} -		else if (d < -ON_EPSILON) -		{ -			back = qtrue; -			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]; -	VectorCopy (vecs, (vecs+(i*3)) ); -	newc[0] = newc[1] = 0; - -	for (i=0, v = vecs ; i<nump ; i++, v+=3) -	{ -		switch (sides[i]) -		{ -		case SIDE_FRONT: -			VectorCopy (v, newv[0][newc[0]]); -			newc[0]++; -			break; -		case SIDE_BACK: -			VectorCopy (v, newv[1][newc[1]]); -			newc[1]++; -			break; -		case SIDE_ON: -			VectorCopy (v, newv[0][newc[0]]); -			newc[0]++; -			VectorCopy (v, newv[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*(v[j+3] - v[j]); -			newv[0][newc[0]][j] = e; -			newv[1][newc[1]][j] = e; -		} -		newc[0]++; -		newc[1]++; -	} - -	// continue -	ClipSkyPolygon (newc[0], newv[0][0], stage+1); -	ClipSkyPolygon (newc[1], newv[1][0], stage+1); -} - -/* -============== -ClearSkyBox -============== -*/ -static void ClearSkyBox (void) { -	int		i; - -	for (i=0 ; i<6 ; i++) { -		sky_mins[0][i] = sky_mins[1][i] = 9999; -		sky_maxs[0][i] = sky_maxs[1][i] = -9999; -	} -} - -/* -================ -RB_ClipSkyPolygons -================ -*/ -void RB_ClipSkyPolygons( shaderCommands_t *input ) -{ -	vec3_t		p[5];	// need one extra point for clipping -	int			i, j; - -	ClearSkyBox(); - -	for ( i = 0; i < input->numIndexes; i += 3 ) -	{ -		for (j = 0 ; j < 3 ; j++)  -		{ -			VectorSubtract( input->xyz[input->indexes[i+j]], -							backEnd.viewParms.or.origin,  -							p[j] ); -		} -		ClipSkyPolygon( 3, p[0], 0 ); -	} -} - -/* -=================================================================================== - -CLOUD VERTEX GENERATION - -=================================================================================== -*/ - -/* -** MakeSkyVec -** -** Parms: s, t range from -1 to 1 -*/ -static void MakeSkyVec( float s, float t, int axis, float outSt[2], vec3_t outXYZ ) -{ -	// 1 = s, 2 = t, 3 = 2048 -	static int	st_to_vec[6][3] = -	{ -		{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 -	}; - -	vec3_t		b; -	int			j, k; -	float	boxSize; - -	boxSize = backEnd.viewParms.zFar / 1.75;		// div sqrt(3) -	b[0] = s*boxSize; -	b[1] = t*boxSize; -	b[2] = boxSize; - -	for (j=0 ; j<3 ; j++) -	{ -		k = st_to_vec[axis][j]; -		if (k < 0) -		{ -			outXYZ[j] = -b[-k - 1]; -		} -		else -		{ -			outXYZ[j] = b[k - 1]; -		} -	} - -	// avoid bilerp seam -	s = (s+1)*0.5; -	t = (t+1)*0.5; -	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.0 - t; - - -	if ( outSt ) -	{ -		outSt[0] = s; -		outSt[1] = t; -	} -} - -static int	sky_texorder[6] = {0,2,1,3,4,5}; -static vec3_t	s_skyPoints[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1]; -static float	s_skyTexCoords[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2]; - -static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] ) -{ -	int s, t; - -	GL_Bind( image ); - -	for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) -	{ -		qglBegin( GL_TRIANGLE_STRIP ); - -		for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) -		{ -			qglTexCoord2fv( s_skyTexCoords[t][s] ); -			qglVertex3fv( s_skyPoints[t][s] ); - -			qglTexCoord2fv( s_skyTexCoords[t+1][s] ); -			qglVertex3fv( s_skyPoints[t+1][s] ); -		} - -		qglEnd(); -	} -} - -static void DrawSkyBox( shader_t *shader ) -{ -	int		i; - -	sky_min = 0; -	sky_max = 1; - -	Com_Memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) ); - -	for (i=0 ; i<6 ; i++) -	{ -		int sky_mins_subd[2], sky_maxs_subd[2]; -		int s, t; - -		sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; -		sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; -		sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; -		sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - -		if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) || -			 ( sky_mins[1][i] >= sky_maxs[1][i] ) ) -		{ -			continue; -		} - -		sky_mins_subd[0] = sky_mins[0][i] * HALF_SKY_SUBDIVISIONS; -		sky_mins_subd[1] = sky_mins[1][i] * HALF_SKY_SUBDIVISIONS; -		sky_maxs_subd[0] = sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS; -		sky_maxs_subd[1] = sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS; - -		if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )  -			sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS; -		else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS )  -			sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS; -		if ( sky_mins_subd[1] < -HALF_SKY_SUBDIVISIONS ) -			sky_mins_subd[1] = -HALF_SKY_SUBDIVISIONS; -		else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS )  -			sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS; - -		if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS )  -			sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS; -		else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS )  -			sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS; -		if ( sky_maxs_subd[1] < -HALF_SKY_SUBDIVISIONS )  -			sky_maxs_subd[1] = -HALF_SKY_SUBDIVISIONS; -		else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS )  -			sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS; - -		// -		// iterate through the subdivisions -		// -		for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ ) -		{ -			for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ ) -			{ -				MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,  -							( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,  -							i,  -							s_skyTexCoords[t][s],  -							s_skyPoints[t][s] ); -			} -		} - -		DrawSkySide( shader->sky.outerbox[sky_texorder[i]], -			         sky_mins_subd, -					 sky_maxs_subd ); -	} - -} - -static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean addIndexes ) -{ -	int s, t; -	int vertexStart = tess.numVertexes; -	int tHeight, sWidth; - -	tHeight = maxs[1] - mins[1] + 1; -	sWidth = maxs[0] - mins[0] + 1; - -	for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) -	{ -		for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) -		{ -			VectorAdd( s_skyPoints[t][s], backEnd.viewParms.or.origin, tess.xyz[tess.numVertexes] ); -			tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0]; -			tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1]; - -			tess.numVertexes++; - -			if ( tess.numVertexes >= SHADER_MAX_VERTEXES ) -			{ -				ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in FillCloudySkySide()\n" ); -			} -		} -	} - -	// only add indexes for one pass, otherwise it would draw multiple times for each pass -	if ( addIndexes ) { -		for ( t = 0; t < tHeight-1; t++ ) -		{	 -			for ( s = 0; s < sWidth-1; s++ ) -			{ -				tess.indexes[tess.numIndexes] = vertexStart + s + t * ( sWidth ); -				tess.numIndexes++; -				tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth ); -				tess.numIndexes++; -				tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth ); -				tess.numIndexes++; - -				tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth ); -				tess.numIndexes++; -				tess.indexes[tess.numIndexes] = vertexStart + s + 1 + ( t + 1 ) * ( sWidth ); -				tess.numIndexes++; -				tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth ); -				tess.numIndexes++; -			} -		} -	} -} - -static void FillCloudBox( const shader_t *shader, int stage ) -{ -	int i; - -	for ( i =0; i < 6; i++ ) -	{ -		int sky_mins_subd[2], sky_maxs_subd[2]; -		int s, t; -		float MIN_T; - -		if ( 1 ) // FIXME? shader->sky.fullClouds ) -		{ -			MIN_T = -HALF_SKY_SUBDIVISIONS; - -			// still don't want to draw the bottom, even if fullClouds -			if ( i == 5 ) -				continue; -		} -		else -		{ -			switch( i ) -			{ -			case 0: -			case 1: -			case 2: -			case 3: -				MIN_T = -1; -				break; -			case 5: -				// don't draw clouds beneath you -				continue; -			case 4:		// top -			default: -				MIN_T = -HALF_SKY_SUBDIVISIONS; -				break; -			} -		} - -		sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; -		sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; -		sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; -		sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - -		if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) || -			 ( sky_mins[1][i] >= sky_maxs[1][i] ) ) -		{ -			continue; -		} - -		sky_mins_subd[0] = myftol( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ); -		sky_mins_subd[1] = myftol( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ); -		sky_maxs_subd[0] = myftol( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ); -		sky_maxs_subd[1] = myftol( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ); - -		if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )  -			sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS; -		else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS )  -			sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS; -		if ( sky_mins_subd[1] < MIN_T ) -			sky_mins_subd[1] = MIN_T; -		else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS )  -			sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS; - -		if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS )  -			sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS; -		else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS )  -			sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS; -		if ( sky_maxs_subd[1] < MIN_T ) -			sky_maxs_subd[1] = MIN_T; -		else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS )  -			sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS; - -		// -		// iterate through the subdivisions -		// -		for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ ) -		{ -			for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ ) -			{ -				MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,  -							( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,  -							i,  -							NULL, -							s_skyPoints[t][s] ); - -				s_skyTexCoords[t][s][0] = s_cloudTexCoords[i][t][s][0]; -				s_skyTexCoords[t][s][1] = s_cloudTexCoords[i][t][s][1]; -			} -		} - -		// only add indexes for first stage -		FillCloudySkySide( sky_mins_subd, sky_maxs_subd, ( stage == 0 ) ); -	} -} - -/* -** R_BuildCloudData -*/ -void R_BuildCloudData( shaderCommands_t *input ) -{ -	int			i; -	shader_t	*shader; - -	shader = input->shader; - -	assert( shader->isSky ); - -	sky_min = 1.0 / 256.0f;		// FIXME: not correct? -	sky_max = 255.0 / 256.0f; - -	// set up for drawing -	tess.numIndexes = 0; -	tess.numVertexes = 0; - -	if ( input->shader->sky.cloudHeight ) -	{ -		for ( i = 0; i < MAX_SHADER_STAGES; i++ ) -		{ -			if ( !tess.xstages[i] ) { -				break; -			} -			FillCloudBox( input->shader, i ); -		} -	} -} - -/* -** R_InitSkyTexCoords -** Called when a sky shader is parsed -*/ -#define SQR( a ) ((a)*(a)) -void R_InitSkyTexCoords( float heightCloud ) -{ -	int i, s, t; -	float radiusWorld = 4096; -	float p; -	float sRad, tRad; -	vec3_t skyVec; -	vec3_t v; - -	// init zfar so MakeSkyVec works even though -	// a world hasn't been bounded -	backEnd.viewParms.zFar = 1024; - -	for ( i = 0; i < 6; i++ ) -	{ -		for ( t = 0; t <= SKY_SUBDIVISIONS; t++ ) -		{ -			for ( s = 0; s <= SKY_SUBDIVISIONS; s++ ) -			{ -				// compute vector from view origin to sky side integral point -				MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,  -							( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,  -							i,  -							NULL, -							skyVec ); - -				// compute parametric value 'p' that intersects with cloud layer -				p = ( 1.0f / ( 2 * DotProduct( skyVec, skyVec ) ) ) * -					( -2 * skyVec[2] * radiusWorld +  -					   2 * sqrt( SQR( skyVec[2] ) * SQR( radiusWorld ) +  -					             2 * SQR( skyVec[0] ) * radiusWorld * heightCloud + -								 SQR( skyVec[0] ) * SQR( heightCloud ) +  -								 2 * SQR( skyVec[1] ) * radiusWorld * heightCloud + -								 SQR( skyVec[1] ) * SQR( heightCloud ) +  -								 2 * SQR( skyVec[2] ) * radiusWorld * heightCloud + -								 SQR( skyVec[2] ) * SQR( heightCloud ) ) ); - -				s_cloudTexP[i][t][s] = p; - -				// compute intersection point based on p -				VectorScale( skyVec, p, v ); -				v[2] += radiusWorld; - -				// compute vector from world origin to intersection point 'v' -				VectorNormalize( v ); - -				sRad = Q_acos( v[0] ); -				tRad = Q_acos( v[1] ); - -				s_cloudTexCoords[i][t][s][0] = sRad; -				s_cloudTexCoords[i][t][s][1] = tRad; -			} -		} -	} -} - -//====================================================================================== - -/* -** RB_DrawSun -*/ -void RB_DrawSun( void ) { -	float		size; -	float		dist; -	vec3_t		origin, vec1, vec2; -	vec3_t		temp; - -	if ( !backEnd.skyRenderedThisView ) { -		return; -	} -	if ( !r_drawSun->integer ) { -		return; -	} -	qglLoadMatrixf( backEnd.viewParms.world.modelMatrix ); -	qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); - -	dist = 	backEnd.viewParms.zFar / 1.75;		// div sqrt(3) -	size = dist * 0.4; - -	VectorScale( tr.sunDirection, dist, origin ); -	PerpendicularVector( vec1, tr.sunDirection ); -	CrossProduct( tr.sunDirection, vec1, vec2 ); - -	VectorScale( vec1, size, vec1 ); -	VectorScale( vec2, size, vec2 ); - -	// farthest depth range -	qglDepthRange( 1.0, 1.0 ); - -	// FIXME: use quad stamp -	RB_BeginSurface( tr.sunShader, tess.fogNum ); -		VectorCopy( origin, temp ); -		VectorSubtract( temp, vec1, temp ); -		VectorSubtract( temp, vec2, temp ); -		VectorCopy( temp, tess.xyz[tess.numVertexes] ); -		tess.texCoords[tess.numVertexes][0][0] = 0; -		tess.texCoords[tess.numVertexes][0][1] = 0; -		tess.vertexColors[tess.numVertexes][0] = 255; -		tess.vertexColors[tess.numVertexes][1] = 255; -		tess.vertexColors[tess.numVertexes][2] = 255; -		tess.numVertexes++; - -		VectorCopy( origin, temp ); -		VectorAdd( temp, vec1, temp ); -		VectorSubtract( temp, vec2, temp ); -		VectorCopy( temp, tess.xyz[tess.numVertexes] ); -		tess.texCoords[tess.numVertexes][0][0] = 0; -		tess.texCoords[tess.numVertexes][0][1] = 1; -		tess.vertexColors[tess.numVertexes][0] = 255; -		tess.vertexColors[tess.numVertexes][1] = 255; -		tess.vertexColors[tess.numVertexes][2] = 255; -		tess.numVertexes++; - -		VectorCopy( origin, temp ); -		VectorAdd( temp, vec1, temp ); -		VectorAdd( temp, vec2, temp ); -		VectorCopy( temp, tess.xyz[tess.numVertexes] ); -		tess.texCoords[tess.numVertexes][0][0] = 1; -		tess.texCoords[tess.numVertexes][0][1] = 1; -		tess.vertexColors[tess.numVertexes][0] = 255; -		tess.vertexColors[tess.numVertexes][1] = 255; -		tess.vertexColors[tess.numVertexes][2] = 255; -		tess.numVertexes++; - -		VectorCopy( origin, temp ); -		VectorSubtract( temp, vec1, temp ); -		VectorAdd( temp, vec2, temp ); -		VectorCopy( temp, tess.xyz[tess.numVertexes] ); -		tess.texCoords[tess.numVertexes][0][0] = 1; -		tess.texCoords[tess.numVertexes][0][1] = 0; -		tess.vertexColors[tess.numVertexes][0] = 255; -		tess.vertexColors[tess.numVertexes][1] = 255; -		tess.vertexColors[tess.numVertexes][2] = 255; -		tess.numVertexes++; - -		tess.indexes[tess.numIndexes++] = 0; -		tess.indexes[tess.numIndexes++] = 1; -		tess.indexes[tess.numIndexes++] = 2; -		tess.indexes[tess.numIndexes++] = 0; -		tess.indexes[tess.numIndexes++] = 2; -		tess.indexes[tess.numIndexes++] = 3; - -	RB_EndSurface(); - -	// back to normal depth range -	qglDepthRange( 0.0, 1.0 ); -} - - - - -/* -================ -RB_StageIteratorSky - -All of the visible sky triangles are in tess - -Other things could be stuck in here, like birds in the sky, etc -================ -*/ -void RB_StageIteratorSky( void ) { -	if ( r_fastsky->integer ) { -		return; -	} - -	// go through all the polygons and project them onto -	// the sky box to see which blocks on each side need -	// to be drawn -	RB_ClipSkyPolygons( &tess ); - -	// r_showsky will let all the sky blocks be drawn in -	// front of everything to allow developers to see how -	// much sky is getting sucked in -	if ( r_showsky->integer ) { -		qglDepthRange( 0.0, 0.0 ); -	} else { -		qglDepthRange( 1.0, 1.0 ); -	} - -	// draw the outer skybox -	if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) { -		qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight ); -		 -		qglPushMatrix (); -		GL_State( 0 ); -		qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); - -		DrawSkyBox( tess.shader ); - -		qglPopMatrix(); -	} - -	// generate the vertexes for all the clouds, which will be drawn -	// by the generic shader routine -	R_BuildCloudData( &tess ); - -	RB_StageIteratorGeneric(); - -	// draw the inner skybox - - -	// back to normal depth range -	qglDepthRange( 0.0, 1.0 ); - -	// note that sky was drawn so we will draw a sun later -	backEnd.skyRenderedThisView = qtrue; -} - diff --git a/ioq3-r437/src/renderer/tr_surface.c b/ioq3-r437/src/renderer/tr_surface.c deleted file mode 100644 index c95e6b25..00000000 --- a/ioq3-r437/src/renderer/tr_surface.c +++ /dev/null @@ -1,1307 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// tr_surf.c -#include "tr_local.h" -#if idppc_altivec && !defined(MACOS_X) -#include <altivec.h> -#endif - -/* - -  THIS ENTIRE FILE IS BACK END - -backEnd.currentEntity will be valid. - -Tess_Begin has already been called for the surface's shader. - -The modelview matrix will be set. - -It is safe to actually issue drawing commands here if you don't want to -use the shader system. -*/ - - -//============================================================================ - - -/* -============== -RB_CheckOverflow -============== -*/ -void RB_CheckOverflow( int verts, int indexes ) { -	if (tess.numVertexes + verts < SHADER_MAX_VERTEXES -		&& tess.numIndexes + indexes < SHADER_MAX_INDEXES) { -		return; -	} - -	RB_EndSurface(); - -	if ( verts >= SHADER_MAX_VERTEXES ) { -		ri.Error(ERR_DROP, "RB_CheckOverflow: verts > MAX (%d > %d)", verts, SHADER_MAX_VERTEXES ); -	} -	if ( indexes >= SHADER_MAX_INDEXES ) { -		ri.Error(ERR_DROP, "RB_CheckOverflow: indices > MAX (%d > %d)", indexes, SHADER_MAX_INDEXES ); -	} - -	RB_BeginSurface(tess.shader, tess.fogNum ); -} - - -/* -============== -RB_AddQuadStampExt -============== -*/ -void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, byte *color, float s1, float t1, float s2, float t2 ) { -	vec3_t		normal; -	int			ndx; - -	RB_CHECKOVERFLOW( 4, 6 ); - -	ndx = tess.numVertexes; - -	// triangle indexes for a simple quad -	tess.indexes[ tess.numIndexes ] = ndx; -	tess.indexes[ tess.numIndexes + 1 ] = ndx + 1; -	tess.indexes[ tess.numIndexes + 2 ] = ndx + 3; - -	tess.indexes[ tess.numIndexes + 3 ] = ndx + 3; -	tess.indexes[ tess.numIndexes + 4 ] = ndx + 1; -	tess.indexes[ tess.numIndexes + 5 ] = ndx + 2; - -	tess.xyz[ndx][0] = origin[0] + left[0] + up[0]; -	tess.xyz[ndx][1] = origin[1] + left[1] + up[1]; -	tess.xyz[ndx][2] = origin[2] + left[2] + up[2]; - -	tess.xyz[ndx+1][0] = origin[0] - left[0] + up[0]; -	tess.xyz[ndx+1][1] = origin[1] - left[1] + up[1]; -	tess.xyz[ndx+1][2] = origin[2] - left[2] + up[2]; - -	tess.xyz[ndx+2][0] = origin[0] - left[0] - up[0]; -	tess.xyz[ndx+2][1] = origin[1] - left[1] - up[1]; -	tess.xyz[ndx+2][2] = origin[2] - left[2] - up[2]; - -	tess.xyz[ndx+3][0] = origin[0] + left[0] - up[0]; -	tess.xyz[ndx+3][1] = origin[1] + left[1] - up[1]; -	tess.xyz[ndx+3][2] = origin[2] + left[2] - up[2]; - - -	// constant normal all the way around -	VectorSubtract( vec3_origin, backEnd.viewParms.or.axis[0], normal ); - -	tess.normal[ndx][0] = tess.normal[ndx+1][0] = tess.normal[ndx+2][0] = tess.normal[ndx+3][0] = normal[0]; -	tess.normal[ndx][1] = tess.normal[ndx+1][1] = tess.normal[ndx+2][1] = tess.normal[ndx+3][1] = normal[1]; -	tess.normal[ndx][2] = tess.normal[ndx+1][2] = tess.normal[ndx+2][2] = tess.normal[ndx+3][2] = normal[2]; -	 -	// standard square texture coordinates -	tess.texCoords[ndx][0][0] = tess.texCoords[ndx][1][0] = s1; -	tess.texCoords[ndx][0][1] = tess.texCoords[ndx][1][1] = t1; - -	tess.texCoords[ndx+1][0][0] = tess.texCoords[ndx+1][1][0] = s2; -	tess.texCoords[ndx+1][0][1] = tess.texCoords[ndx+1][1][1] = t1; - -	tess.texCoords[ndx+2][0][0] = tess.texCoords[ndx+2][1][0] = s2; -	tess.texCoords[ndx+2][0][1] = tess.texCoords[ndx+2][1][1] = t2; - -	tess.texCoords[ndx+3][0][0] = tess.texCoords[ndx+3][1][0] = s1; -	tess.texCoords[ndx+3][0][1] = tess.texCoords[ndx+3][1][1] = t2; - -	// constant color all the way around -	// should this be identity and let the shader specify from entity? -	* ( unsigned int * ) &tess.vertexColors[ndx] =  -	* ( unsigned int * ) &tess.vertexColors[ndx+1] =  -	* ( unsigned int * ) &tess.vertexColors[ndx+2] =  -	* ( unsigned int * ) &tess.vertexColors[ndx+3] =  -		* ( unsigned int * )color; - - -	tess.numVertexes += 4; -	tess.numIndexes += 6; -} - -/* -============== -RB_AddQuadStamp -============== -*/ -void RB_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, byte *color ) { -	RB_AddQuadStampExt( origin, left, up, color, 0, 0, 1, 1 ); -} - -/* -============== -RB_SurfaceSprite -============== -*/ -static void RB_SurfaceSprite( void ) { -	vec3_t		left, up; -	float		radius; - -	// calculate the xyz locations for the four corners -	radius = backEnd.currentEntity->e.radius; -	if ( backEnd.currentEntity->e.rotation == 0 ) { -		VectorScale( backEnd.viewParms.or.axis[1], radius, left ); -		VectorScale( backEnd.viewParms.or.axis[2], radius, up ); -	} else { -		float	s, c; -		float	ang; -		 -		ang = M_PI * backEnd.currentEntity->e.rotation / 180; -		s = sin( ang ); -		c = cos( ang ); - -		VectorScale( backEnd.viewParms.or.axis[1], c * radius, left ); -		VectorMA( left, -s * radius, backEnd.viewParms.or.axis[2], left ); - -		VectorScale( backEnd.viewParms.or.axis[2], c * radius, up ); -		VectorMA( up, s * radius, backEnd.viewParms.or.axis[1], up ); -	} -	if ( backEnd.viewParms.isMirror ) { -		VectorSubtract( vec3_origin, left, left ); -	} - -	RB_AddQuadStamp( backEnd.currentEntity->e.origin, left, up, backEnd.currentEntity->e.shaderRGBA ); -} - - -/* -============= -RB_SurfacePolychain -============= -*/ -void RB_SurfacePolychain( srfPoly_t *p ) { -	int		i; -	int		numv; - -	RB_CHECKOVERFLOW( p->numVerts, 3*(p->numVerts - 2) ); - -	// fan triangles into the tess array -	numv = tess.numVertexes; -	for ( i = 0; i < p->numVerts; i++ ) { -		VectorCopy( p->verts[i].xyz, tess.xyz[numv] ); -		tess.texCoords[numv][0][0] = p->verts[i].st[0]; -		tess.texCoords[numv][0][1] = p->verts[i].st[1]; -		*(int *)&tess.vertexColors[numv] = *(int *)p->verts[ i ].modulate; - -		numv++; -	} - -	// generate fan indexes into the tess array -	for ( i = 0; i < p->numVerts-2; i++ ) { -		tess.indexes[tess.numIndexes + 0] = tess.numVertexes; -		tess.indexes[tess.numIndexes + 1] = tess.numVertexes + i + 1; -		tess.indexes[tess.numIndexes + 2] = tess.numVertexes + i + 2; -		tess.numIndexes += 3; -	} - -	tess.numVertexes = numv; -} - - -/* -============= -RB_SurfaceTriangles -============= -*/ -void RB_SurfaceTriangles( srfTriangles_t *srf ) { -	int			i; -	drawVert_t	*dv; -	float		*xyz, *normal, *texCoords; -	byte		*color; -	int			dlightBits; -	qboolean	needsNormal; - -	dlightBits = srf->dlightBits[backEnd.smpFrame]; -	tess.dlightBits |= dlightBits; - -	RB_CHECKOVERFLOW( srf->numVerts, srf->numIndexes ); - -	for ( i = 0 ; i < srf->numIndexes ; i += 3 ) { -		tess.indexes[ tess.numIndexes + i + 0 ] = tess.numVertexes + srf->indexes[ i + 0 ]; -		tess.indexes[ tess.numIndexes + i + 1 ] = tess.numVertexes + srf->indexes[ i + 1 ]; -		tess.indexes[ tess.numIndexes + i + 2 ] = tess.numVertexes + srf->indexes[ i + 2 ]; -	} -	tess.numIndexes += srf->numIndexes; - -	dv = srf->verts; -	xyz = tess.xyz[ tess.numVertexes ]; -	normal = tess.normal[ tess.numVertexes ]; -	texCoords = tess.texCoords[ tess.numVertexes ][0]; -	color = tess.vertexColors[ tess.numVertexes ]; -	needsNormal = tess.shader->needsNormal; - -	for ( i = 0 ; i < srf->numVerts ; i++, dv++, xyz += 4, normal += 4, texCoords += 4, color += 4 ) { -		xyz[0] = dv->xyz[0]; -		xyz[1] = dv->xyz[1]; -		xyz[2] = dv->xyz[2]; - -		if ( needsNormal ) { -			normal[0] = dv->normal[0]; -			normal[1] = dv->normal[1]; -			normal[2] = dv->normal[2]; -		} - -		texCoords[0] = dv->st[0]; -		texCoords[1] = dv->st[1]; - -		texCoords[2] = dv->lightmap[0]; -		texCoords[3] = dv->lightmap[1]; - -		*(int *)color = *(int *)dv->color; -	} - -	for ( i = 0 ; i < srf->numVerts ; i++ ) { -		tess.vertexDlightBits[ tess.numVertexes + i] = dlightBits; -	} - -	tess.numVertexes += srf->numVerts; -} - - - -/* -============== -RB_SurfaceBeam -============== -*/ -void RB_SurfaceBeam( void )  -{ -#define NUM_BEAM_SEGS 6 -	refEntity_t *e; -	int	i; -	vec3_t perpvec; -	vec3_t direction, normalized_direction; -	vec3_t	start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS]; -	vec3_t oldorigin, origin; - -	e = &backEnd.currentEntity->e; - -	oldorigin[0] = e->oldorigin[0]; -	oldorigin[1] = e->oldorigin[1]; -	oldorigin[2] = e->oldorigin[2]; - -	origin[0] = e->origin[0]; -	origin[1] = e->origin[1]; -	origin[2] = e->origin[2]; - -	normalized_direction[0] = direction[0] = oldorigin[0] - origin[0]; -	normalized_direction[1] = direction[1] = oldorigin[1] - origin[1]; -	normalized_direction[2] = direction[2] = oldorigin[2] - origin[2]; - -	if ( VectorNormalize( normalized_direction ) == 0 ) -		return; - -	PerpendicularVector( perpvec, normalized_direction ); - -	VectorScale( perpvec, 4, perpvec ); - -	for ( i = 0; i < NUM_BEAM_SEGS ; i++ ) -	{ -		RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i ); -//		VectorAdd( start_points[i], origin, start_points[i] ); -		VectorAdd( start_points[i], direction, end_points[i] ); -	} - -	GL_Bind( tr.whiteImage ); - -	GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - -	qglColor3f( 1, 0, 0 ); - -	qglBegin( GL_TRIANGLE_STRIP ); -	for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) { -		qglVertex3fv( start_points[ i % NUM_BEAM_SEGS] ); -		qglVertex3fv( end_points[ i % NUM_BEAM_SEGS] ); -	} -	qglEnd(); -} - -//================================================================================ - -static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, float len, float spanWidth ) -{ -	float		spanWidth2; -	int			vbase; -	float		t = len / 256.0f; - -	vbase = tess.numVertexes; - -	spanWidth2 = -spanWidth; - -	// FIXME: use quad stamp? -	VectorMA( start, spanWidth, up, tess.xyz[tess.numVertexes] ); -	tess.texCoords[tess.numVertexes][0][0] = 0; -	tess.texCoords[tess.numVertexes][0][1] = 0; -	tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 0.25; -	tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 0.25; -	tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 0.25; -	tess.numVertexes++; - -	VectorMA( start, spanWidth2, up, tess.xyz[tess.numVertexes] ); -	tess.texCoords[tess.numVertexes][0][0] = 0; -	tess.texCoords[tess.numVertexes][0][1] = 1; -	tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; -	tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; -	tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; -	tess.numVertexes++; - -	VectorMA( end, spanWidth, up, tess.xyz[tess.numVertexes] ); - -	tess.texCoords[tess.numVertexes][0][0] = t; -	tess.texCoords[tess.numVertexes][0][1] = 0; -	tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; -	tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; -	tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; -	tess.numVertexes++; - -	VectorMA( end, spanWidth2, up, tess.xyz[tess.numVertexes] ); -	tess.texCoords[tess.numVertexes][0][0] = t; -	tess.texCoords[tess.numVertexes][0][1] = 1; -	tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; -	tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; -	tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; -	tess.numVertexes++; - -	tess.indexes[tess.numIndexes++] = vbase; -	tess.indexes[tess.numIndexes++] = vbase + 1; -	tess.indexes[tess.numIndexes++] = vbase + 2; - -	tess.indexes[tess.numIndexes++] = vbase + 2; -	tess.indexes[tess.numIndexes++] = vbase + 1; -	tess.indexes[tess.numIndexes++] = vbase + 3; -} - -static void DoRailDiscs( int numSegs, const vec3_t start, const vec3_t dir, const vec3_t right, const vec3_t up ) -{ -	int i; -	vec3_t	pos[4]; -	vec3_t	v; -	int		spanWidth = r_railWidth->integer; -	float c, s; -	float		scale; - -	if ( numSegs > 1 ) -		numSegs--; -	if ( !numSegs ) -		return; - -	scale = 0.25; - -	for ( i = 0; i < 4; i++ ) -	{ -		c = cos( DEG2RAD( 45 + i * 90 ) ); -		s = sin( DEG2RAD( 45 + i * 90 ) ); -		v[0] = ( right[0] * c + up[0] * s ) * scale * spanWidth; -		v[1] = ( right[1] * c + up[1] * s ) * scale * spanWidth; -		v[2] = ( right[2] * c + up[2] * s ) * scale * spanWidth; -		VectorAdd( start, v, pos[i] ); - -		if ( numSegs > 1 ) -		{ -			// offset by 1 segment if we're doing a long distance shot -			VectorAdd( pos[i], dir, pos[i] ); -		} -	} - -	for ( i = 0; i < numSegs; i++ ) -	{ -		int j; - -		RB_CHECKOVERFLOW( 4, 6 ); - -		for ( j = 0; j < 4; j++ ) -		{ -			VectorCopy( pos[j], tess.xyz[tess.numVertexes] ); -			tess.texCoords[tess.numVertexes][0][0] = ( j < 2 ); -			tess.texCoords[tess.numVertexes][0][1] = ( j && j != 3 ); -			tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; -			tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; -			tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; -			tess.numVertexes++; - -			VectorAdd( pos[j], dir, pos[j] ); -		} - -		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 0; -		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1; -		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3; -		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3; -		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1; -		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 2; -	} -} - -/* -** RB_SurfaceRailRinges -*/ -void RB_SurfaceRailRings( void ) { -	refEntity_t *e; -	int			numSegs; -	int			len; -	vec3_t		vec; -	vec3_t		right, up; -	vec3_t		start, end; - -	e = &backEnd.currentEntity->e; - -	VectorCopy( e->oldorigin, start ); -	VectorCopy( e->origin, end ); - -	// compute variables -	VectorSubtract( end, start, vec ); -	len = VectorNormalize( vec ); -	MakeNormalVectors( vec, right, up ); -	numSegs = ( len ) / r_railSegmentLength->value; -	if ( numSegs <= 0 ) { -		numSegs = 1; -	} - -	VectorScale( vec, r_railSegmentLength->value, vec ); - -	DoRailDiscs( numSegs, start, vec, right, up ); -} - -/* -** RB_SurfaceRailCore -*/ -void RB_SurfaceRailCore( void ) { -	refEntity_t *e; -	int			len; -	vec3_t		right; -	vec3_t		vec; -	vec3_t		start, end; -	vec3_t		v1, v2; - -	e = &backEnd.currentEntity->e; - -	VectorCopy( e->oldorigin, start ); -	VectorCopy( e->origin, end ); - -	VectorSubtract( end, start, vec ); -	len = VectorNormalize( vec ); - -	// compute side vector -	VectorSubtract( start, backEnd.viewParms.or.origin, v1 ); -	VectorNormalize( v1 ); -	VectorSubtract( end, backEnd.viewParms.or.origin, v2 ); -	VectorNormalize( v2 ); -	CrossProduct( v1, v2, right ); -	VectorNormalize( right ); - -	DoRailCore( start, end, right, len, r_railCoreWidth->integer ); -} - -/* -** RB_SurfaceLightningBolt -*/ -void RB_SurfaceLightningBolt( void ) { -	refEntity_t *e; -	int			len; -	vec3_t		right; -	vec3_t		vec; -	vec3_t		start, end; -	vec3_t		v1, v2; -	int			i; - -	e = &backEnd.currentEntity->e; - -	VectorCopy( e->oldorigin, end ); -	VectorCopy( e->origin, start ); - -	// compute variables -	VectorSubtract( end, start, vec ); -	len = VectorNormalize( vec ); - -	// compute side vector -	VectorSubtract( start, backEnd.viewParms.or.origin, v1 ); -	VectorNormalize( v1 ); -	VectorSubtract( end, backEnd.viewParms.or.origin, v2 ); -	VectorNormalize( v2 ); -	CrossProduct( v1, v2, right ); -	VectorNormalize( right ); - -	for ( i = 0 ; i < 4 ; i++ ) { -		vec3_t	temp; - -		DoRailCore( start, end, right, len, 8 ); -		RotatePointAroundVector( temp, vec, right, 45 ); -		VectorCopy( temp, right ); -	} -} - -/* -** VectorArrayNormalize -* -* The inputs to this routing seem to always be close to length = 1.0 (about 0.6 to 2.0) -* This means that we don't have to worry about zero length or enormously long vectors. -*/ -static void VectorArrayNormalize(vec4_t *normals, unsigned int count) -{ -//    assert(count); -         -#if idppc -    { -        register float half = 0.5; -        register float one  = 1.0; -        float *components = (float *)normals; -         -        // Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction, -        // runs *much* faster than calling sqrt().  We'll use a single Newton-Raphson -        // refinement step to get a little more precision.  This seems to yeild results -        // that are correct to 3 decimal places and usually correct to at least 4 (sometimes 5). -        // (That is, for the given input range of about 0.6 to 2.0). -        do { -            float x, y, z; -            float B, y0, y1; -             -            x = components[0]; -            y = components[1]; -            z = components[2]; -            components += 4; -            B = x*x + y*y + z*z; - -#ifdef __GNUC__             -            asm("frsqrte %0,%1" : "=f" (y0) : "f" (B)); -#else -			y0 = __frsqrte(B); -#endif -            y1 = y0 + half*y0*(one - B*y0*y0); - -            x = x * y1; -            y = y * y1; -            components[-4] = x; -            z = z * y1; -            components[-3] = y; -            components[-2] = z; -        } while(count--); -    } -#else // No assembly version for this architecture, or C_ONLY defined -	// given the input, it's safe to call VectorNormalizeFast -    while (count--) { -        VectorNormalizeFast(normals[0]); -        normals++; -    } -#endif - -} - - - -/* -** LerpMeshVertexes -*/ -#if idppc_altivec -static void LerpMeshVertexes_altivec(md3Surface_t *surf, float backlerp) -{ -	short	*oldXyz, *newXyz, *oldNormals, *newNormals; -	float	*outXyz, *outNormal; -	float	oldXyzScale ALIGN(16); -	float   newXyzScale ALIGN(16); -	float	oldNormalScale ALIGN(16); -	float newNormalScale ALIGN(16); -	int		vertNum; -	unsigned lat, lng; -	int		numVerts; - -	outXyz = tess.xyz[tess.numVertexes]; -	outNormal = tess.normal[tess.numVertexes]; - -	newXyz = (short *)((byte *)surf + surf->ofsXyzNormals) -		+ (backEnd.currentEntity->e.frame * surf->numVerts * 4); -	newNormals = newXyz + 3; - -	newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp); -	newNormalScale = 1.0 - backlerp; - -	numVerts = surf->numVerts; - -	if ( backlerp == 0 ) { -		vector signed short newNormalsVec0; -		vector signed short newNormalsVec1; -		vector signed int newNormalsIntVec; -		vector float newNormalsFloatVec; -		vector float newXyzScaleVec; -		vector unsigned char newNormalsLoadPermute; -		vector unsigned char newNormalsStorePermute; -		vector float zero; -		 -		newNormalsStorePermute = vec_lvsl(0,(float *)&newXyzScaleVec); -		newXyzScaleVec = *(vector float *)&newXyzScale; -		newXyzScaleVec = vec_perm(newXyzScaleVec,newXyzScaleVec,newNormalsStorePermute); -		newXyzScaleVec = vec_splat(newXyzScaleVec,0);		 -		newNormalsLoadPermute = vec_lvsl(0,newXyz); -		newNormalsStorePermute = vec_lvsr(0,outXyz); -		zero = (vector float)vec_splat_s8(0); -		// -		// just copy the vertexes -		// -		for (vertNum=0 ; vertNum < numVerts ; vertNum++, -			newXyz += 4, newNormals += 4, -			outXyz += 4, outNormal += 4)  -		{ -			newNormalsLoadPermute = vec_lvsl(0,newXyz); -			newNormalsStorePermute = vec_lvsr(0,outXyz); -			newNormalsVec0 = vec_ld(0,newXyz); -			newNormalsVec1 = vec_ld(16,newXyz); -			newNormalsVec0 = vec_perm(newNormalsVec0,newNormalsVec1,newNormalsLoadPermute); -			newNormalsIntVec = vec_unpackh(newNormalsVec0); -			newNormalsFloatVec = vec_ctf(newNormalsIntVec,0); -			newNormalsFloatVec = vec_madd(newNormalsFloatVec,newXyzScaleVec,zero); -			newNormalsFloatVec = vec_perm(newNormalsFloatVec,newNormalsFloatVec,newNormalsStorePermute); -			//outXyz[0] = newXyz[0] * newXyzScale; -			//outXyz[1] = newXyz[1] * newXyzScale; -			//outXyz[2] = newXyz[2] * newXyzScale; - -			lat = ( newNormals[0] >> 8 ) & 0xff; -			lng = ( newNormals[0] & 0xff ); -			lat *= (FUNCTABLE_SIZE/256); -			lng *= (FUNCTABLE_SIZE/256); - -			// decode X as cos( lat ) * sin( long ) -			// decode Y as sin( lat ) * sin( long ) -			// decode Z as cos( long ) - -			outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; -			outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; -			outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - -			vec_ste(newNormalsFloatVec,0,outXyz); -			vec_ste(newNormalsFloatVec,4,outXyz); -			vec_ste(newNormalsFloatVec,8,outXyz); -		} -	} else { -		// -		// interpolate and copy the vertex and normal -		// -		oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals) -			+ (backEnd.currentEntity->e.oldframe * surf->numVerts * 4); -		oldNormals = oldXyz + 3; - -		oldXyzScale = MD3_XYZ_SCALE * backlerp; -		oldNormalScale = backlerp; - -		for (vertNum=0 ; vertNum < numVerts ; vertNum++, -			oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4, -			outXyz += 4, outNormal += 4)  -		{ -			vec3_t uncompressedOldNormal, uncompressedNewNormal; - -			// interpolate the xyz -			outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale; -			outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale; -			outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale; - -			// FIXME: interpolate lat/long instead? -			lat = ( newNormals[0] >> 8 ) & 0xff; -			lng = ( newNormals[0] & 0xff ); -			lat *= 4; -			lng *= 4; -			uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; -			uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; -			uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - -			lat = ( oldNormals[0] >> 8 ) & 0xff; -			lng = ( oldNormals[0] & 0xff ); -			lat *= 4; -			lng *= 4; - -			uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; -			uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; -			uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - -			outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale; -			outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale; -			outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale; - -//			VectorNormalize (outNormal); -		} -    	VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts); -   	} -} -#endif - -static void LerpMeshVertexes_scalar(md3Surface_t *surf, float backlerp) -{ -	short	*oldXyz, *newXyz, *oldNormals, *newNormals; -	float	*outXyz, *outNormal; -	float	oldXyzScale, newXyzScale; -	float	oldNormalScale, newNormalScale; -	int		vertNum; -	unsigned lat, lng; -	int		numVerts; - -	outXyz = tess.xyz[tess.numVertexes]; -	outNormal = tess.normal[tess.numVertexes]; - -	newXyz = (short *)((byte *)surf + surf->ofsXyzNormals) -		+ (backEnd.currentEntity->e.frame * surf->numVerts * 4); -	newNormals = newXyz + 3; - -	newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp); -	newNormalScale = 1.0 - backlerp; - -	numVerts = surf->numVerts; - -	if ( backlerp == 0 ) { -		// -		// just copy the vertexes -		// -		for (vertNum=0 ; vertNum < numVerts ; vertNum++, -			newXyz += 4, newNormals += 4, -			outXyz += 4, outNormal += 4)  -		{ - -			outXyz[0] = newXyz[0] * newXyzScale; -			outXyz[1] = newXyz[1] * newXyzScale; -			outXyz[2] = newXyz[2] * newXyzScale; - -			lat = ( newNormals[0] >> 8 ) & 0xff; -			lng = ( newNormals[0] & 0xff ); -			lat *= (FUNCTABLE_SIZE/256); -			lng *= (FUNCTABLE_SIZE/256); - -			// decode X as cos( lat ) * sin( long ) -			// decode Y as sin( lat ) * sin( long ) -			// decode Z as cos( long ) - -			outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; -			outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; -			outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; -		} -	} else { -		// -		// interpolate and copy the vertex and normal -		// -		oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals) -			+ (backEnd.currentEntity->e.oldframe * surf->numVerts * 4); -		oldNormals = oldXyz + 3; - -		oldXyzScale = MD3_XYZ_SCALE * backlerp; -		oldNormalScale = backlerp; - -		for (vertNum=0 ; vertNum < numVerts ; vertNum++, -			oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4, -			outXyz += 4, outNormal += 4)  -		{ -			vec3_t uncompressedOldNormal, uncompressedNewNormal; - -			// interpolate the xyz -			outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale; -			outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale; -			outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale; - -			// FIXME: interpolate lat/long instead? -			lat = ( newNormals[0] >> 8 ) & 0xff; -			lng = ( newNormals[0] & 0xff ); -			lat *= 4; -			lng *= 4; -			uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; -			uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; -			uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - -			lat = ( oldNormals[0] >> 8 ) & 0xff; -			lng = ( oldNormals[0] & 0xff ); -			lat *= 4; -			lng *= 4; - -			uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; -			uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; -			uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - -			outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale; -			outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale; -			outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale; - -//			VectorNormalize (outNormal); -		} -    	VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts); -   	} -} - -static void LerpMeshVertexes(md3Surface_t *surf, float backlerp) -{ -#if idppc_altivec -	if (com_altivec->integer) { -		// must be in a seperate function or G3 systems will crash. -		LerpMeshVertexes_altivec( surf, backlerp ); -		return; -	} -#endif // idppc_altivec -	LerpMeshVertexes_scalar( surf, backlerp ); -} - - -/* -============= -RB_SurfaceMesh -============= -*/ -void RB_SurfaceMesh(md3Surface_t *surface) { -	int				j; -	float			backlerp; -	int				*triangles; -	float			*texCoords; -	int				indexes; -	int				Bob, Doug; -	int				numVerts; - -	if (  backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) { -		backlerp = 0; -	} else  { -		backlerp = backEnd.currentEntity->e.backlerp; -	} - -	RB_CHECKOVERFLOW( surface->numVerts, surface->numTriangles*3 ); - -	LerpMeshVertexes (surface, backlerp); - -	triangles = (int *) ((byte *)surface + surface->ofsTriangles); -	indexes = surface->numTriangles * 3; -	Bob = tess.numIndexes; -	Doug = tess.numVertexes; -	for (j = 0 ; j < indexes ; j++) { -		tess.indexes[Bob + j] = Doug + triangles[j]; -	} -	tess.numIndexes += indexes; - -	texCoords = (float *) ((byte *)surface + surface->ofsSt); - -	numVerts = surface->numVerts; -	for ( j = 0; j < numVerts; j++ ) { -		tess.texCoords[Doug + j][0][0] = texCoords[j*2+0]; -		tess.texCoords[Doug + j][0][1] = texCoords[j*2+1]; -		// FIXME: fill in lightmapST for completeness? -	} - -	tess.numVertexes += surface->numVerts; - -} - - -/* -============== -RB_SurfaceFace -============== -*/ -void RB_SurfaceFace( srfSurfaceFace_t *surf ) { -	int			i; -	unsigned	*indices, *tessIndexes; -	float		*v; -	float		*normal; -	int			ndx; -	int			Bob; -	int			numPoints; -	int			dlightBits; - -	RB_CHECKOVERFLOW( surf->numPoints, surf->numIndices ); - -	dlightBits = surf->dlightBits[backEnd.smpFrame]; -	tess.dlightBits |= dlightBits; - -	indices = ( unsigned * ) ( ( ( char  * ) surf ) + surf->ofsIndices ); - -	Bob = tess.numVertexes; -	tessIndexes = tess.indexes + tess.numIndexes; -	for ( i = surf->numIndices-1 ; i >= 0  ; i-- ) { -		tessIndexes[i] = indices[i] + Bob; -	} - -	tess.numIndexes += surf->numIndices; - -	v = surf->points[0]; - -	ndx = tess.numVertexes; - -	numPoints = surf->numPoints; - -	if ( tess.shader->needsNormal ) { -		normal = surf->plane.normal; -		for ( i = 0, ndx = tess.numVertexes; i < numPoints; i++, ndx++ ) { -			VectorCopy( normal, tess.normal[ndx] ); -		} -	} - -	for ( i = 0, v = surf->points[0], ndx = tess.numVertexes; i < numPoints; i++, v += VERTEXSIZE, ndx++ ) { -		VectorCopy( v, tess.xyz[ndx]); -		tess.texCoords[ndx][0][0] = v[3]; -		tess.texCoords[ndx][0][1] = v[4]; -		tess.texCoords[ndx][1][0] = v[5]; -		tess.texCoords[ndx][1][1] = v[6]; -		* ( unsigned int * ) &tess.vertexColors[ndx] = * ( unsigned int * ) &v[7]; -		tess.vertexDlightBits[ndx] = dlightBits; -	} - - -	tess.numVertexes += surf->numPoints; -} - - -static float	LodErrorForVolume( vec3_t local, float radius ) { -	vec3_t		world; -	float		d; - -	// never let it go negative -	if ( r_lodCurveError->value < 0 ) { -		return 0; -	} - -	world[0] = local[0] * backEnd.or.axis[0][0] + local[1] * backEnd.or.axis[1][0] +  -		local[2] * backEnd.or.axis[2][0] + backEnd.or.origin[0]; -	world[1] = local[0] * backEnd.or.axis[0][1] + local[1] * backEnd.or.axis[1][1] +  -		local[2] * backEnd.or.axis[2][1] + backEnd.or.origin[1]; -	world[2] = local[0] * backEnd.or.axis[0][2] + local[1] * backEnd.or.axis[1][2] +  -		local[2] * backEnd.or.axis[2][2] + backEnd.or.origin[2]; - -	VectorSubtract( world, backEnd.viewParms.or.origin, world ); -	d = DotProduct( world, backEnd.viewParms.or.axis[0] ); - -	if ( d < 0 ) { -		d = -d; -	} -	d -= radius; -	if ( d < 1 ) { -		d = 1; -	} - -	return r_lodCurveError->value / d; -} - -/* -============= -RB_SurfaceGrid - -Just copy the grid of points and triangulate -============= -*/ -void RB_SurfaceGrid( srfGridMesh_t *cv ) { -	int		i, j; -	float	*xyz; -	float	*texCoords; -	float	*normal; -	unsigned char *color; -	drawVert_t	*dv; -	int		rows, irows, vrows; -	int		used; -	int		widthTable[MAX_GRID_SIZE]; -	int		heightTable[MAX_GRID_SIZE]; -	float	lodError; -	int		lodWidth, lodHeight; -	int		numVertexes; -	int		dlightBits; -	int		*vDlightBits; -	qboolean	needsNormal; - -	dlightBits = cv->dlightBits[backEnd.smpFrame]; -	tess.dlightBits |= dlightBits; - -	// determine the allowable discrepance -	lodError = LodErrorForVolume( cv->lodOrigin, cv->lodRadius ); - -	// determine which rows and columns of the subdivision -	// we are actually going to use -	widthTable[0] = 0; -	lodWidth = 1; -	for ( i = 1 ; i < cv->width-1 ; i++ ) { -		if ( cv->widthLodError[i] <= lodError ) { -			widthTable[lodWidth] = i; -			lodWidth++; -		} -	} -	widthTable[lodWidth] = cv->width-1; -	lodWidth++; - -	heightTable[0] = 0; -	lodHeight = 1; -	for ( i = 1 ; i < cv->height-1 ; i++ ) { -		if ( cv->heightLodError[i] <= lodError ) { -			heightTable[lodHeight] = i; -			lodHeight++; -		} -	} -	heightTable[lodHeight] = cv->height-1; -	lodHeight++; - - -	// very large grids may have more points or indexes than can be fit -	// in the tess structure, so we may have to issue it in multiple passes - -	used = 0; -	rows = 0; -	while ( used < lodHeight - 1 ) { -		// see how many rows of both verts and indexes we can add without overflowing -		do { -			vrows = ( SHADER_MAX_VERTEXES - tess.numVertexes ) / lodWidth; -			irows = ( SHADER_MAX_INDEXES - tess.numIndexes ) / ( lodWidth * 6 ); - -			// if we don't have enough space for at least one strip, flush the buffer -			if ( vrows < 2 || irows < 1 ) { -				RB_EndSurface(); -				RB_BeginSurface(tess.shader, tess.fogNum ); -			} else { -				break; -			} -		} while ( 1 ); -		 -		rows = irows; -		if ( vrows < irows + 1 ) { -			rows = vrows - 1; -		} -		if ( used + rows > lodHeight ) { -			rows = lodHeight - used; -		} - -		numVertexes = tess.numVertexes; - -		xyz = tess.xyz[numVertexes]; -		normal = tess.normal[numVertexes]; -		texCoords = tess.texCoords[numVertexes][0]; -		color = ( unsigned char * ) &tess.vertexColors[numVertexes]; -		vDlightBits = &tess.vertexDlightBits[numVertexes]; -		needsNormal = tess.shader->needsNormal; - -		for ( i = 0 ; i < rows ; i++ ) { -			for ( j = 0 ; j < lodWidth ; j++ ) { -				dv = cv->verts + heightTable[ used + i ] * cv->width -					+ widthTable[ j ]; - -				xyz[0] = dv->xyz[0]; -				xyz[1] = dv->xyz[1]; -				xyz[2] = dv->xyz[2]; -				texCoords[0] = dv->st[0]; -				texCoords[1] = dv->st[1]; -				texCoords[2] = dv->lightmap[0]; -				texCoords[3] = dv->lightmap[1]; -				if ( needsNormal ) { -					normal[0] = dv->normal[0]; -					normal[1] = dv->normal[1]; -					normal[2] = dv->normal[2]; -				} -				* ( unsigned int * ) color = * ( unsigned int * ) dv->color; -				*vDlightBits++ = dlightBits; -				xyz += 4; -				normal += 4; -				texCoords += 4; -				color += 4; -			} -		} - - -		// add the indexes -		{ -			int		numIndexes; -			int		w, h; - -			h = rows - 1; -			w = lodWidth - 1; -			numIndexes = tess.numIndexes; -			for (i = 0 ; i < h ; i++) { -				for (j = 0 ; j < w ; j++) { -					int		v1, v2, v3, v4; -			 -					// vertex order to be reckognized as tristrips -					v1 = numVertexes + i*lodWidth + j + 1; -					v2 = v1 - 1; -					v3 = v2 + lodWidth; -					v4 = v3 + 1; - -					tess.indexes[numIndexes] = v2; -					tess.indexes[numIndexes+1] = v3; -					tess.indexes[numIndexes+2] = v1; -					 -					tess.indexes[numIndexes+3] = v1; -					tess.indexes[numIndexes+4] = v3; -					tess.indexes[numIndexes+5] = v4; -					numIndexes += 6; -				} -			} - -			tess.numIndexes = numIndexes; -		} - -		tess.numVertexes += rows * lodWidth; - -		used += rows - 1; -	} -} - - -/* -=========================================================================== - -NULL MODEL - -=========================================================================== -*/ - -/* -=================== -RB_SurfaceAxis - -Draws x/y/z lines from the origin for orientation debugging -=================== -*/ -void RB_SurfaceAxis( void ) { -	GL_Bind( tr.whiteImage ); -	qglLineWidth( 3 ); -	qglBegin( GL_LINES ); -	qglColor3f( 1,0,0 ); -	qglVertex3f( 0,0,0 ); -	qglVertex3f( 16,0,0 ); -	qglColor3f( 0,1,0 ); -	qglVertex3f( 0,0,0 ); -	qglVertex3f( 0,16,0 ); -	qglColor3f( 0,0,1 ); -	qglVertex3f( 0,0,0 ); -	qglVertex3f( 0,0,16 ); -	qglEnd(); -	qglLineWidth( 1 ); -} - -//=========================================================================== - -/* -==================== -RB_SurfaceEntity - -Entities that have a single procedurally generated surface -==================== -*/ -void RB_SurfaceEntity( surfaceType_t *surfType ) { -	switch( backEnd.currentEntity->e.reType ) { -	case RT_SPRITE: -		RB_SurfaceSprite(); -		break; -	case RT_BEAM: -		RB_SurfaceBeam(); -		break; -	case RT_RAIL_CORE: -		RB_SurfaceRailCore(); -		break; -	case RT_RAIL_RINGS: -		RB_SurfaceRailRings(); -		break; -	case RT_LIGHTNING: -		RB_SurfaceLightningBolt(); -		break; -	default: -		RB_SurfaceAxis(); -		break; -	} -	return; -} - -void RB_SurfaceBad( surfaceType_t *surfType ) { -	ri.Printf( PRINT_ALL, "Bad surface tesselated.\n" ); -} - -#if 0 - -void RB_SurfaceFlare( srfFlare_t *surf ) { -	vec3_t		left, up; -	float		radius; -	byte		color[4]; -	vec3_t		dir; -	vec3_t		origin; -	float		d; - -	// calculate the xyz locations for the four corners -	radius = 30; -	VectorScale( backEnd.viewParms.or.axis[1], radius, left ); -	VectorScale( backEnd.viewParms.or.axis[2], radius, up ); -	if ( backEnd.viewParms.isMirror ) { -		VectorSubtract( vec3_origin, left, left ); -	} - -	color[0] = color[1] = color[2] = color[3] = 255; - -	VectorMA( surf->origin, 3, surf->normal, origin ); -	VectorSubtract( origin, backEnd.viewParms.or.origin, dir ); -	VectorNormalize( dir ); -	VectorMA( origin, r_ignore->value, dir, origin ); - -	d = -DotProduct( dir, surf->normal ); -	if ( d < 0 ) { -		return; -	} -#if 0 -	color[0] *= d; -	color[1] *= d; -	color[2] *= d; -#endif - -	RB_AddQuadStamp( origin, left, up, color ); -} - -#else - -void RB_SurfaceFlare( srfFlare_t *surf ) { -#if 0 -	vec3_t		left, up; -	byte		color[4]; - -	color[0] = surf->color[0] * 255; -	color[1] = surf->color[1] * 255; -	color[2] = surf->color[2] * 255; -	color[3] = 255; - -	VectorClear( left ); -	VectorClear( up ); - -	left[0] = r_ignore->value; - -	up[1] = r_ignore->value; -	 -	RB_AddQuadStampExt( surf->origin, left, up, color, 0, 0, 1, 1 ); -#endif -} - -#endif - - - -void RB_SurfaceDisplayList( srfDisplayList_t *surf ) { -	// all apropriate state must be set in RB_BeginSurface -	// this isn't implemented yet... -	qglCallList( surf->listNum ); -} - -void RB_SurfaceSkip( void *surf ) { -} - - -void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = { -	(void(*)(void*))RB_SurfaceBad,			// SF_BAD,  -	(void(*)(void*))RB_SurfaceSkip,			// SF_SKIP,  -	(void(*)(void*))RB_SurfaceFace,			// SF_FACE, -	(void(*)(void*))RB_SurfaceGrid,			// SF_GRID, -	(void(*)(void*))RB_SurfaceTriangles,		// SF_TRIANGLES, -	(void(*)(void*))RB_SurfacePolychain,		// SF_POLY, -	(void(*)(void*))RB_SurfaceMesh,			// SF_MD3, -	(void(*)(void*))RB_SurfaceAnim,			// SF_MD4, -#ifdef RAVENMD4 -	(void(*)(void*))RB_MDRSurfaceAnim,		// SF_MDR, -#endif -	(void(*)(void*))RB_SurfaceFlare,		// SF_FLARE, -	(void(*)(void*))RB_SurfaceEntity,		// SF_ENTITY -	(void(*)(void*))RB_SurfaceDisplayList		// SF_DISPLAY_LIST -}; diff --git a/ioq3-r437/src/renderer/tr_types.h b/ioq3-r437/src/renderer/tr_types.h deleted file mode 100644 index 12b526e2..00000000 --- a/ioq3-r437/src/renderer/tr_types.h +++ /dev/null @@ -1,234 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -// -#ifndef __TR_TYPES_H -#define __TR_TYPES_H - - -#define	MAX_DLIGHTS		32			// can't be increased, because bit flags are used on surfaces -#define	MAX_ENTITIES	1023		// can't be increased without changing drawsurf bit packing - -// renderfx flags -#define	RF_MINLIGHT			1		// allways have some light (viewmodel, some items) -#define	RF_THIRD_PERSON		2		// don't draw through eyes, only mirrors (player bodies, chat sprites) -#define	RF_FIRST_PERSON		4		// only draw through eyes (view weapon, damage blood blob) -#define	RF_DEPTHHACK		8		// for view weapon Z crunching -#define	RF_NOSHADOW			64		// don't add stencil shadows - -#define RF_LIGHTING_ORIGIN	128		// use refEntity->lightingOrigin instead of refEntity->origin -									// for lighting.  This allows entities to sink into the floor -									// with their origin going solid, and allows all parts of a -									// player to get the same lighting -#define	RF_SHADOW_PLANE		256		// use refEntity->shadowPlane -#define	RF_WRAP_FRAMES		512		// mod the model frames by the maxframes to allow continuous -									// animation without needing to know the frame count - -// refdef flags -#define RDF_NOWORLDMODEL	1		// used for player configuration screen -#define RDF_HYPERSPACE		4		// teleportation effect - -typedef struct { -	vec3_t		xyz; -	float		st[2]; -	byte		modulate[4]; -} polyVert_t; - -typedef struct poly_s { -	qhandle_t			hShader; -	int					numVerts; -	polyVert_t			*verts; -} poly_t; - -typedef enum { -	RT_MODEL, -	RT_POLY, -	RT_SPRITE, -	RT_BEAM, -	RT_RAIL_CORE, -	RT_RAIL_RINGS, -	RT_LIGHTNING, -	RT_PORTALSURFACE,		// doesn't draw anything, just info for portals - -	RT_MAX_REF_ENTITY_TYPE -} refEntityType_t; - -typedef struct { -	refEntityType_t	reType; -	int			renderfx; - -	qhandle_t	hModel;				// opaque type outside refresh - -	// most recent data -	vec3_t		lightingOrigin;		// so multi-part models can be lit identically (RF_LIGHTING_ORIGIN) -	float		shadowPlane;		// projection shadows go here, stencils go slightly lower - -	vec3_t		axis[3];			// rotation vectors -	qboolean	nonNormalizedAxes;	// axis are not normalized, i.e. they have scale -	float		origin[3];			// also used as MODEL_BEAM's "from" -	int			frame;				// also used as MODEL_BEAM's diameter - -	// previous data for frame interpolation -	float		oldorigin[3];		// also used as MODEL_BEAM's "to" -	int			oldframe; -	float		backlerp;			// 0.0 = current, 1.0 = old - -	// texturing -	int			skinNum;			// inline skin index -	qhandle_t	customSkin;			// NULL for default skin -	qhandle_t	customShader;		// use one image for the entire thing - -	// misc -	byte		shaderRGBA[4];		// colors used by rgbgen entity shaders -	float		shaderTexCoord[2];	// texture coordinates used by tcMod entity modifiers -	float		shaderTime;			// subtracted from refdef time to control effect start times - -	// extra sprite information -	float		radius; -	float		rotation; -} refEntity_t; - - -#define	MAX_RENDER_STRINGS			8 -#define	MAX_RENDER_STRING_LENGTH	32 - -typedef struct { -	int			x, y, width, height; -	float		fov_x, fov_y; -	vec3_t		vieworg; -	vec3_t		viewaxis[3];		// transformation matrix - -	// time in milliseconds for shader effects and other time dependent rendering issues -	int			time; - -	int			rdflags;			// RDF_NOWORLDMODEL, etc - -	// 1 bits will prevent the associated area from rendering at all -	byte		areamask[MAX_MAP_AREA_BYTES]; - -	// text messages for deform text shaders -	char		text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH]; -} refdef_t; - - -typedef enum { -	STEREO_CENTER, -	STEREO_LEFT, -	STEREO_RIGHT -} stereoFrame_t; - - -/* -** glconfig_t -** -** Contains variables specific to the OpenGL configuration -** being run right now.  These are constant once the OpenGL -** subsystem is initialized. -*/ -typedef enum { -	TC_NONE, -	TC_S3TC -} textureCompression_t; - -typedef enum { -	GLDRV_ICD,					// driver is integrated with window system -								// WARNING: there are tests that check for -								// > GLDRV_ICD for minidriverness, so this -								// should always be the lowest value in this -								// enum set -	GLDRV_STANDALONE,			// driver is a non-3Dfx standalone driver -	GLDRV_VOODOO				// driver is a 3Dfx standalone driver -} glDriverType_t; - -typedef enum { -	GLHW_GENERIC,			// where everthing works the way it should -	GLHW_3DFX_2D3D,			// Voodoo Banshee or Voodoo3, relevant since if this is -							// the hardware type then there can NOT exist a secondary -							// display adapter -	GLHW_RIVA128,			// where you can't interpolate alpha -	GLHW_RAGEPRO,			// where you can't modulate alpha on alpha textures -	GLHW_PERMEDIA2			// where you don't have src*dst -} glHardwareType_t; - -typedef struct { -	char					renderer_string[MAX_STRING_CHARS]; -	char					vendor_string[MAX_STRING_CHARS]; -	char					version_string[MAX_STRING_CHARS]; -	char					extensions_string[BIG_INFO_STRING]; - -	int						maxTextureSize;			// queried from GL -	int						maxActiveTextures;		// multitexture ability - -	int						colorBits, depthBits, stencilBits; - -	glDriverType_t			driverType; -	glHardwareType_t		hardwareType; - -	qboolean				deviceSupportsGamma; -	textureCompression_t	textureCompression; -	qboolean				textureEnvAddAvailable; - -	int						vidWidth, vidHeight; -	// aspect is the screen's physical width / height, which may be different -	// than scrWidth / scrHeight if the pixels are non-square -	// normal screens should be 4/3, but wide aspect monitors may be 16/9 -	float					windowAspect; - -	int						displayFrequency; - -	// synonymous with "does rendering consume the entire screen?", therefore -	// a Voodoo or Voodoo2 will have this set to TRUE, as will a Win32 ICD that -	// used CDS. -	qboolean				isFullscreen; -	qboolean				stereoEnabled; -	qboolean				smpActive;		// dual processor -} glconfig_t; - -// FIXME: VM should be OS agnostic .. in theory - -/* -#ifdef Q3_VM - -#define _3DFX_DRIVER_NAME	"Voodoo" -#define OPENGL_DRIVER_NAME	"Default" - -#elif defined(_WIN32) -*/ - -#if defined(Q3_VM) || defined(_WIN32) - -#define _3DFX_DRIVER_NAME	"3dfxvgl" -#define OPENGL_DRIVER_NAME	"opengl32" - -#elif defined(MACOS_X) - -#define _3DFX_DRIVER_NAME	"libMesaVoodooGL.dylib" -#define OPENGL_DRIVER_NAME	"/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib" - -#else - -#define _3DFX_DRIVER_NAME	"libMesaVoodooGL.so" -// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=524 -#define OPENGL_DRIVER_NAME	"libGL.so.1" - -#endif	// !defined _WIN32 - -#endif	// __TR_TYPES_H diff --git a/ioq3-r437/src/renderer/tr_world.c b/ioq3-r437/src/renderer/tr_world.c deleted file mode 100644 index d05373ab..00000000 --- a/ioq3-r437/src/renderer/tr_world.c +++ /dev/null @@ -1,668 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code 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. - -Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -#include "tr_local.h" - - - -/* -================= -R_CullTriSurf - -Returns true if the grid is completely culled away. -Also sets the clipped hint bit in tess -================= -*/ -static qboolean	R_CullTriSurf( srfTriangles_t *cv ) { -	int 	boxCull; - -	boxCull = R_CullLocalBox( cv->bounds ); - -	if ( boxCull == CULL_OUT ) { -		return qtrue; -	} -	return qfalse; -} - -/* -================= -R_CullGrid - -Returns true if the grid is completely culled away. -Also sets the clipped hint bit in tess -================= -*/ -static qboolean	R_CullGrid( srfGridMesh_t *cv ) { -	int 	boxCull; -	int 	sphereCull; - -	if ( r_nocurves->integer ) { -		return qtrue; -	} - -	if ( tr.currentEntityNum != ENTITYNUM_WORLD ) { -		sphereCull = R_CullLocalPointAndRadius( cv->localOrigin, cv->meshRadius ); -	} else { -		sphereCull = R_CullPointAndRadius( cv->localOrigin, cv->meshRadius ); -	} -	boxCull = CULL_OUT; -	 -	// check for trivial reject -	if ( sphereCull == CULL_OUT ) -	{ -		tr.pc.c_sphere_cull_patch_out++; -		return qtrue; -	} -	// check bounding box if necessary -	else if ( sphereCull == CULL_CLIP ) -	{ -		tr.pc.c_sphere_cull_patch_clip++; - -		boxCull = R_CullLocalBox( cv->meshBounds ); - -		if ( boxCull == CULL_OUT )  -		{ -			tr.pc.c_box_cull_patch_out++; -			return qtrue; -		} -		else if ( boxCull == CULL_IN ) -		{ -			tr.pc.c_box_cull_patch_in++; -		} -		else -		{ -			tr.pc.c_box_cull_patch_clip++; -		} -	} -	else -	{ -		tr.pc.c_sphere_cull_patch_in++; -	} - -	return qfalse; -} - - -/* -================ -R_CullSurface - -Tries to back face cull surfaces before they are lighted or -added to the sorting list. - -This will also allow mirrors on both sides of a model without recursion. -================ -*/ -static qboolean	R_CullSurface( surfaceType_t *surface, shader_t *shader ) { -	srfSurfaceFace_t *sface; -	float			d; - -	if ( r_nocull->integer ) { -		return qfalse; -	} - -	if ( *surface == SF_GRID ) { -		return R_CullGrid( (srfGridMesh_t *)surface ); -	} - -	if ( *surface == SF_TRIANGLES ) { -		return R_CullTriSurf( (srfTriangles_t *)surface ); -	} - -	if ( *surface != SF_FACE ) { -		return qfalse; -	} - -	if ( shader->cullType == CT_TWO_SIDED ) { -		return qfalse; -	} - -	// face culling -	if ( !r_facePlaneCull->integer ) { -		return qfalse; -	} - -	sface = ( srfSurfaceFace_t * ) surface; -	d = DotProduct (tr.or.viewOrigin, sface->plane.normal); - -	// don't cull exactly on the plane, because there are levels of rounding -	// through the BSP, ICD, and hardware that may cause pixel gaps if an -	// epsilon isn't allowed here  -	if ( shader->cullType == CT_FRONT_SIDED ) { -		if ( d < sface->plane.dist - 8 ) { -			return qtrue; -		} -	} else { -		if ( d > sface->plane.dist + 8 ) { -			return qtrue; -		} -	} - -	return qfalse; -} - - -static int R_DlightFace( srfSurfaceFace_t *face, int dlightBits ) { -	float		d; -	int			i; -	dlight_t	*dl; - -	for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) { -		if ( ! ( dlightBits & ( 1 << i ) ) ) { -			continue; -		} -		dl = &tr.refdef.dlights[i]; -		d = DotProduct( dl->origin, face->plane.normal ) - face->plane.dist; -		if ( d < -dl->radius || d > dl->radius ) { -			// dlight doesn't reach the plane -			dlightBits &= ~( 1 << i ); -		} -	} - -	if ( !dlightBits ) { -		tr.pc.c_dlightSurfacesCulled++; -	} - -	face->dlightBits[ tr.smpFrame ] = dlightBits; -	return dlightBits; -} - -static int R_DlightGrid( srfGridMesh_t *grid, int dlightBits ) { -	int			i; -	dlight_t	*dl; - -	for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) { -		if ( ! ( dlightBits & ( 1 << i ) ) ) { -			continue; -		} -		dl = &tr.refdef.dlights[i]; -		if ( dl->origin[0] - dl->radius > grid->meshBounds[1][0] -			|| dl->origin[0] + dl->radius < grid->meshBounds[0][0] -			|| dl->origin[1] - dl->radius > grid->meshBounds[1][1] -			|| dl->origin[1] + dl->radius < grid->meshBounds[0][1] -			|| dl->origin[2] - dl->radius > grid->meshBounds[1][2] -			|| dl->origin[2] + dl->radius < grid->meshBounds[0][2] ) { -			// dlight doesn't reach the bounds -			dlightBits &= ~( 1 << i ); -		} -	} - -	if ( !dlightBits ) { -		tr.pc.c_dlightSurfacesCulled++; -	} - -	grid->dlightBits[ tr.smpFrame ] = dlightBits; -	return dlightBits; -} - - -static int R_DlightTrisurf( srfTriangles_t *surf, int dlightBits ) { -	// FIXME: more dlight culling to trisurfs... -	surf->dlightBits[ tr.smpFrame ] = dlightBits; -	return dlightBits; -#if 0 -	int			i; -	dlight_t	*dl; - -	for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) { -		if ( ! ( dlightBits & ( 1 << i ) ) ) { -			continue; -		} -		dl = &tr.refdef.dlights[i]; -		if ( dl->origin[0] - dl->radius > grid->meshBounds[1][0] -			|| dl->origin[0] + dl->radius < grid->meshBounds[0][0] -			|| dl->origin[1] - dl->radius > grid->meshBounds[1][1] -			|| dl->origin[1] + dl->radius < grid->meshBounds[0][1] -			|| dl->origin[2] - dl->radius > grid->meshBounds[1][2] -			|| dl->origin[2] + dl->radius < grid->meshBounds[0][2] ) { -			// dlight doesn't reach the bounds -			dlightBits &= ~( 1 << i ); -		} -	} - -	if ( !dlightBits ) { -		tr.pc.c_dlightSurfacesCulled++; -	} - -	grid->dlightBits[ tr.smpFrame ] = dlightBits; -	return dlightBits; -#endif -} - -/* -==================== -R_DlightSurface - -The given surface is going to be drawn, and it touches a leaf -that is touched by one or more dlights, so try to throw out -more dlights if possible. -==================== -*/ -static int R_DlightSurface( msurface_t *surf, int dlightBits ) { -	if ( *surf->data == SF_FACE ) { -		dlightBits = R_DlightFace( (srfSurfaceFace_t *)surf->data, dlightBits ); -	} else if ( *surf->data == SF_GRID ) { -		dlightBits = R_DlightGrid( (srfGridMesh_t *)surf->data, dlightBits ); -	} else if ( *surf->data == SF_TRIANGLES ) { -		dlightBits = R_DlightTrisurf( (srfTriangles_t *)surf->data, dlightBits ); -	} else { -		dlightBits = 0; -	} - -	if ( dlightBits ) { -		tr.pc.c_dlightSurfaces++; -	} - -	return dlightBits; -} - - - -/* -====================== -R_AddWorldSurface -====================== -*/ -static void R_AddWorldSurface( msurface_t *surf, int dlightBits ) { -	if ( surf->viewCount == tr.viewCount ) { -		return;		// already in this view -	} - -	surf->viewCount = tr.viewCount; -	// FIXME: bmodel fog? - -	// try to cull before dlighting or adding -	if ( R_CullSurface( surf->data, surf->shader ) ) { -		return; -	} - -	// check for dlighting -	if ( dlightBits ) { -		dlightBits = R_DlightSurface( surf, dlightBits ); -		dlightBits = ( dlightBits != 0 ); -	} - -	R_AddDrawSurf( surf->data, surf->shader, surf->fogIndex, dlightBits ); -} - -/* -============================================================= - -	BRUSH MODELS - -============================================================= -*/ - -/* -================= -R_AddBrushModelSurfaces -================= -*/ -void R_AddBrushModelSurfaces ( trRefEntity_t *ent ) { -	bmodel_t	*bmodel; -	int			clip; -	model_t		*pModel; -	int			i; - -	pModel = R_GetModelByHandle( ent->e.hModel ); - -	bmodel = pModel->bmodel; - -	clip = R_CullLocalBox( bmodel->bounds ); -	if ( clip == CULL_OUT ) { -		return; -	} -	 -	R_DlightBmodel( bmodel ); - -	for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) { -		R_AddWorldSurface( bmodel->firstSurface + i, tr.currentEntity->needDlights ); -	} -} - - -/* -============================================================= - -	WORLD MODEL - -============================================================= -*/ - - -/* -================ -R_RecursiveWorldNode -================ -*/ -static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits ) { - -	do { -		int			newDlights[2]; - -		// if the node wasn't marked as potentially visible, exit -		if (node->visframe != tr.visCount) { -			return; -		} - -		// if the bounding volume is outside the frustum, nothing -		// inside can be visible OPTIMIZE: don't do this all the way to leafs? - -		if ( !r_nocull->integer ) { -			int		r; - -			if ( planeBits & 1 ) { -				r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[0]); -				if (r == 2) { -					return;						// culled -				} -				if ( r == 1 ) { -					planeBits &= ~1;			// all descendants will also be in front -				} -			} - -			if ( planeBits & 2 ) { -				r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[1]); -				if (r == 2) { -					return;						// culled -				} -				if ( r == 1 ) { -					planeBits &= ~2;			// all descendants will also be in front -				} -			} - -			if ( planeBits & 4 ) { -				r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[2]); -				if (r == 2) { -					return;						// culled -				} -				if ( r == 1 ) { -					planeBits &= ~4;			// all descendants will also be in front -				} -			} - -			if ( planeBits & 8 ) { -				r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[3]); -				if (r == 2) { -					return;						// culled -				} -				if ( r == 1 ) { -					planeBits &= ~8;			// all descendants will also be in front -				} -			} - -		} - -		if ( node->contents != -1 ) { -			break; -		} - -		// node is just a decision point, so go down both sides -		// since we don't care about sort orders, just go positive to negative - -		// determine which dlights are needed -		newDlights[0] = 0; -		newDlights[1] = 0; -		if ( dlightBits ) { -			int	i; - -			for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) { -				dlight_t	*dl; -				float		dist; - -				if ( dlightBits & ( 1 << i ) ) { -					dl = &tr.refdef.dlights[i]; -					dist = DotProduct( dl->origin, node->plane->normal ) - node->plane->dist; -					 -					if ( dist > -dl->radius ) { -						newDlights[0] |= ( 1 << i ); -					} -					if ( dist < dl->radius ) { -						newDlights[1] |= ( 1 << i ); -					} -				} -			} -		} - -		// recurse down the children, front side first -		R_RecursiveWorldNode (node->children[0], planeBits, newDlights[0] ); - -		// tail recurse -		node = node->children[1]; -		dlightBits = newDlights[1]; -	} while ( 1 ); - -	{ -		// leaf node, so add mark surfaces -		int			c; -		msurface_t	*surf, **mark; - -		tr.pc.c_leafs++; - -		// add to z buffer bounds -		if ( node->mins[0] < tr.viewParms.visBounds[0][0] ) { -			tr.viewParms.visBounds[0][0] = node->mins[0]; -		} -		if ( node->mins[1] < tr.viewParms.visBounds[0][1] ) { -			tr.viewParms.visBounds[0][1] = node->mins[1]; -		} -		if ( node->mins[2] < tr.viewParms.visBounds[0][2] ) { -			tr.viewParms.visBounds[0][2] = node->mins[2]; -		} - -		if ( node->maxs[0] > tr.viewParms.visBounds[1][0] ) { -			tr.viewParms.visBounds[1][0] = node->maxs[0]; -		} -		if ( node->maxs[1] > tr.viewParms.visBounds[1][1] ) { -			tr.viewParms.visBounds[1][1] = node->maxs[1]; -		} -		if ( node->maxs[2] > tr.viewParms.visBounds[1][2] ) { -			tr.viewParms.visBounds[1][2] = node->maxs[2]; -		} - -		// add the individual surfaces -		mark = node->firstmarksurface; -		c = node->nummarksurfaces; -		while (c--) { -			// the surface may have already been added if it -			// spans multiple leafs -			surf = *mark; -			R_AddWorldSurface( surf, dlightBits ); -			mark++; -		} -	} - -} - - -/* -=============== -R_PointInLeaf -=============== -*/ -static mnode_t *R_PointInLeaf( const vec3_t p ) { -	mnode_t		*node; -	float		d; -	cplane_t	*plane; -	 -	if ( !tr.world ) { -		ri.Error (ERR_DROP, "R_PointInLeaf: bad model"); -	} - -	node = tr.world->nodes; -	while( 1 ) { -		if (node->contents != -1) { -			break; -		} -		plane = node->plane; -		d = DotProduct (p,plane->normal) - plane->dist; -		if (d > 0) { -			node = node->children[0]; -		} else { -			node = node->children[1]; -		} -	} -	 -	return node; -} - -/* -============== -R_ClusterPVS -============== -*/ -static const byte *R_ClusterPVS (int cluster) { -	if (!tr.world || !tr.world->vis || cluster < 0 || cluster >= tr.world->numClusters ) { -		return tr.world->novis; -	} - -	return tr.world->vis + cluster * tr.world->clusterBytes; -} - -/* -================= -R_inPVS -================= -*/ -qboolean R_inPVS( const vec3_t p1, const vec3_t p2 ) { -	mnode_t *leaf; -	byte	*vis; - -	leaf = R_PointInLeaf( p1 ); -	vis = CM_ClusterPVS( leaf->cluster ); -	leaf = R_PointInLeaf( p2 ); - -	if ( !(vis[leaf->cluster>>3] & (1<<(leaf->cluster&7))) ) { -		return qfalse; -	} -	return qtrue; -} - -/* -=============== -R_MarkLeaves - -Mark the leaves and nodes that are in the PVS for the current -cluster -=============== -*/ -static void R_MarkLeaves (void) { -	const byte	*vis; -	mnode_t	*leaf, *parent; -	int		i; -	int		cluster; - -	// lockpvs lets designers walk around to determine the -	// extent of the current pvs -	if ( r_lockpvs->integer ) { -		return; -	} - -	// current viewcluster -	leaf = R_PointInLeaf( tr.viewParms.pvsOrigin ); -	cluster = leaf->cluster; - -	// if the cluster is the same and the area visibility matrix -	// hasn't changed, we don't need to mark everything again - -	// if r_showcluster was just turned on, remark everything  -	if ( tr.viewCluster == cluster && !tr.refdef.areamaskModified  -		&& !r_showcluster->modified ) { -		return; -	} - -	if ( r_showcluster->modified || r_showcluster->integer ) { -		r_showcluster->modified = qfalse; -		if ( r_showcluster->integer ) { -			ri.Printf( PRINT_ALL, "cluster:%i  area:%i\n", cluster, leaf->area ); -		} -	} - -	tr.visCount++; -	tr.viewCluster = cluster; - -	if ( r_novis->integer || tr.viewCluster == -1 ) { -		for (i=0 ; i<tr.world->numnodes ; i++) { -			if (tr.world->nodes[i].contents != CONTENTS_SOLID) { -				tr.world->nodes[i].visframe = tr.visCount; -			} -		} -		return; -	} - -	vis = R_ClusterPVS (tr.viewCluster); -	 -	for (i=0,leaf=tr.world->nodes ; i<tr.world->numnodes ; i++, leaf++) { -		cluster = leaf->cluster; -		if ( cluster < 0 || cluster >= tr.world->numClusters ) { -			continue; -		} - -		// check general pvs -		if ( !(vis[cluster>>3] & (1<<(cluster&7))) ) { -			continue; -		} - -		// check for door connection -		if ( (tr.refdef.areamask[leaf->area>>3] & (1<<(leaf->area&7)) ) ) { -			continue;		// not visible -		} - -		parent = leaf; -		do { -			if (parent->visframe == tr.visCount) -				break; -			parent->visframe = tr.visCount; -			parent = parent->parent; -		} while (parent); -	} -} - - -/* -============= -R_AddWorldSurfaces -============= -*/ -void R_AddWorldSurfaces (void) { -	if ( !r_drawworld->integer ) { -		return; -	} - -	if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { -		return; -	} - -	tr.currentEntityNum = ENTITYNUM_WORLD; -	tr.shiftedEntityNum = tr.currentEntityNum << QSORT_ENTITYNUM_SHIFT; - -	// determine which leaves are in the PVS / areamask -	R_MarkLeaves (); - -	// clear out the visible min/max -	ClearBounds( tr.viewParms.visBounds[0], tr.viewParms.visBounds[1] ); - -	// perform frustum culling and add all the potentially visible surfaces -	if ( tr.refdef.num_dlights > 32 ) { -		tr.refdef.num_dlights = 32 ; -	} -	R_RecursiveWorldNode( tr.world->nodes, 15, ( 1 << tr.refdef.num_dlights ) - 1 ); -}  | 
