//---------------------------------------------------------------------------- void ProcessInputData() { if (mOverridingCamera){ mOverridingCamera->ProcessInputData(); return; } auto target = mTarget.lock(); if (!mProcessInput || !mCurrentCamera || !target) return; if (mUserParams.Changed() || mPrevTargetPos != target->GetPosition()) { mInternalParams.dist += mUserParams.dDist; mInternalParams.dist = std::max((Real)2.0f, (Real)mInternalParams.dist); if (mInternalParams.dist > 300.0) mInternalParams.dist = 300.0; mInternalParams.pitch += mUserParams.dPitch; if (mInternalParams.pitch > fb::HALF_PI - fb::Radian(5)) { mInternalParams.pitch = fb::HALF_PI - fb::Radian(5); } else if (mInternalParams.pitch < -fb::HALF_PI + fb::Radian(5)) { mInternalParams.pitch = -fb::HALF_PI + fb::Radian(5); } mInternalParams.yaw += mUserParams.dYaw; if (mInternalParams.yaw > fb::TWO_PI) { mInternalParams.yaw -= fb::TWO_PI; } else if (mInternalParams.yaw < -fb::TWO_PI) { mInternalParams.yaw += fb::TWO_PI; } Vec3 defaultDir = -Vec3::UNIT_Y; Quat qPitch(mInternalParams.pitch, Vec3::UNIT_X); Quat qYaw(-mInternalParams.yaw, Vec3::UNIT_Z); Vec3 toCam = qPitch * defaultDir; toCam = qYaw * toCam; Vec3 forward = -toCam; Vec3 right = forward.Cross(Vec3::UNIT_Z); right.Normalize(); Vec3 up = right.Cross(forward); forward = up.Cross(right); Mat33 rot(right.x, forward.x, up.x, right.y, forward.y, up.y, right.z, forward.z, up.z); Vec3 pos = target->GetPosition() + toCam * mInternalParams.dist; SetTransformation(pos, Quat(rot)); mUserParams.Clear(); mPrevTargetPos = target->GetPosition(); } }
static Transform LookAtRH(const Vec3 eye, const Vec3 at, const Vec3 up) { Vec3 n = (eye - at).Normalized(); Vec3 u = up.Cross(n).Normalized(); Vec3 v = n.Cross(u); float w = sqrtf(1.0f + u.x + v.y + n.z) * 0.5f; float w4 = 1.0f / (4.0f * w); return Transform( Vec3(-u.Dot(eye), -v.Dot(eye), -n.Dot(eye)), // Position Quat((v.z-n.y) * w4, (n.x-u.z) * w4, (u.y-v.x) * w4, -w).Normalized(), // Rotation 1); // Scale }
void CFlashUIWorldScreenPosNode::GetScreenPosFromWorld(IUIElement* pInstance, Vec3& pos /*in/out*/, Vec3& offset /*in/out*/, bool bScaleMode) { // get current camera matrix const CCamera& cam = GetISystem()->GetViewCamera(); const Matrix34& camMat = cam.GetMatrix(); // add offset to position const Vec3 vFaceingPos = camMat.GetTranslation() - camMat.GetColumn1() * 1000.f; const Vec3 vDir = (pos - vFaceingPos).GetNormalizedFast(); const Vec3 vOffsetX = vDir.Cross(Vec3Constants<float>::fVec3_OneZ).GetNormalizedFast() * offset.x; const Vec3 vOffsetY = vDir * offset.y; const Vec3 vOffsetZ = Vec3(0, 0, offset.z); const Vec3 vOffset = vOffsetX + vOffsetY + vOffsetZ; pos += vOffset; Vec2 borders; float scale; Vec3 flashPos; pInstance->WorldToFlash(camMat, pos, flashPos, borders, scale, bScaleMode); // return flashpos in pos pos = flashPos; // store overflow in offset x/y and scale in z offset.x = borders.x; offset.y = borders.y; offset.z = scale; }
void CDeflectorShield::ShootDeflectedEnergy(const CDeflectorShield::SDeflectedEnergy& energy) { if (!m_pAmmoClass) return; CProjectile* pEnergyBlast = g_pGame->GetWeaponSystem()->SpawnAmmo(m_pAmmoClass, false); if (!pEnergyBlast) return; const Matrix34& worldTransform = GetEntity()->GetWorldTM(); const float positionBias = 0.05f; const Vec3 worldReflectPos = worldTransform.TransformPoint(energy.m_localPosition); const Vec3 worldReflectDir = worldTransform.TransformVector(energy.m_localDirection); const Vec3 worldSpreadU = worldReflectDir.GetOrthogonal(); const Vec3 worldSpreadV = worldReflectDir.Cross(worldSpreadU); const float spreadOffset = cry_random(0.0f, m_spread); const Vec3 position = worldReflectPos + worldReflectDir * positionBias; Vec3 direction = worldReflectDir + (worldSpreadU * cry_random(0.0f, m_spread)) + (worldSpreadV * cry_random(0.0f, m_spread)); direction.Normalize(); CProjectile::SProjectileDesc projectileDesc( 0, 0, 0, energy.m_damage, m_dropMinDistance, m_dropPerMeter, float(m_minDamage), m_hitTypeId, 0, false); pEnergyBlast->SetParams(projectileDesc); pEnergyBlast->Launch(position, direction, Vec3(ZERO)); }
void UnderWaterGodRay::_updateProjector() { Plane p(Vec3(0, 1, 0), mWaterPosition); Vec3 sunDir = Environment::Instance()->GetEvParam()->SunDir; Vec3 sunPos = Environment::Instance()->GetEvParam()->SunPos; Ray r(sunPos, sunDir); RayIntersectionInfo info = r.Intersection(p); mEnable = info.iterscetion; mProjPosition = sunPos + sunDir * info.distance; Vec3 y(0, 1, 0); if (sunDir.Dot(y) < 0.001) y = Vec3(0, 0, -1); Vec3 x = y.Cross(sunDir); y = sunDir.Cross(x); mProjMatrix.MakeRotationAxis(x, y, sunDir); mProjMatrix._41 = mProjPosition.x; mProjMatrix._42 = mProjPosition.y; mProjMatrix._43 = mProjPosition.z; }
inline float AngleBetweenVectors( const Vec3 &v1,const Vec3 &v2 ) { float a = acos_tpl(v1.Dot(v2)); Vec3 r = v1.Cross(v2); if (r.z < 0) a = -a; return a; }
Ang3 CVehicleSeatActionOrientateBoneToView::GetDesiredViewAngles(const Vec3& lookPos, const Vec3& aimPos) const { Vec3 forwardDir = (aimPos - lookPos).GetNormalized(); Vec3 upDir = Vec3(0.f, 0.f, 1.f); Vec3 sideDir = forwardDir.Cross(upDir); sideDir.Normalize(); upDir = sideDir.Cross(forwardDir); upDir.Normalize(); Matrix34 matrix; matrix.SetFromVectors(sideDir, forwardDir, upDir, Vec3(0.f, 0.f, 0.f)); Ang3 lookAngles; lookAngles.SetAnglesXYZ(matrix); return lookAngles; }
// Ad-hoc void CFlyer::ProcessMovement(float frameTime) { frameTime = min(1.f, frameTime); float desiredSpeed = m_vDesiredVelocity.GetLength(); const float maxDeltaSpeed = 100.f; float deltaSpeed = min(maxDeltaSpeed, fabsf(desiredSpeed - m_stats.speed)); // Advance "m_velocity" towards "m_vDesiredVelocity" at the speed proportional to (1 / square(deltaSpeed)) Interpolate( m_velocity, m_vDesiredVelocity, 2.5f * ((deltaSpeed > 0.f) ? min(frameTime, 2.f / square(deltaSpeed)) : frameTime), 1.f); Quat desiredVelocityQuat = m_qDesiredRotation; // pitch/roll if (desiredSpeed > 0.f && m_stats.speed > 0.f) { const Vec3& vUp = Vec3Constants<float>::fVec3_OneZ; Vec3 vForward = m_velocity.GetNormalized(); // If the direction is not too vertical if (fabs(vForward.dot(vUp)) < cosf(DEG2RAD(3.f))) { vForward.z = 0; vForward.NormalizeSafe(); Vec3 vRight = vForward.Cross(vUp); vRight.NormalizeSafe(); Vec3 vDesiredVelocityNormalized = m_vDesiredVelocity.GetNormalized(); // Roll in an aircraft-like manner float cofRoll = 6.f * vRight.dot(vDesiredVelocityNormalized) * (m_stats.speed / maxDeltaSpeed); clamp(cofRoll, -1.f, 1.f); desiredVelocityQuat *= Quat::CreateRotationY(DEG2RAD(60.f) * cofRoll); float cofPitch = vDesiredVelocityNormalized.dot(vForward) * (deltaSpeed / maxDeltaSpeed); clamp(cofPitch, -1.f, 1.f); desiredVelocityQuat *= Quat::CreateRotationX(DEG2RAD(-60.f) * cofPitch); } } float cofRot = 2.5f * ((deltaSpeed > 0.f) ? min(frameTime, 1.f / square(deltaSpeed)) : frameTime); clamp(cofRot, 0.f, 1.f); const Quat& qRotation = GetEntity()->GetRotation(); Quat newRot = Quat::CreateSlerp(qRotation, desiredVelocityQuat, cofRot); m_moveRequest.rotation = qRotation.GetInverted() * newRot; m_moveRequest.rotation.Normalize(); m_moveRequest.velocity = m_velocity; m_moveRequest.type = eCMT_Fly; }
void CVehicleMovementAerodynamic::UpdateWing(SWing *_pWing,float _fAngle,float _fDeltaTime) { Matrix34 matWing = m_pEntity->GetWorldTM() * Matrix33::CreateRotationXYZ(Ang3(DEG2RAD(_pWing->fAngleX), DEG2RAD(_pWing->fAngleY), DEG2RAD(_pWing->fAngleZ))).GetInverted(); Vec3 vRight = matWing.GetColumn(0); Vec3 vLook = matWing.GetColumn(1); Vec3 vUp = matWing.GetColumn(2); pe_status_dynamics StatusDynamics; GetPhysics()->GetStatus(&StatusDynamics); // v(relativepoint) = v + w^(relativepoint-center) Vec3 vVelocity = StatusDynamics.v + StatusDynamics.w.Cross(m_pEntity->GetWorldTM().TransformVector(_pWing->vPos)); Vec3 vVelocityNormalized = vVelocity.GetNormalizedSafe(vLook); // TODO: float fAngleOfAttack = RAD2DEG(asin(vRight.Dot(vVelocityNormalized.Cross(vLook)))); DumpText("AoA=%f",fAngleOfAttack); fAngleOfAttack += _fAngle; float Cl = GetCoefficient(_pWing->pLiftPointsMap,fAngleOfAttack) * _pWing->fCl; float Cd = GetCoefficient(_pWing->pDragPointsMap,fAngleOfAttack) * _pWing->fCd; Vec3 vVelocityNormal = vRight.Cross(vVelocityNormalized).GetNormalized(); float fVelocitySquared = vVelocity.len2(); const float c_fDynamicPressure = 1.293f; float fLift = 0.5f * c_fDynamicPressure * _pWing->fSurface * Cl * fVelocitySquared * _fDeltaTime; float fDrag = 0.5f * c_fDynamicPressure * _pWing->fSurface * Cd * fVelocitySquared * _fDeltaTime; Vec3 vLiftImpulse = +fLift * vVelocityNormal; Vec3 vDragImpulse = -fDrag * vVelocityNormalized; AddForce(&vLiftImpulse,&_pWing->vPos,ColorF(0,1,0,1)); AddForce(&vDragImpulse,&_pWing->vPos,ColorF(1,0,1,1)); }
Matrix Matrix::LookAt(const Vec3& position, const Vec3& target, const Vec3& up) { /// Generate view matrix for position camera /// http://wiki.delphigl.com/index.php/gluLookAt const float epsilon = 0.001f; Vec3 f = -(target - position).Normal(); Vec3 s = -f.Cross(up.Normal()); float sl = s.Length(); if (fabs(sl) < epsilon) { s = -f.Cross(Vec3(up.y, up.z, up.x).Normal()); sl = s.Length(); } s /= sl; Vec3 u = s.Cross(f); Matrix m; m.m[0] = s.x; m.m[1] = s.y; m.m[2] = s.z; m.m[3] = 0; m.m[4] = u.x; m.m[5] = u.y; m.m[6] = u.z; m.m[7] = 0; m.m[8] = -f.x; m.m[9] = -f.y; m.m[10] = -f.z; m.m[11] = 0; m.m[12] = 0; m.m[13] = 0; m.m[14] = 0; m.m[15] = 1; return Translate(-position) * m; }
Vec3 RapidTrajectoryGenerator::GetOmega(double t, double timeStep) const { //Calculates the body rates necessary at time t, to rotate the normal vector. //The result is coordinated in the world frame, i.e. would have to be rotated into a //body frame. const Vec3 n0 = GetNormalVector(t); const Vec3 n1 = GetNormalVector(t + timeStep); const Vec3 crossProd = n0.Cross(n1); //direction of omega, in inertial axes if (crossProd.GetNorm2()) return (acos(n0.Dot(n1))/timeStep)*crossProd.GetUnitVector(); else return Vec3(0, 0, 0); }
inline Vec3 RotatedBy(Vec3 const &axisVec, double angleDegCCW) { if(!angleDegCCW) { return Vec3(this->x,this->y,this->z); } Vec3 rotatedVec; double angleRad = angleDegCCW*3.141592653589/180.0; rotatedVec = this->ScaledBy(cos(angleRad)) + (axisVec.Cross(*this)).ScaledBy(sin(angleRad)) + axisVec.ScaledBy(axisVec.Dot(*this)).ScaledBy(1-cos(angleRad)); return rotatedVec; }
// MakeLookAt //------------------------------------------------------------------------------ void Mat44::MakeLookAt( const Vec3 & pos, const Vec3 & lookAt, const Vec3 & upVector ) { // generate the forward vector Vec3 forward( pos - lookAt ); forward.Normalise(); Vec3 right = upVector.Cross( forward ); right.Normalise(); Vec3 up = forward.Cross( right ); up.Normalise(); col0 = Vec4( right.x, up.x, forward.x, 0.0f ); col1 = Vec4( right.y, up.y, forward.y, 0.0f ), col2 = Vec4( right.z, up.z, forward.z, 0.0f ), col3 = Vec4( -right.Dot( pos ), -up.Dot( pos ), -forward.Dot( pos ), 1.0f ); }
void CStickyProjectile::CalculateLocationForStick( const IEntity& projectile, const Vec3& collPos, const Vec3& collNormal, QuatT& outLocation ) const { if(m_flags&eSF_OrientateToCollNormal) { const float bigz = cry_fabsf(collNormal.z)-cry_fabsf(collNormal.y); const Vec3 temp(0.f,(float)__fsel(bigz,1.f,0.f),(float)__fsel(bigz,0.f,1.f)); outLocation.q = Quat(Matrix33::CreateOrientation( temp.Cross(collNormal), -collNormal, 0)); AABB aabb; projectile.GetLocalBounds(aabb); outLocation.t = collPos + (outLocation.q.GetColumn2() * ((aabb.max.y-aabb.min.y)*0.5f)); } else { outLocation.q = projectile.GetRotation(); outLocation.t = collPos + (outLocation.q.GetColumn1() * 0.1f); } }
void CCameraRayScan::ShootRays(const Vec3 &rayPos, const Vec3 &rayDir, IPhysicalEntity **pSkipEnts, int numSkipEnts) { //shoot rays for all ray_hits const Vec3 dirNorm = rayDir.normalized(); const Vec3 right = dirNorm.Cross(Vec3Constants<float>::fVec3_OneZ); const Vec3 rightOff = right * 0.15f; const Vec3 rightDir = right * 0.15f; const float len = rayDir.len() * RAY_SCAN_BUFFER_SCALE; //add some distance to be sure that the view is free const Vec3 rayPos2 = rayPos + (dirNorm * RAY_SCAN_OFFSET_DISTANCE); //move the rays away from the head to prevent clipping //center ray Vec3 tempPos = rayPos2; Vec3 tempDir = dirNorm; ShootRayInt(eRAY_CENTER, tempPos, tempDir, len, pSkipEnts, numSkipEnts); tempDir = (dirNorm - rightDir + g_vRayUpDir).normalized(); tempPos = rayPos2 - rightOff + g_vRayUpOffset; ShootRayInt(eRAY_TOP_LEFT, tempPos, tempDir, len, pSkipEnts, numSkipEnts); tempDir = (dirNorm + rightDir + g_vRayUpDir).normalized(); tempPos = rayPos2 + rightOff + g_vRayUpOffset; ShootRayInt(eRAY_TOP_RIGHT, tempPos, tempDir, len, pSkipEnts, numSkipEnts); tempDir = (dirNorm - rightDir - g_vRayUpDir).normalized(); tempPos = rayPos2 - rightOff - g_vRayUpOffset; ShootRayInt(eRAY_BOTTOM_LEFT, tempPos, tempDir, len, pSkipEnts, numSkipEnts); tempDir = (dirNorm + rightDir - g_vRayUpDir).normalized(); tempPos = rayPos2 + rightOff - g_vRayUpOffset; ShootRayInt(eRAY_BOTTOM_RIGHT, tempPos, tempDir, len, pSkipEnts, numSkipEnts); tempDir = (dirNorm + g_vRayUpDir).normalized(); tempPos = rayPos2 + g_vRayUpOffset * 2.0f; ShootRayInt(eRAY_TOP_CENTER, tempPos, tempDir, len, pSkipEnts, numSkipEnts); tempDir = (dirNorm - g_vRayUpDir).normalized(); tempPos = rayPos2 - g_vRayUpOffset * 2.0f; ShootRayInt(eRAY_BOTTOM_CENTER, tempPos, tempDir, len, pSkipEnts, numSkipEnts); }
void CUIEntityDynTexTag::UpdateView(const SViewParams &viewParams) { static const Quat rot90Deg = Quat::CreateRotationXYZ(Ang3(gf_PI * 0.5f, 0, 0)); const Vec3 vSafeVec = viewParams.rotation.GetColumn1(); for(TTags::iterator it = m_Tags.begin(); it != m_Tags.end(); ++it) { IEntity *pOwner = gEnv->pEntitySystem->GetEntity(it->OwnerId); IEntity *pTagEntity = gEnv->pEntitySystem->GetEntity(it->TagEntityId); if(pOwner && pTagEntity) { const Vec3 offset = it->fLerp < 1 ? Vec3::CreateLerp(it->vOffset, it->vNewOffset, it->fLerp) : it->vOffset; const Vec3 &vPos = pOwner->GetWorldPos(); const Vec3 vFaceingPos = viewParams.position - vSafeVec * 1000.f; const Vec3 vDir = (vPos - vFaceingPos).GetNormalizedSafe(vSafeVec); const Vec3 vOffsetX = vDir.Cross(Vec3Constants<float>::fVec3_OneZ).GetNormalized() * offset.x; const Vec3 vOffsetY = vDir * offset.y; const Vec3 vOffsetZ = Vec3(0, 0, offset.z); const Vec3 vOffset = vOffsetX + vOffsetY + vOffsetZ; const Vec3 vNewPos = vPos + vOffset; const Vec3 vNewDir = (vNewPos - vFaceingPos).GetNormalizedSafe(vSafeVec); const Quat qTagRot = Quat::CreateRotationVDir(vNewDir) * rot90Deg; // rotate 90 degrees around X-Axis pTagEntity->SetPos(vNewPos); pTagEntity->SetRotation(qTagRot); if(it->fLerp < 1) { assert(it->fSpeed > 0); it->fLerp += viewParams.frameTime * it->fSpeed; it->vOffset = offset; } } } }
//------------------------------------------------------------------------ Quat CVehicleViewFirstPerson::GetWorldRotGoal() { // now get fitting vehicle world pos/rot Quat vehicleWorldRot = m_pVehicle->GetEntity()->GetWorldRotation(); if (m_relToHorizon > 0.f) { Quat vehicleRot = m_pVehicle->GetEntity()->GetRotation(); Vec3 vx = vehicleRot * Vec3(1, 0, 0); Vec3 vy = vehicleRot * Vec3(0, 1, 0); Vec3 vz = vehicleRot * Vec3(0, 0, 1); // vx is "correct" vy = (1.0f - m_relToHorizon) * Vec3(0, 0, 1).Cross(vx) + m_relToHorizon * vy; vy.NormalizeSafe(Vec3Constants<float>::fVec3_OneY); vz = vx.Cross(vy); vz.NormalizeSafe(Vec3Constants<float>::fVec3_OneZ); vehicleWorldRot = Quat(Matrix33::CreateFromVectors(vx, vy, vz)); } return vehicleWorldRot; }
void InitIntersection(Intersection &intersection, DWORD faceIndex, FLOAT dist, FLOAT u, FLOAT v, ActorId actorId, WORD* pIndices, T* pVertices, const Mat4x4& matWorld) { intersection.m_dwFace = faceIndex; intersection.m_fDist = dist; intersection.m_fBary1 = u; intersection.m_fBary2 = v; T* v0 = &pVertices[pIndices[3 * faceIndex + 0]]; T* v1 = &pVertices[pIndices[3 * faceIndex + 1]]; T* v2 = &pVertices[pIndices[3 * faceIndex + 2]]; Vec3 a = v0->position - v1->position; Vec3 b = v2->position - v1->position; Vec3 cross = a.Cross(b); cross /= cross.Length(); Vec3 actorLoc = XMVectorBaryCentric(v0->position, v1->position, v2->position, intersection.m_fBary1, intersection.m_fBary2); intersection.m_actorLoc = actorLoc; intersection.m_worldLoc = matWorld.Xform(actorLoc); intersection.m_actorId = actorId; intersection.m_normal = cross; }
void WatchMeProcess::VOnUpdate(unsigned long deltaMs) { StrongActorPtr pTarget = MakeStrongPtr(g_pApp->m_pGame->VGetActor(m_target)); StrongActorPtr pMe = MakeStrongPtr(g_pApp->m_pGame->VGetActor(m_me)); shared_ptr<TransformComponent> pTargetTransform = MakeStrongPtr(pTarget->GetComponent<TransformComponent>(TransformComponent::g_Name)); shared_ptr<TransformComponent> pMyTransform = MakeStrongPtr(pMe->GetComponent<TransformComponent>(TransformComponent::g_Name)); if (!pTarget || !pMe || !pTargetTransform || !pMyTransform) { GCC_ERROR("This shouldn't happen"); Fail(); } Vec3 targetPos = pTargetTransform->GetPosition(); Mat4x4 myTransform = pMyTransform->GetTransform(); Vec3 myDir = myTransform.GetDirection(); myDir = Vec3(0.0f, 0.0f, 1.0f); Vec3 myPos = pMyTransform->GetPosition(); Vec3 toTarget = targetPos - myPos; toTarget.Normalize(); float dotProduct = myDir.Dot(toTarget); Vec3 crossProduct = myDir.Cross(toTarget); float angleInRadians = acos(dotProduct); if (crossProduct.y < 0) angleInRadians = -angleInRadians; Mat4x4 rotation; rotation.BuildRotationY(angleInRadians); rotation.SetPosition(myPos); pMyTransform->SetTransform(rotation); }
int CFlowConvoyNode::OnPhysicsPostStep(const EventPhys * pEvent) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); if(m_bFirstUpdate) return 0; //after QuickLoad OnPhysicsPostStep called before ProcessEvent const EventPhysPostStep *pPhysPostStepEvent = (const EventPhysPostStep *)pEvent; IPhysicalEntity *pEventPhysEnt = pPhysPostStepEvent->pEntity; Vec3 posBack, posFront, posCenter; for (size_t i = 0; i < m_coaches.size(); ++i) { IPhysicalEntity *pPhysEnt = m_coaches[i].m_pEntity->GetPhysics(); if (pEventPhysEnt == pPhysEnt) { if (m_ShiftTime > 0.0f) { m_speed = m_speed * (1.0f - breakValue * pPhysPostStepEvent->dt / m_MaxShiftTime); m_ShiftTime -= pPhysPostStepEvent->dt; } else { m_speed = m_speed + min(1.0f, (pPhysPostStepEvent->dt / 5.0f)) * (m_desiredSpeed - m_speed); } float speed = (m_splitCoachIndex > 0 && (int)i >= m_splitCoachIndex) ? m_splitSpeed : m_speed; float distance = (m_coaches[i].m_distanceOnPath += pPhysPostStepEvent->dt * speed); if(m_splitCoachIndex>0) {//train splitted if(i==m_splitCoachIndex-1) // update m_distanceOnPath for serialization m_distanceOnPath=distance-m_coaches[i].m_coachOffset; else if(i==m_coaches.size()-1) // update m_splitDistanceOnPath for serialization m_splitDistanceOnPath=distance-m_coaches[i].m_coachOffset; } else {//train in one piece if(i==m_coaches.size()-1)// update m_distanceOnPath for serialization m_distanceOnPath=distance-m_coaches[i].m_coachOffset; } posBack = m_path.GetPointAlongPath(distance - m_coaches[i].m_wheelDistance, m_coaches[i].m_backWheelIterator[0]); posFront = m_path.GetPointAlongPath(distance + m_coaches[i].m_wheelDistance, m_coaches[i].m_frontWheelIterator[0]); posCenter = (posBack+posFront)*0.5f; Vec3 posDiff = posFront - posBack; float magnitude = posDiff.GetLength(); if (magnitude > FLT_EPSILON) { posDiff *= 1.0f / magnitude; pe_params_pos ppos; ppos.pos = posCenter; ppos.q = Quat::CreateRotationVDir(posDiff); if (m_bXAxisFwd) ppos.q *= Quat::CreateRotationZ(gf_PI*-0.5f); pPhysEnt->SetParams(&ppos, 0 /* bThreadSafe=0 */); // as we are calling from the physics thread Vec3 futurePositionBack, futurePositionFront; futurePositionBack = m_path.GetPointAlongPath(distance + PATH_DERIVATION_TIME * speed - m_coaches[i].m_wheelDistance, m_coaches[i].m_backWheelIterator[1]); futurePositionFront = m_path.GetPointAlongPath(distance + PATH_DERIVATION_TIME * speed + m_coaches[i].m_wheelDistance, m_coaches[i].m_frontWheelIterator[1]); Vec3 futurePosDiff = futurePositionFront - futurePositionBack; magnitude = futurePosDiff.GetLength(); if (magnitude > FLT_EPSILON) { futurePosDiff *= 1.0f / magnitude; pe_action_set_velocity setVel; setVel.v = ((futurePositionBack+ futurePositionFront)*0.5f - posCenter) * (1.0f/PATH_DERIVATION_TIME); //Vec3 dir=(posFront-posBack).GetNormalized(); //Vec3 future_dir=(futurePositionFront-futurePositionBack).GetNormalized(); Vec3 w=posDiff.Cross(futurePosDiff); float angle=cry_asinf(w.GetLength()); setVel.w=(angle/PATH_DERIVATION_TIME)*w.GetNormalized(); pPhysEnt->Action(&setVel, 0 /* bThreadSafe=0 */); // as we are calling from the physics thread break; } } } } // Done processing once we reach end of path if (m_atEndOfPath) m_processNode = false; return 0; }
inline void Mesh::addTriangle(int vu, int vv, int vw, int nu, int nv, int nw, int tu, int tv, int tw) { int fvu = vu, fvv = vv, fvw = vw, fnu = nu, fnv = nv, fnw = nw, ftu = tu, ftv = tv, ftw = tw; // VP (Vedad and Piotr) test - Flip incorrect normals if (fixNormals) { Vec3 faceNormal; const Vec3 edge1 = s->v[startVertex + fvv] - s->v[startVertex + fvu], edge2 = s->v[startVertex + fvw] - s->v[startVertex + fvu]; faceNormal.Cross(edge1, edge2); faceNormal.Normalize(); Vec3 faceNormalFromVN = (s->vn[startNormal + fnu] + s->vn[startNormal + fnv] + s->vn[startNormal + fnw]); faceNormalFromVN.Normalize(); if (faceNormal.Dot(faceNormalFromVN) <= 0.0f) { fvu = vw; fvv = vv; fvw = vu; fnu = nw, fnv = nv, fnw = nu; ftu = tw, ftv = tv, ftw = tu; } } // Change winding of model (vertices and their normals) if (flipWinding) { fvu = vw; fvv = vv; fvw = vu; fnu = nw, fnv = nv, fnw = nu; ftu = tw, ftv = tv, ftw = tu; } fvu += startVertex; fvv += startVertex; fvw += startVertex; fnu += startNormal; fnv += startNormal; fnw += startNormal; ftu += startTex; ftv += startTex; ftw += startTex; if (curbsdf == NULL) curbsdf = bsdf; // Add index entries s->index.Add(VecIndex(fvu, fvv, fvw)); Vec3 *v[3], *n[3], *t[3]; // Set all initially to NULL n[0] = NULL; n[1] = NULL; n[2] = NULL; t[0] = NULL; t[1] = NULL; t[2] = NULL; v[0] = &s->v[fvu]; v[1] = &s->v[fvv]; v[2] = &s->v[fvw]; if (nu != 0 && nv != 0 && nw != 0) { n[0] = &s->vn[fnu]; n[1] = &s->vn[fnv]; n[2] = &s->vn[fnw]; s->vnIndex.Add(VecIndex(fnu, fnv, fnw)); } else s->vnIndex.Add(VecIndex(-1, -1, -1)); if (tu != 0 && tv != 0 && tw != 0) { t[0] = &s->tex[ftu]; t[1] = &s->tex[ftv]; t[2] = &s->tex[ftw]; s->texIndex.Add(VecIndex(ftu, ftv, ftw)); } else s->texIndex.Add(VecIndex(-1, -1, -1)); s->t.Add(MollerTriangle(s->t.size(), curbsdf, v[0], v[1], v[2], n[0], n[1], n[2], t[0], t[1], t[2])); // Store face that these verticies belong to vertFaces[fvu - startVertex - 1].push_back(s->t.size() - 1); vertFaces[fvv - startVertex - 1].push_back(s->t.size() - 1); vertFaces[fvw - startVertex - 1].push_back(s->t.size() - 1); }
//------------------------------------------------------------------------ void CItem::UpdateMounted(float frameTime) { IRenderAuxGeom* pAuxGeom = gEnv->pRenderer->GetIRenderAuxGeom(); if (!m_ownerId || !m_stats.mounted) return; CActor *pActor = GetOwnerActor(); if (!pActor) return; CheckViewChange(); if (true) { if (IsClient()) { ICharacterInstance *pCharacter = GetEntity()->GetCharacter(eIGS_FirstPerson); if (pCharacter && !m_idleAnimation[eIGS_FirstPerson].empty() && pCharacter->GetISkeletonAnim()->GetNumAnimsInFIFO(0)<1) PlayAction(m_idleAnimation[eIGS_FirstPerson], 0, true); } // need to explicitly update characters at this point // cause the entity system update occered earlier, with the last position for (int i=0; i<eIGS_Last; i++) { if (GetEntity()->GetSlotFlags(i)&ENTITY_SLOT_RENDER) { ICharacterInstance *pCharacter = GetEntity()->GetCharacter(i); if (pCharacter) { Matrix34 mloc = GetEntity()->GetSlotLocalTM(i,false); Matrix34 m34 = GetEntity()->GetWorldTM()*mloc; QuatT renderLocation = QuatT(m34); pCharacter->GetISkeletonPose()->SetForceSkeletonUpdate(9); pCharacter->SkeletonPreProcess(renderLocation, renderLocation, GetISystem()->GetViewCamera(),0x55 ); pCharacter->SetPostProcessParameter(renderLocation, renderLocation, 0, 0.0f, 0x55 ); } } } // f32 fColor[4] = {1,1,0,1}; // f32 g_YLine=60.0f; // gEnv->pRenderer->Draw2dLabel( 1,g_YLine, 1.3f, fColor, false, "Mounted Gun Code" ); //adjust the orientation of the gun based on the aim-direction SMovementState info; IMovementController* pMC = pActor->GetMovementController(); pMC->GetMovementState(info); Vec3 dir = info.aimDirection.GetNormalized(); Matrix34 tm = Matrix33::CreateRotationVDir(dir); Vec3 vGunXAxis=tm.GetColumn0(); if (pActor->GetLinkedVehicle()==0) { if (pMC) { if(!pActor->IsPlayer()) { // prevent snapping direction Vec3 currentDir = GetEntity()->GetWorldRotation().GetColumn1(); float dot = currentDir.Dot(dir); dot = CLAMP(dot,-1,1); float reqAngle = cry_acosf(dot); const float maxRotSpeed = 2.0f; float maxAngle = frameTime * maxRotSpeed; if(fabs(reqAngle) > maxAngle) { Vec3 axis = currentDir.Cross(dir); if(axis.GetLengthSquared()>0.001f) // current dir and new dir are enough different dir = currentDir.GetRotated(axis.GetNormalized(),sgn(reqAngle)*maxAngle); } } //adjust the orientation of the gun based on the aim-direction tm = Matrix33::CreateRotationVDir(dir); Vec3 vWPos=GetEntity()->GetWorldPos(); tm.SetTranslation(vWPos); GetEntity()->SetWorldTM(tm); //set the new orientation of the mounted gun vGunXAxis=tm.GetColumn0(); Vec3 vInitialAimDirection = m_stats.mount_dir; Matrix33 vInitialPlayerOrientation = Matrix33::CreateRotationVDir(vInitialAimDirection); assert( vInitialAimDirection.IsUnit() ); Vec3 newp; if (pActor->IsThirdPerson()) { //third person f32 dist = m_mountparams.body_distance*1.3f; Vec3 oldp = pActor->GetEntity()->GetWorldPos(); newp = GetEntity()->GetWorldPos()-vInitialAimDirection*dist; //mounted gun newp.z = oldp.z; } else { //first person f32 fMoveBack = (1.0f+(dir.z*dir.z*dir.z*dir.z*4.0f))*0.75f; f32 dist = m_mountparams.eye_distance*fMoveBack; Vec3 oldp = pActor->GetEntity()->GetWorldPos(); newp = GetEntity()->GetWorldPos()-dir*dist; //mounted gun //newp.z -= 0.75f; newp.z = oldp.z; } Matrix34 actortm(pActor->GetEntity()->GetWorldTM()); //if (pActor->IsThirdPerson()) actortm=vInitialPlayerOrientation; actortm.SetTranslation(newp); pActor->GetEntity()->SetWorldTM(actortm, ENTITY_XFORM_USER); pActor->GetAnimationGraphState()->SetInput("Action","gunnerMounted"); //f32 g_YLine=80.0f; //gEnv->pRenderer->Draw2dLabel( 1,g_YLine, 1.3f, fColor, false, "Mounted Gun Active for FP and AI" ); if (ICharacterInstance *pCharacter = pActor->GetEntity()->GetCharacter(0)) { ISkeletonAnim *pSkeletonAnim = pCharacter->GetISkeletonAnim(); assert(pSkeletonAnim); uint32 numAnimsLayer = pSkeletonAnim->GetNumAnimsInFIFO(0); for(uint32 i=0; i<numAnimsLayer; i++) { CAnimation &animation = pSkeletonAnim->GetAnimFromFIFO(0, i); if (animation.m_AnimParams.m_nFlags & CA_MANUAL_UPDATE) { f32 aimrad = Ang3::CreateRadZ(Vec2(vInitialAimDirection),Vec2(dir)); animation.m_fAnimTime = clamp_tpl(aimrad/gf_PI,-1.0f,+1.0f)*0.5f+0.5f; //if (pActor->IsThirdPerson()==0) //animation.m_fAnimTime=0.6f; //Ivo & Benito: high advanced future code. don't ask what it is //Benito - Not needed any more ;) //f32 g_YLine=100.0f; //gEnv->pRenderer->Draw2dLabel( 1,g_YLine, 1.3f, fColor, false, "AnimTime: %f MyAimAngle: %f deg:% distance:%f", animation.m_fAnimTime, aimrad, RAD2DEG(aimrad),m_mountparams.body_distance ); } } } m_stats.mount_last_aimdir = dir; } } if (ICharacterInstance* pCharInstance = pActor->GetEntity()->GetCharacter(0)) { if (ISkeletonAnim* pSkeletonAnim = pCharInstance->GetISkeletonAnim()) { OldBlendSpace ap; if (GetAimBlending(ap)) { pSkeletonAnim->SetBlendSpaceOverride(eMotionParamID_TurnSpeed, 0.5f + 0.5f * ap.m_turn, true); } } } UpdateIKMounted(pActor, vGunXAxis*0.1f); RequireUpdate(eIUS_General); } }
void buildPlaneGeometry(Vec3 const &vecCenter, Vec3 const &vecNormal, Vec3 const &vecUp, double width, double height, unsigned int widthSegments, unsigned int heightSegments, std::vector<Vec3> &vertexArray, std::vector<Vec2> &texCoords, std::vector<unsigned int> &triIdx) { double segmentWidth = width/widthSegments; double segmentHeight = height/heightSegments; // build vertex attributes for(int i=0; i <= widthSegments; i++) { // rows for(int j=0; j <= heightSegments; j++) { // cols vertexArray.push_back(Vec3(i*segmentWidth,j*segmentHeight,0.0)); texCoords.push_back(Vec2(i*segmentWidth/width,j*segmentHeight/height)); } } // stitch faces together unsigned int vIdx = 0; for(int i=0; i < widthSegments; i++) { // rows for(int j=0; j < heightSegments; j++) { // cols triIdx.push_back(vIdx); triIdx.push_back(vIdx+heightSegments+1); triIdx.push_back(vIdx+heightSegments+2); triIdx.push_back(vIdx); triIdx.push_back(vIdx+heightSegments+2); triIdx.push_back(vIdx+1); vIdx++; } vIdx++; } // translate to origin, then rotate, then translate to center Vec3 vecTranslate(-1*width/2,-1*height/2,0); // transformed x,y,z Vec3 xformedx = vecUp.Cross(vecNormal).Normalized(); Vec3 xformedy = vecUp.Normalized(); Vec3 xformedz = vecNormal.Normalized(); for(int i=0; i < vertexArray.size(); i++) { // translate relative to (0,0,0) vertexArray[i] = vertexArray[i] + vecTranslate; // xform matrix multiplication (col. major mult.) double vx = vertexArray[i].x; double vy = vertexArray[i].y; double vz = vertexArray[i].z; vx = xformedx.x*vertexArray[i].x + xformedy.x*vertexArray[i].y + xformedz.x*vertexArray[i].z; vy = xformedx.y*vertexArray[i].x + xformedy.y*vertexArray[i].y + xformedz.y*vertexArray[i].z; vz = xformedx.z*vertexArray[i].x + xformedy.z*vertexArray[i].y + xformedz.z*vertexArray[i].z; vertexArray[i].x = vx + vecCenter.x; vertexArray[i].y = vy + vecCenter.y; vertexArray[i].z = vz + vecCenter.z; // Vec3 earthSurfPt; Vec3 rayOrigin = vertexArray[i].Normalized().ScaledBy(ELL_SEMI_MAJOR*1.1); // so its closer to the side we want Vec3 rayDirn = vertexArray[i].Normalized().ScaledBy(-1); // invert direction calcRayEarthIntersection(rayOrigin,rayDirn,earthSurfPt); vertexArray[i] = earthSurfPt; } }
void buildPolylineAsTriStrip(std::vector<Vec3> const &listPolylineVx, double const polylineWidth, std::vector<Vec3> &listVx, std::vector<Vec2> &listTx, double &polylineLength) { size_t numPts = listPolylineVx.size(); size_t numOffsets = (numPts-1)*2; // 2 for each edge std::vector<Vec3> listOffsetPtsL(numOffsets); std::vector<Vec3> listOffsetPtsR(numOffsets); std::vector<Vec2> listOffsetTxL(numOffsets); std::vector<Vec2> listOffsetTxR(numOffsets); Vec3 vecNormal; // vector originating at the center of the earth // (0,0,0) to a vertex on the way Vec3 vecDirn; // vector along a given segment on the way Vec3 vecOffset; // vector normal to both vecPlaneNormal and // vecAlongSegment (used to create offset) Vec3 vecOffsetL,vecOffsetR; // offsets from way center // keep track of edge distances and total length double totalLength = 0; std::vector<double> listEdgeDists(numPts,0); // we offset the polyline on both sides of the // centerline and stitch the resulting shape together // to account for self intersections or gaps that occur in // the 'inner' or 'outer' offsets, we use the perpendicular // bisector of the adjoining edges to find the inner edge // intersection and straight lines to fill outer edge gaps // (this provides a bevel/boxed joint effect) // in the resulting triangle strip, each 'joint' created // from adjacent edges in the original polyline contains // one degenerate triangle // [TODO: in MapRenderer, discard duplicate adjacent vertex data] // for each segment, create dirn and offset vecs size_t k=0; double offsetLength = polylineWidth/2; for(size_t i=1; i < numPts; i++) { // offset vertex coordinates vecNormal = listPolylineVx[i]; vecDirn = listPolylineVx[i]-listPolylineVx[i-1]; vecOffset = vecDirn.Cross(vecNormal).Normalized(); vecOffsetL = vecOffset.ScaledBy(offsetLength); vecOffsetR = vecOffsetL.ScaledBy(-1.0); listOffsetPtsL[k] = listPolylineVx[i-1]+vecOffsetL; listOffsetPtsR[k] = listPolylineVx[i-1]+vecOffsetR; k++; listOffsetPtsL[k] = listPolylineVx[i]+vecOffsetL; listOffsetPtsR[k] = listPolylineVx[i]+vecOffsetR; k++; // edge length and total polyline length double edgeLength = vecDirn.Magnitude(); listEdgeDists[i] = listEdgeDists[i-1]+edgeLength; totalLength += edgeLength; } k=0; for(size_t i=1; i < numPts; i++) { // offset texture coordinates listOffsetTxL[k].x = 0.0; listOffsetTxR[k].x = 1.0; listOffsetTxL[k].y = listEdgeDists[i-1]/totalLength; listOffsetTxR[k].y = listOffsetTxL[k].y; k++; listOffsetTxL[k].x = 0.0; listOffsetTxR[k].x = 1.0; listOffsetTxL[k].y = listEdgeDists[i]/totalLength; listOffsetTxR[k].y = listOffsetTxL[k].y; k++; } if(numPts > 2) { // we only adjust the join vertices // if there's more than one edge for(size_t i=1; i < numPts-1; i++) { // continue; size_t idx = (i*2)-2; // first idx for prev edge offset // determine the angle between two adjacent edges Vec3 edgePrev = (listPolylineVx[i-1]-listPolylineVx[i]).Normalized(); Vec3 edgeNext = (listPolylineVx[i+1]-listPolylineVx[i]).Normalized(); Vec3 edgeBisect = edgePrev+edgeNext; double edgeBisectLength = edgeBisect.Magnitude(); std::cout << "edgeBisectLength:" << edgeBisect.Magnitude() << ", "; // special case: collinear edges if(edgeBisectLength < 0.001) { listOffsetPtsL[idx+1] = listOffsetPtsL[idx+2];//listOffsetPtsR[idx+1]; listOffsetPtsR[idx+1] = listOffsetPtsR[idx+2];//listOffsetPtsR[idx+2]; continue; } // |AxB| = |A|*|B|*sinTheta double sinTheta = (edgePrev.Cross(edgeBisect)).Magnitude()/ (edgePrev.Magnitude()*edgeBisectLength); std::cout << "sinTheta:" << sinTheta << ", "; // special case: // * extreme angle between segments // * edge doubles back on itself [bad data] if(sinTheta < 0.33) { listOffsetPtsL[idx+1] = listOffsetPtsR[idx+2]; listOffsetPtsL[idx+2] = listOffsetPtsR[idx+1]; continue; } // get the vertex coincident with the xsec of adjacent inside edges Vec3 vecBisect = edgeBisect.Normalized().ScaledBy(offsetLength/sinTheta); std::cout << "vecBisect:" << vecBisect.Magnitude() << std::endl; vecBisect = listPolylineVx[i]+vecBisect; // determine which side (left or right) corresponds // to the inner and outer offsets and move vertices double distToXsecL = listOffsetPtsL[idx+1].Distance2To(vecBisect); double distToXsecR = listOffsetPtsR[idx+1].Distance2To(vecBisect); if(distToXsecL < distToXsecR) { // left is the inner offset listOffsetPtsL[idx+1] = vecBisect; listOffsetPtsL[idx+2] = vecBisect; } else { // right is the inner offset listOffsetPtsR[idx+1] = vecBisect; listOffsetPtsR[idx+2] = vecBisect; } } } // save vertex data listVx.resize(listOffsetPtsL.size()*2); listTx.resize(listVx.size()); k=0; for(size_t i=0; i < listOffsetPtsL.size(); i++) { // left listVx[k] = listOffsetPtsL[i]; listTx[k] = listOffsetTxL[i]; k++; // right listVx[k] = listOffsetPtsR[i]; listTx[k] = listOffsetTxR[i]; k++; } // save length polylineLength = totalLength; }
virtual void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo ) { switch (event) { case eFE_Initialize: break; case eFE_Activate: IGameFramework* pGameFramework = gEnv->pGame->GetIGameFramework(); if(IsPortActive(pActInfo, EIP_Cast)) { // setup ray + optionally skip 1 entity ray_hit rayHit; static const float maxRayDist = 100.f; const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any; IPhysicalEntity *skipList[1]; int skipCount = 0; IEntity* skipEntity = gEnv->pEntitySystem->GetEntity(GetPortEntityId(pActInfo, EIP_SkipEntity)); if(skipEntity) { skipList[0] = skipEntity->GetPhysics(); skipCount = 1; } Vec3 rayPos = GetPortVec3(pActInfo, EIP_RayPos); Vec3 rayDir = GetPortVec3(pActInfo, EIP_RayDir); // Check if the ray hits an entity if(gEnv->pSystem->GetIPhysicalWorld()->RayWorldIntersection(rayPos, rayDir * 100, ent_all, flags, &rayHit, 1, skipList, skipCount)) { int type = rayHit.pCollider->GetiForeignData(); if (type == PHYS_FOREIGN_ID_ENTITY) { IEntity* pEntity = (IEntity*)rayHit.pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY); IEntityRenderProxy* pRenderProxy = pEntity ? (IEntityRenderProxy*)pEntity->GetProxy(ENTITY_PROXY_RENDER) : 0; // Get the renderproxy, and use it to check if the material is a DynTex, and get the UIElement if so if(pRenderProxy) { IRenderNode *pRenderNode = pRenderProxy->GetRenderNode(); IMaterial* pMaterial = pRenderProxy->GetRenderMaterial(); SEfResTexture* texture = 0; if(pMaterial && pMaterial->GetShaderItem().m_pShaderResources) texture= pMaterial->GetShaderItem().m_pShaderResources->GetTexture(EFTT_DIFFUSE); IUIElement* pElement = texture ? gEnv->pFlashUI->GetUIElementByInstanceStr(texture->m_Name) : 0; if(pElement && pRenderNode) { int m_dynTexGeomSlot = 0; IStatObj* pObj = pRenderNode->GetEntityStatObj(m_dynTexGeomSlot); // result bool hasHit = false; Vec2 uv0, uv1, uv2; Vec3 p0, p1, p2; Vec3 hitpos; // calculate ray dir CCamera cam = gEnv->pRenderer->GetCamera(); if (pEntity->GetSlotFlags(m_dynTexGeomSlot) & ENTITY_SLOT_RENDER_NEAREST) { ICVar *r_drawnearfov = gEnv->pConsole->GetCVar("r_DrawNearFoV"); assert(r_drawnearfov); cam.SetFrustum(cam.GetViewSurfaceX(),cam.GetViewSurfaceZ(),DEG2RAD(r_drawnearfov->GetFVal()),cam.GetNearPlane(),cam.GetFarPlane(), cam.GetPixelAspectRatio()); } Vec3 vPos0 = rayPos; Vec3 vPos1 = rayPos + rayDir; // translate into object space const Matrix34 m = pEntity->GetWorldTM().GetInverted(); vPos0 = m * vPos0; vPos1 = m * vPos1; // walk through all sub objects const int objCount = pObj->GetSubObjectCount(); for (int obj = 0; obj <= objCount && !hasHit; ++obj) { Vec3 vP0, vP1; IStatObj* pSubObj = NULL; if (obj == objCount) { vP0 = vPos0; vP1 = vPos1; pSubObj = pObj; } else { IStatObj::SSubObject* pSub = pObj->GetSubObject(obj); const Matrix34 mm = pSub->tm.GetInverted(); vP0 = mm * vPos0; vP1 = mm * vPos1; pSubObj = pSub->pStatObj; } IRenderMesh* pMesh = pSubObj ? pSubObj->GetRenderMesh() : NULL; if (pMesh) { const Ray ray(vP0, (vP1-vP0).GetNormalized() * maxRayDist); hasHit = RayIntersectMesh(pMesh, pMaterial, pElement, ray, hitpos, p0, p1, p2, uv0, uv1, uv2); } } // skip if not hit if (!hasHit) { ActivateOutput(pActInfo, EOP_Failed, 1); return; } // calculate vectors from hitpos to vertices p0, p1 and p2: const Vec3 v0 = p0-hitpos; const Vec3 v1 = p1-hitpos; const Vec3 v2 = p2-hitpos; // calculate factors const float h = (p0-p1).Cross(p0-p2).GetLength(); const float f0 = v1.Cross(v2).GetLength() / h; const float f1 = v2.Cross(v0).GetLength() / h; const float f2 = v0.Cross(v1).GetLength() / h; // find the uv corresponding to hitpos Vec3 uv = uv0 * f0 + uv1 * f1 + uv2 * f2; // translate to flash space int x, y, width, height; float aspect; pElement->GetFlashPlayer()->GetViewport(x, y, width, height, aspect); int iX = int_round(uv.x * (float)width); int iY = int_round(uv.y * (float)height); // call the function provided if it is present in the UIElement description string funcName = GetPortString(pActInfo, EIP_CallFunction); const SUIEventDesc* eventDesc = pElement->GetFunctionDesc(funcName); if(eventDesc) { SUIArguments arg; arg.AddArgument(iX); arg.AddArgument(iY); pElement->CallFunction(eventDesc->sName, arg); } ActivateOutput(pActInfo, EOP_Success, 1); } } } } ActivateOutput(pActInfo, EOP_Failed, 1); } break; } }
bool Triangle::Intersect(const Ray& ray, Intersection& intersection) const { // // Moller–Trumbore intersection algorithm // Vec3 p = ray.direction.Cross(e2_); float det = e1_.Dot(p); // check determinant if (ray.refracted) { if (det > -Util::Eps) { // if det is close to 0 - ray lies in plane of triangle // if det is positive - ray comes from outside return false; } } else { if (det < Util::Eps) { // if det is close to 0 - ray lies in plane of triangle // if det is negative - ray comes from middle return false; } } // invert determinant float invDet = 1.0f / det; // get first barycentric coordinate Vec3 s = ray.origin - vertices_[0].coord; float u = invDet * s.Dot(p); // check first barycentric coordinate if ((u < 0.0f) || (u > 1.0f)) { return false; } // get second barycentric coordinate Vec3 q = s.Cross(e1_); float v = invDet * ray.direction.Dot(q); // check second and third barycentric coordinates if ((v < 0.0f) || ((u + v) > 1.0f)) { return false; } // at this stage we can compute t to find out where // the intersection point is on the line float t = invDet * e2_.Dot(q); // check intersection if (t < Util::Eps) { // this means that there is a line intersection // but not a ray intersection return false; } // ray intersection point Vec3 point = ray.origin + t * ray.direction; // normal intersection.normal = ((1.0f - u - v) * vertices_[0].normal + u * vertices_[1].normal + v * vertices_[2].normal).Normalize(); // fill the intersection data intersection.point = std::move(point); // intersection.normal = n; intersection.distance = t; return true; }
void CMountedGunController::Update(EntityId mountedGunID, float frameTime) { CRY_ASSERT_MESSAGE(m_pControlledPlayer, "Controlled player not initialized"); CItem* pMountedGun = static_cast<CItem*>(gEnv->pGame->GetIGameFramework()->GetIItemSystem()->GetItem(mountedGunID)); bool canUpdateMountedGun = (pMountedGun != NULL) && (pMountedGun->GetStats().mounted); if (canUpdateMountedGun) { IMovementController * pMovementController = m_pControlledPlayer->GetMovementController(); assert(pMovementController); SMovementState info; pMovementController->GetMovementState(info); IEntity* pMountedGunEntity = pMountedGun->GetEntity(); const Matrix34& lastMountedGunWorldTM = pMountedGunEntity->GetWorldTM(); Vec3 desiredAimDirection = info.aimDirection.GetNormalized(); // AI can switch directions too fast, prevent snapping if(!m_pControlledPlayer->IsPlayer()) { const Vec3 currentDir = lastMountedGunWorldTM.GetColumn1(); const float dot = clamp(currentDir.Dot(desiredAimDirection), -1.0f, 1.0f); const float reqAngle = cry_acosf(dot); const float maxRotSpeed = 2.0f; const float maxAngle = frameTime * maxRotSpeed; if(fabs(reqAngle) > maxAngle) { const Vec3 axis = currentDir.Cross(desiredAimDirection); if(axis.GetLengthSquared() > 0.001f) // current dir and new dir are enough different { desiredAimDirection = currentDir.GetRotated(axis.GetNormalized(),sgn(reqAngle)*maxAngle); } } } bool isUserClient = m_pControlledPlayer->IsClient(); IEntity* pMountedGunParentEntity = pMountedGunEntity->GetParent(); IVehicle *pVehicle = NULL; if(pMountedGunParentEntity && m_pControlledPlayer) pVehicle = m_pControlledPlayer->GetLinkedVehicle(); CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); //For client update always, for others only when there is notable change if (!pVehicle && (isUserClient || (!desiredAimDirection.IsEquivalent(lastMountedGunWorldTM.GetColumn1(), 0.003f)))) { Quat rotation = Quat::CreateRotationVDir(desiredAimDirection, 0.0f); pMountedGunEntity->SetRotation(rotation); if (isUserClient && pRecordingSystem) { // Only record the gun position if you're using the gun. pRecordingSystem->OnMountedGunRotate(pMountedGunEntity, rotation); } } const Vec3 vInitialAimDirection = GetMountDirection(pMountedGun, pMountedGunParentEntity); assert( vInitialAimDirection.IsUnit() ); //Adjust gunner position and animations UpdateGunnerLocation(pMountedGun, pMountedGunParentEntity, vInitialAimDirection); const float aimrad = Ang3::CreateRadZ(Vec2(vInitialAimDirection),Vec2(-desiredAimDirection)); const float pitchLimit = sin_tpl(DEG2RAD(30.0f)); const float animHeight = fabs_tpl(clamp(desiredAimDirection.z * (float)__fres(pitchLimit), -1.0f, 1.0f)); const float aimUp = (float)__fsel(-desiredAimDirection.z, 0.0f, animHeight); const float aimDown = (float)__fsel(desiredAimDirection.z, 0.0f, animHeight); if (pRecordingSystem) { pRecordingSystem->OnMountedGunUpdate(m_pControlledPlayer, aimrad, aimUp, aimDown); } if(!m_pControlledPlayer->IsThirdPerson()) { UpdateFirstPersonAnimations(pMountedGun, desiredAimDirection); } if(m_pMovementAction) { const float aimUpParam = aimUp; const float aimDownParam = aimDown; const float aimMovementParam = CalculateAnimationTime(aimrad); m_pMovementAction->SetParam(MountedGunCRCs.aimUpParam, aimUpParam); m_pMovementAction->SetParam(MountedGunCRCs.aimDownParam, aimDownParam); m_pMovementAction->SetParam(MountedGunCRCs.aimMovementParam, aimMovementParam); } UpdateIKMounted(pMountedGun); } }
void CHUD::IndicateDamage(EntityId weaponId, Vec3 direction, bool onVehicle) { Vec3 vlookingDirection = FORWARD_DIRECTION; CGameFlashAnimation* pAnim = NULL; CActor *pPlayerActor = static_cast<CActor *>(gEnv->pGame->GetIGameFramework()->GetClientActor()); if(!pPlayerActor) return; if(IEntity *pEntity = gEnv->pEntitySystem->GetEntity(weaponId)) { if(pEntity->GetClass() == CItem::sGaussRifleClass) { m_animRadarCompassStealth.Invoke("GaussHit"); m_animPlayerStats.Invoke("GaussHit"); } } IMovementController *pMovementController = NULL; float fFront = 0.0f; float fRight = 0.0f; if(!onVehicle) { if(!g_pGameCVars->hud_chDamageIndicator) return; pMovementController = pPlayerActor->GetMovementController(); pAnim = m_pHUDCrosshair->GetFlashAnim(); } else if(IVehicle *pVehicle = pPlayerActor->GetLinkedVehicle()) { pMovementController = pVehicle->GetMovementController(); pAnim = &(m_pHUDVehicleInterface->m_animStats); } if(pMovementController && pAnim) { SMovementState sMovementState; pMovementController->GetMovementState(sMovementState); vlookingDirection = sMovementState.eyeDirection; } else return; if(!onVehicle) { //we use a static/world damage indicator and add the view rotation to the indicator animation now fFront = -(Vec3(0,-1,0).Dot(direction)); fRight = -(Vec3(-1, 0, 0).Dot(direction)); } else { Vec3 vRightDir = vlookingDirection.Cross(Vec3(0,0,1)); fFront = -vlookingDirection.Dot(direction); fRight = -vRightDir.Dot(direction); } if(fabsf(fFront) > 0.35f) { if(fFront > 0) pAnim->Invoke("setDamageDirection", 1); else pAnim->Invoke("setDamageDirection", 3); } if(fabsf(fRight) > 0.35f) { if(fRight > 0) pAnim->Invoke("setDamageDirection", 2); else pAnim->Invoke("setDamageDirection", 4); } if(fFront == 0.0f && fRight == 0.0f) { pAnim->Invoke("setDamageDirection", 1); pAnim->Invoke("setDamageDirection", 2); pAnim->Invoke("setDamageDirection", 3); pAnim->Invoke("setDamageDirection", 4); } m_fDamageIndicatorTimer = gEnv->pTimer->GetFrameStartTime().GetSeconds(); }