浏览代码

more cleanup, and bump to 2019.3.12f1 and HDRP 7.3.1

/main
Lasse Jon Fuglsang Pedersen 4 年前
当前提交
a8eae565
共有 32 个文件被更改,包括 383 次插入636 次删除
  1. 43
      Editor/SkinAttachmentEditor.cs
  2. 226
      Editor/SkinDeformationClipEditor.cs
  3. 8
      Editor/SkinDeformationFitting.cs
  4. 14
      Editor/SkinDeformationClipRegions.cs
  5. 4
      README.md
  6. 3
      Runtime/EyeRenderer.cs
  7. 12
      Runtime/SkinAttachment.cs
  8. 2
      Runtime/SkinAttachmentData.cs
  9. 14
      Runtime/SkinAttachmentTarget.cs
  10. 5
      Runtime/SkinDeformation.cs
  11. 209
      Runtime/SkinDeformationClip.cs
  12. 35
      Runtime/SkinDeformationRenderer.cs
  13. 11
      Runtime/SnappersHeadRenderer.cs
  14. 2
      Runtime/TeethJawDriver.cs
  15. 92
      Runtime/TeethRenderer.cs
  16. 82
      Runtime/Utility/MeshBuffers.cs
  17. 140
      Runtime/Utility/NativeFrameStream.cs
  18. 2
      Runtime/Utility/NativeMeshObjLoader.cs
  19. 2
      Runtime/SkinDeformationFittingOptions.cs
  20. 2
      ShaderLibrary/Nodes_Skin/SkinDeformationBlend.hlsl
  21. 2
      ShaderLibrary/Nodes_Skin/SnappersBlend.hlsl
  22. 4
      package.json
  23. 27
      Editor/SkinDeformationClipBuildProcessor.cs
  24. 11
      Editor/SkinDeformationClipBuildProcessor.cs.meta
  25. 37
      Editor/Utility/PrefabTransformHierarchyEditor.cs
  26. 11
      Editor/Utility/PrefabTransformHierarchyEditor.cs.meta
  27. 8
      Runtime/Utility/PrefabTransformHierarchy.cs
  28. 11
      Runtime/Utility/PrefabTransformHierarchy.cs.meta
  29. 0
      /Editor/SkinDeformationClipRegions.cs.meta
  30. 0
      /Editor/SkinDeformationClipRegions.cs
  31. 0
      /Runtime/SkinDeformationFittingOptions.cs.meta
  32. 0
      /Runtime/SkinDeformationFittingOptions.cs

43
Editor/SkinAttachmentEditor.cs


CommitTargetChanges(attachmentTargetSet);
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.Separator();
EditorGUILayout.BeginVertical();
DrawGUIAttachDetachAll(targets, attachmentTargetSet);
CommitTargetChanges(attachmentTargetSet);
EditorGUILayout.EndVertical();
}
}

{
if (attachmentTarget != null)
{
EditorUtility.SetDirty(attachmentTarget);
}
}
}

{
if (GUILayout.Button("Attach"))
{
attachmentTargetSet.Add(attachment.targetActive);
EditorUtility.SetDirty(attachment);
}
}
EditorGUI.EndDisabledGroup();

{
attachmentTargetSet.Add(attachment.targetActive);
attachment.Detach(revertPositionRotation: true);
EditorUtility.SetDirty(attachment);
EditorUtility.SetDirty(attachment);
}
public static void DrawGUIAttachDetachAll(Object[] targets, HashSet<SkinAttachmentTarget> attachmentTargetSet)
{
if (GUILayout.Button("Attach all"))
{
foreach (var target in targets)
{
var attachment = target as SkinAttachment;
if (attachment != null && !attachment.attached)
{
attachment.Attach(storePositionRotation: true);
attachmentTargetSet.Add(attachment.targetActive);
EditorUtility.SetDirty(attachment);
}
}
}
if (GUILayout.Button("Detach all"))
{
foreach (var target in targets)
{
var attachment = target as SkinAttachment;
if (attachment != null && attachment.attached)
{
attachmentTargetSet.Add(attachment.targetActive);
attachment.Detach(revertPositionRotation: true);
EditorUtility.SetDirty(attachment);
}
}
}
}
}
}

226
Editor/SkinDeformationClipEditor.cs


static GUIStyle miniLabelAlignLeft;
static GUIStyle miniLabelAlignRight;
static bool framesFoldout = true;
static bool framesFoldout = false;
var iarr = SkinDeformationFittingImpl.GetBlendShapeIndices(clip.importSettings.transferTarget);
var iarr = SkinDeformationFitting.GetBlendShapeIndices(clip.importSettings.transferTarget);
clip.importSettings.fittedIndices = String.Join(",", iarr.Select(i => i.ToString()).ToArray());
}

var clip = userData as SkinDeformationClip;
var iarr = new int[] {
// all indices from snappers head
// 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317
// subtract linearly dependent indices
// 23,106,107,108,109,176,177,178,179,296,297,298,299
// =>
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317
};
var iarr = new int[]
{
// all indices from snappers head
// 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317
// subtract linearly dependent indices
// 23,106,107,108,109,176,177,178,179,296,297,298,299
// =>
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317
};
clip.importSettings.fittedIndices = String.Join(",", iarr.Select(i => i.ToString()).ToArray());
}

var clip = userData as SkinDeformationClip;
var iarr = new int[] {
// all indices from snappers head that contribute to wrinkle maps
// =>
1,14,15,44,48,51,54,59,62,67,72,80,85,87,89,91,93,95,97,110,113,116,118,119,121,123,126,129,132,135,138,141,144,147,150,158,163,181,183,184,187,191,194,197,200,207,209,219,221,227,229,230,231,232,233,235,237,240,241,250,251,252,253,254,255,256,257,258,259,264,265,290,291,292,293,294,295
};
var iarr = new int[]
{
// all indices from snappers head that contribute to wrinkle maps
// =>
1,14,15,44,48,51,54,59,62,67,72,80,85,87,89,91,93,95,97,110,113,116,118,119,121,123,126,129,132,135,138,141,144,147,150,158,163,181,183,184,187,191,194,197,200,207,209,219,221,227,229,230,231,232,233,235,237,240,241,250,251,252,253,254,255,256,257,258,259,264,265,290,291,292,293,294,295
};
clip.importSettings.fittedIndices = String.Join(",", iarr.Select(i => i.ToString()).ToArray());
}

var iarr = Array.ConvertAll<string, int>(istr.Split(','), int.Parse);
Array.Sort<int>(iarr);
iarr = SkinDeformationFittingImpl.ComputeLinearlyIndependentBlendShapeIndices(clip.importSettings.transferTarget, iarr);
iarr = SkinDeformationFitting.ComputeLinearlyIndependentBlendShapeIndices(clip.importSettings.transferTarget, iarr);
if (iarr == null)
{

void OnDisable()
{
SkinDeformationClipPreview.Disable();
SkinDeformationClipRegions.Disable();
}
public override void OnInspectorGUI()

SkinDeformationClip clip = (SkinDeformationClip)target;
if (clip.importSettings.solveRegionPreview)
SkinDeformationClipPreview.Enable(clip);
SkinDeformationClipRegions.Enable(clip);
SkinDeformationClipPreview.Disable();
SkinDeformationClipRegions.Disable();
EditorGUILayout.HelpBox(GetInfoString(clip), MessageType.Info, true);
if (GUILayout.Button("Import"))

}
else
{
SkinDeformationClipPreview.Disable();
SkinDeformationClipRegions.Disable();
EditorGUILayout.HelpBox("Skin Deformation Clip (multiple)", MessageType.Info, true);
if (GUILayout.Button("Import"))

s += "\n -- contains albedo: " + GetInfoString(clip.framesContainAlbedo);
s += "\n -- contains fitted weights: " + GetInfoString(clip.framesContainFittedWeights);
s += "\n -- (rev " + clip.version + ")";
//s += "\n" + clip.frameDataFilename;
return s;
}

