add MeshQuadIterator

This commit is contained in:
Garux
2025-11-07 20:49:29 +05:00
parent d19c89224a
commit ef8c3fd7c1
9 changed files with 243 additions and 446 deletions
+58 -110
View File
@@ -63,7 +63,7 @@ static Vector3 entityOrigin;
returns false if a texture matrix cannot be created
*/
static bool MakeTextureMatrix( decalProjector_t *dp, const Plane3f& projection, const bspDrawVert_t *a, const bspDrawVert_t *b, const bspDrawVert_t *c ){
static bool MakeTextureMatrix( decalProjector_t& dp, const Plane3f& projection, const bspDrawVert_t *a, const bspDrawVert_t *b, const bspDrawVert_t *c ){
int i, j;
double bb, s, t;
DoubleVector3 pa, pb, pc;
@@ -138,13 +138,13 @@ static bool MakeTextureMatrix( decalProjector_t *dp, const Plane3f& projection,
}
for ( i = 0; i < 2; ++i )
for ( j = 0; j < 3; ++j )
dp->texMat[ i ][ j ] = lengths[ i ] != 0 ? ( axis[ i ][ j ] / lengths[ i ] ) : 0.0;
//% dp->texMat[ i ][ j ] = std::fabs( vecs[ i ][ j ] ) > 0 ? ( 1.0 / vecs[ i ][ j ] ) : 0.0;
//% dp->texMat[ i ][ j ] = axis[ i ][ j ] > 0 ? ( 1.0 / axis[ i ][ j ] ) : 0.0;
dp.texMat[ i ][ j ] = lengths[ i ] != 0 ? ( axis[ i ][ j ] / lengths[ i ] ) : 0.0;
//% dp.texMat[ i ][ j ] = std::fabs( vecs[ i ][ j ] ) > 0 ? ( 1.0 / vecs[ i ][ j ] ) : 0.0;
//% dp.texMat[ i ][ j ] = axis[ i ][ j ] > 0 ? ( 1.0 / axis[ i ][ j ] ) : 0.0;
/* calculalate translation component */
dp->texMat[ 0 ][ 3 ] = a->st[ 0 ] - vector3_dot( a->xyz, dp->texMat[ 0 ].vec3() );
dp->texMat[ 1 ][ 3 ] = a->st[ 1 ] - vector3_dot( a->xyz, dp->texMat[ 1 ].vec3() );
dp.texMat[ 0 ][ 3 ] = a->st[ 0 ] - vector3_dot( a->xyz, dp.texMat[ 0 ].vec3() );
dp.texMat[ 1 ][ 3 ] = a->st[ 1 ] - vector3_dot( a->xyz, dp.texMat[ 1 ].vec3() );
}
#else
{
@@ -186,15 +186,15 @@ static bool MakeTextureMatrix( decalProjector_t *dp, const Plane3f& projection,
/* set texture matrix component */
if ( std::fabs( delta ) > 0 ) {
dp->texMat[ i ][ j ] = texDelta / delta;
dp.texMat[ i ][ j ] = texDelta / delta;
}
else{
dp->texMat[ i ][ j ] = 0;
dp.texMat[ i ][ j ] = 0;
}
}
/* set translation component */
dp->texMat[ i ][ 3 ] = a->st[ i ] - vector3_dot( pa, dp->texMat[ i ].vec3() );
dp.texMat[ i ][ 3 ] = a->st[ i ] - vector3_dot( pa, dp.texMat[ i ].vec3() );
}
}
#endif
@@ -202,34 +202,34 @@ static bool MakeTextureMatrix( decalProjector_t *dp, const Plane3f& projection,
/* debug code */
#if 1
Sys_Printf( "Mat: [ %f %f %f %f ] [ %f %f %f %f ] Theta: %lf (%lf)\n",
dp->texMat[ 0 ][ 0 ], dp->texMat[ 0 ][ 1 ], dp->texMat[ 0 ][ 2 ], dp->texMat[ 0 ][ 3 ],
dp->texMat[ 1 ][ 0 ], dp->texMat[ 1 ][ 1 ], dp->texMat[ 1 ][ 2 ], dp->texMat[ 1 ][ 3 ],
radians_to_degrees( acos( vector3_dot( dp->texMat[ 0 ].vec3(), dp->texMat[ 1 ].vec3() ) ) ),
dp.texMat[ 0 ][ 0 ], dp.texMat[ 0 ][ 1 ], dp.texMat[ 0 ][ 2 ], dp.texMat[ 0 ][ 3 ],
dp.texMat[ 1 ][ 0 ], dp.texMat[ 1 ][ 1 ], dp.texMat[ 1 ][ 2 ], dp.texMat[ 1 ][ 3 ],
radians_to_degrees( acos( vector3_dot( dp.texMat[ 0 ].vec3(), dp.texMat[ 1 ].vec3() ) ) ),
radians_to_degrees( acos( vector3_dot( axis[ 0 ], axis[ 1 ] ) ) ) );
Sys_Printf( "XYZ: %f %f %f ST: %f %f ST(t): %lf %lf\n",
a->xyz[ 0 ], a->xyz[ 1 ], a->xyz[ 2 ],
a->st[ 0 ], a->st[ 1 ],
vector3_dot( a->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ], vector3_dot( a->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ] );
vector3_dot( a->xyz, dp.texMat[ 0 ].vec3() ) + dp.texMat[ 0 ][ 3 ], vector3_dot( a->xyz, dp.texMat[ 1 ].vec3() ) + dp.texMat[ 1 ][ 3 ] );
#endif
/* test texture matrix */
s = vector3_dot( a->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ];
t = vector3_dot( a->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ];
s = vector3_dot( a->xyz, dp.texMat[ 0 ].vec3() ) + dp.texMat[ 0 ][ 3 ];
t = vector3_dot( a->xyz, dp.texMat[ 1 ].vec3() ) + dp.texMat[ 1 ][ 3 ];
if ( !float_equal_epsilon( s, a->st[ 0 ], 0.01 ) || !float_equal_epsilon( t, a->st[ 1 ], 0.01 ) ) {
Sys_Printf( "Bad texture matrix! (A) (%f, %f) != (%f, %f)\n",
s, t, a->st[ 0 ], a->st[ 1 ] );
//% return false;
}
s = vector3_dot( b->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ];
t = vector3_dot( b->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ];
s = vector3_dot( b->xyz, dp.texMat[ 0 ].vec3() ) + dp.texMat[ 0 ][ 3 ];
t = vector3_dot( b->xyz, dp.texMat[ 1 ].vec3() ) + dp.texMat[ 1 ][ 3 ];
if ( !float_equal_epsilon( s, b->st[ 0 ], 0.01 ) || !float_equal_epsilon( t, b->st[ 1 ], 0.01 ) ) {
Sys_Printf( "Bad texture matrix! (B) (%f, %f) != (%f, %f)\n",
s, t, b->st[ 0 ], b->st[ 1 ] );
//% return false;
}
s = vector3_dot( c->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ];
t = vector3_dot( c->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ];
s = vector3_dot( c->xyz, dp.texMat[ 0 ].vec3() ) + dp.texMat[ 0 ][ 3 ];
t = vector3_dot( c->xyz, dp.texMat[ 1 ].vec3() ) + dp.texMat[ 1 ][ 3 ];
if ( !float_equal_epsilon( s, c->st[ 0 ], 0.01 ) || !float_equal_epsilon( t, c->st[ 1 ], 0.01 ) ) {
Sys_Printf( "Bad texture matrix! (C) (%f, %f) != (%f, %f)\n",
s, t, c->st[ 0 ], c->st[ 1 ] );
@@ -286,16 +286,7 @@ static void TransformDecalProjector( decalProjector_t *in, const Vector3 (&axis)
creates a new decal projector from a triangle
*/
static int MakeDecalProjector( shaderInfo_t *si, const Plane3f& projection, float distance, int numVerts, const bspDrawVert_t **dv ){
int i, j;
decalProjector_t *dp;
/* dummy check */
if ( numVerts != 3 && numVerts != 4 ) {
return -1;
}
static int MakeDecalProjector( shaderInfo_t *si, const Plane3f& projection, float distance, const TriRef& tri ){
/* limit check */
if ( numProjectors >= MAX_PROJECTORS ) {
Sys_Warning( "MAX_PROJECTORS (%d) exceeded, no more decal projectors available.\n", MAX_PROJECTORS );
@@ -303,45 +294,47 @@ static int MakeDecalProjector( shaderInfo_t *si, const Plane3f& projection, floa
}
/* create a new projector */
dp = &projectors[ numProjectors ];
memset( dp, 0, sizeof( *dp ) );
decalProjector_t& dp = projectors[ numProjectors ];
memset( &dp, 0, sizeof( dp ) );
/* basic setup */
dp->si = si;
dp->numPlanes = numVerts + 2;
dp.si = si;
dp.numPlanes = tri.size() + 2;
/* make texture matrix */
if ( !MakeTextureMatrix( dp, projection, dv[ 0 ], dv[ 1 ], dv[ 2 ] ) ) {
if ( !MakeTextureMatrix( dp, projection, tri[ 0 ], tri[ 1 ], tri[ 2 ] ) ) {
return -1;
}
/* bound the projector */
dp->minmax.clear();
for ( i = 0; i < numVerts; ++i )
dp.minmax.clear();
for ( size_t i = 0; i < tri.size(); ++i )
{
dp->minmax.extend( dv[ i ]->xyz );
dp->minmax.extend( dv[ i ]->xyz + projection.normal() * distance );
dp.minmax.extend( tri[ i ]->xyz );
dp.minmax.extend( tri[ i ]->xyz + projection.normal() * distance );
}
/* make bouding sphere */
dp->center = dp->minmax.origin();
dp->radius = vector3_length( dp->minmax.maxs - dp->center );
dp->radius2 = dp->radius * dp->radius;
dp.center = dp.minmax.origin();
dp.radius = vector3_length( dp.minmax.maxs - dp.center );
dp.radius2 = dp.radius * dp.radius;
/* make the front plane */
if ( !PlaneFromPoints( dp->planes[ 0 ], dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) ) {
if ( !PlaneFromPoints( dp.planes[ 0 ], tri[ 0 ]->xyz, tri[ 1 ]->xyz, tri[ 2 ]->xyz ) ) {
return -1;
}
/* make the back plane */
dp->planes[ 1 ].normal() = -dp->planes[ 0 ].normal();
dp->planes[ 1 ].dist() = vector3_dot( dv[ 0 ]->xyz + projection.normal() * distance, dp->planes[ 1 ].normal() );
dp.planes[ 1 ].normal() = -dp.planes[ 0 ].normal();
dp.planes[ 1 ].dist() = vector3_dot( tri[ 0 ]->xyz + projection.normal() * distance, dp.planes[ 1 ].normal() );
/* make the side planes */
for ( i = 0; i < numVerts; ++i )
for ( size_t i = 0; i < tri.size(); ++i )
{
j = ( i + 1 ) % numVerts;
if ( !PlaneFromPoints( dp->planes[ i + 2 ], dv[ j ]->xyz, dv[ i ]->xyz, dv[ i ]->xyz + projection.normal() * distance ) ) {
if ( !PlaneFromPoints( dp.planes[ i + 2 ],
tri[ ( i + 1 ) % tri.size() ]->xyz,
tri[ i ]->xyz,
tri[ i ]->xyz + projection.normal() * distance ) ) {
return -1;
}
}
@@ -417,44 +410,19 @@ void ProcessDecals(){
vert.xyz += e.origin;
/* iterate through the mesh quads */
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
for( MeshQuadIterator it( mesh ); it; ++it ){
#if 0
/* planar? (nuking this optimization as it doesn't work on non-rectangular quads) */
if ( 0 && PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) &&
std::fabs( plane3_distance_to_point( plane, dv[ 1 ]->xyz ) ) <= PLANAR_EPSILON ) {
/* make a quad projector */
MakeDecalProjector( p.shaderInfo, projection, distance, 4, dv );
}
else
#endif
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* get drawverts */
const bspDrawVert_t *dv[ 4 ] = {
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ]
};
/* planar? (nuking this optimization as it doesn't work on non-rectangular quads) */
if ( 0 && PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) &&
std::fabs( plane3_distance_to_point( plane, dv[ 1 ]->xyz ) ) <= PLANAR_EPSILON ) {
/* make a quad projector */
MakeDecalProjector( p.shaderInfo, projection, distance, 4, dv );
}
else
{
/* make first triangle */
MakeDecalProjector( p.shaderInfo, projection, distance, 3, dv );
/* make second triangle */
dv[ 1 ] = dv[ 2 ];
dv[ 2 ] = dv[ 3 ];
MakeDecalProjector( p.shaderInfo, projection, distance, 3, dv );
}
for( const TriRef& tri : it.tris() )
MakeDecalProjector( p.shaderInfo, projection, distance, tri );
}
}
@@ -608,34 +576,14 @@ static void ProjectDecalOntoPatch( decalProjector_t& dp, mapDrawSurface_t& ds ){
mesh_t mesh = TessellatedMesh( mesh_t( ds.patchWidth, ds.patchHeight, ds.verts.data() ), IterationsForCurve( ds.longestCurve, patchSubdivisions ) );
/* iterate through the mesh quads */
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* generate decal for first triangle */
for( MeshQuadIterator it( mesh ); it; ++it ){
for( const TriRef& tri : it.tris() ){
/* generate decal for triangle */
winding_t w{
mesh.verts[ pw[ r + 0 ] ].xyz,
mesh.verts[ pw[ r + 1 ] ].xyz,
mesh.verts[ pw[ r + 2 ] ].xyz };
tri[ 0 ]->xyz,
tri[ 1 ]->xyz,
tri[ 2 ]->xyz };
ProjectDecalOntoWinding( dp, ds, w );
/* generate decal for second triangle */
winding_t w2{
mesh.verts[ pw[ r + 0 ] ].xyz,
mesh.verts[ pw[ r + 2 ] ].xyz,
mesh.verts[ pw[ r + 3 ] ].xyz };
ProjectDecalOntoWinding( dp, ds, w2 );
}
}
+34 -64
View File
@@ -662,87 +662,57 @@ void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, const shader
}
/* iterate through the mesh quads */
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
for( MeshQuadIterator it( mesh ); it; ++it )
{
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
const QuadRef quad( it.quad() );
/* planar? */
Plane3f plane;
const bool planar = PlaneFromPoints( plane, quad[ 0 ]->xyz, quad[ 1 ]->xyz, quad[ 2 ]->xyz )
&& std::fabs( plane3_distance_to_point( plane, quad[ 1 ]->xyz ) ) < PLANAR_EPSILON;
/* generate a quad */
if ( planar ) {
radWinding_t rw;
rw.numVerts = 4;
for ( int v = 0; v < 4; ++v )
{
/* get most everything */
memcpy( &rw.verts[ v ], quad[ v ], sizeof( bspDrawVert_t ) );
/* get drawverts */
const bspDrawVert_t *dv[ 4 ] = {
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ]
};
/* planar? */
Plane3f plane;
bool planar = PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz );
if ( planar ) {
if ( std::fabs( plane3_distance_to_point( plane, dv[ 1 ]->xyz ) ) > PLANAR_EPSILON ) {
planar = false;
/* fix colors */
for ( int i = 0; i < MAX_LIGHTMAPS; ++i )
{
rw.verts[ v ].color[ i ].rgb() = getRadVertexLuxel( i, ds.firstVert + quad[ v ]->color[ 0 ][ 0 ] );
rw.verts[ v ].color[ i ].alpha() = quad[ v ]->color[ i ].alpha();
}
}
/* generate a quad */
if ( planar ) {
radWinding_t rw;
rw.numVerts = 4;
for ( int v = 0; v < 4; ++v )
/* subdivide into area lights */
RadSubdivideDiffuseLight( lightmapNum, &ds, lm, si, scale, subdivide, &rw, cw );
}
/* generate 2 tris */
else
{
radWinding_t rw;
rw.numVerts = 3;
for ( const TriRef& tri : it.tris() )
{
for ( int v = 0; v < 3; ++v )
{
/* get most everything */
memcpy( &rw.verts[ v ], dv[ v ], sizeof( bspDrawVert_t ) );
memcpy( &rw.verts[ v ], tri[ v ], sizeof( bspDrawVert_t ) );
/* fix colors */
for ( int i = 0; i < MAX_LIGHTMAPS; ++i )
{
rw.verts[ v ].color[ i ].rgb() = getRadVertexLuxel( i, ds.firstVert + dv[ v ]->color[ 0 ][ 0 ] );
rw.verts[ v ].color[ i ].alpha() = dv[ v ]->color[ i ].alpha();
rw.verts[ v ].color[ i ].rgb() = getRadVertexLuxel( i, ds.firstVert + tri[ v ]->color[ 0 ][ 0 ] );
rw.verts[ v ].color[ i ].alpha() = tri[ v ]->color[ i ].alpha();
}
}
/* subdivide into area lights */
RadSubdivideDiffuseLight( lightmapNum, &ds, lm, si, scale, subdivide, &rw, cw );
}
/* generate 2 tris */
else
{
radWinding_t rw;
rw.numVerts = 3;
for ( int t = 0; t < 2; ++t )
{
for ( int v = 0; v < 3 + t; ++v )
{
/* get "other" triangle (stupid hacky logic, but whatevah) */
if ( v == 1 && t == 1 ) {
v++;
}
/* get most everything */
memcpy( &rw.verts[ v ], dv[ v ], sizeof( bspDrawVert_t ) );
/* fix colors */
for ( int i = 0; i < MAX_LIGHTMAPS; ++i )
{
rw.verts[ v ].color[ i ].rgb() = getRadVertexLuxel( i, ds.firstVert + dv[ v ]->color[ 0 ][ 0 ] );
rw.verts[ v ].color[ i ].alpha() = dv[ v ]->color[ i ].alpha();
}
}
/* subdivide into area lights */
RadSubdivideDiffuseLight( lightmapNum, &ds, lm, si, scale, subdivide, &rw, cw );
}
}
}
}
+62 -95
View File
@@ -177,7 +177,7 @@ static int AllocTraceNode(){
adds a winding to the raytracing pool
*/
static int AddTraceWinding( traceWinding_t *tw ){
static int AddTraceWinding( const traceWinding_t& tw ){
int num;
/* check for a dead winding */
@@ -194,7 +194,7 @@ static int AddTraceWinding( traceWinding_t *tw ){
}
/* add the winding */
memcpy( &traceWindings[ num ], tw, sizeof( *traceWindings ) );
memcpy( &traceWindings[ num ], &tw, sizeof( *traceWindings ) );
if ( num == numTraceWindings ) {
numTraceWindings++;
}
@@ -354,23 +354,23 @@ static int SetupTraceNodes_r( int bspNodeNum ){
#define TW_ON_EPSILON 0.25f
void ClipTraceWinding( traceWinding_t *tw, const Plane3f& plane, traceWinding_t *front, traceWinding_t *back ){
void ClipTraceWinding( const traceWinding_t& tw, const Plane3f& plane, traceWinding_t& front, traceWinding_t& back ){
int i, j, k;
EPlaneSide sides[ MAX_TW_VERTS ];
int counts[ 3 ] = { 0, 0, 0 };
float dists[ MAX_TW_VERTS ];
float frac;
traceVert_t *a, *b, mid;
traceVert_t mid;
/* clear front and back */
front->numVerts = 0;
back->numVerts = 0;
front.numVerts = 0;
back.numVerts = 0;
/* classify points */
for ( i = 0; i < tw->numVerts; ++i )
for ( i = 0; i < tw.numVerts; ++i )
{
dists[ i ] = plane3_distance_to_point( plane, tw->v[ i ].xyz );
dists[ i ] = plane3_distance_to_point( plane, tw.v[ i ].xyz );
if ( dists[ i ] < -TW_ON_EPSILON ) {
sides[ i ] = eSideBack;
}
@@ -385,56 +385,56 @@ void ClipTraceWinding( traceWinding_t *tw, const Plane3f& plane, traceWinding_t
/* entirely on front? */
if ( counts[ eSideBack ] == 0 ) {
memcpy( front, tw, sizeof( *front ) );
memcpy( &front, &tw, sizeof( front ) );
}
/* entirely on back? */
else if ( counts[ eSideFront ] == 0 ) {
memcpy( back, tw, sizeof( *back ) );
memcpy( &back, &tw, sizeof( back ) );
}
/* straddles the plane */
else
{
/* setup front and back */
memcpy( front, tw, sizeof( *front ) );
front->numVerts = 0;
memcpy( back, tw, sizeof( *back ) );
back->numVerts = 0;
memcpy( &front, &tw, sizeof( front ) );
front.numVerts = 0;
memcpy( &back, &tw, sizeof( back ) );
back.numVerts = 0;
/* split the winding */
for ( i = 0; i < tw->numVerts; ++i )
for ( i = 0; i < tw.numVerts; ++i )
{
/* radix */
j = ( i + 1 ) % tw->numVerts;
j = ( i + 1 ) % tw.numVerts;
/* get verts */
a = &tw->v[ i ];
b = &tw->v[ j ];
const traceVert_t& a = tw.v[ i ];
const traceVert_t& b = tw.v[ j ];
/* handle points on the splitting plane */
switch ( sides[ i ] )
{
case eSideFront:
if ( front->numVerts >= MAX_TW_VERTS ) {
if ( front.numVerts >= MAX_TW_VERTS ) {
Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
}
front->v[ front->numVerts++ ] = *a;
front.v[ front.numVerts++ ] = a;
break;
case eSideBack:
if ( back->numVerts >= MAX_TW_VERTS ) {
if ( back.numVerts >= MAX_TW_VERTS ) {
Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
}
back->v[ back->numVerts++ ] = *a;
back.v[ back.numVerts++ ] = a;
break;
case eSideOn:
if ( front->numVerts >= MAX_TW_VERTS || back->numVerts >= MAX_TW_VERTS ) {
if ( front.numVerts >= MAX_TW_VERTS || back.numVerts >= MAX_TW_VERTS ) {
Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
}
front->v[ front->numVerts++ ] = *a;
back->v[ back->numVerts++ ] = *a;
front.v[ front.numVerts++ ] = a;
back.v[ back.numVerts++ ] = a;
continue;
case eSideCross: // unused here, suppress warning
break;
@@ -446,7 +446,7 @@ void ClipTraceWinding( traceWinding_t *tw, const Plane3f& plane, traceWinding_t
}
/* check limit */
if ( front->numVerts >= MAX_TW_VERTS || back->numVerts >= MAX_TW_VERTS ) {
if ( front.numVerts >= MAX_TW_VERTS || back.numVerts >= MAX_TW_VERTS ) {
Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
}
@@ -462,15 +462,15 @@ void ClipTraceWinding( traceWinding_t *tw, const Plane3f& plane, traceWinding_t
mid.xyz[ k ] = -plane.dist();
}
else{
mid.xyz[ k ] = a->xyz[ k ] + frac * ( b->xyz[ k ] - a->xyz[ k ] );
mid.xyz[ k ] = a.xyz[ k ] + frac * ( b.xyz[ k ] - a.xyz[ k ] );
}
}
/* set texture coordinates */
mid.st = a->st + ( b->st - a->st ) * frac;
mid.st = a.st + ( b.st - a.st ) * frac;
/* copy midpoint to front and back polygons */
front->v[ front->numVerts++ ] = mid;
back->v[ back->numVerts++ ] = mid;
front.v[ front.numVerts++ ] = mid;
back.v[ back.numVerts++ ] = mid;
}
}
}
@@ -482,7 +482,7 @@ void ClipTraceWinding( traceWinding_t *tw, const Plane3f& plane, traceWinding_t
filters a trace winding into the raytracing tree
*/
static void FilterTraceWindingIntoNodes_r( traceWinding_t *tw, int nodeNum ){
static void FilterTraceWindingIntoNodes_r( traceWinding_t& tw, int nodeNum ){
int num;
Plane3f plane1, plane2, reverse;
traceNode_t *node;
@@ -501,7 +501,7 @@ static void FilterTraceWindingIntoNodes_r( traceWinding_t *tw, int nodeNum ){
if ( node->type >= 0 ) {
/* create winding plane if necessary, filtering out bogus windings as well */
if ( nodeNum == headNodeNum ) {
if ( !PlaneFromPoints( tw->plane, tw->v[ 0 ].xyz, tw->v[ 1 ].xyz, tw->v[ 2 ].xyz ) ) {
if ( !PlaneFromPoints( tw.plane, tw.v[ 0 ].xyz, tw.v[ 1 ].xyz, tw.v[ 2 ].xyz ) ) {
return;
}
}
@@ -515,7 +515,7 @@ static void FilterTraceWindingIntoNodes_r( traceWinding_t *tw, int nodeNum ){
plane1 = node->plane;
/* get winding plane */
plane2 = tw->plane;
plane2 = tw.plane;
/* invert surface plane */
reverse = plane3_flipped( plane2 );
@@ -533,14 +533,14 @@ static void FilterTraceWindingIntoNodes_r( traceWinding_t *tw, int nodeNum ){
}
/* clip the winding by node plane */
ClipTraceWinding( tw, plane1, &front, &back );
ClipTraceWinding( tw, plane1, front, back );
/* filter by node plane */
if ( front.numVerts >= 3 ) {
FilterTraceWindingIntoNodes_r( &front, node->children[ 0 ] );
FilterTraceWindingIntoNodes_r( front, node->children[ 0 ] );
}
if ( back.numVerts >= 3 ) {
FilterTraceWindingIntoNodes_r( &back, node->children[ 1 ] );
FilterTraceWindingIntoNodes_r( back, node->children[ 1 ] );
}
/* return to caller */
@@ -563,7 +563,7 @@ static void SubdivideTraceNode_r( int nodeNum, int depth ){
int i, j, count, num, frontNum, backNum, type;
float dist;
traceNode_t *node, *frontNode, *backNode;
traceWinding_t *tw, front, back;
traceWinding_t front, back;
/* dummy check */
@@ -599,13 +599,13 @@ static void SubdivideTraceNode_r( int nodeNum, int depth ){
for ( i = 0; i < node->numItems; ++i )
{
/* get winding */
tw = &traceWindings[ node->items[ i ] ];
const traceWinding_t& tw = traceWindings[ node->items[ i ] ];
/* walk its verts */
for ( j = 0; j < tw->numVerts; ++j )
for ( j = 0; j < tw.numVerts; ++j )
{
node->minmax.extend( tw->v[ j ].xyz );
average += tw->v[ j ].xyz;
node->minmax.extend( tw.v[ j ].xyz );
average += tw.v[ j ].xyz;
count++;
}
}
@@ -676,10 +676,10 @@ static void SubdivideTraceNode_r( int nodeNum, int depth ){
for ( i = 0; i < node->numItems; ++i )
{
/* get winding */
tw = &traceWindings[ node->items[ i ] ];
const traceWinding_t& tw = traceWindings[ node->items[ i ] ];
/* clip the winding by the new split plane */
ClipTraceWinding( tw, node->plane, &front, &back );
ClipTraceWinding( tw, node->plane, front, back );
/* kill the existing winding */
if ( front.numVerts >= 3 || back.numVerts >= 3 ) {
@@ -688,13 +688,13 @@ static void SubdivideTraceNode_r( int nodeNum, int depth ){
/* add front winding */
if ( front.numVerts >= 3 ) {
num = AddTraceWinding( &front );
num = AddTraceWinding( front );
AddItemToTraceNode( frontNode, num );
}
/* add back winding */
if ( back.numVerts >= 3 ) {
num = AddTraceWinding( &back );
num = AddTraceWinding( back );
AddItemToTraceNode( backNode, num );
}
}
@@ -894,44 +894,14 @@ static void PopulateWithBSPModel( const bspModel_t& model, const Matrix4& transf
mesh_t mesh = TessellatedMesh( mesh_t( ds.patchWidth, ds.patchHeight, &bspDrawVerts[ ds.firstVert ] ), info.patchIterations );
/* subdivide each quad to place the models */
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* make first triangle */
tw.v[ 0 ].xyz = mesh.verts[ pw[ r + 0 ] ].xyz;
tw.v[ 0 ].st = mesh.verts[ pw[ r + 0 ] ].st;
tw.v[ 1 ].xyz = mesh.verts[ pw[ r + 1 ] ].xyz;
tw.v[ 1 ].st = mesh.verts[ pw[ r + 1 ] ].st;
tw.v[ 2 ].xyz = mesh.verts[ pw[ r + 2 ] ].xyz;
tw.v[ 2 ].st = mesh.verts[ pw[ r + 2 ] ].st;
matrix4_transform_point( transform, tw.v[ 0 ].xyz );
matrix4_transform_point( transform, tw.v[ 1 ].xyz );
matrix4_transform_point( transform, tw.v[ 2 ].xyz );
FilterTraceWindingIntoNodes_r( &tw, nodeNum );
/* make second triangle */
tw.v[ 0 ].xyz = mesh.verts[ pw[ r + 0 ] ].xyz;
tw.v[ 0 ].st = mesh.verts[ pw[ r + 0 ] ].st;
tw.v[ 1 ].xyz = mesh.verts[ pw[ r + 2 ] ].xyz;
tw.v[ 1 ].st = mesh.verts[ pw[ r + 2 ] ].st;
tw.v[ 2 ].xyz = mesh.verts[ pw[ r + 3 ] ].xyz;
tw.v[ 2 ].st = mesh.verts[ pw[ r + 3 ] ].st;
matrix4_transform_point( transform, tw.v[ 0 ].xyz );
matrix4_transform_point( transform, tw.v[ 1 ].xyz );
matrix4_transform_point( transform, tw.v[ 2 ].xyz );
FilterTraceWindingIntoNodes_r( &tw, nodeNum );
for( MeshQuadIterator it( mesh ); it; ++it ){
for( const TriRef& tri : it.tris() ){
for( int i = 0; i < 3; ++i )
{
tw.v[ i ].xyz = matrix4_transformed_point( transform, tri[ i ]->xyz );
tw.v[ i ].st = tri[ i ]->st;
}
FilterTraceWindingIntoNodes_r( tw, nodeNum );
}
}
@@ -950,16 +920,13 @@ static void PopulateWithBSPModel( const bspModel_t& model, const Matrix4& transf
/* walk the triangle list */
for ( int j = 0; j < ds.numIndexes; j += 3 )
{
tw.v[ 0 ].xyz = verts[ indexes[ j + 0 ] ].xyz;
tw.v[ 0 ].st = verts[ indexes[ j + 0 ] ].st;
tw.v[ 1 ].xyz = verts[ indexes[ j + 1 ] ].xyz;
tw.v[ 1 ].st = verts[ indexes[ j + 1 ] ].st;
tw.v[ 2 ].xyz = verts[ indexes[ j + 2 ] ].xyz;
tw.v[ 2 ].st = verts[ indexes[ j + 2 ] ].st;
matrix4_transform_point( transform, tw.v[ 0 ].xyz );
matrix4_transform_point( transform, tw.v[ 1 ].xyz );
matrix4_transform_point( transform, tw.v[ 2 ].xyz );
FilterTraceWindingIntoNodes_r( &tw, nodeNum );
for( int i = 0; i < 3; ++i )
{
const bspDrawVert_t& v = verts[ indexes[ j + i ] ];
tw.v[ i ].xyz = matrix4_transformed_point( transform, v.xyz );
tw.v[ i ].st = v.st;
}
FilterTraceWindingIntoNodes_r( tw, nodeNum );
}
break;
}
@@ -1018,11 +985,11 @@ static void PopulateWithPicoModel( int castShadows, const std::vector<const AssM
/* walk the triangle list */
mesh->forEachFace( [&tw, &transform]( const Vector3 ( &xyz )[3], const Vector2 ( &st )[3] ){
for( size_t i = 0; i < 3; ++i ){
for( int i = 0; i < 3; ++i ){
tw.v[ i ].xyz = matrix4_transformed_point( transform, xyz[ i ] );
tw.v[ i ].st = st[ i ];
}
FilterTraceWindingIntoNodes_r( &tw, headNodeNum );
FilterTraceWindingIntoNodes_r( tw, headNodeNum );
} );
}
}
+12 -70
View File
@@ -1151,7 +1151,7 @@ static bool MapQuad( rawLightmap_t *lm, const surfaceInfo_t *info, const QuadRef
*/
void MapRawLightmap( int rawLightmapNum ){
int n, i, x, y, sx, sy, mapNonAxial;
int n, i, x, y, sx, sy;
float samples, radius, pass;
rawLightmap_t *lm;
bspDrawVert_t fake;
@@ -1207,7 +1207,7 @@ void MapRawLightmap( int rawLightmapNum ){
const bspDrawVert_t *verts = &yDrawVerts[ ds.firstVert ];
/* map the triangles */
for ( mapNonAxial = 0; mapNonAxial < 2; ++mapNonAxial )
for ( int mapNonAxial = 0; mapNonAxial < 2; ++mapNonAxial )
for ( i = 0; i < ds.numIndexes; i += 3 )
MapTriangle( lm, info, TriRef{
&verts[ bspDrawIndexes[ ds.firstIndex + i ] ],
@@ -1232,82 +1232,24 @@ void MapRawLightmap( int rawLightmapNum ){
/* map the mesh quads */
#if 0
for ( mapNonAxial = 0; mapNonAxial < 2; ++mapNonAxial )
for ( int mapNonAxial = 0; mapNonAxial < 2; ++mapNonAxial )
{
for ( y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* get drawverts and map first triangle */
MapTriangle( lm, info, TriRef{
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ] }, mapNonAxial );
/* get drawverts and map second triangle */
MapTriangle( lm, info, TriRef{
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ] }, mapNonAxial );
}
for( MeshQuadIterator it( mesh ); it; ++it ){
for( const TriRef& tri : it.tris() )
MapTriangle( lm, info, tri, mapNonAxial );
}
}
#else
for ( y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* attempt to map quad first */
if ( MapQuad( lm, info, QuadRef{
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ] } ) ) {
continue;
}
for ( mapNonAxial = 0; mapNonAxial < 2; ++mapNonAxial )
for( MeshQuadIterator it( mesh ); it; ++it ){
/* attempt to map quad first */
if ( !MapQuad( lm, info, it.quad() ) ) {
for ( int mapNonAxial = 0; mapNonAxial < 2; ++mapNonAxial )
{
/* get drawverts and map first triangle */
MapTriangle( lm, info, TriRef{
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ] }, mapNonAxial );
/* get drawverts and map second triangle */
MapTriangle( lm, info, TriRef{
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ] }, mapNonAxial );
for( const TriRef& tri : it.tris() )
MapTriangle( lm, info, tri, mapNonAxial );
}
}
}
#endif
/* free the mesh */
+3 -25
View File
@@ -1667,33 +1667,11 @@ static bool ApproximateLightmap( rawLightmap_t *lm ){
/* map the mesh quads */
info.approximated = true;
for ( int y = 0; y < ( mesh.height - 1 ) && info.approximated; ++y )
{
for ( int x = 0; x < ( mesh.width - 1 ) && info.approximated; ++x )
for( MeshQuadIterator it( mesh ); it && info.approximated; ++it ){
for( const TriRef& tri : it.tris() )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* get drawverts and map first triangle */
info.approximated = ApproximateTriangle_r( lm, TriRef{
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ] } );
/* get drawverts and map second triangle */
if ( info.approximated ) {
info.approximated = ApproximateTriangle_r( lm, TriRef{
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ] } );
info.approximated = ApproximateTriangle_r( lm, tri );
}
}
}
+58
View File
@@ -1534,6 +1534,64 @@ mesh_t TessellatedMesh( const mesh_t in, int iterations );
void MakeMeshNormals( mesh_t& in );
void PutMeshOnCurve( mesh_t& in );
class MeshQuadIterator
{
const mesh_t m;
int y, x;
std::array<int, 4> _idx;
void update_idx(){
/* set indexes */
const int pw[ 5 ] = {
x + ( y * m.width ),
x + ( ( y + 1 ) * m.width ),
x + 1 + ( ( y + 1 ) * m.width ),
x + 1 + ( y * m.width ),
x + ( y * m.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
_idx = { pw[ r + 0 ],
pw[ r + 1 ],
pw[ r + 2 ],
pw[ r + 3 ] };
}
public:
MeshQuadIterator( const mesh_t m ) : m( m ), y( 0 ), x( 0 ) {
update_idx();
}
void operator++(){
/* iterate through the mesh quads */
// for ( int y = 0; y < ( m.height - 1 ); ++y )
// for ( int x = 0; x < ( m.width - 1 ); ++x )
if( ++x >= ( m.width - 1 ) ){
x = 0;
++y;
}
update_idx();
}
operator bool() const {
return y < ( m.height - 1 );
}
const std::array<int, 4>& idx() const {
return _idx;
}
QuadRef quad() const {
return { m.verts + _idx[0],
m.verts + _idx[1],
m.verts + _idx[2],
m.verts + _idx[3] };
}
std::array<TriRef, 2> tris() const {
return { TriRef{ m.verts + _idx[0],
m.verts + _idx[1],
m.verts + _idx[2] },
TriRef{ m.verts + _idx[0],
m.verts + _idx[2],
m.verts + _idx[3] } };
}
};
/* map.c */
void LoadMapFile( const char *filename, bool onlyLights, bool noCollapseGroups );
+4 -29
View File
@@ -2846,40 +2846,15 @@ static int AddSurfaceModels( mapDrawSurface_t& ds, entity_t& entity ){
mesh_t mesh = TessellatedMesh( mesh_t( ds.patchWidth, ds.patchHeight, ds.verts.data() ), IterationsForCurve( ds.longestCurve, patchSubdivisions ) );
/* subdivide each quad to place the models */
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
for( MeshQuadIterator it( mesh ); it; ++it ){
for( const TriRef& tri : it.tris() )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ), /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* triangle 1 */
const int n = AddSurfaceModelsToTriangle_r( ds, model, TriRef{
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ] }, entity );
const int n = AddSurfaceModelsToTriangle_r( ds, model, tri, entity );
if ( n < 0 ) {
mesh.freeVerts();
return n;
}
localNumSurfaceModels += n;
/* triangle 2 */
const int n2 = AddSurfaceModelsToTriangle_r( ds, model, TriRef{
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ] }, entity );
if ( n2 < 0 ) {
return n2;
}
localNumSurfaceModels += n2;
}
}
+3 -29
View File
@@ -195,35 +195,9 @@ void Foliage( mapDrawSurface_t& src, entity_t& entity ){
subdivided.freeVerts();
/* map the mesh quads */
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* get drawverts and map first triangle */
SubdivideFoliageTriangle_r( foliage, TriRef{
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ]
} );
/* get drawverts and map second triangle */
SubdivideFoliageTriangle_r( foliage, TriRef{
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ]
} );
}
}
for( MeshQuadIterator it( mesh ); it; ++it )
for( const TriRef& tri : it.tris() )
SubdivideFoliageTriangle_r( foliage, tri );
/* free the mesh */
mesh.freeVerts();
+9 -24
View File
@@ -391,31 +391,16 @@ static void TriangulatePatchSurface( const entity_t& e, mapDrawSurface_t& ds ){
dsNew.verts.assign( mesh.verts, mesh.verts + mesh.numVerts() );
/* iterate through the mesh quads */
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
for( MeshQuadIterator it( mesh ); it; ++it ){
/* make first triangle */
dsNew.indexes.push_back( it.idx()[0] );
dsNew.indexes.push_back( it.idx()[1] );
dsNew.indexes.push_back( it.idx()[2] );
/* make first triangle */
dsNew.indexes.push_back( pw[ r + 0 ] );
dsNew.indexes.push_back( pw[ r + 1 ] );
dsNew.indexes.push_back( pw[ r + 2 ] );
/* make second triangle */
dsNew.indexes.push_back( pw[ r + 0 ] );
dsNew.indexes.push_back( pw[ r + 2 ] );
dsNew.indexes.push_back( pw[ r + 3 ] );
}
/* make second triangle */
dsNew.indexes.push_back( it.idx()[0] );
dsNew.indexes.push_back( it.idx()[2] );
dsNew.indexes.push_back( it.idx()[3] );
}
mesh.freeVerts();