123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using Newtonsoft.Json;
- using Siccity.GLTFUtility.Converters;
- using UnityEngine;
- using UnityEngine.Scripting;
- namespace Siccity.GLTFUtility {
- // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#node
- [Preserve] public class GLTFNode {
- #region Serialization
- public string name;
- /// <summary> Indices of child nodes </summary>
- public int[] children;
- /// <summary> Local TRS </summary>
- [JsonConverter(typeof(Matrix4x4Converter))] public Matrix4x4 matrix = Matrix4x4.identity;
- /// <summary> Local position </summary>
- [JsonConverter(typeof(TranslationConverter))] public Vector3 translation = Vector3.zero;
- /// <summary> Local rotation </summary>
- [JsonConverter(typeof(QuaternionConverter))] public Quaternion rotation = Quaternion.identity;
- /// <summary> Local scale </summary>
- [JsonConverter(typeof(Vector3Converter))] public Vector3 scale = Vector3.one;
- public int? mesh;
- public int? skin;
- public int? camera;
- public int? weights;
- public bool ShouldSerializetranslation() { return translation != Vector3.zero; }
- public bool ShouldSerializerotation() { return rotation != Quaternion.identity; }
- public bool ShouldSerializescale() { return scale != Vector3.one; }
- #endregion
- #region Import
- public class ImportResult {
- public int? parent;
- public int[] children;
- public Transform transform;
- public bool IsRoot { get { return !parent.HasValue; } }
- }
- /// <summary> Set local position, rotation and scale </summary>
- public void ApplyTRS(Transform transform) {
- if(matrix!=Matrix4x4.identity)
- matrix.UnpackTRS(ref translation, ref rotation, ref scale);
- transform.localPosition = translation;
- transform.localRotation = rotation;
- transform.localScale = scale;
- }
- public class ImportTask : Importer.ImportTask<ImportResult[]> {
- List<GLTFNode> nodes;
- GLTFMesh.ImportTask meshTask;
- GLTFSkin.ImportTask skinTask;
- List<GLTFCamera> cameras;
- public ImportTask(List<GLTFNode> nodes, GLTFMesh.ImportTask meshTask, GLTFSkin.ImportTask skinTask, List<GLTFCamera> cameras) : base(meshTask, skinTask) {
- this.nodes = nodes;
- this.meshTask = meshTask;
- this.skinTask = skinTask;
- this.cameras = cameras;
- //task = new Task(() => { });
- }
- public override IEnumerator OnCoroutine(Action<float> onProgress = null) {
- // No nodes
- if (nodes == null) {
- if (onProgress != null) onProgress.Invoke(1f);
- IsCompleted = true;
- yield break;
- }
- Result = new ImportResult[nodes.Count];
-
- // Initialize transforms
- for (int i = 0; i < Result.Length; i++) {
- Result[i] = new GLTFNode.ImportResult();
- Result[i].transform = new GameObject().transform;
- Result[i].transform.name = nodes[i].name;
- }
- // Set up hierarchy
- for (int i = 0; i < Result.Length; i++) {
- if (nodes[i].children != null) {
- int[] children = nodes[i].children;
- Result[i].children = children;
- for (int k = 0; k < children.Length; k++) {
- int childIndex = children[k];
- Result[childIndex].parent = i;
- Result[childIndex].transform.parent = Result[i].transform;
- }
- }
- }
- // Apply TRS
- for (int i = 0; i < Result.Length; i++) {
- nodes[i].ApplyTRS(Result[i].transform);
- }
- // Setup components
- for (int i = 0; i < Result.Length; i++) {
- // Setup mesh
- if (nodes[i].mesh.HasValue) {
- GLTFMesh.ImportResult meshResult = meshTask.Result[nodes[i].mesh.Value];
- if (meshResult == null) continue;
- Mesh mesh = meshResult.mesh;
- Renderer renderer;
- if (nodes[i].skin.HasValue) {
- GLTFSkin.ImportResult skin = skinTask.Result[nodes[i].skin.Value];
- renderer = skin.SetupSkinnedRenderer(Result[i].transform.gameObject, mesh, Result);
- } else if (mesh.blendShapeCount > 0) {
- // Blend shapes require skinned mesh renderer
- SkinnedMeshRenderer mr = Result[i].transform.gameObject.AddComponent<SkinnedMeshRenderer>();
- mr.sharedMesh = mesh;
- renderer = mr;
- } else {
- MeshRenderer mr = Result[i].transform.gameObject.AddComponent<MeshRenderer>();
- MeshFilter mf = Result[i].transform.gameObject.AddComponent<MeshFilter>();
- renderer = mr;
- mf.sharedMesh = mesh;
- }
- //Materials
- renderer.materials = meshResult.materials;
- if (string.IsNullOrEmpty(Result[i].transform.name)) Result[i].transform.name = "node" + i;
- } else {
- if (string.IsNullOrEmpty(Result[i].transform.name)) Result[i].transform.name = "node" + i;
- }
- // Setup camera
- if (nodes[i].camera.HasValue) {
- GLTFCamera cameraData = cameras[nodes[i].camera.Value];
- Camera camera = Result[i].transform.gameObject.AddComponent<Camera>();
- Result[i].transform.localRotation = Result[i].transform.localRotation * Quaternion.Euler(0, 180, 0);
- if (cameraData.type == CameraType.orthographic) {
- camera.orthographic = true;
- camera.nearClipPlane = cameraData.orthographic.znear;
- camera.farClipPlane = cameraData.orthographic.zfar;
- camera.orthographicSize = cameraData.orthographic.ymag;
- } else {
- camera.orthographic = false;
- camera.nearClipPlane = cameraData.perspective.znear;
- if (cameraData.perspective.zfar.HasValue) camera.farClipPlane = cameraData.perspective.zfar.Value;
- if (cameraData.perspective.aspectRatio.HasValue) camera.aspect = cameraData.perspective.aspectRatio.Value;
- camera.fieldOfView = Mathf.Rad2Deg * cameraData.perspective.yfov;
- }
- }
- }
- IsCompleted = true;
- }
- }
- #endregion
- #region Export
- public class ExportResult : GLTFNode {
- [JsonIgnore] public MeshRenderer renderer;
- [JsonIgnore] public MeshFilter filter;
- [JsonIgnore] public SkinnedMeshRenderer skinnedRenderer;
- }
- public static List<ExportResult> Export(Transform root) {
- List<ExportResult> nodes = new List<ExportResult>();
- CreateNodeListRecursive(root, nodes);
- return nodes;
- }
- private static void CreateNodeListRecursive(Transform transform, List<ExportResult> nodes) {
- ExportResult node = new ExportResult();
- node.name = transform.name;
- node.translation = transform.localPosition;
- node.rotation = transform.localRotation;
- node.scale = transform.localScale;
- node.renderer = transform.gameObject.GetComponent<MeshRenderer>();
- node.filter = transform.gameObject.GetComponent<MeshFilter>();
- node.skinnedRenderer = transform.gameObject.GetComponent<SkinnedMeshRenderer>();
- nodes.Add(node);
- if (transform.childCount > 0) {
- if (transform.childCount > 0) {
- node.children = new int[transform.childCount];
- for (int i = 0; i < node.children.Length; i++) {
- Transform child = transform.GetChild(i);
- node.children[i] = nodes.Count;
- CreateNodeListRecursive(child, nodes);
- }
- }
- }
- }
- #endregion
- }
- public static class GLTFNodeExtensions {
- #region Import
- /// <summary> Returns the root if there is one, otherwise creates a new empty root </summary>
- public static GameObject GetRoot(this GLTFNode.ImportResult[] nodes) {
- GLTFNode.ImportResult[] roots = nodes.Where(x => x.IsRoot).ToArray();
- if (roots.Length == 1) return roots[0].transform.gameObject;
- else {
- GameObject root = new GameObject("Root");
- for (int i = 0; i < roots.Length; i++) {
- roots[i].transform.parent = root.transform;
- }
- return root;
- }
- }
- #endregion
- }
- }
|