From 0748c2c515e1e6ce7447839a03ef264ba31a44c5 Mon Sep 17 00:00:00 2001 From: savagex Date: Sun, 18 May 2008 10:08:14 +0000 Subject: [PATCH] evaluate alpha channels (can be used to punch "holes" into the generated terrain for maps with "organic" shape) use platform Look&Feel (nobody likes Swing's Metal theme) git-svn-id: svn://svn.icculus.org/nexuiz/trunk@3632 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- tools/ImgToMap/src/imgtomap/JFrameMain.form | 50 +++++--- tools/ImgToMap/src/imgtomap/JFrameMain.java | 64 ++++++---- tools/ImgToMap/src/imgtomap/Main.java | 16 ++- tools/ImgToMap/src/imgtomap/MapWriter.java | 129 ++++++++++++-------- 4 files changed, 162 insertions(+), 97 deletions(-) diff --git a/tools/ImgToMap/src/imgtomap/JFrameMain.form b/tools/ImgToMap/src/imgtomap/JFrameMain.form index 212ef3db3..a762ef121 100644 --- a/tools/ImgToMap/src/imgtomap/JFrameMain.form +++ b/tools/ImgToMap/src/imgtomap/JFrameMain.form @@ -52,19 +52,19 @@ - + - + - - + + - - + + @@ -78,12 +78,18 @@ - + + + + + + - + + @@ -106,18 +112,21 @@ + - + - + + + @@ -126,12 +135,6 @@ - - - - - - @@ -142,9 +145,6 @@ - - - @@ -199,6 +199,18 @@ + + + + + + + + + + + + diff --git a/tools/ImgToMap/src/imgtomap/JFrameMain.java b/tools/ImgToMap/src/imgtomap/JFrameMain.java index cf2836b2a..acffb3e61 100644 --- a/tools/ImgToMap/src/imgtomap/JFrameMain.java +++ b/tools/ImgToMap/src/imgtomap/JFrameMain.java @@ -18,6 +18,14 @@ public class JFrameMain extends javax.swing.JFrame { /** Creates new form JFrameMain */ public JFrameMain() { initComponents(); + String testinput = "/mnt/data/nexuizsvn/nexuiz/trunk/tools/ImgToMap/test1.png"; + String testoutput = "/tmp/test.map"; + + if(new File(testinput).exists()) { + jTextFieldInput.setText(testinput); + jTextFieldOutput.setText(testoutput); + } + } /** This method is called from within the constructor to @@ -42,19 +50,14 @@ public class JFrameMain extends javax.swing.JFrame { jLabel3 = new javax.swing.JLabel(); jTextFieldTexture = new javax.swing.JTextField(); jCheckBoxDetail = new javax.swing.JCheckBox(); + jLabel4 = new javax.swing.JLabel(); + jSpinner1 = new javax.swing.JSpinner(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("ImgToMap"); jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Convert image to map")); - jTextFieldInput.setText("/home/maik/netbeans/ImgToMap/test1.png"); - jTextFieldInput.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jTextFieldInputActionPerformed(evt); - } - }); - jButtonInput.setText("Select input file"); jButtonInput.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -62,8 +65,6 @@ public class JFrameMain extends javax.swing.JFrame { } }); - jTextFieldOutput.setText("/tmp/test.map"); - jButtonOutput.setText("Select output file"); jSpinnerUnits.setModel(new javax.swing.SpinnerNumberModel(256, 1, 2048, 1)); @@ -88,6 +89,10 @@ public class JFrameMain extends javax.swing.JFrame { jCheckBoxDetail.setSelected(true); jCheckBoxDetail.setText("make detail"); + jLabel4.setText("Texture scale:"); + + jSpinner1.setModel(new javax.swing.SpinnerNumberModel(0.5d, 0.25d, 16.0d, 0.25d)); + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( @@ -95,15 +100,15 @@ public class JFrameMain extends javax.swing.JFrame { .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jTextFieldTexture, javax.swing.GroupLayout.DEFAULT_SIZE, 421, Short.MAX_VALUE) + .addComponent(jTextFieldTexture, javax.swing.GroupLayout.DEFAULT_SIZE, 465, Short.MAX_VALUE) .addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(jTextFieldInput, javax.swing.GroupLayout.DEFAULT_SIZE, 291, Short.MAX_VALUE) - .addComponent(jTextFieldOutput, javax.swing.GroupLayout.DEFAULT_SIZE, 291, Short.MAX_VALUE)) + .addComponent(jTextFieldInput, javax.swing.GroupLayout.DEFAULT_SIZE, 313, Short.MAX_VALUE) + .addComponent(jTextFieldOutput, javax.swing.GroupLayout.DEFAULT_SIZE, 313, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(jButtonOutput, javax.swing.GroupLayout.DEFAULT_SIZE, 124, Short.MAX_VALUE) - .addComponent(jButtonInput, javax.swing.GroupLayout.DEFAULT_SIZE, 124, Short.MAX_VALUE))) + .addComponent(jButtonOutput, javax.swing.GroupLayout.DEFAULT_SIZE, 146, Short.MAX_VALUE) + .addComponent(jButtonInput, javax.swing.GroupLayout.DEFAULT_SIZE, 146, Short.MAX_VALUE))) .addComponent(jButtonOK) .addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -114,9 +119,14 @@ public class JFrameMain extends javax.swing.JFrame { .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(jSpinnerHeight, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) - .addComponent(jCheckBoxDetail)) - .addComponent(jLabel2))) - .addComponent(jLabel3)) + .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel2) + .addGap(18, 18, 18) + .addComponent(jLabel4))) + .addGap(132, 132, 132)) + .addComponent(jLabel3) + .addComponent(jCheckBoxDetail)) .addContainerGap()) ); jPanel1Layout.setVerticalGroup( @@ -133,17 +143,20 @@ public class JFrameMain extends javax.swing.JFrame { .addGap(18, 18, 18) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) - .addComponent(jLabel2)) + .addComponent(jLabel2) + .addComponent(jLabel4)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jSpinnerUnits, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jSpinnerHeight, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jCheckBoxDetail)) + .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jLabel3) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jTextFieldTexture, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 39, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jCheckBoxDetail) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE) .addComponent(jButtonOK) .addContainerGap()) ); @@ -180,17 +193,14 @@ private void jButtonInputActionPerformed(java.awt.event.ActionEvent evt) {//GEN- } }//GEN-LAST:event_jButtonInputActionPerformed -private void jTextFieldInputActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextFieldInputActionPerformed -// TODO add your handling code here: -}//GEN-LAST:event_jTextFieldInputActionPerformed - private void jButtonOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonOKActionPerformed Parameters p = new Parameters(); p.infile = jTextFieldInput.getText(); p.outfile = jTextFieldOutput.getText(); p.texture = jTextFieldTexture.getText(); - p.pixelsize = new Integer(jSpinnerUnits.getValue().toString()); - p.height = new Integer(jSpinnerHeight.getValue().toString()); + p.pixelsize = (Integer)jSpinnerUnits.getValue(); + p.height = (Integer)jSpinnerHeight.getValue(); + p.texturescale = (Double)jSpinner1.getValue(); p.detail = jCheckBoxDetail.isSelected(); new MapWriter().writeMap(p); }//GEN-LAST:event_jButtonOKActionPerformed @@ -214,7 +224,9 @@ private void jButtonOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIR private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; private javax.swing.JPanel jPanel1; + private javax.swing.JSpinner jSpinner1; private javax.swing.JSpinner jSpinnerHeight; private javax.swing.JSpinner jSpinnerUnits; private javax.swing.JTextField jTextFieldInput; diff --git a/tools/ImgToMap/src/imgtomap/Main.java b/tools/ImgToMap/src/imgtomap/Main.java index a10a73867..481e747d1 100644 --- a/tools/ImgToMap/src/imgtomap/Main.java +++ b/tools/ImgToMap/src/imgtomap/Main.java @@ -1,7 +1,10 @@ - package imgtomap; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; /** * @@ -14,12 +17,19 @@ public class Main { */ public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { + public void run() { + + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception ex) { + // not critical, just ignore + } + JFrameMain frame = new JFrameMain(); frame.setVisible(true); } }); - - } + } } diff --git a/tools/ImgToMap/src/imgtomap/MapWriter.java b/tools/ImgToMap/src/imgtomap/MapWriter.java index ade18049e..4873eef64 100644 --- a/tools/ImgToMap/src/imgtomap/MapWriter.java +++ b/tools/ImgToMap/src/imgtomap/MapWriter.java @@ -24,7 +24,7 @@ public class MapWriter { if (!(new File(p.infile).exists())) { return; } - + FileOutputStream fos; try { fos = new FileOutputStream(new File(p.outfile)); @@ -32,7 +32,7 @@ public class MapWriter { Logger.getLogger(MapWriter.class.getName()).log(Level.SEVERE, null, ex); return; } - + double[][] height = getHeightmap(p.infile); double units = 1d * p.pixelsize; double max = p.height; @@ -43,52 +43,56 @@ public class MapWriter { buf.append("{\n\"classname\" \"worldspawn\"\n"); // wander through grid - for (int x = 0; x < height.length-1; ++x) { - for (int y = 0; y < height[0].length-1; ++y) { - - - /* - * - * a +-------+ b - * / /| - * / / | - * / / | - * c +-------+ d + f (e occluded, unused) - * | | / - * | | / - * | |/ - * g +-------+ h - * - */ - - Vector3D a = new Vector3D(x * units, -y * units, height[x][y] * max); - Vector3D b = new Vector3D((x+1) * units, -y * units, height[x+1][y] * max); - Vector3D c = new Vector3D(x * units, -(y+1) * units, height[x][y+1] * max); - Vector3D d = new Vector3D((x+1) * units, -(y+1) * units, height[x+1][y+1] * max); - //Vector3D e = new Vector3D(x * units, -y * units, -16.0); - Vector3D f = new Vector3D((x+1) * units, -y * units, -16.0); - Vector3D g = new Vector3D(x * units, -(y+1) * units, -16.0); - Vector3D h = new Vector3D((x+1) * units, -(y+1) * units, -16.0); - - buf.append("{\n"); - buf.append(getMapPlaneString(a,b,d, p.detail, p.texture, p.texturescale)); - buf.append(getMapPlaneString(d,b,f, p.detail, "common/caulk", p.texturescale)); - buf.append(getMapPlaneString(f,b,a, p.detail, "common/caulk", p.texturescale)); - buf.append(getMapPlaneString(a,d,h, p.detail, "common/caulk", p.texturescale)); - buf.append(getMapPlaneString(g,h,f, p.detail, "common/caulk", p.texturescale)); - buf.append("}\n"); - - - buf.append("{\n"); - buf.append(getMapPlaneString(d,c,a, p.detail, p.texture, p.texturescale)); - buf.append(getMapPlaneString(g,c,d, p.detail, "common/caulk", p.texturescale)); - buf.append(getMapPlaneString(c,g,a, p.detail, "common/caulk", p.texturescale)); - buf.append(getMapPlaneString(h,d,a, p.detail, "common/caulk", p.texturescale)); - buf.append(getMapPlaneString(g,h,f, p.detail, "common/caulk", p.texturescale)); - buf.append("}\n"); + 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; + + if (!skip) { + + /* + * + * a +-------+ b + * / /| + * / / | + * / / | + * c +-------+ d + f (e occluded, unused) + * | | / + * | | / + * | |/ + * g +-------+ h + * + */ + + Vector3D a = new Vector3D(x * units, -y * units, height[x][y] * max); + Vector3D b = new Vector3D((x + 1) * units, -y * units, height[x + 1][y] * max); + Vector3D c = new Vector3D(x * units, -(y + 1) * units, height[x][y + 1] * max); + Vector3D d = new Vector3D((x + 1) * units, -(y + 1) * units, height[x + 1][y + 1] * max); + //Vector3D e = new Vector3D(x * units, -y * units, -16.0); + Vector3D f = new Vector3D((x + 1) * units, -y * units, -16.0); + Vector3D g = new Vector3D(x * units, -(y + 1) * units, -16.0); + Vector3D h = new Vector3D((x + 1) * units, -(y + 1) * units, -16.0); + + buf.append("{\n"); + buf.append(getMapPlaneString(a, b, d, p.detail, p.texture, p.texturescale)); + buf.append(getMapPlaneString(d, b, f, p.detail, "common/caulk", p.texturescale)); + buf.append(getMapPlaneString(f, b, a, p.detail, "common/caulk", p.texturescale)); + buf.append(getMapPlaneString(a, d, h, p.detail, "common/caulk", p.texturescale)); + buf.append(getMapPlaneString(g, h, f, p.detail, "common/caulk", p.texturescale)); + buf.append("}\n"); + + + buf.append("{\n"); + buf.append(getMapPlaneString(d, c, a, p.detail, p.texture, p.texturescale)); + buf.append(getMapPlaneString(g, c, d, p.detail, "common/caulk", p.texturescale)); + buf.append(getMapPlaneString(c, g, a, p.detail, "common/caulk", p.texturescale)); + buf.append(getMapPlaneString(h, d, a, p.detail, "common/caulk", p.texturescale)); + buf.append(getMapPlaneString(g, h, f, p.detail, "common/caulk", p.texturescale)); + buf.append("}\n"); + } } } - + // worldspawn end buf.append("}\n"); try { @@ -172,17 +176,44 @@ public class MapWriter { 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 < pixel.length; ++i) { + for (int i = 0; i < channels; ++i) { tmp += pixel[i]; } - result[xi][yi] = tmp / (pixel.length * 255f); + 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; + } + } } } -- 2.39.2