maint: updated aline

This commit is contained in:
Chris
2025-09-08 17:17:12 -04:00
parent 7a0499f36a
commit 6c1cb44d18
64 changed files with 591 additions and 460 deletions

View File

@@ -108,7 +108,7 @@ namespace Drawing {
///
/// You must do this when you are done with the scope, even if it was never used to actually render anything.
/// The items will stop rendering immediately: the next camera to render will not render the items unless kept alive in some other way.
/// For example items are always rendered at least once.
/// However, items are always rendered at least once.
/// </summary>
public void Dispose () {
if (gizmos.IsAllocated) {
@@ -119,41 +119,7 @@ namespace Drawing {
}
};
/// <summary>
/// Helper for drawing Gizmos in a performant way.
/// This is a replacement for the Unity Gizmos class as that is not very performant
/// when drawing very large amounts of geometry (for example a large grid graph).
/// These gizmos can be persistent, so if the data does not change, the gizmos
/// do not need to be updated.
///
/// How to use
/// - Create a Hasher object and hash whatever data you will be using to draw the gizmos
/// Could be for example the positions of the vertices or something. Just as long as
/// if the gizmos should change, then the hash changes as well.
/// - Check if a cached mesh exists for that hash
/// - If not, then create a Builder object and call the drawing methods until you are done
/// and then call Finalize with a reference to a gizmos class and the hash you calculated before.
/// - Call gizmos.Draw with the hash.
/// - When you are done with drawing gizmos for this frame, call gizmos.FinalizeDraw
///
/// <code>
/// var a = Vector3.zero;
/// var b = Vector3.one;
/// var color = Color.red;
/// var hasher = DrawingData.Hasher.Create(this);
///
/// hasher.Add(a);
/// hasher.Add(b);
/// hasher.Add(color);
/// var gizmos = DrawingManager.instance.gizmos;
/// if (!gizmos.Draw(hasher)) {
/// using (var builder = gizmos.GetBuilder(hasher)) {
/// // Ideally something very complex, not just a single line
/// builder.Line(a, b, color);
/// }
/// }
/// </code>
/// </summary>
/// <summary>Helper for drawing Gizmos in a performant way</summary>
public class DrawingData {
/// <summary>Combines hashes into a single hash value</summary>
public struct Hasher : IEquatable<Hasher> {
@@ -161,6 +127,7 @@ namespace Drawing {
public static Hasher NotSupplied => new Hasher { hash = ulong.MaxValue };
[System.Obsolete("Use the constructor instead")]
public static Hasher Create<T>(T init) {
var h = new Hasher();
@@ -168,17 +135,17 @@ namespace Drawing {
return h;
}
/// <summary>
/// Includes the given data in the final hash.
/// You can call this as many times as you want.
/// </summary>
public void Add<T>(T hash) {
// Just a regular hash function. The + 12289 is to make sure that hashing zeros doesn't just produce a zero (and generally that hashing one X doesn't produce a hash of X)
// (with a struct we can't provide default initialization)
this.hash = (1572869UL * this.hash) ^ (ulong)hash.GetHashCode() + 12289;
}
public ulong Hash {
get {
return hash;
}
}
public readonly ulong Hash => hash;
public override int GetHashCode () {
return (int)hash;
@@ -208,7 +175,11 @@ namespace Drawing {
JobHandle buildJob, splitterJob;
public List<MeshWithType> meshes;
public bool isValid => type != Type.Invalid;
public bool isValid {
get {
return type != Type.Invalid;
}
}
public struct CapturedState {
public Matrix4x4 matrix;
@@ -615,6 +586,18 @@ namespace Drawing {
public void Submit (DrawingData gizmos) {
if (state != State.Initialized) throw new System.InvalidOperationException();
#if !UNITY_EDITOR
if (meta.isGizmos) {
// Gizmos are never drawn in standalone builds.
// Draw.Line, and similar draw commands, will already have been removed in standalone builds,
// but if users use e.g. Draw.editor directly, then the commands will be added to the command buffer.
// For performance we can just discard the whole buffer here.
Release();
return;
}
#endif
unsafe {
// There are about 128 buffers we need to check and it's faster to do that using Burst
if (meshes.Count == 0 && !AnyBuffersWrittenToInvoke((UnsafeAppendBuffer*)commandBuffers.GetUnsafeReadOnlyPtr(), commandBuffers.Length)) {
@@ -825,6 +808,8 @@ namespace Drawing {
Stack<int> freeSlots;
Stack<List<int> > freeLists;
public bool isEmpty => data == null || freeSlots.Count == data.Length;
public int memoryUsage {
get {
int sum = 0;
@@ -1346,7 +1331,7 @@ namespace Drawing {
/// </summary>
public bool Draw (Hasher hasher, RedrawScope scope) {
if (hasher.Equals(Hasher.NotSupplied)) throw new System.ArgumentException("Invalid hash value");
processedData.SetCustomScope(hasher, scope);
if (scope.isValid) processedData.SetCustomScope(hasher, scope);
return processedData.SetVersion(hasher, version);
}
@@ -1549,6 +1534,9 @@ namespace Drawing {
/// <summary>Call after all <see cref="Draw"/> commands for the frame have been done to draw everything.</summary>
/// <param name="allowCameraDefault">Indicates if built-in command builders and custom ones without a custom CommandBuilder.cameraTargets should render to this camera.</param>
public void Render (Camera cam, bool allowGizmos, CommandBufferWrapper commandBuffer, bool allowCameraDefault) {
// Early out when there's nothing to render
if (processedData.isEmpty) return;
LoadMaterials();
// Warn if the materials could not be found
@@ -1559,9 +1547,6 @@ namespace Drawing {
return;
}
var planes = frustrumPlanes;
GeometryUtility.CalculateFrustumPlanes(cam, planes);
if (!cameraVersions.TryGetValue(cam, out Range cameraRenderingRange)) {
cameraRenderingRange = new Range { start = int.MinValue, end = int.MinValue };
}
@@ -1616,71 +1601,78 @@ namespace Drawing {
processedData.CollectMeshes(cameraRenderingRange.start, meshes, cam, allowGizmos, allowCameraDefault);
processedData.PoolDynamicMeshes(this);
MarkerCollectMeshes.End();
MarkerSortMeshes.Begin();
// Note that a stable sort is required as some meshes may have the same sorting index
// but those meshes will have a consistent ordering between them in the list
meshes.Sort(meshSorter);
MarkerSortMeshes.End();
int colorID = Shader.PropertyToID("_Color");
int colorFadeID = Shader.PropertyToID("_FadeColor");
var solidBaseColor = new Color(1, 1, 1, settings.solidOpacity);
var solidFadeColor = new Color(1, 1, 1, settings.solidOpacityBehindObjects);
var lineBaseColor = new Color(1, 1, 1, settings.lineOpacity);
var lineFadeColor = new Color(1, 1, 1, settings.lineOpacityBehindObjects);
var textBaseColor = new Color(1, 1, 1, settings.textOpacity);
var textFadeColor = new Color(1, 1, 1, settings.textOpacityBehindObjects);
// Early out if nothing is being rendered
if (meshes.Count > 0) {
MarkerSortMeshes.Begin();
// Note that a stable sort is required as some meshes may have the same sorting index
// but those meshes will have a consistent ordering between them in the list
meshes.Sort(meshSorter);
MarkerSortMeshes.End();
// The meshes list is already sorted as first surfaces, then lines, then text
for (int i = 0; i < meshes.Count;) {
int meshEndIndex = i+1;
var tp = meshes[i].type & MeshType.BaseType;
while (meshEndIndex < meshes.Count && (meshes[meshEndIndex].type & MeshType.BaseType) == tp) meshEndIndex++;
var planes = frustrumPlanes;
GeometryUtility.CalculateFrustumPlanes(cam, planes);
Material mat;
customMaterialProperties.Clear();
switch (tp) {
case MeshType.Solid:
mat = surfaceMaterial;
customMaterialProperties.SetColor(colorID, solidBaseColor);
customMaterialProperties.SetColor(colorFadeID, solidFadeColor);
break;
case MeshType.Lines:
mat = lineMaterial;
customMaterialProperties.SetColor(colorID, lineBaseColor);
customMaterialProperties.SetColor(colorFadeID, lineFadeColor);
break;
case MeshType.Text:
mat = fontData.material;
customMaterialProperties.SetColor(colorID, textBaseColor);
customMaterialProperties.SetColor(colorFadeID, textFadeColor);
break;
default:
throw new System.InvalidOperationException("Invalid mesh type");
}
int colorID = Shader.PropertyToID("_Color");
int colorFadeID = Shader.PropertyToID("_FadeColor");
var solidBaseColor = new Color(1, 1, 1, settings.solidOpacity);
var solidFadeColor = new Color(1, 1, 1, settings.solidOpacityBehindObjects);
var lineBaseColor = new Color(1, 1, 1, settings.lineOpacity);
var lineFadeColor = new Color(1, 1, 1, settings.lineOpacityBehindObjects);
var textBaseColor = new Color(1, 1, 1, settings.textOpacity);
var textFadeColor = new Color(1, 1, 1, settings.textOpacityBehindObjects);
for (int pass = 0; pass < mat.passCount; pass++) {
for (int j = i; j < meshEndIndex; j++) {
var mesh = meshes[j];
if ((mesh.type & MeshType.Custom) != 0) {
// This mesh type may have a matrix set. So we need to handle that
if (GeometryUtility.TestPlanesAABB(planes, TransformBoundingBox(mesh.matrix, mesh.mesh.bounds))) {
// Custom meshes may have different colors
customMaterialProperties.SetColor(colorID, solidBaseColor * mesh.color);
commandBuffer.DrawMesh(mesh.mesh, mesh.matrix, mat, 0, pass, customMaterialProperties);
customMaterialProperties.SetColor(colorID, solidBaseColor);
// The meshes list is already sorted as first surfaces, then lines, then text
for (int i = 0; i < meshes.Count;) {
int meshEndIndex = i+1;
var tp = meshes[i].type & MeshType.BaseType;
while (meshEndIndex < meshes.Count && (meshes[meshEndIndex].type & MeshType.BaseType) == tp) meshEndIndex++;
Material mat;
customMaterialProperties.Clear();
switch (tp) {
case MeshType.Solid:
mat = surfaceMaterial;
customMaterialProperties.SetColor(colorID, solidBaseColor);
customMaterialProperties.SetColor(colorFadeID, solidFadeColor);
break;
case MeshType.Lines:
mat = lineMaterial;
customMaterialProperties.SetColor(colorID, lineBaseColor);
customMaterialProperties.SetColor(colorFadeID, lineFadeColor);
break;
case MeshType.Text:
mat = fontData.material;
customMaterialProperties.SetColor(colorID, textBaseColor);
customMaterialProperties.SetColor(colorFadeID, textFadeColor);
break;
default:
throw new System.InvalidOperationException("Invalid mesh type");
}
for (int pass = 0; pass < mat.passCount; pass++) {
for (int j = i; j < meshEndIndex; j++) {
var mesh = meshes[j];
if ((mesh.type & MeshType.Custom) != 0) {
// This mesh type may have a matrix set. So we need to handle that
if (GeometryUtility.TestPlanesAABB(planes, TransformBoundingBox(mesh.matrix, mesh.mesh.bounds))) {
// Custom meshes may have different colors
customMaterialProperties.SetColor(colorID, solidBaseColor * mesh.color);
commandBuffer.DrawMesh(mesh.mesh, mesh.matrix, mat, 0, pass, customMaterialProperties);
customMaterialProperties.SetColor(colorID, solidBaseColor);
}
} else if (GeometryUtility.TestPlanesAABB(planes, mesh.mesh.bounds)) {
// This mesh is drawn with an identity matrix
commandBuffer.DrawMesh(mesh.mesh, Matrix4x4.identity, mat, 0, pass, customMaterialProperties);
}
} else if (GeometryUtility.TestPlanesAABB(planes, mesh.mesh.bounds)) {
// This mesh is drawn with an identity matrix
commandBuffer.DrawMesh(mesh.mesh, Matrix4x4.identity, mat, 0, pass, customMaterialProperties);
}
}
i = meshEndIndex;
}
i = meshEndIndex;
meshes.Clear();
}
meshes.Clear();
}
cameraVersions[cam] = cameraRenderingRange;