/* * CG_ViewWeapon_UpdateProjectionSource */ static void CG_ViewWeapon_UpdateProjectionSource( vec3_t hand_origin, mat3_t hand_axis, vec3_t weap_origin, mat3_t weap_axis ) { orientation_t *tag_result = &cg.weapon.projectionSource; orientation_t tag_weapon; weaponinfo_t *weaponInfo; VectorCopy( vec3_origin, tag_weapon.origin ); Matrix3_Copy( axis_identity, tag_weapon.axis ); // move to tag_weapon CG_MoveToTag( tag_weapon.origin, tag_weapon.axis, hand_origin, hand_axis, weap_origin, weap_axis ); weaponInfo = CG_GetWeaponInfo( cg.weapon.weapon ); // move to projectionSource tag if( weaponInfo ) { VectorCopy( vec3_origin, tag_result->origin ); Matrix3_Copy( axis_identity, tag_result->axis ); CG_MoveToTag( tag_result->origin, tag_result->axis, tag_weapon.origin, tag_weapon.axis, weaponInfo->tag_projectionsource.origin, weaponInfo->tag_projectionsource.axis ); return; } // fall back: copy gun origin and move it front by 16 units and 8 up VectorCopy( tag_weapon.origin, tag_result->origin ); Matrix3_Copy( tag_weapon.axis, tag_result->axis ); VectorMA( tag_result->origin, 16, &tag_result->axis[AXIS_FORWARD], tag_result->origin ); VectorMA( tag_result->origin, 8, &tag_result->axis[AXIS_UP], tag_result->origin ); }
/* * CG_PModel_SpawnTeleportEffect */ void CG_PModel_SpawnTeleportEffect( centity_t *cent ) { // the thing is, we must have a built skeleton, so we // can run all bones and spawn a polygon at their origin int i, j; cgs_skeleton_t *skel; orientation_t orient, ref; float radius = 5; lentity_t *le; vec3_t vec, teleportOrigin; skel = CG_SkeletonForModel( cent->ent.model ); if( !skel || !cent->ent.boneposes ) return; for( j = LOCALEFFECT_EV_PLAYER_TELEPORT_IN; j <= LOCALEFFECT_EV_PLAYER_TELEPORT_OUT; j++ ) { if( cent->localEffects[j] ) { cent->localEffects[j] = 0; if( j == LOCALEFFECT_EV_PLAYER_TELEPORT_OUT ) VectorCopy( cent->teleportedFrom, teleportOrigin ); else VectorCopy( cent->ent.origin, teleportOrigin ); for( i = 0; i < skel->numBones; i++ ) { DualQuat_ToMatrixAndVector( cent->ent.boneposes[i].dualquat, orient.axis, orient.origin ); VectorCopy( vec3_origin, ref.origin ); Matrix_Copy( axis_identity, ref.axis ); CG_MoveToTag( ref.origin, ref.axis, teleportOrigin, cent->ent.axis, orient.origin, orient.axis ); VectorSet( vec, 0.1f, 0.1f, 0.1f ); // spawn a sprite at each bone le = CG_AllocSprite( LE_SCALE_ALPHA_FADE, ref.origin, radius, 15 + crandom()*5, 1, 1, 1, 0.5f, 0, 0, 0, 0, CG_MediaShader( cgs.media.shaderTeleporterSmokePuff ) ); VectorSet( le->velocity, -vec[0] * 5 + crandom()*5, -vec[1] * 5 + crandom()*5, -vec[2] * 5 + crandom()*5 + 3 ); le->ent.rotation = rand() % 360; // CG_ParticleEffect( ref.origin, ref.axis[2], 0.9f, 0.9f, 0.9f, 2 ); } } } }
/* * CG_BuildProjectionOrigin * store the orientation_t closer to the tag_flash we can create, * or create one using an offset we consider acceptable. * NOTE: This tag will ignore weapon models animations. You'd have to * do it in realtime to use it with animations. Or be careful on not * moving the weapon too much */ static void CG_BuildProjectionOrigin( weaponinfo_t *weaponinfo ) { orientation_t tag, tag_barrel; static entity_t ent; if( !weaponinfo ) return; if( weaponinfo->model[WEAPON] ) { // assign the model to an entity_t, so we can build boneposes memset( &ent, 0, sizeof( ent ) ); ent.rtype = RT_MODEL; ent.scale = 1.0f; ent.model = weaponinfo->model[WEAPON]; CG_SetBoneposesForTemporaryEntity( &ent ); // assigns and builds the skeleton so we can use grabtag // try getting the tag_flash from the weapon model if( CG_GrabTag( &weaponinfo->tag_projectionsource, &ent, "tag_flash" ) ) return; // succesfully // if it didn't work, try getting it from the barrel model if( CG_GrabTag( &tag_barrel, &ent, "tag_barrel" ) && weaponinfo->model[BARREL] ) { // assign the model to an entity_t, so we can build boneposes memset( &ent, 0, sizeof( ent ) ); ent.rtype = RT_MODEL; ent.scale = 1.0f; ent.model = weaponinfo->model[BARREL]; CG_SetBoneposesForTemporaryEntity( &ent ); if( CG_GrabTag( &tag, &ent, "tag_flash" ) && weaponinfo->model[BARREL] ) { VectorCopy( vec3_origin, weaponinfo->tag_projectionsource.origin ); Matrix3_Identity( weaponinfo->tag_projectionsource.axis ); CG_MoveToTag( weaponinfo->tag_projectionsource.origin, weaponinfo->tag_projectionsource.axis, tag_barrel.origin, tag_barrel.axis, tag.origin, tag.axis ); return; // succesfully } } } // doesn't have a weapon model, or the weapon model doesn't have a tag VectorSet( weaponinfo->tag_projectionsource.origin, 16, 0, 8 ); Matrix3_Identity( weaponinfo->tag_projectionsource.axis ); }
/* * CG_AddWeaponOnTag * * Add weapon model(s) positioned at the tag */ void CG_AddWeaponOnTag( entity_t *ent, orientation_t *tag, int weaponid, int effects, orientation_t *projectionSource, unsigned int flash_time, unsigned int barrel_time ) { entity_t weapon; weaponinfo_t *weaponInfo; float intensity; //don't try without base model if( !ent->model ) return; //don't try without a tag if( !tag ) return; weaponInfo = CG_GetWeaponInfo( weaponid ); if( !weaponInfo ) return; //if( ent->renderfx & RF_WEAPONMODEL ) // effects &= ~EF_RACEGHOST; //weapon memset( &weapon, 0, sizeof( weapon ) ); Vector4Set( weapon.shaderRGBA, 255, 255, 255, 255 ); weapon.scale = ent->scale; weapon.renderfx = ent->renderfx; weapon.frame = 0; weapon.oldframe = 0; weapon.model = weaponInfo->model[WEAPON]; CG_PlaceModelOnTag( &weapon, ent, tag ); CG_AddColoredOutLineEffect( &weapon, effects, 0, 0, 0, 255 ); if( !( effects & EF_RACEGHOST ) ) CG_AddEntityToScene( &weapon ); if( !weapon.model ) return; CG_AddShellEffects( &weapon, effects ); // update projection source if( projectionSource != NULL ) { VectorCopy( vec3_origin, projectionSource->origin ); Matrix3_Copy( axis_identity, projectionSource->axis ); CG_MoveToTag( projectionSource->origin, projectionSource->axis, weapon.origin, weapon.axis, weaponInfo->tag_projectionsource.origin, weaponInfo->tag_projectionsource.axis ); } //expansion if( ( effects & EF_STRONG_WEAPON ) && weaponInfo->model[EXPANSION] ) { if( CG_GrabTag( tag, &weapon, "tag_expansion" ) ) { entity_t expansion; memset( &expansion, 0, sizeof( expansion ) ); Vector4Set( expansion.shaderRGBA, 255, 255, 255, 255 ); expansion.model = weaponInfo->model[EXPANSION]; expansion.scale = ent->scale; expansion.renderfx = ent->renderfx; expansion.frame = 0; expansion.oldframe = 0; CG_PlaceModelOnTag( &expansion, &weapon, tag ); CG_AddColoredOutLineEffect( &expansion, effects, 0, 0, 0, 255 ); if( !( effects & EF_RACEGHOST ) ) CG_AddEntityToScene( &expansion ); // skelmod CG_AddShellEffects( &expansion, effects ); } } // barrel if( weaponInfo->model[BARREL] ) { if( CG_GrabTag( tag, &weapon, "tag_barrel" ) ) { orientation_t barrel_recoiled; vec3_t rotangles = { 0, 0, 0 }; entity_t barrel; memset( &barrel, 0, sizeof( barrel ) ); Vector4Set( barrel.shaderRGBA, 255, 255, 255, 255 ); barrel.model = weaponInfo->model[BARREL]; barrel.scale = ent->scale; barrel.renderfx = ent->renderfx; barrel.frame = 0; barrel.oldframe = 0; // rotation if( barrel_time > cg.time ) { intensity = (float)( barrel_time - cg.time ) / (float)weaponInfo->barrelTime; rotangles[2] = ( 360.0f * weaponInfo->barrelSpeed * intensity * intensity ); while( rotangles[2] > 360 ) rotangles[2] -= 360; // Check for tag_recoil if( CG_GrabTag( &barrel_recoiled, &weapon, "tag_recoil" ) ) VectorLerp( tag->origin, intensity, barrel_recoiled.origin, tag->origin ); } AnglesToAxis( rotangles, barrel.axis ); // barrel requires special tagging CG_PlaceRotatedModelOnTag( &barrel, &weapon, tag ); CG_AddColoredOutLineEffect( &barrel, effects, 0, 0, 0, 255 ); if( !( effects & EF_RACEGHOST ) ) CG_AddEntityToScene( &barrel ); // skelmod CG_AddShellEffects( &barrel, effects ); } } if( flash_time < cg.time ) return; // flash if( !CG_GrabTag( tag, &weapon, "tag_flash" ) ) return; if( weaponInfo->model[FLASH] ) { entity_t flash; qbyte c; if( weaponInfo->flashFade ) { intensity = (float)( flash_time - cg.time )/(float)weaponInfo->flashTime; c = ( qbyte )( 255 * intensity ); } else { intensity = 1.0f; c = 255; } memset( &flash, 0, sizeof( flash ) ); Vector4Set( flash.shaderRGBA, c, c, c, c ); flash.model = weaponInfo->model[FLASH]; flash.scale = ent->scale; flash.renderfx = ent->renderfx | RF_NOSHADOW; flash.frame = 0; flash.oldframe = 0; CG_PlaceModelOnTag( &flash, &weapon, tag ); if( !( effects & EF_RACEGHOST ) ) CG_AddEntityToScene( &flash ); CG_AddLightToScene( flash.origin, weaponInfo->flashRadius * intensity, weaponInfo->flashColor[0], weaponInfo->flashColor[1], weaponInfo->flashColor[2] ); } }
/* * CG_SkeletalPoseGetAttachment * Get the tag from the interpolated and transformed pose */ qboolean CG_SkeletalPoseGetAttachment( orientation_t *orient, cgs_skeleton_t *skel, bonepose_t *boneposes, char *bonename ) { int i; quat_t quat; cgs_bone_t *bone; bonepose_t *bonepose; cg_tagmask_t *tagmask; if( !boneposes || !skel ) { CG_Printf( "CG_SkeletalPoseLerpAttachment: Wrong model or boneposes %s\n", bonename ); return qfalse; } tagmask = CG_TagMask( bonename, skel ); // find the appropriate attachment bone if( tagmask ) { bone = skel->bones; for( i = 0; i < skel->numBones; i++, bone++ ) { if( !Q_stricmp( bone->name, tagmask->bonename ) ) break; } } else { bone = skel->bones; for( i = 0; i < skel->numBones; i++, bone++ ) { if( !Q_stricmp( bone->name, bonename ) ) break; } } if( i == skel->numBones ) { CG_Printf( "CG_SkeletalPoseLerpAttachment: no such bone %s\n", bonename ); return qfalse; } // get the desired bone bonepose = boneposes + i; // copy the inverted bone into the tag Quat_Inverse( &bonepose->dualquat[0], quat ); // inverse the tag direction Quat_Matrix( quat, orient->axis ); DualQuat_GetVector( bonepose->dualquat, orient->origin ); // normalize each axis for( i = 0; i < 3; i++ ) VectorNormalizeFast( orient->axis[i] ); // do the offseting if having a tagmask if( tagmask ) { // we want to place a rotated model over this tag, not to rotate the tag, // because all rotations would move. So we create a new orientation for the // model and we position the new orientation in tag space if( tagmask->rotate[YAW] || tagmask->rotate[PITCH] || tagmask->rotate[ROLL] ) { orientation_t modOrient, newOrient; VectorCopy( tagmask->offset, modOrient.origin ); AnglesToAxis( tagmask->rotate, modOrient.axis ); VectorCopy( vec3_origin, newOrient.origin ); Matrix_Identity( newOrient.axis ); CG_MoveToTag( newOrient.origin, newOrient.axis, orient->origin, orient->axis, modOrient.origin, modOrient.axis ); Matrix_Copy( newOrient.axis, orient->axis ); VectorCopy( newOrient.origin, orient->origin ); } else { // offset for( i = 0; i < 3; i++ ) { if( tagmask->offset[i] ) VectorMA( orient->origin, tagmask->offset[i], orient->axis[i], orient->origin ); } } } return qtrue; }