EditorUtility.DisplayProgressBar(progressTitle, "Loading assets", progressIndex++ / progressCount);
var sourceObjs = null as string[];
var sourceMeshes = null as Mesh[];
var sourceAlbedos = null as Texture2D[];
var sourceObjPaths = null as string[];
var sourceMeshAssets = null as Mesh[];
var sourceAlbedoAssets = null as Texture2D[];
var useExternalLoader = clip.importSettings.externalLoader;
var useExternalLoader = (clip.importSettings.readFrom == SkinDeformationClip.InputType.ExternalObj);
sourceObjs = GetFilesAtPath(clip.importSettings.externalObjPath, clip.importSettings.externalObjPattern);
Debug.Assert(sourceObjs.Length > 0, ".obj count == 0 (check import settings)");
sourceObjPaths = GetFilesAtPath(clip.importSettings.externalObjPath, clip.importSettings.externalObjPattern);
Debug.Assert(sourceObjPaths.Length > 0, "source .obj count == 0 (check import settings)");
using (var nativeMesh = NativeMeshObjLoader.Parse(sourceObjs[0]))
using (var nativeMesh = NativeMeshObjLoader.Parse(sourceObjPaths[0]))
frameCount = sourceObjs.Length;
frameCount = sourceObjPaths.Length;
sourceMeshes = GetAssetsAtPath<Mesh>(clip.importSettings.meshFolder, clip.importSettings.meshPrefix);
Debug.Assert(sourceMeshes.Length > 0, "mesh count == 0 (check import settings)");
sourceMeshAssets = GetAssetsAtPath<Mesh>(clip.importSettings.meshAssetPath, clip.importSettings.meshAssetPrefix);
Debug.Assert(sourceMeshAssets.Length > 0, "mesh count == 0 (check import settings)");
sourceAlbedos = GetAssetsAtPath<Texture2D>(clip.importSettings.albedoFolder, clip.importSettings.albedoPrefix);
if (sourceAlbedos.Length != sourceMeshes.Length)
sourceAlbedoAssets = GetAssetsAtPath<Texture2D>(clip.importSettings.albedoAssetPath, clip.importSettings.albedoAssetPrefix);
if (sourceAlbedoAssets.Length != sourceMeshAssets.Length)
sourceAlbedos = null;
Debug.LogWarning("mesh count != albedo count: skipping albedos");
sourceAlbedoAssets = null;
Debug.LogWarning("mesh asset count != albedo asset count: skipping albedos");
frameCount = sourceMeshes.Length;
frameVertexCount = sourceMeshes[0].vertexCount;
frameCount = sourceMeshAssets.Length;
frameVertexCount = sourceMeshAssets[0].vertexCount;
}
int frameFittedWeightsCount = 0;// modified later

