Last active
February 9, 2020 18:08
-
-
Save gleblebedev/1a6dfd9ce58ad8e1b417abbd23f65ecf to your computer and use it in GitHub Desktop.
Revisions
-
gleblebedev revised this gist
Aug 3, 2017 . 1 changed file with 24 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -323,8 +323,7 @@ private void WriteObject(string prefix, GameObject obj, HashSet<Renderer> exclud WriteAttribute(subSubPrefix, "Height Map", "Image;" + heightmapFileName); WriteAttribute(subSubPrefix, "Material", "Material;"+ materialFileName); WriteTerrainMaterial(terrain, Path.Combine(_assetsFolder, materialFileName)); WriteAttribute(subSubPrefix, "Vertex Spacing", new Vector3(terrainSize.x / w, (max - min), terrainSize.z / h)); Directory.CreateDirectory(Path.GetDirectoryName(Path.Combine(_assetsFolder, heightmapFileName))); using (var imageFile = File.Open(Path.Combine(_assetsFolder, heightmapFileName), FileMode.Create, FileAccess.Write, @@ -638,8 +637,9 @@ private void WriteMesh(BinaryWriter writer, Mesh _mesh) writer.Write(maxZ); } } private void WriteTerrainMaterial(Terrain terrain, string materialFileName) { SplatPrototype[] textures = terrain.terrainData.splatPrototypes; Directory.CreateDirectory(Path.GetDirectoryName(materialFileName)); using (var writer = XmlWriter.Create(materialFileName)) { @@ -653,6 +653,19 @@ private void WriteTerrainMaterial(SplatPrototype[] textures, string materialFile writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); writer.WriteStartElement("parameter"); writer.WriteAttributeString("name", "UOffset"); writer.WriteAttributeString("value", Format(new Vector4(terrain.terrainData.size.x,0,0,0))); writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); writer.WriteStartElement("parameter"); writer.WriteAttributeString("name", "VOffset"); writer.WriteAttributeString("value", Format(new Vector4(0, terrain.terrainData.size.z, 0, 0))); writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); WriteTexture(textures[0].texture, writer, "diffuse"); writer.WriteEndElement(); writer.WriteEndDocument(); @@ -1035,6 +1048,10 @@ private void WriteAttribute(string prefix, string name, Vector3 pos) { WriteAttribute(prefix, name, string.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", pos.x, pos.y, pos.z)); } private void WriteAttribute(string prefix, string name, Vector4 pos) { WriteAttribute(prefix, name, Format(pos)); } private void WriteAttribute(string prefix, string name, Quaternion pos) { @@ -1056,7 +1073,10 @@ private static string Format(Color pos) { return string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", pos.r, pos.g, pos.b, pos.a); } private static string Format(Vector4 pos) { return string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", pos.x, pos.y, pos.z, pos.w); } private void WriteAttribute(string prefix, string name, bool flag) { WriteAttribute(prefix, name, flag ? "true" : "false"); -
gleblebedev revised this gist
Aug 2, 2017 . 1 changed file with 162 additions and 30 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -244,7 +244,22 @@ private void WriteObject(string prefix, GameObject obj, HashSet<Renderer> exclud var terrain = obj.GetComponent<Terrain>(); var light = obj.GetComponent<Light>(); var camera = obj.GetComponent<Camera>(); var reflectionProbe = obj.GetComponent<ReflectionProbe>(); if (reflectionProbe != null) { StartCompoent(subPrefix, "Zone"); WriteAttribute(subSubPrefix, "Bounding Box Min", -(reflectionProbe.size*0.5f)); WriteAttribute(subSubPrefix, "Bounding Box Max", (reflectionProbe.size * 0.5f)); var cubemap = reflectionProbe.bakedTexture as Cubemap; if (cubemap != null) { var name = SaveCubemap(cubemap); WriteAttribute(subSubPrefix, "Zone Texture", "TextureCube;"+name); } EndElement(subPrefix); } if (camera != null) { StartCompoent(subPrefix, "Camera"); @@ -283,7 +298,7 @@ private void WriteObject(string prefix, GameObject obj, HashSet<Renderer> exclud var h = terrain.terrainData.heightmapHeight; float max = float.MinValue; float min = float.MaxValue; var heights = terrain.terrainData.GetHeights(0, 0, w, h); foreach (var height in heights) { if (height > max) max = height; @@ -293,18 +308,26 @@ private void WriteObject(string prefix, GameObject obj, HashSet<Renderer> exclud { max = 1; min = 0; } else if (max == min) { max = min + 0.1f; } WriteAttribute(subPrefix, "Position", new Vector3(terrainSize.x * 0.5f, -min, terrainSize.z * 0.5f)); StartCompoent(subPrefix, "Terrain"); var folderAndName = _fileNameWithoutExtension + "/" + Path.GetInvalidFileNameChars().Aggregate(obj.name, (_1, _2) => _1.Replace(_2, '_')); var heightmapFileName = "Textures/Terrains/" + folderAndName + ".tga"; var materialFileName = "Materials/Terrains/" + folderAndName + ".xml"; WriteAttribute(subSubPrefix, "Height Map", "Image;" + heightmapFileName); WriteAttribute(subSubPrefix, "Material", "Material;"+ materialFileName); WriteTerrainMaterial(terrain.terrainData.splatPrototypes, Path.Combine(_assetsFolder, materialFileName)); WriteAttribute(subSubPrefix, "Vertex Spacing", new Vector3(terrainSize.x / w, (max - min), terrainSize.z / h)); Directory.CreateDirectory(Path.GetDirectoryName(Path.Combine(_assetsFolder, heightmapFileName))); using (var imageFile = File.Open(Path.Combine(_assetsFolder, heightmapFileName), FileMode.Create, FileAccess.Write, FileShare.Read)) { using (var binaryWriter = new BinaryWriter(imageFile)) @@ -325,13 +348,13 @@ private void WriteObject(string prefix, GameObject obj, HashSet<Renderer> exclud { for (int x = 0; x < w; ++x) { var height = (heights[w - x - 1, y] - min) / (max - min) * 255.0f; binaryWriter.Write((byte)height); } } } } //WriteMaterialAttribute(subSubPrefix, terrain.terrainData.splatPrototypes); EndElement(subPrefix); EndElement(subPrefix); } @@ -394,6 +417,92 @@ private void WriteObject(string prefix, GameObject obj, HashSet<Renderer> exclud _writer.WriteEndElement(); _writer.WriteWhitespace("\n"); } private string SaveCubemap(Cubemap cubemap) { var path = "Textures/"+GetRelAssetPath(cubemap); var basefileName = Path.Combine(_assetsFolder, path); Directory.CreateDirectory(Path.GetDirectoryName(basefileName)); using (var writer = XmlWriter.Create(basefileName + ".xml")) { writer.WriteStartDocument(); writer.WriteStartElement("cubemap"); writer.WriteWhitespace(Environment.NewLine); writer.WriteStartElement("face"); writer.WriteAttributeString("name", Path.GetFileName(path)+ "_PosX.png"); writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); writer.WriteStartElement("face"); writer.WriteAttributeString("name", Path.GetFileName(path) + "_NegX.png"); writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); writer.WriteStartElement("face"); writer.WriteAttributeString("name", Path.GetFileName(path) + "_PosY.png"); writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); writer.WriteStartElement("face"); writer.WriteAttributeString("name", Path.GetFileName(path) + "_NegY.png"); writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); writer.WriteStartElement("face"); writer.WriteAttributeString("name", Path.GetFileName(path) + "_PosZ.png"); writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); writer.WriteStartElement("face"); writer.WriteAttributeString("name", Path.GetFileName(path) + "_NegZ.png"); writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); writer.WriteEndElement(); writer.WriteEndDocument(); } Texture2D tex; byte[] bytes; tex = new Texture2D(cubemap.width, cubemap.height, TextureFormat.RGB24, false); try { tex.SetPixels(cubemap.GetPixels(CubemapFace.PositiveX)); bytes = tex.EncodeToPNG(); File.WriteAllBytes(Path.Combine(_assetsFolder, path + "_PosX.png"), bytes); tex.SetPixels(cubemap.GetPixels(CubemapFace.NegativeX)); bytes = tex.EncodeToPNG(); File.WriteAllBytes(Path.Combine(_assetsFolder, path + "_NegX.png"), bytes); tex.SetPixels(cubemap.GetPixels(CubemapFace.PositiveY)); bytes = tex.EncodeToPNG(); File.WriteAllBytes(Path.Combine(_assetsFolder, path + "_PosY.png"), bytes); tex.SetPixels(cubemap.GetPixels(CubemapFace.NegativeY)); bytes = tex.EncodeToPNG(); File.WriteAllBytes(Path.Combine(_assetsFolder, path + "_NegY.png"), bytes); tex.SetPixels(cubemap.GetPixels(CubemapFace.PositiveZ)); bytes = tex.EncodeToPNG(); File.WriteAllBytes(Path.Combine(_assetsFolder, path + "_PosZ.png"), bytes); tex.SetPixels(cubemap.GetPixels(CubemapFace.NegativeZ)); bytes = tex.EncodeToPNG(); File.WriteAllBytes(Path.Combine(_assetsFolder, path + "_NegZ.png"), bytes); } catch (Exception ex) { Debug.LogError(ex); } Object.DestroyImmediate(tex); return path +".xml"; } private void WriteMaterialAttribute(string subSubPrefix, Material[] meshRendererMaterials) { var material = new StringBuilder(); @@ -474,7 +583,7 @@ private void WriteMesh(BinaryWriter writer, Mesh _mesh) writer.Write(2); for (var subMeshIndex = 0; subMeshIndex < _mesh.subMeshCount; ++subMeshIndex) for (var i = 0; i < indicesPerSubMesh[subMeshIndex].Length; ++i) writer.Write((ushort)indicesPerSubMesh[subMeshIndex][i]); } else { @@ -492,7 +601,7 @@ private void WriteMesh(BinaryWriter writer, Mesh _mesh) var numberOfLODLevels = 1; writer.Write(numberOfLODLevels); writer.Write(0.0f); writer.Write((int)PrimitiveType.TRIANGLE_LIST); writer.Write(0); writer.Write(0); writer.Write(totalIndices); @@ -529,8 +638,27 @@ private void WriteMesh(BinaryWriter writer, Mesh _mesh) writer.Write(maxZ); } } private void WriteTerrainMaterial(SplatPrototype[] textures, string materialFileName) { Directory.CreateDirectory(Path.GetDirectoryName(materialFileName)); using (var writer = XmlWriter.Create(materialFileName)) { writer.WriteStartDocument(); writer.WriteStartElement("material"); writer.WriteWhitespace(Environment.NewLine); writer.WriteStartElement("technique"); writer.WriteAttributeString("name", "Techniques/Diff.xml"); writer.WriteAttributeString("quality", "0"); writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); WriteTexture(textures[0].texture, writer, "diffuse"); writer.WriteEndElement(); writer.WriteEndDocument(); } } private void CreateMaterial(string materialFileName, Material material) { Directory.CreateDirectory(Path.GetDirectoryName(materialFileName)); using (var writer = XmlWriter.Create(materialFileName)) @@ -543,7 +671,7 @@ private void CreateMaterial(string materialFileName, Material material) var matSpecColor = new Color(0, 0, 0, 0); var matEmissiveColor = Color.black; var flags = new MaterialFlags(); flags.hasAlpha = material.renderQueue == (int)RenderQueue.Transparent; var shader = material.shader; for (var i = 0; i < ShaderUtil.GetPropertyCount(shader); i++) { @@ -691,7 +819,17 @@ private void CreateMaterial(string materialFileName, Material material) } } private void WriteTexture(Texture texture, XmlWriter writer, string name, bool isNormal = false, bool canCompress = true) { writer.WriteStartElement("texture"); writer.WriteAttributeString("unit", name); writer.WriteAttributeString("name", WriteTexture(texture,isNormal,canCompress)); writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); } private string WriteTexture(Texture texture, bool isNormal = false, bool canCompress = true) { if (texture == null) return null; @@ -723,12 +861,6 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name, bool var dataPath = Application.dataPath; var outputPath = "Textures/" + relPath; var destFileName = Path.Combine(_assetsFolder, outputPath); if (!File.Exists(destFileName)) { @@ -743,10 +875,10 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name, bool texture2d.LoadRawTextureData(sourceTexture2D.GetRawTextureData()); texture2d.Apply(); texture2d.Compress(true); var rawCompressedTexture = texture2d.GetRawTextureData(); var ms = new MemoryStream(); var br = new BinaryWriter(ms); var a = new byte[] @@ -784,10 +916,10 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name, bool pixelFormatFlags |= 1; br.Write(pixelFormatFlags); if (texture2d.format == TextureFormat.DXT5) br.Write(new byte[] { 0x44, 0x58, 0x54, 0x35 }); //dwFourCC else br.Write(new byte[] { 0x44, 0x58, 0x54, 0x31 }); //dwFourCC br.Write(new byte[] { 0x00, 0x00, 0x00, 0x00, //dwRGBBitCount @@ -807,7 +939,7 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name, bool 0x00, 0x00, 0x00, 0x00, //dwCaps4 0x00, 0x00, 0x00, 0x00, //dwReserved2 }); br.Write(rawCompressedTexture); File.WriteAllBytes(destFileName, ms.ToArray()); @@ -820,7 +952,7 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name, bool File.Copy(Path.Combine(dataPath, relPath), destFileName); } } return outputPath; } private string GetRelAssetPath(Object assetObject) @@ -1023,7 +1155,7 @@ internal class MeshVector3Stream : MeshStreamWriter public MeshVector3Stream(Vector3[] positions, VertexElementSemantic sem, int index = 0) { this.positions = positions; Element = (int)VertexElementType.TYPE_VECTOR3 | ((int)sem << 8) | (index << 16); } public override void Write(BinaryWriter writer, int index) @@ -1041,7 +1173,7 @@ internal class MeshVector2Stream : MeshStreamWriter public MeshVector2Stream(Vector2[] positions, VertexElementSemantic sem, int index = 0) { this.positions = positions; Element = (int)VertexElementType.TYPE_VECTOR2 | ((int)sem << 8) | (index << 16); } public override void Write(BinaryWriter writer, int index) -
gleblebedev revised this gist
Aug 1, 2017 . 1 changed file with 56 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -274,13 +274,65 @@ private void WriteObject(string prefix, GameObject obj, HashSet<Renderer> exclud if (terrain != null) { var terrainSize = terrain.terrainData.size; _writer.WriteWhitespace(subPrefix); _writer.WriteStartElement("node"); _writer.WriteAttributeString("id", (++_id).ToString()); _writer.WriteWhitespace("\n"); var w = terrain.terrainData.heightmapWidth; var h = terrain.terrainData.heightmapHeight; float max = float.MinValue; float min = float.MaxValue; var heights = terrain.terrainData.GetHeights(0,0,w,h); foreach (var height in heights) { if (height > max) max = height; if (height < min) min = height; } if (max < min) { max = 1; min = 0; } else if (max == min) { max = min + 0.1f; } WriteAttribute(subPrefix, "Position", new Vector3(-terrainSize.x*0.5f, -min, -terrainSize.z*0.5f)); StartCompoent(subPrefix, "Terrain"); var fileName = "Textures/Heightmaps/" + _fileNameWithoutExtension + "/" + Path.GetInvalidFileNameChars().Aggregate(obj.name,(_1,_2)=>_1.Replace(_2,'_')) + ".tga"; WriteAttribute(subSubPrefix, "Height Map", "Image;"+ fileName); WriteAttribute(subSubPrefix, "Vertex Spacing", new Vector3(terrainSize.x / w, (max-min), terrainSize.z / h)); Directory.CreateDirectory(Path.GetDirectoryName(Path.Combine(_assetsFolder, fileName))); using (var imageFile = File.Open(Path.Combine(_assetsFolder, fileName), FileMode.Create, FileAccess.Write, FileShare.Read)) { using (var binaryWriter = new BinaryWriter(imageFile)) { binaryWriter.Write((byte)0); binaryWriter.Write((byte)0); binaryWriter.Write((byte)3); binaryWriter.Write((short)0); binaryWriter.Write((short)0); binaryWriter.Write((byte)0); binaryWriter.Write((short)0); binaryWriter.Write((short)0); binaryWriter.Write((short)w); binaryWriter.Write((short)h); binaryWriter.Write((byte)8); binaryWriter.Write((byte)0); for (int y = h - 1; y >= 0; --y) { for (int x = 0; x < w; ++x) { var height = (heights[w-x-1,y]-min)/(max-min)*255.0f; binaryWriter.Write((byte)height); } } } } //WriteMaterialAttribute(subSubPrefix, terrain.terrainData.splatPrototypes); EndElement(subPrefix); EndElement(subPrefix); } if (lodGroup != null) -
gleblebedev revised this gist
Aug 1, 2017 . 1 changed file with 193 additions and 57 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,9 @@ using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Xml; using UnityEditor; @@ -48,6 +50,12 @@ public enum VertexElementType MAX_VERTEX_ELEMENT_TYPES } public enum DXGI_FORMAT { Unknown = 0, DXGI_FORMAT_R8G8B8A8_SINT = 32, DXGI_FORMAT_BC3_UNORM = 77, } public const uint Magic2 = 0x32444d55; @@ -129,6 +137,7 @@ public enum VertexElementType private readonly string _outputFileName; private readonly TextWriter _stream; private readonly XmlTextWriter _writer; private readonly string _fileNameWithoutExtension; private int _id; private Scene _scene; @@ -137,6 +146,7 @@ public UrhoExporter(Scene scene, string outputFileName) { _scene = scene; _outputFileName = Path.GetFullPath(outputFileName); _fileNameWithoutExtension = Path.GetFileNameWithoutExtension(_outputFileName); _assetsFolder = Path.GetDirectoryName(Path.GetDirectoryName(_outputFileName)); if (string.IsNullOrEmpty(_assetsFolder)) _assetsFolder = Path.GetDirectoryName(_outputFileName); @@ -186,7 +196,7 @@ public void Export() StartCompoent(prefix, "PhysicsWorld"); EndElement(prefix); EnumerateObjects(prefix, _scene.GetRootGameObjects(), new HashSet<Renderer>()); WriteAttribute(prefix, "Next Replicated Node ID", _id); WriteAttribute(prefix, "Next Replicated Component ID", _id); @@ -196,10 +206,10 @@ public void Export() } private void EnumerateObjects(string prefix, GameObject[] objects, HashSet<Renderer> excludeList) { foreach (var obj in objects) WriteObject(prefix, obj, excludeList); } private string GetFileName(string name) @@ -209,8 +219,9 @@ private string GetFileName(string name) return name; } private void WriteObject(string prefix, GameObject obj, HashSet<Renderer> excludeList) { var localExcludeList = new HashSet<Renderer>(excludeList); _writer.WriteWhitespace(prefix); _writer.WriteStartElement("node"); _writer.WriteAttributeString("id", (++_id).ToString()); @@ -228,6 +239,7 @@ private void WriteObject(string prefix, GameObject obj) var meshFilter = obj.GetComponent<MeshFilter>(); var meshRenderer = obj.GetComponent<MeshRenderer>(); var lodGroup = obj.GetComponent<LODGroup>(); var meshCollider = obj.GetComponent<MeshCollider>(); var terrain = obj.GetComponent<Terrain>(); var light = obj.GetComponent<Light>(); @@ -262,10 +274,28 @@ private void WriteObject(string prefix, GameObject obj) if (terrain != null) { var terrainSize = terrain.terrainData.size; StartCompoent(subPrefix, "Terrain"); var w = terrain.terrainData.heightmapWidth; var h = terrain.terrainData.heightmapHeight; var heights = terrain.terrainData.GetHeights(0,0,w,h); WriteAttribute(subSubPrefix, "Height Map", "Image;Textures/Heightmaps/"+ _fileNameWithoutExtension + ".png"); WriteAttribute(subSubPrefix, "Vertex Spacing", new Vector3(terrainSize.x / w, terrainSize.y / 255.0f, terrainSize.z / h)); //WriteMaterialAttribute(subSubPrefix, terrain.terrainData.splatPrototypes); EndElement(subPrefix); } if (lodGroup != null) { var lods = lodGroup.GetLODs(); foreach (var lod in lods.Skip(1)) { foreach (var renderer in lod.renderers) { localExcludeList.Add(renderer); } } //lods[0].renderers } if (meshRenderer != null && !localExcludeList.Contains(meshRenderer)) if (meshFilter != null) { StartCompoent(subPrefix, "StaticModel"); @@ -294,24 +324,7 @@ private void WriteObject(string prefix, GameObject obj) } } WriteMaterialAttribute(subSubPrefix, meshRenderer.sharedMaterials); WriteAttribute(subSubPrefix, "Cast Shadows", meshRenderer.shadowCastingMode != ShadowCastingMode.Off); EndElement(subPrefix); @@ -323,13 +336,32 @@ private void WriteObject(string prefix, GameObject obj) foreach (Transform childTransform in obj.transform) if (childTransform.parent.gameObject == obj) WriteObject(subPrefix, childTransform.gameObject, localExcludeList); _writer.WriteWhitespace(prefix); _writer.WriteEndElement(); _writer.WriteWhitespace("\n"); } private void WriteMaterialAttribute(string subSubPrefix, Material[] meshRendererMaterials) { var material = new StringBuilder(); material.Append("Material"); for (var i = 0; i < meshRendererMaterials.Length; ++i) { var meshRendererMaterial = meshRendererMaterials[i]; var relPath = GetRelAssetPath(meshRendererMaterial); var outputMaterialName = "Materials/" + relPath + ".xml"; material.Append(";"); material.Append(outputMaterialName); var materialFileName = Path.Combine(_assetsFolder, outputMaterialName); if (!File.Exists(materialFileName)) CreateMaterial(materialFileName, meshRendererMaterial); } WriteAttribute(subSubPrefix, "Material", material.ToString()); } private void WriteMesh(BinaryWriter writer, Mesh _mesh) { writer.Write(Magic2); @@ -355,10 +387,8 @@ private void WriteMesh(BinaryWriter writer, Mesh _mesh) //{ // elements.Add(new MeshColorStream(colors, VertexElementSemantic.SEM_COLOR)); //} if (tangents.Length > 0) elements.Add(new MeshVector4Stream(tangents, VertexElementSemantic.SEM_TANGENT, 0)); if (uvs.Length > 0) elements.Add(new MeshVector2Stream(uvs, VertexElementSemantic.SEM_TEXCOORD, 0)); if (uvs2.Length > 0) @@ -472,6 +502,7 @@ private void CreateMaterial(string materialFileName, Material material) if (texture != null) switch (propertyName) { case "_Diffuse": case "_MainTex": flags.hasDiffuse = true; WriteTexture(texture, writer, "diffuse"); @@ -482,9 +513,10 @@ private void CreateMaterial(string materialFileName, Material material) break; case "_ParallaxMap": break; case "_Normal": case "_BumpMap": flags.hasNormal = true; WriteTexture(texture, writer, "normal", true); break; case "_DetailAlbedoMap": break; @@ -498,6 +530,8 @@ private void CreateMaterial(string materialFileName, Material material) break; case "_OcclusionMap": break; case "_Mask": break; case "_DetailMask": break; default: @@ -510,6 +544,9 @@ private void CreateMaterial(string materialFileName, Material material) var color = material.GetColor(propertyName); switch (propertyName) { case "_FresnelColor": break; case "_MainColor": case "_Color": matDiffColor = color; break; @@ -524,6 +561,52 @@ private void CreateMaterial(string materialFileName, Material material) break; } } else if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.Range) { var value = material.GetFloat(propertyName); switch (propertyName) { case "_Cutoff": case "_Glossiness": case "_GlossMapScale": case "_Parallax": case "_OcclusionStrength": case "_Specular": case "_Gloss": case "_FresnelPower": case "_FresnelExp": case "_Alpha_2": case "_RefractionPower": break; case "_Alpha_1": matDiffColor.a = value; break; default: Debug.LogWarning(propertyName); break; } } else if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.Float) { var value = material.GetFloat(propertyName); switch (propertyName) { case "_SmoothnessTextureChannel": case "_SpecularHighlights": case "_GlossyReflections": case "_BumpScale": case "_DetailNormalMapScale": case "_UVSec": case "_Mode": case "_SrcBlend": case "_DstBlend": case "_ZWrite": break; default: Debug.LogWarning(propertyName); break; } } } if (!flags.hasDiffuse) WriteParameter(writer, "\t", "MatDiffColor", Format(matDiffColor)); @@ -556,7 +639,7 @@ private void CreateMaterial(string materialFileName, Material material) } } private string WriteTexture(Texture texture, XmlWriter writer, string name, bool isNormal = false, bool canCompress = true) { if (texture == null) return null; @@ -572,12 +655,17 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name) { var ext = relPath.Substring(extIndex).ToLower(); if (sourceTexture2D != null) { if (canCompress)// && ext != "tga") { if ((ext == "psd" || sourceTexture2D.format == TextureFormat.DXT5 || sourceTexture2D.format == TextureFormat.DXT1)) { needFormatConvertion = true; relPath = relPath.Substring(0, extIndex) + "dds"; } } } } var dataPath = Application.dataPath; @@ -603,10 +691,10 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name) texture2d.LoadRawTextureData(sourceTexture2D.GetRawTextureData()); texture2d.Apply(); texture2d.Compress(true); var rawCompressedTexture = texture2d.GetRawTextureData(); var ms = new MemoryStream(); var br = new BinaryWriter(ms); var a = new byte[] @@ -616,29 +704,58 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name) br.Write(a); br.Write(sourceTexture2D.width); br.Write(sourceTexture2D.height); br.Write(new byte[] { 0x00, 0x00, 0x40, 0x00, //dwPitchOrLinearSize 0x00, 0x00, 0x00, 0x00, //dwDepth }); int dwMipMapCount = texture2d.mipmapCount; br.Write(dwMipMapCount); br.Write(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, //DDS_PIXELFORMAT dwSize }); int pixelFormatFlags = 4; if (texture2d.alphaIsTransparency) pixelFormatFlags |= 1; br.Write(pixelFormatFlags); if (texture2d.format == TextureFormat.DXT5) br.Write(new byte[] {0x44, 0x58, 0x54, 0x35}); //dwFourCC else br.Write(new byte[] {0x44, 0x58, 0x54, 0x31}); //dwFourCC br.Write(new byte[] { 0x00, 0x00, 0x00, 0x00, //dwRGBBitCount 0x00, 0x00, 0x00, 0x00, //dwRBitMask 0x00, 0x00, 0x00, 0x00, //dwGBitMask 0x00, 0x00, 0x00, 0x00, //dwBBitMask 0x00, 0x00, 0x00, 0x00, //dwABitMask }); int caps = 0x00400008; if (texture2d.alphaIsTransparency) caps |= 0x00001000; br.Write(caps); br.Write(new byte[] { 0x00, 0x00, 0x00, 0x00, //dwCaps2 0x00, 0x00, 0x00, 0x00, //dwCaps3 0x00, 0x00, 0x00, 0x00, //dwCaps4 0x00, 0x00, 0x00, 0x00, //dwReserved2 }); br.Write(rawCompressedTexture); File.WriteAllBytes(destFileName, ms.ToArray()); @@ -881,4 +998,23 @@ public override void Write(BinaryWriter writer, int index) writer.Write(positions[index].y); } } internal class MeshVector4Stream : MeshStreamWriter { private readonly Vector4[] positions; public MeshVector4Stream(Vector4[] positions, VertexElementSemantic sem, int index = 0) { this.positions = positions; Element = (int)VertexElementType.TYPE_VECTOR4 | ((int)sem << 8) | (index << 16); } public override void Write(BinaryWriter writer, int index) { writer.Write(positions[index].x); writer.Write(positions[index].y); writer.Write(positions[index].z); writer.Write(positions[index].w); } } } -
gleblebedev revised this gist
Jun 25, 2017 . 1 changed file with 206 additions and 43 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -50,13 +50,88 @@ public enum VertexElementType public const uint Magic2 = 0x32444d55; public static Technique[] Techniques = { new Technique {Material = new MaterialFlags(), Name = "NoTexture.xml"}, new Technique {Material = new MaterialFlags {hasAlpha = true}, Name = "NoTextureAlpha.xml"}, new Technique {Material = new MaterialFlags {hasNormal = true}, Name = "NoTextureNormal.xml"}, new Technique { Material = new MaterialFlags {hasNormal = true, hasAlpha = true}, Name = "NoTextureNormalAlpha.xml" }, //new Technique //{ // Material = new MaterialFlags {hasNormal = true, hasAlpha = true, hasEmissive = true}, // Name = "NoTextureNormalEmissiveAlpha.xml" //}, new Technique {Material = new MaterialFlags {hasDiffuse = true}, Name = "Diff.xml"}, new Technique {Material = new MaterialFlags {hasDiffuse = true, hasAlpha = true}, Name = "DiffAlpha.xml"}, new Technique {Material = new MaterialFlags {hasDiffuse = true, hasSpecular = true}, Name = "DiffSpec.xml"}, new Technique { Material = new MaterialFlags {hasDiffuse = true, hasSpecular = true, hasAlpha = true}, Name = "DiffSpecAlpha.xml" }, new Technique {Material = new MaterialFlags {hasDiffuse = true, hasNormal = true}, Name = "DiffNormal.xml"}, new Technique { Material = new MaterialFlags {hasDiffuse = true, hasNormal = true, hasAlpha = true}, Name = "DiffNormalAlpha.xml" }, new Technique {Material = new MaterialFlags {hasDiffuse = true, hasEmissive = true}, Name = "DiffEmissive.xml"}, new Technique { Material = new MaterialFlags {hasDiffuse = true, hasEmissive = true, hasAlpha = true}, Name = "DiffEmissiveAlpha.xml" }, new Technique { Material = new MaterialFlags {hasDiffuse = true, hasSpecular = true, hasNormal = true}, Name = "DiffNormalSpec.xml" }, new Technique { Material = new MaterialFlags {hasDiffuse = true, hasSpecular = true, hasNormal = true, hasAlpha = true}, Name = "DiffNormalSpecAlpha.xml" }, new Technique { Material = new MaterialFlags {hasDiffuse = true, hasEmissive = true, hasNormal = true}, Name = "DiffNormalEmissive.xml" }, new Technique { Material = new MaterialFlags {hasDiffuse = true, hasEmissive = true, hasNormal = true, hasAlpha = true}, Name = "DiffNormalEmissiveAlpha.xml" }, new Technique { Material = new MaterialFlags {hasDiffuse = true, hasSpecular = true, hasNormal = true, hasEmissive = true}, Name = "DiffNormalSpecEmissive.xml" }, new Technique { Material = new MaterialFlags { hasDiffuse = true, hasSpecular = true, hasNormal = true, hasEmissive = true, hasAlpha = true }, Name = "DiffNormalSpecEmissiveAlpha.xml" } }; private readonly string _assetsFolder; private readonly string _outputFileName; private readonly TextWriter _stream; private readonly XmlTextWriter _writer; private int _id; private Scene _scene; public UrhoExporter(Scene scene, string outputFileName) { @@ -196,15 +271,13 @@ private void WriteObject(string prefix, GameObject obj) StartCompoent(subPrefix, "StaticModel"); var sharedMesh = meshFilter.sharedMesh; var meshRelFileName = GetRelAssetPath(sharedMesh); var subObjectPath = GetMeshPath(meshFilter); if (!string.IsNullOrEmpty(subObjectPath)) meshRelFileName = meshRelFileName + "/" + subObjectPath; WriteAttribute(subSubPrefix, "Model", "Model;Models/" + meshRelFileName + ".mdl"); @@ -382,37 +455,44 @@ private void CreateMaterial(string materialFileName, Material material) { writer.WriteStartDocument(); writer.WriteStartElement("material"); writer.WriteWhitespace(Environment.NewLine); var matDiffColor = Color.white; var matSpecColor = new Color(0, 0, 0, 0); var matEmissiveColor = Color.black; var flags = new MaterialFlags(); flags.hasAlpha = material.renderQueue == (int) RenderQueue.Transparent; var shader = material.shader; for (var i = 0; i < ShaderUtil.GetPropertyCount(shader); i++) { var propertyName = ShaderUtil.GetPropertyName(shader, i); if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv) { var texture = material.GetTexture(propertyName); if (texture != null) switch (propertyName) { case "_MainTex": flags.hasDiffuse = true; WriteTexture(texture, writer, "diffuse"); break; case "_SpecGlossMap": flags.hasSpecular = true; WriteTexture(texture, writer, "specular"); break; case "_ParallaxMap": break; case "_BumpMap": flags.hasNormal = true; WriteTexture(texture, writer, "normal"); break; case "_DetailAlbedoMap": break; case "_DetailNormalMap": break; case "_EmissionMap": flags.hasEmissive = true; WriteTexture(texture, writer, "emissive"); break; case "_MetallicGlossMap": break; @@ -424,26 +504,52 @@ private void CreateMaterial(string materialFileName, Material material) Debug.LogWarning(propertyName); break; } } else if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.Color) { var color = material.GetColor(propertyName); switch (propertyName) { case "_Color": matDiffColor = color; break; case "_EmissionColor": matEmissiveColor = color; break; case "_SpecColor": matSpecColor = color; break; default: Debug.LogWarning(propertyName); break; } } } if (!flags.hasDiffuse) WriteParameter(writer, "\t", "MatDiffColor", Format(matDiffColor)); if (!flags.hasSpecular) WriteParameter(writer, "\t", "MatSpecColor", Format(matSpecColor)); if (!flags.hasEmissive) WriteParameter(writer, "\t", "MatEmissiveColor", Format(matEmissiveColor)); writer.WriteWhitespace(Environment.NewLine); writer.WriteStartElement("technique"); var bestTechnique = Techniques[0]; var bestTechniqueDistance = bestTechnique.Material - flags; foreach (var technique in Techniques) if (technique.Material.Fits(flags)) { var d = technique.Material - flags; if (d < bestTechniqueDistance) { bestTechnique = technique; bestTechniqueDistance = d; } } writer.WriteAttributeString("name", "Techniques/" + bestTechnique.Name); writer.WriteAttributeString("quality", "0"); writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); writer.WriteEndElement(); writer.WriteEndDocument(); @@ -481,6 +587,7 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name) writer.WriteAttributeString("unit", name); writer.WriteAttributeString("name", outputPath); writer.WriteEndElement(); writer.WriteWhitespace(Environment.NewLine); var destFileName = Path.Combine(_assetsFolder, outputPath); if (!File.Exists(destFileName)) @@ -537,7 +644,7 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name) //var rawCompressedTexture = texture2d.EncodeToPNG(); //File.WriteAllBytes(destFileName, rawCompressedTexture); Object.DestroyImmediate(texture2d); } else { @@ -562,7 +669,7 @@ private string GetMeshPath(MeshFilter prefabFilter) if (string.IsNullOrEmpty(modelPath)) return null; var model = AssetDatabase.LoadAssetAtPath<GameObject>(modelPath); if (!model) { @@ -572,14 +679,12 @@ private string GetMeshPath(MeshFilter prefabFilter) MeshFilter modelFilter = null; var filters = model.GetComponentsInChildren<MeshFilter>(true); foreach (var filter in filters) if (filter.sharedMesh == prefabFilter.sharedMesh) { modelFilter = filter; break; } if (!modelFilter) { @@ -590,8 +695,8 @@ private string GetMeshPath(MeshFilter prefabFilter) if (filters.Length == 1) return null; var transform = modelFilter.transform; var path = transform.name; //while (transform.parent) //{ @@ -638,8 +743,17 @@ private void WriteAttribute(string prefix, string name, Quaternion pos) private void WriteAttribute(string prefix, string name, Color pos) { WriteAttribute(_writer, prefix, name, Format(pos)); } private void WriteAttribute(XmlWriter writer, string prefix, string name, Color pos) { WriteAttribute(writer, prefix, name, Format(pos)); } private static string Format(Color pos) { return string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", pos.r, pos.g, pos.b, pos.a); } private void WriteAttribute(string prefix, string name, bool flag) @@ -670,12 +784,61 @@ private void StartCompoent(string prefix, string type) private void WriteAttribute(string prefix, string name, string vaue) { WriteAttribute(_writer, prefix, name, vaue); } private void WriteAttribute(XmlWriter writer, string prefix, string name, string vaue) { writer.WriteWhitespace(prefix); writer.WriteStartElement("attribute"); writer.WriteAttributeString("name", name); writer.WriteAttributeString("value", vaue); writer.WriteEndElement(); writer.WriteWhitespace("\n"); } private void WriteParameter(XmlWriter writer, string prefix, string name, string vaue) { writer.WriteWhitespace(prefix); writer.WriteStartElement("parameter"); writer.WriteAttributeString("name", name); writer.WriteAttributeString("value", vaue); writer.WriteEndElement(); writer.WriteWhitespace("\n"); } public class MaterialFlags { public bool hasAlpha; public bool hasDiffuse; public bool hasEmissive; public bool hasNormal; public bool hasSpecular; public static int operator -(MaterialFlags a, MaterialFlags b) { return GetDistance(a.hasDiffuse, b.hasDiffuse) + GetDistance(a.hasSpecular, b.hasSpecular) + GetDistance(a.hasNormal, b.hasNormal) + GetDistance(a.hasEmissive, b.hasEmissive) + GetDistance(a.hasAlpha, b.hasAlpha); } private static int GetDistance(bool a, bool b) { return a != b ? 1 : 0; } public bool Fits(MaterialFlags b) { return (!hasDiffuse || b.hasDiffuse) && (!hasSpecular || b.hasSpecular) && (!hasEmissive || b.hasEmissive) && (!hasNormal || b.hasNormal) && hasAlpha == b.hasAlpha; } } public class Technique { public MaterialFlags Material; public string Name; } internal abstract class MeshStreamWriter -
gleblebedev revised this gist
Jun 24, 2017 . 1 changed file with 263 additions and 210 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -5,32 +5,58 @@ using System.Text; using System.Xml; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using Object = UnityEngine.Object; public class UrhoExporter : IDisposable { public enum PrimitiveType { TRIANGLE_LIST = 0, LINE_LIST, POINT_LIST, TRIANGLE_STRIP, LINE_STRIP, TRIANGLE_FAN } public enum VertexElementSemantic { SEM_POSITION = 0, SEM_NORMAL, SEM_BINORMAL, SEM_TANGENT, SEM_TEXCOORD, SEM_COLOR, SEM_BLENDWEIGHTS, SEM_BLENDINDICES, SEM_OBJECTINDEX, MAX_VERTEX_ELEMENT_SEMANTICS } public enum VertexElementType { TYPE_INT = 0, TYPE_FLOAT, TYPE_VECTOR2, TYPE_VECTOR3, TYPE_VECTOR4, TYPE_UBYTE4, TYPE_UBYTE4_NORM, MAX_VERTEX_ELEMENT_TYPES } public const uint Magic2 = 0x32444d55; private readonly string _assetsFolder; private int _id; private readonly string _outputFileName; private Scene _scene; private readonly TextWriter _stream; private readonly XmlTextWriter _writer; public UrhoExporter(Scene scene, string outputFileName) { @@ -44,6 +70,26 @@ public UrhoExporter(Scene scene, string outputFileName) _writer = new XmlTextWriter(_stream); } public void Dispose() { if (_stream != null) _stream.Dispose(); } [MenuItem("Tools/Export Scene To Urho3D")] public static void ExportToUrho() { var activeScene = SceneManager.GetActiveScene(); using (var exporter = new UrhoExporter(activeScene, EditorUtility.SaveFilePanel( "Save scene as Urho XML", "", activeScene.name + ".xml", "xml"))) { exporter.Export(); } } public void Export() { if (string.IsNullOrEmpty(_outputFileName)) @@ -67,36 +113,28 @@ public void Export() EnumerateObjects(prefix, _scene.GetRootGameObjects()); WriteAttribute(prefix, "Next Replicated Node ID", _id); WriteAttribute(prefix, "Next Replicated Component ID", _id); _writer.WriteEndElement(); _writer.WriteEndDocument(); } private void EnumerateObjects(string prefix, GameObject[] objects) { foreach (var obj in objects) WriteObject(prefix, obj); } private string GetFileName(string name) { foreach (var invalidFileNameChar in Path.GetInvalidFileNameChars()) name = name.Replace(invalidFileNameChar, '_'); return name; } private void WriteObject(string prefix, GameObject obj) { _writer.WriteWhitespace(prefix); _writer.WriteStartElement("node"); @@ -106,12 +144,12 @@ private void WriteObject(string prefix,GameObject obj) var subPrefix = prefix + "\t"; var subSubPrefix = subPrefix + "\t"; WriteAttribute(subPrefix, "Is Enabled", obj.activeSelf); WriteAttribute(subPrefix, "Name", obj.name); WriteAttribute(subPrefix, "Tags", obj.tag); WriteAttribute(subPrefix, "Position", obj.transform.localPosition); WriteAttribute(subPrefix, "Rotation", obj.transform.localRotation); WriteAttribute(subPrefix, "Scale", obj.transform.localScale); var meshFilter = obj.GetComponent<MeshFilter>(); var meshRenderer = obj.GetComponent<MeshRenderer>(); @@ -134,19 +172,15 @@ private void WriteObject(string prefix,GameObject obj) { StartCompoent(subPrefix, "Light"); if (light.type == LightType.Directional) WriteAttribute(subSubPrefix, "Light Type", "Directional"); else if (light.type == LightType.Spot) WriteAttribute(subSubPrefix, "Light Type", "Spot"); else if (light.type == LightType.Point) WriteAttribute(subSubPrefix, "Range", light.range); WriteAttribute(subSubPrefix, "Color", light.color); WriteAttribute(subSubPrefix, "Brightness Multiplier", light.intensity); WriteAttribute(subSubPrefix, "Cast Shadows", light.shadows != LightShadows.None); EndElement(subPrefix); } @@ -157,13 +191,22 @@ private void WriteObject(string prefix,GameObject obj) } if (meshRenderer != null) if (meshFilter != null) { StartCompoent(subPrefix, "StaticModel"); var sharedMesh = meshFilter.sharedMesh; var meshRelFileName = GetRelAssetPath(sharedMesh); var subObjectPath = GetMeshPath(meshFilter); if (!string.IsNullOrEmpty(subObjectPath)) { meshRelFileName = meshRelFileName + "/" + subObjectPath; } WriteAttribute(subSubPrefix, "Model", "Model;Models/" + meshRelFileName + ".mdl"); var meshFileName = Path.Combine(Path.Combine(_assetsFolder, "Models"), meshRelFileName + ".mdl"); if (!File.Exists(meshFileName)) @@ -173,60 +216,52 @@ private void WriteObject(string prefix,GameObject obj) { using (var writer = new BinaryWriter(fileStream)) { WriteMesh(writer, sharedMesh); } } } var material = new StringBuilder(); material.Append("Material"); var meshRendererMaterials = meshRenderer.sharedMaterials; for (var i = 0; i < meshRendererMaterials.Length; ++i) { var meshRendererMaterial = meshRendererMaterials[i]; var relPath = GetRelAssetPath(meshRendererMaterial); var outputMaterialName = "Materials/" + relPath + ".xml"; material.Append(";"); material.Append(outputMaterialName); var materialFileName = Path.Combine(_assetsFolder, outputMaterialName); if (!File.Exists(materialFileName)) CreateMaterial(materialFileName, meshRendererMaterial); } WriteAttribute(subSubPrefix, "Material", material.ToString()); WriteAttribute(subSubPrefix, "Cast Shadows", meshRenderer.shadowCastingMode != ShadowCastingMode.Off); EndElement(subPrefix); } if (meshCollider != null) { } foreach (Transform childTransform in obj.transform) if (childTransform.parent.gameObject == obj) WriteObject(subPrefix, childTransform.gameObject); _writer.WriteWhitespace(prefix); _writer.WriteEndElement(); _writer.WriteWhitespace("\n"); } private void WriteMesh(BinaryWriter writer, Mesh _mesh) { writer.Write(Magic2); writer.Write(1); for (var vbIndex = 0; vbIndex < 1 /*_mesh.vertexBufferCount*/; ++vbIndex) { var positions = _mesh.vertices; var normals = _mesh.normals; @@ -240,13 +275,9 @@ private void WriteMesh(BinaryWriter writer, Mesh _mesh) writer.Write(positions.Length); var elements = new List<MeshStreamWriter>(); if (positions.Length > 0) elements.Add(new MeshVector3Stream(positions, VertexElementSemantic.SEM_POSITION)); if (normals.Length > 0) elements.Add(new MeshVector3Stream(normals, VertexElementSemantic.SEM_NORMAL)); //if (colors.Length > 0) //{ // elements.Add(new MeshColorStream(colors, VertexElementSemantic.SEM_COLOR)); @@ -256,40 +287,26 @@ private void WriteMesh(BinaryWriter writer, Mesh _mesh) // elements.Add(new MeshVector4Stream(tangents, VertexElementSemantic.SEM_TANGENT)); //} if (uvs.Length > 0) elements.Add(new MeshVector2Stream(uvs, VertexElementSemantic.SEM_TEXCOORD, 0)); if (uvs2.Length > 0) elements.Add(new MeshVector2Stream(uvs2, VertexElementSemantic.SEM_TEXCOORD, 1)); if (uvs3.Length > 0) elements.Add(new MeshVector2Stream(uvs2, VertexElementSemantic.SEM_TEXCOORD, 2)); if (uvs4.Length > 0) elements.Add(new MeshVector2Stream(uvs2, VertexElementSemantic.SEM_TEXCOORD, 3)); writer.Write(elements.Count); for (var i = 0; i < elements.Count; ++i) writer.Write(elements[i].Element); var morphableVertexRangeStartIndex = 0; var morphableVertexCount = 0; writer.Write(morphableVertexRangeStartIndex); writer.Write(morphableVertexCount); for (var index = 0; index < positions.Length; ++index) for (var i = 0; i < elements.Count; ++i) elements[i].Write(writer, index); var indicesPerSubMesh = new List<int[]>(); var totalIndices = 0; for (var subMeshIndex = 0; subMeshIndex < _mesh.subMeshCount; ++subMeshIndex) { var indices = _mesh.GetIndices(subMeshIndex); indicesPerSubMesh.Add(indices); @@ -300,35 +317,27 @@ private void WriteMesh(BinaryWriter writer, Mesh _mesh) if (positions.Length < 65536) { writer.Write(2); for (var subMeshIndex = 0; subMeshIndex < _mesh.subMeshCount; ++subMeshIndex) for (var i = 0; i < indicesPerSubMesh[subMeshIndex].Length; ++i) writer.Write((ushort) indicesPerSubMesh[subMeshIndex][i]); } else { writer.Write(4); for (var subMeshIndex = 0; subMeshIndex < _mesh.subMeshCount; ++subMeshIndex) for (var i = 0; i < indicesPerSubMesh[subMeshIndex].Length; ++i) writer.Write(indicesPerSubMesh[subMeshIndex][i]); } writer.Write(indicesPerSubMesh.Count); totalIndices = 0; for (var subMeshIndex = 0; subMeshIndex < indicesPerSubMesh.Count; ++subMeshIndex) { var numberOfBoneMappingEntries = 0; writer.Write(numberOfBoneMappingEntries); var numberOfLODLevels = 1; writer.Write(numberOfLODLevels); writer.Write(0.0f); writer.Write((int) PrimitiveType.TRIANGLE_LIST); writer.Write(0); writer.Write(0); writer.Write(totalIndices); @@ -342,7 +351,7 @@ private void WriteMesh(BinaryWriter writer, Mesh _mesh) float maxX, maxY, maxZ; maxX = maxY = maxZ = float.MinValue; minX = minY = minZ = float.MaxValue; for (var i = 0; i < positions.Length; ++i) { if (minX > positions[i].x) minX = positions[i].x; @@ -365,110 +374,39 @@ private void WriteMesh(BinaryWriter writer, Mesh _mesh) writer.Write(maxZ); } } private void CreateMaterial(string materialFileName, Material material) { Directory.CreateDirectory(Path.GetDirectoryName(materialFileName)); using (var writer = XmlWriter.Create(materialFileName)) { writer.WriteStartDocument(); writer.WriteStartElement("material"); Texture diffuse = null; Texture specular = null; Texture normal = null; var shader = material.shader; for (var i = 0; i < ShaderUtil.GetPropertyCount(shader); i++) { if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv) { var propertyName = ShaderUtil.GetPropertyName(shader, i); var texture = material.GetTexture(propertyName); if (texture != null) { switch (propertyName) { case "_MainTex": WriteTexture(diffuse = texture, writer, "diffuse"); break; case "_SpecGlossMap": WriteTexture(specular = texture, writer, "specular"); break; case "_ParallaxMap": break; case "_BumpMap": WriteTexture(normal = texture, writer, "normal"); break; case "_DetailAlbedoMap": break; @@ -489,6 +427,24 @@ private void CreateMaterial(string materialFileName, Material material) } } } writer.WriteStartElement("technique"); if (diffuse == null) { if (normal != null) writer.WriteAttributeString("name", "Techniques/NoTextureNormal.xml"); else writer.WriteAttributeString("name", "Techniques/NoTexture.xml"); } else { if (normal != null) writer.WriteAttributeString("name", "Techniques/DiffNormal.xml"); else writer.WriteAttributeString("name", "Techniques/Diff.xml"); } writer.WriteAttributeString("quality", "0"); writer.WriteEndElement(); writer.WriteEndElement(); writer.WriteEndDocument(); } @@ -503,20 +459,19 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name) var relPath = GetRelAssetPath(texture); var extIndex = relPath.LastIndexOf('.') + 1; var needFormatConvertion = false; if (extIndex > 0) { var ext = relPath.Substring(extIndex).ToLower(); if (sourceTexture2D != null) if (ext == "psd" || sourceTexture2D.format == TextureFormat.DXT5 || sourceTexture2D.format == TextureFormat.DXT1) { needFormatConvertion = true; relPath = relPath.Substring(0, extIndex) + "dds"; } } var dataPath = Application.dataPath; @@ -527,7 +482,7 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name) writer.WriteAttributeString("name", outputPath); writer.WriteEndElement(); var destFileName = Path.Combine(_assetsFolder, outputPath); if (!File.Exists(destFileName)) { Directory.CreateDirectory(Path.GetDirectoryName(destFileName)); @@ -536,7 +491,8 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name) //var texture2d = new Texture2D(sourceTexture.width, sourceTexture.height); //texture2d.SetPixels32(sourceTexture.GetPixels32(0)); var texture2d = new Texture2D(sourceTexture2D.width, sourceTexture2D.height, sourceTexture2D.format, sourceTexture2D.mipmapCount > 1); texture2d.LoadRawTextureData(sourceTexture2D.GetRawTextureData()); texture2d.Apply(); @@ -548,31 +504,31 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name) var br = new BinaryWriter(ms); var a = new byte[] { 0x44, 0x44, 0x53, 0x20, 0x7C, 0x00, 0x00, 0x00, 0x07, 0x10, 0x0A, 0x00 }; br.Write(a); br.Write(sourceTexture2D.width); br.Write(sourceTexture2D.height); a = new byte[] { 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 }; br.Write(a); if (texture2d.format == TextureFormat.DXT5) a = new byte[] {0x44, 0x58, 0x54, 0x35}; else a = new byte[] {0x44, 0x58, 0x54, 0x31}; br.Write(a); a = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; br.Write(a); @@ -581,7 +537,7 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name) //var rawCompressedTexture = texture2d.EncodeToPNG(); //File.WriteAllBytes(destFileName, rawCompressedTexture); Object.Destroy(texture2d); } else { @@ -591,7 +547,7 @@ private string WriteTexture(Texture texture, XmlWriter writer, string name) return relPath; } private string GetRelAssetPath(Object assetObject) { var path = AssetDatabase.GetAssetPath(assetObject); if (string.IsNullOrEmpty(path)) @@ -600,6 +556,52 @@ private string GetRelAssetPath(UnityEngine.Object assetObject) return relPath; } private string GetMeshPath(MeshFilter prefabFilter) { var modelPath = AssetDatabase.GetAssetPath(prefabFilter.sharedMesh); if (string.IsNullOrEmpty(modelPath)) return null; GameObject model = AssetDatabase.LoadAssetAtPath<GameObject>(modelPath); if (!model) { Debug.LogWarning("No game object found at " + modelPath, prefabFilter); return null; } MeshFilter modelFilter = null; var filters = model.GetComponentsInChildren<MeshFilter>(true); foreach (MeshFilter filter in filters) { if (filter.sharedMesh == prefabFilter.sharedMesh) { modelFilter = filter; break; } } if (!modelFilter) { Debug.LogWarning("No game object found for " + prefabFilter, prefabFilter); return null; } if (filters.Length == 1) return null; Transform transform = modelFilter.transform; string path = transform.name; //while (transform.parent) //{ // transform = transform.parent; // path = transform.name + "/" + path; //} return path; } private string TrimInstance(string assetObjectName) { var instance = " Instance"; @@ -622,23 +624,34 @@ private void WriteAttribute(string prefix, string name, float pos) { WriteAttribute(prefix, name, string.Format(CultureInfo.InvariantCulture, "{0}", pos)); } private void WriteAttribute(string prefix, string name, Vector3 pos) { WriteAttribute(prefix, name, string.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", pos.x, pos.y, pos.z)); } private void WriteAttribute(string prefix, string name, Quaternion pos) { WriteAttribute(prefix, name, string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", pos.w, pos.x, pos.y, pos.z)); } private void WriteAttribute(string prefix, string name, Color pos) { WriteAttribute(prefix, name, string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", pos.r, pos.g, pos.b, pos.a)); } private void WriteAttribute(string prefix, string name, bool flag) { WriteAttribute(prefix, name, flag ? "true" : "false"); } private void WriteAttribute(string prefix, string name, int flag) { WriteAttribute(prefix, name, flag.ToString(CultureInfo.InvariantCulture)); } private void EndElement(string prefix) { _writer.WriteWhitespace(prefix); @@ -653,7 +666,6 @@ private void StartCompoent(string prefix, string type) _writer.WriteAttributeString("type", type); _writer.WriteAttributeString("id", (++_id).ToString()); _writer.WriteWhitespace("\n"); } private void WriteAttribute(string prefix, string name, string vaue) @@ -665,4 +677,45 @@ private void WriteAttribute(string prefix, string name, string vaue) _writer.WriteEndElement(); _writer.WriteWhitespace("\n"); } internal abstract class MeshStreamWriter { public int Element; public abstract void Write(BinaryWriter writer, int index); } internal class MeshVector3Stream : MeshStreamWriter { private readonly Vector3[] positions; public MeshVector3Stream(Vector3[] positions, VertexElementSemantic sem, int index = 0) { this.positions = positions; Element = (int) VertexElementType.TYPE_VECTOR3 | ((int) sem << 8) | (index << 16); } public override void Write(BinaryWriter writer, int index) { writer.Write(positions[index].x); writer.Write(positions[index].y); writer.Write(positions[index].z); } } internal class MeshVector2Stream : MeshStreamWriter { private readonly Vector2[] positions; public MeshVector2Stream(Vector2[] positions, VertexElementSemantic sem, int index = 0) { this.positions = positions; Element = (int) VertexElementType.TYPE_VECTOR2 | ((int) sem << 8) | (index << 16); } public override void Write(BinaryWriter writer, int index) { writer.Write(positions[index].x); writer.Write(positions[index].y); } } } -
gleblebedev revised this gist
Jun 21, 2017 . 1 changed file with 88 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -474,6 +474,14 @@ private void CreateMaterial(string materialFileName, Material material) break; case "_DetailNormalMap": break; case "_EmissionMap": break; case "_MetallicGlossMap": break; case "_OcclusionMap": break; case "_DetailMask": break; default: Debug.LogWarning(propertyName); break; @@ -486,12 +494,31 @@ private void CreateMaterial(string materialFileName, Material material) } } private string WriteTexture(Texture texture, XmlWriter writer, string name) { if (texture == null) return null; var sourceTexture2D = texture as Texture2D; var relPath = GetRelAssetPath(texture); int extIndex = relPath.LastIndexOf('.')+1; bool needFormatConvertion = false; if (extIndex > 0) { string ext = relPath.Substring(extIndex).ToLower(); if (sourceTexture2D != null) { if (ext == "psd" || sourceTexture2D.format == TextureFormat.DXT5 || sourceTexture2D.format == TextureFormat.DXT1) { needFormatConvertion = true; relPath = relPath.Substring(0, extIndex) + "dds"; } } } var dataPath = Application.dataPath; var outputPath = "Textures/" + relPath; @@ -504,8 +531,64 @@ private void WriteTexture(Texture materialMainTexture, XmlWriter writer, string if (!File.Exists(destFileName)) { Directory.CreateDirectory(Path.GetDirectoryName(destFileName)); if (needFormatConvertion) { //var texture2d = new Texture2D(sourceTexture.width, sourceTexture.height); //texture2d.SetPixels32(sourceTexture.GetPixels32(0)); var texture2d = new Texture2D(sourceTexture2D.width, sourceTexture2D.height, sourceTexture2D.format, sourceTexture2D.mipmapCount > 1); texture2d.LoadRawTextureData(sourceTexture2D.GetRawTextureData()); texture2d.Apply(); texture2d.Compress(true); var rawCompressedTexture = texture2d.GetRawTextureData(); var ms = new MemoryStream(); var br = new BinaryWriter(ms); var a = new byte[] { 0x44, 0x44, 0x53, 0x20, 0x7C, 0x00, 0x00, 0x00, 0x07, 0x10, 0x0A, 0x00, }; br.Write(a); br.Write(sourceTexture2D.width); br.Write(sourceTexture2D.height); a = new byte[] { 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, }; br.Write(a); if (texture2d.format == TextureFormat.DXT5) a = new byte[] { 0x44, 0x58, 0x54, 0x35 }; else a = new byte[] { 0x44, 0x58, 0x54, 0x31 }; br.Write(a); a = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; br.Write(a); br.Write(rawCompressedTexture); File.WriteAllBytes(destFileName, ms.ToArray()); //var rawCompressedTexture = texture2d.EncodeToPNG(); //File.WriteAllBytes(destFileName, rawCompressedTexture); UnityEngine.Object.Destroy(texture2d); } else { File.Copy(Path.Combine(dataPath, relPath), destFileName); } } return relPath; } private string GetRelAssetPath(UnityEngine.Object assetObject) -
gleblebedev revised this gist
Jun 21, 2017 . 1 changed file with 24 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -130,7 +130,7 @@ private void WriteObject(string prefix,GameObject obj) EndElement(subPrefix); } if (light != null && light.type != LightType.Area) { StartCompoent(subPrefix, "Light"); if (light.type == LightType.Directional) @@ -207,11 +207,10 @@ private void WriteObject(string prefix,GameObject obj) { } foreach (Transform childTransform in obj.transform) { if (childTransform.parent.gameObject == obj) WriteObject(subPrefix, childTransform.gameObject); } _writer.WriteWhitespace(prefix); @@ -513,10 +512,29 @@ private string GetRelAssetPath(UnityEngine.Object assetObject) { var path = AssetDatabase.GetAssetPath(assetObject); if (string.IsNullOrEmpty(path)) return GetFileName(TrimInstance(assetObject.name)); var relPath = path.Substring(path.IndexOf('/') + 1); return relPath; } private string TrimInstance(string assetObjectName) { var instance = " Instance"; var instance2 = " (Instance)"; loop: if (assetObjectName.EndsWith(instance)) { assetObjectName = assetObjectName.Substring(0, assetObjectName.Length - instance.Length); goto loop; } if (assetObjectName.EndsWith(instance2)) { assetObjectName = assetObjectName.Substring(0, assetObjectName.Length - instance2.Length); goto loop; } return assetObjectName; } private void WriteAttribute(string prefix, string name, float pos) { WriteAttribute(prefix, name, string.Format(CultureInfo.InvariantCulture, "{0}", pos)); -
gleblebedev revised this gist
Jun 21, 2017 . 1 changed file with 17 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -137,6 +137,16 @@ private void WriteObject(string prefix,GameObject obj) { WriteAttribute(subSubPrefix, "Light Type", "Directional"); } else if (light.type == LightType.Spot) { WriteAttribute(subSubPrefix, "Light Type", "Spot"); } else if (light.type == LightType.Point) { WriteAttribute(subSubPrefix, "Range", light.range); } WriteAttribute(subSubPrefix, "Color", light.color); WriteAttribute(subSubPrefix, "Brightness Multiplier", light.intensity); EndElement(subPrefix); } @@ -152,7 +162,7 @@ private void WriteObject(string prefix,GameObject obj) { StartCompoent(subPrefix, "StaticModel"); var meshRelFileName = GetRelAssetPath(meshFilter.sharedMesh); WriteAttribute(subSubPrefix, "Model", "Model;Models/" + meshRelFileName + ".mdl"); var meshFileName = Path.Combine(Path.Combine(_assetsFolder, "Models"), meshRelFileName + ".mdl"); @@ -163,14 +173,14 @@ private void WriteObject(string prefix,GameObject obj) { using (var writer = new BinaryWriter(fileStream)) { WriteMesh(writer, meshFilter.sharedMesh); } } } StringBuilder material = new StringBuilder(); material.Append("Material"); var meshRendererMaterials = meshRenderer.sharedMaterials; for (int i = 0; i < meshRendererMaterials.Length; ++i) { var meshRendererMaterial = meshRendererMaterials[i]; @@ -519,6 +529,10 @@ private void WriteAttribute(string prefix, string name, Quaternion pos) { WriteAttribute(prefix, name, string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", pos.w, pos.x, pos.y, pos.z)); } private void WriteAttribute(string prefix, string name, Color pos) { WriteAttribute(prefix, name, string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", pos.r, pos.g, pos.b, pos.a)); } private void WriteAttribute(string prefix, string name, bool flag) { WriteAttribute(prefix, name, flag ? "true" : "false"); -
gleblebedev revised this gist
Jun 21, 2017 . 1 changed file with 6 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -158,10 +158,13 @@ private void WriteObject(string prefix,GameObject obj) var meshFileName = Path.Combine(Path.Combine(_assetsFolder, "Models"), meshRelFileName + ".mdl"); if (!File.Exists(meshFileName)) { Directory.CreateDirectory(Path.GetDirectoryName(meshFileName)); using (var fileStream = File.Open(meshFileName, FileMode.Create, FileAccess.Write, FileShare.Read)) { using (var writer = new BinaryWriter(fileStream)) { WriteMesh(writer, meshFilter.mesh); } } } -
gleblebedev revised this gist
Jun 20, 2017 . 1 changed file with 28 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -117,7 +117,28 @@ private void WriteObject(string prefix,GameObject obj) var meshRenderer = obj.GetComponent<MeshRenderer>(); var meshCollider = obj.GetComponent<MeshCollider>(); var terrain = obj.GetComponent<Terrain>(); var light = obj.GetComponent<Light>(); var camera = obj.GetComponent<Camera>(); if (camera != null) { StartCompoent(subPrefix, "Camera"); WriteAttribute(subSubPrefix, "Near Clip", camera.nearClipPlane); WriteAttribute(subSubPrefix, "Far Clip", camera.farClipPlane); EndElement(subPrefix); } if (light != null) { StartCompoent(subPrefix, "Light"); if (light.type == LightType.Directional) { WriteAttribute(subSubPrefix, "Light Type", "Directional"); } EndElement(subPrefix); } if (terrain != null) { @@ -165,9 +186,7 @@ private void WriteObject(string prefix,GameObject obj) } WriteAttribute(subSubPrefix, "Material", material.ToString()); EndElement(subPrefix); } } @@ -187,6 +206,8 @@ private void WriteObject(string prefix,GameObject obj) _writer.WriteWhitespace("\n"); } public const uint Magic2 = 0x32444d55; private void WriteMesh(BinaryWriter writer, Mesh _mesh) @@ -409,7 +430,6 @@ private void CreateMaterial(string materialFileName, Material material) using (var writer = XmlTextWriter.Create(materialFileName)) { writer.WriteStartDocument(); writer.WriteStartElement("material"); writer.WriteStartElement("technique"); writer.WriteAttributeString("name", "Techniques/Diff.xml"); @@ -484,7 +504,10 @@ private string GetRelAssetPath(UnityEngine.Object assetObject) var relPath = path.Substring(path.IndexOf('/') + 1); return relPath; } private void WriteAttribute(string prefix, string name, float pos) { WriteAttribute(prefix, name, string.Format(CultureInfo.InvariantCulture, "{0}", pos)); } private void WriteAttribute(string prefix,string name, Vector3 pos) { WriteAttribute(prefix, name, string.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", pos.x, pos.y, pos.z)); -
gleblebedev created this gist
Jun 20, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,527 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; using System.Xml; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.SceneManagement; public class UrhoExporter:IDisposable { [MenuItem("Tools/Export Scene To Urho3D")] public static void ExportToUrho() { using (var exporter = new UrhoExporter(EditorSceneManager.GetActiveScene(), EditorUtility.SaveFilePanel( "Save scene as Urho XML", "", "scene.xml", "xml"))) { exporter.Export(); } } private Scene _scene; private int _id; string _outputFileName; private TextWriter _stream; private XmlTextWriter _writer; private string _assetsFolder; public UrhoExporter(Scene scene, string outputFileName) { _scene = scene; _outputFileName = Path.GetFullPath(outputFileName); _assetsFolder = Path.GetDirectoryName(Path.GetDirectoryName(_outputFileName)); if (string.IsNullOrEmpty(_assetsFolder)) _assetsFolder = Path.GetDirectoryName(_outputFileName); _stream = File.CreateText(_outputFileName); _writer = new XmlTextWriter(_stream); } public void Export() { if (string.IsNullOrEmpty(_outputFileName)) return; _writer.WriteStartDocument(); _writer.WriteWhitespace("\n"); _writer.WriteStartElement("scene"); _writer.WriteAttributeString("id", (++_id).ToString()); _writer.WriteWhitespace("\n"); var prefix = "\t"; StartCompoent(prefix, "Octree"); EndElement(prefix); StartCompoent(prefix, "DebugRenderer"); EndElement(prefix); StartCompoent(prefix, "PhysicsWorld"); EndElement(prefix); EnumerateObjects(prefix, _scene.GetRootGameObjects()); _writer.WriteEndElement(); _writer.WriteEndDocument(); } public void Dispose() { if (_stream != null) { _stream.Dispose(); } } private void EnumerateObjects(string prefix, GameObject[] objects) { foreach (var obj in objects) { WriteObject(prefix, obj); } } private string GetFileName(string name) { foreach (var invalidFileNameChar in Path.GetInvalidFileNameChars()) { name = name.Replace(invalidFileNameChar, '_'); } return name; } private void WriteObject(string prefix,GameObject obj) { _writer.WriteWhitespace(prefix); _writer.WriteStartElement("node"); _writer.WriteAttributeString("id", (++_id).ToString()); _writer.WriteWhitespace("\n"); var subPrefix = prefix + "\t"; var subSubPrefix = subPrefix + "\t"; WriteAttribute(subPrefix, "Is Enabled", obj.activeSelf); WriteAttribute(subPrefix, "Name", obj.name); WriteAttribute(subPrefix, "Tags", obj.tag); WriteAttribute(subPrefix, "Position", obj.transform.localPosition); WriteAttribute(subPrefix, "Rotation", obj.transform.localRotation); WriteAttribute(subPrefix, "Scale", obj.transform.localScale); var meshFilter = obj.GetComponent<MeshFilter>(); var meshRenderer = obj.GetComponent<MeshRenderer>(); var meshCollider = obj.GetComponent<MeshCollider>(); var terrain = obj.GetComponent<Terrain>(); if (terrain != null) { var terrainSize = terrain.terrainData.size; var y = terrain.SampleHeight(new Vector3(0, 0, 0)); } if (meshRenderer != null) { if (meshFilter != null) { StartCompoent(subPrefix, "StaticModel"); var meshRelFileName = GetRelAssetPath(meshFilter.mesh); WriteAttribute(subSubPrefix, "Model", "Model;Models/" + meshRelFileName + ".mdl"); var meshFileName = Path.Combine(Path.Combine(_assetsFolder, "Models"), meshRelFileName + ".mdl"); if (!File.Exists(meshFileName)) { using (var writer = new BinaryWriter(File.Open(meshFileName, FileMode.Create, FileAccess.Write, FileShare.Read))) { WriteMesh(writer, meshFilter.mesh); } } StringBuilder material = new StringBuilder(); material.Append("Material"); var meshRendererMaterials = meshRenderer.materials; for (int i = 0; i < meshRendererMaterials.Length; ++i) { var meshRendererMaterial = meshRendererMaterials[i]; var relPath = GetRelAssetPath(meshRendererMaterial); var outputMaterialName = "Materials/" + relPath+".xml"; material.Append(";"); material.Append(outputMaterialName); var materialFileName = Path.Combine(_assetsFolder, outputMaterialName); if (!File.Exists(materialFileName)) { CreateMaterial(materialFileName, meshRendererMaterial); } } WriteAttribute(subSubPrefix, "Material", material.ToString()); _writer.WriteWhitespace(subPrefix); _writer.WriteEndElement(); _writer.WriteWhitespace("\n"); } } if (meshCollider != null) { } var transforms = obj.GetComponentsInChildren<Transform>(true); for (int i = 0; i < transforms.Length; ++i) { if (transforms[i].gameObject != obj) WriteObject(subPrefix, transforms[i].gameObject); } _writer.WriteWhitespace(prefix); _writer.WriteEndElement(); _writer.WriteWhitespace("\n"); } public const uint Magic2 = 0x32444d55; private void WriteMesh(BinaryWriter writer, Mesh _mesh) { writer.Write(Magic2); writer.Write(1); for (int vbIndex = 0; vbIndex < 1 /*_mesh.vertexBufferCount*/; ++vbIndex) { var positions = _mesh.vertices; var normals = _mesh.normals; var colors = _mesh.colors; var tangents = _mesh.tangents; var uvs = _mesh.uv; var uvs2 = _mesh.uv2; var uvs3 = _mesh.uv3; var uvs4 = _mesh.uv4; writer.Write(positions.Length); var elements = new List<MeshStreamWriter>(); if (positions.Length > 0) { elements.Add(new MeshVector3Stream(positions, VertexElementSemantic.SEM_POSITION)); } if (normals.Length > 0) { elements.Add(new MeshVector3Stream(normals, VertexElementSemantic.SEM_NORMAL)); } //if (colors.Length > 0) //{ // elements.Add(new MeshColorStream(colors, VertexElementSemantic.SEM_COLOR)); //} //if (tangents.Length > 0) //{ // elements.Add(new MeshVector4Stream(tangents, VertexElementSemantic.SEM_TANGENT)); //} if (uvs.Length > 0) { elements.Add(new MeshVector2Stream(uvs, VertexElementSemantic.SEM_TEXCOORD, 0)); } if (uvs2.Length > 0) { elements.Add(new MeshVector2Stream(uvs2, VertexElementSemantic.SEM_TEXCOORD, 1)); } if (uvs3.Length > 0) { elements.Add(new MeshVector2Stream(uvs2, VertexElementSemantic.SEM_TEXCOORD, 2)); } if (uvs4.Length > 0) { elements.Add(new MeshVector2Stream(uvs2, VertexElementSemantic.SEM_TEXCOORD, 3)); } writer.Write(elements.Count); for (int i = 0; i < elements.Count; ++i) { writer.Write(elements[i].Element); } int morphableVertexRangeStartIndex = 0; int morphableVertexCount = 0; writer.Write(morphableVertexRangeStartIndex); writer.Write(morphableVertexCount); for (int index = 0; index < positions.Length; ++index) { for (int i = 0; i < elements.Count; ++i) { elements[i].Write(writer, index); } } var indicesPerSubMesh = new List<int[]>(); int totalIndices = 0; for (int subMeshIndex = 0; subMeshIndex < _mesh.subMeshCount; ++subMeshIndex) { var indices = _mesh.GetIndices(subMeshIndex); indicesPerSubMesh.Add(indices); totalIndices += indices.Length; } writer.Write(1); writer.Write(totalIndices); if (positions.Length < 65536) { writer.Write(2); for (int subMeshIndex = 0; subMeshIndex < _mesh.subMeshCount; ++subMeshIndex) { for (int i = 0; i < indicesPerSubMesh[subMeshIndex].Length; ++i) { writer.Write((ushort)indicesPerSubMesh[subMeshIndex][i]); } } } else { writer.Write(4); for (int subMeshIndex = 0; subMeshIndex < _mesh.subMeshCount; ++subMeshIndex) { for (int i = 0; i < indicesPerSubMesh[subMeshIndex].Length; ++i) { writer.Write(indicesPerSubMesh[subMeshIndex][i]); } } } writer.Write(indicesPerSubMesh.Count); totalIndices = 0; for (int subMeshIndex = 0; subMeshIndex < indicesPerSubMesh.Count; ++subMeshIndex) { var numberOfBoneMappingEntries = 0; writer.Write(numberOfBoneMappingEntries); var numberOfLODLevels = 1; writer.Write(numberOfLODLevels); writer.Write(0.0f); writer.Write((int)PrimitiveType.TRIANGLE_LIST); writer.Write(0); writer.Write(0); writer.Write(totalIndices); writer.Write(indicesPerSubMesh[subMeshIndex].Length); totalIndices += indicesPerSubMesh[subMeshIndex].Length; writer.Write(0); var numOfBones = 0; writer.Write(numOfBones); } float minX, minY, minZ; float maxX, maxY, maxZ; maxX = maxY = maxZ = float.MinValue; minX = minY = minZ = float.MaxValue; for (int i = 0; i < positions.Length; ++i) { if (minX > positions[i].x) minX = positions[i].x; if (minY > positions[i].y) minY = positions[i].y; if (minZ > positions[i].z) minZ = positions[i].z; if (maxX < positions[i].x) maxX = positions[i].x; if (maxY < positions[i].y) maxY = positions[i].y; if (maxZ < positions[i].z) maxZ = positions[i].z; } writer.Write(minX); writer.Write(minY); writer.Write(minZ); writer.Write(maxX); writer.Write(maxY); writer.Write(maxZ); } } public enum PrimitiveType { TRIANGLE_LIST = 0, LINE_LIST, POINT_LIST, TRIANGLE_STRIP, LINE_STRIP, TRIANGLE_FAN } public enum VertexElementType { TYPE_INT = 0, TYPE_FLOAT, TYPE_VECTOR2, TYPE_VECTOR3, TYPE_VECTOR4, TYPE_UBYTE4, TYPE_UBYTE4_NORM, MAX_VERTEX_ELEMENT_TYPES } public enum VertexElementSemantic { SEM_POSITION = 0, SEM_NORMAL, SEM_BINORMAL, SEM_TANGENT, SEM_TEXCOORD, SEM_COLOR, SEM_BLENDWEIGHTS, SEM_BLENDINDICES, SEM_OBJECTINDEX, MAX_VERTEX_ELEMENT_SEMANTICS } internal abstract class MeshStreamWriter { public int Element; public abstract void Write(BinaryWriter writer, int index); } internal class MeshVector3Stream: MeshStreamWriter { private Vector3[] positions; public MeshVector3Stream(Vector3[] positions, VertexElementSemantic sem, int index = 0) { this.positions = positions; Element = (int)VertexElementType.TYPE_VECTOR3 | ((int)sem << 8) | (index <<16); } public override void Write(BinaryWriter writer, int index) { writer.Write(positions[index].x); writer.Write(positions[index].y); writer.Write(positions[index].z); } } internal class MeshVector2Stream : MeshStreamWriter { private Vector2[] positions; public MeshVector2Stream(Vector2[] positions, VertexElementSemantic sem, int index = 0) { this.positions = positions; Element = (int)VertexElementType.TYPE_VECTOR2 | ((int)sem << 8) | (index << 16); } public override void Write(BinaryWriter writer, int index) { writer.Write(positions[index].x); writer.Write(positions[index].y); } } private void CreateMaterial(string materialFileName, Material material) { Directory.CreateDirectory(Path.GetDirectoryName(materialFileName)); using (var writer = XmlTextWriter.Create(materialFileName)) { writer.WriteStartDocument(); //<material> <technique name ="Techniques/Diff.xml" quality="0"/> <texture unit="diffuse" name="Textures/_teleport.tga"/></material> writer.WriteStartElement("material"); writer.WriteStartElement("technique"); writer.WriteAttributeString("name", "Techniques/Diff.xml"); writer.WriteAttributeString("quality", "0"); writer.WriteEndElement(); var shader = material.shader; for (int i = 0; i < ShaderUtil.GetPropertyCount(shader); i++) { if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv) { var propertyName = ShaderUtil.GetPropertyName(shader, i); Texture texture = material.GetTexture(propertyName); if (texture != null) { switch (propertyName) { case "_MainTex": WriteTexture(texture, writer, "diffuse"); break; case "_SpecGlossMap": WriteTexture(texture, writer, "specular"); break; case "_ParallaxMap": break; case "_BumpMap": WriteTexture(texture, writer, "normal"); break; case "_DetailAlbedoMap": break; case "_DetailNormalMap": break; default: Debug.LogWarning(propertyName); break; } } } } writer.WriteEndElement(); writer.WriteEndDocument(); } } private void WriteTexture(Texture materialMainTexture, XmlWriter writer, string name) { if (materialMainTexture == null) return; var relPath = GetRelAssetPath(materialMainTexture); var dataPath = Application.dataPath; var outputPath = "Textures/" + relPath; writer.WriteStartElement("texture"); writer.WriteAttributeString("unit", name); writer.WriteAttributeString("name", outputPath); writer.WriteEndElement(); string destFileName = Path.Combine(this._assetsFolder, outputPath); if (!File.Exists(destFileName)) { Directory.CreateDirectory(Path.GetDirectoryName(destFileName)); File.Copy(Path.Combine(dataPath,relPath), destFileName); } } private string GetRelAssetPath(UnityEngine.Object assetObject) { var path = AssetDatabase.GetAssetPath(assetObject); if (string.IsNullOrEmpty(path)) return GetFileName(assetObject.name); var relPath = path.Substring(path.IndexOf('/') + 1); return relPath; } private void WriteAttribute(string prefix,string name, Vector3 pos) { WriteAttribute(prefix, name, string.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", pos.x, pos.y, pos.z)); } private void WriteAttribute(string prefix, string name, Quaternion pos) { WriteAttribute(prefix, name, string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", pos.w, pos.x, pos.y, pos.z)); } private void WriteAttribute(string prefix, string name, bool flag) { WriteAttribute(prefix, name, flag ? "true" : "false"); } private void EndElement(string prefix) { _writer.WriteWhitespace(prefix); _writer.WriteEndElement(); _writer.WriteWhitespace("\n"); } private void StartCompoent(string prefix, string type) { _writer.WriteWhitespace(prefix); _writer.WriteStartElement("component"); _writer.WriteAttributeString("type", type); _writer.WriteAttributeString("id", (++_id).ToString()); _writer.WriteWhitespace("\n"); } private void WriteAttribute(string prefix, string name, string vaue) { _writer.WriteWhitespace(prefix); _writer.WriteStartElement("attribute"); _writer.WriteAttributeString("name", name); _writer.WriteAttributeString("value", vaue); _writer.WriteEndElement(); _writer.WriteWhitespace("\n"); } }