public ImageId SaveImageHDR(Texture2D texture, EHDRTextureType type, int maxSize = -1, string path = null) { if (_texture2d2ImageID.ContainsKey(texture)) { return _texture2d2ImageID[texture]; } string format = ".png"; string[] pathes; if (path == null) { pathes = GetTextureOutPath(texture, format); } else { pathes = ExporterUtils.GetAssetOutPath(path, format); } var exportPath = pathes[0]; var pathInGlTF = pathes[1]; var newtex = GLTFTextureUtils.HDR2RGBD(texture); if (maxSize > 0 && (newtex.width > maxSize || newtex.height > maxSize)) { TextureScale.Bilinear(newtex, maxSize, maxSize); } byte[] content = newtex.EncodeToPNG(); return GenerateImage(content, exportPath, pathInGlTF); }
public static string[] GetAssetOutPath(string assetPath, string format = null) { string pathInArchive = ExporterUtils.CleanPath(Path.GetDirectoryName(assetPath).Replace("Assets/Resources/", "").Replace("Assets/", "")); string exportDir = Path.Combine(ExporterSettings.Export.folder, pathInArchive); if (!Directory.Exists(exportDir)) { Directory.CreateDirectory(exportDir); } string outputFilename = ""; if (format == null) { outputFilename = Path.GetFileName(assetPath); } else { outputFilename = Path.GetFileNameWithoutExtension(assetPath) + format; } outputFilename = ExporterUtils.CleanPath(outputFilename); string exportPath = exportDir + "/" + outputFilename; string pathInGltfFile = pathInArchive + "/" + outputFilename; return(new string[] { exportPath, pathInGltfFile }); }
private void SaveIndices(UnityEngine.Mesh mesh, MeshPrimitive primitive, int i, ref EntryBufferView bufferView) { primitive.Mode = DrawMode.Triangles; if (_mesh2indices.ContainsKey(mesh) && _mesh2indices[mesh].ContainsKey(i)) { primitive.Indices = _mesh2indices[mesh][i]; return; } if (bufferView == null) { bufferView = CreateStreamBufferView(mesh.name + "-indices"); } primitive.Indices = AccessorToId( ExporterUtils.PackToBuffer(bufferView.streamBuffer, mesh.GetTriangles(i), GLTFComponentType.UnsignedShort, (int[] data, int index) => { var offset = index % 3; return data[offset == 0 ? index : offset == 1 ? index + 1 : index - 1]; }), bufferView ); primitive.Indices.Value.Name += "-" + i; if (!_mesh2indices.ContainsKey(mesh)) { _mesh2indices.Add(mesh, new Dictionary<int, AccessorId>()); } _mesh2indices[mesh].Add(i, primitive.Indices); }
public override void Serialize(ExporterEntry entry, Dictionary <string, Extension> extensions, UnityEngine.Object component = null, object options = null) { var material = component as SeinCustomMaterial; var extension = new Sein_customMaterialExtension(); if (material.matScriptPath != null) { if (entry.root.Extensions == null) { entry.root.Extensions = new Dictionary <string, Extension>(); } Sein_customMaterialExtension globalExtension; if (!entry.root.Extensions.ContainsKey(ExtensionName)) { globalExtension = new Sein_customMaterialExtension { matScripts = new List <string>() }; AddExtension(entry.root.Extensions, globalExtension); } else { globalExtension = (Sein_customMaterialExtension)entry.root.Extensions[ExtensionName]; } var pathes = ExporterUtils.GetAssetOutPath(material.matScriptPath); var exportPath = pathes[0]; var pathInGlTF = pathes[1]; if (!File.Exists(exportPath)) { FileUtil.CopyFileOrDirectory(material.matScriptPath, exportPath); } globalExtension.matScripts.Add(pathInGlTF); } extension.className = material.className; extension.cloneForInst = material.cloneForInst; extension.renderOrder = material.renderOrder; extension.transparent = material.transparent; extension.customOptions = material.customOptions; extension.uniformsColor = material.uniformsColor; extension.uniformsTexture = material.uniformsTexture; extension.uniformsCubeTexture = material.uniformsCubeTexture; extension.uniformsFloat = material.uniformsFloat; extension.uniformsFloatVec2 = material.uniformsFloatVec2; extension.uniformsFloatVec3 = material.uniformsFloatVec3; extension.uniformsFloatVec4 = material.uniformsFloatVec4; extension.uniformsFloatMat2 = material.uniformsFloatMat2; extension.uniformsFloatMat3 = material.uniformsFloatMat3; extension.uniformsFloatMat4 = material.uniformsFloatMat4; extension.uniformsInt = material.uniformsInt; extension.uniformsIntVec2 = material.uniformsIntVec2; extension.uniformsIntVec3 = material.uniformsIntVec3; extension.uniformsIntVec4 = material.uniformsIntVec4; AddExtension(extensions, extension); }
public void Export() { List <ExporterEntry> entries = new List <ExporterEntry>(); Transform[] transforms = Selection.GetTransforms(SelectionMode.TopLevel); if (transforms.Length == 0) { var scene = SceneManager.GetActiveScene(); List <GameObject> rootObjects = new List <GameObject>(); scene.GetRootGameObjects(rootObjects); transforms = new Transform[rootObjects.Count]; for (int i = 0; i < rootObjects.Count; i += 1) { transforms[i] = rootObjects[i].transform; } } foreach (Transform tr in transforms) { var go = tr.gameObject; if (go.GetComponent <SeinNode>() == null) { go.AddComponent <SeinNode>(); } } if (!ExporterSettings.Export.splitChunks) { List <Transform> allTrans = new List <Transform>(); foreach (var rootTrans in transforms) { allTrans.AddRange(rootTrans.GetComponentsInChildren <Transform>()); } entries.Add(new ExporterEntry { path = ExporterSettings.Export.GetExportPath(), name = ExporterSettings.Export.name, transforms = allTrans.ToArray() }); } else { foreach (Transform tr in transforms) { entries.Add(new ExporterEntry { path = ExporterSettings.Export.GetExportPath(tr.name), name = ExporterUtils.CleanPath(tr.name), transforms = tr.GetComponentsInChildren <Transform>() }); } } _export.Export(entries); }
public SkinId SaveSkin(Transform tr) { if (root.Skins == null) { root.Skins = new List<GLTF.Schema.Skin>(); } var skinMesh = tr.GetComponent<SkinnedMeshRenderer>(); if (_skin2ID.ContainsKey(skinMesh)) { return _skin2ID[skinMesh]; } var node = tr2node[tr]; var skin = new Skin(); skin.Name = "skeleton-" + skinMesh.rootBone.name + "-" + tr.name; skin.Skeleton = new NodeId { Id = root.Nodes.IndexOf(node), Root = root }; skin.Joints = new List<NodeId>(); foreach (var bone in skinMesh.bones) { if (!tr2node.ContainsKey(bone)) { throw new Exception("You are expoting a skinned mesh '" + node.Name + "', but not select bones!"); } skin.Joints.Add(new NodeId { Id = root.Nodes.IndexOf(tr2node[bone]) }); } // Create invBindMatrices accessor var bufferView = CreateStreamBufferView("invBind-" + skinMesh.rootBone.name + "-" + tr.name); Matrix4x4[] invBindMatrices = new Matrix4x4[skin.Joints.Count]; for (int i = 0; i < skinMesh.bones.Length; ++i) { // Generates inverseWorldMatrix in right-handed coordinate system Matrix4x4 invBind = skinMesh.sharedMesh.bindposes[i]; invBindMatrices[i] = Utils.ConvertMat4LeftToRightHandedness(ref invBind); } skin.InverseBindMatrices = AccessorToId( ExporterUtils.PackToBuffer(bufferView.streamBuffer, invBindMatrices, GLTFComponentType.Float), bufferView ); root.Skins.Add(skin); var id = new SkinId { Id = root.Skins.Count - 1, Root = root }; _skin2ID.Add(skinMesh, id); return id; }
public ImageId SaveImage(Texture2D texture, bool hasTransparency, string path = null) { if (_texture2d2ImageID.ContainsKey(texture)) { return _texture2d2ImageID[texture]; } string format = ".png"; if (!hasTransparency && ExporterSettings.NormalTexture.opaqueType == ENormalTextureType.JPG) { format = ".jpg"; } string[] pathes; if (path == null) { pathes = GetTextureOutPath(texture, format); } else { pathes = ExporterUtils.GetAssetOutPath(path, format); } var exportPath = pathes[0]; var pathInGlTF = pathes[1]; var tex = TextureFlipY( texture, null, newtex => { var maxSize = ExporterSettings.NormalTexture.maxSize; if (newtex.width > maxSize || newtex.height > maxSize) { TextureScale.Bilinear(newtex, maxSize, maxSize); } } ); byte[] content = { }; if (format == ".png") { content = tex.EncodeToPNG(); } else { content = tex.EncodeToJPG(ExporterSettings.NormalTexture.jpgQulity); } return GenerateImage(content, exportPath, pathInGlTF); }
public MaterialId SaveComponentMaterial(SeinCustomMaterial material) { if (root.Materials == null) { root.Materials = new List<GLTF.Schema.Material>(); } var mat = ExporterUtils.ConvertMaterial(material, this); root.Materials.Add(mat); var id = new MaterialId { Id = root.Materials.Count - 1, Root = root }; return id; }
private string SaveAudio(AudioClip clip) { string assetPath = AssetDatabase.GetAssetPath(clip); var pathes = ExporterUtils.GetAssetOutPath(clip); var exportPath = pathes[0]; var pathInGlTF = pathes[1]; if (File.Exists(exportPath)) { return(pathInGlTF); } FileUtil.CopyFileOrDirectory(assetPath, exportPath); return(pathInGlTF); }
private Texture2D TextureFlipY(Texture2D texture, Func<Color, Color> convertColor = null, Action<Texture2D> processTexture = null) { Texture2D newTex; TextureImporter im = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture)) as TextureImporter; if (convertColor == null && (im == null || im.textureType != TextureImporterType.NormalMap)) { // use gpu to speed up newTex = GLTFTextureUtils.flipTexture(texture); } else { int height = texture.height; int width = texture.width; Color[] newTextureColors = new Color[height * width]; ExporterUtils.DoActionForTexture(ref texture, tex => { Color[] textureColors = tex.GetPixels(); for (int i = 0; i < height; ++i) { for (int j = 0; j < width; ++j) { var c = textureColors[(height - i - 1) * width + j]; newTextureColors[i * width + j] = convertColor != null ? convertColor(c) : c; } } } ); newTex = new Texture2D(width, height); newTex.SetPixels(newTextureColors); newTex.Apply(); } if (processTexture != null) { processTexture(newTex); } return newTex; }
public MaterialId SaveNormalMaterial(UnityEngine.Material material) { if (root.Materials == null) { root.Materials = new List<GLTF.Schema.Material>(); } var mid = material.GetInstanceID(); if (_material2ID.ContainsKey(mid)) { return _material2ID[mid]; } var mat = ExporterUtils.ConvertMaterial(material, this); root.Materials.Add(mat); var id = new MaterialId { Id = root.Materials.Count - 1, Root = root }; _material2ID.Add(mid, id); return id; }
private void Clear() { ExporterUtils.FinishExport(); ExtensionManager.FinishExport(); Resources.UnloadUnusedAssets(); }
private List<string> BakeAnimationClip(GLTF.Schema.Animation anim, Transform tr, AnimationClip clip) { var needGenerate = !_animClip2Accessors.ContainsKey(clip); Dictionary<string, Dictionary<GLTFAnimationChannelPath, AnimationCurve[]>> curves = null; Dictionary<string, bool> rotationIsEuler = null; if (needGenerate) { curves = new Dictionary<string, Dictionary<GLTFAnimationChannelPath, AnimationCurve[]>>(); rotationIsEuler = new Dictionary<string, bool>(); } List<string> targets = new List<string>(); foreach (var binding in AnimationUtility.GetCurveBindings(clip)) { var path = binding.path; var curve = AnimationUtility.GetEditorCurve(clip, binding); if (!curves.ContainsKey(path)) { targets.Add(path); if (needGenerate) { curves.Add(path, new Dictionary<GLTFAnimationChannelPath, AnimationCurve[]>()); rotationIsEuler.Add(path, false); } } if (!needGenerate) { continue; } var current = curves[path]; if (binding.propertyName.Contains("m_LocalPosition")) { if (!current.ContainsKey(GLTFAnimationChannelPath.translation)) { current.Add(GLTFAnimationChannelPath.translation, new AnimationCurve[3]); } if (binding.propertyName.Contains(".x")) current[GLTFAnimationChannelPath.translation][0] = curve; else if (binding.propertyName.Contains(".y")) current[GLTFAnimationChannelPath.translation][1] = curve; else if (binding.propertyName.Contains(".z")) current[GLTFAnimationChannelPath.translation][2] = curve; } else if (binding.propertyName.Contains("m_LocalScale")) { if (!current.ContainsKey(GLTFAnimationChannelPath.scale)) { current.Add(GLTFAnimationChannelPath.scale, new AnimationCurve[3]); } if (binding.propertyName.Contains(".x")) current[GLTFAnimationChannelPath.scale][0] = curve; else if (binding.propertyName.Contains(".y")) current[GLTFAnimationChannelPath.scale][1] = curve; else if (binding.propertyName.Contains(".z")) current[GLTFAnimationChannelPath.scale][2] = curve; } else if (binding.propertyName.ToLower().Contains("localrotation")) { if (!current.ContainsKey(GLTFAnimationChannelPath.rotation)) { current.Add(GLTFAnimationChannelPath.rotation, new AnimationCurve[4]); } if (binding.propertyName.Contains(".x")) current[GLTFAnimationChannelPath.rotation][0] = curve; else if (binding.propertyName.Contains(".y")) current[GLTFAnimationChannelPath.rotation][1] = curve; else if (binding.propertyName.Contains(".z")) current[GLTFAnimationChannelPath.rotation][2] = curve; else if (binding.propertyName.Contains(".w")) current[GLTFAnimationChannelPath.rotation][3] = curve; } // Takes into account 'localEuler', 'localEulerAnglesBaked' and 'localEulerAnglesRaw' else if (binding.propertyName.ToLower().Contains("localeuler")) { if (!current.ContainsKey(GLTFAnimationChannelPath.rotation)) { current.Add(GLTFAnimationChannelPath.rotation, new AnimationCurve[3]); rotationIsEuler[path] = true; } if (binding.propertyName.Contains(".x")) current[GLTFAnimationChannelPath.rotation][0] = curve; else if (binding.propertyName.Contains(".y")) current[GLTFAnimationChannelPath.rotation][1] = curve; else if (binding.propertyName.Contains(".z")) current[GLTFAnimationChannelPath.rotation][2] = curve; } //todo: weights } if (!needGenerate) { return targets; } var bufferView = CreateStreamBufferView("animation-" + anim.Name); int nbSamples = (int)(clip.length * 30); float deltaTime = clip.length / nbSamples; var accessors = new List<Dictionary<GLTFAnimationChannelPath, AccessorId>>(); _animClip2Accessors.Add(clip, accessors); foreach (var path in curves.Keys) { var accessor = new Dictionary<GLTFAnimationChannelPath, AccessorId>(); accessors.Add(accessor); float[] times = new float[nbSamples]; Vector3[] translations = null; Vector3[] scales = null; Vector4[] rotations = null; foreach (var curve in curves[path]) { if (curve.Key == GLTFAnimationChannelPath.translation) { translations = new Vector3[nbSamples]; } else if (curve.Key == GLTFAnimationChannelPath.scale) { scales = new Vector3[nbSamples]; } else if (curve.Key == GLTFAnimationChannelPath.rotation) { rotations = new Vector4[nbSamples]; } } for (int i = 0; i < nbSamples; i += 1) { var currentTime = i * deltaTime; times[i] = currentTime; if (translations != null) { var curve = curves[path][GLTFAnimationChannelPath.translation]; translations[i] = new Vector3(curve[0].Evaluate(currentTime), curve[1].Evaluate(currentTime), curve[2].Evaluate(currentTime)); } if (scales != null) { var curve = curves[path][GLTFAnimationChannelPath.scale]; scales[i] = new Vector3(curve[0].Evaluate(currentTime), curve[1].Evaluate(currentTime), curve[2].Evaluate(currentTime)); } if (rotations != null) { var curve = curves[path][GLTFAnimationChannelPath.rotation]; if (rotationIsEuler[path]) { var q = Quaternion.Euler(curve[0].Evaluate(currentTime), curve[1].Evaluate(currentTime), curve[2].Evaluate(currentTime)); rotations[i] = new Vector4(q.x, q.y, q.z, q.w); } else { rotations[i] = new Vector4(curve[0].Evaluate(currentTime), curve[1].Evaluate(currentTime), curve[2].Evaluate(currentTime), curve[3].Evaluate(currentTime)); } } } if (!_animClip2TimeAccessor.ContainsKey(clip)) { var timeView = ExporterUtils.PackToBuffer(bufferView.streamBuffer, times, GLTFComponentType.Float); _animClip2TimeAccessor.Add(clip, AccessorToId(timeView, bufferView)); timeView.Name += "-times"; } AccessorId id = null; if (translations != null) { id = AccessorToId(ExporterUtils.PackToBuffer(bufferView.streamBuffer, translations, GLTFComponentType.Float, (Vector3[] data, int i) => { return Utils.ConvertVector3LeftToRightHandedness(ref data[i]); }), bufferView); accessor.Add(GLTFAnimationChannelPath.translation, id); id.Value.Name += "-" + path + "-" + "translation"; } if (scales != null) { id = AccessorToId(ExporterUtils.PackToBuffer(bufferView.streamBuffer, scales, GLTFComponentType.Float), bufferView); accessor.Add(GLTFAnimationChannelPath.scale, id); id.Value.Name += "-" + path + "-" + "scales"; } if (rotations != null) { id = AccessorToId(ExporterUtils.PackToBuffer(bufferView.streamBuffer, rotations, GLTFComponentType.Float, (Vector4[] data, int i) => { return Utils.ConvertVector4LeftToRightHandedness(ref data[i]); }), bufferView); accessor.Add(GLTFAnimationChannelPath.rotation, id); id.Value.Name += "-" + path + "-" + "rotations"; } } return targets; }
public override void Serialize(ExporterEntry entry, Dictionary <string, Extension> extensions, UnityEngine.Object component = null, object options = null) { if (entry.root.Extensions == null) { entry.root.Extensions = new Dictionary <string, Extension>(); } Sein_spriteExtension globalExtension; if (!entry.root.Extensions.ContainsKey(ExtensionName)) { globalExtension = new Sein_spriteExtension { isGlobal = true }; entry.root.Extensions.Add(ExtensionName, globalExtension); } else { globalExtension = (Sein_spriteExtension)entry.root.Extensions[ExtensionName]; } var sprite = component as SeinSprite; var extension = new Sein_spriteExtension { isGlobal = false }; var sp = sprite; var customMaterial = sprite.GetComponent <SeinCustomMaterial>(); var cacheId = $"w{sp.width}-h{sp.height}-at{sp.atlas.GetInstanceID()}-fn{sp.frameName}-bb{sp.isBillboard}-ft{sp.frustumTest}"; if (customMaterial != null) { cacheId += $"mat{customMaterial.GetInstanceID()}"; } else { cacheId += $"mat{sprite.material.GetInstanceID()}"; } if (!_CAHCE.ContainsKey(entry)) { _CAHCE.Add(entry, new Dictionary <string, int>()); } if (_CAHCE[entry].ContainsKey(cacheId)) { extension.index = _CAHCE[entry][cacheId]; AddExtension(extensions, extension); return; } // process atlases at first ExtensionManager.Serialize(ExtensionManager.GetExtensionName(typeof(Sein_atlasExtensionFactory)), entry, entry.root.Extensions, sprite.atlas); var s = new Sein_spriteExtension.Sprite(); s.width = sprite.width; s.height = sprite.height; s.isBillboard = sprite.isBillboard; s.frustumTest = sprite.frustumTest; s.atlasId = Sein_atlasExtensionFactory.GetAtlasIndex(entry, sprite.atlas); s.frameName = sprite.frameName; GLTF.Schema.Material gltfMat = null; if (customMaterial != null) { gltfMat = ExporterUtils.ConvertMaterial(customMaterial, entry); } else if (sprite.material.shader.name != "Sein/Sprite" && sprite.material.shader.name.Contains("Sein/")) { gltfMat = ExporterUtils.ConvertSeinCustomMaterial(sprite.material, entry); } if (gltfMat != null) { var root = entry.root; if (root.Materials == null) { root.Materials = new List <GLTF.Schema.Material>(); } root.Materials.Add(gltfMat); var id = new MaterialId { Id = root.Materials.Count - 1, Root = root }; s.materialId = id; } globalExtension.sprites.Add(s); var index = globalExtension.sprites.Count - 1; _CAHCE[entry].Add(cacheId, index); extension.index = index; AddExtension(extensions, extension); }
private string[] GetTextureOutPath(Texture2D texture, string format) { return ExporterUtils.GetAssetOutPath(texture, format); }
private Dictionary<string, AccessorId> GenerateAttributes(UnityEngine.Mesh mesh) { if (_mesh2attrs.ContainsKey(mesh)) { return _mesh2attrs[mesh]; } var attrs= new Dictionary<string, AccessorId>(); int stride = GetBufferLength(mesh); var bufferView = CreateByteBufferView(mesh.name + "-primitives", stride * mesh.vertexCount, stride); int offset = 0; attrs.Add("POSITION", PackAttrToBuffer(bufferView, mesh.vertices, offset, (Vector3[] data, int i) => { return Utils.ConvertVector3LeftToRightHandedness(ref data[i]); })); offset += 3 * 4; if (mesh.normals.Length > 0) { attrs.Add("NORMAL", PackAttrToBuffer(bufferView, mesh.normals, offset, (Vector3[] data, int i) => { return Utils.ConvertVector3LeftToRightHandedness(ref data[i]); })); offset += 3 * 4; } if (mesh.colors.Length > 0) { attrs.Add("COLOR_0", PackAttrToBuffer(bufferView, mesh.colors, offset)); offset += 4 * 4; } if (mesh.uv.Length > 0) { attrs.Add("TEXCOORD_0", PackAttrToBuffer(bufferView, mesh.uv, offset)); offset += 2 * 4; } if (mesh.uv2.Length > 0) { attrs.Add("TEXCOORD_1", PackAttrToBuffer(bufferView, mesh.uv2, offset)); offset += 2 * 4; } if (mesh.tangents.Length > 0) { attrs.Add("TANGENT", PackAttrToBuffer(bufferView, mesh.tangents, offset, (Vector4[] data, int i) => { return Utils.ConvertVector4LeftToRightHandedness(ref data[i]); })); offset += 4 * 4; } if (mesh.boneWeights.Length > 0) { attrs.Add("JOINTS_0", PackAttrToBufferShort(bufferView, mesh.boneWeights, offset)); offset += 2 * 4; attrs.Add("WEIGHTS_0", PackAttrToBuffer(bufferView, ExporterUtils.BoneWeightToWeightVec4(mesh.boneWeights), offset)); offset += 4 * 4; } foreach(var attr in attrs) { attr.Value.Value.Name += "-" + attr.Key; } _mesh2attrs.Add(mesh, attrs); return attrs; }
private AccessorId PackAttrToBufferShort<DataType>(EntryBufferView bufferView, DataType[] data, int offset, Func<DataType[], int, DataType> getValueByIndex = null) { var accessor = ExporterUtils.PackToBuffer(bufferView.byteBuffer, data, GLTFComponentType.UnsignedShort, offset, bufferView.view.ByteStride, getValueByIndex); return AccessorToId(accessor, bufferView); }