r3642 - trunk/tools/ImgToMap/src/imgtomap
savagex at icculus.org
savagex at icculus.org
Wed May 21 15:10:31 EDT 2008
Author: savagex
Date: 2008-05-21 15:10:25 -0400 (Wed, 21 May 2008)
New Revision: 3642
Modified:
trunk/tools/ImgToMap/src/imgtomap/JFrameMain.form
trunk/tools/ImgToMap/src/imgtomap/JFrameMain.java
trunk/tools/ImgToMap/src/imgtomap/MapWriter.java
trunk/tools/ImgToMap/src/imgtomap/Parameters.java
Log:
UNBELIEVABLE NEW FEAUTURE! Create hidden visblockers inside the terrain!
Wow!
(also: major rework of skyfillers and stuff)
Modified: trunk/tools/ImgToMap/src/imgtomap/JFrameMain.form
===================================================================
--- trunk/tools/ImgToMap/src/imgtomap/JFrameMain.form 2008-05-21 13:23:41 UTC (rev 3641)
+++ trunk/tools/ImgToMap/src/imgtomap/JFrameMain.form 2008-05-21 19:10:25 UTC (rev 3642)
@@ -42,7 +42,7 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
- <Component id="jPanelSky" min="-2" pref="157" max="-2" attributes="0"/>
+ <Component id="jPanelSky" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jButtonOK" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
@@ -152,18 +152,19 @@
<Component id="jSpinnerHeight" min="0" pref="0" max="32767" attributes="1"/>
<Component id="jSpinnerUnits" alignment="0" max="32767" attributes="1"/>
</Group>
+ <EmptySpace max="-2" attributes="0"/>
+ <Component id="jLabel4" min="-2" max="-2" attributes="1"/>
+ <EmptySpace max="-2" attributes="0"/>
+ <Component id="jSpinnerTextureScale" pref="96" max="32767" attributes="1"/>
+ </Group>
+ <Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
+ <Component id="jTextFieldTexture" alignment="1" pref="416" max="32767" attributes="0"/>
+ <Group type="102" alignment="0" attributes="0">
+ <Component id="jCheckBoxDetail" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
- <Group type="103" groupAlignment="0" attributes="0">
- <Group type="102" attributes="0">
- <Component id="jLabel4" min="-2" max="-2" attributes="1"/>
- <EmptySpace max="-2" attributes="0"/>
- <Component id="jSpinnerTextureScale" max="32767" attributes="1"/>
- </Group>
- <Component id="jCheckBoxDetail" min="-2" max="-2" attributes="0"/>
- </Group>
+ <Component id="jCheckBoxVisBlocker" min="-2" max="-2" attributes="0"/>
+ <EmptySpace max="-2" attributes="0"/>
</Group>
- <Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
- <Component id="jTextFieldTexture" alignment="1" pref="404" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@@ -182,9 +183,13 @@
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jSpinnerHeight" alignment="3" min="-2" max="-2" attributes="0"/>
+ </Group>
+ <EmptySpace max="-2" attributes="0"/>
+ <Group type="103" groupAlignment="3" attributes="0">
<Component id="jCheckBoxDetail" alignment="3" min="-2" max="-2" attributes="0"/>
+ <Component id="jCheckBoxVisBlocker" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
- <EmptySpace type="separate" max="-2" attributes="0"/>
+ <EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
<Component id="jLabel3" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jTextFieldTexture" min="-2" max="-2" attributes="0"/>
@@ -249,6 +254,12 @@
<Property name="text" type="java.lang.String" value="Units per pixel:"/>
</Properties>
</Component>
+ <Component class="javax.swing.JCheckBox" name="jCheckBoxVisBlocker">
+ <Properties>
+ <Property name="selected" type="boolean" value="true"/>
+ <Property name="text" type="java.lang.String" value="generate visblockers"/>
+ </Properties>
+ </Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanelSky">
Modified: trunk/tools/ImgToMap/src/imgtomap/JFrameMain.java
===================================================================
--- trunk/tools/ImgToMap/src/imgtomap/JFrameMain.java 2008-05-21 13:23:41 UTC (rev 3641)
+++ trunk/tools/ImgToMap/src/imgtomap/JFrameMain.java 2008-05-21 19:10:25 UTC (rev 3642)
@@ -55,6 +55,7 @@
jLabel4 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
jLabel1 = new javax.swing.JLabel();
+ jCheckBoxVisBlocker = new javax.swing.JCheckBox();
jPanelSky = new javax.swing.JPanel();
jCheckBoxSky = new javax.swing.JCheckBox();
jLabel5 = new javax.swing.JLabel();
@@ -144,6 +145,9 @@
jLabel1.setText("Units per pixel:");
+ jCheckBoxVisBlocker.setSelected(true);
+ jCheckBoxVisBlocker.setText("generate visblockers");
+
org.jdesktop.layout.GroupLayout jPanel2Layout = new org.jdesktop.layout.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
@@ -159,15 +163,17 @@
.add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
.add(jSpinnerHeight, 0, 0, Short.MAX_VALUE)
.add(jSpinnerUnits))
+ .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+ .add(jLabel4)
+ .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+ .add(jSpinnerTextureScale, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 96, Short.MAX_VALUE))
+ .add(jLabel3)
+ .add(org.jdesktop.layout.GroupLayout.TRAILING, jTextFieldTexture, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 416, Short.MAX_VALUE)
+ .add(jPanel2Layout.createSequentialGroup()
+ .add(jCheckBoxDetail)
.add(18, 18, 18)
- .add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
- .add(jPanel2Layout.createSequentialGroup()
- .add(jLabel4)
- .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
- .add(jSpinnerTextureScale))
- .add(jCheckBoxDetail)))
- .add(jLabel3)
- .add(org.jdesktop.layout.GroupLayout.TRAILING, jTextFieldTexture, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 404, Short.MAX_VALUE))
+ .add(jCheckBoxVisBlocker)
+ .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)))
.addContainerGap())
);
jPanel2Layout.setVerticalGroup(
@@ -181,9 +187,12 @@
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(jLabel2)
- .add(jSpinnerHeight, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
- .add(jCheckBoxDetail))
- .add(18, 18, 18)
+ .add(jSpinnerHeight, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+ .add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
+ .add(jCheckBoxDetail)
+ .add(jCheckBoxVisBlocker))
+ .add(14, 14, 14)
.add(jLabel3)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jTextFieldTexture, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
@@ -273,7 +282,7 @@
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jPanel2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
- .add(jPanelSky, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 157, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+ .add(jPanelSky, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(jButtonOK)
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
@@ -305,6 +314,7 @@
p.height = (Integer)jSpinnerHeight.getValue();
p.sky = jCheckBoxSky.isSelected();
p.skyfill = jCheckBoxSkyFill.isSelected();
+ p.visblockers = jCheckBoxVisBlocker.isSelected();
p.skyheight = (Integer)jSpinnerSkyHeight.getValue();
p.texturescale = (Double)jSpinnerTextureScale.getValue();
p.detail = jCheckBoxDetail.isSelected();
@@ -373,6 +383,7 @@
private javax.swing.JCheckBox jCheckBoxDetail;
private javax.swing.JCheckBox jCheckBoxSky;
private javax.swing.JCheckBox jCheckBoxSkyFill;
+ private javax.swing.JCheckBox jCheckBoxVisBlocker;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
Modified: trunk/tools/ImgToMap/src/imgtomap/MapWriter.java
===================================================================
--- trunk/tools/ImgToMap/src/imgtomap/MapWriter.java 2008-05-21 13:23:41 UTC (rev 3641)
+++ trunk/tools/ImgToMap/src/imgtomap/MapWriter.java 2008-05-21 19:10:25 UTC (rev 3642)
@@ -11,6 +11,8 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.LinkedList;
+import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
@@ -26,15 +28,8 @@
return 1;
}
- FileOutputStream fos;
- try {
- fos = new FileOutputStream(new File(p.outfile));
- } catch (FileNotFoundException ex) {
- Logger.getLogger(MapWriter.class.getName()).log(Level.SEVERE, null, ex);
- return 1;
- }
-
double[][] height = getHeightmap(p.infile);
+ double[][] columns = getColumns(height);
double units = 1d * p.pixelsize;
double max = p.height;
@@ -45,8 +40,8 @@
Logger.getLogger(MapWriter.class.getName()).log(Level.SEVERE, null, ex);
return 1;
}
-
+
// worldspawn start
pw.print("{\n\"classname\" \"worldspawn\"\n");
@@ -54,9 +49,9 @@
for (int x = 0; x < height.length - 1; ++x) {
for (int y = 0; y < height[0].length - 1; ++y) {
- boolean skip = height[x][y] < 0 || height[x][y + 1] < 0 || height[x + 1][y] < 0 || height[x + 1][y + 1] < 0;
+ boolean skip = getMinMaxForRegion(height, x, y, 2)[0] < 0;
- if (!skip) {
+ if (!skip && false) {
/*
*
@@ -97,16 +92,23 @@
pw.print(getMapPlaneString(h, d, a, p.detail, "common/caulk", p.texturescale));
pw.print(getMapPlaneString(g, h, f, p.detail, "common/caulk", p.texturescale));
pw.print("}\n");
- } else if (p.skyfill) {
+ }
+ }
+ }
- boolean totalskip = height[x][y] < -5 || height[x][y + 1] < -5 || height[x + 1][y] < -5 || height[x + 1][y + 1] < -5;
+ if (p.skyfill) {
+ for (int x = 0; x < columns.length; ++x) {
+ for (int y = 0; y < columns[0].length; ++y) {
+ if (columns[x][y] < 0) {
+ // this is a skipped block, see if it neighbours a
+ // relevant block
+ double tmp = getMinMaxForRegion(columns, x - 1, y - 1, 3)[1];
+ if (tmp >= 0) {
+ Vector3D p1 = new Vector3D(x * units, -(y + 1) * units, -32.0);
+ Vector3D p2 = new Vector3D((x + 1) * units, -y * units, p.skyheight);
- if (!totalskip) {
- // fill skipped blocks with sky
- Vector3D p1 = new Vector3D(x * units, -(y + 1) * units, -32.0);
- Vector3D p2 = new Vector3D((x + 1) * units, -y * units, p.skyheight);
-
- writeBoxBrush(pw, p1, p2, false, p.skytexture, 1.0);
+ writeBoxBrush(pw, p1, p2, false, p.skytexture, 1.0);
+ }
}
}
}
@@ -150,6 +152,38 @@
}
+ // genBlockers screws the columns array!
+ // this should be the last step!
+ if (p.visblockers) {
+ List<VisBlocker> blockers = genBlockers(columns, 0.15);
+ double xmax = (columns.length - 1) * units;
+ double ymax = (columns[0].length - 1) * units;
+ for (VisBlocker b : blockers) {
+ double z = b.minheight * p.height;
+ z = Math.floor(z / 16);
+ z = z * 16;
+
+ if (z > 0) {
+ int dim = b.dim;
+
+ double x = b.x * units;
+ double y = (b.y + dim) * units;
+ x = x > xmax ? xmax : x;
+ y = y > ymax ? ymax : y;
+ Vector3D p1 = new Vector3D(x, -y, -32.0);
+
+ x = (b.x + dim) * units;
+ y = b.y * units;
+ x = x > xmax ? xmax : x;
+ y = y > ymax ? ymax : y;
+ Vector3D p2 = new Vector3D(x, -y, z);
+
+ writeBoxBrush(pw, p1, p2, false, "common/caulk", 1.0);
+ }
+
+ }
+ }
+
// worldspawn end
pw.print("}\n");
pw.close();
@@ -187,6 +221,137 @@
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";
}
+ private double[][] getHeightmap(String file) {
+ try {
+ BufferedImage bimg = ImageIO.read(new File(file));
+ Raster raster = bimg.getRaster();
+ int x = raster.getWidth();
+ int y = raster.getHeight();
+
+ double[][] result = new double[x][y];
+
+ for (int xi = 0; xi < x; ++xi) {
+ for (int yi = 0; yi < y; ++yi) {
+ float[] pixel = raster.getPixel(xi, yi, (float[]) null);
+
+ int channels;
+ boolean alpha;
+ if (pixel.length == 3) {
+ // RGB
+ channels = 3;
+ alpha = false;
+ } else if (pixel.length == 4) {
+ // RGBA
+ channels = 3;
+ alpha = true;
+ } else if (pixel.length == 1) {
+ // grayscale
+ channels = 1;
+ alpha = false;
+ } else {
+ // grayscale with alpha
+ channels = 1;
+ alpha = true;
+ }
+
+ float tmp = 0f;
+ for (int i = 0; i < channels; ++i) {
+ tmp += pixel[i];
+ }
+ result[xi][yi] = tmp / (channels * 255f);
+
+ if (alpha) {
+ // mark this pixel to be skipped
+ if (pixel[pixel.length - 1] < 64.0) {
+ result[xi][yi] = -1.0;
+ }
+ }
+ }
+ }
+
+
+ return result;
+ } catch (IOException ex) {
+ Logger.getLogger(MapWriter.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ return null;
+ }
+
+ private double[][] getColumns(double[][] heights) {
+ double[][] result = new double[heights.length][heights[0].length];
+
+ for (int x = 0; x < heights.length; ++x) {
+ for (int y = 0; y < heights[0].length; ++y) {
+ result[x][y] = getMinMaxForRegion(heights, x, y, 2)[0];
+ }
+ }
+
+ return result;
+ }
+
+ private double[] getMinMaxForRegion(double[][] field, int x, int y, int dim) {
+ double max = -100d;
+ double min = 100d;
+
+ for (int i = x; i < x + dim; ++i) {
+ for (int j = y; j < y + dim; ++j) {
+ if (i >= 0 && j >= 0 && i < field.length && j < field[0].length) {
+ min = field[i][j] < min ? field[i][j] : min;
+ max = field[i][j] > max ? field[i][j] : max;
+ }
+ }
+ }
+
+ double[] result = {min, max};
+ return result;
+ }
+
+ public List<VisBlocker> genBlockers(double[][] columns, double delta) {
+
+ VisBlocker[][] blockers = new VisBlocker[columns.length][columns[0].length];
+ LinkedList<VisBlocker> result = new LinkedList<VisBlocker>();
+
+ for (int x = 0; x < columns.length; ++x) {
+ for (int y = 0; y < columns[0].length; ++y) {
+ if (blockers[x][y] == null && columns[x][y] >= 0) {
+ // this pixel isn't covered by a blocker yet... so let's create one!
+ VisBlocker b = new VisBlocker();
+ result.add(b);
+ b.x = x;
+ b.y = y;
+ b.minheight = b.origheight = columns[x][y];
+
+ // grow till the delta hits
+ int dim;
+ double min = b.minheight;
+ for (dim = 1; dim < columns.length; ++dim) {
+ double[] minmax = getMinMaxForRegion(columns, x, y, dim);
+ if (Math.abs(b.origheight - minmax[0]) > delta || Math.abs(b.origheight - minmax[1]) > delta) {
+ break;
+ }
+ min = minmax[0];
+
+ }
+
+ b.dim = dim - 1;
+ b.minheight = min;
+
+ for (int i = x; i < x + b.dim; ++i) {
+ for (int j = y; j < y + b.dim; ++j) {
+ if (i >= 0 && j >= 0 && i < blockers.length && j < blockers[0].length) {
+ blockers[i][j] = b;
+ columns[i][j] = -1337.0;
+ }
+ }
+ }
+
+ }
+ }
+ }
+ return result;
+ }
+
private class Vector3D {
public double x, y, z;
@@ -244,127 +409,9 @@
}
}
- private double[][] markTotalSkip(double[][] input) {
- double[][] result = new double[input.length][input[0].length];
+ private class VisBlocker {
- int xmax = input.length - 1;
- int ymax = input[0].length - 1;
-
- for (int x = 0; x <= xmax; ++x) {
- for (int y = 0; y <= ymax; ++y) {
- double val;
- double max;
-
- val = input[x][y];
- max = val;
-
- if (x - 1 >= 0 && y - 1 >= 0) {
- val = input[x - 1][y - 1];
- max = val > max ? val : max;
- }
-
- if (y - 1 >= 0) {
- val = input[x][y - 1];
- max = val > max ? val : max;
- }
-
- if (x + 1 <= xmax && y - 1 >= 0) {
- val = input[x + 1][y - 1];
- max = val > max ? val : max;
- }
-
- if (x - 1 >= 0) {
- val = input[x - 1][y];
- max = val > max ? val : max;
- }
-
- if (x + 1 <= xmax) {
- val = input[x + 1][y];
- max = val > max ? val : max;
- }
-
- if (x - 1 >= 0 && y + 1 <= ymax) {
- val = input[x - 1][y + 1];
- max = val > max ? val : max;
- }
-
- if (y + 1 <= ymax) {
- val = input[x][y + 1];
- max = val > max ? val : max;
- }
-
- if (x + 1 <= xmax && y + 1 <= ymax) {
- val = input[x + 1][y + 1];
- max = val > max ? val : max;
- }
-
- if (max < 0) {
- result[x][y] = -10.0;
- } else {
- result[x][y] = input[x][y];
- }
-
- }
- }
-
-
- return result;
+ public int x, y, dim;
+ public double origheight, minheight;
}
-
- private double[][] getHeightmap(String file) {
- try {
- BufferedImage bimg = ImageIO.read(new File(file));
- Raster raster = bimg.getRaster();
- int x = raster.getWidth();
- int y = raster.getHeight();
-
- double[][] result = new double[x][y];
-
- for (int xi = 0; xi < x; ++xi) {
- for (int yi = 0; yi < y; ++yi) {
- float[] pixel = raster.getPixel(xi, yi, (float[]) null);
-
- int channels;
- boolean alpha;
- if (pixel.length == 3) {
- // RGB
- channels = 3;
- alpha = false;
- } else if (pixel.length == 4) {
- // RGBA
- channels = 3;
- alpha = true;
- } else if (pixel.length == 1) {
- // grayscale
- channels = 1;
- alpha = false;
- } else {
- // grayscale with alpha
- channels = 1;
- alpha = true;
- }
-
- float tmp = 0f;
- for (int i = 0; i < channels; ++i) {
- tmp += pixel[i];
- }
- result[xi][yi] = tmp / (channels * 255f);
-
- if (alpha) {
- // mark this pixel to be skipped
- if (pixel[pixel.length - 1] < 64.0) {
- result[xi][yi] = -1.0;
- }
- }
- }
- }
-
-
- return markTotalSkip(result);
- } catch (IOException ex) {
- Logger.getLogger(MapWriter.class.getName()).log(Level.SEVERE, null, ex);
- }
-
- return null;
- }
-}
+}
\ No newline at end of file
Modified: trunk/tools/ImgToMap/src/imgtomap/Parameters.java
===================================================================
--- trunk/tools/ImgToMap/src/imgtomap/Parameters.java 2008-05-21 13:23:41 UTC (rev 3641)
+++ trunk/tools/ImgToMap/src/imgtomap/Parameters.java 2008-05-21 19:10:25 UTC (rev 3642)
@@ -12,7 +12,7 @@
public class Parameters {
public String infile, outfile, texture, skytexture;
public int pixelsize, height, skyheight;
- public boolean detail, sky, skyfill;
+ public boolean detail, sky, skyfill, visblockers;
public double texturescale = 0.5;
More information about the nexuiz-commits
mailing list