if (useExternalLoader)
{
using (var nativeMesh = NativeMeshObjLoader.Parse(sourceObjs[0]))
using (var nativeMesh = NativeMeshObjLoader.Parse(sourceObjPaths[0]))
{
buffersFrame0.LoadFrom(nativeMesh);
buffersFrame0.ApplyRotation(sourceRotation);

else
{
buffersFrame0.LoadFrom(sourceMeshes[0]);
buffersFrame0.LoadFrom(sourceMeshAssets[0]);
var denoiseFactor = clip.importSettings.denoiseFactor;
var denoiseIndices = ResolveIndexArrayFromVertexSelectionArray(clip.importSettings.denoiseRegion, weldedAdjacency);
var denoiseIndices = ResolveIndexArrayFromVertexSelectionArray(clip.importSettings.denoiseRegions, weldedAdjacency);
var denoiseFactor = clip.importSettings.denoiseStrength;
var transplantFactor = clip.importSettings.transplantFactor;
var transplantIndices = ResolveIndexArrayFromVertexSelectionArray(clip.importSettings.transplantRegion, weldedAdjacency);
var transplantIndices = ResolveIndexArrayFromVertexSelectionArray(clip.importSettings.transplantRegions, weldedAdjacency);
var transplantFactor = clip.importSettings.transplantStrength;
var transplantSource = clip.importSettings.transferTarget;
if (transplantFactor < float.Epsilon || clip.importSettings.transferTarget == null)
if (transplantFactor < float.Epsilon || transplantSource == null)
//TODO cleanup
var transferIndices = ResolveIndexArrayFromVertexSelection(clip.importSettings.transferRegion, weldedAdjacency);
var laplacianConstraintCount = frameVertexCount;
var laplacianConstraintIndices = null as int[];
var laplacianConstraintCount = frameVertexCount;
var laplacianConstraintIndices = null as int[];
unsafe
{
using (var laplacianFreeVertexMap = new UnsafeArrayBool(frameVertexCount))
{
laplacianFreeVertexMap.Clear(false);
unsafe
{
for (int k = 0; k != denoiseIndices.Length; k++)
{
if (laplacianFreeVertexMap.val[denoiseIndices[k]] == false)
{
laplacianFreeVertexMap.val[denoiseIndices[k]] = true;
laplacianConstraintCount--;
}
}
using (var laplacianFreeVertexMap = new UnsafeArrayBool(frameVertexCount))
{
laplacianFreeVertexMap.Clear(false);
for (int k = 0; k != transplantIndices.Length; k++)
{
if (laplacianFreeVertexMap.val[transplantIndices[k]] == false)
{
laplacianFreeVertexMap.val[transplantIndices[k]] = true;
laplacianConstraintCount--;
}
}
for (int k = 0; k != denoiseIndices.Length; k++)
{
if (laplacianFreeVertexMap.val[denoiseIndices[k]] == false)
{
laplacianFreeVertexMap.val[denoiseIndices[k]] = true;
laplacianConstraintCount--;
}
}
for (int k = 0; k != transplantIndices.Length; k++)
{
if (laplacianFreeVertexMap.val[transplantIndices[k]] == false)
{
laplacianFreeVertexMap.val[transplantIndices[k]] = true;
laplacianConstraintCount--;
}
}
laplacianConstraintIndices = new int[laplacianConstraintCount];
laplacianConstraintIndices = new int[laplacianConstraintCount];
for (int i = 0, k = 0; i != frameVertexCount; i++)
{
if (laplacianFreeVertexMap.val[i] == false)
laplacianConstraintIndices[k++] = i;
}
}
}
for (int i = 0, k = 0; i != frameVertexCount; i++)
{
if (laplacianFreeVertexMap.val[i] == false)
laplacianConstraintIndices[k++] = i;
}
}
}
#else
var laplacianROIIndices = denoiseIndices.Union(transplantIndices).ToArray();
var laplacianConstraintCount = frameVertexCount - laplacianROIIndices.Length;

var meshLaplacianTransform = null as MeshLaplacianTransform;
var meshLaplacianTransform = null as MeshLaplacianTransform;
#else
var meshLaplacianTransform = null as MeshLaplacianTransformROI;
#endif

if (laplacianResolve)
{
#if SOLVE_FULL_LAPLACIAN
meshLaplacianTransform = new MeshLaplacianTransform(weldedAdjacency, laplacianConstraintIndices);
meshLaplacianTransform = new MeshLaplacianTransform(weldedAdjacency, laplacianConstraintIndices);
#else
meshLaplacianTransform = new MeshLaplacianTransformROI(weldedAdjacency, laplacianROIIndices, 0);
{

#endif
meshLaplacianTransform.ComputeMeshLaplacian(meshLaplacianDenoised, buffersFrame0);
if (transplantIndices.Length > 0 && clip.importSettings.transferTarget != null)
if (transplantIndices.Length > 0 && transplantSource != null)
transplantBuffers.LoadFrom(clip.importSettings.transferTarget);
transplantBuffers.LoadFrom(transplantSource);
//TODO cleanup
var transferTemp = new MeshBuffers(frameVertexCount);
var transferLaplacianTransform = null as MeshLaplacianTransformROI;
var transferLaplacian = new MeshLaplacian();
var laplacianTransfer = (transferIndices.Length > 0) && (clip.importSettings.transferTarget != null);
if (laplacianTransfer)
{
transferLaplacianTransform = new MeshLaplacianTransformROI(weldedAdjacency, transferIndices, 0);
}
for (int i = 0; i != frameCount; i++)
{
EditorUtility.DisplayProgressBar(progressTitle, "Importing frames", (progressIndex - 1 + ((float)i / frameCount)) / progressCount);

using (var nativeMesh = NativeMeshObjLoader.Parse(sourceObjs[i]))
using (var nativeMesh = NativeMeshObjLoader.Parse(sourceObjPaths[i]))
{
buffersFrameX.LoadFrom(nativeMesh);
buffersFrameX.ApplyRotation(sourceRotation);

else
{
buffersFrameX.LoadFrom(sourceMeshes[i]);
buffersFrameX.LoadFrom(sourceMeshAssets[i]);
buffersFrameX.ApplyRotation(sourceRotation);
buffersFrameX.ApplyScale(sourceScale);
}

buffersFrameX.ApplyWeldedChanges(weldedAdjacency);
}
//TODO cleanup
if (laplacianTransfer)
{
buffersTarget.CopyTo(transferTemp);
transferLaplacianTransform.ComputeMeshLaplacian(transferLaplacian, buffersFrameX);
transferLaplacianTransform.ResolveMeshBuffers(transferTemp, transferLaplacian);
transferTemp.CopyTo(buffersFrameX);
buffersFrameX.RecalculateNormals(weldedAdjacency);
buffersFrameX.ApplyWeldedChanges(weldedAdjacency);
}
frames[i].SetAlbedo((sourceAlbedos != null) ? sourceAlbedos[i] : null);
//frames[i].SetDeltas(buffersFrame0, buffersFrameX);
//TODO cleanup
if (laplacianTransfer)
frames[i].SetDeltas(buffersTarget, buffersFrameX);
else
frames[i].SetDeltas(buffersFrame0, buffersFrameX);
frames[i].SetAlbedo((sourceAlbedoAssets != null) ? sourceAlbedoAssets[i] : null);
frames[i].SetDeltas(buffersFrame0, buffersFrameX);
var targetVertexCount = laplacianTransfer ? buffersTarget.vertexCount : buffersFrame0.vertexCount;
var targetVertexCount = buffersFrame0.vertexCount;
Debug.LogWarning("frame " + i + " has different vertexCount (" + buffersFrameX.vertexCount + " vs. " + targetVertexCount + " in frame 0)");
{
Debug.LogWarning("frame " + i + " has different vertexCount (" + buffersFrameX.vertexCount + " vs " + targetVertexCount + " in frame 0)");
}
}
for (int i = 0; i != subframeCount; i++)

subframes[i].fractionHi = 1.0f;
}
ImportFrameIntervalsFromCSV(clip.importSettings.keyframesCSV, frameCount - 1, ref subframeCount, ref subframes);
if (clip.importSettings.keyframes)
{
ImportFrameIntervalsFromCSV(clip.importSettings.keyframesCSV, frameCount - 1, ref subframeCount, ref subframes);
}
}
EditorUtility.DisplayProgressBar(progressTitle, "Retargeting frames", progressIndex++ / progressCount);

for (int j = 0; j != frameVertexCount; j++)
{
frames[i].deltaPositions[j] += firstFrameDelta.deltaPositions[j];
frames[i].deltaTangents[j] += firstFrameDelta.deltaTangents[j];
frames[i].deltaNormals[j] += firstFrameDelta.deltaNormals[j];
}
}

var blendShapeIndicesCommaSep = clip.importSettings.fittedIndices;
var blendShapeIndices = Array.ConvertAll<string, int>(blendShapeIndicesCommaSep.Split(','), int.Parse);
SkinDeformationFittingImpl.FitFramesToBlendShapes(frames, clip.importSettings.transferTarget, blendShapeIndices, clip.importSettings.fittingMethod, clip.importSettings.fittingParam);
SkinDeformationFitting.FitFramesToBlendShapes(frames, clip.importSettings.transferTarget, blendShapeIndices, clip.importSettings.fittingMethod, clip.importSettings.fittingParam);
clip.lastBuild = clip.importSettings.Clone();
clip.lastImport = clip.importSettings.Clone();
clip.frameCount = frameCount;
clip.frameVertexCount = frameVertexCount;
clip.frameFittedWeightsCount = frameFittedWeightsCount;

}
}
static void ImportFrameIntervalsFromCSV(string filename, int maxFrameIndex, ref int subframeCount, ref SkinDeformationClip.Subframe[] subframes)
static void ImportFrameIntervalsFromCSV(TextAsset textAsset, int maxFrameIndex, ref int subframeCount, ref SkinDeformationClip.Subframe[] subframes)
if (!File.Exists(filename))
if (textAsset == null)
return;
// skip 1st column of every row

var vals = new int[NUM_ROWS][];
var valCount = NO_VALUE;
using (StreamReader reader = new StreamReader(filename))
using (StringReader reader = new StringReader(textAsset.text))
if (reader.EndOfStream)
return;// bad input, missing rows
var line = reader.ReadLine();
if (line == null)
return;// bad input, missing rows

8
Editor/SkinDeformationFitting.cs


