📄 tr_bsp.c
字号:
surf->data = (surfaceType_t *)tri;
// copy vertexes
ClearBounds( tri->bounds[0], tri->bounds[1] );
verts += LittleLong( ds->firstVert );
for ( i = 0 ; i < numVerts ; i++ ) {
for ( j = 0 ; j < 3 ; j++ ) {
tri->verts[i].xyz[j] = LittleFloat( verts[i].xyz[j] );
tri->verts[i].normal[j] = LittleFloat( verts[i].normal[j] );
}
AddPointToBounds( tri->verts[i].xyz, tri->bounds[0], tri->bounds[1] );
for ( j = 0 ; j < 2 ; j++ ) {
tri->verts[i].st[j] = LittleFloat( verts[i].st[j] );
tri->verts[i].lightmap[j] = LittleFloat( verts[i].lightmap[j] );
}
R_ColorShiftLightingBytes( verts[i].color, tri->verts[i].color );
}
// copy indexes
indexes += LittleLong( ds->firstIndex );
for ( i = 0 ; i < numIndexes ; i++ ) {
tri->indexes[i] = LittleLong( indexes[i] );
if ( tri->indexes[i] < 0 || tri->indexes[i] >= numVerts ) {
ri.Error( ERR_DROP, "Bad index in triangle surface" );
}
}
}
/*
===============
ParseFlare
===============
*/
static void ParseFlare( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int *indexes ) {
srfFlare_t *flare;
int i;
// get fog volume
surf->fogIndex = LittleLong( ds->fogNum ) + 1;
// get shader
surf->shader = ShaderForShaderNum( ds->shaderNum, LIGHTMAP_BY_VERTEX );
if ( r_singleShader->integer && !surf->shader->isSky ) {
surf->shader = tr.defaultShader;
}
flare = ri.Hunk_Alloc( sizeof( *flare ), h_low );
flare->surfaceType = SF_FLARE;
surf->data = (surfaceType_t *)flare;
for ( i = 0 ; i < 3 ; i++ ) {
flare->origin[i] = LittleFloat( ds->lightmapOrigin[i] );
flare->color[i] = LittleFloat( ds->lightmapVecs[0][i] );
flare->normal[i] = LittleFloat( ds->lightmapVecs[2][i] );
}
}
/*
=================
R_MergedWidthPoints
returns true if there are grid points merged on a width edge
=================
*/
int R_MergedWidthPoints(srfGridMesh_t *grid, int offset) {
int i, j;
for (i = 1; i < grid->width-1; i++) {
for (j = i + 1; j < grid->width-1; j++) {
if ( fabs(grid->verts[i + offset].xyz[0] - grid->verts[j + offset].xyz[0]) > .1) continue;
if ( fabs(grid->verts[i + offset].xyz[1] - grid->verts[j + offset].xyz[1]) > .1) continue;
if ( fabs(grid->verts[i + offset].xyz[2] - grid->verts[j + offset].xyz[2]) > .1) continue;
return qtrue;
}
}
return qfalse;
}
/*
=================
R_MergedHeightPoints
returns true if there are grid points merged on a height edge
=================
*/
int R_MergedHeightPoints(srfGridMesh_t *grid, int offset) {
int i, j;
for (i = 1; i < grid->height-1; i++) {
for (j = i + 1; j < grid->height-1; j++) {
if ( fabs(grid->verts[grid->width * i + offset].xyz[0] - grid->verts[grid->width * j + offset].xyz[0]) > .1) continue;
if ( fabs(grid->verts[grid->width * i + offset].xyz[1] - grid->verts[grid->width * j + offset].xyz[1]) > .1) continue;
if ( fabs(grid->verts[grid->width * i + offset].xyz[2] - grid->verts[grid->width * j + offset].xyz[2]) > .1) continue;
return qtrue;
}
}
return qfalse;
}
/*
=================
R_FixSharedVertexLodError_r
NOTE: never sync LoD through grid edges with merged points!
FIXME: write generalized version that also avoids cracks between a patch and one that meets half way?
=================
*/
void R_FixSharedVertexLodError_r( int start, srfGridMesh_t *grid1 ) {
int j, k, l, m, n, offset1, offset2, touch;
srfGridMesh_t *grid2;
for ( j = start; 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;
// if the LOD errors are already fixed for this patch
if ( grid2->lodFixed == 2 ) 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;
//
touch = qfalse;
for (n = 0; n < 2; n++) {
//
if (n) offset1 = (grid1->height-1) * grid1->width;
else offset1 = 0;
if (R_MergedWidthPoints(grid1, offset1)) continue;
for (k = 1; k < grid1->width-1; k++) {
for (m = 0; m < 2; m++) {
if (m) offset2 = (grid2->height-1) * grid2->width;
else offset2 = 0;
if (R_MergedWidthPoints(grid2, offset2)) continue;
for ( l = 1; l < grid2->width-1; l++) {
//
if ( fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1) continue;
if ( fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1) continue;
if ( fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1) continue;
// ok the points are equal and should have the same lod error
grid2->widthLodError[l] = grid1->widthLodError[k];
touch = qtrue;
}
}
for (m = 0; m < 2; m++) {
if (m) offset2 = grid2->width-1;
else offset2 = 0;
if (R_MergedHeightPoints(grid2, offset2)) continue;
for ( l = 1; l < grid2->height-1; l++) {
//
if ( fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1) continue;
if ( fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1) continue;
if ( fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1) continue;
// ok the points are equal and should have the same lod error
grid2->heightLodError[l] = grid1->widthLodError[k];
touch = qtrue;
}
}
}
}
for (n = 0; n < 2; n++) {
//
if (n) offset1 = grid1->width-1;
else offset1 = 0;
if (R_MergedHeightPoints(grid1, offset1)) continue;
for (k = 1; k < grid1->height-1; k++) {
for (m = 0; m < 2; m++) {
if (m) offset2 = (grid2->height-1) * grid2->width;
else offset2 = 0;
if (R_MergedWidthPoints(grid2, offset2)) continue;
for ( l = 1; l < grid2->width-1; l++) {
//
if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1) continue;
if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1) continue;
if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1) continue;
// ok the points are equal and should have the same lod error
grid2->widthLodError[l] = grid1->heightLodError[k];
touch = qtrue;
}
}
for (m = 0; m < 2; m++) {
if (m) offset2 = grid2->width-1;
else offset2 = 0;
if (R_MergedHeightPoints(grid2, offset2)) continue;
for ( l = 1; l < grid2->height-1; l++) {
//
if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1) continue;
if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1) continue;
if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1) continue;
// ok the points are equal and should have the same lod error
grid2->heightLodError[l] = grid1->heightLodError[k];
touch = qtrue;
}
}
}
}
if (touch) {
grid2->lodFixed = 2;
R_FixSharedVertexLodError_r ( start, grid2 );
//NOTE: this would be correct but makes things really slow
//grid2->lodFixed = 1;
}
}
}
/*
=================
R_FixSharedVertexLodError
This function assumes that all patches in one group are nicely stitched together for the highest LoD.
If this is not the case this function will still do its job but won't fix the highest LoD cracks.
=================
*/
void R_FixSharedVertexLodError( void ) {
int i;
srfGridMesh_t *grid1;
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->lodFixed )
continue;
//
grid1->lodFixed = 2;
// recursively fix other patches in the same LOD group
R_FixSharedVertexLodError_r( i + 1, grid1);
}
}
/*
===============
R_StitchPatches
===============
*/
int R_StitchPatches( int grid1num, int grid2num ) {
float *v1, *v2;
srfGridMesh_t *grid1, *grid2;
int k, l, m, n, offset1, offset2, row, column;
grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data;
grid2 = (srfGridMesh_t *) s_worldData.surfaces[grid2num].data;
for (n = 0; n < 2; n++) {
//
if (n) offset1 = (grid1->height-1) * grid1->width;
else offset1 = 0;
if (R_MergedWidthPoints(grid1, offset1))
continue;
for (k = 0; k < grid1->width-2; 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[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]);
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 = 0; k < grid1->height-2; 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;
}
}
}
}
for (n = 0; n < 2; n++) {
//
if (n) offset1 = (grid1->height-1) * grid1->width;
else offset1 = 0;
if (R_MergedWidthPoints(grid1, offset1))
continue;
for (k = grid1->width-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++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -