X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=tools%2Fquake3%2Fq3map2%2Fdecals.c;h=86421b95bc387a4464424fb9759d90f34eaa1402;hb=b7e36c120eb1546a6c6f97f30e42ab7f9a559c61;hp=5260437d1fcbddbd162c2364a3e0a9252dea8186;hpb=99980506540d9546dad31223a6eadf126ba68121;p=xonotic%2Fnetradiant.git diff --git a/tools/quake3/q3map2/decals.c b/tools/quake3/q3map2/decals.c index 5260437d..86421b95 100644 --- a/tools/quake3/q3map2/decals.c +++ b/tools/quake3/q3map2/decals.c @@ -1,29 +1,30 @@ -/* -Copyright (C) 1999-2007 id Software, Inc. and contributors. -For a list of contributors, see the accompanying CONTRIBUTORS file. +/* ------------------------------------------------------------------------------- + + Copyright (C) 1999-2007 id Software, Inc. and contributors. + For a list of contributors, see the accompanying CONTRIBUTORS file. -This file is part of GtkRadiant. + This file is part of GtkRadiant. -GtkRadiant is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -GtkRadiant is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ----------------------------------------------------------------------------------- + ---------------------------------------------------------------------------------- -This code has been altered significantly from its original form, to support -several games based on the Quake III Arena engine, in the form of "Q3Map2." + This code has been altered significantly from its original form, to support + several games based on the Quake III Arena engine, in the form of "Q3Map2." -------------------------------------------------------------------------------- */ + ------------------------------------------------------------------------------- */ @@ -37,76 +38,73 @@ several games based on the Quake III Arena engine, in the form of "Q3Map2." -#define MAX_PROJECTORS 1024 +#define MAX_PROJECTORS 1024 typedef struct decalProjector_s { - shaderInfo_t *si; - vec3_t mins, maxs; - vec3_t center; - float radius, radius2; - int numPlanes; /* either 5 or 6, for quad or triangle projectors */ - vec4_t planes[ 6 ]; - vec4_t texMat[ 2 ]; + shaderInfo_t *si; + vec3_t mins, maxs; + vec3_t center; + float radius, radius2; + int numPlanes; /* either 5 or 6, for quad or triangle projectors */ + vec4_t planes[ 6 ]; + vec4_t texMat[ 2 ]; } decalProjector_t; -static int numProjectors = 0; -static decalProjector_t projectors[ MAX_PROJECTORS ]; +static int numProjectors = 0; +static decalProjector_t projectors[ MAX_PROJECTORS ]; -static int numDecalSurfaces = 0; +static int numDecalSurfaces = 0; -static vec3_t entityOrigin; +static vec3_t entityOrigin; /* -DVectorNormalize() -normalizes a vector, returns the length, operates using doubles -*/ + DVectorNormalize() + normalizes a vector, returns the length, operates using doubles + */ + +typedef double dvec_t; +typedef dvec_t dvec3_t[ 3 ]; + +dvec_t DVectorNormalize( dvec3_t in, dvec3_t out ){ + dvec_t len, ilen; -typedef double dvec_t; -typedef dvec_t dvec3_t[ 3 ]; -dvec_t DVectorNormalize( dvec3_t in, dvec3_t out ) -{ - dvec_t len, ilen; - - len = (dvec_t) sqrt( in[ 0 ] * in[ 0 ] + in[ 1 ] * in[ 1 ] + in[ 2 ] * in[ 2 ] ); - if( len == 0.0 ) - { + if ( len == 0.0 ) { VectorClear( out ); return 0.0; } - + ilen = 1.0 / len; out[ 0 ] = in[ 0 ] * ilen; out[ 1 ] = in[ 1 ] * ilen; out[ 2 ] = in[ 2 ] * ilen; - + return len; } /* -MakeTextureMatrix() -generates a texture projection matrix for a triangle -returns qfalse if a texture matrix cannot be created -*/ + MakeTextureMatrix() + generates a texture projection matrix for a triangle + returns qfalse if a texture matrix cannot be created + */ + +#define Vector2Subtract( a,b,c ) ( ( c )[ 0 ] = ( a )[ 0 ] - ( b )[ 0 ], ( c )[ 1 ] = ( a )[ 1 ] - ( b )[ 1 ] ) + +static qboolean MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c ){ + int i, j; + double bb, s, t, d; + dvec3_t pa, pb, pc; + dvec3_t bary, xyz; + dvec3_t vecs[ 3 ], axis[ 3 ], lengths; -#define Vector2Subtract(a,b,c) ((c)[ 0 ] = (a)[ 0 ] - (b)[ 0 ], (c)[ 1 ] = (a)[ 1 ] - (b)[ 1 ]) -static qboolean MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c ) -{ - int i, j; - double bb, s, t, d; - dvec3_t pa, pb, pc; - dvec3_t bary, xyz; - dvec3_t vecs[ 3 ], axis[ 3 ], lengths; - - /* project triangle onto plane of projection */ d = DotProduct( a->xyz, projection ) - projection[ 3 ]; VectorMA( a->xyz, -d, projection, pa ); @@ -114,84 +112,85 @@ static qboolean MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspD VectorMA( b->xyz, -d, projection, pb ); d = DotProduct( c->xyz, projection ) - projection[ 3 ]; VectorMA( c->xyz, -d, projection, pc ); - + /* two methods */ #if 1 { /* old code */ - + /* calculate barycentric basis for the triangle */ - bb = (b->st[ 0 ] - a->st[ 0 ]) * (c->st[ 1 ] - a->st[ 1 ]) - (c->st[ 0 ] - a->st[ 0 ]) * (b->st[ 1 ] - a->st[ 1 ]); - if( fabs( bb ) < 0.00000001 ) + bb = ( b->st[ 0 ] - a->st[ 0 ] ) * ( c->st[ 1 ] - a->st[ 1 ] ) - ( c->st[ 0 ] - a->st[ 0 ] ) * ( b->st[ 1 ] - a->st[ 1 ] ); + if ( fabs( bb ) < 0.00000001 ) { return qfalse; - + } + /* calculate texture origin */ #if 0 s = 0.0; t = 0.0; - bary[ 0 ] = ((b->st[ 0 ] - s) * (c->st[ 1 ] - t) - (c->st[ 0 ] - s) * (b->st[ 1 ] - t)) / bb; - bary[ 1 ] = ((c->st[ 0 ] - s) * (a->st[ 1 ] - t) - (a->st[ 0 ] - s) * (c->st[ 1 ] - t)) / bb; - bary[ 2 ] = ((a->st[ 0 ] - s) * (b->st[ 1 ] - t) - (b->st[ 0 ] - s) * (a->st[ 1 ] - t)) / bb; - + bary[ 0 ] = ( ( b->st[ 0 ] - s ) * ( c->st[ 1 ] - t ) - ( c->st[ 0 ] - s ) * ( b->st[ 1 ] - t ) ) / bb; + bary[ 1 ] = ( ( c->st[ 0 ] - s ) * ( a->st[ 1 ] - t ) - ( a->st[ 0 ] - s ) * ( c->st[ 1 ] - t ) ) / bb; + bary[ 2 ] = ( ( a->st[ 0 ] - s ) * ( b->st[ 1 ] - t ) - ( b->st[ 0 ] - s ) * ( a->st[ 1 ] - t ) ) / bb; + origin[ 0 ] = bary[ 0 ] * pa[ 0 ] + bary[ 1 ] * pb[ 0 ] + bary[ 2 ] * pc[ 0 ]; origin[ 1 ] = bary[ 0 ] * pa[ 1 ] + bary[ 1 ] * pb[ 1 ] + bary[ 2 ] * pc[ 1 ]; origin[ 2 ] = bary[ 0 ] * pa[ 2 ] + bary[ 1 ] * pb[ 2 ] + bary[ 2 ] * pc[ 2 ]; #endif - + /* calculate s vector */ s = a->st[ 0 ] + 1.0; t = a->st[ 1 ] + 0.0; - bary[ 0 ] = ((b->st[ 0 ] - s) * (c->st[ 1 ] - t) - (c->st[ 0 ] - s) * (b->st[ 1 ] - t)) / bb; - bary[ 1 ] = ((c->st[ 0 ] - s) * (a->st[ 1 ] - t) - (a->st[ 0 ] - s) * (c->st[ 1 ] - t)) / bb; - bary[ 2 ] = ((a->st[ 0 ] - s) * (b->st[ 1 ] - t) - (b->st[ 0 ] - s) * (a->st[ 1 ] - t)) / bb; - + bary[ 0 ] = ( ( b->st[ 0 ] - s ) * ( c->st[ 1 ] - t ) - ( c->st[ 0 ] - s ) * ( b->st[ 1 ] - t ) ) / bb; + bary[ 1 ] = ( ( c->st[ 0 ] - s ) * ( a->st[ 1 ] - t ) - ( a->st[ 0 ] - s ) * ( c->st[ 1 ] - t ) ) / bb; + bary[ 2 ] = ( ( a->st[ 0 ] - s ) * ( b->st[ 1 ] - t ) - ( b->st[ 0 ] - s ) * ( a->st[ 1 ] - t ) ) / bb; + xyz[ 0 ] = bary[ 0 ] * pa[ 0 ] + bary[ 1 ] * pb[ 0 ] + bary[ 2 ] * pc[ 0 ]; xyz[ 1 ] = bary[ 0 ] * pa[ 1 ] + bary[ 1 ] * pb[ 1 ] + bary[ 2 ] * pc[ 1 ]; xyz[ 2 ] = bary[ 0 ] * pa[ 2 ] + bary[ 1 ] * pb[ 2 ] + bary[ 2 ] * pc[ 2 ]; - + //% VectorSubtract( xyz, origin, vecs[ 0 ] ); VectorSubtract( xyz, pa, vecs[ 0 ] ); - + /* calculate t vector */ s = a->st[ 0 ] + 0.0; t = a->st[ 1 ] + 1.0; - bary[ 0 ] = ((b->st[ 0 ] - s) * (c->st[ 1 ] - t) - (c->st[ 0 ] - s) * (b->st[ 1 ] - t)) / bb; - bary[ 1 ] = ((c->st[ 0 ] - s) * (a->st[ 1 ] - t) - (a->st[ 0 ] - s) * (c->st[ 1 ] - t)) / bb; - bary[ 2 ] = ((a->st[ 0 ] - s) * (b->st[ 1 ] - t) - (b->st[ 0 ] - s) * (a->st[ 1 ] - t)) / bb; - + bary[ 0 ] = ( ( b->st[ 0 ] - s ) * ( c->st[ 1 ] - t ) - ( c->st[ 0 ] - s ) * ( b->st[ 1 ] - t ) ) / bb; + bary[ 1 ] = ( ( c->st[ 0 ] - s ) * ( a->st[ 1 ] - t ) - ( a->st[ 0 ] - s ) * ( c->st[ 1 ] - t ) ) / bb; + bary[ 2 ] = ( ( a->st[ 0 ] - s ) * ( b->st[ 1 ] - t ) - ( b->st[ 0 ] - s ) * ( a->st[ 1 ] - t ) ) / bb; + xyz[ 0 ] = bary[ 0 ] * pa[ 0 ] + bary[ 1 ] * pb[ 0 ] + bary[ 2 ] * pc[ 0 ]; xyz[ 1 ] = bary[ 0 ] * pa[ 1 ] + bary[ 1 ] * pb[ 1 ] + bary[ 2 ] * pc[ 1 ]; xyz[ 2 ] = bary[ 0 ] * pa[ 2 ] + bary[ 1 ] * pb[ 2 ] + bary[ 2 ] * pc[ 2 ]; - + //% VectorSubtract( xyz, origin, vecs[ 1 ] ); VectorSubtract( xyz, pa, vecs[ 1 ] ); - + /* calcuate r vector */ VectorScale( projection, -1.0, vecs[ 2 ] ); - + /* calculate transform axis */ - for( i = 0; i < 3; i++ ) + for ( i = 0; i < 3; i++ ) lengths[ i ] = DVectorNormalize( vecs[ i ], axis[ i ] ); - for( i = 0; i < 2; i++ ) - for( j = 0; j < 3; j++ ) - dp->texMat[ i ][ j ] = lengths[ i ] > 0.0 ? (axis[ i ][ j ] / lengths[ i ]) : 0.0; - //% dp->texMat[ i ][ j ] = fabs( vecs[ i ][ j ] ) > 0.0 ? (1.0 / vecs[ i ][ j ]) : 0.0; - //% dp->texMat[ i ][ j ] = axis[ i ][ j ] > 0.0 ? (1.0 / axis[ i ][ j ]) : 0.0; - + for ( i = 0; i < 2; i++ ) + for ( j = 0; j < 3; j++ ) + dp->texMat[ i ][ j ] = lengths[ i ] > 0.0 ? ( axis[ i ][ j ] / lengths[ i ] ) : 0.0; + //% dp->texMat[ i ][ j ] = fabs( vecs[ i ][ j ] ) > 0.0 ? (1.0 / vecs[ i ][ j ]) : 0.0; + //% dp->texMat[ i ][ j ] = axis[ i ][ j ] > 0.0 ? (1.0 / axis[ i ][ j ]) : 0.0; + /* calculalate translation component */ dp->texMat[ 0 ][ 3 ] = a->st[ 0 ] - DotProduct( a->xyz, dp->texMat[ 0 ] ); dp->texMat[ 1 ][ 3 ] = a->st[ 1 ] - DotProduct( a->xyz, dp->texMat[ 1 ] ); } #else { - int k; - dvec3_t origin, deltas[ 3 ]; - double texDeltas[ 3 ][ 2 ]; - double delta, texDelta; - - + int k; + dvec3_t origin, deltas[ 3 ]; + double texDeltas[ 3 ][ 2 ]; + double delta, texDelta; + + /* new code */ - + /* calculate deltas */ VectorSubtract( pa, pb, deltas[ 0 ] ); VectorSubtract( pa, pc, deltas[ 1 ] ); @@ -199,81 +198,79 @@ static qboolean MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspD Vector2Subtract( a->st, b->st, texDeltas[ 0 ] ); Vector2Subtract( a->st, c->st, texDeltas[ 1 ] ); Vector2Subtract( b->st, c->st, texDeltas[ 2 ] ); - + /* walk st */ - for( i = 0; i < 2; i++ ) + for ( i = 0; i < 2; i++ ) { /* walk xyz */ - for( j = 0; j < 3; j++ ) + for ( j = 0; j < 3; j++ ) { /* clear deltas */ delta = 0.0; texDelta = 0.0; - + /* walk deltas */ - for( k = 0; k < 3; k++ ) + for ( k = 0; k < 3; k++ ) { - if( fabs( deltas[ k ][ j ] ) > delta && - fabs( texDeltas[ k ][ i ] ) > texDelta ) - { + if ( fabs( deltas[ k ][ j ] ) > delta && + fabs( texDeltas[ k ][ i ] ) > texDelta ) { delta = deltas[ k ][ j ]; texDelta = texDeltas[ k ][ i ]; } } - + /* set texture matrix component */ - if( fabs( delta ) > 0.0 ) + if ( fabs( delta ) > 0.0 ) { dp->texMat[ i ][ j ] = texDelta / delta; - else + } + else{ dp->texMat[ i ][ j ] = 0.0; + } } - + /* set translation component */ dp->texMat[ i ][ 3 ] = a->st[ i ] - DotProduct( pa, dp->texMat[ i ] ); } } #endif - + /* debug code */ #if 1 - Sys_Printf( "Mat: [ %f %f %f %f ] [ %f %f %f %f ] Theta: %f (%f)\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 ], - RAD2DEG( acos( DotProduct( dp->texMat[ 0 ], dp->texMat[ 1 ] ) ) ), - RAD2DEG( acos( DotProduct( axis[ 0 ], axis[ 1 ] ) ) ) ); - - Sys_Printf( "XYZ: %f %f %f ST: %f %f ST(t): %f %f\n", - a->xyz[ 0 ], a->xyz[ 1 ], a->xyz[ 2 ], - a->st[ 0 ], a->st[ 1 ], - DotProduct( a->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ], DotProduct( a->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ] ); + Sys_Printf( "Mat: [ %f %f %f %f ] [ %f %f %f %f ] Theta: %f (%f)\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 ], + RAD2DEG( acos( DotProduct( dp->texMat[ 0 ], dp->texMat[ 1 ] ) ) ), + RAD2DEG( acos( DotProduct( axis[ 0 ], axis[ 1 ] ) ) ) ); + + Sys_Printf( "XYZ: %f %f %f ST: %f %f ST(t): %f %f\n", + a->xyz[ 0 ], a->xyz[ 1 ], a->xyz[ 2 ], + a->st[ 0 ], a->st[ 1 ], + DotProduct( a->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ], DotProduct( a->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ] ); #endif - + /* test texture matrix */ s = DotProduct( a->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ]; t = DotProduct( a->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ]; - if( fabs( s - a->st[ 0 ] ) > 0.01 || fabs( t - a->st[ 1 ] ) > 0.01 ) - { + if ( fabs( s - a->st[ 0 ] ) > 0.01 || fabs( 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 ] ); + s, t, a->st[ 0 ], a->st[ 1 ] ); //% return qfalse; } s = DotProduct( b->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ]; t = DotProduct( b->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ]; - if( fabs( s - b->st[ 0 ] ) > 0.01 || fabs( t - b->st[ 1 ] ) > 0.01 ) - { + if ( fabs( s - b->st[ 0 ] ) > 0.01 || fabs( 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 ] ); + s, t, b->st[ 0 ], b->st[ 1 ] ); //% return qfalse; } s = DotProduct( c->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ]; t = DotProduct( c->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ]; - if( fabs( s - c->st[ 0 ] ) > 0.01 || fabs( t - c->st[ 1 ] ) > 0.01 ) - { + if ( fabs( s - c->st[ 0 ] ) > 0.01 || fabs( 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 ] ); + s, t, c->st[ 0 ], c->st[ 1 ] ); //% return qfalse; } - + /* disco */ return qtrue; } @@ -281,38 +278,37 @@ static qboolean MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspD /* -TransformDecalProjector() -transforms a decal projector -note: non-normalized axes will screw up the plane transform -*/ + TransformDecalProjector() + transforms a decal projector + note: non-normalized axes will screw up the plane transform + */ + +static void TransformDecalProjector( decalProjector_t *in, vec3_t axis[ 3 ], vec3_t origin, decalProjector_t *out ){ + int i; + -static void TransformDecalProjector( decalProjector_t *in, vec3_t axis[ 3 ], vec3_t origin, decalProjector_t *out ) -{ - int i; - - /* copy misc stuff */ out->si = in->si; out->numPlanes = in->numPlanes; - + /* translate bounding box and sphere (note: rotated projector bounding box will be invalid!) */ VectorSubtract( in->mins, origin, out->mins ); VectorSubtract( in->maxs, origin, out->maxs ); VectorSubtract( in->center, origin, out->center ); out->radius = in->radius; out->radius2 = in->radius2; - + /* translate planes */ - for( i = 0; i < in->numPlanes; i++ ) + for ( i = 0; i < in->numPlanes; i++ ) { out->planes[ i ][ 0 ] = DotProduct( in->planes[ i ], axis[ 0 ] ); out->planes[ i ][ 1 ] = DotProduct( in->planes[ i ], axis[ 1 ] ); out->planes[ i ][ 2 ] = DotProduct( in->planes[ i ], axis[ 2 ] ); out->planes[ i ][ 3 ] = in->planes[ i ][ 3 ] - DotProduct( out->planes[ i ], origin ); } - + /* translate texture matrix */ - for( i = 0; i < 2; i++ ) + for ( i = 0; i < 2; i++ ) { out->texMat[ i ][ 0 ] = DotProduct( in->texMat[ i ], axis[ 0 ] ); out->texMat[ i ][ 1 ] = DotProduct( in->texMat[ i ], axis[ 1 ] ); @@ -324,74 +320,76 @@ static void TransformDecalProjector( decalProjector_t *in, vec3_t axis[ 3 ], vec /* -MakeDecalProjector() -creates a new decal projector from a triangle -*/ + MakeDecalProjector() + creates a new decal projector from a triangle + */ + +static int MakeDecalProjector( shaderInfo_t *si, vec4_t projection, float distance, int numVerts, bspDrawVert_t **dv ){ + int i, j; + decalProjector_t *dp; + vec3_t xyz; + -static int MakeDecalProjector( shaderInfo_t *si, vec4_t projection, float distance, int numVerts, bspDrawVert_t **dv ) -{ - int i, j; - decalProjector_t *dp; - vec3_t xyz; - - /* dummy check */ - if( numVerts != 3 && numVerts != 4 ) + if ( numVerts != 3 && numVerts != 4 ) { return -1; - + } + /* limit check */ - if( numProjectors >= MAX_PROJECTORS ) - { + if ( numProjectors >= MAX_PROJECTORS ) { Sys_Printf( "WARNING: MAX_PROJECTORS (%d) exceeded, no more decal projectors available.\n", MAX_PROJECTORS ); return -2; } - + /* create a new projector */ dp = &projectors[ numProjectors ]; memset( dp, 0, sizeof( *dp ) ); - + /* basic setup */ dp->si = si; dp->numPlanes = numVerts + 2; - + /* make texture matrix */ - if( !MakeTextureMatrix( dp, projection, dv[ 0 ], dv[ 1 ], dv[ 2 ] ) ) + if ( !MakeTextureMatrix( dp, projection, dv[ 0 ], dv[ 1 ], dv[ 2 ] ) ) { return -1; - + } + /* bound the projector */ ClearBounds( dp->mins, dp->maxs ); - for( i = 0; i < numVerts; i++ ) + for ( i = 0; i < numVerts; i++ ) { AddPointToBounds( dv[ i ]->xyz, dp->mins, dp->maxs ); VectorMA( dv[ i ]->xyz, distance, projection, xyz ); AddPointToBounds( xyz, dp->mins, dp->maxs ); } - + /* make bouding sphere */ VectorAdd( dp->mins, dp->maxs, dp->center ); VectorScale( dp->center, 0.5f, dp->center ); VectorSubtract( dp->maxs, dp->center, xyz ); dp->radius = VectorLength( xyz ); 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 ], dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) ) { return -1; - + } + /* make the back plane */ VectorSubtract( vec3_origin, dp->planes[ 0 ], dp->planes[ 1 ] ); VectorMA( dv[ 0 ]->xyz, distance, projection, xyz ); dp->planes[ 1 ][ 3 ] = DotProduct( xyz, dp->planes[ 1 ] ); - + /* make the side planes */ - for( i = 0; i < numVerts; i++ ) + for ( i = 0; i < numVerts; i++ ) { - j = (i + 1) % numVerts; + j = ( i + 1 ) % numVerts; VectorMA( dv[ i ]->xyz, distance, projection, xyz ); - if( !PlaneFromPoints( dp->planes[ i + 2 ], dv[ j ]->xyz, dv[ i ]->xyz, xyz ) ) + if ( !PlaneFromPoints( dp->planes[ i + 2 ], dv[ j ]->xyz, dv[ i ]->xyz, xyz ) ) { return -1; + } } - + /* return ok */ numProjectors++; return numProjectors - 1; @@ -400,117 +398,113 @@ static int MakeDecalProjector( shaderInfo_t *si, vec4_t projection, float distan /* -ProcessDecals() -finds all decal entities and creates decal projectors -*/ + ProcessDecals() + finds all decal entities and creates decal projectors + */ + +#define PLANAR_EPSILON 0.5f + +void ProcessDecals( void ){ + int i, j, x, y, pw[ 5 ], r, iterations; + float distance; + vec4_t projection, plane; + vec3_t origin, target, delta; + entity_t *e, *e2; + parseMesh_t *p; + mesh_t *mesh, *subdivided; + bspDrawVert_t *dv[ 4 ]; + const char *value; -#define PLANAR_EPSILON 0.5f -void ProcessDecals( void ) -{ - int i, j, x, y, pw[ 5 ], r, iterations; - float distance; - vec4_t projection, plane; - vec3_t origin, target, delta; - entity_t *e, *e2; - parseMesh_t *p; - mesh_t *mesh, *subdivided; - bspDrawVert_t *dv[ 4 ]; - const char *value; - - /* note it */ Sys_FPrintf( SYS_VRB, "--- ProcessDecals ---\n" ); - + /* walk entity list */ - for( i = 0; i < numEntities; i++ ) + for ( i = 0; i < numEntities; i++ ) { /* get entity */ e = &entities[ i ]; value = ValueForKey( e, "classname" ); - if( Q_stricmp( value, "_decal" ) ) + if ( Q_stricmp( value, "_decal" ) ) { continue; - + } + /* any patches? */ - if( e->patches == NULL ) - { + if ( e->patches == NULL ) { Sys_Printf( "WARNING: Decal entity without any patch meshes, ignoring.\n" ); - e->epairs = NULL; /* fixme: leak! */ + e->epairs = NULL; /* fixme: leak! */ continue; } - + /* find target */ value = ValueForKey( e, "target" ); e2 = FindTargetEntity( value ); - + /* no target? */ - if( e2 == NULL ) - { + if ( e2 == NULL ) { Sys_Printf( "WARNING: Decal entity without a valid target, ignoring.\n" ); continue; } - + /* walk entity patches */ - for( p = e->patches; p != NULL; p = e->patches ) + for ( p = e->patches; p != NULL; p = e->patches ) { /* setup projector */ - if( VectorCompare( e->origin, vec3_origin ) ) - { + if ( VectorCompare( e->origin, vec3_origin ) ) { VectorAdd( p->eMins, p->eMaxs, origin ); VectorScale( origin, 0.5f, origin ); } - else + else{ VectorCopy( e->origin, origin ); - + } + VectorCopy( e2->origin, target ); VectorSubtract( target, origin, delta ); - + /* setup projection plane */ distance = VectorNormalize( delta, projection ); projection[ 3 ] = DotProduct( origin, projection ); - + /* create projectors */ - if( distance > 0.125f ) - { + if ( distance > 0.125f ) { /* tesselate the patch */ iterations = IterationsForCurve( p->longestCurve, patchSubdivisions ); subdivided = SubdivideMesh2( p->mesh, iterations ); - + /* fit it to the curve and remove colinear verts on rows/columns */ PutMeshOnCurve( *subdivided ); mesh = RemoveLinearMeshColumnsRows( subdivided ); FreeMesh( subdivided ); - + /* offset by projector origin */ - for( j = 0; j < (mesh->width * mesh->height); j++ ) + for ( j = 0; j < ( mesh->width * mesh->height ); j++ ) VectorAdd( mesh->verts[ j ].xyz, e->origin, mesh->verts[ j ].xyz ); - + /* iterate through the mesh quads */ - for( y = 0; y < (mesh->height - 1); y++ ) + for ( y = 0; y < ( mesh->height - 1 ); y++ ) { - for( x = 0; x < (mesh->width - 1); x++ ) + for ( x = 0; x < ( mesh->width - 1 ); x++ ) { /* set indexes */ - pw[ 0 ] = x + (y * mesh->width); - pw[ 1 ] = x + ((y + 1) * mesh->width); - pw[ 2 ] = x + 1 + ((y + 1) * mesh->width); - pw[ 3 ] = x + 1 + (y * mesh->width); - pw[ 4 ] = x + (y * mesh->width); /* same as pw[ 0 ] */ - + pw[ 0 ] = x + ( y * mesh->width ); + pw[ 1 ] = x + ( ( y + 1 ) * mesh->width ); + pw[ 2 ] = x + 1 + ( ( y + 1 ) * mesh->width ); + pw[ 3 ] = x + 1 + ( y * mesh->width ); + pw[ 4 ] = x + ( y * mesh->width ); /* same as pw[ 0 ] */ + /* set radix */ - r = (x + y) & 1; - + r = ( x + y ) & 1; + /* get drawverts */ dv[ 0 ] = &mesh->verts[ pw[ r + 0 ] ]; dv[ 1 ] = &mesh->verts[ pw[ r + 1 ] ]; dv[ 2 ] = &mesh->verts[ pw[ r + 2 ] ]; dv[ 3 ] = &mesh->verts[ pw[ r + 3 ] ]; - + /* planar? (nuking this optimization as it doesn't work on non-rectangular quads) */ - plane[ 0 ] = 0.0f; /* stupid msvc */ - if( 0 && PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) && - fabs( DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ] ) <= PLANAR_EPSILON ) - { + plane[ 0 ] = 0.0f; /* stupid msvc */ + if ( 0 && PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) && + fabs( DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ] ) <= PLANAR_EPSILON ) { /* make a quad projector */ MakeDecalProjector( p->shaderInfo, projection, distance, 4, dv ); } @@ -518,7 +512,7 @@ void ProcessDecals( void ) { /* make first triangle */ MakeDecalProjector( p->shaderInfo, projection, distance, 3, dv ); - + /* make second triangle */ dv[ 1 ] = dv[ 2 ]; dv[ 2 ] = dv[ 3 ]; @@ -526,22 +520,22 @@ void ProcessDecals( void ) } } } - + /* clean up */ free( mesh ); } - + /* remove patch from entity (fixme: leak!) */ e->patches = p->next; - + /* push patch to worldspawn (enable this to debug projectors) */ #if 0 - p->next = entities[ 0 ].patches; - entities[ 0 ].patches = p; + p->next = entities[ 0 ].patches; + entities[ 0 ].patches = p; #endif } } - + /* emit some stats */ Sys_FPrintf( SYS_VRB, "%9d decal projectors\n", numProjectors ); } @@ -549,109 +543,111 @@ void ProcessDecals( void ) /* -ProjectDecalOntoWinding() -projects a decal onto a winding -*/ + ProjectDecalOntoWinding() + projects a decal onto a winding + */ + +static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds, winding_t *w ){ + int i, j; + float d, d2, alpha; + winding_t *front, *back; + mapDrawSurface_t *ds2; + bspDrawVert_t *dv; + vec4_t plane; + -static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds, winding_t *w ) -{ - int i, j; - float d, d2, alpha; - winding_t *front, *back; - mapDrawSurface_t *ds2; - bspDrawVert_t *dv; - vec4_t plane; - - /* dummy check */ - if( w->numpoints < 3 ) - { + if ( w->numpoints < 3 ) { FreeWinding( w ); return; } - + /* offset by entity origin */ - for( i = 0; i < w->numpoints; i++ ) + for ( i = 0; i < w->numpoints; i++ ) VectorAdd( w->p[ i ], entityOrigin, w->p[ i ] ); - + /* make a plane from the winding */ - if( !PlaneFromPoints( plane, w->p[ 0 ], w->p[ 1 ], w->p[ 2 ] ) ) - { + if ( !PlaneFromPoints( plane, w->p[ 0 ], w->p[ 1 ], w->p[ 2 ] ) ) { FreeWinding( w ); return; } - + /* backface check */ d = DotProduct( dp->planes[ 0 ], plane ); - if( d < -0.0001f ) - { + if ( d < -0.0001f ) { FreeWinding( w ); return; } - + /* walk list of planes */ - for( i = 0; i < dp->numPlanes; i++ ) + for ( i = 0; i < dp->numPlanes; i++ ) { /* chop winding by the plane */ - ClipWindingEpsilon( w, dp->planes[ i ], dp->planes[ i ][ 3 ], 0.0625f, &front, &back ); + ClipWindingEpsilonStrict( w, dp->planes[ i ], dp->planes[ i ][ 3 ], 0.0625f, &front, &back ); /* strict, if identical plane we don't want to keep it */ FreeWinding( w ); - + /* lose the front fragment */ - if( front != NULL ) + if ( front != NULL ) { FreeWinding( front ); - + } + /* if nothing left in back, then bail */ - if( back == NULL ) + if ( back == NULL ) { return; - + } + /* reset winding */ w = back; } - + /* nothing left? */ - if( w == NULL || w->numpoints < 3 ) + if ( w == NULL || w->numpoints < 3 ) { return; - + } + /* add to counts */ numDecalSurfaces++; - + /* make a new surface */ ds2 = AllocDrawSurface( SURFACE_DECAL ); - + /* set it up */ ds2->entityNum = ds->entityNum; ds2->castShadows = ds->castShadows; ds2->recvShadows = ds->recvShadows; ds2->shaderInfo = dp->si; - ds2->fogNum = ds->fogNum; /* why was this -1? */ + ds2->fogNum = ds->fogNum; /* why was this -1? */ ds2->lightmapScale = ds->lightmapScale; + ds2->shadeAngleDegrees = ds->shadeAngleDegrees; ds2->numVerts = w->numpoints; ds2->verts = safe_malloc( ds2->numVerts * sizeof( *ds2->verts ) ); memset( ds2->verts, 0, ds2->numVerts * sizeof( *ds2->verts ) ); - + /* set vertexes */ - for( i = 0; i < ds2->numVerts; i++ ) + for ( i = 0; i < ds2->numVerts; i++ ) { /* get vertex */ dv = &ds2->verts[ i ]; - + /* set alpha */ d = DotProduct( w->p[ i ], dp->planes[ 0 ] ) - dp->planes[ 0 ][ 3 ]; d2 = DotProduct( w->p[ i ], dp->planes[ 1 ] ) - dp->planes[ 1 ][ 3 ]; - alpha = 255.0f * d2 / (d + d2); - if( alpha > 255 ) + alpha = 255.0f * d2 / ( d + d2 ); + if ( alpha > 255 ) { alpha = 255; - else if( alpha < 0 ) + } + else if ( alpha < 0 ) { alpha = 0; - + } + /* set misc */ VectorSubtract( w->p[ i ], entityOrigin, dv->xyz ); VectorCopy( plane, dv->normal ); dv->st[ 0 ] = DotProduct( dv->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ]; dv->st[ 1 ] = DotProduct( dv->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ]; - + /* set color */ - for( j = 0; j < MAX_LIGHTMAPS; j++ ) + for ( j = 0; j < MAX_LIGHTMAPS; j++ ) { dv->color[ j ][ 0 ] = 255; dv->color[ j ][ 1 ] = 255; @@ -659,39 +655,36 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds, dv->color[ j ][ 3 ] = alpha; } } - - /* ydnar: finish the surface */ - FinishSurface( ds2 ); } /* -ProjectDecalOntoFace() -projects a decal onto a brushface surface -*/ + ProjectDecalOntoFace() + projects a decal onto a brushface surface + */ + +static void ProjectDecalOntoFace( decalProjector_t *dp, mapDrawSurface_t *ds ){ + vec4_t plane; + float d; + winding_t *w; + -static void ProjectDecalOntoFace( decalProjector_t *dp, mapDrawSurface_t *ds ) -{ - vec4_t plane; - float d; - winding_t *w; - - /* dummy check */ - if( ds->sideRef == NULL || ds->sideRef->side == NULL ) + if ( ds->sideRef == NULL || ds->sideRef->side == NULL ) { return; - + } + /* backface check */ - if( ds->planar ) - { + if ( ds->planar ) { VectorCopy( mapplanes[ ds->planeNum ].normal, plane ); plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin ); d = DotProduct( dp->planes[ 0 ], plane ); - if( d < -0.0001f ) + if ( d < -0.0001f ) { return; + } } - + /* generate decal */ w = WindingFromDrawSurf( ds ); ProjectDecalOntoWinding( dp, ds, w ); @@ -700,56 +693,55 @@ static void ProjectDecalOntoFace( decalProjector_t *dp, mapDrawSurface_t *ds ) /* -ProjectDecalOntoPatch() -projects a decal onto a patch surface -*/ + ProjectDecalOntoPatch() + projects a decal onto a patch surface + */ + +static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ){ + int x, y, pw[ 5 ], r, iterations; + vec4_t plane; + float d; + mesh_t src, *mesh, *subdivided; + winding_t *w; + -static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ) -{ - int x, y, pw[ 5 ], r, iterations; - vec4_t plane; - float d; - mesh_t src, *mesh, *subdivided; - winding_t *w; - - /* backface check */ - if( ds->planar ) - { + if ( ds->planar ) { VectorCopy( mapplanes[ ds->planeNum ].normal, plane ); plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin ); d = DotProduct( dp->planes[ 0 ], plane ); - if( d < -0.0001f ) + if ( d < -0.0001f ) { return; + } } - + /* tesselate the patch */ src.width = ds->patchWidth; src.height = ds->patchHeight; src.verts = ds->verts; iterations = IterationsForCurve( ds->longestCurve, patchSubdivisions ); subdivided = SubdivideMesh2( src, iterations ); - + /* fit it to the curve and remove colinear verts on rows/columns */ PutMeshOnCurve( *subdivided ); mesh = RemoveLinearMeshColumnsRows( subdivided ); FreeMesh( subdivided ); - + /* iterate through the mesh quads */ - for( y = 0; y < (mesh->height - 1); y++ ) + for ( y = 0; y < ( mesh->height - 1 ); y++ ) { - for( x = 0; x < (mesh->width - 1); x++ ) + for ( x = 0; x < ( mesh->width - 1 ); x++ ) { /* set indexes */ - pw[ 0 ] = x + (y * mesh->width); - pw[ 1 ] = x + ((y + 1) * mesh->width); - pw[ 2 ] = x + 1 + ((y + 1) * mesh->width); - pw[ 3 ] = x + 1 + (y * mesh->width); - pw[ 4 ] = x + (y * mesh->width); /* same as pw[ 0 ] */ - + pw[ 0 ] = x + ( y * mesh->width ); + pw[ 1 ] = x + ( ( y + 1 ) * mesh->width ); + pw[ 2 ] = x + 1 + ( ( y + 1 ) * mesh->width ); + pw[ 3 ] = x + 1 + ( y * mesh->width ); + pw[ 4 ] = x + ( y * mesh->width ); /* same as pw[ 0 ] */ + /* set radix */ - r = (x + y) & 1; - + r = ( x + y ) & 1; + /* generate decal for first triangle */ w = AllocWinding( 3 ); w->numpoints = 3; @@ -757,7 +749,7 @@ static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ) VectorCopy( mesh->verts[ pw[ r + 1 ] ].xyz, w->p[ 1 ] ); VectorCopy( mesh->verts[ pw[ r + 2 ] ].xyz, w->p[ 2 ] ); ProjectDecalOntoWinding( dp, ds, w ); - + /* generate decal for second triangle */ w = AllocWinding( 3 ); w->numpoints = 3; @@ -767,7 +759,7 @@ static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ) ProjectDecalOntoWinding( dp, ds, w ); } } - + /* clean up */ free( mesh ); } @@ -775,35 +767,34 @@ static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ) /* -ProjectDecalOntoTriangles() -projects a decal onto a triangle surface -*/ + ProjectDecalOntoTriangles() + projects a decal onto a triangle surface + */ + +static void ProjectDecalOntoTriangles( decalProjector_t *dp, mapDrawSurface_t *ds ){ + int i; + vec4_t plane; + float d; + winding_t *w; + -static void ProjectDecalOntoTriangles( decalProjector_t *dp, mapDrawSurface_t *ds ) -{ - int i; - vec4_t plane; - float d; - winding_t *w; - - /* triangle surfaces without shaders don't get marks by default */ - if( (ds->type == SURFACE_TRIANGLES || ds->type == SURFACE_FORCED_META) && - ds->shaderInfo->shaderText == NULL ) + if ( ds->type == SURFACE_TRIANGLES && ds->shaderInfo->shaderText == NULL ) { return; - + } + /* backface check */ - if( ds->planar ) - { + if ( ds->planar ) { VectorCopy( mapplanes[ ds->planeNum ].normal, plane ); plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin ); d = DotProduct( dp->planes[ 0 ], plane ); - if( d < -0.0001f ) + if ( d < -0.0001f ) { return; + } } - + /* iterate through triangles */ - for( i = 0; i < ds->numIndexes; i += 3 ) + for ( i = 0; i < ds->numIndexes; i += 3 ) { /* generate decal */ w = AllocWinding( 3 ); @@ -818,91 +809,93 @@ static void ProjectDecalOntoTriangles( decalProjector_t *dp, mapDrawSurface_t *d /* -MakeEntityDecals() -projects decals onto world surfaces -*/ + MakeEntityDecals() + projects decals onto world surfaces + */ + +void MakeEntityDecals( entity_t *e ){ + int i, j, k, f, fOld, start; + decalProjector_t dp; + mapDrawSurface_t *ds; + vec3_t identityAxis[ 3 ] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; + -void MakeEntityDecals( entity_t *e ) -{ - int i, j, k, f, fOld, start; - decalProjector_t dp; - mapDrawSurface_t *ds; - vec3_t identityAxis[ 3 ] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; - - /* note it */ Sys_FPrintf( SYS_VRB, "--- MakeEntityDecals ---\n" ); - + /* set entity origin */ VectorCopy( e->origin, entityOrigin ); - + /* transform projector instead of geometry */ VectorClear( entityOrigin ); - + /* init pacifier */ fOld = -1; start = I_FloatTime(); - + /* walk the list of decal projectors */ - for( i = 0; i < numProjectors; i++ ) + for ( i = 0; i < numProjectors; i++ ) { /* print pacifier */ f = 10 * i / numProjectors; - if( f != fOld ) - { + if ( f != fOld ) { fOld = f; Sys_FPrintf( SYS_VRB, "%d...", f ); } - + /* get projector */ TransformDecalProjector( &projectors[ i ], identityAxis, e->origin, &dp ); - + /* walk the list of surfaces in the entity */ - for( j = e->firstDrawSurf; j < numMapDrawSurfs; j++ ) + for ( j = e->firstDrawSurf; j < numMapDrawSurfs; j++ ) { /* get surface */ ds = &mapDrawSurfs[ j ]; - if( ds->numVerts <= 0 ) + if ( ds->numVerts <= 0 ) { continue; - + } + /* ignore autosprite or nomarks */ - if( ds->shaderInfo->autosprite || (ds->shaderInfo->compileFlags & C_NOMARKS) ) + if ( ds->shaderInfo->autosprite || ( ds->shaderInfo->compileFlags & C_NOMARKS ) ) { continue; - + } + /* bounds check */ - for( k = 0; k < 3; k++ ) - if( ds->mins[ k ] >= (dp.center[ k ] + dp.radius) || - ds->maxs[ k ] <= (dp.center[ k ] - dp.radius) ) + for ( k = 0; k < 3; k++ ) + if ( ds->mins[ k ] >= ( dp.center[ k ] + dp.radius ) || + ds->maxs[ k ] <= ( dp.center[ k ] - dp.radius ) ) { break; - if( k < 3 ) + } + if ( k < 3 ) { continue; - + } + /* switch on type */ - switch( ds->type ) + switch ( ds->type ) { - case SURFACE_FACE: - ProjectDecalOntoFace( &dp, ds ); - break; - - case SURFACE_PATCH: - ProjectDecalOntoPatch( &dp, ds ); - break; - - case SURFACE_TRIANGLES: - case SURFACE_FORCED_META: - case SURFACE_META: - ProjectDecalOntoTriangles( &dp, ds ); - break; - - default: - break; + case SURFACE_FACE: + ProjectDecalOntoFace( &dp, ds ); + break; + + case SURFACE_PATCH: + ProjectDecalOntoPatch( &dp, ds ); + break; + + case SURFACE_TRIANGLES: + case SURFACE_FORCED_META: + case SURFACE_META: + ProjectDecalOntoTriangles( &dp, ds ); + break; + + default: + break; } } } - + /* print time */ - Sys_FPrintf( SYS_VRB, " (%d)\n", (int) (I_FloatTime() - start) ); - + Sys_FPrintf( SYS_VRB, " (%d)\n", (int) ( I_FloatTime() - start ) ); + /* emit some stats */ Sys_FPrintf( SYS_VRB, "%9d decal surfaces\n", numDecalSurfaces ); }