This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/engine/client/gl_rsurf.c

244 lines
5.8 KiB
C

//=======================================================================
// Copyright XashXT Group 2010 ©
// gl_rsurf.c - surface-related refresh code
//=======================================================================
#include "common.h"
#include "client.h"
#include "gl_local.h"
#include "cm_local.h"
#define LIGHTMAP_BYTES 4
#define BLOCK_WIDTH 128
#define BLOCK_HEIGHT 128
#define MAX_LIGHTMAPS 128
#define SUBDIVIDE_SIZE 64
//#define SUBDIVIDE_SIZE 1024
byte *Mod_GetCurrentVis( void )
{
// return Mod_LeafPVS( r_viewleaf, r_worldmodel );
return NULL;
}
static void BoundPoly( int numverts, float *verts, vec3_t mins, vec3_t maxs )
{
int i, j;
float *v;
mins[0] = mins[1] = mins[2] = 9999;
maxs[0] = maxs[1] = maxs[2] = -9999;
for( i = 0, v = verts; i < numverts; i++ )
{
for( j = 0; j < 3; j++, v++ )
{
if( *v < mins[j] ) mins[j] = *v;
if( *v > maxs[j] ) maxs[j] = *v;
}
}
}
static void SubdividePolygon_r( msurface_t *warpface, int numverts, float *verts )
{
int i, j, k, f, b;
vec3_t mins, maxs;
float m, frac, s, t, *v;
vec3_t front[SUBDIVIDE_SIZE], back[SUBDIVIDE_SIZE], total;
float dist[SUBDIVIDE_SIZE], total_s, total_t;
glpoly_t *poly;
if( numverts > ( SUBDIVIDE_SIZE - 4 ))
Host_Error( "Mod_SubdividePolygon: too many vertexes on face ( %i )\n", numverts );
BoundPoly( numverts, verts, mins, maxs );
for( i = 0; i < 3; i++ )
{
m = ( mins[i] + maxs[i] ) * 0.5f;
m = SUBDIVIDE_SIZE * floor( m / SUBDIVIDE_SIZE + 0.5f );
if( maxs[i] - m < 8 ) continue;
if( m - mins[i] < 8 ) continue;
// cut it
v = verts + i;
for( j = 0; j < numverts; j++, v += 3 )
dist[j] = *v - m;
// wrap cases
dist[j] = dist[0];
v -= i;
VectorCopy( verts, v );
f = b = 0;
v = verts;
for( j = 0; j < numverts; j++, v += 3 )
{
if( dist[j] >= 0 )
{
VectorCopy( v, front[f] );
f++;
}
if( dist[j] <= 0 )
{
VectorCopy (v, back[b]);
b++;
}
if( dist[j] == 0 || dist[j+1] == 0 )
continue;
if(( dist[j] > 0 ) != ( dist[j+1] > 0 ))
{
// clip point
frac = dist[j] / ( dist[j] - dist[j+1] );
for( k = 0; k < 3; k++ )
front[f][k] = back[b][k] = v[k] + frac * (v[3+k] - v[k]);
f++;
b++;
}
}
SubdividePolygon_r( warpface, f, front[0] );
SubdividePolygon_r( warpface, b, back[0] );
return;
}
// add a point in the center to help keep warp valid
poly = Mem_Alloc( loadmodel->mempool, sizeof( glpoly_t ) + ((numverts-4)+2) * VERTEXSIZE * sizeof( float ));
poly->next = warpface->polys;
warpface->polys = poly;
poly->numverts = numverts + 2;
VectorClear( total );
total_s = 0;
total_t = 0;
for( i = 0; i < numverts; i++, verts += 3 )
{
VectorCopy( verts, poly->verts[i+1] );
s = DotProduct( verts, warpface->texinfo->vecs[0] );
t = DotProduct( verts, warpface->texinfo->vecs[1] );
total_s += s;
total_t += t;
VectorAdd( total, verts, total );
poly->verts[i+1][3] = s;
poly->verts[i+1][4] = t;
}
VectorScale( total, ( 1.0f / numverts ), poly->verts[0] );
poly->verts[0][3] = total_s / numverts;
poly->verts[0][4] = total_t / numverts;
// copy first vertex to last
Mem_Copy( poly->verts[i+1], poly->verts[1], sizeof( poly->verts[0] ));
}
/*
================
GL_SubdivideSurface
Breaks a polygon up along axial 64 unit
boundaries so that turbulent and sky warps
can be done reasonably.
================
*/
void GL_SubdivideSurface( msurface_t *fa )
{
vec3_t verts[SUBDIVIDE_SIZE];
int numverts;
int i, lindex;
float *vec;
// convert edges back to a normal polygon
numverts = 0;
for( i = 0; i < fa->numedges; i++ )
{
lindex = loadmodel->surfedges[fa->firstedge + i];
if( lindex > 0 ) vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position;
else vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position;
VectorCopy (vec, verts[numverts]);
numverts++;
}
// do subdivide
SubdividePolygon_r( fa, numverts, verts[0] );
}
/*
================
GL_BuildPolygonFromSurface
================
*/
void GL_BuildPolygonFromSurface( msurface_t *fa )
{
int i, lindex, lnumverts;
medge_t *pedges, *r_pedge;
int vertpage;
float *vec;
float s, t;
glpoly_t *poly;
vec3_t total;
// reconstruct the polygon
pedges = loadmodel->edges;
lnumverts = fa->numedges;
vertpage = 0;
VectorClear( total );
// draw texture
poly = Mem_Alloc( loadmodel->mempool, sizeof( glpoly_t ) + ( lnumverts - 4 ) * VERTEXSIZE * sizeof( float ));
poly->next = fa->polys;
poly->flags = fa->flags;
fa->polys = poly;
poly->numverts = lnumverts;
for( i = 0; i < lnumverts; i++ )
{
lindex = loadmodel->surfedges[fa->firstedge + i];
if( lindex > 0 )
{
r_pedge = &pedges[lindex];
vec = loadmodel->vertexes[r_pedge->v[0]].position;
}
else
{
r_pedge = &pedges[-lindex];
vec = loadmodel->vertexes[r_pedge->v[1]].position;
}
s = DotProduct( vec, fa->texinfo->vecs[0] ) + fa->texinfo->vecs[0][3];
s /= fa->texinfo->texture->width;
t = DotProduct( vec, fa->texinfo->vecs[1] ) + fa->texinfo->vecs[1][3];
t /= fa->texinfo->texture->height;
VectorAdd( total, vec, total );
VectorCopy( vec, poly->verts[i] );
poly->verts[i][3] = s;
poly->verts[i][4] = t;
// lightmap texture coordinates
s = DotProduct( vec, fa->texinfo->vecs[0] ) + fa->texinfo->vecs[0][3];
s -= fa->texturemins[0];
s += fa->light_s * 16;
s += 8;
s /= BLOCK_WIDTH * 16; //fa->texinfo->texture->width;
t = DotProduct( vec, fa->texinfo->vecs[1] ) + fa->texinfo->vecs[1][3];
t -= fa->texturemins[1];
t += fa->light_t * 16;
t += 8;
t /= BLOCK_HEIGHT * 16; //fa->texinfo->texture->height;
poly->verts[i][5] = s;
poly->verts[i][6] = t;
}
poly->numverts = lnumverts;
}