Tanoda
ObjExporter.cs
Go to the documentation of this file.
1using UnityEngine;
2using System.Collections;
3using System.Collections.Generic;
4using System.IO;
5using System.Linq;
6using System.Text;
7
8public class ObjExporter : MonoBehaviour {
9
10 public static bool applyPosition = true;
11 public static bool applyRotation = true;
12 public static bool applyScale = true;
13 public static bool generateMaterials = true;
14 public static bool exportTextures = true;
15 public static bool splitObjects = true;
16 public static bool autoMarkTexReadable = false;
17 public static bool objNameAddIdNum = false;
18 static string exportPath = "teszt.1.obj";
19 private static string lastExportFolder;
20 private static string versionString = "v2.0";
21 static string MaterialToString(Material m)
22 {
23 StringBuilder sb = new StringBuilder();
24 sb.AppendLine("newmtl " + m.name);
25 //add properties
26 if (m.HasProperty("_Color"))
27 {
28 sb.AppendLine("Kd " + m.color.r.ToString() + " " + m.color.g.ToString() + " " + m.color.b.ToString());
29 if (m.color.a < 1.0f)
30 {
31 //use both implementations of OBJ transparency
32 sb.AppendLine("Tr " + (1f - m.color.a).ToString());
33 sb.AppendLine("d " + m.color.a.ToString());
34 }
35 }
36
37 if (m.HasProperty("_SpecColor"))
38 {
39 Color sc = m.GetColor("_SpecColor");
40 sb.AppendLine("Ks " + sc.r.ToString() + " " + sc.g.ToString() + " " + sc.b.ToString());
41 }
42
44 {
45 //diffuse
46 string exResult = TryExportTexture("_MainTex", m);
47 if (exResult != "false")
48 {
49 sb.AppendLine("map_Kd " + exResult);
50 }
51
52 //spec map
53 exResult = TryExportTexture("_SpecMap", m);
54 if (exResult != "false")
55 {
56 sb.AppendLine("map_Ks " + exResult);
57 }
58
59 //bump map
60 exResult = TryExportTexture("_BumpMap", m);
61 if (exResult != "false")
62 {
63 sb.AppendLine("map_Bump " + exResult);
64 }
65 }
66
67 sb.AppendLine("illum 2");
68 return sb.ToString();
69 }
70
71 static string TryExportTexture(string propertyName, Material m)
72 {
73 if (m.HasProperty(propertyName))
74 {
75 Texture t = m.GetTexture(propertyName);
76 }
77
78 return "false";
79 }
80
81 static Vector3 MultiplyVec3s(Vector3 v1, Vector3 v2)
82 {
83 return new Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
84 }
85
86 static Vector3 RotateAroundPoint(Vector3 point, Vector3 pivot, Quaternion angle)
87 {
88 return angle * (point - pivot) + pivot;
89 }
90
91 private static string ConstructOBJString(int index)
92 {
93 string idxString = index.ToString();
94 return idxString + "/" + idxString + "/" + idxString;
95 }
96
97
98 public static string MeshToText(GameObject go, bool wtf)
99 {
100 //init stuff
101 Dictionary<string, bool> materialCache = new Dictionary<string, bool>();
102 var exportFileInfo = new FileInfo(exportPath);
103 lastExportFolder = exportFileInfo.Directory.FullName;
104 string baseFileName = Path.GetFileNameWithoutExtension(exportPath);
105 //get list of required export things
106 MeshFilter[] sceneMeshes;
107
108 sceneMeshes = go.GetComponentsInChildren<MeshFilter>().ToArray();
109
110 //work on export
111 StringBuilder sb = new StringBuilder();
112 StringBuilder sbMaterials = new StringBuilder();
113 sb.AppendLine("# Export of " + go.name);
114 sb.AppendLine("# from Aaro4130 OBJ Exporter " + versionString);
116 {
117 sb.AppendLine("mtllib " + baseFileName + ".mtl");
118 }
119
120 float maxExportProgress = (float)(sceneMeshes.Length + 1);
121 int lastIndex = 0;
122 for (int i = 0; i < sceneMeshes.Length; i++)
123 {
124 string meshName = sceneMeshes[i].gameObject.name;
125 float progress = (float)(i + 1) / maxExportProgress;
126 MeshFilter mf = sceneMeshes[i];
127 MeshRenderer mr = sceneMeshes[i].gameObject.GetComponent<MeshRenderer>();
128 if (splitObjects)
129 {
130 string exportName = meshName;
131 if (objNameAddIdNum)
132 {
133 exportName += "_" + i;
134 }
135
136 sb.AppendLine("g " + exportName);
137 }
138
139 if (mr != null && generateMaterials)
140 {
141 Material[] mats = mr.sharedMaterials;
142 for (int j = 0; j < mats.Length; j++)
143 {
144 Material m = mats[j];
145 if (!materialCache.ContainsKey(m.name))
146 {
147 materialCache[m.name] = true;
148 sbMaterials.Append(MaterialToString(m));
149 sbMaterials.AppendLine();
150 }
151 }
152 }
153
154 //export the meshhh :3
155 Mesh msh = mf.sharedMesh;
156 int faceOrder = (int)Mathf.Clamp((mf.gameObject.transform.lossyScale.x * mf.gameObject.transform.lossyScale.z), -1, 1);
157 //export vector data (FUN :D)!
158 foreach (Vector3 vx in msh.vertices)
159 {
160 Vector3 v = vx;
161 if (applyScale)
162 {
163 v = MultiplyVec3s(v, mf.gameObject.transform.lossyScale);
164 }
165
166 if (applyRotation)
167 {
168 v = RotateAroundPoint(v, Vector3.zero, mf.gameObject.transform.rotation);
169 }
170
171 if (applyPosition)
172 {
173 v += mf.gameObject.transform.position;
174 }
175
176 v.x *= -1;
177 sb.AppendLine("v " + v.x + " " + v.y + " " + v.z);
178 }
179
180 foreach (Vector3 vx in msh.normals)
181 {
182 Vector3 v = vx;
183 if (applyScale)
184 {
185 v = MultiplyVec3s(v, mf.gameObject.transform.lossyScale.normalized);
186 }
187
188 if (applyRotation)
189 {
190 v = RotateAroundPoint(v, Vector3.zero, mf.gameObject.transform.rotation);
191 }
192
193 v.x *= -1;
194 sb.AppendLine("vn " + v.x + " " + v.y + " " + v.z);
195 }
196
197 foreach (Vector2 v in msh.uv)
198 {
199 sb.AppendLine("vt " + v.x + " " + v.y);
200 }
201
202 for (int j = 0; j < msh.subMeshCount; j++)
203 {
204 if (mr != null && j < mr.sharedMaterials.Length)
205 {
206 string matName = mr.sharedMaterials[j].name;
207 sb.AppendLine("usemtl " + matName);
208 }
209 else
210 {
211 sb.AppendLine("usemtl " + meshName + "_sm" + j);
212 }
213
214 int[] tris = msh.GetTriangles(j);
215 for (int t = 0; t < tris.Length; t += 3)
216 {
217 int idx2 = tris[t] + 1 + lastIndex;
218 int idx1 = tris[t + 1] + 1 + lastIndex;
219 int idx0 = tris[t + 2] + 1 + lastIndex;
220 if (faceOrder < 0)
221 {
222 sb.AppendLine("f " + ConstructOBJString(idx2) + " " + ConstructOBJString(idx1) + " " + ConstructOBJString(idx0));
223 }
224 else
225 {
226 sb.AppendLine("f " + ConstructOBJString(idx0) + " " + ConstructOBJString(idx1) + " " + ConstructOBJString(idx2));
227 }
228 }
229 }
230
231 lastIndex += msh.vertices.Length;
232 }
233
234 if (wtf)
235 {
236 //write to disk
237 File.WriteAllText(exportPath, sb.ToString());
239 {
240 File.WriteAllText(exportFileInfo.Directory.FullName + "\\" + baseFileName + ".mtl", sbMaterials.ToString());
241 }
242 }
243
244 return sb.ToString();
245 }
246}
UnityEngine.Color Color
Definition: TestScript.cs:32
static bool applyPosition
Definition: ObjExporter.cs:10
static bool exportTextures
Definition: ObjExporter.cs:14
static bool splitObjects
Definition: ObjExporter.cs:15
static string MeshToText(GameObject go, bool wtf)
Definition: ObjExporter.cs:98
static bool generateMaterials
Definition: ObjExporter.cs:13
static bool autoMarkTexReadable
Definition: ObjExporter.cs:16
static bool applyRotation
Definition: ObjExporter.cs:11
static bool objNameAddIdNum
Definition: ObjExporter.cs:17
static bool applyScale
Definition: ObjExporter.cs:12