namespace Unity.DemoTeam.DigitalHuman
{
using Param = SkinDeformationFitting.Param;
using Method = SkinDeformationFitting.Method;
using Param = SkinDeformationFittingOptions.Param;
using Method = SkinDeformationFittingOptions.Method;
public static partial class SkinDeformationFittingImpl
public static class SkinDeformationFitting
{
private static T[][] MakeJagged<T>(T[,] m)
{

int k = frameIndex;
var tmpPositions = new UnityEngine.Vector3[sharedJobData.numVertices];
var tmpTangents = new UnityEngine.Vector3[sharedJobData.numVertices];
var tmpNormals = new UnityEngine.Vector3[sharedJobData.numVertices];
var edgeLengths = null as float[];

var b = new double[sharedJobData.numEquations];
{
Array.Copy(sharedJobData.frames[k].deltaPositions, tmpPositions, tmpPositions.Length);
Array.Copy(sharedJobData.frames[k].deltaTangents, tmpTangents, tmpTangents.Length);
Array.Copy(sharedJobData.frames[k].deltaNormals, tmpNormals, tmpNormals.Length);
switch (sharedJobData.fittingParam)

14
Editor/SkinDeformationClipRegions.cs


namespace Unity.DemoTeam.DigitalHuman
{
public static class SkinDeformationClipPreview
public static class SkinDeformationClipRegions
{
private static bool active;

if (mesh == null)
return;
var updateDenoiseIndices = !CompareTextAssetArrays(activeDenoiseIndices, clip.importSettings.denoiseRegion);
var updateTransplantIndices = !CompareTextAssetArrays(activeTransplantIndices, clip.importSettings.transplantRegion);
var updateDenoiseIndices = !CompareTextAssetArrays(activeDenoiseIndices, clip.importSettings.denoiseRegions);
var updateTransplantIndices = !CompareTextAssetArrays(activeTransplantIndices, clip.importSettings.transplantRegions);
foreach (var deformationRenderer in SkinDeformationRenderer.enabledInstances)
{

if (updateDenoiseIndices)
{
updateDenoiseIndices = false;
activeDenoiseIndices = clip.importSettings.denoiseRegion.Clone() as TextAsset[];
activeDenoiseIndices = clip.importSettings.denoiseRegions.Clone() as TextAsset[];
pairedDenoiseIndices = BuildPairsFromIndices(targetMeshInfo.meshAdjacency, SkinDeformationClipEditor.ResolveIndexArrayFromVertexSelectionArray(activeDenoiseIndices));
}

activeTransplantIndices = clip.importSettings.transplantRegion.Clone() as TextAsset[];
activeTransplantIndices = clip.importSettings.transplantRegions.Clone() as TextAsset[];
pairedTransplantIndices = BuildPairsFromIndices(targetMeshInfo.meshAdjacency, SkinDeformationClipEditor.ResolveIndexArrayFromVertexSelectionArray(activeTransplantIndices));
}

public static void Enable(SkinDeformationClip clip)
{
SkinDeformationClipPreview.clip = clip;
SkinDeformationClipRegions.clip = clip;
if (active == false)
{

public static void Disable()
{
SkinDeformationClipPreview.clip = null;
SkinDeformationClipRegions.clip = null;
if (active)
{

4
README.md


## Requirements
- Unity 2019.3.3f1 +
- HDRP 7.2.1 +
- Unity 2019.3.12f1 +
- HDRP 7.3.1 +
## Usage

3
Runtime/EyeRenderer.cs


namespace Unity.DemoTeam.DigitalHuman
{
[ExecuteAlways]
[RequireComponent(typeof(Renderer))]
[ExecuteAlways, RequireComponent(typeof(Renderer))]
public class EyeRenderer : MonoBehaviour
{
private Renderer rnd;

12
Runtime/SkinAttachment.cs


Gizmos.color = Color.Lerp(Color.clear, c, 0.75f);
Gizmos.DrawLine(targetLocalPos, target.meshBuffers.vertexPositions[closestNode]);
target.meshBuffers.DrawGizmoTriangles(targetMeshInfo.meshAdjacency.vertexTriangles[closestNode]);
foreach (var triangle in targetMeshInfo.meshAdjacency.vertexTriangles[closestNode])
{
int _0 = triangle * 3;
int v0 = target.meshBuffers.triangles[_0];
int v1 = target.meshBuffers.triangles[_0 + 1];
int v2 = target.meshBuffers.triangles[_0 + 2];
Gizmos.DrawLine(target.meshBuffers.vertexPositions[v0], target.meshBuffers.vertexPositions[v1]);
Gizmos.DrawLine(target.meshBuffers.vertexPositions[v1], target.meshBuffers.vertexPositions[v2]);
Gizmos.DrawLine(target.meshBuffers.vertexPositions[v2], target.meshBuffers.vertexPositions[v0]);
}
}
}
else

2
Runtime/SkinAttachmentData.cs


public int baseVertex;
public Vector3 baseNormal;
public Vector3 targetNormal;
public Vector3 targetOffset;// TODO split this into leaf type item that doesn't perform full resolve
public Vector3 targetOffset;//TODO split this into leaf type item that doesn't perform full resolve
}
}

14
Runtime/SkinAttachmentTarget.cs


triangleNormal /= triangleArea;
triangleArea *= 0.5f;
//var n0 = meshNormals[pose.v0];
//var n1 = meshNormals[pose.v1];
//var n2 = meshNormals[pose.v2];
//var targetNormal = pose.targetCoord.Resolve(n0, n1, n2);
//TODO back to orig. area?
targetBlended += /*pose.area*/triangleArea * target;
targetWeights += /*pose.area*/triangleArea;
targetBlended += triangleArea * target;
targetWeights += triangleArea;
}
var targetNormalRot = Quaternion.FromToRotation(item.baseNormal, meshNormals[item.baseVertex]);

resolveJob.Complete();
Gizmos.color = Color.yellow;
Vector3 size = 0.0002f * Vector3.one;
Gizmos.DrawSphere(resolvedPositions.val[i], 0.0002f);
Gizmos.DrawCube(resolvedPositions.val[i], size);
}
}
}

5
Runtime/SkinDeformation.cs


public Texture2D albedo;
[NonSerialized] public Vector3[] deltaPositions;
[NonSerialized] public Vector3[] deltaTangents;
[NonSerialized] public Vector3[] deltaNormals;
[NonSerialized] public float[] fittedWeights;

ArrayUtils.ResizeChecked(ref deltaPositions, vertexCount);
ArrayUtils.ResizeChecked(ref deltaTangents, vertexCount);
ArrayUtils.ResizeChecked(ref deltaNormals, vertexCount);
ArrayUtils.ResizeChecked(ref fittedWeights, fittedWeightsCount);

deltaTangents[i] = Vector3.zero;
deltaNormals[i] = Vector3.zero;
}

}
ArrayUtils.ResizeChecked(ref deltaPositions, vertexCount);
ArrayUtils.ResizeChecked(ref deltaTangents, vertexCount);
deltaTangents[i] = buffersFrameX.vertexTangents[i] - buffersFrame0.vertexTangents[i];
deltaNormals[i] = buffersFrameX.vertexNormals[i] - buffersFrame0.vertexNormals[i];
}
}

209
Runtime/SkinDeformationClip.cs


using Unity.DemoTeam.Attributes;
#if UNITY_EDITOR
using UnityEditor;
using System.Text.RegularExpressions;
#endif
namespace Unity.DemoTeam.DigitalHuman

{
public unsafe struct Frame
{
public const int FLT_STRIDE = 9;
public const int FLT_OFFSET_POSITION = 0;
public const int FLT_OFFSET_TANGENT = 3;
public const int FLT_OFFSET_NORMAL = 6;
public float* deltaPosTanNrm;
//TODO don't write the data interleaved if we're not going to use it as such!
//public float* deltaPositions;
//public float* deltaTangents;
//public float* deltaNormals;
public float* deltaPositions;
public float* deltaNormals;
public float* fittedWeights;
public Texture2D albedo;
}

if (frameDataPending)
{
Debug.Log("hotloading frame data");
LoadFrameData();
}

//frame.deltaPositions = floatPtr + 0 * frameVertexCount;
//frame.deltaTangents = floatPtr + 3 * frameVertexCount;
//frame.deltaNormals = floatPtr + 6 * frameVertexCount;
frame.deltaPosTanNrm = floatPtr + 0 * frameVertexCount;
frame.fittedWeights = floatPtr + 9 * frameVertexCount;
frame.deltaPositions = floatPtr + 0 * frameVertexCount;
frame.deltaNormals = floatPtr + 3 * frameVertexCount;
frame.fittedWeights = floatPtr + 6 * frameVertexCount;
frame.albedo = frames[frameIndex].albedo;
return frame;
}

{
return (9 * frameVertexCount + frameFittedWeightsCount) * sizeof(float);
return (6 * frameVertexCount + 1 * frameFittedWeightsCount) * sizeof(float);
}
public void PrepareFrame(int frameIndex)

