Better sound occlusion (#1102)

* Better occlusion; introduce IntersectRayPenetration

* Use ToArray instead of casting

* Better doc

* Use Debug.Assert
This commit is contained in:
Clyybber
2020-06-05 12:53:43 +02:00
committed by GitHub
parent dc82748daf
commit c32f21bea3
4 changed files with 37 additions and 6 deletions

View File

@@ -300,17 +300,17 @@ namespace Robust.Client.Audio.Midi
else
{
var sourceRelative = _eyeManager.CurrentEye.Position.Position - pos.Position;
var occlusion = 0;
var occlusion = 0f;
if (sourceRelative.Length > 0)
{
occlusion = IoCManager.Resolve<IPhysicsManager>().IntersectRay(
occlusion = IoCManager.Resolve<IPhysicsManager>().IntersectRayPenetration(
pos.MapId,
new CollisionRay(
pos.Position,
sourceRelative.Normalized,
OcclusionCollisionMask),
sourceRelative.Length,
renderer.TrackingEntity, false).Count();
renderer.TrackingEntity);
}
renderer.Source.SetOcclusion(occlusion);
}

View File

@@ -107,17 +107,17 @@ namespace Robust.Client.GameObjects.EntitySystems
else
{
var sourceRelative = _eyeManager.CurrentEye.Position.Position - pos.Position;
var occlusion = 0;
var occlusion = 0f;
if (sourceRelative.Length > 0)
{
occlusion = IoCManager.Resolve<IPhysicsManager>().IntersectRay(
occlusion = IoCManager.Resolve<IPhysicsManager>().IntersectRayPenetration(
pos.MapId,
new CollisionRay(
pos.Position,
sourceRelative.Normalized,
OcclusionCollisionMask),
sourceRelative.Length,
stream.TrackingEntity, false).Count();
stream.TrackingEntity);
}
stream.Source.SetVolume(stream.Volume);
stream.Source.SetOcclusion(occlusion);

View File

@@ -62,6 +62,16 @@ namespace Robust.Shared.Interfaces.Physics
IEnumerable<RayCastResults> IntersectRay(MapId mapId, CollisionRay ray, float maxLength = 50, IEntity ignoredEnt = null, bool returnOnFirstHit = true);
/// <summary>
/// Casts a ray in the world and returns the distance the ray traveled while colliding with entities
/// </summary>
/// <param name="mapId"></param>
/// <param name="ray">Ray to cast in the world.</param>
/// <param name="maxLength">Maximum length of the ray in meters.</param>
/// <param name="ignoredEnt">A single entity that can be ignored by the RayCast. Useful if the ray starts inside the body of an entity.</param>
/// <returns>The distance the ray traveled while colliding with entities</returns>
public float IntersectRayPenetration(MapId mapId, CollisionRay ray, float maxLength, IEntity ignoredEnt = null);
/// <summary>
/// Calculates the normal vector for two colliding bodies
/// </summary>

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using JetBrains.Annotations;
using Robust.Shared.GameObjects.Components;
@@ -276,6 +277,26 @@ namespace Robust.Shared.Physics
public IEnumerable<RayCastResults> IntersectRay(MapId mapId, CollisionRay ray, float maxLength = 50, IEntity ignoredEnt = null, bool returnOnFirstHit = true)
=> IntersectRayWithPredicate(mapId, ray, maxLength, entity => entity == ignoredEnt, returnOnFirstHit);
/// <inheritdoc />
public float IntersectRayPenetration(MapId mapId, CollisionRay ray, float maxLength, IEntity ignoredEnt = null)
{
var penetration = 0f;
var sourceToDest = IntersectRay(mapId, ray, maxLength, ignoredEnt, false).ToArray();
var destToSource = IntersectRay(mapId,
new CollisionRay(ray.Position + ray.Direction * maxLength, -ray.Direction, ray.CollisionMask),
maxLength, ignoredEnt, false).ToArray();
Debug.Assert(sourceToDest.Length == destToSource.Length);
for (int i = 0; i < sourceToDest.Length; i++)
{
penetration += (sourceToDest[i].HitPos - destToSource[sourceToDest.Length - 1 - i].HitPos).Length;
}
return penetration;
}
public event Action<DebugRayData> DebugDrawRay;
public bool Update(IPhysBody collider)