mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-04-24 23:18:04 -05:00
BlendShapeExporter を準備中
This commit is contained in:
parent
d46819bc85
commit
7e42a8bd12
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public struct SparseBase
|
||||
{
|
||||
public readonly Vector3[] Positions;
|
||||
public readonly Vector3[] Normals;
|
||||
|
||||
public SparseBase(Vector3[] positions, Vector3[] normals)
|
||||
{
|
||||
Positions = positions;
|
||||
Normals = normals;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BlendShapeExporter
|
||||
{
|
||||
public static gltfMorphTarget Export(glTF gltf, int gltfBuffer, Vector3[] positions, Vector3[] normals, SparseBase? sparseBase)
|
||||
{
|
||||
if (sparseBase.HasValue)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
else
|
||||
{
|
||||
// position
|
||||
var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(gltfBuffer, positions, glBufferTarget.ARRAY_BUFFER);
|
||||
gltf.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray();
|
||||
|
||||
// normal
|
||||
var normalAccessorIndex = -1;
|
||||
if (normals != null)
|
||||
{
|
||||
normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(gltfBuffer, normals, glBufferTarget.ARRAY_BUFFER);
|
||||
}
|
||||
gltf.accessors[positionAccessorIndex].max = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray();
|
||||
|
||||
return new gltfMorphTarget
|
||||
{
|
||||
POSITION = positionAccessorIndex,
|
||||
NORMAL = normalAccessorIndex,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 49e5f06c3492116409bc0c0745b5edf7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -15,37 +15,27 @@ namespace UniGLTF
|
|||
{
|
||||
public class BlendShapeBuffer
|
||||
{
|
||||
readonly List<Vector3> m_positions;
|
||||
readonly List<Vector3> m_normals;
|
||||
readonly Vector3[] m_positions;
|
||||
readonly Vector3[] m_normals;
|
||||
|
||||
public BlendShapeBuffer(int reserve)
|
||||
{
|
||||
m_positions = new List<Vector3>(reserve);
|
||||
m_normals = new List<Vector3>(reserve);
|
||||
m_positions = new Vector3[reserve];
|
||||
m_normals = new Vector3[reserve];
|
||||
}
|
||||
|
||||
public void Push(Vector3 position, Vector3 normal)
|
||||
public void Set(int index, Vector3 position, Vector3 normal)
|
||||
{
|
||||
m_positions.Add(position);
|
||||
m_normals.Add(normal);
|
||||
m_positions[index] = position;
|
||||
m_normals[index] = normal;
|
||||
}
|
||||
|
||||
public gltfMorphTarget ToGltf(glTF gltf, int bufferIndex, bool useNormal)
|
||||
public gltfMorphTarget ToGltf(glTF gltf, int gltfBuffer, bool useNormal, SparseBase? sparseBase)
|
||||
{
|
||||
var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, m_positions.ToArray(), glBufferTarget.ARRAY_BUFFER);
|
||||
gltf.accessors[positionAccessorIndex].min = m_positions.Aggregate(m_positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray();
|
||||
gltf.accessors[positionAccessorIndex].max = m_positions.Aggregate(m_positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray();
|
||||
|
||||
var normalAccessorIndex = -1;
|
||||
if (useNormal)
|
||||
{
|
||||
normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, m_normals.ToArray(), glBufferTarget.ARRAY_BUFFER);
|
||||
}
|
||||
return new gltfMorphTarget
|
||||
{
|
||||
POSITION = positionAccessorIndex,
|
||||
NORMAL = normalAccessorIndex,
|
||||
};
|
||||
return BlendShapeExporter.Export(gltf, gltfBuffer,
|
||||
m_positions,
|
||||
useNormal ? m_normals : null,
|
||||
sparseBase);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,11 +103,12 @@ namespace UniGLTF
|
|||
m_weights.Add(new Vector4(boneWeight.weight0, boneWeight.weight1, boneWeight.weight2, boneWeight.weight3));
|
||||
}
|
||||
|
||||
public glTFPrimitives ToGltfPrimitive(glTF gltf, int bufferIndex, int materialIndex, IEnumerable<int> indices)
|
||||
public (glTFPrimitives, SparseBase) ToGltfPrimitive(glTF gltf, int bufferIndex, int materialIndex, IEnumerable<int> indices)
|
||||
{
|
||||
var sparseBase = new SparseBase(m_positions.ToArray(), m_normals.ToArray());
|
||||
var indicesAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, indices.Select(x => (uint)m_vertexIndexMap[x]).ToArray(), glBufferTarget.ELEMENT_ARRAY_BUFFER);
|
||||
var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, m_positions.ToArray(), glBufferTarget.ARRAY_BUFFER);
|
||||
var normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, m_normals.ToArray(), glBufferTarget.ARRAY_BUFFER);
|
||||
var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, sparseBase.Positions, glBufferTarget.ARRAY_BUFFER);
|
||||
var normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, sparseBase.Normals, glBufferTarget.ARRAY_BUFFER);
|
||||
var uvAccessorIndex0 = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, m_uv.ToArray(), glBufferTarget.ARRAY_BUFFER);
|
||||
|
||||
int? jointsAccessorIndex = default;
|
||||
|
|
@ -146,7 +137,7 @@ namespace UniGLTF
|
|||
mode = 4,
|
||||
};
|
||||
|
||||
return primitive;
|
||||
return (primitive, sparseBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,17 @@ namespace UniGLTF
|
|||
{
|
||||
public static class MeshExporter_DividedVertexBuffer
|
||||
{
|
||||
public static (glTFMesh, Dictionary<int, int>) Export(glTF gltf, int bufferIndex,
|
||||
/// <summary>
|
||||
/// Divide vertex buffer(Position, Normal, UV, VertexColor, Skinning and BlendShapes) by submesh usage, then export
|
||||
/// </summary>
|
||||
/// <param name="gltf"></param>
|
||||
/// <param name="gltfBuffer"></param>
|
||||
/// <param name="unityMesh"></param>
|
||||
/// <param name="unityMaterials"></param>
|
||||
/// <param name="axisInverter"></param>
|
||||
/// <param name="settings"></param>
|
||||
/// <returns></returns>
|
||||
public static (glTFMesh, Dictionary<int, int>) Export(glTF gltf, int gltfBuffer,
|
||||
MeshExportInfo unityMesh, List<Material> unityMaterials,
|
||||
IAxisInverter axisInverter, MeshExportSettings settings)
|
||||
{
|
||||
|
|
@ -16,7 +26,7 @@ namespace UniGLTF
|
|||
|
||||
if (settings.ExportTangents)
|
||||
{
|
||||
// support しない
|
||||
// no support
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
|
@ -40,15 +50,14 @@ namespace UniGLTF
|
|||
var indices = mesh.GetIndices(i);
|
||||
var hash = new HashSet<int>(indices);
|
||||
|
||||
// mesh
|
||||
// index の順に attributes を蓄える
|
||||
// aggrigate vertex attributes
|
||||
var buffer = new MeshExportUtil.VertexBuffer(indices.Length, getJointIndex);
|
||||
usedIndices.Clear();
|
||||
for (int k = 0; k < positions.Length; ++k)
|
||||
{
|
||||
if (hash.Contains(k))
|
||||
{
|
||||
// indices から参照される頂点だけを蓄える
|
||||
// aggrigate indices
|
||||
usedIndices.Add(k);
|
||||
buffer.Push(k, axisInverter.InvertVector3(positions[k]), axisInverter.InvertVector3(normals[k]), uv[k].ReverseUV());
|
||||
if (getJointIndex != null)
|
||||
|
|
@ -75,23 +84,25 @@ namespace UniGLTF
|
|||
flipped.Add(t1);
|
||||
flipped.Add(t0);
|
||||
}
|
||||
var gltfPrimitive = buffer.ToGltfPrimitive(gltf, bufferIndex, materialIndex, flipped);
|
||||
var (gltfPrimitive, sparseBase) = buffer.ToGltfPrimitive(gltf, gltfBuffer, materialIndex, flipped);
|
||||
|
||||
// blendShape
|
||||
// blendShape(morph target)
|
||||
for (int j = 0; j < mesh.blendShapeCount; ++j)
|
||||
{
|
||||
var blendShape = new MeshExportUtil.BlendShapeBuffer(indices.Length);
|
||||
|
||||
// index の順に attributes を蓄える
|
||||
// aggriage morph target
|
||||
mesh.GetBlendShapeFrameVertices(j, 0, blendShapePositions, blendShapeNormals, null);
|
||||
int l = 0;
|
||||
foreach (var k in usedIndices)
|
||||
{
|
||||
blendShape.Push(
|
||||
blendShape.Set(l++,
|
||||
axisInverter.InvertVector3(blendShapePositions[k]),
|
||||
axisInverter.InvertVector3(blendShapeNormals[k]));
|
||||
}
|
||||
|
||||
gltfPrimitive.targets.Add(blendShape.ToGltf(gltf, bufferIndex, !settings.ExportOnlyBlendShapePosition));
|
||||
gltfPrimitive.targets.Add(blendShape.ToGltf(gltf, gltfBuffer, !settings.ExportOnlyBlendShapePosition,
|
||||
settings.UseSparseAccessorForMorphTarget ? sparseBase : default));
|
||||
}
|
||||
|
||||
gltfMesh.primitives.Add(gltfPrimitive);
|
||||
|
|
|
|||
|
|
@ -10,11 +10,12 @@ namespace UniGLTF
|
|||
{
|
||||
/// <summary>
|
||||
/// primitive 間で vertex を共有する形で Export する。
|
||||
/// UniVRM-0.71.0 以降は、MeshExporterDivided.Export もある。
|
||||
///
|
||||
/// UniVRM-0.71.0 までの挙動
|
||||
/// * GLB/GLTF は shared(default) と divided を選択可能
|
||||
/// * VRM0 は shared 仕様
|
||||
/// * VRM1 は divided 仕様
|
||||
///
|
||||
/// UniVRM-0.71.0 以降は、MeshExporterDivided.Export もある
|
||||
///
|
||||
/// /// </summary>
|
||||
/// <param name="gltf"></param>
|
||||
/// <param name="bufferIndex"></param>
|
||||
|
|
@ -159,12 +160,13 @@ namespace UniGLTF
|
|||
unityMesh.Mesh, j,
|
||||
settings.UseSparseAccessorForMorphTarget,
|
||||
settings.ExportOnlyBlendShapePosition, axisInverter);
|
||||
if (morphTarget.POSITION < 0 && morphTarget.NORMAL < 0 && morphTarget.TANGENT < 0)
|
||||
if (morphTarget.POSITION < 0)
|
||||
{
|
||||
// Skip empty blendShape.
|
||||
// Shift blendShape's index.
|
||||
continue;
|
||||
}
|
||||
|
||||
// maybe skip
|
||||
var blendShapeName = unityMesh.Mesh.GetBlendShapeName(j);
|
||||
blendShapeIndexMap.Add(j, exportBlendShapes++);
|
||||
targetNames.Add(blendShapeName);
|
||||
|
|
@ -199,7 +201,7 @@ namespace UniGLTF
|
|||
}
|
||||
|
||||
static gltfMorphTarget ExportMorphTarget(glTF gltf, int bufferIndex,
|
||||
Mesh mesh, int j,
|
||||
Mesh mesh, int blendShapeIndex,
|
||||
bool useSparseAccessorForMorphTarget,
|
||||
bool exportOnlyBlendShapePosition,
|
||||
IAxisInverter axisInverter)
|
||||
|
|
@ -215,8 +217,8 @@ namespace UniGLTF
|
|||
//var useTangent = usePosition && blendShapeTangents != null && blendShapeTangents.Length == blendShapeVertices.Length;
|
||||
var useTangent = false;
|
||||
|
||||
var frameCount = mesh.GetBlendShapeFrameCount(j);
|
||||
mesh.GetBlendShapeFrameVertices(j, frameCount - 1, blendShapeVertices, blendShapeNormals, null);
|
||||
var frameCount = mesh.GetBlendShapeFrameCount(blendShapeIndex);
|
||||
mesh.GetBlendShapeFrameVertices(blendShapeIndex, frameCount - 1, blendShapeVertices, blendShapeNormals, null);
|
||||
|
||||
var blendShapePositionAccessorIndex = -1;
|
||||
var blendShapeNormalAccessorIndex = -1;
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ namespace UniVRM10
|
|||
}
|
||||
}
|
||||
var materialIndex = submesh.Material;
|
||||
var gltfPrimitive = buffer.ToGltfPrimitive(storage.Gltf, bufferIndex, materialIndex, indices);
|
||||
var (gltfPrimitive, sparseBase) = buffer.ToGltfPrimitive(storage.Gltf, bufferIndex, materialIndex, indices);
|
||||
|
||||
// blendShape
|
||||
for (int j = 0; j < mesh.MorphTargets.Count; ++j)
|
||||
|
|
@ -136,15 +136,16 @@ namespace UniVRM10
|
|||
{
|
||||
blendShapeNormals = morph.VertexBuffer.Normals.GetSpan<UnityEngine.Vector3>();
|
||||
}
|
||||
int l = 0;
|
||||
foreach (var k in usedIndices)
|
||||
{
|
||||
blendShape.Push(
|
||||
blendShape.Set(l++,
|
||||
blendShapePositions[k],
|
||||
blendShapeNormals.HasValue ? blendShapeNormals.Value[k] : UnityEngine.Vector3.zero
|
||||
);
|
||||
}
|
||||
|
||||
gltfPrimitive.targets.Add(blendShape.ToGltf(storage.Gltf, bufferIndex, !option.removeMorphNormal));
|
||||
gltfPrimitive.targets.Add(blendShape.ToGltf(storage.Gltf, bufferIndex, !option.removeMorphNormal, option.sparse ? sparseBase : default));
|
||||
}
|
||||
|
||||
yield return gltfPrimitive;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user