From 546b90d75f6572e41fa755b0f5a6dd408375fa52 Mon Sep 17 00:00:00 2001 From: smallmodel <15067410+smallmodel@users.noreply.github.com> Date: Sat, 21 Dec 2024 17:04:23 +0100 Subject: [PATCH] Add basic 3D GL2 rendering with static models and terrain --- code/renderergl2/tr_backend.c | 102 ++-- code/renderergl2/tr_bsp.c | 678 ++++++++++++++++++++++++++- code/renderergl2/tr_cmds.c | 8 +- code/renderergl2/tr_image.c | 7 + code/renderergl2/tr_init.c | 32 ++ code/renderergl2/tr_local.h | 61 ++- code/renderergl2/tr_main.c | 143 +++++- code/renderergl2/tr_marks.c | 1 + code/renderergl2/tr_scene.c | 101 ++++ code/renderergl2/tr_shade.c | 15 + code/renderergl2/tr_shader.c | 4 +- code/renderergl2/tr_sphere_shade.cpp | 7 + code/renderergl2/tr_surface.c | 134 +++++- code/renderergl2/tr_world.c | 57 +++ 14 files changed, 1303 insertions(+), 47 deletions(-) diff --git a/code/renderergl2/tr_backend.c b/code/renderergl2/tr_backend.c index 71548779..b9c09637 100644 --- a/code/renderergl2/tr_backend.c +++ b/code/renderergl2/tr_backend.c @@ -433,6 +433,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { int oldSort; double originalTime; FBO_t* fbo = NULL; + qboolean bStaticModel, oldbStaticModel; // save original time for entity shader offsets originalTime = backEnd.refdef.floatTime; @@ -450,6 +451,10 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { oldPshadowed = qfalse; oldCubemapIndex = -1; oldSort = -1; + // OPENMOHAA-specific stuff + //========================= + oldbStaticModel = -1; + //========================= backEnd.pc.c_surfaces += numDrawSurfs; @@ -463,7 +468,19 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { continue; } oldSort = drawSurf->sort; - R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed ); + // + // OPENMOHAA-specific stuff + //========================= + if (*drawSurf->surface != SF_SPRITE) { + R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed, + &bStaticModel ); + } else { + shader = tr.sortedShaders[((refSprite_t*)drawSurf->surface)->shaderNum]; + entityNum = ENTITYNUM_WORLD; + dlighted = 0; + bStaticModel = qfalse; + } + //========================= cubemapIndex = drawSurf->cubemapIndex; // @@ -471,7 +488,9 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { // a "entityMergable" shader is a shader that can have surfaces from separate // entities merged into a single batch, like smoke and blood puff sprites if ( shader != NULL && ( shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted || pshadowed != oldPshadowed || cubemapIndex != oldCubemapIndex - || ( entityNum != oldEntityNum && !shader->entityMergable ) ) ) { + || ( entityNum != oldEntityNum && !shader->entityMergable ) + || ( bStaticModel != oldbStaticModel && !shader->entityMergable ) + ) ) { if (oldShader != NULL) { RB_EndSurface(); } @@ -490,43 +509,60 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { // // change the modelview matrix if needed // - if ( entityNum != oldEntityNum ) { + if ( entityNum != oldEntityNum + || bStaticModel != oldbStaticModel ) { depthRange = isCrosshair = qfalse; + + // + // OPENMOHAA-specific stuff + //========================= + if (bStaticModel) { + backEnd.shaderStartTime = 0.0; + backEnd.currentEntity = 0; + backEnd.spareSphere.TessFunction = 0; + backEnd.currentStaticModel = &backEnd.refdef.staticModels[entityNum]; + R_RotateForStaticModel(backEnd.currentStaticModel, &backEnd.viewParms, &backEnd.or); + } + else { + backEnd.currentStaticModel = NULL; + oldbStaticModel = bStaticModel; + //========================= - if ( entityNum != REFENTITYNUM_WORLD ) { - backEnd.currentEntity = &backEnd.refdef.entities[entityNum]; + if ( entityNum != REFENTITYNUM_WORLD ) { + backEnd.currentEntity = &backEnd.refdef.entities[entityNum]; - // FIXME: e.shaderTime must be passed as int to avoid fp-precision loss issues - backEnd.refdef.floatTime = originalTime - (double)backEnd.currentEntity->e.shaderTime; + // FIXME: e.shaderTime must be passed as int to avoid fp-precision loss issues + backEnd.refdef.floatTime = originalTime - (double)backEnd.currentEntity->e.shaderTime; - // we have to reset the shaderTime as well otherwise image animations start - // from the wrong frame - tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; + // we have to reset the shaderTime as well otherwise image animations start + // from the wrong frame + tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; - // set up the transformation matrix - R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or ); + // set up the transformation matrix + R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or ); - // set up the dynamic lighting if needed - if ( backEnd.currentEntity->needDlights ) { + // set up the dynamic lighting if needed + if ( backEnd.currentEntity->needDlights ) { + R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or ); + } + + if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK) + { + // hack the depth range to prevent view model from poking into walls + depthRange = qtrue; + + if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR) + isCrosshair = qtrue; + } + } else { + backEnd.currentEntity = &tr.worldEntity; + backEnd.refdef.floatTime = originalTime; + backEnd.or = backEnd.viewParms.world; + // we have to reset the shaderTime as well otherwise image animations on + // the world (like water) continue with the wrong frame + tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or ); } - - if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK) - { - // hack the depth range to prevent view model from poking into walls - depthRange = qtrue; - - if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR) - isCrosshair = qtrue; - } - } else { - backEnd.currentEntity = &tr.worldEntity; - backEnd.refdef.floatTime = originalTime; - backEnd.or = backEnd.viewParms.world; - // we have to reset the shaderTime as well otherwise image animations on - // the world (like water) continue with the wrong frame - tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; - R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or ); } GL_SetModelviewMatrix( backEnd.or.modelMatrix ); @@ -579,6 +615,10 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { oldEntityNum = entityNum; } + if (*drawSurf->surface == SF_SPRITE) { + backEnd.shaderStartTime = ((refSprite_t*)drawSurf->surface)->shaderTime; + } + // add the triangles for this surface rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface ); } diff --git a/code/renderergl2/tr_bsp.c b/code/renderergl2/tr_bsp.c index 152a5970..78fb6881 100644 --- a/code/renderergl2/tr_bsp.c +++ b/code/renderergl2/tr_bsp.c @@ -37,6 +37,8 @@ void RE_LoadWorldMap( const char *name ); */ +#define _R( id ) ri.UI_LoadResource( "*" #id ) + static world_t s_worldData; static byte *fileBase; @@ -1982,6 +1984,16 @@ static void R_LoadNodesAndLeafs (lump_t *nodeLump, lump_t *leafLump) { out->firstmarksurface = LittleLong(inLeaf->firstLeafSurface); out->nummarksurfaces = LittleLong(inLeaf->numLeafSurfaces); + + // + // OPENMOHAA-specific stuff + //========================= + out->firstTerraPatch = LittleLong(inLeaf->firstTerraPatch); + out->numTerraPatches = LittleLong(inLeaf->numTerraPatches); + + out->firstStaticModel = LittleLong(inLeaf->firstStaticModel); + out->numStaticModels = LittleLong(inLeaf->numStaticModels); + //========================= } // chain descendants @@ -2320,6 +2332,29 @@ void R_LoadEntities( lump_t *l ) { w->lightGridSize[1] = 64; w->lightGridSize[2] = 128; + // + // OPENMOHAA-specific stuff + //========================= + switch (map_version) + { + case 21: + w->lightGridSize[0] = 80.0; + w->lightGridSize[1] = 80.0; + w->lightGridSize[2] = 80.0; + break; + case 20: + w->lightGridSize[0] = 48.0; + w->lightGridSize[1] = 48.0; + w->lightGridSize[2] = 64.0; + break; + default: + w->lightGridSize[0] = 32.0; + w->lightGridSize[1] = 32.0; + w->lightGridSize[2] = 32.0; + break; + } + //========================= + p = (char *)(fileBase + l->fileofs); // store for reference by the cgame @@ -2730,6 +2765,530 @@ void R_CalcVertexLightDirs( void ) } } +// +// OPENMOHAA-specific stuff +//========================= + +/* +================ +R_LoadSphereLights +================ +*/ +void R_LoadSphereLights(lump_t* l) { + int i, j; + mapspherel_t* at; + spherel_t* light; + + if (l->filelen % sizeof(mapspherel_t)) { + Com_Error(ERR_DROP, "LoadMap: funny lump size in spherelight data for %s\n", s_worldData.name); + } + + tr.numSLights = l->filelen / sizeof(mapspherel_t); + + if (tr.numSLights >= MAX_MAP_SPHERE_L_SIZE) { + Com_Error(ERR_DROP, "LoadMap: Too many spherelights on map %s, limit is %d\n", s_worldData.name, MAX_MAP_SPHERE_L_SIZE); + } + + at = (mapspherel_t*)(fileBase + l->fileofs); + light = tr.sLights; + + for (i = 0; i < tr.numSLights; at++, light++, i++) { + VectorCopy(at->origin, light->origin); + VectorCopy(at->color, light->color); + VectorCopy(at->spot_dir, light->spot_dir); + + for (j = 0; j < 3; j++) { + light->origin[j] = LittleFloat(light->origin[j]); + light->color[j] = LittleFloat(light->color[j]); + light->spot_dir[j] = LittleFloat(light->spot_dir[j]); + } + + light->spot_radiusbydistance = LittleFloat(at->spot_radiusbydistance); + light->intensity = LittleFloat(at->intensity); + light->spot_light = LittleLong(at->spot_light); + light->needs_trace = LittleLong(at->needs_trace); + light->leaf = &s_worldData.nodes[s_worldData.numDecisionNodes + LittleLong(at->leaf)]; + } +} + +/* +================ +R_LoadSphereLightVis +================ +*/ +void R_LoadSphereLightVis(lump_t* l) { + int i; + int j; + int h; + mnode_t* node; + int numentries; + int* entries; + + memset(&tr.sSunLight, 0, sizeof(spherel_t)); + + if (l->filelen % 4) { + ri.Error(ERR_DROP, "LoadMap: funny lump size in spherelight vis data for %s\n", + s_worldData.name); + } + else { + entries = (int*)(fileBase + l->fileofs); + numentries = l->filelen / sizeof(int); + + if (numentries) { + if (numentries != s_worldData.numnodes - s_worldData.numDecisionNodes) { + for (i = 0; i < numentries; ++i) + entries[i] = LittleLong(entries[i]); + + for (node = &s_worldData.nodes[s_worldData.numDecisionNodes]; numentries; node++) { + j = 0; + if (entries[0] != -1) { + do + ++j; + while (entries[j] != -1); + } + if (j) { + node->lights = ri.Hunk_Alloc(j * sizeof(spherel_t*), h_dontcare); + node->numlights = j; + h = 0; + if (entries[0] == -2) { + node->lights[0] = &tr.sSunLight; + tr.sSunLight.leaf = (mnode_t*)-1; + h = 1; + } + while (entries[h] != -1) { + node->lights[h] = &tr.sLights[entries[h]]; + h++; + } + entries += h + 1; + numentries = numentries - 1 - h; + } + else { + numentries--; + entries++; + } + } + } + } + } +} + +/* +================= +R_LoadNodesAndLeafsOld +================= +*/ +static void R_LoadNodesAndLeafsOld(lump_t* nodeLump, lump_t* leafLump) { + int i, j, p; + dnode_t* in; + dleaf_t_ver17* inLeaf; + mnode_t* out; + int numNodes, numLeafs; + + in = (dnode_t*)(fileBase + nodeLump->fileofs); + if (nodeLump->filelen % sizeof(dnode_t) || + leafLump->filelen % sizeof(dleaf_t)) { + ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name); + } + numNodes = nodeLump->filelen / sizeof(dnode_t); + numLeafs = leafLump->filelen / sizeof(dleaf_t); + + out = ri.Hunk_Alloc((numNodes + numLeafs) * sizeof(*out), h_dontcare); + + s_worldData.nodes = out; + s_worldData.numnodes = numNodes + numLeafs; + s_worldData.numDecisionNodes = numNodes; + + // load nodes + for (i = 0; i < numNodes; i++, in++, out++) + { + for (j = 0; j < 3; j++) + { + out->mins[j] = LittleLong(in->mins[j]); + out->maxs[j] = LittleLong(in->maxs[j]); + } + + p = LittleLong(in->planeNum); + out->plane = s_worldData.planes + p; + + out->contents = CONTENTS_NODE; // differentiate from leafs + + for (j = 0; j < 2; j++) + { + p = LittleLong(in->children[j]); + if (p >= 0) + out->children[j] = s_worldData.nodes + p; + else + out->children[j] = s_worldData.nodes + numNodes + (-1 - p); + } + } + + // load leafs + inLeaf = (dleaf_t_ver17*)(fileBase + leafLump->fileofs); + for (i = 0; i < numLeafs; i++, inLeaf++, out++) + { + for (j = 0; j < 3; j++) + { + out->mins[j] = LittleLong(inLeaf->mins[j]); + out->maxs[j] = LittleLong(inLeaf->maxs[j]); + } + + out->cluster = LittleLong(inLeaf->cluster); + out->area = LittleLong(inLeaf->area); + + if (out->cluster >= s_worldData.numClusters) { + s_worldData.numClusters = out->cluster + 1; + } + + out->firstmarksurface = s_worldData.marksurfaces + + LittleLong(inLeaf->firstLeafSurface); + out->nummarksurfaces = LittleLong(inLeaf->numLeafSurfaces); + + out->firstTerraPatch = LittleLong(inLeaf->firstTerraPatch); + out->numTerraPatches = LittleLong(inLeaf->numTerraPatches); + } + + // chain decendants + R_SetParent(s_worldData.nodes, NULL); +} + +/* +================ +R_UnpackTerraPatch +================ +*/ +void R_UnpackTerraPatch(cTerraPatch_t* pPacked, cTerraPatchUnpacked_t* pUnpacked) { + int i, j; + + pUnpacked->byDirty = qfalse; + pUnpacked->visCountCheck = 0; + pUnpacked->visCountDraw = 0; + pUnpacked->uiDistRecalc = 0; + + if (pPacked->lmapScale <= 0) { + Com_Error(ERR_DROP, "invalid map: terrain has lmapScale <= 0"); + } + + pUnpacked->drawinfo.lmapStep = (float)(64 / pPacked->lmapScale); + pUnpacked->drawinfo.lmapSize = pPacked->lmapScale * 8 + 1; + pUnpacked->s = ((float)pPacked->s + 0.5) / LIGHTMAP_SIZE; + pUnpacked->t = ((float)pPacked->t + 0.5) / LIGHTMAP_SIZE; + pUnpacked->drawinfo.lmData = NULL; + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + pUnpacked->texCoord[i][j][0] = pPacked->texCoord[i][j][0]; + pUnpacked->texCoord[i][j][1] = pPacked->texCoord[i][j][1]; + } + } + + pUnpacked->x0 = ((int)pPacked->x << 6); + pUnpacked->y0 = ((int)pPacked->y << 6); + pUnpacked->z0 = pPacked->iBaseHeight; + pUnpacked->shader = ShaderForShaderNum(pPacked->iShader, pPacked->iLightMap); + pUnpacked->iNorth = pPacked->iNorth; + pUnpacked->iEast = pPacked->iEast; + pUnpacked->iSouth = pPacked->iSouth; + pUnpacked->iWest = pPacked->iWest; + + for (i = 0; i < MAX_TERRAIN_VARNODES; i++) + { + varnode_t *packedVarTree; + + packedVarTree = &pPacked->varTree[0][i]; + pUnpacked->varTree[0][i].fVariance = packedVarTree->flags & 0x7FF; + pUnpacked->varTree[0][i].flags &= ~0xFF; + pUnpacked->varTree[0][i].flags |= (packedVarTree->flags >> 12) & 0xFF; + + packedVarTree = &pPacked->varTree[1][i]; + pUnpacked->varTree[1][i].fVariance = packedVarTree->flags & 0x7FF; + pUnpacked->varTree[1][i].flags &= ~0xFF; + pUnpacked->varTree[1][i].flags |= (packedVarTree->flags >> 12) & 0xFF; + } + + for (i = 0; i < ARRAY_LEN(pUnpacked->heightmap); i++) { + pUnpacked->heightmap[i] = pPacked->heightmap[i]; + } + + pUnpacked->zmax = 0; + pUnpacked->flags = pPacked->flags; + + for (i = 0; i < ARRAY_LEN(pUnpacked->heightmap); i++) + { + if (pUnpacked->zmax < pUnpacked->heightmap[i]) { + pUnpacked->zmax = pUnpacked->heightmap[i]; + } + } + + pUnpacked->frameCount = 0; + pUnpacked->zmax += pUnpacked->zmax; +} + +/* +================ +R_LoadTerrain +================ +IneQuation was here +*/ +void R_LoadTerrain(lump_t* lump) { + int i; + cTerraPatch_t* in; + cTerraPatchUnpacked_t* out; + + if (!lump->filelen) { + s_worldData.numTerraPatches = 0; + s_worldData.terraPatches = NULL; + return; + } + + if (lump->filelen % sizeof(cTerraPatch_t)) { + Com_Error(ERR_DROP, "R_LoadTerrain: funny lump size"); + } + + s_worldData.numTerraPatches = lump->filelen / sizeof(cTerraPatch_t); + s_worldData.terraPatches = ri.Hunk_Alloc(s_worldData.numTerraPatches * sizeof(cTerraPatchUnpacked_t), h_dontcare); + + in = (cTerraPatch_t*)(fileBase + lump->fileofs); + out = s_worldData.terraPatches; + + for (i = 0; i < s_worldData.numTerraPatches; in++, out++, i++) { + R_SwapTerraPatch(in); + R_UnpackTerraPatch(in, out); + } +} + +/* +================ +R_LoadTerrainIndexes +================ +*/ +void R_LoadTerrainIndexes(lump_t* lump) { + int i; + short* in; + cTerraPatchUnpacked_t** out; + + if (!lump->filelen) { + s_worldData.numVisTerraPatches = 0; + s_worldData.visTerraPatches = NULL; + return; + } + + if (lump->filelen % sizeof(short)) { + Com_Error(ERR_DROP, "R_LoadTerrainIndexes: funny lump size"); + } + + s_worldData.numVisTerraPatches = lump->filelen / sizeof(short); + s_worldData.visTerraPatches = ri.Hunk_Alloc(s_worldData.numVisTerraPatches * sizeof(cTerraPatchUnpacked_t*), h_dontcare); + + in = (short*)(fileBase + lump->fileofs); + out = s_worldData.visTerraPatches; + + for (i = 0; i < s_worldData.numVisTerraPatches; in++, out++, i++) { + *out = &s_worldData.terraPatches[LittleShort(*in)]; + } +} + +/* +================ +R_LoadLightGrid2 + +================ +*/ +void R_LoadLightGrid2(lump_t* plPal, lump_t* plOffsets, lump_t* plData) { + int i; + vec3_t maxs; + int numGridPoints; + world_t *w; + float *wMins, *wMaxs; + + w = &s_worldData; + + if (!plPal->filelen || !plOffsets->filelen || !plData->filelen) { + ri.Printf(PRINT_WARNING, "WARNING: No light grid data present\n"); + w->lightGridOffsets = 0; + w->lightGridData = 0; + return; + } + + switch (map_version) + { + case 21: + w->lightGridSize[0] = 80.0; + w->lightGridSize[1] = 80.0; + w->lightGridSize[2] = 80.0; + break; + case 20: + w->lightGridSize[0] = 48.0; + w->lightGridSize[1] = 48.0; + w->lightGridSize[2] = 64.0; + break; + default: + w->lightGridSize[0] = 32.0; + w->lightGridSize[1] = 32.0; + w->lightGridSize[2] = 32.0; + break; + } + + w->lightGridInverseSize[0] = 1.0f / w->lightGridSize[0]; + w->lightGridInverseSize[1] = 1.0f / w->lightGridSize[1]; + w->lightGridInverseSize[2] = 1.0f / w->lightGridSize[2]; + + wMins = w->bmodels[0].bounds[0]; + wMaxs = w->bmodels[0].bounds[1]; + + for ( i = 0 ; i < 3 ; i++ ) { + w->lightGridOrigin[i] = w->lightGridSize[i] * ceil( wMins[i] / w->lightGridSize[i] ); + maxs[i] = w->lightGridSize[i] * floor( wMaxs[i] / w->lightGridSize[i] ); + w->lightGridBounds[i] = (maxs[i] - w->lightGridOrigin[i])/w->lightGridSize[i] + 1; + } + + numGridPoints = w->lightGridBounds[0] * w->lightGridBounds[1] + w->lightGridBounds[0]; + + if (plOffsets->filelen != numGridPoints * 2) { + ri.Printf(PRINT_WARNING, "WARNING: light grid offset size mismatch\n"); + w->lightGridOffsets = NULL; + w->lightGridData = NULL; + return; + } + + if (plPal->filelen != 768) { + ri.Printf(PRINT_WARNING, "WARNING: light grid palette size mismatch\n"); + w->lightGridOffsets = NULL; + w->lightGridData = NULL; + return; + } + + w->lightGridOffsets = ri.Hunk_Alloc(plOffsets->filelen, h_dontcare); + for (i = 0; i < plOffsets->filelen / 2; i++) { + w->lightGridOffsets[i] = LittleUnsignedShort(((short*)(fileBase + plOffsets->fileofs))[i]); + } + Com_Memcpy(w->lightGridPalette, fileBase + plPal->fileofs, sizeof(s_worldData.lightGridPalette)); + + //w->lightGridData = ri.Hunk_Alloc(plData->filelen, h_dontcare); + //Com_Memcpy(w->lightGridData, fileBase + plData->fileofs, plData->filelen); +} + +/* +================ +R_LoadStaticModelData +================ +*/ +void R_LoadStaticModelData(lump_t* lump) { + int i; + byte* pDstColors; + byte* pSrcColors; + + if (!lump->filelen) { + s_worldData.numStaticModelData = 0; + s_worldData.staticModelData = 0; + return; + } + + + if (lump->filelen % (sizeof(byte) * 3)) { + Com_Error(1, "R_LoadStaticModelData: funny lump size"); + } + + s_worldData.numStaticModelData = lump->filelen / (sizeof(byte) * 3); + s_worldData.staticModelData = (byte*)ri.Hunk_Alloc(s_worldData.numStaticModelData * sizeof(color4ub_t), h_dontcare); + + pSrcColors = (byte*)(fileBase + lump->fileofs); + pDstColors = s_worldData.staticModelData; + + for (i = 0; i < lump->filelen; i += sizeof(byte) * 3) + { + // Colors are stored as integers + pDstColors[0] = pSrcColors[0]; + pDstColors[1] = pSrcColors[1]; + pDstColors[2] = pSrcColors[2]; + pDstColors[3] = 0xFF; + + pSrcColors += sizeof(byte) * 3; + pDstColors += sizeof(byte) * 4; + } +} + +/* +================ +R_CopyStaticModel +================ +*/ +void R_CopyStaticModel(cStaticModel_t* pSM, cStaticModelUnpacked_t* pUnpackedSM) { + pUnpackedSM->visCount = 0; + pUnpackedSM->angles[0] = LittleFloat(pSM->angles[0]); + pUnpackedSM->angles[1] = LittleFloat(pSM->angles[1]); + pUnpackedSM->angles[2] = LittleFloat(pSM->angles[2]); + pUnpackedSM->origin[0] = LittleFloat(pSM->origin[0]); + pUnpackedSM->origin[1] = LittleFloat(pSM->origin[1]); + pUnpackedSM->origin[2] = LittleFloat(pSM->origin[2]); + pUnpackedSM->scale = LittleFloat(pSM->scale); + pUnpackedSM->firstVertexData = LittleLong(pSM->firstVertexData) * sizeof(color4ub_t) / (sizeof(byte) * 3); + pUnpackedSM->numVertexData = LittleLong(pSM->numVertexData); + memcpy(pUnpackedSM->model, pSM->model, sizeof(pUnpackedSM->model)); +} + +/* +================ +R_LoadStaticModelDefs +================ +*/ +void R_LoadStaticModelDefs(lump_t* lump) { + int i; + cStaticModel_t* in; + cStaticModelUnpacked_t* out; + + if (!lump->filelen) { + s_worldData.numStaticModels = 0; + s_worldData.staticModels = NULL; + return; + } + + if (lump->filelen % sizeof(cStaticModel_t)) { + Com_Error(ERR_DROP, "R_LoadStaticModelDefs: funny lump size"); + } + + s_worldData.numStaticModels = lump->filelen / sizeof(cStaticModel_t); + s_worldData.staticModels = ri.Hunk_Alloc(s_worldData.numStaticModels * sizeof(cStaticModelUnpacked_t), h_dontcare); + + in = (cStaticModel_t*)(fileBase + lump->fileofs); + out = s_worldData.staticModels; + + for (i = 0; i < s_worldData.numStaticModels; in++, out++, i++) { + R_CopyStaticModel(in, out); + } +} + +/* +================ +R_LoadStaticModelIndexes +================ +*/ +void R_LoadStaticModelIndexes(lump_t* lump) { + int i; + unsigned short* in; + cStaticModelUnpacked_t** out; + + if (lump->filelen % sizeof(short)) { + Com_Error(ERR_DROP, "R_LoadStaticModelDefs: funny lump size"); + } + + s_worldData.numVisStaticModels = lump->filelen / sizeof(short); + s_worldData.visStaticModels = ri.Hunk_Alloc(s_worldData.numVisStaticModels * sizeof(cStaticModelUnpacked_t*), h_dontcare); + + in = (unsigned short*)(fileBase + lump->fileofs); + out = s_worldData.visStaticModels; + + for (i = 0; i < s_worldData.numVisStaticModels; in++, out++, i++) { + unsigned short index = LittleUnsignedShort(*in); + if (index >= s_worldData.numStaticModels) { + // Added in OPM + Com_Error(ERR_DROP, "R_LoadStaticModelIndexes: bad static model index %d", index); + } + + *out = &s_worldData.staticModels[index]; + } +} + +//========================= /* ================= @@ -2809,18 +3368,119 @@ void RE_LoadWorldMap( const char *name ) { ((int *)header)[i] = LittleLong ( ((int *)header)[i]); } + // + // OPENMOHAA-specific stuff + //========================= + map_version = header->version; + //========================= + // load into heap +#if 0 R_LoadEntities( &header->lumps[LUMP_ENTITIES] ); R_LoadShaders( &header->lumps[LUMP_SHADERS] ); R_LoadLightmaps( &header->lumps[LUMP_LIGHTMAPS], &header->lumps[LUMP_SURFACES] ); R_LoadPlanes (&header->lumps[LUMP_PLANES]); - R_LoadFogs( &header->lumps[LUMP_FOGS], &header->lumps[LUMP_BRUSHES], &header->lumps[LUMP_BRUSHSIDES] ); + //R_LoadFogs( &header->lumps[LUMP_FOGS], &header->lumps[LUMP_BRUSHES], &header->lumps[LUMP_BRUSHSIDES] ); R_LoadSurfaces( &header->lumps[LUMP_SURFACES], &header->lumps[LUMP_DRAWVERTS], &header->lumps[LUMP_DRAWINDEXES] ); R_LoadMarksurfaces (&header->lumps[LUMP_LEAFSURFACES]); R_LoadNodesAndLeafs (&header->lumps[LUMP_NODES], &header->lumps[LUMP_LEAFS]); R_LoadSubmodels (&header->lumps[LUMP_MODELS]); R_LoadVisibility( &header->lumps[LUMP_VISIBILITY] ); R_LoadLightGrid( &header->lumps[LUMP_LIGHTGRID] ); +#endif + + // + // OPENMOHAA-specific stuff + //========================= + _R(53); + _R(54); + R_LoadShaders(Q_GetLumpByVersion(header, LUMP_SHADERS)); + _R(55); + _R(56); + R_LoadPlanes(Q_GetLumpByVersion(header, LUMP_PLANES)); + _R(57); + _R(58); + _R(59); + R_LoadLightmaps(Q_GetLumpByVersion(header, LUMP_LIGHTMAPS), Q_GetLumpByVersion(header, LUMP_SURFACES)); + _R(60); + _R(61); + _R(62); + _R(63); + _R(64); + R_LoadSurfaces(Q_GetLumpByVersion(header, LUMP_SURFACES), Q_GetLumpByVersion(header, LUMP_DRAWVERTS), Q_GetLumpByVersion(header, LUMP_DRAWINDEXES)); + _R(65); + _R(66); + _R(67); + _R(68); + _R(69); + R_LoadMarksurfaces(Q_GetLumpByVersion(header, LUMP_LEAFSURFACES)); + _R(70); + _R(71); + _R(72); + _R(73); + if (header->version > BSP_BETA_VERSION) { + R_LoadNodesAndLeafs(Q_GetLumpByVersion(header, LUMP_NODES), Q_GetLumpByVersion(header, LUMP_LEAFS)); + } else { + R_LoadNodesAndLeafsOld(Q_GetLumpByVersion(header, LUMP_NODES), Q_GetLumpByVersion(header, LUMP_LEAFS)); + } + _R(74); + _R(75); + _R(76); + numFogs = 0; + _R(77); + R_LoadSubmodels(Q_GetLumpByVersion(header, LUMP_MODELS)); + _R(78); + _R(79); + _R(80); + R_LoadVisibility(Q_GetLumpByVersion(header, LUMP_VISIBILITY)); + _R(81); + _R(82); + _R(83); + _R(84); + _R(85); + R_LoadLightGrid2(Q_GetLumpByVersion(header, LUMP_LIGHTGRIDPALETTE), Q_GetLumpByVersion(header, LUMP_LIGHTGRIDOFFSETS), Q_GetLumpByVersion(header, LUMP_LIGHTGRIDDATA)); + _R(86); + _R(87); + _R(88); + _R(89); + _R(90); + R_LoadSphereLights(Q_GetLumpByVersion(header, LUMP_SPHERELIGHTS)); + _R(91); + _R(92); + _R(93); + R_LoadSphereLightVis(Q_GetLumpByVersion(header, LUMP_SPHERELIGHTVIS)); + _R(94); + _R(95); + _R(96); + R_LoadTerrain(Q_GetLumpByVersion(header, LUMP_TERRAIN)); + _R(97); + _R(98); + _R(99); + R_LoadTerrainIndexes(Q_GetLumpByVersion(header, LUMP_TERRAININDEXES)); + _R(100); + _R(101); + if (header->version > BSP_BETA_VERSION) + { + _R(102); + R_LoadStaticModelData(Q_GetLumpByVersion(header, LUMP_STATICMODELDATA)); + _R(103); + _R(104); + _R(105); + R_LoadStaticModelDefs(Q_GetLumpByVersion(header, LUMP_STATICMODELDEF)); + _R(106); + _R(107); + _R(108); + R_LoadStaticModelIndexes(Q_GetLumpByVersion(header, LUMP_STATICMODELINDEXES)); + _R(109); + _R(110); + } + else + { + g_nStaticModelData = 0; + g_nStaticModels = 0; + g_nStaticModelIndices = 0; + } + //========================= // determine vertex light directions R_CalcVertexLightDirs(); @@ -3051,6 +3711,22 @@ void RE_LoadWorldMap( const char *name ) { } ri.FS_FreeFile( buffer.v ); + + // + // OPENMOHAA-specific stuff + //========================= + ri.UI_LoadResource("*111"); + R_Sphere_InitLights(); + ri.UI_LoadResource("*112"); + R_InitTerrain(); + ri.UI_LoadResource("*113"); + R_InitStaticModels(); + ri.UI_LoadResource("*114"); + R_LevelMarksLoad(name); + ri.UI_LoadResource("*115"); + R_VisDebugLoad(name); + ri.UI_LoadResource("*116"); + //========================= } // diff --git a/code/renderergl2/tr_cmds.c b/code/renderergl2/tr_cmds.c index ff2195df..2d4279e8 100644 --- a/code/renderergl2/tr_cmds.c +++ b/code/renderergl2/tr_cmds.c @@ -554,7 +554,13 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) { } } - tr.refdef.stereoFrame = stereoFrame; + tr.refdef.stereoFrame = stereoFrame; + + // + // OPENMOHAA-specific stuff + // + + g_nStaticSurfaces = 0; } diff --git a/code/renderergl2/tr_image.c b/code/renderergl2/tr_image.c index 2957c449..42c28955 100644 --- a/code/renderergl2/tr_image.c +++ b/code/renderergl2/tr_image.c @@ -3098,6 +3098,13 @@ void R_SetColorMappings( void ) { { GLimp_SetGamma( s_gammatable, s_gammatable, s_gammatable ); } + + // + // OPENMOHAA-specific stuff + //========================= + tr.overbrightShift = r_mapOverBrightBits->integer - tr.overbrightBits; + tr.overbrightMult = (float)(1 << tr.overbrightShift); + //========================= } /* diff --git a/code/renderergl2/tr_init.c b/code/renderergl2/tr_init.c index e8c0382d..db1133e2 100644 --- a/code/renderergl2/tr_init.c +++ b/code/renderergl2/tr_init.c @@ -265,6 +265,13 @@ int max_termarks; cvar_t* r_skyportal; cvar_t* r_skyportal_origin; +cvar_t* r_farplane; +cvar_t* r_farplane_bias; +cvar_t* r_farplane_color; +cvar_t* r_farplane_nocull; +cvar_t* r_farplane_nofog; +cvar_t* r_skybox_farplane; +cvar_t* r_farclip; cvar_t* r_lightcoronasize; // LOD @@ -313,6 +320,7 @@ cvar_t* r_showstaticbboxes; cvar_t* r_showcull; cvar_t* r_showlod; cvar_t* r_showstaticlod; +cvar_t* r_showportal; //========================= @@ -1555,6 +1563,13 @@ void R_Register( void ) r_skyportal = ri.Cvar_Get("r_skyportal", "0", 0); r_skyportal_origin = ri.Cvar_Get("r_skyportal_origin", "0 0 0", 0); + r_farplane = ri.Cvar_Get("r_farplane", "0", CVAR_CHEAT); + r_farplane_bias = ri.Cvar_Get("r_farplane_bias", "0", CVAR_CHEAT); + r_farplane_color = ri.Cvar_Get("r_farplane_color", ".5 .5 .5", CVAR_CHEAT); + r_farplane_nocull = ri.Cvar_Get("r_farplane_nocull", "0", CVAR_CHEAT); + r_farplane_nofog = ri.Cvar_Get("r_farplane_nofog", "0", CVAR_CHEAT); + r_skybox_farplane = ri.Cvar_Get("r_skybox_farplane", "0", CVAR_CHEAT); + r_farclip = ri.Cvar_Get("r_farclip", "0", CVAR_CHEAT); r_lightcoronasize = ri.Cvar_Get("r_lightcoronasize", ".1", CVAR_ARCHIVE); // LOD @@ -1603,6 +1618,7 @@ void R_Register( void ) r_showcull = ri.Cvar_Get("r_showcull", "0", CVAR_CHEAT); r_showlod = ri.Cvar_Get("r_showlod", "0", CVAR_TEMP); r_showstaticlod = ri.Cvar_Get("r_showstaticlod", "0", CVAR_TEMP); + r_showportal = ri.Cvar_Get("r_showportal", "0", 0); } void R_InitQueries(void) @@ -1718,6 +1734,22 @@ void R_Init( void ) { R_InitQueries(); + // + // OPENMOHAA-specific stuff + //========================= + + R_Sky_Init(); + + max_termarks = r_maxtermarks->integer; + if (max_termarks < MAX_TERMARKS) + max_termarks = MAX_TERMARKS; + + R_LevelMarksInit(); + + tr.pFontDebugStrings = R_LoadFont("verdana-14"); + g_bInfoworldtris = qfalse; + + //========================= err = qglGetError(); if ( err != GL_NO_ERROR ) diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index 19db5dc5..911565a6 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -78,6 +78,18 @@ typedef unsigned int vaoCacheGlIndex_t; #define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces #define PSHADOW_MAP_SIZE 512 +// +// OPENMOHAA-specific stuff +//========================= + +#define MAX_SPHERE_LIGHTS 512 +#define MAX_SPRITESURFS 0x8000 + +#define MAX_SPRITE_DIST 16384.0f +#define MAX_SPRITE_DIST_SQUARED (MAX_SPRITE_DIST * MAX_SPRITE_DIST) + +//========================= + typedef struct cubemap_s { char name[MAX_QPATH]; vec3_t origin; @@ -874,6 +886,9 @@ typedef struct { // OPENMOHAA-specific stuff // + int num_sprites; + struct refSprite_s *sprites; + int numTerMarks; struct srfMarkFragment_s *terMarks; @@ -1020,7 +1035,6 @@ typedef enum { // SF_MARK_FRAG, - SF_DISPLAY_LIST, SF_TIKI_SKEL, SF_TIKI_STATIC, SF_SWIPE, @@ -1215,7 +1229,7 @@ extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void *); // // OPENMOHAA-specific stuff -// +//========================= typedef struct { struct mnode_s* cntNode; @@ -1417,6 +1431,8 @@ typedef struct refSprite_s { float shaderTime; } refSprite_t; +//========================= + /* ============================================================================== @@ -1586,6 +1602,9 @@ typedef struct { // OPENMOHAA-specific stuff // + unsigned short* lightGridOffsets; + byte lightGridPalette[768]; + int numTerraPatches; cTerraPatchUnpacked_t* terraPatches; cTerraPatchUnpacked_t* activeTerraPatches; @@ -1605,7 +1624,7 @@ typedef struct { // // OPENMOHAA-specific stuff -// +//========================= typedef struct { float width; float height; @@ -1614,6 +1633,7 @@ typedef struct { float scale; shader_t* shader; } sprite_t; +//========================= /* ============================================================================== @@ -1696,7 +1716,10 @@ typedef enum { MOD_MESH, MOD_MDR, MOD_IQM, + + // // OPENMOHAA-specific stuff + // MOD_TIKI, MOD_SPRITE } modtype_t; @@ -1767,6 +1790,11 @@ the bits are allocated as follows: 1 : pshadow flag 0 : dlight flag */ +/* +#define QSORT_FOGNUM_SHIFT 2 +#define QSORT_REFENTITYNUM_SHIFT 7 +#define QSORT_SHADERNUM_SHIFT (QSORT_REFENTITYNUM_SHIFT+REFENTITYNUM_BITS) +*/ #define QSORT_FOGNUM_SHIFT 2 #define QSORT_REFENTITYNUM_SHIFT 4 #define QSORT_STATICMODEL_SHIFT (QSORT_REFENTITYNUM_SHIFT+REFENTITYNUM_BITS) @@ -1932,7 +1960,13 @@ typedef struct { // // OPENMOHAA-specific stuff // + sphereor_t spheres[MAX_SPHERE_LIGHTS]; + unsigned short numSpheresUsed; + sphereor_t* currentSphere; + sphereor_t spareSphere; + sphereor_t hudSphere; cStaticModelUnpacked_t* currentStaticModel; + float shaderStartTime; int dsStreamVert; } backEndState_t; @@ -2139,6 +2173,7 @@ typedef struct { int frame_skel_index; int skel_index[1024]; fontheader_t* pFontDebugStrings; + int farclip; } trGlobals_t; extern backEndState_t backEnd; @@ -2339,6 +2374,13 @@ extern int max_termarks; extern cvar_t* r_skyportal; extern cvar_t* r_skyportal_origin; +extern cvar_t* r_farplane; +extern cvar_t* r_farplane_bias; +extern cvar_t* r_farplane_color; +extern cvar_t* r_farplane_nocull; +extern cvar_t* r_farplane_nofog; +extern cvar_t* r_skybox_farplane; +extern cvar_t* r_farclip; extern cvar_t* r_lightcoronasize; // LOD @@ -2387,6 +2429,7 @@ extern cvar_t* r_showstaticbboxes; extern cvar_t* r_showcull; extern cvar_t* r_showlod; extern cvar_t* r_showstaticlod; +extern cvar_t* r_showportal; //========================= @@ -2435,7 +2478,7 @@ void R_AddLightningBoltSurfaces( trRefEntity_t *e ); void R_AddPolygonSurfaces( void ); void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader, - int *fogNum, int *dlightMap, int *pshadowMap ); + int *fogNum, int *dlightMap, int *pshadowMap, qboolean *bStaticModel ); void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int fogIndex, int dlightMap, int pshadowMap, int cubemap ); @@ -2741,6 +2784,8 @@ int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, ve int R_LightDirForPoint( vec3_t point, vec3_t lightDir, vec3_t normal, world_t *world ); int R_CubemapForPoint( vec3_t point ); +void R_Sphere_InitLights(); + /* ============================================================ @@ -2920,7 +2965,6 @@ int R_IQMLerpTag( orientation_t *tag, iqmData_t *data, // OPENMOHAA-specific stuff //========================= - /* ============================================================= @@ -3060,6 +3104,10 @@ TERRAIN ============================================================= */ + +extern terraTri_t* g_pTris; +extern terrainVert_t* g_pVert; + void R_MarkTerrainPatch(cTerraPatchUnpacked_t* pPatch); void R_AddTerrainSurfaces(); void R_AddTerrainMarkSurfaces(); @@ -3335,7 +3383,8 @@ typedef struct { // // OPENMOHAA-specific stuff - // + // + drawSurf_t spriteSurfs[MAX_SPRITESURFS]; srfMarkFragment_t* terMarks; refSprite_t sprites[2048]; cStaticModelUnpacked_t* staticModels; diff --git a/code/renderergl2/tr_main.c b/code/renderergl2/tr_main.c index 4b7e9d23..249f4516 100644 --- a/code/renderergl2/tr_main.c +++ b/code/renderergl2/tr_main.c @@ -743,6 +743,86 @@ void R_SetupFrustum (viewParms_t *dest, float xmin, float xmax, float ymax, floa SetPlaneSignbits( &dest->frustum[4] ); dest->flags |= VPF_FARPLANEFRUSTUM; } + + // + // OPENMOHAA-specific stuff + //========================= + + if (dest->isPortalSky) { + // since 2.0: skybox farplane + if (r_skybox_farplane->integer) { + dest->farplane_distance = r_skybox_farplane->value; + + sscanf( + r_farplane_color->string, + "%f %f %f", + &dest->farplane_color[0], + &dest->farplane_color[1], + &dest->farplane_color[2] + ); + + if (r_farplane_nocull->integer > 0) { + dest->farplane_cull = 0; + } else if (r_farplane_nocull->integer == 0) { + dest->farplane_cull = 1; + } else { + dest->farplane_cull = 2; + } + } + } + else if (r_farplane->integer) + { + dest->farplane_distance = r_farplane->value; + dest->farplane_bias = r_farplane_bias->value; + + sscanf( + r_farplane_color->string, + "%f %f %f", + &dest->farplane_color[0], + &dest->farplane_color[1], + &dest->farplane_color[2]); + + if (r_farplane_nocull->integer > 0) { + dest->farplane_cull = 0; + } else if (r_farplane_nocull->integer == 0) { + dest->farplane_cull = 1; + } else { + dest->farplane_cull = 2; + } + } + + if (dest->farplane_distance) + { + vec3_t farPoint; + float realPlaneLen; + float tmp; + vec4_t fogColor; + + dest->fog.len = dest->farplane_distance; + dest->fog.oolen = 1.0 / dest->farplane_distance; + VectorMA(dest->or.origin, dest->farplane_distance, dest->or.axis[0], farPoint); + + VectorNegate(dest->or.axis[0], dest->frustum[4].normal); + dest->frustum[4].type = PLANE_NON_AXIAL; + dest->frustum[4].dist = DotProduct(farPoint, dest->frustum[4].normal); + SetPlaneSignbits(&dest->frustum[4]); + + dest->fog.enabled = r_farplane_nofog->integer == 0; + if (dest->farplane_cull) { + // extra fustum for culling + dest->flags |= VPF_FARPLANEFRUSTUM; + dest->fog.extrafrustums = 1; + } else { + dest->fog.extrafrustums = 0; + } + } + else + { + dest->fog.enabled = 0; + dest->fog.extrafrustums = 0; + } + + //========================= } /* @@ -1208,10 +1288,12 @@ static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128 int i; unsigned int pointOr = 0; unsigned int pointAnd = (unsigned int)~0; + qboolean bStaticModel; R_RotateForViewer(); - R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed ); + R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed, + &bStaticModel ); RB_BeginSurface( shader, fogNum, drawSurf->cubemapIndex); rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface ); @@ -1469,7 +1551,8 @@ void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, // compared quickly during the qsorting process tr.refdef.drawSurfs[index].sort = (shader->sortedIndex << QSORT_SHADERNUM_SHIFT) | tr.shiftedEntityNum | ( fogIndex << QSORT_FOGNUM_SHIFT ) - | ((int)pshadowMap << QSORT_PSHADOW_SHIFT) | (int)dlightMap; + | ((int)pshadowMap << QSORT_PSHADOW_SHIFT) | (int)dlightMap + | tr.shiftedIsStatic; tr.refdef.drawSurfs[index].cubemapIndex = cubemap; tr.refdef.drawSurfs[index].surface = surface; tr.refdef.numDrawSurfs++; @@ -1481,12 +1564,21 @@ R_DecomposeSort ================= */ void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader, - int *fogNum, int *dlightMap, int *pshadowMap ) { + int *fogNum, int *dlightMap, int *pshadowMap, + qboolean *bStaticModel + ) { *fogNum = ( sort >> QSORT_FOGNUM_SHIFT ) & 31; *shader = tr.sortedShaders[ ( sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1) ]; *entityNum = ( sort >> QSORT_REFENTITYNUM_SHIFT ) & REFENTITYNUM_MASK; *pshadowMap = (sort >> QSORT_PSHADOW_SHIFT ) & 1; - *dlightMap = sort & 1; + *dlightMap = sort & 1; + + // + // OPENMOHAA-specific stuff + //========================= + *fogNum = 0; + *bStaticModel = sort & (1 << QSORT_STATICMODEL_SHIFT); + //========================= } /* @@ -1500,7 +1592,8 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) { int entityNum; int dlighted; int pshadowed; - int i; + int i; + qboolean bStaticModel; //ri.Printf(PRINT_ALL, "firstDrawSurf %d numDrawSurfs %d\n", (int)(drawSurfs - tr.refdef.drawSurfs), numDrawSurfs); @@ -1524,7 +1617,7 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) { // check for any pass through drawing, which // may cause another view to be rendered first for ( i = 0 ; i < numDrawSurfs ; i++ ) { - R_DecomposeSort( (drawSurfs+i)->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed ); + R_DecomposeSort( (drawSurfs+i)->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed, &bStaticModel ); if ( shader->sort > SS_PORTAL ) { break; @@ -1611,6 +1704,16 @@ static void R_AddEntitySurface (int entityNum) case MOD_BRUSH: R_AddBrushModelSurfaces( ent ); break; + // + // OPENMOHAA-specific stuff + //========================= + case MOD_SPRITE: + ri.Printf(PRINT_ALL, "sprite model '%s' being added to renderer!\n", tr.currentModel->name); + break; + case MOD_TIKI: + R_AddSkelSurfaces(ent); + break; + //========================= case MOD_BAD: // null model axis if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal) { break; @@ -1640,6 +1743,12 @@ void R_AddEntitySurfaces (void) { return; } + // + // OPENMOHAA-specific stuff + //========================= + tr.shiftedIsStatic = 0; + //========================= + for ( i = 0; i < tr.refdef.num_entities; i++) R_AddEntitySurface(i); } @@ -1826,6 +1935,8 @@ R_DrawDebugLines ================ */ void R_DrawDebugLines(void) { + // FIXME: unimplemented +#if 0 debugline_t* line; int i; float width; @@ -1902,6 +2013,7 @@ void R_DrawDebugLines(void) { } qglDepthRange(0.0, 1.0); +#endif } /* @@ -2891,6 +3003,25 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene ) // OPENMOHAA-specific stuff // +/* +================= +R_AddSpriteSurf +================= +*/ +void R_AddSpriteSurf(surfaceType_t* surface, shader_t* shader, float zDistance) +{ + int index; + + if (zDistance > MAX_SPRITE_DIST_SQUARED) { + zDistance = MAX_SPRITE_DIST_SQUARED; + } + + index = tr.refdef.numSpriteSurfs % MAX_SPRITES; + tr.refdef.spriteSurfs[index].sort = (int)(MAX_SPRITE_DIST_SQUARED - zDistance) | (shader->sortedIndex << QSORT_SHADERNUM_SHIFT); + tr.refdef.spriteSurfs[index].surface = surface; + tr.refdef.numSpriteSurfs++; +} + /* ================= R_RotateForStaticModel diff --git a/code/renderergl2/tr_marks.c b/code/renderergl2/tr_marks.c index 0fd7a00d..0c81b4e8 100644 --- a/code/renderergl2/tr_marks.c +++ b/code/renderergl2/tr_marks.c @@ -243,6 +243,7 @@ void R_AddMarkFragments(int numClipPoints, vec3_t clipPoints[2][MAX_VERTS_ON_POL mf = fragmentBuffer + (*returnedFragments); mf->firstPoint = (*returnedPoints); mf->numPoints = numClipPoints; + mf->iIndex = 0; // OPENMOHAA-specific stuff Com_Memcpy( pointBuffer + (*returnedPoints) * 3, clipPoints[pingPong], numClipPoints * sizeof(vec3_t) ); (*returnedPoints) += numClipPoints; diff --git a/code/renderergl2/tr_scene.c b/code/renderergl2/tr_scene.c index d21e6146..8e19a8eb 100644 --- a/code/renderergl2/tr_scene.c +++ b/code/renderergl2/tr_scene.c @@ -39,6 +39,8 @@ int r_numpolyverts; // OPENMOHAA-specific stuff //========================= +int r_firstSceneSpriteSurf; + int r_numsprites; int r_firstSceneSprite; @@ -453,6 +455,35 @@ void RE_BeginScene(const refdef_t *fd) // each scene / view. tr.frameSceneNum++; tr.sceneCount++; + + // + // OPENMOHAA-specific stuff + //========================= + TIKI_Reset_Caches(); + + // copy the sky data + tr.refdef.sky_alpha = fd->sky_alpha; + tr.refdef.sky_portal = fd->sky_portal; + + VectorCopy(fd->sky_origin, tr.refdef.sky_origin); + VectorCopy(fd->sky_axis[0], tr.refdef.sky_axis[0]); + VectorCopy(fd->sky_axis[1], tr.refdef.sky_axis[1]); + VectorCopy(fd->sky_axis[2], tr.refdef.sky_axis[2]); + + tr.refdef.numSpriteSurfs = r_firstSceneSpriteSurf; + tr.refdef.spriteSurfs = backEndData->spriteSurfs; + + tr.refdef.num_sprites = r_numsprites - r_firstSceneSprite; + tr.refdef.sprites = &backEndData->sprites[r_firstSceneSprite]; + + tr.refdef.numTerMarks = r_numtermarks - r_firstSceneTerMark; + tr.refdef.terMarks = &backEndData->terMarks[r_firstSceneTerMark]; + + backEndData->staticModelData = tr.refdef.staticModelData; + + tr.skyRendered = qfalse; + tr.portalRendered = qfalse; + //========================= } @@ -463,6 +494,14 @@ void RE_EndScene(void) r_firstSceneEntity = r_numentities; r_firstSceneDlight = r_numdlights; r_firstScenePoly = r_numpolys; + + // + // OPENMOHAA-specific stuff + // + + r_firstSceneSpriteSurf = tr.refdef.numSpriteSurfs; + r_firstSceneSprite = r_numsprites; + r_firstSceneTerMark = r_numtermarks; } /* @@ -583,6 +622,68 @@ void RE_RenderScene( const refdef_t *fd ) { parms.flags = VPF_USESUNLIGHT; } + // + // OPENMOHAA-specific stuff + //========================= + + // copy the farplane data + parms.farplane_distance = fd->farplane_distance; + parms.farplane_bias = fd->farplane_bias; + parms.farplane_color[0] = fd->farplane_color[0]; + parms.farplane_color[1] = fd->farplane_color[1]; + parms.farplane_color[2] = fd->farplane_color[2]; + parms.farplane_cull = fd->farplane_cull; + parms.renderTerrain = fd->renderTerrain; + + tr.refdef.skybox_farplane = fd->skybox_farplane; + tr.refdef.render_terrain = parms.renderTerrain; + + if (fd->farclipOverride >= 15900 || fd->farclipOverride <= -0.99) { + tr.farclip = 0; + } else { + tr.farclip = r_farclip->integer; + if (!tr.farclip && (r_picmip->integer > 1 || r_colorbits->integer == 16)) { + tr.farclip = 2800; + } + } + + if (tr.farclip) { + if (fd->farclipOverride != 0) { + parms.farplane_distance = fd->farclipOverride; + } else { + parms.farplane_distance = tr.farclip; + } + + if (fd->farplane_color[0] >= 0 && fd->farplane_color[1] >= 0 && fd->farplane_color[2] >= 0) { + parms.farplane_color[0] = fd->farplane_color[0]; + parms.farplane_color[1] = fd->farplane_color[1]; + parms.farplane_color[2] = fd->farplane_color[2]; + } + + if (fd->farplaneColorOverride[0] >= 0 && fd->farplaneColorOverride[1] >= 0 && fd->farplaneColorOverride[2] >= 0) { + parms.farplane_color[0] = fd->farplaneColorOverride[0]; + parms.farplane_color[1] = fd->farplaneColorOverride[1]; + parms.farplane_color[2] = fd->farplaneColorOverride[2]; + } + + parms.farplane_cull = qtrue; + + if (fd->farplane_distance > 0 && fd->farplane_distance < parms.farplane_distance) { + parms.farplane_distance = fd->farplane_distance; + } else { + if (fd->farplane_bias == 0) { + parms.farplane_bias = parms.farplane_distance * 0.18f; + } else if (fd->farplane_distance <= 500.f) { + parms.farplane_bias = parms.farplane_distance * 0.18f; + } else { + parms.farplane_bias = parms.farplane_distance / fd->farplane_distance; + } + } + } else if (parms.farplane_bias == 0) { + parms.farplane_bias = parms.farplane_distance * 0.18f; + } + //========================= + R_RenderView( &parms ); if(!( fd->rdflags & RDF_NOWORLDMODEL )) diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c index dec35e52..484f4ae7 100644 --- a/code/renderergl2/tr_shade.c +++ b/code/renderergl2/tr_shade.c @@ -541,6 +541,21 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t case CGEN_IDENTITY_LIGHTING: case CGEN_BAD: break; + // + // OPENMOHAA-specific stuff + //========================= + case CGEN_STATIC: + baseColor[0] = + baseColor[1] = + baseColor[2] = + baseColor[3] = 0.0f; + + vertColor[0] = + vertColor[1] = + vertColor[2] = + vertColor[3] = 1.0f; + break; + //========================= } // diff --git a/code/renderergl2/tr_shader.c b/code/renderergl2/tr_shader.c index 21ef5039..ac140cd0 100644 --- a/code/renderergl2/tr_shader.c +++ b/code/renderergl2/tr_shader.c @@ -3165,9 +3165,11 @@ static void FixRenderCommandList( int newShader ) { int pshadowMap; int sortedIndex; const drawSurfsCommand_t *ds_cmd = (const drawSurfsCommand_t *)curCmd; + qboolean bStaticModel; for( i = 0, drawSurf = ds_cmd->drawSurfs; i < ds_cmd->numDrawSurfs; i++, drawSurf++ ) { - R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlightMap, &pshadowMap ); + R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlightMap, &pshadowMap, + &bStaticModel ); sortedIndex = (( drawSurf->sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1)); if( sortedIndex >= newShader ) { sortedIndex++; diff --git a/code/renderergl2/tr_sphere_shade.cpp b/code/renderergl2/tr_sphere_shade.cpp index c2dd2701..cf4d1951 100644 --- a/code/renderergl2/tr_sphere_shade.cpp +++ b/code/renderergl2/tr_sphere_shade.cpp @@ -1344,6 +1344,13 @@ static void R_InsertLightIntoList(spherel_t *pLight, float fIntensity, gatheredL pCurrLight->pLight = pLight; } +#else + +void R_Sphere_InitLights() +{ + // UNIMPLEMENTED +} + #endif #define MAX_GATHERED_LIGHTS 8 diff --git a/code/renderergl2/tr_surface.c b/code/renderergl2/tr_surface.c index 3151638a..72e3a585 100644 --- a/code/renderergl2/tr_surface.c +++ b/code/renderergl2/tr_surface.c @@ -1299,6 +1299,128 @@ void RB_SurfaceVaoMdvMesh(srfVaoMdvMesh_t * surface) static void RB_SurfaceSkip( void *surf ) { } +// +// OPENMOHAA-specific stuff +//========================= + +/* +============= +RB_SurfaceMarkFragment +============= +*/ +void RB_SurfaceMarkFragment(srfMarkFragment_t* p) { + int i; + int numv; + + RB_CHECKOVERFLOW( p->numVerts, 3*(p->numVerts - 2) ); + + if (p->iIndex <= 0 || R_TerrainHeightForPoly(&tr.world->terraPatches[p->iIndex - 1], p->verts, p->numVerts)) + { + // FIXME: from here on out, it's mostly the same code as in RB_SurfacePolychain, + // common part could be extracted into an inline func + + // fan triangles into the tess array + numv = tess.numVertexes; + for ( i = 0; i < p->numVerts; i++ ) + { + VectorCopy( p->verts[i].xyz, tess.xyz[numv] ); + tess.texCoords[numv][0] = p->verts[i].st[0]; + tess.texCoords[numv][1] = p->verts[i].st[1]; + tess.color[numv][0] = p->verts[i].modulate[0] * 65535 / 255; + tess.color[numv][1] = p->verts[i].modulate[1] * 65535 / 255; + tess.color[numv][2] = p->verts[i].modulate[2] * 65535 / 255; + tess.color[numv][3] = p->verts[i].modulate[3] * 65535 / 255; + + numv++; + } + + // generate fan indexes into the tess array + for ( i = 0; i < p->numVerts - 2; i++ ) { + tess.indexes[tess.numIndexes + 0] = tess.numVertexes; + tess.indexes[tess.numIndexes + 1] = tess.numVertexes + i + 1; + tess.indexes[tess.numIndexes + 2] = tess.numVertexes + i + 2; + tess.numIndexes += 3; + } + + tess.numVertexes = numv; + } +} + +void RB_DrawTerrainTris(srfTerrain_t* p) { + int i; + terraInt numv; + int dlightBits; + + RB_CHECKOVERFLOW(p->nVerts, p->nTris * 3); + + dlightBits = p->dlightBits[0]; + tess.dlightBits |= dlightBits; + if (p->dlightMap[0]) + { + float lmScale = (1.0 / LIGHTMAP_SIZE) / p->lmapStep; + + for (i = p->iVertHead; i; i = g_pVert[i].iNext) { + assert(tess.numVertexes < SHADER_MAX_VERTEXES); + + VectorCopy(g_pVert[i].xyz, tess.xyz[tess.numVertexes]); + tess.texCoords[tess.numVertexes][0] = g_pVert[i].texCoords[0][0]; + tess.texCoords[tess.numVertexes][1] = g_pVert[i].texCoords[0][1]; + tess.lightCoords[tess.numVertexes][0] = g_pVert[i].xyz[0] * lmScale + p->lmapX; + tess.lightCoords[tess.numVertexes][1] = g_pVert[i].xyz[1] * lmScale + p->lmapY; + tess.normal[tess.numVertexes][0] = 0; + tess.normal[tess.numVertexes][1] = 0; + tess.normal[tess.numVertexes][2] = 1.0; + tess.color[tess.numVertexes][0] = 0xffff; + tess.color[tess.numVertexes][1] = 0xffff; + tess.color[tess.numVertexes][2] = 0xffff; + tess.color[tess.numVertexes][3] = 0xffff; + + g_pVert[i].iVertArray = tess.numVertexes; + tess.numVertexes++; + } + } + else + { + for (i = p->iVertHead; i; i = g_pVert[i].iNext) { + assert(tess.numVertexes < SHADER_MAX_VERTEXES); + + VectorCopy(g_pVert[i].xyz, tess.xyz[tess.numVertexes]); + tess.texCoords[tess.numVertexes][0] = g_pVert[i].texCoords[0][0]; + tess.texCoords[tess.numVertexes][1] = g_pVert[i].texCoords[0][1]; + tess.lightCoords[tess.numVertexes][0] = g_pVert[i].texCoords[1][0]; + tess.lightCoords[tess.numVertexes][1] = g_pVert[i].texCoords[1][1]; + //tess.vertexDlightBits[tess.numVertexes] = dlightBits; + tess.normal[tess.numVertexes][0] = 0; + tess.normal[tess.numVertexes][1] = 0; + tess.normal[tess.numVertexes][2] = 1.0; + tess.color[tess.numVertexes][0] = 0xffff; + tess.color[tess.numVertexes][1] = 0xffff; + tess.color[tess.numVertexes][2] = 0xffff; + tess.color[tess.numVertexes][3] = 0xffff; + + g_pVert[i].iVertArray = tess.numVertexes; + tess.numVertexes++; + } + } + + for (i = p->iTriHead; i; i = g_pTris[i].iNext) + { + assert(tess.numVertexes < SHADER_MAX_INDEXES); + + // + // Make sure these can be drawn + // + if (g_pTris[i].byConstChecks & 4) + { + tess.indexes[tess.numIndexes] = g_pVert[g_pTris[i].iPt[0]].iVertArray; + tess.indexes[tess.numIndexes + 1] = g_pVert[g_pTris[i].iPt[1]].iVertArray; + tess.indexes[tess.numIndexes + 2] = g_pVert[g_pTris[i].iPt[2]].iVertArray; + tess.numIndexes += 3; + } + } +} + +//========================= void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = { (void(*)(void*))RB_SurfaceBad, // SF_BAD, @@ -1313,5 +1435,15 @@ void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = { (void(*)(void*))RB_SurfaceFlare, // SF_FLARE, (void(*)(void*))RB_SurfaceEntity, // SF_ENTITY (void(*)(void*))RB_SurfaceVaoMdvMesh, // SF_VAO_MDVMESH - (void(*)(void*))RB_IQMSurfaceAnimVao, // SF_VAO_IQM + (void(*)(void*))RB_IQMSurfaceAnimVao, // SF_VAO_IQM + // + // OPENMOHAA-specific stuff + //========================= + (void(*)(void*))RB_SurfaceMarkFragment, // SF_MARK_FRAG + (void(*)(void*))RB_SkelMesh, // SF_TIKI_SKEL + (void(*)(void*))RB_StaticMesh, // SF_TIKI_STATIC + (void(*)(void*))RB_DrawSwipeSurface, // SF_SWIPE + (void(*)(void*))RB_DrawSprite, // SF_SPRITE + (void(*)(void*))RB_DrawTerrainTris, // SF_TERRAIN_PATCH + //========================= }; diff --git a/code/renderergl2/tr_world.c b/code/renderergl2/tr_world.c index 1a51b765..850996d0 100644 --- a/code/renderergl2/tr_world.c +++ b/code/renderergl2/tr_world.c @@ -581,6 +581,35 @@ static void R_RecursiveWorldNode( mnode_t *node, uint32_t planeBits, uint32_t dl } } + + // + // OPENMOHAA-specific stuff + //========================= + + if (r_drawterrain->integer && tr.refdef.render_terrain && !tr.viewParms.isPortalSky) + { + int i; + + for (i = 0; i < node->numTerraPatches; i++) { + R_MarkTerrainPatch(tr.world->visTerraPatches[node->firstTerraPatch + i]); + } + } + + if (r_drawstaticdecals->integer) { + if (node->pFirstMarkFragment) { + R_AddPermanentMarkFragmentSurfaces(node->pFirstMarkFragment, node->iNumMarkFragment); + } + } + + if (r_drawstaticmodels->integer) { + int i; + + for (i = 0; i < node->numStaticModels; i++) { + tr.world->visStaticModels[node->firstStaticModel + i]->visCount = tr.visCounts[tr.visIndex]; + } + } + + //========================= } @@ -752,6 +781,14 @@ void R_AddWorldSurfaces (void) { tr.currentEntityNum = REFENTITYNUM_WORLD; tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT; + // + // OPENMOHAA-specific stuff + //========================= + if (r_drawterrain->integer && tr.refdef.render_terrain && !tr.viewParms.isPortalSky) { + R_TerrainPrepareFrame(); + } + //========================= + // determine which leaves are in the PVS / areamask if (!(tr.viewParms.flags & VPF_DEPTHSHADOW)) R_MarkLeaves (); @@ -806,6 +843,26 @@ void R_AddWorldSurfaces (void) { tr.refdef.dlightMask = ~tr.refdef.dlightMask; } + + // + // OPENMOHAA-specific stuff + //========================= + + if (r_drawterrain->integer && tr.refdef.render_terrain && !tr.viewParms.isPortalSky) { + R_AddTerrainSurfaces(); + } + if (r_drawstaticmodels->integer) { + R_AddStaticModelSurfaces(); + } + + if (g_bInfostaticmodels) { + g_bInfostaticmodels = 0; + R_PrintInfoStaticModels(); + } + + R_UpdateLevelMarksSystem(); + + //========================= } //