Merge remote-tracking branch 'origin/master'

This commit is contained in:
Wojciech Figat
2022-07-05 09:01:22 +02:00
25 changed files with 250 additions and 154 deletions

View File

@@ -196,7 +196,7 @@ void Model::Draw(const RenderContext& renderContext, MaterialBase* material, con
const BoundingBox box = GetBox(world);
BoundingSphere sphere;
BoundingSphere::FromBox(box, sphere);
int32 lodIndex = RenderTools::ComputeModelLOD(this, sphere.Center, (float)sphere.Radius, renderContext); // TODO: large-worlds
int32 lodIndex = RenderTools::ComputeModelLOD(this, sphere.Center - renderContext.View.Origin, (float)sphere.Radius, renderContext);
if (lodIndex == -1)
return;
lodIndex += renderContext.View.ModelLODBias;

View File

@@ -129,30 +129,28 @@ void BoundingBox::Transform(const BoundingBox& box, const Matrix& matrix, Boundi
const auto zb = backward * box.Maximum.Z;
const auto translation = matrix.GetTranslation();
result = BoundingBox(
Vector3::Min(xa, xb) + Vector3::Min(ya, yb) + Vector3::Min(za, zb) + translation,
Vector3::Max(xa, xb) + Vector3::Max(ya, yb) + Vector3::Max(za, zb) + translation);
/*
// Get box corners
Vector3 corners[8];
box.GetCorners(corners);
// Transform them
for (int32 i = 0; i < 8; i++)
{
corners[i] = Vector3::Transform(corners[i], matrix);
}
// Construct box from the points
result = FromPoints(corners, 8);
*/
const auto min = Vector3::Min(xa, xb) + Vector3::Min(ya, yb) + Vector3::Min(za, zb) + translation;
const auto max = Vector3::Max(xa, xb) + Vector3::Max(ya, yb) + Vector3::Max(za, zb) + translation;
result = BoundingBox(min, max);
}
void BoundingBox::Transform(const BoundingBox& box, const ::Transform& transform, BoundingBox& result)
{
// TODO: optimize it and support large worlds without using Matrix
Matrix matrix;
transform.GetWorld(matrix);
Transform(box, matrix, result);
// Reference: http://dev.theomader.com/transform-bounding-boxes/
const auto right = transform.GetRight();
const auto xa = right * box.Minimum.X;
const auto xb = right * box.Maximum.X;
const auto up = transform.GetUp();
const auto ya = up * box.Minimum.Y;
const auto yb = up * box.Maximum.Y;
const auto backward = transform.GetBackward();
const auto za = backward * box.Minimum.Z;
const auto zb = backward * box.Maximum.Z;
const auto min = Vector3::Min(xa, xb) + Vector3::Min(ya, yb) + Vector3::Min(za, zb) + transform.Translation;
const auto max = Vector3::Max(xa, xb) + Vector3::Max(ya, yb) + Vector3::Max(za, zb) + transform.Translation;
result = BoundingBox(min, max);
}

View File

@@ -454,24 +454,48 @@ namespace FlaxEngine
var zb = backward * box.Maximum.Z;
var translation = transform.TranslationVector;
result = new BoundingBox(
Vector3.Min(xa, xb) + Vector3.Min(ya, yb) + Vector3.Min(za, zb) + translation,
Vector3.Max(xa, xb) + Vector3.Max(ya, yb) + Vector3.Max(za, zb) + translation);
var min = Vector3.Min(xa, xb) + Vector3.Min(ya, yb) + Vector3.Min(za, zb) + translation;
var max = Vector3.Max(xa, xb) + Vector3.Max(ya, yb) + Vector3.Max(za, zb) + translation;
result = new BoundingBox(min, max);
}
/*
// Get box corners
var corners = new Vector3[8];
box.GetCorners(corners);
/// <summary>
/// Transforms bounding box using the given transformation matrix.
/// </summary>
/// <param name="box">The bounding box to transform.</param>
/// <param name="transform">The transformation matrix.</param>
/// <returns>The result of the transformation.</returns>
public static BoundingBox Transform(BoundingBox box, Transform transform)
{
Transform(ref box, ref transform, out BoundingBox result);
return result;
}
// Transform them
for (int i = 0; i < 8; i++)
{
Vector3.Transform(ref corners[i], ref transform, out corners[i]);
}
/// <summary>
/// Transforms bounding box using the given transformation.
/// </summary>
/// <param name="box">The bounding box to transform.</param>
/// <param name="transform">The transformation.</param>
/// <param name="result">The result of the transformation.</param>
public static void Transform(ref BoundingBox box, ref Transform transform, out BoundingBox result)
{
// Reference: http://dev.theomader.com/transform-bounding-boxes/
// Construct box from the points
FromPoints(corners, out result);
*/
Double3 right = transform.Right;
var xa = right * box.Minimum.X;
var xb = right * box.Maximum.X;
Double3 up = transform.Up;
var ya = up * box.Minimum.Y;
var yb = up * box.Maximum.Y;
Double3 backward = transform.Backward;
var za = backward * box.Minimum.Z;
var zb = backward * box.Maximum.Z;
var min = Vector3.Min(xa, xb) + Vector3.Min(ya, yb) + Vector3.Min(za, zb) + transform.Translation;
var max = Vector3.Max(xa, xb) + Vector3.Max(ya, yb) + Vector3.Max(za, zb) + transform.Translation;
result = new BoundingBox(min, max);
}
/// <summary>

View File

@@ -76,10 +76,11 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
// Set reflection probe data
EnvironmentProbe* probe = nullptr;
// TODO: optimize env probe searching for a transparent material - use spatial cache for renderer to find it
const Vector3 drawCallOrigin = drawCall.World.GetTranslation() + view.Origin;
for (int32 i = 0; i < cache->EnvironmentProbes.Count(); i++)
{
const auto p = cache->EnvironmentProbes[i];
if (p->GetSphere().Contains(drawCall.World.GetTranslation()) != ContainmentType::Disjoint)
if (p->GetSphere().Contains(drawCallOrigin) != ContainmentType::Disjoint)
{
probe = p;
break;
@@ -87,7 +88,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
}
if (probe && probe->GetProbe())
{
probe->SetupProbeData(&data.EnvironmentProbe);
probe->SetupProbeData(params.RenderContext, &data.EnvironmentProbe);
const auto texture = probe->GetProbe()->GetTexture();
context->BindSR(envProbeShaderRegisterIndex, GET_TEXTURE_VIEW_SAFE(texture));
}

View File

@@ -44,10 +44,10 @@ float EnvironmentProbe::GetScaledRadius() const
return _radius * _transform.Scale.MaxValue();
}
void EnvironmentProbe::SetupProbeData(ProbeData* data) const
void EnvironmentProbe::SetupProbeData(const RenderContext& renderContext, ProbeData* data) const
{
const float radius = GetScaledRadius();
data->Data0 = Float4(GetPosition(), 0); // TODO: large-worlds
data->Data0 = Float4(GetPosition() - renderContext.View.Origin, 0);
data->Data1 = Float4(radius, 1.0f / radius, Brightness, 0);
}

View File

@@ -89,8 +89,9 @@ public:
/// <summary>
/// Setup probe data structure
/// </summary>
/// <param name="data">Rendering context</param>
/// <param name="data">Packed probe data to set</param>
void SetupProbeData(struct ProbeData* data) const;
void SetupProbeData(const RenderContext& renderContext, struct ProbeData* data) const;
/// <summary>
/// Gets the custom probe (null if using baked one or none).

