Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user