// shared code for all surface types #include "quakedef.h" #include "d3d8_quake.h" // these could go in a vertexbuffer/indexbuffer pair #define MAX_BATCHED_SURFVERTEXES 65535 #define MAX_BATCHED_SURFINDEXES 262144 brushpolyvert_t *r_batchedsurfvertexes = NULL; unsigned short *r_batchedsurfindexes = NULL; int r_numsurfvertexes = 0; int r_numsurfindexes = 0; int r_firstsurfvertex = 0; int r_firstsurfindex = 0; IDirect3DVertexBuffer8 *r_surfbatchvb = NULL; IDirect3DIndexBuffer8 *r_surfbatchib = NULL; void R_SurfBatchCreateObjects (void) { if (!r_surfbatchvb) { IDirect3DDevice8_CreateVertexBuffer ( d3d_Device, MAX_BATCHED_SURFVERTEXES * sizeof (brushpolyvert_t), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &r_surfbatchvb ); r_firstsurfvertex = 0; } if (!r_surfbatchib) { IDirect3DDevice8_CreateIndexBuffer ( d3d_Device, MAX_BATCHED_SURFINDEXES * sizeof (unsigned short), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &r_surfbatchib ); r_firstsurfindex = 0; } } void R_SurfBatchDestroyObjects (void) { SAFE_RELEASE (r_surfbatchvb); SAFE_RELEASE (r_surfbatchib); } void R_BeginBatchingSurfaces (void) { // create the objects for batching the first time they're seen // this handles both standard startup and recovery from a lost device R_SurfBatchCreateObjects (); D3D_SetStreamSource (0, r_surfbatchvb, sizeof (brushpolyvert_t)); D3D_SetIndices (r_surfbatchib, 0); r_numsurfvertexes = 0; r_numsurfindexes = 0; } void R_EndBatchingSurfaces (void) { if (r_batchedsurfvertexes) { IDirect3DVertexBuffer8_Unlock (r_surfbatchvb); r_batchedsurfvertexes = NULL; } if (r_batchedsurfindexes) { IDirect3DIndexBuffer8_Unlock (r_surfbatchib); r_batchedsurfindexes = NULL; } if (r_numsurfvertexes && r_numsurfindexes) { D3D_DrawIndexed (r_firstsurfvertex, r_numsurfvertexes, r_firstsurfindex, r_numsurfindexes / 3); r_firstsurfvertex += r_numsurfvertexes; r_firstsurfindex += r_numsurfindexes; } // either may be 0 r_numsurfvertexes = 0; r_numsurfindexes = 0; } void R_BatchSurface (msurface_t *surf) { int i; DWORD vblock = D3DLOCK_NOOVERWRITE | D3DLOCK_NOSYSLOCK; DWORD iblock = D3DLOCK_NOOVERWRITE | D3DLOCK_NOSYSLOCK; if (r_numsurfvertexes + r_firstsurfvertex + surf->numvertexes >= MAX_BATCHED_SURFVERTEXES) { R_EndBatchingSurfaces (); vblock = D3DLOCK_DISCARD | D3DLOCK_NOSYSLOCK; r_firstsurfvertex = 0; } if (r_numsurfindexes + r_firstsurfindex + surf->numindexes >= MAX_BATCHED_SURFINDEXES) { R_EndBatchingSurfaces (); iblock = D3DLOCK_DISCARD | D3DLOCK_NOSYSLOCK; r_firstsurfindex = 0; } if (!r_batchedsurfvertexes) { IDirect3DVertexBuffer8_Lock ( r_surfbatchvb, (r_numsurfvertexes + r_firstsurfvertex) * sizeof (brushpolyvert_t), (MAX_BATCHED_SURFVERTEXES - (r_numsurfvertexes + r_firstsurfvertex)) * sizeof (brushpolyvert_t), (BYTE **) &r_batchedsurfvertexes, vblock ); } if (!r_batchedsurfindexes) { IDirect3DIndexBuffer8_Lock ( r_surfbatchib, (r_numsurfindexes + r_firstsurfindex) * sizeof (unsigned short), (MAX_BATCHED_SURFINDEXES - (r_numsurfindexes + r_firstsurfindex)) * sizeof (unsigned short), (BYTE **) &r_batchedsurfindexes, iblock ); } memcpy (r_batchedsurfvertexes, surf->verts, surf->numvertexes * sizeof (brushpolyvert_t)); r_batchedsurfvertexes += surf->numvertexes; for (i = 2; i < surf->numvertexes; i++, r_batchedsurfindexes += 3) { r_batchedsurfindexes[0] = r_numsurfvertexes + r_firstsurfvertex; r_batchedsurfindexes[1] = r_numsurfvertexes + r_firstsurfvertex + i - 1; r_batchedsurfindexes[2] = r_numsurfvertexes + r_firstsurfvertex + i; } r_numsurfvertexes += surf->numvertexes; r_numsurfindexes += surf->numindexes; }