/// \brief /// Helper function to retrieve current distance to a given plane /// /// \param vCameraPos /// Camera position to test the distance against /// \param fLODScaleSqr /// Square of the LOD scaling factor /// \param fPlane /// Reference plane distance, will be subtracted from final result /// /// \returns /// Relative distance from object to given plane inline float GetDistanceToPlane(const hkvVec3& vCameraPos, float fLODScaleSqr=1.f, float fPlane=0.f) const { int iLODMode = m_iPerformTestFlags&VIS_PERFORM_LODTEST; float fDistSqr; switch (iLODMode) { case VIS_LOD_TEST_NONE: fDistSqr = 0.0f; break; case VIS_LOD_TEST_CLIPPOSITION: fDistSqr = vCameraPos.getDistanceToSquared(m_vClipReference); break; case VIS_LOD_TEST_CLIPPOSITION|VIS_LOD_TEST_APPLYLODSCALING: fDistSqr = vCameraPos.getDistanceToSquared(m_vClipReference)*fLODScaleSqr; break; case VIS_LOD_TEST_BOUNDINGBOX: fDistSqr = m_BoundingBox.getDistanceToSquared(vCameraPos); break; case VIS_LOD_TEST_BOUNDINGBOX|VIS_LOD_TEST_APPLYLODSCALING: fDistSqr = m_BoundingBox.getDistanceToSquared(vCameraPos)*fLODScaleSqr; break; default: VASSERT_MSG(false,"Invalid combination of LOD flags"); return false; } return hkvMath::sqrt(fDistSqr) - fPlane; }
VOVERRIDE void OnClick(VMenuEventDataObject *pEvent) { VDialog::OnClick(pEvent); hkvVec2 vMousePos = GetContext()->GetCurrentMousePos(); hkvVec3 vDir; Vision::Contexts.GetCurrentContext()->GetTraceDirFromScreenPos(vMousePos.x, vMousePos.y, vDir, 10000.f); hkvVec3 vFrom = Vision::Camera.GetCurrentCameraPosition(); hkvVec3 vTo = vFrom + vDir; const float v2h = vHavokConversionUtils::GetVision2HavokScale(); hkVector4 from; from.set( vFrom.x*v2h, vFrom.y*v2h, vFrom.z*v2h ); hkVector4 to; to.set( vTo.x*v2h, vTo.y*v2h, vTo.z*v2h ); hkaiNavMeshQueryMediator::HitDetails hit; hit.m_hitFaceKey = HKAI_INVALID_PACKED_KEY; hit.m_hitFraction = -1.f; if (vHavokAiModule::GetInstance()->GetAiWorld()->getDynamicQueryMediator()->castRay(from, to, hit)) { hkVector4 hitPoint; hitPoint.setInterpolate(from, to, hit.m_hitFraction); hitPoint.mul4( vHavokConversionUtils::GetHavok2VisionScale() ); if (pEvent->m_iButtons & BUTTON_LMOUSE) { vStartPoint.set( hitPoint(0), hitPoint(1), hitPoint(2) ); } else { vEndPoint.set( hitPoint(0), hitPoint(1), hitPoint(2) ); } } }
/// \brief /// Helper function for visibility loop implementations /// /// \param vCameraPos /// Camera position to test LOD clipping /// \param fLODScaleSqr /// Square of the LOD scaling factor /// /// \returns /// true if the object is clipped either by near of far clip distance (if specified) inline bool IsNearOrFarClipped(const hkvVec3& vCameraPos, float fLODScaleSqr=1.f) const { // changes in this function have to be reflected in SPU version IsNearOrFarClipped int iLODMode = m_iPerformTestFlags&VIS_PERFORM_LODTEST; float fDistSqr; switch (iLODMode) { case VIS_LOD_TEST_NONE: return false; case VIS_LOD_TEST_CLIPPOSITION: fDistSqr = vCameraPos.getDistanceToSquared(m_vClipReference); break; case VIS_LOD_TEST_CLIPPOSITION|VIS_LOD_TEST_APPLYLODSCALING: fDistSqr = vCameraPos.getDistanceToSquared(m_vClipReference)*fLODScaleSqr; break; case VIS_LOD_TEST_BOUNDINGBOX: fDistSqr = m_BoundingBox.getDistanceToSquared(vCameraPos); break; case VIS_LOD_TEST_BOUNDINGBOX|VIS_LOD_TEST_APPLYLODSCALING: fDistSqr = m_BoundingBox.getDistanceToSquared(vCameraPos)*fLODScaleSqr; break; default: VASSERT_MSG(false,"Invalid combination of LOD flags"); return false; } return ((m_fNearClipDistance>0.f) && (fDistSqr<(m_fNearClipDistance*m_fNearClipDistance))) || ((m_fFarClipDistance>0.f) && (fDistSqr>=(m_fFarClipDistance*m_fFarClipDistance))); }
bool LineConeIntersection(IVRenderInterface *pRenderer, const hkvVec3 &vConePos, const hkvVec3 &vConeAxis, float fConeAngle, const hkvVec3 &vLineStart, const hkvVec3 &vLineDir, hkvVec3 &vIntersection) { // cull back cone float fConeLineAngle = vConeAxis.dot(vLineDir); if (fConeLineAngle < 0) return false; float fCosAngle = hkvMath::cosDeg(fConeAngle); float fCosSquared = fCosAngle*fCosAngle; hkvVec3 vLineToCone = vLineStart - vConePos; float fDotA = vConeAxis.dot(vLineToCone); float fDotB = vLineDir.dot(vLineToCone); float fDotC = vLineToCone.dot(vLineToCone); float a = fConeLineAngle*fConeLineAngle - fCosSquared; float b = fConeLineAngle*fDotA - fCosSquared*fDotB; float c = fDotA*fDotA - fCosSquared*fDotC; float fInnerValue = b*b-4*a*c; float fDenominator = 2*a; if(fInnerValue < 0.0f || fDenominator == 0.0f) return false; float fSqrtInnerValue = sqrt(fInnerValue); float t1 = (-b + fSqrtInnerValue)/fDenominator; float t2 = (-b - fSqrtInnerValue)/fDenominator; // choose front cone float t = (t1 > t2) ? t1 : t2; vIntersection = vLineStart+vLineDir*t; return true; }
bool RPG_PlayerCharacterSynchronizationGroup::QuerySynchronize(const VNetworkViewContext& context, VNetworkSynchronizationGroupInstanceInfo_t &instanceInfo, VMessageSettings& out_paketSettings) { RPG_PlayerCharacter *pObj = (RPG_PlayerCharacter*) instanceInfo.m_pInstance; VHistoryData* pData = (VHistoryData*) instanceInfo.m_pCustomData; // Save previously changed data, will be compared against the current changes. BYTE iPreviousChangedDataFlags = pData->m_iChangedDataFlags; // Add data flags, will be removed if following extrapolation tests succeed. pData->m_iChangedDataFlags |= VCD_DataFlags; hkvVec3 vInterpolatedEntry(false); float fEpsilon = 0.5f * Vision::World.GetGlobalUnitScaling(); // Extrapolate current position pData->m_positionHistory.Interpolate (&vInterpolatedEntry, context.m_iCurrentServerTimeMS); const hkvVec3 vCurrentPos = pObj->GetPosition(); if (vCurrentPos.Equals(vInterpolatedEntry, fEpsilon)) pData->m_iChangedDataFlags &= ~VCD_POSITION; // Remove position flag // Extrapolate current rotation pData->m_rotationHistory.Interpolate (&vInterpolatedEntry, context.m_iCurrentServerTimeMS); const hkvVec3 vCurrentOrientation = pObj->GetOrientation(); if (vCurrentOrientation.Equals(vInterpolatedEntry, fEpsilon)) pData->m_iChangedDataFlags &= ~VCD_ROTATION; // Remove rotation flag // Change from previous tick, send changes reliably if ((iPreviousChangedDataFlags^pData->m_iChangedDataFlags) != 0) { pData->m_iDataFlagsToSend = (iPreviousChangedDataFlags^pData->m_iChangedDataFlags) | pData->m_iChangedDataFlags; out_paketSettings.SetReliability (VMR_Reliable_Ordered); out_paketSettings.SetPriority (VMP_HighPriority); out_paketSettings.SetOrderingChannel (1); return true; } // No change from previous tick else { // Is there anything to send? if ((pData->m_iChangedDataFlags & VCD_DataFlags) != 0) { // Continuous changes are sent unreliably pData->m_iDataFlagsToSend = pData->m_iChangedDataFlags; out_paketSettings.SetReliability (VMR_Unreliable_Sequenced); out_paketSettings.SetPriority (VMP_MediumPriority); out_paketSettings.SetOrderingChannel (1); return true; } else { return false; } } }
void VFpsCameraEntity::GetCurrentMoveAxes(hkvVec3& vForward, hkvVec3& vRight, hkvVec3& vUp) const { VFreeCamera::GetCurrentMoveAxes(vForward, vRight, vUp); // Disable vertical movement. vUp = hkvVec3::ZeroVector(); // Constrain horizontal movement to the XY-plane. vForward.z = vRight.z = 0.0f; vForward.normalize(); vRight.normalize(); }
hkvVec3 RPG_Explosion::GetHerringBoneImpulse( hkvVec3 const& position ) { hkvVec3 impulse(0.0f, 0.0f, 0.0f); hkvVec3 attackLine = m_direction; attackLine.z = 0.0f; attackLine.normalize(); float const lineProjection = hkvMath::Max(0.0f, position.dot(attackLine) - m_center.dot(attackLine)); hkvVec3 const& closestPointOnAttackLine = m_center + lineProjection * attackLine; impulse = (position - closestPointOnAttackLine); impulse.z = 0.0f; float distanceLineToImpact = impulse.getLengthAndNormalize(); if(hkvMath::isFloatEqual(0.0f, distanceLineToImpact)) { if(Vision::Game.GetFloatRand() > 0.5) { impulse.x = attackLine.y; impulse.y = -attackLine.x; } else { impulse.x = -attackLine.y; impulse.y = -attackLine.x; } } impulse += attackLine; impulse.normalize(); float const strengthScale = hkvMath::Max(0.0f, (m_length - lineProjection) / m_length) * hkvMath::Max(0.0f, (m_radius - distanceLineToImpact) / m_radius); impulse.z = 0.1f; return impulse * strengthScale * m_impulseStrength; }
// Idling void RPG_PlayerControllerState::Idling::OnTick(RPG_ControllerComponent *const controller, float const deltaTime) { RPG_ControllerStateBase::OnTick(controller, deltaTime); RPG_PlayerControllerComponent *playerController = vstatic_cast<RPG_PlayerControllerComponent*>(controller); RPG_PlayerControllerInput const& input = playerController->GetInput(); RPG_PlayerControllerInput const& prevInput = playerController->GetPrevInput(); // Tick special attacks if(RPG_PlayerControllerState::OnTickSpecialAttacks(playerController, input, prevInput)) { return; } // Move bool const primaryDown = input.IsDown(RPG_PlayerControllerInput::B_PRIMARY, prevInput); bool const primaryHeld = input.IsPressed(RPG_PlayerControllerInput::B_PRIMARY) && prevInput.IsPressed(RPG_PlayerControllerInput::B_PRIMARY); if(primaryDown || primaryHeld) { if(primaryDown && input.m_targetEntity) { // Move to target controller->SetTarget(input.m_targetEntity); controller->SetTargetPoint(input.m_targetEntity->GetPosition()); } else { // Move to point controller->SetTarget(NULL); controller->SetTargetPoint(input.m_targetPoint); } hkvVec3 const targetPoint = controller->GetTargetPoint(); hkvVec3 const targetPointToCharacter(controller->GetCharacter()->GetPosition() - targetPoint); float const targetPointToCharactedDistSqr = targetPointToCharacter.getLengthSquared(); float const distTolerance = hkvMath::Max(60.0f, controller->GetPathGoalReachedTolerance()); float const distToleranceSqr = distTolerance * distTolerance; if(targetPointToCharactedDistSqr > distToleranceSqr) { controller->SetState(RPG_ControllerStateId::kMoving); return; } } }
void VFreeCamera::GetCurrentMoveAxes(hkvVec3& vForward, hkvVec3& vRight, hkvVec3& vUp) const { vUp.set(0.0f, 0.0f, 1.0f); hkvMat3 mat(hkvNoInitialization); GetRotationMatrix(mat); vForward = mat.getAxis(0); vRight = mat.getAxis(1); }
bool VWallmarkManager::IsTracePointOnPlane(const hkvVec3& vPos, const hkvVec3& vNormal, float fTraceRad, float fEpsilon, hkvVec3& vNewNormal) { hkvVec3 vStart = vPos + vNormal*fTraceRad; hkvVec3 vEnd = vPos - vNormal*fTraceRad; #ifdef WALLMARKS_USE_VISION_TRACELINES VisTraceLineInfo_t result; if (Vision::CollisionToolkit.TraceLine(vStart,vEnd,(ULONG)VIS_TRACE_ALL,(ULONG)VIS_TRACE_NONE,NULL,NULL,&result)) return false; // no hit // only allow wallmarks on static geometry and terrain if (result.hitType != VIS_TRACETYPE_STATICGEOMETRY && result.hitType != VIS_TRACETYPE_TERRAIN) return false; if (hkvMath::Abs (result.distance - fTraceRad)>fEpsilon) return false; // too much deviation from plane normal vNewNormal = result.primitivePlane.m_vNormal; float fDot = vNewNormal.dot(vNormal); if (hkvMath::Abs (fDot-1.f)>fEpsilon) return false; #else IVisPhysicsModule_cl *pPhysMod = Vision::GetApplication()->GetPhysicsModule(); VisPhysicsHit_t result; if (pPhysMod==NULL || !pPhysMod->Raycast(vStart,vEnd,result)) return false; // only allow wallmarks on static geometry and terrain if (result.eHitType != VIS_TRACETYPE_STATICGEOMETRY && result.eHitType != VIS_TRACETYPE_TERRAIN) return false; if (hkvMath::Abs ((result.fHitFraction - 0.5f)*fTraceRad)>fEpsilon) return false; //NOTE: result.vImpactNormal is the interpolated vertex normal and thus not useful here vNewNormal = vNormal; #endif // Vision::Game.DrawSingleLine(vPos,vPos+vNewNormal*20.f); return true; }
void RPG_Projectile::Fire(hkvVec3 position, hkvVec3 direction, float speed) { VASSERT(m_characterOwner); m_spawnTime = Vision::GetTimer()->GetTime(); m_currentPosition = position; SetPosition(position); VASSERT_MSG(direction.isNormalized(), "Please normalize your projectile fire direction."); m_direction = direction; m_speed = speed; hkvMat3 vRotation; vRotation.setLookInDirectionMatrix(m_direction); SetRotationMatrix(vRotation); CreateShapePhantom(); // create inflight effect CreateEffect(PFX_Inflight); }
/// \brief /// Initializes useful default inline void InitDefaults() { m_bSortTextureChannels = false; m_bUseTempFolder = false; m_sTerrainFolder = "TerrainScene"; m_iSectorCount[0] = m_iSectorCount[1] = 16; m_fViewDistance = 100000.f; m_iHeightSamplesPerSector[0] = m_iHeightSamplesPerSector[1] = 128; ///< ideal size m_vSectorSize.set(10000.f,10000.f); m_iTilesPerSector[0] = m_iTilesPerSector[1] = 16; m_iDensityMapSamplesPerSector[0] = m_iDensityMapSamplesPerSector[1] = 32; m_vTerrainPos.set(0.f,0.f,0.f); m_fPurgeInterval = 100.f; m_iMemoryLimit = 500; m_iDefaultWeightmapResolution[0] = m_iDefaultWeightmapResolution[1] = 512; m_iMaterialMapResolution[0] = m_iMaterialMapResolution[1] = 0; // no material map by default m_fVisibilityHeightOverTerrain = 2000.f; m_iReplacementLOD = -1; m_fReplacementDistance = -1.f; m_bDistanceBasedLODOnly = false; m_bIgnoreHeightForLOD = false; m_bNormalmapUsesBorder = false; m_bSceneSpecificLightmaps = false; m_bUseThreeWayMapping = false; m_bUseNormalMapping = false; m_bUseLightMapping = false; m_fPrecacheMargin = 1.0f; m_iOldSectorCount[0] = 0; m_iOldSectorCount[1] = 0; m_iOldSectorStartIndex[0] = 0; // For Terrain sector expansion m_iOldSectorStartIndex[1] = 0; m_iNewSectorStartIndex[0] = 0; // For Terrain sector expansion m_iNewSectorStartIndex[1] = 0; Finalize(); }
// Moving void RPG_PlayerControllerState::Moving::OnTick(RPG_ControllerComponent *const controller, float const deltaTime) { RPG_ControllerStateBase::OnTick(controller, deltaTime); RPG_PlayerControllerComponent *playerController = vstatic_cast<RPG_PlayerControllerComponent*>(controller); RPG_PlayerControllerInput const& input = playerController->GetInput(); RPG_PlayerControllerInput const& prevInput = playerController->GetPrevInput(); // Tick special attacks if(RPG_PlayerControllerState::OnTickSpecialAttacks(playerController, input, prevInput)) { return; } // Move or melee bool const primaryDown = input.IsDown(RPG_PlayerControllerInput::B_PRIMARY, prevInput); bool const primaryHeld = input.IsPressed(RPG_PlayerControllerInput::B_PRIMARY) && prevInput.IsPressed(RPG_PlayerControllerInput::B_PRIMARY); // Update target on click if(primaryDown) { playerController->SetTarget(input.m_targetEntity); } RPG_Character *const character = playerController->GetCharacter(); RPG_DamageableEntity *const target = playerController->GetTarget(); if(target) { hkvVec3 targetToCharacterProjectedDir; float targetToCharacterProjectedDist; RPG_ControllerUtil::GetProjectedDirAndDistanceFromTarget(character, target, targetToCharacterProjectedDir, targetToCharacterProjectedDist); float const minDist = RPG_ControllerUtil::GetMinimumDistanceToAttack(character, target); if(targetToCharacterProjectedDist > minDist) { controller->SetTargetPoint(target->GetPosition() + (target->GetCollisionRadius() + character->GetCollisionRadius()) * targetToCharacterProjectedDir); } else { controller->GetCharacter()->RaiseAnimationEvent(RPG_CharacterAnimationEvent::kMeleeAttack); controller->SetState(RPG_ControllerStateId::kMeleeAttacking); return; } } else if(primaryDown || primaryHeld) { controller->SetTargetPoint(input.m_targetPoint); } // Handle target reached or target update hkvVec3 const targetPoint = controller->GetTargetPoint(); hkvVec3 const targetPointToCharacter(character->GetPosition() - targetPoint); float const targetPointToCharactedDistSqr = targetPointToCharacter.getLengthSquared(); float const pathGoaltoleranceSqr = controller->GetPathGoalReachedTolerance() * controller->GetPathGoalReachedTolerance(); if(targetPointToCharactedDistSqr <= pathGoaltoleranceSqr) { controller->SetState(RPG_ControllerStateId::kIdling); return; } else if(primaryDown || primaryHeld) { controller->RequestPath(targetPoint); } // Reorient hkvVec3 dir; RPG_ControllerUtil::CalcDirection(dir, controller->GetCharacter()->GetDirection(), controller->GetDirection(), 0.25f); controller->GetCharacter()->SetDirection(dir); }
void vHavokShapeFactory::ExtractScaling(const hkvMat4 &mat, hkvVec3& destScaling) { hkvVec3 vx(hkvNoInitialization),vy(hkvNoInitialization),vz(hkvNoInitialization); mat.getAxisXYZ (&vx, &vy, &vz); destScaling.set(vx.getLength(),vy.getLength(),vz.getLength()); }