Integrating github/staging through commit 5f214be
This commit is contained in:
@@ -82,9 +82,6 @@
|
||||
|
||||
static const char* s_azFrameworkWarningWindow = "AzFramework";
|
||||
|
||||
static const char* s_engineConfigFileName = "engine.json";
|
||||
static const char* s_engineConfigEngineVersionKey = "LumberyardVersion";
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
namespace ApplicationInternal
|
||||
@@ -264,24 +261,8 @@ namespace AzFramework
|
||||
|
||||
void Application::PreModuleLoad()
|
||||
{
|
||||
// Calculate the engine root by reading the engine.json file
|
||||
AZStd::string engineJsonPath = AZStd::string_view{ m_engineRoot };
|
||||
engineJsonPath += s_engineConfigFileName;
|
||||
AzFramework::StringFunc::Path::Normalize(engineJsonPath);
|
||||
AZ::IO::LocalFileIO localFileIO;
|
||||
auto readJsonResult = AzFramework::FileFunc::ReadJsonFile(engineJsonPath, &localFileIO);
|
||||
|
||||
if (readJsonResult.IsSuccess())
|
||||
{
|
||||
SetRootPath(RootPathType::EngineRoot, m_engineRoot.c_str());
|
||||
AZ_TracePrintf(s_azFrameworkWarningWindow, "Engine Path: %s\n", m_engineRoot.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is any problem reading the engine.json file, then default to engine root to the app root
|
||||
AZ_Warning(s_azFrameworkWarningWindow, false, "Unable to read engine.json file '%s' (%s). Defaulting the engine root to '%s'", engineJsonPath.c_str(), readJsonResult.GetError().c_str(), m_appRoot.c_str());
|
||||
SetRootPath(RootPathType::EngineRoot, m_appRoot.c_str());
|
||||
}
|
||||
SetRootPath(RootPathType::EngineRoot, m_engineRoot.c_str());
|
||||
AZ_TracePrintf(s_azFrameworkWarningWindow, "Engine Path: %s\n", m_engineRoot.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -504,13 +485,13 @@ namespace AzFramework
|
||||
|
||||
void Application::ResolveEnginePath(AZStd::string& engineRelativePath) const
|
||||
{
|
||||
AZStd::string fullPath = AZStd::string(m_engineRoot) + AZStd::string(AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING) + engineRelativePath;
|
||||
engineRelativePath = fullPath;
|
||||
AZ::IO::FixedMaxPath fullPath = m_engineRoot / engineRelativePath;
|
||||
engineRelativePath = fullPath.String();
|
||||
}
|
||||
|
||||
void Application::CalculateBranchTokenForEngineRoot(AZStd::string& token) const
|
||||
{
|
||||
AzFramework::StringFunc::AssetPath::CalculateBranchToken(AZStd::string(m_engineRoot), token);
|
||||
AzFramework::StringFunc::AssetPath::CalculateBranchToken(m_engineRoot.String(), token);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -648,37 +629,21 @@ namespace AzFramework
|
||||
|
||||
void Application::SetRootPath(RootPathType type, const char* source)
|
||||
{
|
||||
size_t sourceLen = strlen(source);
|
||||
|
||||
constexpr AZStd::string_view pathSeparators{ AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR };
|
||||
// Determine if we need to append a trailing path separator
|
||||
bool appendTrailingPathSep = sourceLen > 0 && pathSeparators.find_first_of(source[sourceLen - 1]) == AZStd::string_view::npos;
|
||||
const size_t sourceLen = strlen(source);
|
||||
|
||||
// Copy the source path to the intended root path and correct the path separators as well
|
||||
switch (type)
|
||||
{
|
||||
case RootPathType::AppRoot:
|
||||
{
|
||||
AZ_Assert(sourceLen < m_appRoot.max_size(), "String overflow for App Root: %s", source);
|
||||
m_appRoot = source;
|
||||
|
||||
AZStd::replace(std::begin(m_appRoot), std::end(m_appRoot), AZ_WRONG_FILESYSTEM_SEPARATOR, AZ_CORRECT_FILESYSTEM_SEPARATOR);
|
||||
if (appendTrailingPathSep)
|
||||
{
|
||||
m_appRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
|
||||
}
|
||||
AZ_Assert(sourceLen < m_appRoot.Native().max_size(), "String overflow for App Root: %s", source);
|
||||
m_appRoot = AZ::IO::PathView(source).LexicallyNormal();
|
||||
}
|
||||
break;
|
||||
case RootPathType::EngineRoot:
|
||||
{
|
||||
AZ_Assert(sourceLen < m_engineRoot.max_size(), "String overflow for Engine Root: %s", source);
|
||||
m_engineRoot = source;
|
||||
|
||||
AZStd::replace(std::begin(m_engineRoot), std::end(m_engineRoot), AZ_WRONG_FILESYSTEM_SEPARATOR, AZ_CORRECT_FILESYSTEM_SEPARATOR);
|
||||
if (appendTrailingPathSep)
|
||||
{
|
||||
m_engineRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
|
||||
}
|
||||
AZ_Assert(sourceLen < m_engineRoot.Native().max_size(), "String overflow for Engine Root: %s", source);
|
||||
m_engineRoot = AZ::IO::PathView(source).LexicallyNormal();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace AZ::IO::Internal
|
||||
static bool IsIgnored(const char* szPath);
|
||||
|
||||
// Do not report missing LOD files if no CGF files depend on them
|
||||
// Do not report missing .cgfm files since they're not actually created and used in Lumberyard
|
||||
// Do not report missing .cgfm files since they're not actually created and used in Open 3D Engine
|
||||
// This checking prevents our missing dependency scanner from having a lot of false positives on these files
|
||||
static bool IgnoreCGFDependencies(const char* szPath);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace AZ
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
// Class to describe metadata about an AssetBundle in Lumberyard
|
||||
// Class to describe metadata about an AssetBundle in Open 3D Engine
|
||||
class AssetBundleManifest
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -597,9 +597,9 @@ namespace AZ
|
||||
{
|
||||
// here we are making sure that the buffer being passed in has enough space to include the alias in it.
|
||||
// we are trying to find the LONGEST match, meaning of the following two examples, the second should 'win'
|
||||
// File: g:/lumberyard/dev/files/morefiles/blah.xml
|
||||
// Alias1 links to 'g:/lumberyard/dev/'
|
||||
// Alias2 links to 'g:/lumberyard/dev/files/morefiles'
|
||||
// File: g:/O3DE/dev/files/morefiles/blah.xml
|
||||
// Alias1 links to 'g:/O3DE/dev/'
|
||||
// Alias2 links to 'g:/O3DE/dev/files/morefiles'
|
||||
// so returning Alias2 is preferred as it is more specific, even though alias1 includes it.
|
||||
// note that its not possible for this to be matched if the string is shorter than the length of the alias itself so we skip
|
||||
// strings that are shorter than the alias's mapped path without checking.
|
||||
|
||||
@@ -126,19 +126,22 @@ namespace AzFramework
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushData>)
|
||||
else
|
||||
{
|
||||
FlushCache(args.m_path);
|
||||
if constexpr (AZStd::is_same_v<Command, FileRequest::FlushData>)
|
||||
{
|
||||
FlushCache(args.m_path);
|
||||
}
|
||||
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushAllData>)
|
||||
{
|
||||
FlushEntireCache();
|
||||
}
|
||||
else if constexpr (AZStd::is_same_v<Command, FileRequest::ReportData>)
|
||||
{
|
||||
Report(args);
|
||||
}
|
||||
StreamStackEntry::QueueRequest(request);
|
||||
}
|
||||
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushAllData>)
|
||||
{
|
||||
FlushEntireCache();
|
||||
}
|
||||
else if constexpr (AZStd::is_same_v<Command, FileRequest::ReportData>)
|
||||
{
|
||||
Report(args);
|
||||
}
|
||||
StreamStackEntry::QueueRequest(request);
|
||||
}, request->GetCommand());
|
||||
}
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ namespace Physics
|
||||
MaterialId m_id;
|
||||
};
|
||||
|
||||
/// An asset that holds a list of materials to be edited and assigned in Lumberyard Editor
|
||||
/// An asset that holds a list of materials to be edited and assigned in Open 3D Engine Editor
|
||||
/// ======================================================================================
|
||||
///
|
||||
/// Use Asset Editor to create a MaterialLibraryAsset and add materials to it.\n
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Math/Matrix3x3.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
|
||||
#include <AzFramework/Physics/WorldBody.h>
|
||||
#include <AzFramework/Physics/ShapeConfiguration.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class ShapeConfiguration;
|
||||
class World;
|
||||
class Shape;
|
||||
|
||||
/// Default values used for initializing RigidBodySettings.
|
||||
/// These can be modified by Physics Implementation gems. // O3DE_DEPRECATED(LY-114472) - DefaultRigidBodyConfiguration values are not shared across modules.
|
||||
// Use RigidBodyConfiguration default values.
|
||||
struct DefaultRigidBodyConfiguration
|
||||
{
|
||||
static float m_mass;
|
||||
static bool m_computeInertiaTensor;
|
||||
static float m_linearDamping;
|
||||
static float m_angularDamping;
|
||||
static float m_sleepMinEnergy;
|
||||
static float m_maxAngularVelocity;
|
||||
};
|
||||
|
||||
enum class MassComputeFlags : AZ::u8
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
//! Flags indicating whether a certain mass property should be auto-computed or not.
|
||||
COMPUTE_MASS = 1,
|
||||
COMPUTE_INERTIA = 1 << 1,
|
||||
COMPUTE_COM = 1 << 2,
|
||||
|
||||
//! If set, non-simulated shapes will also be included in the mass properties calculation.
|
||||
INCLUDE_ALL_SHAPES = 1 << 3,
|
||||
|
||||
DEFAULT = COMPUTE_COM | COMPUTE_INERTIA | COMPUTE_MASS
|
||||
};
|
||||
|
||||
class RigidBodyConfiguration
|
||||
: public WorldBodyConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(RigidBodyConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(RigidBodyConfiguration, "{ACFA8900-8530-4744-AF00-AA533C868A8E}", WorldBodyConfiguration);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
enum PropertyVisibility : AZ::u16
|
||||
{
|
||||
InitialVelocities = 1 << 0, ///< Whether the initial linear and angular velocities are visible.
|
||||
InertiaProperties = 1 << 1, ///< Whether the whole category of inertia properties (mass, compute inertia,
|
||||
///< inertia tensor etc) is visible.
|
||||
Damping = 1 << 2, ///< Whether linear and angular damping are visible.
|
||||
SleepOptions = 1 << 3, ///< Whether the sleep threshold and start asleep options are visible.
|
||||
Interpolation = 1 << 4, ///< Whether the interpolation option is visible.
|
||||
Gravity = 1 << 5, ///< Whether the effected by gravity option is visible.
|
||||
Kinematic = 1 << 6, ///< Whether the option to make the body kinematic is visible.
|
||||
ContinuousCollisionDetection = 1 << 7, ///< Whether the option to enable continuous collision detection is visible.
|
||||
MaxVelocities = 1 << 8 ///< Whether upper limits on velocities are visible.
|
||||
};
|
||||
|
||||
RigidBodyConfiguration() = default;
|
||||
RigidBodyConfiguration(const RigidBodyConfiguration& settings) = default;
|
||||
|
||||
// Visibility functions.
|
||||
AZ::Crc32 GetPropertyVisibility(PropertyVisibility property) const;
|
||||
void SetPropertyVisibility(PropertyVisibility property, bool isVisible);
|
||||
|
||||
AZ::Crc32 GetInitialVelocitiesVisibility() const;
|
||||
/// Returns whether the whole category of inertia settings (mass, inertia, center of mass offset etc) is visible.
|
||||
AZ::Crc32 GetInertiaSettingsVisibility() const;
|
||||
/// Returns whether the individual inertia tensor field is visible or is hidden because the compute inertia option is selected.
|
||||
AZ::Crc32 GetInertiaVisibility() const;
|
||||
/// Returns whether the mass field is visible or is hidden because compute mass option is selected.
|
||||
AZ::Crc32 GetMassVisibility() const;
|
||||
/// Returns whether the individual centre of mass offset field is visible or is hidden because compute CoM option is selected.
|
||||
AZ::Crc32 GetCoMVisibility() const;
|
||||
AZ::Crc32 GetDampingVisibility() const;
|
||||
AZ::Crc32 GetSleepOptionsVisibility() const;
|
||||
AZ::Crc32 GetInterpolationVisibility() const;
|
||||
AZ::Crc32 GetGravityVisibility() const;
|
||||
AZ::Crc32 GetKinematicVisibility() const;
|
||||
AZ::Crc32 GetCCDVisibility() const;
|
||||
AZ::Crc32 GetMaxVelocitiesVisibility() const;
|
||||
MassComputeFlags GetMassComputeFlags() const;
|
||||
void SetMassComputeFlags(MassComputeFlags flags);
|
||||
|
||||
bool IsCCDEnabled() const;
|
||||
|
||||
// Basic initial settings.
|
||||
AZ::Vector3 m_initialLinearVelocity = AZ::Vector3::CreateZero();
|
||||
AZ::Vector3 m_initialAngularVelocity = AZ::Vector3::CreateZero();
|
||||
AZ::Vector3 m_centerOfMassOffset = AZ::Vector3::CreateZero();
|
||||
|
||||
// Simulation parameters.
|
||||
float m_mass = DefaultRigidBodyConfiguration::m_mass;
|
||||
AZ::Matrix3x3 m_inertiaTensor = AZ::Matrix3x3::CreateIdentity();
|
||||
float m_linearDamping = DefaultRigidBodyConfiguration::m_linearDamping;
|
||||
float m_angularDamping = DefaultRigidBodyConfiguration::m_angularDamping;
|
||||
float m_sleepMinEnergy = DefaultRigidBodyConfiguration::m_sleepMinEnergy;
|
||||
float m_maxAngularVelocity = DefaultRigidBodyConfiguration::m_maxAngularVelocity;
|
||||
|
||||
// Visibility settings.
|
||||
AZ::u16 m_propertyVisibilityFlags = (std::numeric_limits<AZ::u16>::max)();
|
||||
|
||||
bool m_startAsleep = false;
|
||||
bool m_interpolateMotion = false;
|
||||
bool m_gravityEnabled = true;
|
||||
bool m_simulated = true;
|
||||
bool m_kinematic = false;
|
||||
bool m_ccdEnabled = false; ///< Whether continuous collision detection is enabled.
|
||||
float m_ccdMinAdvanceCoefficient = 0.15f; ///< Coefficient affecting how granularly time is subdivided in CCD.
|
||||
bool m_ccdFrictionEnabled = false; ///< Whether friction is applied when resolving CCD collisions.
|
||||
|
||||
bool m_computeCenterOfMass = true;
|
||||
bool m_computeInertiaTensor = true;
|
||||
bool m_computeMass = true;
|
||||
|
||||
//! If set, non-simulated shapes will also be included in the mass properties calculation.
|
||||
bool m_includeAllShapesInMassCalculation = false;
|
||||
};
|
||||
|
||||
/// Dynamic rigid body.
|
||||
class RigidBody
|
||||
: public WorldBody
|
||||
{
|
||||
public:
|
||||
|
||||
AZ_CLASS_ALLOCATOR(RigidBody, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(RigidBody, "{156E459F-7BB7-4B4E-ADA0-2130D96B7E80}", WorldBody);
|
||||
|
||||
public:
|
||||
RigidBody() = default;
|
||||
explicit RigidBody(const RigidBodyConfiguration& settings);
|
||||
|
||||
|
||||
virtual void AddShape(AZStd::shared_ptr<Shape> shape) = 0;
|
||||
virtual void RemoveShape(AZStd::shared_ptr<Shape> shape) = 0;
|
||||
virtual AZ::u32 GetShapeCount() { return 0; }
|
||||
virtual AZStd::shared_ptr<Shape> GetShape(AZ::u32 /*index*/) { return nullptr; }
|
||||
|
||||
virtual AZ::Vector3 GetCenterOfMassWorld() const = 0;
|
||||
virtual AZ::Vector3 GetCenterOfMassLocal() const = 0;
|
||||
|
||||
virtual AZ::Matrix3x3 GetInverseInertiaWorld() const = 0;
|
||||
virtual AZ::Matrix3x3 GetInverseInertiaLocal() const = 0;
|
||||
|
||||
virtual float GetMass() const = 0;
|
||||
virtual float GetInverseMass() const = 0;
|
||||
virtual void SetMass(float mass) = 0;
|
||||
virtual void SetCenterOfMassOffset(const AZ::Vector3& comOffset) = 0;
|
||||
|
||||
/// Retrieves the velocity at center of mass; only linear velocity, no rotational velocity contribution.
|
||||
virtual AZ::Vector3 GetLinearVelocity() const = 0;
|
||||
virtual void SetLinearVelocity(const AZ::Vector3& velocity) = 0;
|
||||
virtual AZ::Vector3 GetAngularVelocity() const = 0;
|
||||
virtual void SetAngularVelocity(const AZ::Vector3& angularVelocity) = 0;
|
||||
virtual AZ::Vector3 GetLinearVelocityAtWorldPoint(const AZ::Vector3& worldPoint) = 0;
|
||||
virtual void ApplyLinearImpulse(const AZ::Vector3& impulse) = 0;
|
||||
virtual void ApplyLinearImpulseAtWorldPoint(const AZ::Vector3& impulse, const AZ::Vector3& worldPoint) = 0;
|
||||
virtual void ApplyAngularImpulse(const AZ::Vector3& angularImpulse) = 0;
|
||||
|
||||
virtual float GetLinearDamping() const = 0;
|
||||
virtual void SetLinearDamping(float damping) = 0;
|
||||
virtual float GetAngularDamping() const = 0;
|
||||
virtual void SetAngularDamping(float damping) = 0;
|
||||
|
||||
virtual bool IsAwake() const = 0;
|
||||
virtual void ForceAsleep() = 0;
|
||||
virtual void ForceAwake() = 0;
|
||||
virtual float GetSleepThreshold() const = 0;
|
||||
virtual void SetSleepThreshold(float threshold) = 0;
|
||||
|
||||
virtual bool IsKinematic() const = 0;
|
||||
virtual void SetKinematic(bool kinematic) = 0;
|
||||
virtual void SetKinematicTarget(const AZ::Transform& targetPosition) = 0;
|
||||
|
||||
virtual bool IsGravityEnabled() const = 0;
|
||||
virtual void SetGravityEnabled(bool enabled) = 0;
|
||||
virtual void SetSimulationEnabled(bool enabled) = 0;
|
||||
virtual void SetCCDEnabled(bool enabled) = 0;
|
||||
|
||||
//! Recalculates mass, inertia and center of mass based on the flags passed.
|
||||
//! @param flags MassComputeFlags specifying which properties should be recomputed.
|
||||
//! @param centerOfMassOffsetOverride Optional override of the center of mass. Note: This parameter will be ignored if COMPUTE_COM is passed in flags.
|
||||
//! @param inertiaTensorOverride Optional override of the inertia. Note: This parameter will be ignored if COMPUTE_INERTIA is passed in flags.
|
||||
//! @param massOverride Optional override of the mass. Note: This parameter will be ignored if COMPUTE_MASS is passed in flags.
|
||||
virtual void UpdateMassProperties(MassComputeFlags flags = MassComputeFlags::DEFAULT,
|
||||
const AZ::Vector3* centerOfMassOffsetOverride = nullptr,
|
||||
const AZ::Matrix3x3* inertiaTensorOverride = nullptr,
|
||||
const float* massOverride = nullptr) = 0;
|
||||
};
|
||||
|
||||
/// Bitwise operators for MassComputeFlags
|
||||
inline MassComputeFlags operator|(MassComputeFlags lhs, MassComputeFlags rhs)
|
||||
{
|
||||
return aznumeric_cast<MassComputeFlags>(aznumeric_cast<AZ::u8>(lhs) | aznumeric_cast<AZ::u8>(rhs));
|
||||
}
|
||||
|
||||
inline MassComputeFlags operator&(MassComputeFlags lhs, MassComputeFlags rhs)
|
||||
{
|
||||
return aznumeric_cast<MassComputeFlags>(aznumeric_cast<AZ::u8>(lhs) & aznumeric_cast<AZ::u8>(rhs));
|
||||
}
|
||||
|
||||
/// Static rigid body.
|
||||
class RigidBodyStatic
|
||||
: public WorldBody
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(RigidBodyStatic, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(RigidBodyStatic, "{13A677BB-7085-4EDB-BCC8-306548238692}", WorldBody);
|
||||
|
||||
virtual void AddShape(const AZStd::shared_ptr<Shape>& shape) = 0;
|
||||
virtual AZ::u32 GetShapeCount() { return 0; }
|
||||
virtual AZStd::shared_ptr<Shape> GetShape(AZ::u32 /*index*/) { return nullptr; }
|
||||
};
|
||||
} // namespace Physics
|
||||
+2
-2
@@ -84,7 +84,7 @@ namespace AzFramework
|
||||
{
|
||||
if (IVisibilitySystem* visibilitySystem = AZ::Interface<IVisibilitySystem>::Get())
|
||||
{
|
||||
visibilitySystem->RemoveEntry(instance_it->second.m_visibilityEntry);
|
||||
visibilitySystem->GetDefaultVisibilityScene()->RemoveEntry(instance_it->second.m_visibilityEntry);
|
||||
m_entityVisibilityBoundsUnionInstanceMapping.erase(instance_it);
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,7 @@ namespace AzFramework
|
||||
if (visibilitySystem && !worldEntityBoundsUnion.IsClose(instance.m_visibilityEntry.m_boundingVolume))
|
||||
{
|
||||
instance.m_visibilityEntry.m_boundingVolume = worldEntityBoundsUnion;
|
||||
visibilitySystem->InsertOrUpdateEntry(instance.m_visibilityEntry);
|
||||
visibilitySystem->GetDefaultVisibilityScene()->InsertOrUpdateEntry(instance.m_visibilityEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +56,10 @@ namespace AzFramework
|
||||
m_octreeDebug.Clear();
|
||||
m_visibleEntityIds.clear();
|
||||
|
||||
visSystem->Enumerate(
|
||||
visSystem->GetDefaultVisibilityScene()->Enumerate(
|
||||
viewFrustum,
|
||||
[&viewFrustum, &visibleEntityIdsOut = m_visibleEntityIds,
|
||||
&octreeDebug = m_octreeDebug](const AzFramework::IVisibilitySystem::NodeData& nodeData)
|
||||
&octreeDebug = m_octreeDebug](const AzFramework::IVisibilityScene::NodeData& nodeData)
|
||||
{
|
||||
if (ed_visibility_showDebug)
|
||||
{
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <AzCore/Math/Sphere.h>
|
||||
#include <AzCore/Math/Frustum.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
@@ -45,12 +47,15 @@ namespace AzFramework
|
||||
TypeFlags m_typeFlags = TYPE_None;
|
||||
};
|
||||
|
||||
//! @class IVisibilitySystem
|
||||
//! @brief This is an AZ::Interface<> useful for extremely fast, CPU only, proximity and visibility queries.
|
||||
class IVisibilitySystem
|
||||
//! @class IVisibilityScene
|
||||
//! @brief This is the interface for managing objects and visibility queries for a given scene.
|
||||
class IVisibilityScene
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(IVisibilitySystem, "{7C6C710F-ACDB-44CD-867D-A2C4B912ECF5}");
|
||||
AZ_RTTI(IVisibilityScene, "{822BC414-3CE3-40B4-A9A2-A42EA5B9499F}");
|
||||
|
||||
IVisibilityScene() = default;
|
||||
virtual ~IVisibilityScene() = default;
|
||||
|
||||
struct NodeData
|
||||
{
|
||||
@@ -59,8 +64,8 @@ namespace AzFramework
|
||||
};
|
||||
using EnumerateCallback = AZStd::function<void(const NodeData&)>;
|
||||
|
||||
IVisibilitySystem() = default;
|
||||
virtual ~IVisibilitySystem() = default;
|
||||
//! Get the unique scene name, used to look up the scene in the IVisibilitySystem. Duplicate names will assert on creation.
|
||||
virtual const AZ::Name& GetName() const = 0;
|
||||
|
||||
//! Insert or update an entry within the visibility system.
|
||||
//! This encompasses the following three scenarios:
|
||||
@@ -68,11 +73,11 @@ namespace AzFramework
|
||||
// 2. A previously added entry moves to a new position within its current node in the spatial hash.
|
||||
// 3. A previously added entry moves to a new node in the spatial hash.
|
||||
// (causing it to be removed from its original node and added to its new node)
|
||||
//! @param visibilityEntry data for the object being added to the visibility system
|
||||
//! @param visibilityEntry data for the object being added/updated
|
||||
virtual void InsertOrUpdateEntry(VisibilityEntry& visibilityEntry) = 0;
|
||||
|
||||
//! Removes an entry from the visibility system.
|
||||
//! @param visibilityEntry data for the object being added to the visibility system
|
||||
//! @param visibilityEntry data for the object being removed
|
||||
virtual void RemoveEntry(VisibilityEntry& visibilityEntry) = 0;
|
||||
|
||||
//! Intersects an axis aligned bounding box against the visibility system.
|
||||
@@ -99,6 +104,34 @@ namespace AzFramework
|
||||
|
||||
//! Return the number of VisibilityEntries that have been added to the system
|
||||
virtual uint32_t GetEntryCount() const = 0;
|
||||
};
|
||||
|
||||
//! @class IVisibilitySystem
|
||||
//! @brief This is an AZ::Interface<> useful for extremely fast, CPU only, proximity and visibility queries.
|
||||
class IVisibilitySystem
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(IVisibilitySystem, "{7C6C710F-ACDB-44CD-867D-A2C4B912ECF5}");
|
||||
|
||||
IVisibilitySystem() = default;
|
||||
virtual ~IVisibilitySystem() = default;
|
||||
|
||||
//! Return the default IVisibilityScene for entities.
|
||||
virtual IVisibilityScene* GetDefaultVisibilityScene() = 0;
|
||||
|
||||
//! Create a new IVisibilityScene that is uniquely identified by the scene name.
|
||||
virtual IVisibilityScene* CreateVisibilityScene(const AZ::Name& sceneName) = 0;
|
||||
|
||||
//! Destroy the visibility scene.
|
||||
//! This does not destroy the entities that are a part of the scene, only the visibility scene.
|
||||
//! This will set the visScene to nullptr
|
||||
virtual void DestroyVisibilityScene(IVisibilityScene* visScene) = 0;
|
||||
|
||||
//! Find the IVisibilityScene that is identified by sceneName.
|
||||
virtual IVisibilityScene* FindVisibilityScene(const AZ::Name& sceneName) = 0;
|
||||
|
||||
//! Logs stats about the visibility system to the console.
|
||||
virtual void DumpStats(const AZ::ConsoleCommandContainer& arguments) = 0;
|
||||
|
||||
AZ_DISABLE_COPY_MOVE(IVisibilitySystem);
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
AZ_CVAR(bool, bg_octreeUseQuadtree, false, nullptr, AZ::ConsoleFunctorFlags::ReadOnly, "If set to true, the octreeSystemComponent will degenerate to a quadtree split along the X/Y plane");
|
||||
AZ_CVAR(bool, bg_octreeUseQuadtree, false, nullptr, AZ::ConsoleFunctorFlags::ReadOnly, "If set to true, the visibility octrees will degenerate to a quadtree split along the X/Y plane");
|
||||
AZ_CVAR(float, bg_octreeMaxWorldExtents, 16384.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum supported world size by the world octreeSystemComponent");
|
||||
AZ_CVAR(uint32_t, bg_octreeNodeMaxEntries, 64, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum number of entries to allow in any node before forcing a split");
|
||||
AZ_CVAR(uint32_t, bg_octreeNodeMinEntries, 32, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum number of entries to allow in a node resulting from a merge operation");
|
||||
@@ -67,9 +67,9 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Insert(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry)
|
||||
void OctreeNode::Insert(OctreeScene& octreeScene, VisibilityEntry* entry)
|
||||
{
|
||||
AZ_Assert(entry->m_internalNode == nullptr, "Double-insertion: Insert invoked for an entry already bound to the OctreeSystemComponent");
|
||||
AZ_Assert(entry->m_internalNode == nullptr, "Double-insertion: Insert invoked for an entry already bound to the OctreeScene");
|
||||
|
||||
// If this is not a leaf node, try to insert into the child nodes
|
||||
if (m_children != nullptr)
|
||||
@@ -80,7 +80,7 @@ namespace AzFramework
|
||||
{
|
||||
if (AZ::ShapeIntersection::Contains(m_children[child].m_bounds, boundingVolume))
|
||||
{
|
||||
return m_children[child].Insert(octreeSystemComponent, entry);
|
||||
return m_children[child].Insert(octreeScene, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,8 +90,8 @@ namespace AzFramework
|
||||
if ((m_children == nullptr) && (m_entries.size() >= bg_octreeNodeMaxEntries))
|
||||
{
|
||||
// If we're not already split, and our entry list gets too large, split this node
|
||||
Split(octreeSystemComponent);
|
||||
Insert(octreeSystemComponent, entry);
|
||||
Split(octreeScene);
|
||||
Insert(octreeScene, entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -102,7 +102,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Update(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry)
|
||||
void OctreeNode::Update(OctreeScene& octreeScene, VisibilityEntry* entry)
|
||||
{
|
||||
AZ_Assert(entry->m_internalNode == this, "Update invoked for an entry bound to a different OctreeNode");
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
// Remove the entry from our current node, since it is no longer contained
|
||||
Remove(octreeSystemComponent, entry);
|
||||
Remove(octreeScene, entry);
|
||||
|
||||
// Traverse up our ancestor nodes to find the first node that fully contains the entry
|
||||
// This strategy assumes an entry will typically move a small distance relative to the total world
|
||||
@@ -125,14 +125,14 @@ namespace AzFramework
|
||||
{
|
||||
if (AZ::ShapeIntersection::Contains(insertCheck->m_bounds, boundingVolume))
|
||||
{
|
||||
return insertCheck->Insert(octreeSystemComponent, entry);
|
||||
return insertCheck->Insert(octreeScene, entry);
|
||||
}
|
||||
insertCheck = insertCheck->m_parent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Remove(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry)
|
||||
void OctreeNode::Remove(OctreeScene& octreeScene, VisibilityEntry* entry)
|
||||
{
|
||||
AZ_Assert(entry->m_internalNode == this, "Remove invoked for an entry bound to a different OctreeNode");
|
||||
AZ_Assert(m_entries[entry->m_internalNodeIndex] == entry, "Visibility entry data is corrupt");
|
||||
@@ -150,29 +150,30 @@ namespace AzFramework
|
||||
|
||||
if (m_parent != nullptr)
|
||||
{
|
||||
m_parent->TryMerge(octreeSystemComponent);
|
||||
m_parent->TryMerge(octreeScene);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Enumerate(const AZ::Aabb& aabb, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeNode::Enumerate(const AZ::Aabb& aabb, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
EnumerateHelper(aabb, callback);
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Enumerate(const AZ::Sphere& sphere, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeNode::Enumerate(const AZ::Sphere& sphere, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
EnumerateHelper(sphere, callback);
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Enumerate(const AZ::Frustum& frustum, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeNode::Enumerate(const AZ::Frustum& frustum, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
EnumerateHelper(frustum, callback);
|
||||
}
|
||||
|
||||
void OctreeNode::EnumerateNoCull(const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
|
||||
void OctreeNode::EnumerateNoCull(const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
// Invoke the callback for the current node
|
||||
if (!m_entries.empty())
|
||||
@@ -191,6 +192,7 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const AZStd::vector<VisibilityEntry*>& OctreeNode::GetEntries() const
|
||||
{
|
||||
return m_entries;
|
||||
@@ -209,7 +211,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::TryMerge(OctreeSystemComponent& octreeSystemComponent)
|
||||
void OctreeNode::TryMerge(OctreeScene& octreeScene)
|
||||
{
|
||||
if (IsLeaf())
|
||||
{
|
||||
@@ -222,7 +224,7 @@ namespace AzFramework
|
||||
const uint32_t childCount = GetChildNodeCount();
|
||||
for (uint32_t child = 0; child < childCount; ++child)
|
||||
{
|
||||
m_children[child].TryMerge(octreeSystemComponent);
|
||||
m_children[child].TryMerge(octreeScene);
|
||||
if (!m_children[child].IsLeaf())
|
||||
{
|
||||
return;
|
||||
@@ -232,13 +234,13 @@ namespace AzFramework
|
||||
|
||||
if (potentialNodeCount <= bg_octreeNodeMinEntries)
|
||||
{
|
||||
Merge(octreeSystemComponent);
|
||||
Merge(octreeScene);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void OctreeNode::EnumerateHelper(const T& boundingVolume, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeNode::EnumerateHelper(const T& boundingVolume, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
AZ_Assert(AZ::ShapeIntersection::Overlaps(boundingVolume, m_bounds), "EnumerateHelper invoked on an octreeSystemComponent node that is not within the bounding volume");
|
||||
|
||||
@@ -263,11 +265,11 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Split(OctreeSystemComponent& octreeSystemComponent)
|
||||
void OctreeNode::Split(OctreeScene& octreeScene)
|
||||
{
|
||||
AZ_Assert(m_children == nullptr, "Split invoked on an octreeSystemComponent node that has already been split");
|
||||
m_childNodeIndex = octreeSystemComponent.AllocateChildNodes();
|
||||
m_children = octreeSystemComponent.GetChildNodesAtIndex(m_childNodeIndex);
|
||||
AZ_Assert(m_children == nullptr, "Split invoked on an octreeScene node that has already been split");
|
||||
m_childNodeIndex = octreeScene.AllocateChildNodes();
|
||||
m_children = octreeScene.GetChildNodesAtIndex(m_childNodeIndex);
|
||||
|
||||
// Set child split planes and bounding volumes
|
||||
{
|
||||
@@ -308,14 +310,14 @@ namespace AzFramework
|
||||
{
|
||||
entry->m_internalNode = nullptr;
|
||||
entry->m_internalNodeIndex = 0;
|
||||
Insert(octreeSystemComponent, entry);
|
||||
Insert(octreeScene, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OctreeNode::Merge(OctreeSystemComponent& octreeSystemComponent)
|
||||
void OctreeNode::Merge(OctreeScene& octreeScene)
|
||||
{
|
||||
AZ_Assert(m_children != nullptr, "Merge invoked on an octreeSystemComponent node that does not have children");
|
||||
AZ_Assert(m_children != nullptr, "Merge invoked on an octreeScene node that does not have children");
|
||||
|
||||
// Move all child entries to our own entry set
|
||||
const uint32_t childCount = GetChildNodeCount();
|
||||
@@ -330,46 +332,20 @@ namespace AzFramework
|
||||
m_children[child].m_entries.clear();
|
||||
}
|
||||
|
||||
octreeSystemComponent.ReleaseChildNodes(m_childNodeIndex);
|
||||
octreeScene.ReleaseChildNodes(m_childNodeIndex);
|
||||
m_childNodeIndex = InvalidChildNodeIndex;
|
||||
m_children = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
OctreeScene::OctreeScene(const AZ::Name& sceneName)
|
||||
: m_sceneName(sceneName)
|
||||
, m_root(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-bg_octreeMaxWorldExtents), AZ::Vector3(bg_octreeMaxWorldExtents)))
|
||||
{
|
||||
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<OctreeSystemComponent, AZ::Component>()
|
||||
->Version(1);
|
||||
}
|
||||
AZ_Assert(!sceneName.IsEmpty(), "sceneName must be a valid string");
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
OctreeScene::~OctreeScene()
|
||||
{
|
||||
provided.push_back(AZ_CRC_CE("VisibilityService"));
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC_CE("VisibilityService"));
|
||||
}
|
||||
|
||||
|
||||
OctreeSystemComponent::OctreeSystemComponent()
|
||||
: m_root(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-bg_octreeMaxWorldExtents), AZ::Vector3(bg_octreeMaxWorldExtents)))
|
||||
{
|
||||
AZ::Interface<IVisibilitySystem>::Register(this);
|
||||
IVisibilitySystemRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
|
||||
OctreeSystemComponent::~OctreeSystemComponent()
|
||||
{
|
||||
IVisibilitySystemRequestBus::Handler::BusDisconnect();
|
||||
AZ::Interface<IVisibilitySystem>::Unregister(this);
|
||||
for (auto page : m_nodeCache)
|
||||
{
|
||||
delete page;
|
||||
@@ -378,21 +354,14 @@ namespace AzFramework
|
||||
m_nodeCache.shrink_to_fit();
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Activate()
|
||||
const AZ::Name& OctreeScene::GetName() const
|
||||
{
|
||||
;
|
||||
return m_sceneName;
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Deactivate()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::InsertOrUpdateEntry(VisibilityEntry& entry)
|
||||
void OctreeScene::InsertOrUpdateEntry(VisibilityEntry& entry)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::shared_mutex> lock(m_sharedMutex);
|
||||
if (entry.m_internalNode != nullptr)
|
||||
{
|
||||
static_cast<OctreeNode*>(entry.m_internalNode)->Update(*this, &entry);
|
||||
@@ -405,8 +374,9 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::RemoveEntry(VisibilityEntry& entry)
|
||||
void OctreeScene::RemoveEntry(VisibilityEntry& entry)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::shared_mutex> lock(m_sharedMutex);
|
||||
if (entry.m_internalNode)
|
||||
{
|
||||
static_cast<OctreeNode*>(entry.m_internalNode)->Remove(*this, &entry);
|
||||
@@ -415,70 +385,71 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Enumerate(const AZ::Aabb& aabb, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeScene::Enumerate(const AZ::Aabb& aabb, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(m_sharedMutex);
|
||||
m_root.Enumerate(aabb, callback);
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Enumerate(const AZ::Sphere& sphere, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeScene::Enumerate(const AZ::Sphere& sphere, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(m_sharedMutex);
|
||||
m_root.Enumerate(sphere, callback);
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Enumerate(const AZ::Frustum& frustum, const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
void OctreeScene::Enumerate(const AZ::Frustum& frustum, const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(m_sharedMutex);
|
||||
m_root.Enumerate(frustum, callback);
|
||||
}
|
||||
|
||||
void OctreeSystemComponent::EnumerateNoCull(const IVisibilitySystem::EnumerateCallback& callback) const
|
||||
|
||||
void OctreeScene::EnumerateNoCull(const IVisibilityScene::EnumerateCallback& callback) const
|
||||
{
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(m_sharedMutex);
|
||||
m_root.EnumerateNoCull(callback);
|
||||
}
|
||||
|
||||
uint32_t OctreeSystemComponent::GetEntryCount() const
|
||||
|
||||
uint32_t OctreeScene::GetEntryCount() const
|
||||
{
|
||||
return m_entryCount;
|
||||
}
|
||||
|
||||
OctreeNode& OctreeSystemComponent::GetRoot()
|
||||
{
|
||||
return m_root;
|
||||
}
|
||||
|
||||
uint32_t OctreeSystemComponent::GetNodeCount() const
|
||||
uint32_t OctreeScene::GetNodeCount() const
|
||||
{
|
||||
return m_nodeCount;
|
||||
}
|
||||
|
||||
|
||||
uint32_t OctreeSystemComponent::GetFreeNodeCount() const
|
||||
uint32_t OctreeScene::GetFreeNodeCount() const
|
||||
{
|
||||
// Each entry represents GetChildNodeCount() nodes
|
||||
return aznumeric_cast<uint32_t>(m_freeOctreeNodes.size() * GetChildNodeCount());
|
||||
}
|
||||
|
||||
|
||||
uint32_t OctreeSystemComponent::GetPageCount() const
|
||||
uint32_t OctreeScene::GetPageCount() const
|
||||
{
|
||||
return aznumeric_cast<uint32_t>(m_nodeCache.size());
|
||||
}
|
||||
|
||||
|
||||
uint32_t OctreeSystemComponent::GetChildNodeCount() const
|
||||
uint32_t OctreeScene::GetChildNodeCount() const
|
||||
{
|
||||
return AzFramework::GetChildNodeCount();
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::DumpStats([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
|
||||
void OctreeScene::DumpStats()
|
||||
{
|
||||
AZ_TracePrintf("Console", "OctreeNode::EntryCount = %u", GetEntryCount());
|
||||
AZ_TracePrintf("Console", "OctreeNode::NodeCount = %u", GetNodeCount());
|
||||
AZ_TracePrintf("Console", "OctreeNode::FreeNodeCount = %u", GetFreeNodeCount());
|
||||
AZ_TracePrintf("Console", "OctreeNode::PageCount = %u", GetPageCount());
|
||||
AZ_TracePrintf("Console", "OctreeNode::ChildNodeCount = %u", GetChildNodeCount());
|
||||
AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::EntryCount = %u", GetName().GetCStr(), GetEntryCount());
|
||||
AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::NodeCount = %u", GetName().GetCStr(), GetNodeCount());
|
||||
AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::FreeNodeCount = %u", GetName().GetCStr(), GetFreeNodeCount());
|
||||
AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::PageCount = %u", GetName().GetCStr(), GetPageCount());
|
||||
AZ_TracePrintf("Console", "OctreeScene[\"%s\"]::ChildNodeCount = %u", GetName().GetCStr(), GetChildNodeCount());
|
||||
}
|
||||
|
||||
|
||||
@@ -496,7 +467,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
uint32_t OctreeSystemComponent::AllocateChildNodes()
|
||||
uint32_t OctreeScene::AllocateChildNodes()
|
||||
{
|
||||
const uint32_t childCount = GetChildNodeCount();
|
||||
m_nodeCount += childCount;
|
||||
@@ -540,18 +511,124 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::ReleaseChildNodes(uint32_t nodeIndex)
|
||||
void OctreeScene::ReleaseChildNodes(uint32_t nodeIndex)
|
||||
{
|
||||
m_nodeCount -= GetChildNodeCount();
|
||||
m_freeOctreeNodes.push(nodeIndex);
|
||||
}
|
||||
|
||||
|
||||
OctreeNode* OctreeSystemComponent::GetChildNodesAtIndex(uint32_t nodeIndex) const
|
||||
OctreeNode* OctreeScene::GetChildNodesAtIndex(uint32_t nodeIndex) const
|
||||
{
|
||||
uint32_t childPage;
|
||||
uint32_t childOffset;
|
||||
ExtractPageAndOffsetFromIndex(nodeIndex, childPage, childOffset);
|
||||
return &(*m_nodeCache[childPage])[childOffset];
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<OctreeSystemComponent, AZ::Component>()
|
||||
->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
{
|
||||
provided.push_back(AZ_CRC("OctreeService"));
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC("OctreeService"));
|
||||
}
|
||||
|
||||
|
||||
OctreeSystemComponent::OctreeSystemComponent()
|
||||
{
|
||||
AZ::Interface<IVisibilitySystem>::Register(this);
|
||||
IVisibilitySystemRequestBus::Handler::BusConnect();
|
||||
|
||||
m_defaultScene = aznew OctreeScene(AZ::Name("DefaultVisibilityScene"));
|
||||
}
|
||||
|
||||
|
||||
OctreeSystemComponent::~OctreeSystemComponent()
|
||||
{
|
||||
AZ_Assert(m_scenes.empty(), "All IVisibilityScenes must be destroyed before shutdown");
|
||||
|
||||
delete m_defaultScene;
|
||||
|
||||
IVisibilitySystemRequestBus::Handler::BusDisconnect();
|
||||
AZ::Interface<IVisibilitySystem>::Unregister(this);
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Activate()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::Deactivate()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
IVisibilityScene* OctreeSystemComponent::GetDefaultVisibilityScene()
|
||||
{
|
||||
return m_defaultScene;
|
||||
}
|
||||
|
||||
IVisibilityScene* OctreeSystemComponent::CreateVisibilityScene(const AZ::Name& sceneName)
|
||||
{
|
||||
AZ_Assert(FindVisibilityScene(sceneName) == nullptr, "Scene with same name already created!");
|
||||
OctreeScene* newScene = aznew OctreeScene(sceneName);
|
||||
m_scenes.push_back(newScene);
|
||||
return newScene;
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::DestroyVisibilityScene(IVisibilityScene* visScene)
|
||||
{
|
||||
for (auto iter = m_scenes.begin(); iter != m_scenes.end(); ++iter)
|
||||
{
|
||||
if (*iter == visScene)
|
||||
{
|
||||
delete visScene;
|
||||
m_scenes.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
AZ_Assert(false, "visScene[\"%s\"] not found in the OctreeSystemComponent", visScene->GetName().GetCStr());
|
||||
}
|
||||
|
||||
|
||||
IVisibilityScene* OctreeSystemComponent::FindVisibilityScene(const AZ::Name& sceneName)
|
||||
{
|
||||
for (OctreeScene* scene : m_scenes)
|
||||
{
|
||||
if(scene->GetName() == sceneName)
|
||||
{
|
||||
return scene;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void OctreeSystemComponent::DumpStats([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
|
||||
{
|
||||
for (OctreeScene* scene : m_scenes)
|
||||
{
|
||||
AZ_TracePrintf("Console", "============================================");
|
||||
scene->DumpStats();
|
||||
}
|
||||
AZ_TracePrintf("Console", "============================================");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,14 +15,15 @@
|
||||
#include <AzFramework/Visibility/IVisibilitySystem.h>
|
||||
#include <AzCore/Math/Plane.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/std/containers/stack.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/containers/fixed_vector.h>
|
||||
#include <AzCore/std/parallel/shared_mutex.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class OctreeSystemComponent;
|
||||
class OctreeScene;
|
||||
|
||||
//! An internal node within the tree.
|
||||
//! It contains all objects that are *fully contained* by the node, if an object spans multiple child nodes that object will be stored in the parent.
|
||||
@@ -40,25 +41,25 @@ namespace AzFramework
|
||||
OctreeNode& operator=(OctreeNode&& rhs);
|
||||
|
||||
//! Inserts a VisibilityEntry into this OctreeNode, potentially triggering a split.
|
||||
void Insert(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry);
|
||||
void Insert(OctreeScene& octreeScene, VisibilityEntry* entry);
|
||||
|
||||
//! Updates a VisibilityEntry that is currently bound to this OctreeNode.
|
||||
//! The provided entry must be bound to this node, but may no longer be bound to this node upon function exit.
|
||||
void Update(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry);
|
||||
void Update(OctreeScene& octreeScene, VisibilityEntry* entry);
|
||||
|
||||
//! Removes a VisibilityEntry from this OctreeNode.
|
||||
//! The provided entry must be bound to this node.
|
||||
void Remove(OctreeSystemComponent& octreeSystemComponent, VisibilityEntry* entry);
|
||||
void Remove(OctreeScene& octreeScene, VisibilityEntry* entry);
|
||||
|
||||
//! Recursively enumerates any OctreeNodes and their children that intersect the provided bounding volume.
|
||||
//! @{
|
||||
void Enumerate(const AZ::Aabb& aabb, const IVisibilitySystem::EnumerateCallback& callback) const;
|
||||
void Enumerate(const AZ::Sphere& sphere, const IVisibilitySystem::EnumerateCallback& callback) const;
|
||||
void Enumerate(const AZ::Frustum& frustum, const IVisibilitySystem::EnumerateCallback& callback) const;
|
||||
void Enumerate(const AZ::Aabb& aabb, const IVisibilityScene::EnumerateCallback& callback) const;
|
||||
void Enumerate(const AZ::Sphere& sphere, const IVisibilityScene::EnumerateCallback& callback) const;
|
||||
void Enumerate(const AZ::Frustum& frustum, const IVisibilityScene::EnumerateCallback& callback) const;
|
||||
//! @}
|
||||
|
||||
//! Recursively enumerate *all* OctreeNodes that have any entries in them (without any culling).
|
||||
void EnumerateNoCull(const IVisibilitySystem::EnumerateCallback& callback) const;
|
||||
void EnumerateNoCull(const IVisibilityScene::EnumerateCallback& callback) const;
|
||||
|
||||
//! Returns the set of entries bound to this node.
|
||||
const AZStd::vector<VisibilityEntry*>& GetEntries() const;
|
||||
@@ -71,13 +72,13 @@ namespace AzFramework
|
||||
|
||||
private:
|
||||
|
||||
void TryMerge(OctreeSystemComponent& octreeSystemComponent);
|
||||
void TryMerge(OctreeScene& octreeScene);
|
||||
|
||||
template <typename T>
|
||||
void EnumerateHelper(const T& boundingVolume, const IVisibilitySystem::EnumerateCallback& callback) const;
|
||||
void EnumerateHelper(const T& boundingVolume, const IVisibilityScene::EnumerateCallback& callback) const;
|
||||
|
||||
void Split(OctreeSystemComponent& octreeSystemComponent);
|
||||
void Merge(OctreeSystemComponent& octreeSystemComponent);
|
||||
void Split(OctreeScene& octreeScene);
|
||||
void Merge(OctreeScene& octreeScene);
|
||||
|
||||
// The page is stored in the upper 16-bits of the child node index, the offset into the page is the lower 16-bits
|
||||
// This gives us a maximum of 65,536 pages and 65,536 nodes per page, for a total of 2^32 - 1 total pages (-1 reserved for the invalid index)
|
||||
@@ -90,60 +91,47 @@ namespace AzFramework
|
||||
};
|
||||
|
||||
//! Implementation of the visibility system interface.
|
||||
//! This uses a simple adaptive octreeSystemComponent to support partitioning an object set and efficiently running gathers and visibility queries.
|
||||
class OctreeSystemComponent
|
||||
: public AZ::Component
|
||||
, public IVisibilitySystemRequestBus::Handler
|
||||
//! This uses a simple adaptive octree to support partitioning an object set for a specific scene and efficiently running gathers and visibility queries.
|
||||
class OctreeScene
|
||||
: public IVisibilityScene
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(OctreeScene, "{A88E4D86-11F1-4E3F-A91A-66DE99502B93}");
|
||||
AZ_CLASS_ALLOCATOR(OctreeScene, AZ::SystemAllocator, 0);
|
||||
AZ_DISABLE_COPY_MOVE(OctreeScene);
|
||||
|
||||
AZ_COMPONENT(OctreeSystemComponent, "{CD4FF1C5-BAF4-421D-951B-1E05DAEEF67B}");
|
||||
explicit OctreeScene(const AZ::Name& sceneName);
|
||||
virtual ~OctreeScene();
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
|
||||
|
||||
OctreeSystemComponent();
|
||||
virtual ~OctreeSystemComponent();
|
||||
|
||||
//! AZ::Component overrides.
|
||||
//! @{
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
//! @}
|
||||
|
||||
//! IVisibilitySystem overrides.
|
||||
//! IVisibilityScene overrides.
|
||||
//! @{
|
||||
const AZ::Name& GetName() const override;
|
||||
void InsertOrUpdateEntry(VisibilityEntry& entry) override;
|
||||
void RemoveEntry(VisibilityEntry& entry) override;
|
||||
void Enumerate(const AZ::Aabb& aabb, const IVisibilitySystem::EnumerateCallback& callback) const override;
|
||||
void Enumerate(const AZ::Sphere& sphere, const IVisibilitySystem::EnumerateCallback& callback) const override;
|
||||
void Enumerate(const AZ::Frustum& frustum, const IVisibilitySystem::EnumerateCallback& callback) const override;
|
||||
void EnumerateNoCull(const IVisibilitySystem::EnumerateCallback& callback) const override;
|
||||
void Enumerate(const AZ::Aabb& aabb, const IVisibilityScene::EnumerateCallback& callback) const override;
|
||||
void Enumerate(const AZ::Sphere& sphere, const IVisibilityScene::EnumerateCallback& callback) const override;
|
||||
void Enumerate(const AZ::Frustum& frustum, const IVisibilityScene::EnumerateCallback& callback) const override;
|
||||
void EnumerateNoCull(const IVisibilityScene::EnumerateCallback& callback) const override;
|
||||
uint32_t GetEntryCount() const override;
|
||||
//! @}
|
||||
|
||||
//! Returns the OctreeSystemComponent's root node.
|
||||
OctreeNode& GetRoot();
|
||||
|
||||
//! OctreeSystemComponent stats
|
||||
//! Stats
|
||||
//! @{
|
||||
uint32_t GetNodeCount() const;
|
||||
uint32_t GetFreeNodeCount() const;
|
||||
uint32_t GetPageCount() const;
|
||||
uint32_t GetChildNodeCount() const;
|
||||
void DumpStats(const AZ::ConsoleCommandContainer& arguments);
|
||||
void DumpStats();
|
||||
//! @}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t AllocateChildNodes();
|
||||
void ReleaseChildNodes(uint32_t nodeIndex);
|
||||
OctreeNode* GetChildNodesAtIndex(uint32_t nodeIndex) const;
|
||||
|
||||
// Bind the DumpStats member function to the console as 'OctreeSystemComponent.DumpStats'
|
||||
AZ_CONSOLEFUNC(OctreeSystemComponent, DumpStats, AZ::ConsoleFunctorFlags::Null, "Dump octreeSystemComponent stats to the console window");
|
||||
mutable AZStd::shared_mutex m_sharedMutex;
|
||||
|
||||
AZ::Name m_sceneName; //< The uniquely identifying name for the visibility scene.
|
||||
OctreeNode m_root; //< The root node for the octreeSystemComponent.
|
||||
|
||||
uint32_t m_entryCount = 0; //< Metric tracking the number of entries inserted into the octreeSystemComponent.
|
||||
@@ -158,4 +146,47 @@ namespace AzFramework
|
||||
|
||||
friend class OctreeNode; // For access to the node allocator methods
|
||||
};
|
||||
|
||||
//! Implementation of the visibility system interface.
|
||||
//! This manages creating, destroying, and finding the underlying octrees that are associated with specific scenes
|
||||
class OctreeSystemComponent
|
||||
: public AZ::Component
|
||||
, public IVisibilitySystemRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(OctreeSystemComponent, "{CD4FF1C5-BAF4-421D-951B-1E05DAEEF67B}");
|
||||
|
||||
// Bind the DumpStats member function to the console as 'OctreeSystemComponent.DumpStats'
|
||||
AZ_CONSOLEFUNC(OctreeSystemComponent, DumpStats, AZ::ConsoleFunctorFlags::Null, "Dump octreeSystemComponent stats to the console window");
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
|
||||
|
||||
OctreeSystemComponent();
|
||||
virtual ~OctreeSystemComponent();
|
||||
|
||||
//! AZ::Component overrides.
|
||||
//! @{
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
//! @}
|
||||
|
||||
//! IVisibilitySystem overrides
|
||||
//! @{
|
||||
IVisibilityScene* GetDefaultVisibilityScene() override;
|
||||
IVisibilityScene* CreateVisibilityScene(const AZ::Name& sceneName) override;
|
||||
void DestroyVisibilityScene(IVisibilityScene* visScene) override;
|
||||
IVisibilityScene* FindVisibilityScene(const AZ::Name& sceneName) override;
|
||||
void DumpStats(const AZ::ConsoleCommandContainer& arguments) override;
|
||||
//! @}
|
||||
|
||||
private:
|
||||
//! The default scene used for most entities (e.g. gameplay, networking)
|
||||
OctreeScene* m_defaultScene = nullptr;
|
||||
|
||||
//! Other scenes (e.g. each rendering scene) are stored here and looked up by name.
|
||||
AZStd::vector<OctreeScene*> m_scenes; //using a vector<> here because we'll generally have a small number of scenes
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
#include <AzCore/Android/APKFileHandler.h>
|
||||
#include <AzCore/Android/Utils.h>
|
||||
#include <AzCore/IO/IOUtils.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
#include <android/api-level.h>
|
||||
|
||||
#if __ANDROID_API__ == 19
|
||||
// The following were apparently introduced in API 21, however in earlier versions of the
|
||||
// The following were apparently introduced in API 21, however in earlier versions of the
|
||||
// platform specific headers they were defines. In the move to unified headers, the following
|
||||
// defines were removed from stat.h
|
||||
#ifndef stat64
|
||||
@@ -52,7 +53,7 @@ namespace AZ
|
||||
|
||||
if (AZ::Android::Utils::IsApkPath(resolvedPath))
|
||||
{
|
||||
return AZ::Android::APKFileHandler::IsDirectory(AZ::Android::Utils::StripApkPrefix(resolvedPath));
|
||||
return AZ::Android::APKFileHandler::IsDirectory(AZ::Android::Utils::StripApkPrefix(resolvedPath).c_str());
|
||||
}
|
||||
|
||||
struct stat result;
|
||||
@@ -108,7 +109,7 @@ namespace AZ
|
||||
|
||||
if (isInAPK)
|
||||
{
|
||||
AZ::OSString strippedPath = AZ::Android::Utils::StripApkPrefix(pathWithoutSlash.c_str());
|
||||
AZ::IO::FixedMaxPath strippedPath = AZ::Android::Utils::StripApkPrefix(pathWithoutSlash.c_str());
|
||||
|
||||
char tempBuffer[AZ_MAX_PATH_LEN] = {0};
|
||||
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ namespace AzFramework
|
||||
{
|
||||
AZStd::string GetPersistentName()
|
||||
{
|
||||
AZStd::string persistentName = "Lumberyard";
|
||||
AZStd::string persistentName = "Open 3D Engine";
|
||||
|
||||
char procPath[AZ_MAX_PATH_LEN];
|
||||
AZ::Utils::GetExecutablePathReturnType ret = AZ::Utils::GetExecutablePath(procPath, AZ_MAX_PATH_LEN);
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ namespace AzFramework
|
||||
bool m_isInBorderlessWindowFullScreenState = false; //!< Was a borderless window used to enter full screen state?
|
||||
};
|
||||
|
||||
const char* NativeWindowImpl_Win32::s_defaultClassName = "LumberyardWin32Class";
|
||||
const char* NativeWindowImpl_Win32::s_defaultClassName = "O3DEWin32Class";
|
||||
|
||||
NativeWindow::Implementation* NativeWindow::Implementation::Create()
|
||||
{
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ namespace AzFramework
|
||||
//!
|
||||
//! return another vector relative to the specified display orientation, and such that the
|
||||
//! +y axis points out the back of the screen and z+ axis points out the top of the device.
|
||||
//! This flipping of axes is to match Lumberyard's z-up and left-handed coordinate system.
|
||||
//! This flipping of axes is to match Open 3D Engine's z-up and left-handed coordinate system.
|
||||
//!
|
||||
//! \param[in] x The x component of the vector to be aligned
|
||||
//! \param[in] y The y component of the vector to be aligned
|
||||
|
||||
Reference in New Issue
Block a user