void AIFly::Update() { Assert(m_npc); Assert(m_target); m_npc->SetAnim("fly"); // why not just in OnActivated?? TODO // Accelerate towards point above player's head Vec3f a = (m_target->GetPos() + Vec3f(0, 50.0f, 0)) - m_npc->GetPos(); a.Normalise(); a *= 50.0f; // TODO CONFIG m_npc->SetAcc(a); // Cap speed a = m_npc->GetVel(); float speedSq = a.SqLen(); const float MAX_SPEED = 50.0f; // TODO CONFIG if (speedSq > MAX_SPEED * MAX_SPEED) { a.Normalise(); a *= MAX_SPEED; m_npc->SetVel(a); } float degs = RadToDeg(atan2(a.x, a.z)); m_npc->SetDir(degs); }
void Ve1ObjectChar::MoveTo(const Vec3f& newpos) { m_newPos = newpos; m_isMoving = true; Vec3f dir = GetPos() - newpos; float sqLen = dir.SqLen(); // TODO Check if distance is greater than last time - if so, we have missed the target! static const float STOP_DIST = ROConfig()->GetFloat("stop-dist", 10.0f); if (sqLen < STOP_DIST) { SetVel(Vec3f(0, 0, 0)); m_isMoving = false; // Not sure why this wasn't here } // TODO enable this when we are reliably resetting sqLenLastTime, otherwise sometimes characters won't move /* else if (sqLen > sqLenLastTime) { SetVel(Vec3f(0, 0, 0)); m_isMoving = false; // Not sure why this wasn't here } */ else { dir.Normalise(); SetVel(-dir * SPEED); // Work out direction to face SetDir(RadToDeg(atan2((double)m_vel.x, (double)m_vel.z))); } sqLenLastTime = sqLen; }
void MakeNormal(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2, Vec3f* pResult) { AMJU_CALL_STACK; Vec3f cp = CrossProduct(v1 - v0, v2 - v0); cp.Normalise(); *pResult = cp; }
// https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Arcball void Camera::RotateArcball(float ax, float ay, float bx, float by) { Vec3f a, b; Vec2f from(ax, ay); Vec2f to(bx, by); float az = from.x * from.x + from.y * from.y; float bz = to.x * to.x + to.y * to.y; // keep the controls stable by rejecting very small movements. if(fabsf(az - bz) < 1e-5f) return; if(az < 1.0f) { a = Vec3f(from.x, from.y, sqrt(1.0f - az)); } else { a = Vec3f(from.x, from.y, 0.0f); a.Normalise(); } if(bz < 1.0f) { b = Vec3f(to.x, to.y, sqrt(1.0f - bz)); } else { b = Vec3f(to.x, to.y, 0.0f); b.Normalise(); } float angle = acosf(RDCMIN(1.0f, a.Dot(b))); Vec3f axis = a.Cross(b); axis.Normalise(); dirty = true; Quatf delta = Quatf::AxisAngle(axis, angle); arcrot = arcrot * delta; }
void AIChasePet::Update() { AI::Update(); Assert(m_npc); // Head towards target Vec3f aim = m_target->GetPos(); Vec3f vel = aim - m_npc->GetPos(); static const float MAX_DIST = ROConfig()->GetFloat("dino-chase-dist"); static const float MAX_DIST_SQ = MAX_DIST * MAX_DIST; float sqlen = vel.SqLen(); if (sqlen < 1.0f) { std::cout << "AI chase: " << Describe(m_npc) << " has reached target " << Describe(m_target) << "!\n"; m_npc->DecideAI(); } else if (sqlen < MAX_DIST_SQ) { vel.Normalise(); static const float SPEED = ROConfig()->GetFloat("dino-chase-speed"); vel *= SPEED; Vec3f v = m_npc->GetVel(); v.x = vel.x; v.z = vel.z; m_npc->SetVel(v); float degs = RadToDeg(atan2(vel.x, vel.z)); m_npc->SetDir(degs); m_npc->SetIsControlled(true); m_npc->SetAnim("run"); } else { #ifdef _DEBUG std::cout << m_npc->GetTypeName() << " giving up chase\n"; #endif m_npc->SetAI(AIIdle::NAME); } }
void Spring::Update() { // Vector between spring ends Vec3f v = m_particles[0]->GetPos() - m_particles[1]->GetPos(); Vec3f newVec = v; // Force along this line proportional to distance // == Hooke's Law, springs float len = sqrt(v.SqLen()); if (len < 0.00001f) // TODO { return; // zero length spring, so do nothing } //len = std::min(m_maxLength, len); v.Normalise(); // Force at spring ends is proportional to squash/stretch distance Vec3f forceAtEnd = v * ((len - m_naturalLength) * m_k); m_particles[0]->AddForce(-forceAtEnd); m_particles[1]->AddForce(forceAtEnd); // If max spring length exceeded, pull ends together if (len > m_maxLength) { std::cout << "Spring exceeds max length (" << m_maxLength << ")\n"; // TODO Take masses into account! float dist = (len - m_maxLength) * 0.5f; // move each end this dist Vec3f moveVec = v * dist; m_particles[0]->Move(-moveVec); m_particles[1]->Move(moveVec); } else if (len < m_minLength) { std::cout << "Spring under min length (" << m_minLength << ")\n"; // TODO Take masses into account! float dist = (len - m_minLength) * 0.5f; // move each end this dist Vec3f moveVec = v * dist; m_particles[0]->Move(-moveVec); m_particles[1]->Move(moveVec); } /* // Set box centre and extents Vec3f centre = (m_particles[0]->GetPos() + m_particles[1]->GetPos()) * 0.5f; m_box.SetCentre(centre); m_box.SetExtents(Vec3f(len * 0.5f, 0.2f, 1.0f)); // Align box with line seg connecting end points Vec3f xAxis = v; // Create a zAxis perpendicular to xAxis Vec3f up(0, 1.0f, 0); // Choose new up vector if xAxis is vertical! const float VERTICAL = 0.9f; float dot = DotProduct(xAxis, up); if (fabs(dot) > VERTICAL) { up = Vec3f(1.0f, 0, 0); // TODO may face other dir } Vec3f zAxis = CrossProduct(xAxis, up); Vec3f yAxis = CrossProduct(xAxis, zAxis); m_box.SetAxes(xAxis, yAxis); */ /* // Twist spring m_oldVec.Normalise(); newVec.Normalise(); float theta = acos(DotProduct(m_oldVec, newVec)); if (fabs(theta) > 0.001f) { Vec3f axis = CrossProduct(m_oldVec, newVec); axis.Normalise(); Quaternion q(axis, theta); q = GetQuat() * q; SetQuat(q); } */ m_oldVec = newVec; }
void ThirdPersonCameraBase::Update() { Camera::Update(); float dt = Engine::Instance()->GetDeltaTime(); // New for POOL // Zoom in/out, (not using mouse) if (m_zoomVel != 0) { #ifdef ZOOM_DEBUG std::cout << "ZOOM: old zoom vel: " << m_zoomVel << "\n"; #endif // Decelerate to zero static const float ZOOM_DECEL = Engine::Instance()->GetConfigFloat( "pool_cam_zoom_decel"); Assert(ZOOM_DECEL > 0); if (m_zoomVel > 0) { m_zoomVel -= ZOOM_DECEL * dt; if (m_zoomVel < 0) { m_zoomVel = 0; } } else if (m_zoomVel < 0) { m_zoomVel += ZOOM_DECEL * dt; if (m_zoomVel > 0) { m_zoomVel = 0; } } #ifdef ZOOM_DEBUG std::cout << "ZOOM: new zoom vel: " << m_zoomVel << "\n"; #endif // Move away or towards the target, at the zoom vel. Vec3f v = m_orientation.GetVertex() - m_lookAtPos; v.Normalise(); v *= m_zoomVel * dt; #ifdef ZOOM_DEBUG std::cout << "ZOOM add vec: " << ToString(v).c_str() << "\n"; #endif Vec3f v0 = m_orientation.GetVertex(); v0 += v; m_orientation.SetVertex(v0); } static float prevRot = m_yRotVel; if (m_yRotVel != 0) { static const float MAX_Y_ROT_VEL = 360.0f; //static const float MIN_Y_ROT_VEL = 10.0f; m_yRotVel += dt * m_yRotAcc; if (fabs(m_yRotVel) > MAX_Y_ROT_VEL) { m_yRotVel = MAX_Y_ROT_VEL; m_yRotAcc = 0; } if (Sign(m_yRotVel) != Sign(prevRot) && prevRot != 0) { m_yRotVel = 0; m_yRotAcc = 0; } float yRot = m_yRotVel * dt; RotateCameraHoriz(yRot); } prevRot = m_yRotVel; static float prevUp = m_upVel; if (m_upVel != 0) { //std::cout << "Up vel: " << m_upVel << " acc: " << m_upAcc; float y = GetOrientation()->GetY(); m_upVel += dt * m_upAcc; if (Sign(m_upVel) != Sign(prevUp) && prevUp != 0) { m_upVel = 0; m_upAcc = 0; } y += m_upVel * dt; //std::cout << " new Up vel: " << m_upVel << "\n"; Orientation o = *(GetOrientation()); // Never exceed the absolute max camera height. if (y > m_maxAbsHeight) { y = m_maxAbsHeight; } o.SetY(y); SetOrientation(o); } prevUp = m_upVel; }