protected override IInstantiator GetDefaultInstantiator(ICodeLogger logger) { var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager; var sceneArchetype = entityManager.CreateArchetype( typeof(Translation), typeof(Rotation), typeof(Scale), typeof(LocalToWorld) // typeof(LinkedEntityGroup) ); sceneRoot = entityManager.CreateEntity(sceneArchetype); #if UNITY_EDITOR entityManager.SetName(sceneRoot, "glTF"); #endif entityManager.SetComponentData(sceneRoot, new Translation { Value = new float3(0, 0, 0) }); entityManager.SetComponentData(sceneRoot, new Rotation { Value = quaternion.identity }); entityManager.SetComponentData(sceneRoot, new Scale { Value = 1 }); // entityManager.AddBuffer<LinkedEntityGroup>(sceneRoot); return(new EntityInstantiator(importer, sceneRoot, logger)); }
protected override IInstantiator GetDefaultInstantiator(ICodeLogger logger) { var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager; var sceneArchetype = entityManager.CreateArchetype( typeof(Translation), typeof(Rotation), typeof(Scale), typeof(LocalToWorld) // typeof(LinkedEntityGroup) ); sceneRoot = entityManager.CreateEntity(sceneArchetype); #if UNITY_EDITOR entityManager.SetName(sceneRoot, string.IsNullOrEmpty(name) ? "glTF" : name); #endif entityManager.SetComponentData(sceneRoot, new Translation { Value = transform.position }); entityManager.SetComponentData(sceneRoot, new Rotation { Value = transform.rotation }); entityManager.SetComponentData(sceneRoot, new Scale { Value = transform.localScale.x }); // entityManager.AddBuffer<LinkedEntityGroup>(sceneRoot); return(new EntityInstantiator(importer, sceneRoot, logger, instantiationSettings)); }
/// <inheritdoc /> public override async Task <bool> Load( string url, IDownloadProvider downloadProvider = null, IDeferAgent deferAgent = null, IMaterialGenerator materialGenerator = null, ICodeLogger logger = null ) { importer = new GltfImport(downloadProvider, deferAgent, materialGenerator); var success = await importer.Load(url); if (success) { var insta = (GameObjectBoundsInstantiator)GetDefaultInstantiator(logger); // Auto-Instantiate if (sceneId >= 0) { success = importer.InstantiateScene(insta, sceneId); currentSceneId = success ? sceneId : (int?)null; } else { success = importer.InstantiateMainScene(insta); currentSceneId = importer.defaultSceneIndex; } sceneInstance = insta.sceneInstance; if (success) { SetBounds(insta); } } return(success); }
public override async Task <bool> Load( string url, IDownloadProvider downloadProvider = null, IDeferAgent deferAgent = null, IMaterialGenerator materialGenerator = null, ICodeLogger logger = null ) { logger = logger ?? new ConsoleLogger(); var success = await base.Load(url, downloadProvider, deferAgent, materialGenerator, logger); if (success) { if (deferAgent != null) { await deferAgent.BreakPoint(); } // Auto-Instantiate if (sceneId >= 0) { InstantiateScene(sceneId, logger); } else { Instantiate(logger); } } return(success); }
public bool AddMorphTarget( IGltfBuffers buffers, int positionAccessorIndex, int normalAccessorIndex, int tangentAccessorIndex, ICodeLogger logger ) { var newMorphTarget = new MorphTargetContext(); var jobHandle = newMorphTarget.ScheduleMorphTargetJobs( buffers, positionAccessorIndex, normalAccessorIndex, tangentAccessorIndex, logger ); if (jobHandle.HasValue) { handles[currentIndex] = jobHandle.Value; contexts[currentIndex] = newMorphTarget; currentIndex++; } else { return(false); } return(true); }
/// <summary> /// Provides glTF export of GameObject based scenes and hierarchies. /// </summary> /// <param name="exportSettings">Export settings</param> /// <param name="deferAgent">Defer agent; decides when/if to preempt /// export to preserve a stable frame rate <seealso cref="IDeferAgent"/></param> /// <param name="logger">Interface for logging (error) messages /// <seealso cref="ConsoleLogger"/></param> public GameObjectExport( ExportSettings exportSettings = null, IDeferAgent deferAgent = null, ICodeLogger logger = null ) { m_Writer = new GltfWriter(exportSettings, deferAgent, logger); }
/// <inheritdoc /> public GameObjectBoundsInstantiator( IGltfReadable gltf, Transform parent, ICodeLogger logger = null, InstantiationSettings settings = null ) : base(gltf, parent, logger, settings) { }
/// <summary> /// Method for manual loading with custom <see cref="IDownloadProvider"/> and <see cref="IDeferAgent"/>. /// </summary> /// <param name="url">URL of the glTF file.</param> /// <param name="downloadProvider">Download Provider for custom loading (e.g. caching or HTTP authorization)</param> /// <param name="deferAgent">Defer Agent takes care of interrupting the /// loading procedure in order to keep the frame rate responsive.</param> /// <param name="materialGenerator">Used to convert glTF materials to <see cref="Material"/> instances</param> /// <param name="logger">Used for message reporting</param> /// <returns>Async Task that loads the glTF's contents</returns> public virtual async Task <bool> Load( string url, IDownloadProvider downloadProvider = null, IDeferAgent deferAgent = null, IMaterialGenerator materialGenerator = null, ICodeLogger logger = null ) { importer = new GltfImport(downloadProvider, deferAgent, materialGenerator, logger); return(await importer.Load(url)); }
/// <summary> /// Creates an instance of the scene specified by the scene index. /// </summary> /// <param name="sceneIndex">Index of the scene to be instantiated</param> /// <param name="logger">Used for message reporting</param> /// <returns>True if instantiation was successful.</returns> public virtual bool InstantiateScene(int sceneIndex, ICodeLogger logger = null) { if (importer == null) { return(false); } var instantiator = GetDefaultInstantiator(logger); var success = importer.InstantiateScene(instantiator, sceneIndex); PostInstantiation(instantiator, success); return(success); }
/// <summary> /// Creates an instance of the main scene /// </summary> /// <param name="logger">Used for message reporting</param> /// <returns>True if instantiation was successful.</returns> public bool Instantiate(ICodeLogger logger = null) { if (importer == null) { return(false); } var instantiator = GetDefaultInstantiator(logger); var success = importer.InstantiateMainScene(instantiator); PostInstantiation(instantiator, success); return(success); }
public EntityInstantiator( IGltfReadable gltf, Entity parent, ICodeLogger logger = null, InstantiationSettings settings = null ) { this.gltf = gltf; this.parent = parent; this.logger = logger; this.settings = settings ?? new InstantiationSettings(); }
/// <summary> /// Constructs a GameObjectInstantiator /// </summary> /// <param name="gltf">glTF to instantiate from</param> /// <param name="parent">Generated GameObjects will get parented to this Transform</param> /// <param name="logger">Custom logger</param> /// <param name="settings">Instantiation settings</param> public GameObjectInstantiator( IGltfReadable gltf, Transform parent, ICodeLogger logger = null, InstantiationSettings settings = null ) { this.gltf = gltf; this.parent = parent; this.logger = logger; this.settings = settings ?? new InstantiationSettings(); }
/// <summary> /// Provides glTF export of GameObject based scenes and hierarchies. /// </summary> /// <param name="exportSettings">Export settings</param> /// <param name="gameObjectExportSettings">GameObject export settings</param> /// <param name="materialExport">Provides material conversion</param> /// <param name="deferAgent">Defer agent; decides when/if to preempt /// export to preserve a stable frame rate <seealso cref="IDeferAgent"/></param> /// <param name="logger">Interface for logging (error) messages /// <seealso cref="ConsoleLogger"/></param> public GameObjectExport( ExportSettings exportSettings = null, GameObjectExportSettings gameObjectExportSettings = null, IMaterialExport materialExport = null, IDeferAgent deferAgent = null, ICodeLogger logger = null ) { m_Settings = gameObjectExportSettings ?? new GameObjectExportSettings(); m_Writer = new GltfWriter(exportSettings, deferAgent, logger); m_MaterialExport = materialExport ?? MaterialExport.GetDefaultMaterialExport(); m_Logger = logger; }
/// <inheritdoc /> public override bool InstantiateScene(int sceneIndex, ICodeLogger logger = null) { base.InstantiateScene(sceneIndex, logger); var instantiator = (GameObjectBoundsInstantiator)GetDefaultInstantiator(logger); var success = base.InstantiateScene(sceneIndex, instantiator); currentSceneId = success ? sceneIndex : (int?)null; sceneInstance = instantiator.sceneInstance; if (success) { SetBounds(instantiator); } return(success); }
static unsafe JobHandle?GetJointsJob( void *input, int count, GLTFComponentType inputType, int inputByteStride, uint4 *output, int outputByteStride, ICodeLogger logger ) { Profiler.BeginSample("GetJointsJob"); JobHandle?jobHandle; switch (inputType) { case GLTFComponentType.UnsignedByte: var jointsUInt8Job = new Jobs.ConvertBoneJointsUInt8ToUInt32Job(); jointsUInt8Job.inputByteStride = inputByteStride > 0 ? inputByteStride : 4; jointsUInt8Job.input = (byte *)input; jointsUInt8Job.outputByteStride = outputByteStride; jointsUInt8Job.result = output; jobHandle = jointsUInt8Job.Schedule(count, GltfImport.DefaultBatchCount); break; case GLTFComponentType.UnsignedShort: var jointsUInt16Job = new Jobs.ConvertBoneJointsUInt16ToUInt32Job(); jointsUInt16Job.inputByteStride = inputByteStride > 0 ? inputByteStride : 8; jointsUInt16Job.input = (byte *)input; jointsUInt16Job.outputByteStride = outputByteStride; jointsUInt16Job.result = output; jobHandle = jointsUInt16Job.Schedule(count, GltfImport.DefaultBatchCount); break; default: logger?.Error(LogCode.TypeUnsupported, "Joints", inputType.ToString()); jobHandle = null; break; } Profiler.EndSample(); return(jobHandle); }
/// <summary> /// Converts an unlit Unity material into a glTF material /// </summary> /// <param name="material">Destination glTF material</param> /// <param name="uMaterial">Source Unity material</param> /// <param name="mainTexProperty">Main texture property ID</param> /// <param name="gltf">Context glTF to export to</param> /// <param name="logger">Custom logger</param> protected static void ExportUnlit( Material material, UnityEngine.Material uMaterial, int mainTexProperty, IGltfWritable gltf, ICodeLogger logger ) { gltf.RegisterExtensionUsage(Extension.MaterialsUnlit); material.extensions = material.extensions ?? new MaterialExtension(); material.extensions.KHR_materials_unlit = new MaterialUnlit(); var pbr = material.pbrMetallicRoughness ?? new PbrMetallicRoughness(); if (uMaterial.HasProperty(k_Color)) { pbr.baseColor = uMaterial.GetColor(k_Color); } if (uMaterial.HasProperty(mainTexProperty)) { var mainTex = uMaterial.GetTexture(mainTexProperty); if (mainTex != null) { if (mainTex is Texture2D) { pbr.baseColorTexture = ExportTextureInfo(mainTex, gltf); if (pbr.baseColorTexture != null) { ExportTextureTransform(pbr.baseColorTexture, uMaterial, mainTexProperty, gltf); } } else { logger?.Error(LogCode.TextureInvalidType, "main", material.name); } } } material.pbrMetallicRoughness = pbr; }
public VertexBufferTexCoords(ICodeLogger logger) : base(logger) { }
public void SetLogger(ICodeLogger logger) { this.logger = logger; }
public VertexBufferTexCoordsBase(ICodeLogger logger) { this.logger = logger; }
public unsafe JobHandle?ScheduleMorphTargetJobs( IGltfBuffers buffers, int positionAccessorIndex, int normalAccessorIndex, int tangentAccessorIndex, ICodeLogger logger ) { Profiler.BeginSample("ScheduleMorphTargetJobs"); buffers.GetAccessor(positionAccessorIndex, out var posAcc, out var posData, out var posByteStride); positions = new Vector3[posAcc.count]; positionsHandle = GCHandle.Alloc(positions, GCHandleType.Pinned); var jobCount = 1; if (posAcc.isSparse && posAcc.bufferView >= 0) { jobCount++; } Accessor nrmAcc = null; void * nrmInput = null; int nrmInputByteStride = 0; if (normalAccessorIndex >= 0) { normals = new Vector3[posAcc.count]; normalsHandle = GCHandle.Alloc(normals, GCHandleType.Pinned); buffers.GetAccessor(normalAccessorIndex, out nrmAcc, out nrmInput, out nrmInputByteStride); if (nrmAcc.isSparse && nrmAcc.bufferView >= 0) { jobCount += 2; } else { jobCount++; } } Accessor tanAcc = null; void * tanInput = null; int tanInputByteStride = 0; if (tangentAccessorIndex >= 0) { tangents = new Vector3[posAcc.count]; tangentsHandle = GCHandle.Alloc(tangents, GCHandleType.Pinned); buffers.GetAccessor(normalAccessorIndex, out tanAcc, out tanInput, out tanInputByteStride); if (tanAcc.isSparse && tanAcc.bufferView >= 0) { jobCount += 2; } else { jobCount++; } } NativeArray <JobHandle> handles = new NativeArray <JobHandle>(jobCount, VertexBufferConfigBase.defaultAllocator); var handleIndex = 0; fixed(void *dest = &(positions[0])) { JobHandle?h = null; if (posData != null) { #if DEBUG if (posAcc.normalized) { Debug.LogError("Normalized Positions will likely produce incorrect results. Please report this error at https://github.com/atteneder/glTFast/issues/new?assignees=&labels=bug&template=bug_report.md&title=Normalized%20Positions"); } #endif h = VertexBufferConfigBase.GetVector3sJob( posData, posAcc.count, posAcc.componentType, posByteStride, (float3 *)dest, 12, posAcc.normalized, false // positional data never needs to be normalized ); if (h.HasValue) { handles[handleIndex] = h.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } if (posAcc.isSparse) { buffers.GetAccessorSparseIndices(posAcc.sparse.indices, out var posIndexData); buffers.GetAccessorSparseValues(posAcc.sparse.values, out var posValueData); var sparseJobHandle = VertexBufferConfigBase.GetVector3sSparseJob( posIndexData, posValueData, posAcc.sparse.count, posAcc.sparse.indices.componentType, posAcc.componentType, (float3 *)dest, 12, dependsOn: ref h, posAcc.normalized ); if (sparseJobHandle.HasValue) { handles[handleIndex] = sparseJobHandle.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } } if (nrmAcc != null) { fixed(void *dest = &(normals[0])) { JobHandle?h = null; if (nrmAcc.bufferView >= 0) { h = VertexBufferConfigBase.GetVector3sJob( nrmInput, nrmAcc.count, nrmAcc.componentType, nrmInputByteStride, (float3 *)dest, 12, nrmAcc.normalized, false // morph target normals are deltas -> don't normalize ); if (h.HasValue) { handles[handleIndex] = h.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } if (nrmAcc.isSparse) { buffers.GetAccessorSparseIndices(nrmAcc.sparse.indices, out var indexData); buffers.GetAccessorSparseValues(nrmAcc.sparse.values, out var valueData); var sparseJobHandle = VertexBufferConfigBase.GetVector3sSparseJob( indexData, valueData, nrmAcc.sparse.count, nrmAcc.sparse.indices.componentType, nrmAcc.componentType, (float3 *)dest, 12, dependsOn: ref h, nrmAcc.normalized ); if (sparseJobHandle.HasValue) { handles[handleIndex] = sparseJobHandle.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } } } if (tanAcc != null) { fixed(void *dest = &(tangents[0])) { JobHandle?h = null; if (tanAcc.bufferView >= 0) { h = VertexBufferConfigBase.GetVector3sJob( tanInput, tanAcc.count, tanAcc.componentType, tanInputByteStride, (float3 *)dest, 12, tanAcc.normalized, false // morph target tangents are deltas -> don't normalize ); if (h.HasValue) { handles[handleIndex] = h.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } if (tanAcc.isSparse) { buffers.GetAccessorSparseIndices(tanAcc.sparse.indices, out var indexData); buffers.GetAccessorSparseValues(tanAcc.sparse.values, out var valueData); var sparseJobHandle = VertexBufferConfigBase.GetVector3sSparseJob( indexData, valueData, tanAcc.sparse.count, tanAcc.sparse.indices.componentType, tanAcc.componentType, (float3 *)dest, 12, dependsOn: ref h, tanAcc.normalized ); if (sparseJobHandle.HasValue) { handles[handleIndex] = sparseJobHandle.Value; handleIndex++; } else { Profiler.EndSample(); return(null); } } } } var handle = (jobCount > 1) ? JobHandle.CombineDependencies(handles) : handles[0]; handles.Dispose(); Profiler.EndSample(); return(handle); }
public EntityInstantiator(IGltfReadable gltf, Entity parent, ICodeLogger logger = null) { this.gltf = gltf; this.parent = parent; this.logger = logger; }
static bool ExportPbrMetallicRoughness( UnityEngine.Material uMaterial, Material material, IGltfWritable gltf, ICodeLogger logger ) { var success = true; var pbr = new PbrMetallicRoughness { metallicFactor = 0, roughnessFactor = 1.0f }; MaskMapImageExport ormImageExport = null; if (uMaterial.IsKeywordEnabled(k_KeywordMaskMap) && uMaterial.HasProperty(k_MaskMap)) { var maskMap = uMaterial.GetTexture(k_MaskMap) as Texture2D; if (maskMap != null) { ormImageExport = new MaskMapImageExport(maskMap); if (AddImageExport(gltf, ormImageExport, out var ormTextureId)) { // TODO: smartly detect if metallic roughness channels are used and not create the // texture info if not. pbr.metallicRoughnessTexture = new TextureInfo { index = ormTextureId }; ExportTextureTransform(pbr.metallicRoughnessTexture, uMaterial, k_MaskMap, gltf); // TODO: smartly detect if occlusion channel is used and not create the // texture info if not. material.occlusionTexture = new OcclusionTextureInfo { index = ormTextureId }; if (uMaterial.HasProperty(k_AORemapMin)) { var occMin = uMaterial.GetFloat(k_AORemapMin); material.occlusionTexture.strength = math.clamp(1 - occMin, 0, 1); var occMax = uMaterial.GetFloat(k_AORemapMax); if (occMax < 1f) { // TODO: remap texture values logger?.Warning(LogCode.RemapUnsupported, "AO"); } } } } } if (uMaterial.HasProperty(k_BaseColor)) { pbr.baseColor = uMaterial.GetColor(k_BaseColor); } else if (uMaterial.HasProperty(k_Color)) { pbr.baseColor = uMaterial.GetColor(k_Color); } if (uMaterial.HasProperty(k_BaseColorMap)) { // TODO if additive particle, render black into alpha // TODO use private Material.GetFirstPropertyNameIdByAttribute here, supported from 2020.1+ var mainTex = uMaterial.GetTexture(k_BaseColorMap); if (mainTex) { if (mainTex is Texture2D) { pbr.baseColorTexture = ExportTextureInfo(mainTex, gltf); ExportTextureTransform(pbr.baseColorTexture, uMaterial, k_BaseColorMap, gltf); } else { logger?.Error(LogCode.TextureInvalidType, "main", uMaterial.name); success = false; } } } if (uMaterial.HasProperty(k_Metallic)) { pbr.metallicFactor = uMaterial.GetFloat(k_Metallic); } if (ormImageExport != null && uMaterial.HasProperty(k_SmoothnessRemapMax)) { pbr.roughnessFactor = uMaterial.GetFloat(k_SmoothnessRemapMax); if (uMaterial.HasProperty(k_SmoothnessRemapMin) && uMaterial.GetFloat(k_SmoothnessRemapMin) > 0) { logger?.Warning(LogCode.RemapUnsupported, "Smoothness"); } } else if (uMaterial.HasProperty(k_Smoothness)) { pbr.roughnessFactor = 1f - uMaterial.GetFloat(k_Smoothness); } material.pbrMetallicRoughness = pbr; return(success); }
protected override IInstantiator GetDefaultInstantiator(ICodeLogger logger) { return(new GameObjectInstantiator(importer, transform, logger)); }
public VertexBufferBonesBase(ICodeLogger logger) { this.logger = logger; }
public VertexBufferBones(ICodeLogger logger) : base(logger) { }
/// <summary> /// Converts a Unity material to a glTF material. /// </summary> /// <param name="uMaterial">Source material</param> /// <param name="material">Resulting material</param> /// <param name="gltf">Associated IGltfWriter. Is used for adding images and textures.</param> /// <param name="logger">Logger used for reporting</param> /// <returns>True if no errors occured, false otherwise</returns> public override bool ConvertMaterial(UnityEngine.Material uMaterial, out Material material, IGltfWritable gltf, ICodeLogger logger) { var success = true; material = new Material { name = uMaterial.name, pbrMetallicRoughness = new PbrMetallicRoughness { metallicFactor = 0, roughnessFactor = 1.0f } }; SetAlphaModeAndCutoff(uMaterial, material); material.doubleSided = IsDoubleSided(uMaterial); // // Emission // if (uMaterial.HasProperty(k_EmissiveColor)) { var emissionColor = uMaterial.GetColor(k_EmissiveColor); // Clamp emissiveColor to 0..1 var maxFactor = math.max(emissionColor.r, math.max(emissionColor.g, emissionColor.b)); if (maxFactor > 1f) { emissionColor.r /= maxFactor; emissionColor.g /= maxFactor; emissionColor.b /= maxFactor; // TODO: use maxFactor as emissiveStrength (KHR_materials_emissive_strength) } material.emissive = emissionColor; } if (uMaterial.HasProperty(k_EmissionColorMap)) { var emissionTex = uMaterial.GetTexture(k_EmissionColorMap); if (emissionTex != null) { if (emissionTex is Texture2D) { material.emissiveTexture = ExportTextureInfo(emissionTex, gltf); ExportTextureTransform(material.emissiveTexture, uMaterial, k_EmissionColorMap, gltf); } else { logger?.Error(LogCode.TextureInvalidType, "emission", material.name); success = false; } } } // // Normal Map // if ( uMaterial.HasProperty(k_NormalMap) && uMaterial.IsKeywordEnabled(k_KeywordNormalMapTangentSpace) ) { var normalTex = uMaterial.GetTexture(k_NormalMap); if (normalTex != null) { if (normalTex is Texture2D) { material.normalTexture = ExportNormalTextureInfo(normalTex, uMaterial, gltf); ExportTextureTransform(material.normalTexture, uMaterial, k_NormalMap, gltf); } else { logger?.Error(LogCode.TextureInvalidType, "normal", uMaterial.name); success = false; } } } var mainTexProperty = uMaterial.HasProperty(k_BaseColorMap) ? k_BaseColorMap : k_MainTex; if (IsUnlit(uMaterial)) { ExportUnlit(material, uMaterial, mainTexProperty, gltf, logger); } else { success &= ExportPbrMetallicRoughness( uMaterial, material, gltf, logger ); } return(success); }
/// <summary> /// Returns an instance of the default instantiator /// </summary> /// <param name="logger">Custom logger to use with the instantiator</param> /// <returns>Default instantiator instance</returns> protected abstract IInstantiator GetDefaultInstantiator(ICodeLogger logger);
public GameObjectBoundsInstantiator(IGltfReadable gltf, Transform parent, ICodeLogger logger = null) : base(gltf, parent, logger) { }
public VertexBufferConfigBase(ICodeLogger logger) { this.logger = logger; }
public VertexBufferConfig(ICodeLogger logger) : base(logger) { }