View File

@@ -409,13 +409,11 @@ void ParticleEmitterGraphCPUExecutor::Draw(ParticleEmitter* emitter, ParticleEff
const float radius = (float)GetValue(module->GetBox(1), 3);
const float fallOffExponent = (float)GetValue(module->GetBox(2), 4);
lightData.Position = *(Float3*)positionPtr;
lightData.Color = Float3(color) * color.W;
lightData.Radius = radius;
lightData.FallOffExponent = fallOffExponent;
if (emitter->SimulationSpace == ParticlesSimulationSpace::Local)
Float3::Transform(lightData.Position, transform, lightData.Position);
Float3::Transform(*(Float3*)positionPtr, transform, lightData.Position);
renderContext.List->PointLights.Add(lightData);

View File

@@ -231,7 +231,11 @@ void GPUParticles::Execute(GPUContext* context, ParticleEmitter* emitter, Partic
else
{
Matrix worldMatrix;
effect->GetWorld(&worldMatrix);
const Transform transform = effect->GetTransform();
if (viewTask)
viewTask->View.GetWorldMatrix(transform, worldMatrix);
else
transform.GetWorld(worldMatrix);
Matrix::Transpose(worldMatrix, cbData->WorldMatrix);
worldMatrix.Invert();
Matrix::Transpose(worldMatrix, cbData->InvWorldMatrix);

View File

@@ -14,8 +14,8 @@ ParticleEffect::ParticleEffect(const SpawnParams& params)
, _lastUpdateFrame(0)
, _lastMinDstSqr(MAX_Real)
{
_world = Matrix::Identity;
UpdateBounds();
_box = BoundingBox(_transform.Translation);
BoundingSphere::FromBox(_box, _sphere);
ParticleSystem.Changed.Bind<ParticleEffect, &ParticleEffect::OnParticleSystemModified>(this);
ParticleSystem.Loaded.Bind<ParticleEffect, &ParticleEffect::OnParticleSystemLoaded>(this);
@@ -295,7 +295,7 @@ void ParticleEffect::UpdateBounds()
if (emitter->SimulationSpace == ParticlesSimulationSpace::Local)
{
BoundingBox::Transform(emitterBounds, _world, emitterBounds);
BoundingBox::Transform(emitterBounds, _transform, emitterBounds);
}
BoundingBox::Merge(emitterBounds, bounds, bounds);
@@ -737,6 +737,5 @@ void ParticleEffect::OnTransformChanged()
// Base
Actor::OnTransformChanged();
_transform.GetWorld(_world);
UpdateBounds();
}

View File

@@ -179,7 +179,6 @@ public:
private:
uint64 _lastUpdateFrame;
Real _lastMinDstSqr;
Matrix _world;
int32 _sceneRenderingKey = -1;
uint32 _parametersVersion = 0; // Version number for _parameters to be in sync with Instance.ParametersVersion
Array<ParticleEffectParameter> _parameters; // Cached for scripting API
@@ -246,15 +245,6 @@ public:
API_FIELD(Attributes="EditorDisplay(\"Particle Effect\"), EditorOrder(75), DefaultValue(DrawPass.Default)")
DrawPass DrawModes = DrawPass::Default;
/// <summary>
/// Gets the actor world matrix transform.
/// </summary>
/// <param name="world">Result world matrix</param>
FORCE_INLINE void GetWorld(Matrix* world) const
{
*world = _world;
}
public:
/// <summary>
/// Gets the effect parameters collection. Those parameters are instanced from the <see cref="ParticleSystem"/> that contains a linear list of emitters and every emitter has a list of own parameters.

View File

@@ -362,7 +362,7 @@ Asset::LoadResult ParticleSystem::load()
continue;
#endif
EmittersParametersOverrides.Add(key, Variant(value));
EmittersParametersOverrides[key] = Variant(value);
}
}
@@ -441,7 +441,7 @@ Asset::LoadResult ParticleSystem::load()
continue;
#endif
EmittersParametersOverrides.Add(key, value);
EmittersParametersOverrides[key] = value;
}
}

View File

@@ -877,8 +877,9 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
const auto drawModes = static_cast<DrawPass>(view.Pass & effect->DrawModes);
if (drawModes == DrawPass::None || SpriteRenderer.Init())
return;
Matrix world;
effect->GetWorld(&world);
Matrix worlds[2];
Matrix::Translation(-renderContext.View.Origin, worlds[0]); // World
renderContext.View.GetWorldMatrix(effect->GetTransform(), worlds[1]); // Local
const auto staticFlags = effect->GetStaticFlags();
// Draw lights
@@ -888,14 +889,15 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
const auto buffer = emitterData.Buffer;
if (!buffer || (buffer->Mode == ParticlesSimulationMode::CPU && buffer->CPU.Count == 0))
continue;
auto emitter = buffer->Emitter;
buffer->Emitter->GraphExecutorCPU.Draw(buffer->Emitter, effect, emitterData, renderContext, world);
buffer->Emitter->GraphExecutorCPU.Draw(buffer->Emitter, effect, emitterData, renderContext, worlds[(int32)emitter->SimulationSpace]);
}
// Setup a draw call common data
DrawCall drawCall;
drawCall.PerInstanceRandom = effect->GetPerInstanceRandom();
drawCall.ObjectPosition = world.GetTranslation();
drawCall.ObjectPosition = effect->GetPosition();
// Draw all emitters
for (int32 emitterIndex = 0; emitterIndex < effect->Instance.Emitters.Count(); emitterIndex++)
@@ -906,7 +908,7 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
continue;
auto emitter = buffer->Emitter;
drawCall.World = emitter->SimulationSpace == ParticlesSimulationSpace::World ? Matrix::Identity : world;
drawCall.World = worlds[(int32)emitter->SimulationSpace];
drawCall.WorldDeterminantSign = Math::FloatSelect(drawCall.World.RotDeterminant(), 1, -1);
drawCall.Particle.Particles = buffer;

View File

