diff --git a/libs/generic/vector.h b/libs/generic/vector.h index 55e895ec..c90e3492 100644 --- a/libs/generic/vector.h +++ b/libs/generic/vector.h @@ -11,6 +11,11 @@ Element m_elements[2]; public: BasicVector2(){ } +template +BasicVector2( const BasicVector2& other ){ + x() = static_cast( other.x() ); + y() = static_cast( other.y() ); +} BasicVector2( const Element& x_, const Element& y_ ){ x() = x_; y() = y_; diff --git a/tools/quake3/common/qmath.h b/tools/quake3/common/qmath.h index a3f70620..0e9cc292 100644 --- a/tools/quake3/common/qmath.h +++ b/tools/quake3/common/qmath.h @@ -5,7 +5,6 @@ #include "math/plane.h" -#define VectorSet( v, a, b, c ) ( ( v )[0] = ( a ),( v )[1] = ( b ),( v )[2] = ( c ) ) #define VectorCopy( a,b ) ( ( b )[0] = ( a )[0],( b )[1] = ( a )[1],( b )[2] = ( a )[2] ) #define RGBTOGRAY( x ) ( (float)( ( x )[0] ) * 0.2989f + (float)( ( x )[1] ) * 0.5870f + (float)( ( x )[2] ) * 0.1140f ) diff --git a/tools/quake3/q3map2/convert_map.cpp b/tools/quake3/q3map2/convert_map.cpp index 8f2498da..61445a34 100644 --- a/tools/quake3/q3map2/convert_map.cpp +++ b/tools/quake3/q3map2/convert_map.cpp @@ -522,8 +522,8 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or if ( brushPrimitives ) { int i; Vector3 texX, texY; - float xyI[2], xyJ[2], xyK[2]; - float stI[2], stJ[2], stK[2]; + Vector2 xyI, xyJ, xyK; + Vector2 stI, stJ, stK; float D, D0, D1, D2; ComputeAxisBase( buildPlane->normal(), texX, texY ); @@ -534,9 +534,9 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& or xyJ[1] = vector3_dot( vert[1]->xyz, texY ); xyK[0] = vector3_dot( vert[2]->xyz, texX ); xyK[1] = vector3_dot( vert[2]->xyz, texY ); - stI[0] = vert[0]->st[0]; stI[1] = vert[0]->st[1]; - stJ[0] = vert[1]->st[0]; stJ[1] = vert[1]->st[1]; - stK[0] = vert[2]->st[0]; stK[1] = vert[2]->st[1]; + stI = vert[0]->st; + stJ = vert[1]->st; + stK = vert[2]->st; // - solve linear equations: // - (x, y) := xyz . (texX, texY) diff --git a/tools/quake3/q3map2/decals.cpp b/tools/quake3/q3map2/decals.cpp index afcd7c99..03631038 100644 --- a/tools/quake3/q3map2/decals.cpp +++ b/tools/quake3/q3map2/decals.cpp @@ -62,8 +62,6 @@ static Vector3 entityOrigin; returns false 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 bool MakeTextureMatrix( decalProjector_t *dp, const Plane3f& projection, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c ){ int i, j; double bb, s, t; @@ -151,7 +149,7 @@ static bool MakeTextureMatrix( decalProjector_t *dp, const Plane3f& projection, { int k; DoubleVector3 deltas[ 3 ]; - double texDeltas[ 3 ][ 2 ]; + BasicVector2 texDeltas[ 3 ]; double delta, texDelta; @@ -161,9 +159,9 @@ static bool MakeTextureMatrix( decalProjector_t *dp, const Plane3f& projection, deltas[ 0 ] = pa - pb; deltas[ 1 ] = pa - pc; deltas[ 2 ] = pb - pc; - Vector2Subtract( a->st, b->st, texDeltas[ 0 ] ); - Vector2Subtract( a->st, c->st, texDeltas[ 1 ] ); - Vector2Subtract( b->st, c->st, texDeltas[ 2 ] ); + texDeltas[ 0 ] = a->st - b->st; + texDeltas[ 1 ] = a->st - c->st; + texDeltas[ 2 ] = b->st - c->st; /* walk st */ for ( i = 0; i < 2; i++ ) diff --git a/tools/quake3/q3map2/light.cpp b/tools/quake3/q3map2/light.cpp index b1e249bf..253e7541 100644 --- a/tools/quake3/q3map2/light.cpp +++ b/tools/quake3/q3map2/light.cpp @@ -95,9 +95,7 @@ static void CreateSunLight( sun_t *sun ){ //% Sys_Printf( "%d: Angle: %3.4lf Elevation: %3.3lf\n", sun->numSamples, radians_to_degrees( angle ), radians_to_degrees( elevation ) ); /* create new vector */ - direction[ 0 ] = cos( angle ) * cos( elevation ); - direction[ 1 ] = sin( angle ) * cos( elevation ); - direction[ 2 ] = sin( elevation ); + direction = vector3_for_spherical( angle, elevation ); } /* create a light */ @@ -163,7 +161,6 @@ static void CreateSkyLights( const Vector3& color, float value, int iterations, /* setup */ elevationSteps = iterations - 1; angleSteps = elevationSteps * 4; - angle = 0.0f; elevationStep = degrees_to_radians( 90.0f / iterations ); /* skip elevation 0 */ angleStep = degrees_to_radians( 360.0f / angleSteps ); @@ -180,9 +177,7 @@ static void CreateSkyLights( const Vector3& color, float value, int iterations, for ( j = 0; j < angleSteps; j++ ) { /* create sun */ - sun.direction[ 0 ] = cos( angle ) * cos( elevation ); - sun.direction[ 1 ] = sin( angle ) * cos( elevation ); - sun.direction[ 2 ] = sin( elevation ); + sun.direction = vector3_for_spherical( angle, elevation ); CreateSunLight( &sun ); /* move */ diff --git a/tools/quake3/q3map2/light_trace.cpp b/tools/quake3/q3map2/light_trace.cpp index 5221c37d..29d8b921 100644 --- a/tools/quake3/q3map2/light_trace.cpp +++ b/tools/quake3/q3map2/light_trace.cpp @@ -37,8 +37,6 @@ -#define Vector2Copy( a, b ) ( ( b )[ 0 ] = ( a )[ 0 ], ( b )[ 1 ] = ( a )[ 1 ] ) - #define MAX_NODE_ITEMS 5 #define MAX_NODE_TRIANGLES 5 #define MAX_TRACE_DEPTH 32 diff --git a/tools/quake3/q3map2/lightmaps_ydnar.cpp b/tools/quake3/q3map2/lightmaps_ydnar.cpp index 1cf58553..486c0458 100644 --- a/tools/quake3/q3map2/lightmaps_ydnar.cpp +++ b/tools/quake3/q3map2/lightmaps_ydnar.cpp @@ -1028,7 +1028,7 @@ void SetupSurfaceLightmaps( void ){ info->sampleSize = GetSurfaceExtraSampleSize( num ); info->longestCurve = GetSurfaceExtraLongestCurve( num ); info->patchIterations = IterationsForCurve( info->longestCurve, patchSubdivisions ); - GetSurfaceExtraLightmapAxis( num, info->axis ); + info->axis = GetSurfaceExtraLightmapAxis( num ); /* mark parent */ if ( info->parentSurfaceNum >= 0 ) { diff --git a/tools/quake3/q3map2/model.cpp b/tools/quake3/q3map2/model.cpp index 67082eb2..f071f28b 100644 --- a/tools/quake3/q3map2/model.cpp +++ b/tools/quake3/q3map2/model.cpp @@ -214,7 +214,6 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor mapDrawSurface_t *ds; bspDrawVert_t *dv; const char *picoShaderName; - picoVec_t *xyz, *normal, *st; byte *color; picoIndex_t *indexes; char *skinfilecontent; @@ -427,12 +426,10 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor dv = &ds->verts[ i ]; /* xyz and normal */ - xyz = PicoGetSurfaceXYZ( surface, i ); - VectorCopy( xyz, dv->xyz ); + dv->xyz = vector3_from_array( PicoGetSurfaceXYZ( surface, i ) ); matrix4_transform_point( transform, dv->xyz ); - normal = PicoGetSurfaceNormal( surface, i ); - VectorCopy( normal, dv->normal ); + dv->normal = vector3_from_array( PicoGetSurfaceNormal( surface, i ) ); matrix4_transform_direction( nTransform, dv->normal ); VectorNormalize( dv->normal ); @@ -451,9 +448,7 @@ void InsertModel( const char *name, int skin, int frame, const Matrix4& transfor /* normal texture coordinates */ else { - st = PicoGetSurfaceST( surface, 0, i ); - dv->st[ 0 ] = st[ 0 ]; - dv->st[ 1 ] = st[ 1 ]; + dv->st = vector2_from_array( PicoGetSurfaceST( surface, 0, i ) ); } /* set lightmap/color bits */ diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index 420c1819..f986d7cb 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -437,7 +437,7 @@ struct bspAdvertisement_t ------------------------------------------------------------------------------- */ /* ydnar: for q3map_tcMod */ -typedef float tcMod_t[ 3 ][ 3 ]; +typedef Vector3 tcMod_t[ 3 ]; /* ydnar: for multiple game support */ @@ -626,9 +626,9 @@ struct shaderInfo_t bool invert; /* ydnar: reverse facing */ bool nonplanar; /* ydnar: for nonplanar meta surface merging */ bool tcGen; /* ydnar: has explicit texcoord generation */ - Vector3 vecs[ 2 ]; /* ydnar: explicit texture vectors for [0,1] texture space */ + Vector3 vecs[ 2 ]; /* ydnar: explicit texture vectors for [0,1] texture space */ tcMod_t mod; /* ydnar: q3map_tcMod matrix for djbob :) */ - Vector3 lightmapAxis; /* ydnar: explicit lightmap axis projection */ + Vector3 lightmapAxis = { 0, 0, 0 }; /* ydnar: explicit lightmap axis projection */ colorMod_t *colorMod; /* ydnar: q3map_rgb/color/alpha/Set/Mod support */ int furNumLayers; /* ydnar: number of fur layers */ @@ -673,8 +673,8 @@ struct shaderInfo_t int skyLightIterations; /* ydnar */ sun_t *sun; /* ydnar */ - Vector3 color; /* normalized color */ - Color4f averageColor; + Vector3 color = { 0, 0, 0 }; /* normalized color */ + Color4f averageColor = { 0, 0, 0, 0 }; byte lightStyle; /* vortex: per-surface floodlight */ @@ -691,7 +691,7 @@ struct shaderInfo_t int shaderWidth, shaderHeight; /* ydnar */ Vector2 stFlat; - Vector3 fogDir; /* ydnar */ + Vector3 fogDir = { 0, 0, 0 }; /* ydnar */ char *shaderText; /* ydnar */ bool custom; @@ -744,7 +744,7 @@ struct side_t int outputNum; /* set when the side is written to the file list */ - Vector3 texMat[ 2 ]; /* brush primitive texture matrix */ + Vector3 texMat[ 2 ]; /* brush primitive texture matrix */ Vector4 vecs[ 2 ]; /* old-style texture coordinate mapping */ winding_t *winding; @@ -799,7 +799,7 @@ struct brush_t /* ydnar: gs mods */ int lightmapSampleSize; /* jal : entity based _lightmapsamplesize */ float lightmapScale; - float shadeAngleDegrees; /* jal : entity based _shadeangle */ + float shadeAngleDegrees; /* jal : entity based _shadeangle */ MinMax eMinmax; indexMap_t *im; @@ -933,8 +933,8 @@ struct mapDrawSurface_t int *indexes; int planeNum; - Vector3 lightmapOrigin; /* also used for flares */ - Vector3 lightmapVecs[ 3 ]; /* also used for flares */ + Vector3 lightmapOrigin; /* also used for flares */ + Vector3 lightmapVecs[ 3 ]; /* also used for flares */ int lightStyle; /* used for flares */ /* ydnar: per-surface (per-entity, actually) lightmap sample size scaling */ @@ -952,7 +952,7 @@ struct mapDrawSurface_t int castShadows, recvShadows; /* ydnar: texture coordinate range monitoring for hardware with limited texcoord precision (in texel space) */ - float bias[ 2 ]; + Vector2 bias; int texMins[ 2 ], texMaxs[ 2 ], texRange[ 2 ]; /* ydnar: for patches */ @@ -1156,7 +1156,7 @@ struct vportal_t visPlane_t plane; /* normal pointing into neighbor */ int leaf; /* neighbor */ - Vector3 origin; /* for fast clip testing */ + Vector3 origin; /* for fast clip testing */ float radius; fixedWinding_t *winding; @@ -1307,9 +1307,9 @@ struct trace_t float distance; /* input and output */ - Vector3 color; /* starts out at full color, may be reduced if transparent surfaces are crossed */ - Vector3 colorNoShadow; /* result color with no shadow casting */ - Vector3 directionContribution; /* result contribution to the deluxe map */ + Vector3 color; /* starts out at full color, may be reduced if transparent surfaces are crossed */ + Vector3 colorNoShadow; /* result color with no shadow casting */ + Vector3 directionContribution; /* result contribution to the deluxe map */ /* output */ Vector3 hit; @@ -1760,7 +1760,7 @@ int GetSurfaceExtraRecvShadows( int num ); int GetSurfaceExtraSampleSize( int num ); int GetSurfaceExtraMinSampleSize( int num ); float GetSurfaceExtraLongestCurve( int num ); -void GetSurfaceExtraLightmapAxis( int num, Vector3& lightmapAxis ); +Vector3 GetSurfaceExtraLightmapAxis( int num ); void WriteSurfaceExtraFile( const char *path ); void LoadSurfaceExtraFile( const char *path ); @@ -1870,12 +1870,12 @@ image_t *ImageLoad( const char *filename ); /* shaders.c */ void ColorMod( colorMod_t *am, int numVerts, bspDrawVert_t *drawVerts ); -void TCMod( tcMod_t mod, Vector2& st ); -void TCModIdentity( tcMod_t mod ); -void TCModMultiply( tcMod_t a, tcMod_t b, tcMod_t out ); -void TCModTranslate( tcMod_t mod, float s, float t ); -void TCModScale( tcMod_t mod, float s, float t ); -void TCModRotate( tcMod_t mod, float euler ); +void TCMod( const tcMod_t& mod, Vector2& st ); +void TCModIdentity( tcMod_t& mod ); +void TCModMultiply( const tcMod_t& a, const tcMod_t& b, tcMod_t& out ); +void TCModTranslate( tcMod_t& mod, float s, float t ); +void TCModScale( tcMod_t& mod, float s, float t ); +void TCModRotate( tcMod_t& mod, float euler ); bool ApplySurfaceParm( const char *name, int *contentFlags, int *surfaceFlags, int *compileFlags ); diff --git a/tools/quake3/q3map2/shaders.cpp b/tools/quake3/q3map2/shaders.cpp index 334bd01f..57a7a709 100644 --- a/tools/quake3/q3map2/shaders.cpp +++ b/tools/quake3/q3map2/shaders.cpp @@ -163,29 +163,23 @@ void ColorMod( colorMod_t *cm, int numVerts, bspDrawVert_t *drawVerts ){ routines for dealing with a 3x3 texture mod matrix */ -void TCMod( tcMod_t mod, Vector2& st ){ - float old[ 2 ]; +void TCMod( const tcMod_t& mod, Vector2& st ){ + const Vector2 old = st; - - old[ 0 ] = st[ 0 ]; - old[ 1 ] = st[ 1 ]; st[ 0 ] = ( mod[ 0 ][ 0 ] * old[ 0 ] ) + ( mod[ 0 ][ 1 ] * old[ 1 ] ) + mod[ 0 ][ 2 ]; st[ 1 ] = ( mod[ 1 ][ 0 ] * old[ 0 ] ) + ( mod[ 1 ][ 1 ] * old[ 1 ] ) + mod[ 1 ][ 2 ]; } -void TCModIdentity( tcMod_t mod ){ +void TCModIdentity( tcMod_t& mod ){ mod[ 0 ][ 0 ] = 1.0f; mod[ 0 ][ 1 ] = 0.0f; mod[ 0 ][ 2 ] = 0.0f; mod[ 1 ][ 0 ] = 0.0f; mod[ 1 ][ 1 ] = 1.0f; mod[ 1 ][ 2 ] = 0.0f; mod[ 2 ][ 0 ] = 0.0f; mod[ 2 ][ 1 ] = 0.0f; mod[ 2 ][ 2 ] = 1.0f; /* this row is only used for multiples, not transformation */ } -void TCModMultiply( tcMod_t a, tcMod_t b, tcMod_t out ){ - int i; - - - for ( i = 0; i < 3; i++ ) +void TCModMultiply( const tcMod_t& a, const tcMod_t& b, tcMod_t& out ){ + for ( int i = 0; i < 3; i++ ) { out[ i ][ 0 ] = ( a[ i ][ 0 ] * b[ 0 ][ 0 ] ) + ( a[ i ][ 1 ] * b[ 1 ][ 0 ] ) + ( a[ i ][ 2 ] * b[ 2 ][ 0 ] ); out[ i ][ 1 ] = ( a[ i ][ 0 ] * b[ 0 ][ 1 ] ) + ( a[ i ][ 1 ] * b[ 1 ][ 1 ] ) + ( a[ i ][ 2 ] * b[ 2 ][ 1 ] ); @@ -194,19 +188,19 @@ void TCModMultiply( tcMod_t a, tcMod_t b, tcMod_t out ){ } -void TCModTranslate( tcMod_t mod, float s, float t ){ +void TCModTranslate( tcMod_t& mod, float s, float t ){ mod[ 0 ][ 2 ] += s; mod[ 1 ][ 2 ] += t; } -void TCModScale( tcMod_t mod, float s, float t ){ +void TCModScale( tcMod_t& mod, float s, float t ){ mod[ 0 ][ 0 ] *= s; mod[ 1 ][ 1 ] *= t; } -void TCModRotate( tcMod_t mod, float euler ){ +void TCModRotate( tcMod_t& mod, float euler ){ tcMod_t old, temp; float radians, sinv, cosv; @@ -1235,7 +1229,6 @@ static void ParseShaderFile( const char *filename ){ degree of 0 = from the east, 90 = north, etc. altitude of 0 = sunrise/set, 90 = noon ydnar: sof2map has bareword 'sun' token, so we support that as well */ else if ( striEqual( token, "sun" ) /* sof2 */ || striEqual( token, "q3map_sun" ) || striEqual( token, "q3map_sunExt" ) ) { - float a, b; sun_t *sun; /* ydnar: extended sun directive? */ const bool ext = striEqual( token, "q3map_sunext" ); @@ -1269,14 +1262,12 @@ static void ParseShaderFile( const char *filename ){ /* get sun angle/elevation */ GetTokenAppend( shaderText, false ); - a = degrees_to_radians( atof( token ) ); + const double a = degrees_to_radians( atof( token ) ); GetTokenAppend( shaderText, false ); - b = degrees_to_radians( atof( token ) ); + const double b = degrees_to_radians( atof( token ) ); - sun->direction[ 0 ] = cos( a ) * cos( b ); - sun->direction[ 1 ] = sin( a ) * cos( b ); - sun->direction[ 2 ] = sin( b ); + sun->direction = vector3_for_spherical( a, b ); /* get filter radius from shader */ sun->filterRadius = si->lightFilterRadius; diff --git a/tools/quake3/q3map2/surface.cpp b/tools/quake3/q3map2/surface.cpp index 1fa8a23c..69d84db1 100644 --- a/tools/quake3/q3map2/surface.cpp +++ b/tools/quake3/q3map2/surface.cpp @@ -2884,8 +2884,7 @@ static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ){ /* set it */ dv->xyz = w->p[ i ]; dv->normal = p->plane.normal(); - dv->st[ 0 ] = 0; - dv->st[ 1 ] = 0; + dv->st = { 0, 0 }; for ( k = 0; k < MAX_LIGHTMAPS; k++ ) { dv->color[ k ].rgb() = debugColors[ c % 12 ]; @@ -2985,9 +2984,6 @@ void MakeFogHullSurfs( entity_t *e, tree_t *tree, const char *shader ){ */ void BiasSurfaceTextures( mapDrawSurface_t *ds ){ - int i; - - /* calculate the surface texture bias */ CalcSurfaceTextureRange( ds ); @@ -2997,10 +2993,9 @@ void BiasSurfaceTextures( mapDrawSurface_t *ds ){ } /* bias the texture coordinates */ - for ( i = 0; i < ds->numVerts; i++ ) + for ( int i = 0; i < ds->numVerts; i++ ) { - ds->verts[ i ].st[ 0 ] += ds->bias[ 0 ]; - ds->verts[ i ].st[ 1 ] += ds->bias[ 1 ]; + ds->verts[ i ].st += ds->bias; } } diff --git a/tools/quake3/q3map2/surface_extra.cpp b/tools/quake3/q3map2/surface_extra.cpp index beedeb6e..ffe12931 100644 --- a/tools/quake3/q3map2/surface_extra.cpp +++ b/tools/quake3/q3map2/surface_extra.cpp @@ -139,50 +139,42 @@ static surfaceExtra_t *GetSurfaceExtra( int num ){ shaderInfo_t *GetSurfaceExtraShaderInfo( int num ){ - surfaceExtra_t *se = GetSurfaceExtra( num ); - return se->si; + return GetSurfaceExtra( num )->si; } int GetSurfaceExtraParentSurfaceNum( int num ){ - surfaceExtra_t *se = GetSurfaceExtra( num ); - return se->parentSurfaceNum; + return GetSurfaceExtra( num )->parentSurfaceNum; } int GetSurfaceExtraEntityNum( int num ){ - surfaceExtra_t *se = GetSurfaceExtra( num ); - return se->entityNum; + return GetSurfaceExtra( num )->entityNum; } int GetSurfaceExtraCastShadows( int num ){ - surfaceExtra_t *se = GetSurfaceExtra( num ); - return se->castShadows; + return GetSurfaceExtra( num )->castShadows; } int GetSurfaceExtraRecvShadows( int num ){ - surfaceExtra_t *se = GetSurfaceExtra( num ); - return se->recvShadows; + return GetSurfaceExtra( num )->recvShadows; } int GetSurfaceExtraSampleSize( int num ){ - surfaceExtra_t *se = GetSurfaceExtra( num ); - return se->sampleSize; + return GetSurfaceExtra( num )->sampleSize; } float GetSurfaceExtraLongestCurve( int num ){ - surfaceExtra_t *se = GetSurfaceExtra( num ); - return se->longestCurve; + return GetSurfaceExtra( num )->longestCurve; } -void GetSurfaceExtraLightmapAxis( int num, Vector3& lightmapAxis ){ - surfaceExtra_t *se = GetSurfaceExtra( num ); - lightmapAxis = se->lightmapAxis; +Vector3 GetSurfaceExtraLightmapAxis( int num ){ + return GetSurfaceExtra( num )->lightmapAxis; } diff --git a/tools/quake3/q3map2/surface_meta.cpp b/tools/quake3/q3map2/surface_meta.cpp index 308ff124..c2a5f367 100644 --- a/tools/quake3/q3map2/surface_meta.cpp +++ b/tools/quake3/q3map2/surface_meta.cpp @@ -549,7 +549,9 @@ void MaxAreaFaceSurface( mapDrawSurface_t *ds ){ if ( ds->numVerts == 3 ) { ds->numIndexes = 3; ds->indexes = safe_malloc( ds->numIndexes * sizeof( int ) ); - VectorSet( ds->indexes, 0, 1, 2 ); + ds->indexes[0] = 0; + ds->indexes[1] = 1; + ds->indexes[2] = 2; numMaxAreaSurfaces++; return; } @@ -677,7 +679,9 @@ void StripFaceSurface( mapDrawSurface_t *ds ){ /* is this a simple triangle? */ if ( ds->numVerts == 3 ) { numIndexes = 3; - VectorSet( indexes, 0, 1, 2 ); + indexes[0] = 0; + indexes[1] = 1; + indexes[2] = 2; } else {