/*------------------------------------------------------------------------------* | <<< 球と線分の交差判定 >>> | 入力 pvecSphere = 球の中心座標 | fRadius = 球の大きさ | pvecLine = 線分の始点 | pvecDir = 線分の向き | 戻り値 TRUE : ヒットしている *------------------------------------------------------------------------------*/ BOOL collision_sphere_ray(VEC3 *pvecSphere, float fR, VEC3 *pvecLine, VEC3 *pvecDir) { VEC3 e = *pvecSphere; VEC3 v; D3DXVec3Normalize(&v, pvecDir); VEC3 r = *pvecLine - *pvecSphere; VEC3 a = D3DXVec3Dot( &e, &v) * v - e; VEC3 c = r - D3DXVec3Dot(&r, &v) * v; float fAlpha = D3DXVec3LengthSq(&a); float fBeta = D3DXVec3Dot( &a, &c); float fOmega = D3DXVec3LengthSq(&c) - fR * fR; // 衝突判定 float tmp = fBeta * fBeta - fAlpha * fOmega; // 衝突しないか止まっている場合は不正値を返す if(fabs(fAlpha) <= EPSIRON || tmp < 0) { // 既にめり込んでいる場合は衝突を返す if(fOmega < 0.0f){ return TRUE;} return FALSE; } // 現在の位置でめり込んでいるかチェック if(fOmega < 0.0f){ return TRUE;} // 指定の間では衝突しない return FALSE; }
//Closest Point to ... D3DXVECTOR3 ClosestPtOnPolygon(D3DXVECTOR3 A, D3DXVECTOR3 B, D3DXVECTOR3 C, D3DXVECTOR3 P) { D3DXVECTOR3 Rab = ClosestPtOnLine(A, B, P); D3DXVECTOR3 Rbc = ClosestPtOnLine(B, C, P); D3DXVECTOR3 Rca = ClosestPtOnLine(C, A, P); D3DXVECTOR3 vDist0 = Rab - P; float SqDist0 = D3DXVec3LengthSq(&vDist0); D3DXVECTOR3 vDist1 = Rbc - P; float SqDist1 = D3DXVec3LengthSq(&vDist1); D3DXVECTOR3 vDist2 = Rca - P; float SqDist2 = D3DXVec3LengthSq(&vDist2); float Min = FLT_MAX; D3DXVECTOR3 pClosest; if(SqDist0 <= Min) { Min = SqDist0; pClosest = Rab; } if(SqDist1 <= Min) { Min = SqDist1; pClosest = Rbc; } if(SqDist2 <= Min) { Min = SqDist2; pClosest = Rca; } return pClosest; }
void Monai::LaserModeStart(){ D3DXVECTOR3 length = g_vec3LaserPosition - pCha->GetPosition(); FLOAT M = D3DXVec3LengthSq(&length); if(D3DXVec3LengthSq(&length)<(MYSIZE+LASER_SIZE)*(MYSIZE*LASER_SIZE)*g_fLaserLength){ pUI->DamageUI(); pCha->SetLife(g_fLaserDamage); } }
bool Enemy::noticeFollower() { bool returnBool = false; D3DXVECTOR3 followerPos = gFollower->getPosition(); float distanceSq = D3DXVec3LengthSq(&(mPosition - followerPos)); if (distanceSq > mSightRangeSq)//if not within range, they can't see follower { bAttackFollower = false; return false; } // they are close enough to hear the follower through a wall or behind them if (distanceSq < mHearRangeSq) returnBool = true; //if the follower would be behind the enemy, they don't get a chance to see them //current enemy rotation is mRotation.y //find rotation towards follower D3DXVECTOR3 toFollower = gFollower->getPosition() - mPosition; float followerDirection = atan2(toFollower.x, toFollower.z); //if not within VISION_RANGE degrees/PI radians of each other //this only applies if the player has not injured them. If player has, they are more //watchful if (mHealth == mHealthMax && returnBool == false) { //1.57 ~ 1/2 * PI 6.28 ~ 2 * PI if ((fabs(followerDirection - mRotation.y) > 1.57) && ((fabs(followerDirection - 6.28)) + mRotation.y > 1.57) && ((fabs(mRotation.y - 6.28)) + followerDirection > 1.57)) { bAttackFollower = false; return false; } } //if they are between max hearing and max sight range, see if they are line of sight to player //make a line segment between enemy and player location //only take into account x and z here since map is flat, will save time LineSegment line3D(mPosition, followerPos); for (Mesh* M : gCurrentLevel->getWorldGeometry()) { for (AxisAlignedBoundingBox AABB : M->getBoundsBoxList()) { //if further out than sight range, no point in checking it if (D3DXVec3LengthSq(&(AABB.mMin - mPosition)) > mSightRangeSq) continue; //see if it collides with the line if (collides(AABB, line3D)) { bAttackPlayer = false; return returnBool; } } } //if it gets through the above checks, then it can see the player mLoseSightFollower = 0.0f; bAttackFollower = true; bSeenPlayer = true; return true; }
/************************************************************************* * D3DXSphereBoundProbe */ BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *pcenter, FLOAT radius, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection) { D3DXVECTOR3 difference; FLOAT a, b, c, d; a = D3DXVec3LengthSq(praydirection); if (!D3DXVec3Subtract(&difference, prayposition, pcenter)) return FALSE; b = D3DXVec3Dot(&difference, praydirection); c = D3DXVec3LengthSq(&difference) - radius * radius; d = b * b - a * c; if ( ( d <= 0.0f ) || ( sqrt(d) <= b ) ) return FALSE; return TRUE; }
BOOL cCollision::IntersectLineSphere( cLine& Line,cSphere& TargetSphere,float* pT/*=NULL*/,float* pPiercedDist/*=NULL*/,D3DXVECTOR3* pReflectionVec/*=NULL*/) { D3DXVECTOR3 vecLineStartToSphereCenter; D3DXVECTOR3 NearPiercedPos,FarPiercedPos; float CrossToCenter_LengthSQ; //구의중점에서 직선에 내린 수선의길이SQ float CrossToPierced_Legnth; //라인과수선교점에서부터 관통점까지의 길이 float projection_length; //직선시작점과 구의 중점의 내적에의한 투영길이 vecLineStartToSphereCenter= TargetSphere.GetCenterPos() - Line.GetStart(); // 구의중점과 라인의시작점 거리검사로 원안에 라인의 시작점이 있는지 검사한다. (충돌여부만 검사할때 필요) if ((pT==NULL)&&(pPiercedDist==NULL)&&(pReflectionVec==NULL)) { if (D3DXVec3LengthSq(&vecLineStartToSphereCenter) < TargetSphere.GetRadiusSQ()) return TRUE; } // 라인의 방향벡터를 기준으로 90~270 도 즉 뒤쪽에 있는지 검사 projection_length=D3DXVec3Dot(&vecLineStartToSphereCenter,&Line.GetDirection()); if( projection_length< 0 ) return FALSE; // 수선교점과 구중점사이의 거리검사 CrossToCenter_LengthSQ = D3DXVec3LengthSq(&vecLineStartToSphereCenter) - projection_length*projection_length; if (CrossToCenter_LengthSQ >= TargetSphere.GetRadiusSQ()) return FALSE; // 이제 완전 충돌 // 직선의 시작점에서부터의 거리 if (pT!=NULL) *pT=projection_length; //수선교점과 관통점 사이의 거리를 구한다. if (pPiercedDist!=NULL) { CrossToPierced_Legnth = sqrt(TargetSphere.GetRadiusSQ() - CrossToCenter_LengthSQ); *pPiercedDist=CrossToPierced_Legnth; } // 반사벡터를 구한다. if (pReflectionVec!=NULL) { D3DXVECTOR3 CrossPos,CrossNormal; CrossPos= Line.GetDirection()*projection_length; CrossNormal = TargetSphere.GetCenterPos() - CrossPos; *pReflectionVec = (2.0f * CrossNormal) + vecLineStartToSphereCenter; } return TRUE; }
bool Minion::CollisionMonsters(D3DXVECTOR3* direction) { bool collision = false; if (!monsters.empty()) { for (auto iter = monsters.begin(); iter != monsters.end(); ++iter) { collision = Collision::IsSphereToSphere(boundingSphere, (*iter)->GetBoundingSphereValue()); if (collision) { *direction = boundingSphere.center - (*iter)->GetBoundingSphereValue().center; if (D3DXVec3LengthSq(direction) > 0.3) { break; } else { continue; } } } } return collision; }
void cameraObject::shoot(GameObject* player) { if(D3DXVec3LengthSq(&aimVec) > cameraNS::RANGE*cameraNS::RANGE) return; if(!active) return; if (timeSinceLastShot > 0.5) timeSinceLastShot = 0; else return; int index = -1; for (int i = 0; i < bullets.size(); i++) { if (!bullets[i]->getActiveState()) { //If the bullet at index i is not in use index = i; i = bullets.size(); } } if (index == -1) return; bullets[index]->setPosition(position); bullets[index]->setSpeed(bulletNS::SPEED); D3DXVec3Normalize(&aimVec, &aimVec); bullets[index]->setVelocity(aimVec); bullets[index]->setActive(); //bullet->setPosition(position); //Vector3 aimVec = player->getPosition() - position; //if(D3DXVec3Length(&aimVec) > cameraNS::RANGE) return; //D3DXVec3Normalize(&aimVec, &aimVec); //bullet->setVelocity(aimVec * bulletNS::SPEED); //bullet->setActive(); // }
__forceinline void FindNearestPointOnLineSegment(const D3DXVECTOR3 & A1, const D3DXVECTOR3 & L, const D3DXVECTOR3 & B, D3DXVECTOR3 & Nearest, float ¶meter) { // Line/Segment is degenerate --- special case #1 float D = D3DXVec3LengthSq(&L); if (D < MY_EPSILON*MY_EPSILON) { Nearest = A1; return; } D3DXVECTOR3 AB = B-A1; // parameter is computed from Equation (20). parameter = (D3DXVec3Dot(&AB,&L)) / D; //if (false == infinite_line) parameter = FMAX(0.0f, FMIN(1.0f, parameter)); Nearest = A1 + parameter * L; return; }
bool BoundingSphere::containsPoint(const D3DXVECTOR3 &point) const { D3DXVECTOR3 distFromCenter; D3DXVec3Subtract(&distFromCenter, &point, ¢er); return D3DXVec3LengthSq(&distFromCenter) <= (radius * radius); }
void Follower::pointForward(float _dt) { //if they aren't moving, do nothing if (D3DXVec3LengthSq(&mVelocity) == 0.0f) return; //face the direction it is going float targetDir = atan2(mVelocity.x, mVelocity.z) + D3DX_PI;//target direction float angleDiff;//difference between angle we have and angle we want float pi2 = 2 * D3DX_PI;//2 * PI (full circle in radians) float facingMinusTarget = mRotation.y - targetDir;//vector difference between present rotation and target if (fabs(facingMinusTarget) > D3DX_PI)//if the angle we get is > half a circle {//figure angle difference to make it smaller if (mRotation.y > targetDir) angleDiff = -(pi2 - mRotation.y + targetDir); else angleDiff = pi2 - targetDir + mRotation.y; } else//else the angle difference we have is ok angleDiff = facingMinusTarget; if (angleDiff > 0.0f) mRotation.y -= 3.0f * _dt; else if (angleDiff < 0.0f) mRotation.y += 3.0f * _dt; }
void BaseMpOnlineAIObject::UpdateOnlineEntity(float dt) { D3DXVECTOR3 normDir = (m_TargetLocation-m_Owner->GetPhysicsPointer()->m_Position); float mag = D3DXVec3LengthSq(&normDir); D3DXVec3Normalize(&normDir,&normDir); m_Owner->GetPhysicsPointer()->addForce((normDir*mag*dt)); }
void ElCamera::setDirection(const D3DXVECTOR3& vec) { // Do nothing if given a zero vector if (vec == D3DXVECTOR3(0.0f, 0.0f, 0.0f)) return; D3DXVECTOR3 adjustVec = vec; if (mYawFixed) adjustVec.y = 0.0f; D3DXVec3Normalize(&adjustVec, &adjustVec); D3DXMATRIX m; if (D3DXVec3LengthSq(&(D3DXVECTOR3(0.0f, 0.0f, 1.0f) + adjustVec)) < 0.00005f) { // Oops, a 180 degree turn (infinite possible rotation axes) // Default to yaw i.e. use current DOWN D3DXMatrixRotationAxis(&m, &D3DXVECTOR3(0.0f, -1.0f, 0.0f), D3DX_PI); } else { D3DXVECTOR3 axe; D3DXVec3Cross(&axe, &D3DXVECTOR3(0.0f, 0.0f, 1.0f), &adjustVec); float dot = D3DXVec3Dot(&D3DXVECTOR3(0.0f, 0.0f, 1.0f), &adjustVec); D3DXMatrixRotationAxis(&m, &axe, acos(dot)); } mLook = vec; D3DXVec3TransformCoord(&mUp, &D3DXVECTOR3(0.0f, 1.0f, 0.0f), &m); D3DXVec3TransformCoord(&mRight, &D3DXVECTOR3(1.0f, 0.0f, 0.0f), &m); calcViewOrientation(); invalidateView(); }
float ElBillboardChain::getSquaredViewDepth(ElCamera* cam) const { // we only need this for transparent objects float dist = 0.0f; if (mParentNode) dist = D3DXVec3LengthSq(&(mParentNode->getDerivedPosition() - cam->getRealPosition())); return dist; }
//**関数*************************************************************************** // 概要 : 拡大球判定 //********************************************************************************* bool CCalc::IntersectSphere(CHitCircle circleA , CHitCircle circleB) { float fDist = D3DXVec3LengthSq(&(circleA.m_Point - circleB.m_Point)); float fRadi = powf(circleA.m_fRadius + circleB.m_fRadius , 2.0f); if(fRadi > fDist) return true; else return false; }
float ElRibbonTrail::getSquaredViewDepth(ElCamera* cam) const { // we only need this for transparent objects float dist = 0.0f; if (!mTraceList.empty()) dist = D3DXVec3LengthSq(&(mTraceList[0] - cam->getRealPosition())); return dist; }
bool GameObjectBullet::collided(GameObjectBullet *gameObject) { Vector3 diff = position - gameObject->getPosition(); float length = D3DXVec3LengthSq(&diff); float radii = radiusSquared + gameObject->getRadiusSquare(); if (length <= radii) return true; return false; }
void CPartyMng::PartyMapInfo( ) { const float PARTY_MAP_AROUND = 32.0f * 32.0f; // m_nVisibilityRange에 영향을 받는다. if( ++m_nSecCount < PARTY_MAP_SEC ) return; m_nSecCount = 0; D3DXVECTOR3 vPosBuf; float fDist; for( C2PartyPtr::iterator i = m_2PartyPtr.begin(); i != m_2PartyPtr.end(); ++i ) { CParty* pParty = (CParty*)i->second; for( int j = 0 ; j < pParty->GetSizeofMember() ; ++j ) { CMover* pMover = prj.GetUserByID( pParty->GetPlayerId( j ) ); if( !IsValidObj( pMover ) ) continue; vPosBuf = pMover->GetPos() - pParty->GetPos( j ); fDist = D3DXVec3LengthSq( &vPosBuf ); if( 0.0f < fDist ) { pParty->SetPos( j, pMover->GetPos() ); CMover* pSendMover; for( int k = 0 ; k < pParty->GetSizeofMember() ; ++k ) { if( k == j ) continue; pSendMover = prj.GetUserByID( pParty->GetPlayerId( k ) ); if( !IsValidObj( pSendMover ) ) continue; vPosBuf = pSendMover->GetPos() - pMover->GetPos(); fDist = D3DXVec3LengthSq( &vPosBuf ); if( fDist > PARTY_MAP_AROUND ) ((CUser*)pSendMover)->AddPartyMapInfo( j, pMover->GetPos() ); } } } } }
BOOL cCollision::IntersectSphereSphere( cSphere& SphereA,cSphere& SphereB ) { float LengthSq=D3DXVec3LengthSq( &D3DXVECTOR3(SphereB.GetCenterPos() - SphereA.GetCenterPos())); if ((SphereA.GetRadiusSQ()+SphereB.GetRadiusSQ())<=LengthSq) { return FALSE; } return TRUE; }
//-------------------------------------------------------------------------------------- void SortParticles( D3DXVECTOR3 vEye ) { for( UINT i = 0; i < g_NumUsedParticles; i++ ) { g_pParticleIndices[i] = i; D3DXVECTOR3 vDelta = vEye - g_pParticleArray[i].vPos; g_pParticleDepths[i] = D3DXVec3LengthSq( &vDelta ); } QuickDepthSort( g_pParticleIndices, g_pParticleDepths, 0, g_NumUsedParticles - 1 ); }
//follow the path, return false if you are out of path to follow bool Follower::followPath(float _speed) { if (mPath.size() > (UINT)2) { //to make it a bit smoother, it goes towards the next to last node instead //of the last one, then pops the last node off once it's closer to the next to last //node than the last one int lastIndex = mPath.size() - 1; float distLast = D3DXVec3LengthSq(&(mPosition - mPath[lastIndex])); float distNext = D3DXVec3LengthSq(&(mPosition - mPath[lastIndex - 1])); if (distNext < distLast) { mPath.pop_back(); --lastIndex; } mVelocity = mPath[lastIndex - 1] - mPosition; D3DXVec3Normalize(&mVelocity, &mVelocity);//normalize to 1 unit length vector mVelocity *= (mSpeed * _speed);//multiply by speed, wandering is slower return true; } //if the path is getting short, go ahead to the next/last node else if (mPath.size() > (UINT)1) { //if you are near the next node, take it off and go to the next one int lastIndex = mPath.size() - 1; float distLast = D3DXVec3LengthSq(&(mPosition - mPath[lastIndex])); if (distLast < 100)//within 10 units { mPath.pop_back(); --lastIndex; } //go towards the next node mVelocity = mPath[lastIndex] - mPosition;//find vector between the two points D3DXVec3Normalize(&mVelocity, &mVelocity);//normalize to 1 unit length vector mVelocity *= (mSpeed * _speed);//multiply by speed, wandering is slower return true; } else //if shorter than that, we need to redo it return false; }
////////////////////////////////////////////////////////////////////////// // SetExplosion ////////////////////////////////////////////////////////////////////////// void ZClothEmblem::setExplosion( rvector& pos_, float power_ ) { rvector dir = m_pX[0] - pos_; float lengthsq = D3DXVec3LengthSq( &dir ); if( lengthsq > 250000 ) // 5미터 안의 것들만 영향을 받음.. { return; } D3DXVec3Normalize( &dir, &dir ); *mpWind += dir * power_ / sqrt(lengthsq) * 10; }
BSPSector* BSP::sectorRender(BSPSector* sector) { if( intersectAABBFrustum( §or->_boundingBox, Camera::frustrum ) ) { if( sector->_leftSubset ) { sector->_lsc = sector->_leftSubset->getBoundingBox()->inf + 0.5f * ( sector->_leftSubset->getBoundingBox()->sup - sector->_leftSubset->getBoundingBox()->inf ); sector->_rsc = sector->_rightSubset->getBoundingBox()->inf + 0.5f * ( sector->_rightSubset->getBoundingBox()->sup - sector->_rightSubset->getBoundingBox()->inf ); sector->_lsd = Camera::eyePos - sector->_lsc; sector->_rsd = Camera::eyePos - sector->_rsd; if( D3DXVec3LengthSq( §or->_lsd ) < D3DXVec3LengthSq( §or->_rsd ) ) { sectorRender( sector->_leftSubset ); sectorRender( sector->_rightSubset ); } else { sectorRender( sector->_rightSubset ); sectorRender( sector->_leftSubset ); } } else { sector->render(); if( Engine::instance->getRenderMode() & engine::rmBSPAABB ) { if( sector->_atomicsInSector.size() ) { dxRenderAABB( sector->getBoundingBox(), &green, NULL ); } else { dxRenderAABB( sector->getBoundingBox(), &yellow, NULL ); } } } } return sector; }
void CPlayer::CollideWithPlayer( CPlayer* pPlayer ) { D3DXVECTOR3 vLocalPos = GetPosition(); D3DXVECTOR3 vLocalVel = GetVelocity(); float fLocalRad = GetRadius(); D3DXVECTOR3 vPos = pPlayer->GetPosition(); D3DXVECTOR3 vVel = pPlayer->GetVelocity(); float fRad = pPlayer->GetRadius(); //----------------------------------------------------------------------------------------- // o/__ <-- BreakdancinBob TODO: Sqrt seems to be the main bottleneck here. The sqrt // | (\ function lives inside of D3DXVec3Length. However, // that's not the entire problem. Even optimizing the sqrt // here may not give us a huge performance gain. We also // need to look at why this function is being called so // often. // // HINT: Go to exercise01.cpp and look for breakdancin' bob there. // He may have some hints on how to avoid doing so many // collisions. //----------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------- // Answer // Move the sqrt to occur after the proximity check. Also, use sqrtf, instead of sqrt. // This only gives a moderate speedup. Exercise01.cpp also needs to change to call this // function less often. // Find the normal of collision between the two balls D3DXVECTOR3 vNormal = vLocalPos - vPos; float length = D3DXVec3LengthSq( &vNormal ); float fRadSq = fLocalRad + fRad; fRadSq *= fRadSq; if( length >= fRadSq ) return; // NOW, do the sqrtf length = sqrtf( length ); // normalize vNormal /= length; // Push the ball a little more than half way from the collision m_vPosition[1] += vNormal * ( ( fLocalRad + fRad ) - length ) / 1.99f; D3DXVECTOR3 Vab; Vab = vLocalVel - vVel; float j = -( 0.9f ) * D3DXVec3Dot( &Vab, &vNormal ); m_vVelocity[1] = vLocalVel + j * vNormal; }
void CZombieTrackingState::Excute(CEntity* _ett) { CZombie* zombie = (CZombie*)_ett; D3DXVECTOR3 vLen = _ett->GetPos() - zombie->GetHero()->GetPos(); //추적하다 사정거리로 들어오면 공격 if( D3DXVec3LengthSq( &vLen) < pow(zombie->GetRange(), 2) ) zombie->GetFSM()->ChangeState( _SINGLE(CZombieAttackState) ); //추적하다가 시야 범위 밖으로 나가면 이전 상태로 전이. else if( D3DXVec3LengthSq( &vLen) >= pow(zombie->GetVisibility(), 2) ) zombie->GetFSM()->ChangeState( _SINGLE(CZombieIdleState) ); //추적 계속하기 D3DXVECTOR3 vMove= zombie->GetHero()->GetPos() - zombie->GetPos(); D3DXVec3Normalize(&vMove, &vMove ); zombie->SetMove( vMove); }
bool Collision::IsSphereToSphere(BoundingSphere& s1, BoundingSphere& s2) { bool result = false; D3DXVECTOR3 dv = s1.center - s2.center; float d = D3DXVec3LengthSq(&dv); float rSum = (s1.radius + s2.radius) * (s1.radius + s2.radius); if (d <= rSum) { result = true; } return result; }
bool GameObject::collided(GameObject *gameObject) { //extra code that makes sure something is active might change for specific circumstances if(!gameObject->getActiveState()) { return false; } Vector3 diff = position - gameObject->getPosition(); float length = D3DXVec3LengthSq(&diff); float radii = radiusSquared + gameObject->getRadiusSquare(); if (length <= radii) return true; return false; }
BOOL cCollision::CollisionSphereSphere( cSphere& SphereA,D3DXVECTOR3& vecA,cSphere& SphereB,D3DXVECTOR3& vecB ) { //둘다 멈춰있는 구라면 float LengthSqA=D3DXVec3LengthSq(&vecA); float LengthSqB=D3DXVec3LengthSq(&vecB); if ((LengthSqA==0)&&(LengthSqB==0)) { // 그냥 겹침검사 return IntersectSphereSphere(SphereA,SphereB); } cLine LineA,LineB; // float CrossTA,CrossTB; if ((LengthSqA!=0.0f)&&(LengthSqB!=0.0f)) { LineA.Make(SphereA.GetCenterPos(),SphereA.GetCenterPos()+vecA); LineB.Make(SphereB.GetCenterPos(),SphereB.GetCenterPos()+vecB); LineA.GetDirection(); } else if (LengthSqA==0.0f) { LineB.Make(SphereB.GetCenterPos(),SphereB.GetCenterPos()+vecB); } else { LineA.Make(SphereA.GetCenterPos(),SphereA.GetCenterPos()+vecA); } // IntersectLineSphere() return TRUE; }
bool IsIntersect( rvector& o, rvector& d, rvector& dir, rvector& c, float r, rvector& normal, rvector* intersect ) { rvector ddir = c-d; float d_sq = D3DXVec3LengthSq(&ddir); float r_sq = r * r; if( d_sq > r_sq ) return false; // 최종 목적지가 원의 바깥쪽이면 상관없음 rvector ldir = c-o; float s = D3DXVec3Dot(&ldir, &dir); float l_sq = D3DXVec3LengthSq( &ldir ); float m_sq = l_sq - s*s; if( m_sq > r_sq ) return false; // 이건 충돌이 아님... 이런 경우가 왜 생길까? float q = sqrt( r_sq - m_sq ); float t; if( D3DXVec3Dot( &normal, &dir) < 0 ) t = s-q; else t = s + q; *intersect = o + dir*t; return true; }
//find node nearest the position, used by findPath //will return the first node within 150 units void AStar::getNodeNearPosition(PathNode*& _node, D3DXVECTOR3 _position) { PathNode* whichNode = NULL; float closestDistanceSq = 1000000000000000000000000.0f; for (UINT i = 0; i < mPathNodes.size(); ++i) { float distanceSq = D3DXVec3LengthSq(&(_position - mPathNodes[i]->getPosition())); if (distanceSq < closestDistanceSq) { whichNode = mPathNodes[i]; closestDistanceSq = distanceSq; } } _node = whichNode; }