/* * GClip_SetBrushModel * * Also sets mins and maxs for inline bmodels */ void GClip_SetBrushModel( edict_t *ent, char *name ) { struct cmodel_s *cmodel; if( !name ) { //racesow G_Printf( "Warning: GClip_SetBrushModel: NULL model in '%s'", ent->classname ? ent->classname : "no classname\n" ); GClip_UnlinkEntity( ent ); G_FreeEdict( ent ); return; //!racesow } if( !name[0] ) { ent->s.modelindex = 0; return; } if( name[0] != '*' ) { ent->s.modelindex = trap_ModelIndex( name ); return; } // if it is an inline model, get the size information for it // world model is special if( !strcmp( name, "*0" ) ) { ent->s.modelindex = 0; cmodel = trap_CM_InlineModel( 0 ); trap_CM_InlineModelBounds( cmodel, ent->r.mins, ent->r.maxs ); return; } // racesow: THIS IS A VERY DIRTY "FIX": it assigns normally unreachable models (the ones over MAX_MODELS) to unrelated models.. // normally this only affects buggy maps that otherwise wouldn't load (like amt-freestyle3) // brush model //ent->s.modelindex = trap_ModelIndex( name ); // <- This is the unmodified version ent->s.modelindex = atoi( name+1 ); // !racesow assert( ent->s.modelindex == (unsigned int)atoi( name + 1 ) ); cmodel = trap_CM_InlineModel( ent->s.modelindex ); trap_CM_InlineModelBounds( cmodel, ent->r.mins, ent->r.maxs ); GClip_LinkEntity( ent ); }
/* * CG_DemoCam_LookAt */ bool CG_DemoCam_LookAt( int trackEnt, vec3_t vieworg, vec3_t viewangles ) { centity_t *cent; vec3_t dir; vec3_t origin; struct cmodel_s *cmodel; int i; if( trackEnt < 1 || trackEnt >= MAX_EDICTS ) { return false; } cent = &cg_entities[trackEnt]; if( cent->serverFrame != cg.frame.serverFrame ) { return false; } // seems to be valid. Find the angles to look at this entity VectorLerp( cent->prev.origin, cg.lerpfrac, cent->current.origin, origin ); // if having a bounding box, look to its center if( ( cmodel = CG_CModelForEntity( trackEnt ) ) != NULL ) { vec3_t mins, maxs; trap_CM_InlineModelBounds( cmodel, mins, maxs ); for( i = 0; i < 3; i++ ) origin[i] += ( mins[i] + maxs[i] ); } VectorSubtract( origin, vieworg, dir ); VectorNormalize( dir ); VecToAngles( dir, viewangles ); return true; }
/* * GClip_SetBrushModel * * Also sets mins and maxs for inline bmodels */ void GClip_SetBrushModel( edict_t *ent, const char *name ) { struct cmodel_s *cmodel; if( !name ) { G_Error( "GClip_SetBrushModel: NULL model in '%s'", ent->classname ? ent->classname : "no classname" ); // racesow GClip_UnlinkEntity( ent ); G_FreeEdict( ent ); return; // !racesow } if( !name[0] ) { ent->s.modelindex = 0; return; } if( name[0] != '*' ) { ent->s.modelindex = trap_ModelIndex( name ); return; } // if it is an inline model, get the size information for it // world model is special if( !strcmp( name, "*0" ) ) { ent->s.modelindex = 0; cmodel = trap_CM_InlineModel( 0 ); trap_CM_InlineModelBounds( cmodel, ent->r.mins, ent->r.maxs ); return; } // brush model ent->s.modelindex = trap_ModelIndex( name ); assert( ent->s.modelindex == (unsigned int)atoi( name + 1 ) ); cmodel = trap_CM_InlineModel( ent->s.modelindex ); trap_CM_InlineModelBounds( cmodel, ent->r.mins, ent->r.maxs ); GClip_LinkEntity( ent ); }
/* * GClip_ClearWorld * called after the world model has been loaded, before linking any entities */ void GClip_ClearWorld( void ) { vec3_t world_mins, world_maxs; struct cmodel_s *world_model; world_model = trap_CM_InlineModel( 0 ); trap_CM_InlineModelBounds( world_model, world_mins, world_maxs ); GClip_Init_AreaGrid( &g_areagrid, world_mins, world_maxs ); }
/* * GClip_ClearWorld * called after the world model has been loaded, before linking any entities */ void GClip_ClearWorld( void ) { vec3_t mins, maxs; struct cmodel_s *cmodel; memset( sv_areanodes, 0, sizeof( sv_areanodes ) ); sv_numareanodes = 0; cmodel = trap_CM_InlineModel( 0 ); trap_CM_InlineModelBounds( cmodel, mins, maxs ); GClip_CreateAreaNode( 0, mins, maxs ); }
/* * CG_Democam_CalcView */ static int CG_Democam_CalcView( void ) { int i, viewType; float lerpfrac; vec3_t v; viewType = VIEWDEF_PLAYERVIEW; VectorClear( cam_velocity ); if( currentcam ) { if( !nextcam ) { lerpfrac = 0; } else { lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp ); } switch( currentcam->type ) { case DEMOCAM_FIRSTPERSON: VectorCopy( cg.view.origin, cam_origin ); VectorCopy( cg.view.angles, cam_angles ); VectorCopy( cg.view.velocity, cam_velocity ); cam_fov = cg.view.fov_y; break; case DEMOCAM_THIRDPERSON: VectorCopy( cg.view.origin, cam_origin ); VectorCopy( cg.view.angles, cam_angles ); VectorCopy( cg.view.velocity, cam_velocity ); cam_fov = cg.view.fov_y; cam_3dPerson = true; break; case DEMOCAM_POSITIONAL: viewType = VIEWDEF_DEMOCAM; cam_POVent = 0; VectorCopy( currentcam->origin, cam_origin ); if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) { VectorCopy( currentcam->angles, cam_angles ); } cam_fov = currentcam->fov; break; case DEMOCAM_PATH_LINEAR: viewType = VIEWDEF_DEMOCAM; cam_POVent = 0; VectorCopy( cam_origin, v ); if( !nextcam || nextcam->type == DEMOCAM_FIRSTPERSON || nextcam->type == DEMOCAM_THIRDPERSON ) { CG_Printf( "Warning: CG_DemoCam: path_linear cam without a valid next cam\n" ); VectorCopy( currentcam->origin, cam_origin ); if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) { VectorCopy( currentcam->angles, cam_angles ); } cam_fov = currentcam->fov; } else { VectorLerp( currentcam->origin, lerpfrac, nextcam->origin, cam_origin ); if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) { for( i = 0; i < 3; i++ ) cam_angles[i] = LerpAngle( currentcam->angles[i], nextcam->angles[i], lerpfrac ); } cam_fov = (float)currentcam->fov + (float)( nextcam->fov - currentcam->fov ) * lerpfrac; } // set velocity VectorSubtract( cam_origin, v, cam_velocity ); VectorScale( cam_velocity, 1.0f / (float)cg.frameTime, cam_velocity ); break; case DEMOCAM_PATH_SPLINE: viewType = VIEWDEF_DEMOCAM; cam_POVent = 0; clamp( lerpfrac, 0, 1 ); VectorCopy( cam_origin, v ); if( !nextcam || nextcam->type == DEMOCAM_FIRSTPERSON || nextcam->type == DEMOCAM_THIRDPERSON ) { CG_Printf( "Warning: CG_DemoCam: path_spline cam without a valid next cam\n" ); VectorCopy( currentcam->origin, cam_origin ); if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) { VectorCopy( currentcam->angles, cam_angles ); } cam_fov = currentcam->fov; } else { // valid spline path #define VectorHermiteInterp( a, at, b, bt, c, v ) ( ( v )[0] = ( 2 * pow( c, 3 ) - 3 * pow( c, 2 ) + 1 ) * a[0] + ( pow( c, 3 ) - 2 * pow( c, 2 ) + c ) * 2 * at[0] + ( -2 * pow( c, 3 ) + 3 * pow( c, 2 ) ) * b[0] + ( pow( c, 3 ) - pow( c, 2 ) ) * 2 * bt[0], ( v )[1] = ( 2 * pow( c, 3 ) - 3 * pow( c, 2 ) + 1 ) * a[1] + ( pow( c, 3 ) - 2 * pow( c, 2 ) + c ) * 2 * at[1] + ( -2 * pow( c, 3 ) + 3 * pow( c, 2 ) ) * b[1] + ( pow( c, 3 ) - pow( c, 2 ) ) * 2 * bt[1], ( v )[2] = ( 2 * pow( c, 3 ) - 3 * pow( c, 2 ) + 1 ) * a[2] + ( pow( c, 3 ) - 2 * pow( c, 2 ) + c ) * 2 * at[2] + ( -2 * pow( c, 3 ) + 3 * pow( c, 2 ) ) * b[2] + ( pow( c, 3 ) - pow( c, 2 ) ) * 2 * bt[2] ) float lerpspline, A, B, C, n1, n2, n3; cg_democam_t *previouscam = NULL; cg_democam_t *secondnextcam = NULL; if( nextcam ) { secondnextcam = CG_Democam_FindNext( nextcam->timeStamp ); } if( currentcam->timeStamp > 0 ) { previouscam = CG_Democam_FindCurrent( currentcam->timeStamp - 1 ); } if( !previouscam && nextcam && !secondnextcam ) { lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp ); lerpspline = lerpfrac; } else if( !previouscam && nextcam && secondnextcam ) { n1 = nextcam->timeStamp - currentcam->timeStamp; n2 = secondnextcam->timeStamp - nextcam->timeStamp; A = n1 * ( n1 - n2 ) / ( pow( n1, 2 ) + n1 * n2 - n1 - n2 ); B = ( 2 * n1 * n2 - n1 - n2 ) / ( pow( n1, 2 ) + n1 * n2 - n1 - n2 ); lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp ); lerpspline = A * pow( lerpfrac, 2 ) + B * lerpfrac; } else if( previouscam && nextcam && !secondnextcam ) { n2 = currentcam->timeStamp - previouscam->timeStamp; n3 = nextcam->timeStamp - currentcam->timeStamp; A = n3 * ( n2 - n3 ) / ( -n2 - n3 + n2 * n3 + pow( n3, 2 ) ); B = -1 / ( -n2 - n3 + n2 * n3 + pow( n3, 2 ) ) * ( n2 + n3 - 2 * pow( n3, 2 ) ); lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp ); lerpspline = A * pow( lerpfrac, 2 ) + B * lerpfrac; } else if( previouscam && nextcam && secondnextcam ) { n1 = currentcam->timeStamp - previouscam->timeStamp; n2 = nextcam->timeStamp - currentcam->timeStamp; n3 = secondnextcam->timeStamp - nextcam->timeStamp; A = -2 * pow( n2, 2 ) * ( -pow( n2, 2 ) + n1 * n3 ) / ( 2 * n2 * n3 + pow( n2, 3 ) * n3 - 3 * pow( n2, 2 ) * n1 + n1 * pow( n2, 3 ) + 2 * n1 * n2 - 3 * pow( n2, 2 ) * n3 - 3 * pow( n2, 3 ) + 2 * pow( n2, 2 ) + pow( n2, 4 ) + n1 * pow( n2, 2 ) * n3 - 3 * n1 * n2 * n3 + 2 * n1 * n3 ); B = pow( n2, 2 ) * ( -2 * n1 - 3 * pow( n2, 2 ) - n2 * n3 + 2 * n3 + 3 * n1 * n3 + n1 * n2 ) / ( 2 * n2 * n3 + pow( n2, 3 ) * n3 - 3 * pow( n2, 2 ) * n1 + n1 * pow( n2, 3 ) + 2 * n1 * n2 - 3 * pow( n2, 2 ) * n3 - 3 * pow( n2, 3 ) + 2 * pow( n2, 2 ) + pow( n2, 4 ) + n1 * pow( n2, 2 ) * n3 - 3 * n1 * n2 * n3 + 2 * n1 * n3 ); C = -( pow( n2, 2 ) * n1 - 2 * n1 * n2 + 3 * n1 * n2 * n3 - 2 * n1 * n3 - 2 * pow( n2, 4 ) + 3 * pow( n2, 3 ) - 2 * pow( n2, 3 ) * n3 + 5 * pow( n2, 2 ) * n3 - 2 * pow( n2, 2 ) - 2 * n2 * n3 ) / ( 2 * n2 * n3 + pow( n2, 3 ) * n3 - 3 * pow( n2, 2 ) * n1 + n1 * pow( n2, 3 ) + 2 * n1 * n2 - 3 * pow( n2, 2 ) * n3 - 3 * pow( n2, 3 ) + 2 * pow( n2, 2 ) + pow( n2, 4 ) + n1 * pow( n2, 2 ) * n3 - 3 * n1 * n2 * n3 + 2 * n1 * n3 ); lerpfrac = (float)( demo_time - currentcam->timeStamp ) / (float)( nextcam->timeStamp - currentcam->timeStamp ); lerpspline = A * pow( lerpfrac, 3 ) + B * pow( lerpfrac, 2 ) + C * lerpfrac; } else { lerpfrac = 0; lerpspline = 0; } VectorHermiteInterp( currentcam->origin, currentcam->tangent, nextcam->origin, nextcam->tangent, lerpspline, cam_origin ); if( !CG_DemoCam_LookAt( currentcam->trackEnt, cam_origin, cam_angles ) ) { VectorHermiteInterp( currentcam->angles, currentcam->angles_tangent, nextcam->angles, nextcam->angles_tangent, lerpspline, cam_angles ); } cam_fov = (float)currentcam->fov + (float)( nextcam->fov - currentcam->fov ) * lerpfrac; #undef VectorHermiteInterp } // set velocity VectorSubtract( cam_origin, v, cam_velocity ); VectorScale( cam_velocity, 1.0f / (float)cg.frameTime, cam_velocity ); break; case DEMOCAM_ORBITAL: viewType = VIEWDEF_DEMOCAM; cam_POVent = 0; cam_fov = currentcam->fov; VectorCopy( cam_origin, v ); if( !currentcam->trackEnt || currentcam->trackEnt >= MAX_EDICTS ) { CG_Printf( "Warning: CG_DemoCam: orbital cam needs a track entity set\n" ); VectorCopy( currentcam->origin, cam_origin ); VectorClear( cam_angles ); VectorClear( cam_velocity ); } else { vec3_t center, forward; struct cmodel_s *cmodel; const float ft = (float)cg.frameTime * 0.001f; // find the trackEnt origin VectorLerp( cg_entities[currentcam->trackEnt].prev.origin, cg.lerpfrac, cg_entities[currentcam->trackEnt].current.origin, center ); // if having a bounding box, look to its center if( ( cmodel = CG_CModelForEntity( currentcam->trackEnt ) ) != NULL ) { vec3_t mins, maxs; trap_CM_InlineModelBounds( cmodel, mins, maxs ); for( i = 0; i < 3; i++ ) center[i] += ( mins[i] + maxs[i] ); } if( !cam_orbital_radius ) { // cam is just started, find distance from cam to trackEnt and keep it as radius VectorSubtract( currentcam->origin, center, forward ); cam_orbital_radius = VectorNormalize( forward ); VecToAngles( forward, cam_orbital_angles ); } for( i = 0; i < 3; i++ ) { cam_orbital_angles[i] += currentcam->angles[i] * ft; cam_orbital_angles[i] = AngleNormalize360( cam_orbital_angles[i] ); } AngleVectors( cam_orbital_angles, forward, NULL, NULL ); VectorMA( center, cam_orbital_radius, forward, cam_origin ); // lookat VectorInverse( forward ); VecToAngles( forward, cam_angles ); } // set velocity VectorSubtract( cam_origin, v, cam_velocity ); VectorScale( cam_velocity, 1.0f / ( cg.frameTime * 1000.0f ), cam_velocity ); break; default: break; } if( currentcam->type != DEMOCAM_ORBITAL ) { VectorClear( cam_orbital_angles ); cam_orbital_radius = 0; } } return viewType; }