bool PhysicsEngine::CollisionWithMapSimple(PowerBall* b, Map* map, Vector3 &normalPlane) { MaloW::Array<MeshStrip*>* temp = map->GetMesh()->GetStrips(); //int sizeMstrip = temp->size(); int sizeVertexS0 = temp->get(0)->getNrOfVerts(); Vertex* verts; //Vector3 origin = this->GetPositionVector3(); Vector3 origin = b->GetTempPosition(); Vector3 dir = b->GetVelocity(); Vector3 dirN = dir/dir.GetLength(); verts = temp->get(0)->getVerts(); /* for(int i = 0;i<sizeMstrip;i++) { } */ Vector3 p0,p1,p2, normal, v1,v2; float smalestTime = -1; bool firstHit = false; float u, v,t; float lengthProjN = 0; Vector3 p0Store, p1Store,p2Store, normalStore; Vector3 pos = Vector3(map->GetMesh()->GetPosition()); Vector3 posS = b->GetTempPosition();//this->GetPositionVector3(); Vector3 rayDirection; Vector3 scalingMesh = map->GetMesh()->GetScaling(); D3DXMATRIX quat; D3DXMatrixRotationQuaternion(&quat, &map->GetMesh()->GetRotation()); Matrix4 rotate(quat); rotate.TransposeThis(); Matrix4 scaling; scaling.SetScale(scalingMesh); Matrix4 translate; translate.SetTranslate(pos); Matrix4 world = translate*rotate*scaling; for(int i =0; i< sizeVertexS0; i+=3) { /* p0 = Vector3(verts[i].pos).GetComponentMultiplication(scalingMesh) + pos; p1 = Vector3(verts[i+1].pos).GetComponentMultiplication(scalingMesh) +pos; p2 = Vector3(verts[i+2].pos).GetComponentMultiplication(scalingMesh) + pos; */ p0 = world*Vector3(verts[i].pos); p1 = world*Vector3(verts[i+1].pos); p2 = world*Vector3(verts[i+2].pos); v1 = p1-p0; v2 = p2-p0; rayDirection = v1.GetCrossProduct(v2); rayDirection.normalize(); float tempLength; Vector3 ny; Vector3 projN; if(RayTriIntersect(origin , rayDirection, p0, p1, p2, u, v, t) ) { normal = rayDirection; ny = origin - p0; projN = normal*ny.GetDotProduct(normal); tempLength = projN.GetLength(); if(!firstHit) { firstHit = true; smalestTime = t; lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normal; } else { if( tempLength < lengthProjN ) { smalestTime = t; lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normal; } } } // check agains all edges Vector3 lineDirection; float scalarProj; Vector3 projOnLine; Vector3 normalToLine; // edge 1: ny = origin - p0; lineDirection = p1 - p0; scalarProj = (ny.GetDotProduct(lineDirection)/lineDirection.GetLengthSquared()); projOnLine = lineDirection * scalarProj; if( (scalarProj >= 0.0f) && (scalarProj <= 1) ) { normalToLine = ny - projOnLine; tempLength = normalToLine.GetLength(); if(!firstHit) { firstHit = true; lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normalToLine; normalStore.normalize(); } else { if( tempLength < lengthProjN ) { lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normalToLine; normalStore.normalize(); } } } // edge 2: ny = origin - p1; lineDirection = p2 - p1; scalarProj = (ny.GetDotProduct(lineDirection)/lineDirection.GetLengthSquared()); projOnLine = lineDirection * scalarProj; if( (scalarProj >= 0.0f) && (scalarProj <= 1) ) { normalToLine = ny - projOnLine; tempLength = normalToLine.GetLength(); if(!firstHit) { firstHit = true; lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normalToLine; normalStore.normalize(); } else { if( tempLength < lengthProjN ) { lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normalToLine; normalStore.normalize(); } } } // edge 3: ny = origin - p2; lineDirection = p0 - p2; scalarProj = (ny.GetDotProduct(lineDirection)/lineDirection.GetLengthSquared()); projOnLine = lineDirection * scalarProj; if( (scalarProj >= 0.0f) && (scalarProj <= 1) ) { normalToLine = ny - projOnLine; tempLength = normalToLine.GetLength(); if(!firstHit) { firstHit = true; lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normalToLine; normalStore.normalize(); } else { if( tempLength < lengthProjN ) { lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normal; } } } } if(firstHit) { // for checking if the ball are in the air not turned on at the moment, float eps = 0.5f; //0.001 if( (lengthProjN < (b->GetRadius() + eps)) && (lengthProjN > (b->GetRadius() - eps)) ) { b->SetNormalContact(normalStore); b->SetHasContact(true); } else { b->SetNormalContact(normalStore); b->SetHasContact(false); } if( lengthProjN <= b->GetRadius()) { Vector3 velNorm = b->GetVelocity(); velNorm.normalize(); if(normalStore.GetDotProduct(velNorm) >=0) return false; float diff = abs(lengthProjN- b->GetRadius()); //Vector3 newPo = origin -dirN*diff; //Vector3 projVel = normalStore * this->mVelocity.GetDotProduct(normalStore); Vector3 newPo = origin + normalStore*diff; /* if( projVel.GetDotProduct(normalStore) < 0.0f) { newPo = origin - normalStore*diff; return false; } else newPo = origin + normalStore*diff; */ //this->SetPosition(newPo); b->SetTempPosition(newPo); normalPlane = normalStore; //this->mNormalContact = normalPlane; //this->mHasContact = true; return true; } else { normalPlane = Vector3(0,0,0); //this->mNormalContact = normalPlane; //this->mHasContact = false; return false; } } normalPlane = Vector3(0,0,0); b->SetNormalContact(normalPlane); //this->mHasContact = false; return false; }
//! called during the update of the entity void KamikazeAttacker::Update() { if(m_fHitPoints < 0.0f || !GSETTINGS) { return; } auto settings = DYNAMIC_CAST(m_Settings, KamikazeAttackerSettings); switch (m_eState) { case KamikazeAttacker::S_Moving: { Vector3 vToHQ = m_TargetHQ->GetAbsolutePosition() - GetAbsolutePosition(); bool reachedHQ = false; if ((int)m_CurrentTarget > (int)m_Path.size() - 3) { float fDistToHQSq = vToHQ.GetLengthSquared(); reachedHQ = fDistToHQSq < settings->m_fHQKamikazeRange*settings->m_fHQKamikazeRange; } if (reachedHQ) { m_fDecelTimer = 0.0f; m_eState = S_PreparingAttack; m_bTargetReached = true; break; } if (!m_bTargetReached) MoveToTarget(); else SteerToTarget(); LookAtTarget(); } break; case S_PreparingAttack: { if (m_TargetHQ->GetHitPoints() < 0.0f) { if (auto nextTarget = WAVEMGR->GetNextHQ()) { m_TargetHQ = nextTarget; m_eState = S_Moving; } else m_eState = S_Idle; } else { m_vSpeed = Math::Damp(m_vSpeed, Vector3::Zero, g_fDeltaTime, settings->m_fDecelDuration); m_fDecelTimer += g_fDeltaTime; if (m_fDecelTimer > settings->m_fDecelDuration) { m_eState = S_AttackingHQ; break; } Translate(m_vSpeed * g_fDeltaTime); auto vToHQ = (m_TargetHQ->GetAbsolutePosition() - GetAbsolutePosition()).Normalized(); m_vLookAt = Math::Damp(m_vLookAt, vToHQ, g_fDeltaTime, 0.1f).Normalized(); LookAt(m_vLookAt); } } break; case KamikazeAttacker::S_AttackingHQ: { Vector3 vToHQ = (m_TargetHQ->GetAbsolutePosition() - GetAbsolutePosition()).Normalized(); Vector3 vAcceleration = vToHQ*settings->m_fKamikazeMaxAccel*g_fDeltaTime; m_vSpeed += vAcceleration; m_vSpeed.Limit(settings->m_fKamikazeMaxSpeed); Translate(m_vSpeed * g_fDeltaTime); } break; } super::Update(); }
bool PhysicsEngine::CollisionWithSphereSimple(PowerBall* b, PowerBall* b1) { Vector3 r = b->GetPositionVector3() - b1->GetPositionVector3(); r = b->GetTempPosition() - b1->GetTempPosition(); float distanceBalls = r.GetLength(); float sumRadius = b->GetRadius() + b1->GetRadius(); if(distanceBalls > sumRadius) return false; /* we have collision but we need to move the balls so they are not inside each other * solve this equation: ((pos1 - t*vel1) - (pos2 - t*vel2)).length = radie1 + radie2 * * this gives ut the following: * d = distance = p1-p2 * rV = relative velocity = v2-v1 * sumR = sumRadius = r1 + r2 * * t = - rV.dot(d)/|rV|^2 +- sqrt( rV.dot(d)^2/|rV|^4 - (sumR^2 - |d|^2) / |rV|^2 * */ Vector3 d = b->GetPositionVector3() - b1->GetPositionVector3(); d = b->GetTempPosition() - b1->GetTempPosition(); Vector3 rV = b1->GetVelocity() - b->GetVelocity(); float sumR = b->GetRadius() + b1->GetRadius(); float tempA = rV.GetDotProduct(d) / rV.GetLengthSquared(); float tempB = tempA*tempA; float tempC = (d.GetLengthSquared() - sumR*sumR) / rV.GetLengthSquared(); float tempSq = tempB - tempC; if( tempSq < 0) // no real solutions return false; else { float t1 = - tempA - sqrt(tempSq); float t2 = - tempA + sqrt(tempSq); Vector3 newPos1, newPos2; if(t1 >= 0) { /* newPos1 = this->GetPositionVector3() - this->mVelocity*t1; newPos2 = b1->GetPositionVector3() - b1->mVelocity*t1; this->SetPosition(newPos1); b1->SetPosition(newPos2); */ newPos1 = b->GetTempPosition() - b->GetVelocity()*t1; newPos2 = b1->GetTempPosition() - b1->GetVelocity()*t1; b->SetTempPosition(newPos1); b1->SetTempPosition(newPos2); } else if(t2 >= 0) { /* newPos1 = this->GetPositionVector3() - this->mVelocity*t2; newPos2 = b1->GetPositionVector3() - b1->mVelocity*t2; this->SetPosition(newPos1); b1->SetPosition(newPos2); */ newPos1 = b->GetTempPosition() - b->GetVelocity()*t2; newPos2 = b1->GetTempPosition() - b1->GetVelocity()*t2; b->SetTempPosition(newPos1); b1->SetTempPosition(newPos2); } else return false; } return true; }