/* ================ idBotAI::Vehicle_Ram_Attack_Movement ================ */ bool idBotAI::Vehicle_Ram_Attack_Movement() { proxyInfo_t enemyVehicleInfo; idBox enemyBox; if ( enemyInfo.enemyDist < 700.0f && botVehicleInfo->forwardSpeed < 100.0f && botVehicleInfo->type != HOG ) { //mal: somethings holding us up, we can't ram at this speed/dist! VEHICLE_COMBAT_MOVEMENT_STATE = NULL; return false; } if ( !Bot_VehicleCanRamClient( enemy ) ) { VEHICLE_COMBAT_MOVEMENT_STATE = NULL; return false; } if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) { GetVehicleInfo( botWorld->clientInfo[ enemy ].proxyInfo.entNum, enemyVehicleInfo ); enemyBox = idBox( enemyVehicleInfo.bbox, enemyVehicleInfo.origin, enemyVehicleInfo.axis ); } else { enemyBox = idBox( botWorld->clientInfo[ enemy ].localBounds, botWorld->clientInfo[ enemy ].origin, botWorld->clientInfo[ enemy ].bodyAxis ); } if ( !InFrontOfVehicle( botVehicleInfo->entNum, enemyBox.GetCenter(), false ) ) { VEHICLE_COMBAT_MOVEMENT_STATE = NULL; return false; } Bot_MoveToGoal( enemyBox.GetCenter(), vec3_zero, SPRINT_ATTACK, NULLMOVETYPE ); //mal: Prepare for ramming speed! Ram them until they're dead, or we are.... Bot_LookAtLocation( enemyBox.GetCenter(), SMOOTH_TURN ); return true; }
void idRestoreGame::ReadBox( idBox &box ) { idVec3 center, extents; idMat3 axis; ReadVec3( center ); ReadVec3( extents ); ReadMat3( axis ); box = idBox( center, extents, axis ); }
/* ================== R_CalcEntityScissorRectangle ================== */ idScreenRect R_CalcEntityScissorRectangle( viewEntity_t *vEntity ) { idBounds bounds; idRenderEntityLocal *def = vEntity->entityDef; tr.viewDef->viewFrustum.ProjectionBounds( idBox( def->referenceBounds, def->parms.origin, def->parms.axis ), bounds ); return R_ScreenRectFromViewFrustumBounds( bounds ); }
/* =================== idInteraction::CullInteractionByViewFrustum =================== */ bool idInteraction::CullInteractionByViewFrustum( const idFrustum &viewFrustum ) { if ( !r_useInteractionCulling.GetBool() ) { return false; } if ( frustumState == idInteraction::FRUSTUM_INVALID ) { return false; } if ( frustumState == idInteraction::FRUSTUM_UNINITIALIZED ) { frustum.FromProjection( idBox( entityDef->referenceBounds, entityDef->parms.origin, entityDef->parms.axis ), lightDef->globalLightOrigin, MAX_WORLD_SIZE ); if ( !frustum.IsValid() ) { frustumState = idInteraction::FRUSTUM_INVALID; return false; } if ( lightDef->parms.pointLight ) { frustum.ConstrainToBox( idBox( lightDef->parms.origin, lightDef->parms.lightRadius, lightDef->parms.axis ) ); } else { frustum.ConstrainToBox( idBox( lightDef->frustumTris->bounds ) ); } frustumState = idInteraction::FRUSTUM_VALID; } if ( !viewFrustum.IntersectsFrustum( frustum ) ) { return true; } if ( r_showInteractionFrustums.GetInteger() ) { static idVec4 colors[] = { colorRed, colorGreen, colorBlue, colorYellow, colorMagenta, colorCyan, colorWhite, colorPurple }; tr.viewDef->renderWorld->DebugFrustum( colors[lightDef->index & 7], frustum, ( r_showInteractionFrustums.GetInteger() > 1 ) ); if ( r_showInteractionFrustums.GetInteger() > 2 ) { tr.viewDef->renderWorld->DebugBox( colorWhite, idBox( entityDef->referenceBounds, entityDef->parms.origin, entityDef->parms.axis ) ); } } return false; }
/* ================== idInteraction::CalcInteractionScissorRectangle ================== */ idScreenRect idInteraction::CalcInteractionScissorRectangle( const idFrustum &viewFrustum ) { idBounds projectionBounds; idScreenRect portalRect; idScreenRect scissorRect; if ( r_useInteractionScissors.GetInteger() == 0 ) { return lightDef->viewLight->scissorRect; } if ( r_useInteractionScissors.GetInteger() < 0 ) { // this is the code from Cass at nvidia, it is more precise, but slower return R_CalcIntersectionScissor( lightDef, entityDef, tr.viewDef ); } // the following is Mr.E's code // frustum must be initialized and valid if ( frustumState == idInteraction::FRUSTUM_UNINITIALIZED || frustumState == idInteraction::FRUSTUM_INVALID ) { return lightDef->viewLight->scissorRect; } // calculate scissors for the portals through which the interaction is visible if ( r_useInteractionScissors.GetInteger() > 1 ) { areaNumRef_t *area; if ( frustumState == idInteraction::FRUSTUM_VALID ) { // retrieve all the areas the interaction frustum touches for ( areaReference_t *ref = entityDef->entityRefs; ref; ref = ref->ownerNext ) { area = entityDef->world->areaNumRefAllocator.Alloc(); area->areaNum = ref->area->areaNum; area->next = frustumAreas; frustumAreas = area; } frustumAreas = tr.viewDef->renderWorld->FloodFrustumAreas( frustum, frustumAreas ); frustumState = idInteraction::FRUSTUM_VALIDAREAS; } portalRect.Clear(); for ( area = frustumAreas; area; area = area->next ) { portalRect.Union( entityDef->world->GetAreaScreenRect( area->areaNum ) ); } portalRect.Intersect( lightDef->viewLight->scissorRect ); } else { portalRect = lightDef->viewLight->scissorRect; } // early out if the interaction is not visible through any portals if ( portalRect.IsEmpty() ) { return portalRect; } // calculate bounds of the interaction frustum projected into the view frustum if ( lightDef->parms.pointLight ) { viewFrustum.ClippedProjectionBounds( frustum, idBox( lightDef->parms.origin, lightDef->parms.lightRadius, lightDef->parms.axis ), projectionBounds ); } else { viewFrustum.ClippedProjectionBounds( frustum, idBox( lightDef->frustumTris->bounds ), projectionBounds ); } if ( projectionBounds.IsCleared() ) { return portalRect; } // derive a scissor rectangle from the projection bounds scissorRect = R_ScreenRectFromViewFrustumBounds( projectionBounds ); // intersect with the portal crossing scissor rectangle scissorRect.Intersect( portalRect ); if ( r_showInteractionScissors.GetInteger() > 0 ) { R_ShowColoredScreenRect( scissorRect, lightDef->index ); } return scissorRect; }
/* ============ GetObstacles ============ */ int GetObstacles( const idPhysics *physics, const idAAS *aas, const idEntity *ignore, int areaNum, const idVec3 &startPos, const idVec3 &seekPos, obstacle_t *obstacles, int maxObstacles, idBounds &clipBounds ) { int i, j, numListedClipModels, numObstacles, numVerts, clipMask, blockingObstacle, blockingEdgeNum; int wallEdges[MAX_AAS_WALL_EDGES], numWallEdges, verts[2], lastVerts[2], nextVerts[2]; float stepHeight, headHeight, blockingScale, min, max; idVec3 seekDelta, silVerts[32], start, end, nextStart, nextEnd; idVec2 expBounds[2], edgeDir, edgeNormal, nextEdgeDir, nextEdgeNormal, lastEdgeNormal; idVec2 obDelta; idPhysics *obPhys; idBox box; idEntity *obEnt; idClipModel *clipModel; idClipModel *clipModelList[ MAX_GENTITIES ]; numObstacles = 0; seekDelta = seekPos - startPos; expBounds[0] = physics->GetBounds()[0].ToVec2() - idVec2( CM_BOX_EPSILON, CM_BOX_EPSILON ); expBounds[1] = physics->GetBounds()[1].ToVec2() + idVec2( CM_BOX_EPSILON, CM_BOX_EPSILON ); physics->GetAbsBounds().AxisProjection( -physics->GetGravityNormal(), stepHeight, headHeight ); stepHeight += aas->GetSettings()->maxStepHeight; // clip bounds for the obstacle search space clipBounds[0] = clipBounds[1] = startPos; clipBounds.AddPoint( seekPos ); clipBounds.ExpandSelf( MAX_OBSTACLE_RADIUS ); clipMask = physics->GetClipMask(); // find all obstacles touching the clip bounds numListedClipModels = gameLocal.clip.ClipModelsTouchingBounds( clipBounds, clipMask, clipModelList, MAX_GENTITIES ); for ( i = 0; i < numListedClipModels && numObstacles < MAX_OBSTACLES; i++ ) { clipModel = clipModelList[i]; obEnt = clipModel->GetEntity(); if ( !clipModel->IsTraceModel() ) { continue; } if ( obEnt->IsType( idActor::Type ) ) { obPhys = obEnt->GetPhysics(); // ignore myself, my enemy, and dead bodies if ( ( obPhys == physics ) || ( obEnt == ignore ) || ( obEnt->health <= 0 ) ) { continue; } // if the actor is moving idVec3 v1 = obPhys->GetLinearVelocity(); if ( v1.LengthSqr() > Square( 10.0f ) ) { idVec3 v2 = physics->GetLinearVelocity(); if ( v2.LengthSqr() > Square( 10.0f ) ) { // if moving in about the same direction if ( v1 * v2 > 0.0f ) { continue; } } } } else if ( obEnt->IsType( idMoveable::Type ) ) { // moveables are considered obstacles } else { // ignore everything else continue; } // check if we can step over the object clipModel->GetAbsBounds().AxisProjection( -physics->GetGravityNormal(), min, max ); if ( max < stepHeight || min > headHeight ) { // can step over this one continue; } // project a box containing the obstacle onto the floor plane box = idBox( clipModel->GetBounds(), clipModel->GetOrigin(), clipModel->GetAxis() ); numVerts = box.GetParallelProjectionSilhouetteVerts( physics->GetGravityNormal(), silVerts ); // create a 2D winding for the obstacle; obstacle_t &obstacle = obstacles[numObstacles++]; obstacle.winding.Clear(); for ( j = 0; j < numVerts; j++ ) { obstacle.winding.AddPoint( silVerts[j].ToVec2() ); } if ( ai_showObstacleAvoidance.GetBool() ) { for ( j = 0; j < numVerts; j++ ) { silVerts[j].z = startPos.z; } for ( j = 0; j < numVerts; j++ ) { gameRenderWorld->DebugArrow( colorWhite, silVerts[j], silVerts[(j+1)%numVerts], 4 ); } } // expand the 2D winding for collision with a 2D box obstacle.winding.ExpandForAxialBox( expBounds ); obstacle.winding.GetBounds( obstacle.bounds ); obstacle.entity = obEnt; } // if there are no dynamic obstacles the path should be through valid AAS space if ( numObstacles == 0 ) { return 0; } // if the current path doesn't intersect any dynamic obstacles the path should be through valid AAS space if ( PointInsideObstacle( obstacles, numObstacles, startPos.ToVec2() ) == -1 ) { if ( !GetFirstBlockingObstacle( obstacles, numObstacles, -1, startPos.ToVec2(), seekDelta.ToVec2(), blockingScale, blockingObstacle, blockingEdgeNum ) ) { return 0; } } // create obstacles for AAS walls if ( aas ) { float halfBoundsSize = ( expBounds[ 1 ].x - expBounds[ 0 ].x ) * 0.5f; numWallEdges = aas->GetWallEdges( areaNum, clipBounds, TFL_WALK, wallEdges, MAX_AAS_WALL_EDGES ); aas->SortWallEdges( wallEdges, numWallEdges ); lastVerts[0] = lastVerts[1] = 0; lastEdgeNormal.Zero(); nextVerts[0] = nextVerts[1] = 0; for ( i = 0; i < numWallEdges && numObstacles < MAX_OBSTACLES; i++ ) { aas->GetEdge( wallEdges[i], start, end ); aas->GetEdgeVertexNumbers( wallEdges[i], verts ); edgeDir = end.ToVec2() - start.ToVec2(); edgeDir.Normalize(); edgeNormal.x = edgeDir.y; edgeNormal.y = -edgeDir.x; if ( i < numWallEdges-1 ) { aas->GetEdge( wallEdges[i+1], nextStart, nextEnd ); aas->GetEdgeVertexNumbers( wallEdges[i+1], nextVerts ); nextEdgeDir = nextEnd.ToVec2() - nextStart.ToVec2(); nextEdgeDir.Normalize(); nextEdgeNormal.x = nextEdgeDir.y; nextEdgeNormal.y = -nextEdgeDir.x; } obstacle_t &obstacle = obstacles[numObstacles++]; obstacle.winding.Clear(); obstacle.winding.AddPoint( end.ToVec2() ); obstacle.winding.AddPoint( start.ToVec2() ); obstacle.winding.AddPoint( start.ToVec2() - edgeDir - edgeNormal * halfBoundsSize ); obstacle.winding.AddPoint( end.ToVec2() + edgeDir - edgeNormal * halfBoundsSize ); if ( lastVerts[1] == verts[0] ) { obstacle.winding[2] -= lastEdgeNormal * halfBoundsSize; } else { obstacle.winding[1] -= edgeDir; } if ( verts[1] == nextVerts[0] ) { obstacle.winding[3] -= nextEdgeNormal * halfBoundsSize; } else { obstacle.winding[0] += edgeDir; } obstacle.winding.GetBounds( obstacle.bounds ); obstacle.entity = NULL; memcpy( lastVerts, verts, sizeof( lastVerts ) ); lastEdgeNormal = edgeNormal; } } // show obstacles if ( ai_showObstacleAvoidance.GetBool() ) { for ( i = 0; i < numObstacles; i++ ) { obstacle_t &obstacle = obstacles[i]; for ( j = 0; j < obstacle.winding.GetNumPoints(); j++ ) { silVerts[j].ToVec2() = obstacle.winding[j]; silVerts[j].z = startPos.z; } for ( j = 0; j < obstacle.winding.GetNumPoints(); j++ ) { gameRenderWorld->DebugArrow( colorGreen, silVerts[j], silVerts[(j+1)%obstacle.winding.GetNumPoints()], 4 ); } } } return numObstacles; }
/* ================ sdPlayerArmIK::Update ================ */ void sdPlayerArmIK::Update( idPlayer* player, idEntity* target ) { struct arm_t { idMat3 targetShoulderAxis; idMat3 targetElbowAxis; idMat3 targetHandAxis; }; arm_t arms[ NUM_ARMS ]; ClearJointMods( player ); idAnimator* animator = player->GetAnimator(); idMat3 tempAxis; idVec3 modelOrigin = player->GetRenderEntity()->origin; idMat3 modelAxis = player->GetRenderEntity()->axis; idMat3 transposeModelAxis = modelAxis.Transpose(); // get the arm bone lengths and rotation matrices for ( int i = 0; i < NUM_ARMS; i++ ) { if ( armTargets[ i ].joint == INVALID_JOINT ) { continue; } idMat3 handAxis; idVec3 handOrigin; animator->GetJointTransform( player->GetHandJoint( i ), gameLocal.time, handOrigin, handAxis ); idMat3 elbowAxis; idVec3 elbowOrigin; animator->GetJointTransform( player->GetElbowJoint( i ), gameLocal.time, elbowOrigin, elbowAxis ); idMat3 shoulderAxis; idVec3 shoulderOrigin; animator->GetJointTransform( player->GetShoulderJoint( i ), gameLocal.time, shoulderOrigin, shoulderAxis ); idVec3 t1 = ( elbowOrigin - shoulderOrigin ); // t1.Normalize(); idVec3 t2 = ( elbowOrigin - handOrigin ); // t2.Normalize(); idVec3 dir = t1 + t2; dir.Normalize(); // conversion from upper arm bone axis to should joint axis float upperArmLength = idIK::GetBoneAxis( shoulderOrigin, elbowOrigin, dir, tempAxis ); idMat3 upperArmToShoulderJoint = shoulderAxis * tempAxis.Transpose(); // conversion from lower arm bone axis to elbow joint axis float lowerArmLength = idIK::GetBoneAxis( elbowOrigin, handOrigin, dir, tempAxis ); idMat3 lowerArmToElbowJoint = elbowAxis * tempAxis.Transpose(); // get target idVec3 targetOrigin; target->GetWorldOriginAxis( armTargets[ i ].joint, targetOrigin, arms[ i ].targetHandAxis ); idVec3 targetOriginLocal = targetOrigin - modelOrigin; targetOriginLocal *= transposeModelAxis; arms[ i ].targetHandAxis *= transposeModelAxis; // solve IK and calculate elbow position idIK::SolveTwoBones( shoulderOrigin, targetOriginLocal, dir, upperArmLength, lowerArmLength, elbowOrigin ); if ( ik_debug.GetBool() ) { idVec3 shoulderWorld = ( shoulderOrigin * modelAxis ) + modelOrigin; idVec3 elbowWorld = ( elbowOrigin * modelAxis ) + modelOrigin; gameRenderWorld->DebugLine( colorCyan, shoulderWorld, elbowWorld ); gameRenderWorld->DebugLine( colorRed, elbowWorld, targetOrigin ); gameRenderWorld->DebugBox( colorYellow, idBox( targetOrigin, idVec3( 2, 2, 2 ), mat3_identity ) ); gameRenderWorld->DebugLine( colorGreen, elbowWorld, elbowWorld + ( ( dir * modelAxis ) * 8 ) ); } // get the axis for the shoulder joint idIK::GetBoneAxis( shoulderOrigin, elbowOrigin, dir, tempAxis ); arms[ i ].targetShoulderAxis = upperArmToShoulderJoint * tempAxis; // get the axis for the elbow joint idIK::GetBoneAxis( elbowOrigin, targetOriginLocal, dir, tempAxis ); arms[ i ].targetElbowAxis = lowerArmToElbowJoint * tempAxis; } for ( int i = 0; i < NUM_ARMS; i++ ) { if ( armTargets[ i ].joint == INVALID_JOINT ) { continue; } animator->SetJointAxis( player->GetShoulderJoint( i ), JOINTMOD_WORLD_OVERRIDE, arms[ i ].targetShoulderAxis ); animator->SetJointAxis( player->GetElbowJoint( i ), JOINTMOD_WORLD_OVERRIDE, arms[ i ].targetElbowAxis ); animator->SetJointAxis( player->GetHandJoint( i ), JOINTMOD_WORLD_OVERRIDE, arms[ i ].targetHandAxis ); } }
/* ============== idDragEntity::Update ============== */ void idDragEntity::Update( idPlayer *player ) { idVec3 viewPoint, origin; idMat3 viewAxis, axis; trace_t trace; idEntity *newEnt; idAngles angles; jointHandle_t newJoint; idStr newBodyName; player->GetViewPos( viewPoint, viewAxis ); // if no entity selected for dragging if ( !dragEnt.GetEntity() ) { if ( player->usercmd.buttons & BUTTON_ATTACK ) { gameLocal.clip.TracePoint( trace, viewPoint, viewPoint + viewAxis[0] * MAX_DRAG_TRACE_DISTANCE, (CONTENTS_SOLID|CONTENTS_RENDERMODEL|CONTENTS_BODY), player ); if ( trace.fraction < 1.0f ) { newEnt = gameLocal.entities[ trace.c.entityNum ]; if ( newEnt ) { if ( newEnt->GetBindMaster() ) { if ( newEnt->GetBindJoint() ) { trace.c.id = JOINT_HANDLE_TO_CLIPMODEL_ID( newEnt->GetBindJoint() ); } else { trace.c.id = newEnt->GetBindBody(); } newEnt = newEnt->GetBindMaster(); } if ( newEnt->IsType( idAFEntity_Base::Type ) && static_cast<idAFEntity_Base *>(newEnt)->IsActiveAF() ) { idAFEntity_Base *af = static_cast<idAFEntity_Base *>(newEnt); // joint being dragged newJoint = CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id ); // get the body id from the trace model id which might be a joint handle trace.c.id = af->BodyForClipModelId( trace.c.id ); // get the name of the body being dragged newBodyName = af->GetAFPhysics()->GetBody( trace.c.id )->GetName(); } else if ( !newEnt->IsType( idWorldspawn::Type ) ) { if ( trace.c.id < 0 ) { newJoint = CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id ); } else { newJoint = INVALID_JOINT; } newBodyName = ""; } else { newJoint = INVALID_JOINT; newEnt = NULL; } } if ( newEnt ) { dragEnt = newEnt; selected = newEnt; joint = newJoint; id = trace.c.id; bodyName = newBodyName; if ( !cursor ) { cursor = ( idCursor3D * )gameLocal.SpawnEntityType( idCursor3D::Type ); } idPhysics *phys = dragEnt.GetEntity()->GetPhysics(); localPlayerPoint = ( trace.c.point - viewPoint ) * viewAxis.Transpose(); origin = phys->GetOrigin( id ); axis = phys->GetAxis( id ); localEntityPoint = ( trace.c.point - origin ) * axis.Transpose(); cursor->drag.Init( g_dragDamping.GetFloat() ); cursor->drag.SetPhysics( phys, id, localEntityPoint ); cursor->Show(); if ( phys->IsType( idPhysics_AF::Type ) || phys->IsType( idPhysics_RigidBody::Type ) || phys->IsType( idPhysics_Monster::Type ) ) { cursor->BecomeActive( TH_THINK ); } } } } } // if there is an entity selected for dragging idEntity *drag = dragEnt.GetEntity(); if ( drag ) { if ( !( player->usercmd.buttons & BUTTON_ATTACK ) ) { StopDrag(); return; } cursor->SetOrigin( viewPoint + localPlayerPoint * viewAxis ); cursor->SetAxis( viewAxis ); cursor->drag.SetDragPosition( cursor->GetPhysics()->GetOrigin() ); renderEntity_t *renderEntity = drag->GetRenderEntity(); idAnimator *dragAnimator = drag->GetAnimator(); if ( joint != INVALID_JOINT && renderEntity && dragAnimator ) { dragAnimator->GetJointTransform( joint, gameLocal.time, cursor->draggedPosition, axis ); cursor->draggedPosition = renderEntity->origin + cursor->draggedPosition * renderEntity->axis; gameRenderWorld->DrawText( va( "%s\n%s\n%s, %s", drag->GetName(), drag->GetType()->classname, dragAnimator->GetJointName( joint ), bodyName.c_str() ), cursor->GetPhysics()->GetOrigin(), 0.1f, colorWhite, viewAxis, 1 ); } else { cursor->draggedPosition = cursor->GetPhysics()->GetOrigin(); gameRenderWorld->DrawText( va( "%s\n%s\n%s", drag->GetName(), drag->GetType()->classname, bodyName.c_str() ), cursor->GetPhysics()->GetOrigin(), 0.1f, colorWhite, viewAxis, 1 ); } } // if there is a selected entity if ( selected.GetEntity() && g_dragShowSelection.GetBool() ) { // draw the bbox of the selected entity renderEntity_t *renderEntity = selected.GetEntity()->GetRenderEntity(); if ( renderEntity ) { gameRenderWorld->DebugBox( colorYellow, idBox( renderEntity->bounds, renderEntity->origin, renderEntity->axis ) ); } } }
idScreenRect R_CalcLightScissorRectangle( viewLight_t *vLight ) { idScreenRect r; srfTriangles_t *tri; idPlane eye, clip; idVec3 ndc; if( vLight->lightDef->parms.pointLight ) { idBounds bounds; idRenderLightLocal *lightDef = vLight->lightDef; tr.viewDef->viewFrustum.ProjectionBounds( idBox( lightDef->parms.origin, lightDef->parms.lightRadius, lightDef->parms.axis ), bounds ); return R_ScreenRectFromViewFrustumBounds( bounds ); } if( r_useClippedLightScissors.GetInteger() == 2 ) { return R_ClippedLightScissorRectangle( vLight ); } r.Clear(); tri = vLight->lightDef->frustumTris; for( int i = 0; i < tri->numVerts; i++ ) { R_TransformModelToClip( tri->verts[i].xyz, tr.viewDef->worldSpace.modelViewMatrix, tr.viewDef->projectionMatrix, eye, clip ); // if it is near clipped, clip the winding polygons to the view frustum if( clip[3] <= 1 ) { c_clippedLight++; if( r_useClippedLightScissors.GetInteger() ) { return R_ClippedLightScissorRectangle( vLight ); } else { r.x1 = r.y1 = 0; r.x2 = ( tr.viewDef->viewport.x2 - tr.viewDef->viewport.x1 ) - 1; r.y2 = ( tr.viewDef->viewport.y2 - tr.viewDef->viewport.y1 ) - 1; return r; } } R_TransformClipToDevice( clip, ndc ); float windowX = 0.5f * ( 1.0f + ndc[0] ) * ( tr.viewDef->viewport.x2 - tr.viewDef->viewport.x1 ); float windowY = 0.5f * ( 1.0f + ndc[1] ) * ( tr.viewDef->viewport.y2 - tr.viewDef->viewport.y1 ); if( windowX > tr.viewDef->scissor.x2 ) { windowX = tr.viewDef->scissor.x2; } else if( windowX < tr.viewDef->scissor.x1 ) { windowX = tr.viewDef->scissor.x1; } if( windowY > tr.viewDef->scissor.y2 ) { windowY = tr.viewDef->scissor.y2; } else if( windowY < tr.viewDef->scissor.y1 ) { windowY = tr.viewDef->scissor.y1; } r.AddPoint( windowX, windowY ); } // add the fudge boundary r.Expand(); c_unclippedLight++; return r; }
void idAASLocal::DrawAreas(const idVec3& playerOrigin) { if ( file == NULL ) { return; } // Initialize AAS area colors if we haven't already done so if ( aasColors.Num() == 0 ) { // Get a color for each cluster int numClusters = file->GetNumClusters(); for ( int c = 0 ; c < numClusters ; c++ ) { aasColors.Alloc() = idVec4(gameLocal.random.RandomFloat() + 0.1f, gameLocal.random.RandomFloat() + 0.1f, gameLocal.random.RandomFloat() + 0.1f, 1); } } idMat3 playerViewMatrix(gameLocal.GetLocalPlayer()->viewAngles.ToMat3()); idList<int> clusterNums; // Paint the AAS areas for ( int i = 0 ; i < file->GetNumAreas() ; i++ ) { idVec3 areaCenter = AreaCenter(i); // angua: only draw areas near the player, no need to see them at the other end of the map if ( (areaCenter - playerOrigin).LengthFast() < 150 ) { idBounds areaBounds = GetAreaBounds(i); int clusterNum = file->GetArea(i).cluster; clusterNums.AddUnique(clusterNum); idVec4 color = (clusterNum <= 0) ? colorWhite : aasColors[clusterNum]; gameRenderWorld->DrawText(va("%d", i), areaCenter, 0.2f, color, playerViewMatrix, 1, 16); gameRenderWorld->DebugBox(color, idBox(areaBounds), 16); } } // Paint the cluster numbers for ( int i = 0 ; i < clusterNums.Num() ; i++ ) { int area = GetAreaInCluster(clusterNums[i]); if ( area <= 0 ) { continue; } idVec3 origin = file->GetArea(area).center; if ( (origin - playerOrigin).LengthFast() < 300 ) { gameRenderWorld->DrawText(va("%d", clusterNums[i]), origin, 1, colorRed, playerViewMatrix, 1, 16); } } }