From 32cd873deccdfc4526bc46e4da635a540cef4821 Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Sat, 30 May 2020 22:44:44 -0700 Subject: [PATCH] Rework bounds culling and colliders --- .../Plugins/ConformalDecals.dll | 4 +- Source/ConformalDecals/ConformalDecals.csproj | 3 + .../ConformalDecals/ModuleConformalDecal.cs | 93 +++++++++++++++---- Source/ConformalDecals/ProjectionTarget.cs | 28 +++--- 4 files changed, 95 insertions(+), 33 deletions(-) diff --git a/Distribution/GameData/ConformalDecals/Plugins/ConformalDecals.dll b/Distribution/GameData/ConformalDecals/Plugins/ConformalDecals.dll index d94dfc0..7f26384 100644 --- a/Distribution/GameData/ConformalDecals/Plugins/ConformalDecals.dll +++ b/Distribution/GameData/ConformalDecals/Plugins/ConformalDecals.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73cd94acb4687058e5a69522168bcd31d6ce65a9ba7be7cffe4fa8d76a1ca0fc -size 23552 +oid sha256:938eed012fe2148a4a3dc8a0f534677b7ebecd62e38d43b7b7b44c62b280bc29 +size 25088 diff --git a/Source/ConformalDecals/ConformalDecals.csproj b/Source/ConformalDecals/ConformalDecals.csproj index 3d846fd..2109274 100644 --- a/Source/ConformalDecals/ConformalDecals.csproj +++ b/Source/ConformalDecals/ConformalDecals.csproj @@ -44,6 +44,9 @@ dlls\UnityEngine.CoreModule.dll + + dlls\UnityEngine.PhysicsModule.dll + diff --git a/Source/ConformalDecals/ModuleConformalDecal.cs b/Source/ConformalDecals/ModuleConformalDecal.cs index 466e9eb..22865c0 100644 --- a/Source/ConformalDecals/ModuleConformalDecal.cs +++ b/Source/ConformalDecals/ModuleConformalDecal.cs @@ -6,8 +6,9 @@ using UnityEngine; namespace ConformalDecals { public class ModuleConformalDecal : PartModule { - [KSPField] public string decalPreviewTransform = ""; - [KSPField] public string decalModelTransform = ""; + [KSPField] public string decalPreviewTransform = ""; + [KSPField] public string decalModelTransform = ""; + [KSPField] public string decalProjectorTransform = ""; [KSPField(guiName = "Scale", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "F2", guiUnits = "m"), UI_FloatRange(minValue = 0.05f, maxValue = 4f, stepIncrement = 0.05f)] @@ -22,8 +23,12 @@ namespace ConformalDecals { [KSPField] public MaterialPropertyCollection materialProperties; - [KSPField] public Transform decalPreviewTransformRef; - [KSPField] public Transform decalModelTransformRef; + [KSPField] public Transform decalPreviewTransformRef; + [KSPField] public Transform decalModelTransformRef; + [KSPField] public Transform decalProjectorTransformRef; + [KSPField] public Transform modelTransformRef; + [KSPField] public Transform colliderTransformRef; + [KSPField] public BoxCollider colliderRef; private List _targets; @@ -50,11 +55,34 @@ namespace ConformalDecals { } // find preview object references + modelTransformRef = part.transform.Find("model"); + decalPreviewTransformRef = part.FindModelTransform(decalPreviewTransform); if (decalPreviewTransformRef == null) throw new FormatException("Missing decal preview reference"); - decalModelTransformRef = part.FindModelTransform(decalModelTransform); - if (decalModelTransformRef == null) throw new FormatException("Missing decal mesh reference"); + if (String.IsNullOrEmpty(decalModelTransform)) { + decalModelTransformRef = decalPreviewTransformRef; + } + else { + decalModelTransformRef = part.FindModelTransform(decalModelTransform); + if (decalModelTransformRef == null) throw new FormatException("Missing decal mesh reference"); + } + + if (String.IsNullOrEmpty(decalProjectorTransform)) { + decalProjectorTransformRef = modelTransformRef; + } + else { + decalProjectorTransformRef = part.FindModelTransform(decalProjectorTransform); + if (decalProjectorTransform == null) throw new FormatException("Missing decal projector reference"); + } + + colliderTransformRef = new GameObject("Decal Collider").transform; + colliderTransformRef.parent = modelTransformRef; + colliderTransformRef.position = decalProjectorTransformRef.position; + colliderTransformRef.rotation = decalProjectorTransformRef.rotation; + colliderTransformRef.gameObject.SetActive(false); + + colliderRef = colliderTransformRef.gameObject.AddComponent(); } catch (Exception e) { this.LogException("Exception parsing partmodule", e); @@ -71,6 +99,7 @@ namespace ConformalDecals { if ((state & StartState.Editor) != 0) { // setup OnTweakEvent for scale and depth fields in editor GameEvents.onEditorPartEvent.Add(OnEditorEvent); + GameEvents.onVariantApplied.Add(OnVariantApplied); Fields[nameof(scale)].uiControlEditor.onFieldChanged = OnTweakEvent; Fields[nameof(depth)].uiControlEditor.onFieldChanged = OnTweakEvent; } @@ -80,16 +109,27 @@ namespace ConformalDecals { } } - public void OnDisable() { + private void OnDestroy() { + GameEvents.onEditorPartEvent.Remove(OnEditorEvent); + GameEvents.onVariantApplied.Remove(OnVariantApplied); + // remove from preCull delegate Camera.onPreCull -= Render; } + public void OnTweakEvent(BaseField field, object obj) { // scale or depth values have been changed, so update the projection matrix for each target Project(); } + public void OnVariantApplied(Part eventPart, PartVariant variant) { + if (IsAttached && eventPart == part.parent) { + Detach(); + Attach(); + } + } + public void OnEditorEvent(ConstructionEventType eventType, Part eventPart) { if (eventPart != this.part) return; switch (eventType) { @@ -100,7 +140,7 @@ namespace ConformalDecals { Detach(); break; case ConstructionEventType.PartOffsetting: - case ConstructionEventType.PartRotated: + case ConstructionEventType.PartRotating: case ConstructionEventType.PartDragging: Project(); break; @@ -127,6 +167,9 @@ namespace ConformalDecals { // find all valid renderers var renderers = part.parent.FindModelComponents(); foreach (var renderer in renderers) { + // skip disabled renderers + if (renderer.gameObject.activeInHierarchy == false) continue; + var meshFilter = renderer.GetComponent(); if (meshFilter == null) continue; // object has a meshRenderer with no filter, invalid var mesh = meshFilter.mesh; @@ -143,20 +186,23 @@ namespace ConformalDecals { } // hide preview model - //decalModelTransformRef.gameObject.SetActive(false); + decalModelTransformRef.gameObject.SetActive(false); + + // enable decal collider + colliderTransformRef.gameObject.SetActive(true); // add to preCull delegate Camera.onPreCull += Render; + + Project(); } public void Detach() { - if (IsAttached) { - this.LogError("Detach function called but part still has parent!"); - return; - } - // unhide preview model - //decalModelTransformRef.gameObject.SetActive(true); + decalModelTransformRef.gameObject.SetActive(true); + + // enable decal collider + colliderTransformRef.gameObject.SetActive(false); // remove from preCull delegate Camera.onPreCull -= Render; @@ -166,18 +212,27 @@ namespace ConformalDecals { public void Project() { if (!IsAttached) return; + float width = scale; + float height = scale * aspectRatio; // generate orthogonal matrix scale values - _orthoMatrix[0, 0] = 1 / scale; - _orthoMatrix[1, 1] = 1 / (aspectRatio * scale); + _orthoMatrix[0, 0] = 1 / width; + _orthoMatrix[1, 1] = 1 / height; _orthoMatrix[2, 2] = 1 / depth; // generate bounding box for decal for culling purposes _decalBounds.center = Vector3.forward * (depth / 2); - _decalBounds.extents = new Vector3(scale / 2, aspectRatio * scale / 2, depth / 2); + _decalBounds.extents = new Vector3(width / 2, height / 2, depth / 2); + + // rescale preview model + decalModelTransformRef.localScale = new Vector3(width, height, (width + height) / 2); + + // assign dimensions to collider + colliderRef.center = _decalBounds.center; + colliderRef.size = _decalBounds.size; // project to each target object foreach (var target in _targets) { - target.Project(_orthoMatrix, _decalBounds, this.transform); + target.Project(_orthoMatrix, colliderRef.bounds, decalProjectorTransformRef); } } diff --git a/Source/ConformalDecals/ProjectionTarget.cs b/Source/ConformalDecals/ProjectionTarget.cs index 826585b..61213cd 100644 --- a/Source/ConformalDecals/ProjectionTarget.cs +++ b/Source/ConformalDecals/ProjectionTarget.cs @@ -46,24 +46,28 @@ namespace ConformalDecals { } public void Project(Matrix4x4 orthoMatrix, Bounds projectorBounds, Transform projector) { - var projectorToTargetMatrix = target.worldToLocalMatrix * projector.localToWorldMatrix; + var targetBounds = _targetRenderer.bounds; + if (targetBounds.Intersects(projectorBounds)) { + _projectionEnabled = true; + var projectorToTargetMatrix = target.worldToLocalMatrix * projector.localToWorldMatrix; - var projectionMatrix = orthoMatrix * projectorToTargetMatrix.inverse; - var decalNormal = projectorToTargetMatrix.MultiplyVector(Vector3.back).normalized; - var decalTangent = projectorToTargetMatrix.MultiplyVector(Vector3.right).normalized; + var projectionMatrix = orthoMatrix * projectorToTargetMatrix.inverse; + var decalNormal = projectorToTargetMatrix.MultiplyVector(Vector3.back).normalized; + var decalTangent = projectorToTargetMatrix.MultiplyVector(Vector3.right).normalized; - decalMPB.SetMatrix(_projectionMatrixID, projectionMatrix); - decalMPB.SetVector(_decalNormalID, decalNormal); - decalMPB.SetVector(_decalTangentID, decalTangent); - - var targetBounds = new OrientedBounds(target.localToWorldMatrix, _targetRenderer.bounds); - _projectionEnabled = targetBounds.Intersects(projectorBounds); + decalMPB.SetMatrix(_projectionMatrixID, projectionMatrix); + decalMPB.SetVector(_decalNormalID, decalNormal); + decalMPB.SetVector(_decalTangentID, decalTangent); + } + else { + _projectionEnabled = false; + } } public bool Render(Material decalMaterial, MaterialPropertyBlock partMPB, Camera camera) { - if (true) { + if (_projectionEnabled) { decalMPB.SetFloat(PropertyIDs._RimFalloff, partMPB.GetFloat(PropertyIDs._RimFalloff)); - decalMPB.SetColor(PropertyIDs._RimFalloff, partMPB.GetColor(PropertyIDs._RimFalloff)); + decalMPB.SetColor(PropertyIDs._RimColor, partMPB.GetColor(PropertyIDs._RimFalloff)); Graphics.DrawMesh(_targetMesh, target.localToWorldMatrix, decalMaterial, 0, camera, 0, decalMPB, ShadowCastingMode.Off, true);