Tanoda
GLTFastInstantiator.cs
Go to the documentation of this file.
1using GLTFast;
2using System.Collections.Generic;
3using Unity.Collections;
4using UnityEngine;
5public class GLTFastInstantiator : IInstantiator
6{
7
8 public class Settings
9 {
10 public bool skinUpdateWhenOffscreen = true;
11 }
12
13 public class SceneInstance
14 {
15 public List<Camera> cameras { get; private set; }
16
17 public void AddCamera(Camera camera)
18 {
19 if (cameras == null)
20 {
21 cameras = new List<Camera>();
22 }
23 cameras.Add(camera);
24 }
25 }
26
27 protected Settings settings;
28
29 protected ICodeLogger logger;
30
31 protected IGltfReadable gltf;
32
33 protected Transform parent;
34
35 protected Dictionary<uint, GameObject> nodes;
36
40 public SceneInstance sceneInstance { get; protected set; }
41
43 IGltfReadable gltf,
44 Transform parent,
45 ICodeLogger logger = null,
46 Settings settings = null
47 )
48 {
49 this.gltf = gltf;
50 this.parent = parent;
51 this.logger = logger;
52 this.settings = settings ?? new Settings();
53 }
54
55 public virtual void Init()
56 {
57 nodes = new Dictionary<uint, GameObject>();
59 }
60
61 public void CreateNode(
62 uint nodeIndex,
63 Vector3 position,
64 Quaternion rotation,
65 Vector3 scale
66 )
67 {
68 var go = new GameObject();
69 go.transform.localScale = scale;
70 go.transform.localPosition = position;
71 go.transform.localRotation = rotation;
72 nodes[nodeIndex] = go;
73 }
74
75 public void SetParent(uint nodeIndex, uint parentIndex)
76 {
77 if (nodes[nodeIndex] == null || nodes[parentIndex] == null)
78 {
79 logger?.Error(LogCode.HierarchyInvalid);
80 return;
81 }
82 nodes[nodeIndex].transform.SetParent(nodes[parentIndex].transform, false);
83 }
84
85 public virtual void SetNodeName(uint nodeIndex, string name)
86 {
87 nodes[nodeIndex].name = name ?? $"Node-{nodeIndex}";
88 }
89
90 public virtual void AddPrimitive(
91 uint nodeIndex,
92 string meshName,
93 Mesh mesh,
94 int[] materialIndices,
95 uint[] joints = null,
96 uint? rootJoint = null,
97 float[] morphTargetWeights = null,
98 int primitiveNumeration = 0
99 )
100 {
101
102 GameObject meshGo;
103 if (primitiveNumeration == 0)
104 {
105 // Use Node GameObject for first Primitive
106 meshGo = nodes[nodeIndex];
107 }
108 else
109 {
110 meshGo = new GameObject(meshName);
111 meshGo.transform.SetParent(nodes[nodeIndex].transform, false);
112 }
113
114 Renderer renderer;
115
116 var hasMorphTargets = mesh.blendShapeCount > 0;
117 if (joints == null && !hasMorphTargets)
118 {
119 var mf = meshGo.AddComponent<MeshFilter>();
120 mf.mesh = mesh;
121 var mr = meshGo.AddComponent<MeshRenderer>();
122 renderer = mr;
123 }
124 else
125 {
126 var smr = meshGo.AddComponent<SkinnedMeshRenderer>();
127 smr.updateWhenOffscreen = settings.skinUpdateWhenOffscreen;
128 if (joints != null)
129 {
130 var bones = new Transform[joints.Length];
131 for (var j = 0; j < bones.Length; j++)
132 {
133 var jointIndex = joints[j];
134 bones[j] = nodes[jointIndex].transform;
135 }
136 smr.bones = bones;
137 if (rootJoint.HasValue)
138 {
139 smr.rootBone = nodes[rootJoint.Value].transform;
140 }
141 }
142 smr.sharedMesh = mesh;
143 if (morphTargetWeights != null)
144 {
145 for (var i = 0; i < morphTargetWeights.Length; i++)
146 {
147 var weight = morphTargetWeights[i];
148 smr.SetBlendShapeWeight(i, weight);
149 }
150 }
151 renderer = smr;
152 }
153
154 var materials = new Material[materialIndices.Length];
155 for (var index = 0; index < materials.Length; index++)
156 {
157 var material = gltf.GetMaterial(materialIndices[index]) ?? gltf.GetDefaultMaterial();
158 materials[index] = material;
159 }
160
161 renderer.sharedMaterials = materials;
162 }
163
165 uint nodeIndex,
166 string meshName,
167 Mesh mesh,
168 int[] materialIndices,
169 uint instanceCount,
170 NativeArray<Vector3>? positions,
171 NativeArray<Quaternion>? rotations,
172 NativeArray<Vector3>? scales,
173 int primitiveNumeration = 0
174 )
175 {
176 var materials = new Material[materialIndices.Length];
177 for (var index = 0; index < materials.Length; index++)
178 {
179 var material = gltf.GetMaterial(materialIndices[index]) ?? gltf.GetDefaultMaterial();
180 material.enableInstancing = true;
181 materials[index] = material;
182 }
183
184 for (var i = 0; i < instanceCount; i++)
185 {
186 var meshGo = new GameObject($"{meshName}_i{i}");
187 var t = meshGo.transform;
188 t.SetParent(nodes[nodeIndex].transform, false);
189 t.localPosition = positions?[i] ?? Vector3.zero;
190 t.localRotation = rotations?[i] ?? Quaternion.identity;
191 t.localScale = scales?[i] ?? Vector3.one;
192
193 var mf = meshGo.AddComponent<MeshFilter>();
194 mf.mesh = mesh;
195 Renderer renderer = meshGo.AddComponent<MeshRenderer>();
196 renderer.sharedMaterials = materials;
197 }
198 }
199
200 public virtual void AddScene(string name, uint[] nodeIndices)
201 {
202 var go = new GameObject(GLTFastLoader.instance.CurrentFileName);
203 go.transform.SetParent(parent, false);
204
205 if (nodeIndices != null)
206 {
207 foreach (var nodeIndex in nodeIndices)
208 {
209 if (nodes[nodeIndex] != null)
210 {
211 nodes[nodeIndex].transform.SetParent(go.transform, false);
212 nodes[nodeIndex].name = nodes[nodeIndex].name.Replace("(Clone)", "");
213 }
214 }
215 }
217 }
218
219 public void AddCamera(uint nodeIndex, uint cameraIndex)
220 {
221 }
222
223 public void AddScene(string name, uint[] nodeIndices, AnimationClip[] animationClips)
224 {
225 AddScene(name, nodeIndices);
226 }
227}
void CreateNode(uint nodeIndex, Vector3 position, Quaternion rotation, Vector3 scale)
GLTFastInstantiator(IGltfReadable gltf, Transform parent, ICodeLogger logger=null, Settings settings=null)
void AddScene(string name, uint[] nodeIndices, AnimationClip[] animationClips)
virtual void SetNodeName(uint nodeIndex, string name)
void AddPrimitiveInstanced(uint nodeIndex, string meshName, Mesh mesh, int[] materialIndices, uint instanceCount, NativeArray< Vector3 >? positions, NativeArray< Quaternion >? rotations, NativeArray< Vector3 >? scales, int primitiveNumeration=0)
void SetParent(uint nodeIndex, uint parentIndex)
virtual void AddScene(string name, uint[] nodeIndices)
virtual void AddPrimitive(uint nodeIndex, string meshName, Mesh mesh, int[] materialIndices, uint[] joints=null, uint? rootJoint=null, float[] morphTargetWeights=null, int primitiveNumeration=0)
Dictionary< uint, GameObject > nodes
SceneInstance sceneInstance
Contains information about the latest instance of a glTF scene
void AddCamera(uint nodeIndex, uint cameraIndex)
static GLTFastLoader instance
GameObject LastLoadedGameObject
string CurrentFileName