#include "Stdafx.h" #include "CollisionData.h" #include "Pool.h" #include "GrpScreen.h" #include "GrpMath.h" #include "lineintersect_utils.h" #include "StateManager.h" const float gc_fReduceMove = 0.5f; //const float gc_fSlideMoveSpeed = 5.0f; /*inline D3DXVECTOR3 FitAtSpecifiedLength(const D3DXVECTOR3 & v3Vector, float length) { D3DXVECTOR3 v; D3DXVec3Normalize(&v,&v3Vector); return v*length; } */ CDynamicPool gs_sci; CDynamicPool gs_cci; CDynamicPool gs_pci; CDynamicPool gs_aci; CDynamicPool gs_oci; void DestroyCollisionInstanceSystem() { gs_sci.Destroy(); gs_cci.Destroy(); gs_pci.Destroy(); gs_aci.Destroy(); gs_oci.Destroy(); } ///////////////////////////////////////////// // Base CBaseCollisionInstance * CBaseCollisionInstance::BuildCollisionInstance(const CStaticCollisionData * c_pCollisionData, const D3DXMATRIX * pMat) { switch(c_pCollisionData->dwType) { case COLLISION_TYPE_PLANE: { CPlaneCollisionInstance * ppci = gs_pci.Alloc(); D3DXMATRIX matRotation; D3DXMATRIX matTranslationLocal; D3DXMatrixRotationQuaternion(&matRotation, &c_pCollisionData->quatRotation); D3DXMatrixTranslation(&matTranslationLocal, c_pCollisionData->v3Position.x, c_pCollisionData->v3Position.y, c_pCollisionData->v3Position.z); D3DXMATRIX matTransform = matRotation * matTranslationLocal * *pMat; TPlaneData & PlaneData = ppci->GetAttribute(); D3DXVec3TransformCoord(&PlaneData.v3Position, &c_pCollisionData->v3Position, pMat); float fHalfWidth = c_pCollisionData->fDimensions[0] / 2.0f; float fHalfLength = c_pCollisionData->fDimensions[1] / 2.0f; PlaneData.v3QuadPosition[0].x = -fHalfWidth; PlaneData.v3QuadPosition[0].y = -fHalfLength; PlaneData.v3QuadPosition[0].z = 0.0f; PlaneData.v3QuadPosition[1].x = +fHalfWidth; PlaneData.v3QuadPosition[1].y = -fHalfLength; PlaneData.v3QuadPosition[1].z = 0.0f; PlaneData.v3QuadPosition[2].x = -fHalfWidth; PlaneData.v3QuadPosition[2].y = +fHalfLength; PlaneData.v3QuadPosition[2].z = 0.0f; PlaneData.v3QuadPosition[3].x = +fHalfWidth; PlaneData.v3QuadPosition[3].y = +fHalfLength; PlaneData.v3QuadPosition[3].z = 0.0f; for (DWORD i = 0; i < 4; ++i) D3DXVec3TransformCoord(&PlaneData.v3QuadPosition[i], &PlaneData.v3QuadPosition[i], &matTransform); D3DXVECTOR3 v3Line0 = PlaneData.v3QuadPosition[1] - PlaneData.v3QuadPosition[0]; D3DXVECTOR3 v3Line1 = PlaneData.v3QuadPosition[2] - PlaneData.v3QuadPosition[0]; D3DXVECTOR3 v3Line2 = PlaneData.v3QuadPosition[1] - PlaneData.v3QuadPosition[3]; D3DXVECTOR3 v3Line3 = PlaneData.v3QuadPosition[2] - PlaneData.v3QuadPosition[3]; D3DXVec3Normalize(&v3Line0, &v3Line0); D3DXVec3Normalize(&v3Line1, &v3Line1); D3DXVec3Normalize(&v3Line2, &v3Line2); D3DXVec3Normalize(&v3Line3, &v3Line3); D3DXVec3Cross(&PlaneData.v3Normal, &v3Line0, &v3Line1); D3DXVec3Normalize(&PlaneData.v3Normal, &PlaneData.v3Normal); D3DXVec3Cross(&PlaneData.v3InsideVector[0], &PlaneData.v3Normal, &v3Line0 ); D3DXVec3Cross(&PlaneData.v3InsideVector[1], &v3Line1, &PlaneData.v3Normal); D3DXVec3Cross(&PlaneData.v3InsideVector[2], &v3Line2, &PlaneData.v3Normal); D3DXVec3Cross(&PlaneData.v3InsideVector[3], &PlaneData.v3Normal, &v3Line3); return ppci; } break; case COLLISION_TYPE_BOX: assert(false && "COLLISION_TYPE_BOX not implemented"); break; case COLLISION_TYPE_AABB: { CAABBCollisionInstance * paci = gs_aci.Alloc(); D3DXMATRIX matTranslationLocal; D3DXMatrixTranslation(&matTranslationLocal, c_pCollisionData->v3Position.x, c_pCollisionData->v3Position.y, c_pCollisionData->v3Position.z); D3DXMATRIX matTransform = *pMat; D3DXVECTOR3 v3Pos; v3Pos.x = matTranslationLocal._41; v3Pos.y = matTranslationLocal._42; v3Pos.z = matTranslationLocal._43; TAABBData & AABBData = paci->GetAttribute(); AABBData.v3Min.x = v3Pos.x - c_pCollisionData->fDimensions[0]; AABBData.v3Min.y = v3Pos.y - c_pCollisionData->fDimensions[1]; AABBData.v3Min.z = v3Pos.z - c_pCollisionData->fDimensions[2]; AABBData.v3Max.x = v3Pos.x + c_pCollisionData->fDimensions[0]; AABBData.v3Max.y = v3Pos.y + c_pCollisionData->fDimensions[1]; AABBData.v3Max.z = v3Pos.z + c_pCollisionData->fDimensions[2]; D3DXVec3TransformCoord(&AABBData.v3Min, &AABBData.v3Min, &matTransform); D3DXVec3TransformCoord(&AABBData.v3Max, &AABBData.v3Max, &matTransform); return paci; } break; case COLLISION_TYPE_OBB: { COBBCollisionInstance * poci = gs_oci.Alloc(); D3DXMATRIX matTranslationLocal; D3DXMatrixTranslation(&matTranslationLocal, c_pCollisionData->v3Position.x, c_pCollisionData->v3Position.y, c_pCollisionData->v3Position.z); D3DXMATRIX matRotation; D3DXMatrixRotationQuaternion(&matRotation, &c_pCollisionData->quatRotation); D3DXMATRIX matTranslationWorld; D3DXMatrixIdentity(&matTranslationWorld); matTranslationWorld._41 = pMat->_41; matTranslationWorld._42 = pMat->_42; matTranslationWorld._43 = pMat->_43; matTranslationWorld._44 = pMat->_44; D3DXVECTOR3 v3Min, v3Max; v3Min.x = c_pCollisionData->v3Position.x - c_pCollisionData->fDimensions[0]; v3Min.y = c_pCollisionData->v3Position.y - c_pCollisionData->fDimensions[1]; v3Min.z = c_pCollisionData->v3Position.z - c_pCollisionData->fDimensions[2]; v3Max.x = c_pCollisionData->v3Position.x + c_pCollisionData->fDimensions[0]; v3Max.y = c_pCollisionData->v3Position.y + c_pCollisionData->fDimensions[1]; v3Max.z = c_pCollisionData->v3Position.z + c_pCollisionData->fDimensions[2]; D3DXVec3TransformCoord(&v3Min, &v3Min, pMat); D3DXVec3TransformCoord(&v3Max, &v3Max, pMat); D3DXVECTOR3 v3Position = (v3Min + v3Max) * 0.5f; TOBBData & OBBData = poci->GetAttribute(); OBBData.v3Min.x = v3Position.x - c_pCollisionData->fDimensions[0]; OBBData.v3Min.y = v3Position.y - c_pCollisionData->fDimensions[1]; OBBData.v3Min.z = v3Position.z - c_pCollisionData->fDimensions[2]; OBBData.v3Max.x = v3Position.x + c_pCollisionData->fDimensions[0]; OBBData.v3Max.y = v3Position.y + c_pCollisionData->fDimensions[1]; OBBData.v3Max.z = v3Position.z + c_pCollisionData->fDimensions[2]; D3DXMATRIX matTransform = *pMat; D3DXMatrixIdentity(&OBBData.matRot); OBBData.matRot = *pMat; OBBData.matRot._41 = 0; OBBData.matRot._42 = 0; OBBData.matRot._43 = 0; OBBData.matRot._44 = 1; return poci; } break; case COLLISION_TYPE_SPHERE: { CSphereCollisionInstance * psci = gs_sci.Alloc(); D3DXMATRIX matTranslationLocal; D3DXMatrixTranslation(&matTranslationLocal, c_pCollisionData->v3Position.x, c_pCollisionData->v3Position.y, c_pCollisionData->v3Position.z); matTranslationLocal = matTranslationLocal * *pMat; TSphereData & SphereData = psci->GetAttribute(); SphereData.v3Position.x = matTranslationLocal._41; SphereData.v3Position.y = matTranslationLocal._42; SphereData.v3Position.z = matTranslationLocal._43; SphereData.fRadius = c_pCollisionData->fDimensions[0]; return psci; } break; case COLLISION_TYPE_CYLINDER: { CCylinderCollisionInstance * pcci = gs_cci.Alloc(); D3DXMATRIX matTranslationLocal; D3DXMatrixTranslation(&matTranslationLocal, c_pCollisionData->v3Position.x, c_pCollisionData->v3Position.y, c_pCollisionData->v3Position.z); matTranslationLocal = matTranslationLocal * *pMat; TCylinderData & CylinderData = pcci->GetAttribute(); CylinderData.fRadius = c_pCollisionData->fDimensions[0]; CylinderData.fHeight = c_pCollisionData->fDimensions[1]; CylinderData.v3Position.x = matTranslationLocal._41; CylinderData.v3Position.y = matTranslationLocal._42; CylinderData.v3Position.z = matTranslationLocal._43 /*+ CylinderData.fHeight/2.0f*/; return pcci; } break; } assert(false && "NOT_REACHED"); return 0; } void CBaseCollisionInstance::Destroy() { OnDestroy(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /*------------------------------------------------------Sphere---------------------------------------------------------------*/ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TSphereData & CSphereCollisionInstance::GetAttribute() { return m_attribute; } const TSphereData & CSphereCollisionInstance::GetAttribute() const { return m_attribute; } void CSphereCollisionInstance::Render(D3DFILLMODE d3dFillMode) { static CScreen s; STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, 0xffffffff); s.RenderSphere(NULL, m_attribute.v3Position.x, m_attribute.v3Position.y, m_attribute.v3Position.z, m_attribute.fRadius, d3dFillMode); } void CSphereCollisionInstance::OnDestroy() { gs_sci.Free(this); } bool CSphereCollisionInstance::OnMovementCollisionDynamicSphere(const CDynamicSphereInstance & s) const { if (square_distance_between_linesegment_and_point(s.v3LastPosition,s.v3Position,m_attribute.v3Position) < (m_attribute.fRadius+s.fRadius)*(m_attribute.fRadius+s.fRadius)) { // NOTE : °Å¸®°¡ °¡±î¿ö Á³À»¶§¸¸.. - [levites] if (GetVector3Distance(s.v3Position, m_attribute.v3Position) < GetVector3Distance(s.v3LastPosition, m_attribute.v3Position)) return true; } return false; } bool CSphereCollisionInstance::OnCollisionDynamicSphere(const CDynamicSphereInstance & s) const { //Tracef("OnCollisionDynamicSphere\n"); if (square_distance_between_linesegment_and_point(s.v3LastPosition,s.v3Position,m_attribute.v3Position)<(m_attribute.fRadius+s.fRadius)*(m_attribute.fRadius+s.fRadius)) { return true; } return false; } D3DXVECTOR3 CSphereCollisionInstance::OnGetCollisionMovementAdjust(const CDynamicSphereInstance & s) const { if (D3DXVec3LengthSq(&(s.v3Position-m_attribute.v3Position))>=(s.fRadius+m_attribute.fRadius)*(m_attribute.fRadius+s.fRadius)) return D3DXVECTOR3(0.0f,0.0f,0.0f); D3DXVECTOR3 c; D3DXVec3Cross(&c, &(s.v3Position-s.v3LastPosition), &D3DXVECTOR3(0.0f,0.0f,1.0f) ); float sum = - D3DXVec3Dot(&c,&(s.v3Position-m_attribute.v3Position)); float mul = (s.fRadius+m_attribute.fRadius)*(s.fRadius+m_attribute.fRadius)-D3DXVec3LengthSq(&(s.v3Position-m_attribute.v3Position)); if (sum*sum-4*mul<=0) return D3DXVECTOR3(0.0f,0.0f,0.0f); float sq = sqrt(sum*sum-4*mul); float t1=-sum-sq, t2=-sum+sq; t1*=0.5f; t2*=0.5f; if (fabs(t1)<=fabs(t2)) { return (gc_fReduceMove*t1)*c; } else return (gc_fReduceMove*t2)*c; /* D3DXVECTOR3 p1 = s.v3Position+t1*c; D3DXVECTOR3 p2 = s.v3Position+t2*c; if (D3DXVec3LengthSq(&(p2-s.v3Position))>D3DXVec3LengthSq(&(p1-s.v3Position))) { return p1-s.v3Position; } else { return p2-s.v3Position; } */ } ///////////////////////////////////////////// // Plane TPlaneData & CPlaneCollisionInstance::GetAttribute() { return m_attribute; } const TPlaneData & CPlaneCollisionInstance::GetAttribute() const { return m_attribute; } bool CPlaneCollisionInstance::OnMovementCollisionDynamicSphere(const CDynamicSphereInstance & s) const { D3DXVECTOR3 v3SpherePosition = s.v3Position - m_attribute.v3Position; D3DXVECTOR3 v3SphereLastPosition = s.v3LastPosition - m_attribute.v3Position; float fPosition1 = D3DXVec3Dot(&m_attribute.v3Normal, &v3SpherePosition); float fPosition2 = D3DXVec3Dot(&m_attribute.v3Normal, &v3SphereLastPosition); if (fPosition1 >0.0f && fPosition2 < 0.0f || fPosition1 <0.0f && fPosition2 >0.0f || (fPosition1) <= s.fRadius && fPosition1 >= -s.fRadius) { D3DXVECTOR3 v3QuadPosition1 = s.v3Position - m_attribute.v3QuadPosition[0]; D3DXVECTOR3 v3QuadPosition2 = s.v3Position - m_attribute.v3QuadPosition[3]; if (D3DXVec3Dot(&v3QuadPosition1, &m_attribute.v3InsideVector[0]) > - s.fRadius/*0.0f*/) if (D3DXVec3Dot(&v3QuadPosition1, &m_attribute.v3InsideVector[1]) > -s.fRadius/*0.0f*/) if (D3DXVec3Dot(&v3QuadPosition2, &m_attribute.v3InsideVector[2]) > - s.fRadius/*0.0f*/) if (D3DXVec3Dot(&v3QuadPosition2, &m_attribute.v3InsideVector[3]) > - s.fRadius/*0.0f*/) { // NOTE : °Å¸®°¡ °¡±î¿ö Á³À»¶§¸¸.. - [levites] if (fabs(D3DXVec3Dot(&(s.v3Position - m_attribute.v3Position), &m_attribute.v3Normal)) < fabs(D3DXVec3Dot(&(s.v3LastPosition - m_attribute.v3Position), &m_attribute.v3Normal))) return true; } } return false; } bool CPlaneCollisionInstance::OnCollisionDynamicSphere(const CDynamicSphereInstance & s) const { //Tracef("OnCollisionDynamicSphere\n"); D3DXVECTOR3 v3SpherePosition = s.v3Position - m_attribute.v3Position; D3DXVECTOR3 v3SphereLastPosition = s.v3LastPosition - m_attribute.v3Position; float fPosition1 = D3DXVec3Dot(&m_attribute.v3Normal, &v3SpherePosition); float fPosition2 = D3DXVec3Dot(&m_attribute.v3Normal, &v3SphereLastPosition); if (fPosition1 >0.0f && fPosition2 < 0.0f || fPosition1 <0.0f && fPosition2 >0.0f || (fPosition1) <= s.fRadius && fPosition1 >= -s.fRadius) { D3DXVECTOR3 v3QuadPosition1 = s.v3Position - m_attribute.v3QuadPosition[0]; D3DXVECTOR3 v3QuadPosition2 = s.v3Position - m_attribute.v3QuadPosition[3]; if (D3DXVec3Dot(&v3QuadPosition1, &m_attribute.v3InsideVector[0]) > - s.fRadius/*0.0f*/) if (D3DXVec3Dot(&v3QuadPosition1, &m_attribute.v3InsideVector[1]) > -s.fRadius/*0.0f*/) if (D3DXVec3Dot(&v3QuadPosition2, &m_attribute.v3InsideVector[2]) > - s.fRadius/*0.0f*/) if (D3DXVec3Dot(&v3QuadPosition2, &m_attribute.v3InsideVector[3]) > - s.fRadius/*0.0f*/) { return true; } } return false; } D3DXVECTOR3 CPlaneCollisionInstance::OnGetCollisionMovementAdjust(const CDynamicSphereInstance & s) const { D3DXVECTOR3 advance = s.v3Position-s.v3LastPosition; float d = D3DXVec3Dot(&m_attribute.v3Normal, &advance); if (d>=-0.0001 && d<=0.0001) return D3DXVECTOR3(0.0f,0.0f,0.0f); float t= - D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position))/d; //D3DXVECTOR3 onplane = s.v3Position+t*advance; if (D3DXVec3Dot(&m_attribute.v3Normal, &advance)>=0) { //return m_attribute.v3Normal*((-s.fRadius+D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position)))*gc_fReduceMove); return t*advance -s.fRadius*m_attribute.v3Normal; } else { //return m_attribute.v3Normal*((s.fRadius+D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position)))*gc_fReduceMove); return t*advance +s.fRadius*m_attribute.v3Normal; } /*if (D3DXVec3Dot(&m_attribute.v3Normal, &advance)>=0) { Tracef("%f %f\n",s.fRadius,-(D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position)))); return m_attribute.v3Normal*((-s.fRadius+D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position)))*gc_fReduceMove); } else { Tracef("%f %f\n",(s.fRadius),(D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position)))); return m_attribute.v3Normal*((s.fRadius+D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position)))*gc_fReduceMove); }*/ /* D3DXVECTOR3 advance = s.v3Position-s.v3LastPosition; D3DXVECTOR3 slide(-advance.y,advance.x,advance.z); slide = m_attribute.v3Normal; D3DXVECTOR3 radius_adjust = advance; D3DXVec3Normalize(&radius_adjust,&radius_adjust); radius_adjust*=s.fRadius; float d = D3DXVec3Dot(&m_attribute.v3Normal, &slide); if (d>=-0.0001 && d<=0.0001) return D3DXVECTOR3(0.0f,0.0f,0.0f); float t= - D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position+radius_adjust-m_attribute.v3Position)) / d;*/ //D3DXVECTOR3 nextposition; //nextposition = s.v3Position + t*slide; //Tracef("$T %f",t); //if (D3DXVec3Dot(&m_attribute.v3Normal, &advance)>=0) // return (t*slide - m_attribute.v3Normal * s.fRadius)/**gc_fReduceMove*/; //else // return (t*slide + m_attribute.v3Normal * s.fRadius)/*gc_fReduceMove*/; //if (D3DXVec3Dot(&m_attribute.v3Normal, &advance)>=0) // return (t*slide + m_attribute.v3Normal * D3DXVec3Dot(&m_attribute.v3Normal,&(s.v3LastPosition-m_attribute.v3Position))/** s.fRadius*/)*gc_fReduceMove; //else // return (t*slide + m_attribute.v3Normal * D3DXVec3Dot(&m_attribute.v3Normal,&(s.v3LastPosition-m_attribute.v3Position))/*s.fRadius*/)*gc_fReduceMove; // } void CPlaneCollisionInstance::Render(D3DFILLMODE /*d3dFillMode*/) { static CScreen s; s.RenderBar3d(m_attribute.v3QuadPosition); } void CPlaneCollisionInstance::OnDestroy() { gs_pci.Free(this); } ///////////////////////////////////////////// // Cylinder TCylinderData & CCylinderCollisionInstance::GetAttribute() { return m_attribute; } const TCylinderData & CCylinderCollisionInstance::GetAttribute() const { return m_attribute; } bool CCylinderCollisionInstance::CollideCylinderVSDynamicSphere(const TCylinderData & c_rattribute, const CDynamicSphereInstance & s) const { if (s.v3Position.z + s.fRadius < c_rattribute.v3Position.z) return false; if (s.v3Position.z - s.fRadius > c_rattribute.v3Position.z + c_rattribute.fHeight) return false; /*D3DXVECTOR2 v2curDistance(s.v3Position.x - c_rattribute.v3Position.x, s.v3Position.y - c_rattribute.v3Position.y); float fDistance = D3DXVec2Length(&v2curDistance); if (fDistance <= s.fRadius + c_rattribute.fRadius) return true; */ D3DXVECTOR3 oa, ob; IntersectLineSegments(c_rattribute.v3Position, D3DXVECTOR3(c_rattribute.v3Position.x,c_rattribute.v3Position.y,c_rattribute.v3Position.z+c_rattribute.fHeight), s.v3LastPosition, s.v3Position, oa, ob); return (D3DXVec3LengthSq(&(oa-ob))<=(c_rattribute.fRadius+s.fRadius)*(c_rattribute.fRadius+s.fRadius)); } bool CCylinderCollisionInstance::OnMovementCollisionDynamicSphere(const CDynamicSphereInstance & s) const { if (CollideCylinderVSDynamicSphere(m_attribute, s)) { // NOTE : °Å¸®°¡ °¡±î¿ö Á³À»¶§¸¸.. - [levites] if (GetVector3Distance(s.v3Position, m_attribute.v3Position) < GetVector3Distance(s.v3LastPosition, m_attribute.v3Position)) return true; } // NOTE : À̵¿ °Å¸®°¡ Ŭ °æ¿ì ºóÆ´¾øÀÌ (¿ø Å©±â ´ÜÀ§·Î) À̵¿Çϸ鼭 ÀüºÎ üũ ÇØ º»´Ù - [levites] D3DXVECTOR3 v3Distance = s.v3Position - s.v3LastPosition; float fDistance = D3DXVec3Length(&v3Distance); if (s.fRadius<=0.0001f) return false; if (fDistance >= s.fRadius*2.0f) { TCylinderData cylinder; cylinder = m_attribute; cylinder.v3Position = s.v3LastPosition; int iStep = fDistance / s.fRadius*2.0f; D3DXVECTOR3 v3Step = v3Distance / float(iStep); for (int i = 0; i < iStep; ++i) { cylinder.v3Position += v3Step; if (CollideCylinderVSDynamicSphere(cylinder, s)) return true; } } return false; } bool CCylinderCollisionInstance::OnCollisionDynamicSphere(const CDynamicSphereInstance & s) const { //Tracef("OnCollisionDynamicSphere\n"); return (CollideCylinderVSDynamicSphere(m_attribute, s)); } D3DXVECTOR3 CCylinderCollisionInstance::OnGetCollisionMovementAdjust(const CDynamicSphereInstance & s) const { D3DXVECTOR3 v3Position = m_attribute.v3Position; v3Position.z = s.v3Position.z; if (D3DXVec3LengthSq(&(s.v3Position-v3Position))>=(s.fRadius+m_attribute.fRadius)*(m_attribute.fRadius+s.fRadius)) return D3DXVECTOR3(0.0f,0.0f,0.0f); D3DXVECTOR3 c; D3DXVECTOR3 advance = s.v3Position - s.v3LastPosition; advance.z = 0; D3DXVec3Cross(&c, &advance, &D3DXVECTOR3(0.0f,0.0f,1.0f) ); float sum = - D3DXVec3Dot(&c,&(s.v3Position-v3Position)); float mul = (s.fRadius+m_attribute.fRadius)*(s.fRadius+m_attribute.fRadius)-D3DXVec3LengthSq(&(s.v3Position-v3Position)); if (sum*sum-4*mul<=0) return D3DXVECTOR3(0.0f,0.0f,0.0f); float sq = sqrt(sum*sum-4*mul); float t1=-sum-sq, t2=-sum+sq; t1*=0.5f; t2*=0.5f; if (fabs(t1)<=fabs(t2)) { return (gc_fReduceMove*t1)*c; } else return (gc_fReduceMove*t2)*c; /*D3DXVECTOR3 p1 = s.v3Position+t1*c; D3DXVECTOR3 p2 = s.v3Position+t2*c; if (D3DXVec3LengthSq(&(p2-s.v3Position))>D3DXVec3LengthSq(&(p1-s.v3Position))) { return p1-s.v3Position; } else { return p2-s.v3Position; }*/ } void CCylinderCollisionInstance::Render(D3DFILLMODE d3dFillMode) { static CScreen s; STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, 0xffffffff); s.RenderCylinder(NULL, m_attribute.v3Position.x, m_attribute.v3Position.y, m_attribute.v3Position.z+m_attribute.fHeight/2, m_attribute.fRadius, m_attribute.fHeight, d3dFillMode); } void CCylinderCollisionInstance::OnDestroy() { gs_cci.Free(this); } ///////////////////////////////////////////// // AABB (Aligned Axis Bounding Box) TAABBData & CAABBCollisionInstance::GetAttribute() { return m_attribute; } const TAABBData & CAABBCollisionInstance::GetAttribute() const { return m_attribute; } bool CAABBCollisionInstance::OnMovementCollisionDynamicSphere(const CDynamicSphereInstance & s) const { D3DXVECTOR3 v; D3DXVECTOR3 v3center = (m_attribute.v3Min + m_attribute.v3Max) * 0.5f; memcpy(&v, &s.v3Position, sizeof(D3DXVECTOR3)); if(v.x < m_attribute.v3Min.x) v.x = m_attribute.v3Min.x; if(v.x > m_attribute.v3Max.x) v.x = m_attribute.v3Max.x; if(v.y < m_attribute.v3Min.y) v.x = m_attribute.v3Min.y; if(v.y > m_attribute.v3Max.y) v.x = m_attribute.v3Max.y; if(v.z < m_attribute.v3Min.z) v.z = m_attribute.v3Min.z; if(v.z > m_attribute.v3Max.z) v.z = m_attribute.v3Max.z; if(GetVector3Distance(v, s.v3Position) <= s.fRadius * s.fRadius) { return true; } memcpy(&v, &s.v3LastPosition, sizeof(D3DXVECTOR3)); if(v.x < m_attribute.v3Min.x) v.x = m_attribute.v3Min.x; if(v.x > m_attribute.v3Max.x) v.x = m_attribute.v3Max.x; if(v.y < m_attribute.v3Min.y) v.x = m_attribute.v3Min.y; if(v.y > m_attribute.v3Max.y) v.x = m_attribute.v3Max.y; if(v.z < m_attribute.v3Min.z) v.z = m_attribute.v3Min.z; if(v.z > m_attribute.v3Max.z) v.z = m_attribute.v3Max.z; if(GetVector3Distance(v, s.v3LastPosition) <= s.fRadius * s.fRadius) { return true; } return false; } bool CAABBCollisionInstance::OnCollisionDynamicSphere(const CDynamicSphereInstance & s) const { D3DXVECTOR3 v; memcpy(&v, &s.v3Position, sizeof(D3DXVECTOR3)); if(v.x < m_attribute.v3Min.x) v.x = m_attribute.v3Min.x; if(v.x > m_attribute.v3Max.x) v.x = m_attribute.v3Max.x; if(v.y < m_attribute.v3Min.y) v.x = m_attribute.v3Min.y; if(v.y > m_attribute.v3Max.y) v.x = m_attribute.v3Max.y; if(v.z < m_attribute.v3Min.z) v.z = m_attribute.v3Min.z; if(v.z > m_attribute.v3Max.z) v.z = m_attribute.v3Max.z; if(v.x > m_attribute.v3Min.x && v.x < m_attribute.v3Max.x && v.y > m_attribute.v3Min.y && v.y < m_attribute.v3Max.y && v.z > m_attribute.v3Min.z && v.z < m_attribute.v3Max.z) { return true; } if(GetVector3Distance(v, s.v3Position) <= s.fRadius * s.fRadius) { return true; } memcpy(&v, &s.v3LastPosition, sizeof(D3DXVECTOR3)); if(v.x < m_attribute.v3Min.x) v.x = m_attribute.v3Min.x; if(v.x > m_attribute.v3Max.x) v.x = m_attribute.v3Max.x; if(v.y < m_attribute.v3Min.y) v.x = m_attribute.v3Min.y; if(v.y > m_attribute.v3Max.y) v.x = m_attribute.v3Max.y; if(v.z < m_attribute.v3Min.z) v.z = m_attribute.v3Min.z; if(v.z > m_attribute.v3Max.z) v.z = m_attribute.v3Max.z; if(v.x > m_attribute.v3Min.x && v.x < m_attribute.v3Max.x && v.y > m_attribute.v3Min.y && v.y < m_attribute.v3Max.y && v.z > m_attribute.v3Min.z && v.z < m_attribute.v3Max.z) { return true; } if(GetVector3Distance(v, s.v3LastPosition) <= s.fRadius * s.fRadius) { return true; } return false; } D3DXVECTOR3 CAABBCollisionInstance::OnGetCollisionMovementAdjust(const CDynamicSphereInstance & s) const { //Tracef("OnGetCollisionMovementAdjust v3Min.x = %f, v3Max.x = %f\n", m_attribute.v3Min.x, m_attribute.v3Max.x); /* float fARadius = D3DXVec3Length(&(m_attribute.v3Min - m_attribute.v3Max)); if (D3DXVec3LengthSq(&(s.v3Position-(m_attribute.v3Max + m_attribute.v3Min)))>=(s.fRadius+fARadius)*(fARadius+s.fRadius)) return D3DXVECTOR3(0.0f,0.0f,0.0f); D3DXVECTOR3 c; D3DXVec3Cross(&c, &(s.v3Position-s.v3LastPosition), &D3DXVECTOR3(0.0f,0.0f,1.0f) ); float sum = - D3DXVec3Dot(&c,&(s.v3Position-(m_attribute.v3Max + m_attribute.v3Min))); float mul = (s.fRadius+fARadius)*(s.fRadius+fARadius)-D3DXVec3LengthSq(&(s.v3Position-(m_attribute.v3Max + m_attribute.v3Min))); if (sum*sum-4*mul<=0) return D3DXVECTOR3(0.0f,0.0f,0.0f); float sq = sqrt(sum*sum-4*mul); float t1=-sum-sq, t2=-sum+sq; t1*=0.5f; t2*=0.5f; if (fabs(t1)<=fabs(t2)) { return (gc_fReduceMove*t1)*c; } else return (gc_fReduceMove*t2)*c; */ D3DXVECTOR3 v3Temp; if(s.v3Position.x + s.fRadius <= m_attribute.v3Min.x) { v3Temp.x = m_attribute.v3Min.x; } else if(s.v3Position.x - s.fRadius >= m_attribute.v3Max.x) { v3Temp.x = m_attribute.v3Max.x; } else if(s.v3Position.x + s.fRadius >= m_attribute.v3Min.x && s.v3Position.x + s.fRadius <= m_attribute.v3Max.x) { v3Temp.x = s.v3Position.x + s.fRadius; } else { v3Temp.x = s.v3Position.x - s.fRadius; } if(s.v3Position.y + s.fRadius <= m_attribute.v3Min.y) { v3Temp.y = m_attribute.v3Min.y; } else if(s.v3Position.y - s.fRadius >= m_attribute.v3Max.y) { v3Temp.y = m_attribute.v3Max.y; } else if(s.v3Position.y + s.fRadius >= m_attribute.v3Min.y && s.v3Position.y + s.fRadius <= m_attribute.v3Max.y) { v3Temp.y = s.v3Position.y + s.fRadius; } else { v3Temp.y = s.v3Position.y - s.fRadius; } if(s.v3Position.z + s.fRadius <= m_attribute.v3Min.z) { v3Temp.z = m_attribute.v3Min.z; } else if(s.v3Position.z - s.fRadius >= m_attribute.v3Max.z) { v3Temp.z = m_attribute.v3Max.z; } else if(s.v3Position.z + s.fRadius >= m_attribute.v3Min.z && s.v3Position.z + s.fRadius <= m_attribute.v3Max.z) { v3Temp.z = s.v3Position.z + s.fRadius; } else { v3Temp.z = s.v3Position.z - s.fRadius; } if(D3DXVec3LengthSq(&(v3Temp - s.v3Position)) < s.fRadius * s.fRadius) return D3DXVECTOR3(.0f, .0f, .0f); return D3DXVECTOR3(.0f, .0f, .0f); } void CAABBCollisionInstance::Render(D3DFILLMODE d3dFillMode) { static CScreen s; STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, 0xffffffff); s.RenderCube(m_attribute.v3Min.x, m_attribute.v3Min.y, m_attribute.v3Min.z, m_attribute.v3Max.x, m_attribute.v3Max.y, m_attribute.v3Max.z); return; } void CAABBCollisionInstance::OnDestroy() { gs_aci.Free(this); } ///////////////////////////////////////////// // OBB TOBBData & COBBCollisionInstance::GetAttribute() { return m_attribute; } const TOBBData & COBBCollisionInstance::GetAttribute() const { return m_attribute; } bool COBBCollisionInstance::OnMovementCollisionDynamicSphere(const CDynamicSphereInstance & s) const { D3DXVECTOR3 v3Center = 0.5f * (m_attribute.v3Min + m_attribute.v3Max); D3DXVECTOR3 v3Sphere = s.v3Position - v3Center; D3DXVec3TransformCoord(&v3Sphere, &v3Sphere, &m_attribute.matRot); v3Sphere = v3Sphere + v3Center; D3DXVECTOR3 v3Point = v3Sphere; if(v3Point.x < m_attribute.v3Min.x) { v3Point.x = m_attribute.v3Min.x; } if(v3Point.x > m_attribute.v3Max.x) { v3Point.x = m_attribute.v3Max.x; } if(v3Point.y < m_attribute.v3Min.y) { v3Point.y = m_attribute.v3Min.y; } if(v3Point.y > m_attribute.v3Max.y) { v3Point.y = m_attribute.v3Max.y; } if(v3Point.z < m_attribute.v3Min.z) { v3Point.z = m_attribute.v3Min.z; } if(v3Point.z > m_attribute.v3Max.z) { v3Point.z = m_attribute.v3Max.z; } if(GetVector3Distance(v3Point, v3Sphere) <= s.fRadius * s.fRadius) { return true; } v3Sphere = s.v3LastPosition - v3Center; D3DXVec3TransformCoord(&v3Sphere, &v3Sphere, &m_attribute.matRot); v3Sphere = v3Sphere + v3Center; v3Point = v3Sphere; if(v3Point.x < m_attribute.v3Min.x) { v3Point.x = m_attribute.v3Min.x; } if(v3Point.x > m_attribute.v3Max.x) { v3Point.x = m_attribute.v3Max.x; } if(v3Point.y < m_attribute.v3Min.y) { v3Point.y = m_attribute.v3Min.y; } if(v3Point.y > m_attribute.v3Max.y) { v3Point.y = m_attribute.v3Max.y; } if(v3Point.z < m_attribute.v3Min.z) { v3Point.z = m_attribute.v3Min.z; } if(v3Point.z > m_attribute.v3Max.z) { v3Point.z = m_attribute.v3Max.z; } if(GetVector3Distance(v3Point, v3Sphere) <= s.fRadius * s.fRadius) { return true; } return false; } bool COBBCollisionInstance::OnCollisionDynamicSphere(const CDynamicSphereInstance & s) const { D3DXVECTOR3 v3Center = 0.5f * (m_attribute.v3Min + m_attribute.v3Max); D3DXVECTOR3 v3Sphere = s.v3Position - v3Center; D3DXVec3TransformCoord(&v3Sphere, &v3Sphere, &m_attribute.matRot); v3Sphere = v3Sphere + v3Center; D3DXVECTOR3 v3Point = v3Sphere; if(v3Point.x < m_attribute.v3Min.x) { v3Point.x = m_attribute.v3Min.x; } if(v3Point.x > m_attribute.v3Max.x) { v3Point.x = m_attribute.v3Max.x; } if(v3Point.y < m_attribute.v3Min.y) { v3Point.y = m_attribute.v3Min.y; } if(v3Point.y > m_attribute.v3Max.y) { v3Point.y = m_attribute.v3Max.y; } if(v3Point.z < m_attribute.v3Min.z) { v3Point.z = m_attribute.v3Min.z; } if(v3Point.z > m_attribute.v3Max.z) { v3Point.z = m_attribute.v3Max.z; } if(GetVector3Distance(v3Point, v3Sphere) <= s.fRadius * s.fRadius) { return true; } v3Sphere = s.v3LastPosition - v3Center; D3DXVec3TransformCoord(&v3Sphere, &v3Sphere, &m_attribute.matRot); v3Sphere = v3Sphere + v3Center; v3Point = v3Sphere; if(v3Point.x < m_attribute.v3Min.x) { v3Point.x = m_attribute.v3Min.x; } if(v3Point.x > m_attribute.v3Max.x) { v3Point.x = m_attribute.v3Max.x; } if(v3Point.y < m_attribute.v3Min.y) { v3Point.y = m_attribute.v3Min.y; } if(v3Point.y > m_attribute.v3Max.y) { v3Point.y = m_attribute.v3Max.y; } if(v3Point.z < m_attribute.v3Min.z) { v3Point.z = m_attribute.v3Min.z; } if(v3Point.z > m_attribute.v3Max.z) { v3Point.z = m_attribute.v3Max.z; } if(GetVector3Distance(v3Point, v3Sphere) <= s.fRadius * s.fRadius) { return true; } return false; } D3DXVECTOR3 COBBCollisionInstance::OnGetCollisionMovementAdjust(const CDynamicSphereInstance & s) const { return D3DXVECTOR3(.0f, .0f, .0f); } void COBBCollisionInstance::Render(D3DFILLMODE d3dFillMode) { static CScreen s; STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, 0xffffffff); s.RenderCube(m_attribute.v3Min.x, m_attribute.v3Min.y, m_attribute.v3Min.z, m_attribute.v3Max.x, m_attribute.v3Max.y, m_attribute.v3Max.z, m_attribute.matRot); return; } void COBBCollisionInstance::OnDestroy() { gs_oci.Free(this); }