PassThroughWithFirstFrameDelta,
}
public enum InputType
{
ExternalObj,
ProjectAssets,
}
[Header("Asset paths")]
public string keyframesCSV;
[EditableIf("externalLoader", false)] public string meshFolder;
[EditableIf("externalLoader", false)] public string meshPrefix;
[EditableIf("externalLoader", false)] public string albedoFolder;
[EditableIf("externalLoader", false)] public string albedoPrefix;
public bool externalLoader = false;
[EditableIf("externalLoader", true)] public string externalObjPath;
[EditableIf("externalLoader", true)] public string externalObjPattern = "*.obj";
[Header("Sequence")]
public InputType readFrom = InputType.ExternalObj;
[VisibleIf("readFrom", InputType.ExternalObj)] public string externalObjPath;
[VisibleIf("readFrom", InputType.ExternalObj)] public string externalObjPattern = "*.obj";
[VisibleIf("readFrom", InputType.ProjectAssets)] public string meshAssetPath;
[VisibleIf("readFrom", InputType.ProjectAssets)] public string meshAssetPrefix;
[VisibleIf("readFrom", InputType.ProjectAssets)] public string albedoAssetPath;
[VisibleIf("readFrom", InputType.ProjectAssets)] public string albedoAssetPrefix;
[Space]
public bool keyframes = false;
[Tooltip("CSV specifying how the frames are distributed. The first column is ignored. Rows read as follows:\nRow 1: Frame indices\nRow 2: Keyframe indices\nRow 3: Frame progress (0-100) between keys")]
[EditableIf("keyframes", true)]
public TextAsset keyframesCSV;
[Header("Mesh processing")]
[Header("Mesh differential processing")]
[Tooltip("Regions are specified in text files. Each file should contain an array of vertex indices on the form: [i, j, k, ...]")]
public TextAsset[] denoiseRegions;
public float denoiseFactor = 0.0f;
public TextAsset[] denoiseRegion;
public float denoiseStrength = 0.0f;
[Tooltip("Regions are specified in text files. Each file should contain an array of vertex indices on the form: [i, j, k, ...]")]
public TextAsset[] transplantRegions;
public float transplantFactor = 0.0f;
public TextAsset[] transplantRegion;
public float transplantStrength = 0.0f;
public bool solveWelded = false;
public bool solveWelded = true;
//PACKAGETODO cleanup
public TextAsset transferRegion;
public TransferMode transferMode;
[Header("Frame fitting")]

public SkinDeformationFitting.Method fittingMethod = SkinDeformationFitting.Method.LinearLeastSquares;
public SkinDeformationFitting.Param fittingParam = SkinDeformationFitting.Param.DeltaPosition;
public SkinDeformationFittingOptions.Method fittingMethod = SkinDeformationFittingOptions.Method.LinearLeastSquares;
public SkinDeformationFittingOptions.Param fittingParam = SkinDeformationFittingOptions.Param.DeltaPosition;
c.keyframesCSV = c.keyframesCSV.Clone() as string;
c.meshFolder = c.meshFolder.Clone() as string;
c.meshPrefix = c.meshPrefix.Clone() as string;
c.albedoFolder = c.albedoFolder.Clone() as string;
c.albedoPrefix = c.albedoPrefix.Clone() as string;
c.denoiseRegion = c.denoiseRegion.Clone() as TextAsset[];
c.transplantRegion = c.transplantRegion.Clone() as TextAsset[];
c.externalObjPath = c.externalObjPath.Clone() as string;
c.externalObjPattern = c.externalObjPattern.Clone() as string;
c.meshAssetPath = c.meshAssetPath.Clone() as string;
c.meshAssetPrefix = c.meshAssetPrefix.Clone() as string;
c.albedoAssetPath = c.albedoAssetPath.Clone() as string;
c.albedoAssetPrefix = c.albedoAssetPrefix.Clone() as string;
c.denoiseRegions = c.denoiseRegions.Clone() as TextAsset[];
c.transplantRegions = c.transplantRegions.Clone() as TextAsset[];
c.fittedIndices = c.fittedIndices.Clone() as string;
return c;
}

public ImportSettings lastBuild = new ImportSettings();
public ImportSettings lastImport = new ImportSettings();
public ImportSettings importSettings = new ImportSettings();
//--- import settings end ---

Debug.LogError("failed to load frame data (filename = " + filename + ")");
return;
}
/* OLD
for (int i = 0; i != frameCount; i++)
{
frames[i].Allocate(frameVertexCount, frameFittedWeightsCount);
}
using (FileStream stream = File.OpenRead(filename))
{
using (BinaryReader reader = new BinaryReader(stream))
{
int __frameCount = reader.ReadInt32();
int __frameVertexCount = reader.ReadInt32();
int __frameFittedWeightsCount = reader.ReadInt32();
Debug.Assert(__frameCount == frameCount);
Debug.Assert(__frameVertexCount == frameVertexCount);
Debug.Assert(__frameFittedWeightsCount == frameFittedWeightsCount);
var srcCursor = 0;
var srcBuffer = new float[3 * 3 * frameVertexCount + 1 * frameFittedWeightsCount];
var dstBuffer = new byte[4 * srcBuffer.Length];
for (int i = 0; i != frameCount; i++)
{
reader.Read(dstBuffer, 0, dstBuffer.Length);
Buffer.BlockCopy(dstBuffer, 0, srcBuffer, 0, dstBuffer.Length);
for (int j = 0; j != frameVertexCount; j++)
{
frames[i].deltaPositions[j].x = srcBuffer[srcCursor++];
frames[i].deltaPositions[j].y = srcBuffer[srcCursor++];
frames[i].deltaPositions[j].z = srcBuffer[srcCursor++];
frames[i].deltaTangents[j].x = srcBuffer[srcCursor++];
frames[i].deltaTangents[j].y = srcBuffer[srcCursor++];
frames[i].deltaTangents[j].z = srcBuffer[srcCursor++];
frames[i].deltaNormals[j].x = srcBuffer[srcCursor++];
frames[i].deltaNormals[j].y = srcBuffer[srcCursor++];
frames[i].deltaNormals[j].z = srcBuffer[srcCursor++];
}
for (int j = 0; j != frameFittedWeightsCount; j++)
{
frames[i].fittedWeights[j] = srcBuffer[srcCursor++];
}
srcCursor = 0;
}
frameDataPending = false;
}
}
*/
}
public void UnloadFrameData()

