4383 lines
105 KiB
C
4383 lines
105 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <GL/gl.h>
|
|
#include <GL/glext.h>
|
|
|
|
#include "fixer.h"
|
|
|
|
#include "3dc.h"
|
|
#include "platform.h"
|
|
#include "inline.h"
|
|
#include "module.h"
|
|
#include "stratdef.h"
|
|
#include "projfont.h"
|
|
#include "krender.h"
|
|
#include "kshape.h"
|
|
#include "prototyp.h"
|
|
#include "frustum.h"
|
|
#include "lighting.h"
|
|
#include "bh_types.h"
|
|
#include "showcmds.h"
|
|
#include "d3d_hud.h"
|
|
#include "hud_layout.h"
|
|
#include "avp_userprofile.h"
|
|
#include "aw.h"
|
|
|
|
int LightIntensityAtPoint(VECTORCH *pointPtr);
|
|
|
|
extern IMAGEHEADER ImageHeaderArray[];
|
|
extern VIEWDESCRIPTORBLOCK *Global_VDB_Ptr;
|
|
extern unsigned char GammaValues[256];
|
|
extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
|
|
|
|
extern int SpecialFXImageNumber;
|
|
extern int StaticImageNumber;
|
|
extern int PredatorNumbersImageNumber;
|
|
extern int BurningImageNumber;
|
|
extern int ChromeImageNumber;
|
|
extern int WaterShaftImageNumber;
|
|
extern int HUDFontsImageNumber;
|
|
extern int AAFontImageNumber;
|
|
|
|
extern int FMVParticleColour;
|
|
extern int HUDScaleFactor;
|
|
extern int CloakingPhase;
|
|
|
|
static D3DTexture *CurrTextureHandle;
|
|
|
|
|
|
static enum TRANSLUCENCY_TYPE CurrentTranslucencyMode = TRANSLUCENCY_OFF;
|
|
static enum FILTERING_MODE_ID CurrentFilteringMode = FILTERING_BILINEAR_OFF;
|
|
static D3DTexture *CurrentlyBoundTexture = NULL;
|
|
|
|
#define TA_MAXVERTICES 2048
|
|
#define TA_MAXTRIANGLES 2048
|
|
|
|
typedef struct VertexArray
|
|
{
|
|
GLfloat v[4];
|
|
|
|
GLfloat t[3]; /* 3rd float is padding */
|
|
|
|
GLubyte c[4];
|
|
} VertexArray;
|
|
|
|
typedef struct TriangleArray
|
|
{
|
|
int a;
|
|
int b;
|
|
int c;
|
|
} TriangleArray;
|
|
|
|
static VertexArray varr[TA_MAXVERTICES*2];
|
|
static TriangleArray tarr[TA_MAXTRIANGLES*2];
|
|
static VertexArray *varrp = varr;
|
|
static TriangleArray *tarrp = tarr;
|
|
static int varrc, tarrc;
|
|
|
|
static VertexArray *svarr = &varr[TA_MAXVERTICES], *svarrp = &varr[TA_MAXVERTICES];
|
|
static TriangleArray *starr = &tarr[TA_MAXTRIANGLES], *starrp = &tarr[TA_MAXTRIANGLES];
|
|
static int svarrc, starrc;
|
|
|
|
static int haslocked = 0;
|
|
|
|
/* Do not call this directly! */
|
|
static void SetTranslucencyMode(enum TRANSLUCENCY_TYPE mode)
|
|
{
|
|
switch(mode) {
|
|
case TRANSLUCENCY_OFF:
|
|
if (TRIPTASTIC_CHEATMODE||MOTIONBLUR_CHEATMODE) {
|
|
glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
|
|
} else {
|
|
//glDisable(GL_BLEND);
|
|
glBlendFunc(GL_ONE, GL_ZERO); /* this *should* be optimized */
|
|
}
|
|
break;
|
|
case TRANSLUCENCY_NORMAL:
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
break;
|
|
case TRANSLUCENCY_COLOUR:
|
|
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
|
|
break;
|
|
case TRANSLUCENCY_INVCOLOUR:
|
|
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
|
break;
|
|
case TRANSLUCENCY_GLOWING:
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
break;
|
|
case TRANSLUCENCY_DARKENINGCOLOUR:
|
|
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
|
break;
|
|
case TRANSLUCENCY_JUSTSETZ:
|
|
glBlendFunc(GL_ZERO, GL_ONE);
|
|
break;
|
|
default:
|
|
fprintf(stderr, "RenderPolygon.TranslucencyMode: invalid %d\n", RenderPolygon.TranslucencyMode);
|
|
return;
|
|
}
|
|
|
|
//if (mode != TRANSLUCENCY_OFF && CurrentTranslucencyMode == TRANSLUCENCY_OFF)
|
|
// glEnable(GL_BLEND);
|
|
}
|
|
|
|
/*
|
|
A few things:
|
|
- Vertices with a specular color are done twice.
|
|
Might want to try spitting apart the three arrays and using the same vertex
|
|
array for both passes.
|
|
*/
|
|
|
|
static void FlushTriangleBuffers(int backup)
|
|
{
|
|
int i;
|
|
|
|
if (haslocked == 0) {
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glVertexPointer(4, GL_FLOAT, sizeof(varr[0]), varr[0].v);
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glTexCoordPointer(2, GL_FLOAT, sizeof(varr[0]), varr[0].t);
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(varr[0]), varr[0].c);
|
|
|
|
haslocked = 1;
|
|
}
|
|
|
|
if (tarrc) {
|
|
#if 1
|
|
glBegin(GL_TRIANGLES);
|
|
for (i = 0; i < tarrc; i++) {
|
|
glArrayElement(tarr[i].a);
|
|
glArrayElement(tarr[i].b);
|
|
glArrayElement(tarr[i].c);
|
|
}
|
|
glEnd();
|
|
#else
|
|
glDrawElements(GL_TRIANGLES, tarrc*3, GL_UNSIGNED_INT, tarr);
|
|
#endif
|
|
|
|
tarrc = 0;
|
|
tarrp = tarr;
|
|
|
|
varrc = 0;
|
|
varrp = varr;
|
|
}
|
|
|
|
if (starrc) {
|
|
if (CurrentlyBoundTexture != NULL) {
|
|
if (!backup) CurrentlyBoundTexture = NULL;
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
}
|
|
|
|
if (CurrentTranslucencyMode != TRANSLUCENCY_GLOWING) {
|
|
if (!backup) CurrentTranslucencyMode = TRANSLUCENCY_GLOWING;
|
|
SetTranslucencyMode(TRANSLUCENCY_GLOWING);
|
|
//if (CurrentTranslucencyMode == TRANSLUCENCY_OFF)
|
|
// glEnable(GL_BLEND);
|
|
//glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
}
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
#if 1
|
|
glBegin(GL_TRIANGLES);
|
|
for (i = 0; i < starrc; i++) {
|
|
glArrayElement(starr[i].a);
|
|
glArrayElement(starr[i].b);
|
|
glArrayElement(starr[i].c);
|
|
}
|
|
glEnd();
|
|
#else
|
|
glDrawElements(GL_TRIANGLES, starrc*3, GL_UNSIGNED_INT, starr);
|
|
#endif
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
if (backup) {
|
|
if (CurrentlyBoundTexture)
|
|
glBindTexture(GL_TEXTURE_2D, CurrentlyBoundTexture->id);
|
|
if (CurrentTranslucencyMode != TRANSLUCENCY_GLOWING)
|
|
SetTranslucencyMode(CurrentTranslucencyMode);
|
|
} else {
|
|
CurrentlyBoundTexture = NULL;
|
|
CurrentTranslucencyMode = TRANSLUCENCY_GLOWING;
|
|
}
|
|
|
|
starrc = 0;
|
|
starrp = starr;
|
|
|
|
svarrc = 0;
|
|
svarrp = svarr;
|
|
}
|
|
|
|
}
|
|
|
|
static void CheckBoundTextureIsCorrect(D3DTexture *tex)
|
|
{
|
|
if (tex == CurrentlyBoundTexture)
|
|
return;
|
|
|
|
FlushTriangleBuffers(1);
|
|
|
|
if (tex == NULL) {
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
CurrentlyBoundTexture = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
glBindTexture(GL_TEXTURE_2D, tex->id);
|
|
|
|
if (tex->filter != CurrentFilteringMode) {
|
|
switch(CurrentFilteringMode) {
|
|
case FILTERING_BILINEAR_OFF:
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
break;
|
|
case FILTERING_BILINEAR_ON:
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
break;
|
|
default:
|
|
}
|
|
|
|
tex->filter = CurrentFilteringMode;
|
|
}
|
|
|
|
CurrentlyBoundTexture = tex;
|
|
}
|
|
|
|
static void CheckFilteringModeIsCorrect(enum FILTERING_MODE_ID filter)
|
|
{
|
|
CurrentFilteringMode = filter;
|
|
|
|
if (CurrentlyBoundTexture && CurrentlyBoundTexture->filter != CurrentFilteringMode) {
|
|
FlushTriangleBuffers(1);
|
|
|
|
switch(CurrentFilteringMode) {
|
|
case FILTERING_BILINEAR_OFF:
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
break;
|
|
case FILTERING_BILINEAR_ON:
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
break;
|
|
default:
|
|
}
|
|
|
|
CurrentlyBoundTexture->filter = CurrentFilteringMode;
|
|
}
|
|
}
|
|
|
|
static void CheckTranslucencyModeIsCorrect(enum TRANSLUCENCY_TYPE mode)
|
|
{
|
|
if (CurrentTranslucencyMode == mode)
|
|
return;
|
|
|
|
FlushTriangleBuffers(1);
|
|
|
|
SetTranslucencyMode(mode);
|
|
|
|
CurrentTranslucencyMode = mode;
|
|
}
|
|
|
|
static void CheckTriangleBuffer(int rver, int sver, int rtri, int stri, D3DTexture *tex, enum TRANSLUCENCY_TYPE mode, enum FILTERING_MODE_ID filter)
|
|
{
|
|
if ((rver+varrc) >= TA_MAXVERTICES) {
|
|
FlushTriangleBuffers(0);
|
|
} else if ((sver+svarrc) >= TA_MAXVERTICES) {
|
|
FlushTriangleBuffers(0);
|
|
} else if (rtri == 0 && ((rver-2+tarrc) >= TA_MAXTRIANGLES)) {
|
|
FlushTriangleBuffers(0);
|
|
} else if (rtri && ((rtri+tarrc) >= TA_MAXTRIANGLES)) {
|
|
FlushTriangleBuffers(0);
|
|
} else if (stri == 0 && ((sver-2+starrc) >= TA_MAXTRIANGLES)) {
|
|
FlushTriangleBuffers(0);
|
|
} else if (stri && ((stri+starrc) >= TA_MAXTRIANGLES)) {
|
|
FlushTriangleBuffers(0);
|
|
}
|
|
|
|
if ((int)tex != -1)
|
|
CheckBoundTextureIsCorrect(tex);
|
|
if (mode != -1)
|
|
CheckTranslucencyModeIsCorrect(mode);
|
|
if (filter != -1)
|
|
CheckFilteringModeIsCorrect(filter);
|
|
|
|
#define OUTPUT_TRIANGLE(x, y, z) \
|
|
{ \
|
|
tarrp->a = varrc+(x); \
|
|
tarrp->b = varrc+(y); \
|
|
tarrp->c = varrc+(z); \
|
|
\
|
|
tarrp++; \
|
|
tarrc++; \
|
|
}
|
|
|
|
if (rtri == 0) {
|
|
switch(rver) {
|
|
case 0:
|
|
break;
|
|
case 3:
|
|
OUTPUT_TRIANGLE(0, 2, 1);
|
|
break;
|
|
case 5:
|
|
OUTPUT_TRIANGLE(0, 1, 4);
|
|
OUTPUT_TRIANGLE(1, 3, 4);
|
|
OUTPUT_TRIANGLE(1, 2, 3);
|
|
break;
|
|
case 8:
|
|
OUTPUT_TRIANGLE(0, 6, 7);
|
|
case 7:
|
|
OUTPUT_TRIANGLE(0, 5, 6);
|
|
case 6:
|
|
OUTPUT_TRIANGLE(0, 4, 5);
|
|
OUTPUT_TRIANGLE(0, 3, 4);
|
|
case 4:
|
|
OUTPUT_TRIANGLE(0, 2, 3);
|
|
OUTPUT_TRIANGLE(0, 1, 2);
|
|
break;
|
|
default:
|
|
fprintf(stderr, "DrawTriangles_T2F_C4UB_V4F: vertices = %d\n", rver);
|
|
}
|
|
}
|
|
#undef OUTPUT_TRIANGLE
|
|
|
|
#define OUTPUT_TRIANGLE(x, y, z) \
|
|
{ \
|
|
starrp->a = TA_MAXVERTICES+svarrc+(x); \
|
|
starrp->b = TA_MAXVERTICES+svarrc+(y); \
|
|
starrp->c = TA_MAXVERTICES+svarrc+(z); \
|
|
\
|
|
starrp++; \
|
|
starrc++; \
|
|
}
|
|
if (stri == 0) {
|
|
switch(sver) {
|
|
case 0:
|
|
break;
|
|
case 3:
|
|
OUTPUT_TRIANGLE(0, 2, 1);
|
|
break;
|
|
case 5:
|
|
OUTPUT_TRIANGLE(0, 1, 4);
|
|
OUTPUT_TRIANGLE(1, 3, 4);
|
|
OUTPUT_TRIANGLE(1, 2, 3);
|
|
break;
|
|
case 8:
|
|
OUTPUT_TRIANGLE(0, 6, 7);
|
|
case 7:
|
|
OUTPUT_TRIANGLE(0, 5, 6);
|
|
case 6:
|
|
OUTPUT_TRIANGLE(0, 4, 5);
|
|
OUTPUT_TRIANGLE(0, 3, 4);
|
|
case 4:
|
|
OUTPUT_TRIANGLE(0, 2, 3);
|
|
OUTPUT_TRIANGLE(0, 1, 2);
|
|
break;
|
|
default:
|
|
fprintf(stderr, "DrawTriangles_T2F_C4UB_V4F: vertices = %d\n", sver);
|
|
}
|
|
}
|
|
#undef OUTPUT_TRIANGLE
|
|
|
|
}
|
|
|
|
static void SelectPolygonBeginType(int points)
|
|
{
|
|
if (tarrc || starrc)
|
|
FlushTriangleBuffers(1);
|
|
|
|
switch(points) {
|
|
case 3:
|
|
glBegin(GL_TRIANGLES);
|
|
break;
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
glBegin(GL_TRIANGLE_FAN);
|
|
break;
|
|
default:
|
|
fprintf(stderr, "SelectPolygonBeginType: points = %d\n", points);
|
|
break;
|
|
}
|
|
}
|
|
|
|
GLuint CreateOGLTexture(D3DTexture *tex, unsigned char *buf)
|
|
{
|
|
GLuint h;
|
|
|
|
FlushTriangleBuffers(1);
|
|
|
|
glGenTextures(1, &h);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, h);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->w, tex->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
|
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
|
|
tex->id = h;
|
|
tex->filter = FILTERING_BILINEAR_ON;
|
|
|
|
if (CurrentlyBoundTexture)
|
|
glBindTexture(GL_TEXTURE_2D, CurrentlyBoundTexture->id); /* restore current */
|
|
|
|
return h;
|
|
}
|
|
|
|
/* ** */
|
|
|
|
void ThisFramesRenderingHasBegun()
|
|
{
|
|
CheckFilteringModeIsCorrect(FILTERING_BILINEAR_ON);
|
|
}
|
|
|
|
void ThisFramesRenderingHasFinished()
|
|
{
|
|
LightBlockDeallocation();
|
|
|
|
FlushTriangleBuffers(0);
|
|
}
|
|
|
|
/* ** */
|
|
|
|
void FlushD3DZBuffer()
|
|
{
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
|
|
void SecondFlushD3DZBuffer()
|
|
{
|
|
FlushTriangleBuffers(0);
|
|
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
|
|
void D3D_DecalSystem_Setup()
|
|
{
|
|
FlushTriangleBuffers(0);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
/* this does stop zfighting with bulletmarks on walls... */
|
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
|
glPolygonOffset(-10.0, -10.0);
|
|
}
|
|
|
|
void D3D_DecalSystem_End()
|
|
{
|
|
FlushTriangleBuffers(0);
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
|
}
|
|
|
|
/* ** */
|
|
|
|
void D3D_Rectangle(int x0, int y0, int x1, int y1, int r, int g, int b, int a)
|
|
{
|
|
GLfloat x[4], y[4];
|
|
|
|
if (y1 <= y0)
|
|
return;
|
|
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_GLOWING);
|
|
CheckBoundTextureIsCorrect(NULL);
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
x[0] = x0;
|
|
x[0] = (x[0] - ScreenDescriptorBlock.SDB_CentreX)/ScreenDescriptorBlock.SDB_CentreX;
|
|
y[0] = y0;
|
|
y[0] = -(y[0] - ScreenDescriptorBlock.SDB_CentreY)/ScreenDescriptorBlock.SDB_CentreY;
|
|
|
|
x[1] = x1 - 1;
|
|
x[1] = (x[1] - ScreenDescriptorBlock.SDB_CentreX)/ScreenDescriptorBlock.SDB_CentreX;
|
|
y[1] = y0;
|
|
y[1] = -(y[1] - ScreenDescriptorBlock.SDB_CentreY)/ScreenDescriptorBlock.SDB_CentreY;
|
|
|
|
x[2] = x1 - 1;
|
|
x[2] = (x[2] - ScreenDescriptorBlock.SDB_CentreX)/ScreenDescriptorBlock.SDB_CentreX;
|
|
y[2] = y1 - 1;
|
|
y[2] = -(y[2] - ScreenDescriptorBlock.SDB_CentreY)/ScreenDescriptorBlock.SDB_CentreY;
|
|
|
|
x[3] = x0;
|
|
x[3] = (x[3] - ScreenDescriptorBlock.SDB_CentreX)/ScreenDescriptorBlock.SDB_CentreX;
|
|
y[3] = y1 - 1;
|
|
y[3] = -(y[3] - ScreenDescriptorBlock.SDB_CentreY)/ScreenDescriptorBlock.SDB_CentreY;
|
|
|
|
SelectPolygonBeginType(3); /* triangles */
|
|
|
|
glVertex3f(x[0], y[0], -1.0f);
|
|
glVertex3f(x[1], y[1], -1.0f);
|
|
glVertex3f(x[3], y[3], -1.0f);
|
|
|
|
glVertex3f(x[1], y[1], -1.0f);
|
|
glVertex3f(x[2], y[2], -1.0f);
|
|
glVertex3f(x[3], y[3], -1.0f);
|
|
|
|
glEnd();
|
|
}
|
|
|
|
/* ** */
|
|
|
|
void D3D_ZBufferedGouraudTexturedPolygon_Output(POLYHEADER *inputPolyPtr, RENDERVERTEX *renderVerticesPtr)
|
|
{
|
|
int texoffset;
|
|
D3DTexture *TextureHandle;
|
|
int i;
|
|
GLfloat ZNear;
|
|
float RecipW, RecipH;
|
|
|
|
ZNear = (GLfloat) (Global_VDB_Ptr->VDB_ClipZ * GlobalScale);
|
|
|
|
texoffset = inputPolyPtr->PolyColour & ClrTxDefn;
|
|
if (texoffset) {
|
|
TextureHandle = (void *)ImageHeaderArray[texoffset].D3DTexture;
|
|
|
|
CurrTextureHandle = TextureHandle;
|
|
} else {
|
|
TextureHandle = CurrTextureHandle;
|
|
}
|
|
|
|
if (TextureHandle->w == 128) {
|
|
RecipW = (1.0f / 128.0f) / 65536.0f;
|
|
} else {
|
|
float width = TextureHandle->w;
|
|
RecipW = (1.0f / width) / 65536.0f;
|
|
}
|
|
if (TextureHandle->h == 128) {
|
|
RecipH = (1.0f / 128.0f) / 65536.0f;
|
|
} else {
|
|
float height = TextureHandle->h;
|
|
RecipH = (1.0f / height) / 65536.0f;
|
|
}
|
|
|
|
CheckTriangleBuffer(RenderPolygon.NumberOfVertices, RenderPolygon.NumberOfVertices, 0, 0, TextureHandle, RenderPolygon.TranslucencyMode, -1);
|
|
|
|
for (i = 0; i < RenderPolygon.NumberOfVertices; i++) {
|
|
RENDERVERTEX *vertices = &renderVerticesPtr[i];
|
|
GLfloat x, y, z;
|
|
GLfloat s, t;
|
|
GLfloat rhw = 1.0/(float)vertices->Z, zvalue;
|
|
|
|
s = ((float)vertices->U) * RecipW + (1.0f/256.0f);
|
|
t = ((float)vertices->V) * RecipH + (1.0f/256.0f);
|
|
|
|
// if (s < 0.0 || t < 0.0 || s >= 1.0 || t >= 1.0)
|
|
// fprintf(stderr, "HEY! s = %f, t = %f (%d, %d)\n", s, t, vertices->U, vertices->V);
|
|
|
|
x = ((float)vertices->X*((float)Global_VDB_Ptr->VDB_ProjX+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreX);
|
|
y = -((float)vertices->Y*((float)Global_VDB_Ptr->VDB_ProjY+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreY);
|
|
|
|
zvalue = vertices->Z+HeadUpDisplayZOffset;
|
|
z = 1.0f - 2.0f*ZNear/zvalue;
|
|
|
|
varrp->v[0] = svarrp->v[0] = x/rhw;
|
|
varrp->v[1] = svarrp->v[1] = y/rhw;
|
|
varrp->v[2] = svarrp->v[2] = z/rhw;
|
|
varrp->v[3] = svarrp->v[3] = 1/rhw;
|
|
|
|
varrp->t[0] = /**/ svarrp->t[0] = /**/ s;
|
|
varrp->t[1] = /**/ svarrp->t[1] = /**/ t;
|
|
|
|
varrp->c[0] = GammaValues[vertices->R];
|
|
varrp->c[1] = GammaValues[vertices->G];
|
|
varrp->c[2] = GammaValues[vertices->B];
|
|
varrp->c[3] = vertices->A;
|
|
|
|
svarrp->c[0] = GammaValues[vertices->SpecularR];
|
|
svarrp->c[1] = GammaValues[vertices->SpecularG];
|
|
svarrp->c[2] = GammaValues[vertices->SpecularB];
|
|
svarrp->c[3] = 255;
|
|
|
|
varrp++;
|
|
varrc++;
|
|
svarrp++;
|
|
svarrc++;
|
|
}
|
|
}
|
|
|
|
void D3D_SkyPolygon_Output(POLYHEADER *inputPolyPtr, RENDERVERTEX *renderVerticesPtr)
|
|
{
|
|
int texoffset;
|
|
D3DTexture *TextureHandle;
|
|
int i;
|
|
float RecipW, RecipH;
|
|
|
|
texoffset = inputPolyPtr->PolyColour & ClrTxDefn;
|
|
TextureHandle = (void *)ImageHeaderArray[texoffset].D3DTexture;
|
|
CurrTextureHandle = TextureHandle;
|
|
|
|
if (TextureHandle->w == 128) {
|
|
RecipW = (1.0f / 128.0f) / 65536.0f;
|
|
} else {
|
|
float width = TextureHandle->w;
|
|
RecipW = (1.0f / width) / 65536.0f;
|
|
}
|
|
if (TextureHandle->h == 128) {
|
|
RecipH = (1.0f / 128.0f) / 65536.0f;
|
|
} else {
|
|
float height = TextureHandle->h;
|
|
RecipH = (1.0f / height) / 65536.0f;
|
|
}
|
|
|
|
CheckTriangleBuffer(RenderPolygon.NumberOfVertices, 0, 0, 0, TextureHandle, RenderPolygon.TranslucencyMode, -1);
|
|
|
|
for (i = 0; i < RenderPolygon.NumberOfVertices; i++) {
|
|
RENDERVERTEX *vertices = &renderVerticesPtr[i];
|
|
GLfloat x, y, z;
|
|
GLfloat s, t;
|
|
GLfloat rhw;
|
|
|
|
rhw = 1.0 / (float)vertices->Z;
|
|
|
|
s = ((float)vertices->U) * RecipW + (1.0f/256.0f);
|
|
t = ((float)vertices->V) * RecipH + (1.0f/256.0f);
|
|
|
|
// if (s < 0.0 || t < 0.0 || s >= 1.0 || t >= 1.0)
|
|
// fprintf(stderr, "HEY! s = %f, t = %f (%d, %d)\n", s, t, vertices->U, vertices->V);
|
|
|
|
|
|
x = ((float)vertices->X*((float)Global_VDB_Ptr->VDB_ProjX+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreX);
|
|
y = -((float)vertices->Y*((float)Global_VDB_Ptr->VDB_ProjY+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreY);
|
|
|
|
z = 1.0f;
|
|
|
|
varrp->v[0] = x/rhw;
|
|
varrp->v[1] = y/rhw;
|
|
varrp->v[2] = z/rhw;
|
|
varrp->v[3] = 1/rhw;
|
|
|
|
varrp->t[0] = s;
|
|
varrp->t[1] = t;
|
|
|
|
varrp->c[0] = vertices->R;
|
|
varrp->c[1] = vertices->G;
|
|
varrp->c[2] = vertices->B;
|
|
varrp->c[3] = vertices->A;
|
|
|
|
varrp++;
|
|
varrc++;
|
|
}
|
|
}
|
|
|
|
void D3D_ZBufferedCloakedPolygon_Output(POLYHEADER *inputPolyPtr, RENDERVERTEX *renderVerticesPtr)
|
|
{
|
|
int flags;
|
|
int texoffset;
|
|
int i;
|
|
D3DTexture *TextureHandle;
|
|
|
|
float ZNear;
|
|
float RecipW, RecipH;
|
|
|
|
ZNear = (float) (Global_VDB_Ptr->VDB_ClipZ * GlobalScale);
|
|
|
|
flags = inputPolyPtr->PolyFlags;
|
|
texoffset = (inputPolyPtr->PolyColour & ClrTxDefn);
|
|
|
|
TextureHandle = ImageHeaderArray[texoffset].D3DTexture;
|
|
CurrTextureHandle = TextureHandle;
|
|
|
|
if (TextureHandle->w == 128) {
|
|
RecipW = 1.0f / 128.0f;
|
|
} else {
|
|
float width = (float) TextureHandle->w;
|
|
RecipW = 1.0f / width;
|
|
}
|
|
|
|
if (TextureHandle->h == 128) {
|
|
RecipH = 1.0f / 128.0f;
|
|
} else {
|
|
float height = (float) TextureHandle->h;
|
|
RecipH = 1.0f / height;
|
|
}
|
|
|
|
CheckTriangleBuffer(RenderPolygon.NumberOfVertices, 0, 0, 0, TextureHandle, TRANSLUCENCY_NORMAL, -1);
|
|
|
|
for (i = 0; i < RenderPolygon.NumberOfVertices; i++) {
|
|
RENDERVERTEX *vertices = &renderVerticesPtr[i];
|
|
|
|
GLfloat x, y, z;
|
|
GLfloat s, t;
|
|
GLfloat rhw;
|
|
GLfloat zvalue;
|
|
|
|
rhw = 1.0 / (float)vertices->Z;
|
|
|
|
s = (((float)vertices->U/65536.0f)+0.5) * RecipW;
|
|
t = (((float)vertices->V/65536.0f)+0.5) * RecipH;
|
|
|
|
// if (s < 0.0 || t < 0.0 || s >= 1.0 || t >= 1.0)
|
|
// fprintf(stderr, "HEY! s = %f, t = %f (%d, %d)\n", s, t, vertices->U, vertices->V);
|
|
|
|
|
|
x = ((float)vertices->X*((float)Global_VDB_Ptr->VDB_ProjX+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreX);
|
|
y = -((float)vertices->Y*((float)Global_VDB_Ptr->VDB_ProjY+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreY);
|
|
|
|
zvalue = vertices->Z+HeadUpDisplayZOffset;
|
|
z = 1.0 - 2*ZNear/zvalue;
|
|
|
|
varrp->v[0] = x/rhw;
|
|
varrp->v[1] = y/rhw;
|
|
varrp->v[2] = z/rhw;
|
|
varrp->v[3] = 1/rhw;
|
|
|
|
varrp->t[0] = s;
|
|
varrp->t[1] = t;
|
|
|
|
varrp->c[0] = vertices->R;
|
|
varrp->c[1] = vertices->G;
|
|
varrp->c[2] = vertices->B;
|
|
varrp->c[3] = vertices->A;
|
|
|
|
varrp++;
|
|
varrc++;
|
|
}
|
|
}
|
|
|
|
void D3D_Decal_Output(DECAL *decalPtr, RENDERVERTEX *renderVerticesPtr)
|
|
{
|
|
DECAL_DESC *decalDescPtr = &DecalDescription[decalPtr->DecalID];
|
|
int texoffset;
|
|
D3DTexture *TextureHandle;
|
|
int i;
|
|
|
|
float ZNear;
|
|
float RecipW, RecipH;
|
|
int r, g, b, a;
|
|
|
|
ZNear = (float) (Global_VDB_Ptr->VDB_ClipZ * GlobalScale);
|
|
|
|
|
|
if (decalPtr->DecalID == DECAL_FMV) {
|
|
/* not (yet) implemented */
|
|
return;
|
|
} else if (decalPtr->DecalID == DECAL_SHAFTOFLIGHT||decalPtr->DecalID == DECAL_SHAFTOFLIGHT_OUTER) {
|
|
TextureHandle = NULL;
|
|
|
|
RecipW = 1.0 / 256.0; /* ignored */
|
|
RecipH = 1.0 / 256.0;
|
|
} else {
|
|
texoffset = SpecialFXImageNumber;
|
|
|
|
TextureHandle = ImageHeaderArray[texoffset].D3DTexture;
|
|
|
|
if (TextureHandle->w == 256) {
|
|
RecipW = 1.0 / 256.0;
|
|
} else {
|
|
float width = (float) TextureHandle->w;
|
|
RecipW = 1.0 / width;
|
|
}
|
|
|
|
if (TextureHandle->h == 256) {
|
|
RecipH = 1.0 / 256.0;
|
|
} else {
|
|
float height = (float) TextureHandle->h;
|
|
RecipH = 1.0 / height;
|
|
}
|
|
}
|
|
|
|
if (decalDescPtr->IsLit) {
|
|
int intensity = LightIntensityAtPoint(decalPtr->Vertices);
|
|
|
|
r = MUL_FIXED(intensity,decalDescPtr->RedScale[CurrentVisionMode]);
|
|
g = MUL_FIXED(intensity,decalDescPtr->GreenScale[CurrentVisionMode]);
|
|
b = MUL_FIXED(intensity,decalDescPtr->BlueScale[CurrentVisionMode]);
|
|
a = decalDescPtr->Alpha;
|
|
} else {
|
|
r = decalDescPtr->RedScale[CurrentVisionMode];
|
|
g = decalDescPtr->GreenScale[CurrentVisionMode];
|
|
b = decalDescPtr->BlueScale[CurrentVisionMode];
|
|
a = decalDescPtr->Alpha;
|
|
}
|
|
|
|
if (RAINBOWBLOOD_CHEATMODE) {
|
|
r = FastRandom()&255;
|
|
g = FastRandom()&255;
|
|
b = FastRandom()&255;
|
|
a = decalDescPtr->Alpha;
|
|
}
|
|
|
|
CheckTriangleBuffer(RenderPolygon.NumberOfVertices, 0, 0, 0, TextureHandle, decalDescPtr->TranslucencyType, -1);
|
|
|
|
for (i = 0; i < RenderPolygon.NumberOfVertices; i++) {
|
|
RENDERVERTEX *vertices = &renderVerticesPtr[i];
|
|
|
|
GLfloat x, y, z, zvalue;
|
|
GLfloat s, t, rhw;
|
|
|
|
rhw = 1.0 / (float)vertices->Z;
|
|
|
|
x = ((float)vertices->X*((float)Global_VDB_Ptr->VDB_ProjX+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreX);
|
|
y = -((float)vertices->Y*((float)Global_VDB_Ptr->VDB_ProjY+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreY);
|
|
|
|
s = ((float)(vertices->U/65536.0f)+0.5f) * RecipW;
|
|
t = ((float)(vertices->V/65536.0f)+0.5f) * RecipH;
|
|
|
|
zvalue = vertices->Z+HeadUpDisplayZOffset;
|
|
z = 1.0f - 2.0f*ZNear/zvalue;
|
|
|
|
varrp->v[0] = x/rhw;
|
|
varrp->v[1] = y/rhw;
|
|
varrp->v[2] = z/rhw;
|
|
varrp->v[3] = 1/rhw;
|
|
|
|
varrp->t[0] = s;
|
|
varrp->t[1] = t;
|
|
|
|
varrp->c[0] = r;
|
|
varrp->c[1] = g;
|
|
varrp->c[2] = b;
|
|
varrp->c[3] = a;
|
|
|
|
varrp++;
|
|
varrc++;
|
|
}
|
|
}
|
|
|
|
void D3D_Particle_Output(PARTICLE *particlePtr, RENDERVERTEX *renderVerticesPtr)
|
|
{
|
|
PARTICLE_DESC *particleDescPtr = &ParticleDescription[particlePtr->ParticleID];
|
|
int texoffset = SpecialFXImageNumber;
|
|
GLfloat ZNear;
|
|
int i;
|
|
float RecipW, RecipH;
|
|
int r, g, b, a;
|
|
|
|
D3DTexture *TextureHandle;
|
|
|
|
|
|
ZNear = (GLfloat) (Global_VDB_Ptr->VDB_ClipZ * GlobalScale);
|
|
|
|
TextureHandle = ImageHeaderArray[texoffset].D3DTexture;
|
|
|
|
if (TextureHandle->w == 256) {
|
|
RecipW = 1.0 / 256.0;
|
|
} else {
|
|
float width = (float) TextureHandle->w;
|
|
|
|
RecipW = (1.0 / width);
|
|
}
|
|
|
|
if (TextureHandle->h == 256) {
|
|
RecipH = 1.0 / 256.0;
|
|
} else {
|
|
float height = (float) TextureHandle->h;
|
|
|
|
RecipH = (1.0 / height);
|
|
}
|
|
|
|
if (particleDescPtr->IsLit && !(particlePtr->ParticleID==PARTICLE_ALIEN_BLOOD && CurrentVisionMode==VISION_MODE_PRED_SEEALIENS) )
|
|
{
|
|
int intensity = LightIntensityAtPoint(&particlePtr->Position);
|
|
|
|
if (particlePtr->ParticleID==PARTICLE_SMOKECLOUD || particlePtr->ParticleID==PARTICLE_ANDROID_BLOOD)
|
|
{
|
|
/* this should be OK. (ColourComponents was RGBA while RGBA_MAKE is BGRA (little endian) */
|
|
r = (particlePtr->Colour >> 0) & 0xFF;
|
|
g = (particlePtr->Colour >> 8) & 0xFF;
|
|
b = (particlePtr->Colour >> 16) & 0xFF;
|
|
a = (particlePtr->Colour >> 24) & 0xFF;
|
|
} else {
|
|
r = MUL_FIXED(intensity,particleDescPtr->RedScale[CurrentVisionMode]);
|
|
g = MUL_FIXED(intensity,particleDescPtr->GreenScale[CurrentVisionMode]);
|
|
b = MUL_FIXED(intensity,particleDescPtr->BlueScale[CurrentVisionMode]);
|
|
a = particleDescPtr->Alpha;
|
|
}
|
|
} else {
|
|
b = (particlePtr->Colour >> 0) & 0xFF;
|
|
g = (particlePtr->Colour >> 8) & 0xFF;
|
|
r = (particlePtr->Colour >> 16) & 0xFF;
|
|
a = (particlePtr->Colour >> 24) & 0xFF;
|
|
}
|
|
if (RAINBOWBLOOD_CHEATMODE) {
|
|
r = FastRandom()&255;
|
|
g = FastRandom()&255;
|
|
b = FastRandom()&255;
|
|
a = particleDescPtr->Alpha;
|
|
}
|
|
|
|
CheckTriangleBuffer(RenderPolygon.NumberOfVertices, 0, 0, 0, TextureHandle, particleDescPtr->TranslucencyType, -1);
|
|
|
|
for (i = 0; i < RenderPolygon.NumberOfVertices; i++) {
|
|
RENDERVERTEX *vertices = &renderVerticesPtr[i];
|
|
|
|
GLfloat x, y, z;
|
|
GLfloat s, t;
|
|
GLfloat rhw = 1/(float)vertices->Z;
|
|
|
|
s = ((float)(vertices->U>>16)+.5) * RecipW;
|
|
t = ((float)(vertices->V>>16)+.5) * RecipH;
|
|
|
|
x = ((float)vertices->X*((float)Global_VDB_Ptr->VDB_ProjX+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreX);
|
|
y = -((float)vertices->Y*((float)Global_VDB_Ptr->VDB_ProjY+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreY);
|
|
|
|
if (particleDescPtr->IsDrawnInFront) {
|
|
z = -0.999f; /* ... */
|
|
} else if (particleDescPtr->IsDrawnAtBack) {
|
|
z = 0.999f;
|
|
} else {
|
|
z = 1.0 - 2.0*ZNear/((float)vertices->Z); /* currently maps [ZNear, inf) to [-1, 1], probably could be more precise with a ZFar */
|
|
}
|
|
|
|
varrp->v[0] = x/rhw;
|
|
varrp->v[1] = y/rhw;
|
|
varrp->v[2] = z/rhw;
|
|
varrp->v[3] = 1/rhw;
|
|
|
|
varrp->t[0] = s;
|
|
varrp->t[1] = t;
|
|
|
|
varrp->c[0] = r;
|
|
varrp->c[1] = g;
|
|
varrp->c[2] = b;
|
|
varrp->c[3] = a;
|
|
|
|
varrp++;
|
|
varrc++;
|
|
}
|
|
}
|
|
|
|
void D3D_PredatorThermalVisionPolygon_Output(POLYHEADER *inputPolyPtr, RENDERVERTEX *renderVerticesPtr)
|
|
{
|
|
float ZNear;
|
|
int i;
|
|
ZNear = (float) (Global_VDB_Ptr->VDB_ClipZ * GlobalScale);
|
|
|
|
CheckTriangleBuffer(RenderPolygon.NumberOfVertices, 0, 0, 0, NULL, TRANSLUCENCY_OFF, -1);
|
|
|
|
for (i = 0; i < RenderPolygon.NumberOfVertices; i++) {
|
|
RENDERVERTEX *vertices = &renderVerticesPtr[i];
|
|
|
|
GLfloat x, y, z;
|
|
float rhw, zvalue;
|
|
|
|
x = ((float)vertices->X*((float)Global_VDB_Ptr->VDB_ProjX+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreX);
|
|
y = -((float)vertices->Y*((float)Global_VDB_Ptr->VDB_ProjY+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreY);
|
|
|
|
zvalue = vertices->Z+HeadUpDisplayZOffset;
|
|
z = 1.0 - 2*ZNear/zvalue;
|
|
|
|
rhw = 1.0/(float)vertices->Z;
|
|
|
|
varrp->v[0] = x/rhw;
|
|
varrp->v[1] = y/rhw;
|
|
varrp->v[2] = z/rhw;
|
|
varrp->v[3] = 1/rhw;
|
|
|
|
varrp->c[0] = vertices->R;
|
|
varrp->c[1] = vertices->G;
|
|
varrp->c[2] = vertices->B;
|
|
varrp->c[3] = vertices->A;
|
|
|
|
varrp++;
|
|
varrc++;
|
|
}
|
|
}
|
|
|
|
void D3D_ZBufferedGouraudPolygon_Output(POLYHEADER *inputPolyPtr, RENDERVERTEX *renderVerticesPtr)
|
|
{
|
|
int flags, i;
|
|
float ZNear;
|
|
|
|
ZNear = (float) (Global_VDB_Ptr->VDB_ClipZ * GlobalScale);
|
|
|
|
flags = inputPolyPtr->PolyFlags;
|
|
|
|
CheckTriangleBuffer(RenderPolygon.NumberOfVertices, 0, 0, 0, NULL, RenderPolygon.TranslucencyMode, -1);
|
|
|
|
for (i = 0; i < RenderPolygon.NumberOfVertices; i++) {
|
|
RENDERVERTEX *vertices = &renderVerticesPtr[i];
|
|
GLfloat x, y, z;
|
|
float rhw, zvalue;
|
|
|
|
zvalue = vertices->Z+HeadUpDisplayZOffset;
|
|
z = 1.0 - 2*ZNear/zvalue;
|
|
|
|
rhw = 1.0/(float)vertices->Z;
|
|
|
|
x = ((float)vertices->X*((float)Global_VDB_Ptr->VDB_ProjX+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreX);
|
|
y = -((float)vertices->Y*((float)Global_VDB_Ptr->VDB_ProjY+1.0f))/((float)vertices->Z*(float)ScreenDescriptorBlock.SDB_CentreY);
|
|
|
|
varrp->v[0] = x/rhw;
|
|
varrp->v[1] = y/rhw;
|
|
varrp->v[2] = z/rhw;
|
|
varrp->v[3] = 1/rhw;
|
|
|
|
varrp->c[0] = vertices->R;
|
|
varrp->c[1] = vertices->G;
|
|
varrp->c[2] = vertices->B;
|
|
if (flags & iflag_transparent)
|
|
varrp->c[3] = vertices->A;
|
|
else
|
|
varrp->c[3] = 255;
|
|
|
|
varrp++;
|
|
varrc++;
|
|
}
|
|
}
|
|
|
|
void D3D_PlayerOnFireOverlay()
|
|
{
|
|
int c = 128;
|
|
int colour = (FMVParticleColour&0xffffff)+(c<<24);
|
|
GLfloat x[4], y[4], s[4], t[4];
|
|
float u, v;
|
|
int r, g, b, a;
|
|
D3DTexture *TextureHandle;
|
|
|
|
b = (colour >> 0) & 0xFF;
|
|
g = (colour >> 8) & 0xFF;
|
|
r = (colour >> 16) & 0xFF;
|
|
a = (colour >> 24) & 0xFF;
|
|
|
|
TextureHandle = ImageHeaderArray[BurningImageNumber].D3DTexture;
|
|
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_GLOWING);
|
|
CheckBoundTextureIsCorrect(TextureHandle);
|
|
CheckFilteringModeIsCorrect(FILTERING_BILINEAR_ON);
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
u = (FastRandom()&255)/256.0f;
|
|
v = (FastRandom()&255)/256.0f;
|
|
|
|
x[0] = -1.0f;
|
|
y[0] = -1.0f;
|
|
s[0] = u;
|
|
t[0] = v;
|
|
x[1] = 1.0f;
|
|
y[1] = -1.0f;
|
|
s[1] = u + 1.0f;
|
|
t[1] = v;
|
|
x[2] = 1.0f;
|
|
y[2] = 1.0f;
|
|
s[2] = u + 1.0f;
|
|
t[2] = v + 1.0f;
|
|
x[3] = -1.0f;
|
|
y[3] = 1.0f;
|
|
s[3] = u;
|
|
t[3] = v + 1.0f;
|
|
|
|
SelectPolygonBeginType(3); /* triangles */
|
|
|
|
glTexCoord2f(s[0], t[0]);
|
|
glVertex3f(x[0], y[0], -1.0f);
|
|
glTexCoord2f(s[1], t[1]);
|
|
glVertex3f(x[1], y[1], -1.0f);
|
|
glTexCoord2f(s[3], t[3]);
|
|
glVertex3f(x[3], y[3], -1.0f);
|
|
|
|
glTexCoord2f(s[1], t[1]);
|
|
glVertex3f(x[1], y[1], -1.0f);
|
|
glTexCoord2f(s[2], t[2]);
|
|
glVertex3f(x[2], y[2], -1.0f);
|
|
glTexCoord2f(s[3], t[3]);
|
|
glVertex3f(x[3], y[3], -1.0f);
|
|
|
|
glEnd();
|
|
}
|
|
|
|
void D3D_PlayerDamagedOverlay(int intensity)
|
|
{
|
|
D3DTexture *TextureHandle;
|
|
int theta[2];
|
|
int colour, baseColour;
|
|
int r, g, b, a;
|
|
int i;
|
|
|
|
theta[0] = (CloakingPhase/8)&4095;
|
|
theta[1] = (800-CloakingPhase/8)&4095;
|
|
|
|
TextureHandle = ImageHeaderArray[SpecialFXImageNumber].D3DTexture;
|
|
switch(AvP.PlayerType) {
|
|
default:
|
|
// LOCALASSERT(0);
|
|
case I_Marine:
|
|
baseColour = 0xff0000;
|
|
break;
|
|
case I_Alien:
|
|
baseColour = 0xffff00;
|
|
break;
|
|
case I_Predator:
|
|
baseColour = 0x00ff00;
|
|
break;
|
|
}
|
|
|
|
CheckBoundTextureIsCorrect(TextureHandle);
|
|
CheckFilteringModeIsCorrect(FILTERING_BILINEAR_ON);
|
|
|
|
colour = 0xffffff - baseColour + (intensity<<24);
|
|
|
|
b = (colour >> 0) & 0xFF;
|
|
g = (colour >> 8) & 0xFF;
|
|
r = (colour >> 16) & 0xFF;
|
|
a = (colour >> 24) & 0xFF;
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_INVCOLOUR);
|
|
for (i = 0; i < 2; i++) {
|
|
GLfloat x[4], y[4], s[4], t[4];
|
|
|
|
float sin = (GetSin(theta[i]))/65536.0f/16.0f;
|
|
float cos = (GetCos(theta[i]))/65536.0f/16.0f;
|
|
|
|
x[0] = -1.0f;
|
|
y[0] = -1.0f;
|
|
s[0] = 0.875f + (cos*(-1) - sin*(-1));
|
|
t[0] = 0.375f + (sin*(-1) + cos*(-1));
|
|
x[1] = 1.0f;
|
|
y[1] = -1.0f;
|
|
s[1] = 0.875f + (cos*(+1) - sin*(-1));
|
|
t[1] = 0.375f + (sin*(+1) + cos*(-1));
|
|
x[2] = 1.0f;
|
|
y[2] = 1.0f;
|
|
s[2] = 0.875f + (cos*(+1) - sin*(+1));
|
|
t[2] = 0.375f + (sin*(+1) + cos*(+1));
|
|
x[3] = -1.0f;
|
|
y[3] = 1.0f;
|
|
s[3] = 0.875f + (cos*(-1) - sin*(+1));
|
|
t[3] = 0.375f + (sin*(-1) + cos*(+1));
|
|
|
|
SelectPolygonBeginType(3); /* triangles */
|
|
|
|
glTexCoord2f(s[0], t[0]);
|
|
glVertex3f(x[0], y[0], -1.0f);
|
|
glTexCoord2f(s[1], t[1]);
|
|
glVertex3f(x[1], y[1], -1.0f);
|
|
glTexCoord2f(s[3], t[3]);
|
|
glVertex3f(x[3], y[3], -1.0f);
|
|
|
|
glTexCoord2f(s[1], t[1]);
|
|
glVertex3f(x[1], y[1], -1.0f);
|
|
glTexCoord2f(s[2], t[2]);
|
|
glVertex3f(x[2], y[2], -1.0f);
|
|
glTexCoord2f(s[3], t[3]);
|
|
glVertex3f(x[3], y[3], -1.0f);
|
|
|
|
glEnd();
|
|
|
|
colour = baseColour + (intensity<<24);
|
|
|
|
b = (colour >> 0) & 0xFF;
|
|
g = (colour >> 8) & 0xFF;
|
|
r = (colour >> 16) & 0xFF;
|
|
a = (colour >> 24) & 0xFF;
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_GLOWING);
|
|
}
|
|
}
|
|
|
|
void DrawNoiseOverlay(int tr)
|
|
{
|
|
GLfloat x[4], y[4], s[4], t[4], u, v;
|
|
int r, g, b;
|
|
D3DTexture *tex;
|
|
int size;
|
|
|
|
r = 255;
|
|
g = 255;
|
|
b = 255;
|
|
|
|
size = 256;
|
|
|
|
tex = ImageHeaderArray[StaticImageNumber].D3DTexture;
|
|
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_GLOWING);
|
|
CheckBoundTextureIsCorrect(tex);
|
|
CheckFilteringModeIsCorrect(FILTERING_BILINEAR_ON);
|
|
glDepthFunc(GL_ALWAYS);
|
|
|
|
u = FastRandom()&255;
|
|
v = FastRandom()&255;
|
|
|
|
x[0] = -1.0f;
|
|
y[0] = -1.0f;
|
|
s[0] = u / 256.0f;
|
|
t[0] = v / 256.0f;
|
|
x[1] = 1.0f;
|
|
y[1] = -1.0f;
|
|
s[1] = (u + size) / 256.0f;
|
|
t[1] = v / 256.0f;
|
|
x[2] = 1.0f;
|
|
y[2] = 1.0f;
|
|
s[2] = (u + size) / 256.0f;
|
|
t[2] = (v + size) / 256.0f;
|
|
x[3] = -1.0f;
|
|
y[3] = 1.0f;
|
|
s[3] = u / 256.0f;
|
|
t[3] = (v + size) / 256.0f;
|
|
|
|
SelectPolygonBeginType(3); /* triangles */
|
|
glColor4ub(r, g, b, tr);
|
|
|
|
glTexCoord2f(s[0], t[0]);
|
|
glVertex3f(x[0], y[0], 1.0f);
|
|
glTexCoord2f(s[1], t[1]);
|
|
glVertex3f(x[1], y[1], 1.0f);
|
|
glTexCoord2f(s[3], t[3]);
|
|
glVertex3f(x[3], y[3], 1.0f);
|
|
|
|
glTexCoord2f(s[1], t[1]);
|
|
glVertex3f(x[1], y[1], 1.0f);
|
|
glTexCoord2f(s[2], t[2]);
|
|
glVertex3f(x[2], y[2], 1.0f);
|
|
glTexCoord2f(s[3], t[3]);
|
|
glVertex3f(x[3], y[3], 1.0f);
|
|
|
|
glEnd();
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
|
}
|
|
|
|
void D3D_ScreenInversionOverlay()
|
|
{
|
|
D3DTexture *tex;
|
|
int theta[2];
|
|
int i;
|
|
|
|
theta[0] = (CloakingPhase/8)&4095;
|
|
theta[1] = (800-CloakingPhase/8)&4095;
|
|
|
|
tex = ImageHeaderArray[SpecialFXImageNumber].D3DTexture;
|
|
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_DARKENINGCOLOUR);
|
|
CheckBoundTextureIsCorrect(tex);
|
|
CheckFilteringModeIsCorrect(FILTERING_BILINEAR_ON);
|
|
|
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
GLfloat x[4], y[4], s[4], t[4];
|
|
|
|
float sin = (GetSin(theta[i]))/65536.0f/16.0f;
|
|
float cos = (GetCos(theta[i]))/65536.0f/16.0f;
|
|
|
|
x[0] = -1.0f;
|
|
y[0] = -1.0f;
|
|
s[0] = 0.375f + (cos*(-1) - sin*(-1));
|
|
t[0] = 0.375f + (sin*(-1) + cos*(-1));
|
|
x[1] = 1.0f;
|
|
y[1] = -1.0f;
|
|
s[1] = 0.375f + (cos*(+1) - sin*(-1));
|
|
t[1] = 0.375f + (sin*(+1) + cos*(-1));
|
|
x[2] = 1.0f;
|
|
y[2] = 1.0f;
|
|
s[2] = 0.375f + (cos*(+1) - sin*(+1));
|
|
t[2] = 0.375f + (sin*(+1) + cos*(+1));
|
|
x[3] = -1.0f;
|
|
y[3] = 1.0f;
|
|
s[3] = 0.375f + (cos*(-1) - sin*(+1));
|
|
t[3] = 0.375f + (sin*(-1) + cos*(+1));
|
|
|
|
SelectPolygonBeginType(3); /* triangles */
|
|
|
|
glTexCoord2f(s[0], t[0]);
|
|
glVertex3f(x[0], y[0], 1.0f);
|
|
glTexCoord2f(s[1], t[1]);
|
|
glVertex3f(x[1], y[1], 1.0f);
|
|
glTexCoord2f(s[3], t[3]);
|
|
glVertex3f(x[3], y[3], 1.0f);
|
|
|
|
glTexCoord2f(s[1], t[1]);
|
|
glVertex3f(x[1], y[1], 1.0f);
|
|
glTexCoord2f(s[2], t[2]);
|
|
glVertex3f(x[2], y[2], 1.0f);
|
|
glTexCoord2f(s[3], t[3]);
|
|
glVertex3f(x[3], y[3], 1.0f);
|
|
|
|
glEnd();
|
|
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_COLOUR);
|
|
}
|
|
}
|
|
|
|
void D3D_PredatorScreenInversionOverlay()
|
|
{
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_DARKENINGCOLOUR);
|
|
CheckBoundTextureIsCorrect(NULL);
|
|
glDepthFunc(GL_ALWAYS);
|
|
|
|
SelectPolygonBeginType(3); /* triangles */
|
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
glVertex3f(-1.0f, -1.0f, 1.0f);
|
|
glVertex3f( 1.0f, -1.0f, 1.0f);
|
|
glVertex3f(-1.0f, 1.0f, 1.0f);
|
|
|
|
glVertex3f( 1.0f, -1.0f, 1.0f);
|
|
glVertex3f( 1.0f, 1.0f, 1.0f);
|
|
glVertex3f(-1.0f, 1.0f, 1.0f);
|
|
|
|
glEnd();
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
|
}
|
|
|
|
void DrawScanlinesOverlay(float level)
|
|
{
|
|
D3DTexture *tex;
|
|
GLfloat x[4], y[4], s[4], t[4];
|
|
float v, size;
|
|
int c;
|
|
int a;
|
|
|
|
tex = ImageHeaderArray[PredatorNumbersImageNumber].D3DTexture;
|
|
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_NORMAL);
|
|
CheckBoundTextureIsCorrect(tex);
|
|
CheckFilteringModeIsCorrect(FILTERING_BILINEAR_ON);
|
|
glDepthFunc(GL_ALWAYS);
|
|
|
|
c = 255;
|
|
a = 64.0f+level*64.0f;
|
|
|
|
v = 128.0f;
|
|
size = 128.0f*(1.0f-level*0.8f);
|
|
|
|
glColor4ub(c, c, c, a);
|
|
|
|
x[0] = -1.0f;
|
|
y[0] = -1.0f;
|
|
s[0] = (v - size) / 256.0f;
|
|
t[0] = 1.0f;
|
|
x[1] = 1.0f;
|
|
y[1] = -1.0f;
|
|
s[1] = (v - size) / 256.0f;
|
|
t[1] = 1.0f;
|
|
x[2] = 1.0f;
|
|
y[2] = 1.0f;
|
|
s[2] = (v + size) / 256.0f;
|
|
t[2] = 1.0f;
|
|
x[3] = -1.0f;
|
|
y[3] = 1.0f;
|
|
s[3] = (v + size) / 256.0f;
|
|
t[3] = 1.0f;
|
|
|
|
SelectPolygonBeginType(3); /* triangles */
|
|
|
|
glTexCoord2f(s[0], t[0]);
|
|
glVertex3f(x[0], y[0], 1.0f);
|
|
glTexCoord2f(s[1], t[1]);
|
|
glVertex3f(x[1], y[1], 1.0f);
|
|
glTexCoord2f(s[3], t[3]);
|
|
glVertex3f(x[3], y[3], 1.0f);
|
|
|
|
glTexCoord2f(s[1], t[1]);
|
|
glVertex3f(x[1], y[1], 1.0f);
|
|
glTexCoord2f(s[2], t[2]);
|
|
glVertex3f(x[2], y[2], 1.0f);
|
|
glTexCoord2f(s[3], t[3]);
|
|
glVertex3f(x[3], y[3], 1.0f);
|
|
|
|
glEnd();
|
|
glDepthFunc(GL_LEQUAL);
|
|
}
|
|
|
|
void D3D_FadeDownScreen(int brightness, int colour)
|
|
{
|
|
int t, r, g, b, a;
|
|
GLfloat x[4], y[4];
|
|
|
|
t = 255 - (brightness>>8);
|
|
if (t<0) t = 0;
|
|
colour = (t<<24)+colour;
|
|
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_NORMAL);
|
|
CheckBoundTextureIsCorrect(NULL);
|
|
|
|
b = (colour >> 0) & 0xFF;
|
|
g = (colour >> 8) & 0xFF;
|
|
r = (colour >> 16) & 0xFF;
|
|
a = (colour >> 24) & 0xFF;
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
x[0] = -1.0f;
|
|
y[0] = -1.0f;
|
|
x[1] = 1.0f;
|
|
y[1] = -1.0f;
|
|
x[2] = 1.0f;
|
|
y[2] = 1.0f;
|
|
x[3] = -1.0f;
|
|
y[3] = 1.0f;
|
|
|
|
SelectPolygonBeginType(3); /* triangles */
|
|
|
|
glVertex3f(x[0], y[0], -1.0f);
|
|
glVertex3f(x[1], y[1], -1.0f);
|
|
glVertex3f(x[3], y[3], -1.0f);
|
|
|
|
glVertex3f(x[1], y[1], -1.0f);
|
|
glVertex3f(x[2], y[2], -1.0f);
|
|
glVertex3f(x[3], y[3], -1.0f);
|
|
|
|
glEnd();
|
|
}
|
|
|
|
void D3D_HUD_Setup()
|
|
{
|
|
FlushTriangleBuffers(1);
|
|
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_GLOWING);
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
|
}
|
|
|
|
void D3D_HUDQuad_Output(int imageNumber, struct VertexTag *quadVerticesPtr, unsigned int colour)
|
|
{
|
|
float RecipW, RecipH;
|
|
int i;
|
|
D3DTexture *tex = ImageHeaderArray[imageNumber].D3DTexture;
|
|
GLfloat x[4], y[4], s[4], t[4];
|
|
int r, g, b, a;
|
|
|
|
/* possibly use polygon offset? (predator hud) */
|
|
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_GLOWING);
|
|
CheckBoundTextureIsCorrect(tex);
|
|
|
|
if (tex->w == 128) {
|
|
RecipW = 1.0f / 128.0f;
|
|
} else {
|
|
float width = (float) tex->w;
|
|
RecipW = 1.0f / width;
|
|
}
|
|
|
|
if (tex->h == 128) {
|
|
RecipH = 1.0f / 128.0f;
|
|
} else {
|
|
float height = (float) tex->h;
|
|
RecipH = 1.0f / height;
|
|
}
|
|
|
|
b = (colour >> 0) & 0xFF;
|
|
g = (colour >> 8) & 0xFF;
|
|
r = (colour >> 16) & 0xFF;
|
|
a = (colour >> 24) & 0xFF;
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
x[i] = quadVerticesPtr[i].X;
|
|
x[i] = (x[i] - ScreenDescriptorBlock.SDB_CentreX)/ScreenDescriptorBlock.SDB_CentreX;
|
|
y[i] = quadVerticesPtr[i].Y;
|
|
y[i] = -(y[i] - ScreenDescriptorBlock.SDB_CentreY)/ScreenDescriptorBlock.SDB_CentreY;
|
|
|
|
s[i] = ((float)quadVerticesPtr[i].U)*RecipW;
|
|
t[i] = ((float)quadVerticesPtr[i].V)*RecipH;
|
|
}
|
|
|
|
SelectPolygonBeginType(3); /* triangles */
|
|
|
|
glTexCoord2f(s[0], t[0]);
|
|
glVertex3f(x[0], y[0], -1.0f);
|
|
glTexCoord2f(s[1], t[1]);
|
|
glVertex3f(x[1], y[1], -1.0f);
|
|
glTexCoord2f(s[3], t[3]);
|
|
glVertex3f(x[3], y[3], -1.0f);
|
|
|
|
glTexCoord2f(s[1], t[1]);
|
|
glVertex3f(x[1], y[1], -1.0f);
|
|
glTexCoord2f(s[2], t[2]);
|
|
glVertex3f(x[2], y[2], -1.0f);
|
|
glTexCoord2f(s[3], t[3]);
|
|
glVertex3f(x[3], y[3], -1.0f);
|
|
|
|
glEnd();
|
|
}
|
|
|
|
void D3D_RenderHUDNumber_Centred(unsigned int number,int x,int y,int colour)
|
|
{
|
|
struct VertexTag quadVertices[4];
|
|
int noOfDigits=3;
|
|
int h = MUL_FIXED(HUDScaleFactor,HUD_DIGITAL_NUMBERS_HEIGHT);
|
|
int w = MUL_FIXED(HUDScaleFactor,HUD_DIGITAL_NUMBERS_WIDTH);
|
|
|
|
quadVertices[0].Y = y;
|
|
quadVertices[1].Y = y;
|
|
quadVertices[2].Y = y + h;
|
|
quadVertices[3].Y = y + h;
|
|
|
|
x += (3*w)/2;
|
|
|
|
CheckFilteringModeIsCorrect(FILTERING_BILINEAR_OFF);
|
|
|
|
do {
|
|
int topLeftU, topLeftV;
|
|
|
|
int digit = number%10;
|
|
number/=10;
|
|
|
|
if (digit<8) {
|
|
topLeftU = 1+(digit)*16;
|
|
topLeftV = 1;
|
|
} else {
|
|
topLeftU = 1+(digit-8)*16;
|
|
topLeftV = 1+24;
|
|
}
|
|
if (AvP.PlayerType == I_Marine) topLeftV+=80;
|
|
|
|
quadVertices[0].U = topLeftU;
|
|
quadVertices[0].V = topLeftV;
|
|
quadVertices[1].U = topLeftU + HUD_DIGITAL_NUMBERS_WIDTH;
|
|
quadVertices[1].V = topLeftV;
|
|
quadVertices[2].U = topLeftU + HUD_DIGITAL_NUMBERS_WIDTH;
|
|
quadVertices[2].V = topLeftV + HUD_DIGITAL_NUMBERS_HEIGHT;
|
|
quadVertices[3].U = topLeftU;
|
|
quadVertices[3].V = topLeftV + HUD_DIGITAL_NUMBERS_HEIGHT;
|
|
|
|
x -= 1+w;
|
|
quadVertices[0].X = x;
|
|
quadVertices[3].X = x;
|
|
quadVertices[1].X = x + w;
|
|
quadVertices[2].X = x + w;
|
|
|
|
D3D_HUDQuad_Output(HUDFontsImageNumber, quadVertices, colour);
|
|
|
|
} while (--noOfDigits);
|
|
}
|
|
|
|
void D3D_RenderHUDString(char *stringPtr,int x,int y,int colour)
|
|
{
|
|
struct VertexTag quadVertices[4];
|
|
|
|
if (stringPtr == NULL) return;
|
|
|
|
quadVertices[0].Y = y-1;
|
|
quadVertices[1].Y = y-1;
|
|
quadVertices[2].Y = y + HUD_FONT_HEIGHT + 1;
|
|
quadVertices[3].Y = y + HUD_FONT_HEIGHT + 1;
|
|
|
|
CheckFilteringModeIsCorrect(FILTERING_BILINEAR_OFF);
|
|
|
|
while( *stringPtr )
|
|
{
|
|
char c = *stringPtr++;
|
|
|
|
{
|
|
int topLeftU = 1+((c-32)&15)*16;
|
|
int topLeftV = 1+((c-32)>>4)*16;
|
|
|
|
quadVertices[0].U = topLeftU - 1;
|
|
quadVertices[0].V = topLeftV - 1;
|
|
quadVertices[1].U = topLeftU + HUD_FONT_WIDTH + 1;
|
|
quadVertices[1].V = topLeftV - 1;
|
|
quadVertices[2].U = topLeftU + HUD_FONT_WIDTH + 1;
|
|
quadVertices[2].V = topLeftV + HUD_FONT_HEIGHT + 1;
|
|
quadVertices[3].U = topLeftU - 1;
|
|
quadVertices[3].V = topLeftV + HUD_FONT_HEIGHT + 1;
|
|
|
|
quadVertices[0].X = x - 1;
|
|
quadVertices[3].X = x - 1;
|
|
quadVertices[1].X = x + HUD_FONT_WIDTH + 1;
|
|
quadVertices[2].X = x + HUD_FONT_WIDTH + 1;
|
|
|
|
D3D_HUDQuad_Output
|
|
(
|
|
AAFontImageNumber,
|
|
quadVertices,
|
|
colour
|
|
);
|
|
}
|
|
x += AAFontWidths[(int)c];
|
|
}
|
|
}
|
|
|
|
void D3D_RenderHUDString_Clipped(char *stringPtr,int x,int y,int colour)
|
|
{
|
|
struct VertexTag quadVertices[4];
|
|
|
|
// LOCALASSERT(y<=0);
|
|
if (stringPtr == NULL) return;
|
|
|
|
CheckFilteringModeIsCorrect(FILTERING_BILINEAR_OFF);
|
|
|
|
quadVertices[2].Y = y + HUD_FONT_HEIGHT + 1;
|
|
quadVertices[3].Y = y + HUD_FONT_HEIGHT + 1;
|
|
|
|
quadVertices[0].Y = 0;
|
|
quadVertices[1].Y = 0;
|
|
|
|
while ( *stringPtr )
|
|
{
|
|
char c = *stringPtr++;
|
|
|
|
{
|
|
int topLeftU = 1+((c-32)&15)*16;
|
|
int topLeftV = 1+((c-32)>>4)*16;
|
|
|
|
quadVertices[0].U = topLeftU - 1;
|
|
quadVertices[0].V = topLeftV - y;
|
|
quadVertices[1].U = topLeftU + HUD_FONT_WIDTH+1;
|
|
quadVertices[1].V = topLeftV - y;
|
|
quadVertices[2].U = topLeftU + HUD_FONT_WIDTH+1;
|
|
quadVertices[2].V = topLeftV + HUD_FONT_HEIGHT+1;
|
|
quadVertices[3].U = topLeftU - 1;
|
|
quadVertices[3].V = topLeftV + HUD_FONT_HEIGHT+1;
|
|
|
|
quadVertices[0].X = x - 1;
|
|
quadVertices[3].X = x - 1;
|
|
quadVertices[1].X = x + HUD_FONT_WIDTH + 1;
|
|
quadVertices[2].X = x + HUD_FONT_WIDTH + 1;
|
|
|
|
D3D_HUDQuad_Output
|
|
(
|
|
AAFontImageNumber,
|
|
quadVertices,
|
|
colour
|
|
);
|
|
}
|
|
x += AAFontWidths[(int)c];
|
|
}
|
|
}
|
|
|
|
void D3D_RenderHUDString_Centred(char *stringPtr, int centreX, int y, int colour)
|
|
{
|
|
int x, length = 0;
|
|
char *ptr = stringPtr;
|
|
struct VertexTag quadVertices[4];
|
|
|
|
if (stringPtr == NULL) return;
|
|
|
|
while(*ptr)
|
|
{
|
|
length+=AAFontWidths[(int)*ptr++];
|
|
}
|
|
length = MUL_FIXED(HUDScaleFactor,length);
|
|
|
|
x = centreX-length/2;
|
|
|
|
quadVertices[0].Y = y-MUL_FIXED(HUDScaleFactor,1);
|
|
quadVertices[1].Y = y-MUL_FIXED(HUDScaleFactor,1);
|
|
quadVertices[2].Y = y + MUL_FIXED(HUDScaleFactor,HUD_FONT_HEIGHT + 1);
|
|
quadVertices[3].Y = y + MUL_FIXED(HUDScaleFactor,HUD_FONT_HEIGHT + 1);
|
|
|
|
CheckFilteringModeIsCorrect(FILTERING_BILINEAR_OFF);
|
|
|
|
while( *stringPtr )
|
|
{
|
|
char c = *stringPtr++;
|
|
|
|
{
|
|
int topLeftU = 1+((c-32)&15)*16;
|
|
int topLeftV = 1+((c-32)>>4)*16;
|
|
|
|
quadVertices[0].U = topLeftU - 1;
|
|
quadVertices[0].V = topLeftV - 1;
|
|
quadVertices[1].U = topLeftU + HUD_FONT_WIDTH + 1;
|
|
quadVertices[1].V = topLeftV - 1;
|
|
quadVertices[2].U = topLeftU + HUD_FONT_WIDTH + 1;
|
|
quadVertices[2].V = topLeftV + HUD_FONT_HEIGHT + 1;
|
|
quadVertices[3].U = topLeftU - 1;
|
|
quadVertices[3].V = topLeftV + HUD_FONT_HEIGHT + 1;
|
|
|
|
quadVertices[0].X = x - MUL_FIXED(HUDScaleFactor,1);
|
|
quadVertices[3].X = x - MUL_FIXED(HUDScaleFactor,1);
|
|
quadVertices[1].X = x + MUL_FIXED(HUDScaleFactor,HUD_FONT_WIDTH + 1);
|
|
quadVertices[2].X = x + MUL_FIXED(HUDScaleFactor,HUD_FONT_WIDTH + 1);
|
|
|
|
D3D_HUDQuad_Output
|
|
(
|
|
AAFontImageNumber,
|
|
quadVertices,
|
|
colour
|
|
);
|
|
}
|
|
x += MUL_FIXED(HUDScaleFactor,AAFontWidths[(int)c]);
|
|
}
|
|
}
|
|
|
|
void RenderString(char *stringPtr, int x, int y, int colour)
|
|
{
|
|
if (stringPtr == NULL) return;
|
|
|
|
D3D_RenderHUDString(stringPtr,x,y,colour);
|
|
}
|
|
|
|
void RenderStringCentred(char *stringPtr, int centreX, int y, int colour)
|
|
{
|
|
int length = 0;
|
|
char *ptr = stringPtr;
|
|
|
|
if (stringPtr == NULL) return;
|
|
|
|
while(*ptr)
|
|
{
|
|
length+=AAFontWidths[(int)*ptr++];
|
|
}
|
|
D3D_RenderHUDString(stringPtr,centreX-length/2,y,colour);
|
|
}
|
|
|
|
void RenderStringVertically(char *stringPtr, int centreX, int bottomY, int colour)
|
|
{
|
|
struct VertexTag quadVertices[4];
|
|
int y = bottomY;
|
|
|
|
if (stringPtr == NULL) return;
|
|
|
|
quadVertices[0].X = centreX - (HUD_FONT_HEIGHT/2) - 1;
|
|
quadVertices[1].X = quadVertices[0].X;
|
|
quadVertices[2].X = quadVertices[0].X+2+HUD_FONT_HEIGHT*1;
|
|
quadVertices[3].X = quadVertices[2].X;
|
|
|
|
CheckFilteringModeIsCorrect(FILTERING_BILINEAR_OFF);
|
|
while( *stringPtr )
|
|
{
|
|
char c = *stringPtr++;
|
|
|
|
{
|
|
int topLeftU = 1+((c-32)&15)*16;
|
|
int topLeftV = 1+((c-32)>>4)*16;
|
|
|
|
quadVertices[0].U = topLeftU - 1;
|
|
quadVertices[0].V = topLeftV - 1;
|
|
quadVertices[1].U = topLeftU + HUD_FONT_WIDTH;
|
|
quadVertices[1].V = topLeftV - 1;
|
|
quadVertices[2].U = topLeftU + HUD_FONT_WIDTH;
|
|
quadVertices[2].V = topLeftV + HUD_FONT_HEIGHT + 1;
|
|
quadVertices[3].U = topLeftU - 1;
|
|
quadVertices[3].V = topLeftV + HUD_FONT_HEIGHT + 1;
|
|
|
|
quadVertices[0].Y = y ;
|
|
quadVertices[1].Y = y - HUD_FONT_WIDTH*1 -1;
|
|
quadVertices[2].Y = y - HUD_FONT_WIDTH*1 -1;
|
|
quadVertices[3].Y = y ;
|
|
|
|
D3D_HUDQuad_Output
|
|
(
|
|
AAFontImageNumber,
|
|
quadVertices,
|
|
colour
|
|
);
|
|
}
|
|
y -= AAFontWidths[(int)c];
|
|
}
|
|
}
|
|
|
|
void ColourFillBackBuffer(int FillColour)
|
|
{
|
|
float r, g, b, a;
|
|
|
|
b = ((FillColour >> 0) & 0xFF) / 255.0f;
|
|
g = ((FillColour >> 8) & 0xFF) / 255.0f;
|
|
r = ((FillColour >> 16) & 0xFF) / 255.0f;
|
|
a = ((FillColour >> 24) & 0xFF) / 255.0f;
|
|
|
|
glClearColor(r, g, b, a);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
}
|
|
|
|
void D3D_DrawBackdrop()
|
|
{
|
|
extern int NumActiveBlocks;
|
|
extern DISPLAYBLOCK *ActiveBlockList[];
|
|
extern MODULE *playerPherModule;
|
|
|
|
PLAYER_STATUS *playerStatusPtr;
|
|
int numOfObjects = NumActiveBlocks;
|
|
int needToDrawBackdrop = 0;
|
|
|
|
if (TRIPTASTIC_CHEATMODE||MOTIONBLUR_CHEATMODE)
|
|
return;
|
|
|
|
if (ShowDebuggingText.Tears) {
|
|
ColourFillBackBuffer((63<<5));
|
|
return;
|
|
}
|
|
|
|
while(numOfObjects--) {
|
|
DISPLAYBLOCK *objectPtr = ActiveBlockList[numOfObjects];
|
|
MODULE *modulePtr = objectPtr->ObMyModule;
|
|
|
|
if (modulePtr && (ModuleCurrVisArray[modulePtr->m_index] == 2) && modulePtr->m_flags&MODULEFLAG_SKY) {
|
|
needToDrawBackdrop = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (needToDrawBackdrop) {
|
|
extern BOOL LevelHasStars;
|
|
extern void RenderSky(void);
|
|
extern void RenderStarfield(void);
|
|
|
|
ColourFillBackBuffer(0);
|
|
|
|
if (LevelHasStars) {
|
|
RenderStarfield();
|
|
} else {
|
|
RenderSky();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (!playerPherModule) {
|
|
ColourFillBackBuffer(0);
|
|
return;
|
|
}
|
|
|
|
playerStatusPtr = (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
|
|
|
|
if (!playerStatusPtr->IsAlive || FREEFALL_CHEATMODE) {
|
|
ColourFillBackBuffer(0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* ** */
|
|
|
|
/* Hacked in special effects */
|
|
|
|
extern int sine[];
|
|
extern int cosine[];
|
|
extern int NormalFrameTime;
|
|
|
|
void UpdateForceField(void);
|
|
void D3D_DrawForceField(int xOrigin, int yOrigin, int zOrigin, int fieldType);
|
|
|
|
void UpdateWaterFall(void);
|
|
void D3D_DrawWaterFall(int xOrigin, int yOrigin, int zOrigin);
|
|
void D3D_DrawPowerFence(int xOrigin, int yOrigin, int zOrigin, int xScale, int yScale, int zScale);
|
|
void D3D_DrawExplosion(int xOrigin, int yOrigin, int zOrigin, int size);
|
|
|
|
void D3D_DrawWaterPatch(int xOrigin, int yOrigin, int zOrigin);
|
|
|
|
void D3D_DrawWaterOctagonPatch(int xOrigin, int yOrigin, int zOrigin, int xOffset, int zOffset);
|
|
|
|
int LightSourceWaterPoint(VECTORCH *pointPtr,int offset);
|
|
void D3D_DrawWaterMesh_Unclipped(void);
|
|
void D3D_DrawWaterMesh_Clipped(void);
|
|
|
|
|
|
void D3D_DrawMoltenMetal(int xOrigin, int yOrigin, int zOrigin);
|
|
void D3D_DrawMoltenMetalMesh_Unclipped(void);
|
|
void D3D_DrawMoltenMetalMesh_Clipped(void);
|
|
|
|
int MeshXScale;
|
|
int MeshZScale;
|
|
int WaterFallBase;
|
|
|
|
int WaterXOrigin;
|
|
int WaterZOrigin;
|
|
float WaterUScale;
|
|
float WaterVScale;
|
|
|
|
void D3D_DrawParticle_Rain(PARTICLE *particlePtr,VECTORCH *prevPositionPtr)
|
|
{
|
|
VECTORCH vertices[3];
|
|
float ZNear;
|
|
int i;
|
|
|
|
vertices[0] = *prevPositionPtr;
|
|
|
|
/* translate second vertex into view space */
|
|
TranslatePointIntoViewspace(&vertices[0]);
|
|
|
|
/* is particle within normal view frustrum ? */
|
|
if((-vertices[0].vx <= vertices[0].vz)
|
|
&&(vertices[0].vx <= vertices[0].vz)
|
|
&&(-vertices[0].vy <= vertices[0].vz)
|
|
&&(vertices[0].vy <= vertices[0].vz))
|
|
{
|
|
|
|
vertices[1] = particlePtr->Position;
|
|
vertices[2] = particlePtr->Position;
|
|
vertices[1].vx += particlePtr->Offset.vx;
|
|
vertices[2].vx -= particlePtr->Offset.vx;
|
|
vertices[1].vz += particlePtr->Offset.vz;
|
|
vertices[2].vz -= particlePtr->Offset.vz;
|
|
|
|
/* translate particle into view space */
|
|
TranslatePointIntoViewspace(&vertices[1]);
|
|
TranslatePointIntoViewspace(&vertices[2]);
|
|
|
|
ZNear = (float) (Global_VDB_Ptr->VDB_ClipZ * GlobalScale);
|
|
|
|
CheckTriangleBuffer(3, 0, 0, 0, NULL, TRANSLUCENCY_NORMAL, -1);
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
GLfloat xf, yf, zf, rhw;
|
|
|
|
xf = ((float)vertices[i].vx*((float)Global_VDB_Ptr->VDB_ProjX+1.0f))/((float)vertices[i].vz*(float)ScreenDescriptorBlock.SDB_CentreX);
|
|
yf = -((float)vertices[i].vy*((float)Global_VDB_Ptr->VDB_ProjY+1.0f))/((float)vertices[i].vz*(float)ScreenDescriptorBlock.SDB_CentreY);
|
|
|
|
zf = 1.0f - 2.0f*ZNear/(float)vertices[i].vz;
|
|
rhw = 1.0f / (float)vertices[i].vz;
|
|
|
|
varrp->v[0] = xf/rhw;
|
|
varrp->v[1] = yf/rhw;
|
|
varrp->v[2] = zf/rhw;
|
|
varrp->v[3] = 1.0f/rhw;
|
|
|
|
if (i == 0) {
|
|
varrp->c[0] = 0;
|
|
varrp->c[1] = 255;
|
|
varrp->c[2] = 255;
|
|
varrp->c[3] = 32;
|
|
} else {
|
|
varrp->c[0] = 255;
|
|
varrp->c[1] = 255;
|
|
varrp->c[2] = 255;
|
|
varrp->c[3] = 32;
|
|
}
|
|
varrp++;
|
|
varrc++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PostLandscapeRendering()
|
|
{
|
|
extern int NumOnScreenBlocks;
|
|
extern DISPLAYBLOCK *OnScreenBlockList[];
|
|
int numOfObjects = NumOnScreenBlocks;
|
|
|
|
extern char LevelName[];
|
|
|
|
if (!strcmp(LevelName,"fall")||!strcmp(LevelName,"fall_m"))
|
|
{
|
|
char drawWaterFall = 0;
|
|
char drawStream = 0;
|
|
char drawStream2 = 0;
|
|
|
|
while(numOfObjects)
|
|
{
|
|
DISPLAYBLOCK *objectPtr = OnScreenBlockList[--numOfObjects];
|
|
MODULE *modulePtr = objectPtr->ObMyModule;
|
|
|
|
/* if it's a module, which isn't inside another module */
|
|
if (modulePtr && modulePtr->name)
|
|
{
|
|
if( (!strcmp(modulePtr->name,"fall01"))
|
|
||(!strcmp(modulePtr->name,"well01"))
|
|
||(!strcmp(modulePtr->name,"well02"))
|
|
||(!strcmp(modulePtr->name,"well03"))
|
|
||(!strcmp(modulePtr->name,"well04"))
|
|
||(!strcmp(modulePtr->name,"well05"))
|
|
||(!strcmp(modulePtr->name,"well06"))
|
|
||(!strcmp(modulePtr->name,"well07"))
|
|
||(!strcmp(modulePtr->name,"well08"))
|
|
||(!strcmp(modulePtr->name,"well")))
|
|
{
|
|
drawWaterFall = 1;
|
|
}
|
|
else if( (!strcmp(modulePtr->name,"stream02"))
|
|
||(!strcmp(modulePtr->name,"stream03"))
|
|
||(!strcmp(modulePtr->name,"watergate")))
|
|
{
|
|
drawStream = 1;
|
|
}
|
|
else if( (!strcmp(modulePtr->name,"openwat03"))
|
|
||(!strcmp(modulePtr->name,"openwat04"))
|
|
||(!strcmp(modulePtr->name,"openwat04A"))
|
|
||(!strcmp(modulePtr->name,"openwat02")))
|
|
{
|
|
drawStream2 = 1;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (drawWaterFall)
|
|
{
|
|
// CurrTextureHandle = NULL;
|
|
// CheckBoundTextureIsCorrect(NULL);
|
|
// CheckTranslucencyModeIsCorrect(TRANSLUCENCY_NORMAL);
|
|
|
|
FlushTriangleBuffers(1);
|
|
glDepthMask(GL_FALSE);
|
|
|
|
WaterFallBase = 109952;
|
|
|
|
MeshZScale = (66572-51026)/15;
|
|
MeshXScale = (109952+3039)/45;
|
|
|
|
D3D_DrawWaterFall(175545,-3039,51026);
|
|
// MeshZScale = -(538490-392169);
|
|
// MeshXScale = 55000;
|
|
// D3D_DrawWaterPatch(-100000, WaterFallBase, 538490);
|
|
|
|
FlushTriangleBuffers(1);
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
if (drawStream)
|
|
{
|
|
int x = 68581;
|
|
int y = 12925; /* probably should lower this a little.. */
|
|
int z = 93696;
|
|
MeshXScale = (87869-68581);
|
|
MeshZScale = (105385-93696);
|
|
{
|
|
extern void CheckForObjectsInWater(int minX, int maxX, int minZ, int maxZ, int averageY);
|
|
CheckForObjectsInWater(x, x+MeshXScale, z, z+MeshZScale, y);
|
|
}
|
|
|
|
WaterXOrigin=x;
|
|
WaterZOrigin=z;
|
|
WaterUScale = 4.0f/(float)MeshXScale;
|
|
WaterVScale = 4.0f/(float)MeshZScale;
|
|
MeshXScale/=4;
|
|
MeshZScale/=2;
|
|
|
|
CurrTextureHandle = ImageHeaderArray[ChromeImageNumber].D3DTexture;
|
|
CheckTriangleBuffer(0, 0, 0, 0, CurrTextureHandle, TRANSLUCENCY_NORMAL, -1);
|
|
|
|
D3D_DrawWaterPatch(x, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale*2, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale*3, y, z);
|
|
D3D_DrawWaterPatch(x, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale*2, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale*3, y, z+MeshZScale);
|
|
}
|
|
if (drawStream2)
|
|
{
|
|
#if 0 /* added, but then disabled (too squishy) */
|
|
int x = 217400;
|
|
int y = 20750;
|
|
int z = 54000;
|
|
MeshXScale = (87869-68581);
|
|
MeshZScale = (105385-93696);
|
|
{
|
|
extern void CheckForObjectsInWater(int minX, int maxX, int minZ, int maxZ, int averageY);
|
|
CheckForObjectsInWater(x, x+MeshXScale, z, z+MeshZScale, y);
|
|
}
|
|
|
|
WaterXOrigin=x;
|
|
WaterZOrigin=z;
|
|
WaterUScale = 4.0f/(float)MeshXScale;
|
|
WaterVScale = 4.0f/(float)MeshZScale;
|
|
MeshXScale/=4;
|
|
MeshZScale/=2;
|
|
|
|
CurrTextureHandle = ImageHeaderArray[ChromeImageNumber].D3DTexture;
|
|
CheckTriangleBuffer(0, 0, 0, 0, CurrTextureHandle, TRANSLUCENCY_NORMAL, -1);
|
|
|
|
D3D_DrawWaterPatch(x, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale*2, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale*3, y, z);
|
|
D3D_DrawWaterPatch(x, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale*2, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale*3, y, z+MeshZScale);
|
|
#endif
|
|
}
|
|
}
|
|
#if 0
|
|
else if ( (!__stricmp(LevelName,"e3demo")) || (!__stricmp(LevelName,"e3demosp")) )
|
|
{
|
|
int drawOctagonPool = -1;
|
|
int drawFMV = -1;
|
|
int drawPredatorFMV = -1;
|
|
int drawSwirlyFMV = -1;
|
|
int drawSwirlyFMV2 = -1;
|
|
int drawSwirlyFMV3 = -1;
|
|
while(numOfObjects)
|
|
{
|
|
DISPLAYBLOCK *objectPtr = OnScreenBlockList[--numOfObjects];
|
|
MODULE *modulePtr = objectPtr->ObMyModule;
|
|
|
|
/* if it's a module, which isn't inside another module */
|
|
if (modulePtr && modulePtr->name)
|
|
{
|
|
if(!__stricmp(modulePtr->name,"water1"))
|
|
{
|
|
drawOctagonPool = modulePtr->m_index;
|
|
}
|
|
else if(!__stricmp(modulePtr->name,"marine01b"))
|
|
{
|
|
drawFMV = modulePtr->m_index;
|
|
}
|
|
else if(!_stricmp(modulePtr->name,"predator01"))
|
|
{
|
|
drawPredatorFMV = modulePtr->m_index;
|
|
}
|
|
else if(!_stricmp(modulePtr->name,"toptopgr01"))
|
|
{
|
|
drawSwirlyFMV = modulePtr->m_index;
|
|
}
|
|
else if(!_stricmp(modulePtr->name,"grille04"))
|
|
{
|
|
drawSwirlyFMV2 = modulePtr->m_index;
|
|
}
|
|
#if 0
|
|
else if(!_stricmp(modulePtr->name,"marine05"))
|
|
{
|
|
drawSwirlyFMV3 = modulePtr->m_index;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
#if FMV_ON
|
|
// UpdateFMVTextures(3);
|
|
|
|
|
|
if (drawFMV!=-1)
|
|
{
|
|
DECAL fmvDecal =
|
|
{
|
|
DECAL_FMV,
|
|
};
|
|
fmvDecal.ModuleIndex = drawFMV;
|
|
fmvDecal.UOffset = 0;
|
|
|
|
UpdateFMVTextures(4);
|
|
|
|
for (int z=0; z<6; z++)
|
|
{
|
|
for (int y=0; y<3; y++)
|
|
{
|
|
fmvDecal.Vertices[0].vx = -149;
|
|
fmvDecal.Vertices[1].vx = -149;
|
|
fmvDecal.Vertices[2].vx = -149;
|
|
fmvDecal.Vertices[3].vx = -149;
|
|
|
|
fmvDecal.Vertices[0].vy = -3254+y*744;
|
|
fmvDecal.Vertices[1].vy = -3254+y*744;
|
|
fmvDecal.Vertices[2].vy = -3254+y*744+744;
|
|
fmvDecal.Vertices[3].vy = -3254+y*744+744;
|
|
|
|
fmvDecal.Vertices[0].vz = 49440+z*993;
|
|
fmvDecal.Vertices[1].vz = 49440+z*993+993;
|
|
fmvDecal.Vertices[2].vz = 49440+z*993+993;
|
|
fmvDecal.Vertices[3].vz = 49440+z*993;
|
|
fmvDecal.Centre.vx = ((z+y)%3)+1;
|
|
RenderDecal(&fmvDecal);
|
|
}
|
|
}
|
|
}
|
|
if (drawPredatorFMV!=-1)
|
|
{
|
|
DECAL fmvDecal =
|
|
{
|
|
DECAL_FMV,
|
|
};
|
|
fmvDecal.ModuleIndex = drawPredatorFMV;
|
|
fmvDecal.UOffset = 0;
|
|
|
|
UpdateFMVTextures(4);
|
|
|
|
for (int z=0; z<12; z++)
|
|
{
|
|
for (int y=0; y<7; y++)
|
|
{
|
|
fmvDecal.Vertices[0].vx = -7164;
|
|
fmvDecal.Vertices[1].vx = -7164;
|
|
fmvDecal.Vertices[2].vx = -7164;
|
|
fmvDecal.Vertices[3].vx = -7164;
|
|
|
|
fmvDecal.Vertices[0].vy = -20360+y*362;
|
|
fmvDecal.Vertices[1].vy = -20360+y*362;
|
|
fmvDecal.Vertices[2].vy = -20360+y*362+362;
|
|
fmvDecal.Vertices[3].vy = -20360+y*362+362;
|
|
|
|
fmvDecal.Vertices[0].vz = 1271+z*483+483;
|
|
fmvDecal.Vertices[1].vz = 1271+z*483;
|
|
fmvDecal.Vertices[2].vz = 1271+z*483;
|
|
fmvDecal.Vertices[3].vz = 1271+z*483+483;
|
|
fmvDecal.Centre.vx = (z+y)%3;
|
|
RenderDecal(&fmvDecal);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
if (drawSwirlyFMV!=-1)
|
|
{
|
|
UpdateFMVTextures(1);
|
|
D3D_DrawSwirlyFMV(30000,-12500,0);
|
|
}
|
|
if (drawSwirlyFMV2!=-1)
|
|
{
|
|
UpdateFMVTextures(1);
|
|
D3D_DrawSwirlyFMV(2605,-6267-2000,17394-3200);
|
|
}
|
|
|
|
if (drawSwirlyFMV3!=-1)
|
|
{
|
|
// UpdateFMVTextures(1);
|
|
D3D_DrawSwirlyFMV(5117,3456-3000,52710-2000);
|
|
}
|
|
if (drawOctagonPool!=-1)
|
|
{
|
|
#if FMV_ON
|
|
UpdateFMVTextures(1);
|
|
|
|
MeshXScale = (3000);
|
|
MeshZScale = (4000);
|
|
D3D_DrawFMVOnWater(-1000,3400,22000);
|
|
{
|
|
DECAL fmvDecal =
|
|
{
|
|
DECAL_FMV,
|
|
{
|
|
{0,-2500,29000},
|
|
{2000,-2500,29000},
|
|
{2000,-2500+750*2,29000},
|
|
{0,-2500+750*2,29000}
|
|
},
|
|
0
|
|
};
|
|
fmvDecal.ModuleIndex = drawOctagonPool;
|
|
fmvDecal.Centre.vx = 0;
|
|
fmvDecal.UOffset = 0;
|
|
|
|
RenderDecal(&fmvDecal);
|
|
}
|
|
#endif
|
|
|
|
int highDetailRequired = 1;
|
|
int x = 1023;
|
|
int y = 3400;
|
|
int z = 27536;
|
|
|
|
{
|
|
int dx = Player->ObWorld.vx - x;
|
|
if (dx< -8000 || dx > 8000)
|
|
{
|
|
highDetailRequired = 0;
|
|
}
|
|
else
|
|
{
|
|
int dz = Player->ObWorld.vz - z;
|
|
if (dz< -8000 || dz > 8000)
|
|
{
|
|
highDetailRequired = 0;
|
|
}
|
|
}
|
|
}
|
|
MeshXScale = 7700;
|
|
MeshZScale = 7700;
|
|
{
|
|
extern void CheckForObjectsInWater(int minX, int maxX, int minZ, int maxZ, int averageY);
|
|
CheckForObjectsInWater(x-MeshXScale, x+MeshXScale, z-MeshZScale, z+MeshZScale, y);
|
|
}
|
|
|
|
MeshXScale /=15;
|
|
MeshZScale /=15;
|
|
|
|
// Turn OFF texturing if it is on...
|
|
D3DTEXTUREHANDLE TextureHandle = NULL;
|
|
if (CurrTextureHandle != TextureHandle)
|
|
{
|
|
OP_STATE_RENDER(1, ExecBufInstPtr);
|
|
STATE_DATA(D3DRENDERSTATE_TEXTUREHANDLE, TextureHandle, ExecBufInstPtr);
|
|
CurrTextureHandle = TextureHandle;
|
|
}
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_NORMAL);
|
|
if (NumVertices)
|
|
{
|
|
WriteEndCodeToExecuteBuffer();
|
|
UnlockExecuteBufferAndPrepareForUse();
|
|
ExecuteBuffer();
|
|
LockExecuteBuffer();
|
|
}
|
|
if (highDetailRequired)
|
|
{
|
|
MeshXScale /= 2;
|
|
MeshZScale /= 2;
|
|
D3D_DrawWaterOctagonPatch(x,y,z,0,0);
|
|
D3D_DrawWaterOctagonPatch(x,y,z,15,0);
|
|
D3D_DrawWaterOctagonPatch(x,y,z,0,15);
|
|
D3D_DrawWaterOctagonPatch(x,y,z,15,15);
|
|
MeshXScale = -MeshXScale;
|
|
D3D_DrawWaterOctagonPatch(x,y,z,0,0);
|
|
D3D_DrawWaterOctagonPatch(x,y,z,15,0);
|
|
D3D_DrawWaterOctagonPatch(x,y,z,0,15);
|
|
D3D_DrawWaterOctagonPatch(x,y,z,15,15);
|
|
MeshZScale = -MeshZScale;
|
|
D3D_DrawWaterOctagonPatch(x,y,z,0,0);
|
|
D3D_DrawWaterOctagonPatch(x,y,z,15,0);
|
|
D3D_DrawWaterOctagonPatch(x,y,z,0,15);
|
|
D3D_DrawWaterOctagonPatch(x,y,z,15,15);
|
|
MeshXScale = -MeshXScale;
|
|
D3D_DrawWaterOctagonPatch(x,y,z,0,0);
|
|
D3D_DrawWaterOctagonPatch(x,y,z,15,0);
|
|
D3D_DrawWaterOctagonPatch(x,y,z,0,15);
|
|
D3D_DrawWaterOctagonPatch(x,y,z,15,15);
|
|
}
|
|
else
|
|
{
|
|
D3D_DrawWaterOctagonPatch(x,y,z,0,0);
|
|
MeshXScale = -MeshXScale;
|
|
D3D_DrawWaterOctagonPatch(x,y,z,0,0);
|
|
MeshZScale = -MeshZScale;
|
|
D3D_DrawWaterOctagonPatch(x,y,z,0,0);
|
|
MeshXScale = -MeshXScale;
|
|
D3D_DrawWaterOctagonPatch(x,y,z,0,0);
|
|
}
|
|
|
|
}
|
|
}
|
|
#endif
|
|
else if (!strcasecmp(LevelName,"hangar"))
|
|
{
|
|
#if 0 /* not yet */
|
|
#if FMV_ON
|
|
#if WIBBLY_FMV_ON
|
|
UpdateFMVTextures(1);
|
|
D3D_DrawFMV(FmvPosition.vx,FmvPosition.vy,FmvPosition.vz);
|
|
#endif
|
|
#endif
|
|
#if 0
|
|
{
|
|
VECTORCH v = {49937,-4000,-37709}; // hangar
|
|
D3D_DrawCable(&v);
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
else if (!strcasecmp(LevelName,"invasion_a"))
|
|
{
|
|
char drawWater = 0;
|
|
char drawEndWater = 0;
|
|
|
|
while(numOfObjects)
|
|
{
|
|
DISPLAYBLOCK *objectPtr = OnScreenBlockList[--numOfObjects];
|
|
MODULE *modulePtr = objectPtr->ObMyModule;
|
|
|
|
/* if it's a module, which isn't inside another module */
|
|
if (modulePtr && modulePtr->name)
|
|
{
|
|
if( (!strcmp(modulePtr->name,"hivepool"))
|
|
||(!strcmp(modulePtr->name,"hivepool04")))
|
|
{
|
|
drawWater = 1;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if(!strcmp(modulePtr->name,"shaftbot"))
|
|
{
|
|
drawEndWater = 1;
|
|
}
|
|
if((!strcasecmp(modulePtr->name,"shaft01"))
|
|
||(!strcasecmp(modulePtr->name,"shaft02"))
|
|
||(!strcasecmp(modulePtr->name,"shaft03"))
|
|
||(!strcasecmp(modulePtr->name,"shaft04"))
|
|
||(!strcasecmp(modulePtr->name,"shaft05"))
|
|
||(!strcasecmp(modulePtr->name,"shaft06")))
|
|
{
|
|
extern void HandleRainShaft(MODULE *modulePtr, int bottomY, int topY, int numberOfRaindrops);
|
|
HandleRainShaft(modulePtr, -11726,-107080,10);
|
|
drawEndWater = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (drawWater)
|
|
{
|
|
int x = 20767;
|
|
int y = -36000+200;
|
|
int z = 30238;
|
|
MeshXScale = (36353-20767);
|
|
MeshZScale = (41927-30238);
|
|
{
|
|
extern void CheckForObjectsInWater(int minX, int maxX, int minZ, int maxZ, int averageY);
|
|
CheckForObjectsInWater(x, x+MeshXScale, z, z+MeshZScale, y);
|
|
}
|
|
|
|
WaterXOrigin=x;
|
|
WaterZOrigin=z;
|
|
WaterUScale = 4.0f/(float)MeshXScale;
|
|
WaterVScale = 4.0f/(float)MeshZScale;
|
|
MeshXScale/=4;
|
|
MeshZScale/=2;
|
|
|
|
CurrTextureHandle = ImageHeaderArray[ChromeImageNumber].D3DTexture;
|
|
CheckTriangleBuffer(0, 0, 0, 0, CurrTextureHandle, TRANSLUCENCY_NORMAL, -1);
|
|
D3D_DrawWaterPatch(x, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale*2, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale*3, y, z);
|
|
D3D_DrawWaterPatch(x, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale*2, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale*3, y, z+MeshZScale);
|
|
}
|
|
else if (drawEndWater)
|
|
{
|
|
int x = -15471;
|
|
int y = -11720-500;
|
|
int z = -55875;
|
|
MeshXScale = (15471-1800);
|
|
MeshZScale = (55875-36392);
|
|
{
|
|
extern void CheckForObjectsInWater(int minX, int maxX, int minZ, int maxZ, int averageY);
|
|
CheckForObjectsInWater(x, x+MeshXScale, z, z+MeshZScale, y);
|
|
}
|
|
WaterXOrigin=x;
|
|
WaterZOrigin=z;
|
|
WaterUScale = 4.0f/(float)(MeshXScale+1800-3782);
|
|
WaterVScale = 4.0f/(float)MeshZScale;
|
|
MeshXScale/=4;
|
|
MeshZScale/=2;
|
|
|
|
CurrTextureHandle = ImageHeaderArray[WaterShaftImageNumber].D3DTexture;
|
|
CheckTriangleBuffer(0, 0, 0, 0, CurrTextureHandle, TRANSLUCENCY_NORMAL, -1);
|
|
D3D_DrawWaterPatch(x, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale*2, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale*3, y, z);
|
|
D3D_DrawWaterPatch(x, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale*2, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale*3, y, z+MeshZScale);
|
|
}
|
|
}
|
|
else if (!strcasecmp(LevelName, "derelict"))
|
|
{
|
|
char drawMirrorSurfaces = 0;
|
|
char drawWater = 0;
|
|
|
|
while(numOfObjects)
|
|
{
|
|
DISPLAYBLOCK *objectPtr = OnScreenBlockList[--numOfObjects];
|
|
MODULE *modulePtr = objectPtr->ObMyModule;
|
|
|
|
/* if it's a module, which isn't inside another module */
|
|
if (modulePtr && modulePtr->name)
|
|
{
|
|
if( (!strcasecmp(modulePtr->name,"start-en01"))
|
|
||(!strcasecmp(modulePtr->name,"start")))
|
|
{
|
|
drawMirrorSurfaces = 1;
|
|
}
|
|
else if (!strcasecmp(modulePtr->name,"water-01"))
|
|
{
|
|
extern void HandleRainShaft(MODULE *modulePtr, int bottomY, int topY, int numberOfRaindrops);
|
|
drawWater = 1;
|
|
HandleRainShaft(modulePtr, 32000, 0, 16);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (drawMirrorSurfaces)
|
|
{
|
|
extern void RenderMirrorSurface(void);
|
|
extern void RenderMirrorSurface2(void);
|
|
extern void RenderParticlesInMirror(void);
|
|
RenderParticlesInMirror();
|
|
RenderMirrorSurface();
|
|
RenderMirrorSurface2();
|
|
}
|
|
if (drawWater)
|
|
{
|
|
int x = -102799;
|
|
int y = 32000;
|
|
int z = -200964;
|
|
MeshXScale = (102799-87216);
|
|
MeshZScale = (200964-180986);
|
|
{
|
|
extern void CheckForObjectsInWater(int minX, int maxX, int minZ, int maxZ, int averageY);
|
|
CheckForObjectsInWater(x, x+MeshXScale, z, z+MeshZScale, y);
|
|
}
|
|
|
|
WaterXOrigin=x;
|
|
WaterZOrigin=z;
|
|
WaterUScale = 4.0f/(float)MeshXScale;
|
|
WaterVScale = 4.0f/(float)MeshZScale;
|
|
MeshXScale/=2;
|
|
MeshZScale/=2;
|
|
|
|
CurrTextureHandle = ImageHeaderArray[ChromeImageNumber].D3DTexture;
|
|
CheckTriangleBuffer(0, 0, 0, 0, CurrTextureHandle, TRANSLUCENCY_NORMAL, -1);
|
|
D3D_DrawWaterPatch(x, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z);
|
|
D3D_DrawWaterPatch(x, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z+MeshZScale);
|
|
}
|
|
|
|
}
|
|
else if (!strcasecmp(LevelName,"genshd1"))
|
|
{
|
|
while(numOfObjects)
|
|
{
|
|
DISPLAYBLOCK *objectPtr = OnScreenBlockList[--numOfObjects];
|
|
MODULE *modulePtr = objectPtr->ObMyModule;
|
|
|
|
/* if it's a module, which isn't inside another module */
|
|
if (modulePtr && modulePtr->name)
|
|
{
|
|
if( (!strcasecmp(modulePtr->name,"largespace"))
|
|
||(!strcasecmp(modulePtr->name,"proc13"))
|
|
||(!strcasecmp(modulePtr->name,"trench01"))
|
|
||(!strcasecmp(modulePtr->name,"trench02"))
|
|
||(!strcasecmp(modulePtr->name,"trench03"))
|
|
||(!strcasecmp(modulePtr->name,"trench04"))
|
|
||(!strcasecmp(modulePtr->name,"trench05"))
|
|
||(!strcasecmp(modulePtr->name,"trench06"))
|
|
||(!strcasecmp(modulePtr->name,"trench07"))
|
|
||(!strcasecmp(modulePtr->name,"trench08"))
|
|
||(!strcasecmp(modulePtr->name,"trench09")))
|
|
{
|
|
extern void HandleRain(int numberOfRaindrops);
|
|
HandleRain(999);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void D3D_DrawWaterTest(MODULE *testModulePtr)
|
|
{
|
|
extern char LevelName[];
|
|
if (!strcmp(LevelName,"genshd1"))
|
|
{
|
|
// DISPLAYBLOCK *objectPtr = OnScreenBlockList[numOfObjects];
|
|
MODULE *modulePtr = testModulePtr;//objectPtr->ObMyModule;
|
|
#if 0
|
|
if (testModulePtr && testModulePtr->name)
|
|
if(!strcmp(testModulePtr->name,"LargeSpace"))
|
|
{
|
|
extern void HandleRain(int numberOfRaindrops);
|
|
HandleRain(999);
|
|
}
|
|
#endif
|
|
if (modulePtr && modulePtr->name)
|
|
{
|
|
if (!strcmp(modulePtr->name,"05"))
|
|
{
|
|
int y = modulePtr->m_maxy+modulePtr->m_world.vy-500;
|
|
int x = modulePtr->m_minx+modulePtr->m_world.vx;
|
|
int z = modulePtr->m_minz+modulePtr->m_world.vz;
|
|
MeshXScale = (7791 - -7794);
|
|
MeshZScale = (23378 - 7793);
|
|
{
|
|
extern void CheckForObjectsInWater(int minX, int maxX, int minZ, int maxZ, int averageY);
|
|
CheckForObjectsInWater(x, x+MeshXScale, z, z+MeshZScale, y);
|
|
}
|
|
|
|
CurrTextureHandle = ImageHeaderArray[WaterShaftImageNumber].D3DTexture;
|
|
CheckBoundTextureIsCorrect(CurrTextureHandle);
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_NORMAL);
|
|
|
|
WaterXOrigin=x;
|
|
WaterZOrigin=z;
|
|
WaterUScale = 4.0f/(float)(MeshXScale);
|
|
WaterVScale = 4.0f/(float)MeshZScale;
|
|
#if 1
|
|
MeshXScale/=2;
|
|
MeshZScale/=2;
|
|
|
|
CurrTextureHandle = ImageHeaderArray[WaterShaftImageNumber].D3DTexture;
|
|
CheckTriangleBuffer(0, 0, 0, 0, CurrTextureHandle, TRANSLUCENCY_NORMAL, -1);
|
|
D3D_DrawWaterPatch(x, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z);
|
|
D3D_DrawWaterPatch(x, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z+MeshZScale);
|
|
|
|
{
|
|
extern void HandleRainShaft(MODULE *modulePtr, int bottomY, int topY, int numberOfRaindrops);
|
|
HandleRainShaft(modulePtr, y,-21000,1);
|
|
}
|
|
#else
|
|
MeshXScale/=4;
|
|
MeshZScale/=4;
|
|
D3D_DrawWaterPatch(x, y, z);
|
|
D3D_DrawWaterPatch(x, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x, y, z+MeshZScale*2);
|
|
D3D_DrawWaterPatch(x, y, z+MeshZScale*3);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z+MeshZScale*2);
|
|
D3D_DrawWaterPatch(x+MeshXScale, y, z+MeshZScale*3);
|
|
D3D_DrawWaterPatch(x+MeshXScale*2, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale*2, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale*2, y, z+MeshZScale*2);
|
|
D3D_DrawWaterPatch(x+MeshXScale*2, y, z+MeshZScale*3);
|
|
D3D_DrawWaterPatch(x+MeshXScale*3, y, z);
|
|
D3D_DrawWaterPatch(x+MeshXScale*3, y, z+MeshZScale);
|
|
D3D_DrawWaterPatch(x+MeshXScale*3, y, z+MeshZScale*2);
|
|
D3D_DrawWaterPatch(x+MeshXScale*3, y, z+MeshZScale*3);
|
|
HandleRainDrops(modulePtr,2);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
#if 0
|
|
else if ( (!_stricmp(LevelName,"e3demo")) || (!_stricmp(LevelName,"e3demosp")) )
|
|
{
|
|
if (testModulePtr && testModulePtr->name)
|
|
{
|
|
#if 0
|
|
if(!_stricmp(testModulePtr->name,"watermid"))
|
|
{
|
|
DECAL fmvDecal =
|
|
{
|
|
DECAL_FMV,
|
|
{
|
|
{0,-2500,29000},
|
|
{2000,-2500,29000},
|
|
{2000,-2500+750*2,29000},
|
|
{0,-2500+750*2,29000}
|
|
},
|
|
0
|
|
};
|
|
fmvDecal.ModuleIndex = testModulePtr->m_index;
|
|
fmvDecal.Centre.vx = 0;
|
|
fmvDecal.UOffset = 0;
|
|
|
|
RenderDecal(&fmvDecal);
|
|
}
|
|
#endif
|
|
if(!_stricmp(testModulePtr->name,"lowlowlo03"))
|
|
{
|
|
VECTORCH position = {6894,469,-13203};
|
|
VECTORCH disp = position;
|
|
int i,d;
|
|
|
|
disp.vx -= Player->ObWorld.vx;
|
|
disp.vy -= Player->ObWorld.vy;
|
|
disp.vz -= Player->ObWorld.vz;
|
|
d = ONE_FIXED - Approximate3dMagnitude(&disp)*2;
|
|
if (d<0) d = 0;
|
|
|
|
i = MUL_FIXED(10,d);
|
|
while(i--)
|
|
{
|
|
VECTORCH velocity;
|
|
velocity.vx = ((FastRandom()&1023) - 512);
|
|
velocity.vy = ((FastRandom()&1023) - 512)+2000;
|
|
velocity.vz = (1000+(FastRandom()&255))*2;
|
|
MakeParticle(&(position),&(velocity),PARTICLE_STEAM);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/* TODO: doubled this from 256 to 512 because of overflows in DrawMoltenMetal_Clipped */
|
|
VECTORCH MeshVertex[512];
|
|
#define TEXTURE_WATER 0
|
|
|
|
VECTORCH MeshWorldVertex[512];
|
|
unsigned int MeshVertexColour[512];
|
|
unsigned int MeshVertexSpecular[512];
|
|
char MeshVertexOutcode[512];
|
|
|
|
void D3D_DrawWaterPatch(int xOrigin, int yOrigin, int zOrigin)
|
|
{
|
|
int i=0;
|
|
int x;
|
|
int offset;
|
|
|
|
for (x=0; x<16; x++)
|
|
{
|
|
int z;
|
|
for(z=0; z<16; z++)
|
|
{
|
|
VECTORCH *point = &MeshVertex[i];
|
|
|
|
point->vx = xOrigin+(x*MeshXScale)/15;
|
|
point->vz = zOrigin+(z*MeshZScale)/15;
|
|
|
|
|
|
offset=0;
|
|
|
|
#if 1
|
|
/* basic noise ripples */
|
|
// offset = MUL_FIXED(32,GetSin( (point->vx+point->vz+CloakingPhase)&4095 ) );
|
|
// offset += MUL_FIXED(16,GetSin( (point->vx-point->vz*2+CloakingPhase/2)&4095 ) );
|
|
|
|
{
|
|
offset += EffectOfRipples(point);
|
|
}
|
|
#endif
|
|
// if (offset>450) offset = 450;
|
|
// if (offset<-450) offset = -450;
|
|
point->vy = yOrigin+offset;
|
|
|
|
#if 0
|
|
MeshVertexColour[i] = LightSourceWaterPoint(point,offset);
|
|
#else
|
|
{
|
|
int alpha = 128-offset/4;
|
|
// if (alpha>255) alpha = 255;
|
|
// if (alpha<128) alpha = 128;
|
|
switch (CurrentVisionMode)
|
|
{
|
|
default:
|
|
case VISION_MODE_NORMAL:
|
|
{
|
|
// MeshVertexColour[i] = RGBALIGHT_MAKE(10,51,28,alpha);
|
|
MeshVertexColour[i] = RGBA_MAKE(255,255,255,alpha);
|
|
#if 0
|
|
#if 1
|
|
VECTORCH pos = {24087,yOrigin,39165};
|
|
int c = (8191-VectorDistance(&pos,point));
|
|
if (c<0) c=0;
|
|
else
|
|
{
|
|
int s = GetSin((CloakingPhase/2)&4095);
|
|
s = MUL_FIXED(s,s)/64;
|
|
c = MUL_FIXED(s,c);
|
|
}
|
|
MeshVertexSpecular[i] = (c<<16)+(((c/4)<<8)&0xff00) + (c/4);
|
|
#else
|
|
if (!(FastRandom()&1023))
|
|
{
|
|
MeshVertexSpecular[i] = 0xc04040;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexSpecular[i] = 0;
|
|
}
|
|
#endif
|
|
#endif
|
|
break;
|
|
}
|
|
case VISION_MODE_IMAGEINTENSIFIER:
|
|
{
|
|
MeshVertexColour[i] = RGBA_MAKE(0,51,0,alpha);
|
|
break;
|
|
}
|
|
case VISION_MODE_PRED_THERMAL:
|
|
case VISION_MODE_PRED_SEEALIENS:
|
|
case VISION_MODE_PRED_SEEPREDTECH:
|
|
{
|
|
MeshVertexColour[i] = RGBA_MAKE(0,0,28,alpha);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
#if 1
|
|
MeshWorldVertex[i].vx = ((point->vx-WaterXOrigin)/4+MUL_FIXED(GetSin((point->vy*16)&4095),128));
|
|
MeshWorldVertex[i].vy = ((point->vz-WaterZOrigin)/4+MUL_FIXED(GetSin((point->vy*16+200)&4095),128));
|
|
#endif
|
|
|
|
#if 1
|
|
TranslatePointIntoViewspace(point);
|
|
#else
|
|
point->vx -= Global_VDB_Ptr->VDB_World.vx;
|
|
point->vy -= Global_VDB_Ptr->VDB_World.vy;
|
|
point->vz -= Global_VDB_Ptr->VDB_World.vz;
|
|
RotateVector(point,&(Global_VDB_Ptr->VDB_Mat));
|
|
point->vy = MUL_FIXED(point->vy,87381);
|
|
|
|
#endif
|
|
/* is particle within normal view frustrum ? */
|
|
if(AvP.PlayerType==I_Alien) /* wide frustrum */
|
|
{
|
|
if(( (-point->vx <= point->vz*2)
|
|
&&(point->vx <= point->vz*2)
|
|
&&(-point->vy <= point->vz*2)
|
|
&&(point->vy <= point->vz*2) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(( (-point->vx <= point->vz)
|
|
&&(point->vx <= point->vz)
|
|
&&(-point->vy <= point->vz)
|
|
&&(point->vy <= point->vz) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
if ((MeshVertexOutcode[0]&&MeshVertexOutcode[15]&&MeshVertexOutcode[240]&&MeshVertexOutcode[255]))
|
|
{
|
|
D3D_DrawMoltenMetalMesh_Unclipped();
|
|
// D3D_DrawWaterMesh_Unclipped();
|
|
} else {
|
|
D3D_DrawMoltenMetalMesh_Clipped();
|
|
// D3D_DrawWaterMesh_Clipped();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
void D3D_DrawWaterMesh_Unclipped(void)
|
|
{
|
|
float ZNear = (float) (Global_VDB_Ptr->VDB_ClipZ * GlobalScale);
|
|
|
|
/* OUTPUT VERTICES TO EXECUTE BUFFER */
|
|
{
|
|
D3DTLVERTEX *vertexPtr = &((LPD3DTLVERTEX)ExecuteBufferDataArea)[NumVertices];
|
|
VECTORCH *point = MeshVertex;
|
|
#if TEXTURE_WATER
|
|
VECTORCH *pointWS = MeshWorldVertex;
|
|
#endif
|
|
int i;
|
|
for (i=0; i<256; i++)
|
|
{
|
|
|
|
if (point->vz<=1) point->vz = 1;
|
|
int x = (point->vx*(Global_VDB_Ptr->VDB_ProjX))/point->vz+Global_VDB_Ptr->VDB_CentreX;
|
|
int y = (point->vy*(Global_VDB_Ptr->VDB_ProjY))/point->vz+Global_VDB_Ptr->VDB_CentreY;
|
|
// textprint("%d, %d\n",x,y);
|
|
#if 1
|
|
{
|
|
if (x<Global_VDB_Ptr->VDB_ClipLeft)
|
|
{
|
|
x=Global_VDB_Ptr->VDB_ClipLeft;
|
|
}
|
|
else if (x>Global_VDB_Ptr->VDB_ClipRight)
|
|
{
|
|
x=Global_VDB_Ptr->VDB_ClipRight;
|
|
}
|
|
|
|
vertexPtr->sx=x;
|
|
}
|
|
{
|
|
if (y<Global_VDB_Ptr->VDB_ClipUp)
|
|
{
|
|
y=Global_VDB_Ptr->VDB_ClipUp;
|
|
}
|
|
else if (y>Global_VDB_Ptr->VDB_ClipDown)
|
|
{
|
|
y=Global_VDB_Ptr->VDB_ClipDown;
|
|
}
|
|
vertexPtr->sy=y;
|
|
}
|
|
#else
|
|
vertexPtr->sx=x;
|
|
vertexPtr->sy=y;
|
|
#endif
|
|
#if FOG_ON
|
|
{
|
|
int fog = (point->vz)/FOG_SCALE;
|
|
if (fog<0) fog=0;
|
|
if (fog>254) fog=254;
|
|
fog=255-fog;
|
|
vertexPtr->specular=RGBALIGHT_MAKE(0,0,0,fog);
|
|
}
|
|
#endif
|
|
point->vz+=HeadUpDisplayZOffset;
|
|
float oneOverZ = ((float)(point->vz)-ZNear)/(float)(point->vz);
|
|
//vertexPtr->color = RGBALIGHT_MAKE(66,70,0,127+(FastRandom()&63));
|
|
vertexPtr->color = MeshVertexColour[i];
|
|
vertexPtr->sz = oneOverZ;
|
|
#if TEXTURE_WATER
|
|
vertexPtr->tu = pointWS->vx/128.0;
|
|
vertexPtr->tv = pointWS->vz/128.0;
|
|
#endif
|
|
|
|
|
|
NumVertices++;
|
|
vertexPtr++;
|
|
point++;
|
|
#if TEXTURE_WATER
|
|
pointWS++;
|
|
#endif
|
|
}
|
|
}
|
|
// textprint("numvertices %d\n",NumVertices);
|
|
|
|
|
|
/*
|
|
* Make sure that the triangle data (not OP) will be QWORD aligned
|
|
*/
|
|
if (QWORD_ALIGNED(ExecBufInstPtr))
|
|
{
|
|
OP_NOP(ExecBufInstPtr);
|
|
}
|
|
|
|
OP_TRIANGLE_LIST(450, ExecBufInstPtr);
|
|
/* CONSTRUCT POLYS */
|
|
{
|
|
int x;
|
|
for (x=0; x<15; x++)
|
|
{
|
|
int y;
|
|
for(y=0; y<15; y++)
|
|
{
|
|
OUTPUT_TRIANGLE(0+x+(16*y),1+x+(16*y),16+x+(16*y), 256);
|
|
OUTPUT_TRIANGLE(1+x+(16*y),17+x+(16*y),16+x+(16*y), 256);
|
|
}
|
|
}
|
|
}
|
|
#if 1
|
|
{
|
|
WriteEndCodeToExecuteBuffer();
|
|
UnlockExecuteBufferAndPrepareForUse();
|
|
ExecuteBuffer();
|
|
LockExecuteBuffer();
|
|
}
|
|
#endif
|
|
}
|
|
void D3D_DrawWaterMesh_Clipped(void)
|
|
{
|
|
float ZNear = (float) (Global_VDB_Ptr->VDB_ClipZ * GlobalScale);
|
|
|
|
/* OUTPUT VERTICES TO EXECUTE BUFFER */
|
|
{
|
|
D3DTLVERTEX *vertexPtr = &((LPD3DTLVERTEX)ExecuteBufferDataArea)[NumVertices];
|
|
VECTORCH *point = MeshVertex;
|
|
#if TEXTURE_WATER
|
|
VECTORCH *pointWS = MeshWorldVertex;
|
|
#endif
|
|
int i;
|
|
for (i=0; i<256; i++)
|
|
{
|
|
{
|
|
if (point->vz<=1) point->vz = 1;
|
|
int x = (point->vx*(Global_VDB_Ptr->VDB_ProjX))/point->vz+Global_VDB_Ptr->VDB_CentreX;
|
|
int y = (point->vy*(Global_VDB_Ptr->VDB_ProjY))/point->vz+Global_VDB_Ptr->VDB_CentreY;
|
|
#if 1
|
|
{
|
|
if (x<Global_VDB_Ptr->VDB_ClipLeft)
|
|
{
|
|
x=Global_VDB_Ptr->VDB_ClipLeft;
|
|
}
|
|
else if (x>Global_VDB_Ptr->VDB_ClipRight)
|
|
{
|
|
x=Global_VDB_Ptr->VDB_ClipRight;
|
|
}
|
|
|
|
vertexPtr->sx=x;
|
|
}
|
|
{
|
|
if (y<Global_VDB_Ptr->VDB_ClipUp)
|
|
{
|
|
y=Global_VDB_Ptr->VDB_ClipUp;
|
|
}
|
|
else if (y>Global_VDB_Ptr->VDB_ClipDown)
|
|
{
|
|
y=Global_VDB_Ptr->VDB_ClipDown;
|
|
}
|
|
vertexPtr->sy=y;
|
|
}
|
|
#else
|
|
vertexPtr->sx=x;
|
|
vertexPtr->sy=y;
|
|
#endif
|
|
#if FOG_ON
|
|
{
|
|
int fog = ((point->vz)/FOG_SCALE);
|
|
if (fog<0) fog=0;
|
|
if (fog>254) fog=254;
|
|
fog=255-fog;
|
|
vertexPtr->specular=RGBALIGHT_MAKE(0,0,0,fog);
|
|
}
|
|
#endif
|
|
#if TEXTURE_WATER
|
|
vertexPtr->tu = pointWS->vx/128.0;
|
|
vertexPtr->tv = pointWS->vz/128.0;
|
|
#endif
|
|
point->vz+=HeadUpDisplayZOffset;
|
|
float oneOverZ = ((float)(point->vz)-ZNear)/(float)(point->vz);
|
|
// vertexPtr->color = RGBALIGHT_MAKE(66,70,0,127+(FastRandom()&63));
|
|
vertexPtr->color = MeshVertexColour[i];
|
|
vertexPtr->sz = oneOverZ;
|
|
}
|
|
NumVertices++;
|
|
vertexPtr++;
|
|
point++;
|
|
#if TEXTURE_WATER
|
|
pointWS++;
|
|
#endif
|
|
}
|
|
}
|
|
// textprint("numvertices %d\n",NumVertices);
|
|
/* CONSTRUCT POLYS */
|
|
{
|
|
int x;
|
|
for (x=0; x<15; x++)
|
|
{
|
|
int y;
|
|
for(y=0; y<15; y++)
|
|
{
|
|
#if 1
|
|
int p1 = 0+x+(16*y);
|
|
int p2 = 1+x+(16*y);
|
|
int p3 = 16+x+(16*y);
|
|
int p4 = 17+x+(16*y);
|
|
|
|
if (MeshVertexOutcode[p1]||MeshVertexOutcode[p2]||MeshVertexOutcode[p3])
|
|
{
|
|
OP_TRIANGLE_LIST(1, ExecBufInstPtr);
|
|
OUTPUT_TRIANGLE(p1,p2,p3, 256);
|
|
}
|
|
if (MeshVertexOutcode[p2]||MeshVertexOutcode[p3]||MeshVertexOutcode[p4])
|
|
{
|
|
OP_TRIANGLE_LIST(1, ExecBufInstPtr);
|
|
OUTPUT_TRIANGLE(p2,p4,p3, 256);
|
|
}
|
|
#else
|
|
int p2 = 1+x+(16*y);
|
|
int p3 = 16+x+(16*y);
|
|
|
|
if (MeshVertexOutcode[p2]&&MeshVertexOutcode[p3])
|
|
{
|
|
int p1 = 0+x+(16*y);
|
|
int p4 = 17+x+(16*y);
|
|
if (MeshVertexOutcode[p1])
|
|
{
|
|
OP_TRIANGLE_LIST(1, ExecBufInstPtr);
|
|
OUTPUT_TRIANGLE(p1,p2,p3, 256);
|
|
}
|
|
if (MeshVertexOutcode[p4])
|
|
{
|
|
OP_TRIANGLE_LIST(1, ExecBufInstPtr);
|
|
OUTPUT_TRIANGLE(p2,p4,p3, 256);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
#if 1
|
|
{
|
|
WriteEndCodeToExecuteBuffer();
|
|
UnlockExecuteBufferAndPrepareForUse();
|
|
ExecuteBuffer();
|
|
LockExecuteBuffer();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
signed int ForceFieldPointDisplacement[15*3+1][16];
|
|
signed int ForceFieldPointDisplacement2[15*3+1][16];
|
|
signed int ForceFieldPointVelocity[15*3+1][16];
|
|
unsigned char ForceFieldPointColour1[15*3+1][16];
|
|
unsigned char ForceFieldPointColour2[15*3+1][16];
|
|
|
|
int Phase=0;
|
|
int ForceFieldPhase=0;
|
|
void InitForceField(void)
|
|
{
|
|
int x, y;
|
|
|
|
for (x=0; x<15*3+1; x++)
|
|
for (y=0; y<16; y++)
|
|
{
|
|
ForceFieldPointDisplacement[x][y]=0;
|
|
ForceFieldPointDisplacement2[x][y]=0;
|
|
ForceFieldPointVelocity[x][y]=0;
|
|
}
|
|
ForceFieldPhase=0;
|
|
}
|
|
|
|
#if 0 /* not used */
|
|
|
|
#if 1
|
|
|
|
extern int NormalFrameTime;
|
|
|
|
void UpdateForceField(void)
|
|
{
|
|
#if 1
|
|
int x, y;
|
|
|
|
Phase+=NormalFrameTime>>6;
|
|
ForceFieldPhase+=NormalFrameTime>>5;
|
|
for (x=1; x<15*3; x++)
|
|
{
|
|
for (y=1; y<15; y++)
|
|
{
|
|
|
|
int acceleration =32*(-8*ForceFieldPointDisplacement[x][y]
|
|
+ForceFieldPointDisplacement[x-1][y-1]
|
|
+ForceFieldPointDisplacement[x-1][y]
|
|
+ForceFieldPointDisplacement[x-1][y+1]
|
|
+ForceFieldPointDisplacement[x][y-1]
|
|
+ForceFieldPointDisplacement[x][y+1]
|
|
#if 0
|
|
)
|
|
#else
|
|
|
|
+ForceFieldPointDisplacement[x+1][y-1]
|
|
+ForceFieldPointDisplacement[x+1][y]
|
|
+ForceFieldPointDisplacement[x+1][y+1])
|
|
#endif
|
|
-(ForceFieldPointVelocity[x][y]*5);
|
|
|
|
ForceFieldPointVelocity[x][y] += MUL_FIXED(acceleration,NormalFrameTime);
|
|
ForceFieldPointDisplacement2[x][y] += MUL_FIXED(ForceFieldPointVelocity[x][y],NormalFrameTime);
|
|
#if 1
|
|
if(ForceFieldPointDisplacement2[x][y]>200) ForceFieldPointDisplacement2[x][y]=200;
|
|
if(ForceFieldPointDisplacement2[x][y]<-200) ForceFieldPointDisplacement2[x][y]=-200;
|
|
#else
|
|
if(ForceFieldPointDisplacement2[x][y]>512) ForceFieldPointDisplacement2[x][y]=512;
|
|
if(ForceFieldPointDisplacement2[x][y]<-512) ForceFieldPointDisplacement2[x][y]=-512;
|
|
|
|
#endif
|
|
{
|
|
int offset = ForceFieldPointDisplacement2[x][y];
|
|
int colour = ForceFieldPointVelocity[x][y]/4;
|
|
|
|
if (offset<0) offset =-offset;
|
|
if (colour<0) colour =-colour;
|
|
colour=(colour+offset)/2;
|
|
|
|
if(colour>255) colour=255;
|
|
colour++;
|
|
|
|
ForceFieldPointColour1[x][y]=FastRandom()%colour;
|
|
ForceFieldPointColour2[x][y]=FastRandom()%colour;
|
|
}
|
|
}
|
|
|
|
}
|
|
for (x=1; x<15*3; x++)
|
|
{
|
|
int y;
|
|
for (y=1; y<15; y++)
|
|
{
|
|
ForceFieldPointDisplacement[x][y] = ForceFieldPointDisplacement2[x][y];
|
|
}
|
|
}
|
|
{
|
|
#if 1
|
|
if(ForceFieldPhase>1000)
|
|
{
|
|
ForceFieldPhase=0;
|
|
x = 1+(FastRandom()%(15*3-2));
|
|
y = 1+(FastRandom()%13);
|
|
ForceFieldPointVelocity[x][y] = 10000;
|
|
ForceFieldPointVelocity[x][y+1] = 10000;
|
|
ForceFieldPointVelocity[x+1][y] = 10000;
|
|
ForceFieldPointVelocity[x+1][y+1] = 10000;
|
|
}
|
|
#else
|
|
// if(ForceFieldPhase>1000)
|
|
{
|
|
ForceFieldPhase=0;
|
|
x = 1+(FastRandom()%(15*3-2));
|
|
y = 1+(FastRandom()%13);
|
|
ForceFieldPointVelocity[x][y] = (FastRandom()&16383)+8192;
|
|
}
|
|
#endif
|
|
}
|
|
#else
|
|
int x;
|
|
int y;
|
|
for (y=0; y<=15; y++)
|
|
{
|
|
ForceFieldPointDisplacement[0][y] += (FastRandom()&127)-64;
|
|
if(ForceFieldPointDisplacement[0][y]>512) ForceFieldPointDisplacement[0][y]=512;
|
|
if(ForceFieldPointDisplacement[0][y]<-512) ForceFieldPointDisplacement[0][y]=-512;
|
|
ForceFieldPointVelocity[0][y] = (FastRandom()&16383)-8192;
|
|
}
|
|
for (x=15*3-1; x>0; x--)
|
|
{
|
|
for (y=0; y<=15; y++)
|
|
{
|
|
ForceFieldPointDisplacement[x][y] = ForceFieldPointDisplacement[x-1][y];
|
|
ForceFieldPointVelocity[x][y] = ForceFieldPointVelocity[x-1][y];
|
|
}
|
|
|
|
}
|
|
for (x=15*3-1; x>1; x--)
|
|
{
|
|
y = FastRandom()&15;
|
|
ForceFieldPointDisplacement[x][y] = ForceFieldPointDisplacement[x-1][y];
|
|
y = (FastRandom()&15)-1;
|
|
ForceFieldPointDisplacement[x][y] = ForceFieldPointDisplacement[x-1][y];
|
|
}
|
|
#endif
|
|
}
|
|
void UpdateWaterFall(void)
|
|
{
|
|
int x;
|
|
int y;
|
|
for (y=0; y<=15; y++)
|
|
{
|
|
ForceFieldPointDisplacement[0][y] += (FastRandom()&127)-64;
|
|
if(ForceFieldPointDisplacement[0][y]>512) ForceFieldPointDisplacement[0][y]=512;
|
|
if(ForceFieldPointDisplacement[0][y]<-512) ForceFieldPointDisplacement[0][y]=-512;
|
|
ForceFieldPointVelocity[0][y] = (FastRandom()&16383)-8192;
|
|
}
|
|
for (x=15*3-1; x>0; x--)
|
|
{
|
|
for (y=0; y<=15; y++)
|
|
{
|
|
ForceFieldPointDisplacement[x][y] = ForceFieldPointDisplacement[x-1][y];
|
|
ForceFieldPointVelocity[x][y] = ForceFieldPointVelocity[x-1][y];
|
|
}
|
|
|
|
}
|
|
for (x=15*3-1; x>1; x--)
|
|
{
|
|
y = FastRandom()&15;
|
|
ForceFieldPointDisplacement[x][y] = ForceFieldPointDisplacement[x-1][y];
|
|
y = (FastRandom()&15)-1;
|
|
ForceFieldPointDisplacement[x][y] = ForceFieldPointDisplacement[x-1][y];
|
|
}
|
|
}
|
|
|
|
#endif
|
|
#endif /* not used */
|
|
|
|
#if 0 /* not yet */
|
|
|
|
void D3D_DrawForceField(int xOrigin, int yOrigin, int zOrigin, int fieldType)
|
|
{
|
|
MeshXScale = 4096/16;
|
|
MeshZScale = 4096/16;
|
|
|
|
for (int field=0; field<3; field++)
|
|
{
|
|
int i=0;
|
|
int x;
|
|
for (x=(0+field*15); x<(16+field*15); x++)
|
|
{
|
|
int z;
|
|
for(z=0; z<16; z++)
|
|
{
|
|
VECTORCH *point = &MeshVertex[i];
|
|
int offset = ForceFieldPointDisplacement[x][z];
|
|
|
|
switch(fieldType)
|
|
{
|
|
case 0:
|
|
{
|
|
point->vx = xOrigin+(x*MeshXScale);
|
|
point->vy = yOrigin+(z*MeshZScale);
|
|
point->vz = zOrigin+offset;
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
|
|
int theta = (z*4095)/15;
|
|
int u = (x*65536)/45;
|
|
|
|
int b = MUL_FIXED(2*u,(65536-u));
|
|
int c = MUL_FIXED(u,u);
|
|
int phi = (Phase&4095);
|
|
int x3 = (GetSin(phi))/64;
|
|
int y3 = 5000-(GetCos((phi*3+1000)&4095)/128);
|
|
int z3 = (GetSin((3*phi+1324)&4095))/32;
|
|
int x2 = -x3/2;
|
|
int y2 = 3000;
|
|
int z2 = -z3/4;
|
|
int innerRadius = 100;//GetSin(u/32)/16+offset;
|
|
|
|
point->vx = xOrigin+(b*x2+c*x3)/65536+MUL_FIXED(innerRadius,GetSin(theta));
|
|
point->vy = yOrigin-5000+(b*y2+c*y3)/65536;
|
|
point->vz = zOrigin+(b*z2+c*z3)/65536+MUL_FIXED(innerRadius,GetCos(theta));
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
int theta = (z*4095)/15;
|
|
int phi = (x*4095)/45;
|
|
int innerRadius = 1000+offset;
|
|
int outerRadius = 4000;
|
|
|
|
|
|
point->vx = xOrigin+MUL_FIXED(outerRadius-MUL_FIXED(innerRadius,GetSin(theta)),GetCos(phi));
|
|
point->vy = yOrigin+MUL_FIXED(innerRadius,GetCos(theta));
|
|
point->vz = zOrigin+MUL_FIXED(outerRadius-MUL_FIXED(innerRadius,GetSin(theta)),GetSin(phi));
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
|
|
int theta = (x*4095)/45;
|
|
int radius = offset+2000;
|
|
point->vx = xOrigin+MUL_FIXED(radius,GetCos(theta));
|
|
point->vy = yOrigin+(z*MeshZScale);
|
|
point->vz = zOrigin+MUL_FIXED(radius,GetSin(theta));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (offset<0) offset =-offset;
|
|
offset+=16;
|
|
|
|
// offset-=32;
|
|
// if (offset<0) offset = 0;
|
|
|
|
if(offset>255) offset=255;
|
|
|
|
MeshVertexColour[i] = RGBALIGHT_MAKE(ForceFieldPointColour1[x][z],ForceFieldPointColour2[x][z],255,offset);
|
|
#if TEXTURE_WATER
|
|
MeshWorldVertex[i].vx = point->vx;
|
|
MeshWorldVertex[i].vz = point->vz;
|
|
#endif
|
|
|
|
TranslatePointIntoViewspace(point);
|
|
|
|
/* is particle within normal view frustrum ? */
|
|
if(AvP.PlayerType==I_Alien) /* wide frustrum */
|
|
{
|
|
if(( (-point->vx <= point->vz*2)
|
|
&&(point->vx <= point->vz*2)
|
|
&&(-point->vy <= point->vz*2)
|
|
&&(point->vy <= point->vz*2) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(( (-point->vx <= point->vz)
|
|
&&(point->vx <= point->vz)
|
|
&&(-point->vy <= point->vz)
|
|
&&(point->vy <= point->vz) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
//textprint("\n");
|
|
if ((MeshVertexOutcode[0]&&MeshVertexOutcode[15]&&MeshVertexOutcode[240]&&MeshVertexOutcode[255]))
|
|
{
|
|
D3D_DrawWaterMesh_Unclipped();
|
|
}
|
|
else
|
|
// else if (MeshVertexOutcode[0]||MeshVertexOutcode[15]||MeshVertexOutcode[240]||MeshVertexOutcode[255])
|
|
{
|
|
D3D_DrawWaterMesh_Clipped();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void D3D_DrawPowerFence(int xOrigin, int yOrigin, int zOrigin, int xScale, int yScale, int zScale)
|
|
{
|
|
for (int field=0; field<3; field++)
|
|
{
|
|
int i=0;
|
|
int x;
|
|
for (x=(0+field*15); x<(16+field*15); x++)
|
|
{
|
|
int z;
|
|
for(z=0; z<16; z++)
|
|
{
|
|
VECTORCH *point = &MeshVertex[i];
|
|
int offset = ForceFieldPointDisplacement[x][z];
|
|
|
|
point->vx = xOrigin+(x*xScale);
|
|
point->vy = yOrigin+(z*yScale);
|
|
point->vz = zOrigin+(x*zScale);
|
|
|
|
if (offset<0) offset =-offset;
|
|
offset+=16;
|
|
|
|
if(offset>255) offset=255;
|
|
|
|
MeshVertexColour[i] = RGBALIGHT_MAKE(ForceFieldPointColour1[x][z],ForceFieldPointColour2[x][z],255,offset);
|
|
|
|
/* translate particle into view space */
|
|
TranslatePointIntoViewspace(point);
|
|
|
|
/* is particle within normal view frustrum ? */
|
|
if(AvP.PlayerType==I_Alien) /* wide frustrum */
|
|
{
|
|
if(( (-point->vx <= point->vz*2)
|
|
&&(point->vx <= point->vz*2)
|
|
&&(-point->vy <= point->vz*2)
|
|
&&(point->vy <= point->vz*2) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(( (-point->vx <= point->vz)
|
|
&&(point->vx <= point->vz)
|
|
&&(-point->vy <= point->vz)
|
|
&&(point->vy <= point->vz) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
//textprint("\n");
|
|
if ((MeshVertexOutcode[0]&&MeshVertexOutcode[15]&&MeshVertexOutcode[240]&&MeshVertexOutcode[255]))
|
|
{
|
|
D3D_DrawWaterMesh_Unclipped();
|
|
}
|
|
else
|
|
// else if (MeshVertexOutcode[0]||MeshVertexOutcode[15]||MeshVertexOutcode[240]||MeshVertexOutcode[255])
|
|
{
|
|
D3D_DrawWaterMesh_Clipped();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* not yet */
|
|
|
|
void D3D_DrawWaterFall(int xOrigin, int yOrigin, int zOrigin)
|
|
{
|
|
int i;
|
|
int noRequired = MUL_FIXED(250,NormalFrameTime);
|
|
for (i=0; i<noRequired; i++)
|
|
{
|
|
VECTORCH velocity;
|
|
VECTORCH position;
|
|
position.vx = xOrigin;
|
|
position.vy = yOrigin-(FastRandom()&511);//+45*MeshXScale;
|
|
position.vz = zOrigin+(FastRandom()%(15*MeshZScale));
|
|
|
|
velocity.vy = (FastRandom()&511)+512;//-((FastRandom()&1023)+2048)*8;
|
|
velocity.vx = ((FastRandom()&511)+256)*2;
|
|
velocity.vz = 0;//-((FastRandom()&511))*8;
|
|
MakeParticle(&(position), &velocity, PARTICLE_WATERFALLSPRAY);
|
|
}
|
|
|
|
#if 0 /* not used */
|
|
#if 0
|
|
noRequired = MUL_FIXED(200,NormalFrameTime);
|
|
for (i=0; i<noRequired; i++)
|
|
{
|
|
VECTORCH velocity;
|
|
VECTORCH position;
|
|
position.vx = xOrigin+(FastRandom()%(15*MeshZScale));
|
|
position.vy = yOrigin+45*MeshXScale;
|
|
position.vz = zOrigin;
|
|
|
|
velocity.vy = -((FastRandom()&16383)+4096);
|
|
velocity.vx = ((FastRandom()&4095)-2048);
|
|
velocity.vz = -((FastRandom()&2047)+1048);
|
|
MakeParticle(&(position), &velocity, PARTICLE_WATERFALLSPRAY);
|
|
}
|
|
#endif
|
|
{
|
|
extern void RenderWaterFall(int xOrigin, int yOrigin, int zOrigin);
|
|
//RenderWaterFall(xOrigin, yOrigin-500, zOrigin+50);
|
|
}
|
|
return;
|
|
for (int field=0; field<3; field++)
|
|
{
|
|
int i=0;
|
|
int x;
|
|
for (x=(0+field*15); x<(16+field*15); x++)
|
|
{
|
|
int z;
|
|
for(z=0; z<16; z++)
|
|
{
|
|
VECTORCH *point = &MeshVertex[i];
|
|
int offset = ForceFieldPointDisplacement[x][z];
|
|
|
|
#if 1
|
|
int u = (x*65536)/45;
|
|
|
|
int b = MUL_FIXED(2*u,(65536-u));
|
|
int c = MUL_FIXED(u,u);
|
|
int y3 = 45*MeshXScale;
|
|
int x3 = 5000;
|
|
int y2 = 1*MeshXScale;
|
|
int x2 = GetSin(CloakingPhase&4095)+GetCos((CloakingPhase*3+399)&4095);
|
|
x2 = MUL_FIXED(x2,x2)/128;
|
|
|
|
if (offset<0) offset =-offset;
|
|
point->vx = xOrigin+MUL_FIXED(b,x2)+MUL_FIXED(c,x3)+offset;
|
|
point->vy = yOrigin+MUL_FIXED(b,y2)+MUL_FIXED(c,y3);
|
|
point->vz = zOrigin+(z*MeshZScale);
|
|
|
|
if (point->vy>4742)
|
|
{
|
|
if (z<=4)
|
|
{
|
|
point->vy-=MeshXScale;
|
|
if (point->vy<4742) point->vy=4742;
|
|
if (point->vx<179427) point->vx=179427;
|
|
}
|
|
else if (z<=8)
|
|
{
|
|
point->vx+=(8-z)*1000;
|
|
}
|
|
}
|
|
|
|
#else
|
|
if (offset<0) offset =-offset;
|
|
point->vx = xOrigin-offset;
|
|
point->vy = yOrigin+(x*MeshXScale);
|
|
point->vz = zOrigin+(z*MeshZScale);
|
|
#endif
|
|
|
|
|
|
|
|
|
|
offset= (offset/4)+127;
|
|
|
|
// offset-=32;
|
|
// if (offset<0) offset = 0;
|
|
|
|
if(offset>255) offset=255;
|
|
|
|
MeshVertexColour[i] = RGBALIGHT_MAKE(offset,offset,255,offset/2);
|
|
#if TEXTURE_WATER
|
|
MeshWorldVertex[i].vx = point->vx;
|
|
MeshWorldVertex[i].vz = point->vz;
|
|
#endif
|
|
|
|
/* translate particle into view space */
|
|
TranslatePointIntoViewspace(point);
|
|
|
|
/* is particle within normal view frustrum ? */
|
|
if(AvP.PlayerType==I_Alien) /* wide frustrum */
|
|
{
|
|
if(( (-point->vx <= point->vz*2)
|
|
&&(point->vx <= point->vz*2)
|
|
&&(-point->vy <= point->vz*2)
|
|
&&(point->vy <= point->vz*2) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(( (-point->vx <= point->vz)
|
|
&&(point->vx <= point->vz)
|
|
&&(-point->vy <= point->vz)
|
|
&&(point->vy <= point->vz) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
//textprint("\n");
|
|
if ((MeshVertexOutcode[0]&&MeshVertexOutcode[15]&&MeshVertexOutcode[240]&&MeshVertexOutcode[255]))
|
|
{
|
|
D3D_DrawWaterMesh_Unclipped();
|
|
}
|
|
else
|
|
// else if (MeshVertexOutcode[0]||MeshVertexOutcode[15]||MeshVertexOutcode[240]||MeshVertexOutcode[255])
|
|
{
|
|
D3D_DrawWaterMesh_Clipped();
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if 0 /* not yet */
|
|
|
|
void D3D_DrawMoltenMetal(int xOrigin, int yOrigin, int zOrigin)
|
|
{
|
|
int i=0;
|
|
int x;
|
|
for (x=0; x<16; x++)
|
|
{
|
|
int z;
|
|
for(z=0; z<16; z++)
|
|
{
|
|
VECTORCH *point = &MeshVertex[i];
|
|
|
|
point->vx = xOrigin+(x*MeshXScale)/15;
|
|
point->vz = zOrigin+(z*MeshZScale)/15;
|
|
#if 0
|
|
|
|
int offset=0;
|
|
|
|
offset = MUL_FIXED(32,GetSin( (point->vx+point->vz+CloakingPhase)&4095 ) );
|
|
offset += MUL_FIXED(16,GetSin( (point->vx-point->vz*2+CloakingPhase/2)&4095 ) );
|
|
{
|
|
float dx=point->vx-22704;
|
|
float dz=point->vz+20652;
|
|
float a = dx*dx+dz*dz;
|
|
a=sqrt(a);
|
|
|
|
offset+= MUL_FIXED(200,GetSin( (((int)a-CloakingPhase)&4095) ));
|
|
}
|
|
#endif
|
|
#if 1
|
|
int offset=0;
|
|
|
|
/* basic noise ripples */
|
|
offset = MUL_FIXED(128,GetSin( ((point->vx+point->vz)/16+CloakingPhase)&4095 ) );
|
|
offset += MUL_FIXED(64,GetSin( ((point->vx-point->vz*2)/4+CloakingPhase/2)&4095 ) );
|
|
offset += MUL_FIXED(64,GetSin( ((point->vx*5-point->vz)/32+CloakingPhase/5)&4095 ) );
|
|
|
|
#endif
|
|
if (offset>450) offset = 450;
|
|
if (offset<-1000) offset = -1000;
|
|
point->vy = yOrigin+offset;
|
|
|
|
{
|
|
int shade = 191+(offset+256)/8;
|
|
MeshVertexColour[i] = RGBLIGHT_MAKE(shade,shade,shade);
|
|
}
|
|
|
|
#if 1
|
|
TranslatePointIntoViewspace(point);
|
|
#else
|
|
point->vx -= Global_VDB_Ptr->VDB_World.vx;
|
|
point->vy -= Global_VDB_Ptr->VDB_World.vy;
|
|
point->vz -= Global_VDB_Ptr->VDB_World.vz;
|
|
MeshWorldVertex[i] = *point;
|
|
RotateVector(point,&(Global_VDB_Ptr->VDB_Mat));
|
|
point->vy = MUL_FIXED(point->vy,87381);
|
|
|
|
#endif
|
|
/* is particle within normal view frustrum ? */
|
|
if(AvP.PlayerType==I_Alien) /* wide frustrum */
|
|
{
|
|
if(( (-point->vx <= point->vz*2)
|
|
&&(point->vx <= point->vz*2)
|
|
&&(-point->vy <= point->vz*2)
|
|
&&(point->vy <= point->vz*2) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(( (-point->vx <= point->vz)
|
|
&&(point->vx <= point->vz)
|
|
&&(-point->vy <= point->vz)
|
|
&&(point->vy <= point->vz) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
{
|
|
// v
|
|
MeshWorldVertex[i].vy = (offset+256)*4;
|
|
// u
|
|
MeshWorldVertex[i].vx = ((MeshWorldVertex[i].vx)&4095);
|
|
|
|
}
|
|
#else
|
|
{
|
|
Normalise(&MeshWorldVertex[i]);
|
|
// v
|
|
int theta = (MeshWorldVertex[i].vy+offset);
|
|
if (theta<0) theta=0;
|
|
if (theta>ONE_FIXED) theta=ONE_FIXED;
|
|
|
|
// u
|
|
int arctan = ((atan2((double)MeshWorldVertex[i].vx,(double)MeshWorldVertex[i].vz)/ 6.28318530718))*4095;
|
|
MeshWorldVertex[i].vx = (arctan+offset)&4095;
|
|
|
|
MeshWorldVertex[i].vy = ArcCos(theta);
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
D3DTEXTUREHANDLE TextureHandle = (D3DTEXTUREHANDLE)ImageHeaderArray[StaticImageNumber].D3DHandle;
|
|
if (CurrTextureHandle != TextureHandle)
|
|
{
|
|
OP_STATE_RENDER(1, ExecBufInstPtr);
|
|
STATE_DATA(D3DRENDERSTATE_TEXTUREHANDLE, TextureHandle, ExecBufInstPtr);
|
|
CurrTextureHandle = TextureHandle;
|
|
}
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_OFF);
|
|
if (NumVertices)
|
|
{
|
|
WriteEndCodeToExecuteBuffer();
|
|
UnlockExecuteBufferAndPrepareForUse();
|
|
ExecuteBuffer();
|
|
LockExecuteBuffer();
|
|
}
|
|
if ((MeshVertexOutcode[0]&&MeshVertexOutcode[15]&&MeshVertexOutcode[240]&&MeshVertexOutcode[255]))
|
|
{
|
|
D3D_DrawMoltenMetalMesh_Unclipped();
|
|
}
|
|
else
|
|
// else if (MeshVertexOutcode[0]||MeshVertexOutcode[15]||MeshVertexOutcode[240]||MeshVertexOutcode[255])
|
|
{
|
|
D3D_DrawMoltenMetalMesh_Clipped();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
#endif /* not yet */
|
|
|
|
void D3D_DrawMoltenMetalMesh_Unclipped(void)
|
|
{
|
|
float ZNear = (float) (Global_VDB_Ptr->VDB_ClipZ * GlobalScale);
|
|
|
|
VECTORCH *point = MeshVertex;
|
|
VECTORCH *pointWS = MeshWorldVertex;
|
|
|
|
int i, x, y, z;
|
|
int start;
|
|
|
|
CheckTriangleBuffer( /*256*/ 273, 0, 450, 0, (D3DTexture *)-1, -1, -1);
|
|
|
|
start = varrc;
|
|
for (i=0; i<256; i++) {
|
|
GLfloat xf, yf, zf;
|
|
GLfloat sf, tf, rhw;
|
|
int r, g, b, a;
|
|
|
|
if (point->vz < 1) point->vz = 1;
|
|
|
|
x = (point->vx*(Global_VDB_Ptr->VDB_ProjX+1))/point->vz+Global_VDB_Ptr->VDB_CentreX;
|
|
y = (point->vy*(Global_VDB_Ptr->VDB_ProjY+1))/point->vz+Global_VDB_Ptr->VDB_CentreY;
|
|
|
|
if (x<Global_VDB_Ptr->VDB_ClipLeft) {
|
|
x=Global_VDB_Ptr->VDB_ClipLeft;
|
|
} else if (x>Global_VDB_Ptr->VDB_ClipRight) {
|
|
x=Global_VDB_Ptr->VDB_ClipRight;
|
|
}
|
|
|
|
if (y<Global_VDB_Ptr->VDB_ClipUp) {
|
|
y=Global_VDB_Ptr->VDB_ClipUp;
|
|
} else if (y>Global_VDB_Ptr->VDB_ClipDown) {
|
|
y=Global_VDB_Ptr->VDB_ClipDown;
|
|
}
|
|
|
|
sf = pointWS->vx*WaterUScale+(1.0f/256.0f);
|
|
tf = pointWS->vy*WaterVScale+(1.0f/256.0f);
|
|
|
|
z = point->vz + HeadUpDisplayZOffset;
|
|
rhw = 1.0f / (float)point->vz;
|
|
|
|
b = (MeshVertexColour[i] >> 0) & 0xFF;
|
|
g = (MeshVertexColour[i] >> 8) & 0xFF;
|
|
r = (MeshVertexColour[i] >> 16) & 0xFF;
|
|
a = (MeshVertexColour[i] >> 24) & 0xFF;
|
|
|
|
xf = ((float)x - (float)ScreenDescriptorBlock.SDB_CentreX - 0.5f) / ((float)ScreenDescriptorBlock.SDB_CentreX - 0.5f);
|
|
yf = -((float)y - (float)ScreenDescriptorBlock.SDB_CentreY - 0.5f) / ((float)ScreenDescriptorBlock.SDB_CentreY - 0.5f);
|
|
zf = 1.0f - 2.0f*ZNear/(float)z;
|
|
|
|
varrp->v[0] = xf/rhw;
|
|
varrp->v[1] = yf/rhw;
|
|
varrp->v[2] = zf/rhw;
|
|
varrp->v[3] = 1.0f/rhw;
|
|
|
|
varrp->t[0] = sf;
|
|
varrp->t[1] = tf;
|
|
|
|
varrp->c[0] = r;
|
|
varrp->c[1] = g;
|
|
varrp->c[2] = b;
|
|
varrp->c[3] = a;
|
|
|
|
varrp++;
|
|
varrc++;
|
|
|
|
point++;
|
|
pointWS++;
|
|
}
|
|
|
|
/* CONSTRUCT POLYS */
|
|
|
|
for (x = 0; x < 15; x++) {
|
|
for(y = 0; y < 15; y++) {
|
|
// OUTPUT_TRIANGLE(0+x+(16*y),1+x+(16*y),16+x+(16*y), 256);
|
|
// OUTPUT_TRIANGLE(1+x+(16*y),17+x+(16*y),16+x+(16*y), 256);
|
|
|
|
tarrp[0].a = start+0+x+(16*y);
|
|
tarrp[0].b = start+1+x+(16*y);
|
|
tarrp[0].c = start+16+x+(16*y);
|
|
|
|
tarrp[1].a = start+1+x+(16*y);
|
|
tarrp[1].b = start+17+x+(16*y);
|
|
tarrp[1].c = start+16+x+(16*y);
|
|
|
|
tarrp += 2;
|
|
tarrc += 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
void D3D_DrawMoltenMetalMesh_Clipped(void)
|
|
{
|
|
/* clipping unnecessary. */
|
|
D3D_DrawMoltenMetalMesh_Unclipped();
|
|
#if 0
|
|
int i, x, y, z;
|
|
|
|
float ZNear = (float) (Global_VDB_Ptr->VDB_ClipZ * GlobalScale);
|
|
|
|
VECTORCH *point = MeshVertex;
|
|
VECTORCH *pointWS = MeshWorldVertex;
|
|
|
|
CheckTriangleBuffer(256, 0, 450, 0, (D3DTexture *)-1, -1, -1);
|
|
|
|
for (i=0; i<256; i++)
|
|
{
|
|
GLfloat xf, yf, zf;
|
|
GLfloat sf, tf, rhw;
|
|
int r, g, b, a;
|
|
|
|
if (point->vz < 1) point->vz = 1;
|
|
|
|
x = (point->vx*(Global_VDB_Ptr->VDB_ProjX+1))/point->vz+Global_VDB_Ptr->VDB_CentreX;
|
|
y = (point->vy*(Global_VDB_Ptr->VDB_ProjY+1))/point->vz+Global_VDB_Ptr->VDB_CentreY;
|
|
|
|
if (x<Global_VDB_Ptr->VDB_ClipLeft) {
|
|
x=Global_VDB_Ptr->VDB_ClipLeft;
|
|
} else if (x>Global_VDB_Ptr->VDB_ClipRight) {
|
|
x=Global_VDB_Ptr->VDB_ClipRight;
|
|
}
|
|
|
|
if (y<Global_VDB_Ptr->VDB_ClipUp) {
|
|
y=Global_VDB_Ptr->VDB_ClipUp;
|
|
} else if (y>Global_VDB_Ptr->VDB_ClipDown) {
|
|
y=Global_VDB_Ptr->VDB_ClipDown;
|
|
}
|
|
|
|
sf = pointWS->vx*WaterUScale+(1.0f/256.0f);
|
|
tf = pointWS->vy*WaterVScale+(1.0f/256.0f);
|
|
|
|
z = point->vz + HeadUpDisplayZOffset;
|
|
rhw = 1.0f / (float)point->vz;
|
|
|
|
b = (MeshVertexColour[i] >> 0) & 0xFF;
|
|
g = (MeshVertexColour[i] >> 8) & 0xFF;
|
|
r = (MeshVertexColour[i] >> 16) & 0xFF;
|
|
a = (MeshVertexColour[i] >> 24) & 0xFF;
|
|
|
|
xf = ((float)x - (float)ScreenDescriptorBlock.SDB_CentreX - 0.5f) / ((float)ScreenDescriptorBlock.SDB_CentreX - 0.5f);
|
|
yf = -((float)y - (float)ScreenDescriptorBlock.SDB_CentreY - 0.5f) / ((float)ScreenDescriptorBlock.SDB_CentreY - 0.5f);
|
|
zf = 1.0f - 2.0f*ZNear/(float)z;
|
|
|
|
tarr[i].v[0] = xf/rhw;
|
|
tarr[i].v[1] = yf/rhw;
|
|
tarr[i].v[2] = zf/rhw;
|
|
tarr[i].v[3] = 1.0f/rhw;
|
|
|
|
tarr[i].t[0] = sf;
|
|
tarr[i].t[1] = tf;
|
|
|
|
tarr[i].c[0] = r;
|
|
tarr[i].c[1] = g;
|
|
tarr[i].c[2] = b;
|
|
tarr[i].c[3] = a;
|
|
|
|
point++;
|
|
pointWS++;
|
|
}
|
|
|
|
/* CONSTRUCT POLYS */
|
|
{
|
|
int tc = 0;
|
|
|
|
for (x=0; x<15; x++)
|
|
{
|
|
for(y=0; y<15; y++)
|
|
{
|
|
int p1 = 0+x+(16*y);
|
|
int p2 = 1+x+(16*y);
|
|
int p3 = 16+x+(16*y);
|
|
int p4 = 17+x+(16*y);
|
|
|
|
if (p3 > 255)
|
|
continue;
|
|
#if 0
|
|
#if 0
|
|
if (MeshVertexOutcode[p1]&&MeshVertexOutcode[p2]&&MeshVertexOutcode[p3])
|
|
{
|
|
OP_TRIANGLE_LIST(1, ExecBufInstPtr);
|
|
OUTPUT_TRIANGLE(p1,p2,p3, 256);
|
|
}
|
|
if (MeshVertexOutcode[p2]&&MeshVertexOutcode[p3]&&MeshVertexOutcode[p4])
|
|
{
|
|
OP_TRIANGLE_LIST(1, ExecBufInstPtr);
|
|
OUTPUT_TRIANGLE(p2,p4,p3, 256);
|
|
}
|
|
#else
|
|
if (MeshVertexOutcode[p1]&&MeshVertexOutcode[p2]&&MeshVertexOutcode[p3]&&MeshVertexOutcode[p4])
|
|
{
|
|
OP_TRIANGLE_LIST(2, ExecBufInstPtr);
|
|
OUTPUT_TRIANGLE(p1,p2,p3, 256);
|
|
OUTPUT_TRIANGLE(p2,p4,p3, 256);
|
|
}
|
|
|
|
#endif
|
|
#endif
|
|
if (MeshVertexOutcode[p1]&&MeshVertexOutcode[p2]&&MeshVertexOutcode[p3]&&MeshVertexOutcode[p4]) {
|
|
#if 0
|
|
tris[tc+0].a = p1;
|
|
tris[tc+0].b = p2;
|
|
tris[tc+0].c = p3;
|
|
tris[tc+1].a = p2;
|
|
tris[tc+1].b = p4;
|
|
tris[tc+1].c = p3;
|
|
#endif
|
|
tc += 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
{
|
|
POLYHEADER fakeHeader;
|
|
|
|
fakeHeader.PolyFlags = 0;
|
|
fakeHeader.PolyColour = 0;
|
|
RenderPolygon.TranslucencyMode = TRANSLUCENCY_NORMAL;
|
|
|
|
for (x=0; x<15; x++)
|
|
{
|
|
for(y=0; y<15; y++)
|
|
{
|
|
int p[4];
|
|
p[0] = 0+x+(16*y);
|
|
p[1] = 1+x+(16*y);
|
|
p[2] = 17+x+(16*y);
|
|
p[3] = 16+x+(16*y);
|
|
|
|
if (p[3] > 255)
|
|
continue;
|
|
|
|
if (!(MeshVertexOutcode[p[0]]&&MeshVertexOutcode[p[1]]&&MeshVertexOutcode[p[2]]&&MeshVertexOutcode[p[3]]))
|
|
{
|
|
for (i=0; i<4; i++)
|
|
{
|
|
VerticesBuffer[i].X = MeshVertex[p[i]].vx;
|
|
VerticesBuffer[i].Y = MeshVertex[p[i]].vy;
|
|
VerticesBuffer[i].Z = MeshVertex[p[i]].vz;
|
|
VerticesBuffer[i].U = MeshWorldVertex[p[i]].vx*(WaterUScale*128.0f*65536.0f);
|
|
VerticesBuffer[i].V = MeshWorldVertex[p[i]].vy*(WaterVScale*128.0f*65536.0f);
|
|
|
|
VerticesBuffer[i].A = (MeshVertexColour[p[i]]&0xff000000)>>24;
|
|
VerticesBuffer[i].R = (MeshVertexColour[p[i]]&0x00ff0000)>>16;
|
|
VerticesBuffer[i].G = (MeshVertexColour[p[i]]&0x0000ff00)>>8;
|
|
VerticesBuffer[i].B = MeshVertexColour[p[i]]&0x000000ff;
|
|
VerticesBuffer[i].SpecularR = 0;
|
|
VerticesBuffer[i].SpecularG = 0;
|
|
VerticesBuffer[i].SpecularB = 0;
|
|
RenderPolygon.NumberOfVertices=4;
|
|
|
|
}
|
|
if (QuadWithinFrustrum())
|
|
{
|
|
GouraudTexturedPolygon_ClipWithZ();
|
|
if(RenderPolygon.NumberOfVertices<3) continue;
|
|
GouraudTexturedPolygon_ClipWithNegativeX();
|
|
if(RenderPolygon.NumberOfVertices<3) continue;
|
|
GouraudTexturedPolygon_ClipWithPositiveY();
|
|
if(RenderPolygon.NumberOfVertices<3) continue;
|
|
GouraudTexturedPolygon_ClipWithNegativeY();
|
|
if(RenderPolygon.NumberOfVertices<3) continue;
|
|
GouraudTexturedPolygon_ClipWithPositiveX();
|
|
if(RenderPolygon.NumberOfVertices<3) continue;
|
|
|
|
if (CurrTextureHandle == NULL)
|
|
D3D_ZBufferedGouraudPolygon_Output(&fakeHeader,RenderPolygon.Vertices);
|
|
else
|
|
D3D_ZBufferedGouraudTexturedPolygon_Output(&fakeHeader,RenderPolygon.Vertices);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if 0 /* not yet */
|
|
|
|
void D3D_DrawWaterOctagonPatch(int xOrigin, int yOrigin, int zOrigin, int xOffset, int zOffset)
|
|
{
|
|
float grad = 2.414213562373;
|
|
int i=0;
|
|
int x;
|
|
for (x=xOffset; x<16+xOffset; x++)
|
|
{
|
|
int z;
|
|
for(z=zOffset; z<16+zOffset; z++)
|
|
{
|
|
VECTORCH *point = &MeshVertex[i];
|
|
|
|
if (x>z)
|
|
{
|
|
float m,xs;
|
|
if (x!=0)
|
|
{
|
|
m = (float)(z)/(float)(x);
|
|
xs = grad/(grad+m);
|
|
}
|
|
else
|
|
{
|
|
xs = 0;
|
|
}
|
|
#if 1
|
|
f2i(point->vx , xs*x*MeshXScale);
|
|
f2i(point->vz , (grad-grad*xs)*x*MeshZScale);
|
|
#else
|
|
point->vx = xs*x*MeshXScale;
|
|
point->vz = (grad-grad*xs)*x*MeshZScale;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
float m,xs;
|
|
if (z!=0)
|
|
{
|
|
m = (float)(x)/(float)(z);
|
|
xs = grad/(grad+m);
|
|
}
|
|
else
|
|
{
|
|
xs = 0;
|
|
}
|
|
#if 1
|
|
f2i(point->vz , xs*z*MeshZScale);
|
|
f2i(point->vx , (grad-grad*xs)*z*MeshXScale);
|
|
#else
|
|
point->vz = xs*z*MeshZScale;
|
|
point->vx = (grad-grad*xs)*z*MeshXScale;
|
|
#endif
|
|
}
|
|
|
|
point->vx += xOrigin;
|
|
point->vz += zOrigin;
|
|
|
|
int offset = EffectOfRipples(point);
|
|
|
|
point->vy = yOrigin+offset;
|
|
|
|
#if 0
|
|
MeshVertexColour[i] = LightSourceWaterPoint(point,offset);
|
|
#else
|
|
{
|
|
int alpha = 128-offset/4;
|
|
// if (alpha>255) alpha = 255;
|
|
// if (alpha<128) alpha = 128;
|
|
switch (CurrentVisionMode)
|
|
{
|
|
default:
|
|
case VISION_MODE_NORMAL:
|
|
{
|
|
MeshVertexColour[i] = RGBALIGHT_MAKE(10,51,28,alpha);
|
|
break;
|
|
}
|
|
case VISION_MODE_IMAGEINTENSIFIER:
|
|
{
|
|
MeshVertexColour[i] = RGBALIGHT_MAKE(0,51,0,alpha);
|
|
break;
|
|
}
|
|
case VISION_MODE_PRED_THERMAL:
|
|
case VISION_MODE_PRED_SEEALIENS:
|
|
case VISION_MODE_PRED_SEEPREDTECH:
|
|
{
|
|
MeshVertexColour[i] = RGBALIGHT_MAKE(0,0,28,alpha);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
#endif
|
|
TranslatePointIntoViewspace(point);
|
|
/* is particle within normal view frustrum ? */
|
|
if(AvP.PlayerType==I_Alien) /* wide frustrum */
|
|
{
|
|
if(( (-point->vx <= point->vz*2)
|
|
&&(point->vx <= point->vz*2)
|
|
&&(-point->vy <= point->vz*2)
|
|
&&(point->vy <= point->vz*2) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(( (-point->vx <= point->vz)
|
|
&&(point->vx <= point->vz)
|
|
&&(-point->vy <= point->vz)
|
|
&&(point->vy <= point->vz) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
if ((MeshVertexOutcode[0]&&MeshVertexOutcode[15]&&MeshVertexOutcode[240]&&MeshVertexOutcode[255]))
|
|
{
|
|
D3D_DrawWaterMesh_Unclipped();
|
|
}
|
|
else
|
|
// else if (MeshVertexOutcode[0]||MeshVertexOutcode[15]||MeshVertexOutcode[240]||MeshVertexOutcode[255])
|
|
{
|
|
D3D_DrawWaterMesh_Clipped();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
#endif /* not yet */
|
|
|
|
void D3D_DrawCable(VECTORCH *centrePtr, MATRIXCH *orientationPtr)
|
|
{
|
|
int field;
|
|
|
|
CurrTextureHandle = NULL;
|
|
CheckBoundTextureIsCorrect(NULL);
|
|
CheckTranslucencyModeIsCorrect(TRANSLUCENCY_GLOWING);
|
|
glDepthMask(GL_FALSE);
|
|
|
|
MeshXScale = 4096/16;
|
|
MeshZScale = 4096/16;
|
|
|
|
for (field=0; field<3; field++)
|
|
{
|
|
int i=0;
|
|
int x;
|
|
for (x=(0+field*15); x<(16+field*15); x++)
|
|
{
|
|
int z;
|
|
for(z=0; z<16; z++)
|
|
{
|
|
VECTORCH *point = &MeshVertex[i];
|
|
{
|
|
int innerRadius = 20;
|
|
VECTORCH radius;
|
|
int theta = ((4096*z)/15)&4095;
|
|
int rOffset = GetSin((x*64+theta/32-CloakingPhase)&4095);
|
|
rOffset = MUL_FIXED(rOffset,rOffset)/512;
|
|
|
|
|
|
radius.vx = MUL_FIXED(innerRadius+rOffset/8,GetSin(theta));
|
|
radius.vy = MUL_FIXED(innerRadius+rOffset/8,GetCos(theta));
|
|
radius.vz = 0;
|
|
|
|
RotateVector(&radius,orientationPtr);
|
|
|
|
point->vx = centrePtr[x].vx+radius.vx;
|
|
point->vy = centrePtr[x].vy+radius.vy;
|
|
point->vz = centrePtr[x].vz+radius.vz;
|
|
|
|
MeshVertexColour[i] = RGBA_MAKE(0,rOffset,255,128);
|
|
|
|
}
|
|
|
|
TranslatePointIntoViewspace(point);
|
|
|
|
/* is particle within normal view frustrum ? */
|
|
if(AvP.PlayerType==I_Alien) /* wide frustrum */
|
|
{
|
|
if(( (-point->vx <= point->vz*2)
|
|
&&(point->vx <= point->vz*2)
|
|
&&(-point->vy <= point->vz*2)
|
|
&&(point->vy <= point->vz*2) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(( (-point->vx <= point->vz)
|
|
&&(point->vx <= point->vz)
|
|
&&(-point->vy <= point->vz)
|
|
&&(point->vy <= point->vz) ))
|
|
{
|
|
MeshVertexOutcode[i]=1;
|
|
}
|
|
else
|
|
{
|
|
MeshVertexOutcode[i]=0;
|
|
}
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
//textprint("\n");
|
|
if ((MeshVertexOutcode[0]&&MeshVertexOutcode[15]&&MeshVertexOutcode[240]&&MeshVertexOutcode[255]))
|
|
{
|
|
D3D_DrawMoltenMetalMesh_Unclipped();
|
|
// D3D_DrawWaterMesh_Unclipped();
|
|
}
|
|
else
|
|
// else if (MeshVertexOutcode[0]||MeshVertexOutcode[15]||MeshVertexOutcode[240]||MeshVertexOutcode[255])
|
|
{
|
|
D3D_DrawMoltenMetalMesh_Clipped();
|
|
// D3D_DrawWaterMesh_Clipped();
|
|
}
|
|
}
|
|
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
|
|
#if 0
|
|
/* ** menu-type stuff that should be moved later ** */
|
|
#include "avp_menugfx.hpp"
|
|
|
|
int Hardware_RenderSmallMenuText(char *textPtr, int x, int y, int alpha, enum AVPMENUFORMAT_ID format)
|
|
{
|
|
switch(format)
|
|
{
|
|
default:
|
|
// GLOBALASSERT("UNKNOWN TEXT FORMAT"==0);
|
|
case AVPMENUFORMAT_LEFTJUSTIFIED:
|
|
{
|
|
// supplied x is correct
|
|
break;
|
|
}
|
|
case AVPMENUFORMAT_RIGHTJUSTIFIED:
|
|
{
|
|
int length = 0;
|
|
char *ptr = textPtr;
|
|
|
|
while(*ptr)
|
|
{
|
|
length+=AAFontWidths[*ptr++];
|
|
}
|
|
|
|
x -= length;
|
|
break;
|
|
}
|
|
case AVPMENUFORMAT_CENTREJUSTIFIED:
|
|
{
|
|
int length = 0;
|
|
char *ptr = textPtr;
|
|
|
|
while(*ptr)
|
|
{
|
|
length+=AAFontWidths[*ptr++];
|
|
}
|
|
|
|
x -= length/2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// LOCALASSERT(x>0);
|
|
|
|
{
|
|
unsigned int colour = alpha>>8;
|
|
if (colour>255) colour = 255;
|
|
colour = (colour<<24)+0xffffff;
|
|
D3D_RenderHUDString(textPtr,x,y,colour);
|
|
}
|
|
return x;
|
|
}
|
|
|
|
void RenderBriefingText(int centreY, int brightness)
|
|
{
|
|
int lengthOfLongestLine=-1;
|
|
int x,y,i;
|
|
|
|
for(i=0; i<5; i++)
|
|
{
|
|
int length = 0;
|
|
{
|
|
char *ptr = BriefingTextString[i];
|
|
|
|
while(*ptr)
|
|
{
|
|
length+=AAFontWidths[*ptr++];
|
|
}
|
|
}
|
|
|
|
if (lengthOfLongestLine < length)
|
|
{
|
|
lengthOfLongestLine = length;
|
|
}
|
|
}
|
|
|
|
x = (ScreenDescriptorBlock.SDB_Width-lengthOfLongestLine)/2;
|
|
y = centreY - 3*HUD_FONT_HEIGHT;
|
|
for(i=0; i<5; i++)
|
|
{
|
|
// if (AvPMenus.MenusState != MENUSSTATE_MAINMENUS)
|
|
{
|
|
Hardware_RenderSmallMenuText(BriefingTextString[i], x, y, brightness, AVPMENUFORMAT_LEFTJUSTIFIED/*,MENU_CENTREY-60-100,MENU_CENTREY-60+180*/);
|
|
// }
|
|
// else
|
|
// {
|
|
// RenderSmallMenuText(BriefingTextString[i], x, y, brightness, AVPMENUFORMAT_LEFTJUSTIFIED);
|
|
// }
|
|
if (i) y+=HUD_FONT_HEIGHT;
|
|
else y+=HUD_FONT_HEIGHT*2;
|
|
}
|
|
}
|
|
#endif
|