您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
229 行
8.3 KiB
229 行
8.3 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UniGLTF;
|
|
using VrmLib;
|
|
|
|
namespace UniVRM10
|
|
{
|
|
/// <summary>
|
|
/// GLTF -> VrmLib.MeshGroup
|
|
/// </summary>
|
|
public static class MeshReader
|
|
{
|
|
/// <summary>
|
|
/// VertexBufferはひとつでIndexBufferの参照が異なる
|
|
///
|
|
/// VertexBuffer
|
|
/// +----------------------------------+
|
|
/// | |
|
|
/// +----------------------------------+
|
|
/// A A A
|
|
/// | | |
|
|
/// +---------+--------+--------+
|
|
/// | submesh0|submesh1|submesh2|
|
|
/// +---------+--------+--------+
|
|
/// IndexBuffer
|
|
/// </summary>
|
|
static Mesh SharedBufferFromGltf(this glTFMesh x, Vrm10ImportData storage)
|
|
{
|
|
// 先頭を使う
|
|
return FromGltf(storage, x, x.primitives[0], true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// IndexBuffer毎に異なるVertexBufferを参照する
|
|
///
|
|
/// VertexBuffer
|
|
/// +--------+ +--------+ +--------+
|
|
/// |0 | |1 | |2 |
|
|
/// +--------+ +--------+ +--------+
|
|
/// A A A
|
|
/// | | |
|
|
/// +---------+--------+--------+
|
|
/// | submesh0|submesh1|submesh2|
|
|
/// +---------+--------+--------+
|
|
/// IndexBuffer
|
|
/// </summary>
|
|
static Mesh FromGltf(this glTFPrimitives primitive, Vrm10ImportData storage, glTFMesh x)
|
|
{
|
|
return FromGltf(storage, x, primitive, false);
|
|
}
|
|
|
|
static Mesh FromGltf(Vrm10ImportData storage, glTFMesh x, glTFPrimitives primitive, bool isShared)
|
|
{
|
|
var mesh = new Mesh((TopologyType)primitive.mode)
|
|
{
|
|
VertexBuffer = primitive.attributes.FromGltf(storage)
|
|
};
|
|
|
|
if (isShared)
|
|
{
|
|
// create joined index buffer
|
|
mesh.IndexBuffer = storage.CreateAccessor(x.primitives.Select(y => y.indices).ToArray());
|
|
}
|
|
else
|
|
{
|
|
mesh.IndexBuffer = storage.CreateAccessor(primitive.indices);
|
|
}
|
|
|
|
if (mesh.IndexBuffer == null)
|
|
{
|
|
var indices = Enumerable.Range(0, mesh.VertexBuffer.Count).ToArray();
|
|
var na = storage.Data.NativeArrayManager.CreateNativeArray(indices);
|
|
mesh.IndexBuffer = new BufferAccessor(storage.Data.NativeArrayManager, na.Reinterpret<byte>(4), AccessorValueType.UNSIGNED_INT, AccessorVectorType.SCALAR, na.Length);
|
|
}
|
|
|
|
{
|
|
gltf_mesh_extras_targetNames.TryGet(x, out List<string> targetNames);
|
|
|
|
for (int i = 0; i < primitive.targets.Count; ++i)
|
|
{
|
|
var gltfTarget = primitive.targets[i];
|
|
|
|
string targetName = null;
|
|
{
|
|
targetName = targetNames[i];
|
|
}
|
|
var target = new MorphTarget(targetName)
|
|
{
|
|
VertexBuffer = gltfTarget.FromGltf(storage)
|
|
};
|
|
|
|
// validate count
|
|
foreach (var kv in target.VertexBuffer)
|
|
{
|
|
if (kv.Value.Count != mesh.VertexBuffer.Count)
|
|
{
|
|
throw new Exception();
|
|
}
|
|
}
|
|
|
|
mesh.MorphTargets.Add(target);
|
|
}
|
|
}
|
|
|
|
return mesh;
|
|
}
|
|
|
|
static VertexBuffer FromGltf(this glTFAttributes attributes,
|
|
Vrm10ImportData storage)
|
|
{
|
|
var b = new VertexBuffer();
|
|
|
|
if (storage.TryCreateAccessor(attributes.POSITION, out BufferAccessor position))
|
|
{
|
|
b.Add(VertexBuffer.PositionKey, position);
|
|
}
|
|
else
|
|
{
|
|
// position required
|
|
throw new Exception();
|
|
}
|
|
|
|
if (storage.TryCreateAccessor(attributes.NORMAL, out BufferAccessor normal)) b.Add(VertexBuffer.NormalKey, normal);
|
|
if (storage.TryCreateAccessor(attributes.COLOR_0, out BufferAccessor color)) b.Add(VertexBuffer.ColorKey, color);
|
|
if (storage.TryCreateAccessor(attributes.TEXCOORD_0, out BufferAccessor tex0)) b.Add(VertexBuffer.TexCoordKey, tex0);
|
|
if (storage.TryCreateAccessor(attributes.TEXCOORD_1, out BufferAccessor tex1)) b.Add(VertexBuffer.TexCoordKey2, tex1);
|
|
// if(storage.TryCreateAccessor(attributes.TANGENT, out BufferAccessor tangent))b.Add(VertexBuffer.TangentKey, tangent);
|
|
if (storage.TryCreateAccessor(attributes.WEIGHTS_0, out BufferAccessor weights)) b.Add(VertexBuffer.WeightKey, weights);
|
|
if (storage.TryCreateAccessor(attributes.JOINTS_0, out BufferAccessor joints)) b.Add(VertexBuffer.JointKey, joints);
|
|
|
|
return b;
|
|
}
|
|
|
|
static VertexBuffer FromGltf(this gltfMorphTarget target, Vrm10ImportData storage)
|
|
{
|
|
var b = new VertexBuffer();
|
|
storage.CreateBufferAccessorAndAdd(target.POSITION, b, VertexBuffer.PositionKey);
|
|
storage.CreateBufferAccessorAndAdd(target.NORMAL, b, VertexBuffer.NormalKey);
|
|
storage.CreateBufferAccessorAndAdd(target.TANGENT, b, VertexBuffer.TangentKey);
|
|
return b;
|
|
}
|
|
|
|
static bool HasSameVertexBuffer(this glTFPrimitives lhs, glTFPrimitives rhs)
|
|
{
|
|
if (lhs.attributes.POSITION != rhs.attributes.POSITION) return false;
|
|
if (lhs.attributes.NORMAL != rhs.attributes.NORMAL) return false;
|
|
if (lhs.attributes.TEXCOORD_0 != rhs.attributes.TEXCOORD_0) return false;
|
|
if (lhs.attributes.TEXCOORD_1 != rhs.attributes.TEXCOORD_1) return false;
|
|
if (lhs.attributes.COLOR_0 != rhs.attributes.COLOR_0) return false;
|
|
if (lhs.attributes.WEIGHTS_0 != rhs.attributes.WEIGHTS_0) return false;
|
|
if (lhs.attributes.JOINTS_0 != rhs.attributes.JOINTS_0) return false;
|
|
return true;
|
|
}
|
|
|
|
static bool AllPrimitivesHasSameVertexBuffer(this glTFMesh m)
|
|
{
|
|
if (m.primitives.Count <= 1)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
var first = m.primitives[0];
|
|
for (int i = 1; i < m.primitives.Count; ++i)
|
|
{
|
|
if (!first.HasSameVertexBuffer(m.primitives[i]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static MeshGroup FromGltf(this glTFMesh x, Vrm10ImportData storage)
|
|
{
|
|
var group = new MeshGroup(x.name);
|
|
|
|
if (x.primitives.Count == 1)
|
|
{
|
|
var primitive = x.primitives[0];
|
|
var mesh = primitive.FromGltf(storage, x);
|
|
var materialIndex = primitive.material;
|
|
|
|
mesh.Submeshes.Add(
|
|
new Submesh(0, mesh.IndexBuffer.Count, materialIndex));
|
|
|
|
group.Meshes.Add(mesh);
|
|
}
|
|
else if (!x.AllPrimitivesHasSameVertexBuffer())
|
|
{
|
|
int offset = 0;
|
|
foreach (var primitive in x.primitives)
|
|
{
|
|
var mesh = primitive.FromGltf(storage, x);
|
|
var materialIndex = primitive.material;
|
|
|
|
mesh.Submeshes.Add(
|
|
new Submesh(offset, mesh.IndexBuffer.Count, materialIndex));
|
|
offset += mesh.IndexBuffer.Count;
|
|
|
|
group.Meshes.Add(mesh);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// obsolete
|
|
//
|
|
// for VRM
|
|
|
|
var mesh = x.SharedBufferFromGltf(storage);
|
|
int offset = 0;
|
|
foreach (var primitive in x.primitives)
|
|
{
|
|
var materialIndex = primitive.material;
|
|
var count = storage.Gltf.accessors[primitive.indices].count;
|
|
mesh.Submeshes.Add(
|
|
new Submesh(offset, count, materialIndex));
|
|
offset += count;
|
|
}
|
|
|
|
group.Meshes.Add(mesh);
|
|
}
|
|
|
|
return group;
|
|
}
|
|
}
|
|
}
|