mirror of
https://github.com/PorktoberRevolution/ReStocked
synced 2024-09-01 17:34:42 +00:00
Cache generated girder meshes for later use
Should help with vessels that have large numbers of launch clamps
This commit is contained in:
parent
1ce483f36b
commit
fd68fe9b10
Binary file not shown.
133
Source/Restock/LaunchClampGirderFactory.cs
Normal file
133
Source/Restock/LaunchClampGirderFactory.cs
Normal file
@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Restock
|
||||
{
|
||||
public class LaunchClampGirderFactory : ScriptableObject
|
||||
{
|
||||
public Mesh girderSegmentMesh;
|
||||
|
||||
[SerializeField] private Mesh[] _girderMeshCache;
|
||||
[SerializeField] private int _maxLength;
|
||||
|
||||
private float _girderSegmentHeight;
|
||||
private bool _girderHasTangents;
|
||||
private bool _girderHasColors;
|
||||
private int _girderVertCount;
|
||||
private int _girderTriCount;
|
||||
|
||||
private int _girderSegments;
|
||||
private List<Vector3> _girderVerts;
|
||||
private List<Vector2> _girderUVs;
|
||||
private List<Vector3> _girderNormals;
|
||||
private List<Vector4> _girderTangents;
|
||||
private List<Color32> _girderColors;
|
||||
private List<int> _girderTris;
|
||||
|
||||
public void Initialize(Mesh girderSegmentMesh, float girderSegmentHeight, int maxLength = 100)
|
||||
{
|
||||
this.girderSegmentMesh = girderSegmentMesh;
|
||||
|
||||
_girderSegmentHeight = girderSegmentHeight;
|
||||
_maxLength = maxLength;
|
||||
_girderMeshCache = new Mesh[maxLength];
|
||||
|
||||
_girderMeshCache[0] = new Mesh();
|
||||
_girderMeshCache[1] = girderSegmentMesh;
|
||||
|
||||
_girderVertCount = girderSegmentMesh.vertexCount;
|
||||
_girderTriCount = girderSegmentMesh.triangles.Length;
|
||||
|
||||
_girderVerts = new List<Vector3>(girderSegmentMesh.vertices);
|
||||
_girderUVs = new List<Vector2>(girderSegmentMesh.uv);
|
||||
_girderNormals = new List<Vector3>(girderSegmentMesh.normals);
|
||||
if (girderSegmentMesh.tangents.Length > 0)
|
||||
{
|
||||
_girderHasTangents = true;
|
||||
_girderTangents = new List<Vector4>(girderSegmentMesh.tangents);
|
||||
}
|
||||
|
||||
if (girderSegmentMesh.colors32.Length > 0)
|
||||
{
|
||||
_girderHasColors = true;
|
||||
_girderColors = new List<Color32>(girderSegmentMesh.colors32);
|
||||
}
|
||||
|
||||
_girderTris = new List<int>(girderSegmentMesh.triangles);
|
||||
_girderSegments = 1;
|
||||
}
|
||||
public Mesh makeGirder(int length)
|
||||
{
|
||||
if (length < 0) length = 0;
|
||||
if (length > _maxLength) length = _maxLength;
|
||||
|
||||
if (_girderMeshCache[length] == null)
|
||||
{
|
||||
Debug.Log("Girder mesh not generated, making it now...");
|
||||
var girderMesh = makeGirderMesh(length);
|
||||
_girderMeshCache[length] = girderMesh;
|
||||
}
|
||||
|
||||
return _girderMeshCache[length];
|
||||
}
|
||||
|
||||
private Mesh makeGirderMesh(int length)
|
||||
{
|
||||
if (length < 1)
|
||||
{
|
||||
return new Mesh();
|
||||
}
|
||||
var girderMesh = new Mesh();
|
||||
if (length > _girderSegments)
|
||||
{
|
||||
for (int i = _girderSegments; i < length ; i++)
|
||||
{
|
||||
var offset = Vector3.down * _girderSegmentHeight * i;
|
||||
var indexOffset = _girderVertCount * i;
|
||||
for (int v = 0; v < _girderVertCount; v++)
|
||||
{
|
||||
_girderVerts.Add(girderSegmentMesh.vertices[v] + offset);
|
||||
}
|
||||
|
||||
_girderNormals.AddRange(girderSegmentMesh.normals);
|
||||
_girderUVs.AddRange(girderSegmentMesh.uv);
|
||||
|
||||
if (_girderHasTangents) _girderTangents.AddRange(girderSegmentMesh.tangents);
|
||||
if (_girderHasColors) _girderColors.AddRange(girderSegmentMesh.colors32);
|
||||
|
||||
for (int t = 0; t < _girderTriCount; t++)
|
||||
{
|
||||
_girderTris.Add(girderSegmentMesh.triangles[t] + indexOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (length < _girderSegments)
|
||||
{
|
||||
var startIndex = length * _girderVertCount;
|
||||
var count = (_girderSegments - length) * _girderVertCount;
|
||||
_girderVerts.RemoveRange(startIndex, count);
|
||||
_girderNormals.RemoveRange(startIndex, count);
|
||||
_girderUVs.RemoveRange(startIndex, count);
|
||||
if (_girderHasTangents) _girderTangents.RemoveRange(startIndex, count);
|
||||
if (_girderHasColors) _girderColors.RemoveRange(startIndex, count);
|
||||
|
||||
_girderTris.RemoveRange(length * _girderTriCount,
|
||||
(_girderSegments - length) * _girderTriCount);
|
||||
}
|
||||
|
||||
girderMesh.SetVertices(_girderVerts);
|
||||
girderMesh.SetNormals(_girderNormals);
|
||||
girderMesh.SetUVs(0, _girderUVs);
|
||||
if (_girderHasTangents) girderMesh.SetTangents(_girderTangents);
|
||||
if (_girderHasColors) girderMesh.SetColors(_girderColors);
|
||||
girderMesh.SetTriangles(_girderTris, 0);
|
||||
|
||||
girderMesh.RecalculateBounds();
|
||||
_girderSegments = length;
|
||||
|
||||
return girderMesh;
|
||||
}
|
||||
}
|
||||
}
|
@ -17,46 +17,54 @@ namespace Restock
|
||||
[KSPField] public string trf_towerYoke_name = "";
|
||||
|
||||
[KSPField] public Mesh girderMesh;
|
||||
[KSPField] public MeshFilter girderMeshFilter;
|
||||
[KSPField] public float girderSegmentHeight;
|
||||
public LaunchClampGirderFactory girderFactory;
|
||||
|
||||
private int _girderSegments;
|
||||
|
||||
private Material _girderMaterial;
|
||||
private Matrix4x4[] _girderMatrices;
|
||||
|
||||
//used by non-instanced fallback girder implementation
|
||||
[KSPField] public bool instancingEnabled = true;
|
||||
[KSPField] public Mesh girderSegmentMesh;
|
||||
|
||||
private List<Vector3> _girderVerts;
|
||||
private List<Vector2> _girderUVs;
|
||||
private List<Vector3> _girderNormals;
|
||||
private List<Vector4> _girderTangents;
|
||||
private List<Color32> _girderColors;
|
||||
private List<int> _girderTris;
|
||||
|
||||
private bool _girderFlightUpdated = false;
|
||||
|
||||
private bool _girderHasTangents = false;
|
||||
private bool _girderHasColors = false;
|
||||
private int _girderVertCount;
|
||||
private int _girderTriCount;
|
||||
private int _girderSegments;
|
||||
[KSPField] public bool instancingEnabled = true;
|
||||
|
||||
public override void OnLoad(ConfigNode node)
|
||||
{
|
||||
towerPivot = part.FindModelTransform(trf_towerPivot_name);
|
||||
towerYoke = part.FindModelTransform(trf_towerYoke_name);
|
||||
towerAnchor = part.FindModelTransform(trf_anchor_name);
|
||||
towerGirder = part.FindModelTransform(trf_towerGirder_name);
|
||||
towerStretch = part.FindModelTransform(trf_towerStretch_name);
|
||||
|
||||
if (!SystemInfo.supportsInstancing)
|
||||
if (!HighLogic.LoadedSceneIsGame)
|
||||
{
|
||||
this.LogWarning("You are using a computer which does not support instancing, " +
|
||||
"falling back to a slower launch clamp implementation");
|
||||
instancingEnabled = false;
|
||||
towerPivot = part.FindModelTransform(trf_towerPivot_name);
|
||||
towerYoke = part.FindModelTransform(trf_towerYoke_name);
|
||||
towerAnchor = part.FindModelTransform(trf_anchor_name);
|
||||
towerGirder = part.FindModelTransform(trf_towerGirder_name);
|
||||
towerStretch = part.FindModelTransform(trf_towerStretch_name);
|
||||
|
||||
girderMeshFilter = towerGirder.GetComponent<MeshFilter>();
|
||||
girderMesh = girderMeshFilter.mesh;
|
||||
|
||||
if (!SystemInfo.supportsInstancing)
|
||||
{
|
||||
this.LogWarning("You are using a computer which does not support instancing, " +
|
||||
"falling back to a slower launch clamp implementation in the editor");
|
||||
instancingEnabled = false;
|
||||
}
|
||||
|
||||
if (girderFactory == null)
|
||||
{
|
||||
//Debug.Log("Making new girder factory...");
|
||||
girderSegmentHeight = Vector3.Distance(towerAnchor.position, towerStretch.position);
|
||||
if (float.IsInfinity(girderSegmentHeight))
|
||||
{
|
||||
girderSegmentHeight = -1f;
|
||||
}
|
||||
|
||||
girderFactory = ScriptableObject.CreateInstance<LaunchClampGirderFactory>();
|
||||
girderFactory.Initialize(girderMesh, girderSegmentHeight, maxSegments);
|
||||
}
|
||||
}
|
||||
|
||||
girderMesh = towerGirder.GetComponent<MeshFilter>().mesh;
|
||||
girderSegmentMesh = Instantiate<Mesh>(girderMesh);
|
||||
_girderSegments = 1;
|
||||
|
||||
base.OnLoad(node);
|
||||
}
|
||||
@ -77,29 +85,6 @@ namespace Restock
|
||||
_girderMaterial = girderRenderer.material;
|
||||
_girderMaterial.enableInstancing = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_girderVertCount = girderSegmentMesh.vertexCount;
|
||||
_girderTriCount = girderSegmentMesh.triangles.Length;
|
||||
|
||||
_girderVerts = new List<Vector3>(girderSegmentMesh.vertices);
|
||||
_girderUVs = new List<Vector2>(girderSegmentMesh.uv);
|
||||
_girderNormals = new List<Vector3>(girderSegmentMesh.normals);
|
||||
if (girderSegmentMesh.tangents.Length > 0)
|
||||
{
|
||||
_girderHasTangents = true;
|
||||
_girderTangents = new List<Vector4>(girderSegmentMesh.tangents);
|
||||
}
|
||||
|
||||
if (girderSegmentMesh.colors32.Length > 0)
|
||||
{
|
||||
_girderHasColors = true;
|
||||
_girderColors = new List<Color32>(girderSegmentMesh.colors32);
|
||||
}
|
||||
|
||||
_girderTris = new List<int>(girderSegmentMesh.triangles);
|
||||
_girderSegments = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void LateUpdate()
|
||||
@ -117,26 +102,27 @@ namespace Restock
|
||||
girderSegments = Math.Min(girderSegments, maxSegments);
|
||||
girderSegments = Math.Max(girderSegments, 0);
|
||||
|
||||
if (HighLogic.LoadedSceneIsEditor){
|
||||
if (HighLogic.LoadedSceneIsEditor)
|
||||
{
|
||||
if (instancingEnabled)
|
||||
{
|
||||
UpdateGirder(girderSegments);
|
||||
UpdateGirderInstanced(girderSegments);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateGirderFallback(girderSegments);
|
||||
UpdateGirderMesh(girderSegments);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_girderFlightUpdated) return;
|
||||
|
||||
UpdateGirderFallback(girderSegments);
|
||||
|
||||
UpdateGirderMesh(girderSegments);
|
||||
_girderFlightUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGirder(int girderSegments)
|
||||
private void UpdateGirderInstanced(int girderSegments)
|
||||
{
|
||||
var matrix = towerGirder.localToWorldMatrix;
|
||||
var offset = Matrix4x4.Translate(towerGirder.TransformVector(Vector3.down * initialHeight));
|
||||
@ -151,58 +137,11 @@ namespace Restock
|
||||
UnityEngine.Rendering.ShadowCastingMode.On, true, towerGirder.gameObject.layer);
|
||||
}
|
||||
|
||||
private void UpdateGirderFallback(int newGirderSegments)
|
||||
private void UpdateGirderMesh(int girderSegments)
|
||||
{
|
||||
if (newGirderSegments == _girderSegments) return;
|
||||
if (girderSegments == _girderSegments) return;
|
||||
|
||||
if (newGirderSegments > _girderSegments)
|
||||
{
|
||||
for (int i = _girderSegments; i < newGirderSegments; i++)
|
||||
{
|
||||
var offset = Vector3.down * base.initialHeight * i;
|
||||
var indexOffset = _girderVertCount * i;
|
||||
for (int v = 0; v < _girderVertCount; v++)
|
||||
{
|
||||
_girderVerts.Add(girderSegmentMesh.vertices[v] + offset);
|
||||
}
|
||||
|
||||
_girderNormals.AddRange(girderSegmentMesh.normals);
|
||||
_girderUVs.AddRange(girderSegmentMesh.uv);
|
||||
|
||||
if (_girderHasTangents) _girderTangents.AddRange(girderSegmentMesh.tangents);
|
||||
if (_girderHasColors) _girderColors.AddRange(girderSegmentMesh.colors32);
|
||||
|
||||
for (int t = 0; t < _girderTriCount; t++)
|
||||
{
|
||||
_girderTris.Add(girderSegmentMesh.triangles[t] + indexOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (newGirderSegments < _girderSegments)
|
||||
{
|
||||
var startIndex = newGirderSegments * _girderVertCount;
|
||||
var count = (_girderSegments - newGirderSegments) * _girderVertCount;
|
||||
_girderVerts.RemoveRange(startIndex, count);
|
||||
_girderNormals.RemoveRange(startIndex, count);
|
||||
_girderUVs.RemoveRange(startIndex, count);
|
||||
if (_girderHasTangents) _girderTangents.RemoveRange(startIndex, count);
|
||||
if (_girderHasColors) _girderColors.RemoveRange(startIndex, count);
|
||||
|
||||
_girderTris.RemoveRange(newGirderSegments * _girderTriCount,
|
||||
(_girderSegments - newGirderSegments) * _girderTriCount);
|
||||
}
|
||||
|
||||
girderMesh.Clear();
|
||||
|
||||
girderMesh.SetVertices(_girderVerts);
|
||||
girderMesh.SetNormals(_girderNormals);
|
||||
girderMesh.SetUVs(0, _girderUVs);
|
||||
if (_girderHasTangents) girderMesh.SetTangents(_girderTangents);
|
||||
if (_girderHasColors) girderMesh.SetColors(_girderColors);
|
||||
girderMesh.SetTriangles(_girderTris, 0);
|
||||
|
||||
girderMesh.RecalculateBounds();
|
||||
_girderSegments = newGirderSegments;
|
||||
girderMeshFilter.mesh = girderFactory.makeGirder(girderSegments);
|
||||
}
|
||||
}
|
||||
}
|
@ -49,6 +49,7 @@
|
||||
<Compile Include="Constraints\IConstraint.cs" />
|
||||
<Compile Include="Constraints\LookAtConstraint.cs" />
|
||||
<Compile Include="InstallChecker.cs" />
|
||||
<Compile Include="LaunchClampGirderFactory.cs" />
|
||||
<Compile Include="MaterialModifiers\ColorPropertyMaterialModifier.cs" />
|
||||
<Compile Include="MaterialModifiers\FloatPropertyMaterialModifier.cs" />
|
||||
<Compile Include="MaterialModifiers\IMaterialModifier.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user