writer.Write(frameVertexCount);
writer.Write(frameFittedWeightsCount);
var srcCursor = 0;
var srcBuffer = new float[3 * 3 * frameVertexCount + 1 * frameFittedWeightsCount];
var dstBuffer = new byte[4 * srcBuffer.Length];
var fltCursor = 0;
var fltBuffer = new float[6 * frameVertexCount + 1 * frameFittedWeightsCount];
var dstBuffer = new byte[4 * fltBuffer.Length];
srcCursor = 0;
Debug.Assert(frames[i].fittedWeights.Length == frameFittedWeightsCount, "invalid fitted weights count");
fltCursor = 0;
// write positions
srcBuffer[srcCursor++] = frames[i].deltaPositions[j].x;
srcBuffer[srcCursor++] = frames[i].deltaPositions[j].y;
srcBuffer[srcCursor++] = frames[i].deltaPositions[j].z;
fltBuffer[fltCursor++] = frames[i].deltaPositions[j].x;
fltBuffer[fltCursor++] = frames[i].deltaPositions[j].y;
fltBuffer[fltCursor++] = frames[i].deltaPositions[j].z;
}
srcBuffer[srcCursor++] = frames[i].deltaTangents[j].x;
srcBuffer[srcCursor++] = frames[i].deltaTangents[j].y;
srcBuffer[srcCursor++] = frames[i].deltaTangents[j].z;
srcBuffer[srcCursor++] = frames[i].deltaNormals[j].x;
srcBuffer[srcCursor++] = frames[i].deltaNormals[j].y;
srcBuffer[srcCursor++] = frames[i].deltaNormals[j].z;
// write normals
for (int j = 0; j != frameVertexCount; j++)
{
fltBuffer[fltCursor++] = frames[i].deltaNormals[j].x;
fltBuffer[fltCursor++] = frames[i].deltaNormals[j].y;
fltBuffer[fltCursor++] = frames[i].deltaNormals[j].z;
Debug.Assert(frames[i].fittedWeights.Length == frameFittedWeightsCount, "invalid fitted weights count");
// write fitted weights
srcBuffer[srcCursor++] = frames[i].fittedWeights[j];
fltBuffer[fltCursor++] = frames[i].fittedWeights[j];
Buffer.BlockCopy(srcBuffer, 0, dstBuffer, 0, dstBuffer.Length);
Buffer.BlockCopy(fltBuffer, 0, dstBuffer, 0, dstBuffer.Length);
writer.Write(dstBuffer, 0, dstBuffer.Length);
writer.Flush();

}
}
}
#endif
//--- frame data serialization end ---
#if UNITY_EDITOR
[ContextMenu("Save To StreamingAssets")]
public void SaveToStreamingAssets()
[ContextMenu("Copy To StreamingAssets")]
public void CopyToStreamingAssets()
{
string filenameAsset = AssetDatabase.GetAssetPath(this);
string filenameFrameData = filenameAsset + "_frames.bin";

}
}
#endif
}
#if UNITY_EDITOR
public class SkinDeformationClipBuildProcessor : UnityEditor.Build.IPreprocessBuildWithReport
{
public int callbackOrder { get { return 0; } }
public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
{
var clips = Resources.FindObjectsOfTypeAll<SkinDeformationClip>();
foreach (var clip in clips)
{
clip.SaveToStreamingAssets();
EditorUtility.SetDirty(clip);
}
AssetDatabase.SaveAssets();
}
//--- frame data serialization end ---
#endif
}

35
Runtime/SkinDeformationRenderer.cs


namespace Unity.DemoTeam.DigitalHuman
{
[ExecuteAlways]
[RequireComponent(typeof(SkinnedMeshRenderer))]
[ExecuteAlways, RequireComponent(typeof(SkinnedMeshRenderer))]
public class SkinDeformationRenderer : MeshInstanceBehaviour
{
#if UNITY_EDITOR

{
const int innerLoopBatchCount = 128;//TODO?
var jobPositions = new AddBlendedStridedDeltaJob()
var jobPositions = new AddBlendedDeltaJob()
deltaA = (Vector3*)(frameLo.deltaPosTanNrm + SkinDeformationClip.Frame.FLT_OFFSET_POSITION),
deltaB = (Vector3*)(frameHi.deltaPosTanNrm + SkinDeformationClip.Frame.FLT_OFFSET_POSITION),
stride = SkinDeformationClip.Frame.FLT_STRIDE / 3,
deltaA = (Vector3*)(frameLo.deltaPositions),
deltaB = (Vector3*)(frameHi.deltaPositions),
var jobNormals = new AddBlendedStridedDeltaJob()
var jobNormals = new AddBlendedDeltaJob()
deltaA = (Vector3*)(frameLo.deltaPosTanNrm + SkinDeformationClip.Frame.FLT_OFFSET_NORMAL),
deltaB = (Vector3*)(frameHi.deltaPosTanNrm + SkinDeformationClip.Frame.FLT_OFFSET_NORMAL),
stride = SkinDeformationClip.Frame.FLT_STRIDE / 3,
deltaA = (Vector3*)(frameLo.deltaNormals),
deltaB = (Vector3*)(frameHi.deltaNormals),
output = outputNormals,
cursor = frameFraction,
weight = clipWeight,

}
}
/* PACKAGETODO reuse when data is not interleaved
[BurstCompile(FloatMode = FloatMode.Fast)]
unsafe struct AddBlendedDeltaJob : IJobParallelFor
{

public void Execute(int i)
{
output[i] += weight * Vector3.Lerp(deltaA[i], deltaB[i], cursor);
}
}*/
[BurstCompile(FloatMode = FloatMode.Fast)]
unsafe struct AddBlendedStridedDeltaJob : IJobParallelFor
{
[NativeDisableUnsafePtrRestriction] public Vector3* deltaA;
[NativeDisableUnsafePtrRestriction] public Vector3* deltaB;
[NativeDisableUnsafePtrRestriction] public Vector3* output;
public int stride;
public float cursor;
public float weight;
public void Execute(int i)
{
output[i] += weight * Vector3.Lerp(deltaA[i * stride], deltaB[i * stride], cursor);
}
}
}

11
Runtime/SnappersHeadRenderer.cs


