]> icculus.org git repositories - divverent/nexuiz.git/blob - tools/ImgToMap/src/imgtomap/MapWriter.java
some UI stuff, some meaningless messages, some test files
[divverent/nexuiz.git] / tools / ImgToMap / src / imgtomap / MapWriter.java
1 /*
2  * To change this template, choose Tools | Templates
3  * and open the template in the editor.
4  */
5 package imgtomap;
6
7 import java.awt.image.BufferedImage;
8 import java.awt.image.Raster;
9 import java.io.File;
10 import java.io.FileNotFoundException;
11 import java.io.FileOutputStream;
12 import java.io.IOException;
13 import java.util.logging.Level;
14 import java.util.logging.Logger;
15 import javax.imageio.ImageIO;
16
17 /**
18  *
19  * @author maik
20  */
21 public class MapWriter {
22
23     public int writeMap(Parameters p) {
24         if (!(new File(p.infile).exists())) {
25             return 1;
26         }
27
28         FileOutputStream fos;
29         try {
30             fos = new FileOutputStream(new File(p.outfile));
31         } catch (FileNotFoundException ex) {
32             Logger.getLogger(MapWriter.class.getName()).log(Level.SEVERE, null, ex);
33             return 1;
34         }
35
36         double[][] height = getHeightmap(p.infile);
37         double units = 1d * p.pixelsize;
38         double max = p.height;
39
40         StringBuffer buf = new StringBuffer();
41
42         // worldspawn start
43         buf.append("{\n\"classname\" \"worldspawn\"\n");
44
45         // wander through grid
46         for (int x = 0; x < height.length - 1; ++x) {
47             for (int y = 0; y < height[0].length - 1; ++y) {
48
49                 boolean skip = height[x][y] < 0 || height[x][y + 1] < 0 || height[x + 1][y] < 0 || height[x + 1][y + 1] < 0;
50
51                 if (!skip) {
52
53                     /*
54                      * 
55                      *      a +-------+ b
56                      *       /       /|
57                      *      /       / |
58                      *     /       /  |
59                      *  c +-------+ d + f   (e occluded, unused)
60                      *    |       |  /
61                      *    |       | /
62                      *    |       |/
63                      *  g +-------+ h
64                      * 
65                      */
66
67                     Vector3D a = new Vector3D(x * units, -y * units, height[x][y] * max);
68                     Vector3D b = new Vector3D((x + 1) * units, -y * units, height[x + 1][y] * max);
69                     Vector3D c = new Vector3D(x * units, -(y + 1) * units, height[x][y + 1] * max);
70                     Vector3D d = new Vector3D((x + 1) * units, -(y + 1) * units, height[x + 1][y + 1] * max);
71                     //Vector3D e = new Vector3D(x * units, -y * units, -16.0);
72                     Vector3D f = new Vector3D((x + 1) * units, -y * units, -16.0);
73                     Vector3D g = new Vector3D(x * units, -(y + 1) * units, -16.0);
74                     Vector3D h = new Vector3D((x + 1) * units, -(y + 1) * units, -16.0);
75
76                     buf.append("{\n");
77                     buf.append(getMapPlaneString(a, b, d, p.detail, p.texture, p.texturescale));
78                     buf.append(getMapPlaneString(d, b, f, p.detail, "common/caulk", p.texturescale));
79                     buf.append(getMapPlaneString(f, b, a, p.detail, "common/caulk", p.texturescale));
80                     buf.append(getMapPlaneString(a, d, h, p.detail, "common/caulk", p.texturescale));
81                     buf.append(getMapPlaneString(g, h, f, p.detail, "common/caulk", p.texturescale));
82                     buf.append("}\n");
83
84
85                     buf.append("{\n");
86                     buf.append(getMapPlaneString(d, c, a, p.detail, p.texture, p.texturescale));
87                     buf.append(getMapPlaneString(g, c, d, p.detail, "common/caulk", p.texturescale));
88                     buf.append(getMapPlaneString(c, g, a, p.detail, "common/caulk", p.texturescale));
89                     buf.append(getMapPlaneString(h, d, a, p.detail, "common/caulk", p.texturescale));
90                     buf.append(getMapPlaneString(g, h, f, p.detail, "common/caulk", p.texturescale));
91                     buf.append("}\n");
92                 }
93             }
94         }
95
96         // worldspawn end
97         buf.append("}\n");
98         try {
99             fos.write(buf.toString().getBytes());
100         } catch (IOException ex) {
101             Logger.getLogger(MapWriter.class.getName()).log(Level.SEVERE, null, ex);
102             return 1;
103         }
104         return 0;
105     }
106
107     private String getMapPlaneString(Vector3D p1, Vector3D p2, Vector3D p3, boolean detail, String material, double scale) {
108         int flag;
109         if (detail) {
110             flag = 134217728;
111         } else {
112             flag = 0;
113         }
114         return "( " + p1.x + " " + p1.y + " " + p1.z + " ) ( " + p2.x + " " + p2.y + " " + p2.z + " ) ( " + p3.x + " " + p3.y + " " + p3.z + " ) " + material + " 0 0 0 " + scale + " " + scale + " " + flag + " 0 0\n";
115     }
116
117     private class Vector3D {
118
119         public double x,  y,  z;
120
121         public Vector3D() {
122             this(0.0, 0.0, 0.0);
123         }
124
125         public Vector3D(double x, double y, double z) {
126             this.x = x;
127             this.y = y;
128             this.z = z;
129         }
130
131         public Vector3D crossproduct(Vector3D p1) {
132             Vector3D result = new Vector3D();
133
134             result.x = this.y * p1.z - this.z * p1.y;
135             result.y = this.z * p1.x - this.x * p1.z;
136             result.z = this.x * p1.y - this.y * p1.x;
137
138             return result;
139         }
140
141         public double dotproduct(Vector3D p1) {
142             return this.x * p1.x + this.y * p1.y + this.z * p1.z;
143         }
144
145         public Vector3D substract(Vector3D p1) {
146             Vector3D result = new Vector3D();
147
148             result.x = this.x - p1.x;
149             result.y = this.y - p1.y;
150             result.z = this.z - p1.z;
151
152             return result;
153         }
154
155         public void scale(double factor) {
156             x *= factor;
157             y *= factor;
158             z *= factor;
159         }
160
161         public double length() {
162             return Math.sqrt((x * x) + (y * y) + (z * z));
163         }
164
165         public void normalize() {
166             double l = length();
167
168             x /= l;
169             y /= l;
170             z /= l;
171         }
172     }
173
174     private double[][] getHeightmap(String file) {
175         try {
176             BufferedImage bimg = ImageIO.read(new File(file));
177             Raster raster = bimg.getRaster();
178             int x = raster.getWidth();
179             int y = raster.getHeight();
180
181             double[][] result = new double[x][y];
182
183             for (int xi = 0; xi < x; ++xi) {
184                 for (int yi = 0; yi < y; ++yi) {
185                     float[] pixel = raster.getPixel(xi, yi, (float[]) null);
186
187                     int channels;
188                     boolean alpha;
189                     if (pixel.length == 3) {
190                         // RGB
191                         channels = 3;
192                         alpha = false;
193                     } else if (pixel.length == 4) {
194                         // RGBA
195                         channels = 3;
196                         alpha = true;
197                     } else if (pixel.length == 1) {
198                         // grayscale
199                         channels = 1;
200                         alpha = false;
201                     } else {
202                         // grayscale with alpha
203                         channels = 1;
204                         alpha = true;
205                     }
206
207                     float tmp = 0f;
208                     for (int i = 0; i < channels; ++i) {
209                         tmp += pixel[i];
210                     }
211                     result[xi][yi] = tmp / (channels * 255f);
212
213                     if (alpha) {
214                         // mark this pixel to be skipped
215                         if (pixel[pixel.length - 1] < 64.0) {
216                             result[xi][yi] = -1.0;
217                         }
218                     }
219                 }
220             }
221
222
223             return result;
224         } catch (IOException ex) {
225             Logger.getLogger(MapWriter.class.getName()).log(Level.SEVERE, null, ex);
226         }
227
228         return null;
229     }
230 }