@@ -327,7 +327,7 @@ void RigidBody::OnColliderChanged(Collider* c)
void RigidBody::UpdateBounds()
{
void* actor = GetPhysicsActor();
void* actor = _actor;
if (actor && PhysicsBackend::GetRigidActorShapesCount(actor) != 0)
PhysicsBackend::GetActorBounds(actor, _box);
else
@@ -406,7 +406,7 @@ void RigidBody::OnActiveTransformChanged()
ASSERT(!_isUpdatingTransform);
_isUpdatingTransform = true;
Transform transform;
PhysicsBackend::GetRigidActorPose(GetPhysicsActor(), transform.Translation, transform.Orientation);
PhysicsBackend::GetRigidActorPose(_actor, transform.Translation, transform.Orientation);
transform.Scale = _transform.Scale;
if (_parent)
{
@@ -424,7 +424,8 @@ void RigidBody::BeginPlay(SceneBeginData* data)
{
// Create rigid body
ASSERT(_actor == nullptr);
_actor = PhysicsBackend::CreateRigidDynamicActor(this, _transform.Translation, _transform.Orientation);
void* scene = GetPhysicsScene()->GetPhysicsScene();
_actor = PhysicsBackend::CreateRigidDynamicActor(this, _transform.Translation, _transform.Orientation, scene);
// Apply properties
auto actorFlags = PhysicsBackend::ActorFlags::None;
@@ -462,7 +463,6 @@ void RigidBody::BeginPlay(SceneBeginData* data)
PhysicsBackend::SetRigidDynamicActorCenterOfMassOffset(_actor, _centerOfMassOffset);
// Register actor
void* scene = GetPhysicsScene()->GetPhysicsScene();
PhysicsBackend::AddSceneActor(scene, _actor);
const bool putToSleep = !_startAwake && GetEnableSimulation() && !GetIsKinematic() && IsActiveInHierarchy();
if (putToSleep)

View File

@@ -258,13 +258,13 @@ void Collider::UpdateGeometry()
void Collider::CreateStaticActor()
{
ASSERT(_staticActor == nullptr);
_staticActor = PhysicsBackend::CreateRigidStaticActor(nullptr, _transform.Translation, _transform.Orientation);
void* scene = GetPhysicsScene()->GetPhysicsScene();
_staticActor = PhysicsBackend::CreateRigidStaticActor(nullptr, _transform.Translation, _transform.Orientation, scene);
// Reset local pos of the shape and link it to the actor
PhysicsBackend::SetShapeLocalPose(_shape, _center, Quaternion::Identity);
PhysicsBackend::AttachShape(_shape, _staticActor);
void* scene = GetPhysicsScene()->GetPhysicsScene();
PhysicsBackend::AddSceneActor(scene, _staticActor);
}

View File

@@ -65,6 +65,7 @@ struct ScenePhysX
PxCpuDispatcher* CpuDispatcher = nullptr;
PxControllerManager* ControllerManager = nullptr;
void* ScratchMemory = nullptr;
Vector3 Origin = Vector3::Zero;
float LastDeltaTime = 0.0f;
FixedStepper Stepper;
SimulationEventCallback EventsCallback;
@@ -303,7 +304,8 @@ protected:
DynamicHitBuffer<PxOverlapHit> buffer
#define SCENE_QUERY_COLLECT_SINGLE() const auto& hit = buffer.getAnyHit(0); \
P2C(hit, hitInfo)
P2C(hit, hitInfo); \
hitInfo.Point += scenePhysX->Origin
#define SCENE_QUERY_COLLECT_ALL() results.Clear(); \
results.Resize(buffer.getNbAnyHits(), false); \
@@ -311,6 +313,7 @@ protected:
{ \
const auto& hit = buffer.getAnyHit(i); \
P2C(hit, results[i]); \
results[i].Point += scenePhysX->Origin; \
}
#define SCENE_QUERY_COLLECT_OVERLAP() results.Clear(); \
@@ -348,6 +351,7 @@ namespace
QueryFilterPhysX QueryFilter;
CharacterQueryFilterPhysX CharacterQueryFilter;
CharacterControllerFilterPhysX CharacterControllerFilter;
Dictionary<PxScene*, Vector3, InlinedAllocation<32>> SceneOrigins;
CriticalSection FlushLocker;
Array<PxBase*> DeleteObjects;
@@ -721,6 +725,9 @@ bool PhysicsBackend::Init()
// Create default material
DefaultMaterial = PhysX->createMaterial(0.7f, 0.7f, 0.3f);
// Return origin 0,0,0 for invalid/null scenes
SceneOrigins.Add((PxScene*)nullptr, Vector3::Zero);
return false;
}
@@ -772,6 +779,7 @@ void PhysicsBackend::Shutdown()
RELEASE_PHYSX(PVD);
#endif
RELEASE_PHYSX(Foundation);
SceneOrigins.Clear();
}
void PhysicsBackend::ApplySettings(const PhysicsSettings& settings)
@@ -825,6 +833,7 @@ void* PhysicsBackend::CreateScene(const PhysicsSettings& settings)
// Create scene
scenePhysX->Scene = PhysX->createScene(sceneDesc);
CHECK_INIT(scenePhysX->Scene, "createScene failed!");
SceneOrigins[scenePhysX->Scene] = Vector3::Zero;
#if WITH_PVD
auto pvdClient = scenePhysX->Scene->getScenePvdClient();
if (pvdClient)
@@ -852,6 +861,7 @@ void PhysicsBackend::DestroyScene(void* scene)
FlushRequests(scene);
// Release resources
SceneOrigins.Remove(scenePhysX->Scene);
#if WITH_VEHICLE
RELEASE_PHYSX(scenePhysX->WheelRaycastBatchQuery);
#endif
@@ -1182,15 +1192,15 @@ void PhysicsBackend::EndSimulateScene(void* scene)
auto& state = wheelData.State;
state.IsInAir = perWheel.isInAir;
state.TireContactCollider = perWheel.tireContactShape ? static_cast<PhysicsColliderActor*>(perWheel.tireContactShape->userData) : nullptr;
state.TireContactPoint = P2C(perWheel.tireContactPoint);
state.TireContactPoint = P2C(perWheel.tireContactPoint) + scenePhysX->Origin;
state.TireContactNormal = P2C(perWheel.tireContactNormal);
state.TireFriction = perWheel.tireFriction;
state.SteerAngle = RadiansToDegrees * perWheel.steerAngle;
state.RotationAngle = -RadiansToDegrees * drive->mWheelsDynData.getWheelRotationAngle(j);
state.SuspensionOffset = perWheel.suspJounce;
#if USE_EDITOR
state.SuspensionTraceStart = P2C(perWheel.suspLineStart);
state.SuspensionTraceEnd = P2C(perWheel.suspLineStart + perWheel.suspLineDir * perWheel.suspLineLength);
state.SuspensionTraceStart = P2C(perWheel.suspLineStart) + scenePhysX->Origin;
state.SuspensionTraceEnd = P2C(perWheel.suspLineStart + perWheel.suspLineDir * perWheel.suspLineLength) + scenePhysX->Origin;
#endif
if (!wheelData.Collider)
@@ -1274,6 +1284,26 @@ void PhysicsBackend::SetSceneBounceThresholdVelocity(void* scene, float value)
scenePhysX->Scene->setBounceThresholdVelocity(value);
}
void PhysicsBackend::SetSceneOrigin(void* scene, const Vector3& oldOrigin, const Vector3& newOrigin)
{
auto scenePhysX = (ScenePhysX*)scene;
const PxVec3 shift = C2P(newOrigin - oldOrigin);
scenePhysX->Origin = newOrigin;
scenePhysX->Scene->shiftOrigin(shift);
scenePhysX->ControllerManager->shiftOrigin(shift);
WheelVehiclesCache.Clear();
for (auto wheelVehicle : scenePhysX->WheelVehicles)
{
if (!wheelVehicle->IsActiveInHierarchy())
continue;
auto drive = (PxVehicleWheels*)wheelVehicle->_vehicle;
ASSERT(drive);
WheelVehiclesCache.Add(drive);
}
PxVehicleShiftOrigin(shift, WheelVehiclesCache.Count(), WheelVehiclesCache.Get());
SceneOrigins[scenePhysX->Scene] = newOrigin;
}
void PhysicsBackend::AddSceneActor(void* scene, void* actor)
{
auto scenePhysX = (ScenePhysX*)scene;
@@ -1304,14 +1334,14 @@ bool PhysicsBackend::RayCast(void* scene, const Vector3& origin, const Vector3&
{
SCENE_QUERY_SETUP(true);
PxRaycastBuffer buffer;
return scenePhysX->Scene->raycast(C2P(origin), C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter);
return scenePhysX->Scene->raycast(C2P(origin - scenePhysX->Origin), C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter);
}
bool PhysicsBackend::RayCast(void* scene, const Vector3& origin, const Vector3& direction, RayCastHit& hitInfo, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP(true);
PxRaycastBuffer buffer;
if (!scenePhysX->Scene->raycast(C2P(origin), C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter))
if (!scenePhysX->Scene->raycast(C2P(origin - scenePhysX->Origin), C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter))
return false;
SCENE_QUERY_COLLECT_SINGLE();
return true;
@@ -1321,7 +1351,7 @@ bool PhysicsBackend::RayCastAll(void* scene, const Vector3& origin, const Vector
{
SCENE_QUERY_SETUP(false);
DynamicHitBuffer<PxRaycastHit> buffer;
if (!scenePhysX->Scene->raycast(C2P(origin), C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter))
if (!scenePhysX->Scene->raycast(C2P(origin - scenePhysX->Origin), C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter))
return false;
SCENE_QUERY_COLLECT_ALL();
return true;
@@ -1330,7 +1360,7 @@ bool PhysicsBackend::RayCastAll(void* scene, const Vector3& origin, const Vector
bool PhysicsBackend::BoxCast(void* scene, const Vector3& center, const Vector3& halfExtents, const Vector3& direction, const Quaternion& rotation, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_SWEEP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxBoxGeometry geometry(C2P(halfExtents));
return scenePhysX->Scene->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter);
}
@@ -1338,7 +1368,7 @@ bool PhysicsBackend::BoxCast(void* scene, const Vector3& center, const Vector3&
bool PhysicsBackend::BoxCast(void* scene, const Vector3& center, const Vector3& halfExtents, const Vector3& direction, RayCastHit& hitInfo, const Quaternion& rotation, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_SWEEP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxBoxGeometry geometry(C2P(halfExtents));
if (!scenePhysX->Scene->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter))
return false;
@@ -1349,7 +1379,7 @@ bool PhysicsBackend::BoxCast(void* scene, const Vector3& center, const Vector3&
bool PhysicsBackend::BoxCastAll(void* scene, const Vector3& center, const Vector3& halfExtents, const Vector3& direction, Array<RayCastHit>& results, const Quaternion& rotation, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_SWEEP();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxBoxGeometry geometry(C2P(halfExtents));
if (!scenePhysX->Scene->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter))
return false;
@@ -1360,7 +1390,7 @@ bool PhysicsBackend::BoxCastAll(void* scene, const Vector3& center, const Vector
bool PhysicsBackend::SphereCast(void* scene, const Vector3& center, const float radius, const Vector3& direction, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_SWEEP_1();
const PxTransform pose(C2P(center));
const PxTransform pose(C2P(center - scenePhysX->Origin));
const PxSphereGeometry geometry(radius);
return scenePhysX->Scene->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter);
}
@@ -1368,7 +1398,7 @@ bool PhysicsBackend::SphereCast(void* scene, const Vector3& center, const float
bool PhysicsBackend::SphereCast(void* scene, const Vector3& center, const float radius, const Vector3& direction, RayCastHit& hitInfo, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_SWEEP_1();
const PxTransform pose(C2P(center));
const PxTransform pose(C2P(center - scenePhysX->Origin));
const PxSphereGeometry geometry(radius);
if (!scenePhysX->Scene->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter))
return false;
@@ -1379,7 +1409,7 @@ bool PhysicsBackend::SphereCast(void* scene, const Vector3& center, const float
bool PhysicsBackend::SphereCastAll(void* scene, const Vector3& center, const float radius, const Vector3& direction, Array<RayCastHit>& results, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_SWEEP();
const PxTransform pose(C2P(center));
const PxTransform pose(C2P(center - scenePhysX->Origin));
const PxSphereGeometry geometry(radius);
if (!scenePhysX->Scene->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter))
return false;
@@ -1390,7 +1420,7 @@ bool PhysicsBackend::SphereCastAll(void* scene, const Vector3& center, const flo
bool PhysicsBackend::CapsuleCast(void* scene, const Vector3& center, const float radius, const float height, const Vector3& direction, const Quaternion& rotation, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_SWEEP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
return scenePhysX->Scene->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter);
}
@@ -1398,7 +1428,7 @@ bool PhysicsBackend::CapsuleCast(void* scene, const Vector3& center, const float
bool PhysicsBackend::CapsuleCast(void* scene, const Vector3& center, const float radius, const float height, const Vector3& direction, RayCastHit& hitInfo, const Quaternion& rotation, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_SWEEP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
if (!scenePhysX->Scene->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter))
return false;
@@ -1409,7 +1439,7 @@ bool PhysicsBackend::CapsuleCast(void* scene, const Vector3& center, const float
bool PhysicsBackend::CapsuleCastAll(void* scene, const Vector3& center, const float radius, const float height, const Vector3& direction, Array<RayCastHit>& results, const Quaternion& rotation, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_SWEEP();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
if (!scenePhysX->Scene->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter))
return false;
@@ -1421,7 +1451,7 @@ bool PhysicsBackend::ConvexCast(void* scene, const Vector3& center, const Collis
{
CHECK_RETURN(convexMesh && convexMesh->GetOptions().Type == CollisionDataType::ConvexMesh, false)
SCENE_QUERY_SETUP_SWEEP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxConvexMeshGeometry geometry((PxConvexMesh*)convexMesh->GetConvex(), PxMeshScale(C2P(scale)));
return scenePhysX->Scene->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter);
}
@@ -1430,7 +1460,7 @@ bool PhysicsBackend::ConvexCast(void* scene, const Vector3& center, const Collis
{
CHECK_RETURN(convexMesh && convexMesh->GetOptions().Type == CollisionDataType::ConvexMesh, false)
SCENE_QUERY_SETUP_SWEEP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxConvexMeshGeometry geometry((PxConvexMesh*)convexMesh->GetConvex(), PxMeshScale(C2P(scale)));
if (!scenePhysX->Scene->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter))
return false;
@@ -1442,7 +1472,7 @@ bool PhysicsBackend::ConvexCastAll(void* scene, const Vector3& center, const Col
{
CHECK_RETURN(convexMesh && convexMesh->GetOptions().Type == CollisionDataType::ConvexMesh, false)
SCENE_QUERY_SETUP_SWEEP();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxConvexMeshGeometry geometry((PxConvexMesh*)convexMesh->GetConvex(), PxMeshScale(C2P(scale)));
if (!scenePhysX->Scene->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, &QueryFilter))
return false;
@@ -1453,7 +1483,7 @@ bool PhysicsBackend::ConvexCastAll(void* scene, const Vector3& center, const Col
bool PhysicsBackend::CheckBox(void* scene, const Vector3& center, const Vector3& halfExtents, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_OVERLAP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxBoxGeometry geometry(C2P(halfExtents));
return scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter);
}
@@ -1461,7 +1491,7 @@ bool PhysicsBackend::CheckBox(void* scene, const Vector3& center, const Vector3&
bool PhysicsBackend::CheckSphere(void* scene, const Vector3& center, const float radius, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_OVERLAP_1();
const PxTransform pose(C2P(center));
const PxTransform pose(C2P(center - scenePhysX->Origin));
const PxSphereGeometry geometry(radius);
return scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter);
}
@@ -1469,7 +1499,7 @@ bool PhysicsBackend::CheckSphere(void* scene, const Vector3& center, const float
bool PhysicsBackend::CheckCapsule(void* scene, const Vector3& center, const float radius, const float height, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_OVERLAP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
return scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter);
}
@@ -1478,7 +1508,7 @@ bool PhysicsBackend::CheckConvex(void* scene, const Vector3& center, const Colli
{
CHECK_RETURN(convexMesh && convexMesh->GetOptions().Type == CollisionDataType::ConvexMesh, false)
SCENE_QUERY_SETUP_OVERLAP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxConvexMeshGeometry geometry((PxConvexMesh*)convexMesh->GetConvex(), PxMeshScale(C2P(scale)));
return scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter);
}
@@ -1486,7 +1516,7 @@ bool PhysicsBackend::CheckConvex(void* scene, const Vector3& center, const Colli
bool PhysicsBackend::OverlapBox(void* scene, const Vector3& center, const Vector3& halfExtents, Array<Collider*>& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_OVERLAP();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxBoxGeometry geometry(C2P(halfExtents));
if (!scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter))
return false;
@@ -1497,7 +1527,7 @@ bool PhysicsBackend::OverlapBox(void* scene, const Vector3& center, const Vector
bool PhysicsBackend::OverlapSphere(void* scene, const Vector3& center, const float radius, Array<Collider*>& results, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_OVERLAP();
const PxTransform pose(C2P(center));
const PxTransform pose(C2P(center - scenePhysX->Origin));
const PxSphereGeometry geometry(radius);
if (!scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter))
return false;
@@ -1508,7 +1538,7 @@ bool PhysicsBackend::OverlapSphere(void* scene, const Vector3& center, const flo
bool PhysicsBackend::OverlapCapsule(void* scene, const Vector3& center, const float radius, const float height, Array<Collider*>& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_OVERLAP();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
if (!scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter))
return false;
@@ -1520,7 +1550,7 @@ bool PhysicsBackend::OverlapConvex(void* scene, const Vector3& center, const Col
{
CHECK_RETURN(convexMesh && convexMesh->GetOptions().Type == CollisionDataType::ConvexMesh, false)
SCENE_QUERY_SETUP_OVERLAP();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxConvexMeshGeometry geometry((PxConvexMesh*)convexMesh->GetConvex(), PxMeshScale(C2P(scale)));
if (!scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter))
return false;
@@ -1531,7 +1561,7 @@ bool PhysicsBackend::OverlapConvex(void* scene, const Vector3& center, const Col
bool PhysicsBackend::OverlapBox(void* scene, const Vector3& center, const Vector3& halfExtents, Array<PhysicsColliderActor*>& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_OVERLAP();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxBoxGeometry geometry(C2P(halfExtents));
if (!scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter))
return false;
@@ -1542,7 +1572,7 @@ bool PhysicsBackend::OverlapBox(void* scene, const Vector3& center, const Vector
bool PhysicsBackend::OverlapSphere(void* scene, const Vector3& center, const float radius, Array<PhysicsColliderActor*>& results, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_OVERLAP();
const PxTransform pose(C2P(center));
const PxTransform pose(C2P(center - scenePhysX->Origin));
const PxSphereGeometry geometry(radius);
if (!scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter))
return false;
@@ -1553,7 +1583,7 @@ bool PhysicsBackend::OverlapSphere(void* scene, const Vector3& center, const flo
bool PhysicsBackend::OverlapCapsule(void* scene, const Vector3& center, const float radius, const float height, Array<PhysicsColliderActor*>& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{
SCENE_QUERY_SETUP_OVERLAP();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
if (!scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter))
return false;
@@ -1565,7 +1595,7 @@ bool PhysicsBackend::OverlapConvex(void* scene, const Vector3& center, const Col
{
CHECK_RETURN(convexMesh && convexMesh->GetOptions().Type == CollisionDataType::ConvexMesh, false)
SCENE_QUERY_SETUP_OVERLAP();
const PxTransform pose(C2P(center), C2P(rotation));
const PxTransform pose(C2P(center - scenePhysX->Origin), C2P(rotation));
const PxConvexMeshGeometry geometry((PxConvexMesh*)convexMesh->GetConvex(), PxMeshScale(C2P(scale)));
if (!scenePhysX->Scene->overlap(geometry, pose, buffer, filterData, &QueryFilter))
return false;
@@ -1604,6 +1634,9 @@ void PhysicsBackend::GetActorBounds(void* actor, BoundingBox& bounds)
auto actorPhysX = (PxActor*)actor;
const float boundsScale = 1.02f;
bounds = P2C(actorPhysX->getWorldBounds(boundsScale));
const Vector3 sceneOrigin = SceneOrigins[actorPhysX->getScene()];
bounds.Minimum += sceneOrigin;
bounds.Maximum += sceneOrigin;
}
int32 PhysicsBackend::GetRigidActorShapesCount(void* actor)
@@ -1612,9 +1645,10 @@ int32 PhysicsBackend::GetRigidActorShapesCount(void* actor)
return actorPhysX->getNbShapes();
}
void* PhysicsBackend::CreateRigidDynamicActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation)
void* PhysicsBackend::CreateRigidDynamicActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation, void* scene)
{
const PxTransform trans(C2P(position), C2P(orientation));
const Vector3 sceneOrigin = SceneOrigins[scene ? ( (ScenePhysX*)scene)->Scene : nullptr];
const PxTransform trans(C2P(position - sceneOrigin), C2P(orientation));
PxRigidDynamic* actorPhysX = PhysX->createRigidDynamic(trans);
actorPhysX->userData = actor;
#if PHYSX_DEBUG_NAMING
@@ -1626,9 +1660,10 @@ void* PhysicsBackend::CreateRigidDynamicActor(IPhysicsActor* actor, const Vector
return actorPhysX;
}
void* PhysicsBackend::CreateRigidStaticActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation)
void* PhysicsBackend::CreateRigidStaticActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation, void* scene)
{
const PxTransform trans(C2P(position), C2P(orientation));
const Vector3 sceneOrigin = SceneOrigins[scene ? ( (ScenePhysX*)scene)->Scene : nullptr];
const PxTransform trans(C2P(position - sceneOrigin), C2P(orientation));
PxRigidStatic* actorPhysX = PhysX->createRigidStatic(trans);
actorPhysX->userData = actor;
#if PHYSX_DEBUG_NAMING
@@ -1667,13 +1702,15 @@ void PhysicsBackend::GetRigidActorPose(void* actor, Vector3& position, Quaternio
{
auto actorPhysX = (PxRigidActor*)actor;
auto pose = actorPhysX->getGlobalPose();
position = P2C(pose.p);
const Vector3 sceneOrigin = SceneOrigins[actorPhysX->getScene()];
position = P2C(pose.p) + sceneOrigin;
orientation = P2C(pose.q);
}
void PhysicsBackend::SetRigidActorPose(void* actor, const Vector3& position, const Quaternion& orientation, bool kinematic, bool wakeUp)
{
const PxTransform trans(C2P(position), C2P(orientation));
const Vector3 sceneOrigin = SceneOrigins[((PxActor*)actor)->getScene()];
const PxTransform trans(C2P(position - sceneOrigin), C2P(orientation));
if (kinematic)
{
auto actorPhysX = (PxRigidDynamic*)actor;
@@ -1852,7 +1889,8 @@ void PhysicsBackend::AddRigidDynamicActorForce(void* actor, const Vector3& force
void PhysicsBackend::AddRigidDynamicActorForceAtPosition(void* actor, const Vector3& force, const Vector3& position, ForceMode mode)
{
auto actorPhysX = (PxRigidDynamic*)actor;
PxRigidBodyExt::addForceAtPos(*actorPhysX, C2P(force), C2P(position), static_cast<PxForceMode::Enum>(mode));
const Vector3 sceneOrigin = SceneOrigins[actorPhysX->getScene()];
PxRigidBodyExt::addForceAtPos(*actorPhysX, C2P(force), C2P(position - sceneOrigin), static_cast<PxForceMode::Enum>(mode));
}
void PhysicsBackend::AddRigidDynamicActorTorque(void* actor, const Vector3& torque, ForceMode mode)
@@ -1907,7 +1945,8 @@ void PhysicsBackend::GetShapePose(void* shape, Vector3& position, Quaternion& or
auto shapePhysX = (PxShape*)shape;
PxRigidActor* actorPhysX = shapePhysX->getActor();
PxTransform pose = actorPhysX->getGlobalPose().transform(shapePhysX->getLocalPose());
position = P2C(pose.p);
const Vector3 sceneOrigin = SceneOrigins[actorPhysX->getScene()];
position = P2C(pose.p) + sceneOrigin;
orientation = P2C(pose.q);
}
@@ -2015,10 +2054,11 @@ float PhysicsBackend::ComputeShapeSqrDistanceToPoint(void* shape, const Vector3&
bool PhysicsBackend::RayCastShape(void* shape, const Vector3& position, const Quaternion& orientation, const Vector3& origin, const Vector3& direction, float& resultHitDistance, float maxDistance)
{
auto shapePhysX = (PxShape*)shape;
const PxTransform trans(C2P(position), C2P(orientation));
const Vector3 sceneOrigin = SceneOrigins[shapePhysX->getActor() ? shapePhysX->getActor()->getScene() : nullptr];
const PxTransform trans(C2P(position - sceneOrigin), C2P(orientation));
const PxHitFlags hitFlags = (PxHitFlags)0;
PxRaycastHit hit;
if (PxGeometryQuery::raycast(C2P(origin), C2P(direction), shapePhysX->getGeometry().any(), trans, maxDistance, hitFlags, 1, &hit) != 0)
if (PxGeometryQuery::raycast(C2P(origin - sceneOrigin), C2P(direction), shapePhysX->getGeometry().any(), trans, maxDistance, hitFlags, 1, &hit) != 0)
{
resultHitDistance = hit.distance;
return true;
@@ -2029,12 +2069,14 @@ bool PhysicsBackend::RayCastShape(void* shape, const Vector3& position, const Qu
bool PhysicsBackend::RayCastShape(void* shape, const Vector3& position, const Quaternion& orientation, const Vector3& origin, const Vector3& direction, RayCastHit& hitInfo, float maxDistance)
{
auto shapePhysX = (PxShape*)shape;
const PxTransform trans(C2P(position), C2P(orientation));
const Vector3 sceneOrigin = SceneOrigins[shapePhysX->getActor() ? shapePhysX->getActor()->getScene() : nullptr];
const PxTransform trans(C2P(position - sceneOrigin), C2P(orientation));
const PxHitFlags hitFlags = PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eFACE_INDEX | PxHitFlag::eUV;
PxRaycastHit hit;
if (PxGeometryQuery::raycast(C2P(origin), C2P(direction), shapePhysX->getGeometry().any(), trans, maxDistance, hitFlags, 1, &hit) == 0)
if (PxGeometryQuery::raycast(C2P(origin - sceneOrigin), C2P(direction), shapePhysX->getGeometry().any(), trans, maxDistance, hitFlags, 1, &hit) == 0)
return false;
P2C(hit, hitInfo);
hitInfo.Point += sceneOrigin;
return true;
}
@@ -2390,10 +2432,11 @@ float PhysicsBackend::GetD6JointSwingZ(void* joint)
void* PhysicsBackend::CreateController(void* scene, IPhysicsActor* actor, PhysicsColliderActor* collider, float contactOffset, const Vector3& position, float slopeLimit, int32 nonWalkableMode, JsonAsset* material, float radius, float height, float stepOffset, void*& shape)
{
auto scenePhysX = (ScenePhysX*)scene;
const Vector3 sceneOrigin = SceneOrigins[scenePhysX->Scene];
PxCapsuleControllerDesc desc;
desc.userData = actor;
desc.contactOffset = Math::Max(contactOffset, ZeroTolerance);
desc.position = PxExtendedVec3(position.X, position.Y, position.Z);
desc.position = PxExtendedVec3(position.X - sceneOrigin.X, position.Y - sceneOrigin.Y, position.Z - sceneOrigin.Z);
desc.slopeLimit = Math::Cos(slopeLimit * DegreesToRadians);
desc.nonWalkableMode = static_cast<PxControllerNonWalkableMode::Enum>(nonWalkableMode);
desc.climbingMode = PxCapsuleClimbingMode::eEASY;
@@ -2465,13 +2508,15 @@ void PhysicsBackend::SetControllerUpDirection(void* controller, const Vector3& v
Vector3 PhysicsBackend::GetControllerPosition(void* controller)
{
auto controllerPhysX = (PxCapsuleController*)controller;
return P2C(controllerPhysX->getPosition());
const Vector3 origin = SceneOrigins[controllerPhysX->getScene()];
return P2C(controllerPhysX->getPosition()) + origin;
}
void PhysicsBackend::SetControllerPosition(void* controller, const Vector3& value)
{
auto controllerPhysX = (PxCapsuleController*)controller;
controllerPhysX->setPosition(PxExtendedVec3(value.X, value.Y, value.Z));
const Vector3 sceneOrigin = SceneOrigins[controllerPhysX->getScene()];
controllerPhysX->setPosition(PxExtendedVec3(value.X - sceneOrigin.X, value.Y - sceneOrigin.Y, value.Z - sceneOrigin.Z));
}
int32 PhysicsBackend::MoveController(void* controller, void* shape, const Vector3& displacement, float minMoveDistance, float deltaTime)

View File

@@ -384,12 +384,12 @@ void PhysicsScene::SetGravity(const Vector3& value)
PhysicsBackend::SetSceneGravity(_scene, value);
}
Vector3 PhysicsScene::GetGravity()
Vector3 PhysicsScene::GetGravity() const
{
return PhysicsBackend::GetSceneGravity(_scene);
}
bool PhysicsScene::GetEnableCCD()
bool PhysicsScene::GetEnableCCD() const
{
return PhysicsBackend::GetSceneEnableCCD(_scene);
}
@@ -409,6 +409,15 @@ void PhysicsScene::SetBounceThresholdVelocity(float value)
PhysicsBackend::SetSceneBounceThresholdVelocity(_scene, value);
}
void PhysicsScene::SetOrigin(const Vector3& value)
{
if (_origin != value)
{
PhysicsBackend::SetSceneOrigin(_scene, _origin, value);
_origin = value;
}
}
bool PhysicsScene::Init(const StringView& name, const PhysicsSettings& settings)
{
if (_scene)

View File

@@ -94,6 +94,7 @@ public:
static void SetSceneEnableCCD(void* scene, bool value);
static float GetSceneBounceThresholdVelocity(void* scene);
static void SetSceneBounceThresholdVelocity(void* scene, float value);
static void SetSceneOrigin(void* scene, const Vector3& oldOrigin, const Vector3& newOrigin);
static void AddSceneActor(void* scene, void* actor);
static void RemoveSceneActor(void* scene, void* actor);
static void AddSceneActorAction(void* scene, void* actor, ActionType action);
@@ -132,8 +133,8 @@ public:
static void SetActorFlags(void* actor, ActorFlags value);
static void GetActorBounds(void* actor, BoundingBox& bounds);
static int32 GetRigidActorShapesCount(void* actor);
static void* CreateRigidDynamicActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation);
static void* CreateRigidStaticActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation);
static void* CreateRigidDynamicActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation, void* scene);
static void* CreateRigidStaticActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation, void* scene);
static RigidDynamicFlags GetRigidDynamicActorFlags(void* actor);
static void SetRigidDynamicActorFlags(void* actor, RigidDynamicFlags value);
static void GetRigidActorPose(void* actor, Vector3& position, Quaternion& orientation);

View File

@@ -28,6 +28,7 @@ private:
String _name;
bool _autoSimulation = true;
bool _isDuringSimulation = false;
Vector3 _origin = Vector3::Zero;
void* _scene = nullptr;
public:
@@ -59,7 +60,7 @@ public:
/// <summary>
/// Gets the current gravity force.
/// </summary>
API_PROPERTY() Vector3 GetGravity();
API_PROPERTY() Vector3 GetGravity() const;
/// <summary>
/// Sets the current gravity force.
@@ -69,7 +70,7 @@ public:
/// <summary>
/// Gets the CCD feature enable flag.
/// </summary>
API_PROPERTY() bool GetEnableCCD();
API_PROPERTY() bool GetEnableCCD() const;
/// <summary>
/// Sets the CCD feature enable flag.
@@ -86,6 +87,19 @@ public:
/// </summary>
API_PROPERTY() void SetBounceThresholdVelocity(float value);
/// <summary>
/// Gets the current scene origin that defines the center of the simulation (in world). Can be used to run physics simulation relative to the camera.
/// </summary>
API_PROPERTY() FORCE_INLINE Vector3 GetOrigin() const
{
return _origin;
}
/// <summary>
/// Sets the current scene origin that defines the center of the simulation (in world). Can be used to run physics simulation relative to the camera.
/// </summary>
API_PROPERTY() void SetOrigin(const Vector3& value);
public:
/// <summary>
/// Initializes the scene.

View File

@@ -12,6 +12,7 @@
#include "Engine/Level/Actors/EnvironmentProbe.h"
#include "Engine/Level/Actors/SkyLight.h"
#include "Engine/Level/SceneQuery.h"
#include "Engine/Level/LargeWorlds.h"
#include "Engine/ContentExporters/AssetExporters.h"
#include "Engine/Serialization/FileWriteStream.h"
#include "Engine/Engine/Time.h"
@@ -430,12 +431,11 @@ bool fixFarPlaneTreeExecute(Actor* actor, const Vector3& position, float& farPla
if (auto* pointLight = dynamic_cast<PointLight*>(actor))
{
const Real dst = Vector3::Distance(pointLight->GetPosition(), position) + pointLight->GetScaledRadius();
if (dst > farPlane)
if (dst > farPlane && dst * 0.5f < farPlane)
{
farPlane = (float)dst;
}
}
return true;
}
@@ -480,7 +480,8 @@ void ProbesRenderer::onRender(RenderTask* task, GPUContext* context)
SceneQuery::TreeExecute<const Vector3&, float&>(f, position, farPlane);
// Setup view
_task->View.SetUpCube(nearPlane, farPlane, position);
LargeWorlds::UpdateOrigin(_task->View.Origin, position);
_task->View.SetUpCube(nearPlane, farPlane, position - _task->View.Origin);
}
else if (_current.Type == EntryType::SkyLight)
{
@@ -494,7 +495,8 @@ void ProbesRenderer::onRender(RenderTask* task, GPUContext* context)
// TODO: use setLowerHemisphereToBlack feature for SkyLight?
// Setup view
_task->View.SetUpCube(nearPlane, farPlane, position);
LargeWorlds::UpdateOrigin(_task->View.Origin, position);
_task->View.SetUpCube(nearPlane, farPlane, position - _task->View.Origin);
}
// Disable actor during baking (it cannot influence own results)

View File

@@ -415,7 +415,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light
if (!probe->HasProbeLoaded())
continue;
float probeRadius = probe->GetScaledRadius();
Vector3 probePosition = probe->GetPosition(); // TODO: large-worlds
Float3 probePosition = probe->GetPosition() - renderContext.View.Origin;
// Get distance from view center to light center less radius (check if view is inside a sphere)
const float sphereModelScale = 2.0f;
@@ -430,7 +430,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light
Matrix::Multiply(world, view.ViewProjection(), wvp);
// Pack probe properties buffer
probe->SetupProbeData(&data.PData);
probe->SetupProbeData(renderContext, &data.PData);
Matrix::Transpose(wvp, data.WVP);
// Render reflections

View File

@@ -2113,9 +2113,9 @@ void TerrainPatch::CreateCollision()
PhysicsBackend::SetShapeLocalPose(_physicsShape, Vector3(0, _yOffset * terrainTransform.Scale.Y, 0), Quaternion::Identity);
// Create static actor
_physicsActor = PhysicsBackend::CreateRigidStaticActor(nullptr, terrainTransform.LocalToWorld(_offset), terrainTransform.Orientation);
PhysicsBackend::AttachShape(_physicsShape, _physicsActor);
void* scene = _terrain->GetPhysicsScene()->GetPhysicsScene();
_physicsActor = PhysicsBackend::CreateRigidStaticActor(nullptr, terrainTransform.LocalToWorld(_offset), terrainTransform.Orientation, scene);
PhysicsBackend::AttachShape(_physicsShape, _physicsActor);
PhysicsBackend::AddSceneActor(scene, _physicsActor);
}

View File

@@ -113,22 +113,21 @@ void SpriteRender::Draw(RenderContext& renderContext)
auto model = _quadModel.As<Model>();
if (model->GetLoadedLODs() == 0)
return;
auto& view = renderContext.View;
const auto& view = renderContext.View;
Matrix m1, m2, m3, world;
Matrix::Scaling(_size.X, _size.Y, 1.0f, m2);
Matrix::RotationY(PI, m3);
Matrix::Multiply(m2, m3, m1);
// TODO: large-worlds
if (FaceCamera)
{
Matrix::Billboard(_transform.Translation, view.Position, Vector3::Up, view.Direction, m2);
Matrix::Billboard(_transform.Translation - view.Origin, view.Position, Vector3::Up, view.Direction, m2);
Matrix::Multiply(m1, m2, m3);
Matrix::Scaling(_transform.Scale, m1);
Matrix::Multiply(m1, m3, world);
}
else
{
_transform.GetWorld(m2);
view.GetWorldMatrix(_transform, m2);
Matrix::Multiply(m1, m2, world);
}
model->LODs[0].Draw(renderContext, _materialInstance, world, GetStaticFlags(), false, DrawModes, GetPerInstanceRandom());

View File

@@ -56,7 +56,7 @@ public:
/// <summary>
/// Gets the text.
/// </summary>
API_PROPERTY(Attributes="EditorOrder(0), EditorDisplay(\"Text\")")
API_PROPERTY(Attributes="EditorOrder(0), MultilineText, EditorDisplay(\"Text\")")
const LocalizedString& GetText() const;
/// <summary>

View File

@@ -17,25 +17,21 @@ namespace FlaxEngine
/// <summary>
/// The screen space rendering mode that places UI elements on the screen rendered on top of the scene. If the screen is resized or changes resolution, the Canvas will automatically change size to match this.
/// </summary>
[Tooltip("The screen space rendering mode that places UI elements on the screen rendered on top of the scene. If the screen is resized or changes resolution, the Canvas will automatically change size to match this.")]
ScreenSpace = 0,
/// <summary>
/// The camera space rendering mode that places Canvas in a given distance in front of a specified Camera. The UI elements are rendered by this camera, which means that the Camera settings affect the appearance of the UI. If the Camera is set to Perspective, the UI elements will be rendered with perspective, and the amount of perspective distortion can be controlled by the Camera Field of View. If the screen is resized, changes resolution, or the camera frustum changes, the Canvas will automatically change size to match as well.
/// </summary>
[Tooltip("The camera space rendering mode that places Canvas in a given distance in front of a specified Camera. The UI elements are rendered by this camera, which means that the Camera settings affect the appearance of the UI. If the Camera is set to Perspective, the UI elements will be rendered with perspective, and the amount of perspective distortion can be controlled by the Camera Field of View. If the screen is resized, changes resolution, or the camera frustum changes, the Canvas will automatically change size to match as well.")]
CameraSpace = 1,
/// <summary>
/// The world space rendering mode that places Canvas as any other object in the scene. The size of the Canvas can be set manually using its Transform, and UI elements will render in front of or behind other objects in the scene based on 3D placement. This is useful for UIs that are meant to be a part of the world. This is also known as a 'diegetic interface'.
/// </summary>
[Tooltip("The world space rendering mode that places Canvas as any other object in the scene. The size of the Canvas can be set manually using its Transform, and UI elements will render in front of or behind other objects in the scene based on 3D placement. This is useful for UIs that are meant to be a part of the world. This is also known as a 'diegetic interface'.")]
WorldSpace = 2,
/// <summary>
/// The world space rendering mode that places Canvas as any other object in the scene and orients it to face the camera. The size of the Canvas can be set manually using its Transform, and UI elements will render in front of or behind other objects in the scene based on 3D placement. This is useful for UIs that are meant to be a part of the world. This is also known as a 'diegetic interface'.
/// </summary>
[Tooltip("The world space rendering mode that places Canvas as any other object in the scene and orients canvas to face the camera. The size of the Canvas can be set manually using its Transform, and UI elements will render in front of or behind other objects in the scene based on 3D placement. This is useful for UIs that are meant to be a part of the world. This is also known as a 'diegetic interface'.")]
WorldSpaceFaceCamera = 3,
}
@@ -63,13 +59,15 @@ namespace FlaxEngine
/// <inheritdoc />
public override void Render(GPUContext context, ref RenderContext renderContext, GPUTexture input, GPUTexture output)
{
if (renderContext.View.Frustum.Contains(Canvas.Bounds.GetBoundingBox()) == ContainmentType.Disjoint)
var bounds = Canvas.Bounds;
bounds.Transformation.Translation -= renderContext.View.Origin;
if (renderContext.View.Frustum.Contains(bounds.GetBoundingBox()) == ContainmentType.Disjoint)
return;
Profiler.BeginEventGPU("UI Canvas");
// Calculate rendering matrix (world*view*projection)
Canvas.GetWorldMatrix(out Matrix worldMatrix);
Canvas.GetWorldMatrix(renderContext.View.Origin, out Matrix worldMatrix);
Matrix.Multiply(ref worldMatrix, ref renderContext.View.View, out Matrix viewMatrix);
Matrix.Multiply(ref viewMatrix, ref renderContext.View.Projection, out Matrix viewProjectionMatrix);
@@ -352,25 +350,37 @@ namespace FlaxEngine
/// <param name="world">The world.</param>
public void GetWorldMatrix(out Matrix world)
{
GetWorldMatrix(Vector3.Zero, out world);
}
/// <summary>
/// Gets the world matrix used to transform the GUI from the local space to the world space. Handles canvas rendering mode
/// </summary>
/// <param name="viewOrigin">The view origin (when using relative-to-camera rendering).</param>
/// <param name="world">The world.</param>
public void GetWorldMatrix(Vector3 viewOrigin, out Matrix world)
{
var transform = Transform;
Float3 translation = transform.Translation - viewOrigin;
#if FLAX_EDITOR
// Override projection for editor preview
if (_editorTask)
{
if (_renderMode == CanvasRenderMode.WorldSpace)
{
GetLocalToWorldMatrix(out world);
Matrix.Transformation(ref transform.Scale, ref transform.Orientation, ref translation, out world);
}
else if (_renderMode == CanvasRenderMode.WorldSpaceFaceCamera)
{
var view = _editorTask.View;
var transform = Transform;
Matrix.Translation(_guiRoot.Width * -0.5f, _guiRoot.Height * -0.5f, 0, out var m1);
Matrix.Scaling(ref transform.Scale, out var m2);
Matrix.Multiply(ref m1, ref m2, out var m3);
Quaternion.Euler(180, 180, 0, out var quat);
Matrix.RotationQuaternion(ref quat, out m2);
Matrix.Multiply(ref m3, ref m2, out m1);
m2 = Matrix.Transformation(Float3.One, Quaternion.FromDirection(-view.Direction), transform.Translation);
m2 = Matrix.Transformation(Float3.One, Quaternion.FromDirection(-view.Direction), translation);
Matrix.Multiply(ref m1, ref m2, out world);
}
else if (_renderMode == CanvasRenderMode.CameraSpace)
@@ -384,7 +394,7 @@ namespace FlaxEngine
Matrix.Translation(_guiRoot.Width / -2.0f, _guiRoot.Height / -2.0f, 0, out world);
Matrix.RotationYawPitchRoll(Mathf.Pi, Mathf.Pi, 0, out var tmp2);
Matrix.Multiply(ref world, ref tmp2, out var tmp1);
var viewPos = (Float3)view.Position; // TODO: large-worlds
Float3 viewPos = view.Position - viewOrigin;
var viewRot = view.Direction != Float3.Up ? Quaternion.LookRotation(view.Direction, Float3.Up) : Quaternion.LookRotation(view.Direction, Float3.Right);
var viewUp = Float3.Up * viewRot;
var viewForward = view.Direction;
@@ -407,19 +417,18 @@ namespace FlaxEngine
if (_renderMode == CanvasRenderMode.WorldSpace || (_renderMode == CanvasRenderMode.WorldSpaceFaceCamera && !camera))
{
// In 3D world
GetLocalToWorldMatrix(out world);
Matrix.Transformation(ref transform.Scale, ref transform.Orientation, ref translation, out world);
}
else if (_renderMode == CanvasRenderMode.WorldSpaceFaceCamera)
{
// In 3D world face camera
var transform = Transform;
Matrix.Translation(_guiRoot.Width * -0.5f, _guiRoot.Height * -0.5f, 0, out var m1);
Matrix.Scaling(ref transform.Scale, out var m2);
Matrix.Multiply(ref m1, ref m2, out var m3);
Quaternion.Euler(180, 180, 0, out var quat);
Matrix.RotationQuaternion(ref quat, out m2);
Matrix.Multiply(ref m3, ref m2, out m1);
m2 = Matrix.Transformation(Vector3.One, Quaternion.FromDirection(-camera.Direction), transform.Translation);
m2 = Matrix.Transformation(Vector3.One, Quaternion.FromDirection(-camera.Direction), translation);
Matrix.Multiply(ref m1, ref m2, out world);
}
else if (_renderMode == CanvasRenderMode.CameraSpace && camera)
@@ -446,7 +455,7 @@ namespace FlaxEngine
Matrix.Multiply(ref world, ref tmp2, out tmp1);
// In front of the camera
var viewPos = (Float3)camera.Position; // TODO: large-worlds
Float3 viewPos = camera.Position - viewOrigin;
var viewRot = camera.Orientation;
var viewUp = Float3.Up * viewRot;
var viewForward = Float3.Forward * viewRot;