果然是在开玩笑。
等后面上传git代码
代码,用ComputeShader来运算,虽然不用遍历运算了,但是还要遍历赋值。感觉没淘到多少便宜.
using UnityEngine;
public class MeshDeformerInputByCS : MonoBehaviour
{
float force = 1f;
float forceOffset = 0.1f;//用于产生力的角度
void Update()
{
if (Input.GetMouseButton(0))
{
HandleInInput();
}
if (Input.GetMouseButtonUp(0) )
{
HandleEndPression();
}
}
void HandleInInput()
{
Ray inputRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(inputRay, out hit))
{
MeshDeformerByCS deformer = hit.collider.GetComponent();
if (deformer)
{
Vector3 point = hit.point;//World space
point += hit.normal * forceOffset;//world space 用于计算受力的方向
deformer.AddInDeformingForce(point, force);
}
}
}
void HandleEndPression()
{
Ray inputRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(inputRay, out hit))
{
MeshDeformerByCS deformer = hit.collider.GetComponent();
if (deformer)
{
deformer.ClearVertexVelocities();
}
}
}
}
using UnityEngine;
struct DBuffer
{
public Vector3 vertexPos;//作用的mesh顶点
}
[RequireComponent(typeof(MeshFilter))]
public class MeshDeformerByCS : MonoBehaviour
{
public ComputeShader shader;
private ComputeBuffer buffer;
int bufferArrayLength;
private Mesh deformingMesh;
Vector3[] originalVertices, displacedVertices;
Vector3[] vertexVelocities;
new MeshCollider collider;
public float AlphaOfVertexes = 0.5f;
Vector3 lastPoint = Vector3.zero;
float uniformScale = 1f;
#region public
public void AddInDeformingForce(Vector3 point, float force)
{
point = transform.InverseTransformPoint(point);
if (lastPoint == Vector3.zero)
lastPoint = point;
else if (lastPoint != Vector3.zero && lastPoint != point)
{
lastPoint = point;
ClearVertexVelocities();
}
Dispatch(force, point);
//根据Shader返回的buffer数据更新物体信息
DBuffer[] values = new DBuffer[bufferArrayLength];
buffer.GetData(values);
for (int i = 0; i < bufferArrayLength; i++)
{
displacedVertices[i] = values[i].vertexPos;
}
deformingMesh.vertices = displacedVertices;
deformingMesh.RecalculateNormals();
collider.sharedMesh = deformingMesh;
}
public void ReCover()
{
vertexVelocities = new Vector3[originalVertices.Length];
deformingMesh.vertices = originalVertices;
deformingMesh.RecalculateNormals();
}
public void ClearVertexVelocities()
{
vertexVelocities = new Vector3[originalVertices.Length];
}
#endregion
#region unity
void Start()
{
deformingMesh = transform.GetComponent().mesh;
bufferArrayLength = deformingMesh.vertexCount;
originalVertices = deformingMesh.vertices;
displacedVertices = new Vector3[originalVertices.Length];
for (int i = 0; i < originalVertices.Length; i++)
{
displacedVertices[i] = originalVertices[i];
}
vertexVelocities = new Vector3[originalVertices.Length];
collider = GetComponent();
CreateBuffer();
}
#endregion
void CreateBuffer()
{
//count数组的长度(等于2个三维的积 2x2x1 * 2x2x1),40是结构体的字节长度
buffer = new ComputeBuffer(bufferArrayLength, 12);
DBuffer[] values = new DBuffer[bufferArrayLength];
for (int i = 0; i < bufferArrayLength; i++)
{
DBuffer m = new DBuffer();
SetStruct(ref m, displacedVertices[i]);
values[i] = m;
}
// 初始化结构体并赋予buffer
buffer.SetData(values);
}
void SetStruct(ref DBuffer m, Vector3 vertexPos)
{
m.vertexPos = vertexPos;
}
void Dispatch(float force, Vector3 pressPos)
{
//必须分配足够多的线程
//int groupx = (int)Mathf.Pow(bufferArrayLength / 256, 1 / 3);
shader.SetFloat("force", force);
shader.SetVector("pressPos", pressPos);
shader.SetInt("groupx", 8);
shader.SetInt("groupy", 8);
int kid = shader.FindKernel("CSMain");
shader.SetBuffer(kid, "dBuffer", buffer);
shader.Dispatch(kid, 8, 8, 8);
}
#region private
#endregion
void ReleaseBuffer()
{
buffer.Release();
}
private void OnDisable()
{
ReleaseBuffer();
}
}
// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CSMain
struct DeformBuffer
{
float3 vertexPos;//作用的mesh顶点
};
RWStructuredBuffer dBuffer;
float force;//力
float3 pressPos;//力的作用点
uint groupx;
uint groupy;
[numthreads(8,8,8)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
int index = id.x + id.y * groupx * 8 + id.z * groupx * groupy * 8 * 8;
float3 pointToVertex = dBuffer[index].vertexPos -pressPos;
float attenuatedForce = force / (1 +length(pointToVertex));
float3 Velocity0 = normalize( pointToVertex) * attenuatedForce * 0.01f;
dBuffer[index].vertexPos += Velocity0;
}