//#define _SNAPPERS_TEXTURE_ARRAYS
using UnityEngine;
using UnityEngine.Serialization;
[ExecuteAlways]
[RequireComponent(typeof(SkinnedMeshRenderer))]
[ExecuteAlways, RequireComponent(typeof(SkinnedMeshRenderer))]
public class SnappersHeadRenderer : MonoBehaviour
{
private SkinnedMeshRenderer smr;

public SnappersHeadDefinition.InstanceData headInstance;
public SnappersHeadDefinition headDefinition;
public Transform headController;
[FormerlySerializedAs("headController")]
public Transform headControllers;
[EnumFlag]
public SnappersHeadDefinition.Warnings warnings;

smr.GetPropertyBlock(smrProps);
{
if (headInstance.shaderParamFloats != null)//PACKAGETODO introduce IsCreated() or similar?
if (headInstance.shaderParamFloats != null)//TODO introduce IsCreated() or similar?
{
SnappersHeadDefinition.ResetShaderParam(ref headInstance);
SnappersHeadDefinition.ApplyShaderParam(ref headInstance, smrProps);

{
if (headDefinition != null)
{
headDefinition.PrepareInstance(ref headInstance, smr, headController, warnings);
headDefinition.PrepareInstance(ref headInstance, smr, headControllers, warnings);
headDefinition.ResolveControllers(ref headInstance);
headDefinition.ResolveBlendShapes(ref headInstance, smr);

2
Runtime/TeethJawDriver.cs


public Vector3 neutralChinPos;
public Vector3 neutralChinDir;
[Range(0.0f, 1.0f)]
[Range(0.0f, 2.0f)]
public float jawForward = 1.0f;
[ContextMenu("Initialize Neutral Position")]

92
Runtime/TeethRenderer.cs


namespace Unity.DemoTeam.DigitalHuman
{
[ExecuteAlways]
[RequireComponent(typeof(Renderer))]
[ExecuteAlways, RequireComponent(typeof(Renderer))]
public class TeethRenderer : MonoBehaviour
{
private Renderer rnd;

rnd.GetPropertyBlock(rndProps);
{
rndProps.Clear();// TODO would be nice if SetVectorArray didn't truncate ...
rndProps.Clear();//TODO would be nice if SetVectorArray didn't truncate ...
rndProps.SetVector("_TeethParams", new Vector4(litPotentialMin, litPotentialMax, litPotentialFalloff));
rndProps.SetVectorArray("_TeethVertexData", vertexData);
rndProps.SetInt("_TeethVertexCount", outputSize);

Gizmos.DrawLine(O + preDir, O + curDir);
}
}
//----
/*
const int NUM_VERTS = 6;
const float NUM_VERTS_FLT = 6.0f;
const int LAST_VERT = NUM_VERTS - 1;
const float PI = 3.14159265359f;
static Vector3 normalize(Vector3 v) { return Vector3.Normalize(v); }
static Vector3 cross(Vector3 a, Vector3 b) { return -Vector3.Cross(a, b); }
static float dot(Vector3 a, Vector3 b) { return Vector3.Dot(a, b); }
static float sign(float s) { return Mathf.Sign(s); }
static float acos(float s) { return Mathf.Acos(s); }
void SphericalPoly_CalcInteriorAngles(Vector3[] P, float[] A)
{
Vector3[] N = new Vector3[NUM_VERTS];
// calc plane normals
// where N[i] = normal of incident plane
// eg. N[i+0] = cross(C, A);
// N[i+1] = cross(A, B);
{
N[0] = normalize(cross(P[LAST_VERT], P[0]));
for (int i = 1; i != NUM_VERTS; i++)
{
N[i] = normalize(cross(P[i - 1], P[i]));
}
}
// calc interior angles
{
string As = " A = [ ";
string Ds = " dot = [ ";
for (int i = 0; i != LAST_VERT; i++)
{
A[i] = PI - sign(dot(N[i], P[i + 1])) * acos(dot(N[i], N[i + 1]));
{
As += A[i] + ", ";
Ds += dot(N[i], P[i + 1]) + ", ";
}
}
A[LAST_VERT] = PI - sign(dot(N[LAST_VERT], P[0])) * acos(dot(N[LAST_VERT], N[0]));
{
As += A[LAST_VERT] + " ]";
Ds += sign(dot(N[LAST_VERT], P[0])) + " ]";
}
Debug.Log(As + "\n" + Ds);
}
}
void SphericalPoly_CalcAreaFromInteriorAngles(float[] A, out float area)
{
float E = 0.0f;
for (int i = 0; i != NUM_VERTS; i++)
{
E += A[i];
}
area = E - (NUM_VERTS_FLT - 2.0f) * PI;
}
void SphericalPoly_CalcAreaFromProjectedPositions(Vector3[] P, out float area)
{
float[] A = new float[NUM_VERTS];
SphericalPoly_CalcInteriorAngles(P, A);
SphericalPoly_CalcAreaFromInteriorAngles(A, out area);
}
void DebugSpherical()
{
if (skyPolygonDebugSphere == null)
return;
Vector3[] P = new Vector3[NUM_VERTS];
for (int i = 0; i != NUM_VERTS; i++)
{
Vector3 vertPos = vertices[i];
//P[i] = normalize(mul(input.worldToTangent, _TeethSkyPolygon[i].xyz - positionWS));
P[i] = normalize(vertPos - skyPolygonDebugSphere.position);
}
float skyIncident;
float maxIncident = 2.0f * Mathf.PI;// hemisphere
SphericalPoly_CalcAreaFromProjectedPositions(P, out skyIncident);
Debug.Log("skyIncident = " + skyIncident + ", maxIncident = " + maxIncident);
}*/
}
}

82
Runtime/Utility/MeshBuffers.cs


using UnityEngine;
using UnityEngine.Profiling;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using Unity.Burst;
namespace Unity.DemoTeam.DigitalHuman
{

public static List<Vector4> __tempVertexTangents = new List<Vector4>();
public static List<Vector3> __tempVertexNormals = new List<Vector3>();
public static Vector4[] __tempVector4;
public Vector3[] vertexTangents;
public Vector4[] vertexTangents;
public Vector3[] vertexNormals;
public int triangleCount;

{
vertexCount = 0;
vertexPositions = new Vector3[vertexCapacity];
vertexTangents = new Vector3[vertexCapacity];
vertexTangents = new Vector4[vertexCapacity];
vertexNormals = new Vector3[vertexCapacity];
triangleCount = 0;

ArrayUtils.ResizeCheckedIfLessThan(ref vertexPositions, vertexCount);
__tempVertexPositions.CopyTo(vertexPositions);
ArrayUtils.ResizeCheckedIfLessThan(ref __tempVector4, vertexCount);
__tempVertexTangents.CopyTo(__tempVector4);
unsafe
{
fixed (Vector3* dst = vertexTangents)
fixed (Vector4* src = __tempVector4)
{
var job = new CopyTangentsJob()
{
dst = dst,
src = src,
};
job.Schedule(vertexCount, 1024).Complete();
}
}
__tempVertexTangents.CopyTo(vertexTangents);
ArrayUtils.ResizeCheckedIfLessThan(ref vertexNormals, vertexCount);
__tempVertexNormals.CopyTo(vertexNormals);

Profiler.EndSample();
}
[BurstCompile]
unsafe struct CopyTangentsJob : IJobParallelFor
{
[NativeDisableUnsafePtrRestriction] public Vector3* dst;
[NativeDisableUnsafePtrRestriction] public Vector4* src;
public void Execute(int i)
{
dst[i].x = src[i].x * src[i].w;
dst[i].y = src[i].y * src[i].w;
dst[i].z = src[i].z * src[i].w;
}
}
{
}
vertexTangents[i] = q * vertexTangents[i];
{
Vector3 tangent3 = q * ((Vector3)vertexTangents[i]);
vertexTangents[i].x = tangent3.x;
vertexTangents[i].y = tangent3.y;
vertexTangents[i].z = tangent3.z;
vertexTangents[i].w = vertexTangents[i].w;
}
{
}
{
}
}
public void ApplySmoothing(MeshAdjacency meshAdjacency, int iterations)

}
}
}
#if UNITY_EDITOR
public void DrawGizmoTriangle(int triangle)
{
int _0 = triangle * 3;
int v0 = triangles[_0];
int v1 = triangles[_0 + 1];
int v2 = triangles[_0 + 2];
Gizmos.DrawLine(vertexPositions[v0], vertexPositions[v1]);
Gizmos.DrawLine(vertexPositions[v1], vertexPositions[v2]);
Gizmos.DrawLine(vertexPositions[v2], vertexPositions[v0]);
}
public void DrawGizmoTriangles(IEnumerable<int> triangleEnumerable)
{
var triangleEnumerator = triangleEnumerable.GetEnumerator();
while (triangleEnumerator.MoveNext())
{
int _0 = triangleEnumerator.Current * 3;
int v0 = triangles[_0];
int v1 = triangles[_0 + 1];
int v2 = triangles[_0 + 2];
Gizmos.DrawLine(vertexPositions[v0], vertexPositions[v1]);
Gizmos.DrawLine(vertexPositions[v1], vertexPositions[v2]);
Gizmos.DrawLine(vertexPositions[v2], vertexPositions[v0]);
}
}
#endif
}
}

140
Runtime/Utility/NativeFrameStream.cs


