diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 9f8fc85a..737bd2fe 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -260,7 +260,7 @@ usercmd_t CL_CreateCmd( void ) { usercmd_t cmd; static double extramsec = 0; - vec3_t color; + color24 color; int ms; // send milliseconds of time to apply the move @@ -292,8 +292,8 @@ usercmd_t CL_CreateCmd( void ) clgame.dllFuncs.CL_CreateMove( cl.time - cl.oldtime, &cmd, ( cls.state == ca_active && !cl.refdef.paused )); - R_LightForPoint( cl.frame.local.client.origin, color ); - cmd.lightlevel = VectorAvg( color ) * 255; + R_LightForPoint( cl.frame.local.client.origin, &color, false ); + cmd.lightlevel = (color.r + color.g + color.b) / 3; // random seed for predictable random values cl.random_seed = Com_RandomLong( 0, 0x7fffffff ); // full range diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index b645311d..f7618c2b 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -1456,7 +1456,7 @@ void CL_Projectile( const vec3_t origin, const vec3_t velocity, int modelIndex, pTemp = CL_TempEntAlloc( origin, CM_ClipHandleToModel( modelIndex )); if( !pTemp ) return; - pfnVecToAngles( velocity, pTemp->entity.angles ); + VectorAngles( velocity, pTemp->entity.angles ); VectorCopy( velocity, pTemp->entity.baseline.origin ); pTemp->entity.curstate.body = 0; diff --git a/engine/client/gl_local.h b/engine/client/gl_local.h index 599c8716..8759af9e 100644 --- a/engine/client/gl_local.h +++ b/engine/client/gl_local.h @@ -153,7 +153,8 @@ typedef struct matrix4x4 projectionMatrix; matrix4x4 worldviewProjectionMatrix; // worldviewMatrix * projectionMatrix - int lightstylevalue[MAX_LIGHTSTYLES]; + int lightstylevalue[MAX_LIGHTSTYLES]; // value 0 - 65536 + float lightstylecolor[MAX_LIGHTSTYLES]; // color 0 - 1.0 mplane_t clipPlane; } ref_instance_t; @@ -179,6 +180,12 @@ typedef struct uint num_static_entities; uint num_solid_entities; uint num_trans_entities; + + uint numColors; // vertex array num colors + uint numVertex; // vertex array num vertex + rgb_t colorsArray[4096]; // MAXSTUDIOVERTS + vec3_t normalArray[4096]; + vec3_t vertexArray[4096]; // OpenGL matrix states qboolean modelviewIdentity; @@ -195,6 +202,8 @@ typedef struct uint c_studio_polys; uint c_sprite_polys; uint c_world_leafs; + + uint c_studio_models; } ref_speeds_t; extern ref_speeds_t r_stats; @@ -242,7 +251,7 @@ gltexture_t *R_GetTexture( GLenum texnum ); void GL_SetTextureType( GLenum texnum, GLenum type ); int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags ); int GL_LoadTextureInternal( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ); -byte *GL_ResampleTexture( const byte *source, int inWidth, int inHeight, int outWidth, int outHeight, qboolean isNormalMap ); +byte *GL_ResampleTexture( const byte *source, int in_w, int in_h, int out_w, int out_h, qboolean isNormalMap ); void GL_FreeTexture( GLenum texnum ); void GL_FreeImage( const char *name ); void R_TextureList_f( void ); @@ -260,6 +269,8 @@ void R_StoreEfrags( efrag_t **ppefrag ); void R_PushDlights( void ); void R_AnimateLight( void ); void R_MarkLights( dlight_t *light, int bit, mnode_t *node ); +void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight ); +void R_LightForOrigin( const vec3_t origin, vec3_t dir, color24 *ambient, color24 *diffuse, float radius ); // // gl_rmain.c @@ -274,8 +285,13 @@ void R_RotateForEntity( cl_entity_t *e ); // // gl_rmath.c // +void R_InitMathlib( void ); +void R_LatLongToNorm( const byte latlong[2], vec3_t normal ); +void R_NormToLatLong( const vec3_t normal, byte latlong[2] ); float V_CalcFov( float *fov_x, float width, float height ); void V_AdjustFov( float *fov_x, float *fov_y, float width, float height, qboolean lock_x ); +byte R_FloatToByte( float x ); + // // gl_rsurf.c @@ -296,6 +312,12 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer ); mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw ); void R_DrawSpriteModel( cl_entity_t *e ); +// +// gl_studio.c +// +void R_StudioInit( void ); +void R_DrawStudioModel( cl_entity_t *e ); + // // gl_warp.c // @@ -477,6 +499,8 @@ extern convar_t *r_speeds; extern convar_t *r_fullbright; extern convar_t *r_norefresh; extern convar_t *r_lighting_modulate; +extern convar_t *r_lighting_ambient; +extern convar_t *r_lighting_direct; extern convar_t *r_faceplanecull; extern convar_t *r_drawentities; extern convar_t *r_adjust_fov; diff --git a/engine/client/gl_rlight.c b/engine/client/gl_rlight.c index 7464382d..344167d3 100644 --- a/engine/client/gl_rlight.c +++ b/engine/client/gl_rlight.c @@ -5,7 +5,9 @@ #include "common.h" #include "client.h" +#include "matrix_lib.h" #include "gl_local.h" +#include "studio.h" /* ============================================================================= @@ -23,7 +25,7 @@ R_AnimateLight void R_AnimateLight( void ) { int i, k, flight, clight; - float l, lerpfrac, backlerp; + float l, c, lerpfrac, backlerp; lightstyle_t *ls; // light animations @@ -38,6 +40,7 @@ void R_AnimateLight( void ) if( r_fullbright->integer || !cl.worldmodel->lightdata ) { RI.lightstylevalue[i] = 256 * 256; + RI.lightstylecolor[i] = 1.0f; continue; } @@ -45,17 +48,20 @@ void R_AnimateLight( void ) { // was 256, changed to 264 for consistency RI.lightstylevalue[i] = 256 * r_lighting_modulate->value; + RI.lightstylecolor[i] = 1.0f * r_lighting_ambient->value; continue; } else if( ls->length == 1 ) { // single length style so don't bother interpolating RI.lightstylevalue[i] = ls->map[0] * 22 * r_lighting_modulate->value; + RI.lightstylecolor[i] = (ls->map[0] / 12.0f ) * r_lighting_ambient->value; continue; } else if( !ls->interp || !cl_lightstyle_lerping->integer ) { RI.lightstylevalue[i] = ls->map[flight%ls->length] * 22 * r_lighting_modulate->value; + RI.lightstylecolor[i] = (ls->map[flight%ls->length] / 12.0f) * r_lighting_ambient->value; continue; } @@ -63,12 +69,15 @@ void R_AnimateLight( void ) // frame just gone k = ls->map[flight % ls->length]; l = (float)( k * 22 ) * backlerp; + c = (float)( k / 12 ) * backlerp; // upcoming frame k = ls->map[clight % ls->length]; l += (float)( k * 22 ) * lerpfrac; + c += (float)( k / 12 ) * lerpfrac; RI.lightstylevalue[i] = (int)l * r_lighting_modulate->value; + RI.lightstylecolor[i] = c * r_lighting_ambient->value; } } @@ -138,7 +147,576 @@ void R_PushDlights( void ) R_MarkLights( l, 1<nodes ); } } - -void R_LightForPoint( const vec3_t point, vec3_t ambientLight ) + +//=================================================================== +/* +================= +R_ReadLightGrid +================= +*/ +static void R_ReadLightGrid( const vec3_t origin, vec3_t lightDir ) { + vec3_t vf1, vf2, tdir; + int vi[3], elem[4]; + float scale[8]; + int i, k, s; + + if( !world.lightgrid ) + { + // pre-defined light vector + lightDir[0] = RI.refdef.movevars->skyvec_x; + lightDir[1] = RI.refdef.movevars->skyvec_y; + lightDir[2] = RI.refdef.movevars->skyvec_z; + return; + } + + for( i = 0; i < 3; i++ ) + { + vf1[i] = (origin[i] - world.gridMins[i]) / world.gridSize[i]; + vi[i] = (int)vf1[i]; + vf1[i] = vf1[i] - floor( vf1[i] ); + vf2[i] = 1.0f - vf1[i]; + } + + elem[0] = vi[2] * world.gridBounds[3] + vi[1] * world.gridBounds[0] + vi[0]; + elem[1] = elem[0] + world.gridBounds[0]; + elem[2] = elem[0] + world.gridBounds[3]; + elem[3] = elem[2] + world.gridBounds[0]; + + for( i = 0; i < 4; i++ ) + { + if( elem[i] < 0 || elem[i] >= world.numgridpoints - 1 ) + { + // pre-defined light vector + lightDir[0] = RI.refdef.movevars->skyvec_x; + lightDir[1] = RI.refdef.movevars->skyvec_y; + lightDir[2] = RI.refdef.movevars->skyvec_z; + return; + } + } + + scale[0] = vf2[0] * vf2[1] * vf2[2]; + scale[1] = vf1[0] * vf2[1] * vf2[2]; + scale[2] = vf2[0] * vf1[1] * vf2[2]; + scale[3] = vf1[0] * vf1[1] * vf2[2]; + scale[4] = vf2[0] * vf2[1] * vf1[2]; + scale[5] = vf1[0] * vf2[1] * vf1[2]; + scale[6] = vf2[0] * vf1[1] * vf1[2]; + scale[7] = vf1[0] * vf1[1] * vf1[2]; + + VectorClear( lightDir ); + + for( i = 0; i < 4; i++ ) + { + R_LatLongToNorm( world.lightgrid[elem[i]+0].direction, tdir ); + VectorScale( tdir, scale[i*2+0], tdir ); + + for( k = 0; k < LM_STYLES && ( s = world.lightgrid[elem[i]+0].styles[k] ) != 255; k++ ) + { + lightDir[0] += RI.lightstylecolor[s] * tdir[0]; + lightDir[1] += RI.lightstylecolor[s] * tdir[1]; + lightDir[2] += RI.lightstylecolor[s] * tdir[2]; + } + + R_LatLongToNorm( world.lightgrid[elem[i]+1].direction, tdir ); + VectorScale( tdir, scale[i*2+1], tdir ); + + for( k = 0; k < LM_STYLES && ( s = world.lightgrid[elem[i]+1].styles[k] ) != 255; k++ ) + { + lightDir[0] += RI.lightstylecolor[s] * tdir[0]; + lightDir[1] += RI.lightstylecolor[s] * tdir[1]; + lightDir[2] += RI.lightstylecolor[s] * tdir[2]; + } + } +} + +/* +======================================================================= + + AMBIENT & DIFFUSE LIGHTING + +======================================================================= +*/ + +static uint r_pointColor[3]; +static vec3_t r_lightColors[MAXSTUDIOVERTS]; + +/* +================= +R_RecursiveLightPoint +================= +*/ +static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, const vec3_t start, const vec3_t end ) +{ + float front, back, frac; + int i, map, side, size, s, t; + msurface_t *surf; + mtexinfo_t *tex; + color24 *lm; + vec3_t mid; + + // didn't hit anything + if( node->contents < 0 ) + return false; + + // calculate mid point + front = PlaneDiff( start, node->plane ); + back = PlaneDiff( end, node->plane ); + + side = front < 0; + if(( back < 0 ) == side ) + return R_RecursiveLightPoint( model, node->children[side], start, end ); + + frac = front / ( front - back ); + + VectorLerp( start, frac, end, mid ); + + // co down front side + if( R_RecursiveLightPoint( model, node->children[side], start, mid )) + return true; // hit something + + if(( back < 0 ) == side ) + return false;// didn't hit anything + + // check for impact on this node + surf = model->surfaces + node->firstsurface; + + for( i = 0; i < node->numsurfaces; i++, surf++ ) + { + tex = surf->texinfo; + + if( surf->flags & SURF_DRAWTILED ) + continue; // no lightmaps + + s = DotProduct( mid, tex->vecs[0] ) + tex->vecs[0][3] - surf->texturemins[0]; + t = DotProduct( mid, tex->vecs[1] ) + tex->vecs[1][3] - surf->texturemins[1]; + + if(( s < 0 || s > surf->extents[0] ) || ( t < 0 || t > surf->extents[1] )) + continue; + + s >>= 4; + t >>= 4; + + if( !surf->samples ) + return true; + + VectorClear( r_pointColor ); + + lm = surf->samples + (t * ((surf->extents[0] >> 4) + 1) + s); + size = ((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1); + + for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ ) + { + uint scale = RI.lightstylevalue[surf->styles[map]]; + + r_pointColor[0] += lm->r * scale; + r_pointColor[1] += lm->g * scale; + r_pointColor[2] += lm->b * scale; + + lm += size; // skip to next lightmap + } + return true; + } + + // go down back side + return R_RecursiveLightPoint( model, node->children[!side], mid, end ); +} + +/* +================= +R_LightForPoint +================= +*/ +void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight ) +{ + dlight_t *dl; + vec3_t end, dir; + float dist, add; + int lnum; + + // set to full bright if no light data + if( !cl.worldmodel || !cl.worldmodel->lightdata ) + { + ambientLight->r = 255; + ambientLight->g = 255; + ambientLight->b = 255; + return; + } + + // Get lighting at this point + VectorCopy( point, end ); + if( invLight ) end[2] = point[2] + 8192; + else end[2] = point[2] - 8192; + + VectorSet( r_pointColor, 255, 255, 255 ); + R_RecursiveLightPoint( cl.worldmodel, cl.worldmodel->nodes, point, end ); + + ambientLight->r = min((r_pointColor[0] >> 7), 255 ); + ambientLight->g = min((r_pointColor[1] >> 7), 255 ); + ambientLight->b = min((r_pointColor[2] >> 7), 255 ); + + // add dynamic lights + if( r_dynamic->integer ) + { + for( lnum = 0, dl = cl_dlights; lnum < MAX_DLIGHTS; lnum++, dl++ ) + { + if( dl->die < cl.time || !dl->radius ) + continue; + + VectorSubtract( dl->origin, point, dir ); + dist = VectorLength( dir ); + + if( !dist || dist > dl->radius ) + continue; + + add = (dl->radius - dist); + ambientLight->r = ambientLight->r + (dl->color.r * add); + ambientLight->g = ambientLight->g + (dl->color.g * add); + ambientLight->b = ambientLight->b + (dl->color.b * add); + } + } +} + +/* +================= +R_LightDir +================= +*/ +void R_LightDir( const vec3_t origin, vec3_t lightDir, float radius ) +{ + dlight_t *dl; + vec3_t dir; + float dist; + int lnum; + + // get light direction from light grid + R_ReadLightGrid( origin, lightDir ); + + // add dynamic lights + if( radius > 0.0f && r_dynamic->integer ) + { + for( lnum = 0, dl = cl_dlights; lnum < MAX_DLIGHTS; lnum++, dl++ ) + { + if( dl->die < cl.time || !dl->radius ) + continue; + + VectorSubtract( dl->origin, origin, dir ); + dist = VectorLength( dir ); + + if( !dist || dist > dl->radius + radius ) + continue; + VectorAdd( lightDir, dir, lightDir ); + } + } + + // FIXME: should we normalize final direction ? +// VectorNormalize( lightDir ); +} + +/* +=============== +R_LightForOrigin + +extended version of LightForPoint +=============== +*/ +void R_LightForOrigin( const vec3_t origin, vec3_t dir, color24 *ambient, color24 *diffuse, float radius ) +{ + int i, j, k, s; + float dot, t[8]; + vec3_t vf, vf2, tdir; + int vi[3], elem[4]; + vec3_t ambientLocal, diffuseLocal; + float *gridSize, *gridMins; + int *gridBounds; + mgridlight_t *lightgrid; + + if( !cl.worldmodel || !world.lightgrid || !world.numgridpoints ) + { + // get fullbright + VectorSet( ambientLocal, 255, 255, 255 ); + VectorSet( diffuseLocal, 255, 255, 255 ); + dir[0] = RI.refdef.movevars->skyvec_x; + dir[1] = RI.refdef.movevars->skyvec_y; + dir[2] = RI.refdef.movevars->skyvec_z; + goto dynamic; + } + else + { + VectorClear( ambientLocal ); + VectorClear( diffuseLocal ); + } + + lightgrid = world.lightgrid; + gridSize = world.gridSize; + gridMins = world.gridMins; + gridBounds = world.gridBounds; + + for( i = 0; i < 3; i++ ) + { + vf[i] = ( origin[i] - gridMins[i] ) / gridSize[i]; + vi[i] = (int)vf[i]; + vf[i] = vf[i] - floor( vf[i] ); + vf2[i] = 1.0f - vf[i]; + } + + elem[0] = vi[2] * gridBounds[3] + vi[1] * gridBounds[0] + vi[0]; + elem[1] = elem[0] + gridBounds[0]; + elem[2] = elem[0] + gridBounds[3]; + elem[3] = elem[2] + gridBounds[0]; + + for( i = 0; i < 4; i++ ) + { + if( elem[i] < 0 || elem[i] >= ( world.numgridpoints - 1 )) + { + dir[0] = RI.refdef.movevars->skyvec_x; + dir[1] = RI.refdef.movevars->skyvec_y; + dir[2] = RI.refdef.movevars->skyvec_z; + goto dynamic; + } + } + + t[0] = vf2[0] * vf2[1] * vf2[2]; + t[1] = vf[0] * vf2[1] * vf2[2]; + t[2] = vf2[0] * vf[1] * vf2[2]; + t[3] = vf[0] * vf[1] * vf2[2]; + t[4] = vf2[0] * vf2[1] * vf[2]; + t[5] = vf[0] * vf2[1] * vf[2]; + t[6] = vf2[0] * vf[1] * vf[2]; + t[7] = vf[0] * vf[1] * vf[2]; + + VectorClear( dir ); + + for( i = 0; i < 4; i++ ) + { + R_LatLongToNorm( lightgrid[elem[i]].direction, tdir ); + VectorScale( tdir, t[i*2+0], tdir ); + for( k = 0; k < LM_STYLES && ( s = lightgrid[elem[i]].styles[k] ) != 255; k++ ) + { + dir[0] += RI.lightstylecolor[s] * tdir[0]; + dir[1] += RI.lightstylecolor[s] * tdir[1]; + dir[2] += RI.lightstylecolor[s] * tdir[2]; + } + + R_LatLongToNorm( lightgrid[elem[i] + 1].direction, tdir ); + VectorScale( tdir, t[i*2+1], tdir ); + for( k = 0; k < LM_STYLES && ( s = lightgrid[elem[i] + 1].styles[k] ) != 255; k++ ) + { + dir[0] += RI.lightstylecolor[s] * tdir[0]; + dir[1] += RI.lightstylecolor[s] * tdir[1]; + dir[2] += RI.lightstylecolor[s] * tdir[2]; + } + } + + for( j = 0; j < 3; j++ ) + { + if( ambient ) + { + for( i = 0; i < 4; i++ ) + { + for( k = 0; k < LM_STYLES; k++ ) + { + if(( s = lightgrid[elem[i]].styles[k] ) != 255 ) + ambientLocal[j] += t[i*2+0] * lightgrid[elem[i]+0].ambient[k][j] * RI.lightstylecolor[s]; + if(( s = lightgrid[elem[i] + 1].styles[k] ) != 255 ) + ambientLocal[j] += t[i*2+1] * lightgrid[elem[i]+1].ambient[k][j] * RI.lightstylecolor[s]; + } + } + } + + if( diffuse || radius ) + { + for( i = 0; i < 4; i++ ) + { + for( k = 0; k < LM_STYLES; k++ ) + { + if( ( s = lightgrid[elem[i]].styles[k] ) != 255 ) + diffuseLocal[j] += t[i*2+0] * lightgrid[elem[i]+0].diffuse[k][j] * RI.lightstylecolor[s]; + if( ( s = lightgrid[elem[i] + 1].styles[k] ) != 255 ) + diffuseLocal[j] += t[i*2+1] * lightgrid[elem[i]+1].diffuse[k][j] * RI.lightstylecolor[s]; + } + } + } + } + +dynamic: + // add dynamic lights + if( radius && r_dynamic->integer ) + { + uint lnum; + dlight_t *dl; + float dist, dist2, add; + vec3_t direction; + qboolean anyDlights = false; + + for( lnum = 0, dl = cl_dlights; lnum < MAX_DLIGHTS; lnum++, dl++ ) + { + if( dl->die < cl.time || !dl->radius ) + continue; + + VectorSubtract( dl->origin, origin, direction ); + dist = VectorLength( direction ); + + if( !dist || dist > dl->radius + radius ) + continue; + + if( !anyDlights ) + { + VectorNormalizeFast( dir ); + anyDlights = true; + } + + add = 1.0f - (dist / ( dl->radius + radius )); + dist2 = add * 0.5f / dist; + + dot = dl->color.r * add; + diffuseLocal[0] += dot; + ambientLocal[0] += dot * 0.05f; + dir[0] += direction[0] * dist2; + dot = dl->color.g * add; + diffuseLocal[1] += dot; + ambientLocal[1] += dot * 0.05f; + dir[1] += direction[1] * dist2; + dot = dl->color.b * add; + diffuseLocal[2] += dot; + ambientLocal[2] += dot * 0.05f; + dir[2] += direction[2] * dist2; + } + } + + VectorNormalizeFast( dir ); + + if( ambient ) + { + dot = bound( 0.0f, r_lighting_ambient->value, 1.0f ) * 255.0f; + ambient->r = (byte)bound( 0, ambientLocal[0] * dot, 255 ); + ambient->g = (byte)bound( 0, ambientLocal[1] * dot, 255 ); + ambient->b = (byte)bound( 0, ambientLocal[2] * dot, 255 ); + } + + if( diffuse ) + { + dot = bound( 0.0f, r_lighting_direct->value, 1.0f ) * 255.0f; + diffuse->r = (byte)bound( 0, diffuseLocal[0] * dot, 255 ); + diffuse->g = (byte)bound( 0, diffuseLocal[1] * dot, 255 ); + diffuse->b = (byte)bound( 0, diffuseLocal[2] * dot, 255 ); + } +} +/* +================= +R_LightForEntity +================= +*/ +void R_LightForEntity( cl_entity_t *e, byte *bArray ) +{ + dlight_t *dl; + vec3_t end, dir; + float scale = 1.0f; + float add, dot, dist, intensity, radius; + vec3_t ambientLight, directedLight, lightDir; + matrix4x4 matrix, imatrix; + vec3_t pointColor; + float *cArray; + int i, l; + + if(( e->curstate.effects & EF_FULLBRIGHT ) || r_fullbright->integer ) + return; + + // never gets diffuse lighting for world brushes or sprites + if( !e->model || ( e->model->type == mod_brush ) || ( e->model->type == mod_sprite )) + return; + + // get lighting at this point + if( e->curstate.effects & EF_INVLIGHT ) + VectorSet( end, e->origin[0], e->origin[1], e->origin[2] + 8192 ); + else VectorSet( end, e->origin[0], e->origin[1], e->origin[2] - 8192 ); + VectorSet( r_pointColor, 1.0f, 1.0f, 1.0f ); + + R_RecursiveLightPoint( cl.worldmodel, cl.worldmodel->nodes, e->origin, end ); + + pointColor[0] = (float)min((r_pointColor[0] >> 7), 255 ) * (1.0f / 255.0f); + pointColor[1] = (float)min((r_pointColor[1] >> 7), 255 ) * (1.0f / 255.0f); + pointColor[2] = (float)min((r_pointColor[2] >> 7), 255 ) * (1.0f / 255.0f); + + VectorScale( pointColor, r_lighting_ambient->value, ambientLight ); + VectorScale( pointColor, r_lighting_direct->value, directedLight ); + + R_ReadLightGrid( e->origin, lightDir ); + + // always have some light + if( e->curstate.effects & EF_MINLIGHT ) + { + for( i = 0; i < 3; i++ ) + { + if( ambientLight[i] > 0.01f ) + break; + } + + if( i == 3 ) + { + VectorSet( ambientLight, 0.01f, 0.01f, 0.01f ); + } + } + + if( e->model->type != mod_brush && e->curstate.scale > 0.0f ) + scale = e->curstate.scale; + + // compute lighting at each vertex + Matrix4x4_CreateFromEntity( matrix, 0.0f, 0.0f, 0.0f, e->angles[0], e->angles[1], e->angles[2], scale ); + Matrix4x4_Invert_Simple( imatrix, matrix ); + + // rotate direction + Matrix4x4_VectorRotate( imatrix, lightDir, dir ); + VectorNormalizeFast( dir ); + + for( i = 0; i < tr.numColors; i++ ) + { + dot = DotProduct( tr.normalArray[i], dir ); + if( dot <= 0.0f ) VectorCopy( ambientLight, r_lightColors[i] ); + else VectorMA( ambientLight, dot, directedLight, r_lightColors[i] ); + } + + // add dynamic lights + if( r_dynamic->integer ) + { + radius = e->model->radius; + + for( l = 0, dl = cl_dlights; l < MAX_DLIGHTS; l++, dl++ ) + { + if( dl->die < cl.time || !dl->radius ) + continue; + + VectorSubtract( dl->origin, e->origin, dir ); + dist = VectorLength( dir ); + + if( !dist || dist > dl->radius + radius ) + continue; + + Matrix4x4_VectorRotate( imatrix, dir, lightDir ); + intensity = dl->radius * 8; + + // compute lighting at each vertex + for( i = 0; i < tr.numColors; i++ ) + { + VectorSubtract( lightDir, tr.vertexArray[i], dir ); + add = DotProduct( tr.normalArray[i], dir ); + if( add <= 0.0f ) continue; + + dot = DotProduct( dir, dir ); + add *= ( intensity / dot ) * rsqrt( dot ); + r_lightColors[i][0] = r_lightColors[i][0] + (dl->color.r * add); + r_lightColors[i][1] = r_lightColors[i][1] + (dl->color.g * add); + r_lightColors[i][2] = r_lightColors[i][2] + (dl->color.b * add); + } + } + } + + cArray = r_lightColors[0]; + + for( i = 0; i < tr.numColors; i++, bArray += 4, cArray += 3 ) + { + bArray[0] = R_FloatToByte( cArray[0] ); + bArray[1] = R_FloatToByte( cArray[1] ); + bArray[2] = R_FloatToByte( cArray[2] ); + } } \ No newline at end of file diff --git a/engine/client/gl_rmain.c b/engine/client/gl_rmain.c index d613ed79..d81db83d 100644 --- a/engine/client/gl_rmain.c +++ b/engine/client/gl_rmain.c @@ -43,9 +43,6 @@ typically is a func_wall, func_breakable, func_ladder etc */ static qboolean R_StaticEntity( cl_entity_t *ent ) { - if( gl_test->integer ) - return false; - if( ent->curstate.rendermode != kRenderNormal ) return false; @@ -698,6 +695,9 @@ void R_DrawEntitiesOnList( void ) case mod_brush: R_DrawBrushModel( RI.currententity ); break; + case mod_studio: + R_DrawStudioModel( RI.currententity ); + break; case mod_sprite: R_DrawSpriteModel( RI.currententity ); break; @@ -729,6 +729,9 @@ void R_DrawEntitiesOnList( void ) case mod_brush: R_DrawBrushModel( RI.currententity ); break; + case mod_studio: + R_DrawStudioModel( RI.currententity ); + break; case mod_sprite: R_DrawSpriteModel( RI.currententity ); break; diff --git a/engine/client/gl_rmath.c b/engine/client/gl_rmath.c index 2a2d8299..3fa74323 100644 --- a/engine/client/gl_rmath.c +++ b/engine/client/gl_rmath.c @@ -7,6 +7,67 @@ #include "gl_local.h" #include "mathlib.h" +#define FTABLE_SIZE_POW 10 +#define NOISE_SIZE 256 +#define FTABLE_SIZE ( 1< 0 ) + { + latlong[0] = 0; // acos ( 1 ) + latlong[1] = 0; + } + else + { + latlong[0] = 128; // acos ( -1 ) + latlong[1] = 0; + } + } + else + { + int angle; + + angle = (int)(com.acos( normal[2]) * 255.0 / M_PI2 ) & 255; + latlong[0] = angle; + angle = (int)(com.atan2( normal[1], normal[0] ) * 255.0 / M_PI2 ) & 255; + latlong[1] = angle; + } +} + +/* +============= +R_LatLongToNorm +============= +*/ +void R_LatLongToNorm( const byte latlong[2], vec3_t normal ) +{ + float sin_a, sin_b, cos_a, cos_b; + + cos_a = r_sintableByte[(latlong[0] + 64) & 255]; + sin_a = r_sintableByte[latlong[0]]; + cos_b = r_sintableByte[(latlong[1] + 64) & 255]; + sin_b = r_sintableByte[latlong[1]]; + + VectorSet( normal, cos_b * sin_a, sin_b * sin_a, cos_a ); +} + +byte R_FloatToByte( float x ) +{ + union { + float f; + uint i; + } f2i; + + // shift float to have 8bit fraction at base of number + f2i.f = x + 32768.0f; + f2i.i &= 0x7FFFFF; + + // then read as integer and kill float bits... + return ( byte )min( f2i.i, 255 ); } \ No newline at end of file diff --git a/engine/client/gl_sprite.c b/engine/client/gl_sprite.c index 27d11d08..32ec38f4 100644 --- a/engine/client/gl_sprite.c +++ b/engine/client/gl_sprite.c @@ -811,9 +811,16 @@ void R_DrawSpriteModel( cl_entity_t *e ) GL_SetState( state ); - color.r = e->curstate.rendercolor.r; - color.g = e->curstate.rendercolor.g; - color.b = e->curstate.rendercolor.b; + if( !gl_test->integer && psprite->texFormat == SPR_ALPHTEST ) + { + R_LightForPoint( origin, &color, false ); + } + else + { + color.r = e->curstate.rendercolor.r; + color.g = e->curstate.rendercolor.g; + color.b = e->curstate.rendercolor.b; + } if( e->curstate.rendermode == kRenderNormal || e->curstate.rendermode == kRenderTransAlpha ) frame = oldframe = R_GetSpriteFrame( model, e->curstate.frame, e->angles[YAW] ); diff --git a/engine/client/gl_studio.c b/engine/client/gl_studio.c index 3fa87a2a..651103db 100644 --- a/engine/client/gl_studio.c +++ b/engine/client/gl_studio.c @@ -12,7 +12,32 @@ #include "pm_local.h" #include "gl_local.h" +convar_t *r_studio_lerping; static r_studio_interface_t *pStudioDraw; +static float aliasXscale, aliasYscale; +static matrix3x4 g_rotationmatrix; + +/* +==================== +R_StudioInit + +==================== +*/ +void R_StudioInit( void ) +{ + float pixelAspect; + + r_studio_lerping = Cvar_Get( "r_studio_lerping", "1", CVAR_ARCHIVE, "enables studio animation lerping" ); + + // recalc software X and Y alias scale (this stuff is used only by HL software renderer but who knews...) + pixelAspect = ((float)scr_height->integer / (float)scr_width->integer); + if( scr_width->integer < 640 ) + pixelAspect *= (320.0f / 240.0f); + else pixelAspect *= (640.0f / 480.0f); + + aliasXscale = (float)scr_width->integer / RI.refdef.fov_y; + aliasYscale = aliasXscale * pixelAspect; +} /* =============== @@ -22,9 +47,7 @@ pfnGetCurrentEntity */ static cl_entity_t *pfnGetCurrentEntity( void ) { - // FIXME: implement - // this is will be needs is we called StudioDrawModel or StudioDrawPlayer - return NULL; + return RI.currententity; } /* @@ -72,7 +95,7 @@ pfnGetEngineTimes */ static void pfnGetEngineTimes( int *framecount, double *current, double *old ) { - if( framecount ) *framecount = host.framecount; // this is will not working properly with mirros etc + if( framecount ) *framecount = tr.framecount; if( current ) *current = cl.time; if( old ) *old = cl.oldtime; } @@ -85,10 +108,10 @@ pfnGetViewInfo */ static void pfnGetViewInfo( float *origin, float *upv, float *rightv, float *forwardv ) { - if( origin ) VectorCopy( cl.refdef.vieworg, origin ); - if( upv ) VectorCopy( cl.refdef.up, upv ); - if( rightv ) VectorCopy( cl.refdef.right, rightv ); - if( forwardv ) VectorCopy( cl.refdef.forward, forwardv ); + if( origin ) VectorCopy( RI.vieworg, origin ); + if( forwardv ) VectorCopy( RI.vforward, forwardv ); + if( rightv ) VectorCopy( RI.vright, rightv ); + if( upv ) VectorCopy( RI.vup, upv ); } /* @@ -123,13 +146,12 @@ static void pfnGetModelCounters( int **s, int **a ) =============== pfnGetAliasScale -Software scales not used in Xash3D =============== */ static void pfnGetAliasScale( float *x, float *y ) { - if( x ) *x = 0.0f; - if( y ) *y = 0.0f; + if( x ) *x = aliasXscale; + if( y ) *y = aliasYscale; } /* @@ -176,8 +198,7 @@ pfnStudioGetRotationMatrix */ static float ***pfnStudioGetRotationMatrix( void ) { - // FIXME: implement - return NULL; + return (float ***)g_rotationmatrix; } /* @@ -443,6 +464,51 @@ static void pfnStudioDrawShadow( void ) MsgDev( D_INFO, "GL_StudioDrawShadow()\n" ); // just a debug } +/* +=============== +R_StudioDrawModel + +=============== +*/ +static int R_StudioDrawModel( int flags ) +{ + return 0; +} + +/* +=============== +R_StudioDrawPlayer + +=============== +*/ +static int R_StudioDrawPlayer( int flags, entity_state_t *pplayer ) +{ + return 0; +} + +/* +================= +R_DrawStudioModel +================= +*/ +void R_DrawStudioModel( cl_entity_t *e ) +{ + int flags, result; + + ASSERT( pStudioDraw != NULL ); + + if( e == &clgame.viewent ) + flags = STUDIO_EVENTS; + else flags = STUDIO_RENDER|STUDIO_EVENTS; + + // select the properly method + if( e->player ) + result = pStudioDraw->StudioDrawPlayer( flags, &cl.frame.playerstate[e->index-1] ); + else result = pStudioDraw->StudioDrawModel( flags ); + + if( result ) r_stats.c_studio_models++; +} + void Mod_UnloadStudioModel( model_t *mod ) { studiohdr_t *pstudio; @@ -514,7 +580,13 @@ static engine_studio_api_t gStudioAPI = pfnIsHardware, pfnStudioDrawShadow, GL_SetRenderMode, +}; +static r_studio_interface_t gStudioDraw = +{ + STUDIO_INTERFACE_VERSION, + R_StudioDrawModel, + R_StudioDrawPlayer, }; /* @@ -526,11 +598,19 @@ Initialize client studio */ qboolean CL_InitStudioAPI( void ) { + pStudioDraw = &gStudioDraw; + // Xash will be used internal StudioModelRenderer if( !clgame.dllFuncs.pfnGetStudioModelInterface ) return true; - pStudioDraw = NULL; // clear previous API + if( clgame.dllFuncs.pfnGetStudioModelInterface( STUDIO_INTERFACE_VERSION, &pStudioDraw, &gStudioAPI )) + return true; - return clgame.dllFuncs.pfnGetStudioModelInterface( STUDIO_INTERFACE_VERSION, &pStudioDraw, &gStudioAPI ); + // NOTE: we always return true even if game interface was not correct + // because we need Draw our StudioModels + // just restore pointer to builtin function + pStudioDraw = &gStudioDraw; + + return true; } \ No newline at end of file diff --git a/engine/client/gl_vidnt.c b/engine/client/gl_vidnt.c index 7fc2d966..e61b001c 100644 --- a/engine/client/gl_vidnt.c +++ b/engine/client/gl_vidnt.c @@ -45,6 +45,8 @@ convar_t *r_speeds; convar_t *r_fullbright; convar_t *r_norefresh; convar_t *r_lighting_modulate; +convar_t *r_lighting_ambient; +convar_t *r_lighting_direct; convar_t *r_faceplanecull; convar_t *r_drawentities; convar_t *r_adjust_fov; @@ -1363,6 +1365,8 @@ void GL_InitCommands( void ) r_fullbright = Cvar_Get( "r_fullbright", "0", CVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); r_norefresh = Cvar_Get( "r_norefresh", "0", 0, "disable 3D rendering (use with caution)" ); r_lighting_modulate = Cvar_Get( "r_lighting_modulate", "0.6", CVAR_ARCHIVE, "lightstyles modulate scale" ); + r_lighting_ambient = Cvar_Get( "r_lighting_ambient", "0.6", 0, "map ambient lighting scale" ); + r_lighting_direct = Cvar_Get( "r_lighting_direct", "1", 0, "map directed lighting scale" ); r_adjust_fov = Cvar_Get( "r_adjust_fov", "1", CVAR_ARCHIVE, "making FOV adjustment for wide-screens" ); r_novis = Cvar_Get( "r_novis", "0", 0, "ignore vis information (perfomance test)" ); r_nocull = Cvar_Get( "r_nocull", "0", 0, "ignore frustrum culling (perfomance test)" ); @@ -1598,8 +1602,10 @@ qboolean R_Init( void ) GL_InitExtensions(); GL_SetDefaults(); + R_InitMathlib(); R_InitImages(); R_SpriteInit(); + R_StudioInit(); R_ClearScene(); GL_CheckForErrors(); diff --git a/engine/common/cm_local.h b/engine/common/cm_local.h index 6bc341e7..925475b0 100644 --- a/engine/common/cm_local.h +++ b/engine/common/cm_local.h @@ -35,6 +35,14 @@ typedef struct leaflist_s int topnode; // for overflows where each leaf can't be stored individually } leaflist_t; +typedef struct +{ + byte ambient[LM_STYLES][3]; + byte diffuse[LM_STYLES][3]; + byte styles[LM_STYLES]; + byte direction[2]; +} mgridlight_t; + typedef struct { int version; // map version @@ -44,6 +52,14 @@ typedef struct msurface_t **draw_surfaces; // used for sorting translucent surfaces int max_surfaces; // max surfaces per submodel (for all models) qboolean loading; // true is worldmodel is loading + + // lightgrid stuff + mgridlight_t *lightgrid; + int numgridpoints; + + vec3_t gridSize; + vec3_t gridMins; + int gridBounds[4]; } world_static_t; extern world_static_t world; diff --git a/engine/common/com_export.h b/engine/common/com_export.h index 0e0ad700..1cdacac6 100644 --- a/engine/common/com_export.h +++ b/engine/common/com_export.h @@ -83,7 +83,7 @@ void Mod_UnloadStudioModel( struct model_s *mod ); void Mod_UnloadBrushModel( struct model_s *mod ); void GL_SetRenderMode( int mode ); int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame ); -void R_LightForPoint( const vec3_t point, vec3_t ambientLight ); +void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight ); qboolean R_DecalShoot( int texture, int ent, int model, vec3_t pos, vec3_t saxis, int flags, rgba_t color ); void R_RemoveEfrags( struct cl_entity_s *ent ); void R_AddEfrags( struct cl_entity_s *ent ); diff --git a/engine/common/common.h b/engine/common/common.h index 5b53ddee..7b3fee5a 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -11,7 +11,6 @@ #include #include "launch_api.h" -#include "engine_api.h" #include "ref_params.h" #include "com_export.h" #include "com_model.h" @@ -33,11 +32,12 @@ // config strings are a general means of communication from // the server to all connected clients. // each config string can be at most CS_SIZE characters. -#define CS_SIZE 64 // size of one config string -#define CS_TIME 16 // size of time string +#define CS_SIZE 64 // size of one config string +#define CS_TIME 16 // size of time string -#define MAX_MSGLEN 32768 // max length of network message - // FIXME: replace with NET_MAX_PAYLOAD +#define MAX_DECALS 512 // touching TE_DECAL messages, etc +#define MAX_MSGLEN 32768 // max length of network message + // FIXME: replace with NET_MAX_PAYLOAD #ifdef _DEBUG void DBG_AssertFunction( qboolean fExpr, const char* szExpr, const char* szFile, int szLine, const char* szMessage ); @@ -208,7 +208,6 @@ void *pfnGetProcAddress( void *hInstance, const char *name ); void pfnFreeLibrary( void *hInstance ); long pfnRandomLong( long lLow, long lHigh ); float pfnRandomFloat( float flLow, float flHigh ); -void pfnVecToAngles( const float *rgflVectorIn, float *rgflVectorOut ); int pfnAddCommand( const char *cmd_name, xcommand_t func ); void pfnDelCommand( const char *cmd_name ); void *Cache_Check( byte *mempool, struct cache_user_s *c ); diff --git a/engine/common/engfuncs.c b/engine/common/engfuncs.c index 9381fa72..dda78098 100644 --- a/engine/common/engfuncs.c +++ b/engine/common/engfuncs.c @@ -287,44 +287,6 @@ float pfnRandomFloat( float flLow, float flHigh ) return Com_RandomFloat( flLow, flHigh ); } -/* -================= -pfnVecToAngles - -================= -*/ -void pfnVecToAngles( const float *rgflVectorIn, float *rgflVectorOut ) -{ - float tmp, yaw, pitch; - - if( !rgflVectorIn ) - { - if( rgflVectorOut ) VectorClear( rgflVectorOut ); - return; - } - - if( rgflVectorIn[1] == 0 && rgflVectorIn[0] == 0 ) - { - // fast case - yaw = 0; - if( rgflVectorIn[2] > 0 ) - pitch = 90; - else pitch = 270; - } - else - { - yaw = ( com.atan2( rgflVectorIn[1], rgflVectorIn[0] ) * 180 / M_PI ); - if( yaw < 0 ) yaw += 360; - - tmp = com.sqrt( rgflVectorIn[0] * rgflVectorIn[0] + rgflVectorIn[1] * rgflVectorIn[1] ); - pitch = ( com.atan2( rgflVectorIn[2], tmp ) * 180 / M_PI ); - if( pitch < 0 ) pitch += 360; - } - - if( rgflVectorOut ) VectorSet( rgflVectorOut, pitch, yaw, 0 ); - else MsgDev( D_ERROR, "SV_VecToAngles: no output vector specified\n" ); -} - /* ============= pfnTime diff --git a/engine/common/host.c b/engine/common/host.c index 99bcfb0c..dfefd0b2 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -5,6 +5,7 @@ #include "common.h" #include "netchan.h" +#include "protocol.h" #include "cm_local.h" #include "input.h" diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index d01e54e5..d7a9e1cd 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -108,6 +108,12 @@ void VectorVectors( vec3_t forward, vec3_t right, vec3_t up ) CrossProduct(right, forward, up); } +/* +================= +AngleVectors + +================= +*/ void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up ) { float sr, sp, sy, cr, cp, cy; @@ -138,6 +144,42 @@ void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up } } +/* +================= +VectorAngles + +================= +*/ +void VectorAngles( const float *forward, float *angles ) +{ + float tmp, yaw, pitch; + + if( !forward || !angles ) + { + if( angles ) VectorClear( angles ); + return; + } + + if( forward[1] == 0 && forward[0] == 0 ) + { + // fast case + yaw = 0; + if( forward[2] > 0 ) + pitch = 90.0f; + else pitch = 270.0f; + } + else + { + yaw = ( com.atan2( forward[1], forward[0] ) * 180 / M_PI ); + if( yaw < 0 ) yaw += 360; + + tmp = com.sqrt( forward[0] * forward[0] + forward[1] * forward[1] ); + pitch = ( com.atan2( forward[2], tmp ) * 180 / M_PI ); + if( pitch < 0 ) pitch += 360; + } + VectorSet( angles, pitch, yaw, 0 ); +} + // // bounds operations // diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 227dbc4b..2399ae56 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -90,6 +90,7 @@ int SignbitsForPlane( const vec3_t normal ); int NearestPOW( int value, qboolean roundDown ); float VectorNormalizeLength2( const vec3_t v, vec3_t out ); void VectorVectors( vec3_t forward, vec3_t right, vec3_t up ); +void VectorAngles( const float *forward, float *angles ); void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up ); void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ); @@ -102,6 +103,23 @@ float RadiusFromBounds( const vec3_t mins, const vec3_t maxs ); void AngleQuaternion( const vec3_t angles, vec4_t q ); void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ); -extern vec3_t vec3_origin; +// +// matrixlib.c +// +#define Matrix3x4_LoadIdentity( mat ) Matrix3x4_Copy( mat, matrix3x4_identity ) +#define Matrix3x4_Copy( out, in ) Mem_Copy( out, in, sizeof( matrix3x4 )) + +void Matrix3x4_VectorTransform( const matrix3x4 in, const float v[3], float out[3] ); +void Matrix3x4_VectorITransform( const matrix3x4 in, const float v[3], float out[3] ); +void Matrix3x4_VectorRotate( const matrix3x4 in, const float v[3], float out[3] ); +void Matrix3x4_VectorIRotate( const matrix3x4 in, const float v[3], float out[3] ); +void Matrix3x4_ConcatTransforms( matrix3x4 out, const matrix3x4 in1, const matrix3x4 in2 ); +void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec3_t origin ); +void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_t origin, float scale ); +void Matrix3x4_SetOrigin( matrix3x4 out, float x, float y, float z ); +void Matrix3x4_OriginFromMatrix( const matrix3x4 in, float *out ); + +extern vec3_t vec3_origin; +extern const matrix3x4 matrix3x4_identity; #endif//MATHLIB_H \ No newline at end of file diff --git a/engine/common/matrixlib.c b/engine/common/matrixlib.c new file mode 100644 index 00000000..ba0a088a --- /dev/null +++ b/engine/common/matrixlib.c @@ -0,0 +1,185 @@ +//======================================================================= +// Copyright XashXT Group 2010 © +// matrixlib.c - internal matrixlib +//======================================================================= + +#include "common.h" +#include "mathlib.h" + +const matrix3x4 matrix3x4_identity = +{ +{ 1, 0, 0, 0 }, // PITCH [forward], org[0] +{ 0, 1, 0, 0 }, // YAW [right] , org[1] +{ 0, 0, 1, 0 }, // ROLL [up] , org[2] +}; + +/* +======================================================================== + + Matrix3x4 operations + +======================================================================== +*/ +void Matrix3x4_VectorTransform( const matrix3x4 in, const float v[3], float out[3] ) +{ + out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3]; + out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3]; + out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3]; +} + +void Matrix3x4_VectorITransform( const matrix3x4 in, const float v[3], float out[3] ) +{ + float dir[3]; + + dir[0] = v[0] - in[0][3]; + dir[1] = v[1] - in[1][3]; + dir[2] = v[2] - in[2][3]; + + out[0] = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0]; + out[1] = dir[0] * in[0][1] + dir[1] * in[1][1] + dir[2] * in[2][1]; + out[2] = dir[0] * in[0][2] + dir[1] * in[1][2] + dir[2] * in[2][2]; +} + +void Matrix3x4_VectorRotate( const matrix3x4 in, const float v[3], float out[3] ) +{ + out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2]; + out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2]; + out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2]; +} + +void Matrix3x4_VectorIRotate( const matrix3x4 in, const float v[3], float out[3] ) +{ + out[0] = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0]; + out[1] = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1]; + out[2] = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2]; +} + +void Matrix3x4_ConcatTransforms( matrix3x4 out, const matrix3x4 in1, const matrix3x4 in2 ) +{ + out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0]; + out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1]; + out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2]; + out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3]; + out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0]; + out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1]; + out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2]; + out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3]; + out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0]; + out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1]; + out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2]; + out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3]; +} + +void Matrix3x4_SetOrigin( matrix3x4 out, float x, float y, float z ) +{ + out[0][3] = x; + out[1][3] = y; + out[2][3] = z; +} + +void Matrix3x4_OriginFromMatrix( const matrix3x4 in, float *out ) +{ + out[0] = in[0][3]; + out[1] = in[1][3]; + out[2] = in[2][3]; +} + +void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec3_t origin ) +{ + out[0][0] = 1.0f - 2.0f * quaternion[1] * quaternion[1] - 2.0f * quaternion[2] * quaternion[2]; + out[1][0] = 2.0f * quaternion[0] * quaternion[1] + 2.0f * quaternion[3] * quaternion[2]; + out[2][0] = 2.0f * quaternion[0] * quaternion[2] - 2.0f * quaternion[3] * quaternion[1]; + + out[0][1] = 2.0f * quaternion[0] * quaternion[1] - 2.0f * quaternion[3] * quaternion[2]; + out[1][1] = 1.0f - 2.0f * quaternion[0] * quaternion[0] - 2.0f * quaternion[2] * quaternion[2]; + out[2][1] = 2.0f * quaternion[1] * quaternion[2] + 2.0f * quaternion[3] * quaternion[0]; + + out[0][2] = 2.0f * quaternion[0] * quaternion[2] + 2.0f * quaternion[3] * quaternion[1]; + out[1][2] = 2.0f * quaternion[1] * quaternion[2] - 2.0f * quaternion[3] * quaternion[0]; + out[2][2] = 1.0f - 2.0f * quaternion[0] * quaternion[0] - 2.0f * quaternion[1] * quaternion[1]; + + out[0][3] = origin[0]; + out[1][3] = origin[1]; + out[2][3] = origin[2]; +} + +void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_t origin, float scale ) +{ + float angle, sr, sp, sy, cr, cp, cy; + + if( angles[ROLL] ) + { + angle = angles[YAW] * (M_PI*2 / 360); + com.sincos( angle, &sy, &cy ); + angle = angles[PITCH] * (M_PI*2 / 360); + com.sincos( angle, &sp, &cp ); + angle = angles[ROLL] * (M_PI*2 / 360); + com.sincos( angle, &sr, &cr ); + + out[0][0] = (cp*cy) * scale; + out[0][1] = (sr*sp*cy+cr*-sy) * scale; + out[0][2] = (cr*sp*cy+-sr*-sy) * scale; + out[0][3] = origin[0]; + out[1][0] = (cp*sy) * scale; + out[1][1] = (sr*sp*sy+cr*cy) * scale; + out[1][2] = (cr*sp*sy+-sr*cy) * scale; + out[1][3] = origin[1]; + out[2][0] = (-sp) * scale; + out[2][1] = (sr*cp) * scale; + out[2][2] = (cr*cp) * scale; + out[2][3] = origin[2]; + } + else if( angles[PITCH] ) + { + angle = angles[YAW] * (M_PI*2 / 360); + com.sincos( angle, &sy, &cy ); + angle = angles[PITCH] * (M_PI*2 / 360); + com.sincos( angle, &sp, &cp ); + + out[0][0] = (cp*cy) * scale; + out[0][1] = (-sy) * scale; + out[0][2] = (sp*cy) * scale; + out[0][3] = origin[0]; + out[1][0] = (cp*sy) * scale; + out[1][1] = (cy) * scale; + out[1][2] = (sp*sy) * scale; + out[1][3] = origin[1]; + out[2][0] = (-sp) * scale; + out[2][1] = 0; + out[2][2] = (cp) * scale; + out[2][3] = origin[2]; + } + else if( angles[YAW] ) + { + angle = angles[YAW] * (M_PI*2 / 360); + com.sincos( angle, &sy, &cy ); + + out[0][0] = (cy) * scale; + out[0][1] = (-sy) * scale; + out[0][2] = 0; + out[0][3] = origin[0]; + out[1][0] = (sy) * scale; + out[1][1] = (cy) * scale; + out[1][2] = 0; + out[1][3] = origin[1]; + out[2][0] = 0; + out[2][1] = 0; + out[2][2] = scale; + out[2][3] = origin[2]; + } + else + { + out[0][0] = scale; + out[0][1] = 0; + out[0][2] = 0; + out[0][3] = origin[0]; + out[1][0] = 0; + out[1][1] = scale; + out[1][2] = 0; + out[1][3] = origin[1]; + out[2][0] = 0; + out[2][1] = 0; + out[2][2] = scale; + out[2][3] = origin[2]; + } +} \ No newline at end of file diff --git a/engine/common/net_buffer.c b/engine/common/net_buffer.c index fc9b8ffc..fc8b0e56 100644 --- a/engine/common/net_buffer.c +++ b/engine/common/net_buffer.c @@ -4,6 +4,7 @@ //======================================================================= #include "common.h" +#include "protocol.h" #include "net_buffer.h" // precalculated bit masks for WriteUBitLong. diff --git a/engine/common/protocol.h b/engine/common/protocol.h index b5a7e2e3..bfa67d1c 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -84,10 +84,22 @@ #define MAX_EVENT_BITS 10 #define MAX_EVENTS (1<value < 256.0f ) Cvar_SetFloat( "sv_zmax", 256.0f ); - if( sv_zmax->value > 8192.0f ) Cvar_SetFloat( "sv_zmax", 8192.0f ); + if( sv_zmax->value > 32767.0f ) Cvar_SetFloat( "sv_zmax", 32767.0f ); svgame.movevars.gravity = sv_gravity->value; svgame.movevars.stopspeed = sv_stopspeed->value; diff --git a/engine/server/sv_studio.c b/engine/server/sv_studio.c index f92dbb4a..e1574821 100644 --- a/engine/server/sv_studio.c +++ b/engine/server/sv_studio.c @@ -926,7 +926,7 @@ trace_t SV_TraceHitbox( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t ma void SV_StudioGetAttachment( edict_t *e, int iAttachment, float *org, float *ang ) { mstudioattachment_t *pAtt; - vec3_t axis[3], bonepos; + vec3_t forward, bonepos; vec3_t localOrg, localAng; void *hdr; @@ -953,10 +953,9 @@ void SV_StudioGetAttachment( edict_t *e, int iAttachment, float *org, float *ang // compute pos and angles Matrix4x4_VectorTransform( sv_studiobones[pAtt[iAttachment].bone], pAtt[iAttachment].org, localOrg ); Matrix4x4_OriginFromMatrix( sv_studiobones[pAtt[iAttachment].bone], bonepos ); - VectorSubtract( localOrg, bonepos, axis[0] ); // make forward - VectorNormalizeFast( axis[0] ); - VectorVectors( axis[0], axis[1], axis[2] ); // make right and up - Matrix3x3_ToAngles( axis, localAng, false ); // FIXME: dll's uses FLU ? + VectorSubtract( localOrg, bonepos, forward ); // make forward + VectorNormalizeFast( forward ); + VectorAngles( forward, localAng ); if( org ) VectorCopy( localOrg, org ); if( ang ) VectorCopy( localAng, ang ); diff --git a/launch/system.c b/launch/system.c index fa72bf43..dab1e89e 100644 --- a/launch/system.c +++ b/launch/system.c @@ -6,7 +6,6 @@ #include "launch.h" #include "library.h" -#include "engine_api.h" #include "mathlib.h" #define MAX_QUED_EVENTS 256 diff --git a/launch/tools/tools.c b/launch/tools/tools.c index 324e542b..c84b4c20 100644 --- a/launch/tools/tools.c +++ b/launch/tools/tools.c @@ -6,7 +6,6 @@ #include "launch.h" #include "utils.h" #include "mdllib.h" -#include "engine_api.h" #include "mathlib.h" #include "badimage.h" diff --git a/public/engine_api.h b/public/engine_api.h deleted file mode 100644 index 5db886fe..00000000 --- a/public/engine_api.h +++ /dev/null @@ -1,56 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2008 © -// engine_api.h - xash engine api -//======================================================================= -#ifndef ENGINE_API_H -#define ENGINE_API_H - -#include "const.h" - -// -// engine constant limits, touching networking protocol modify with precaution -// -#define MAX_MODEL_BITS 11 -#define MAX_MODELS (1< ############################################################################### -Project: "vid_gl"=".\vid_gl\vid_gl.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - Global: Package=<5>