Skip to content

Commit 3f11d99

Browse files
committed
can export obj with materials. todo: textures.
1 parent 41333c8 commit 3f11d99

File tree

2 files changed

+838
-93
lines changed

2 files changed

+838
-93
lines changed

Editor/ZOExportOBJ.cs

Lines changed: 91 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11

22
using UnityEngine;
33
using UnityEditor;
4-
using System.Collections;
4+
using System.Collections.Generic;
55
using System.IO;
66
using System.Text;
77

88
namespace ZO.Export {
9-
public class ZOObjExporterScript {
9+
public class ZOObjExporter {
1010
private static int _startIndex = 0;
1111

1212
public static void Start() {
@@ -24,39 +24,39 @@ public static string MeshToString(MeshFilter meshFilter, Transform transform) {
2424

2525

2626
int numVertices = 0;
27-
Mesh m = meshFilter.sharedMesh;
28-
if (!m) {
27+
Mesh mesh = meshFilter.sharedMesh;
28+
if (!mesh) {
2929
return "####Error####";
3030
}
3131
Material[] mats = meshFilter.GetComponent<Renderer>().sharedMaterials;
3232

3333
StringBuilder sb = new StringBuilder();
3434

35-
foreach (Vector3 vv in m.vertices) {
35+
foreach (Vector3 vv in mesh.vertices) {
3636
Vector3 v = transform.TransformPoint(vv);
3737
numVertices++;
3838
sb.Append(string.Format("v {0} {1} {2}\n", v.x, v.y, -v.z));
3939
}
4040
sb.Append("\n");
41-
foreach (Vector3 nn in m.normals) {
41+
foreach (Vector3 nn in mesh.normals) {
4242
Vector3 v = r * nn;
4343
sb.Append(string.Format("vn {0} {1} {2}\n", -v.x, -v.y, v.z));
4444
}
4545
sb.Append("\n");
46-
foreach (Vector3 v in m.uv) {
46+
foreach (Vector3 v in mesh.uv) {
4747
sb.Append(string.Format("vt {0} {1}\n", v.x, v.y));
4848
}
49-
50-
for (int material = 0; material < m.subMeshCount; material++) {
49+
50+
for (int material = 0; material < mesh.subMeshCount; material++) {
5151
sb.Append("\n");
5252
sb.Append("usemtl ").Append(mats[material].name).Append("\n");
5353
sb.Append("usemap ").Append(mats[material].name).Append("\n");
5454

55-
int[] triangles = m.GetTriangles(material);
55+
int[] triangles = mesh.GetTriangles(material);
5656
for (int i = 0; i < triangles.Length; i += 3) {
5757
sb.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n",
58-
triangles[i] + 1 + _startIndex,
59-
triangles[i + 1] + 1 + _startIndex,
58+
triangles[i] + 1 + _startIndex,
59+
triangles[i + 1] + 1 + _startIndex,
6060
triangles[i + 2] + 1 + _startIndex));
6161
// sb.Append(string.Format("f {0}//{0} {1}//{1} {2}//{2}\n", // pos, None, Norm
6262
// triangles[i] + 1 + _startIndex,
@@ -69,6 +69,26 @@ public static string MeshToString(MeshFilter meshFilter, Transform transform) {
6969
_startIndex += numVertices;
7070
return sb.ToString();
7171
}
72+
73+
public static string MaterialToString(Material material) {
74+
StringBuilder sb = new StringBuilder();
75+
sb.AppendFormat("newmtl {0}", material.name).AppendLine();
76+
if (material.HasProperty("_Color")) {
77+
Color c = material.GetColor("_Color");
78+
sb.AppendFormat("Kd {0} {1} {2}", c.r, c.g, c.b).AppendLine();
79+
}
80+
if (material.HasProperty("_MainTex")) {
81+
string assetPath = AssetDatabase.GetAssetPath(material.GetTexture("_MainTex"));
82+
string texName = Path.GetFileName(assetPath);
83+
// string exportPath = Path.Combine(dir, texName);
84+
sb.AppendFormat("map_Kd {0}", texName).AppendLine();
85+
// if (!File.Exists(exportPath))
86+
// {
87+
// File.Copy(assetPath, exportPath);
88+
// }
89+
}
90+
return sb.ToString();
91+
}
7292
}
7393

7494
public class ZOExportOBJ : EditorWindow {
@@ -98,9 +118,9 @@ private void OnGUI() {
98118
EditorGUI.BeginDisabledGroup(Selection.gameObjects.Length == 0);
99119
if (GUILayout.Button("Export OBJ")) {
100120
string meshName = Selection.gameObjects[0].name;
101-
string fileName = EditorUtility.SaveFilePanel("Export .obj file", "", meshName, "obj");
121+
string fileDirectory = EditorUtility.OpenFolderPanel("Export .OBJ to directory", "", "");
102122

103-
DoExport(_exportSubMeshes, fileName);
123+
DoExport(_exportSubMeshes, fileDirectory);
104124
}
105125
EditorGUI.EndDisabledGroup();
106126

@@ -110,16 +130,21 @@ private void OnInspectorUpdate() {
110130
Repaint();
111131
}
112132

113-
public static void DoExport(bool makeSubmeshes, string fileName, bool zeroPosition=true) {
114-
if (Selection.gameObjects.Length == 0) {
133+
public static void DoExport(bool makeSubmeshes, string fileDirectory, bool zeroPosition = true, GameObject gameObject = null) {
134+
135+
if (gameObject == null && Selection.gameObjects.Length == 0) {
115136
Debug.Log("Didn't Export Any Meshes; Nothing was selected!");
116137
return;
117138
}
118139

119-
string meshName = Selection.gameObjects[0].name;
140+
if (gameObject == null) {
141+
gameObject = Selection.gameObjects[0];
142+
}
143+
144+
string meshName = gameObject.name;
120145
// string fileName = EditorUtility.SaveFilePanel("Export .obj file", "", meshName, "obj");
121146

122-
ZOObjExporterScript.Start();
147+
ZOObjExporter.Start();
123148

124149
StringBuilder meshString = new StringBuilder();
125150

@@ -129,10 +154,12 @@ public static void DoExport(bool makeSubmeshes, string fileName, bool zeroPositi
129154
+ "\n#-------"
130155
+ "\n\n");
131156

132-
Transform transform = Selection.gameObjects[0].transform;
157+
meshString.AppendLine($"mtllib {meshName}.mtl");
158+
159+
Transform transform = gameObject.transform;
133160

134161
Vector3 originalPosition = transform.position;
135-
if (zeroPosition == true) {
162+
if (zeroPosition == true) {
136163
transform.position = Vector3.zero;
137164
}
138165

@@ -141,12 +168,52 @@ public static void DoExport(bool makeSubmeshes, string fileName, bool zeroPositi
141168
}
142169
meshString.Append(ProcessTransform(transform, makeSubmeshes));
143170

144-
WriteToFile(meshString.ToString(), fileName);
171+
172+
string objFilePath = Path.Combine(fileDirectory, $"{meshName}.obj");
173+
174+
WriteToFile(meshString.ToString(), objFilePath);
145175

146176
transform.position = originalPosition;
147177

148-
ZOObjExporterScript.End();
149-
Debug.Log("Exported Mesh: " + fileName);
178+
179+
// export materials and textures
180+
StringBuilder mtlFileString = new StringBuilder();
181+
HashSet<string> materialNames = new HashSet<string>();
182+
MeshFilter meshFilter = transform.GetComponent<MeshFilter>();
183+
if (meshFilter != null) {
184+
Material[] materials = meshFilter.GetComponent<Renderer>().sharedMaterials;
185+
foreach (Material material in materials) {
186+
if (materialNames.Contains(material.name) == false) {
187+
string materialString = ZOObjExporter.MaterialToString(material);
188+
mtlFileString.Append(materialString);
189+
materialNames.Add(material.name);
190+
}
191+
}
192+
}
193+
194+
195+
// go through the children materials
196+
for (int i = 0; i < transform.childCount; i++) {
197+
Transform child = transform.GetChild(i);
198+
meshFilter = child.GetComponent<MeshFilter>();
199+
200+
if (meshFilter != null) {
201+
// meshString.Append(ZOObjExporterScript.MeshToString(meshFilter, transform));
202+
Material[] materials = meshFilter.GetComponent<Renderer>().sharedMaterials;
203+
foreach (Material material in materials) {
204+
if (materialNames.Contains(material.name) == false) {
205+
string materialString = ZOObjExporter.MaterialToString(material);
206+
mtlFileString.Append(materialString);
207+
materialNames.Add(material.name);
208+
}
209+
}
210+
}
211+
}
212+
string mtlFilePath = Path.Combine(fileDirectory, $"{meshName}.mtl");
213+
WriteToFile(mtlFileString.ToString(), mtlFilePath);
214+
215+
ZOObjExporter.End();
216+
Debug.Log("Exported Mesh: " + objFilePath);
150217
}
151218

152219
static string ProcessTransform(Transform transform, bool makeSubmeshes) {
@@ -162,7 +229,7 @@ static string ProcessTransform(Transform transform, bool makeSubmeshes) {
162229

163230
MeshFilter meshFilter = transform.GetComponent<MeshFilter>();
164231
if (meshFilter != null) {
165-
meshString.Append(ZOObjExporterScript.MeshToString(meshFilter, transform));
232+
meshString.Append(ZOObjExporter.MeshToString(meshFilter, transform));
166233
}
167234

168235
for (int i = 0; i < transform.childCount; i++) {

0 commit comments

Comments
 (0)