//-------------------------------------------------------------------------------------- // 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); } }
//-------------------------------------------------------------------------------------- // Tells whether a soldier is at a certain target or not. Accounts for the target reached // radius used by the soldier. // Param1: The target position, for which to check if the soldier has reached it. // Returns true if the soldier has reached the target, false otherwise. //-------------------------------------------------------------------------------------- bool Soldier::IsAtTarget(const XMFLOAT2& target) { float distance(0.0f); XMStoreFloat(&distance, XMVector2Length(XMLoadFloat2(&target) - XMLoadFloat2(&GetPosition()))); return (distance <= m_soldierProperties.m_targetReachedRadius); }
//-------------------------------------------------------------------------------------- // 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); } }
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; }
//-------------------------------------------------------------------------------------- // Checks for collision of a point with this collider. // Param1: The point to test. // Returns true if the point is within the collider, that includes touching its outer line, // false otherwise. //-------------------------------------------------------------------------------------- bool CircleCollider::CheckPointCollision(const XMFLOAT2& point) const { float squareRadius = GetRadius() * GetRadius(); float squareDistance = 0.0f; XMStoreFloat(&squareDistance, XMVector2LengthSq(XMLoadFloat2(&GetCentre()) - XMLoadFloat2(&point))); return squareRadius >= squareDistance; }
void FirstPersonCamera::Update(const GameTime& gameTime) { XMFLOAT2 movementAmount = Vector2Helper::Zero; if (mKeyboard != nullptr) { if (mKeyboard->IsKeyDown(DIK_W)) { movementAmount.y = 1.0f; } if (mKeyboard->IsKeyDown(DIK_S)) { movementAmount.y = -1.0f; } if (mKeyboard->IsKeyDown(DIK_A)) { movementAmount.x = -1.0f; } if (mKeyboard->IsKeyDown(DIK_D)) { movementAmount.x = 1.0f; } } XMFLOAT2 rotationAmount = Vector2Helper::Zero; if ((mMouse != nullptr) && (mMouse->IsButtonHeldDown(MouseButtons::Left))) { LPDIMOUSESTATE mouseState = mMouse->CurrentState(); rotationAmount.x = -mouseState->lX * mMouseSensitivity; rotationAmount.y = -mouseState->lY * mMouseSensitivity; } float elapsedTime = (float)gameTime.ElapsedGameTime(); XMVECTOR rotationVector = XMLoadFloat2(&rotationAmount) * mRotationRate * elapsedTime; XMVECTOR right = XMLoadFloat3(&mRight); XMMATRIX pitchMatrix = XMMatrixRotationAxis(right, XMVectorGetY(rotationVector)); XMMATRIX yawMatrix = XMMatrixRotationY(XMVectorGetX(rotationVector)); ApplyRotation(XMMatrixMultiply(pitchMatrix, yawMatrix)); XMVECTOR position = XMLoadFloat3(&mPosition); XMVECTOR movement = XMLoadFloat2(&movementAmount) * mMovementRate * elapsedTime; XMVECTOR strafe = right * XMVectorGetX(movement); position += strafe; XMVECTOR forward = XMLoadFloat3(&mDirection) * XMVectorGetY(movement); position += forward; XMStoreFloat3(&mPosition, position); Camera::Update(gameTime); }
int Map:: BuildTransform() { world_ = XMMatrixTransformation2D(XMLoadFloat2(&XMFLOAT2(0,0)), 0, XMLoadFloat2(&XMFLOAT2(scale_,scale_)), XMLoadFloat2(&XMFLOAT2(0,0)), angle_, XMLoadFloat2(&XMFLOAT2(x_,y_))); world_._43 = z_; return S_OK; }
//-------------------------------------------------------------------------------------- // 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); }
//-------------------------------------------------------------------------------------- // 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; }
//-------------------------------------------------------------------------------------- // 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; } } } }
// Transform the triangle coordinates so that they remain centered and at the right scale. // (mapping a [0,0,1,1] square into a [0,0,1,1] rectangle) inline XMFLOAT3 D3D12HDR::TransformVertex(XMFLOAT2 point, XMFLOAT2 offset) { auto scale = XMFLOAT2(min(1.0f, 1.0f / m_aspectRatio), min(1.0f, m_aspectRatio)); auto margin = XMFLOAT2(0.5f * (1.0f - scale.x), 0.5f * (1.0f - scale.y)); auto v = XMVectorMultiplyAdd( XMLoadFloat2(&point), XMLoadFloat2(&scale), XMVectorAdd(XMLoadFloat2(&margin), XMLoadFloat2(&offset))); XMFLOAT3 result; XMStoreFloat3(&result, v); return result; }
void RayTracingDemo::draw(const GameTimer & timer) { mTextureSize = { static_cast<float>(mGame->screenWidth()), static_cast<float>(mGame->screenHeight()) }; ID3D11DeviceContext * deviceContext = mGame->deviceContext(); mMaterial->TextureSize() << XMLoadFloat2(&mTextureSize); mMaterial->BlueColor() << mBlueColor; mMaterial->CameraPosition() << mCamera->positionVector(); mMaterial->InverseViewMatrix() << XMMatrixInverse(nullptr,mCamera->viewMatrix()); mMaterial->InverseProjectionMatrix() << XMMatrixInverse(nullptr, mCamera->projectionMatrix()); mMaterial->ViewMatrix() << mCamera->viewMatrix(); mMaterial->Position() << XMLoadFloat3(&mPosition); mMaterial->LightPosition() << XMLoadFloat3(&mLightPosition); mMaterial->ProjectionMatrix() << mCamera->projectionMatrix(); //mMaterial->SpherePosition() << mPosition; mMaterial->OutputTexture() << mOutputTexture; mComputePass->apply(0, deviceContext); deviceContext->Dispatch(mThreadGroupCount.x, mThreadGroupCount.y, 1); static ID3D11UnorderedAccessView * emptyUAV = nullptr; deviceContext->CSSetUnorderedAccessViews(0, 1, &emptyUAV, nullptr); mFullScreenQuad->draw(timer); }
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); }
//-------------------------------------------------------------------------------------- // Calculate the path following force and add it to the total force. // Param1: A pointer to the path to follow. // Param2: When the entity has approached the target by this distance, it counts as reached. // Param3: The speed, at which the entity should follow the path. // Returns true if the end of the current path was reached, false if there is still way to go. //-------------------------------------------------------------------------------------- bool EntityMovementManager::FollowPath(std::vector<XMFLOAT2>* pPath, float nodeReachedRadius, float speed) { if(!pPath) { return false; } if(!pPath->empty()) { // There is an active path XMFLOAT2 target = (*pPath)[m_currentNode]; // Calculate the distance between the current position of the entity and the target float distance = 0.0f; XMStoreFloat(&distance, XMVector2Length(XMLoadFloat2(&target) - XMLoadFloat2(&m_pEntity->GetPosition()))); if(distance <= nodeReachedRadius) { // The entity has reached the node ++m_currentNode; if(m_currentNode >= pPath->size()) { // Final destination reached, clear the path pPath->clear(); m_velocity = XMFLOAT2(0.0f, 0.0f); return true; }else { Seek((*pPath)[m_currentNode], nodeReachedRadius, speed); return false; } }else { Seek((*pPath)[m_currentNode], nodeReachedRadius, speed); return false; } } return true; }
//-------------------------------------------------------------------------------------- // Checks for collision of a line with this collider. // Param1: The start point of the line. // Param2: The end point of the line. // Returns true if the line intersects with the collider, that includes touching it and // being fully encompassed by it, false otherwise. //-------------------------------------------------------------------------------------- bool CircleCollider::CheckLineCollision(const XMFLOAT2& lineStart, const XMFLOAT2& lineEnd) const { if(lineStart.x == lineEnd.x && lineStart.y == lineEnd.y) { // If the points are identical, check whether that shared point lies within the collider. return CheckPointCollision(lineStart); } XMVECTOR lineSegment = XMLoadFloat2(&lineEnd) - XMLoadFloat2(&lineStart); XMVECTOR startToCollider = XMLoadFloat2(&GetCentre()) - XMLoadFloat2(&lineStart); float segmentLength = 0.0f; XMStoreFloat(&segmentLength, XMVector2Length(lineSegment)); XMVECTOR normLineSegment = lineSegment / segmentLength; float projection = 0.0f; XMStoreFloat(&projection, XMVector2Dot(startToCollider, normLineSegment)); if((projection < 0.0f) || (projection > segmentLength)) { // Projection is beyond the start or end point of the segment return false; } // Get the projected point XMVECTOR projectedPoint = XMLoadFloat2(&lineStart) + normLineSegment * projection; // Check if the projected point lies within the radius of the collider float squareRadius = GetRadius() * GetRadius(); float squareDistance = 0.0f; XMStoreFloat(&squareDistance, XMVector2Dot(XMLoadFloat2(&GetCentre()) - projectedPoint, XMLoadFloat2(&GetCentre()) - projectedPoint)); return squareRadius >= squareDistance; }
void UIObject::Draw(ID3D11DeviceContext* deviceContext, ID3D11Buffer* cBuffer, VertexShaderConstantBufferLayout* cBufferData) { batch->Draw(material->resourceView, XMFLOAT2(position.x, position.y)); font->DrawString(batch, text, XMLoadFloat2(&textPos)); }
DirectX::BoundingOrientedBox GetBoundsInOrientedSpace(_In_ bool findTightestBounds, _In_ function<bool(XMFLOAT3*)> vertGenerator) { // we find tight bounds by // 1. find the convex hull // 2. rotating calipers to find the ideal bounding box - http://en.wikipedia.org/wiki/Rotating_calipers // The idea behind rotating calipers is that we keep track of some extreme vertices, and slowly rotate our coordinate frame. // As we rotate, a vertex may no-longer be extreme in the new rotated coordinate frame, so we increment the index to the next vertex // in the convex hull that is now extreme. float zmin = FLT_MAX, zmax = -FLT_MAX; auto convexHull = FindConvexHull([&](XMFLOAT2 *planarVert, UINT32 *index) -> bool { *index = 0; // we dont' care about the index here - only useful when exposing the convex hull directly XMFLOAT3 vert; bool ret = vertGenerator(&vert); if (ret) { if (vert.z < zmin) { zmin = vert.z; } if (vert.z > zmax) { zmax = vert.z; } } *planarVert = { vert.x, vert.y }; return ret; }); // first we need to set up the calipers - extreme vertices that we will incrementally update as we rotate XMFLOAT2 maxv = convexHull[0].first; XMFLOAT2 minv = convexHull[0].first; struct RotatedBoundingBox { UINT32 maxx, maxy, minx, miny; // these represent the indices of the max/min x and y coordinates in a rotated coordated frame. float area; float minwidth; float angle; }; // find the initial orientation's bounds: RotatedBoundingBox best = { 0, 0, 0, 0, FLT_MAX, FLT_MAX, XM_2PI }; for (UINT32 i = 1; i < convexHull.size(); ++i) { const auto vertex = convexHull[i].first; if (vertex.x > maxv.x) { maxv.x = vertex.x; best.maxx = i; } else if (vertex.x < minv.x) { minv.x = vertex.x; best.minx = i; } if (vertex.y > maxv.y) { maxv.y = vertex.y; best.maxy = i; } else if (vertex.y < minv.y) { minv.y = vertex.y; best.miny = i; } } best.angle = 0; best.area = (maxv.x - minv.x) * (maxv.y - minv.y); best.minwidth = min(maxv.x - minv.x, maxv.y - minv.y); ASSERT(best.minx != best.maxx); // xmin and xmax indices should never be the same ASSERT(best.miny != best.maxy); ASSERT(best.minx <= best.maxy); // our vertices should be located around the convex hull xmin->ymax->xmax->ymin ASSERT(best.maxy <= best.maxx); ASSERT(best.maxx <= best.miny || best.minx == best.miny); ASSERT(best.miny <= best.minx + convexHull.size()); ASSERT(best.minx <= convexHull.size()); // all of the indices should be in the convex hull ASSERT(best.maxx <= convexHull.size()); ASSERT(best.miny <= convexHull.size()); ASSERT(best.maxy <= convexHull.size()); ASSERT(best.minx == 0); // we expect minx to be the first vertex in the convex hull // Helper to calculate the rotation if we move from the given vertex to the next vertex in the convex hull auto getDeltaVectorForIndex = [&](UINT32 vert) { // return the delta between the given vertex and the subsequent vertex, so we can determine the angle our bounding box // would have to rotate to be parallel with this edge auto start = convexHull[vert % convexHull.size()].first; auto next = convexHull[(vert + 1) % convexHull.size()].first; ASSERT(start.x != next.x || start.y != next.y); return XMFLOAT2({ next.x - start.x, next.y - start.y }); }; // once we have the extreme vertices, we slowly rotate our coordinate system and adjust them // we rotate in such a way that only one extreme vertex changes at a time float angle = 0; RotatedBoundingBox current = best; BoundingOrientedBox bestBoxInPlaneSpace; bestBoxInPlaneSpace.Center = { (maxv.x + minv.x) / 2, (maxv.y + minv.y) / 2, (zmax + zmin) / 2 }; bestBoxInPlaneSpace.Extents = { (maxv.x - minv.x) / 2, (maxv.y - minv.y) / 2, (zmax - zmin) / 2 }; bestBoxInPlaneSpace.Orientation = { 0, 0, 0, 1 }; if (findTightestBounds) { RotatedBoundingBox initial = best; // The tightest bounding box will share a side with the convex hull. We start with a candidate bounding box oriented along // the x/y axes and iterate through all orientations where the box is aligned with an edge of the convex hull. The maximum possible rotations // we need to consider is convexHull.size(), which would be a rotation of 90 degrees. // Each iteration through the loop, we pick the vertex from our extreme vertices that has the smallest incremental rotation along its outgoing edge. // A neat trick is that the other extreme vertices remain extreme in the new rotated orientation. while (angle <= XM_PIDIV2 + ROTATING_CALIPERS_EPSILON && current.minx <= initial.maxy && current.maxy <= initial.maxx && current.maxx <= initial.miny && current.miny <= convexHull.size()) { const auto vectForXmin = getDeltaVectorForIndex(current.minx); const auto vectForXmax = getDeltaVectorForIndex(current.maxx); const auto vectForYmin = getDeltaVectorForIndex(current.miny); const auto vectForYmax = getDeltaVectorForIndex(current.maxy); UINT32* boundIndices[4] = { ¤t.minx, ¤t.maxx, ¤t.miny, ¤t.maxy }; float angles[4] = { atan2(vectForXmin.x, vectForXmin.y), atan2(-vectForXmax.x, -vectForXmax.y), atan2(vectForYmin.y, -vectForYmin.x), atan2(-vectForYmax.y, vectForYmax.x) }; int index = 0; float minAngle = XM_PI * 4 + angle; for (int i = 0; i < 4; ++i) { if (angles[i] > -ROTATING_CALIPERS_EPSILON && angles[i] < 0) { // the vector between vertices are horizontal/vertical, so angle is close to 0, treat it as zero // this can only occur with a rounding error angles[i] = 0; } else if (angles[i] < 0) { angles[i] += XM_PI * 2; } if (angles[i] < minAngle) { minAngle = angles[i]; index = i; } } *(boundIndices[index]) = ((*(boundIndices[index])) + 1); ASSERT(current.minx <= current.maxy); // we should remain ordering of vertices xmin->ymax->xmax->ymin as we rotate ASSERT(current.maxy <= current.maxx); ASSERT(current.maxx <= current.miny || best.minx == best.miny); ASSERT(current.miny <= current.minx + convexHull.size()); ASSERT(current.minx != current.maxx); // and we shouldn't ever have min and max indices equal ASSERT(current.miny != current.maxy); // now update our box: angle = minAngle; current.angle = minAngle; if (angle < XM_PIDIV2 + ROTATING_CALIPERS_EPSILON) { XMVECTOR vertsInRotatedPlaneSpace[4]; const XMMATRIX rotationTransform = XMMatrixRotationZ(angle); for (int i = 0; i < 4; ++i) { vertsInRotatedPlaneSpace[i] = XMVector3TransformCoord(XMLoadFloat2(&convexHull[(*(boundIndices[i])) % convexHull.size()].first), rotationTransform); } BoundingOrientedBox xmBoundsInPlaneSpace; xmBoundsInPlaneSpace.Center = { XMVectorGetX(vertsInRotatedPlaneSpace[0] + vertsInRotatedPlaneSpace[1]) / 2, XMVectorGetY(vertsInRotatedPlaneSpace[2] + vertsInRotatedPlaneSpace[3]) / 2, (zmax + zmin) / 2 }; xmBoundsInPlaneSpace.Extents = { XMVectorGetX(vertsInRotatedPlaneSpace[1] - vertsInRotatedPlaneSpace[0]) / 2, XMVectorGetY(vertsInRotatedPlaneSpace[3] - vertsInRotatedPlaneSpace[2]) / 2, (zmax - zmin) / 2 }; xmBoundsInPlaneSpace.Orientation = { 0, 0, 0, 1 }; xmBoundsInPlaneSpace.Transform(xmBoundsInPlaneSpace, XMMatrixTranspose(rotationTransform)); // rotate back to plane space from rotated plane space const XMFLOAT2 size = { xmBoundsInPlaneSpace.Extents.x * 2, xmBoundsInPlaneSpace.Extents.y * 2 }; current.area = size.x * size.y; current.minwidth = min(size.x, size.y); if (current.area < best.area || (current.area == best.area && current.minwidth < best.minwidth)) { best = current; bestBoxInPlaneSpace = xmBoundsInPlaneSpace; } } } } return bestBoxInPlaneSpace; }
bool MathHelper::CompareVector2WithEpsilon(const XMFLOAT2& lhs, const XMFLOAT2& rhs) { return XMVector3NearEqual(XMLoadFloat2(&lhs), XMLoadFloat2(&rhs), XMLoadFloat2(&vector2Epsilon)) == TRUE; }
//-------------------------------------------------------------------------------------- // 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; }
XMVECTOR Float2::ToSIMD() const { return XMLoadFloat2(reinterpret_cast<const XMFLOAT2*>(this)); }
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); } }
operator XMVECTOR () const { return XMLoadFloat2(this); }
void RenderingGame::init() { // input if (FAILED(DirectInput8Create(m_instance, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&m_input, nullptr))) { throw GameException("DirectInput8Create() failed."); } m_keyboard = new Keyboard(*this, m_input); m_components.push_back(m_keyboard); m_services.add_service(Keyboard::TypeIdClass(), m_keyboard); m_mouse = new Mouse(*this, m_input); m_components.push_back(m_mouse); m_services.add_service(Mouse::TypeIdClass(), m_mouse); // render m_render_state_helper = new RenderStateHelper(*this); auto* position = new RenderTarget(*this, true, true, DXGI_FORMAT_R32G32B32A32_FLOAT); auto* normal = new RenderTarget(*this, true, false, DXGI_FORMAT_R32G32B32A32_FLOAT); auto* albedo_specular = new RenderTarget(*this, true, false); auto* color = new RenderTarget(*this, true, false); auto* color_down = new RenderTarget(*this, true, false, DXGI_FORMAT_R8G8B8A8_UNORM, 4); auto* gaussian_blur_h = new RenderTarget(*this, true, false); auto* gaussian_blur_v = new RenderTarget(*this, true, false); m_render_targets.push_back(position); m_render_targets.push_back(normal); m_render_targets.push_back(albedo_specular); m_render_targets.push_back(color); m_render_targets.push_back(color_down); m_render_targets.push_back(gaussian_blur_h); m_render_targets.push_back(gaussian_blur_v); m_render_targets_raw = new ID3D11RenderTargetView*[m_render_targets.size()]; for (UINT i = 0; i < m_render_targets.size(); i++) { m_render_targets_raw[i] = m_render_targets[i]->render_target(); } // camera m_camera = new CameraFirstPerson(*this); m_components.push_back(m_camera); // scene m_components.push_back(new EarthDemo(*this, *m_camera, L"content\\textures\\Earth.dds")); // light m_sun = new LightDirectional(*this); m_components.push_back(m_sun); m_point_light = new LightPoint(*this); m_components.push_back(m_point_light); m_point_light->set_color(1.0f, 0, 0, 1.0f); m_point_light->As<LightPoint>()->set_attenuation(1.0f, 0.04f, 0.002f); m_point_light->As<LightPoint>()->set_position(0, 10.0f, -40.0f); // projectors /*m_projector = new Camera(*this); m_components.push_back(m_projector);*/ // stencil SetCurrentDirectory(Utility::ExecutableDirectory().c_str()); m_stencil_effect = new Effect(*this); m_stencil_effect->load(L"content\\effects\\deferred_stencil.cso"); m_stencil_material = new MaterialDeferredStencil(); m_stencil_material->init(m_stencil_effect); // point light volume m_light_effect = new Effect(*this); m_light_effect->load(L"content\\effects\\deferred_p_light.cso"); m_light_material = new MaterialDeferredPLight(); m_light_material->init(m_light_effect); m_light_material->As<MaterialDeferredPLight>()-> ScreenResolution() << XMLoadFloat2(&XMFLOAT2(m_screen_width, m_screen_height)); m_model = new Model(*this, "content\\models\\Sphere.obj", true); Mesh* mesh = m_model->meshes().at(0); m_sphere = new Geometry(*this, *mesh); m_components.push_back(m_sphere); // quad m_quad_effect = new Effect(*this); m_quad_effect->load(L"content\\effects\\deferred_d_light.cso"); m_quad_material = new MaterialDeferredDLight(); m_quad_material->init(m_quad_effect); m_quad_material->As<MaterialDeferredDLight>()-> ScreenResolution() << XMLoadFloat2(&XMFLOAT2(m_screen_width, m_screen_height)); m_quad = new FullScreenQuad(*this); m_components.push_back(m_quad); // test m_test_effect = new Effect(*this); m_test_effect->load(L"content\\effects\\basic.cso"); m_test_material = new MaterialBasic(); m_test_material->init(m_test_effect); m_test_material->set_curr_technique(1); // down-sampling m_down_sampling_effect = new Effect(*this); m_down_sampling_effect->load(L"content\\effects\\down_sampling.cso"); m_down_sampling_material = new MaterialDownSampling(4); m_down_sampling_material->init(m_down_sampling_effect); // gaussian blur m_blur_effect = new Effect(*this); m_blur_effect->load(L"content\\effects\\gaussian_blur.cso"); m_blur_material = new MaterialGaussianBlur(1.5f); m_blur_material->init(m_blur_effect); // dof m_dof_effect = new Effect(*this); m_dof_effect->load(L"content\\effects\\depth_of_field.cso"); m_dof_material = new MaterialDoF(m_camera->As<CameraFirstPerson>()); m_dof_material->init(m_dof_effect); // init each component Game::init(); // after init m_camera->set_position(0, 0, 20.0f); //m_projector->set_position(m_point_light->As<LightPoint>()->positionv()); }
float VectorMath::Magnitude(const Vec2* vec) { XMVECTOR xmVec = XMLoadFloat2((_XMFLOAT2*) vec); return XMVector2Length(xmVec).m128_f32[0]; }