2 * To change this template, choose Tools | Templates
3 * and open the template in the editor.
7 import java.awt.image.BufferedImage;
8 import java.awt.image.Raster;
9 import java.io.BufferedOutputStream;
11 import java.io.FileNotFoundException;
12 import java.io.FileOutputStream;
13 import java.io.IOException;
14 import java.io.PrintWriter;
15 import java.util.logging.Level;
16 import java.util.logging.Logger;
17 import javax.imageio.ImageIO;
23 public class MapWriter {
25 public int writeMap(Parameters p) {
26 if (!(new File(p.infile).exists())) {
32 fos = new FileOutputStream(new File(p.outfile));
33 } catch (FileNotFoundException ex) {
34 Logger.getLogger(MapWriter.class.getName()).log(Level.SEVERE, null, ex);
38 double[][] height = getHeightmap(p.infile);
39 double units = 1d * p.pixelsize;
40 double max = p.height;
42 PrintWriter pw = null;
44 pw = new PrintWriter(new FileOutputStream(new File(p.outfile)));
45 } catch (FileNotFoundException ex) {
46 Logger.getLogger(MapWriter.class.getName()).log(Level.SEVERE, null, ex);
52 pw.print("{\n\"classname\" \"worldspawn\"\n");
54 // wander through grid
55 for (int x = 0; x < height.length - 1; ++x) {
56 for (int y = 0; y < height[0].length - 1; ++y) {
58 boolean skip = height[x][y] < 0 || height[x][y + 1] < 0 || height[x + 1][y] < 0 || height[x + 1][y + 1] < 0;
68 * c +-------+ d + f (e occluded, unused)
76 Vector3D a = new Vector3D(x * units, -y * units, height[x][y] * max);
77 Vector3D b = new Vector3D((x + 1) * units, -y * units, height[x + 1][y] * max);
78 Vector3D c = new Vector3D(x * units, -(y + 1) * units, height[x][y + 1] * max);
79 Vector3D d = new Vector3D((x + 1) * units, -(y + 1) * units, height[x + 1][y + 1] * max);
80 //Vector3D e = new Vector3D(x * units, -y * units, -16.0);
81 Vector3D f = new Vector3D((x + 1) * units, -y * units, -16.0);
82 Vector3D g = new Vector3D(x * units, -(y + 1) * units, -16.0);
83 Vector3D h = new Vector3D((x + 1) * units, -(y + 1) * units, -16.0);
86 pw.print(getMapPlaneString(a, b, d, p.detail, p.texture, p.texturescale));
87 pw.print(getMapPlaneString(d, b, f, p.detail, "common/caulk", p.texturescale));
88 pw.print(getMapPlaneString(f, b, a, p.detail, "common/caulk", p.texturescale));
89 pw.print(getMapPlaneString(a, d, h, p.detail, "common/caulk", p.texturescale));
90 pw.print(getMapPlaneString(g, h, f, p.detail, "common/caulk", p.texturescale));
95 pw.print(getMapPlaneString(d, c, a, p.detail, p.texture, p.texturescale));
96 pw.print(getMapPlaneString(g, c, d, p.detail, "common/caulk", p.texturescale));
97 pw.print(getMapPlaneString(c, g, a, p.detail, "common/caulk", p.texturescale));
98 pw.print(getMapPlaneString(h, d, a, p.detail, "common/caulk", p.texturescale));
99 pw.print(getMapPlaneString(g, h, f, p.detail, "common/caulk", p.texturescale));
101 } else if (p.skyfill) {
103 boolean totalskip = height[x][y] < -5 || height[x][y + 1] < -5 || height[x + 1][y] < -5 || height[x + 1][y + 1] < -5;
106 // fill skipped blocks with sky
107 Vector3D p1 = new Vector3D(x * units, -(y + 1) * units, -32.0);
108 Vector3D p2 = new Vector3D((x + 1) * units, -y * units, p.skyheight);
110 writeBoxBrush(pw, p1, p2, false, p.skytexture, 1.0);
118 int x = height.length - 1;
119 int y = height[0].length - 1;
122 Vector3D p1 = new Vector3D(0, -y * units, p.skyheight);
123 Vector3D p2 = new Vector3D(x * units, 0, p.skyheight + 32.0);
124 writeBoxBrush(pw, p1, p2, false, p.skytexture, 1.0);
127 p1 = new Vector3D(0, -y * units, -64.0);
128 p2 = new Vector3D(x * units, 0, -32.0);
129 writeBoxBrush(pw, p1, p2, false, p.skytexture, 1.0);
132 p1 = new Vector3D(0, 0, -32.0);
133 p2 = new Vector3D(x * units, 32, p.skyheight);
134 writeBoxBrush(pw, p1, p2, false, p.skytexture, 1.0);
137 p1 = new Vector3D(x * units, -y * units, -32.0);
138 p2 = new Vector3D(x * units + 32.0, 0, p.skyheight);
139 writeBoxBrush(pw, p1, p2, false, p.skytexture, 1.0);
142 p1 = new Vector3D(0, -y * units - 32, -32.0);
143 p2 = new Vector3D(x * units, -y * units, p.skyheight);
144 writeBoxBrush(pw, p1, p2, false, p.skytexture, 1.0);
148 p1 = new Vector3D(0 - 32.0, -y * units, -32.0);
149 p2 = new Vector3D(0, 0, p.skyheight);
150 writeBoxBrush(pw, p1, p2, false, p.skytexture, 1.0);
160 private void writeBoxBrush(PrintWriter pw, Vector3D p1, Vector3D p2, boolean detail, String texture, double scale) {
161 Vector3D a = new Vector3D(p1.x, p2.y, p2.z);
163 Vector3D c = new Vector3D(p1.x, p1.y, p2.z);
164 Vector3D d = new Vector3D(p2.x, p1.y, p2.z);
166 Vector3D f = new Vector3D(p2.x, p2.y, p1.z);
168 Vector3D h = new Vector3D(p2.x, p1.y, p1.z);
171 pw.print(getMapPlaneString(a, b, d, detail, texture, scale));
172 pw.print(getMapPlaneString(d, b, f, detail, texture, scale));
173 pw.print(getMapPlaneString(c, d, h, detail, texture, scale));
174 pw.print(getMapPlaneString(a, c, g, detail, texture, scale));
175 pw.print(getMapPlaneString(f, b, a, detail, texture, scale));
176 pw.print(getMapPlaneString(g, h, f, detail, texture, scale));
181 private String getMapPlaneString(Vector3D p1, Vector3D p2, Vector3D p3, boolean detail, String material, double scale) {
188 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";
191 private class Vector3D {
193 public double x, y, z;
199 public Vector3D(double x, double y, double z) {
205 public Vector3D crossproduct(Vector3D p1) {
206 Vector3D result = new Vector3D();
208 result.x = this.y * p1.z - this.z * p1.y;
209 result.y = this.z * p1.x - this.x * p1.z;
210 result.z = this.x * p1.y - this.y * p1.x;
215 public double dotproduct(Vector3D p1) {
216 return this.x * p1.x + this.y * p1.y + this.z * p1.z;
219 public Vector3D substract(Vector3D p1) {
220 Vector3D result = new Vector3D();
222 result.x = this.x - p1.x;
223 result.y = this.y - p1.y;
224 result.z = this.z - p1.z;
229 public void scale(double factor) {
235 public double length() {
236 return Math.sqrt((x * x) + (y * y) + (z * z));
239 public void normalize() {
248 private double[][] markTotalSkip(double[][] input) {
249 double[][] result = new double[input.length][input[0].length];
251 int xmax = input.length - 1;
252 int ymax = input[0].length - 1;
254 for (int x = 0; x <= xmax; ++x) {
255 for (int y = 0; y <= ymax; ++y) {
262 if (x - 1 >= 0 && y - 1 >= 0) {
263 val = input[x - 1][y - 1];
264 max = val > max ? val : max;
268 val = input[x][y - 1];
269 max = val > max ? val : max;
272 if (x + 1 <= xmax && y - 1 >= 0) {
273 val = input[x + 1][y - 1];
274 max = val > max ? val : max;
278 val = input[x - 1][y];
279 max = val > max ? val : max;
283 val = input[x + 1][y];
284 max = val > max ? val : max;
287 if (x - 1 >= 0 && y + 1 <= ymax) {
288 val = input[x - 1][y + 1];
289 max = val > max ? val : max;
293 val = input[x][y + 1];
294 max = val > max ? val : max;
297 if (x + 1 <= xmax && y + 1 <= ymax) {
298 val = input[x + 1][y + 1];
299 max = val > max ? val : max;
303 result[x][y] = -10.0;
305 result[x][y] = input[x][y];
315 private double[][] getHeightmap(String file) {
317 BufferedImage bimg = ImageIO.read(new File(file));
318 Raster raster = bimg.getRaster();
319 int x = raster.getWidth();
320 int y = raster.getHeight();
322 double[][] result = new double[x][y];
324 for (int xi = 0; xi < x; ++xi) {
325 for (int yi = 0; yi < y; ++yi) {
326 float[] pixel = raster.getPixel(xi, yi, (float[]) null);
330 if (pixel.length == 3) {
334 } else if (pixel.length == 4) {
338 } else if (pixel.length == 1) {
343 // grayscale with alpha
349 for (int i = 0; i < channels; ++i) {
352 result[xi][yi] = tmp / (channels * 255f);
355 // mark this pixel to be skipped
356 if (pixel[pixel.length - 1] < 64.0) {
357 result[xi][yi] = -1.0;
364 return markTotalSkip(result);
365 } catch (IOException ex) {
366 Logger.getLogger(MapWriter.class.getName()).log(Level.SEVERE, null, ex);