]> icculus.org git repositories - divverent/nexuiz.git/blob - misc/tools/ObjToMap/objtomap/ObjToMap.java
pro is now havoc, just minor nitpicking but one more file that knows this fact :P
[divverent/nexuiz.git] / misc / tools / ObjToMap / objtomap / ObjToMap.java
1 /* This code is *ugly*. It may blind you.
2  *
3  * I hereby pollute the software world by putting this into public domain.
4  *
5  * SavageX
6  */
7
8
9 package objtomap;
10
11 import java.io.BufferedReader;
12 import java.io.FileReader;
13 import java.io.FileWriter;
14 import java.io.IOException;
15 import java.io.PrintWriter;
16 import java.util.Vector;
17
18 public class ObjToMap {
19     
20     private Vector points, faces;
21     private Configuration config;
22     
23     public ObjToMap(Configuration c) {
24         config = c;
25     }
26     
27     public void parseOBJ() throws IOException {
28         
29         points = new Vector();
30         faces = new Vector();
31         double scale = config.scale;
32         config.simpleterrain = true;
33         config.minz = Double.MAX_VALUE;
34         
35         
36         BufferedReader in = null;
37         try {
38             in = new BufferedReader(new FileReader(config.objfile));
39         } catch(Exception e) {
40             System.err.println("Input file not found!");
41             return;
42         }
43         
44         String currentmat = "common/caulk";
45         
46         while(in.ready()) {
47             String line = in.readLine();
48             line.trim();
49             line = line.replaceAll("  ", " ");
50             String[] tokens = line.split(" ");
51             if(tokens.length > 1) {
52                 
53                 if(tokens[0].equals("v")) {
54                     // vertices
55                     Vector3D p = new Vector3D();
56                     p.x = Double.parseDouble(tokens[3]) * scale;
57                     p.y = Double.parseDouble(tokens[1]) * scale;
58                     p.z = Double.parseDouble(tokens[2]) * scale;
59                     points.add(p);
60                     
61                     if(p.z < config.minz)
62                         config.minz = p.z;
63                     
64                 } else if(tokens[0].equals("f")) {
65                     // faces
66                     
67                     if(tokens.length == 4) {
68                         // TriFace
69                         
70                         String[] facetokens1 = tokens[1].split("/");
71                         String[] facetokens2 = tokens[2].split("/");
72                         String[] facetokens3 = tokens[3].split("/");
73                         
74                         Face f = new Face();
75                         f.material = currentmat;
76                         Vector3D p1, p2, p3;
77                         p1 = (Vector3D)points.get(Integer.parseInt(facetokens1[0]) - 1);
78                         p2 = (Vector3D)points.get(Integer.parseInt(facetokens2[0]) - 1);
79                         p3 = (Vector3D)points.get(Integer.parseInt(facetokens3[0]) - 1);
80                         
81                         f.setPoints(p1, p2, p3);
82                         if(f.getXYangle() >= 90.0)
83                             config.simpleterrain = false;
84                         
85                         faces.add(f);
86                         
87                     } else if(tokens.length == 5) {
88                         // QuadFace
89                         String[] facetokens1 = tokens[1].split("/");
90                         String[] facetokens2 = tokens[2].split("/");
91                         String[] facetokens3 = tokens[3].split("/");
92                         String[] facetokens4 = tokens[4].split("/");
93                         
94                         Vector3D p1, p2, p3;
95                         
96                         Face f1 = new Face();
97                         f1.material = currentmat;
98                         p1 = (Vector3D)points.get(Integer.parseInt(facetokens1[0]) - 1);
99                         p2 = (Vector3D)points.get(Integer.parseInt(facetokens2[0]) - 1);
100                         p3 = (Vector3D)points.get(Integer.parseInt(facetokens3[0]) - 1);
101                         f1.setPoints(p1, p2, p3);
102                         
103                         if(f1.getXYangle() >= 90.0)
104                             config.simpleterrain = false;
105                         
106                         faces.add(f1);
107                         
108                         Face f2 = new Face();
109                         f2.material = currentmat;
110                         p1 = (Vector3D)points.get(Integer.parseInt(facetokens1[0]) - 1);
111                         p2 = (Vector3D)points.get(Integer.parseInt(facetokens3[0]) - 1);
112                         p3 = (Vector3D)points.get(Integer.parseInt(facetokens4[0]) - 1);
113                         f2.setPoints(p1, p2, p3);
114                         
115                         if(f2.getXYangle() >= 90.0)
116                             config.simpleterrain = false;
117                         
118                         faces.add(f2);
119                     }
120                 } else if(tokens[0].equals("usemtl")) {
121                     //change material
122                     
123                     currentmat = tokens[1];
124                 }
125             }
126             
127         }
128         
129         System.out.println("Read points: " + points.size() + " Read faces: " + faces.size());
130         
131     }
132     
133     public void writeMap() {
134         if(faces == null) return;
135         
136         PrintWriter out = null;
137         try {
138             out = new PrintWriter(new FileWriter(config.mapfile));
139         } catch(Exception e) {
140             System.err.println("Can't open output file?!");
141             return;
142         }
143         
144         out.print("{\n\"classname\" \"worldspawn\"\n");
145         
146         for(int i = 0; i < faces.size(); i++) {
147             Face f = (Face)faces.get(i);
148             out.print(f.generateBrush());
149         }
150         
151         out.print("}\n");
152         out.flush();
153         out.close();
154     }
155     
156     
157     private class Vector3D {
158         public double x, y, z;
159         
160         public Vector3D() {
161             this(0.0, 0.0, 0.0);
162         }
163         
164         public Vector3D(double x, double y, double z) {
165             this.x = x;
166             this.y = y;
167             this.z = z;
168         }
169         
170         public Vector3D crossproduct(Vector3D p1) {
171             Vector3D result = new Vector3D();
172             
173             result.x = this.y * p1.z - this.z * p1.y;
174             result.y = this.z * p1.x - this.x * p1.z;
175             result.z = this.x * p1.y - this.y * p1.x;
176             
177             return result;
178         }
179         
180         public double dotproduct(Vector3D p1) {
181             return this.x * p1.x + this.y * p1.y + this.z * p1.z;
182         }
183         
184         public Vector3D substract(Vector3D p1) {
185             Vector3D result = new Vector3D();
186             
187             result.x = this.x - p1.x;
188             result.y = this.y - p1.y;
189             result.z = this.z - p1.z;
190             
191             return result;
192         }
193         
194         public void scale(double factor) {
195             x *= factor;
196             y *= factor;
197             z *= factor;
198         }
199         
200         public double length() {
201             return Math.sqrt((x*x) + (y*y) + (z*z));
202         }
203         
204         public void normalize() {
205             double l = length();
206             
207             x /= l;
208             y /= l;
209             z /= l;
210         }
211         
212     }
213     
214     
215     private class Face {
216         private Vector3D p1, p2, p3, normal;
217         private double angle_xy = 0.0;
218         public String material;
219         
220         public void setPoints(Vector3D p1, Vector3D p2, Vector3D p3) {
221             this.p1 = p1;
222             this.p2 = p2;
223             this.p3 = p3;
224             
225             computeNormal();
226             computeXYangle();
227         }
228         
229         public double getXYangle() {
230             return angle_xy;
231         }
232         
233         private void computeNormal() {
234             Vector3D vector1 = p1.substract(p2);
235             Vector3D vector2 = p1.substract(p3);
236             
237             normal = vector1.crossproduct(vector2);
238             normal.normalize();
239         }
240         
241         private void computeXYangle() {
242             Vector3D normal_xy = new Vector3D(0.0, 0.0, 1.0);
243             angle_xy = Math.acos(normal.dotproduct(normal_xy)) / (2 * Math.PI) * 360.0;
244         }
245         
246         public String generateBrush() {
247             String result = "{\n";
248             
249             // this looks like a floor, extrude along the z-axis
250             if(angle_xy < 70.0) {
251                 normal.x = 0.0;
252                 normal.y = 0.0;
253                 normal.z = 1.0;
254             }
255             
256             normal.scale(config.brush_thickness);
257             
258             Vector3D p1_, p2_, p3_;
259             
260             if(!config.simpleterrain) {
261                 p1_ = p1.substract(normal);
262                 p2_ = p2.substract(normal);
263                 p3_ = p3.substract(normal);
264             } else {
265                 double min = config.minz;
266                 min -= 16.0;
267                 p1_ = new Vector3D(p1.x, p1.y, min);
268                 p2_ = new Vector3D(p2.x, p2.y, min);
269                 p3_ = new Vector3D(p3.x, p3.y, min);
270             }
271             
272             String mat = material;
273             
274             if(config.autotexturing.size() > 0) {
275                 double maxangle = -1.0;
276                 for(int i = 0; i < config.autotexturing.size(); i++) {
277                     AutoTexturingEntry e = (AutoTexturingEntry)config.autotexturing.get(i);
278                     if(angle_xy >= e.angle && e.angle > maxangle) {
279                         mat = e.texturename;
280                         maxangle = e.angle;
281                     }
282                 }
283             }
284             
285             // top face, apply texture here
286             result += getMapPlaneString(p3, p2, p1, mat);
287             
288             // bottom face
289             result += getMapPlaneString(p1_, p2_, p3_, "common/caulk");
290             
291             // extruded side 1
292             result += getMapPlaneString(p1, p1_, p3_, "common/caulk");
293             
294             // extruded side 2
295             result += getMapPlaneString(p2, p3, p3_, "common/caulk");
296             
297             // extruded side 3
298             result += getMapPlaneString(p1, p2, p2_, "common/caulk");
299             
300             result += "}\n";
301             
302             return result;
303         }
304         
305         
306         private String getMapPlaneString(Vector3D p1, Vector3D p2, Vector3D p3, String material) {
307             int flag;
308             if(config.detail)
309                 flag = 134217728;
310             else
311                 flag = 0;
312             
313             return "( " + p1.x + " " + p1.y + " " + p1.z + " ) ( " + p2.x + " " + p2.y + " " + p2.z + " ) ( " + p3.x + " " + p3.y + " " + p3.z + " ) " + material + " 0 0 0 " + config.texture_scale + " " + config.texture_scale + " " + flag + " 0 0\n";
314         }
315         
316     }
317     
318 }