673 lines
21 KiB
C#
673 lines
21 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace AmplifyMotion
|
|
{
|
|
internal class SkinnedState : MotionState
|
|
{
|
|
private SkinnedMeshRenderer m_renderer;
|
|
|
|
private int m_boneCount;
|
|
|
|
private Transform[] m_boneTransforms;
|
|
|
|
private Matrix4x4[] m_bones;
|
|
|
|
private int m_weightCount;
|
|
|
|
private int[] m_boneIndices;
|
|
|
|
private float[] m_boneWeights;
|
|
|
|
private int m_vertexCount;
|
|
|
|
private Vector4[] m_baseVertices;
|
|
|
|
private Vector3[] m_prevVertices;
|
|
|
|
private Vector3[] m_currVertices;
|
|
|
|
private int m_gpuBoneTexWidth;
|
|
|
|
private int m_gpuBoneTexHeight;
|
|
|
|
private int m_gpuVertexTexWidth;
|
|
|
|
private int m_gpuVertexTexHeight;
|
|
|
|
private Material m_gpuSkinDeformMat;
|
|
|
|
private Color[] m_gpuBoneData;
|
|
|
|
private Texture2D m_gpuBones;
|
|
|
|
private Texture2D m_gpuBoneIndices;
|
|
|
|
private Texture2D[] m_gpuBaseVertices;
|
|
|
|
private RenderTexture m_gpuPrevVertices;
|
|
|
|
private RenderTexture m_gpuCurrVertices;
|
|
|
|
private Mesh m_clonedMesh;
|
|
|
|
private Matrix4x4 m_worldToLocalMatrix;
|
|
|
|
private Matrix4x4 m_prevLocalToWorld;
|
|
|
|
private Matrix4x4 m_currLocalToWorld;
|
|
|
|
private MaterialDesc[] m_sharedMaterials;
|
|
|
|
private ManualResetEvent m_asyncUpdateSignal;
|
|
|
|
private bool m_asyncUpdateTriggered;
|
|
|
|
private bool m_starting;
|
|
|
|
private bool m_wasVisible;
|
|
|
|
private bool m_useFallback;
|
|
|
|
private bool m_useGPU;
|
|
|
|
public SkinnedState(AmplifyMotionCamera owner, AmplifyMotionObjectBase obj)
|
|
: base(owner, obj)
|
|
{
|
|
m_renderer = m_obj.GetComponent<SkinnedMeshRenderer>();
|
|
}
|
|
|
|
internal override void Initialize()
|
|
{
|
|
Transform[] bones = m_renderer.bones;
|
|
m_useFallback = bones == null || bones.Length == 0;
|
|
if (!m_useFallback)
|
|
{
|
|
m_useGPU = m_owner.Instance.CanUseGPU;
|
|
}
|
|
base.Initialize();
|
|
m_vertexCount = m_renderer.sharedMesh.vertexCount;
|
|
m_prevVertices = new Vector3[m_vertexCount];
|
|
m_currVertices = new Vector3[m_vertexCount];
|
|
m_clonedMesh = new Mesh();
|
|
if (!m_useFallback)
|
|
{
|
|
if (m_renderer.quality == SkinQuality.Auto)
|
|
{
|
|
m_weightCount = (int)QualitySettings.blendWeights;
|
|
}
|
|
else
|
|
{
|
|
m_weightCount = (int)m_renderer.quality;
|
|
}
|
|
m_boneTransforms = m_renderer.bones;
|
|
m_boneCount = m_renderer.bones.Length;
|
|
m_bones = new Matrix4x4[m_boneCount];
|
|
Vector4[] baseVertices = new Vector4[m_vertexCount * m_weightCount];
|
|
int[] boneIndices = new int[m_vertexCount * m_weightCount];
|
|
float[] boneWeights = ((m_weightCount <= 1) ? null : new float[m_vertexCount * m_weightCount]);
|
|
if (m_weightCount == 1)
|
|
{
|
|
InitializeBone1(baseVertices, boneIndices);
|
|
}
|
|
else if (m_weightCount == 2)
|
|
{
|
|
InitializeBone2(baseVertices, boneIndices, boneWeights);
|
|
}
|
|
else
|
|
{
|
|
InitializeBone4(baseVertices, boneIndices, boneWeights);
|
|
}
|
|
m_baseVertices = baseVertices;
|
|
m_boneIndices = boneIndices;
|
|
m_boneWeights = boneWeights;
|
|
Mesh sharedMesh = m_renderer.sharedMesh;
|
|
m_clonedMesh.vertices = sharedMesh.vertices;
|
|
m_clonedMesh.normals = sharedMesh.vertices;
|
|
m_clonedMesh.uv = sharedMesh.uv;
|
|
m_clonedMesh.subMeshCount = sharedMesh.subMeshCount;
|
|
for (int i = 0; i < sharedMesh.subMeshCount; i++)
|
|
{
|
|
m_clonedMesh.SetTriangles(sharedMesh.GetTriangles(i), i);
|
|
}
|
|
if (m_useGPU)
|
|
{
|
|
if (!InitializeGPUSkinDeform())
|
|
{
|
|
Debug.LogWarning("[AmplifyMotion] Failed initializing GPU skin deform for object " + m_obj.name + ". Falling back to CPU path.");
|
|
m_useGPU = false;
|
|
}
|
|
else
|
|
{
|
|
m_boneIndices = null;
|
|
m_boneWeights = null;
|
|
m_baseVertices = null;
|
|
m_prevVertices = null;
|
|
m_currVertices = null;
|
|
}
|
|
}
|
|
if (!m_useGPU)
|
|
{
|
|
m_asyncUpdateSignal = new ManualResetEvent(false);
|
|
m_asyncUpdateTriggered = false;
|
|
}
|
|
}
|
|
m_sharedMaterials = ProcessSharedMaterials(m_renderer.sharedMaterials);
|
|
m_wasVisible = false;
|
|
}
|
|
|
|
internal override void Shutdown()
|
|
{
|
|
if (!m_useFallback && !m_useGPU)
|
|
{
|
|
WaitForAsyncUpdate();
|
|
}
|
|
if (m_useGPU)
|
|
{
|
|
ShutdownGPUSkinDeform();
|
|
}
|
|
if (m_clonedMesh != null)
|
|
{
|
|
UnityEngine.Object.Destroy(m_clonedMesh);
|
|
m_clonedMesh = null;
|
|
}
|
|
m_boneTransforms = null;
|
|
m_bones = null;
|
|
m_boneIndices = null;
|
|
m_boneWeights = null;
|
|
m_baseVertices = null;
|
|
m_prevVertices = null;
|
|
m_currVertices = null;
|
|
m_sharedMaterials = null;
|
|
}
|
|
|
|
private bool InitializeGPUSkinDeform()
|
|
{
|
|
bool result = true;
|
|
try
|
|
{
|
|
m_gpuBoneTexWidth = Mathf.NextPowerOfTwo(m_boneCount);
|
|
m_gpuBoneTexHeight = 4;
|
|
m_gpuVertexTexWidth = Mathf.NextPowerOfTwo(Mathf.CeilToInt(Mathf.Sqrt(m_vertexCount)));
|
|
m_gpuVertexTexHeight = Mathf.NextPowerOfTwo(m_vertexCount / m_gpuVertexTexWidth);
|
|
m_gpuSkinDeformMat = new Material(Shader.Find("Hidden/Amplify Motion/GPUSkinDeform"))
|
|
{
|
|
hideFlags = HideFlags.DontSave
|
|
};
|
|
m_gpuBones = new Texture2D(m_gpuBoneTexWidth, m_gpuBoneTexHeight, TextureFormat.RGBAFloat, false, true);
|
|
m_gpuBones.filterMode = FilterMode.Point;
|
|
m_gpuBoneData = new Color[m_gpuBoneTexWidth * m_gpuBoneTexHeight];
|
|
UpdateBonesGPU();
|
|
TextureFormat textureFormat = TextureFormat.RHalf;
|
|
textureFormat = ((m_weightCount != 2) ? textureFormat : TextureFormat.RGHalf);
|
|
textureFormat = ((m_weightCount != 4) ? textureFormat : TextureFormat.RGBAHalf);
|
|
m_gpuBoneIndices = new Texture2D(m_gpuVertexTexWidth, m_gpuVertexTexHeight, textureFormat, false, true);
|
|
m_gpuBoneIndices.filterMode = FilterMode.Point;
|
|
m_gpuBoneIndices.wrapMode = TextureWrapMode.Clamp;
|
|
BoneWeight[] boneWeights = m_renderer.sharedMesh.boneWeights;
|
|
Color[] array = new Color[m_gpuVertexTexWidth * m_gpuVertexTexHeight];
|
|
for (int i = 0; i < m_vertexCount; i++)
|
|
{
|
|
int num = i % m_gpuVertexTexWidth;
|
|
int num2 = i / m_gpuVertexTexWidth;
|
|
int num3 = num2 * m_gpuVertexTexWidth + num;
|
|
BoneWeight boneWeight = boneWeights[i];
|
|
array[num3] = new Vector4(boneWeight.boneIndex0, boneWeight.boneIndex1, boneWeight.boneIndex2, boneWeight.boneIndex3);
|
|
}
|
|
m_gpuBoneIndices.SetPixels(array);
|
|
m_gpuBoneIndices.Apply();
|
|
m_gpuBaseVertices = new Texture2D[m_weightCount];
|
|
for (int j = 0; j < m_weightCount; j++)
|
|
{
|
|
m_gpuBaseVertices[j] = new Texture2D(m_gpuVertexTexWidth, m_gpuVertexTexHeight, TextureFormat.RGBAFloat, false, true);
|
|
m_gpuBaseVertices[j].filterMode = FilterMode.Point;
|
|
}
|
|
List<Color[]> list = new List<Color[]>(m_weightCount);
|
|
for (int k = 0; k < m_weightCount; k++)
|
|
{
|
|
list.Add(new Color[m_gpuVertexTexWidth * m_gpuVertexTexHeight]);
|
|
}
|
|
for (int l = 0; l < m_vertexCount; l++)
|
|
{
|
|
int num4 = l % m_gpuVertexTexWidth;
|
|
int num5 = l / m_gpuVertexTexWidth;
|
|
int num6 = num5 * m_gpuVertexTexWidth + num4;
|
|
for (int m = 0; m < m_weightCount; m++)
|
|
{
|
|
list[m][num6] = m_baseVertices[l * m_weightCount + m];
|
|
}
|
|
}
|
|
for (int n = 0; n < m_weightCount; n++)
|
|
{
|
|
m_gpuBaseVertices[n].SetPixels(list[n]);
|
|
m_gpuBaseVertices[n].Apply();
|
|
}
|
|
m_gpuPrevVertices = new RenderTexture(m_gpuVertexTexWidth, m_gpuVertexTexHeight, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
|
|
m_gpuPrevVertices.filterMode = FilterMode.Point;
|
|
m_gpuPrevVertices.wrapMode = TextureWrapMode.Clamp;
|
|
m_gpuPrevVertices.Create();
|
|
m_gpuCurrVertices = new RenderTexture(m_gpuVertexTexWidth, m_gpuVertexTexHeight, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
|
|
m_gpuCurrVertices.filterMode = FilterMode.Point;
|
|
m_gpuCurrVertices.wrapMode = TextureWrapMode.Clamp;
|
|
m_gpuCurrVertices.Create();
|
|
m_gpuSkinDeformMat.SetTexture("_AM_BONE_TEX", m_gpuBones);
|
|
m_gpuSkinDeformMat.SetTexture("_AM_BONE_INDEX_TEX", m_gpuBoneIndices);
|
|
for (int num7 = 0; num7 < m_weightCount; num7++)
|
|
{
|
|
m_gpuSkinDeformMat.SetTexture("_AM_BASE_VERTEX" + num7 + "_TEX", m_gpuBaseVertices[num7]);
|
|
}
|
|
Vector4 vector = new Vector4(1f / (float)m_gpuBoneTexWidth, 1f / (float)m_gpuBoneTexHeight, m_gpuBoneTexWidth, m_gpuBoneTexHeight);
|
|
Vector4 vector2 = new Vector4(1f / (float)m_gpuVertexTexWidth, 1f / (float)m_gpuVertexTexHeight, m_gpuVertexTexWidth, m_gpuVertexTexHeight);
|
|
m_gpuSkinDeformMat.SetVector("_AM_BONE_TEXEL_SIZE", vector);
|
|
m_gpuSkinDeformMat.SetVector("_AM_BONE_TEXEL_HALFSIZE", vector * 0.5f);
|
|
m_gpuSkinDeformMat.SetVector("_AM_VERTEX_TEXEL_SIZE", vector2);
|
|
m_gpuSkinDeformMat.SetVector("_AM_VERTEX_TEXEL_HALFSIZE", vector2 * 0.5f);
|
|
Vector2[] array2 = new Vector2[m_vertexCount];
|
|
for (int num8 = 0; num8 < m_vertexCount; num8++)
|
|
{
|
|
int num9 = num8 % m_gpuVertexTexWidth;
|
|
int num10 = num8 / m_gpuVertexTexWidth;
|
|
float x = (float)num9 / (float)m_gpuVertexTexWidth + vector2.x * 0.5f;
|
|
float y = (float)num10 / (float)m_gpuVertexTexHeight + vector2.y * 0.5f;
|
|
array2[num8] = new Vector2(x, y);
|
|
}
|
|
m_clonedMesh.uv2 = array2;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
result = false;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private void ShutdownGPUSkinDeform()
|
|
{
|
|
if (m_gpuSkinDeformMat != null)
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(m_gpuSkinDeformMat);
|
|
m_gpuSkinDeformMat = null;
|
|
}
|
|
m_gpuBoneData = null;
|
|
if (m_gpuBones != null)
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(m_gpuBones);
|
|
m_gpuBones = null;
|
|
}
|
|
if (m_gpuBoneIndices != null)
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(m_gpuBoneIndices);
|
|
m_gpuBoneIndices = null;
|
|
}
|
|
if (m_gpuBaseVertices != null)
|
|
{
|
|
for (int i = 0; i < m_gpuBaseVertices.Length; i++)
|
|
{
|
|
UnityEngine.Object.DestroyImmediate(m_gpuBaseVertices[i]);
|
|
}
|
|
m_gpuBaseVertices = null;
|
|
}
|
|
if (m_gpuPrevVertices != null)
|
|
{
|
|
RenderTexture.active = null;
|
|
UnityEngine.Object.DestroyImmediate(m_gpuPrevVertices);
|
|
m_gpuPrevVertices = null;
|
|
}
|
|
if (m_gpuCurrVertices != null)
|
|
{
|
|
RenderTexture.active = null;
|
|
UnityEngine.Object.DestroyImmediate(m_gpuCurrVertices);
|
|
m_gpuCurrVertices = null;
|
|
}
|
|
}
|
|
|
|
private void UpdateBonesGPU()
|
|
{
|
|
for (int i = 0; i < m_boneCount; i++)
|
|
{
|
|
for (int j = 0; j < m_gpuBoneTexHeight; j++)
|
|
{
|
|
m_gpuBoneData[j * m_gpuBoneTexWidth + i] = m_bones[i].GetRow(j);
|
|
}
|
|
}
|
|
m_gpuBones.SetPixels(m_gpuBoneData);
|
|
m_gpuBones.Apply();
|
|
}
|
|
|
|
private void UpdateVerticesGPU(CommandBuffer updateCB, bool starting)
|
|
{
|
|
if (!starting && m_wasVisible)
|
|
{
|
|
AmplifyMotionEffectBase.DiscardContents(m_gpuPrevVertices);
|
|
updateCB.Blit(new RenderTargetIdentifier(m_gpuCurrVertices), m_gpuPrevVertices);
|
|
}
|
|
updateCB.SetGlobalMatrix("_AM_WORLD_TO_LOCAL_MATRIX", m_worldToLocalMatrix);
|
|
AmplifyMotionEffectBase.DiscardContents(m_gpuCurrVertices);
|
|
RenderTexture tex = null;
|
|
updateCB.Blit(new RenderTargetIdentifier(tex), m_gpuCurrVertices, m_gpuSkinDeformMat, Mathf.Min(m_weightCount - 1, 2));
|
|
if (starting || !m_wasVisible)
|
|
{
|
|
AmplifyMotionEffectBase.DiscardContents(m_gpuPrevVertices);
|
|
updateCB.Blit(new RenderTargetIdentifier(m_gpuCurrVertices), m_gpuPrevVertices);
|
|
}
|
|
}
|
|
|
|
private void UpdateBones()
|
|
{
|
|
for (int i = 0; i < m_boneCount; i++)
|
|
{
|
|
m_bones[i] = ((!(m_boneTransforms[i] != null)) ? Matrix4x4.identity : m_boneTransforms[i].localToWorldMatrix);
|
|
}
|
|
m_worldToLocalMatrix = m_transform.worldToLocalMatrix;
|
|
if (m_useGPU)
|
|
{
|
|
UpdateBonesGPU();
|
|
}
|
|
}
|
|
|
|
private void UpdateVerticesFallback(bool starting)
|
|
{
|
|
if (!starting && m_wasVisible)
|
|
{
|
|
Array.Copy(m_currVertices, m_prevVertices, m_vertexCount);
|
|
}
|
|
m_renderer.BakeMesh(m_clonedMesh);
|
|
Array.Copy(m_clonedMesh.vertices, m_currVertices, m_vertexCount);
|
|
if (starting || !m_wasVisible)
|
|
{
|
|
Array.Copy(m_currVertices, m_prevVertices, m_vertexCount);
|
|
}
|
|
}
|
|
|
|
private void AsyncUpdateVertices(bool starting)
|
|
{
|
|
if (!starting && m_wasVisible)
|
|
{
|
|
Array.Copy(m_currVertices, m_prevVertices, m_vertexCount);
|
|
}
|
|
for (int i = 0; i < m_boneCount; i++)
|
|
{
|
|
m_bones[i] = m_worldToLocalMatrix * m_bones[i];
|
|
}
|
|
if (m_weightCount == 1)
|
|
{
|
|
UpdateVerticesBone1();
|
|
}
|
|
else if (m_weightCount == 2)
|
|
{
|
|
UpdateVerticesBone2();
|
|
}
|
|
else
|
|
{
|
|
UpdateVerticesBone4();
|
|
}
|
|
if (starting || !m_wasVisible)
|
|
{
|
|
Array.Copy(m_currVertices, m_prevVertices, m_vertexCount);
|
|
}
|
|
}
|
|
|
|
private void InitializeBone1(Vector4[] baseVertices, int[] boneIndices)
|
|
{
|
|
Vector3[] vertices = m_renderer.sharedMesh.vertices;
|
|
Matrix4x4[] bindposes = m_renderer.sharedMesh.bindposes;
|
|
BoneWeight[] boneWeights = m_renderer.sharedMesh.boneWeights;
|
|
for (int i = 0; i < m_vertexCount; i++)
|
|
{
|
|
int num = i * m_weightCount;
|
|
Vector3 vector = bindposes[boneIndices[num] = boneWeights[i].boneIndex0].MultiplyPoint3x4(vertices[i]);
|
|
baseVertices[num] = new Vector4(vector.x, vector.y, vector.z, 1f);
|
|
}
|
|
}
|
|
|
|
private void InitializeBone2(Vector4[] baseVertices, int[] boneIndices, float[] boneWeights)
|
|
{
|
|
Vector3[] vertices = m_renderer.sharedMesh.vertices;
|
|
Matrix4x4[] bindposes = m_renderer.sharedMesh.bindposes;
|
|
BoneWeight[] boneWeights2 = m_renderer.sharedMesh.boneWeights;
|
|
for (int i = 0; i < m_vertexCount; i++)
|
|
{
|
|
int num = i * m_weightCount;
|
|
int num2 = num + 1;
|
|
BoneWeight boneWeight = boneWeights2[i];
|
|
int num3 = (boneIndices[num] = boneWeight.boneIndex0);
|
|
int num4 = (boneIndices[num2] = boneWeight.boneIndex1);
|
|
float weight = boneWeight.weight0;
|
|
float weight2 = boneWeight.weight1;
|
|
float num5 = 1f / (weight + weight2);
|
|
weight = (boneWeights[num] = weight * num5);
|
|
weight2 = (boneWeights[num2] = weight2 * num5);
|
|
Vector3 vector = weight * bindposes[num3].MultiplyPoint3x4(vertices[i]);
|
|
Vector3 vector2 = weight2 * bindposes[num4].MultiplyPoint3x4(vertices[i]);
|
|
baseVertices[num] = new Vector4(vector.x, vector.y, vector.z, weight);
|
|
baseVertices[num2] = new Vector4(vector2.x, vector2.y, vector2.z, weight2);
|
|
}
|
|
}
|
|
|
|
private void InitializeBone4(Vector4[] baseVertices, int[] boneIndices, float[] boneWeights)
|
|
{
|
|
Vector3[] vertices = m_renderer.sharedMesh.vertices;
|
|
Matrix4x4[] bindposes = m_renderer.sharedMesh.bindposes;
|
|
BoneWeight[] boneWeights2 = m_renderer.sharedMesh.boneWeights;
|
|
for (int i = 0; i < m_vertexCount; i++)
|
|
{
|
|
int num = i * m_weightCount;
|
|
int num2 = num + 1;
|
|
int num3 = num + 2;
|
|
int num4 = num + 3;
|
|
BoneWeight boneWeight = boneWeights2[i];
|
|
int num5 = (boneIndices[num] = boneWeight.boneIndex0);
|
|
int num6 = (boneIndices[num2] = boneWeight.boneIndex1);
|
|
int num7 = (boneIndices[num3] = boneWeight.boneIndex2);
|
|
int num8 = (boneIndices[num4] = boneWeight.boneIndex3);
|
|
float num9 = (boneWeights[num] = boneWeight.weight0);
|
|
float num10 = (boneWeights[num2] = boneWeight.weight1);
|
|
float num11 = (boneWeights[num3] = boneWeight.weight2);
|
|
float num12 = (boneWeights[num4] = boneWeight.weight3);
|
|
Vector3 vector = num9 * bindposes[num5].MultiplyPoint3x4(vertices[i]);
|
|
Vector3 vector2 = num10 * bindposes[num6].MultiplyPoint3x4(vertices[i]);
|
|
Vector3 vector3 = num11 * bindposes[num7].MultiplyPoint3x4(vertices[i]);
|
|
Vector3 vector4 = num12 * bindposes[num8].MultiplyPoint3x4(vertices[i]);
|
|
baseVertices[num] = new Vector4(vector.x, vector.y, vector.z, num9);
|
|
baseVertices[num2] = new Vector4(vector2.x, vector2.y, vector2.z, num10);
|
|
baseVertices[num3] = new Vector4(vector3.x, vector3.y, vector3.z, num11);
|
|
baseVertices[num4] = new Vector4(vector4.x, vector4.y, vector4.z, num12);
|
|
}
|
|
}
|
|
|
|
private void UpdateVerticesBone1()
|
|
{
|
|
for (int i = 0; i < m_vertexCount; i++)
|
|
{
|
|
MotionState.MulPoint3x4_XYZ(ref m_currVertices[i], ref m_bones[m_boneIndices[i]], m_baseVertices[i]);
|
|
}
|
|
}
|
|
|
|
private void UpdateVerticesBone2()
|
|
{
|
|
Vector3 result = Vector3.zero;
|
|
for (int i = 0; i < m_vertexCount; i++)
|
|
{
|
|
int num = i * 2;
|
|
int num2 = num + 1;
|
|
int num3 = m_boneIndices[num];
|
|
int num4 = m_boneIndices[num2];
|
|
float num5 = m_boneWeights[num2];
|
|
MotionState.MulPoint3x4_XYZW(ref result, ref m_bones[num3], m_baseVertices[num]);
|
|
if (num5 != 0f)
|
|
{
|
|
MotionState.MulAddPoint3x4_XYZW(ref result, ref m_bones[num4], m_baseVertices[num2]);
|
|
}
|
|
m_currVertices[i] = result;
|
|
}
|
|
}
|
|
|
|
private void UpdateVerticesBone4()
|
|
{
|
|
Vector3 result = Vector3.zero;
|
|
for (int i = 0; i < m_vertexCount; i++)
|
|
{
|
|
int num = i * 4;
|
|
int num2 = num + 1;
|
|
int num3 = num + 2;
|
|
int num4 = num + 3;
|
|
int num5 = m_boneIndices[num];
|
|
int num6 = m_boneIndices[num2];
|
|
int num7 = m_boneIndices[num3];
|
|
int num8 = m_boneIndices[num4];
|
|
float num9 = m_boneWeights[num2];
|
|
float num10 = m_boneWeights[num3];
|
|
float num11 = m_boneWeights[num4];
|
|
MotionState.MulPoint3x4_XYZW(ref result, ref m_bones[num5], m_baseVertices[num]);
|
|
if (num9 != 0f)
|
|
{
|
|
MotionState.MulAddPoint3x4_XYZW(ref result, ref m_bones[num6], m_baseVertices[num2]);
|
|
}
|
|
if (num10 != 0f)
|
|
{
|
|
MotionState.MulAddPoint3x4_XYZW(ref result, ref m_bones[num7], m_baseVertices[num3]);
|
|
}
|
|
if (num11 != 0f)
|
|
{
|
|
MotionState.MulAddPoint3x4_XYZW(ref result, ref m_bones[num8], m_baseVertices[num4]);
|
|
}
|
|
m_currVertices[i] = result;
|
|
}
|
|
}
|
|
|
|
internal override void AsyncUpdate()
|
|
{
|
|
try
|
|
{
|
|
AsyncUpdateVertices(m_starting);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogError("[AmplifyMotion] Failed on SkinnedMeshRenderer data. Please contact support.\n" + ex.Message);
|
|
}
|
|
finally
|
|
{
|
|
m_asyncUpdateSignal.Set();
|
|
}
|
|
}
|
|
|
|
internal override void UpdateTransform(CommandBuffer updateCB, bool starting)
|
|
{
|
|
if (!m_initialized)
|
|
{
|
|
Initialize();
|
|
return;
|
|
}
|
|
if (!starting && m_wasVisible)
|
|
{
|
|
m_prevLocalToWorld = m_currLocalToWorld;
|
|
}
|
|
bool isVisible = m_renderer.isVisible;
|
|
if (!m_error && (isVisible || starting))
|
|
{
|
|
UpdateBones();
|
|
m_starting = !m_wasVisible || starting;
|
|
if (!m_useFallback)
|
|
{
|
|
if (!m_useGPU)
|
|
{
|
|
m_asyncUpdateSignal.Reset();
|
|
m_asyncUpdateTriggered = true;
|
|
m_owner.Instance.WorkerPool.EnqueueAsyncUpdate(this);
|
|
}
|
|
else
|
|
{
|
|
UpdateVerticesGPU(updateCB, m_starting);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UpdateVerticesFallback(m_starting);
|
|
}
|
|
}
|
|
if (!m_useFallback)
|
|
{
|
|
m_currLocalToWorld = m_transform.localToWorldMatrix;
|
|
}
|
|
else
|
|
{
|
|
m_currLocalToWorld = Matrix4x4.TRS(m_transform.position, m_transform.rotation, Vector3.one);
|
|
}
|
|
if (starting || !m_wasVisible)
|
|
{
|
|
m_prevLocalToWorld = m_currLocalToWorld;
|
|
}
|
|
m_wasVisible = isVisible;
|
|
}
|
|
|
|
private void WaitForAsyncUpdate()
|
|
{
|
|
if (m_asyncUpdateTriggered)
|
|
{
|
|
if (!m_asyncUpdateSignal.WaitOne(100))
|
|
{
|
|
Debug.LogWarning("[AmplifyMotion] Aborted abnormally long Async Skin deform operation. Not a critical error but might indicate a problem. Please contact support.");
|
|
}
|
|
else
|
|
{
|
|
m_asyncUpdateTriggered = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal override void RenderVectors(Camera camera, CommandBuffer renderCB, float scale, Quality quality)
|
|
{
|
|
if (!m_initialized || m_error || !m_renderer.isVisible)
|
|
{
|
|
return;
|
|
}
|
|
if (!m_useFallback && !m_useGPU)
|
|
{
|
|
WaitForAsyncUpdate();
|
|
}
|
|
if (!m_useGPU)
|
|
{
|
|
if (!m_useFallback)
|
|
{
|
|
m_clonedMesh.vertices = m_currVertices;
|
|
}
|
|
m_clonedMesh.normals = m_prevVertices;
|
|
}
|
|
bool flag = ((int)m_owner.Instance.CullingMask & (1 << m_obj.gameObject.layer)) != 0;
|
|
int num = ((!flag) ? 255 : m_owner.Instance.GenerateObjectId(m_obj.gameObject));
|
|
Matrix4x4 value = ((!m_obj.FixedStep) ? (m_owner.PrevViewProjMatrixRT * m_prevLocalToWorld) : (m_owner.PrevViewProjMatrixRT * m_currLocalToWorld));
|
|
renderCB.SetGlobalMatrix("_AM_MATRIX_PREV_MVP", value);
|
|
renderCB.SetGlobalFloat("_AM_OBJECT_ID", (float)num * 0.003921569f);
|
|
renderCB.SetGlobalFloat("_AM_MOTION_SCALE", (!flag) ? 0f : scale);
|
|
if (m_useGPU)
|
|
{
|
|
Vector4 vector = new Vector4(1f / (float)m_gpuVertexTexWidth, 1f / (float)m_gpuVertexTexHeight, m_gpuVertexTexWidth, m_gpuVertexTexHeight);
|
|
renderCB.SetGlobalVector("_AM_VERTEX_TEXEL_SIZE", vector);
|
|
renderCB.SetGlobalVector("_AM_VERTEX_TEXEL_HALFSIZE", vector * 0.5f);
|
|
renderCB.SetGlobalTexture("_AM_PREV_VERTEX_TEX", m_gpuPrevVertices);
|
|
renderCB.SetGlobalTexture("_AM_CURR_VERTEX_TEX", m_gpuCurrVertices);
|
|
}
|
|
int num2 = (m_useGPU ? 4 : 0);
|
|
int num3 = ((quality != Quality.Mobile) ? 2 : 0);
|
|
int num4 = num2 + num3;
|
|
for (int i = 0; i < m_sharedMaterials.Length; i++)
|
|
{
|
|
MaterialDesc materialDesc = m_sharedMaterials[i];
|
|
int shaderPass = num4 + (materialDesc.coverage ? 1 : 0);
|
|
materialDesc.propertyBlock.Clear();
|
|
if (materialDesc.coverage)
|
|
{
|
|
materialDesc.propertyBlock.SetTexture("_MainTex", materialDesc.material.mainTexture);
|
|
if (materialDesc.cutoff)
|
|
{
|
|
materialDesc.propertyBlock.SetFloat("_Cutoff", materialDesc.material.GetFloat("_Cutoff"));
|
|
}
|
|
}
|
|
renderCB.DrawMesh(m_clonedMesh, m_currLocalToWorld, m_owner.Instance.SkinnedVectorsMaterial, i, shaderPass, materialDesc.propertyBlock);
|
|
}
|
|
}
|
|
}
|
|
}
|