//-------------------------------------------------------------------------------------- // Move the entity to a specified target position. // Param1: The target position of the entity. // Param2: The radius around the target position from which the target counts as reached. // Param3: The speed, at which the entity should seek the target. // Returns true if the target was reached, false if there is still way to go. //-------------------------------------------------------------------------------------- bool EntityMovementManager::Seek(const XMFLOAT2& targetPosition, float targetReachedRadius, float speed) { XMFLOAT2 desiredVelocity; XMStoreFloat2(&desiredVelocity, XMLoadFloat2(&targetPosition) - XMLoadFloat2(&m_pEntity->GetPosition())); // Get the distance from the current position of the entity to the target float distance; XMStoreFloat(&distance, XMVector2Length(XMLoadFloat2(&desiredVelocity))); // Normalise the desired velocity XMStoreFloat2(&desiredVelocity, XMVector2Normalize(XMLoadFloat2(&desiredVelocity))); XMStoreFloat2(&desiredVelocity, XMLoadFloat2(&desiredVelocity) * speed); bool targetReached = false; // Target reached if(distance <= targetReachedRadius) { desiredVelocity = XMFLOAT2(0.0f, 0.0f); targetReached = true; } XMFLOAT2 force; XMStoreFloat2(&force, XMLoadFloat2(&desiredVelocity) - XMLoadFloat2(&m_velocity)); // Add the seek force to the accumulated steering force XMStoreFloat2(&m_steeringForce, XMLoadFloat2(&m_steeringForce) + XMLoadFloat2(&force)); return targetReached; }
XMFLOAT2 Skeleton::CalculatePosition2D(std::vector<XMFLOAT2> &jointPositions2D, std::vector<float> &jointRotations2D, XMFLOAT2 &endEffectorPosition) { if (jointPositions2D.size() < 2) return XMFLOAT2(0.f, 0.f); // Walk through each link and apply the transform for (size_t i = 0; i < jointPositions2D.size() - 1; ++i) { float sumRotations = 0.f; for (size_t j = 0; j <= i; ++j) { sumRotations += jointRotations2D[j]; } XMFLOAT2 direction; direction.x = cos(sumRotations); direction.y = sin(sumRotations); XMStoreFloat2(&jointPositions2D[i + 1], XMVectorAdd(XMLoadFloat2(&jointPositions2D[i]), XMVectorScale(XMLoadFloat2(&direction), m_IKLinkLength))); } float sumRotations = 0.f; for (size_t j = 0; j < jointRotations2D.size(); ++j) { sumRotations += jointRotations2D[j]; } XMFLOAT2 direction; direction.x = cos(sumRotations); direction.y = sin(sumRotations); XMStoreFloat2(&endEffectorPosition, XMVectorAdd(XMLoadFloat2(&jointPositions2D.back()), XMVectorScale(XMLoadFloat2(&direction), m_IKLinkLength))); return endEffectorPosition; }
//-------------------------------------------------------------------------------------- // Calculate the collision avoidance force and add it to the total force. This force // is used to avoid collisions of an entity with static obstacles in the environment and // other entities. // Param1: Obstacles and entities within this distance in front of the entity will be avoided. // Param2: The maximal size of this force. //-------------------------------------------------------------------------------------- void EntityMovementManager::AvoidCollisions(float seeAheadDistance, float maximalForce) { if(m_velocity.x == 0.0f && m_velocity.y == 0.0f) { return; } std::multimap<float, CollidableObject*> nearbyObjects; m_pEnvironment->GetNearbyObjects(m_pEntity->GetPosition(), seeAheadDistance, GroupAllSoldiersAndObstacles, nearbyObjects); // One element is entity itself -> Check if there are more than one if(nearbyObjects.size() > 1) { XMFLOAT2 lineEndPoint(0.0f, 0.0f); XMStoreFloat2(&lineEndPoint, XMLoadFloat2(&m_pEntity->GetPosition()) + XMVector2Normalize(XMLoadFloat2(&m_pEntity->GetViewDirection())) * seeAheadDistance); for(std::multimap<float, CollidableObject*>::iterator it = nearbyObjects.begin(); it != nearbyObjects.end(); ++it) { if((it->second->GetId() != m_pEntity->GetId()) && reinterpret_cast<CollidableObject*>(it->second)->GetCollider()->CheckLineCollision(m_pEntity->GetPosition(), lineEndPoint)) { // Determine whether the other entity is left or right of this entity XMFLOAT2 entityToObject(0.0f, 0.0f); XMStoreFloat2(&entityToObject, XMLoadFloat2(&it->second->GetPosition()) - XMLoadFloat2(&m_pEntity->GetPosition())); float dot = m_pEntity->GetViewDirection().x * (-entityToObject.y) + m_pEntity->GetViewDirection().y * entityToObject.x; XMFLOAT2 avoidanceVector = m_pEntity->GetViewDirection(); if(dot > 0) { // Object is right of entity, steer left to avoid avoidanceVector.x = -m_pEntity->GetViewDirection().y; avoidanceVector.y = m_pEntity->GetViewDirection().x; }else { // Object is left of entity, steer right to avoid avoidanceVector.x = m_pEntity->GetViewDirection().y; avoidanceVector.y = -m_pEntity->GetViewDirection().x; } XMStoreFloat2(&m_steeringForce, XMLoadFloat2(&m_steeringForce) + XMVector2Normalize(XMLoadFloat2(&avoidanceVector)) * maximalForce); // Bail out of the function as soon as the first collision is found (the nearby entities are already sorted // by their distance from the original entity, thus the first collision found is the closest one) return; } } } }
//-------------------------------------------------------------------------------------- // Calculate the separation force and add it to the total force. // Param1: The entity will try to move away from entities that are at this distance or closer. // Param2: The maximal size of this force. //-------------------------------------------------------------------------------------- void EntityMovementManager::Separate(float separationRadius, float maximalForce) { XMVECTOR separationVector = XMVectorZero(); // The separation force to prevent overlapping of moving entities // Find the moving entities that are in close proximity to this one (check both teams) std::multimap<float, CollidableObject*> nearbySoldiers; m_pEnvironment->GetNearbyObjects(m_pEntity->GetPosition(), separationRadius, GroupAllSoldiers, nearbySoldiers); // The entity itself will be included in the list of soldiers -> check if there are others as well if(nearbySoldiers.size() > 1) { for(std::multimap<float, CollidableObject*>::const_iterator it = nearbySoldiers.begin(); it != nearbySoldiers.end(); ++it) { if(it->second->GetId() != m_pEntity->GetId()) { // Scale the force according to the proximity of the nearby entity. Thus the push from close objects will be // stronger than that from objects that are farther away. // Avoid possible division by zero float proximity = (it->first != 0) ? it->first : 0.01f; separationVector += (XMLoadFloat2(&m_pEntity->GetPosition()) - XMLoadFloat2(&it->second->GetPosition())) / proximity; } } // Truncate the force according to the maximally allowed separation force. separationVector = XMVector2Normalize(separationVector) * maximalForce; // Add the separation force to the accumulated steering force XMStoreFloat2(&m_steeringForce, XMLoadFloat2(&m_steeringForce) + separationVector); } }
//-------------------------------------------------------------------------------------- // Calculate the wall avoidance force and add it to the total force. This force // is used to push the entity away from walls (objects) that it is getting too close to. // Param1: Obstacles within this radius around the entity will be avoided. // Param2: The maximal size of this force. //-------------------------------------------------------------------------------------- void EntityMovementManager::StayAwayFromWalls(float avoidWallsRadius, float maximalForce) { // Get nearby obstacles std::multimap<float, CollidableObject*> nearbyObjects; m_pEnvironment->GetNearbyObjects(m_pEntity->GetPosition(), avoidWallsRadius, GroupObstacles, nearbyObjects); if(!nearbyObjects.empty()) { XMVECTOR avoidanceForce = XMVectorZero(); for(std::multimap<float, CollidableObject*>::iterator it = nearbyObjects.begin(); it != nearbyObjects.end(); ++it) { // Scale the force according to the proximity of the nearby entity. Thus the push from close objects will be // stronger than that from objects that are farther away. avoidanceForce += (XMLoadFloat2(&m_pEntity->GetPosition()) - XMLoadFloat2(&(it->second->GetPosition()))) / it->first; } // Truncate the force according to the maximally allowed wall avoidance force. avoidanceForce = XMVector2Normalize(avoidanceForce) * maximalForce; // Add the collision avoidance force to the accumulated steering force XMStoreFloat2(&m_steeringForce, XMLoadFloat2(&m_steeringForce) + avoidanceForce); } }
Vec2 VectorMath::Normalize(const Vec2* vec) { Vec2 retval; XMVECTOR xmVec = XMLoadFloat2((_XMFLOAT2*)vec); xmVec = XMVector2Normalize(xmVec); XMStoreFloat2((XMFLOAT2*)&retval, xmVec); return retval; }
void DirectionSelector::VerifyDirection() { if (_direction.x * _direction.x + _direction.y * _direction.y >= 1.0f || (_direction.x == 0.0f && _direction.y == 0.0f)) { XMVECTOR vec = XMLoadFloat2(&_direction); vec = XMVector2Normalize(vec) * (1.0f - EPSILON); XMStoreFloat2(&_direction, vec); } }
void LineConnection::FormConnection(XMVECTOR node1Pos, XMVECTOR node2Pos, float distance) { m_visible = true; // draw a line between 2 nodes. The thickness/alpha varies depending on distance m_strokeThickness = Node::Map(distance, 0, MinDist, StrokeWeightMax, StrokeWeightMin); XMVECTORF32 color = {1, 1, 1, Node::Map(distance, 0, MinDist, 1.0f, 0)}; m_color = color; XMStoreFloat2(&m_start, node1Pos); XMStoreFloat2(&m_end, node2Pos); m_destRect.left = (long)m_start.x; m_destRect.top = (long)m_start.y; m_destRect.right = (long)(m_start.x + m_strokeThickness); m_destRect.bottom = (long)(m_start.y + Distance(XMLoadFloat2(&m_start), XMLoadFloat2(&m_end))); m_rotation = PIOVER2 - (float)atan2(m_end.y - m_start.y, m_start.x - m_end.x); }
Sprite::Sprite(FXMVECTOR pos2D, FXMVECTOR scale2D, unsigned short frameWidth, unsigned short frameHeight, float depth, const std::vector<Frame*>& frames, float frameRate, ID3D11Device* device) : mFrameWidth(frameWidth), mFrameHeight(frameHeight), mDepth(depth), mFrames(frames), mFrameRate(frameRate), mFrameIndex(0), mAngle(0), mCurrFrameTime(0.0f) { XMStoreFloat2(&mPos, pos2D); XMStoreFloat2(&mScale, scale2D); InitVB(device); InitIB(device); }
//-------------------------------------------------------------------------------------- // Rotates the entity towards a specific point. // Param1: The position, the entity should look at. //-------------------------------------------------------------------------------------- void EntityMovementManager::LookAt(const XMFLOAT2& lookAtPosition) { XMFLOAT2 newViewDirection(0.0f, 1.0f); XMStoreFloat2(&newViewDirection, XMVector2Normalize(XMLoadFloat2(&lookAtPosition) - XMLoadFloat2(&m_pEntity->GetPosition()))); m_pEntity->SetViewDirection(newViewDirection); float rotation = (atan2(m_pEntity->GetViewDirection().x, m_pEntity->GetViewDirection().y)) * 180 / XM_PI; m_pEntity->SetRotation(rotation); }
void UIObject::SetText(const wchar_t* pText) { text = pText; XMVECTOR xmSize = font->MeasureString(text); XMFLOAT2 size; XMStoreFloat2(&size, xmSize); textWidth = size.x; textHeight = size.y; textPos = XMFLOAT2(position.x + (material->getTexWidth() - size.x) / 2, position.y + (material->getTexHeight() - size.y) / 2); }
XMFLOAT2 HydraManager::getJoystick(int controllerIndex) const { XMFLOAT2 directionVector(0.0f, 0.0f); if (sixenseIsControllerEnabled(controllerIndex)) { XMStoreFloat2(&directionVector, XMVector2Normalize(XMVectorSet(mAcd.controllers[controllerIndex].joystick_x, mAcd.controllers[controllerIndex].joystick_y, 0.0f, 0.0f))); } return directionVector; }
//-------------------------------------------------------------------------------------- // Updates the position and velocity of the entity associated to this movement manager // using the accumulated sum of all forces impacting the entity. // Param1: The time in seconds passed since the last frame. // Param2: The maximal speed of the entity. // Param3: The maximal size of the accumulated forces. // Param4: The handicap to use if the entity is currently being handicapped. //-------------------------------------------------------------------------------------- void EntityMovementManager::UpdatePosition(float deltaTime, float maxSpeed, float maxForce, float handicap) { // Truncate steering force to not be greater than the maximal allowed force float magnitude = 0.0f; XMStoreFloat(&magnitude, XMVector2Length(XMLoadFloat2(&m_steeringForce))); if(magnitude > maxForce) { // Truncate the vector to be of the magnitude corresponding to the maximal allowed force XMStoreFloat2(&m_steeringForce, XMVector2Normalize(XMLoadFloat2(&m_steeringForce)) * maxForce); } // Calculate the new velocity for the entity XMFLOAT2 newVelocity; XMStoreFloat2(&newVelocity, XMLoadFloat2(&m_velocity) + XMLoadFloat2(&m_steeringForce)); // Truncate the velocity if it is greater than the maximally allowed velocity for the entity XMStoreFloat(&magnitude, XMVector2Length(XMLoadFloat2(&newVelocity))); if(magnitude > maxSpeed) { // Truncate the vector to be of the magnitude corresponding to the maximal allowed velocity XMStoreFloat2(&newVelocity, XMVector2Normalize(XMLoadFloat2(&newVelocity)) * maxSpeed); } // Set the new velocity and position on the entity m_velocity = newVelocity; XMFLOAT2 newPosition; if(m_pEntity->IsHandicapped()) { XMStoreFloat2(&newPosition, XMLoadFloat2(&m_pEntity->GetPosition()) + XMLoadFloat2(&newVelocity) * deltaTime * handicap); }else { XMStoreFloat2(&newPosition, XMLoadFloat2(&m_pEntity->GetPosition()) + XMLoadFloat2(&newVelocity) * deltaTime); } m_pEntity->SetPosition(newPosition); m_pEntity->UpdateColliderPosition(newPosition); // Update the rotation to make the entity face the direction, in which it is moving if(!(newVelocity.x == 0.0f && newVelocity.y == 0.0f)) { XMFLOAT2 lookAtPoint(0.0f, 0.0f); XMStoreFloat2(&lookAtPoint, XMLoadFloat2(&m_pEntity->GetPosition()) + XMLoadFloat2(&newVelocity)); LookAt(lookAtPoint); } // Reset the steering force for the next frame m_steeringForce.x = 0.0f; m_steeringForce.y = 0.0f; }
Vector2& operator = (FXMVECTOR v) { XMStoreFloat2(this, v); return *this; }
bool Terrain::computeIntersection(const Ray& ray) { const UINT width = m_width; const UINT depth = m_depth; const float halfWidth = 0.5f * (float)width; const float halfDepth = 0.5f * (float)depth; const UINT heightmapWidth = width + 1; const UINT heightmapDepth = depth + 1; const float halfHeightmapWidth = 0.5f * (float)heightmapWidth; const float halfHeightmapDepth = 0.5f * (float)heightmapDepth; const float heightmapDx = (float)heightmapWidth / ((float)heightmapWidth - 1.f); const float heightmapDz = (float)heightmapDepth / ((float)heightmapDepth - 1.f); XMVECTOR origin = XMVectorSet(XMVectorGetX(ray.origin), XMVectorGetZ(ray.origin), 0.f, 0.f); const float directionX = XMVectorGetX(ray.direction); const float directionZ = XMVectorGetZ(ray.direction); XMVECTOR direction = XMVectorSet(directionX, directionZ, 0.f, 0.f); if (directionX != 0.f && directionZ != 0.f) { const float absDirectionX = abs(directionX); const float absDirectionZ = abs(directionZ); direction /= (absDirectionX > absDirectionZ) ? absDirectionX : absDirectionZ; } direction *= m_selectionIntervalSample; float t = -1.f; XMVECTOR position = origin; int prevRow, prevCol; const UINT n = (UINT)(m_selectionDistance / m_selectionIntervalSample); for (UINT i = 0; i < n; i++) { if (i > 0) position += direction; XMFLOAT2 p; XMStoreFloat2(&p, position); const float c = p.x + halfWidth; const float d = -p.y + halfDepth; const int row = (int)floorf(d); const int col = (int)floorf(c); if ((i <= 0 || (row != prevRow || col != prevCol)) && inBounds(row, col) && inBounds(row + 1, col + 1)) { const float x0 = -halfHeightmapWidth + (float)col * heightmapDx; const float x1 = -halfHeightmapWidth + (float)(col + 1) * heightmapDx; const UINT y0 = row * heightmapWidth + col; const UINT y1 = (row + 1) * heightmapWidth + col; const float z0 = halfHeightmapDepth - (float)row * heightmapDz; const float z1 = halfHeightmapDepth - (float)(row + 1) * heightmapDz; XMVECTOR A = XMVectorSet(x0, m_heightmap[y0 ], z0, 0.f); XMVECTOR B = XMVectorSet(x1, m_heightmap[y0 + 1], z0, 0.f); XMVECTOR C = XMVectorSet(x0, m_heightmap[y1 ], z1, 0.f); XMVECTOR D = XMVectorSet(x1, m_heightmap[y1 + 1], z1, 0.f); XMVECTOR triangle1[3] = { A, B, C }; XMVECTOR triangle2[3] = { D, C, B }; const float t1 = computeTriangleIntersection(ray, triangle1); const float t2 = computeTriangleIntersection(ray, triangle2); if (t1 < 0.f && t2 < 0.f) { } else if (t1 >= 0.f && t2 < 0.f) { t = t1; break; } else if (t1 < 0.f && t2 >= 0.f) { t = t2; break; } else { t = (t1 > t2) ? t2 : t1; break; } } prevRow = row; prevCol = col; } if (t >= 0.f) { XMStoreFloat3(&m_targetPosition, ray.origin + t * ray.direction); return true; } else return false; }
Float2::Float2(FXMVECTOR xy) { XMStoreFloat2(reinterpret_cast<XMFLOAT2*>(this), xy); }
void MovementManagerServer::Update(double p_dt) { // Some debug bools just to test various effects. We'll have these read some other way later bool iceEffect = false; bool fireEffect = false; const size_t length = EntityHandler::GetInstance().GetLastEntityIndex(); int mask = (int)ComponentType::Movement | (int)ComponentType::CharacterController; for(size_t i = 0; i < length; i++) { if(EntityHandler::GetInstance().HasComponents(i, mask)) { /// 1 Get comp MovementComponent* movementComp = EntityHandler::GetInstance().GetComponentFromStorage<MovementComponent>(i); /// 2 Clamp speed // Clamp down XZ movement to maximum movement speed (we don't mess with y due to jump/gravity) XMVECTOR movementXZVec = XMLoadFloat2(&XMFLOAT2(movementComp->movement.x, movementComp->movement.z)); movementXZVec = XMVector2Normalize(movementXZVec) * movementComp->speed * p_dt; // movementXZVec = XMVector2ClampLength(movementXZVec, 0, 0.8f); // Store it back XMFLOAT2 movementXZ; XMStoreFloat2(&movementXZ, movementXZVec); movementComp->movement.x = movementXZ.x; movementComp->movement.z = movementXZ.y; /// 3 Move controller // Perform move bool hitGround = m_sharedContext.GetPhysicsModule().GetCharacterControlManager().MoveController(i, movementComp->movement, p_dt); if(hitGround) { EntityHandler::GetInstance().GetComponentFromStorage<GravityComponent>(i)->travelSpeed = 0; if(EntityHandler::GetInstance().HasComponents(i, (int)ComponentType::Jump)) // temporary fix { EntityHandler::GetInstance().GetComponentFromStorage<JumpComponent>(i)->active = false; } } /// 4 Fix speed for next iteration // If we're sliding around, only reduce speed, don't entierly reset it if(iceEffect) { float iceSlowdownFactor = 0.99f * (1 - p_dt); movementComp->movement.x *= iceSlowdownFactor; movementComp->movement.z *= iceSlowdownFactor; } // If we're not running on fire (or ice) we can stop else if(!fireEffect) { movementComp->movement = XMFLOAT3(0, 0, 0); } // Always reset y movement. Again, we don't mess with y movementComp->movement.y = 0; // RigidBodyComponent* rigidBody = EntityHandler::GetInstance().GetComponentFromStorage<RigidBodyComponent>(i); // XMFLOAT3 currentVelocity = m_sharedContext.GetPhysicsModule().GetRigidBodyManager().GetBodyVelocity(rigidBody->p_bodyID); // XMVECTOR forward = XMLoadFloat3(&movement->direction); // XMVECTOR up = XMLoadFloat3(&XMFLOAT3(0, 1, 0)); // XMVECTOR right = XMVector3Cross(up, forward); // right *= movement->rightAcceleration; // forward *= movement->forwardAcceleration; // XMVECTOR moveForce = right + forward; // XMVECTOR currentVel = XMLoadFloat3(¤tVelocity); //// moveForce -= (XMVector3Length(currentVel)/movement->maxSpeed) * moveForce ; // XMFLOAT3 force; // XMStoreFloat3(&force, moveForce); // m_sharedContext.GetPhysicsModule().GetRigidBodyManager().AddForceToBody(rigidBody->p_bodyID, force); } } }
//-------------------------------------------------------------------------------------- // Processes an inbox message that the manoeuvre received. // Param1: A pointer to the message to process. //-------------------------------------------------------------------------------------- void GuardedFlagCapture::ProcessMessage(Message* pMessage) { switch(pMessage->GetType()) { case FlagDroppedMessageType: { FlagDroppedMessage* pMsg = reinterpret_cast<FlagDroppedMessage*>(pMessage); if(pMsg->GetData().m_flagOwner != GetTeamAI()->GetTeam()) { // The flag was dropped, the manoeuvre failed SetFailed(true); } break; } case ScoreUpdateMessageType: { ScoreUpdateMessage* pMsg = reinterpret_cast<ScoreUpdateMessage*>(pMessage); if(pMsg->GetData().m_team == GetTeamAI()->GetTeam()) { // The flag was captured -> the manoeuvre succeeded SetSucceeded(true); } break; } case EntityKilledMessageType: { EntityKilledMessage* pMsg = reinterpret_cast<EntityKilledMessage*>(pMessage); if(IsParticipant(pMsg->GetData().m_id) && pMsg->GetData().m_team == GetTeamAI()->GetTeam()) { // Participants that get killed, drop out of the manoeuvre m_pTeamAI->ReleaseEntityFromManoeuvre(pMsg->GetData().m_id); } break; } case AttackedByEnemyMessageType: { AttackedByEnemyMessage* pMsg = reinterpret_cast<AttackedByEnemyMessage*>(pMessage); if(pMsg->GetData().m_entityId == m_flagCarrierId) { // The flag carrier is being attacked, protect him. // Get the attack direction XMFLOAT2 viewDirection(0.0f, 0.0f); XMStoreFloat2(&viewDirection, XMLoadFloat2(&pMsg->GetData().m_attackPosition) - XMLoadFloat2(&GetParticipant(pMsg->GetData().m_entityId)->GetPosition())); // Send all protectors to the position of the attacker to protect the carrier for(std::vector<Entity*>::iterator it = m_participants.begin(); it != m_participants.end(); ++it) { if((*it)->GetId() != m_flagCarrierId) { // Change the movement target in the orders for the entities reinterpret_cast<MoveOrder*>(m_activeOrders[(*it)->GetId()])->SetTargetPosition(pMsg->GetData().m_attackPosition); } } } break; } case UpdateOrderStateMessageType: { // Cancel old order, Send Follow-Up Orders, finish manoeuvre etc UpdateOrderStateMessage* pMsg = reinterpret_cast<UpdateOrderStateMessage*>(pMessage); if(IsParticipant(pMsg->GetData().m_entityId)) { if(pMsg->GetData().m_orderState == SucceededOrderState) { // Let the entity wait for the next movement update (switch to defend?) }else if(pMsg->GetData().m_orderState == FailedOrderState) { m_pTeamAI->ReleaseEntityFromManoeuvre(pMsg->GetData().m_entityId); } } break; } default: TeamManoeuvre::ProcessMessage(pMessage); } }
explicit Vector2(FXMVECTOR v) { XMStoreFloat2(this, v); }