#include "quakedef.h" #ifdef D3DQUAKE #include "d3dquake.h" #include "glquake.h" #include "renderque.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 (D3D7_R_DeInit) (void) { } void (D3D7_R_ReInit) (void) { } void (D3D7_R_Init) (void) { D3D7_R_ReInit(); } //most of this is a direct copy from gl void (D3D7_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 D3D7_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; D3D7_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 D3D7_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->tn.base); 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 D3D7_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->tn.base); 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 D3D7_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->p.d.data); /* { 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 D3D7R_DrawSprite(int count, void **e, void *parm) { while(count--) { currententity = *e++; D3D7_DrawSpriteModel (currententity); } } qboolean D3D7_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 D3D7R_DrawEntitiesOnList (void) { int i; if (!r_drawentities.value) return; // draw sprites seperately, because of alpha blending for (i=0 ; irtype) { case RT_SPRITE: RQ_AddDistReorder(D3D7R_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) D3D7_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) D3D7_BaseBModelTextures (currententity); break; case mod_sprite: RQ_AddDistReorder(D3D7R_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 D3D7_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) { R_MarkLeaves_Q3 (); D3D7_LeafWorldNode (); } else #endif { R_MarkLeaves_Q2 (); D3D7_RecursiveQ2WorldNode (cl.worldmodel->nodes); } } else #endif */ { R_MarkLeaves_Q1 (); D3D7_RecursiveWorldNode (cl.worldmodel->nodes); } RSpeedEnd(RSPEED_WORLDNODE); TRACE(("dbg: calling PPL_DrawWorld\n")); // if (r_shadows.value >= 2 && gl_canstencil && gl_mtexable) D3D7_DrawTextureChains(); // else // DrawTextureChains (cl.worldmodel, 1, r_refdef.vieworg); //qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // GLR_LessenStains(); } } void D3D7_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)) { D3D7_DrawWorld (); // adds static entities to the list } D3D7R_DrawEntitiesOnList (); P_DrawParticles(); } void (D3D7_R_RenderView) (void) { D3D7_SetupFrame(); D3D7_SetupViewPort(); R_SetFrustum(); D3D7_R_RenderScene(); } #ifdef PSET_SCRIPT #include "particles.h" #define TYPESONLY #include "p_script.c" #define APPLYD3DBLEND(bm) \ switch (bm) \ { \ case BM_ADD: \ pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA); \ pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE); \ break; \ case BM_SUBTRACT: \ pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA); \ pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR); \ break; \ case BM_BLENDCOLOUR: \ pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCCOLOR); \ pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR); \ break; \ case BM_BLEND: \ default: \ pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA); \ pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA); \ break; \ } extern vec3_t pright, pup; static float particletime; typedef struct d3dparticlevert_s { float org[3]; unsigned int colour; float s, t; //these could actually be preinitialised } d3dparticlevert_t; static d3dparticlevert_t d3dparticlevert[4]; typedef struct d3dparticlevertut_s { float org[3]; unsigned int colour; } d3dparticlevertut_t; static d3dparticlevertut_t d3dparticlevertut[4]; static unsigned short d3dparticlevertindexes[] = { 0, 1, 2, 0, 2, 3 }; static void D3D_DrawParticleBlob(int count, particle_t **plist, plooks_t *type) { float scale; float x; float y; unsigned int colour; int cb, cg, cr, ca; particle_t *p; pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, type->d3dtexture); 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_MODULATE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); APPLYD3DBLEND(type->blendmode); while(count--) { p = *plist++; scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + (p->org[2] - r_origin[2])*vpn[2]; scale = (scale*p->scale)*(type->invscalefactor) + p->scale * (type->scalefactor*250); if (scale < 20) scale = 0.25; else scale = 0.25 + scale * 0.001; cr = p->rgb[0]*255; if (cr < 0) cr = 0; if (cr > 255) cr = 255; cg = p->rgb[1]*255; if (cg < 0) cg = 0; if (cg > 255) cg = 255; cb = p->rgb[2]*255; if (cb < 0) cb = 0; if (cb > 255) cb = 255; ca = p->alpha*255; if (ca < 0) ca = 0; if (ca > 255) ca = 255; colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); if (p->angle) { x = sin(p->angle)*scale; y = cos(p->angle)*scale; } else { x = 0; y = scale; } d3dparticlevert[0].s = 0; d3dparticlevert[0].t = 0; d3dparticlevert[0].colour = colour; d3dparticlevert[0].org[0] = p->org[0] - x*pright[0] - y*pup[0]; d3dparticlevert[0].org[1] = p->org[1] - x*pright[1] - y*pup[1]; d3dparticlevert[0].org[2] = p->org[2] - x*pright[2] - y*pup[2]; d3dparticlevert[1].s = 0; d3dparticlevert[1].t = 1; d3dparticlevert[1].colour = colour; d3dparticlevert[1].org[0] = p->org[0] - y*pright[0] + x*pup[0]; d3dparticlevert[1].org[1] = p->org[1] - y*pright[1] + x*pup[1]; d3dparticlevert[1].org[2] = p->org[2] - y*pright[2] + x*pup[2]; d3dparticlevert[2].s = 1; d3dparticlevert[2].t = 1; d3dparticlevert[2].colour = colour; d3dparticlevert[2].org[0] = p->org[0] + x*pright[0] + y*pup[0]; d3dparticlevert[2].org[1] = p->org[1] + x*pright[1] + y*pup[1]; d3dparticlevert[2].org[2] = p->org[2] + x*pright[2] + y*pup[2]; d3dparticlevert[3].s = 1; d3dparticlevert[3].t = 0; d3dparticlevert[3].colour = colour; d3dparticlevert[3].org[0] = p->org[0] + y*pright[0] - x*pup[0]; d3dparticlevert[3].org[1] = p->org[1] + y*pright[1] - x*pup[1]; d3dparticlevert[3].org[2] = p->org[2] + y*pright[2] - x*pup[2]; //FIXME: batch properly pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dparticlevert, 4, d3dparticlevertindexes, 6, 0); } } static void D3D_DrawParticleSpark(int count, particle_t **plist, plooks_t *type) { vec3_t v, crv, o2; unsigned int colour; int cb, cg, cr, ca; particle_t *p; pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, type->d3dtexture); 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_MODULATE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); APPLYD3DBLEND(type->blendmode); while(count--) { p = *plist++; cr = p->rgb[0]*255; if (cr < 0) cr = 0; if (cr > 255) cr = 255; cg = p->rgb[1]*255; if (cg < 0) cg = 0; if (cg > 255) cg = 255; cb = p->rgb[2]*255; if (cb < 0) cb = 0; if (cb > 255) cb = 255; ca = p->alpha*255; if (ca < 0) ca = 0; if (ca > 255) ca = 255; colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); VectorSubtract(r_refdef.vieworg, p->org, v); CrossProduct(v, p->vel, crv); VectorNormalize(crv); VectorMA(p->org, -p->scale/2, crv, d3dparticlevert[0].org); d3dparticlevert[0].s = 0; d3dparticlevert[0].t = 0; d3dparticlevert[0].colour = colour; VectorMA(p->org, p->scale/2, crv, d3dparticlevert[1].org); d3dparticlevert[1].s = 0; d3dparticlevert[1].t = 1; d3dparticlevert[1].colour = colour; VectorMA(p->org, 0.1, p->vel, o2); VectorSubtract(r_refdef.vieworg, o2, v); CrossProduct(v, p->vel, crv); VectorNormalize(crv); VectorMA(o2, p->scale/2, crv, d3dparticlevert[2].org); d3dparticlevert[2].s = 1; d3dparticlevert[2].t = 1; d3dparticlevert[2].colour = colour; VectorMA(o2, -p->scale/2, crv, d3dparticlevert[3].org); d3dparticlevert[3].s = 1; d3dparticlevert[3].t = 0; d3dparticlevert[3].colour = colour; pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dparticlevert, 4, d3dparticlevertindexes, 6, 0); } } static void D3D_DrawParticleBeam(int count, beamseg_t **blist, plooks_t *type) { vec3_t v; vec3_t crv; beamseg_t *b, *c; particle_t *p; particle_t *q; float ts; unsigned int colour; int cb, cg, cr, ca; pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, type->d3dtexture); 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_MODULATE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); APPLYD3DBLEND(type->blendmode); while(count--) { b = *blist++; c = b->next; q = c->p; p = b->p; cr = q->rgb[0]*255; if (cr < 0) cr = 0; if (cr > 255) cr = 255; cg = q->rgb[1]*255; if (cg < 0) cg = 0; if (cg > 255) cg = 255; cb = q->rgb[2]*255; if (cb < 0) cb = 0; if (cb > 255) cb = 255; ca = q->alpha*255; if (ca < 0) ca = 0; if (ca > 255) ca = 255; colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); c = b->next; q = c->p; p = b->p; VectorSubtract(r_refdef.vieworg, q->org, v); VectorNormalize(v); CrossProduct(c->dir, v, crv); ts = c->texture_s*q->angle + particletime*q->rotationspeed; VectorMA(q->org, -q->scale, crv, d3dparticlevert[0].org); d3dparticlevert[0].s = ts; d3dparticlevert[0].t = 0; d3dparticlevert[0].colour = colour; VectorMA(q->org, q->scale, crv, d3dparticlevert[1].org); d3dparticlevert[1].s = ts; d3dparticlevert[1].t = 1; d3dparticlevert[1].colour = colour; cr = p->rgb[0]*255; if (cr < 0) cr = 0; if (cr > 255) cr = 255; cg = p->rgb[1]*255; if (cg < 0) cg = 0; if (cg > 255) cg = 255; cb = p->rgb[2]*255; if (cb < 0) cb = 0; if (cb > 255) cb = 255; ca = p->alpha*255; if (ca < 0) ca = 0; if (ca > 255) ca = 255; colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); VectorSubtract(r_refdef.vieworg, p->org, v); VectorNormalize(v); CrossProduct(b->dir, v, crv); // replace with old p->dir? ts = b->texture_s*p->angle + particletime*p->rotationspeed; VectorMA(p->org, p->scale, crv, d3dparticlevert[2].org); d3dparticlevert[2].s = ts; d3dparticlevert[2].t = 1; d3dparticlevert[2].colour = colour; VectorMA(p->org, -p->scale, crv, d3dparticlevert[3].org); d3dparticlevert[3].s = ts; d3dparticlevert[3].t = 0; d3dparticlevert[3].colour = colour; pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dparticlevert, 4, d3dparticlevertindexes, 6, 0); } } static void D3D_DrawParticleBeamUT(int count, beamseg_t **blist, plooks_t *type) { vec3_t v; vec3_t crv; beamseg_t *b, *c; particle_t *p; particle_t *q; float ts; unsigned int colour; int cb, cg, cr, ca; // D3D_DrawParticleBeam(b, type); // return; pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, NULL); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); APPLYD3DBLEND(type->blendmode); while (count--) { b = *blist++; c = b->next; q = c->p; p = b->p; cr = q->rgb[0]*255; if (cr < 0) cr = 0; if (cr > 255) cr = 255; cg = q->rgb[1]*255; if (cg < 0) cg = 0; if (cg > 255) cg = 255; cb = q->rgb[2]*255; if (cb < 0) cb = 0; if (cb > 255) cb = 255; ca = q->alpha*255; if (ca < 0) ca = 0; if (ca > 255) ca = 255; colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); c = b->next; q = c->p; p = b->p; VectorSubtract(r_refdef.vieworg, q->org, v); VectorNormalize(v); CrossProduct(c->dir, v, crv); ts = c->texture_s*q->angle + particletime*q->rotationspeed; VectorMA(q->org, -q->scale, crv, d3dparticlevertut[0].org); d3dparticlevertut[0].colour = colour; VectorMA(q->org, q->scale, crv, d3dparticlevertut[1].org); d3dparticlevertut[1].colour = colour; cr = p->rgb[0]*255; if (cr < 0) cr = 0; if (cr > 255) cr = 255; cg = p->rgb[1]*255; if (cg < 0) cg = 0; if (cg > 255) cg = 255; cb = p->rgb[2]*255; if (cb < 0) cb = 0; if (cb > 255) cb = 255; ca = p->alpha*255; if (ca < 0) ca = 0; if (ca > 255) ca = 255; colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); VectorSubtract(r_refdef.vieworg, p->org, v); VectorNormalize(v); CrossProduct(b->dir, v, crv); // replace with old p->dir? ts = b->texture_s*p->angle + particletime*p->rotationspeed; VectorMA(p->org, p->scale, crv, d3dparticlevertut[2].org); d3dparticlevertut[2].colour = colour; VectorMA(p->org, -p->scale, crv, d3dparticlevertut[3].org); d3dparticlevertut[3].colour = colour; pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE, d3dparticlevertut, 4, d3dparticlevertindexes, 6, 0); } } qboolean D3D7_DrawParticles(float ptime) { RSpeedLocals(); if (!pD3DDev) return false; particletime = ptime; PScript_DrawParticleTypes(D3D_DrawParticleBlob, D3D_DrawParticleSpark, D3D_DrawParticleSpark, D3D_DrawParticleSpark, D3D_DrawParticleBeam, D3D_DrawParticleBeamUT, NULL); pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ZWRITEENABLE, FALSE ); pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, FALSE ); pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE ); RSpeedRemark(); RQ_RenderDistAndClear(); RSpeedEnd(RSPEED_PARTICLESDRAW); pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ZWRITEENABLE, TRUE ); pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, TRUE ); pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE ); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); return true; } #endif #endif