mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-28 13:54:45 -05:00
Merge pull request #764 from ichi-23/ichi/add_mesh_export_func
MeshExporter に Renderer を必要としない Export 関数を追加 `v0.68.0`
This commit is contained in:
@@ -23,6 +23,132 @@ namespace UniGLTF
|
||||
|
||||
public static class MeshExporter
|
||||
{
|
||||
static glTFMesh ExportPrimitives(glTF gltf, int bufferIndex, Mesh mesh, Material[] meshMaterials, BoneWeight[] boneWeights, int[] jointIndexMap,
|
||||
List<Material> exportedMaterials)
|
||||
{
|
||||
var positions = mesh.vertices.Select(y => y.ReverseZ()).ToArray();
|
||||
var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, 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();
|
||||
|
||||
var normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.normals.Select(y => y.normalized.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER);
|
||||
#if GLTF_EXPORT_TANGENTS
|
||||
var tangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.tangents.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER);
|
||||
#endif
|
||||
var uvAccessorIndex0 = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv.Select(y => y.ReverseUV()).ToArray(), glBufferTarget.ARRAY_BUFFER);
|
||||
var uvAccessorIndex1 = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv2.Select(y => y.ReverseUV()).ToArray(), glBufferTarget.ARRAY_BUFFER);
|
||||
|
||||
var colorAccessorIndex = -1;
|
||||
|
||||
var vColorState = MeshExportInfo.DetectVertexColor(mesh, meshMaterials);
|
||||
if (vColorState == MeshExportInfo.VertexColorState.ExistsAndIsUsed // VColor使っている
|
||||
|| vColorState == MeshExportInfo.VertexColorState.ExistsAndMixed // VColorを使っているところと使っていないところが混在(とりあえずExportする)
|
||||
)
|
||||
{
|
||||
// UniUnlit で Multiply 設定になっている
|
||||
colorAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.colors, glBufferTarget.ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
var weightAccessorIndex = -1;
|
||||
var jointsAccessorIndex = -1;
|
||||
|
||||
if (boneWeights != null && jointIndexMap != null)
|
||||
{
|
||||
weightAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneWeights.Select(y => new Vector4(y.weight0, y.weight1, y.weight2, y.weight3)).ToArray(), glBufferTarget.ARRAY_BUFFER);
|
||||
jointsAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneWeights.Select(y =>
|
||||
new UShort4(
|
||||
(ushort)jointIndexMap[y.boneIndex0],
|
||||
(ushort)jointIndexMap[y.boneIndex1],
|
||||
(ushort)jointIndexMap[y.boneIndex2],
|
||||
(ushort)jointIndexMap[y.boneIndex3])
|
||||
).ToArray(), glBufferTarget.ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
var attributes = new glTFAttributes
|
||||
{
|
||||
POSITION = positionAccessorIndex,
|
||||
};
|
||||
if (normalAccessorIndex != -1)
|
||||
{
|
||||
attributes.NORMAL = normalAccessorIndex;
|
||||
}
|
||||
#if GLTF_EXPORT_TANGENTS
|
||||
if (tangentAccessorIndex != -1)
|
||||
{
|
||||
attributes.TANGENT = tangentAccessorIndex;
|
||||
}
|
||||
#endif
|
||||
if (uvAccessorIndex0 != -1)
|
||||
{
|
||||
attributes.TEXCOORD_0 = uvAccessorIndex0;
|
||||
}
|
||||
if (uvAccessorIndex1 != -1)
|
||||
{
|
||||
attributes.TEXCOORD_1 = uvAccessorIndex1;
|
||||
}
|
||||
if (colorAccessorIndex != -1)
|
||||
{
|
||||
attributes.COLOR_0 = colorAccessorIndex;
|
||||
}
|
||||
if (weightAccessorIndex != -1)
|
||||
{
|
||||
attributes.WEIGHTS_0 = weightAccessorIndex;
|
||||
}
|
||||
if (jointsAccessorIndex != -1)
|
||||
{
|
||||
attributes.JOINTS_0 = jointsAccessorIndex;
|
||||
}
|
||||
|
||||
var gltfMesh = new glTFMesh(mesh.name);
|
||||
var indices = new List<uint>();
|
||||
for (var j = 0; j < mesh.subMeshCount; ++j)
|
||||
{
|
||||
indices.Clear();
|
||||
|
||||
var triangles = mesh.GetIndices(j);
|
||||
if (triangles.Length == 0)
|
||||
{
|
||||
// https://github.com/vrm-c/UniVRM/issues/664
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var i = 0; i < triangles.Length; i += 3)
|
||||
{
|
||||
var i0 = triangles[i];
|
||||
var i1 = triangles[i + 1];
|
||||
var i2 = triangles[i + 2];
|
||||
|
||||
// flip triangle
|
||||
indices.Add((uint)i2);
|
||||
indices.Add((uint)i1);
|
||||
indices.Add((uint)i0);
|
||||
}
|
||||
|
||||
var indicesAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, indices.ToArray(), glBufferTarget.ELEMENT_ARRAY_BUFFER);
|
||||
if (indicesAccessorIndex < 0)
|
||||
{
|
||||
// https://github.com/vrm-c/UniVRM/issues/664
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
var primitives = new glTFPrimitives
|
||||
{
|
||||
attributes = attributes,
|
||||
indices = indicesAccessorIndex,
|
||||
mode = 4, // triangles ?
|
||||
};
|
||||
|
||||
if (meshMaterials != null)
|
||||
{
|
||||
primitives.material = exportedMaterials.IndexOf(meshMaterials[j]);
|
||||
}
|
||||
|
||||
gltfMesh.primitives.Add(primitives);
|
||||
|
||||
}
|
||||
return gltfMesh;
|
||||
}
|
||||
|
||||
static glTFMesh ExportPrimitives(glTF gltf, int bufferIndex,
|
||||
MeshWithRenderer unityMesh, List<Material> unityMaterials,
|
||||
IAxisInverter axisInverter)
|
||||
@@ -328,5 +454,64 @@ namespace UniGLTF
|
||||
yield return (unityMesh.Mesh, gltfMesh, blendShapeIndexMap);
|
||||
}
|
||||
}
|
||||
|
||||
public static (glTFMesh gltfMesh, Dictionary<int, int> blendShapeIndexMap) ExportMesh(glTF gltf, int bufferIndex, Mesh mesh, Renderer renderer, List<Material> exportedMaterials, MeshExportSettings meshExportSettings, IAxisInverter axisInverter)
|
||||
{
|
||||
var meshMaterials = default(Material[]);
|
||||
if (renderer != null)
|
||||
{
|
||||
meshMaterials = renderer.sharedMaterials;
|
||||
}
|
||||
|
||||
var boneWeights = default(BoneWeight[]);
|
||||
var jointIndexMap = default(int[]);
|
||||
if (renderer is SkinnedMeshRenderer skin)
|
||||
{
|
||||
var bones = skin.bones;
|
||||
var uniqueBones = bones.Distinct().ToArray();
|
||||
jointIndexMap = new int[bones.Length];
|
||||
for (var i = 0; i < bones.Length; i++)
|
||||
{
|
||||
jointIndexMap[i] = Array.IndexOf(uniqueBones, bones[i]);
|
||||
}
|
||||
|
||||
boneWeights = mesh.boneWeights;
|
||||
}
|
||||
|
||||
var gltfMesh = ExportPrimitives(gltf, bufferIndex, mesh, meshMaterials, boneWeights, jointIndexMap, exportedMaterials);
|
||||
|
||||
var targetNames = new List<string>();
|
||||
|
||||
var blendShapeIndexMap = new Dictionary<int, int>();
|
||||
int exportBlendShapes = 0;
|
||||
for (int j = 0; j < mesh.blendShapeCount; ++j)
|
||||
{
|
||||
var morphTarget = ExportMorphTarget(gltf, bufferIndex,
|
||||
mesh, j,
|
||||
meshExportSettings.UseSparseAccessorForMorphTarget,
|
||||
meshExportSettings.ExportOnlyBlendShapePosition, axisInverter);
|
||||
if (morphTarget.POSITION < 0 && morphTarget.NORMAL < 0 && morphTarget.TANGENT < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// maybe skip
|
||||
var blendShapeName = mesh.GetBlendShapeName(j);
|
||||
blendShapeIndexMap.Add(j, exportBlendShapes++);
|
||||
targetNames.Add(blendShapeName);
|
||||
|
||||
//
|
||||
// all primitive has same blendShape
|
||||
//
|
||||
for (int k = 0; k < gltfMesh.primitives.Count; ++k)
|
||||
{
|
||||
gltfMesh.primitives[k].targets.Add(morphTarget);
|
||||
}
|
||||
}
|
||||
|
||||
gltf_mesh_extras_targetNames.Serialize(gltfMesh, targetNames);
|
||||
|
||||
return (gltfMesh, blendShapeIndexMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user