📄 tr_bsp.c
字号:
//
v1 = grid1->verts[k + offset1].xyz;
v2 = grid2->verts[l + offset2].xyz;
if ( fabs(v1[0] - v2[0]) > .1)
continue;
if ( fabs(v1[1] - v2[1]) > .1)
continue;
if ( fabs(v1[2] - v2[2]) > .1)
continue;
v1 = grid1->verts[k - 2 + offset1].xyz;
v2 = grid2->verts[l + 1 + offset2].xyz;
if ( fabs(v1[0] - v2[0]) > .1)
continue;
if ( fabs(v1[1] - v2[1]) > .1)
continue;
if ( fabs(v1[2] - v2[2]) > .1)
continue;
//
v1 = grid2->verts[l + offset2].xyz;
v2 = grid2->verts[(l + 1) + offset2].xyz;
if ( fabs(v1[0] - v2[0]) < .01 &&
fabs(v1[1] - v2[1]) < .01 &&
fabs(v1[2] - v2[2]) < .01)
continue;
//
//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
// insert column into grid2 right after after column l
if (m) row = grid2->height-1;
else row = 0;
grid2 = R_GridInsertColumn( grid2, l+1, row,
grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k+1]);
grid2->lodStitched = qfalse;
s_worldData.surfaces[grid2num].data = (void *) grid2;
return qtrue;
}
}
for (m = 0; m < 2; m++) {
if (grid2->height >= MAX_GRID_SIZE)
break;
if (m) offset2 = grid2->width-1;
else offset2 = 0;
for ( l = 0; l < grid2->height-1; l++) {
//
v1 = grid1->verts[k + offset1].xyz;
v2 = grid2->verts[grid2->width * l + offset2].xyz;
if ( fabs(v1[0] - v2[0]) > .1)
continue;
if ( fabs(v1[1] - v2[1]) > .1)
continue;
if ( fabs(v1[2] - v2[2]) > .1)
continue;
v1 = grid1->verts[k - 2 + offset1].xyz;
v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
if ( fabs(v1[0] - v2[0]) > .1)
continue;
if ( fabs(v1[1] - v2[1]) > .1)
continue;
if ( fabs(v1[2] - v2[2]) > .1)
continue;
//
v1 = grid2->verts[grid2->width * l + offset2].xyz;
v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
if ( fabs(v1[0] - v2[0]) < .01 &&
fabs(v1[1] - v2[1]) < .01 &&
fabs(v1[2] - v2[2]) < .01)
continue;
//
//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
// insert row into grid2 right after after row l
if (m) column = grid2->width-1;
else column = 0;
grid2 = R_GridInsertRow( grid2, l+1, column,
grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k+1]);
if (!grid2)
break;
grid2->lodStitched = qfalse;
s_worldData.surfaces[grid2num].data = (void *) grid2;
return qtrue;
}
}
}
}
for (n = 0; n < 2; n++) {
//
if (n) offset1 = grid1->width-1;
else offset1 = 0;
if (R_MergedHeightPoints(grid1, offset1))
continue;
for (k = grid1->height-1; k > 1; k -= 2) {
for (m = 0; m < 2; m++) {
if ( grid2->width >= MAX_GRID_SIZE )
break;
if (m) offset2 = (grid2->height-1) * grid2->width;
else offset2 = 0;
for ( l = 0; l < grid2->width-1; l++) {
//
v1 = grid1->verts[grid1->width * k + offset1].xyz;
v2 = grid2->verts[l + offset2].xyz;
if ( fabs(v1[0] - v2[0]) > .1)
continue;
if ( fabs(v1[1] - v2[1]) > .1)
continue;
if ( fabs(v1[2] - v2[2]) > .1)
continue;
v1 = grid1->verts[grid1->width * (k - 2) + offset1].xyz;
v2 = grid2->verts[l + 1 + offset2].xyz;
if ( fabs(v1[0] - v2[0]) > .1)
continue;
if ( fabs(v1[1] - v2[1]) > .1)
continue;
if ( fabs(v1[2] - v2[2]) > .1)
continue;
//
v1 = grid2->verts[l + offset2].xyz;
v2 = grid2->verts[(l + 1) + offset2].xyz;
if ( fabs(v1[0] - v2[0]) < .01 &&
fabs(v1[1] - v2[1]) < .01 &&
fabs(v1[2] - v2[2]) < .01)
continue;
//
//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
// insert column into grid2 right after after column l
if (m) row = grid2->height-1;
else row = 0;
grid2 = R_GridInsertColumn( grid2, l+1, row,
grid1->verts[grid1->width * (k - 1) + offset1].xyz, grid1->heightLodError[k+1]);
grid2->lodStitched = qfalse;
s_worldData.surfaces[grid2num].data = (void *) grid2;
return qtrue;
}
}
for (m = 0; m < 2; m++) {
if (grid2->height >= MAX_GRID_SIZE)
break;
if (m) offset2 = grid2->width-1;
else offset2 = 0;
for ( l = 0; l < grid2->height-1; l++) {
//
v1 = grid1->verts[grid1->width * k + offset1].xyz;
v2 = grid2->verts[grid2->width * l + offset2].xyz;
if ( fabs(v1[0] - v2[0]) > .1)
continue;
if ( fabs(v1[1] - v2[1]) > .1)
continue;
if ( fabs(v1[2] - v2[2]) > .1)
continue;
v1 = grid1->verts[grid1->width * (k - 2) + offset1].xyz;
v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
if ( fabs(v1[0] - v2[0]) > .1)
continue;
if ( fabs(v1[1] - v2[1]) > .1)
continue;
if ( fabs(v1[2] - v2[2]) > .1)
continue;
//
v1 = grid2->verts[grid2->width * l + offset2].xyz;
v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
if ( fabs(v1[0] - v2[0]) < .01 &&
fabs(v1[1] - v2[1]) < .01 &&
fabs(v1[2] - v2[2]) < .01)
continue;
//
//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
// insert row into grid2 right after after row l
if (m) column = grid2->width-1;
else column = 0;
grid2 = R_GridInsertRow( grid2, l+1, column,
grid1->verts[grid1->width * (k - 1) + offset1].xyz, grid1->heightLodError[k+1]);
grid2->lodStitched = qfalse;
s_worldData.surfaces[grid2num].data = (void *) grid2;
return qtrue;
}
}
}
}
return qfalse;
}
/*
===============
R_TryStitchPatch
This function will try to stitch patches in the same LoD group together for the highest LoD.
Only single missing vertice cracks will be fixed.
Vertices will be joined at the patch side a crack is first found, at the other side
of the patch (on the same row or column) the vertices will not be joined and cracks
might still appear at that side.
===============
*/
int R_TryStitchingPatch( int grid1num ) {
int j, numstitches;
srfGridMesh_t *grid1, *grid2;
numstitches = 0;
grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data;
for ( j = 0; j < s_worldData.numsurfaces; j++ ) {
//
grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data;
// if this surface is not a grid
if ( grid2->surfaceType != SF_GRID ) continue;
// grids in the same LOD group should have the exact same lod radius
if ( grid1->lodRadius != grid2->lodRadius ) continue;
// grids in the same LOD group should have the exact same lod origin
if ( grid1->lodOrigin[0] != grid2->lodOrigin[0] ) continue;
if ( grid1->lodOrigin[1] != grid2->lodOrigin[1] ) continue;
if ( grid1->lodOrigin[2] != grid2->lodOrigin[2] ) continue;
//
while (R_StitchPatches(grid1num, j))
{
numstitches++;
}
}
return numstitches;
}
/*
===============
R_StitchAllPatches
===============
*/
void R_StitchAllPatches( void ) {
int i, stitched, numstitches;
srfGridMesh_t *grid1;
numstitches = 0;
do
{
stitched = qfalse;
for ( i = 0; i < s_worldData.numsurfaces; i++ ) {
//
grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data;
// if this surface is not a grid
if ( grid1->surfaceType != SF_GRID )
continue;
//
if ( grid1->lodStitched )
continue;
//
grid1->lodStitched = qtrue;
stitched = qtrue;
//
numstitches += R_TryStitchingPatch( i );
}
}
while (stitched);
ri.Printf( PRINT_ALL, "stitched %d LoD cracks\n", numstitches );
}
/*
===============
R_MovePatchSurfacesToHunk
===============
*/
void R_MovePatchSurfacesToHunk(void) {
int i, size;
srfGridMesh_t *grid, *hunkgrid;
for ( i = 0; i < s_worldData.numsurfaces; i++ ) {
//
grid = (srfGridMesh_t *) s_worldData.surfaces[i].data;
// if this surface is not a grid
if ( grid->surfaceType != SF_GRID )
continue;
//
size = (grid->width * grid->height - 1) * sizeof( drawVert_t ) + sizeof( *grid );
hunkgrid = ri.Hunk_Alloc( size, h_low );
Com_Memcpy(hunkgrid, grid, size);
hunkgrid->widthLodError = ri.Hunk_Alloc( grid->width * 4, h_low );
Com_Memcpy( hunkgrid->widthLodError, grid->widthLodError, grid->width * 4 );
hunkgrid->heightLodError = ri.Hunk_Alloc( grid->height * 4, h_low );
Com_Memcpy( grid->heightLodError, grid->heightLodError, grid->height * 4 );
R_FreeSurfaceGridMesh( grid );
s_worldData.surfaces[i].data = (void *) hunkgrid;
}
}
/*
===============
R_LoadSurfaces
===============
*/
static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) {
dsurface_t *in;
msurface_t *out;
drawVert_t *dv;
int *indexes;
int count;
int numFaces, numMeshes, numTriSurfs, numFlares;
int i;
numFaces = 0;
numMeshes = 0;
numTriSurfs = 0;
numFlares = 0;
in = (void *)(fileBase + surfs->fileofs);
if (surfs->filelen % sizeof(*in))
ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
count = surfs->filelen / sizeof(*in);
dv = (void *)(fileBase + verts->fileofs);
if (verts->filelen % sizeof(*dv))
ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
indexes = (void *)(fileBase + indexLump->fileofs);
if ( indexLump->filelen % sizeof(*indexes))
ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
out = ri.Hunk_Alloc ( count * sizeof(*out), h_low );
s_worldData.surfaces = out;
s_worldData.numsurfaces = count;
for ( i = 0 ; i < count ; i++, in++, out++ ) {
switch ( LittleLong( in->surfaceType ) ) {
case MST_PATCH:
ParseMesh ( in, dv, out );
numMeshes++;
break;
case MST_TRIANGLE_SOUP:
ParseTriSurf( in, dv, out, indexes );
numTriSurfs++;
break;
case MST_PLANAR:
ParseFace( in, dv, out, indexes );
numFaces++;
break;
case MST_FLARE:
ParseFlare( in, dv, out, indexes );
numFlares++;
break;
default:
ri.Error( ERR_DROP, "Bad surfaceType" );
}
}
#ifdef PATCH_STITCHING
R_StitchAllPatches();
#endif
R_FixSharedVertexLodError();
#ifdef PATCH_STITCHING
R_MovePatchSurfacesToHunk();
#endif
ri.Printf( PRINT_ALL, "...loaded %d faces, %i meshes, %i trisurfs, %i flares\n",
numFaces, numMeshes, numTriSurfs, numFlares );
}
/*
=================
R_LoadSubmodels
=================
*/
static void R_LoadSubmodels( lump_t *l ) {
dmodel_t *in;
bmodel_t *out;
int i, j, count;
in = (void *)(fileBase + l->fileofs);
if (l->filelen % sizeof(*in))
ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
count = l->filelen / sizeof(*in);
s_worldData.bmodels = out = ri.Hunk_Alloc( count * sizeof(*out), h_low );
for ( i=0 ; i<count ; i++, in++, out++ ) {
model_t *model;
model = R_AllocModel();
assert( model != NULL ); // this should never happen
model->type = MOD_BRUSH;
model->bmodel = out;
Com_sprintf( model->name, sizeof( model->name ), "*%d", i );
for (j=0 ; j<3 ; j++) {
out->bounds[0][j] = LittleFloat (in->mins[j]);
out->bounds[1][j] = LittleFloat (in->maxs[j]);
}
out->firstSurface = s_worldData.surfaces + LittleLong( in->firstSurface );
out->numSurfaces = LittleLong( in->numSurfaces );
}
}
//==================================================================
/*
=================
R_SetParent
=================
*/
static void R_SetParent (mnode_t *node, mnode_t *parent)
{
node->parent = parent;
if (node->contents != -1)
return;
R_SetParent (node->children[0], node);
R_SetParent (node->children[1], node);
}
/*
=================
R_LoadNodesAndLeafs
=================
*/
static void R_LoadNodesAndLeafs (lump_t *nodeLump, lump_t *leafLump) {
int i, j, p;
dnode_t *in;
dleaf_t *inLeaf;
mnode_t *out;
int numNodes, numLeafs;
in = (void *)(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_low);
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -