Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add gltf export and fix morphTarget sparse #581

Merged
merged 4 commits into from
Oct 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Assets/VRM/UniGLTF/Scripts/Format/glTF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -500,5 +500,26 @@ public byte[] ToGlbBytes(SerializerTypes serializer = SerializerTypes.Generated)

return Glb.ToBytes(json, buffers[0].GetBytes());
}

public (string, List<glTFBuffer>) ToGltf(string gltfPath)
{
var f = new JsonFormatter();

// fix buffer path
if (buffers.Count == 1)
{
var withoutExt = Path.GetFileNameWithoutExtension(gltfPath);
buffers[0].uri = $"{withoutExt}.bin";
}
else
{
throw new NotImplementedException();
}

f.GenSerialize(this);
var json = f.ToString().ParseAsJson().ToString(" ");
RemoveUnusedExtensions(json);
return (json, buffers);
}
}
}
14 changes: 10 additions & 4 deletions Assets/VRM/UniGLTF/Scripts/IO/MeshExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ static gltfMorphTarget ExportMorphTarget(glTF gltf, int bufferIndex,
blendShapePositionAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(bufferIndex, accessorCount,
blendShapeVertices,
sparseIndices, sparseIndicesViewIndex,
glBufferTarget.ARRAY_BUFFER);
glBufferTarget.NONE);
}

if (useNormal)
Expand All @@ -315,15 +315,15 @@ static gltfMorphTarget ExportMorphTarget(glTF gltf, int bufferIndex,
blendShapeNormalAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(bufferIndex, accessorCount,
blendShapeNormals,
sparseIndices, sparseIndicesViewIndex,
glBufferTarget.ARRAY_BUFFER);
glBufferTarget.NONE);
}

if (useTangent)
{
blendShapeTangents = sparseIndices.Select(x => blendShapeTangents[x].ReverseZ()).ToArray();
blendShapeTangentAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(bufferIndex, accessorCount,
blendShapeTangents, sparseIndices, sparseIndicesViewIndex,
glBufferTarget.ARRAY_BUFFER);
glBufferTarget.NONE);
}
}
else
Expand Down Expand Up @@ -380,6 +380,10 @@ static gltfMorphTarget ExportMorphTarget(glTF gltf, int bufferIndex,
var gltfMesh = ExportPrimitives(gltf, bufferIndex,
x.Renderer.name,
mesh, materials, unityMaterials);
if (gltfMesh.extras == null)
{
gltfMesh.extras = new glTFMesh_extras();
}

var blendShapeIndexMap = new Dictionary<int, int>();
int exportBlendShapes = 0;
Expand All @@ -395,15 +399,17 @@ static gltfMorphTarget ExportMorphTarget(glTF gltf, int bufferIndex,
}

// maybe skip
var blendShapeName = mesh.GetBlendShapeName(j);
blendShapeIndexMap.Add(j, exportBlendShapes++);
gltfMesh.extras.targetNames.Add(blendShapeName);

//
// all primitive has same blendShape
//
for (int k = 0; k < gltfMesh.primitives.Count; ++k)
{
gltfMesh.primitives[k].targets.Add(morphTarget);
gltfMesh.primitives[k].extras.targetNames.Add(mesh.GetBlendShapeName(j));
gltfMesh.primitives[k].extras.targetNames.Add(blendShapeName);
}
}

Expand Down
53 changes: 45 additions & 8 deletions Assets/VRM/UniGLTF/Scripts/IO/gltfExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,45 @@ namespace UniGLTF
{
public class gltfExporter : IDisposable
{
const string CONVERT_HUMANOID_KEY = UniGLTFVersion.MENU + "/Export";
const string MENU_EXPORT_GLB_KEY = UniGLTFVersion.MENU + "/Export(glb)";
const string MENU_EXPORT_GLTF_KEY = UniGLTFVersion.MENU + "/Export(gltf)";

#if UNITY_EDITOR
[MenuItem(CONVERT_HUMANOID_KEY, true, 1)]
[MenuItem(MENU_EXPORT_GLTF_KEY, true, 1)]
[MenuItem(MENU_EXPORT_GLB_KEY, true, 1)]
private static bool ExportValidate()
{
return Selection.activeObject != null && Selection.activeObject is GameObject;
}

[MenuItem(CONVERT_HUMANOID_KEY, false, 1)]
private static void ExportFromMenu()
[MenuItem(MENU_EXPORT_GLTF_KEY, false, 1)]
private static void ExportGltfFromMenu()
{
ExportFromMenu(false, new MeshExportSettings
{
ExportOnlyBlendShapePosition = false,
UseSparseAccessorForMorphTarget = true,
});
}

[MenuItem(MENU_EXPORT_GLB_KEY, false, 1)]
private static void ExportGlbFromMenu()
{
ExportFromMenu(true, MeshExportSettings.Default);
}

private static void ExportFromMenu(bool isGlb, MeshExportSettings settings)
{
var go = Selection.activeObject as GameObject;

var ext = isGlb ? "glb" : "gltf";

if (go.transform.position == Vector3.zero &&
go.transform.rotation == Quaternion.identity &&
go.transform.localScale == Vector3.one)
{
var path = EditorUtility.SaveFilePanel(
"Save glb", "", go.name + ".glb", "glb");
$"Save {ext}", "", go.name + $".{ext}", $"{ext}");
if (string.IsNullOrEmpty(path))
{
return;
Expand All @@ -41,10 +60,28 @@ private static void ExportFromMenu()
using (var exporter = new gltfExporter(gltf))
{
exporter.Prepare(go);
exporter.Export(MeshExportSettings.Default);
exporter.Export(settings);
}

if (isGlb)
{
var bytes = gltf.ToGlbBytes();
File.WriteAllBytes(path, bytes);
}
else
{
var (json, buffers) = gltf.ToGltf(path);
// without BOM
var encoding = new System.Text.UTF8Encoding(false);
File.WriteAllText(path, json, encoding);
// write to local folder
var dir = Path.GetDirectoryName(path);
foreach (var b in buffers)
{
var bufferPath = Path.Combine(dir, b.uri);
File.WriteAllBytes(bufferPath, b.GetBytes().ToArray());
}
}
var bytes = gltf.ToGlbBytes();
File.WriteAllBytes(path, bytes);

if (path.StartsWithUnityAssetPath())
{
Expand Down