2025-04-25 21:14:54 +09:00

144 lines
4.4 KiB
C#

using System.Linq;
using UnityEngine;
using System;
using System.Collections.Generic;
namespace UniVRM10
{
[Serializable]
public sealed class PreviewMeshItem
{
public string Path
{
get;
private set;
}
public SkinnedMeshRenderer SkinnedMeshRenderer
{
get;
private set;
}
public Mesh Mesh
{
get;
private set;
}
public string[] BlendShapeNames
{
get;
private set;
}
public int BlendShapeCount
{
get { return BlendShapeNames.Length; }
}
public Material[] Materials
{
get;
private set;
}
Transform m_transform;
public Vector3 Position
{
get { return m_transform.position; }
}
public Quaternion Rotation
{
get { return m_transform.rotation; }
}
PreviewMeshItem(string path, Transform transform, Material[] materials)
{
Path = path;
m_transform = transform;
Materials = materials;
}
public void Bake(IEnumerable<MorphTargetBinding> values, float weight)
{
if (SkinnedMeshRenderer == null) return;
// Update baked mesh
if (values != null)
{
// clear
for (int i = 0; i < BlendShapeCount; ++i)
{
SkinnedMeshRenderer.SetBlendShapeWeight(i, 0);
}
foreach (var x in values)
{
if (x.RelativePath == Path)
{
if (x.Index >= 0 && x.Index < SkinnedMeshRenderer.sharedMesh.blendShapeCount)
{
SkinnedMeshRenderer.SetBlendShapeWeight(x.Index, x.Weight * weight * MorphTargetBinding.VRM_TO_UNITY);
}
else
{
Debug.LogWarningFormat("Out of range {0}: 0 <= {1} < {2}",
SkinnedMeshRenderer.name,
x.Index,
SkinnedMeshRenderer.sharedMesh.blendShapeCount);
}
}
}
}
SkinnedMeshRenderer.BakeMesh(Mesh);
}
public static PreviewMeshItem Create(Transform t, Transform root,
Func<Material, Material> getOrCreateMaterial)
{
//Debug.Log("create");
var meshFilter = t.GetComponent<MeshFilter>();
var meshRenderer = t.GetComponent<MeshRenderer>();
var skinnedMeshRenderer = t.GetComponent<SkinnedMeshRenderer>();
if (meshFilter != null && meshRenderer != null)
{
// copy
meshRenderer.sharedMaterials = meshRenderer.sharedMaterials.Select(x => getOrCreateMaterial(x)).ToArray();
return new PreviewMeshItem(t.RelativePathFrom(root), t, meshRenderer.sharedMaterials)
{
Mesh = meshFilter.sharedMesh
};
}
else if (skinnedMeshRenderer != null)
{
// copy
skinnedMeshRenderer.sharedMaterials = skinnedMeshRenderer.sharedMaterials.Select(x => getOrCreateMaterial(x)).ToArray();
if (skinnedMeshRenderer.sharedMesh.blendShapeCount > 0)
{
// bake required
var sharedMesh = skinnedMeshRenderer.sharedMesh;
return new PreviewMeshItem(t.RelativePathFrom(root), t, skinnedMeshRenderer.sharedMaterials)
{
SkinnedMeshRenderer = skinnedMeshRenderer,
Mesh = new Mesh(), // for bake
BlendShapeNames = Enumerable.Range(0, sharedMesh.blendShapeCount).Select(x => sharedMesh.GetBlendShapeName(x)).ToArray()
};
}
else
{
return new PreviewMeshItem(t.RelativePathFrom(root), t, skinnedMeshRenderer.sharedMaterials)
{
Mesh = skinnedMeshRenderer.sharedMesh,
};
}
}
else
{
return null;
}
}
}
}