Initial commit.
This commit is contained in:
471
code/renderer/amd3d.h
Normal file
471
code/renderer/amd3d.h
Normal file
@@ -0,0 +1,471 @@
|
||||
/******************************************************************
|
||||
; *
|
||||
; * Copyright (c) 1996-1998 ADVANCED MICRO DEVICES, INC.
|
||||
; * All Rights reserved.
|
||||
; *
|
||||
; * This software is unpublished and contains the trade secrets
|
||||
; * and confidential proprietary information of AMD. Unless
|
||||
; * otherwise provided in the Software Agreement associated
|
||||
; * herewith, it is licensed in confidence "AS IS" and
|
||||
; * is not to be reproduced in whole or part by any means except
|
||||
; * for backup. Use, duplication, or disclosure by the Government
|
||||
; * is subject to the restrictions in paragraph(b)(3)(B)of the
|
||||
; * Rights in Technical Data and Computer Software clause in
|
||||
; * DFAR 52.227-7013(a)(Oct 1988). Software owned by Advanced
|
||||
; * Micro Devices Inc., One AMD Place, P.O. Box 3453, Sunnyvale,
|
||||
; * CA 94088-3453.
|
||||
; *
|
||||
; ******************************************************************
|
||||
*
|
||||
* AMD3D.H
|
||||
*
|
||||
* MACRO FORMAT
|
||||
* ============
|
||||
* This file contains inline assembly macros that
|
||||
* generate AMD-3D instructions in binary format.
|
||||
* Therefore, C or C++ programmer can use AMD-3D instructions
|
||||
* without any penalty in their C or C++ source code.
|
||||
*
|
||||
* The macro's name and format conventions are as follow:
|
||||
*
|
||||
*
|
||||
* 1. First argument of macro is a destination and
|
||||
* second argument is a source operand.
|
||||
* ex) _asm PFCMPEQ (m3, m4)
|
||||
* | |
|
||||
* dst src
|
||||
*
|
||||
* 2. The destination operand can be m0 to m7 only.
|
||||
* The source operand can be any one of the register
|
||||
* m0 to m7 or _eax, _ecx, _edx, _ebx, _esi, or _edi
|
||||
* that contains effective address.
|
||||
* ex) _asm PFRCP (M7, M6)
|
||||
* ex) _asm PFRCPIT2 (m0, m4)
|
||||
* ex) _asm PFMUL (m3, _edi)
|
||||
*
|
||||
* 3. The prefetch(w) takes one src operand _eax, ecx, _edx,
|
||||
* _ebx, _esi, or _edi that contains effective address.
|
||||
* ex) _asm PREFETCH (_edi)
|
||||
*
|
||||
* EXAMPLE
|
||||
* =======
|
||||
* Following program doesn't do anything but it shows you
|
||||
* how to use inline assembly AMD-3D instructions in C.
|
||||
* Note that this will only work in flat memory model which
|
||||
* segment registers cs, ds, ss and es point to the same
|
||||
* linear address space total less than 4GB.
|
||||
*
|
||||
* Used Microsoft VC++ 5.0
|
||||
*
|
||||
* #include <stdio.h>
|
||||
* #include "amd3d.h"
|
||||
*
|
||||
* void main ()
|
||||
* {
|
||||
* float x = (float)1.25;
|
||||
* float y = (float)1.25;
|
||||
* float z, zz;
|
||||
*
|
||||
* _asm {
|
||||
* movd mm1, x
|
||||
* movd mm2, y
|
||||
* pfmul (m1, m2)
|
||||
* movd z, mm1
|
||||
* femms
|
||||
* }
|
||||
*
|
||||
* printf ("value of z = %f\n", z);
|
||||
*
|
||||
* //
|
||||
* // Demonstration of using the memory instead of
|
||||
* // multimedia register
|
||||
* //
|
||||
* _asm {
|
||||
* movd mm3, x
|
||||
* lea esi, y // load effective address of y
|
||||
* pfmul (m3, _esi)
|
||||
* movd zz, mm3
|
||||
* femms
|
||||
* }
|
||||
*
|
||||
* printf ("value of zz = %f\n", zz);
|
||||
* }
|
||||
******************************************************************/
|
||||
|
||||
#define M0 0xc0
|
||||
#define M1 0xc1
|
||||
#define M2 0xc2
|
||||
#define M3 0xc3
|
||||
#define M4 0xc4
|
||||
#define M5 0xc5
|
||||
#define M6 0xc6
|
||||
#define M7 0xc7
|
||||
|
||||
#define m0 0xc0
|
||||
#define m1 0xc1
|
||||
#define m2 0xc2
|
||||
#define m3 0xc3
|
||||
#define m4 0xc4
|
||||
#define m5 0xc5
|
||||
#define m6 0xc6
|
||||
#define m7 0xc7
|
||||
#define _EAX 0x00
|
||||
#define _ECX 0x01
|
||||
#define _EDX 0x02
|
||||
#define _EBX 0x03
|
||||
#define _ESI 0x06
|
||||
#define _EDI 0x07
|
||||
#define _eax 0x00
|
||||
#define _ecx 0x01
|
||||
#define _edx 0x02
|
||||
#define _ebx 0x03
|
||||
#define _esi 0x06
|
||||
#define _edi 0x07
|
||||
|
||||
#define PF2ID(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x1d \
|
||||
}
|
||||
|
||||
#define PFACC(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xae \
|
||||
}
|
||||
|
||||
#define PFADD(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x9e \
|
||||
}
|
||||
|
||||
#define PFCMPEQ(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xb0 \
|
||||
}
|
||||
|
||||
#define PFCMPGE(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x90 \
|
||||
}
|
||||
|
||||
#define PFCMPGT(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xa0 \
|
||||
}
|
||||
|
||||
#define PFMAX(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xa4 \
|
||||
}
|
||||
|
||||
#define PFMIN(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x94 \
|
||||
}
|
||||
|
||||
#define PFMUL(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xb4 \
|
||||
}
|
||||
|
||||
#define PFRCP(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x96 \
|
||||
}
|
||||
|
||||
#define PFRCPIT1(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xa6 \
|
||||
}
|
||||
|
||||
#define PFRCPIT2(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xb6 \
|
||||
}
|
||||
|
||||
#define PFRSQRT(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x97 \
|
||||
}
|
||||
|
||||
#define PFRSQIT1(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xa7 \
|
||||
}
|
||||
|
||||
#define PFSUB(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x9a \
|
||||
}
|
||||
|
||||
#define PFSUBR(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xaa \
|
||||
}
|
||||
|
||||
#define PI2FD(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x0d \
|
||||
}
|
||||
|
||||
#define FEMMS \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0e \
|
||||
}
|
||||
|
||||
#define PAVGUSB(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xbf \
|
||||
}
|
||||
|
||||
#define PMULHRW(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xb7 \
|
||||
}
|
||||
|
||||
#define PREFETCH(src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0d \
|
||||
_asm _emit 0x00 | src \
|
||||
}
|
||||
|
||||
#define PREFETCHW(src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0d \
|
||||
_asm _emit 0x08 | src \
|
||||
}
|
||||
|
||||
//
|
||||
// Exactly same as above except macro names are all
|
||||
// lower case latter.
|
||||
//
|
||||
#define pf2id(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x1d \
|
||||
}
|
||||
|
||||
#define pfacc(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xae \
|
||||
}
|
||||
|
||||
#define pfadd(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x9e \
|
||||
}
|
||||
|
||||
#define pfcmpeq(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xb0 \
|
||||
}
|
||||
|
||||
#define pfcmpge(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x90 \
|
||||
}
|
||||
|
||||
#define pfcmpgt(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xa0 \
|
||||
}
|
||||
|
||||
#define pfmax(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xa4 \
|
||||
}
|
||||
|
||||
#define pfmin(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x94 \
|
||||
}
|
||||
|
||||
#define pfmul(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xb4 \
|
||||
}
|
||||
|
||||
#define pfrcp(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x96 \
|
||||
}
|
||||
|
||||
#define pfrcpit1(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xa6 \
|
||||
}
|
||||
|
||||
#define pfrcpit2(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xb6 \
|
||||
}
|
||||
|
||||
#define pfrsqrt(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x97 \
|
||||
}
|
||||
|
||||
#define pfrsqit1(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xa7 \
|
||||
}
|
||||
|
||||
#define pfsub(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x9a \
|
||||
}
|
||||
|
||||
#define pfsubr(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xaa \
|
||||
}
|
||||
|
||||
#define pi2fd(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0x0d \
|
||||
}
|
||||
|
||||
#define femms \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0e \
|
||||
}
|
||||
|
||||
#define pavgusb(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xbf \
|
||||
}
|
||||
|
||||
#define pmulhrw(dst, src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit ((dst & 0x3f) << 3) | src \
|
||||
_asm _emit 0xb7 \
|
||||
}
|
||||
|
||||
#define prefetch(src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0d \
|
||||
_asm _emit 0x00 | src \
|
||||
}
|
||||
|
||||
#define prefetchw(src) \
|
||||
{\
|
||||
_asm _emit 0x0f \
|
||||
_asm _emit 0x0d \
|
||||
_asm _emit 0x08 | src \
|
||||
}
|
||||
2920
code/renderer/glext.h
Normal file
2920
code/renderer/glext.h
Normal file
File diff suppressed because it is too large
Load Diff
2521
code/renderer/glext_console.h
Normal file
2521
code/renderer/glext_console.h
Normal file
File diff suppressed because it is too large
Load Diff
361
code/renderer/matcomp.c
Normal file
361
code/renderer/matcomp.c
Normal file
@@ -0,0 +1,361 @@
|
||||
#include "MatComp.h"
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h> // for memcpy
|
||||
|
||||
#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_Compress(const float mat[3][4],unsigned char * _comp)
|
||||
{
|
||||
char comp[MC_COMP_BYTES*2];
|
||||
|
||||
int i,val;
|
||||
for (i=0;i<MC_COMP_BYTES;i++)
|
||||
comp[i]=0;
|
||||
|
||||
val=(int)(mat[0][3]/MC_SCALE_X);
|
||||
val+=1<<(MC_BITS_X-1);
|
||||
if (val>=(1<<MC_BITS_X))
|
||||
val=(1<<MC_BITS_X)-1;
|
||||
if (val<0)
|
||||
val=0;
|
||||
*(unsigned int *)(comp+MC_POS_X)|=((unsigned int)(val))<<MC_SHIFT_X;
|
||||
|
||||
val=(int)(mat[1][3]/MC_SCALE_Y);
|
||||
val+=1<<(MC_BITS_Y-1);
|
||||
if (val>=(1<<MC_BITS_Y))
|
||||
val=(1<<MC_BITS_Y)-1;
|
||||
if (val<0)
|
||||
val=0;
|
||||
*(unsigned int *)(comp+MC_POS_Y)|=((unsigned int)(val))<<MC_SHIFT_Y;
|
||||
|
||||
val=(int)(mat[2][3]/MC_SCALE_Z);
|
||||
val+=1<<(MC_BITS_Z-1);
|
||||
if (val>=(1<<MC_BITS_Z))
|
||||
val=(1<<MC_BITS_Z)-1;
|
||||
if (val<0)
|
||||
val=0;
|
||||
*(unsigned int *)(comp+MC_POS_Z)|=((unsigned int)(val))<<MC_SHIFT_Z;
|
||||
|
||||
|
||||
val=(int)(mat[0][0]/MC_SCALE_VECT);
|
||||
val+=1<<(MC_BITS_VECT-1);
|
||||
if (val>=(1<<MC_BITS_VECT))
|
||||
val=(1<<MC_BITS_VECT)-1;
|
||||
if (val<0)
|
||||
val=0;
|
||||
*(unsigned int *)(comp+MC_POS_V11)|=((unsigned int)(val))<<MC_SHIFT_V11;
|
||||
|
||||
val=(int)(mat[0][1]/MC_SCALE_VECT);
|
||||
val+=1<<(MC_BITS_VECT-1);
|
||||
if (val>=(1<<MC_BITS_VECT))
|
||||
val=(1<<MC_BITS_VECT)-1;
|
||||
if (val<0)
|
||||
val=0;
|
||||
*(unsigned int *)(comp+MC_POS_V12)|=((unsigned int)(val))<<MC_SHIFT_V12;
|
||||
|
||||
val=(int)(mat[0][2]/MC_SCALE_VECT);
|
||||
val+=1<<(MC_BITS_VECT-1);
|
||||
if (val>=(1<<MC_BITS_VECT))
|
||||
val=(1<<MC_BITS_VECT)-1;
|
||||
if (val<0)
|
||||
val=0;
|
||||
*(unsigned int *)(comp+MC_POS_V13)|=((unsigned int)(val))<<MC_SHIFT_V13;
|
||||
|
||||
|
||||
val=(int)(mat[1][0]/MC_SCALE_VECT);
|
||||
val+=1<<(MC_BITS_VECT-1);
|
||||
if (val>=(1<<MC_BITS_VECT))
|
||||
val=(1<<MC_BITS_VECT)-1;
|
||||
if (val<0)
|
||||
val=0;
|
||||
*(unsigned int *)(comp+MC_POS_V21)|=((unsigned int)(val))<<MC_SHIFT_V21;
|
||||
|
||||
val=(int)(mat[1][1]/MC_SCALE_VECT);
|
||||
val+=1<<(MC_BITS_VECT-1);
|
||||
if (val>=(1<<MC_BITS_VECT))
|
||||
val=(1<<MC_BITS_VECT)-1;
|
||||
if (val<0)
|
||||
val=0;
|
||||
*(unsigned int *)(comp+MC_POS_V22)|=((unsigned int)(val))<<MC_SHIFT_V22;
|
||||
|
||||
val=(int)(mat[1][2]/MC_SCALE_VECT);
|
||||
val+=1<<(MC_BITS_VECT-1);
|
||||
if (val>=(1<<MC_BITS_VECT))
|
||||
val=(1<<MC_BITS_VECT)-1;
|
||||
if (val<0)
|
||||
val=0;
|
||||
*(unsigned int *)(comp+MC_POS_V23)|=((unsigned int)(val))<<MC_SHIFT_V23;
|
||||
|
||||
val=(int)(mat[2][0]/MC_SCALE_VECT);
|
||||
val+=1<<(MC_BITS_VECT-1);
|
||||
if (val>=(1<<MC_BITS_VECT))
|
||||
val=(1<<MC_BITS_VECT)-1;
|
||||
if (val<0)
|
||||
val=0;
|
||||
*(unsigned int *)(comp+MC_POS_V31)|=((unsigned int)(val))<<MC_SHIFT_V31;
|
||||
|
||||
val=(int)(mat[2][1]/MC_SCALE_VECT);
|
||||
val+=1<<(MC_BITS_VECT-1);
|
||||
if (val>=(1<<MC_BITS_VECT))
|
||||
val=(1<<MC_BITS_VECT)-1;
|
||||
if (val<0)
|
||||
val=0;
|
||||
*(unsigned int *)(comp+MC_POS_V32)|=((unsigned int)(val))<<MC_SHIFT_V32;
|
||||
|
||||
val=(int)(mat[2][2]/MC_SCALE_VECT);
|
||||
val+=1<<(MC_BITS_VECT-1);
|
||||
if (val>=(1<<MC_BITS_VECT))
|
||||
val=(1<<MC_BITS_VECT)-1;
|
||||
if (val<0)
|
||||
val=0;
|
||||
*(unsigned int *)(comp+MC_POS_V33)|=((unsigned int)(val))<<MC_SHIFT_V33;
|
||||
|
||||
// I added this because the line above actually ORs data into an int at the 22 byte (from 0), and therefore technically
|
||||
// is writing beyond the 24th byte of the output array. This *should** be harmless if the OR'd-in value doesn't change
|
||||
// those bytes, but BoundsChecker says that it's accessing undefined memory (which it does, sometimes). This is probably
|
||||
// bad, so...
|
||||
memcpy(_comp,comp,MC_COMP_BYTES);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
/* ROTATION/TRANSLATION COMPRESSION DEBUG CODE (RTCDC)
|
||||
unsigned short comp_rot_maskx = 0xfff0;
|
||||
unsigned short comp_rot_masky = 0xfff0;
|
||||
unsigned short comp_rot_maskz = 0xfff0;
|
||||
unsigned short comp_rot_maskw = 0xfff0;
|
||||
|
||||
unsigned short comp_tra_maskf1 = 0xfff0;
|
||||
unsigned short comp_tra_maskf2 = 0xfff0;
|
||||
unsigned short comp_tra_maskf3 = 0xfff0;
|
||||
|
||||
int use_comp_rot_mask = 0;
|
||||
int use_comp_tra_mask = 0;
|
||||
unsigned short cw;
|
||||
unsigned short cx;
|
||||
unsigned short cy;
|
||||
unsigned short cz;
|
||||
unsigned short f1;
|
||||
unsigned short f2;
|
||||
unsigned short f3;
|
||||
*/
|
||||
|
||||
void MC_UnCompressQuat(float mat[3][4],const unsigned char * comp)
|
||||
{
|
||||
float w,x,y,z,f;
|
||||
float fTx;
|
||||
float fTy;
|
||||
float fTz;
|
||||
float fTwx;
|
||||
float fTwy;
|
||||
float fTwz;
|
||||
float fTxx;
|
||||
float fTxy;
|
||||
float fTxz;
|
||||
float fTyy;
|
||||
float fTyz;
|
||||
float fTzz;
|
||||
|
||||
const unsigned short *pwIn = (unsigned short *) comp;
|
||||
|
||||
|
||||
/* RTCDC
|
||||
if(use_comp_rot_mask)
|
||||
{
|
||||
cw = *pwIn++;
|
||||
cx = *pwIn++;
|
||||
cy = *pwIn++;
|
||||
cz = *pwIn++;
|
||||
|
||||
cw &= comp_rot_maskw;
|
||||
cx &= comp_rot_maskx;
|
||||
cy &= comp_rot_masky;
|
||||
cz &= comp_rot_maskz;
|
||||
}
|
||||
else
|
||||
{
|
||||
cw = *pwIn++;
|
||||
cx = *pwIn++;
|
||||
cy = *pwIn++;
|
||||
cz = *pwIn++;
|
||||
}
|
||||
|
||||
if(use_comp_tra_mask)
|
||||
{
|
||||
f1 = *pwIn++;
|
||||
f2 = *pwIn++;
|
||||
f3 = *pwIn++;
|
||||
|
||||
f1 &= comp_tra_maskf1;
|
||||
f2 &= comp_tra_maskf2;
|
||||
f3 &= comp_tra_maskf3;
|
||||
}
|
||||
else
|
||||
{
|
||||
f1 = *pwIn++;
|
||||
f2 = *pwIn++;
|
||||
f3 = *pwIn++;
|
||||
}
|
||||
*/
|
||||
|
||||
w = *pwIn++;
|
||||
// RTCDC w = cw;
|
||||
w/=16383.0f;
|
||||
w-=2.0f;
|
||||
x = *pwIn++;
|
||||
// RTCDC x = cx;
|
||||
x/=16383.0f;
|
||||
x-=2.0f;
|
||||
y = *pwIn++;
|
||||
// RTCDC y = cy;
|
||||
y/=16383.0f;
|
||||
y-=2.0f;
|
||||
z = *pwIn++;
|
||||
// RTCDC z = cz;
|
||||
z/=16383.0f;
|
||||
z-=2.0f;
|
||||
|
||||
fTx = 2.0f*x;
|
||||
fTy = 2.0f*y;
|
||||
fTz = 2.0f*z;
|
||||
fTwx = fTx*w;
|
||||
fTwy = fTy*w;
|
||||
fTwz = fTz*w;
|
||||
fTxx = fTx*x;
|
||||
fTxy = fTy*x;
|
||||
fTxz = fTz*x;
|
||||
fTyy = fTy*y;
|
||||
fTyz = fTz*y;
|
||||
fTzz = fTz*z;
|
||||
|
||||
// rot...
|
||||
//
|
||||
mat[0][0] = 1.0f-(fTyy+fTzz);
|
||||
mat[0][1] = fTxy-fTwz;
|
||||
mat[0][2] = fTxz+fTwy;
|
||||
mat[1][0] = fTxy+fTwz;
|
||||
mat[1][1] = 1.0f-(fTxx+fTzz);
|
||||
mat[1][2] = fTyz-fTwx;
|
||||
mat[2][0] = fTxz-fTwy;
|
||||
mat[2][1] = fTyz+fTwx;
|
||||
mat[2][2] = 1.0f-(fTxx+fTyy);
|
||||
|
||||
// xlat...
|
||||
//
|
||||
f = *pwIn++;
|
||||
// RTCDC f = f1;
|
||||
f/=64;
|
||||
f-=512;
|
||||
mat[0][3] = f;
|
||||
|
||||
f = *pwIn++;
|
||||
// RTCDC f = f2;
|
||||
f/=64;
|
||||
f-=512;
|
||||
mat[1][3] = f;
|
||||
|
||||
f = *pwIn++;
|
||||
// RTCDC f = f3;
|
||||
f/=64;
|
||||
f-=512;
|
||||
mat[2][3] = f;
|
||||
}
|
||||
|
||||
|
||||
31
code/renderer/matcomp.h
Normal file
31
code/renderer/matcomp.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef __MATCOMP__
|
||||
#define __MATCOMP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#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)
|
||||
|
||||
|
||||
// currently 24 (.875)
|
||||
#define MC_COMP_BYTES (((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*9)+7)/8)
|
||||
|
||||
void MC_Compress(const float mat[3][4],unsigned char * comp);
|
||||
void MC_UnCompress(float mat[3][4],const unsigned char * comp);
|
||||
void MC_UnCompressQuat(float mat[3][4],const unsigned char * comp);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
434
code/renderer/mdx_format.h
Normal file
434
code/renderer/mdx_format.h
Normal file
@@ -0,0 +1,434 @@
|
||||
// Filename:- mdx_format.h
|
||||
//
|
||||
// DO NOT UPDATE THIS FILE IN ANY WAY WHATSOEVER WITHOUT TELLING ME (-Ste),
|
||||
// BECAUSE THE MASTER COPY IS IN A DIFFERENT SOURCESAFE DATABASE AND WILL
|
||||
// JUST GET PASTED OVER THIS ONE WHENEVER I CHANGE IT.
|
||||
//
|
||||
//
|
||||
//
|
||||
// MDX file format (typically uses file extension GLX for mesh, and GLA for anim/skeleton file)
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// - All offset fields are relative to the address of the structure they occur in
|
||||
// - So far, the only external symbol needed is MAX_QPATH, plus the typedefs for vec3_t, vec2_t etc
|
||||
|
||||
#ifndef MDX_FORMAT_H
|
||||
#define MDX_FORMAT_H
|
||||
|
||||
|
||||
#define MDXM_IDENT (('M'<<24)+('G'<<16)+('L'<<8)+'2')
|
||||
#define MDXA_IDENT (('A'<<24)+('G'<<16)+('L'<<8)+'2')
|
||||
|
||||
#define MAX_TAGNAME_BYTES 32 // matches MDR, can be changed if nec.
|
||||
|
||||
//
|
||||
// normal version numbers...
|
||||
//
|
||||
#define MDXM_VERSION 6
|
||||
#define MDXA_VERSION 6
|
||||
|
||||
// (Note that since there is now a "<modelname>_info.txt" file written out by carcass any changes made in here that
|
||||
// introduce new data should also be reflected in the info-output)
|
||||
|
||||
// 32 bit-flags for ghoul2 bone properties... (all undefined fields will be blank)
|
||||
//
|
||||
#define G2BONEFLAG_ALWAYSXFORM 0x00000001
|
||||
|
||||
// same thing but for surfaces... (Carcass will only generate 1st 2 flags, others are ingame
|
||||
//
|
||||
#define G2SURFACEFLAG_ISBOLT 0x00000001
|
||||
#define G2SURFACEFLAG_OFF 0x00000002 // saves strcmp()ing for "_off" in surface names
|
||||
#define G2SURFACEFLAG_SPARE0 0x00000004 // future-expansion fields, saves invalidating models if we add more
|
||||
#define G2SURFACEFLAG_SPARE1 0x00000008 //
|
||||
#define G2SURFACEFLAG_SPARE2 0x00000010 //
|
||||
#define G2SURFACEFLAG_SPARE3 0x00000020 //
|
||||
#define G2SURFACEFLAG_SPARE4 0x00000040 //
|
||||
#define G2SURFACEFLAG_SPARE5 0x00000080 //
|
||||
//
|
||||
#define G2SURFACEFLAG_NODESCENDANTS 0x00000100 // ingame-stuff, never generated by Carcass....
|
||||
#define G2SURFACEFLAG_GENERATED 0x00000200 //
|
||||
|
||||
|
||||
|
||||
// triangle side-ordering stuff for tags...
|
||||
//
|
||||
#define iG2_TRISIDE_MIDDLE 1
|
||||
#define iG2_TRISIDE_LONGEST 0
|
||||
#define iG2_TRISIDE_SHORTEST 2
|
||||
|
||||
#define fG2_BONEWEIGHT_RECIPROCAL_MULT ((float)(1.0f/1023.0f))
|
||||
#define iG2_BITS_PER_BONEREF 5
|
||||
#define iMAX_G2_BONEREFS_PER_SURFACE (1<<iG2_BITS_PER_BONEREF) // (32)
|
||||
#define iMAX_G2_BONEWEIGHTS_PER_VERT 4 // can't just be blindly increased, affects cache size etc
|
||||
|
||||
#define iG2_BONEWEIGHT_TOPBITS_SHIFT ((iG2_BITS_PER_BONEREF * iMAX_G2_BONEWEIGHTS_PER_VERT) - 8) // 8 bits because of 8 in the BoneWeight[] array entry
|
||||
#define iG2_BONEWEIGHT_TOPBITS_AND 0x300 // 2 bits, giving 10 total, or 10 bits, for 1023/1024 above
|
||||
|
||||
|
||||
#define sDEFAULT_GLA_NAME "*default" // used when making special simple ghoul2 models, usually from MD3 files
|
||||
|
||||
|
||||
////////////////////////////////////
|
||||
//
|
||||
// these structs are defined here purely because of structure dependancy order...
|
||||
//
|
||||
/*
|
||||
#ifdef __cplusplus
|
||||
struct mdxmWeight_t
|
||||
#else
|
||||
typedef struct
|
||||
#endif
|
||||
{
|
||||
int boneIndex; // these are indexes into the surface boneReferences, not the global bone index
|
||||
float boneWeight; // not the global per-frame bone list
|
||||
|
||||
// I'm defining this '<' operator so this struct can be used with an STL <set>...
|
||||
// (note that I've defined it using '>' internally, so it sorts with higher weights being "less", for distance weight-culling
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
bool operator < (const mdxmWeight_t& _X) const {return (boneWeight>_X.boneWeight);}
|
||||
#endif
|
||||
}
|
||||
#ifndef __cplusplus
|
||||
mdxmWeight_t
|
||||
#endif
|
||||
;
|
||||
*/
|
||||
/*
|
||||
#ifdef __cplusplus
|
||||
struct mdxaCompBone_t
|
||||
#else
|
||||
typedef struct
|
||||
#endif
|
||||
{
|
||||
unsigned char Comp[24]; // MC_COMP_BYTES is in MatComp.h, but don't want to couple
|
||||
|
||||
// I'm defining this '<' operator so this struct can be used as an STL <map> key...
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
bool operator < (const mdxaCompBone_t& _X) const {return (memcmp(Comp,_X.Comp,sizeof(Comp))<0);}
|
||||
#endif
|
||||
}
|
||||
#ifndef __cplusplus
|
||||
mdxaCompBone_t
|
||||
#endif
|
||||
;
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
struct mdxaCompQuatBone_t
|
||||
#else
|
||||
typedef struct
|
||||
#endif
|
||||
{
|
||||
unsigned char Comp[14];
|
||||
|
||||
// I'm defining this '<' operator so this struct can be used as an STL <map> key...
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
bool operator < (const mdxaCompQuatBone_t& _X) const {return (memcmp(Comp,_X.Comp,sizeof(Comp))<0);}
|
||||
#endif
|
||||
}
|
||||
#ifndef __cplusplus
|
||||
mdxaCompQuatBone_t
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
#ifndef MDXABONEDEF
|
||||
typedef struct {
|
||||
float matrix[3][4];
|
||||
} mdxaBone_t;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// mdxHeader_t - this contains the header for the file, with sanity checking and version checking, plus number of lod's to be expected
|
||||
//
|
||||
typedef struct {
|
||||
//
|
||||
// ( first 3 fields are same format as MD3/MDR so we can apply easy model-format-type checks )
|
||||
//
|
||||
int ident; // "IDP3" = MD3, "RDM5" = MDR, "2LGM"(GL2 Mesh) = MDX (cruddy char order I know, but I'm following what was there in other versions)
|
||||
int version; // 1,2,3 etc as per format revision
|
||||
char name[MAX_QPATH]; // model name (eg "models/players/marine.glm") // note: extension supplied
|
||||
char animName[MAX_QPATH];// name of animation file this mesh requires // note: extension missing
|
||||
int animIndex; // filled in by game (carcass defaults it to 0)
|
||||
|
||||
int numBones; // (for ingame version-checks only, ensure we don't ref more bones than skel file has)
|
||||
|
||||
int numLODs;
|
||||
int ofsLODs;
|
||||
|
||||
int numSurfaces; // now that surfaces are drawn hierarchically, we have same # per LOD
|
||||
int ofsSurfHierarchy;
|
||||
|
||||
int ofsEnd; // EOF, which of course gives overall file size
|
||||
} mdxmHeader_t;
|
||||
|
||||
|
||||
// for each surface (doesn't actually need a struct for this, just makes source clearer)
|
||||
// {
|
||||
typedef struct
|
||||
{
|
||||
int offsets[1]; // variable sized (mdxmHeader_t->numSurfaces), each offset points to a mdxmSurfHierarchy_t below
|
||||
} mdxmHierarchyOffsets_t;
|
||||
// }
|
||||
|
||||
// for each surface... (mdxmHeader_t->numSurfaces)
|
||||
// {
|
||||
// mdxmSurfHierarchy_t - contains hierarchical info for surfaces...
|
||||
|
||||
typedef struct {
|
||||
char name[MAX_QPATH];
|
||||
unsigned int flags;
|
||||
char shader[MAX_QPATH];
|
||||
int shaderIndex; // for in-game use (carcass defaults to 0)
|
||||
int parentIndex; // this points to the index in the file of the parent surface. -1 if null/root
|
||||
int numChildren; // number of surfaces which are children of this one
|
||||
int childIndexes[1]; // [mdxmSurfHierarch_t->numChildren] (variable sized)
|
||||
} mdxmSurfHierarchy_t; // struct size = (int)( &((mdxmSurfHierarch_t *)0)->childIndexes[ mdxmSurfHierarch_t->numChildren ] );
|
||||
// }
|
||||
|
||||
|
||||
// for each LOD... (mdxmHeader_t->numLODs)
|
||||
// {
|
||||
// mdxLOD_t - this contains the header for this LOD. Contains num of surfaces, offset to surfaces and offset to next LOD. Surfaces are shader sorted, so each surface = 1 shader
|
||||
|
||||
typedef struct {
|
||||
// (used to contain numSurface/ofsSurfaces fields, but these are same per LOD level now)
|
||||
//
|
||||
int ofsEnd; // offset to next LOD
|
||||
} mdxmLOD_t;
|
||||
|
||||
|
||||
typedef struct { // added in GLM version 3 for ingame use at Jake's request
|
||||
int offsets[1]; // variable sized (mdxmHeader_t->numSurfaces), each offset points to surfaces below
|
||||
} mdxmLODSurfOffset_t;
|
||||
|
||||
|
||||
// for each surface... (mdxmHeader_t->numSurfaces)
|
||||
// {
|
||||
// mdxSurface_t - reuse of header format containing surface name, number of bones, offset to poly data and number of polys, offset to vertex information, and number of verts. NOTE offsets are relative to this header.
|
||||
|
||||
typedef struct {
|
||||
int ident; // this one field at least should be kept, since the game-engine may switch-case (but currently=0 in carcass)
|
||||
|
||||
int thisSurfaceIndex; // 0...mdxmHeader_t->numSurfaces-1 (because of how ingame renderer works)
|
||||
|
||||
int ofsHeader; // this will be a negative number, pointing back to main header
|
||||
|
||||
int numVerts;
|
||||
int ofsVerts;
|
||||
|
||||
int numTriangles;
|
||||
int ofsTriangles;
|
||||
|
||||
// Bone references are a set of ints representing all the bones
|
||||
// present in any vertex weights for this surface. This is
|
||||
// needed because a model may have surfaces that need to be
|
||||
// drawn at different sort times, and we don't want to have
|
||||
// to re-interpolate all the bones for each surface.
|
||||
//
|
||||
int numBoneReferences;
|
||||
int ofsBoneReferences;
|
||||
|
||||
int ofsEnd; // next surface follows
|
||||
|
||||
} mdxmSurface_t;
|
||||
|
||||
|
||||
// for each triangle... (mdxmSurface_t->numTriangles)
|
||||
// {
|
||||
// mdxTriangle_t - contains indexes into verts. One struct entry per poly.
|
||||
|
||||
typedef struct {
|
||||
int indexes[3];
|
||||
} mdxmTriangle_t;
|
||||
// }
|
||||
|
||||
|
||||
// for each vert... (mdxmSurface_t->numVerts)
|
||||
// {
|
||||
// mdxVertex_t - this is an array with number of verts from the surface definition as its bounds. It contains normal info, texture coors and number of weightings for this bone
|
||||
// (this is now kept at 32 bytes for cache-aligning)
|
||||
typedef struct {
|
||||
#ifdef _XBOX
|
||||
//short normal[3];
|
||||
unsigned int normal;
|
||||
short vertCoords[3];
|
||||
unsigned int tangent;
|
||||
#else
|
||||
vec3_t normal;
|
||||
vec3_t vertCoords;
|
||||
#endif
|
||||
|
||||
// packed int...
|
||||
unsigned int uiNmWeightsAndBoneIndexes; // 32 bits. format:
|
||||
// 31 & 30: 0..3 (= 1..4) weight count
|
||||
// 29 & 28 (spare)
|
||||
// 2 bit pairs at 20,22,24,26 are 2-bit overflows from 4 BonWeights below (20=[0], 22=[1]) etc)
|
||||
// 5-bits each (iG2_BITS_PER_BONEREF) for boneweights
|
||||
// effectively a packed int, each bone weight converted from 0..1 float to 0..255 int...
|
||||
// promote each entry to float and multiply by fG2_BONEWEIGHT_RECIPROCAL_MULT to convert.
|
||||
byte BoneWeightings[iMAX_G2_BONEWEIGHTS_PER_VERT]; // 4
|
||||
|
||||
} mdxmVertex_t;
|
||||
|
||||
// } vert
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
// these are convenience functions that I can invoked in code. Do NOT change them (because this is a shared file),
|
||||
// but if you want to copy the logic out and use your own versions then fine...
|
||||
//
|
||||
static inline int G2_GetVertWeights( const mdxmVertex_t *pVert )
|
||||
{
|
||||
int iNumWeights = (pVert->uiNmWeightsAndBoneIndexes >> 30)+1; // 1..4 count
|
||||
|
||||
return iNumWeights;
|
||||
}
|
||||
|
||||
static inline int G2_GetVertBoneIndex( const mdxmVertex_t *pVert, const int iWeightNum)
|
||||
{
|
||||
int iBoneIndex = (pVert->uiNmWeightsAndBoneIndexes>>(iG2_BITS_PER_BONEREF*iWeightNum))&((1<<iG2_BITS_PER_BONEREF)-1);
|
||||
|
||||
return iBoneIndex;
|
||||
}
|
||||
|
||||
static inline float G2_GetVertBoneWeight( const mdxmVertex_t *pVert, const int iWeightNum, float &fTotalWeight, int iNumWeights )
|
||||
{
|
||||
float fBoneWeight;
|
||||
|
||||
if (iWeightNum == iNumWeights-1)
|
||||
{
|
||||
fBoneWeight = 1.0f-fTotalWeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iTemp = pVert->BoneWeightings[iWeightNum];
|
||||
iTemp|= (pVert->uiNmWeightsAndBoneIndexes >> (iG2_BONEWEIGHT_TOPBITS_SHIFT+(iWeightNum*2)) ) & iG2_BONEWEIGHT_TOPBITS_AND;
|
||||
|
||||
fBoneWeight = fG2_BONEWEIGHT_RECIPROCAL_MULT * iTemp;
|
||||
fTotalWeight += fBoneWeight;
|
||||
}
|
||||
|
||||
return fBoneWeight;
|
||||
}
|
||||
#endif
|
||||
// for each vert... (mdxmSurface_t->numVerts) (seperated from mdxmVertex_t struct for cache reasons)
|
||||
// {
|
||||
// mdxVertex_t - this is an array with number of verts from the surface definition as its bounds. It contains normal info, texture coors and number of weightings for this bone
|
||||
|
||||
typedef struct {
|
||||
#ifdef _XBOX
|
||||
short texCoords[2];
|
||||
#else
|
||||
vec2_t texCoords;
|
||||
#endif
|
||||
} mdxmVertexTexCoord_t;
|
||||
|
||||
// } vert
|
||||
|
||||
|
||||
// } surface
|
||||
// } LOD
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// seperate file here for animation data...
|
||||
//
|
||||
|
||||
|
||||
// mdxaHeader_t - this contains the header for the file, with sanity checking and version checking, plus number of lod's to be expected
|
||||
//
|
||||
typedef struct {
|
||||
//
|
||||
// ( first 3 fields are same format as MD3/MDR so we can apply easy model-format-type checks )
|
||||
//
|
||||
int ident; // "IDP3" = MD3, "RDM5" = MDR, "2LGA"(GL2 Anim) = MDXA
|
||||
int version; // 1,2,3 etc as per format revision
|
||||
//
|
||||
char name[MAX_QPATH]; // GLA name (eg "skeletons/marine") // note: extension missing
|
||||
float fScale; // will be zero if build before this field was defined, else scale it was built with
|
||||
|
||||
// frames and bones are shared by all levels of detail
|
||||
//
|
||||
int numFrames;
|
||||
int ofsFrames; // points at mdxaFrame_t array
|
||||
int numBones; // (no offset to these since they're inside the frames array)
|
||||
int ofsCompBonePool; // offset to global compressed-bone pool that all frames use
|
||||
int ofsSkel; // offset to mdxaSkel_t info
|
||||
|
||||
int ofsEnd; // EOF, which of course gives overall file size
|
||||
|
||||
} mdxaHeader_t;
|
||||
|
||||
|
||||
// for each bone... (doesn't actually need a struct for this, just makes source clearer)
|
||||
// {
|
||||
typedef struct
|
||||
{
|
||||
int offsets[1]; // variable sized (mdxaHeader_t->numBones), each offset points to an mdxaSkel_t below
|
||||
} mdxaSkelOffsets_t;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// for each bone... (mdxaHeader_t->numBones)
|
||||
// {
|
||||
// mdxaSkel_t - contains hierarchical info only...
|
||||
|
||||
typedef struct {
|
||||
char name[MAX_QPATH]; // name of bone
|
||||
unsigned int flags;
|
||||
int parent; // index of bone that is parent to this one, -1 = NULL/root
|
||||
mdxaBone_t BasePoseMat; // base pose
|
||||
mdxaBone_t BasePoseMatInv; // inverse, to save run-time calc
|
||||
int numChildren; // number of children bones
|
||||
int children[1]; // [mdxaSkel_t->numChildren] (variable sized)
|
||||
} mdxaSkel_t; // struct size = (int)( &((mdxaSkel_t *)0)->children[ mdxaSkel_t->numChildren ] );
|
||||
// }
|
||||
|
||||
|
||||
// (offset @ mdxaHeader_t->ofsFrames)
|
||||
//
|
||||
// array of 3 byte indices here (hey, 25% saving over 4-byte really adds up)...
|
||||
//
|
||||
//
|
||||
// access as follows to get the index for a given <iFrameNum, iBoneNum>
|
||||
//
|
||||
// (iFrameNum * mdxaHeader_t->numBones * 3) + (iBoneNum * 3)
|
||||
//
|
||||
// then read the int at that location and AND it with 0x00FFFFFF. I use the struct below simply for easy searches
|
||||
typedef struct
|
||||
{
|
||||
int iIndex; // this struct for pointing purposes, need to and with 0x00FFFFFF to be meaningful
|
||||
} mdxaIndex_t;
|
||||
//
|
||||
// (note that there's then an alignement-pad here to get the next struct back onto 32-bit alignement)
|
||||
//
|
||||
// this index then points into the following...
|
||||
|
||||
|
||||
// Compressed-bone pool that all frames use (mdxaHeader_t->ofsCompBonePool) (defined at end because size unknown until end)
|
||||
// for each bone in pool (unknown number, no actual total stored at the moment)...
|
||||
// {
|
||||
// mdxaCompBone_t (defined at file top because of struct dependancy)
|
||||
// }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif // #ifndef MDX_FORMAT_H
|
||||
|
||||
//////////////////////// eof ///////////////////////
|
||||
|
||||
|
||||
|
||||
734
code/renderer/qgl.h
Normal file
734
code/renderer/qgl.h
Normal file
@@ -0,0 +1,734 @@
|
||||
/*
|
||||
** QGL.H
|
||||
*/
|
||||
|
||||
#ifndef __QGL_H__
|
||||
#define __QGL_H__
|
||||
|
||||
#if defined( __LINT__ )
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
#elif defined( _WIN32 )
|
||||
|
||||
#pragma warning (disable: 4201)
|
||||
#pragma warning (disable: 4214)
|
||||
#pragma warning (disable: 4514)
|
||||
#pragma warning (disable: 4032)
|
||||
#pragma warning (disable: 4201)
|
||||
#pragma warning (disable: 4214)
|
||||
#include <windows.h>
|
||||
#include <gl/gl.h>
|
||||
|
||||
#elif defined( __APPLE__ ) && defined( __MACH__ )
|
||||
|
||||
#include <MesaGL/gl.h>
|
||||
|
||||
#elif defined( __linux__ )
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
#include <GL/fxmesa.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <gl.h>
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef APIENTRY
|
||||
#define APIENTRY
|
||||
#endif
|
||||
#ifndef WINAPI
|
||||
#define WINAPI
|
||||
#endif
|
||||
|
||||
|
||||
//===========================================================================
|
||||
|
||||
/*
|
||||
** multitexture extension definitions
|
||||
*/
|
||||
#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
|
||||
|
||||
#define GL_TEXTURE_RECTANGLE_EXT 0x84F5
|
||||
|
||||
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);
|
||||
|
||||
|
||||
// Steps to adding a new extension:
|
||||
// - Add the typedef and function pointer externs here.
|
||||
// - Define the function pointer in tr_init.cpp and possibly add a cvar to track your ext status.
|
||||
// - Load the extension in win_glimp.cpp.
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Register Combiner extension definitions. - AReis
|
||||
/***********************************************************************************************************/
|
||||
// NOTE: These are obviously not all the regcom flags. I'm only including the ones I use (to reduce code clutter), so
|
||||
// if you need any of the other flags, just add them.
|
||||
#define GL_REGISTER_COMBINERS_NV 0x8522
|
||||
#define GL_COMBINER0_NV 0x8550
|
||||
#define GL_COMBINER1_NV 0x8551
|
||||
#define GL_COMBINER2_NV 0x8552
|
||||
#define GL_COMBINER3_NV 0x8553
|
||||
#define GL_COMBINER4_NV 0x8554
|
||||
#define GL_COMBINER5_NV 0x8555
|
||||
#define GL_COMBINER6_NV 0x8556
|
||||
#define GL_COMBINER7_NV 0x8557
|
||||
#define GL_NUM_GENERAL_COMBINERS_NV 0x854E
|
||||
#define GL_VARIABLE_A_NV 0x8523
|
||||
#define GL_VARIABLE_B_NV 0x8524
|
||||
#define GL_VARIABLE_C_NV 0x8525
|
||||
#define GL_VARIABLE_D_NV 0x8526
|
||||
#define GL_VARIABLE_E_NV 0x8527
|
||||
#define GL_VARIABLE_F_NV 0x8528
|
||||
#define GL_VARIABLE_G_NV 0x8529
|
||||
#define GL_DISCARD_NV 0x8530
|
||||
#define GL_CONSTANT_COLOR0_NV 0x852A
|
||||
#define GL_CONSTANT_COLOR1_NV 0x852B
|
||||
#define GL_SPARE0_NV 0x852E
|
||||
#define GL_SPARE1_NV 0x852F
|
||||
#define GL_UNSIGNED_IDENTITY_NV 0x8536
|
||||
#define GL_UNSIGNED_INVERT_NV 0x8537
|
||||
|
||||
typedef void (APIENTRY *PFNGLCOMBINERPARAMETERFVNV) (GLenum pname,const GLfloat *params);
|
||||
typedef void (APIENTRY *PFNGLCOMBINERPARAMETERIVNV) (GLenum pname,const GLint *params);
|
||||
typedef void (APIENTRY *PFNGLCOMBINERPARAMETERFNV) (GLenum pname,GLfloat param);
|
||||
typedef void (APIENTRY *PFNGLCOMBINERPARAMETERINV) (GLenum pname,GLint param);
|
||||
typedef void (APIENTRY *PFNGLCOMBINERINPUTNV) (GLenum stage,GLenum portion,GLenum variable,GLenum input,GLenum mapping,
|
||||
GLenum componentUsage);
|
||||
typedef void (APIENTRY *PFNGLCOMBINEROUTPUTNV) (GLenum stage,GLenum portion,GLenum abOutput,GLenum cdOutput,GLenum sumOutput,
|
||||
GLenum scale, GLenum bias,GLboolean abDotProduct,GLboolean cdDotProduct,
|
||||
GLboolean muxSum);
|
||||
typedef void (APIENTRY *PFNGLFINALCOMBINERINPUTNV) (GLenum variable,GLenum input,GLenum mapping,GLenum componentUsage);
|
||||
|
||||
typedef void (APIENTRY *PFNGLGETCOMBINERINPUTPARAMETERFVNV) (GLenum stage,GLenum portion,GLenum variable,GLenum pname,GLfloat *params);
|
||||
typedef void (APIENTRY *PFNGLGETCOMBINERINPUTPARAMETERIVNV) (GLenum stage,GLenum portion,GLenum variable,GLenum pname,GLint *params);
|
||||
typedef void (APIENTRY *PFNGLGETCOMBINEROUTPUTPARAMETERFVNV) (GLenum stage,GLenum portion,GLenum pname,GLfloat *params);
|
||||
typedef void (APIENTRY *PFNGLGETCOMBINEROUTPUTPARAMETERIVNV) (GLenum stage,GLenum portion,GLenum pname,GLint *params);
|
||||
typedef void (APIENTRY *PFNGLGETFINALCOMBINERINPUTPARAMETERFVNV) (GLenum variable,GLenum pname,GLfloat *params);
|
||||
typedef void (APIENTRY *PFNGLGETFINALCOMBINERINPUTPARAMETERIVNV) (GLenum variable,GLenum pname,GLfloat *params);
|
||||
/***********************************************************************************************************/
|
||||
|
||||
// Declare Register Combiners function pointers.
|
||||
extern PFNGLCOMBINERPARAMETERFVNV qglCombinerParameterfvNV;
|
||||
extern PFNGLCOMBINERPARAMETERIVNV qglCombinerParameterivNV;
|
||||
extern PFNGLCOMBINERPARAMETERFNV qglCombinerParameterfNV;
|
||||
extern PFNGLCOMBINERPARAMETERINV qglCombinerParameteriNV;
|
||||
extern PFNGLCOMBINERINPUTNV qglCombinerInputNV;
|
||||
extern PFNGLCOMBINEROUTPUTNV qglCombinerOutputNV;
|
||||
extern PFNGLFINALCOMBINERINPUTNV qglFinalCombinerInputNV;
|
||||
extern PFNGLGETCOMBINERINPUTPARAMETERFVNV qglGetCombinerInputParameterfvNV;
|
||||
extern PFNGLGETCOMBINERINPUTPARAMETERIVNV qglGetCombinerInputParameterivNV;
|
||||
extern PFNGLGETCOMBINEROUTPUTPARAMETERFVNV qglGetCombinerOutputParameterfvNV;
|
||||
extern PFNGLGETCOMBINEROUTPUTPARAMETERIVNV qglGetCombinerOutputParameterivNV;
|
||||
extern PFNGLGETFINALCOMBINERINPUTPARAMETERFVNV qglGetFinalCombinerInputParameterfvNV;
|
||||
extern PFNGLGETFINALCOMBINERINPUTPARAMETERIVNV qglGetFinalCombinerInputParameterivNV;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Pixel Format extension definitions. - AReis
|
||||
/***********************************************************************************************************/
|
||||
#define WGL_COLOR_BITS_ARB 0x2014
|
||||
#define WGL_ALPHA_BITS_ARB 0x201B
|
||||
#define WGL_DEPTH_BITS_ARB 0x2022
|
||||
#define WGL_STENCIL_BITS_ARB 0x2023
|
||||
|
||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
|
||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
|
||||
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
|
||||
/***********************************************************************************************************/
|
||||
|
||||
// Declare Pixel Format function pointers.
|
||||
extern PFNWGLGETPIXELFORMATATTRIBIVARBPROC qwglGetPixelFormatAttribivARB;
|
||||
extern PFNWGLGETPIXELFORMATATTRIBFVARBPROC qwglGetPixelFormatAttribfvARB;
|
||||
extern PFNWGLCHOOSEPIXELFORMATARBPROC qwglChoosePixelFormatARB;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Pixel Buffer extension definitions. - AReis
|
||||
/***********************************************************************************************************/
|
||||
DECLARE_HANDLE(HPBUFFERARB);
|
||||
|
||||
#define WGL_SUPPORT_OPENGL_ARB 0x2010
|
||||
#define WGL_DOUBLE_BUFFER_ARB 0x2011
|
||||
#define WGL_DRAW_TO_PBUFFER_ARB 0x202D
|
||||
#define WGL_PBUFFER_WIDTH_ARB 0x2034
|
||||
#define WGL_PBUFFER_HEIGHT_ARB 0x2035
|
||||
#define WGL_RED_BITS_ARB 0x2015
|
||||
#define WGL_GREEN_BITS_ARB 0x2017
|
||||
#define WGL_BLUE_BITS_ARB 0x2019
|
||||
|
||||
typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
|
||||
typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
|
||||
typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC);
|
||||
typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);
|
||||
typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
|
||||
/***********************************************************************************************************/
|
||||
|
||||
// Declare Pixel Buffer function pointers.
|
||||
extern PFNWGLCREATEPBUFFERARBPROC qwglCreatePbufferARB;
|
||||
extern PFNWGLGETPBUFFERDCARBPROC qwglGetPbufferDCARB;
|
||||
extern PFNWGLRELEASEPBUFFERDCARBPROC qwglReleasePbufferDCARB;
|
||||
extern PFNWGLDESTROYPBUFFERARBPROC qwglDestroyPbufferARB;
|
||||
extern PFNWGLQUERYPBUFFERARBPROC qwglQueryPbufferARB;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Render-Texture extension definitions. - AReis
|
||||
/***********************************************************************************************************/
|
||||
#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071
|
||||
#define WGL_TEXTURE_FORMAT_ARB 0x2072
|
||||
#define WGL_TEXTURE_TARGET_ARB 0x2073
|
||||
#define WGL_TEXTURE_RGB_ARB 0x2075
|
||||
#define WGL_TEXTURE_RGBA_ARB 0x2076
|
||||
#define WGL_TEXTURE_2D_ARB 0x207A
|
||||
#define WGL_FRONT_LEFT_ARB 0x2083
|
||||
|
||||
typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
|
||||
typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
|
||||
typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int * piAttribList);
|
||||
/***********************************************************************************************************/
|
||||
|
||||
// Declare Render-Texture function pointers.
|
||||
extern PFNWGLBINDTEXIMAGEARBPROC qwglBindTexImageARB;
|
||||
extern PFNWGLRELEASETEXIMAGEARBPROC qwglReleaseTexImageARB;
|
||||
extern PFNWGLSETPBUFFERATTRIBARBPROC qwglSetPbufferAttribARB;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Vertex and Fragment Program extension definitions. - AReis
|
||||
/***********************************************************************************************************/
|
||||
#ifndef GL_ARB_fragment_program
|
||||
#define GL_FRAGMENT_PROGRAM_ARB 0x8804
|
||||
#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
|
||||
#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
|
||||
#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
|
||||
#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
|
||||
#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
|
||||
#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
|
||||
#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
|
||||
#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
|
||||
#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
|
||||
#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
|
||||
#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
|
||||
#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
|
||||
#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
|
||||
#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
|
||||
#endif
|
||||
|
||||
// NOTE: These are obviously not all the vertex program flags (have you seen how many there actually are!). I'm
|
||||
// only including the ones I use (to reduce code clutter), so if you need any of the other flags, just add them.
|
||||
#define GL_VERTEX_PROGRAM_ARB 0x8620
|
||||
#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
|
||||
|
||||
typedef void (APIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string);
|
||||
typedef void (APIENTRY * PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);
|
||||
typedef void (APIENTRY * PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs);
|
||||
typedef void (APIENTRY * PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs);
|
||||
typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
|
||||
typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
|
||||
typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
|
||||
typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
|
||||
typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
|
||||
typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
|
||||
typedef void (APIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
|
||||
typedef void (APIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
|
||||
typedef void (APIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
|
||||
typedef void (APIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
|
||||
typedef void (APIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string);
|
||||
typedef GLboolean (APIENTRY * PFNGLISPROGRAMARBPROC) (GLuint program);
|
||||
/***********************************************************************************************************/
|
||||
|
||||
// Declare Vertex and Fragment Program function pointers.
|
||||
extern PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB;
|
||||
extern PFNGLBINDPROGRAMARBPROC qglBindProgramARB;
|
||||
extern PFNGLDELETEPROGRAMSARBPROC qglDeleteProgramsARB;
|
||||
extern PFNGLGENPROGRAMSARBPROC qglGenProgramsARB;
|
||||
extern PFNGLPROGRAMENVPARAMETER4DARBPROC qglProgramEnvParameter4dARB;
|
||||
extern PFNGLPROGRAMENVPARAMETER4DVARBPROC qglProgramEnvParameter4dvARB;
|
||||
extern PFNGLPROGRAMENVPARAMETER4FARBPROC qglProgramEnvParameter4fARB;
|
||||
extern PFNGLPROGRAMENVPARAMETER4FVARBPROC qglProgramEnvParameter4fvARB;
|
||||
extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC qglProgramLocalParameter4dARB;
|
||||
extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC qglProgramLocalParameter4dvARB;
|
||||
extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC qglProgramLocalParameter4fARB;
|
||||
extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC qglProgramLocalParameter4fvARB;
|
||||
extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC qglGetProgramEnvParameterdvARB;
|
||||
extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC qglGetProgramEnvParameterfvARB;
|
||||
extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC qglGetProgramLocalParameterdvARB;
|
||||
extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC qglGetProgramLocalParameterfvARB;
|
||||
extern PFNGLGETPROGRAMIVARBPROC qglGetProgramivARB;
|
||||
extern PFNGLGETPROGRAMSTRINGARBPROC qglGetProgramStringARB;
|
||||
extern PFNGLISPROGRAMARBPROC qglIsProgramARB;
|
||||
|
||||
|
||||
/*
|
||||
** 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);
|
||||
|
||||
extern void ( APIENTRY * qglPointParameterfEXT)( GLenum, GLfloat);
|
||||
extern void ( APIENTRY * qglPointParameterfvEXT)( GLenum, GLfloat *);
|
||||
|
||||
// Added 10/23/02 by Aurelio Reis.
|
||||
extern void ( APIENTRY * qglPointParameteriNV)( GLenum, GLint);
|
||||
extern void ( APIENTRY * qglPointParameterivNV)( GLenum, const GLint *);
|
||||
|
||||
//===========================================================================
|
||||
|
||||
// non-windows systems will just redefine qgl* to gl*
|
||||
#if !defined( _WIN32 ) && !defined( __linux__ )
|
||||
|
||||
#include "qgl_linked.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 l);
|
||||
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 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__ )
|
||||
|
||||
//FX Mesa Functions
|
||||
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);
|
||||
|
||||
//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__
|
||||
|
||||
#endif // _WIN32 && __linux__
|
||||
|
||||
#endif
|
||||
1207
code/renderer/qgl_console.h
Normal file
1207
code/renderer/qgl_console.h
Normal file
File diff suppressed because it is too large
Load Diff
336
code/renderer/qgl_linked.h
Normal file
336
code/renderer/qgl_linked.h
Normal file
@@ -0,0 +1,336 @@
|
||||
|
||||
#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
|
||||
|
||||
2
code/renderer/ref_trin.def
Normal file
2
code/renderer/ref_trin.def
Normal file
@@ -0,0 +1,2 @@
|
||||
EXPORTS
|
||||
GetRefAPI
|
||||
2295
code/renderer/tr_WorldEffects.cpp
Normal file
2295
code/renderer/tr_WorldEffects.cpp
Normal file
File diff suppressed because it is too large
Load Diff
43
code/renderer/tr_WorldEffects.h
Normal file
43
code/renderer/tr_WorldEffects.h
Normal file
@@ -0,0 +1,43 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RAVEN SOFTWARE - STAR WARS: JK II
|
||||
// (c) 2002 Activision
|
||||
//
|
||||
// World Effects
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
#if !defined __TR_WORLDEFFECTS_H
|
||||
#define __TR_WORLDEFFECTS_H
|
||||
|
||||
#include "../game/q_shared.h" // For Vec3_t
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Supported Commands
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
void R_AddWeatherZone(vec3_t mins, vec3_t maxs);
|
||||
|
||||
void R_InitWorldEffects(void);
|
||||
void R_ShutdownWorldEffects(void);
|
||||
void RB_RenderWorldEffects(void);
|
||||
|
||||
void R_WorldEffectCommand(const char *command);
|
||||
void R_WorldEffect_f(void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Exported Functionality
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool R_GetWindVector(vec3_t windVector, vec3_t atpoint);
|
||||
bool R_GetWindSpeed(float &windSpeed, vec3_t atpoint);
|
||||
bool R_GetWindGusting(vec3_t atpoint);
|
||||
bool R_IsOutside(vec3_t pos);
|
||||
float R_IsOutsideCausingPain(vec3_t pos);
|
||||
float R_GetChanceOfSaberFizz();
|
||||
bool R_IsShaking(vec3_t pos);
|
||||
bool R_SetTempGlobalFogColor(vec3_t color);
|
||||
|
||||
bool R_IsRaining();
|
||||
bool R_IsPuffing();
|
||||
|
||||
|
||||
#endif // __TR_WORLDEFFECTS_H
|
||||
478
code/renderer/tr_animation.cpp
Normal file
478
code/renderer/tr_animation.cpp
Normal file
@@ -0,0 +1,478 @@
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
#include "tr_local.h"
|
||||
#include "MatComp.h"
|
||||
|
||||
#ifdef VV_LIGHTING
|
||||
#include "tr_lightmanager.h"
|
||||
#endif
|
||||
|
||||
extern int R_ComputeLOD( trRefEntity_t *ent );
|
||||
|
||||
/*
|
||||
|
||||
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_ACullModel
|
||||
=============
|
||||
*/
|
||||
static int R_ACullModel( md4Header_t *header, trRefEntity_t *ent ) {
|
||||
vec3_t bounds[2];
|
||||
md4Frame_t *oldFrame, *newFrame;
|
||||
int i;
|
||||
int frameSize;
|
||||
// compute frame pointers
|
||||
|
||||
if (header->ofsFrames<0) // Compressed
|
||||
{
|
||||
frameSize = (int)( &((md4CompFrame_t *)0)->bones[ tr.currentModel->md4->numBones ] );
|
||||
newFrame = (md4Frame_t *)((byte *)header - header->ofsFrames + ent->e.frame * frameSize );
|
||||
oldFrame = (md4Frame_t *)((byte *)header - header->ofsFrames + ent->e.oldframe * frameSize );
|
||||
// HACK! These frames actually are md4CompFrames, but the first fields are the same,
|
||||
// so this will work for this routine.
|
||||
}
|
||||
else
|
||||
{
|
||||
frameSize = (int)( &((md4Frame_t *)0)->bones[ tr.currentModel->md4->numBones ] );
|
||||
newFrame = (md4Frame_t *)((byte *)header + header->ofsFrames + ent->e.frame * frameSize );
|
||||
oldFrame = (md4Frame_t *)((byte *)header + header->ofsFrames + ent->e.oldframe * frameSize );
|
||||
}
|
||||
|
||||
// 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_AComputeFogNum
|
||||
|
||||
=================
|
||||
*/
|
||||
static int R_AComputeFogNum( md4Header_t *header, trRefEntity_t *ent ) {
|
||||
int i;
|
||||
fog_t *fog;
|
||||
md4Frame_t *frame;
|
||||
vec3_t localOrigin;
|
||||
int frameSize;
|
||||
|
||||
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (header->ofsFrames<0) // Compressed
|
||||
{
|
||||
frameSize = (int)( &((md4CompFrame_t *)0)->bones[ header->numBones ] );
|
||||
frame = (md4Frame_t *)((byte *)header - header->ofsFrames + ent->e.frame * frameSize );
|
||||
// HACK! These frames actually are md4CompFrames, but the first fields are the same,
|
||||
// so this will work for this routine.
|
||||
}
|
||||
else
|
||||
{
|
||||
frameSize = (int)( &((md4Frame_t *)0)->bones[ header->numBones ] );
|
||||
frame = (md4Frame_t *)((byte *)header + header->ofsFrames + ent->e.frame * frameSize );
|
||||
}
|
||||
|
||||
VectorAdd( ent->e.origin, frame->localOrigin, localOrigin );
|
||||
int partialFog = 0;
|
||||
for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
|
||||
fog = &tr.world->fogs[i];
|
||||
if ( localOrigin[0] - frame->radius >= fog->bounds[0][0]
|
||||
&& localOrigin[0] + frame->radius <= fog->bounds[1][0]
|
||||
&& localOrigin[1] - frame->radius >= fog->bounds[0][1]
|
||||
&& localOrigin[1] + frame->radius <= fog->bounds[1][1]
|
||||
&& localOrigin[2] - frame->radius >= fog->bounds[0][2]
|
||||
&& localOrigin[2] + frame->radius <= fog->bounds[1][2] )
|
||||
{//totally inside it
|
||||
return i;
|
||||
break;
|
||||
}
|
||||
if ( ( localOrigin[0] - frame->radius >= fog->bounds[0][0] && localOrigin[1] - frame->radius >= fog->bounds[0][1] && localOrigin[2] - frame->radius >= fog->bounds[0][2] &&
|
||||
localOrigin[0] - frame->radius <= fog->bounds[1][0] && localOrigin[1] - frame->radius <= fog->bounds[1][1] && localOrigin[2] - frame->radius <= fog->bounds[1][2] ) ||
|
||||
( localOrigin[0] + frame->radius >= fog->bounds[0][0] && localOrigin[1] + frame->radius >= fog->bounds[0][1] && localOrigin[2] + frame->radius >= fog->bounds[0][2] &&
|
||||
localOrigin[0] + frame->radius <= fog->bounds[1][0] && localOrigin[1] + frame->radius <= fog->bounds[1][1] && localOrigin[2] + frame->radius <= fog->bounds[1][2] ) )
|
||||
{//partially inside it
|
||||
if ( tr.refdef.fogIndex == i || R_FogParmsMatch( tr.refdef.fogIndex, i ) )
|
||||
{//take new one only if it's the same one that the viewpoint is in
|
||||
return i;
|
||||
break;
|
||||
}
|
||||
else if ( !partialFog )
|
||||
{//first partialFog
|
||||
partialFog = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
//if all else fails, return the first partialFog
|
||||
return partialFog;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
R_AddAnimSurfaces
|
||||
==============
|
||||
*/
|
||||
void R_AddAnimSurfaces( trRefEntity_t *ent ) {
|
||||
md4Header_t *header;
|
||||
md4Surface_t *surface;
|
||||
md4LOD_t *lod;
|
||||
shader_t *shader = 0;
|
||||
shader_t *cust_shader = 0;
|
||||
int fogNum = 0;
|
||||
qboolean personalModel;
|
||||
int cull;
|
||||
int i, whichLod;
|
||||
|
||||
// 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_CAP_FRAMES) {
|
||||
if (ent->e.frame > tr.currentModel->md4->numFrames-1)
|
||||
ent->e.frame = tr.currentModel->md4->numFrames-1;
|
||||
if (ent->e.oldframe > tr.currentModel->md4->numFrames-1)
|
||||
ent->e.oldframe = tr.currentModel->md4->numFrames-1;
|
||||
}
|
||||
else if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
|
||||
ent->e.frame %= tr.currentModel->md4->numFrames;
|
||||
ent->e.oldframe %= tr.currentModel->md4->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->md4->numFrames)
|
||||
|| (ent->e.frame < 0)
|
||||
|| (ent->e.oldframe >= tr.currentModel->md4->numFrames)
|
||||
|| (ent->e.oldframe < 0) )
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
VID_Printf (PRINT_ALL, "R_AddAnimSurfaces: no such frame %d to %d for '%s'\n",
|
||||
#else
|
||||
VID_Printf (PRINT_DEVELOPER, "R_AddAnimSurfaces: no such frame %d to %d for '%s'\n",
|
||||
#endif
|
||||
ent->e.oldframe, ent->e.frame,
|
||||
tr.currentModel->name );
|
||||
ent->e.frame = 0;
|
||||
ent->e.oldframe = 0;
|
||||
}
|
||||
|
||||
header = tr.currentModel->md4;
|
||||
|
||||
//
|
||||
// cull the entire model if merged bounding box of both frames
|
||||
// is outside the view frustum.
|
||||
//
|
||||
cull = R_ACullModel ( header, ent );
|
||||
if ( cull == CULL_OUT ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// compute LOD
|
||||
//
|
||||
lod = (md4LOD_t *)( (byte *)header + header->ofsLODs );
|
||||
whichLod = R_ComputeLOD( ent );
|
||||
for ( i = 0; i < whichLod; i++)
|
||||
{
|
||||
lod = (md4LOD_t*)( (byte *)lod + lod->ofsEnd );
|
||||
}
|
||||
|
||||
//
|
||||
// set up lighting now that we know we aren't culled
|
||||
//
|
||||
if ( !personalModel || r_shadows->integer > 1 ) {
|
||||
#ifdef VV_LIGHTING
|
||||
VVLightMan.R_SetupEntityLighting( &tr.refdef, ent );
|
||||
#else
|
||||
R_SetupEntityLighting( &tr.refdef, ent );
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// see if we are in a fog volume
|
||||
//
|
||||
fogNum = R_AComputeFogNum( header, ent );
|
||||
|
||||
|
||||
//
|
||||
// draw all surfaces
|
||||
//
|
||||
cust_shader = R_GetShaderByHandle( ent->e.customShader );
|
||||
|
||||
|
||||
surface = (md4Surface_t *)( (byte *)lod + lod->ofsSurfaces );
|
||||
for ( i = 0 ; i < lod->numSurfaces ; i++ ) {
|
||||
if ( ent->e.customShader ) {
|
||||
shader = cust_shader;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
shader = R_GetShaderByHandle( surface->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
|
||||
#ifndef VV_LIGHTING
|
||||
&& fogNum == 0
|
||||
#endif
|
||||
&& (ent->e.renderfx & RF_SHADOW_PLANE )
|
||||
&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
|
||||
&& shader->sort == SS_OPAQUE ) {
|
||||
R_AddDrawSurf( (surfaceType_t *)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( (surfaceType_t *)surface, tr.projectionShadowShader, 0, qfalse );
|
||||
}
|
||||
|
||||
// don't add third_person objects if not viewing through a portal
|
||||
if ( !personalModel ) {
|
||||
R_AddDrawSurf( (surfaceType_t *)surface, shader, 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 tbone[2];
|
||||
md4Bone_t *bonePtr, *bone;
|
||||
md4Header_t *header;
|
||||
md4Frame_t *frame=0;
|
||||
md4Frame_t *oldFrame=0;
|
||||
md4CompFrame_t *cframe=0;
|
||||
md4CompFrame_t *coldFrame=0;
|
||||
int frameSize;
|
||||
qboolean compressed;
|
||||
|
||||
|
||||
if ( backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) {
|
||||
backlerp = 0;
|
||||
frontlerp = 1;
|
||||
} else {
|
||||
backlerp = backEnd.currentEntity->e.backlerp;
|
||||
frontlerp = 1.0 - backlerp;
|
||||
}
|
||||
header = (md4Header_t *)((byte *)surface + surface->ofsHeader);
|
||||
|
||||
if (header->ofsFrames<0) // Compressed
|
||||
{
|
||||
compressed = qtrue;
|
||||
frameSize = (int)( &((md4CompFrame_t *)0)->bones[ header->numBones ] );
|
||||
cframe = (md4CompFrame_t *)((byte *)header - header->ofsFrames + backEnd.currentEntity->e.frame * frameSize );
|
||||
coldFrame = (md4CompFrame_t *)((byte *)header - header->ofsFrames + backEnd.currentEntity->e.oldframe * frameSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
compressed = qfalse;
|
||||
frameSize = (int)( &((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 );
|
||||
|
||||
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] = baseVertex + triangles[j];
|
||||
}
|
||||
tess.numIndexes += indexes;
|
||||
|
||||
//
|
||||
// lerp all the needed bones
|
||||
//
|
||||
if ( !backlerp && !compressed)
|
||||
// no lerping needed
|
||||
bonePtr = frame->bones;
|
||||
else
|
||||
{
|
||||
bonePtr = bones;
|
||||
if (compressed)
|
||||
{
|
||||
for ( i = 0 ; i < header->numBones ; i++ )
|
||||
{
|
||||
if ( !backlerp )
|
||||
MC_UnCompress(bonePtr[i].matrix,cframe->bones[i].Comp);
|
||||
else
|
||||
{
|
||||
MC_UnCompress(tbone[0].matrix,cframe->bones[i].Comp);
|
||||
MC_UnCompress(tbone[1].matrix,coldFrame->bones[i].Comp);
|
||||
for ( j = 0 ; j < 12 ; j++ )
|
||||
((float *)&bonePtr[i])[j] = frontlerp * ((float *)&tbone[0])[j]
|
||||
+ backlerp * ((float *)&tbone[1])[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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 = (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];
|
||||
|
||||
v = (md4Vertex_t *)&v->weights[v->numWeights];
|
||||
}
|
||||
|
||||
tess.numVertexes += surface->numVerts;
|
||||
}
|
||||
149
code/renderer/tr_arioche.cpp
Normal file
149
code/renderer/tr_arioche.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
#include "tr_local.h"
|
||||
#include "tr_worldeffects.h"
|
||||
|
||||
// Patches up the loaded map to handle the parameters passed from the UI
|
||||
|
||||
// Remap sky to contents of the cvar ar_sky
|
||||
// Grab sunlight properties from the indirected sky
|
||||
|
||||
//void R_RemapShader(const char *shaderName, const char *newShaderName, const char *timeOffset);
|
||||
void R_ColorShiftLightingBytes( byte in[4], byte out[4] );
|
||||
|
||||
void NormalToLatLong( const vec3_t normal, byte bytes[2] )
|
||||
{
|
||||
// check for singularities
|
||||
if (!normal[0] && !normal[1])
|
||||
{
|
||||
if ( normal[2] > 0.0f )
|
||||
{
|
||||
bytes[0] = 0;
|
||||
bytes[1] = 0; // lat = 0, long = 0
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes[0] = 128;
|
||||
bytes[1] = 0; // lat = 0, long = 128
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int a, b;
|
||||
|
||||
a = (int)(RAD2DEG( (vec_t)atan2( normal[1], normal[0] ) ) * (255.0f / 360.0f ));
|
||||
a &= 0xff;
|
||||
|
||||
b = (int)(RAD2DEG( (vec_t)acos( normal[2] ) ) * ( 255.0f / 360.0f ));
|
||||
b &= 0xff;
|
||||
|
||||
bytes[0] = b; // longitude
|
||||
bytes[1] = a; // lattitude
|
||||
}
|
||||
}
|
||||
|
||||
void R_RMGInit(void)
|
||||
{
|
||||
char newSky[MAX_QPATH];
|
||||
char newFog[MAX_QPATH];
|
||||
shader_t *sky;
|
||||
shader_t *fog;
|
||||
fog_t *gfog;
|
||||
mgrid_t *grid;
|
||||
char temp[MAX_QPATH];
|
||||
int i;
|
||||
unsigned short *pos;
|
||||
|
||||
Cvar_VariableStringBuffer("RMG_sky", newSky, MAX_QPATH);
|
||||
// Get sunlight - this should set up all the sunlight data
|
||||
sky = R_FindShader( newSky, lightmapsNone, stylesDefault, qfalse );
|
||||
|
||||
// Remap sky
|
||||
// R_RemapShader("textures/tools/_sky", newSky, NULL);
|
||||
|
||||
// Fill in the lightgrid with sunlight
|
||||
if(tr.world->lightGridData)
|
||||
{
|
||||
#ifdef _XBOX
|
||||
byte *memory = (byte *)tr.world->lightGridData;
|
||||
|
||||
byte *array;
|
||||
array = memory;
|
||||
memory += 3;
|
||||
|
||||
array[0] = (byte)Com_Clamp(0, 255, tr.sunAmbient[0] * 255.0f);
|
||||
array[1] = (byte)Com_Clamp(0, 255, tr.sunAmbient[1] * 255.0f);
|
||||
array[2] = (byte)Com_Clamp(0, 255, tr.sunAmbient[2] * 255.0f);
|
||||
|
||||
array[3] = (byte)Com_Clamp(0, 255, tr.sunLight[0]);
|
||||
array[4] = (byte)Com_Clamp(0, 255, tr.sunLight[1]);
|
||||
array[5] = (byte)Com_Clamp(0, 255, tr.sunLight[2]);
|
||||
|
||||
NormalToLatLong(tr.sunDirection, grid->latLong);
|
||||
#else // _XBOX
|
||||
grid = tr.world->lightGridData;
|
||||
grid->ambientLight[0][0] = (byte)Com_Clamp(0, 255, tr.sunAmbient[0] * 255.0f);
|
||||
grid->ambientLight[0][1] = (byte)Com_Clamp(0, 255, tr.sunAmbient[1] * 255.0f);
|
||||
grid->ambientLight[0][2] = (byte)Com_Clamp(0, 255, tr.sunAmbient[2] * 255.0f);
|
||||
R_ColorShiftLightingBytes(grid->ambientLight[0], grid->ambientLight[0]);
|
||||
|
||||
grid->directLight[0][0] = (byte)Com_Clamp(0, 255, tr.sunLight[0]);
|
||||
grid->directLight[0][1] = (byte)Com_Clamp(0, 255, tr.sunLight[1]);
|
||||
grid->directLight[0][2] = (byte)Com_Clamp(0, 255, tr.sunLight[2]);
|
||||
R_ColorShiftLightingBytes(grid->directLight[0], grid->directLight[0]);
|
||||
|
||||
NormalToLatLong(tr.sunDirection, grid->latLong);
|
||||
#endif // _XBOX
|
||||
|
||||
pos = tr.world->lightGridArray;
|
||||
for(i=0;i<tr.world->numGridArrayElements;i++)
|
||||
{
|
||||
*pos = 0;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
// Override the global fog with the defined one
|
||||
if(tr.world->globalFog != -1)
|
||||
{
|
||||
Cvar_VariableStringBuffer("RMG_fog", newFog, MAX_QPATH);
|
||||
fog = R_FindShader( newFog, lightmapsNone, stylesDefault, qfalse);
|
||||
if (fog != tr.defaultShader)
|
||||
{
|
||||
gfog = tr.world->fogs + tr.world->globalFog;
|
||||
gfog->parms = *fog->fogParms;
|
||||
if (gfog->parms.depthForOpaque)
|
||||
{
|
||||
gfog->tcScale = 1.0f / ( gfog->parms.depthForOpaque * 8.0f );
|
||||
tr.distanceCull = gfog->parms.depthForOpaque;
|
||||
Cvar_Set("RMG_distancecull", va("%f", tr.distanceCull));
|
||||
}
|
||||
else
|
||||
{
|
||||
gfog->tcScale = 1.0f;
|
||||
}
|
||||
gfog->colorInt = ColorBytes4 ( gfog->parms.color[0],
|
||||
gfog->parms.color[1],
|
||||
gfog->parms.color[2], 1.0f );
|
||||
}
|
||||
}
|
||||
|
||||
Cvar_VariableStringBuffer("RMG_weather", temp, MAX_QPATH);
|
||||
|
||||
// Set up any weather effects
|
||||
switch(atol(temp))
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
R_WorldEffectCommand("rain init 1000");
|
||||
R_WorldEffectCommand("rain outside");
|
||||
break;
|
||||
case 2:
|
||||
R_WorldEffectCommand("snow init 1000 outside");
|
||||
R_WorldEffectCommand("snow outside");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// end
|
||||
2073
code/renderer/tr_backend.cpp
Normal file
2073
code/renderer/tr_backend.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1458
code/renderer/tr_bsp.cpp
Normal file
1458
code/renderer/tr_bsp.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1699
code/renderer/tr_bsp_xbox.cpp
Normal file
1699
code/renderer/tr_bsp_xbox.cpp
Normal file
File diff suppressed because it is too large
Load Diff
512
code/renderer/tr_cmds.cpp
Normal file
512
code/renderer/tr_cmds.cpp
Normal file
@@ -0,0 +1,512 @@
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
#include "tr_local.h"
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
R_PerformanceCounters
|
||||
=====================
|
||||
*/
|
||||
void R_PerformanceCounters( void ) {
|
||||
#ifndef _XBOX
|
||||
if ( !r_speeds->integer ) {
|
||||
// clear the counters even if we aren't printing
|
||||
memset( &tr.pc, 0, sizeof( tr.pc ) );
|
||||
memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if (r_speeds->integer == 1) {
|
||||
const float texSize = R_SumOfUsedImages( qfalse )/(8*1048576.0f)*(r_texturebits->integer?r_texturebits->integer:glConfig.colorBits);
|
||||
VID_Printf (PRINT_ALL, "%i/%i shdrs/srfs %i leafs %i vrts %i/%i tris %.2fMB tex %.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,
|
||||
texSize, backEnd.pc.c_overDraw / (float)(glConfig.vidWidth * glConfig.vidHeight) );
|
||||
} else if (r_speeds->integer == 2) {
|
||||
VID_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 );
|
||||
VID_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) {
|
||||
VID_Printf (PRINT_ALL, "viewcluster: %i\n", tr.viewCluster );
|
||||
} else if (r_speeds->integer == 4) {
|
||||
if ( backEnd.pc.c_dlightVertexes ) {
|
||||
VID_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 )
|
||||
{
|
||||
VID_Printf( PRINT_ALL, "zFar: %.0f\n", tr.viewParms.zFar );
|
||||
}
|
||||
else if (r_speeds->integer == 6 )
|
||||
{
|
||||
VID_Printf( PRINT_ALL, "flare adds:%i tests:%i renders:%i\n",
|
||||
backEnd.pc.c_flareAdds, backEnd.pc.c_flareTests, backEnd.pc.c_flareRenders );
|
||||
}
|
||||
else if (r_speeds->integer == 7) {
|
||||
const float texSize = R_SumOfUsedImages(qtrue) / (1048576.0f);
|
||||
const float backBuff= glConfig.vidWidth * glConfig.vidHeight * glConfig.colorBits / (8.0f * 1024*1024);
|
||||
const float depthBuff= glConfig.vidWidth * glConfig.vidHeight * glConfig.depthBits / (8.0f * 1024*1024);
|
||||
const float stencilBuff= glConfig.vidWidth * glConfig.vidHeight * glConfig.stencilBits / (8.0f * 1024*1024);
|
||||
VID_Printf (PRINT_ALL, "Tex MB %.2f + buffers %.2f MB = Total %.2fMB\n",
|
||||
texSize, backBuff*2+depthBuff+stencilBuff, texSize+backBuff*2+depthBuff+stencilBuff);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset( &tr.pc, 0, sizeof( tr.pc ) );
|
||||
memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
R_InitCommandBuffers
|
||||
====================
|
||||
*/
|
||||
void R_InitCommandBuffers( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
R_ShutdownCommandBuffers
|
||||
====================
|
||||
*/
|
||||
void R_ShutdownCommandBuffers( void ) {
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
R_IssueRenderCommands
|
||||
====================
|
||||
*/
|
||||
int c_blockedOnRender;
|
||||
int c_blockedOnMain;
|
||||
|
||||
void R_IssueRenderCommands( qboolean runPerformanceCounters ) {
|
||||
renderCommandList_t *cmdList;
|
||||
|
||||
cmdList = &backEndData->commands;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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
|
||||
RB_ExecuteRenderCommands( cmdList->cmds );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
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 ) {
|
||||
#ifndef _XBOX
|
||||
if ( !tr.registered ) {
|
||||
return;
|
||||
}
|
||||
R_IssueRenderCommands( qfalse );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
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->commands;
|
||||
|
||||
// always leave room for the end of list command
|
||||
if ( cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS ) {
|
||||
#if defined(_DEBUG) && defined(_XBOX)
|
||||
Com_Printf(S_COLOR_RED"Command buffer overflow! Tell Brian.\n");
|
||||
#endif
|
||||
if ( bytes > MAX_RENDER_COMMANDS - 4 ) {
|
||||
Com_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 = (drawSurfsCommand_t *) 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;
|
||||
|
||||
cmd = (setColorCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) );
|
||||
if ( !cmd ) {
|
||||
return;
|
||||
}
|
||||
cmd->commandId = RC_SET_COLOR;
|
||||
if ( rgba ) {
|
||||
cmd->color[0] = rgba[0];
|
||||
cmd->color[1] = rgba[1];
|
||||
cmd->color[2] = rgba[2];
|
||||
cmd->color[3] = rgba[3];
|
||||
return;
|
||||
}
|
||||
|
||||
cmd->color[0] = 1;
|
||||
cmd->color[1] = 1;
|
||||
cmd->color[2] = 1;
|
||||
cmd->color[3] = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
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;
|
||||
|
||||
cmd = (stretchPicCommand_t *) 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_RotatePic
|
||||
=============
|
||||
*/
|
||||
void RE_RotatePic ( float x, float y, float w, float h,
|
||||
float s1, float t1, float s2, float t2,float a, qhandle_t hShader ) {
|
||||
rotatePicCommand_t *cmd;
|
||||
|
||||
cmd = (rotatePicCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) );
|
||||
if ( !cmd ) {
|
||||
return;
|
||||
}
|
||||
cmd->commandId = RC_ROTATE_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;
|
||||
cmd->a = a;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
RE_RotatePic2
|
||||
=============
|
||||
*/
|
||||
void RE_RotatePic2 ( float x, float y, float w, float h,
|
||||
float s1, float t1, float s2, float t2,float a, qhandle_t hShader ) {
|
||||
rotatePicCommand_t *cmd;
|
||||
|
||||
cmd = (rotatePicCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) );
|
||||
if ( !cmd ) {
|
||||
return;
|
||||
}
|
||||
cmd->commandId = RC_ROTATE_PIC2;
|
||||
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;
|
||||
cmd->a = a;
|
||||
}
|
||||
|
||||
void RE_LAGoggles( void )
|
||||
{
|
||||
tr.refdef.rdflags |= (RDF_doLAGoggles|RDF_doFullbright);
|
||||
|
||||
fog_t *fog = &tr.world->fogs[tr.world->numfogs];
|
||||
|
||||
fog->parms.color[0] = 0.75f;
|
||||
fog->parms.color[1] = 0.42f + random() * 0.025f;
|
||||
fog->parms.color[2] = 0.07f;
|
||||
fog->parms.color[3] = 1.0f;
|
||||
fog->parms.depthForOpaque = 10000;
|
||||
fog->colorInt = ColorBytes4(fog->parms.color[0], fog->parms.color[1], fog->parms.color[2], fog->parms.color[3]);
|
||||
fog->tcScale = 2.0f / ( fog->parms.depthForOpaque * (1.0f + cos( tr.refdef.floatTime) * 0.1f));
|
||||
}
|
||||
|
||||
void RE_RenderWorldEffects(void)
|
||||
{
|
||||
setModeCommand_t *cmd;
|
||||
|
||||
cmd = (setModeCommand_t *)R_GetCommandBuffer( sizeof( *cmd ) );
|
||||
if ( !cmd ) {
|
||||
return;
|
||||
}
|
||||
cmd->commandId = RC_WORLD_EFFECTS;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
RE_Scissor
|
||||
=============
|
||||
*/
|
||||
void RE_Scissor ( float x, float y, float w, float h)
|
||||
{
|
||||
scissorCommand_t *cmd;
|
||||
|
||||
cmd = (scissorCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) );
|
||||
if ( !cmd ) {
|
||||
return;
|
||||
}
|
||||
cmd->commandId = RC_SCISSOR;
|
||||
cmd->x = x;
|
||||
cmd->y = y;
|
||||
cmd->w = w;
|
||||
cmd->h = h;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
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
|
||||
//
|
||||
#ifndef _XBOX
|
||||
if ( r_measureOverdraw->integer )
|
||||
{
|
||||
if ( glConfig.stencilBits < 4 )
|
||||
{
|
||||
VID_Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits );
|
||||
Cvar_Set( "r_measureOverdraw", "0" );
|
||||
r_measureOverdraw->modified = qfalse;
|
||||
}
|
||||
else if ( r_shadows->integer == 2 )
|
||||
{
|
||||
VID_Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" );
|
||||
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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// texturemode stuff
|
||||
//
|
||||
if ( r_textureMode->modified || r_ext_texture_filter_anisotropic->modified) {
|
||||
R_SyncRenderThread();
|
||||
GL_TextureMode( r_textureMode->string );
|
||||
r_textureMode->modified = qfalse;
|
||||
r_ext_texture_filter_anisotropic->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 ) {
|
||||
Com_Error( ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!\n", err );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// draw buffer stuff
|
||||
//
|
||||
cmd = (drawBufferCommand_t *) 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 {
|
||||
Com_Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
|
||||
}
|
||||
} else {
|
||||
if ( stereoFrame != STEREO_CENTER ) {
|
||||
Com_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 = (swapBuffersCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) );
|
||||
if ( !cmd ) {
|
||||
return;
|
||||
}
|
||||
cmd->commandId = RC_SWAP_BUFFERS;
|
||||
|
||||
#ifdef _XBOX
|
||||
if (!qglBeginFrame()) return;
|
||||
#endif
|
||||
|
||||
R_IssueRenderCommands( qtrue );
|
||||
|
||||
#ifdef _XBOX
|
||||
RE_ProcessDissolve(); // render the disolve now
|
||||
qglEndFrame();
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
|
||||
for(int i=0;i<MAX_LIGHT_STYLES;i++)
|
||||
{
|
||||
styleUpdated[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
903
code/renderer/tr_curve.cpp
Normal file
903
code/renderer/tr_curve.cpp
Normal file
@@ -0,0 +1,903 @@
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
|
||||
#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
|
||||
============
|
||||
*/
|
||||
#ifdef _XBOX
|
||||
static void LerpDrawVert( drawVert_t *a, drawVert_t *b, drawVert_t *out ) {
|
||||
int k;
|
||||
out->xyz[0] = 0.5 * (a->xyz[0] + b->xyz[0]);
|
||||
out->xyz[1] = 0.5 * (a->xyz[1] + b->xyz[1]);
|
||||
out->xyz[2] = 0.5 * (a->xyz[2] + b->xyz[2]);
|
||||
|
||||
out->dvst[0] = (short)(0.5 * (float)(a->dvst[0] + b->dvst[0]));
|
||||
out->dvst[1] = (short)(0.5 * (float)(a->dvst[1] + b->dvst[1]));
|
||||
|
||||
out->normal[0] = 0.5 * (a->normal[0] + b->normal[0]);
|
||||
out->normal[1] = 0.5 * (a->normal[1] + b->normal[1]);
|
||||
out->normal[2] = 0.5 * (a->normal[2] + b->normal[2]);
|
||||
|
||||
for(k=0;k<MAXLIGHTMAPS;k++)
|
||||
{
|
||||
out->dvlightmap[k][0] = (short)(0.5 * (float)(a->dvlightmap[k][0] + b->dvlightmap[k][0]));
|
||||
out->dvlightmap[k][1] = (short)(0.5 * (float)(a->dvlightmap[k][1] + b->dvlightmap[k][1]));
|
||||
|
||||
#ifdef COMPRESS_VERTEX_COLORS
|
||||
// Need to do averaging per every four bits
|
||||
for (int j = 0; j < 2; ++j)
|
||||
{
|
||||
byte ah, al, bh, bl;
|
||||
ah = a->dvcolor[k][j] >> 4;
|
||||
al = a->dvcolor[k][j] & 0x0F;
|
||||
bh = b->dvcolor[k][j] >> 4;
|
||||
bl = b->dvcolor[k][j] & 0x0F;
|
||||
out->dvcolor[k][j] = (((ah+bh) / 2) << 4) | ((al+bl) / 2);
|
||||
}
|
||||
#else
|
||||
out->dvcolor[k][0] = (a->dvcolor[k][0] + b->dvcolor[k][0]) / 2;
|
||||
out->dvcolor[k][1] = (a->dvcolor[k][1] + b->dvcolor[k][1]) / 2;
|
||||
out->dvcolor[k][2] = (a->dvcolor[k][2] + b->dvcolor[k][2]) / 2;
|
||||
out->dvcolor[k][3] = (a->dvcolor[k][3] + b->dvcolor[k][3]) / 2;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#else // _XBOX
|
||||
|
||||
static void LerpDrawVert( drawVert_t *a, drawVert_t *b, drawVert_t *out ) {
|
||||
int k;
|
||||
out->xyz[0] = 0.5 * (a->xyz[0] + b->xyz[0]);
|
||||
out->xyz[1] = 0.5 * (a->xyz[1] + b->xyz[1]);
|
||||
out->xyz[2] = 0.5 * (a->xyz[2] + b->xyz[2]);
|
||||
|
||||
out->st[0] = 0.5 * (a->st[0] + b->st[0]);
|
||||
out->st[1] = 0.5 * (a->st[1] + b->st[1]);
|
||||
|
||||
out->normal[0] = 0.5 * (a->normal[0] + b->normal[0]);
|
||||
out->normal[1] = 0.5 * (a->normal[1] + b->normal[1]);
|
||||
out->normal[2] = 0.5 * (a->normal[2] + b->normal[2]);
|
||||
|
||||
for(k=0;k<MAXLIGHTMAPS;k++)
|
||||
{
|
||||
out->lightmap[k][0] = 0.5 * (a->lightmap[k][0] + b->lightmap[k][0]);
|
||||
out->lightmap[k][1] = 0.5 * (a->lightmap[k][1] + b->lightmap[k][1]);
|
||||
|
||||
out->color[k][0] = (a->color[k][0] + b->color[k][0]) >> 1;
|
||||
out->color[k][1] = (a->color[k][1] + b->color[k][1]) >> 1;
|
||||
out->color[k][2] = (a->color[k][2] + b->color[k][2]) >> 1;
|
||||
out->color[k][3] = (a->color[k][3] + b->color[k][3]) >> 1;
|
||||
}
|
||||
}
|
||||
#endif // _XBOX
|
||||
|
||||
/*
|
||||
============
|
||||
Transpose
|
||||
============
|
||||
*/
|
||||
#ifdef _XBOX
|
||||
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*MAX_GRID_SIZE+i];
|
||||
ctrl[j*MAX_GRID_SIZE+i] = ctrl[i*MAX_GRID_SIZE+j];
|
||||
ctrl[i*MAX_GRID_SIZE+j] = temp;
|
||||
} else {
|
||||
// just copy
|
||||
ctrl[j*MAX_GRID_SIZE+i] = ctrl[i*MAX_GRID_SIZE+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for ( i = 0 ; i < width ; i++ ) {
|
||||
for ( j = i + 1 ; j < height ; j++ ) {
|
||||
if ( j < width ) {
|
||||
// swap the value
|
||||
temp = ctrl[i*MAX_GRID_SIZE+j];
|
||||
ctrl[i*MAX_GRID_SIZE+j] = ctrl[j*MAX_GRID_SIZE+i];
|
||||
ctrl[j*MAX_GRID_SIZE+i] = temp;
|
||||
} else {
|
||||
// just copy
|
||||
ctrl[i*MAX_GRID_SIZE+j] = ctrl[j*MAX_GRID_SIZE+i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#else // _XBOX
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
=================
|
||||
MakeMeshNormals
|
||||
|
||||
Handles all the complicated wrapping and degenerate cases
|
||||
=================
|
||||
*/
|
||||
#ifdef _XBOX
|
||||
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;
|
||||
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*MAX_GRID_SIZE+0].xyz, ctrl[i*MAX_GRID_SIZE+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*MAX_GRID_SIZE+i].xyz, ctrl[(height-1)*MAX_GRID_SIZE+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*MAX_GRID_SIZE+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*MAX_GRID_SIZE+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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else // _XBOX
|
||||
|
||||
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;
|
||||
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 = VectorLength( 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 = VectorLength( 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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
InvertCtrl
|
||||
============
|
||||
*/
|
||||
#ifdef _XBOX
|
||||
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*MAX_GRID_SIZE+j];
|
||||
ctrl[i*MAX_GRID_SIZE+j] = ctrl[i*MAX_GRID_SIZE+width-1-j];
|
||||
ctrl[i*MAX_GRID_SIZE+width-1-j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else // _XBOX
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // _XBOX
|
||||
|
||||
/*
|
||||
=================
|
||||
InvertErrorTable
|
||||
=================
|
||||
*/
|
||||
#ifdef _XBOX
|
||||
static void InvertErrorTable( float* errorTable/*[2][MAX_GRID_SIZE]*/, int width, int height ) {
|
||||
int i;
|
||||
float copy[2][MAX_GRID_SIZE];
|
||||
|
||||
memcpy( copy, errorTable, sizeof( copy ) );
|
||||
|
||||
for ( i = 0 ; i < width ; i++ ) {
|
||||
errorTable[1*MAX_GRID_SIZE+i] = copy[0][i]; //[width-1-i];
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < height ; i++ ) {
|
||||
errorTable[0*MAX_GRID_SIZE+i] = copy[1][height-1-i];
|
||||
}
|
||||
|
||||
}
|
||||
#else // _XBOX
|
||||
static void InvertErrorTable( float errorTable[2][MAX_GRID_SIZE], int width, int height ) {
|
||||
int i;
|
||||
float copy[2][MAX_GRID_SIZE];
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
}
|
||||
#endif // _XBOX
|
||||
|
||||
/*
|
||||
==================
|
||||
PutPointsOnCurve
|
||||
==================
|
||||
*/
|
||||
#ifdef _XBOX
|
||||
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*MAX_GRID_SIZE+i], &ctrl[(j+1)*MAX_GRID_SIZE+i], &prev );
|
||||
LerpDrawVert( &ctrl[j*MAX_GRID_SIZE+i], &ctrl[(j-1)*MAX_GRID_SIZE+i], &next );
|
||||
LerpDrawVert( &prev, &next, &ctrl[j*MAX_GRID_SIZE+i] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for ( j = 0 ; j < height ; j++ ) {
|
||||
for ( i = 1 ; i < width ; i += 2 ) {
|
||||
LerpDrawVert( &ctrl[j*MAX_GRID_SIZE+i], &ctrl[j*MAX_GRID_SIZE+i+1], &prev );
|
||||
LerpDrawVert( &ctrl[j*MAX_GRID_SIZE+i], &ctrl[j*MAX_GRID_SIZE+i-1], &next );
|
||||
LerpDrawVert( &prev, &next, &ctrl[j*MAX_GRID_SIZE+i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else // _XBOX
|
||||
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] );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // _XBOX
|
||||
|
||||
/*
|
||||
=================
|
||||
R_SubdividePatchToGrid
|
||||
|
||||
=================
|
||||
*/
|
||||
#ifdef _XBOX
|
||||
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, drawVert_t* points,
|
||||
drawVert_t* ctrl, float* errorTable ) {
|
||||
int i, j, k, l;
|
||||
drawVert_t prev, next, mid;
|
||||
float len, maxLen;
|
||||
int dir;
|
||||
int t;
|
||||
srfGridMesh_t *grid;
|
||||
drawVert_t *vert;
|
||||
vec3_t tmpVec;
|
||||
|
||||
for ( i = 0 ; i < width ; i++ ) {
|
||||
for ( j = 0 ; j < height ; j++ ) {
|
||||
ctrl[j*MAX_GRID_SIZE+i] = points[j*width+i];
|
||||
}
|
||||
}
|
||||
|
||||
for ( dir = 0 ; dir < 2 ; dir++ ) {
|
||||
|
||||
for ( j = 0 ; j < MAX_GRID_SIZE ; j++ ) {
|
||||
errorTable[dir*MAX_GRID_SIZE+j] = 0;
|
||||
}
|
||||
|
||||
// horizontal subdivisions
|
||||
for ( j = 0 ; j + 2 < width ; j += 2 ) {
|
||||
// check subdivided midpoints against control points
|
||||
maxLen = 0;
|
||||
for ( i = 0 ; i < height ; i++ ) {
|
||||
vec3_t midxyz;
|
||||
vec3_t dir;
|
||||
vec3_t projected;
|
||||
float d;
|
||||
|
||||
// calculate the point on the curve
|
||||
for ( l = 0 ; l < 3 ; l++ ) {
|
||||
midxyz[l] = (ctrl[i*MAX_GRID_SIZE+j].xyz[l]
|
||||
+ ctrl[i*MAX_GRID_SIZE+j+1].xyz[l] * 2
|
||||
+ ctrl[i*MAX_GRID_SIZE+j+2].xyz[l] ) * 0.25;
|
||||
}
|
||||
|
||||
// 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*MAX_GRID_SIZE+j].xyz, midxyz );
|
||||
VectorSubtract( ctrl[i*MAX_GRID_SIZE+j+2].xyz, ctrl[i*MAX_GRID_SIZE+j].xyz, dir );
|
||||
VectorNormalize( dir );
|
||||
|
||||
d = DotProduct( midxyz, dir );
|
||||
VectorScale( dir, d, projected );
|
||||
VectorSubtract( midxyz, projected, midxyz);
|
||||
len = VectorLengthSquared( midxyz );
|
||||
|
||||
if ( len > maxLen ) {
|
||||
maxLen = len;
|
||||
}
|
||||
}
|
||||
maxLen = sqrt(maxLen);
|
||||
|
||||
// if all the points are on the lines, remove the entire columns
|
||||
if ( maxLen < 0.1 ) {
|
||||
errorTable[dir*MAX_GRID_SIZE+j+1] = 999;
|
||||
continue;
|
||||
}
|
||||
|
||||
// see if we want to insert subdivided columns
|
||||
if ( width + 2 > MAX_GRID_SIZE ) {
|
||||
errorTable[dir*MAX_GRID_SIZE+j+1] = 1.0/maxLen;
|
||||
continue; // can't subdivide any more
|
||||
}
|
||||
|
||||
if ( maxLen <= r_subdivisions->value ) {
|
||||
errorTable[dir*MAX_GRID_SIZE+j+1] = 1.0/maxLen;
|
||||
continue; // didn't need subdivision
|
||||
}
|
||||
|
||||
errorTable[dir*MAX_GRID_SIZE+j+2] = 1.0/maxLen;
|
||||
|
||||
// insert two columns and replace the peak
|
||||
width += 2;
|
||||
for ( i = 0 ; i < height ; i++ ) {
|
||||
LerpDrawVert( &ctrl[i*MAX_GRID_SIZE+j], &ctrl[i*MAX_GRID_SIZE+j+1], &prev );
|
||||
LerpDrawVert( &ctrl[i*MAX_GRID_SIZE+j+1], &ctrl[i*MAX_GRID_SIZE+j+2], &next );
|
||||
LerpDrawVert( &prev, &next, &mid );
|
||||
|
||||
for ( k = width - 1 ; k > j + 3 ; k-- ) {
|
||||
ctrl[i*MAX_GRID_SIZE+k] = ctrl[i*MAX_GRID_SIZE+k-2];
|
||||
}
|
||||
ctrl[i*MAX_GRID_SIZE+j + 1] = prev;
|
||||
ctrl[i*MAX_GRID_SIZE+j + 2] = mid;
|
||||
ctrl[i*MAX_GRID_SIZE+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*MAX_GRID_SIZE+i] != 999 ) {
|
||||
continue;
|
||||
}
|
||||
for ( j = i+1 ; j < width ; j++ ) {
|
||||
for ( k = 0 ; k < height ; k++ ) {
|
||||
ctrl[k*MAX_GRID_SIZE+j-1] = ctrl[k*MAX_GRID_SIZE+j];
|
||||
}
|
||||
errorTable[0*MAX_GRID_SIZE+j-1] = errorTable[0*MAX_GRID_SIZE+j];
|
||||
}
|
||||
width--;
|
||||
}
|
||||
|
||||
for ( i = 1 ; i < height-1 ; i++ ) {
|
||||
if ( errorTable[1*MAX_GRID_SIZE+i] != 999 ) {
|
||||
continue;
|
||||
}
|
||||
for ( j = i+1 ; j < height ; j++ ) {
|
||||
for ( k = 0 ; k < width ; k++ ) {
|
||||
ctrl[(j-1)*MAX_GRID_SIZE+k] = ctrl[j*MAX_GRID_SIZE+k];
|
||||
}
|
||||
errorTable[1*MAX_GRID_SIZE+j-1] = errorTable[1*MAX_GRID_SIZE+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 );
|
||||
|
||||
// copy the results out to a grid
|
||||
grid = (struct srfGridMesh_s *) Hunk_Alloc( (width * height - 1) * sizeof( drawVert_t ) + sizeof( *grid ) + width * 4 + height * 4, qtrue );
|
||||
|
||||
grid->widthLodError = (float*)(((char*)grid) + (width * height - 1) *
|
||||
sizeof(drawVert_t) + sizeof(*grid));
|
||||
memcpy( grid->widthLodError, &errorTable[0*MAX_GRID_SIZE], width * 4 );
|
||||
|
||||
grid->heightLodError = (float*)(((char*)grid->widthLodError) + width * 4);
|
||||
memcpy( grid->heightLodError, &errorTable[1*MAX_GRID_SIZE], height * 4 );
|
||||
|
||||
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*MAX_GRID_SIZE+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;
|
||||
}
|
||||
|
||||
#else // _XBOX
|
||||
|
||||
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
|
||||
drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
|
||||
int i, j, k, l;
|
||||
drawVert_t prev, next, mid;
|
||||
float len, maxLen;
|
||||
int dir;
|
||||
int t;
|
||||
MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
|
||||
float errorTable[2][MAX_GRID_SIZE];
|
||||
srfGridMesh_t *grid;
|
||||
drawVert_t *vert;
|
||||
vec3_t tmpVec;
|
||||
|
||||
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
|
||||
maxLen = 0;
|
||||
for ( i = 0 ; i < height ; i++ ) {
|
||||
vec3_t midxyz;
|
||||
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.25;
|
||||
}
|
||||
|
||||
// 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, midxyz);
|
||||
len = VectorLength( midxyz );
|
||||
|
||||
if ( len > maxLen ) {
|
||||
maxLen = len;
|
||||
}
|
||||
}
|
||||
|
||||
// if all the points are on the lines, remove the entire columns
|
||||
if ( maxLen < 0.1 ) {
|
||||
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.0/maxLen;
|
||||
continue; // can't subdivide any more
|
||||
}
|
||||
|
||||
if ( maxLen <= r_subdivisions->value ) {
|
||||
errorTable[dir][j+1] = 1.0/maxLen;
|
||||
continue; // didn't need subdivision
|
||||
}
|
||||
|
||||
errorTable[dir][j+2] = 1.0/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 );
|
||||
|
||||
// copy the results out to a grid
|
||||
grid = (struct srfGridMesh_s *) Hunk_Alloc( (width * height - 1) * sizeof( drawVert_t ) + sizeof( *grid ), qtrue );
|
||||
|
||||
grid->widthLodError = (float *) Hunk_Alloc( width * 4, qfalse );
|
||||
memcpy( grid->widthLodError, errorTable[0], width * 4 );
|
||||
|
||||
grid->heightLodError = (float *) Hunk_Alloc( height * 4, qfalse );
|
||||
memcpy( grid->heightLodError, errorTable[1], height * 4 );
|
||||
|
||||
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;
|
||||
}
|
||||
#endif // _XBOX
|
||||
1155
code/renderer/tr_draw.cpp
Normal file
1155
code/renderer/tr_draw.cpp
Normal file
File diff suppressed because it is too large
Load Diff
427
code/renderer/tr_flares.cpp
Normal file
427
code/renderer/tr_flares.cpp
Normal file
@@ -0,0 +1,427 @@
|
||||
// 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
|
||||
float lightScale;
|
||||
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;
|
||||
|
||||
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, float lightScale) {
|
||||
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;
|
||||
f->lightScale = lightScale;
|
||||
|
||||
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, 1.0f );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
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.0 - ( ( 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 = f->lightScale * backEnd.viewParms.viewportWidth * ( r_flareSize->value/640.0 + 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();
|
||||
}
|
||||
|
||||
1785
code/renderer/tr_font.cpp
Normal file
1785
code/renderer/tr_font.cpp
Normal file
File diff suppressed because it is too large
Load Diff
34
code/renderer/tr_font.h
Normal file
34
code/renderer/tr_font.h
Normal file
@@ -0,0 +1,34 @@
|
||||
// Filename:- tr_font.h
|
||||
//
|
||||
// font support
|
||||
|
||||
// This file is shared in the single and multiplayer codebases, so be CAREFUL WHAT YOU ADD/CHANGE!!!!!
|
||||
|
||||
#ifndef TR_FONT_H
|
||||
#define TR_FONT_H
|
||||
|
||||
|
||||
void R_ShutdownFonts(void);
|
||||
void R_InitFonts(void);
|
||||
int RE_RegisterFont(const char *psName);
|
||||
int RE_Font_StrLenPixels(const char *psText, const int iFontHandle, const float fScale = 1.0f);
|
||||
int RE_Font_StrLenChars(const char *psText);
|
||||
int RE_Font_HeightPixels(const int iFontHandle, const float fScale = 1.0f);
|
||||
void RE_Font_DrawString(int ox, int oy, const char *psText, const float *rgba, const int iFontHandle, int iMaxPixelWidth, const float fScale = 1.0f);
|
||||
|
||||
// Dammit, I can't use this more elegant form because of !@#@!$%% VM code... (can't alter passed in ptrs, only contents of)
|
||||
//
|
||||
//unsigned int AnyLanguage_ReadCharFromString( const char **ppsText, qboolean *pbIsTrailingPunctuation = NULL);
|
||||
//
|
||||
// so instead we have to use this messier method...
|
||||
//
|
||||
unsigned int AnyLanguage_ReadCharFromString( const char *psText, int *piAdvanceCount, qboolean *pbIsTrailingPunctuation = NULL);
|
||||
|
||||
qboolean Language_IsAsian(void);
|
||||
qboolean Language_UsesSpaces(void);
|
||||
|
||||
|
||||
#endif // #ifndef TR_FONT_H
|
||||
|
||||
// end
|
||||
|
||||
4906
code/renderer/tr_ghoul2.cpp
Normal file
4906
code/renderer/tr_ghoul2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2678
code/renderer/tr_image.cpp
Normal file
2678
code/renderer/tr_image.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1633
code/renderer/tr_init.cpp
Normal file
1633
code/renderer/tr_init.cpp
Normal file
File diff suppressed because it is too large
Load Diff
541
code/renderer/tr_jpeg_interface.cpp
Normal file
541
code/renderer/tr_jpeg_interface.cpp
Normal file
@@ -0,0 +1,541 @@
|
||||
// Filename:- tr_jpeg_interace.cpp
|
||||
//
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
|
||||
#include "tr_local.h"
|
||||
#include "tr_jpeg_interface.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"
|
||||
|
||||
// JPG decompression now subroutinised so I can call it from the savegame stuff...
|
||||
//
|
||||
// (note, the param "byte* pJPGData" should be a malloc of 4K more than the JPG data because the decompressor will read
|
||||
// up to 4K beyond what's actually presented during decompression).
|
||||
//
|
||||
// This will Z_Malloc the output data buffer that gets fed back into "pic", so Z_Free it yourself later.
|
||||
//
|
||||
void Decompress_JPG( const char *filename, byte *pJPGData, 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;
|
||||
/* 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 */
|
||||
int row_stride; /* physical row width in output buffer */
|
||||
unsigned char *out;
|
||||
byte *bbuf;
|
||||
|
||||
/* 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, pJPGData);
|
||||
|
||||
/* 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 */
|
||||
row_stride = cinfo.output_width * cinfo.output_components;
|
||||
|
||||
if (cinfo.output_components!=4 && cinfo.output_components!=1 ) {
|
||||
VID_Printf(PRINT_WARNING, "JPG %s is unsupported color depth (%d)\n", filename, cinfo.output_components);
|
||||
}
|
||||
out = (byte *)Z_Malloc(cinfo.output_width*cinfo.output_height*4, TAG_TEMP_JPG, qfalse );
|
||||
|
||||
*pic = out;
|
||||
*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.
|
||||
*/
|
||||
bbuf = ((out+(row_stride*cinfo.output_scanline)));
|
||||
buffer = &bbuf;
|
||||
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
}
|
||||
|
||||
// if we've just loaded a greyscale, then adjust it from 8-bit to 32bit by stretch-copying it over itself...
|
||||
// (this also does the alpha stuff as well)
|
||||
//
|
||||
if (cinfo.output_components == 1)
|
||||
{
|
||||
byte *pbDest = (*pic + (cinfo.output_width * cinfo.output_height * 4))-1;
|
||||
byte *pbSrc = (*pic + (cinfo.output_width * cinfo.output_height ))-1;
|
||||
int iPixels = cinfo.output_width * cinfo.output_height;
|
||||
|
||||
for (int i=0; i<iPixels; i++)
|
||||
{
|
||||
byte b = *pbSrc--;
|
||||
*pbDest-- = 255;
|
||||
*pbDest-- = b;
|
||||
*pbDest-- = b;
|
||||
*pbDest-- = b;
|
||||
}
|
||||
}
|
||||
else
|
||||
{// clear all the alphas to 255
|
||||
int i, j;
|
||||
byte *buf;
|
||||
|
||||
buf = *pic;
|
||||
|
||||
j = cinfo.output_width * cinfo.output_height * 4;
|
||||
for ( i = 3 ; i < j ; i+=4 ) {
|
||||
buf[i] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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...)
|
||||
*/
|
||||
|
||||
/* 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! */
|
||||
}
|
||||
|
||||
int LoadJPG( const char *filename, unsigned char **pic, int *width, int *height )
|
||||
{
|
||||
*pic = NULL;
|
||||
|
||||
fileHandle_t h;
|
||||
const int len = FS_FOpenFileRead( filename, &h, qfalse );
|
||||
if(!h)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
//JPEG system reads 4K past input buffer so we tack on an additional 4k.
|
||||
byte *pJPGData = (byte *)Z_Malloc(len + 4096, TAG_TEMP_JPG, qfalse);
|
||||
FS_Read(pJPGData, len, h);
|
||||
FS_FCloseFile( h );
|
||||
|
||||
Decompress_JPG( filename, pJPGData, pic, width, height );
|
||||
|
||||
Z_Free (pJPGData);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
// returns a Z_Malloc'd piece of mem that you should free up yourself
|
||||
//
|
||||
byte *Compress_JPG(int *pOutputSize, int quality, int image_width, int image_height, byte *image_buffer, qboolean bInvertDuringCompression)
|
||||
{
|
||||
/* 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 */
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
byte *out = // (unsigned char *)ri.Hunk_AllocateTempMemory(image_width*image_height*4);
|
||||
(unsigned char *)Z_Malloc(image_width*image_height*4, TAG_TEMP_JPG, qfalse);
|
||||
|
||||
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.
|
||||
*/
|
||||
if (bInvertDuringCompression)
|
||||
{
|
||||
row_pointer[0] = & image_buffer[((cinfo.image_height-1)*row_stride)-cinfo.next_scanline * row_stride];
|
||||
}
|
||||
else
|
||||
{
|
||||
row_pointer[0] = & image_buffer[ cinfo.next_scanline * row_stride];
|
||||
}
|
||||
|
||||
jpeg_write_scanlines(&cinfo, row_pointer, 1);
|
||||
}
|
||||
|
||||
/* Step 6: Finish compression */
|
||||
|
||||
jpeg_finish_compress(&cinfo);
|
||||
|
||||
/* 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! */
|
||||
|
||||
*pOutputSize = hackSize;
|
||||
return out;
|
||||
}
|
||||
|
||||
void SaveJPG(const char * filename, int quality, int image_width, int image_height, unsigned char *image_buffer)
|
||||
{
|
||||
int iOutputSize = 0;
|
||||
|
||||
byte *pbOut = Compress_JPG(&iOutputSize, quality, image_width, image_height, image_buffer, qtrue);
|
||||
|
||||
FS_WriteFile( filename, pbOut, iOutputSize );
|
||||
|
||||
Z_Free(pbOut);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void JPG_ErrorThrow(LPCSTR message)
|
||||
{
|
||||
Com_Error( ERR_FATAL, "JPG: %s\n", message );
|
||||
}
|
||||
|
||||
void JPG_MessageOut(LPCSTR message)
|
||||
{
|
||||
VID_Printf(PRINT_ALL, "%s\n", message);
|
||||
}
|
||||
|
||||
//////////////// eof ////////////
|
||||
|
||||
40
code/renderer/tr_jpeg_interface.h
Normal file
40
code/renderer/tr_jpeg_interface.h
Normal file
@@ -0,0 +1,40 @@
|
||||
// Filename:- tr_jpeg_interface.h
|
||||
//
|
||||
#pragma warning (disable: 4100) //unreferenced formal parameter
|
||||
#pragma warning (disable: 4127) //conditional expression is constant
|
||||
#pragma warning (disable: 4244) //int to unsigned short
|
||||
|
||||
#ifndef TR_JPEG_INTERFACE_H
|
||||
#define TR_JPEG_INTERFACE_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef LPCSTR
|
||||
typedef const char * LPCSTR;
|
||||
#endif
|
||||
|
||||
int LoadJPG( const char *filename, unsigned char **pic, int *width, int *height );
|
||||
void SaveJPG( const char *filename, int quality, int image_width, int image_height, unsigned char *image_buffer);
|
||||
|
||||
void JPG_ErrorThrow(LPCSTR message);
|
||||
void JPG_MessageOut(LPCSTR message);
|
||||
#define ERROR_STRING_NO_RETURN(message) JPG_ErrorThrow(message)
|
||||
#define MESSAGE_STRING(message) JPG_MessageOut(message)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif // #ifndef TR_JPEG_INTERFACE_H
|
||||
|
||||
|
||||
////////////////// eof //////////////////
|
||||
|
||||
193
code/renderer/tr_landscape.h
Normal file
193
code/renderer/tr_landscape.h
Normal file
@@ -0,0 +1,193 @@
|
||||
#ifndef _INC_LANDSCAPE_H
|
||||
#define _INC_LANDSCAPE_H
|
||||
|
||||
// Number of TriTreeNodes available
|
||||
#define POOL_SIZE (50000)
|
||||
|
||||
#define TEXTURE_ALPHA_TL 0x000000ff
|
||||
#define TEXTURE_ALPHA_TR 0x0000ff00
|
||||
#define TEXTURE_ALPHA_BL 0x00ff0000
|
||||
#define TEXTURE_ALPHA_BR 0x000000ff
|
||||
|
||||
#define INDEX_TL 0
|
||||
#define INDEX_TR 1
|
||||
#define INDEX_BL 2
|
||||
#define INDEX_BR 3
|
||||
|
||||
#define VARIANCE_MIN 0.0f
|
||||
#define VARIANCE_MAX 2000.0f
|
||||
#define SPLIT_VARIANCE_SIZE 20
|
||||
#define SPLIT_VARIANCE_STEP (VARIANCE_MAX / SPLIT_VARIANCE_SIZE)
|
||||
|
||||
#define VectorAverage(a,b,c) (((c)[0]=((a)[0]+(b)[0])*0.5f),((c)[1]=((a)[1]+(b)[1])*0.5f),((c)[2]=((a)[2]+(b)[2])*0.5f))
|
||||
|
||||
class CTerVert
|
||||
{
|
||||
public:
|
||||
vec3_t coords; // real world coords of terxel
|
||||
vec3_t normal; // required to calculate lighting and used in physics
|
||||
color4ub_t tint; // tint at this terxel
|
||||
float tex[2]; // texture coordinates at this terxel
|
||||
int height; // Copy of heightmap data
|
||||
int tessIndex; // Index of the vert in the tess array
|
||||
int tessRegistration; // ...... for the tess with this registration
|
||||
|
||||
CTerVert( void ) { memset(this, 0, sizeof(*this)); }
|
||||
~CTerVert( void ) { }
|
||||
};
|
||||
|
||||
class CTRHeightDetails
|
||||
{
|
||||
private:
|
||||
qhandle_t mShader;
|
||||
public:
|
||||
CTRHeightDetails( void ) { }
|
||||
~CTRHeightDetails( void ) { }
|
||||
|
||||
const qhandle_t GetShader( void ) const { return(mShader); }
|
||||
void SetShader(const qhandle_t shader) { mShader = shader; }
|
||||
};
|
||||
|
||||
//
|
||||
// Information of each patch (tessellated area) of a CTRLandScape
|
||||
//
|
||||
class CTRPatch
|
||||
{
|
||||
private:
|
||||
class CCMLandScape *owner;
|
||||
class CTRLandScape *localowner;
|
||||
|
||||
CCMPatch *common;
|
||||
vec3_t mCenter; // Real world center of the patch
|
||||
// vec3_t mNormal[2];
|
||||
// float mDistance[2];
|
||||
|
||||
CTerVert *mRenderMap; // Modulation value and texture coords per vertex
|
||||
shader_t *mTLShader; // Dynamically created blended shader for the top left triangle
|
||||
shader_t *mBRShader; // Dynamically created blended shader for the bottom right triangle
|
||||
|
||||
bool misVisible; // Is this patch visible in the current frame?
|
||||
|
||||
public:
|
||||
CTRPatch(void) { }
|
||||
~CTRPatch(void) { }
|
||||
|
||||
// Accessors
|
||||
const vec3_t &GetWorld(void) const { return(common->GetWorld()); }
|
||||
const vec3_t &GetMins(void) const { return(common->GetMins()); }
|
||||
const vec3_t &GetMaxs(void) const { return(common->GetMaxs()); }
|
||||
const vec3pair_t &GetBounds(void) const { return(common->GetBounds()); }
|
||||
shader_t *GetTLShader(void) { return mTLShader; }
|
||||
shader_t *GetBRShader(void) { return mBRShader; }
|
||||
|
||||
void SetCommon(CCMPatch *in) { common = in; }
|
||||
const CCMPatch *GetCommon(void) const { return(common); }
|
||||
bool isVisible(void) { return(misVisible); }
|
||||
void SetTLShader(qhandle_t in) { mTLShader = R_GetShaderByHandle(in); }
|
||||
void SetBRShader(qhandle_t in) { mBRShader = R_GetShaderByHandle(in); }
|
||||
void SetOwner(CCMLandScape *in) { owner = in; }
|
||||
void SetLocalOwner(CTRLandScape *in) { localowner = in; }
|
||||
void Clear(void) { memset(this, 0, sizeof(*this)); }
|
||||
void SetCenter(void) { VectorAverage(common->GetMins(), common->GetMaxs(), mCenter); }
|
||||
void CalcNormal(void);
|
||||
|
||||
// Prototypes
|
||||
void SetVisibility(bool visCheck);
|
||||
void RenderCorner(ivec5_t corner);
|
||||
void Render(int Part);
|
||||
void RecurseRender(int depth, ivec5_t left, ivec5_t right, ivec5_t apex);
|
||||
void SetRenderMap(const int x, const int y);
|
||||
int RenderWaterVert(int x, int y);
|
||||
void RenderWater(void);
|
||||
const bool HasWater(void) const;
|
||||
};
|
||||
|
||||
|
||||
#define PI_TOP 1
|
||||
#define PI_BOTTOM 2
|
||||
#define PI_BOTH 3
|
||||
|
||||
typedef struct SPatchInfo
|
||||
{
|
||||
CTRPatch *mPatch;
|
||||
shader_t *mShader;
|
||||
int mPart;
|
||||
} TPatchInfo;
|
||||
|
||||
//
|
||||
// The master class used to define an area of terrain
|
||||
//
|
||||
|
||||
class CTRLandScape
|
||||
{
|
||||
private:
|
||||
const CCMLandScape *common;
|
||||
CTRPatch *mTRPatches; // Local patch info
|
||||
TPatchInfo *mSortedPatches;
|
||||
|
||||
int mPatchMinx, mPatchMaxx;
|
||||
int mPatchMiny, mPatchMaxy;
|
||||
int mMaxNode; // terxels * terxels = exit condition for splitting
|
||||
int mSortedCount;
|
||||
|
||||
float mPatchSize;
|
||||
|
||||
shader_t *mShader; // shader the terrain got its contents from
|
||||
|
||||
CTerVert *mRenderMap; // modulation value and texture coords per vertex
|
||||
float mTextureScale; // Scale of texture mapped to terrain
|
||||
|
||||
float mScalarSize;
|
||||
|
||||
shader_t *mWaterShader; // Water shader
|
||||
qhandle_t mFlatShader; // Flat ground shader
|
||||
|
||||
CTRHeightDetails mHeightDetails[HEIGHT_RESOLUTION]; // Array of info specific to height
|
||||
#if _DEBUG
|
||||
int mCycleCount;
|
||||
#endif
|
||||
public:
|
||||
CTRLandScape(const char *configstring);
|
||||
~CTRLandScape(void);
|
||||
|
||||
// Accessors
|
||||
const int GetBlockWidth(void) const { return(common->GetBlockWidth()); }
|
||||
const int GetBlockHeight(void) const { return(common->GetBlockHeight()); }
|
||||
const vec3_t &GetMins(void) const { return(common->GetMins()); }
|
||||
const vec3_t &GetMaxs(void) const { return(common->GetMaxs()); }
|
||||
const vec3_t &GetTerxelSize(void) const { return(common->GetTerxelSize()); }
|
||||
const vec3_t &GetPatchSize(void) const { return(common->GetPatchSize()); }
|
||||
const int GetWidth(void) const { return(common->GetWidth()); }
|
||||
const int GetHeight(void) const { return(common->GetHeight()); }
|
||||
const int GetRealWidth(void) const { return(common->GetRealWidth()); }
|
||||
const int GetRealHeight(void) const { return(common->GetRealHeight()); }
|
||||
|
||||
void SetCommon(const CCMLandScape *landscape) { common = landscape; }
|
||||
const CCMLandScape *GetCommon( void ) const { return(common); }
|
||||
const thandle_t GetCommonId( void ) const { return(common->GetTerrainId()); }
|
||||
shader_t *GetShader(void) const { return(mShader); }
|
||||
CTerVert *GetRenderMap(const int x, const int y) const { return(mRenderMap + x + (y * common->GetRealWidth())); }
|
||||
CTRPatch *GetPatch(const int x, const int y) const { return(mTRPatches + (common->GetBlockWidth() * y) + x); }
|
||||
const CTRHeightDetails *GetHeightDetail(int height) const { return(mHeightDetails + height); }
|
||||
const float GetScalarSize(void) const { return(mScalarSize); }
|
||||
const int GetMaxNode(void) const { return(mMaxNode); }
|
||||
|
||||
// Prototypes
|
||||
void CalculateRegion(void);
|
||||
void Reset(bool visCheck = true);
|
||||
void Render(void);
|
||||
void CalculateRealCoords(void);
|
||||
void CalculateNormals(void);
|
||||
void CalculateTextureCoords(void);
|
||||
void CalculateLighting(void);
|
||||
void CalculateShaders(void);
|
||||
qhandle_t GetBlendedShader(qhandle_t a, qhandle_t b, qhandle_t c, bool surfaceSprites);
|
||||
void LoadTerrainDef(const char *td);
|
||||
void CopyHeightMap(void);
|
||||
void SetShaders(const int height, const qhandle_t shader);
|
||||
};
|
||||
|
||||
void R_CalcTerrainVisBounds(CTRLandScape *landscape);
|
||||
void R_AddTerrainSurfaces(void);
|
||||
|
||||
#endif //INC_LANDSCAPE_H
|
||||
572
code/renderer/tr_light.cpp
Normal file
572
code/renderer/tr_light.cpp
Normal file
@@ -0,0 +1,572 @@
|
||||
// tr_light.c
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
#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
|
||||
=============
|
||||
*/
|
||||
#ifndef VV_LIGHTING
|
||||
void R_DlightBmodel( bmodel_t *bmodel, qboolean NoLight ) {
|
||||
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;
|
||||
if (!NoLight)
|
||||
{
|
||||
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);
|
||||
tr.currentEntity->dlightBits = mask;
|
||||
|
||||
|
||||
// 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 = mask;
|
||||
} else if ( *surf->data == SF_GRID ) {
|
||||
((srfGridMesh_t *)surf->data)->dlightBits = mask;
|
||||
} else if ( *surf->data == SF_TRIANGLES ) {
|
||||
((srfTriangles_t *)surf->data)->dlightBits = mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // VV_LIGHTING
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
LIGHT SAMPLING
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
extern cvar_t *r_ambientScale;
|
||||
extern cvar_t *r_directedScale;
|
||||
extern cvar_t *r_debugLight;
|
||||
|
||||
/*
|
||||
=================
|
||||
R_SetupEntityLightingGrid
|
||||
|
||||
=================
|
||||
*/
|
||||
#ifdef VV_LIGHTING
|
||||
void R_SetupEntityLightingGrid( trRefEntity_t *ent ) {
|
||||
#else
|
||||
static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) {
|
||||
#endif
|
||||
vec3_t lightOrigin;
|
||||
int pos[3];
|
||||
int i, j;
|
||||
float frac[3];
|
||||
int gridStep[3];
|
||||
vec3_t direction;
|
||||
float totalFactor;
|
||||
unsigned short *startGridPos;
|
||||
#ifdef _XBOX
|
||||
byte zeroArray[3];
|
||||
byte style;
|
||||
|
||||
zeroArray[0] = zeroArray[1] = zeroArray[2] = 0;
|
||||
#endif
|
||||
|
||||
|
||||
if (r_fullbright->integer || (tr.refdef.rdflags & RDF_doLAGoggles) )
|
||||
{
|
||||
ent->ambientLight[0] = ent->ambientLight[1] = ent->ambientLight[2] = 255.0;
|
||||
ent->directedLight[0] = ent->directedLight[1] = ent->directedLight[2] = 255.0;
|
||||
VectorCopy( tr.sunDirection, ent->lightDir );
|
||||
return;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
#define ACCURATE_LIGHTGRID_SAMPLING 1
|
||||
#if ACCURATE_LIGHTGRID_SAMPLING
|
||||
vec3_t startLightOrigin;
|
||||
VectorCopy( lightOrigin, startLightOrigin );
|
||||
#endif
|
||||
|
||||
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 );
|
||||
|
||||
// trilerp the light value
|
||||
gridStep[0] = 1;
|
||||
gridStep[1] = tr.world->lightGridBounds[0];
|
||||
gridStep[2] = tr.world->lightGridBounds[0] * tr.world->lightGridBounds[1];
|
||||
startGridPos = tr.world->lightGridArray + pos[0] * gridStep[0]
|
||||
+ pos[1] * gridStep[1] + pos[2] * gridStep[2];
|
||||
#if ACCURATE_LIGHTGRID_SAMPLING
|
||||
vec3_t startGridOrg;
|
||||
VectorCopy( tr.world->lightGridOrigin, startGridOrg );
|
||||
startGridOrg[0] += pos[0] * tr.world->lightGridSize[0];
|
||||
startGridOrg[1] += pos[1] * tr.world->lightGridSize[1];
|
||||
startGridOrg[2] += pos[2] * tr.world->lightGridSize[2];
|
||||
#endif
|
||||
totalFactor = 0;
|
||||
for ( i = 0 ; i < 8 ; i++ ) {
|
||||
float factor;
|
||||
mgrid_t *data;
|
||||
unsigned short *gridPos;
|
||||
int lat, lng;
|
||||
vec3_t normal;
|
||||
#if ACCURATE_LIGHTGRID_SAMPLING
|
||||
vec3_t gridOrg;
|
||||
VectorCopy( startGridOrg, gridOrg );
|
||||
#endif
|
||||
|
||||
factor = 1.0;
|
||||
gridPos = startGridPos;
|
||||
for ( j = 0 ; j < 3 ; j++ ) {
|
||||
if ( i & (1<<j) ) {
|
||||
factor *= frac[j];
|
||||
gridPos += gridStep[j];
|
||||
#if ACCURATE_LIGHTGRID_SAMPLING
|
||||
gridOrg[j] += tr.world->lightGridSize[j];
|
||||
#endif
|
||||
} else {
|
||||
factor *= (1.0 - frac[j]);
|
||||
}
|
||||
}
|
||||
|
||||
if (gridPos >= tr.world->lightGridArray + tr.world->numGridArrayElements)
|
||||
{//we've gone off the array somehow
|
||||
continue;
|
||||
}
|
||||
data = tr.world->lightGridData + *gridPos;
|
||||
|
||||
#ifdef _XBOX
|
||||
const byte *memory = (const byte *)tr.world->lightGridData + data->data;
|
||||
|
||||
style = data->flags & (1 << 4) ? memory[0] : LS_NONE;
|
||||
if ( style == LS_NONE )
|
||||
{
|
||||
continue; // ignore samples in walls
|
||||
}
|
||||
|
||||
totalFactor += factor;
|
||||
|
||||
const byte *array;
|
||||
|
||||
for(j=0;j<MAXLIGHTMAPS;j++)
|
||||
{
|
||||
if(data->flags & (1 << (j + 4))) {
|
||||
style = *memory;
|
||||
memory++;
|
||||
} else {
|
||||
style = LS_NONE;
|
||||
}
|
||||
|
||||
if (style != LS_NONE)
|
||||
{
|
||||
if(data->flags & (1 << j)) {
|
||||
array = memory;
|
||||
memory += 3;
|
||||
} else {
|
||||
array = zeroArray;
|
||||
}
|
||||
|
||||
ent->ambientLight[0] += factor * array[0] * styleColors[style][0] / 255.0f;
|
||||
ent->ambientLight[1] += factor * array[1] * styleColors[style][1] / 255.0f;
|
||||
ent->ambientLight[2] += factor * array[2] * styleColors[style][2] / 255.0f;
|
||||
|
||||
if(array != zeroArray) {
|
||||
array = memory;
|
||||
memory += 3;
|
||||
}
|
||||
|
||||
ent->directedLight[0] += factor * array[0] * styleColors[style][0] / 255.0f;
|
||||
ent->directedLight[1] += factor * array[1] * styleColors[style][1] / 255.0f;
|
||||
ent->directedLight[2] += factor * array[2] * styleColors[style][2] / 255.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#else // _XBOX
|
||||
|
||||
if ( data->styles[0] == LS_NONE )
|
||||
{
|
||||
continue; // ignore samples in walls
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ( !SV_inPVS( startLightOrigin, gridOrg ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
totalFactor += factor;
|
||||
|
||||
for(j=0;j<MAXLIGHTMAPS;j++)
|
||||
{
|
||||
if (data->styles[j] != LS_NONE)
|
||||
{
|
||||
const byte style= data->styles[j];
|
||||
|
||||
ent->ambientLight[0] += factor * data->ambientLight[j][0] * styleColors[style][0] / 255.0f;
|
||||
ent->ambientLight[1] += factor * data->ambientLight[j][1] * styleColors[style][1] / 255.0f;
|
||||
ent->ambientLight[2] += factor * data->ambientLight[j][2] * styleColors[style][2] / 255.0f;
|
||||
|
||||
ent->directedLight[0] += factor * data->directLight[j][0] * styleColors[style][0] / 255.0f;
|
||||
ent->directedLight[1] += factor * data->directLight[j][1] * styleColors[style][1] / 255.0f;
|
||||
ent->directedLight[2] += factor * data->directLight[j][2] * styleColors[style][2] / 255.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _XBOX
|
||||
|
||||
lat = data->latLong[1];
|
||||
lng = data->latLong[0];
|
||||
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 ACCURATE_LIGHTGRID_SAMPLING
|
||||
#ifndef _XBOX
|
||||
if ( r_debugLight->integer && ent->e.hModel == -1 )
|
||||
{
|
||||
//draw
|
||||
refEntity_t refEnt;
|
||||
refEnt.hModel = 0;
|
||||
refEnt.ghoul2 = NULL;
|
||||
refEnt.renderfx = 0;
|
||||
VectorCopy( gridOrg, refEnt.origin );
|
||||
vectoangles( normal, refEnt.angles );
|
||||
AnglesToAxis( refEnt.angles, refEnt.axis );
|
||||
refEnt.reType = RT_MODEL;
|
||||
RE_AddRefEntityToScene( &refEnt );
|
||||
|
||||
refEnt.renderfx = RF_DEPTHHACK;
|
||||
refEnt.reType = RT_SPRITE;
|
||||
refEnt.customShader = RE_RegisterShader( "gfx/misc/debugAmbient" );
|
||||
refEnt.shaderRGBA[0] = data->ambientLight[0][0];
|
||||
refEnt.shaderRGBA[1] = data->ambientLight[0][1];
|
||||
refEnt.shaderRGBA[2] = data->ambientLight[0][2];
|
||||
refEnt.shaderRGBA[3] = 255;
|
||||
refEnt.radius = factor*50+2.0f; // maybe always give it a minimum size?
|
||||
refEnt.rotation = 0; // don't let the sprite wobble around
|
||||
RE_AddRefEntityToScene( &refEnt );
|
||||
|
||||
refEnt.reType = RT_LINE;
|
||||
refEnt.customShader = RE_RegisterShader( "gfx/misc/debugArrow" );
|
||||
refEnt.shaderRGBA[0] = data->directLight[0][0];
|
||||
refEnt.shaderRGBA[1] = data->directLight[0][1];
|
||||
refEnt.shaderRGBA[2] = data->directLight[0][2];
|
||||
refEnt.shaderRGBA[3] = 255;
|
||||
VectorCopy( refEnt.origin, refEnt.oldorigin );
|
||||
VectorMA( gridOrg, (factor*-255) - 2.0f, normal, refEnt.origin ); // maybe always give it a minimum length
|
||||
refEnt.radius = 1.5f;
|
||||
RE_AddRefEntityToScene( &refEnt );
|
||||
}
|
||||
#endif // _XBOX
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( totalFactor > 0 && totalFactor < 0.99 )
|
||||
{
|
||||
totalFactor = 1.0 / 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 = VectorLength( ent->ambientLight );
|
||||
/*
|
||||
max1 = ent->ambientLight[0];
|
||||
if ( ent->ambientLight[1] > max1 ) {
|
||||
max1 = ent->ambientLight[1];
|
||||
} else if ( ent->ambientLight[2] > max1 ) {
|
||||
max1 = ent->ambientLight[2];
|
||||
}
|
||||
*/
|
||||
|
||||
max2 = VectorLength( ent->directedLight );
|
||||
/*
|
||||
max2 = ent->directedLight[0];
|
||||
if ( ent->directedLight[1] > max2 ) {
|
||||
max2 = ent->directedLight[1];
|
||||
} else if ( ent->directedLight[2] > max2 ) {
|
||||
max2 = ent->directedLight[2];
|
||||
}
|
||||
*/
|
||||
|
||||
VID_Printf( PRINT_ALL, "amb:%i dir:%i direction: (%4.2f, %4.2f, %4.2f)\n", max1, max2, ent->lightDir[0], ent->lightDir[1], ent->lightDir[2] );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
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 ) {
|
||||
#ifndef VV_LIGHTING
|
||||
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 ( ent->e.renderfx & RF_MORELIGHT ) {
|
||||
ent->ambientLight[0] += tr.identityLight * 96;
|
||||
ent->ambientLight[1] += tr.identityLight * 96;
|
||||
ent->ambientLight[2] += tr.identityLight * 96;
|
||||
}
|
||||
else {
|
||||
// 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] );
|
||||
|
||||
#endif // VV_LIGHTING
|
||||
}
|
||||
|
||||
//pass in origin
|
||||
qboolean RE_GetLighting( const vec3_t origin, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir) {
|
||||
trRefEntity_t tr_ent;
|
||||
|
||||
if ( !tr.world || !tr.world->lightGridData) {
|
||||
ambientLight[0] = ambientLight[1] = ambientLight[2] = 255.0;
|
||||
directedLight[0] = directedLight[1] = directedLight[2] = 255.0;
|
||||
VectorCopy( tr.sunDirection, lightDir );
|
||||
return qfalse;
|
||||
}
|
||||
memset (&tr_ent, 0, sizeof(tr_ent) );
|
||||
|
||||
if ( ambientLight[0] == 666 )
|
||||
{//HAX0R
|
||||
tr_ent.e.hModel = -1;
|
||||
}
|
||||
|
||||
VectorCopy (origin, tr_ent.e.origin);
|
||||
R_SetupEntityLightingGrid( &tr_ent );
|
||||
VectorCopy ( tr_ent.ambientLight, ambientLight);
|
||||
VectorCopy ( tr_ent.directedLight, directedLight);
|
||||
VectorCopy ( tr_ent.lightDir, lightDir);
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
944
code/renderer/tr_lightmanager.cpp
Normal file
944
code/renderer/tr_lightmanager.cpp
Normal file
@@ -0,0 +1,944 @@
|
||||
/*
|
||||
** tr_lightmanager.cpp
|
||||
*/
|
||||
|
||||
#ifdef VV_LIGHTING
|
||||
|
||||
#include "../server/exe_headers.h"
|
||||
#include "tr_local.h"
|
||||
|
||||
#include "tr_lightmanager.h"
|
||||
|
||||
#include "../win32/glw_win_dx8.h"
|
||||
#include "../win32/win_lighteffects.h"
|
||||
|
||||
|
||||
VVLightManager VVLightMan;
|
||||
|
||||
|
||||
VVLightManager::VVLightManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void VVLightManager::RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
|
||||
VVdlight_t *dl;
|
||||
|
||||
if ( !tr.registered ) {
|
||||
return;
|
||||
}
|
||||
if ( num_dlights >= MAX_DLIGHTS ) {
|
||||
return;
|
||||
}
|
||||
if ( intensity <= 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
dl = &dlights[num_dlights++];
|
||||
|
||||
VectorCopy (org, dl->origin);
|
||||
dl->type = LT_POINT;
|
||||
dl->radius = intensity;// * 5.0f;
|
||||
dl->color[0] = r;
|
||||
dl->color[1] = g;
|
||||
dl->color[2] = b;
|
||||
}
|
||||
|
||||
void VVLightManager::RE_AddLightToScene( VVdlight_t *light )
|
||||
{
|
||||
VVdlight_t *dl;
|
||||
|
||||
if ( !tr.registered ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( num_dlights >= MAX_DLIGHTS ) {
|
||||
return;
|
||||
}
|
||||
|
||||
dl = &dlights[num_dlights++];
|
||||
|
||||
VectorCopy(light->origin, dl->origin);
|
||||
VectorCopy(light->direction, dl->direction);
|
||||
VectorCopy(light->color, dl->color);
|
||||
dl->attenuation = light->attenuation;
|
||||
dl->type = light->type;
|
||||
dl->radius = light->radius;
|
||||
}
|
||||
|
||||
|
||||
//void VVLightManager::RE_AddStaticLightToScene( VVslight_t *light )
|
||||
//{
|
||||
// VVslight_t *sl;
|
||||
//
|
||||
// if( !tr.registered ) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if( num_slights >= MAX_NUM_STATIC_LIGHTS ) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// sl = &slights[num_slights++];
|
||||
//
|
||||
// VectorCopy(light->origin, sl->origin);
|
||||
// VectorCopy(light->color, sl->color);
|
||||
// sl->radius = light->radius;// * 2.0f;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
void VVLightManager::R_TransformDlights( orientationr_t *orient) {
|
||||
int i;
|
||||
vec3_t temp;
|
||||
VVdlight_t *dl;
|
||||
|
||||
for ( i = 0 ; i < num_dlights ; i++ ) {
|
||||
dl = &dlights[i];
|
||||
VectorSubtract( dl->origin, orient->origin, temp );
|
||||
dl->transformed[0] = DotProduct( temp, orient->axis[0] );
|
||||
dl->transformed[1] = DotProduct( temp, orient->axis[1] );
|
||||
dl->transformed[2] = DotProduct( temp, orient->axis[2] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
R_DlightBmodel
|
||||
|
||||
Determine which dynamic lights may effect this bmodel
|
||||
=============
|
||||
*/
|
||||
void VVLightManager::R_DlightBmodel( bmodel_t *bmodel, qboolean NoLight ) {
|
||||
int i, j;
|
||||
VVdlight_t *dl;
|
||||
int mask;
|
||||
msurface_t *surf;
|
||||
|
||||
mask = 0;
|
||||
|
||||
// transform all the lights
|
||||
R_TransformDlights( &tr.or );
|
||||
|
||||
if (!NoLight)
|
||||
{
|
||||
for ( i=0 ; i<num_dlights ; i++ ) {
|
||||
dl = &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;
|
||||
}
|
||||
}
|
||||
// Directional lights are always considered (MATT - change that?)
|
||||
if ( j < 3 && dl->type != LT_DIRECTIONAL ) {
|
||||
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 = mask;
|
||||
} else if ( *surf->data == SF_GRID ) {
|
||||
((srfGridMesh_t *)surf->data)->dlightBits = mask;
|
||||
} else if ( *surf->data == SF_TRIANGLES ) {
|
||||
((srfTriangles_t *)surf->data)->dlightBits = mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int VVLightManager::R_DlightFace( srfSurfaceFace_t *face, int dlightBits ) {
|
||||
float d;
|
||||
int i;
|
||||
VVdlight_t *dl;
|
||||
|
||||
for ( i = 0 ; i < num_dlights ; i++ ) {
|
||||
|
||||
/*if ( ! ( dlightBits & ( 1 << i ) ) ) {
|
||||
continue;
|
||||
}*/
|
||||
dlightBits |= (1 << i);
|
||||
|
||||
dl = &dlights[i];
|
||||
d = DotProduct( dl->origin, face->plane.normal ) - face->plane.dist;
|
||||
// Directional lights are always considered (MATT - change that?)
|
||||
if ( d < -dl->radius || d > dl->radius ) {
|
||||
// dlight doesn't reach the plane
|
||||
dlightBits &= ~( 1 << i );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !dlightBits ) {
|
||||
tr.pc.c_dlightSurfacesCulled++;
|
||||
}
|
||||
|
||||
face->dlightBits = dlightBits;
|
||||
return dlightBits;
|
||||
}
|
||||
|
||||
|
||||
//void VVLightManager::R_SlightFace( srfSurfaceFace_t *face ) {
|
||||
// float d;
|
||||
// int i, count = 0;
|
||||
// VVslight_t *sl;
|
||||
//
|
||||
// for ( i = 0; i < num_slights; i++ ) {
|
||||
//
|
||||
// if(count > MAX_STATIC_LIGHTS_SURFACE - 1)
|
||||
// break;
|
||||
//
|
||||
// sl = &slights[i];
|
||||
// d = DotProduct( sl->origin, face->plane.normal ) - face->plane.dist;
|
||||
//
|
||||
// if ( d > -sl->radius && d < sl->radius ) {
|
||||
// face->slightBits[count++] = i;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
int VVLightManager::R_DlightGrid( srfGridMesh_t *grid, int dlightBits ) {
|
||||
int i;
|
||||
VVdlight_t *dl;
|
||||
|
||||
for ( i = 0 ; i < num_dlights ; i++ ) {
|
||||
if ( ! ( dlightBits & ( 1 << i ) ) ) {
|
||||
continue;
|
||||
}
|
||||
dl = &dlights[i];
|
||||
// Directional lights are always considered (MATT - change that?)
|
||||
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] )
|
||||
&& dl->type != LT_DIRECTIONAL ) {
|
||||
// dlight doesn't reach the bounds
|
||||
dlightBits &= ~( 1 << i );
|
||||
}
|
||||
dlightBits |= (1 << i );
|
||||
}
|
||||
|
||||
if ( !dlightBits ) {
|
||||
tr.pc.c_dlightSurfacesCulled++;
|
||||
}
|
||||
|
||||
grid->dlightBits = dlightBits;
|
||||
return dlightBits;
|
||||
}
|
||||
|
||||
|
||||
//void VVLightManager::R_SlightGrid( srfGridMesh_t *grid ) {
|
||||
// int i, count = 0;
|
||||
// VVslight_t *sl;
|
||||
//
|
||||
// for ( i = 0 ; i < num_slights ; i++ ) {
|
||||
//
|
||||
// if(count > MAX_STATIC_LIGHTS_SURFACE - 1)
|
||||
// break;
|
||||
//
|
||||
// sl = &slights[i];
|
||||
//
|
||||
// if ( sl->origin[0] - sl->radius > grid->meshBounds[1][0]
|
||||
// || sl->origin[0] + sl->radius < grid->meshBounds[0][0]
|
||||
// || sl->origin[1] - sl->radius > grid->meshBounds[1][1]
|
||||
// || sl->origin[1] + sl->radius < grid->meshBounds[0][1]
|
||||
// || sl->origin[2] - sl->radius > grid->meshBounds[1][2]
|
||||
// || sl->origin[2] + sl->radius < grid->meshBounds[0][2] ) {
|
||||
// // slight doesn't reach the bounds
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// grid->slightBits[count++]= i;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
int VVLightManager::R_DlightTrisurf( srfTriangles_t *surf, int dlightBits ) {
|
||||
// FIXME: more dlight culling to trisurfs...
|
||||
surf->dlightBits = dlightBits;
|
||||
return dlightBits;
|
||||
}
|
||||
|
||||
|
||||
//void VVLightManager::R_SlightTrisurf( srfTriangles_t *surf ) {
|
||||
// /*int i;
|
||||
//
|
||||
// for( i = 0; i < num_slights; i++ )
|
||||
// {
|
||||
// slightBits[i] = 1;
|
||||
// }*/
|
||||
//}
|
||||
|
||||
/*
|
||||
====================
|
||||
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.
|
||||
====================
|
||||
*/
|
||||
int VVLightManager::R_DlightSurface( msurface_t *surf, int dlightBits ) {
|
||||
if ( *surf->data == SF_FACE ) {
|
||||
dlightBits = VVLightManager::R_DlightFace( (srfSurfaceFace_t *)surf->data, dlightBits );
|
||||
} else if ( *surf->data == SF_GRID ) {
|
||||
dlightBits = VVLightManager::R_DlightGrid( (srfGridMesh_t *)surf->data, dlightBits );
|
||||
} else if ( *surf->data == SF_TRIANGLES ) {
|
||||
dlightBits = VVLightManager::R_DlightTrisurf( (srfTriangles_t *)surf->data, dlightBits );
|
||||
} else {
|
||||
dlightBits = 0;
|
||||
}
|
||||
|
||||
if ( dlightBits ) {
|
||||
tr.pc.c_dlightSurfaces++;
|
||||
}
|
||||
|
||||
return dlightBits;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
R_SetupEntityLighting
|
||||
|
||||
Calculates all the lighting values that will be used
|
||||
by the Calc_* functions
|
||||
=================
|
||||
*/
|
||||
|
||||
#define DLIGHT_AT_RADIUS 16
|
||||
#define DLIGHT_MINIMUM_RADIUS 16
|
||||
|
||||
void VVLightManager::R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
|
||||
int i;
|
||||
VVdlight_t *dl;
|
||||
vec3_t dir;
|
||||
float d;
|
||||
vec3_t lightDir;
|
||||
vec3_t shadowLightDir;
|
||||
vec3_t lightOrigin;
|
||||
float power;
|
||||
|
||||
// lighting calculations
|
||||
if ( ent->lightingCalculated ) {
|
||||
return;
|
||||
}
|
||||
ent->lightingCalculated = qtrue;
|
||||
|
||||
ent->dlightBits = 0;
|
||||
|
||||
//
|
||||
// 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;
|
||||
// BTO - Fix for UI model rendering. tr.sunDirection is invalid
|
||||
// pick an arbitrary light direction
|
||||
// VectorCopy( tr.sunDirection, ent->lightDir );
|
||||
ent->lightDir[0] = ent->lightDir[1] = 0.0f;
|
||||
ent->lightDir[2] = 1.0f;
|
||||
}
|
||||
|
||||
// bonus items and view weapons have a fixed minimum add
|
||||
if ( ent->e.renderfx & RF_MORELIGHT ) {
|
||||
ent->ambientLight[0] += tr.identityLight * 96;
|
||||
ent->ambientLight[1] += tr.identityLight * 96;
|
||||
ent->ambientLight[2] += tr.identityLight * 96;
|
||||
}
|
||||
else {
|
||||
// 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 );
|
||||
VectorScale( ent->lightDir, d, shadowLightDir );
|
||||
|
||||
for ( i = 0 ; i < num_dlights ; i++ ) {
|
||||
dl = &dlights[i];
|
||||
VectorSubtract( dl->origin, lightOrigin, dir );
|
||||
d = VectorNormalize( dir );
|
||||
|
||||
if( d <= dl->radius )
|
||||
{
|
||||
ent->dlightBits |= (1 << i);
|
||||
ent->needDlights = qtrue;
|
||||
}
|
||||
|
||||
power = DLIGHT_AT_RADIUS * ( dl->radius * dl->radius );
|
||||
if ( d < DLIGHT_MINIMUM_RADIUS ) {
|
||||
d = DLIGHT_MINIMUM_RADIUS;
|
||||
}
|
||||
d = power / ( d * d );
|
||||
|
||||
VectorMA( shadowLightDir, d, dir, shadowLightDir );
|
||||
}
|
||||
|
||||
// clamp
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
if ( ent->ambientLight[i] > tr.identityLightByte ) {
|
||||
ent->ambientLight[i] = tr.identityLightByte;
|
||||
}
|
||||
if ( ent->directedLight[i] > tr.identityLightByte ) {
|
||||
ent->directedLight[i] = tr.identityLightByte;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 );
|
||||
VectorNormalize( shadowLightDir );
|
||||
|
||||
ent->shadowDir[0] = DotProduct( shadowLightDir, ent->e.axis[0] );
|
||||
ent->shadowDir[1] = DotProduct( shadowLightDir, ent->e.axis[1] );
|
||||
ent->shadowDir[2] = DotProduct( shadowLightDir, ent->e.axis[2] );
|
||||
|
||||
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] );
|
||||
}
|
||||
|
||||
inline void Short2Float(float *f, const short *s)
|
||||
{
|
||||
*f = ((float)*s);
|
||||
}
|
||||
|
||||
void VVLightManager::ShortToVec3(const short in[3], vec3_t &out)
|
||||
{
|
||||
Short2Float(&out[0], &in[0]);
|
||||
Short2Float(&out[1], &in[1]);
|
||||
Short2Float(&out[2], &in[2]);
|
||||
}
|
||||
|
||||
int VVLightManager::BoxOnPlaneSide (const short emins[3], const short emaxs[3], struct cplane_s *p)
|
||||
{
|
||||
vec3_t mins;
|
||||
vec3_t maxs;
|
||||
ShortToVec3(emins, mins);
|
||||
ShortToVec3(emaxs, maxs);
|
||||
return ::BoxOnPlaneSide(mins, maxs, &tr.viewParms.frustum[0]);
|
||||
}
|
||||
|
||||
|
||||
void VVLightManager::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 < num_dlights ; i++ ) {
|
||||
VVdlight_t *dl;
|
||||
float dist;
|
||||
|
||||
if ( dlightBits & ( 1 << i ) ) {
|
||||
dl = &dlights[i];
|
||||
dist = DotProduct( dl->origin,
|
||||
tr.world->planes[node->planeNum].normal ) -
|
||||
tr.world->planes[node->planeNum].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;
|
||||
mleaf_s *leaf;
|
||||
|
||||
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
|
||||
leaf = (mleaf_s*)node;
|
||||
mark = tr.world->marksurfaces + leaf->firstMarkSurfNum;
|
||||
c = leaf->nummarksurfaces;
|
||||
while (c--) {
|
||||
// the surface may have already been added if it
|
||||
// spans multiple leafs
|
||||
surf = *mark;
|
||||
#ifdef _XBOX
|
||||
// MATT! - this is a temp hack until bspthing starts parsing flares
|
||||
if(surf->data)
|
||||
#endif
|
||||
R_AddWorldSurface( surf, dlightBits );
|
||||
mark++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VVLightManager::RB_CalcDiffuseColorWorld()
|
||||
{
|
||||
trRefEntity_t *ent;
|
||||
VVdlight_t *dl;
|
||||
|
||||
if(!num_dlights)
|
||||
return;
|
||||
|
||||
ent = backEnd.currentEntity;
|
||||
|
||||
for(int i = 0, l = 0; i < num_dlights; i++)
|
||||
{
|
||||
if ( ( tess.dlightBits & ( 1 << i ) ) )
|
||||
{
|
||||
qglEnable(GL_LIGHTING);
|
||||
dl = &dlights[i];
|
||||
|
||||
vec3_t newColor;
|
||||
newColor[0] = dl->color[0] * 255.0f;
|
||||
newColor[1] = dl->color[1] * 255.0f;
|
||||
newColor[2] = dl->color[2] * 255.0f;
|
||||
|
||||
qglLightfv(l, GL_DIFFUSE, newColor);
|
||||
|
||||
/* vec3_t ambient;
|
||||
ambient[0] = ambient[1] = ambient[2] = 128;
|
||||
|
||||
qglLightfv(l, GL_AMBIENT, ambient);//ent->ambientLight);*/
|
||||
|
||||
if(dl->type == LT_POINT) {
|
||||
qglLightfv(l, GL_SPOT_CUTOFF, &dl->radius);
|
||||
qglLightfv(l, GL_POSITION, dl->origin);
|
||||
} else if(dl->type == LT_DIRECTIONAL) {
|
||||
qglLightfv(l, GL_SPOT_DIRECTION, dl->direction);
|
||||
}
|
||||
|
||||
l++;
|
||||
}
|
||||
}
|
||||
|
||||
float color[4];
|
||||
color[0] = 255;
|
||||
color[1] = 255;
|
||||
color[2] = 255;
|
||||
color[3] = 255;
|
||||
qglMaterialfv( GL_FRONT, GL_AMBIENT, color );
|
||||
}
|
||||
|
||||
|
||||
void VVLightManager::RB_CalcDiffuseColor( DWORD *colors )
|
||||
{
|
||||
trRefEntity_t *ent;
|
||||
|
||||
ent = backEnd.currentEntity;
|
||||
|
||||
// Make sure to turn lighting on....
|
||||
qglEnable(GL_LIGHTING);
|
||||
|
||||
qglLightfv(0, GL_AMBIENT, ent->ambientLight);
|
||||
qglLightfv(0, GL_DIFFUSE, ent->directedLight);
|
||||
|
||||
VectorNormalize(ent->lightDir);
|
||||
|
||||
vec3_t vLight;
|
||||
vLight[0] = DotProduct( ent->lightDir, ent->e.axis[0] );
|
||||
vLight[1] = DotProduct( ent->lightDir, ent->e.axis[1] );
|
||||
vLight[2] = DotProduct( ent->lightDir, ent->e.axis[2] );
|
||||
|
||||
if(VectorLengthSquared(vLight) <= 0.0001f)
|
||||
{
|
||||
vLight[0] = 0.0f;
|
||||
vLight[1] = 1.0f;
|
||||
vLight[2] = 0.0f;
|
||||
}
|
||||
|
||||
qglLightfv(0, GL_SPOT_DIRECTION, vLight);
|
||||
|
||||
memset(colors, 0xffffffff, sizeof(DWORD) * tess.numVertexes);
|
||||
}
|
||||
|
||||
|
||||
void VVLightManager::RB_CalcDiffuseEntityColor( DWORD *colors )
|
||||
{
|
||||
if ( !backEnd.currentEntity )
|
||||
{//error, use the normal lighting
|
||||
RB_CalcDiffuseColor(colors);
|
||||
}
|
||||
|
||||
trRefEntity_t *ent;
|
||||
|
||||
ent = backEnd.currentEntity;
|
||||
|
||||
// Make sure to turn lighting on....
|
||||
qglEnable(GL_LIGHTING);
|
||||
|
||||
// Modulate ambient by entity color:
|
||||
vec3_t ambient;
|
||||
ambient[0] = ent->ambientLight[0] * (ent->e.shaderRGBA[0]/255.0);
|
||||
ambient[1] = ent->ambientLight[1] * (ent->e.shaderRGBA[1]/255.0);
|
||||
ambient[2] = ent->ambientLight[2] * (ent->e.shaderRGBA[2]/255.0);
|
||||
qglLightfv(0, GL_AMBIENT, ambient);
|
||||
qglLightfv(0, GL_DIFFUSE, ent->directedLight);
|
||||
|
||||
VectorNormalize(ent->lightDir);
|
||||
|
||||
vec3_t vLight;
|
||||
vLight[0] = DotProduct( ent->lightDir, ent->e.axis[0] );
|
||||
vLight[1] = DotProduct( ent->lightDir, ent->e.axis[1] );
|
||||
vLight[2] = DotProduct( ent->lightDir, ent->e.axis[2] );
|
||||
|
||||
if(VectorLengthSquared(vLight) <= 0.0001f)
|
||||
{
|
||||
vLight[0] = 0.0f;
|
||||
vLight[1] = 1.0f;
|
||||
vLight[2] = 0.0f;
|
||||
}
|
||||
|
||||
qglLightfv(0, GL_SPOT_DIRECTION, vLight);
|
||||
|
||||
DWORD color = D3DCOLOR_RGBA(backEnd.currentEntity->e.shaderRGBA[0],
|
||||
backEnd.currentEntity->e.shaderRGBA[1],
|
||||
backEnd.currentEntity->e.shaderRGBA[2],
|
||||
backEnd.currentEntity->e.shaderRGBA[3]);
|
||||
|
||||
for(int i = 0; i < tess.numVertexes; i++)
|
||||
{
|
||||
colors[i] = color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//void R_LoadLevelLightdef(const char *filename)
|
||||
//{
|
||||
// const char *text;
|
||||
// const char *curText;
|
||||
// char *token;
|
||||
// VVslight_t light;
|
||||
//
|
||||
// VVLightMan.num_slights = 0;
|
||||
//
|
||||
// if ( ri.FS_ReadFile( filename, (void**)&curText ) <= 0 )
|
||||
// {
|
||||
// ri.Printf( PRINT_WARNING, "WARNING: no lightdef file found\n" );
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// text = curText;
|
||||
//
|
||||
// while(1)
|
||||
// {
|
||||
// token = COM_ParseExt( &text, qtrue );
|
||||
// if(!token[0])
|
||||
// break;
|
||||
//
|
||||
// // Skip to the light's origin
|
||||
// while(strcmp(token, "origin"))
|
||||
// {
|
||||
// token = COM_ParseExt( &text, qtrue );
|
||||
// if(!token[0])
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// // Write the origin
|
||||
// // X
|
||||
// token = COM_ParseExt( &text, qtrue );
|
||||
// if(!token[0])
|
||||
// break;
|
||||
// light.origin[0] = atof(token);
|
||||
//
|
||||
// // Y
|
||||
// token = COM_ParseExt( &text, qtrue );
|
||||
// if(!token[0])
|
||||
// break;
|
||||
// light.origin[1] = atof(token);
|
||||
//
|
||||
// // Z
|
||||
// token = COM_ParseExt( &text, qtrue );
|
||||
// if(!token[0])
|
||||
// break;
|
||||
// light.origin[2] = atof(token);
|
||||
//
|
||||
// // Skip to the light's range
|
||||
// while(strcmp(token, "light"))
|
||||
// {
|
||||
// token = COM_ParseExt( &text, qtrue );
|
||||
// if(!token[0])
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// // Write the light range
|
||||
// token = COM_ParseExt( &text, qtrue );
|
||||
// if(!token[0])
|
||||
// break;
|
||||
// light.radius = atof(token);
|
||||
//
|
||||
// // Default color for now
|
||||
// light.color[0] = 1.0f;
|
||||
// light.color[1] = 1.0f;
|
||||
// light.color[2] = 1.0f;
|
||||
//
|
||||
// VVLightMan.RE_AddStaticLightToScene(&light);
|
||||
// }
|
||||
//
|
||||
// ri.FS_FreeFile( (void*)curText );
|
||||
//}
|
||||
|
||||
#define MAX_LIGHT_TABLE 55
|
||||
|
||||
static levelLightParm_t _levelLightParms[MAX_LIGHT_TABLE];
|
||||
static bool isLightInit = false;
|
||||
|
||||
static void ClearLightParmTable(void)
|
||||
{
|
||||
memset(_levelLightParms, 0, sizeof(levelLightParm_t) * MAX_LIGHT_TABLE);
|
||||
isLightInit = false;
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** R_GetLightParmsForLevel
|
||||
**
|
||||
*/
|
||||
void R_GetLightParmsForLevel()
|
||||
{
|
||||
if(!isLightInit)
|
||||
return;
|
||||
|
||||
char levelname[64];
|
||||
|
||||
COM_StripExtension(tr.world->baseName, levelname);
|
||||
|
||||
for(int i = 0; i < MAX_LIGHT_TABLE; i++)
|
||||
{
|
||||
if(Q_stricmp(COM_SkipPath(levelname), _levelLightParms[i].levelName) == 0)
|
||||
{
|
||||
if(VectorLength(_levelLightParms[i].sundir))
|
||||
{
|
||||
Cvar_SetValue("r_sundir_x", _levelLightParms[i].sundir[0]);
|
||||
Cvar_SetValue("r_sundir_y", _levelLightParms[i].sundir[1]);
|
||||
Cvar_SetValue("r_sundir_z", _levelLightParms[i].sundir[2]);
|
||||
}
|
||||
|
||||
if(_levelLightParms[i].hdrEnable)
|
||||
Cvar_Set("r_hdreffect", "1");
|
||||
else
|
||||
Cvar_Set("r_hdreffect", "0");
|
||||
Cvar_SetValue("r_hdrbloom", _levelLightParms[i].hdrBloom);
|
||||
Cvar_SetValue("r_hdrcutoff", _levelLightParms[i].hdrCutoff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** R_LoadLevelFogTable
|
||||
**
|
||||
*/
|
||||
void R_LoadLevelLightParms()
|
||||
{
|
||||
const char *lightText;
|
||||
const char *curText;
|
||||
char *token;
|
||||
int level = 0;
|
||||
|
||||
if ( FS_ReadFile( "shaders/lightparms.txt", (void**)&curText ) <= 0 )
|
||||
{
|
||||
Com_Printf( "WARNING: no light parms file found\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
ClearLightParmTable();
|
||||
|
||||
lightText = curText;
|
||||
|
||||
while(1)
|
||||
{
|
||||
// Level name
|
||||
token = COM_ParseExt( &lightText, qtrue );
|
||||
if(!token[0])
|
||||
break;
|
||||
strcpy( _levelLightParms[level].levelName, token );
|
||||
|
||||
// Sun dir X
|
||||
token = COM_ParseExt( &lightText, qtrue );
|
||||
if(!token[0])
|
||||
break;
|
||||
_levelLightParms[level].sundir[0] = atof(token);
|
||||
|
||||
// Sun dir Y
|
||||
token = COM_ParseExt( &lightText, qtrue );
|
||||
if(!token[0])
|
||||
break;
|
||||
_levelLightParms[level].sundir[1] = atof(token);
|
||||
|
||||
// Sun dir Z
|
||||
token = COM_ParseExt( &lightText, qtrue );
|
||||
if(!token[0])
|
||||
break;
|
||||
_levelLightParms[level].sundir[2] = atof(token);
|
||||
|
||||
// HDR enable
|
||||
token = COM_ParseExt( &lightText, qtrue );
|
||||
if(!token[0])
|
||||
break;
|
||||
_levelLightParms[level].hdrEnable = atof(token);
|
||||
|
||||
// HDR bloom
|
||||
token = COM_ParseExt( &lightText, qtrue );
|
||||
if(!token[0])
|
||||
break;
|
||||
_levelLightParms[level].hdrBloom = atof(token);
|
||||
|
||||
// HDR cutoff
|
||||
token = COM_ParseExt( &lightText, qtrue );
|
||||
if(!token[0])
|
||||
break;
|
||||
_levelLightParms[level].hdrCutoff = atof(token);
|
||||
|
||||
level++;
|
||||
if(level >= MAX_LIGHT_TABLE)
|
||||
break;
|
||||
}
|
||||
|
||||
isLightInit = true;
|
||||
|
||||
FS_FreeFile( (void*)curText );
|
||||
}
|
||||
|
||||
#endif //VV_LIGHTING
|
||||
70
code/renderer/tr_lightmanager.h
Normal file
70
code/renderer/tr_lightmanager.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
** tr_lightmanager.h
|
||||
*/
|
||||
|
||||
#ifndef TR_LIGHTMANAGER_H
|
||||
#define TR_LIGHTMANAGER_H
|
||||
|
||||
#include "tr_local.h"
|
||||
|
||||
#define MAX_NUM_STATIC_LIGHTS 256
|
||||
|
||||
enum VVlight_type {
|
||||
LT_DIRECTIONAL,
|
||||
LT_POINT,
|
||||
LT_SPOT
|
||||
};
|
||||
|
||||
typedef struct VVdlight_s {
|
||||
VVlight_type type;
|
||||
vec3_t origin;
|
||||
vec3_t direction;
|
||||
vec3_t color;
|
||||
vec3_t transformed;
|
||||
float radius;
|
||||
float attenuation;
|
||||
} VVdlight_t;
|
||||
|
||||
typedef struct VVslight_s {
|
||||
vec3_t origin;
|
||||
vec3_t color;
|
||||
float radius;
|
||||
} VVslight_t;
|
||||
|
||||
|
||||
class VVLightManager {
|
||||
public:
|
||||
|
||||
int num_dlights;
|
||||
int num_slights;
|
||||
VVdlight_t dlights[MAX_DLIGHTS];
|
||||
/*VVslight_t slights[MAX_NUM_STATIC_LIGHTS];
|
||||
unsigned char slightBits[MAX_NUM_STATIC_LIGHTS];*/
|
||||
int currentlight;
|
||||
|
||||
VVLightManager();
|
||||
void R_TransformDlights( orientationr_t *orient);
|
||||
void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b );
|
||||
void RE_AddLightToScene( VVdlight_t *light );
|
||||
//void RE_AddStaticLightToScene( VVslight_t *light );
|
||||
void R_DlightBmodel( bmodel_t *bmodel, qboolean NoLight );
|
||||
int R_DlightFace( srfSurfaceFace_t *face, int dlightBits );
|
||||
//void R_SlightFace( srfSurfaceFace_t *face );
|
||||
int R_DlightGrid( srfGridMesh_t *grid, int dlightBits );
|
||||
//void R_SlightGrid( srfGridMesh_t *grid );
|
||||
int R_DlightTrisurf( srfTriangles_t *surf, int dlightBits );
|
||||
//void R_SlightTrisurf( srfTriangles_t *surf );
|
||||
int R_DlightSurface( msurface_t *surf, int dlightBits );
|
||||
void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent );
|
||||
void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits );
|
||||
void RB_CalcDiffuseColorWorld();
|
||||
void RB_CalcDiffuseColor( DWORD *colors );
|
||||
void RB_CalcDiffuseEntityColor( DWORD *colors );
|
||||
void ShortToVec3(const short in[3], vec3_t &out);
|
||||
int BoxOnPlaneSide (const short emins[3], const short emaxs[3], struct cplane_s *p);
|
||||
};
|
||||
|
||||
extern VVLightManager VVLightMan;
|
||||
|
||||
|
||||
#endif
|
||||
2188
code/renderer/tr_local.h
Normal file
2188
code/renderer/tr_local.h
Normal file
File diff suppressed because it is too large
Load Diff
1726
code/renderer/tr_main.cpp
Normal file
1726
code/renderer/tr_main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
500
code/renderer/tr_marks.cpp
Normal file
500
code/renderer/tr_marks.cpp
Normal file
@@ -0,0 +1,500 @@
|
||||
// tr_marks.c -- polygon projection on the world polygons
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
|
||||
#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;
|
||||
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 ) {
|
||||
#ifdef _XBOX
|
||||
s = BoxOnPlaneSide( mins, maxs, tr.world->planes + node->planeNum );
|
||||
#else
|
||||
s = BoxOnPlaneSide( mins, maxs, node->plane );
|
||||
#endif
|
||||
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
|
||||
#ifdef _XBOX
|
||||
mleaf_s *leaf = (mleaf_s*)node;
|
||||
mark = tr.world->marksurfaces + leaf->firstMarkSurfNum;
|
||||
c = leaf->nummarksurfaces;
|
||||
#else
|
||||
mark = node->firstmarksurface;
|
||||
c = node->nummarksurfaces;
|
||||
#endif
|
||||
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
|
||||
&& *(surfaceType_t *) (surf->data) != SF_TRIANGLES )
|
||||
{
|
||||
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;
|
||||
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];
|
||||
vec3_t normal;
|
||||
vec3_t projectionDir;
|
||||
vec3_t v1, v2;
|
||||
|
||||
//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) {
|
||||
const srfGridMesh_t * const 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.
|
||||
|
||||
const int numClipPoints = 3;
|
||||
|
||||
const drawVert_t * const 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) {
|
||||
const srfSurfaceFace_t * const 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;
|
||||
*/
|
||||
#ifdef _XBOX
|
||||
const unsigned char * const indexes = (unsigned char *)( (byte *)surf + surf->ofsIndices );
|
||||
int nextSurfPoint = NEXT_SURFPOINT(surf->flags);
|
||||
#else
|
||||
const int * const indexes = (int *)( (byte *)surf + surf->ofsIndices );
|
||||
#endif
|
||||
for ( k = 0 ; k < surf->numIndices ; k += 3 ) {
|
||||
for ( j = 0 ; j < 3 ; j++ ) {
|
||||
#ifdef _XBOX
|
||||
const unsigned short* v = surf->srfPoints + nextSurfPoint * indexes[k+j];
|
||||
float fVec[3];
|
||||
Q_CastShort2Float(&fVec[0], (short*)v + 0);
|
||||
Q_CastShort2Float(&fVec[1], (short*)v + 1);
|
||||
Q_CastShort2Float(&fVec[2], (short*)v + 2);
|
||||
VectorMA( fVec, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] );
|
||||
#else
|
||||
const float * const v = surf->points[0] + VERTEXSIZE * indexes[k+j];
|
||||
VectorMA( v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] );
|
||||
#endif
|
||||
}
|
||||
// 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 if (*surfaces[i] == SF_TRIANGLES)
|
||||
{
|
||||
const srfTriangles_t * const surf = ( srfTriangles_t * ) surfaces[i];
|
||||
|
||||
for ( k = 0 ; k < surf->numIndexes ; k += 3 )
|
||||
{
|
||||
int i1=surf->indexes[k];
|
||||
int i2=surf->indexes[k+1];
|
||||
int i3=surf->indexes[k+2];
|
||||
VectorSubtract(surf->verts[i1].xyz,surf->verts[i2].xyz, v1);
|
||||
VectorSubtract(surf->verts[i3].xyz,surf->verts[i2].xyz, v2);
|
||||
CrossProduct(v1, v2, normal);
|
||||
VectorNormalizeFast(normal);
|
||||
// check the normal of this triangle
|
||||
if (DotProduct(normal, projectionDir) < -0.1)
|
||||
{
|
||||
#ifdef _XBOX
|
||||
// This is really ugly, and really inefficient. Of course, the inefficiency
|
||||
// pales in comparison to the misery that ensues once you realze that
|
||||
// MARKER_OFFSET is #define'd to be 0.
|
||||
float fVec[3];
|
||||
Q_CastShort2Float(&fVec[0], &surf->verts[i1].xyz[0]);
|
||||
Q_CastShort2Float(&fVec[1], &surf->verts[i1].xyz[1]);
|
||||
Q_CastShort2Float(&fVec[2], &surf->verts[i1].xyz[2]);
|
||||
VectorMA(fVec, MARKER_OFFSET, normal, clipPoints[0][0]);
|
||||
Q_CastShort2Float(&fVec[0], &surf->verts[i2].xyz[0]);
|
||||
Q_CastShort2Float(&fVec[1], &surf->verts[i2].xyz[1]);
|
||||
Q_CastShort2Float(&fVec[2], &surf->verts[i2].xyz[2]);
|
||||
VectorMA(fVec, MARKER_OFFSET, normal, clipPoints[0][1]);
|
||||
Q_CastShort2Float(&fVec[0], &surf->verts[i3].xyz[0]);
|
||||
Q_CastShort2Float(&fVec[1], &surf->verts[i3].xyz[1]);
|
||||
Q_CastShort2Float(&fVec[2], &surf->verts[i3].xyz[2]);
|
||||
VectorMA(fVec, MARKER_OFFSET, normal, clipPoints[0][2]);
|
||||
#else
|
||||
VectorMA(surf->verts[i1].xyz, MARKER_OFFSET, normal, clipPoints[0][0]);
|
||||
VectorMA(surf->verts[i2].xyz, MARKER_OFFSET, normal, clipPoints[0][1]);
|
||||
VectorMA(surf->verts[i3].xyz, MARKER_OFFSET, normal, clipPoints[0][2]);
|
||||
#endif
|
||||
// add the fragments of this triangle
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
447
code/renderer/tr_mesh.cpp
Normal file
447
code/renderer/tr_mesh.cpp
Normal file
@@ -0,0 +1,447 @@
|
||||
// tr_mesh.c: triangle model functions
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#include "tr_local.h"
|
||||
#include "MatComp.h"
|
||||
|
||||
#ifdef VV_LIGHTING
|
||||
#include "tr_lightmanager.h"
|
||||
#endif
|
||||
|
||||
#ifdef _XBOX
|
||||
#include "../win32/glw_win_dx8.h"
|
||||
#include "../win32/win_stencilshadow.h"
|
||||
#include <xgraphics.h>
|
||||
#include <xgmath.h>
|
||||
#include "../win32/shader_constants.h"
|
||||
#endif
|
||||
|
||||
float ProjectRadius( float r, vec3_t location )
|
||||
{
|
||||
float pr;
|
||||
float dist;
|
||||
float c;
|
||||
vec3_t p;
|
||||
float width;
|
||||
float depth;
|
||||
|
||||
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] = Q_fabs( r );
|
||||
p[2] = -dist;
|
||||
|
||||
width = p[0] * tr.viewParms.projectionMatrix[1] +
|
||||
p[1] * tr.viewParms.projectionMatrix[5] +
|
||||
p[2] * tr.viewParms.projectionMatrix[9] +
|
||||
tr.viewParms.projectionMatrix[13];
|
||||
|
||||
depth = p[0] * tr.viewParms.projectionMatrix[3] +
|
||||
p[1] * tr.viewParms.projectionMatrix[7] +
|
||||
p[2] * tr.viewParms.projectionMatrix[11] +
|
||||
tr.viewParms.projectionMatrix[15];
|
||||
|
||||
pr = width / depth;
|
||||
#if defined (_XBOX)
|
||||
pr = -pr;
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
RE_GetModelBounds
|
||||
|
||||
Returns the bounds of the current model
|
||||
(qhandle_t)hModel and (int)frame need to be set
|
||||
=================
|
||||
*/
|
||||
|
||||
void RE_GetModelBounds(refEntity_t *refEnt, vec3_t bounds1, vec3_t bounds2)
|
||||
{
|
||||
md3Frame_t *frame;
|
||||
md3Header_t *header;
|
||||
model_t *model;
|
||||
|
||||
assert(refEnt);
|
||||
|
||||
model = R_GetModelByHandle( refEnt->hModel );
|
||||
assert(model);
|
||||
header = model->md3[0];
|
||||
assert(header);
|
||||
frame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + refEnt->frame;
|
||||
assert(frame);
|
||||
|
||||
VectorCopy(frame->bounds[0], bounds1);
|
||||
VectorCopy(frame->bounds[1], bounds2);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_ComputeLOD
|
||||
|
||||
=================
|
||||
*/
|
||||
#ifdef _XBOX
|
||||
int R_ComputeLOD( trRefEntity_t *ent ) {
|
||||
#else
|
||||
static int R_ComputeLOD( trRefEntity_t *ent ) {
|
||||
#endif
|
||||
float radius;
|
||||
float flod;
|
||||
float projectedRadius;
|
||||
int lod;
|
||||
|
||||
if ( tr.currentModel->numLods < 2 )
|
||||
{ // model has only 1 LOD level, skip computations and bias
|
||||
return(0);
|
||||
}
|
||||
|
||||
// multiple LODs exist, so compute projected bounding sphere
|
||||
// and use that as a criteria for selecting LOD
|
||||
// if ( tr.currentModel->md3[0] )
|
||||
{ //normal md3
|
||||
md3Frame_t *frame;
|
||||
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 )
|
||||
{
|
||||
flod = 1.0f - projectedRadius * r_lodscale->value;
|
||||
flod *= tr.currentModel->numLods;
|
||||
}
|
||||
else
|
||||
{ // object intersects near view plane, e.g. view weapon
|
||||
flod = 0;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
=================
|
||||
*/
|
||||
static int R_ComputeFogNum( md3Header_t *header, trRefEntity_t *ent ) {
|
||||
int i;
|
||||
fog_t *fog;
|
||||
md3Frame_t *md3Frame;
|
||||
vec3_t localOrigin;
|
||||
|
||||
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( tr.refdef.rdflags & RDF_doLAGoggles )
|
||||
{
|
||||
return tr.world->numfogs;
|
||||
}
|
||||
|
||||
|
||||
// FIXME: non-normalized axis issues
|
||||
md3Frame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.frame;
|
||||
VectorAdd( ent->e.origin, md3Frame->localOrigin, localOrigin );
|
||||
|
||||
int partialFog = 0;
|
||||
for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
|
||||
fog = &tr.world->fogs[i];
|
||||
if ( localOrigin[0] - md3Frame->radius >= fog->bounds[0][0]
|
||||
&& localOrigin[0] + md3Frame->radius <= fog->bounds[1][0]
|
||||
&& localOrigin[1] - md3Frame->radius >= fog->bounds[0][1]
|
||||
&& localOrigin[1] + md3Frame->radius <= fog->bounds[1][1]
|
||||
&& localOrigin[2] - md3Frame->radius >= fog->bounds[0][2]
|
||||
&& localOrigin[2] + md3Frame->radius <= fog->bounds[1][2] )
|
||||
{//totally inside it
|
||||
return i;
|
||||
break;
|
||||
}
|
||||
if ( ( localOrigin[0] - md3Frame->radius >= fog->bounds[0][0] && localOrigin[1] - md3Frame->radius >= fog->bounds[0][1] && localOrigin[2] - md3Frame->radius >= fog->bounds[0][2] &&
|
||||
localOrigin[0] - md3Frame->radius <= fog->bounds[1][0] && localOrigin[1] - md3Frame->radius <= fog->bounds[1][1] && localOrigin[2] - md3Frame->radius <= fog->bounds[1][2]) ||
|
||||
( localOrigin[0] + md3Frame->radius >= fog->bounds[0][0] && localOrigin[1] + md3Frame->radius >= fog->bounds[0][1] && localOrigin[2] + md3Frame->radius >= fog->bounds[0][2] &&
|
||||
localOrigin[0] + md3Frame->radius <= fog->bounds[1][0] && localOrigin[1] + md3Frame->radius <= fog->bounds[1][1] && localOrigin[2] + md3Frame->radius <= fog->bounds[1][2] ) )
|
||||
{//partially inside it
|
||||
if ( tr.refdef.fogIndex == i || R_FogParmsMatch( tr.refdef.fogIndex, i ) )
|
||||
{//take new one only if it's the same one that the viewpoint is in
|
||||
return i;
|
||||
break;
|
||||
}
|
||||
else if ( !partialFog )
|
||||
{//first partialFog
|
||||
partialFog = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
//if all else fails, return the first partialFog
|
||||
return partialFog;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_AddMD3Surfaces
|
||||
|
||||
=================
|
||||
*/
|
||||
void R_AddMD3Surfaces( trRefEntity_t *ent ) {
|
||||
int i;
|
||||
md3Header_t *header = 0;
|
||||
md3Surface_t *surface = 0;
|
||||
md3Shader_t *md3Shader = 0;
|
||||
shader_t *shader = 0;
|
||||
shader_t *main_shader = 0;
|
||||
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_CAP_FRAMES) {
|
||||
if (ent->e.frame > tr.currentModel->md3[0]->numFrames-1)
|
||||
ent->e.frame = tr.currentModel->md3[0]->numFrames-1;
|
||||
if (ent->e.oldframe > tr.currentModel->md3[0]->numFrames-1)
|
||||
ent->e.oldframe = tr.currentModel->md3[0]->numFrames-1;
|
||||
}
|
||||
else 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) )
|
||||
{
|
||||
VID_Printf (PRINT_ALL, "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
|
||||
//
|
||||
#ifdef VV_LIGHTING
|
||||
if ( !personalModel ) {
|
||||
VVLightMan.R_SetupEntityLighting( &tr.refdef, ent );
|
||||
#else
|
||||
if ( !personalModel || r_shadows->integer > 1 ) {
|
||||
R_SetupEntityLighting( &tr.refdef, ent );
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// see if we are in a fog volume
|
||||
//
|
||||
fogNum = R_ComputeFogNum( header, ent );
|
||||
|
||||
//
|
||||
// draw all surfaces
|
||||
//
|
||||
main_shader = R_GetShaderByHandle( ent->e.customShader );
|
||||
|
||||
surface = (md3Surface_t *)( (byte *)header + header->ofsSurfaces );
|
||||
for ( i = 0 ; i < header->numSurfaces ; i++ ) {
|
||||
|
||||
if ( ent->e.customShader ) {// a little more efficient
|
||||
shader = main_shader;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
} 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
|
||||
#ifndef _XBOX // No MD3 shadows on Xbox
|
||||
// stencil shadows can't do personal models unless I polyhedron clip
|
||||
if ( !personalModel
|
||||
&& r_shadows->integer == 2
|
||||
&& (ent->e.renderfx & RF_SHADOW_PLANE )
|
||||
&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
|
||||
&& shader->sort == SS_OPAQUE ) {
|
||||
R_AddDrawSurf( (surfaceType_t *)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( (surfaceType_t *)surface, tr.projectionShadowShader, 0, qfalse );
|
||||
}
|
||||
#endif
|
||||
|
||||
// don't add third_person objects if not viewing through a portal
|
||||
if ( !personalModel ) {
|
||||
#ifdef VV_LIGHTING
|
||||
int dlightBits = ( ent->dlightBits != 0 );
|
||||
R_AddDrawSurf( (surfaceType_t *)surface, shader, fogNum, dlightBits );
|
||||
#else
|
||||
R_AddDrawSurf( (surfaceType_t *)surface, shader, fogNum, qfalse );
|
||||
#endif
|
||||
}
|
||||
|
||||
surface = (md3Surface_t *)( (byte *)surface + surface->ofsEnd );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
1203
code/renderer/tr_model.cpp
Normal file
1203
code/renderer/tr_model.cpp
Normal file
File diff suppressed because it is too large
Load Diff
89
code/renderer/tr_noise.cpp
Normal file
89
code/renderer/tr_noise.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
// tr_noise.c
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
|
||||
#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];
|
||||
}
|
||||
|
||||
float GetNoiseTime( int t )
|
||||
{
|
||||
int index = VAL( t );
|
||||
|
||||
return (1+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 );
|
||||
}
|
||||
srand( com_frameTime );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
147
code/renderer/tr_public.h
Normal file
147
code/renderer/tr_public.h
Normal file
@@ -0,0 +1,147 @@
|
||||
#ifndef __TR_PUBLIC_H
|
||||
#define __TR_PUBLIC_H
|
||||
|
||||
#include "tr_types.h"
|
||||
|
||||
#ifdef _XBOX
|
||||
// Get font functions with default arguments that we need below
|
||||
#include "tr_font.h"
|
||||
#endif
|
||||
|
||||
#define REF_API_VERSION 9
|
||||
|
||||
//
|
||||
// these are the functions exported by the refresh module
|
||||
//
|
||||
#ifdef _XBOX
|
||||
template <class T> class SPARC;
|
||||
#endif
|
||||
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 );
|
||||
int (*GetAnimationCFG)(const char *psCFGFilename, char *psDest, int iDestSize);
|
||||
qhandle_t (*RegisterShader)( const char *name );
|
||||
qhandle_t (*RegisterShaderNoMip)( const char *name );
|
||||
void (*LoadWorld)( const char *name );
|
||||
|
||||
// these two functions added to help with the new model alloc scheme...
|
||||
//
|
||||
void (*RegisterMedia_LevelLoadBegin)(const char *psMapName, ForceReload_e eForceReload, qboolean bAllowScreenDissolve);
|
||||
void (*RegisterMedia_LevelLoadEnd)(void);
|
||||
|
||||
// the vis data is a large enough block of data that we go to the trouble
|
||||
// of sharing it with the clipmodel subsystem
|
||||
#ifdef _XBOX
|
||||
void (*SetWorldVisData)( SPARC<byte> *vis );
|
||||
#else
|
||||
void (*SetWorldVisData)( const byte *vis );
|
||||
#endif
|
||||
|
||||
// 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 );
|
||||
void (*AddLightToScene)( const vec3_t org, float intensity, float r, float g, float b );
|
||||
void (*RenderScene)( const refdef_t *fd );
|
||||
qboolean(*GetLighting)( const vec3_t org, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir);
|
||||
|
||||
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
|
||||
void (*DrawRotatePic) ( float x, float y, float w, float h,
|
||||
float s1, float t1, float s2, float t2, float a1, qhandle_t hShader ); // 0 = white
|
||||
void (*DrawRotatePic2) ( float x, float y, float w, float h,
|
||||
float s1, float t1, float s2, float t2, float a1, qhandle_t hShader ); // 0 = white
|
||||
void (*LAGoggles)(void);
|
||||
void (*Scissor) ( float x, float y, float w, float h); // 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 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 );
|
||||
|
||||
qboolean (*ProcessDissolve)(void);
|
||||
qboolean (*InitDissolve)(qboolean bForceCircularExtroWipe);
|
||||
|
||||
|
||||
// for use with save-games mainly...
|
||||
void (*GetScreenShot)(byte *data, int w, int h);
|
||||
|
||||
// this is so you can get access to raw pixels from a graphics format (TGA/JPG/BMP etc),
|
||||
// currently only the save game uses it (to make raw shots for the autosaves)
|
||||
//
|
||||
byte* (*TempRawImage_ReadFromFile)(const char *psLocalFilename, int *piWidth, int *piHeight, byte *pbReSampleBuffer, qboolean qbVertFlip);
|
||||
void (*TempRawImage_CleanUp)();
|
||||
|
||||
//misc stuff
|
||||
int (*MarkFragments)( int numPoints, const vec3_t *points, const vec3_t projection,
|
||||
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer );
|
||||
|
||||
//model stuff
|
||||
void (*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 );
|
||||
|
||||
void (*GetLightStyle)(int style, color4ub_t color);
|
||||
void (*SetLightStyle)(int style, int color);
|
||||
|
||||
void (*GetBModelVerts)( int bmodelIndex, vec3_t *vec, vec3_t normal );
|
||||
void (*WorldEffectCommand)(const char *command);
|
||||
|
||||
int (*RegisterFont)(const char *name);
|
||||
#ifdef _XBOX // No default arguments through function pointers.
|
||||
int Font_HeightPixels(const int index, const float scale = 1.0f)
|
||||
{
|
||||
return RE_Font_HeightPixels(index, scale);
|
||||
}
|
||||
int Font_StrLenPixels(const char *s, const int index, const float scale = 1.0f)
|
||||
{
|
||||
return RE_Font_StrLenPixels(s, index, scale);
|
||||
}
|
||||
void Font_DrawString(int x, int y, const char *s, const float *rgba, const int iFontHandle, int iMaxPixelWidth, const float scale = 1.0f)
|
||||
{
|
||||
return RE_Font_DrawString(x, y, s, rgba, iFontHandle, iMaxPixelWidth, scale);
|
||||
}
|
||||
#else
|
||||
int (*Font_HeightPixels)(const int index, const float scale = 1.0f);
|
||||
int (*Font_StrLenPixels)(const char *s, const int index, const float scale = 1.0f);
|
||||
void (*Font_DrawString)(int x, int y, const char *s, const float *rgba, const int iFontHandle, int iMaxPixelWidth, const float scale = 1.0f);
|
||||
#endif
|
||||
int (*Font_StrLenChars) (const char *s);
|
||||
qboolean (*Language_IsAsian) (void);
|
||||
qboolean (*Language_UsesSpaces) (void);
|
||||
unsigned int (*AnyLanguage_ReadCharFromString)( const char *psText, int * piAdvanceCount, qboolean *pbIsTrailingPunctuation /* = NULL */);
|
||||
|
||||
} refexport_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 );
|
||||
|
||||
#endif // __TR_PUBLIC_H
|
||||
229
code/renderer/tr_quicksprite.cpp
Normal file
229
code/renderer/tr_quicksprite.cpp
Normal file
@@ -0,0 +1,229 @@
|
||||
// tr_QuickSprite.cpp: implementation of the CQuickSpriteSystem class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#include "../server/exe_headers.h"
|
||||
#include "tr_QuickSprite.h"
|
||||
|
||||
extern void R_BindAnimatedImage( const textureBundle_t *bundle );
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Singleton System
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
CQuickSpriteSystem SQuickSprite;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CQuickSpriteSystem::CQuickSpriteSystem(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SHADER_MAX_VERTEXES; i += 4)
|
||||
{
|
||||
// Bottom right
|
||||
mTextureCoords[i + 0][0] = 1.0;
|
||||
mTextureCoords[i + 0][1] = 1.0;
|
||||
// Top right
|
||||
mTextureCoords[i + 1][0] = 1.0;
|
||||
mTextureCoords[i + 1][1] = 0.0;
|
||||
// Top left
|
||||
mTextureCoords[i + 2][0] = 0.0;
|
||||
mTextureCoords[i + 2][1] = 0.0;
|
||||
// Bottom left
|
||||
mTextureCoords[i + 3][0] = 0.0;
|
||||
mTextureCoords[i + 3][1] = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
CQuickSpriteSystem::~CQuickSpriteSystem(void)
|
||||
{
|
||||
}
|
||||
|
||||
void CQuickSpriteSystem::Flush(void)
|
||||
{
|
||||
if (mNextVert==0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
if (mUseFog && r_drawfog->integer == 2 &&
|
||||
mFogIndex == tr.world->globalFog)
|
||||
{ //enable hardware fog when we draw this thing if applicable -rww
|
||||
fog_t *fog = tr.world->fogs + mFogIndex;
|
||||
|
||||
#ifdef _XBOX
|
||||
qglFogi(GL_FOG_MODE, GL_EXP2);
|
||||
#else
|
||||
qglFogf(GL_FOG_MODE, GL_EXP2);
|
||||
#endif
|
||||
qglFogf(GL_FOG_DENSITY, logtestExp2 / fog->parms.depthForOpaque);
|
||||
qglFogfv(GL_FOG_COLOR, fog->parms.color);
|
||||
qglEnable(GL_FOG);
|
||||
}
|
||||
*/
|
||||
//this should not be needed, since I just wait to disable fog for the surface til after surface sprites are done
|
||||
|
||||
//
|
||||
// render the main pass
|
||||
//
|
||||
R_BindAnimatedImage( mTexBundle );
|
||||
GL_State(mGLStateBits);
|
||||
|
||||
//
|
||||
// set arrays and lock
|
||||
//
|
||||
qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
|
||||
qglTexCoordPointer( 2, GL_FLOAT, 0, mTextureCoords );
|
||||
|
||||
qglEnableClientState( GL_COLOR_ARRAY);
|
||||
qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, mColors );
|
||||
|
||||
qglVertexPointer (3, GL_FLOAT, 16, mVerts);
|
||||
|
||||
if ( qglLockArraysEXT )
|
||||
{
|
||||
qglLockArraysEXT(0, mNextVert);
|
||||
GLimp_LogComment( "glLockArraysEXT\n" );
|
||||
}
|
||||
|
||||
qglDrawArrays(GL_QUADS, 0, mNextVert);
|
||||
|
||||
backEnd.pc.c_vertexes += mNextVert;
|
||||
backEnd.pc.c_indexes += mNextVert;
|
||||
backEnd.pc.c_totalIndexes += mNextVert;
|
||||
|
||||
//only for software fog pass (global soft/volumetric) -rww
|
||||
if (mUseFog && (r_drawfog->integer != 2 || mFogIndex != tr.world->globalFog))
|
||||
{
|
||||
fog_t *fog = tr.world->fogs + mFogIndex;
|
||||
|
||||
//
|
||||
// render the fog pass
|
||||
//
|
||||
GL_Bind( tr.fogImage );
|
||||
GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
|
||||
|
||||
//
|
||||
// set arrays and lock
|
||||
//
|
||||
qglTexCoordPointer( 2, GL_FLOAT, 0, mFogTextureCoords);
|
||||
// qglEnableClientState( GL_TEXTURE_COORD_ARRAY); // Done above
|
||||
|
||||
qglDisableClientState( GL_COLOR_ARRAY );
|
||||
qglColor4ubv((GLubyte *)&fog->colorInt);
|
||||
|
||||
// qglVertexPointer (3, GL_FLOAT, 16, mVerts); // Done above
|
||||
|
||||
qglDrawArrays(GL_QUADS, 0, mNextVert);
|
||||
|
||||
// Second pass from fog
|
||||
backEnd.pc.c_totalIndexes += mNextVert;
|
||||
}
|
||||
|
||||
//
|
||||
// unlock arrays
|
||||
//
|
||||
if (qglUnlockArraysEXT)
|
||||
{
|
||||
qglUnlockArraysEXT();
|
||||
GLimp_LogComment( "glUnlockArraysEXT\n" );
|
||||
}
|
||||
|
||||
mNextVert=0;
|
||||
}
|
||||
|
||||
|
||||
void CQuickSpriteSystem::StartGroup(textureBundle_t *bundle, unsigned long glbits, int fogIndex )
|
||||
{
|
||||
mNextVert = 0;
|
||||
|
||||
mTexBundle = bundle;
|
||||
mGLStateBits = glbits;
|
||||
if (fogIndex != -1)
|
||||
{
|
||||
mUseFog = qtrue;
|
||||
mFogIndex = fogIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
mUseFog = qfalse;
|
||||
}
|
||||
|
||||
int cullingOn;
|
||||
qglGetIntegerv(GL_CULL_FACE,&cullingOn);
|
||||
|
||||
if(cullingOn)
|
||||
{
|
||||
mTurnCullBackOn=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mTurnCullBackOn=false;
|
||||
}
|
||||
qglDisable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
|
||||
void CQuickSpriteSystem::EndGroup(void)
|
||||
{
|
||||
Flush();
|
||||
|
||||
qglColor4ub(255,255,255,255);
|
||||
if(mTurnCullBackOn)
|
||||
{
|
||||
qglEnable(GL_CULL_FACE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void CQuickSpriteSystem::Add(float *pointdata, color4ub_t color, vec2_t fog)
|
||||
{
|
||||
float *curcoord;
|
||||
float *curfogtexcoord;
|
||||
unsigned long *curcolor;
|
||||
|
||||
if (mNextVert>SHADER_MAX_VERTEXES-4)
|
||||
{
|
||||
Flush();
|
||||
}
|
||||
|
||||
curcoord = mVerts[mNextVert];
|
||||
memcpy(curcoord, pointdata, 4*sizeof(vec4_t));
|
||||
|
||||
// Set up color
|
||||
curcolor = &mColors[mNextVert];
|
||||
*curcolor++ = *(unsigned long *)color;
|
||||
*curcolor++ = *(unsigned long *)color;
|
||||
*curcolor++ = *(unsigned long *)color;
|
||||
*curcolor++ = *(unsigned long *)color;
|
||||
|
||||
if (fog)
|
||||
{
|
||||
curfogtexcoord = &mFogTextureCoords[mNextVert][0];
|
||||
*curfogtexcoord++ = fog[0];
|
||||
*curfogtexcoord++ = fog[1];
|
||||
|
||||
*curfogtexcoord++ = fog[0];
|
||||
*curfogtexcoord++ = fog[1];
|
||||
|
||||
*curfogtexcoord++ = fog[0];
|
||||
*curfogtexcoord++ = fog[1];
|
||||
|
||||
*curfogtexcoord++ = fog[0];
|
||||
*curfogtexcoord++ = fog[1];
|
||||
|
||||
mUseFog=qtrue;
|
||||
}
|
||||
else
|
||||
{
|
||||
mUseFog=qfalse;
|
||||
}
|
||||
|
||||
mNextVert+=4;
|
||||
}
|
||||
48
code/renderer/tr_quicksprite.h
Normal file
48
code/renderer/tr_quicksprite.h
Normal file
@@ -0,0 +1,48 @@
|
||||
// this include must remain at the top of every CPP file
|
||||
//#include "../game/q_math.h"
|
||||
#include "tr_local.h"
|
||||
|
||||
// tr_QuickSprite.h: interface for the CQuickSprite class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_TR_QUICKSPRITE_H__6F05EB85_A1ED_4537_9EC0_9F5D82A5D99A__INCLUDED_)
|
||||
#define AFX_TR_QUICKSPRITE_H__6F05EB85_A1ED_4537_9EC0_9F5D82A5D99A__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
class CQuickSpriteSystem
|
||||
{
|
||||
private:
|
||||
textureBundle_t *mTexBundle;
|
||||
unsigned long mGLStateBits;
|
||||
int mFogIndex;
|
||||
qboolean mUseFog;
|
||||
vec4_t mVerts[SHADER_MAX_VERTEXES];
|
||||
unsigned int mIndexes[SHADER_MAX_VERTEXES]; // Ideally this would be static, cause it never changes
|
||||
vec2_t mTextureCoords[SHADER_MAX_VERTEXES]; // Ideally this would be static, cause it never changes
|
||||
vec2_t mFogTextureCoords[SHADER_MAX_VERTEXES];
|
||||
unsigned long mColors[SHADER_MAX_VERTEXES];
|
||||
int mNextVert;
|
||||
qboolean mTurnCullBackOn;
|
||||
|
||||
void Flush(void);
|
||||
|
||||
public:
|
||||
CQuickSpriteSystem(void);
|
||||
~CQuickSpriteSystem(void);
|
||||
|
||||
void StartGroup(textureBundle_t *bundle, unsigned long glbits, int fogIndex = -1);
|
||||
void EndGroup(void);
|
||||
|
||||
void Add(float *pointdata, color4ub_t color, vec2_t fog=NULL);
|
||||
};
|
||||
|
||||
extern CQuickSpriteSystem SQuickSprite;
|
||||
|
||||
|
||||
#endif // !defined(AFX_TR_QUICKSPRITE_H__6F05EB85_A1ED_4537_9EC0_9F5D82A5D99A__INCLUDED_)
|
||||
|
||||
|
||||
405
code/renderer/tr_scene.cpp
Normal file
405
code/renderer/tr_scene.cpp
Normal file
@@ -0,0 +1,405 @@
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
|
||||
#include "tr_local.h"
|
||||
|
||||
#ifdef VV_LIGHTING
|
||||
#include "tr_lightmanager.h"
|
||||
#endif
|
||||
|
||||
int r_firstSceneDrawSurf;
|
||||
|
||||
int r_numdlights;
|
||||
int r_firstSceneDlight;
|
||||
|
||||
int r_numentities;
|
||||
int r_firstSceneEntity;
|
||||
|
||||
int r_numpolys;
|
||||
int r_firstScenePoly;
|
||||
|
||||
int r_numpolyverts;
|
||||
|
||||
int skyboxportal;
|
||||
int drawskyboxportal;
|
||||
|
||||
/*
|
||||
====================
|
||||
R_ToggleSmpFrame
|
||||
|
||||
====================
|
||||
*/
|
||||
void R_ToggleSmpFrame( void ) {
|
||||
|
||||
backEndData->commands.used = 0;
|
||||
|
||||
r_firstSceneDrawSurf = 0;
|
||||
|
||||
r_numdlights = 0;
|
||||
r_firstSceneDlight = 0;
|
||||
|
||||
#ifdef VV_LIGHTING
|
||||
VVLightMan.num_dlights = 0;
|
||||
#endif
|
||||
|
||||
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;
|
||||
tr.refdef.rdflags &= ~(RDF_doLAGoggles|RDF_doFullbright); //probably not needed since it gets copied over in RE_RenderScene
|
||||
}
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
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 = TR_WORLDENT;
|
||||
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( ( surfaceType_t * )poly, sh, poly->fogIndex, qfalse );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
RE_AddPolyToScene
|
||||
|
||||
=====================
|
||||
*/
|
||||
void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts ) {
|
||||
srfPoly_t *poly;
|
||||
int i;
|
||||
int fogIndex = 0;
|
||||
fog_t *fog;
|
||||
vec3_t bounds[2];
|
||||
|
||||
if ( !tr.registered ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !hShader ) {
|
||||
#ifndef FINAL_BUILD
|
||||
VID_Printf( PRINT_WARNING, "WARNING: RE_AddPolyToScene: NULL poly shader\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if ( r_numpolyverts + numVerts > MAX_POLYVERTS || r_numpolys >= MAX_POLYS ) {
|
||||
#if defined(_DEBUG)
|
||||
Com_Printf(S_COLOR_RED"Poly overflow! Tell Brian.\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
poly = &backEndData->polys[r_numpolys];
|
||||
poly->surfaceType = SF_POLY;
|
||||
poly->hShader = hShader;
|
||||
poly->numVerts = numVerts;
|
||||
poly->verts = &backEndData->polyVerts[r_numpolyverts];
|
||||
|
||||
memcpy( poly->verts, verts, numVerts * sizeof( *verts ) );
|
||||
r_numpolys++;
|
||||
r_numpolyverts += numVerts;
|
||||
|
||||
// see if it is in a fog volume
|
||||
if ( !tr.world || 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 ( int fI = 1 ; fI < tr.world->numfogs ; fI++ ) {
|
||||
fog = &tr.world->fogs[fI];
|
||||
if ( bounds[0][0] >= fog->bounds[0][0]
|
||||
&& bounds[0][1] >= fog->bounds[0][1]
|
||||
&& bounds[0][2] >= fog->bounds[0][2]
|
||||
&& bounds[1][0] <= fog->bounds[1][0]
|
||||
&& bounds[1][1] <= fog->bounds[1][1]
|
||||
&& bounds[1][2] <= fog->bounds[1][2] )
|
||||
{//completely in this one
|
||||
fogIndex = fI;
|
||||
break;
|
||||
}
|
||||
else if ( ( bounds[0][0] >= fog->bounds[0][0] && bounds[0][1] >= fog->bounds[0][1] && bounds[0][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]) ||
|
||||
( bounds[1][0] >= fog->bounds[0][0] && bounds[1][1] >= fog->bounds[0][1] && bounds[1][2] >= fog->bounds[0][2] &&
|
||||
bounds[1][0] <= fog->bounds[1][0] && bounds[1][1] <= fog->bounds[1][1] && bounds[1][2] <= fog->bounds[1][2] ) )
|
||||
{//partially in this one
|
||||
if ( tr.refdef.fogIndex == fI || R_FogParmsMatch( tr.refdef.fogIndex, fI ) )
|
||||
{//take new one only if it's the same one that the viewpoint is in
|
||||
fogIndex = fI;
|
||||
break;
|
||||
}
|
||||
else if ( !fogIndex )
|
||||
{//didn't find one yet, so use this one
|
||||
fogIndex = fI;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
poly->fogIndex = fogIndex;
|
||||
}
|
||||
|
||||
|
||||
//=================================================================================
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
RE_AddRefEntityToScene
|
||||
|
||||
=====================
|
||||
*/
|
||||
void RE_AddRefEntityToScene( const refEntity_t *ent ) {
|
||||
if ( !tr.registered ) {
|
||||
return;
|
||||
}
|
||||
if ( r_numentities >= TR_WORLDENT ) {
|
||||
#ifndef FINAL_BUILD
|
||||
VID_Printf( PRINT_WARNING, "WARNING: RE_AddRefEntityToScene: too many entities\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if ( ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) {
|
||||
Com_Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType );
|
||||
}
|
||||
|
||||
backEndData->entities[r_numentities].e = *ent;
|
||||
backEndData->entities[r_numentities].lightingCalculated = qfalse;
|
||||
#ifdef _XBOX
|
||||
backEndData->entities[r_numentities].visible = -1;
|
||||
#endif
|
||||
|
||||
r_numentities++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
RE_AddLightToScene
|
||||
|
||||
=====================
|
||||
*/
|
||||
void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
|
||||
#ifndef VV_LIGHTING
|
||||
dlight_t *dl;
|
||||
|
||||
if ( !tr.registered ) {
|
||||
return;
|
||||
}
|
||||
if ( r_numdlights >= MAX_DLIGHTS ) {
|
||||
return;
|
||||
}
|
||||
if ( intensity <= 0 ) {
|
||||
return;
|
||||
}
|
||||
dl = &backEndData->dlights[r_numdlights++];
|
||||
VectorCopy (org, dl->origin);
|
||||
dl->radius = intensity;
|
||||
dl->color[0] = r;
|
||||
dl->color[1] = g;
|
||||
dl->color[2] = b;
|
||||
#endif // VV_LIGHTING
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@@@@@@@@@@@@@@@@@@@@
|
||||
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,
|
||||
@@@@@@@@@@@@@@@@@@@@@
|
||||
*/
|
||||
extern int recursivePortalCount;
|
||||
void RE_RenderScene( const refdef_t *fd ) {
|
||||
viewParms_t parms;
|
||||
int startTime;
|
||||
static int lastTime = 0;
|
||||
|
||||
if ( !tr.registered ) {
|
||||
return;
|
||||
}
|
||||
GLimp_LogComment( "====== RE_RenderScene =====\n" );
|
||||
|
||||
if ( r_norefresh->integer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
startTime = Sys_Milliseconds();
|
||||
|
||||
if (!tr.world && !( fd->rdflags & RDF_NOWORLDMODEL ) ) {
|
||||
Com_Error (ERR_DROP, "R_RenderScene: NULL worldmodel");
|
||||
}
|
||||
|
||||
// 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.frametime = fd->time - lastTime;
|
||||
tr.refdef.rdflags = fd->rdflags;
|
||||
|
||||
if (fd->rdflags & RDF_SKYBOXPORTAL)
|
||||
{
|
||||
skyboxportal = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// cdr - only change last time for the real render, not the portal
|
||||
lastTime = fd->time;
|
||||
}
|
||||
|
||||
if (fd->rdflags & RDF_DRAWSKYBOX)
|
||||
{
|
||||
drawskyboxportal = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
drawskyboxportal = 0;
|
||||
}
|
||||
|
||||
// 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.001;
|
||||
|
||||
tr.refdef.numDrawSurfs = r_firstSceneDrawSurf;
|
||||
tr.refdef.drawSurfs = backEndData->drawSurfs;
|
||||
|
||||
tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
|
||||
tr.refdef.entities = &backEndData->entities[r_firstSceneEntity];
|
||||
|
||||
#ifndef VV_LIGHTING
|
||||
tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight;
|
||||
tr.refdef.dlights = &backEndData->dlights[r_firstSceneDlight];
|
||||
#endif
|
||||
|
||||
tr.refdef.numPolys = r_numpolys - r_firstScenePoly;
|
||||
tr.refdef.polys = &backEndData->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
|
||||
#ifndef VV_LIGHTING
|
||||
if ( r_dynamiclight->integer == 0 ||
|
||||
r_vertexLight->integer == 1 ) {
|
||||
tr.refdef.num_dlights = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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
|
||||
//
|
||||
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 );
|
||||
|
||||
recursivePortalCount = 0;
|
||||
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 += Sys_Milliseconds() - startTime;
|
||||
RE_RenderWorldEffects();
|
||||
}
|
||||
2821
code/renderer/tr_shade.cpp
Normal file
2821
code/renderer/tr_shade.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1632
code/renderer/tr_shade_calc.cpp
Normal file
1632
code/renderer/tr_shade_calc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
4143
code/renderer/tr_shader.cpp
Normal file
4143
code/renderer/tr_shader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
801
code/renderer/tr_shadows.cpp
Normal file
801
code/renderer/tr_shadows.cpp
Normal file
@@ -0,0 +1,801 @@
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
#include "tr_local.h"
|
||||
|
||||
#ifdef VV_LIGHTING
|
||||
#include "tr_lightmanager.h"
|
||||
#include "../win32/win_stencilshadow.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
||||
for a projection shadow:
|
||||
|
||||
point[x] += light vector * ( z - shadow plane )
|
||||
point[y] +=
|
||||
point[z] = shadow plane
|
||||
|
||||
1 0 light[x] / light[z]
|
||||
|
||||
*/
|
||||
#ifndef _XBOX
|
||||
|
||||
#define _STENCIL_REVERSE
|
||||
|
||||
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];
|
||||
|
||||
#endif // _XBOX
|
||||
|
||||
void R_AddEdgeDef( int i1, int i2, int facing ) {
|
||||
#ifndef _XBOX
|
||||
int c;
|
||||
|
||||
c = numEdgeDefs[ i1 ];
|
||||
if ( c == MAX_EDGE_DEFS ) {
|
||||
return; // overflow
|
||||
}
|
||||
edgeDefs[ i1 ][ c ].i2 = i2;
|
||||
edgeDefs[ i1 ][ c ].facing = facing;
|
||||
|
||||
numEdgeDefs[ i1 ]++;
|
||||
#endif // _XBOX
|
||||
}
|
||||
|
||||
void R_RenderShadowEdges( void ) {
|
||||
#if defined(VV_LIGHTING) && defined(_XBOX)
|
||||
return;
|
||||
#else
|
||||
|
||||
int i;
|
||||
int c;
|
||||
int j;
|
||||
int i2;
|
||||
int c_edges, c_rejected;
|
||||
#if 0
|
||||
int c2, k;
|
||||
int hit[2];
|
||||
#endif
|
||||
#ifdef _STENCIL_REVERSE
|
||||
int numTris;
|
||||
int o1, o2, o3;
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//with this system we can still get edges shared by more than 2 tris which
|
||||
//produces artifacts including seeing the shadow through walls. So for now
|
||||
//we are going to render all edges even though it is a tiny bit slower. -rww
|
||||
#if 1
|
||||
i2 = edgeDefs[ i ][ j ].i2;
|
||||
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();
|
||||
#else
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _STENCIL_REVERSE
|
||||
//Carmack Reverse<tm> method requires that volumes
|
||||
//be capped properly -rww
|
||||
numTris = tess.numIndexes / 3;
|
||||
|
||||
for ( i = 0 ; i < numTris ; i++ )
|
||||
{
|
||||
if ( !facing[i] )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
o1 = tess.indexes[ i*3 + 0 ];
|
||||
o2 = tess.indexes[ i*3 + 1 ];
|
||||
o3 = tess.indexes[ i*3 + 2 ];
|
||||
|
||||
qglBegin(GL_TRIANGLES);
|
||||
qglVertex3fv(tess.xyz[o1]);
|
||||
qglVertex3fv(tess.xyz[o2]);
|
||||
qglVertex3fv(tess.xyz[o3]);
|
||||
qglEnd();
|
||||
qglBegin(GL_TRIANGLES);
|
||||
qglVertex3fv(tess.xyz[o3 + tess.numVertexes]);
|
||||
qglVertex3fv(tess.xyz[o2 + tess.numVertexes]);
|
||||
qglVertex3fv(tess.xyz[o1 + tess.numVertexes]);
|
||||
qglEnd();
|
||||
}
|
||||
#endif
|
||||
#endif // VV_LIGHTING && _XBOX
|
||||
}
|
||||
|
||||
//#define _DEBUG_STENCIL_SHADOWS
|
||||
|
||||
/*
|
||||
=================
|
||||
RB_ShadowTessEnd
|
||||
|
||||
triangleFromEdge[ v1 ][ v2 ]
|
||||
|
||||
|
||||
set triangle from edge( v1, v2, tri )
|
||||
if ( facing[ triangleFromEdge[ v1 ][ v2 ] ] && !facing[ triangleFromEdge[ v2 ][ v1 ] ) {
|
||||
}
|
||||
=================
|
||||
*/
|
||||
void RB_DoShadowTessEnd( vec3_t lightPos );
|
||||
void RB_ShadowTessEnd( void )
|
||||
{
|
||||
#if defined(VV_LIGHTING) && defined(_XBOX)
|
||||
if(StencilShadower.BuildFromLight())
|
||||
StencilShadower.RenderShadow();
|
||||
#else
|
||||
#if 0
|
||||
if (backEnd.currentEntity &&
|
||||
(backEnd.currentEntity->directedLight[0] ||
|
||||
backEnd.currentEntity->directedLight[1] ||
|
||||
backEnd.currentEntity->directedLight[2]))
|
||||
{ //an ent that has its light set for it
|
||||
RB_DoShadowTessEnd(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
// if (!tess.dlightBits)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
|
||||
int i = 0;
|
||||
dlight_t *dl;
|
||||
|
||||
R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.ori );
|
||||
/* while (i < tr.refdef.num_dlights)
|
||||
{
|
||||
if (tess.dlightBits & (1 << i))
|
||||
{
|
||||
dl = &tr.refdef.dlights[i];
|
||||
|
||||
RB_DoShadowTessEnd(dl->transformed);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
*/
|
||||
dl = &tr.refdef.dlights[0];
|
||||
|
||||
RB_DoShadowTessEnd(dl->transformed);
|
||||
|
||||
#else //old ents-only way
|
||||
RB_DoShadowTessEnd(NULL);
|
||||
#endif
|
||||
#endif // VV_LIGHTING && _XBOX
|
||||
}
|
||||
|
||||
void RB_DoShadowTessEnd( vec3_t lightPos )
|
||||
{
|
||||
#ifndef _XBOX
|
||||
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;
|
||||
}
|
||||
|
||||
#if 1 //controlled method - try to keep shadows in range so they don't show through so much -rww
|
||||
vec3_t worldxyz;
|
||||
vec3_t entLight;
|
||||
float groundDist;
|
||||
|
||||
VectorCopy( backEnd.currentEntity->lightDir, entLight );
|
||||
entLight[2] = 0.0f;
|
||||
VectorNormalize(entLight);
|
||||
|
||||
//Oh well, just cast them straight down no matter what onto the ground plane.
|
||||
//This presets no chance of screwups and still looks better than a stupid
|
||||
//shader blob.
|
||||
VectorSet(lightDir, entLight[0]*0.3f, entLight[1]*0.3f, 1.0f);
|
||||
// project vertexes away from light direction
|
||||
for ( i = 0 ; i < tess.numVertexes ; i++ ) {
|
||||
//add or.origin to vert xyz to end up with world oriented coord, then figure
|
||||
//out the ground pos for the vert to project the shadow volume to
|
||||
VectorAdd(tess.xyz[i], backEnd.ori.origin, worldxyz);
|
||||
groundDist = worldxyz[2] - backEnd.currentEntity->e.shadowPlane;
|
||||
groundDist += 16.0f; //fudge factor
|
||||
VectorMA( tess.xyz[i], -groundDist, lightDir, tess.xyz[i+tess.numVertexes] );
|
||||
}
|
||||
#else
|
||||
if (lightPos)
|
||||
{
|
||||
for ( i = 0 ; i < tess.numVertexes ; i++ )
|
||||
{
|
||||
tess.xyz[i+tess.numVertexes][0] = tess.xyz[i][0]+(( tess.xyz[i][0]-lightPos[0] )*128.0f);
|
||||
tess.xyz[i+tess.numVertexes][1] = tess.xyz[i][1]+(( tess.xyz[i][1]-lightPos[1] )*128.0f);
|
||||
tess.xyz[i+tess.numVertexes][2] = tess.xyz[i][2]+(( tess.xyz[i][2]-lightPos[2] )*128.0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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] );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// decide which triangles face the light
|
||||
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 ];
|
||||
|
||||
if (!lightPos)
|
||||
{
|
||||
VectorSubtract( v2, v1, d1 );
|
||||
VectorSubtract( v3, v1, d2 );
|
||||
CrossProduct( d1, d2, normal );
|
||||
|
||||
d = DotProduct( normal, lightDir );
|
||||
}
|
||||
else
|
||||
{
|
||||
float planeEq[4];
|
||||
planeEq[0] = v1[1]*(v2[2]-v3[2]) + v2[1]*(v3[2]-v1[2]) + v3[1]*(v1[2]-v2[2]);
|
||||
planeEq[1] = v1[2]*(v2[0]-v3[0]) + v2[2]*(v3[0]-v1[0]) + v3[2]*(v1[0]-v2[0]);
|
||||
planeEq[2] = v1[0]*(v2[1]-v3[1]) + v2[0]*(v3[1]-v1[1]) + v3[0]*(v1[1]-v2[1]);
|
||||
planeEq[3] = -( v1[0]*( v2[1]*v3[2] - v3[1]*v2[2] ) +
|
||||
v2[0]*(v3[1]*v1[2] - v1[1]*v3[2]) +
|
||||
v3[0]*(v1[1]*v2[2] - v2[1]*v1[2]) );
|
||||
|
||||
d = planeEq[0]*lightPos[0]+
|
||||
planeEq[1]*lightPos[1]+
|
||||
planeEq[2]*lightPos[2]+
|
||||
planeEq[3];
|
||||
}
|
||||
|
||||
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 ] );
|
||||
}
|
||||
|
||||
GL_Bind( tr.whiteImage );
|
||||
//qglEnable( GL_CULL_FACE );
|
||||
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
|
||||
|
||||
#ifndef _DEBUG_STENCIL_SHADOWS
|
||||
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 );
|
||||
#else
|
||||
qglColor3f( 1.0f, 0.0f, 0.0f );
|
||||
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
//qglDisable(GL_DEPTH_TEST);
|
||||
#endif
|
||||
|
||||
#ifdef _STENCIL_REVERSE
|
||||
qglDepthFunc(GL_LESS);
|
||||
|
||||
//now using the Carmack Reverse<tm> -rww
|
||||
if ( backEnd.viewParms.isMirror ) {
|
||||
//qglCullFace( GL_BACK );
|
||||
GL_Cull(CT_BACK_SIDED);
|
||||
qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP );
|
||||
|
||||
R_RenderShadowEdges();
|
||||
|
||||
//qglCullFace( GL_FRONT );
|
||||
GL_Cull(CT_FRONT_SIDED);
|
||||
qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
|
||||
|
||||
R_RenderShadowEdges();
|
||||
} else {
|
||||
//qglCullFace( GL_FRONT );
|
||||
GL_Cull(CT_FRONT_SIDED);
|
||||
qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP );
|
||||
|
||||
R_RenderShadowEdges();
|
||||
|
||||
//qglCullFace( GL_BACK );
|
||||
GL_Cull(CT_BACK_SIDED);
|
||||
qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
|
||||
|
||||
R_RenderShadowEdges();
|
||||
}
|
||||
|
||||
qglDepthFunc(GL_LEQUAL);
|
||||
#else
|
||||
// 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();
|
||||
}
|
||||
#endif
|
||||
|
||||
// reenable writing to the color buffer
|
||||
qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
|
||||
#ifdef _DEBUG_STENCIL_SHADOWS
|
||||
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
#endif
|
||||
#endif // _XBOX
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
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 defined(VV_LIGHTING) && defined(_XBOX)
|
||||
StencilShadower.FinishShadows();
|
||||
#else
|
||||
if ( r_shadows->integer != 2 ) {
|
||||
return;
|
||||
}
|
||||
if ( glConfig.stencilBits < 4 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_STENCIL_SHADOWS
|
||||
return;
|
||||
#endif
|
||||
|
||||
qglEnable( GL_STENCIL_TEST );
|
||||
qglStencilFunc( GL_NOTEQUAL, 0, 255 );
|
||||
|
||||
qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
|
||||
|
||||
bool planeZeroBack = false;
|
||||
if (qglIsEnabled(GL_CLIP_PLANE0))
|
||||
{
|
||||
planeZeroBack = true;
|
||||
qglDisable (GL_CLIP_PLANE0);
|
||||
}
|
||||
GL_Cull(CT_TWO_SIDED);
|
||||
//qglDisable (GL_CULL_FACE);
|
||||
|
||||
GL_Bind( tr.whiteImage );
|
||||
|
||||
qglPushMatrix();
|
||||
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 );
|
||||
|
||||
qglColor4f( 0.0f, 0.0f, 0.0f, 0.5f );
|
||||
//GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
|
||||
GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
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 );
|
||||
if (planeZeroBack)
|
||||
{
|
||||
qglEnable (GL_CLIP_PLANE0);
|
||||
}
|
||||
qglPopMatrix();
|
||||
#endif // VV_LIGHTING && _XBOX
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
RB_ProjectionShadowDeform
|
||||
|
||||
=================
|
||||
*/
|
||||
void RB_ProjectionShadowDeform( void ) {
|
||||
#ifdef _XBOX
|
||||
float shadowMat[4][4];
|
||||
vec3_t light, ground;
|
||||
float d, dot;
|
||||
|
||||
ground[0] = backEnd.ori.axis[0][2];
|
||||
ground[1] = backEnd.ori.axis[1][2];
|
||||
ground[2] = backEnd.ori.axis[2][2];
|
||||
d = backEnd.ori.origin[2] - backEnd.currentEntity->e.shadowPlane;
|
||||
|
||||
light[0] = backEnd.currentEntity->lightDir[0];
|
||||
light[1] = backEnd.currentEntity->lightDir[1];
|
||||
light[2] = backEnd.currentEntity->lightDir[2];
|
||||
|
||||
dot = ground[0] * light[0] +
|
||||
ground[1] * light[1] +
|
||||
ground[2] * light[2];
|
||||
// don't let the shadows get too long or go negative
|
||||
if ( dot < 0.5 )
|
||||
{
|
||||
VectorMA( light, (0.5 - dot), ground, light );
|
||||
dot = DotProduct( light, ground );
|
||||
}
|
||||
|
||||
shadowMat[0][0] = dot - light[0] * ground[0];
|
||||
shadowMat[1][0] = 0.f - light[0] * ground[1];
|
||||
shadowMat[2][0] = 0.f - light[0] * ground[2];
|
||||
shadowMat[3][0] = 0.f - light[0] * d;
|
||||
shadowMat[0][1] = 0.f - light[1] * ground[0];
|
||||
shadowMat[1][1] = dot - light[1] * ground[1];
|
||||
shadowMat[2][1] = 0.f - light[1] * ground[2];
|
||||
shadowMat[3][1] = 0.f - light[1] * d;
|
||||
shadowMat[0][2] = 0.f - light[2] * ground[0];
|
||||
shadowMat[1][2] = 0.f - light[2] * ground[1];
|
||||
shadowMat[2][2] = dot - light[2] * ground[2];
|
||||
shadowMat[3][2] = 0.f - light[2] * d;
|
||||
shadowMat[0][3] = 0.f;
|
||||
shadowMat[1][3] = 0.f;
|
||||
shadowMat[2][3] = 0.f;
|
||||
shadowMat[3][3] = dot;
|
||||
|
||||
qglMatrixMode(GL_MODELVIEW);
|
||||
qglMultMatrixf(&shadowMat[0][0]);
|
||||
|
||||
// Turn on stenciling
|
||||
// This is done to prevent overlapping shadow artifacts
|
||||
qglEnable( GL_STENCIL_TEST );
|
||||
qglStencilFunc( GL_NOTEQUAL, 0x1, 0x7f );
|
||||
qglStencilMask( 0x7f );
|
||||
qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
|
||||
#else
|
||||
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.ori.axis[0][2];
|
||||
ground[1] = backEnd.ori.axis[1][2];
|
||||
ground[2] = backEnd.ori.axis[2][2];
|
||||
|
||||
groundDist = backEnd.ori.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;
|
||||
}
|
||||
#endif // _XBOX
|
||||
}
|
||||
|
||||
//update tr.screenImage
|
||||
void RB_CaptureScreenImage(void)
|
||||
{
|
||||
int radX = 2048;
|
||||
int radY = 2048;
|
||||
int x = glConfig.vidWidth/2;
|
||||
int y = glConfig.vidHeight/2;
|
||||
int cX, cY;
|
||||
|
||||
GL_Bind( tr.screenImage );
|
||||
//using this method, we could pixel-filter the texture and all sorts of crazy stuff.
|
||||
//but, it is slow as hell.
|
||||
/*
|
||||
static byte *tmp = NULL;
|
||||
if (!tmp)
|
||||
{
|
||||
tmp = (byte *)Z_Malloc((sizeof(byte)*4)*(glConfig.vidWidth*glConfig.vidHeight), TAG_ICARUS, qtrue);
|
||||
}
|
||||
qglReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGBA, GL_UNSIGNED_BYTE, tmp);
|
||||
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmp);
|
||||
*/
|
||||
|
||||
if (radX > glConfig.maxTextureSize)
|
||||
{
|
||||
radX = glConfig.maxTextureSize;
|
||||
}
|
||||
if (radY > glConfig.maxTextureSize)
|
||||
{
|
||||
radY = glConfig.maxTextureSize;
|
||||
}
|
||||
|
||||
while (glConfig.vidWidth < radX)
|
||||
{
|
||||
radX /= 2;
|
||||
}
|
||||
while (glConfig.vidHeight < radY)
|
||||
{
|
||||
radY /= 2;
|
||||
}
|
||||
|
||||
cX = x-(radX/2);
|
||||
cY = y-(radY/2);
|
||||
|
||||
if (cX+radX > glConfig.vidWidth)
|
||||
{ //would it go off screen?
|
||||
cX = glConfig.vidWidth-radX;
|
||||
}
|
||||
else if (cX < 0)
|
||||
{ //cap it off at 0
|
||||
cX = 0;
|
||||
}
|
||||
|
||||
if (cY+radY > glConfig.vidHeight)
|
||||
{ //would it go off screen?
|
||||
cY = glConfig.vidHeight-radY;
|
||||
}
|
||||
else if (cY < 0)
|
||||
{ //cap it off at 0
|
||||
cY = 0;
|
||||
}
|
||||
|
||||
#ifndef _XBOX
|
||||
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, cX, cY, radX, radY, 0);
|
||||
#else
|
||||
qglCopyBackBufferToTexEXT(radX, radY, cX, cY, (cX + radX), (cY + radY));
|
||||
#endif // _XBOX
|
||||
}
|
||||
|
||||
|
||||
//yeah.. not really shadow-related.. but it's stencil-related. -rww
|
||||
float tr_distortionAlpha = 1.0f; //opaque
|
||||
float tr_distortionStretch = 0.0f; //no stretch override
|
||||
qboolean tr_distortionPrePost = qfalse; //capture before postrender phase?
|
||||
qboolean tr_distortionNegate = qfalse; //negative blend mode
|
||||
void RB_DistortionFill(void)
|
||||
{
|
||||
float alpha = tr_distortionAlpha;
|
||||
float spost = 0.0f;
|
||||
float spost2 = 0.0f;
|
||||
|
||||
if ( glConfig.stencilBits < 4 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//ok, cap the stupid thing now I guess
|
||||
if (!tr_distortionPrePost)
|
||||
{
|
||||
RB_CaptureScreenImage();
|
||||
}
|
||||
|
||||
// BTO - Xbox fix: High stencil bit is used for glow, don't test against that here!
|
||||
qglEnable(GL_STENCIL_TEST);
|
||||
qglStencilFunc(GL_NOTEQUAL, 0, 0x7F); //0xFFFFFFFF);'
|
||||
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
|
||||
qglDisable (GL_CLIP_PLANE0);
|
||||
GL_Cull( CT_TWO_SIDED );
|
||||
|
||||
//reset the view matrices and go into ortho mode
|
||||
qglMatrixMode(GL_PROJECTION);
|
||||
qglPushMatrix();
|
||||
qglLoadIdentity();
|
||||
qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 32, -1, 1);
|
||||
qglMatrixMode(GL_MODELVIEW);
|
||||
qglPushMatrix();
|
||||
qglLoadIdentity();
|
||||
|
||||
if (tr_distortionStretch)
|
||||
{ //override
|
||||
spost = tr_distortionStretch;
|
||||
spost2 = tr_distortionStretch;
|
||||
}
|
||||
else
|
||||
{ //do slow stretchy effect
|
||||
spost = sin(tr.refdef.time*0.0005f);
|
||||
if (spost < 0.0f)
|
||||
{
|
||||
spost = -spost;
|
||||
}
|
||||
spost *= 0.2f;
|
||||
|
||||
spost2 = sin(tr.refdef.time*0.0005f);
|
||||
if (spost2 < 0.0f)
|
||||
{
|
||||
spost2 = -spost2;
|
||||
}
|
||||
spost2 *= 0.08f;
|
||||
}
|
||||
|
||||
if (alpha != 1.0f)
|
||||
{ //blend
|
||||
GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_SRC_ALPHA);
|
||||
}
|
||||
else
|
||||
{ //be sure to reset the draw state
|
||||
GL_State(0);
|
||||
}
|
||||
|
||||
#ifdef _XBOX
|
||||
qglBeginEXT(GL_QUADS, 4, 0, 0, 4, 0);
|
||||
#else
|
||||
qglBegin(GL_QUADS);
|
||||
#endif // _XBOX
|
||||
qglColor4f(1.0f, 1.0f, 1.0f, alpha);
|
||||
qglTexCoord2f(0+spost2, 1-spost);
|
||||
qglVertex2f(0, 0);
|
||||
|
||||
qglTexCoord2f(0+spost2, 0+spost);
|
||||
qglVertex2f(0, glConfig.vidHeight);
|
||||
|
||||
qglTexCoord2f(1-spost2, 0+spost);
|
||||
qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);
|
||||
|
||||
qglTexCoord2f(1-spost2, 1-spost);
|
||||
qglVertex2f(glConfig.vidWidth, 0);
|
||||
qglEnd();
|
||||
|
||||
if (tr_distortionAlpha == 1.0f && tr_distortionStretch == 0.0f)
|
||||
{ //no overrides
|
||||
if (tr_distortionNegate)
|
||||
{ //probably the crazy alternate saber trail
|
||||
alpha = 0.8f;
|
||||
GL_State(GLS_SRCBLEND_ZERO|GLS_DSTBLEND_ONE_MINUS_SRC_COLOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = 0.5f;
|
||||
GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_SRC_ALPHA);
|
||||
}
|
||||
|
||||
spost = sin(tr.refdef.time*0.0008f);
|
||||
if (spost < 0.0f)
|
||||
{
|
||||
spost = -spost;
|
||||
}
|
||||
spost *= 0.08f;
|
||||
|
||||
spost2 = sin(tr.refdef.time*0.0008f);
|
||||
if (spost2 < 0.0f)
|
||||
{
|
||||
spost2 = -spost2;
|
||||
}
|
||||
spost2 *= 0.2f;
|
||||
|
||||
#ifdef _XBOX
|
||||
qglBeginEXT(GL_QUADS, 4, 0, 0, 4, 0);
|
||||
#else
|
||||
qglBegin(GL_QUADS);
|
||||
#endif // _XBOX
|
||||
qglColor4f(1.0f, 1.0f, 1.0f, alpha);
|
||||
qglTexCoord2f(0+spost2, 1-spost);
|
||||
qglVertex2f(0, 0);
|
||||
|
||||
qglTexCoord2f(0+spost2, 0+spost);
|
||||
qglVertex2f(0, glConfig.vidHeight);
|
||||
|
||||
qglTexCoord2f(1-spost2, 0+spost);
|
||||
qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);
|
||||
|
||||
qglTexCoord2f(1-spost2, 1-spost);
|
||||
qglVertex2f(glConfig.vidWidth, 0);
|
||||
qglEnd();
|
||||
}
|
||||
|
||||
//pop the view matrices back
|
||||
qglMatrixMode(GL_PROJECTION);
|
||||
qglPopMatrix();
|
||||
qglMatrixMode(GL_MODELVIEW);
|
||||
qglPopMatrix();
|
||||
|
||||
qglDisable( GL_STENCIL_TEST );
|
||||
}
|
||||
845
code/renderer/tr_sky.cpp
Normal file
845
code/renderer/tr_sky.cpp
Normal file
@@ -0,0 +1,845 @@
|
||||
// tr_sky.c
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
#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.1 // 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)
|
||||
Com_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] = MAX_WORLD_COORD; //9999;
|
||||
sky_maxs[0][i] = sky_maxs[1][i] = MIN_WORLD_COORD; //-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 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 );
|
||||
|
||||
#ifdef _XBOX
|
||||
int verts = ((maxs[0]+HALF_SKY_SUBDIVISIONS) - (mins[0]+HALF_SKY_SUBDIVISIONS)) * 2 + 2;
|
||||
#endif
|
||||
|
||||
for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
|
||||
{
|
||||
#ifdef _XBOX
|
||||
qglBeginEXT( GL_TRIANGLE_STRIP, verts, 0, 0, verts, 0);
|
||||
#else
|
||||
qglBegin( GL_TRIANGLE_STRIP );
|
||||
#endif
|
||||
|
||||
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.0f;
|
||||
sky_max = 1.0f;
|
||||
|
||||
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[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 )
|
||||
{
|
||||
Com_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->sky );
|
||||
|
||||
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 < input->shader->numUnfoggedPasses; i++ )
|
||||
{
|
||||
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 = MAX_WORLD_COORD;
|
||||
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 = acos( v[0] );
|
||||
tRad = 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;
|
||||
}
|
||||
|
||||
if (skyboxportal && !(backEnd.refdef.rdflags & RDF_SKYBOXPORTAL))
|
||||
{
|
||||
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 {
|
||||
#ifdef _XBOX
|
||||
qglDepthRange( 0.99, 1.0 );
|
||||
#else
|
||||
qglDepthRange( 1.0, 1.0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
82
code/renderer/tr_stl.cpp
Normal file
82
code/renderer/tr_stl.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
#pragma warning(disable : 4786) // identifier was truncated
|
||||
|
||||
// Filename:- tr_stl.cpp
|
||||
//
|
||||
// I mainly made this file because I was getting sick of all the stupid error messages in MS's STL implementation,
|
||||
// and didn't want them showing up in the renderer files they were used in. This way keeps them more or less invisible
|
||||
// because of minimal dependancies
|
||||
//
|
||||
#include "tr_local.h" // this isn't actually needed other than getting rid of warnings via pragmas
|
||||
#include "tr_stl.h"
|
||||
|
||||
#pragma warning( push,3 )
|
||||
|
||||
#pragma warning(disable : 4514) // unreferenced inline function has been removed (within STL, not this code)
|
||||
#pragma warning(disable : 4710) //
|
||||
#pragma warning(disable : 4503) // decorated name length xceeded, name was truncated
|
||||
|
||||
#include <map>
|
||||
#include "../qcommon/sstring.h" // #include <string>
|
||||
using namespace std;
|
||||
|
||||
typedef map<sstring_t, const char *> ShaderEntryPtrs_t;
|
||||
ShaderEntryPtrs_t *ShaderEntryPtrs;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ShaderEntryPtrs_Clear(void)
|
||||
{
|
||||
if( ShaderEntryPtrs )
|
||||
{
|
||||
delete ShaderEntryPtrs;
|
||||
ShaderEntryPtrs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int ShaderEntryPtrs_Size(void)
|
||||
{
|
||||
return ShaderEntryPtrs ? ShaderEntryPtrs->size() : 0;
|
||||
}
|
||||
|
||||
void ShaderEntryPtrs_Insert(const char *token, const char *p)
|
||||
{
|
||||
if( !ShaderEntryPtrs )
|
||||
ShaderEntryPtrs = new ShaderEntryPtrs_t;
|
||||
|
||||
ShaderEntryPtrs_t::iterator it = ShaderEntryPtrs->find(token);
|
||||
|
||||
if (it == ShaderEntryPtrs->end())
|
||||
{
|
||||
(*ShaderEntryPtrs)[token] = p;
|
||||
}
|
||||
}
|
||||
|
||||
// returns NULL if not found...
|
||||
//
|
||||
const char *ShaderEntryPtrs_Lookup(const char *psShaderName)
|
||||
{
|
||||
if( !ShaderEntryPtrs )
|
||||
return NULL;
|
||||
|
||||
ShaderEntryPtrs_t::iterator it = ShaderEntryPtrs->find(psShaderName);
|
||||
if (it != ShaderEntryPtrs->end())
|
||||
{
|
||||
const char *p = (*it).second;
|
||||
return p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma warning ( pop )
|
||||
|
||||
31
code/renderer/tr_stl.h
Normal file
31
code/renderer/tr_stl.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// Filename: tr_stl.h
|
||||
//
|
||||
// I had to make this new file, because if I put the STL "map" include inside tr_local.h then one of the other header
|
||||
// files got compile errors because of using "map" in the function protos as a GLEnum, this way seemed simpler...
|
||||
|
||||
#ifndef TR_STL_H
|
||||
|
||||
|
||||
// REM this out if you want to compile without using STL (but slower of course)
|
||||
//
|
||||
#define USE_STL_FOR_SHADER_LOOKUPS
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef USE_STL_FOR_SHADER_LOOKUPS
|
||||
|
||||
void ShaderEntryPtrs_Clear(void);
|
||||
int ShaderEntryPtrs_Size(void);
|
||||
const char *ShaderEntryPtrs_Lookup(const char *psShaderName);
|
||||
void ShaderEntryPtrs_Insert(const char *token, const char *p);
|
||||
|
||||
#else
|
||||
|
||||
#define ShaderEntryPtrs_Clear()
|
||||
|
||||
#endif // #ifdef USE_STL_FOR_SHADER_LOOKUPS
|
||||
|
||||
#endif // #ifndef TR_STL_H
|
||||
|
||||
|
||||
2477
code/renderer/tr_surface.cpp
Normal file
2477
code/renderer/tr_surface.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1492
code/renderer/tr_surfacesprites.cpp
Normal file
1492
code/renderer/tr_surfacesprites.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1047
code/renderer/tr_terrain.cpp
Normal file
1047
code/renderer/tr_terrain.cpp
Normal file
File diff suppressed because it is too large
Load Diff
244
code/renderer/tr_types.h
Normal file
244
code/renderer/tr_types.h
Normal file
@@ -0,0 +1,244 @@
|
||||
#ifndef __TR_TYPES_H
|
||||
#define __TR_TYPES_H
|
||||
|
||||
#include "..\game\ghoul2_shared.h"
|
||||
|
||||
#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces
|
||||
#ifdef _XBOX
|
||||
#define MAX_ENTITIES 1024 // 11 bits, can't be increased without changing drawsurf bit packing (QSORT_ENTITYNUM_SHIFT)
|
||||
#else
|
||||
#define MAX_ENTITIES 2048 // 11 bits, can't be increased without changing drawsurf bit packing (QSORT_ENTITYNUM_SHIFT)
|
||||
#endif
|
||||
#define TR_WORLDENT (MAX_ENTITIES-1)
|
||||
|
||||
// renderfx flags
|
||||
#define RF_MORELIGHT 0x00001 // allways have some light (viewmodel, some items)
|
||||
#define RF_THIRD_PERSON 0x00002 // don't draw through eyes, only mirrors (player bodies, chat sprites)
|
||||
#define RF_FIRST_PERSON 0x00004 // only draw through eyes (view weapon, damage blood blob)
|
||||
#define RF_DEPTHHACK 0x00008 // for view weapon Z crunching
|
||||
#define RF_NODEPTH 0x00010 // No depth at all (seeing through walls)
|
||||
|
||||
#define RF_VOLUMETRIC 0x00020 // fake volumetric shading
|
||||
|
||||
#define RF_NOSHADOW 0x00040 // don't add stencil shadows
|
||||
|
||||
#define RF_LIGHTING_ORIGIN 0x00080 // 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 0x00100 // use refEntity->shadowPlane
|
||||
#define RF_WRAP_FRAMES 0x00200 // mod the model frames by the maxframes to allow continuous
|
||||
// animation without needing to know the frame count
|
||||
#define RF_CAP_FRAMES 0x00400 // cap the model frames by the maxframes for one shot anims
|
||||
|
||||
#define RF_ALPHA_FADE 0x00800 // hacks blend mode and uses whatever the set alpha is.
|
||||
#define RF_PULSATE 0x01000 // for things like a dropped saber, where we want to add an extra visual clue
|
||||
#define RF_RGB_TINT 0x02000 // overrides ent RGB color to the specified color
|
||||
|
||||
#define RF_FORKED 0x04000 // override lightning to have forks
|
||||
#define RF_TAPERED 0x08000 // lightning tapers
|
||||
#define RF_GROW 0x10000 // lightning grows from start to end during its life
|
||||
|
||||
#define RF_SETANIMINDEX 0x20000 //use backEnd.currentEntity->e.skinNum for R_BindAnimatedImage
|
||||
|
||||
#define RF_DISINTEGRATE1 0x40000 // does a procedural hole-ripping thing.
|
||||
#define RF_DISINTEGRATE2 0x80000 // does a procedural hole-ripping thing with scaling at the ripping point
|
||||
|
||||
#define RF_G2MINLOD 0x100000 // force Lowest lod on g2
|
||||
|
||||
#define RF_SHADOW_ONLY 0x200000 //add surfs for shadowing but don't draw them normally -rww
|
||||
|
||||
#define RF_DISTORTION 0x400000 //area distortion effect -rww
|
||||
|
||||
// refdef flags
|
||||
#define RDF_NOWORLDMODEL 1 // used for player configuration screen
|
||||
#define RDF_HYPERSPACE 4 // teleportation effect
|
||||
|
||||
#define RDF_SKYBOXPORTAL 8
|
||||
#define RDF_DRAWSKYBOX 16 // the above marks a scene as being a 'portal sky'. this flag says to draw it or not
|
||||
|
||||
#define RDF_doLAGoggles 32 // Light Amp goggles
|
||||
#define RDF_doFullbright 64 // Light Amp goggles
|
||||
#define RDF_ForceSightOn 128 // using force sight
|
||||
|
||||
|
||||
extern int skyboxportal;
|
||||
extern int drawskyboxportal;
|
||||
|
||||
typedef byte color4ub_t[4];
|
||||
|
||||
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_ORIENTED_QUAD,
|
||||
RT_LINE,
|
||||
RT_ELECTRICITY,
|
||||
RT_CYLINDER,
|
||||
RT_LATHE,
|
||||
RT_BEAM,
|
||||
RT_SABER_GLOW,
|
||||
RT_PORTALSURFACE, // doesn't draw anything, just info for portals
|
||||
RT_CLOUDS,
|
||||
|
||||
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 colorSrc=vertex shaders
|
||||
float shaderTexCoord[2]; // texture coordinates used by tcMod=vertex modifiers
|
||||
float shaderTime; // subtracted from refdef time to control effect start times
|
||||
|
||||
// extra sprite information
|
||||
float radius;
|
||||
|
||||
// This doesn't have to be unioned, but it does make for more meaningful variable names :)
|
||||
union
|
||||
{
|
||||
float rotation;
|
||||
float endTime;
|
||||
float saberLength;
|
||||
};
|
||||
|
||||
/*
|
||||
Ghoul2 Insert Start
|
||||
*/
|
||||
vec3_t angles; // rotation angles - used for Ghoul2
|
||||
|
||||
vec3_t modelScale; // axis scale for models
|
||||
CGhoul2Info_v *ghoul2; // has to be at the end of the ref-ent in order for it to be created properly
|
||||
/*
|
||||
Ghoul2 Insert End
|
||||
*/
|
||||
|
||||
#ifdef _XBOX
|
||||
int number;
|
||||
#endif
|
||||
|
||||
} 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
|
||||
int viewContents; // world contents at vieworg
|
||||
|
||||
// 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,
|
||||
TC_S3TC_DXT
|
||||
} textureCompression_t;
|
||||
|
||||
typedef struct {
|
||||
const char *renderer_string;
|
||||
const char *vendor_string;
|
||||
const char *version_string;
|
||||
const char *extensions_string;
|
||||
|
||||
int maxTextureSize; // queried from GL
|
||||
int maxActiveTextures; // multitexture ability
|
||||
float maxTextureFilterAnisotropy;
|
||||
|
||||
int colorBits, depthBits, stencilBits;
|
||||
|
||||
qboolean deviceSupportsGamma;
|
||||
textureCompression_t textureCompression;
|
||||
qboolean textureEnvAddAvailable;
|
||||
qboolean textureFilterAnisotropicAvailable;
|
||||
qboolean clampToEdgeAvailable;
|
||||
|
||||
int vidWidth, vidHeight;
|
||||
|
||||
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;
|
||||
} glconfig_t;
|
||||
|
||||
|
||||
#if !defined _WIN32
|
||||
|
||||
#define OPENGL_DRIVER_NAME "libGL.so"
|
||||
|
||||
#else
|
||||
|
||||
#define OPENGL_DRIVER_NAME "opengl32"
|
||||
|
||||
#endif // !defined _WIN32
|
||||
|
||||
|
||||
#endif // __TR_TYPES_H
|
||||
1021
code/renderer/tr_world.cpp
Normal file
1021
code/renderer/tr_world.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user