mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-13 14:29:38 -05:00
Merge pull request #1007 from ousttrue/feature/impl_morph_target_sparse_for_divided
既存の morphTarget の sparse export を整理して、divided 頂点バッファでも動くようにした
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public static class BlendShapeExporter
|
||||
{
|
||||
public static gltfMorphTarget Export(glTF gltf, int gltfBuffer, Vector3[] positions, Vector3[] normals, bool useSparse)
|
||||
{
|
||||
var accessorCount = positions.Length;
|
||||
if (normals != null && positions.Length != normals.Length)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
int[] sparseIndices = default;
|
||||
if (useSparse)
|
||||
{
|
||||
sparseIndices = Enumerable.Range(0, positions.Length).Where(x => positions[x] != Vector3.zero).ToArray();
|
||||
if (sparseIndices.Length == 0)
|
||||
{
|
||||
// sparse 対象がすべて [0, 0, 0] の場合
|
||||
// new glTFSparse
|
||||
// {
|
||||
// count = 0,
|
||||
// }
|
||||
// のようになる。
|
||||
// たぶん、仕様的にはあり。
|
||||
// 解釈できない場合あり。
|
||||
useSparse = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (useSparse)
|
||||
{
|
||||
if (sparseIndices == null)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
// positions
|
||||
var positionAccessorIndex = -1;
|
||||
if (sparseIndices.Length > 0)
|
||||
{
|
||||
Debug.LogFormat("Sparse {0}/{1}", sparseIndices.Length, positions.Length);
|
||||
var sparseIndicesViewIndex = gltf.ExtendBufferAndGetViewIndex(gltfBuffer, sparseIndices);
|
||||
positionAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(gltfBuffer, accessorCount, positions, sparseIndices, sparseIndicesViewIndex, glBufferTarget.NONE);
|
||||
}
|
||||
|
||||
// normals
|
||||
var normalAccessorIndex = -1;
|
||||
if (normals != null)
|
||||
{
|
||||
var sparseNormalIndices = Enumerable.Range(0, positions.Length).Where(x => normals[x] != Vector3.zero).ToArray();
|
||||
if (sparseNormalIndices.Length > 0)
|
||||
{
|
||||
var sparseNormalIndicesViewIndex = gltf.ExtendBufferAndGetViewIndex(gltfBuffer, sparseNormalIndices);
|
||||
normalAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(gltfBuffer, accessorCount, normals, sparseNormalIndices, sparseNormalIndicesViewIndex, glBufferTarget.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
return new gltfMorphTarget
|
||||
{
|
||||
POSITION = positionAccessorIndex,
|
||||
NORMAL = normalAccessorIndex,
|
||||
};
|
||||
}
|
||||
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();
|
||||
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();
|
||||
|
||||
// normal
|
||||
var normalAccessorIndex = -1;
|
||||
if (normals != null)
|
||||
{
|
||||
normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(gltfBuffer, normals, glBufferTarget.ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
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, bool useSparse)
|
||||
{
|
||||
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,
|
||||
useSparse);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,8 +106,10 @@ namespace UniGLTF
|
||||
public glTFPrimitives ToGltfPrimitive(glTF gltf, int bufferIndex, int materialIndex, IEnumerable<int> indices)
|
||||
{
|
||||
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 positions = m_positions.ToArray();
|
||||
var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, positions, glBufferTarget.ARRAY_BUFFER);
|
||||
var normals = m_normals.ToArray();
|
||||
var normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, normals, glBufferTarget.ARRAY_BUFFER);
|
||||
var uvAccessorIndex0 = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, m_uv.ToArray(), glBufferTarget.ARRAY_BUFFER);
|
||||
|
||||
int? jointsAccessorIndex = default;
|
||||
|
||||
@@ -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 = 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));
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -211,106 +213,41 @@ namespace UniGLTF
|
||||
var useNormal = usePosition && blendShapeNormals != null && blendShapeNormals.Length == blendShapeVertices.Length;
|
||||
// var useNormal = usePosition && blendShapeNormals != null && blendShapeNormals.Length == blendShapeVertices.Length && !exportOnlyBlendShapePosition;
|
||||
|
||||
var blendShapeTangents = mesh.tangents.Select(y => (Vector3)y).ToArray();
|
||||
//var useTangent = usePosition && blendShapeTangents != null && blendShapeTangents.Length == blendShapeVertices.Length;
|
||||
var useTangent = false;
|
||||
// var blendShapeTangents = mesh.tangents.Select(y => (Vector3)y).ToArray();
|
||||
// //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;
|
||||
var blendShapeTangentAccessorIndex = -1;
|
||||
if (useSparseAccessorForMorphTarget)
|
||||
//
|
||||
// invert axis
|
||||
//
|
||||
for (int i = 0; i < blendShapeVertices.Length; ++i)
|
||||
{
|
||||
var accessorCount = blendShapeVertices.Length;
|
||||
var sparseIndices = Enumerable.Range(0, blendShapeVertices.Length)
|
||||
.Where(x => UseSparse(
|
||||
usePosition, blendShapeVertices[x],
|
||||
useNormal, blendShapeNormals[x],
|
||||
useTangent, blendShapeTangents[x]))
|
||||
.ToArray()
|
||||
;
|
||||
|
||||
if (sparseIndices.Length == 0)
|
||||
{
|
||||
usePosition = false;
|
||||
useNormal = false;
|
||||
useTangent = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogFormat("Sparse {0}/{1}", sparseIndices.Length, mesh.vertexCount);
|
||||
}
|
||||
|
||||
var sparseIndicesViewIndex = -1;
|
||||
if (usePosition)
|
||||
{
|
||||
sparseIndicesViewIndex = gltf.ExtendBufferAndGetViewIndex(bufferIndex, sparseIndices);
|
||||
|
||||
blendShapeVertices = sparseIndices.Select(x => axisInverter.InvertVector3(blendShapeVertices[x])).ToArray();
|
||||
blendShapePositionAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(bufferIndex, accessorCount,
|
||||
blendShapeVertices,
|
||||
sparseIndices, sparseIndicesViewIndex,
|
||||
glBufferTarget.NONE);
|
||||
}
|
||||
|
||||
if (useNormal)
|
||||
{
|
||||
blendShapeNormals = sparseIndices.Select(x => axisInverter.InvertVector3(blendShapeNormals[x])).ToArray();
|
||||
blendShapeNormalAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(bufferIndex, accessorCount,
|
||||
blendShapeNormals,
|
||||
sparseIndices, sparseIndicesViewIndex,
|
||||
glBufferTarget.NONE);
|
||||
}
|
||||
|
||||
if (useTangent)
|
||||
{
|
||||
blendShapeTangents = sparseIndices.Select(x => axisInverter.InvertVector3(blendShapeTangents[x])).ToArray();
|
||||
blendShapeTangentAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(bufferIndex, accessorCount,
|
||||
blendShapeTangents, sparseIndices, sparseIndicesViewIndex,
|
||||
glBufferTarget.NONE);
|
||||
}
|
||||
blendShapeVertices[i] = axisInverter.InvertVector3(blendShapeVertices[i]);
|
||||
}
|
||||
else
|
||||
for (int i = 0; i < blendShapeNormals.Length; ++i)
|
||||
{
|
||||
for (int i = 0; i < blendShapeVertices.Length; ++i) blendShapeVertices[i] = axisInverter.InvertVector3(blendShapeVertices[i]);
|
||||
if (usePosition)
|
||||
{
|
||||
blendShapePositionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
|
||||
blendShapeVertices,
|
||||
glBufferTarget.ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
if (useNormal)
|
||||
{
|
||||
for (int i = 0; i < blendShapeNormals.Length; ++i) blendShapeNormals[i] = axisInverter.InvertVector3(blendShapeNormals[i]);
|
||||
blendShapeNormalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
|
||||
blendShapeNormals,
|
||||
glBufferTarget.ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
if (useTangent)
|
||||
{
|
||||
for (int i = 0; i < blendShapeTangents.Length; ++i) blendShapeTangents[i] = axisInverter.InvertVector3(blendShapeTangents[i]);
|
||||
blendShapeTangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
|
||||
blendShapeTangents,
|
||||
glBufferTarget.ARRAY_BUFFER);
|
||||
}
|
||||
blendShapeNormals[i] = axisInverter.InvertVector3(blendShapeNormals[i]);
|
||||
}
|
||||
|
||||
if (blendShapePositionAccessorIndex != -1)
|
||||
var positions = mesh.vertices;
|
||||
for (int i = 0; i < positions.Length; ++i)
|
||||
{
|
||||
gltf.accessors[blendShapePositionAccessorIndex].min = blendShapeVertices.Aggregate(blendShapeVertices[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[blendShapePositionAccessorIndex].max = blendShapeVertices.Aggregate(blendShapeVertices[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray();
|
||||
positions[i] = axisInverter.InvertVector3(positions[i]);
|
||||
}
|
||||
|
||||
return new gltfMorphTarget
|
||||
var normals = mesh.normals;
|
||||
for (int i = 0; i < normals.Length; ++i)
|
||||
{
|
||||
POSITION = blendShapePositionAccessorIndex,
|
||||
NORMAL = blendShapeNormalAccessorIndex,
|
||||
TANGENT = blendShapeTangentAccessorIndex,
|
||||
};
|
||||
normals[i] = axisInverter.InvertVector3(normals[i]);
|
||||
}
|
||||
|
||||
return BlendShapeExporter.Export(gltf, bufferIndex,
|
||||
blendShapeVertices,
|
||||
exportOnlyBlendShapePosition && useNormal ? null : blendShapeNormals,
|
||||
useSparseAccessorForMorphTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,9 +62,9 @@ namespace UniVRM10
|
||||
return "cannot migrate";
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
return "migration error";
|
||||
return $"migration error: {ex}";
|
||||
}
|
||||
|
||||
parser = new GltfParser();
|
||||
|
||||
@@ -93,7 +93,15 @@ namespace UniVRM10
|
||||
{
|
||||
var morphTarget = src.Meshes[meshIndex].MorphTargets[i];
|
||||
positions.AddRange(morphTarget.VertexBuffer.Positions.GetSpan<Vector3>());
|
||||
normals.AddRange(morphTarget.VertexBuffer.Normals.GetSpan<Vector3>());
|
||||
if (morphTarget.VertexBuffer.Normals != null)
|
||||
{
|
||||
normals.AddRange(morphTarget.VertexBuffer.Normals.GetSpan<Vector3>());
|
||||
}
|
||||
else
|
||||
{
|
||||
// fill zero
|
||||
normals.AddRange(Enumerable.Range(0, morphTarget.VertexBuffer.Count).Select(x => Vector3.zero));
|
||||
}
|
||||
}
|
||||
dst.AddBlendShapeFrame(name, 100.0f, positions.ToArray(), normals.ToArray(), null);
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace UniVRM10
|
||||
// blendShape
|
||||
for (int j = 0; j < mesh.MorphTargets.Count; ++j)
|
||||
{
|
||||
var blendShape = new MeshExportUtil.BlendShapeBuffer(indices.Length);
|
||||
var blendShape = new MeshExportUtil.BlendShapeBuffer(usedIndices.Count);
|
||||
|
||||
// index の順に attributes を蓄える
|
||||
var morph = mesh.MorphTargets[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));
|
||||
}
|
||||
|
||||
yield return gltfPrimitive;
|
||||
|
||||
@@ -49,6 +49,11 @@ namespace UniVRM10
|
||||
|
||||
static void ReverseVector3Array(glTF gltf, int accessorIndex, HashSet<int> used)
|
||||
{
|
||||
if (accessorIndex == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!used.Add(accessorIndex))
|
||||
{
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user