//-------------------------------------------------------------------------------------- // 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; }
XMFLOAT4 Weapon::GetWeaponOffsetRotation() { XMVECTOR quat = XMQuaternionIdentity(); XMFLOAT3 direction = GetFloat3Value( Direction ); XMFLOAT3 aimPos; XMFLOAT3 pipePos; if (GetJointPosition("PipeAim", aimPos) && GetJointPosition("Pipe", pipePos)) { //handPos.y = pipePos.y; XMVECTOR directionV = XMLoadFloat3(&direction); XMVECTOR handPosV = XMLoadFloat3(&aimPos); XMVECTOR pipePosV = XMLoadFloat3(&pipePos); XMVECTOR offsetDirectionV = pipePosV - handPosV; XMVECTOR angleV = XMVector3AngleBetweenVectors(directionV, offsetDirectionV); float angle; XMStoreFloat(&angle, angleV); if (angle != 0) { XMVECTOR axis = XMVector3Cross(directionV, offsetDirectionV); quat = XMQuaternionRotationAxis(axis, angle); } } XMFLOAT4 result; XMStoreFloat4(&result, quat); return result; }
//-------------------------------------------------------------------------------------- // 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); }
//-------------------------------------------------------------------------------------- // 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; }
float DistanceEstimated(const XMVECTOR& v1, const XMVECTOR& v2) { XMVECTOR& vectorSub = XMVectorSubtract(v1, v2); XMVECTOR& length = XMVector3LengthEst(vectorSub); float Distance = 0.0f; XMStoreFloat(&Distance, length); return Distance; }
//-------------------------------------------------------------------------------------- // 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; }
float LineConnection::Distance(const XMVECTOR& vector1,const XMVECTOR& vector2) { XMVECTOR vectorSub = XMVectorSubtract(vector1,vector2); XMVECTOR length = XMVector3Length(vectorSub); float distance = 0.0f; XMStoreFloat(&distance,length); return distance; }
bool Collider::IsColliding(GameObject* other) { auto otherTransform = other->transform; auto v1 = XMLoadFloat3(&transform->position); auto v2 = XMLoadFloat3(&otherTransform->position); auto vectorDiff = XMVectorSubtract(v1, v2); auto distVector = XMVector3LengthSq(vectorDiff); float dist; XMStoreFloat(&dist, distVector); float radSq = transform->scale.x * transform->scale.x*.56 + otherTransform->scale.x * otherTransform->scale.x*.56; return dist <= radSq; }
//-------------------------------------------------------------------------------------- // 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; }
//-------------------------------------------------------------------------------------- // 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; }
DWORD WINAPI ThreadedRaytracing (void* ptr) { ThreadData_t& data = *reinterpret_cast<ThreadData_t*> (ptr); ThreadData_t copy = data; data.read = true; XMVECTOR curPos = *copy.currentPos; float distance = 0.0f; for (uint64_t i = 0; i < copy.size; i++) { XMVECTOR d = XMVector3Length (XMVectorSet (copy.data[i].r, copy.data[i].g, copy.data[i].b, 0.0f) - curPos); XMStoreFloat (&distance, d); if (distance < copy.range && (distance < copy.data[i].a || copy.data[i].a < -0.5f)) copy.data[i].a = distance; } data.done++; return 0; }
vector KinectMeshAnimator::GetSkeletonOrientation(NUI_SKELETON_DATA& skeleton, int index1, int index2) { vector orientation; Joint* joint1 = bindings[index1]; Joint* joint2 = bindings[index2]; if (!joint1 || !joint2) return XMVectorSet(0.0, 1.0, 0.0, 0.0); // INVERT Z orientation = XMVectorSet( skeleton.SkeletonPositions[index2].x - skeleton.SkeletonPositions[index1].x, skeleton.SkeletonPositions[index2].y - skeleton.SkeletonPositions[index1].y, skeleton.SkeletonPositions[index1].z - skeleton.SkeletonPositions[index2].z, 0.0); vector bindOrientation = bindOrientations[index1]; vector axis = XMVector3Normalize(XMVector3Cross(bindOrientation, orientation)); if (XMVector3Equal(axis, XMVectorZero())) return XMVectorSet(0.0, 1.0, 0.0, 0.0); float angle; XMStoreFloat(&angle, XMVector3Dot(bindOrientation, orientation)); angle = acos(angle); return XMQuaternionRotationAxis(axis, angle); }
void Unit::Update(float DeltaTime, Terrain* TerrainInstance) { if ( IsAlive() && gHealth.first <= 0 ) { SetWeaponState( Hold ); DropWeapon(); Kill(); StopAllAnimations(); PlayAnimation("Death"); PlayAnimationAfter("Death", "Dead"); SoundManager::GetInstance()->Play( gDeathSound, SFX, false ); if (!PlayingAnimation("Death")) { SetState( Dead ); return; } } GameObject::Update(DeltaTime, TerrainInstance); if ( GetState() == Dying ) return; XMVECTOR vel = XMLoadFloat3(&GetFloat3Value( Velocity )); if (!XMVector3Equal(vel, XMVectorZero())) { XMVECTOR dir = XMLoadFloat3(&GetFloat3Value( Direction )); XMVECTOR angleV = XMVector3AngleBetweenVectors(dir, vel); float angle; XMStoreFloat(&angle, angleV); XMVECTOR crossV = XMVector3Cross(dir, vel); if (XMVectorGetY(crossV) < 0) angle *= -1; //cout << 180 * angle / PI << endl; if (fabs(angle) <= PI * 0.25f) gMoveDirection = Forward; else if (fabs(angle) > PI * 0.75f) gMoveDirection = Back; else if (angle < 0) gMoveDirection = Left; else if (angle > 0) gMoveDirection = Right; XMVECTOR L = XMVector3Length(vel); float speed; XMStoreFloat(&speed, L); speed /= UnitsPerMeter; switch (gMoveDirection) { case Forward: if (speed > 1.05f * gWalkSpeed) { SetMoveState(Run); SetAnimationSpeed("Run", speed); SetAnimationSpeed(GetAnimation("UpperRun"), speed); } else { SetMoveState(Walk); SetAnimationSpeed("Walk", speed); } break; case Back: SetMoveState(Walk); SetAnimationSpeed("Back", speed); break; case Right: SetMoveState(Walk); SetAnimationSpeed("SideStepRight", speed); break; case Left: SetMoveState(Walk); SetAnimationSpeed("SideStepLeft", speed); break; } } else { gMoveDirection = None; if (!Crouching()) SetMoveState(Stand); } if ( gCurrentWeapon ) { XMFLOAT3 handPos; XMFLOAT4 handRot; XMVECTOR pos = XMLoadFloat3(&GetFloat3Value( Position )); XMVECTOR dir = XMLoadFloat3(&GetFloat3Value( Direction )); XMVECTOR lv = XMVector3Length(dir); bool gotJointPos = false; bool gotJointRot = false; if (m_ModelInstance) { gotJointPos = GetJointPosition("RightHand", handPos); gotJointRot = GetJointRotation("RightHand", handRot); } if (!gotJointPos) { pos += dir * (GetRadius() - 10); XMStoreFloat3(&handPos, pos); } if (gCurrentWeapon->NeedReload()) { ReloadWeapon(); } //gWeapon->Update(DeltaTime); //gWeapon->MoveTo( position ); gCurrentWeapon->MoveTo( handPos ); XMFLOAT3 weaponPos; if (gCurrentWeapon->GetJointPosition("RightHand", weaponPos)) { XMStoreFloat3(&handPos, XMLoadFloat3(&handPos) + (XMLoadFloat3(&handPos) - XMLoadFloat3(&weaponPos))); gCurrentWeapon->MoveTo( handPos ); } if (gotJointRot) { gCurrentWeapon->SetRotation( handRot ); } else gCurrentWeapon->SetRotation( GetQuaternation() ); } /* else { LoopAnimation("PistolUpperWalk"); } */ }
//----------------------------------------------------------------------------- // Compute the intersection of a ray (Origin, Direction) with an axis aligned // box using the slabs method. //----------------------------------------------------------------------------- BOOL GLibIntersectRayAxisAlignedBox( FXMVECTOR Origin, FXMVECTOR Direction, const XNA::AxisAlignedBox* pVolume, FLOAT* pDist ) { XMASSERT( pVolume ); XMASSERT( pDist ); //XMASSERT( XMVector3IsUnit( Direction ) ); static const XMVECTOR Epsilon = { 1e-20f, 1e-20f, 1e-20f, 1e-20f }; static const XMVECTOR FltMin = { -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX }; static const XMVECTOR FltMax = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX }; // Load the box. XMVECTOR Center = XMLoadFloat3( &pVolume->Center ); XMVECTOR Extents = XMLoadFloat3( &pVolume->Extents ); // Adjust ray origin to be relative to center of the box. XMVECTOR TOrigin = Center - Origin; // Compute the dot product againt each axis of the box. // Since the axii are (1,0,0), (0,1,0), (0,0,1) no computation is necessary. XMVECTOR AxisDotOrigin = TOrigin; XMVECTOR AxisDotDirection = Direction; // if (fabs(AxisDotDirection) <= Epsilon) the ray is nearly parallel to the slab. XMVECTOR IsParallel = XMVectorLessOrEqual( XMVectorAbs( AxisDotDirection ), Epsilon ); // Test against all three axii simultaneously. XMVECTOR InverseAxisDotDirection = XMVectorReciprocal( AxisDotDirection ); XMVECTOR t1 = ( AxisDotOrigin - Extents ) * InverseAxisDotDirection; XMVECTOR t2 = ( AxisDotOrigin + Extents ) * InverseAxisDotDirection; // Compute the max of min(t1,t2) and the min of max(t1,t2) ensuring we don't // use the results from any directions parallel to the slab. XMVECTOR t_min = XMVectorSelect( XMVectorMin( t1, t2 ), FltMin, IsParallel ); XMVECTOR t_max = XMVectorSelect( XMVectorMax( t1, t2 ), FltMax, IsParallel ); // t_min.x = maximum( t_min.x, t_min.y, t_min.z ); // t_max.x = minimum( t_max.x, t_max.y, t_max.z ); t_min = XMVectorMax( t_min, XMVectorSplatY( t_min ) ); // x = max(x,y) t_min = XMVectorMax( t_min, XMVectorSplatZ( t_min ) ); // x = max(max(x,y),z) t_max = XMVectorMin( t_max, XMVectorSplatY( t_max ) ); // x = min(x,y) t_max = XMVectorMin( t_max, XMVectorSplatZ( t_max ) ); // x = min(min(x,y),z) // if ( t_min > t_max ) return FALSE; XMVECTOR NoIntersection = XMVectorGreater( XMVectorSplatX( t_min ), XMVectorSplatX( t_max ) ); // if ( t_max < 0.0f ) return FALSE; NoIntersection = XMVectorOrInt( NoIntersection, XMVectorLess( XMVectorSplatX( t_max ), XMVectorZero() ) ); // if (IsParallel && (-Extents > AxisDotOrigin || Extents < AxisDotOrigin)) return FALSE; XMVECTOR ParallelOverlap = XMVectorInBounds( AxisDotOrigin, Extents ); NoIntersection = XMVectorOrInt( NoIntersection, XMVectorAndCInt( IsParallel, ParallelOverlap ) ); if(!GLibXMVector3AnyTrue( NoIntersection ) ) { // Store the x-component to *pDist XMStoreFloat( pDist, t_min ); return TRUE; } return FALSE; }
//----------------------------------------------------------------------------- // Compute the intersection of a ray (Origin, Direction) with a triangle // (V0, V1, V2). Return TRUE if there is an intersection and also set *pDist // to the distance along the ray to the intersection. // // The algorithm is based on Moller, Tomas and Trumbore, "Fast, Minimum Storage // Ray-Triangle Intersection", Journal of Graphics Tools, vol. 2, no. 1, // pp 21-28, 1997. //----------------------------------------------------------------------------- BOOL GLibIntersectRayTriangle( FXMVECTOR Origin, FXMVECTOR Direction, FXMVECTOR V0, CXMVECTOR V1, CXMVECTOR V2, FLOAT* pDist ) { XMASSERT( pDist ); //XMASSERT( XMVector3IsUnit( Direction ) ); static const XMVECTOR Epsilon = { 1e-20f, 1e-20f, 1e-20f, 1e-20f }; XMVECTOR Zero = XMVectorZero(); XMVECTOR e1 = V1 - V0; XMVECTOR e2 = V2 - V0; // p = Direction ^ e2; XMVECTOR p = XMVector3Cross( Direction, e2 ); // det = e1 * p; XMVECTOR det = XMVector3Dot( e1, p ); XMVECTOR u, v, t; if( XMVector3GreaterOrEqual( det, Epsilon ) ) { // Determinate is positive (front side of the triangle). XMVECTOR s = Origin - V0; // u = s * p; u = XMVector3Dot( s, p ); XMVECTOR NoIntersection = XMVectorLess( u, Zero ); NoIntersection = XMVectorOrInt( NoIntersection, XMVectorGreater( u, det ) ); // q = s ^ e1; XMVECTOR q = XMVector3Cross( s, e1 ); // v = Direction * q; v = XMVector3Dot( Direction, q ); NoIntersection = XMVectorOrInt( NoIntersection, XMVectorLess( v, Zero ) ); NoIntersection = XMVectorOrInt( NoIntersection, XMVectorGreater( u + v, det ) ); // t = e2 * q; t = XMVector3Dot( e2, q ); NoIntersection = XMVectorOrInt( NoIntersection, XMVectorLess( t, Zero ) ); if( XMVector4EqualInt( NoIntersection, XMVectorTrueInt() ) ) return FALSE; } else if( XMVector3LessOrEqual( det, -Epsilon ) ) { // Determinate is negative (back side of the triangle). XMVECTOR s = Origin - V0; // u = s * p; u = XMVector3Dot( s, p ); XMVECTOR NoIntersection = XMVectorGreater( u, Zero ); NoIntersection = XMVectorOrInt( NoIntersection, XMVectorLess( u, det ) ); // q = s ^ e1; XMVECTOR q = XMVector3Cross( s, e1 ); // v = Direction * q; v = XMVector3Dot( Direction, q ); NoIntersection = XMVectorOrInt( NoIntersection, XMVectorGreater( v, Zero ) ); NoIntersection = XMVectorOrInt( NoIntersection, XMVectorLess( u + v, det ) ); // t = e2 * q; t = XMVector3Dot( e2, q ); NoIntersection = XMVectorOrInt( NoIntersection, XMVectorGreater( t, Zero ) ); if ( XMVector4EqualInt( NoIntersection, XMVectorTrueInt() ) ) return FALSE; } else { // Parallel ray. return FALSE; } XMVECTOR inv_det = XMVectorReciprocal( det ); t *= inv_det; // u * inv_det and v * inv_det are the barycentric cooridinates of the intersection. // Store the x-component to *pDist XMStoreFloat( pDist, t ); return TRUE; }
BSphere ComputeBoundingSphereFromPoints(const XMFLOAT3* points, uint32 numPoints, uint32 stride, BBox *optionalBBoxOut) { BSphere sphere; Assert_(numPoints > 0); Assert_(points); // Find the points with minimum and maximum x, y, and z XMVECTOR MinX, MaxX, MinY, MaxY, MinZ, MaxZ; MinX = MaxX = MinY = MaxY = MinZ = MaxZ = XMLoadFloat3(points); GetBoundCornersFromPoints(points, numPoints, stride, MinX, MaxX, MinY, MaxY, MinZ, MaxZ); /*for (uint32 i = 1; i < numPoints; i++) { XMVECTOR Point = XMLoadFloat3((XMFLOAT3*)((BYTE*)points + i * stride)); float px = XMVectorGetX(Point); float py = XMVectorGetY(Point); float pz = XMVectorGetZ(Point); if (px < XMVectorGetX(MinX)) MinX = Point; if (px > XMVectorGetX(MaxX)) MaxX = Point; if (py < XMVectorGetY(MinY)) MinY = Point; if (py > XMVectorGetY(MaxY)) MaxY = Point; if (pz < XMVectorGetZ(MinZ)) MinZ = Point; if (pz > XMVectorGetZ(MaxZ)) MaxZ = Point; }*/ if (optionalBBoxOut != NULL) { float maxx = XMVectorGetX(MaxX); float maxy = XMVectorGetY(MaxY); float maxz = XMVectorGetZ(MaxZ); float minx = XMVectorGetX(MinX); float miny = XMVectorGetY(MinY); float minz = XMVectorGetZ(MinZ); optionalBBoxOut->Max.x = maxx; optionalBBoxOut->Max.y = maxy; optionalBBoxOut->Max.z = maxz; optionalBBoxOut->Min.x = minx; optionalBBoxOut->Min.y = miny; optionalBBoxOut->Min.z = minz; } // Use the min/max pair that are farthest apart to form the initial sphere. XMVECTOR DeltaX = MaxX - MinX; XMVECTOR DistX = XMVector3Length(DeltaX); XMVECTOR DeltaY = MaxY - MinY; XMVECTOR DistY = XMVector3Length(DeltaY); XMVECTOR DeltaZ = MaxZ - MinZ; XMVECTOR DistZ = XMVector3Length(DeltaZ); XMVECTOR Center; XMVECTOR Radius; if (XMVector3Greater(DistX, DistY)) { if (XMVector3Greater(DistX, DistZ)) { // Use min/max x. Center = (MaxX + MinX) * 0.5f; Radius = DistX * 0.5f; } else { // Use min/max z. Center = (MaxZ + MinZ) * 0.5f; Radius = DistZ * 0.5f; } } else // Y >= X { if (XMVector3Greater(DistY, DistZ)) { // Use min/max y. Center = (MaxY + MinY) * 0.5f; Radius = DistY * 0.5f; } else { // Use min/max z. Center = (MaxZ + MinZ) * 0.5f; Radius = DistZ * 0.5f; } } // Add any points not inside the sphere. for (uint32 i = 0; i < numPoints; i++) { XMVECTOR Point = XMLoadFloat3((XMFLOAT3*)((BYTE*)points + i * stride)); XMVECTOR Delta = Point - Center; XMVECTOR Dist = XMVector3Length(Delta); if (XMVector3Greater(Dist, Radius)) { // Adjust sphere to include the new point. Radius = (Radius + Dist) * 0.5f; Center += (XMVectorReplicate(1.0f) - Radius * XMVectorReciprocal(Dist)) * Delta; } } XMStoreFloat3(&sphere.Center, Center); XMStoreFloat(&sphere.Radius, Radius); return sphere; }