return ringDataPtr + ringIndex * frameSize;
}
}
/*
public unsafe struct NativeFrameStream2 : IDisposable
{
public string filename;
public int frameCount;
public int frameSize;
public int streamPosition;
public int streamReadAhead;
public int ringCapacity;
public int ringFrameLo;
public int ringFrameHi;
public NativeArray<byte> ringData;
public NativeArray<ReadHandle> ringDataHnd;
public NativeFrameStream2(string filename, int frameCount, int frameSize, int ringCapacity, int ringReadAhead)
{
this.filename = filename;
this.frameCount = frameCount;
this.frameSize = frameSize;
streamPosition = -1;
streamReadAhead = ringReadAhead;
this.ringCapacity = ringCapacity;
ringFrameLo = -1;
ringFrameHi = -1;
ringData = new NativeArray<byte>(this.ringCapacity * this.frameSize, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
ringDataHnd = new NativeArray<ReadHandle>(this.ringCapacity, Allocator.Persistent, NativeArrayOptions.ClearMemory);
}
[System.Diagnostics.Conditional("UNITY_EDITOR")]
void ASSERT_BUFFERS()
{
Debug.Assert(ringData.IsCreated);
}
public void Dispose()
{
for (int i = 0; i != ringCapacity; i++)
{
if (ringDataHnd[i].Status == ReadStatus.InProgress)
ringDataHnd[i].JobHandle.Complete();
}
ringData.Dispose();
ringDataHnd.Dispose();
}
public void Seek(int frameIndex)
{
ASSERT_BUFFERS();
// sanitize user input
frameIndex = Mathf.Clamp(frameIndex, 0, frameCount - 1);
// requested range will be either
// a) fully contained
// b) fully disjoint
// c) extending up
// d) extending down
int frameLo = Mathf.Max(frameIndex - streamReadAhead, 0);
int frameHi = Mathf.Min(frameIndex + streamReadAhead, frameCount - 1);
var fullyContained = (frameLo >= ringFrameLo) && (frameHi <= ringFrameHi);
if (fullyContained)
{
return;// already buffered
}
else
{
var fullyDisjoint = (frameLo > ringFrameHi + 1) || (frameHi < ringFrameLo - 1);
if (fullyDisjoint)
{
ringFrameLo = frameLo;
ringFrameHi = frameHi;
}
else
{
var extendingUp = frameHi > ringFrameHi;
if (extendingUp)
{
frameLo = ringFrameHi + 1;
ringFrameHi = frameHi;
ringFrameLo = ringFrameHi - Mathf.Min(ringCapacity, ringFrameHi - ringFrameLo);
}
else
{
frameHi = ringFrameLo - 1;
ringFrameLo = frameLo;
ringFrameLo = ringFrameHi - Mathf.Min(ringCapacity, ringFrameHi - ringFrameLo);
}
}
}
// request each frame individually
var ringDataPtr = (byte*)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(ringData);
for (int streamIndex = frameLo; streamIndex <= frameHi; streamIndex++)
{
// wait for element in ring
int ringIndex = (streamIndex % ringCapacity);
if (ringDataHnd[ringIndex].Status == ReadStatus.InProgress)
ringDataHnd[ringIndex].JobHandle.Complete();
// schedule the read
ReadCommand cmd;
cmd.Buffer = ringDataPtr + frameSize * ringIndex;
cmd.Offset = frameSize * streamIndex;
cmd.Size = frameSize;
ringDataHnd[ringIndex] = AsyncReadManager.Read(filename, &cmd, 1);
}
}
public void* Read(int frameIndex)
{
ASSERT_BUFFERS();
// sanitize user input
frameIndex = Mathf.Clamp(frameIndex, 0, frameCount - 1);
// seek if frame is not already in ring
if (frameIndex < ringFrameLo || frameIndex > ringFrameHi)
Seek(frameIndex);
// wait for element in ring
int ringIndex = (frameIndex % ringCapacity);
if (ringDataHnd[ringIndex].Status == ReadStatus.InProgress)
ringDataHnd[ringIndex].JobHandle.Complete();
// return the data
byte* ringDataPtr = (byte*)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(ringData);
return ringDataPtr + ringIndex;
}
}
//*/
}

2
Runtime/Utility/NativeMeshObjLoader.cs


Debug.LogFormat("trying {0}", path);
#endif
var text = File.ReadAllText(path);// TODO replace with native variant
var text = File.ReadAllText(path);//TODO replace with native variant
var textSize = text.Length;
// measure the data

2
Runtime/SkinDeformationFittingOptions.cs


namespace Unity.DemoTeam.DigitalHuman
{
public static class SkinDeformationFitting
public static class SkinDeformationFittingOptions
{
public enum Method
{

2
ShaderLibrary/Nodes_Skin/SkinDeformationBlend.hlsl


blendInputsWeight += _BlendInput1_ClipWeight;
}
outAlbedo = lerp(inAlbedo, blendInputsAlbedo, saturate(blendInputsWeight)/* sanity */);
outAlbedo = lerp(inAlbedo, blendInputsAlbedo, saturate(blendInputsWeight));
}
#endif//__SKINDEFORMATIONBLEND_HLSL__

2
ShaderLibrary/Nodes_Skin/SnappersBlend.hlsl


float AddOpAll_upperbound_1 = min(AddOpAll, 1);
float IntersectionNorm = AddOpAll - AddOpAll_upperbound_1 + 1.0;
float IntersectionInv = (1.0 / IntersectionNorm);//* AddOpAll + (1-IntersectionNorm);
float IntersectionInv = (1.0 / IntersectionNorm);// * AddOpAll + (1-IntersectionNorm);
// blend albedo
{

4
package.json


"com.unity.collections": "0.1.1-preview",
"com.unity.jobs": "0.1.1-preview",
"com.unity.mathematics": "1.1.0",
"com.unity.render-pipelines.high-definition": "7.2.1",
"com.unity.timeline": "1.2.12"
"com.unity.render-pipelines.high-definition": "7.3.1",
"com.unity.timeline": "1.2.14"
}
}

27
Editor/SkinDeformationClipBuildProcessor.cs


using System;
using UnityEngine;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
namespace Unity.DemoTeam.DigitalHuman
{
public class SkinDeformationClipBuildProcessor : IPreprocessBuildWithReport
{
public int callbackOrder
{
get { return 0; }
}
public void OnPreprocessBuild(BuildReport report)
{
var clips = Resources.FindObjectsOfTypeAll<SkinDeformationClip>();
foreach (var clip in clips)
{
clip.CopyToStreamingAssets();
EditorUtility.SetDirty(clip);
}
AssetDatabase.SaveAssets();
}
}
}

11
Editor/SkinDeformationClipBuildProcessor.cs.meta


fileFormatVersion: 2
guid: ee60678e600effa4e9dd911e5db8e7fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

37
Editor/Utility/PrefabTransformHierarchyEditor.cs


using UnityEditor;
using UnityEngine;
namespace Unity.DemoTeam.DigitalHuman
{
[CustomEditor(typeof(PrefabTransformHierarchy))]
public class PrefabTransformHierarchyEditor : Editor
{
public override void OnInspectorGUI()
{
var root = target as PrefabTransformHierarchy;
if (root != null)
{
EditorGUI.BeginDisabledGroup(Application.isPlaying);
{
if (GUILayout.Button("Revert transform hierarchy"))
{
var transforms = root.GetComponentsInChildren<Transform>(includeInactive: true);
for (int i = 0; i != transforms.Length; i++)
{
EditorUtility.DisplayProgressBar("Reverting transforms ...", (i + 1) + " / " + transforms.Length, (float)i / transforms.Length);
var transform = transforms[i];
if (transform != null)
{
PrefabUtility.RevertObjectOverride(transforms[i], InteractionMode.UserAction);
}
}
EditorUtility.ClearProgressBar();
}
}
EditorGUI.EndDisabledGroup();
}
}
}
}

11
Editor/Utility/PrefabTransformHierarchyEditor.cs.meta


fileFormatVersion: 2
guid: dcc6c530d8db08544b4d29b1540bf5e6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/Utility/PrefabTransformHierarchy.cs


using UnityEngine;
namespace Unity.DemoTeam.DigitalHuman
{
public class PrefabTransformHierarchy : MonoBehaviour
{
}
}

11
Runtime/Utility/PrefabTransformHierarchy.cs.meta


fileFormatVersion: 2
guid: d30b498bf7a3a084db3e10fc53b91c4e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

/Editor/SkinDeformationClipPreview.cs.meta → /Editor/SkinDeformationClipRegions.cs.meta

/Editor/SkinDeformationClipPreview.cs → /Editor/SkinDeformationClipRegions.cs

/Runtime/SkinDeformationFitting.cs.meta → /Runtime/SkinDeformationFittingOptions.cs.meta

/Runtime/SkinDeformationFitting.cs → /Runtime/SkinDeformationFittingOptions.cs

正在加载...
取消
保存