Netcode Bootstrap
This commit is contained in:
+14
@@ -0,0 +1,14 @@
|
||||
using Unity.Entities;
|
||||
#if RUKHANKA_WITH_NETCODE
|
||||
using Unity.NetCode;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Rukhanka
|
||||
{
|
||||
#if RUKHANKA_WITH_NETCODE
|
||||
[GhostComponent(PrefabType = GhostPrefabType.Client)]
|
||||
#endif
|
||||
public struct CullAnimationsTag: IComponentData, IEnableableComponent { }
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ea374b0d867d4d46af7d12fe9a9b617
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 298480
|
||||
packageName: Rukhanka Animation System 2
|
||||
packageVersion: 2.9.0
|
||||
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Culling/AnimationCullingComponents.cs
|
||||
uploadId: 897522
|
||||
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
#if HDRP_10_0_0_OR_NEWER
|
||||
using UnityEngine.Rendering.HighDefinition;
|
||||
#elif URP_10_0_0_OR_NEWER
|
||||
using UnityEngine.Rendering.Universal;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Rukhanka
|
||||
{
|
||||
public class AnimationCullingConfig: MonoBehaviour
|
||||
{
|
||||
[Tooltip("Add all cameras that should be used for visibility calculation")]
|
||||
public Camera[] cullingCameras;
|
||||
[Tooltip("Add all shadow casting lights for proper shadow occlusion calculation")]
|
||||
public Light[] shadowCastingLights;
|
||||
[Tooltip("Use editor scene view as culling camera")]
|
||||
public bool addEditorSceneCamera = true;
|
||||
|
||||
#if HDRP_10_0_0_OR_NEWER
|
||||
[HideInInspector]
|
||||
public HDShadowSettings shadowSettings;
|
||||
#elif URP_10_0_0_OR_NEWER
|
||||
[HideInInspector]
|
||||
public UniversalRenderPipelineAsset urpAsset;
|
||||
#endif
|
||||
|
||||
public bool drawCullingVolumes;
|
||||
public Color cullingVolumeColor = Color.blue;
|
||||
public bool drawSceneBoundingBoxes;
|
||||
public Color visibleChunkColor = Color.green;
|
||||
public Color invisibleChunkColor = Color.red;
|
||||
public Color visibleRendererColor = Color.white;
|
||||
public Color invisibleRendererColor = Color.red;
|
||||
|
||||
public static AnimationCullingConfig Instance { get; private set; }
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (Instance != null)
|
||||
throw new Exception($"There is more then single AnimationCullingConfig in scene!");
|
||||
|
||||
foreach (var l in shadowCastingLights)
|
||||
{
|
||||
if (l == null) continue;
|
||||
|
||||
if (l.shadows == LightShadows.None)
|
||||
Debug.LogWarning($"Animation Culling Config: Light '{l.name}' does not casting shadows. It is meaningless to account it for culling calculation.");
|
||||
}
|
||||
|
||||
#if HDRP_10_0_0_OR_NEWER
|
||||
var volumes = FindObjectsByType<Volume>(FindObjectsSortMode.None);
|
||||
foreach (var v in volumes)
|
||||
{
|
||||
if (!v.isGlobal) continue;
|
||||
if (v.sharedProfile.TryGet(out shadowSettings))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
#elif URP_10_0_0_OR_NEWER
|
||||
urpAsset = (UniversalRenderPipelineAsset)GraphicsSettings.currentRenderPipeline;
|
||||
#endif
|
||||
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Update()
|
||||
{
|
||||
float shadowDistance = 0;
|
||||
|
||||
#if HDRP_10_0_0_OR_NEWER
|
||||
if (shadowSettings == null)
|
||||
return;
|
||||
shadowDistance = shadowSettings.maxShadowDistance.value;
|
||||
#elif URP_10_0_0_OR_NEWER
|
||||
if (urpAsset == null)
|
||||
return;
|
||||
shadowDistance = urpAsset.shadowDistance;
|
||||
#endif
|
||||
|
||||
foreach (var l in shadowCastingLights)
|
||||
{
|
||||
if (l == null || l.type != LightType.Directional) continue;
|
||||
// Need to update shadow range according to shadow settings
|
||||
l.range = shadowDistance;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
Instance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2573637d14a0c34488e43cbfb7c74236
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 298480
|
||||
packageName: Rukhanka Animation System 2
|
||||
packageVersion: 2.9.0
|
||||
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Culling/AnimationCullingConfig.cs
|
||||
uploadId: 897522
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Rendering;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Rukhanka
|
||||
{
|
||||
public struct AnimationCullingContext: IComponentData, IDisposable
|
||||
{
|
||||
public NativeList<float4> cullingPlanes;
|
||||
public NativeList<int2> cullingVolumePlaneRanges;
|
||||
public NativeList<LODGroupExtensions.LODParams> lodAffectors;
|
||||
|
||||
#if RUKHANKA_DEBUG_INFO
|
||||
public bool drawCullingVolumes;
|
||||
public uint cullingVolumeColor;
|
||||
|
||||
public bool drawSceneBoundingBoxes;
|
||||
public uint visibleChunkColor;
|
||||
public uint invisibleChunkColor;
|
||||
public uint visibleRendererColor;
|
||||
public uint invisibleRendererColor;
|
||||
#endif
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
cullingPlanes.Dispose();
|
||||
cullingVolumePlaneRanges.Dispose();
|
||||
lodAffectors.Dispose();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
internal void AddCullingPlanes(NativeArray<float4> planes)
|
||||
{
|
||||
if (planes.Length == 0)
|
||||
return;
|
||||
|
||||
var volumePlaneRanges = new int2(cullingPlanes.Length, planes.Length);
|
||||
cullingVolumePlaneRanges.Add(volumePlaneRanges);
|
||||
cullingPlanes.AddRange(planes);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
internal void AddLODAffector(AnimationCullingContextUpdateSystem.CullingCameraData ccd, float lodBias)
|
||||
{
|
||||
var lp = new LODGroupExtensions.LODParams()
|
||||
{
|
||||
cameraPos = ccd.pos,
|
||||
orthosize = ccd.orthographicSize,
|
||||
distanceScale = CalculateDistanceScale(ccd.fieldOfView, lodBias, ccd.isOrthographic, ccd.orthographicSize),
|
||||
isOrtho = ccd.isOrthographic
|
||||
};
|
||||
lodAffectors.Add(lp);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
float CalculateDistanceScale(float fov, float globalLodBias, bool isOrtho, float orthoSize)
|
||||
{
|
||||
float rv;
|
||||
if (isOrtho)
|
||||
{
|
||||
rv = 2.0f * orthoSize / globalLodBias;
|
||||
}
|
||||
else
|
||||
{
|
||||
var halfAngle = math.tan(math.radians(fov * 0.5f));
|
||||
rv = 2.0f * halfAngle / globalLodBias;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a28be9e97595a9149a02bba33792b217
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 298480
|
||||
packageName: Rukhanka Animation System 2
|
||||
packageVersion: 2.9.0
|
||||
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Culling/AnimationCullingContextSingleton.cs
|
||||
uploadId: 897522
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
#if !RUKHANKA_NO_DEBUG_DRAWER
|
||||
using Rukhanka.DebugDrawer;
|
||||
#endif
|
||||
using Rukhanka.Toolbox;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
#if RUKHANKA_WITH_NETCODE
|
||||
using Unity.NetCode;
|
||||
#endif
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Rukhanka
|
||||
{
|
||||
[DisableAutoCreation]
|
||||
[UpdateAfter(typeof(FillAnimationsFromControllerSystem))]
|
||||
public partial class AnimationCullingContextUpdateSystem: SystemBase
|
||||
{
|
||||
internal struct CullingCameraData
|
||||
{
|
||||
public float3 pos;
|
||||
public float3 viewDir;
|
||||
public float4x4 cullingMatrix;
|
||||
public float fieldOfView;
|
||||
public bool isOrthographic;
|
||||
public float orthographicSize;
|
||||
}
|
||||
|
||||
internal struct LightData
|
||||
{
|
||||
public float4 posOrDir;
|
||||
public float range;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected override void OnCreate()
|
||||
{
|
||||
#if RUKHANKA_WITH_NETCODE
|
||||
bool isServer = World.IsServer();
|
||||
if (isServer)
|
||||
Enabled = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
var acc = AnimationCullingConfig.Instance;
|
||||
if (acc == null)
|
||||
return;
|
||||
|
||||
if (!SystemAPI.TryGetSingletonRW<AnimationCullingContext>(out var actx))
|
||||
{
|
||||
var newContext = new AnimationCullingContext();
|
||||
newContext.cullingPlanes = new (32, Allocator.Persistent);
|
||||
newContext.cullingVolumePlaneRanges = new (32, Allocator.Persistent);
|
||||
newContext.lodAffectors = new (32, Allocator.Persistent);
|
||||
EntityManager.CreateSingleton(newContext, "Rukhanka.AnimationCullingContextSingleton");
|
||||
actx = SystemAPI.GetSingletonRW<AnimationCullingContext>();
|
||||
}
|
||||
|
||||
var cullingCameras = new NativeList<CullingCameraData>(acc.cullingCameras.Length, CheckedStateRef.WorldUpdateAllocator);
|
||||
foreach (var cullingCam in acc.cullingCameras)
|
||||
{
|
||||
AddCullingCamera(cullingCam, ref cullingCameras);
|
||||
}
|
||||
|
||||
var shadowCastingLights = new NativeList<LightData>(acc.shadowCastingLights.Length, CheckedStateRef.WorldUpdateAllocator);
|
||||
foreach (var l in acc.shadowCastingLights)
|
||||
{
|
||||
AddShadowCastingLight(l, ref shadowCastingLights);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (acc.addEditorSceneCamera)
|
||||
{
|
||||
var sceneCam = SceneView.lastActiveSceneView?.camera;
|
||||
AddCullingCamera(sceneCam, ref cullingCameras);
|
||||
}
|
||||
#endif
|
||||
|
||||
Dependency = BuildCullingContext(cullingCameras, shadowCastingLights, ref actx.ValueRW, acc, Dependency);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AddShadowCastingLight(Light l, ref NativeList<LightData> shadowCastingLights)
|
||||
{
|
||||
if (l == null || l.shadows == LightShadows.None || !l.isActiveAndEnabled) return;
|
||||
|
||||
var lt = l.transform;
|
||||
var ld = new LightData()
|
||||
{
|
||||
posOrDir = l.type == LightType.Directional ? new float4(-lt.forward, 0) : new float4(lt.position, 1),
|
||||
range = l.range,
|
||||
};
|
||||
shadowCastingLights.Add(ld);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AddCullingCamera(Camera cam, ref NativeList<CullingCameraData> cullingCameras)
|
||||
{
|
||||
if (cam == null) return;
|
||||
|
||||
var camTransform = cam.transform;
|
||||
var ccd = new CullingCameraData()
|
||||
{
|
||||
pos = camTransform.position,
|
||||
viewDir = camTransform.forward,
|
||||
cullingMatrix = cam.cullingMatrix,
|
||||
fieldOfView = cam.fieldOfView,
|
||||
isOrthographic = cam.orthographic,
|
||||
orthographicSize = cam.orthographicSize
|
||||
};
|
||||
cullingCameras.Add(ccd);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
JobHandle BuildCullingContext(NativeList<CullingCameraData> cullingCameras, NativeList<LightData> shadowCastingLights, ref AnimationCullingContext actx, AnimationCullingConfig acc, JobHandle dependsOn)
|
||||
{
|
||||
#if (RUKHANKA_DEBUG_INFO && !RUKHANKA_NO_DEBUG_DRAWER)
|
||||
SystemAPI.TryGetSingletonRW<Drawer>(out var dd);
|
||||
#endif
|
||||
|
||||
var buildCullingContextJob = new BuildCullingContextJob()
|
||||
{
|
||||
cullingCameras = cullingCameras.AsArray(),
|
||||
shadowCastingLights = shadowCastingLights.AsArray(),
|
||||
lodBias = QualitySettings.lodBias,
|
||||
actx = actx,
|
||||
#if (RUKHANKA_DEBUG_INFO && !RUKHANKA_NO_DEBUG_DRAWER)
|
||||
dd = dd.ValueRW,
|
||||
#endif
|
||||
};
|
||||
|
||||
var rv = buildCullingContextJob.Schedule(dependsOn);
|
||||
|
||||
#if (RUKHANKA_DEBUG_INFO && !RUKHANKA_NO_DEBUG_DRAWER)
|
||||
actx.invisibleChunkColor = ColorTools.ToUint(acc.invisibleChunkColor);
|
||||
actx.visibleChunkColor = ColorTools.ToUint(acc.visibleChunkColor);
|
||||
actx.invisibleRendererColor = ColorTools.ToUint(acc.invisibleRendererColor);
|
||||
actx.visibleRendererColor = ColorTools.ToUint(acc.visibleRendererColor);
|
||||
actx.drawSceneBoundingBoxes = acc.drawSceneBoundingBoxes;
|
||||
|
||||
actx.drawCullingVolumes = acc.drawCullingVolumes;
|
||||
actx.cullingVolumeColor = ColorTools.ToUint(acc.cullingVolumeColor);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
if (SystemAPI.TryGetSingleton<AnimationCullingContext>(out var actx))
|
||||
{
|
||||
actx.Dispose();
|
||||
EntityManager.DestroyEntity(SystemAPI.GetSingletonEntity<AnimationCullingContext>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b13e4736832aacd4b8bc21c586cb54c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 298480
|
||||
packageName: Rukhanka Animation System 2
|
||||
packageVersion: 2.9.0
|
||||
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Culling/AnimationCullingContextUpdateSystem.cs
|
||||
uploadId: 897522
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
using Rukhanka.Toolbox;
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
|
||||
#if !RUKHANKA_NO_DEBUG_DRAWER
|
||||
using Rukhanka.DebugDrawer;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Rukhanka
|
||||
{
|
||||
public partial class AnimationCullingContextUpdateSystem
|
||||
{
|
||||
|
||||
[BurstCompile]
|
||||
struct BuildCullingContextJob: IJob
|
||||
{
|
||||
[ReadOnly]
|
||||
public NativeArray<CullingCameraData> cullingCameras;
|
||||
[ReadOnly]
|
||||
public NativeArray<LightData> shadowCastingLights;
|
||||
|
||||
public float lodBias;
|
||||
public AnimationCullingContext actx;
|
||||
|
||||
#if (RUKHANKA_DEBUG_INFO && !RUKHANKA_NO_DEBUG_DRAWER)
|
||||
public Drawer dd;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void Execute()
|
||||
{
|
||||
actx.cullingPlanes.Clear();
|
||||
actx.cullingVolumePlaneRanges.Clear();
|
||||
actx.lodAffectors.Clear();
|
||||
|
||||
foreach (var cm in cullingCameras)
|
||||
{
|
||||
var frustum = FrustumVolume.MakeCullingCameraFrustum(cm);
|
||||
actx.AddLODAffector(cm, lodBias);
|
||||
|
||||
var i = 0;
|
||||
for (; i < shadowCastingLights.Length; ++i)
|
||||
{
|
||||
var l = shadowCastingLights[i];
|
||||
var cullingPlanes = MakeShadowVolume(frustum, l, cm.pos);
|
||||
actx.AddCullingPlanes(cullingPlanes);
|
||||
}
|
||||
|
||||
// In case of no lights add input frustum as culling planes
|
||||
if (i == 0)
|
||||
{
|
||||
actx.AddCullingPlanes(frustum.planes);
|
||||
|
||||
#if (RUKHANKA_DEBUG_INFO && !RUKHANKA_NO_DEBUG_DRAWER)
|
||||
if (actx.drawCullingVolumes)
|
||||
frustum.DrawWireOutline(dd, actx.cullingVolumeColor);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NativeArray<float4> MakeShadowVolume(FrustumVolume frustum, LightData l, float3 cameraPos)
|
||||
{
|
||||
var rv = new NativeList<float4>(16, Allocator.Temp);
|
||||
var lightDir = l.posOrDir.xyz;
|
||||
var nearShadowPlane = float4.zero;
|
||||
|
||||
// For infinite (directional) lights
|
||||
if (l.posOrDir.w == 0)
|
||||
{
|
||||
// Project hull points onto light vector and pick maximum distance
|
||||
var shadowDist = l.range;
|
||||
for (var i = 0; i < frustum.points.Length; ++i)
|
||||
{
|
||||
var fp = frustum.points[i];
|
||||
var cameraRelativePos = fp - cameraPos;
|
||||
var projPos = math.dot(cameraRelativePos, lightDir) * lightDir;
|
||||
// Ignore points that lie behind camera
|
||||
var d = math.dot(lightDir, cameraRelativePos);
|
||||
if (d > 0)
|
||||
shadowDist = math.max(math.length(projPos), shadowDist);
|
||||
}
|
||||
|
||||
// Make "near" shadow plane
|
||||
var nearShadowPlanePoint = cameraPos + lightDir * shadowDist;
|
||||
nearShadowPlane = MathUtils.BuildPlaneFromNormalAndPoint(-lightDir, nearShadowPlanePoint);
|
||||
rv.Add(nearShadowPlane);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip entire calculation if light sphere is not visible or light inside view frustum
|
||||
var distanceToLight = frustum.GetMinimumDistanceToPoint(l.posOrDir.xyz);
|
||||
if (distanceToLight < -l.range || distanceToLight >= 0)
|
||||
{
|
||||
#if (RUKHANKA_DEBUG_INFO && ! RUKHANKA_NO_DEBUG_DRAWER)
|
||||
if (actx.drawCullingVolumes)
|
||||
frustum.DrawWireOutline(dd, actx.cullingVolumeColor);
|
||||
#endif
|
||||
|
||||
return frustum.planes;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < FrustumVolume.frustumEdgeIndices.Length; ++i)
|
||||
{
|
||||
var fep = FrustumVolume.frustumEdgeIndices[i];
|
||||
var ep = fep.zw;
|
||||
var pts = fep.xy;
|
||||
|
||||
var p0 = frustum.planes[ep.x];
|
||||
var p1 = frustum.planes[ep.y];
|
||||
|
||||
var d0 = math.dot(p0, l.posOrDir);
|
||||
var d1 = math.dot(p1, l.posOrDir);
|
||||
|
||||
// This is a silhouette edge
|
||||
if (d0 * d1 < 0)
|
||||
{
|
||||
var pt0 = frustum.points[pts.x];
|
||||
var pt1 = frustum.points[pts.y];
|
||||
|
||||
var planeNormal = math.cross(l.posOrDir.xyz - pt0 * l.posOrDir.w, pt1 - pt0);
|
||||
|
||||
var m = math.lengthsq(planeNormal);
|
||||
if (m > math.EPSILON)
|
||||
{
|
||||
planeNormal *= math.rcp(math.sqrt(m));
|
||||
if (math.dot(frustum.middlePoint - pt0, planeNormal) < 0)
|
||||
planeNormal *= -1;
|
||||
var d = -math.dot(planeNormal, pt0);
|
||||
var plane = new float4(planeNormal, d);
|
||||
rv.Add(plane);
|
||||
}
|
||||
|
||||
#if (RUKHANKA_DEBUG_INFO && !RUKHANKA_NO_DEBUG_DRAWER)
|
||||
if (actx.drawCullingVolumes)
|
||||
{
|
||||
if (l.posOrDir.w == 0)
|
||||
{
|
||||
float3 ip0 = 0;
|
||||
MathUtils.PlaneLineIntersection(pt0, lightDir, nearShadowPlane, ref ip0);
|
||||
|
||||
float3 ip1 = 0;
|
||||
MathUtils.PlaneLineIntersection(pt1, lightDir, nearShadowPlane, ref ip1);
|
||||
|
||||
dd.DrawLine(ip0, pt0, actx.cullingVolumeColor);
|
||||
dd.DrawLine(pt0, pt1, actx.cullingVolumeColor);
|
||||
dd.DrawLine(pt1, ip1, actx.cullingVolumeColor);
|
||||
dd.DrawLine(ip1, ip0, actx.cullingVolumeColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
dd.DrawLine(pt0, pt1, actx.cullingVolumeColor);
|
||||
dd.DrawLine(l.posOrDir.xyz, pt1, actx.cullingVolumeColor);
|
||||
dd.DrawLine(l.posOrDir.xyz, pt0, actx.cullingVolumeColor);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if (RUKHANKA_DEBUG_INFO && ! RUKHANKA_NO_DEBUG_DRAWER)
|
||||
else if (d0 > 0 && actx.drawCullingVolumes)
|
||||
{
|
||||
// Draw edge with light facing planes
|
||||
var pt0 = frustum.points[pts.x];
|
||||
var pt1 = frustum.points[pts.y];
|
||||
dd.DrawLine(pt0, pt1, actx.cullingVolumeColor);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
AddExistingLightFacingEdges(l.posOrDir, frustum.planes, ref rv);
|
||||
|
||||
return rv.AsArray();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AddExistingLightFacingEdges(float4 lightPos, NativeArray<float4> planes, ref NativeList<float4> outPlanes)
|
||||
{
|
||||
for (var i = 0; i < planes.Length; ++i)
|
||||
{
|
||||
var pln = planes[i];
|
||||
if (math.dot(pln, lightPos) > 0)
|
||||
{
|
||||
outPlanes.Add(pln);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19986fdaa7bc0ef4b8683d0b63b19ff6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 298480
|
||||
packageName: Rukhanka Animation System 2
|
||||
packageVersion: 2.9.0
|
||||
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Culling/AnimationCullingContextUpdateSystem_Jobs.cs
|
||||
uploadId: 897522
|
||||
@@ -0,0 +1,93 @@
|
||||
#if !RUKHANKA_NO_DEBUG_DRAWER
|
||||
using Rukhanka.DebugDrawer;
|
||||
#endif
|
||||
|
||||
using Unity.Burst;
|
||||
using Unity.Entities;
|
||||
using Unity.Rendering;
|
||||
using UnityEngine;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Rukhanka
|
||||
{
|
||||
|
||||
[DisableAutoCreation]
|
||||
[UpdateAfter(typeof(AnimationCullingContextUpdateSystem))]
|
||||
partial struct AnimationCullingSystem: ISystem
|
||||
{
|
||||
EntityQuery cullAnimationTagQuery;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
[BurstCompile]
|
||||
public void OnCreate(ref SystemState ss)
|
||||
{
|
||||
cullAnimationTagQuery = SystemAPI.QueryBuilder()
|
||||
.WithAll<CullAnimationsTag>()
|
||||
.WithOptions(EntityQueryOptions.IgnoreComponentEnabledState)
|
||||
.Build();
|
||||
|
||||
ss.RequireForUpdate(cullAnimationTagQuery);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState ss)
|
||||
{
|
||||
if (!SystemAPI.TryGetSingleton<AnimationCullingContext>(out var actx))
|
||||
{
|
||||
if (!cullAnimationTagQuery.IsEmptyIgnoreFilter)
|
||||
{
|
||||
Debug.LogError($"Animation culling config is absent on scene, but some entities request animation culling functionality. <a href=\"https://docs.rukhanka.com/Optimizing%20Rukhanka/animation_frustum_culling#animation-culling-environment-setup\">Please properly configure the culling environment!</a>");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var resetCullingStateJob = new ResetAnimationCullingJob()
|
||||
{
|
||||
cullAnimationsTypeHandle = SystemAPI.GetComponentTypeHandle<CullAnimationsTag>()
|
||||
};
|
||||
|
||||
var resetCullingStateJH = resetCullingStateJob.ScheduleParallel(cullAnimationTagQuery, ss.Dependency);
|
||||
|
||||
var wrbTypeHandle = SystemAPI.GetComponentTypeHandle<WorldRenderBounds>(true);
|
||||
var chunkWrbTypeHandle = SystemAPI.GetComponentTypeHandle<ChunkWorldRenderBounds>(true);
|
||||
var cullAnimationsTagLookup = SystemAPI.GetComponentLookup<CullAnimationsTag>();
|
||||
var skinnedMeshTypeHandle = SystemAPI.GetComponentTypeHandle<SkinnedMeshRendererComponent>(true);
|
||||
|
||||
var cullAnimationsJob = new CullAnimationsJob()
|
||||
{
|
||||
actx = actx,
|
||||
wrbTypeHandle = wrbTypeHandle,
|
||||
chunkWrbTypeHandle = chunkWrbTypeHandle,
|
||||
cullAnimationsTagLookup = cullAnimationsTagLookup,
|
||||
asmTypeHandle = skinnedMeshTypeHandle
|
||||
};
|
||||
|
||||
var cullQuery = SystemAPI.QueryBuilder()
|
||||
.WithAllChunkComponent<ChunkWorldRenderBounds>()
|
||||
.WithAll<WorldRenderBounds, SkinnedMeshRendererComponent>()
|
||||
.Build();
|
||||
|
||||
ss.Dependency = cullAnimationsJob.ScheduleParallel(cullQuery, resetCullingStateJH);
|
||||
|
||||
#if (RUKHANKA_DEBUG_INFO && !RUKHANKA_NO_DEBUG_DRAWER)
|
||||
SystemAPI.TryGetSingletonRW<Drawer>(out var dd);
|
||||
|
||||
var debugDrawJob = new DebugDrawRendererBoundingBoxes()
|
||||
{
|
||||
dd = dd.ValueRW,
|
||||
actx = actx,
|
||||
wrbTypeHandle = wrbTypeHandle,
|
||||
chunkWrbTypeHandle = chunkWrbTypeHandle,
|
||||
cullAnimationsTagLookup = cullAnimationsTagLookup,
|
||||
asmTypeHandle = skinnedMeshTypeHandle
|
||||
};
|
||||
|
||||
ss.Dependency = debugDrawJob.ScheduleParallel(cullQuery, ss.Dependency);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7c6913d44171114eaffae78da19800c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 298480
|
||||
packageName: Rukhanka Animation System 2
|
||||
packageVersion: 2.9.0
|
||||
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Culling/AnimationCullingSystem.cs
|
||||
uploadId: 897522
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
#if !RUKHANKA_NO_DEBUG_DRAWER
|
||||
using Rukhanka.DebugDrawer;
|
||||
#endif
|
||||
|
||||
using Unity.Burst;
|
||||
using Unity.Burst.Intrinsics;
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Rendering;
|
||||
using Unity.Collections;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Rukhanka
|
||||
{
|
||||
partial struct AnimationCullingSystem
|
||||
{
|
||||
|
||||
[BurstCompile]
|
||||
struct CullAnimationsJob: IJobChunk
|
||||
{
|
||||
[ReadOnly]
|
||||
public AnimationCullingContext actx;
|
||||
[ReadOnly]
|
||||
public ComponentTypeHandle<ChunkWorldRenderBounds> chunkWrbTypeHandle;
|
||||
[ReadOnly]
|
||||
public ComponentTypeHandle<WorldRenderBounds> wrbTypeHandle;
|
||||
[ReadOnly]
|
||||
public ComponentTypeHandle<SkinnedMeshRendererComponent> asmTypeHandle;
|
||||
|
||||
[NativeDisableParallelForRestriction]
|
||||
public ComponentLookup<CullAnimationsTag> cullAnimationsTagLookup;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
|
||||
{
|
||||
var cee = new ChunkEntityEnumerator(useEnabledMask, chunkEnabledMask, chunk.Count);
|
||||
|
||||
var chunkWRB = chunk.GetChunkComponentData(ref chunkWrbTypeHandle);
|
||||
var isChunkVisible = IsAxisAlignedBoxVisible(chunkWRB.Value, actx);
|
||||
|
||||
var wrbArr = chunk.GetNativeArray(ref wrbTypeHandle);
|
||||
var asmArr = chunk.GetNativeArray(ref asmTypeHandle);
|
||||
|
||||
while (cee.NextEntityIndex(out var i) && isChunkVisible)
|
||||
{
|
||||
var arEntity = asmArr[i].animatedRigEntity;
|
||||
|
||||
if (arEntity == Entity.Null || !cullAnimationsTagLookup.HasComponent(arEntity))
|
||||
continue;
|
||||
|
||||
var cullAnimsAlreadyDisabled = !cullAnimationsTagLookup.IsComponentEnabled(arEntity);
|
||||
if (cullAnimsAlreadyDisabled)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var wrb = wrbArr[i].Value;
|
||||
var isVisible = IsAxisAlignedBoxVisible(wrb, actx);
|
||||
cullAnimationsTagLookup.SetComponentEnabled(arEntity, !isVisible);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
internal static bool IsAxisAlignedBoxVisible(in AABB wrb, in AnimationCullingContext actx)
|
||||
{
|
||||
var isVisible = false;
|
||||
for (var j = 0; j < actx.cullingVolumePlaneRanges.Length && !isVisible; ++j)
|
||||
{
|
||||
var planeRange = actx.cullingVolumePlaneRanges[j];
|
||||
var isVisibleForPlaneRange = true;
|
||||
for (var i = 0; i < planeRange.y && isVisibleForPlaneRange; ++i)
|
||||
{
|
||||
var pln = actx.cullingPlanes[i + planeRange.x];
|
||||
var rg0 = pln.xyz * wrb.Extents;
|
||||
var rg = math.dot(math.abs(rg0), 1);
|
||||
var distance = math.dot(pln, new float4(wrb.Center, 1));
|
||||
isVisibleForPlaneRange = distance > -rg;
|
||||
}
|
||||
isVisible |= isVisibleForPlaneRange;
|
||||
}
|
||||
return isVisible;
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================================//
|
||||
|
||||
#if !RUKHANKA_NO_DEBUG_DRAWER
|
||||
[BurstCompile]
|
||||
struct DebugDrawRendererBoundingBoxes: IJobChunk
|
||||
{
|
||||
public Drawer dd;
|
||||
|
||||
[ReadOnly]
|
||||
public AnimationCullingContext actx;
|
||||
[ReadOnly]
|
||||
public ComponentTypeHandle<ChunkWorldRenderBounds> chunkWrbTypeHandle;
|
||||
[ReadOnly]
|
||||
public ComponentTypeHandle<WorldRenderBounds> wrbTypeHandle;
|
||||
[ReadOnly]
|
||||
public ComponentTypeHandle<SkinnedMeshRendererComponent> asmTypeHandle;
|
||||
|
||||
[NativeDisableParallelForRestriction]
|
||||
public ComponentLookup<CullAnimationsTag> cullAnimationsTagLookup;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
|
||||
{
|
||||
#if RUKHANKA_DEBUG_INFO
|
||||
var cee = new ChunkEntityEnumerator(useEnabledMask, chunkEnabledMask, chunk.Count);
|
||||
|
||||
var chunkWRB = chunk.GetChunkComponentData(ref chunkWrbTypeHandle);
|
||||
var isChunkVisible = CullAnimationsJob.IsAxisAlignedBoxVisible(chunkWRB.Value, actx);
|
||||
|
||||
if (actx.drawSceneBoundingBoxes)
|
||||
{
|
||||
var chunkBBColor = isChunkVisible ? actx.visibleChunkColor : actx.invisibleChunkColor;
|
||||
var xformChunk = new RigidTransform(quaternion.identity, chunkWRB.Value.Center);
|
||||
dd.DrawWireCuboid(chunkWRB.Value.Size, chunkBBColor, xformChunk);
|
||||
}
|
||||
|
||||
var wrbArr = chunk.GetNativeArray(ref wrbTypeHandle);
|
||||
var asmArr = chunk.GetNativeArray(ref asmTypeHandle);
|
||||
|
||||
while (cee.NextEntityIndex(out var i) && isChunkVisible)
|
||||
{
|
||||
var arEntity = asmArr[i].animatedRigEntity;
|
||||
|
||||
if (arEntity == Entity.Null || !cullAnimationsTagLookup.HasComponent(arEntity))
|
||||
continue;
|
||||
|
||||
var isEntityVisible = !cullAnimationsTagLookup.IsComponentEnabled(arEntity);
|
||||
|
||||
var wrb = wrbArr[i].Value;
|
||||
if (actx.drawSceneBoundingBoxes)
|
||||
{
|
||||
var cl = isEntityVisible ? actx.visibleRendererColor : actx.invisibleRendererColor;
|
||||
var xform = new RigidTransform(quaternion.identity, wrb.Center);
|
||||
dd.DrawWireCuboid(wrb.Size, cl, xform);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//=================================================================================================================//
|
||||
|
||||
[BurstCompile]
|
||||
struct ResetAnimationCullingJob: IJobChunk
|
||||
{
|
||||
public ComponentTypeHandle<CullAnimationsTag> cullAnimationsTypeHandle;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
|
||||
{
|
||||
chunk.SetComponentEnabledForAll(ref cullAnimationsTypeHandle, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 725330bc4d248af4ca096c867a7fb86d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 298480
|
||||
packageName: Rukhanka Animation System 2
|
||||
packageVersion: 2.9.0
|
||||
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Culling/AnimationCullingSystem_Jobs.cs
|
||||
uploadId: 897522
|
||||
@@ -0,0 +1,153 @@
|
||||
#if !RUKHANKA_NO_DEBUG_DRAWER
|
||||
using Rukhanka.DebugDrawer;
|
||||
#endif
|
||||
|
||||
using Rukhanka.Toolbox;
|
||||
using Unity.Collections;
|
||||
using Unity.Mathematics;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Rukhanka
|
||||
{
|
||||
internal struct FrustumVolume
|
||||
{
|
||||
public NativeArray<float4> planes;
|
||||
public NativeArray<float3> points;
|
||||
public float3 middlePoint;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Frustum corners in NDC
|
||||
static readonly float4[] frustumCorners =
|
||||
{
|
||||
// Near plane
|
||||
new float4(-1, -1, -1, 1),
|
||||
new float4(-1, +1, -1, 1),
|
||||
new float4(+1, +1, -1, 1),
|
||||
new float4(+1, -1, -1, 1),
|
||||
// Far plane
|
||||
new float4(-1, -1, +1, 1),
|
||||
new float4(-1, +1, +1, 1),
|
||||
new float4(+1, +1, +1, 1),
|
||||
new float4(+1, -1, +1, 1),
|
||||
};
|
||||
|
||||
// Point (xy) and plane (zw) indices used to form edges
|
||||
public static readonly int4[] frustumEdgeIndices =
|
||||
{
|
||||
// Sides
|
||||
new int4(2, 6, 0, 2),
|
||||
new int4(1, 5, 1, 2),
|
||||
new int4(0, 4, 1, 3),
|
||||
new int4(3, 7, 0, 3),
|
||||
|
||||
// Near plane edges
|
||||
new int4(1, 2, 5, 2),
|
||||
new int4(2, 3, 5, 0),
|
||||
new int4(0, 3, 5, 3),
|
||||
new int4(0, 1, 5, 1),
|
||||
|
||||
// Far plane edges
|
||||
new int4(5, 6, 4, 2),
|
||||
new int4(6, 7, 4, 0),
|
||||
new int4(4, 7, 4, 3),
|
||||
new int4(4, 5, 4, 1),
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static FrustumVolume Allocate()
|
||||
{
|
||||
var rv = new FrustumVolume()
|
||||
{
|
||||
points = new (frustumCorners.Length, Allocator.Temp),
|
||||
planes = new (6, Allocator.Temp),
|
||||
};
|
||||
return rv;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !RUKHANKA_NO_DEBUG_DRAWER
|
||||
public void DrawWireOutline(Drawer dd, uint color)
|
||||
{
|
||||
for (var j = 0; j < frustumEdgeIndices.Length; ++j)
|
||||
{
|
||||
var e = frustumEdgeIndices[j].xy;
|
||||
var p0 = points[e.x];
|
||||
var p1 = points[e.y];
|
||||
dd.DrawLine(p0, p1, color);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public float GetMinimumDistanceToPoint(float3 pt)
|
||||
{
|
||||
var distance = float.MaxValue;
|
||||
var pt4 = new float4(pt, 1);
|
||||
foreach (var pln in planes)
|
||||
{
|
||||
var d = math.dot(pln, pt4);
|
||||
distance = math.min(distance, d);
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static FrustumVolume MakeCullingCameraFrustum(AnimationCullingContextUpdateSystem.CullingCameraData ccd)
|
||||
{
|
||||
var rv = Allocate();
|
||||
|
||||
var cullingMatrix = math.inverse(ccd.cullingMatrix);
|
||||
|
||||
// Build point list
|
||||
for (var i = 0; i < frustumCorners.Length; ++i)
|
||||
{
|
||||
var vtx = math.mul(cullingMatrix, frustumCorners[i]);
|
||||
vtx /= vtx.w;
|
||||
rv.points[i] = vtx.xyz;
|
||||
}
|
||||
|
||||
var mp = math.mul(cullingMatrix, new float4(0, 0, 0.1f, 1));
|
||||
rv.middlePoint = mp.xyz / mp.w;
|
||||
|
||||
// Build planes
|
||||
if (ccd.isOrthographic)
|
||||
{
|
||||
// +X
|
||||
rv.planes[0] = MathUtils.BuildPlaneFromThreePoints(rv.points[3], rv.points[7], rv.points[2]);
|
||||
// -X
|
||||
rv.planes[1] = MathUtils.BuildPlaneFromThreePoints(rv.points[1], rv.points[5], rv.points[0]);
|
||||
// +Y
|
||||
rv.planes[2] = MathUtils.BuildPlaneFromThreePoints(rv.points[2], rv.points[6], rv.points[1]);
|
||||
// -Y
|
||||
rv.planes[3] = MathUtils.BuildPlaneFromThreePoints(rv.points[0], rv.points[4], rv.points[3]);
|
||||
// +Z
|
||||
rv.planes[4] = MathUtils.BuildPlaneFromThreePoints(rv.points[5], rv.points[6], rv.points[4]);
|
||||
// -Z
|
||||
rv.planes[5] = MathUtils.BuildPlaneFromThreePoints(rv.points[0], rv.points[2], rv.points[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// +X
|
||||
rv.planes[0] = MathUtils.BuildPlaneFromThreePoints(ccd.pos, rv.points[7], rv.points[6]);
|
||||
// -X
|
||||
rv.planes[1] = MathUtils.BuildPlaneFromThreePoints(ccd.pos, rv.points[5], rv.points[4]);
|
||||
// +Y
|
||||
rv.planes[2] = MathUtils.BuildPlaneFromThreePoints(ccd.pos, rv.points[6], rv.points[5]);
|
||||
// -Y
|
||||
rv.planes[3] = MathUtils.BuildPlaneFromThreePoints(ccd.pos, rv.points[4], rv.points[7]);
|
||||
// +Z
|
||||
rv.planes[4] = MathUtils.BuildPlaneFromNormalAndPoint(-ccd.viewDir, rv.points[5]);
|
||||
// -Z
|
||||
rv.planes[5] = MathUtils.BuildPlaneFromNormalAndPoint(ccd.viewDir, rv.points[0]);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd54353fe71e7634782b86662178035a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 298480
|
||||
packageName: Rukhanka Animation System 2
|
||||
packageVersion: 2.9.0
|
||||
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Culling/FrustumVolume.cs
|
||||
uploadId: 897522
|
||||
Reference in New Issue
Block a user