8482bc2c52
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2724 fc73d0e0-1445-4013-8a0c-d673dee63da5
965 lines
23 KiB
C
965 lines
23 KiB
C
#include "quakedef.h"
|
|
#ifdef D3DQUAKE
|
|
#include "d3dquake.h"
|
|
#include "glquake.h"
|
|
|
|
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
|
|
extern mleaf_t *r_viewleaf2, *r_oldviewleaf2;
|
|
extern int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
|
|
extern qbyte areabits[MAX_Q2MAP_AREAS/8];
|
|
|
|
|
|
int r_visframecount;
|
|
entity_t r_worldentity;
|
|
refdef_t r_refdef;
|
|
vec3_t r_origin, vpn, vright, vup;
|
|
extern float r_projection_matrix[16];
|
|
extern float r_view_matrix[16];
|
|
|
|
|
|
//mplane_t frustum[4];
|
|
|
|
vec3_t modelorg;
|
|
|
|
entity_t *currententity;
|
|
extern cvar_t gl_mindist;
|
|
|
|
|
|
void (D3D_R_DeInit) (void)
|
|
{
|
|
}
|
|
void (D3D_R_ReInit) (void)
|
|
{
|
|
}
|
|
void (D3D_R_Init) (void)
|
|
{
|
|
D3D_R_ReInit();
|
|
}
|
|
|
|
//most of this is a direct copy from gl
|
|
void (D3D_SetupFrame) (void)
|
|
{
|
|
mleaf_t *leaf;
|
|
vec3_t temp;
|
|
|
|
GLR_AnimateLight();
|
|
AngleVectors (r_refdef.viewangles, vpn, vright, vup);
|
|
VectorCopy (r_refdef.vieworg, r_origin);
|
|
r_framecount++;
|
|
|
|
r_oldviewleaf = r_viewleaf;
|
|
r_oldviewleaf2 = r_viewleaf2;
|
|
r_viewleaf = GLMod_PointInLeaf (cl.worldmodel, r_origin);
|
|
|
|
if (!r_viewleaf)
|
|
{
|
|
}
|
|
else if (r_viewleaf->contents == Q1CONTENTS_EMPTY)
|
|
{ //look down a bit
|
|
VectorCopy (r_origin, temp);
|
|
temp[2] -= 16;
|
|
leaf = GLMod_PointInLeaf (cl.worldmodel, temp);
|
|
if (leaf->contents <= Q1CONTENTS_WATER && leaf->contents >= Q1CONTENTS_LAVA)
|
|
r_viewleaf2 = leaf;
|
|
else
|
|
r_viewleaf2 = NULL;
|
|
}
|
|
else if (r_viewleaf->contents <= Q1CONTENTS_WATER && r_viewleaf->contents >= Q1CONTENTS_LAVA)
|
|
{ //in water, look up a bit.
|
|
|
|
VectorCopy (r_origin, temp);
|
|
temp[2] += 16;
|
|
leaf = GLMod_PointInLeaf (cl.worldmodel, temp);
|
|
if (leaf->contents == Q1CONTENTS_EMPTY)
|
|
r_viewleaf2 = leaf;
|
|
else
|
|
r_viewleaf2 = NULL;
|
|
}
|
|
else
|
|
r_viewleaf2 = NULL;
|
|
|
|
if (r_viewleaf)
|
|
V_SetContentsColor (r_viewleaf->contents);
|
|
}
|
|
|
|
void D3D_SetupViewPort(void)
|
|
{
|
|
float screenaspect;
|
|
int glwidth = vid.width, glheight=vid.height;
|
|
int x, x2, y2, y, w, h;
|
|
|
|
float fov_x, fov_y;
|
|
|
|
D3DVIEWPORT7 vport;
|
|
|
|
D3D_GetBufferSize(&glwidth, &glheight);
|
|
|
|
//
|
|
// set up viewpoint
|
|
//
|
|
x = r_refdef.vrect.x * glwidth/(int)vid.width;
|
|
x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/(int)vid.width;
|
|
y = (/*vid.height-*/r_refdef.vrect.y) * glheight/(int)vid.height;
|
|
y2 = ((int)/*vid.height - */(r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/(int)vid.height;
|
|
|
|
// fudge around because of frac screen scale
|
|
if (x > 0)
|
|
x--;
|
|
if (x2 < glwidth)
|
|
x2++;
|
|
if (y < 0)
|
|
y--;
|
|
if (y2 < glheight)
|
|
y2++;
|
|
|
|
w = x2 - x;
|
|
h = y2 - y;
|
|
|
|
/* if (envmap)
|
|
{
|
|
x = y2 = 0;
|
|
w = h = 256;
|
|
}
|
|
*/
|
|
|
|
vport.dwX = x;
|
|
vport.dwY = y;
|
|
vport.dwWidth = w;
|
|
vport.dwHeight = h;
|
|
vport.dvMinZ = 0;
|
|
vport.dvMaxZ = 1;
|
|
pD3DDev->lpVtbl->SetViewport(pD3DDev, &vport);
|
|
|
|
fov_x = r_refdef.fov_x;//+sin(cl.time)*5;
|
|
fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5;
|
|
|
|
if (r_waterwarp.value<0 && r_viewleaf->contents <= Q1CONTENTS_WATER)
|
|
{
|
|
fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
|
|
fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
|
|
}
|
|
|
|
screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
|
|
// if (r_refdef.useperspective)
|
|
{
|
|
/* if ((!r_shadows.value || !gl_canstencil) && gl_maxdist.value>256)//gl_nv_range_clamp)
|
|
{
|
|
// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
|
|
// yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect;
|
|
// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov.value*2)/M_PI;
|
|
// MYgluPerspective (yfov, screenaspect, 4, 4096);
|
|
MYgluPerspective (fov_x, fov_y, gl_mindist.value, gl_maxdist.value);
|
|
}
|
|
else*/
|
|
{
|
|
GL_InfinatePerspective(fov_x, fov_y, gl_mindist.value);
|
|
}
|
|
}
|
|
/* else
|
|
{
|
|
if (gl_maxdist.value>=1)
|
|
GL_ParallelPerspective(-fov_x/2, fov_x/2, fov_y/2, -fov_y/2, -gl_maxdist.value, gl_maxdist.value);
|
|
else
|
|
GL_ParallelPerspective(0, r_refdef.vrect.width, 0, r_refdef.vrect.height, -9999, 9999);
|
|
}*/
|
|
|
|
Matrix4_ModelViewMatrixFromAxis(r_view_matrix, vpn, vright, vup, r_refdef.vieworg);
|
|
|
|
|
|
pD3DDev->lpVtbl->SetTransform(pD3DDev, D3DTRANSFORMSTATE_PROJECTION, (D3DMATRIX*)r_projection_matrix);
|
|
pD3DDev->lpVtbl->SetTransform(pD3DDev, D3DTRANSFORMSTATE_VIEW, (D3DMATRIX*)r_view_matrix);
|
|
|
|
|
|
pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
|
|
pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
qbyte *Q1BSP_LeafPVS (model_t *model, mleaf_t *leaf, qbyte *buffer);
|
|
|
|
|
|
|
|
//fixme: direct copy from gl (apart from lightmaps)
|
|
static void D3D7_RecursiveWorldNode (mnode_t *node)
|
|
{
|
|
int c, side;
|
|
mplane_t *plane;
|
|
msurface_t *surf, **mark;
|
|
mleaf_t *pleaf;
|
|
double dot;
|
|
int shift;
|
|
|
|
start:
|
|
|
|
if (node->contents == Q1CONTENTS_SOLID)
|
|
return; // solid
|
|
|
|
if (node->visframe != r_visframecount)
|
|
return;
|
|
if (R_CullBox (node->minmaxs, node->minmaxs+3))
|
|
return;
|
|
|
|
// if a leaf node, draw stuff
|
|
if (node->contents < 0)
|
|
{
|
|
pleaf = (mleaf_t *)node;
|
|
|
|
mark = pleaf->firstmarksurface;
|
|
c = pleaf->nummarksurfaces;
|
|
|
|
if (c)
|
|
{
|
|
do
|
|
{
|
|
(*mark++)->visframe = r_framecount;
|
|
} while (--c);
|
|
}
|
|
|
|
// deal with model fragments in this leaf
|
|
if (pleaf->efrags)
|
|
R_StoreEfrags (&pleaf->efrags);
|
|
return;
|
|
}
|
|
|
|
// node is just a decision point, so go down the apropriate sides
|
|
|
|
// find which side of the node we are on
|
|
plane = node->plane;
|
|
|
|
switch (plane->type)
|
|
{
|
|
case PLANE_X:
|
|
dot = modelorg[0] - plane->dist;
|
|
break;
|
|
case PLANE_Y:
|
|
dot = modelorg[1] - plane->dist;
|
|
break;
|
|
case PLANE_Z:
|
|
dot = modelorg[2] - plane->dist;
|
|
break;
|
|
default:
|
|
dot = DotProduct (modelorg, plane->normal) - plane->dist;
|
|
break;
|
|
}
|
|
|
|
if (dot >= 0)
|
|
side = 0;
|
|
else
|
|
side = 1;
|
|
|
|
// recurse down the children, front side first
|
|
D3D7_RecursiveWorldNode (node->children[side]);
|
|
|
|
// draw stuff
|
|
c = node->numsurfaces;
|
|
|
|
if (c)
|
|
{
|
|
surf = cl.worldmodel->surfaces + node->firstsurface;
|
|
|
|
shift = 0;//GLR_LightmapShift(cl.worldmodel);
|
|
|
|
// if (dot < 0 -BACKFACE_EPSILON)
|
|
// side = SURF_PLANEBACK;
|
|
// else if (dot > BACKFACE_EPSILON)
|
|
// side = 0;
|
|
{
|
|
for ( ; c ; c--, surf++)
|
|
{
|
|
if (surf->visframe != r_framecount)
|
|
continue;
|
|
|
|
// if (((dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)))
|
|
// continue; // wrong side
|
|
|
|
D3DR_RenderDynamicLightmaps (surf, shift);
|
|
// if sorting by texture, just store it out
|
|
/* if (surf->flags & SURF_DRAWALPHA)
|
|
{ // add to the translucent chain
|
|
surf->nextalphasurface = r_alpha_surfaces;
|
|
r_alpha_surfaces = surf;
|
|
surf->ownerent = &r_worldentity;
|
|
}
|
|
else
|
|
*/ {
|
|
surf->texturechain = surf->texinfo->texture->texturechain;
|
|
surf->texinfo->texture->texturechain = surf;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// recurse down the back side
|
|
// GLR_RecursiveWorldNode (node->children[!side]);
|
|
node = node->children[!side];
|
|
goto start;
|
|
}
|
|
|
|
struct {
|
|
float x, y, z;
|
|
// unsigned colour;
|
|
float wms, wmt;
|
|
float lms, lmt;
|
|
} worldvert[64];
|
|
void D3D_DrawTextureChains(void)
|
|
{
|
|
texture_t *t;
|
|
msurface_t *s;
|
|
vec3_t *xyz;
|
|
vec2_t *wm;
|
|
vec2_t *lm;
|
|
mesh_t *m;
|
|
int i;
|
|
int v;
|
|
int lmnum;
|
|
extern int skytexturenum; // index in cl.loadmodel, not gl texture object
|
|
|
|
if (skytexturenum>=0)
|
|
{
|
|
t = currentmodel->textures[skytexturenum];
|
|
if (t)
|
|
{
|
|
s = t->texturechain;
|
|
if (s)
|
|
{
|
|
t->texturechain = NULL;
|
|
D3D7_DrawSkyChain (s);
|
|
}
|
|
}
|
|
}
|
|
|
|
pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, FALSE );
|
|
for (i = 0; i < currentmodel->numtextures; i++)
|
|
{
|
|
t = currentmodel->textures[i];
|
|
if (!t)
|
|
continue; //happens on e1m2
|
|
s = t->texturechain;
|
|
if (!s)
|
|
continue;
|
|
t->texturechain = NULL;
|
|
|
|
pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, (LPDIRECTDRAWSURFACE7)t->gl_texturenum);
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_TEXCOORDINDEX, 0);
|
|
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
|
|
|
|
while(s)
|
|
{
|
|
m = s->mesh;
|
|
if (m)
|
|
{
|
|
|
|
lmnum = s->lightmaptexturenum;
|
|
if (lmnum >= 0)
|
|
{
|
|
if (lightmap[lmnum]->modified)
|
|
{
|
|
DDSURFACEDESC2 desc;
|
|
|
|
desc.dwSize = sizeof(desc);
|
|
lightmap_d3dtextures[lmnum]->lpVtbl->Lock(lightmap_d3dtextures[lmnum], NULL, &desc, DDLOCK_NOSYSLOCK|DDLOCK_WAIT|DDLOCK_WRITEONLY|DDLOCK_DISCARDCONTENTS, NULL);
|
|
memcpy(desc.lpSurface, lightmap[lmnum]->lightmaps, LMBLOCK_WIDTH*LMBLOCK_HEIGHT*4);
|
|
/* {
|
|
int i;
|
|
unsigned char *c;
|
|
unsigned char v;
|
|
c = desc.lpSurface;
|
|
for (i = 0; i < LMBLOCK_WIDTH*LMBLOCK_HEIGHT; i++)
|
|
{
|
|
v = rand();
|
|
*c++ = v;
|
|
*c++ = v;
|
|
*c++ = v;
|
|
c++;
|
|
}
|
|
}*/
|
|
lightmap_d3dtextures[lmnum]->lpVtbl->Unlock(lightmap_d3dtextures[lmnum], NULL);
|
|
|
|
lightmap[lmnum]->modified = false;
|
|
}
|
|
|
|
|
|
pD3DDev->lpVtbl->SetTexture(pD3DDev, 1, (LPDIRECTDRAWSURFACE7)lightmap_d3dtextures[lmnum]);
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_TEXCOORDINDEX, 1);
|
|
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
|
|
}
|
|
else
|
|
{
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|
}
|
|
|
|
//pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|
|
|
xyz = m->xyz_array;
|
|
wm = m->st_array;
|
|
lm = m->lmst_array;
|
|
|
|
for (v = 0; v < m->numvertexes; v++, xyz++, wm++, lm++)
|
|
{
|
|
worldvert[v].x = (*xyz)[0];
|
|
worldvert[v].y = (*xyz)[1];
|
|
worldvert[v].z = (*xyz)[2];
|
|
// worldvert[v].colour = 0;
|
|
worldvert[v].wms = (*wm)[0];
|
|
worldvert[v].wmt = (*wm)[1];
|
|
worldvert[v].lms = (*lm)[0];
|
|
worldvert[v].lmt = (*lm)[1];
|
|
}
|
|
|
|
pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_TEX2, worldvert, m->numvertexes, m->indexes, m->numindexes, 0);
|
|
}
|
|
s = s->texturechain;
|
|
}
|
|
}
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|
pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, TRUE );
|
|
}
|
|
|
|
void D3D_BaseBModelTextures(entity_t *e)
|
|
{
|
|
texture_t *t;
|
|
msurface_t *s;
|
|
vec3_t *xyz;
|
|
vec2_t *wm;
|
|
vec2_t *lm;
|
|
mesh_t *m;
|
|
int i;
|
|
int v;
|
|
float matrix[16];
|
|
int lmnum = -1;
|
|
currentmodel = e->model;
|
|
|
|
|
|
for (s = currentmodel->surfaces+currentmodel->firstmodelsurface, i = 0; i < currentmodel->nummodelsurfaces; i++, s++)
|
|
{
|
|
t = R_TextureAnimation(s->texinfo->texture);
|
|
|
|
{
|
|
m = s->mesh;
|
|
if (m)
|
|
D3DR_RenderDynamicLightmaps (s, 0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Matrix4_ModelMatrixFromAxis(matrix, e->axis[0], e->axis[1], e->axis[2], e->origin);
|
|
pD3DDev->lpVtbl->SetTransform(pD3DDev, D3DTRANSFORMSTATE_WORLD, (D3DMATRIX*)matrix);
|
|
|
|
pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, FALSE );
|
|
for (s = currentmodel->surfaces+currentmodel->firstmodelsurface, i = 0; i < currentmodel->nummodelsurfaces; i++, s++)
|
|
{
|
|
t = R_TextureAnimation(s->texinfo->texture);
|
|
|
|
pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, (LPDIRECTDRAWSURFACE7)t->gl_texturenum);
|
|
pD3DDev->lpVtbl->SetTexture(pD3DDev, 1, (LPDIRECTDRAWSURFACE7)lightmap_d3dtextures[s->lightmaptexturenum]);
|
|
{
|
|
m = s->mesh;
|
|
if (m)
|
|
{
|
|
|
|
if (lmnum != s->lightmaptexturenum)
|
|
{
|
|
lmnum = s->lightmaptexturenum;
|
|
if (lmnum >= 0)
|
|
{
|
|
if (lightmap[lmnum]->modified)
|
|
{
|
|
DDSURFACEDESC2 desc;
|
|
|
|
desc.dwSize = sizeof(desc);
|
|
lightmap_d3dtextures[lmnum]->lpVtbl->Lock(lightmap_d3dtextures[lmnum], NULL, &desc, DDLOCK_NOSYSLOCK|DDLOCK_WAIT|DDLOCK_WRITEONLY|DDLOCK_DISCARDCONTENTS, NULL);
|
|
memcpy(desc.lpSurface, lightmap[lmnum]->lightmaps, LMBLOCK_WIDTH*LMBLOCK_HEIGHT*4);
|
|
/* {
|
|
int i;
|
|
unsigned char *c;
|
|
unsigned char v;
|
|
c = desc.lpSurface;
|
|
for (i = 0; i < LMBLOCK_WIDTH*LMBLOCK_HEIGHT; i++)
|
|
{
|
|
v = rand();
|
|
*c++ = v;
|
|
*c++ = v;
|
|
*c++ = v;
|
|
c++;
|
|
}
|
|
}*/
|
|
lightmap_d3dtextures[lmnum]->lpVtbl->Unlock(lightmap_d3dtextures[lmnum], NULL);
|
|
|
|
lightmap[lmnum]->modified = false;
|
|
}
|
|
|
|
|
|
pD3DDev->lpVtbl->SetTexture(pD3DDev, 1, (LPDIRECTDRAWSURFACE7)lightmap_d3dtextures[lmnum]);
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_TEXCOORDINDEX, 1);
|
|
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
|
|
}
|
|
else
|
|
{
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
xyz = m->xyz_array;
|
|
wm = m->st_array;
|
|
lm = m->lmst_array;
|
|
|
|
for (v = 0; v < m->numvertexes; v++, xyz++, wm++, lm++)
|
|
{
|
|
worldvert[v].x = (*xyz)[0];
|
|
worldvert[v].y = (*xyz)[1];
|
|
worldvert[v].z = (*xyz)[2];
|
|
// worldvert[v].colour = 0;
|
|
worldvert[v].wms = (*wm)[0];
|
|
worldvert[v].wmt = (*wm)[1];
|
|
worldvert[v].lms = (*lm)[0];
|
|
worldvert[v].lmt = (*lm)[1];
|
|
}
|
|
|
|
pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_TEX2, worldvert, m->numvertexes, m->indexes, m->numindexes, 0);
|
|
}
|
|
}
|
|
}
|
|
pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, TRUE );
|
|
|
|
pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|
|
|
|
|
pD3DDev->lpVtbl->SetTransform(pD3DDev, D3DTRANSFORMSTATE_WORLD, (D3DMATRIX*)matrix);
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
|
float pos[3];
|
|
int colour;
|
|
float tc[2];
|
|
} d3dvert_t;
|
|
/*
|
|
================
|
|
R_GetSpriteFrame
|
|
================
|
|
*/
|
|
/*
|
|
mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
|
|
{
|
|
msprite_t *psprite;
|
|
mspritegroup_t *pspritegroup;
|
|
mspriteframe_t *pspriteframe;
|
|
int i, numframes, frame;
|
|
float *pintervals, fullinterval, targettime, time;
|
|
|
|
psprite = currententity->model->cache.data;
|
|
frame = currententity->frame;
|
|
|
|
if ((frame >= psprite->numframes) || (frame < 0))
|
|
{
|
|
Con_DPrintf ("R_DrawSprite: no such frame %d (%s)\n", frame, currententity->model->name);
|
|
frame = 0;
|
|
}
|
|
|
|
if (psprite->frames[frame].type == SPR_SINGLE)
|
|
{
|
|
pspriteframe = psprite->frames[frame].frameptr;
|
|
}
|
|
else if (psprite->frames[frame].type == SPR_ANGLED)
|
|
{
|
|
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
|
|
pspriteframe = pspritegroup->frames[(int)((r_refdef.viewangles[1]-currententity->angles[1])/360*8 + 0.5-4)&7];
|
|
}
|
|
else
|
|
{
|
|
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
|
|
pintervals = pspritegroup->intervals;
|
|
numframes = pspritegroup->numframes;
|
|
fullinterval = pintervals[numframes-1];
|
|
|
|
time = currententity->frame1time;
|
|
|
|
// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
|
|
// are positive, so we don't have to worry about division by 0
|
|
targettime = time - ((int)(time / fullinterval)) * fullinterval;
|
|
|
|
for (i=0 ; i<(numframes-1) ; i++)
|
|
{
|
|
if (pintervals[i] > targettime)
|
|
break;
|
|
}
|
|
|
|
pspriteframe = pspritegroup->frames[i];
|
|
}
|
|
|
|
return pspriteframe;
|
|
}
|
|
*/
|
|
static void D3D_DrawSpriteModel (entity_t *e)
|
|
{
|
|
vec3_t point;
|
|
mspriteframe_t *frame;
|
|
vec3_t forward, right, up;
|
|
msprite_t *psprite;
|
|
|
|
d3dvert_t d3dvert[4];
|
|
index_t vertindexes[6] = {
|
|
0, 1, 2,
|
|
0, 2, 3
|
|
};
|
|
|
|
if (!e->model)
|
|
return;
|
|
|
|
if (e->flags & RF_NODEPTHTEST)
|
|
pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ZFUNC, D3DCMP_ALWAYS);
|
|
|
|
// don't even bother culling, because it's just a single
|
|
// polygon without a surface cache
|
|
frame = R_GetSpriteFrame (e);
|
|
psprite = e->model->cache.data;
|
|
// frame = 0x05b94140;
|
|
|
|
switch(psprite->type)
|
|
{
|
|
case SPR_ORIENTED:
|
|
// bullet marks on walls
|
|
AngleVectors (e->angles, forward, right, up);
|
|
break;
|
|
|
|
case SPR_FACING_UPRIGHT:
|
|
up[0] = 0;up[1] = 0;up[2]=1;
|
|
right[0] = e->origin[1] - r_origin[1];
|
|
right[1] = -(e->origin[0] - r_origin[0]);
|
|
right[2] = 0;
|
|
VectorNormalize (right);
|
|
break;
|
|
case SPR_VP_PARALLEL_UPRIGHT:
|
|
up[0] = 0;up[1] = 0;up[2]=1;
|
|
VectorCopy (vright, right);
|
|
break;
|
|
|
|
default:
|
|
case SPR_VP_PARALLEL:
|
|
//normal sprite
|
|
VectorCopy(vup, up);
|
|
VectorCopy(vright, right);
|
|
break;
|
|
}
|
|
up[0]*=e->scale;
|
|
up[1]*=e->scale;
|
|
up[2]*=e->scale;
|
|
right[0]*=e->scale;
|
|
right[1]*=e->scale;
|
|
right[2]*=e->scale;
|
|
|
|
pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, (LPDIRECTDRAWSURFACE7)frame->gl_texturenum);
|
|
|
|
/* {
|
|
extern int gldepthfunc;
|
|
qglDepthFunc(gldepthfunc);
|
|
qglDepthMask(0);
|
|
if (gldepthmin == 0.5)
|
|
qglCullFace ( GL_BACK );
|
|
else
|
|
qglCullFace ( GL_FRONT );
|
|
|
|
GL_TexEnv(GL_MODULATE);
|
|
|
|
qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
qglDisable (GL_ALPHA_TEST);
|
|
qglDisable(GL_BLEND);
|
|
}*/
|
|
|
|
/* if (e->flags & Q2RF_ADDATIVE)
|
|
{
|
|
qglEnable(GL_BLEND);
|
|
qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
}
|
|
else if (e->shaderRGBAf[3]<1 || gl_blendsprites.value)
|
|
{
|
|
qglEnable(GL_BLEND);
|
|
qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
}
|
|
else
|
|
qglEnable (GL_ALPHA_TEST);
|
|
*/
|
|
|
|
d3dvert[0].colour = 0xffffffff;
|
|
d3dvert[0].tc[0] = 0;
|
|
d3dvert[0].tc[1] = 1;
|
|
VectorMA (e->origin, frame->down, up, point);
|
|
VectorMA (point, frame->left, right, d3dvert[0].pos);
|
|
|
|
d3dvert[1].colour = 0xffffffff;
|
|
d3dvert[1].tc[0] = 0;
|
|
d3dvert[1].tc[0] = 0;
|
|
VectorMA (e->origin, frame->up, up, point);
|
|
VectorMA (point, frame->left, right, d3dvert[1].pos);
|
|
|
|
d3dvert[2].colour = 0xffffffff;
|
|
d3dvert[2].tc[0] = 1;
|
|
d3dvert[2].tc[1] = 0;
|
|
VectorMA (e->origin, frame->up, up, point);
|
|
VectorMA (point, frame->right, right, d3dvert[2].pos);
|
|
|
|
d3dvert[3].colour = 0xffffffff;
|
|
d3dvert[3].tc[0] = 1;
|
|
d3dvert[3].tc[1] = 1;
|
|
VectorMA (e->origin, frame->down, up, point);
|
|
VectorMA (point, frame->right, right, d3dvert[3].pos);
|
|
|
|
|
|
pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLEFAN, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dvert, 4, vertindexes, 6, 0);
|
|
|
|
|
|
if (e->flags & RF_NODEPTHTEST)
|
|
pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
|
|
|
|
// if (e->flags & Q2RF_ADDATIVE) //back to regular blending for us!
|
|
// qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
|
|
//==================================================================================
|
|
|
|
void D3DR_DrawSprite(void *e, void *parm)
|
|
{
|
|
currententity = e;
|
|
|
|
D3D_DrawSpriteModel (currententity);
|
|
|
|
// P_FlushRenderer();
|
|
}
|
|
|
|
|
|
|
|
qboolean D3D_ShouldDraw(void)
|
|
{
|
|
{
|
|
if (currententity->flags & Q2RF_EXTERNALMODEL)
|
|
return false;
|
|
// if (currententity->keynum == (cl.viewentity[r_refdef.currentplayernum]?cl.viewentity[r_refdef.currentplayernum]:(cl.playernum[r_refdef.currentplayernum]+1)))
|
|
// return false;
|
|
// if (cl.viewentity[r_refdef.currentplayernum] && currententity->keynum == cl.viewentity[r_refdef.currentplayernum])
|
|
// continue;
|
|
if (!Cam_DrawPlayer(r_refdef.currentplayernum, currententity->keynum-1))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
void D3DR_DrawEntitiesOnList (void)
|
|
{
|
|
int i;
|
|
|
|
if (!r_drawentities.value)
|
|
return;
|
|
|
|
// draw sprites seperately, because of alpha blending
|
|
for (i=0 ; i<cl_numvisedicts ; i++)
|
|
{
|
|
currententity = &cl_visedicts[i];
|
|
|
|
if (!D3D_ShouldDraw())
|
|
continue;
|
|
|
|
|
|
switch (currententity->rtype)
|
|
{
|
|
case RT_SPRITE:
|
|
RQ_AddDistReorder(D3DR_DrawSprite, currententity, NULL, currententity->origin);
|
|
continue;
|
|
#ifdef Q3SHADERS
|
|
case RT_BEAM:
|
|
case RT_RAIL_RINGS:
|
|
case RT_LIGHTNING:
|
|
R_DrawLightning(currententity);
|
|
continue;
|
|
case RT_RAIL_CORE:
|
|
R_DrawRailCore(currententity);
|
|
continue;
|
|
#endif
|
|
case RT_MODEL: //regular model
|
|
break;
|
|
case RT_PORTALSURFACE:
|
|
continue; //this doesn't do anything anyway, does it?
|
|
default:
|
|
case RT_POLY: //these are a little painful, we need to do them some time... just not yet.
|
|
continue;
|
|
}
|
|
if (currententity->flags & Q2RF_BEAM)
|
|
{
|
|
// R_DrawBeam(currententity);
|
|
continue;
|
|
}
|
|
if (!currententity->model)
|
|
continue;
|
|
|
|
|
|
if (cl.lerpents && (cls.allow_anyparticles || currententity->visframe)) //allowed or static
|
|
{
|
|
/* if (gl_part_flame.value)
|
|
{
|
|
if (currententity->model->engineflags & MDLF_ENGULPHS)
|
|
continue;
|
|
}*/
|
|
}
|
|
|
|
switch (currententity->model->type)
|
|
{
|
|
|
|
case mod_alias:
|
|
// if (r_refdef.flags & Q2RDF_NOWORLDMODEL || !cl.worldmodel || cl.worldmodel->type != mod_brush || cl.worldmodel->fromgame == fg_doom)
|
|
D3D_DrawAliasModel ();
|
|
break;
|
|
|
|
#ifdef HALFLIFEMODELS
|
|
case mod_halflife:
|
|
R_DrawHLModel (currententity);
|
|
break;
|
|
#endif
|
|
|
|
case mod_brush:
|
|
// if (!cl.worldmodel || cl.worldmodel->type != mod_brush || cl.worldmodel->fromgame == fg_doom)
|
|
D3D_BaseBModelTextures (currententity);
|
|
break;
|
|
|
|
case mod_sprite:
|
|
RQ_AddDistReorder(D3DR_DrawSprite, currententity, NULL, currententity->origin);
|
|
break;
|
|
/*
|
|
#ifdef TERRAIN
|
|
case mod_heightmap:
|
|
D3D_DrawHeightmapModel(currententity);
|
|
break;
|
|
#endif
|
|
*/
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
{
|
|
float m_identity[16] = {
|
|
1, 0, 0, 0,
|
|
0, 1, 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1
|
|
};
|
|
pD3DDev->lpVtbl->SetTransform(pD3DDev, D3DTRANSFORMSTATE_WORLD, (D3DMATRIX*)m_identity);
|
|
}
|
|
}
|
|
|
|
void D3D_DrawWorld(void)
|
|
{
|
|
RSpeedLocals();
|
|
entity_t ent;
|
|
|
|
memset (&ent, 0, sizeof(ent));
|
|
ent.model = cl.worldmodel;
|
|
currentmodel = cl.worldmodel;
|
|
|
|
VectorCopy (r_refdef.vieworg, modelorg);
|
|
|
|
currententity = &ent;
|
|
#ifdef TERRAIN
|
|
// FIXME: Dunno what needs to be fixed here?
|
|
// if (currentmodel->type == mod_heightmap)
|
|
// D3D_DrawHeightmapModel(currententity);
|
|
// else
|
|
#endif
|
|
{
|
|
// qglColor3f (1,1,1);
|
|
//#ifdef QUAKE2
|
|
// R_ClearSkyBox ();
|
|
//#endif
|
|
|
|
RSpeedRemark();
|
|
/*
|
|
#ifdef Q2BSPS
|
|
if (ent.model->fromgame == fg_quake2 || ent.model->fromgame == fg_quake3)
|
|
{
|
|
int leafnum;
|
|
int clientarea;
|
|
#ifdef QUAKE2
|
|
if (cls.protocol == CP_QUAKE2) //we can get server sent info
|
|
memcpy(areabits, cl.q2frame.areabits, sizeof(areabits));
|
|
else
|
|
#endif
|
|
{ //generate the info each frame.
|
|
leafnum = CM_PointLeafnum (cl.worldmodel, r_refdef.vieworg);
|
|
clientarea = CM_LeafArea (cl.worldmodel, leafnum);
|
|
CM_WriteAreaBits(cl.worldmodel, areabits, clientarea);
|
|
}
|
|
#ifdef Q3BSPS
|
|
if (ent.model->fromgame == fg_quake3)
|
|
{
|
|
D3D7_LeafWorldNode ();
|
|
}
|
|
else
|
|
#endif
|
|
D3D7_RecursiveQ2WorldNode (cl.worldmodel->nodes);
|
|
}
|
|
else
|
|
#endif
|
|
*/
|
|
D3D7_RecursiveWorldNode (cl.worldmodel->nodes);
|
|
|
|
RSpeedEnd(RSPEED_WORLDNODE);
|
|
TRACE(("dbg: calling PPL_DrawWorld\n"));
|
|
// if (r_shadows.value >= 2 && gl_canstencil && gl_mtexable)
|
|
D3D_DrawTextureChains();
|
|
// else
|
|
// DrawTextureChains (cl.worldmodel, 1, r_refdef.vieworg);
|
|
|
|
|
|
//qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
|
|
// GLR_LessenStains();
|
|
}
|
|
}
|
|
|
|
void D3D_R_RenderScene(void)
|
|
{
|
|
if (!cl.worldmodel || (!cl.worldmodel->nodes && cl.worldmodel->type != mod_heightmap))
|
|
r_refdef.flags |= Q2RDF_NOWORLDMODEL;
|
|
|
|
if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL))
|
|
{
|
|
R_MarkLeaves (); // done here so we know if we're in water
|
|
D3D_DrawWorld (); // adds static entities to the list
|
|
}
|
|
|
|
D3DR_DrawEntitiesOnList ();
|
|
|
|
P_DrawParticles();
|
|
}
|
|
|
|
void (D3D_R_RenderView) (void)
|
|
{
|
|
D3D_SetupFrame();
|
|
D3D_SetupViewPort();
|
|
R_SetFrustum();
|
|
D3D_R_RenderScene();
|
|
}
|
|
#endif
|