You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
4.6 KiB
C#
121 lines
4.6 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace FluffyGroomingTool {
|
|
[Serializable]
|
|
public class HairStrandLayer : ICloneable {
|
|
[SerializeField, HideInInspector] public HairStrand[] layerHairStrands = new HairStrand[0];
|
|
[SerializeField, HideInInspector] public ClumpModifierLayer[] clumpsModifiers = new ClumpModifierLayer[0];
|
|
[SerializeField, HideInInspector] public CardMeshProperties cardMeshProperties = new CardMeshProperties();
|
|
[SerializeField, HideInInspector] public VerletSimulationSettings verletSimulationSettings;
|
|
[SerializeField, HideInInspector] public float sourceMeshNormalToStrandNormalPercent = -1;
|
|
[SerializeField, HideInInspector] public string layerName;
|
|
private Mesh _cardMesh;
|
|
public ComputeBuffer hairStrandsBuffer;
|
|
|
|
public ComputeShader meshBakerComputeShader;
|
|
private MeshBaker meshBaker;
|
|
|
|
public Mesh CardMesh {
|
|
get {
|
|
if (_cardMesh == null || meshBaker == null) {
|
|
recreateCardMesh();
|
|
}
|
|
|
|
return _cardMesh;
|
|
}
|
|
}
|
|
|
|
public void recreateCardMesh() {
|
|
meshBaker?.dispose();
|
|
_cardMesh = FurMeshCreator.CreateHairCard(cardMeshProperties);
|
|
if (meshBakerComputeShader == null)
|
|
meshBakerComputeShader = Resources.Load<ComputeShader>(ShaderID.MESH_BAKER_FULL_CS_NAME);
|
|
meshBaker = new MeshBaker(_cardMesh, meshBakerComputeShader);
|
|
}
|
|
|
|
public bool hasClumps() {
|
|
return clumpsModifiers.Length > 0;
|
|
}
|
|
|
|
public ComputeBuffer getLastClumpModifierBuffer() {
|
|
return getLastClumpModifier().clumpsPositionBuffer;
|
|
}
|
|
|
|
public ComputeBuffer getLastClumpAttractionBuffer() {
|
|
return getLastClumpModifier().clumpAttractionBuffer;
|
|
}
|
|
|
|
public ClumpModifierLayer getLastClumpModifier() {
|
|
return clumpsModifiers[clumpsModifiers.Length - 1];
|
|
}
|
|
|
|
public void recreateHairStrandsBuffers() {
|
|
hairStrandsBuffer?.Dispose();
|
|
hairStrandsBuffer = new ComputeBuffer(layerHairStrands.Length, HairStrandStruct.size());
|
|
|
|
var instancedHairCardsStruct = layerHairStrands.ToList().Select(it => it.convertToStruct()).ToArray();
|
|
|
|
hairStrandsBuffer.SetData(instancedHairCardsStruct);
|
|
}
|
|
|
|
public void copyValuesFromComputeBufferToNativeObject() {
|
|
if (hairStrandsBuffer != null) AsyncGPUReadback.Request(hairStrandsBuffer, onCompleteReadback);
|
|
}
|
|
|
|
|
|
private void onCompleteReadback(AsyncGPUReadbackRequest request) {
|
|
if (request.hasError) {
|
|
Debug.Log("GPU readback error detected for hairStrandsBuffer.");
|
|
return;
|
|
}
|
|
|
|
var hairStrandStructs = request.ToPersistentArray<HairStrandStruct>();
|
|
new Thread(() => {
|
|
layerHairStrands = hairStrandStructs.Select(it => it.convertToObject()).ToArray();
|
|
hairStrandStructs.Dispose();
|
|
}).Start();
|
|
}
|
|
|
|
public void dispose() {
|
|
hairStrandsBuffer?.Dispose();
|
|
hairStrandsBuffer = null;
|
|
meshBaker?.dispose();
|
|
|
|
foreach (var clumpsModifier in clumpsModifiers) {
|
|
clumpsModifier.dispose();
|
|
}
|
|
}
|
|
|
|
public void passCardMeshPropertiesToComputeShader(int kernel, ComputeShader computeShader) {
|
|
if (hairStrandsBuffer == null) { //May have been disposed by another objects onDisable
|
|
recreateHairStrandsBuffers();
|
|
recreateCardMesh();
|
|
}
|
|
|
|
computeShader.SetBuffer(kernel, "hairStrandsBuffer", hairStrandsBuffer);
|
|
computeShader.SetBuffer(kernel, "cardMesh", meshBaker.bakedMesh);
|
|
computeShader.SetInt("cardMeshVerticesCount", CardMesh.vertexCount);
|
|
}
|
|
|
|
public HairStrandLayer setupCardShape(GroomContainer groomContainer) {
|
|
if (groomContainer.isUsingCardPreset) {
|
|
cardMeshProperties.shapeCurve = AnimationCurve.Linear(0, 1, 1, 1);
|
|
cardMeshProperties.cardSubdivisionsY = 3;
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
public object Clone() {
|
|
return new HairStrandLayer() {
|
|
layerHairStrands = layerHairStrands,
|
|
clumpsModifiers = clumpsModifiers.Select(e => (ClumpModifierLayer) e.Clone()).ToArray(),
|
|
cardMeshProperties = (CardMeshProperties) cardMeshProperties.Clone()
|
|
};
|
|
}
|
|
}
|
|
} |