From 365634146c7e841a074896ee04c3055d383c1d89 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 7 Nov 2005 02:20:13 +0000 Subject: [PATCH] Added tool/task to build sphere maps from cube maps. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3748 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../threerings/jme/tools/BuildSphereMap.java | 167 ++++++++++++++++++ .../jme/tools/BuildSphereMapTask.java | 86 +++++++++ 2 files changed, 253 insertions(+) create mode 100644 src/java/com/threerings/jme/tools/BuildSphereMap.java create mode 100644 src/java/com/threerings/jme/tools/BuildSphereMapTask.java diff --git a/src/java/com/threerings/jme/tools/BuildSphereMap.java b/src/java/com/threerings/jme/tools/BuildSphereMap.java new file mode 100644 index 000000000..a147893c4 --- /dev/null +++ b/src/java/com/threerings/jme/tools/BuildSphereMap.java @@ -0,0 +1,167 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.jme.tools; + +import java.awt.image.BufferedImage; + +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import com.jme.image.Texture; +import com.jme.math.FastMath; +import com.jme.math.Vector3f; + +/** + * A tool for converting cube maps (sky boxes) to sphere maps. + */ +public class BuildSphereMap +{ + public static void main (String[] args) + { + if (args.length < 7) { + System.err.println("Usage: BuildSphereMap front.ext back.ext " + + "left.ext right.ext up.ext dest.ext size"); + System.exit(-1); + } + + try { + execute(new File(args[0]), new File(args[1]), new File(args[2]), + new File(args[3]), new File(args[4]), new File(args[5]), + Integer.parseInt(args[6])); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Builds the sphere map. + * + * @param front the file containing the front side of the cube map + * @param back the file containing the back side of the cube map + * @param left the file containing the left side of the cube map + * @param right the file containing the right side of the cube map + * @param up the file containing the up side of the cube map + * @param target the file to contain the sphere map + * @param size the size of the sphere map to generate + */ + public static void execute (File front, File back, File left, File right, + File up, File target, int size) + throws IOException + { + // load up the sides of the cube map + BufferedImage[] sides = new BufferedImage[5]; + sides[FRONT] = ImageIO.read(front); + sides[BACK] = ImageIO.read(back); + sides[LEFT] = ImageIO.read(left); + sides[RIGHT] = ImageIO.read(right); + sides[UP] = ImageIO.read(up); + + // compute the pixels + int[] rgb = new int[size * size]; + Vector3f vec = new Vector3f(); + for (int y = 0, idx = 0; y < size; y++) { + for (int x = 0; x < size; x++, idx++) { + float vx = x / (size*0.5f) - 1f, vy = y / (size*0.5f) - 1f, + d2 = vx*vx + vy*vy; + int p = 0; + if (d2 <= 1f) { + vec.set(vx, vy, FastMath.sqrt(1f - d2)); + rgb[idx] = getCubeMapPixel(vec, sides); + } + } + } + + // create and write the image + BufferedImage image = new BufferedImage(size, size, + BufferedImage.TYPE_INT_RGB); + image.setRGB(0, 0, size, size, rgb, 0, size); + String dest = target.toString(), + ext = dest.substring(dest.lastIndexOf('.')+1); + ImageIO.write(image, ext, target); + } + + /** + * Returns the pixel from the cube map to which the given vector points. + */ + protected static int getCubeMapPixel (Vector3f vec, BufferedImage[] sides) + { + int side = getCubeMapSide(vec); + + float s, t; + switch (side) { + case FRONT: + s = -vec.x / vec.y; + t = vec.z / vec.y; + break; + case BACK: + s = -vec.x / vec.y; + t = -vec.z / vec.y; + break; + case LEFT: + s = vec.y / vec.x; + t = -vec.z / vec.x; + break; + case RIGHT: + s = vec.y / vec.x; + t = vec.z / vec.x; + break; + default: + case UP: + s = vec.x / vec.z; + t = -vec.y / vec.z; + break; + } + int width = sides[side].getWidth(), height = sides[side].getHeight(); + return sides[side].getRGB((int)((width-1) * (s+1f)/2f), + (int)((height-1) * (1f-t)/2f)); + } + + /** + * Returns the side index identifying the face of the cube map to which + * the given vector points. + */ + protected static int getCubeMapSide (Vector3f vec) + { + if (vec.x > vec.z && vec.x > vec.y && vec.x > -vec.y) { + return RIGHT; + + } else if (vec.x < -vec.z && vec.x < -vec.y && vec.x < vec.y) { + return LEFT; + + } else if (vec.y > vec.z) { + return FRONT; + + } else if (vec.y < -vec.z) { + return BACK; + + } else { + return UP; + } + } + + /** The sides of the cube map. */ + protected static final int FRONT = 0, BACK = 1, LEFT = 2, RIGHT = 3, + UP = 4; +} diff --git a/src/java/com/threerings/jme/tools/BuildSphereMapTask.java b/src/java/com/threerings/jme/tools/BuildSphereMapTask.java new file mode 100644 index 000000000..27ad058a8 --- /dev/null +++ b/src/java/com/threerings/jme/tools/BuildSphereMapTask.java @@ -0,0 +1,86 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.jme.tools; + +import java.io.File; +import java.io.IOException; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +/** + * An ant task for converting cube maps (sky boxes) to sphere maps. + */ +public class BuildSphereMapTask extends Task +{ + public void setFront (File front) + { + _front = front; + } + + public void setBack (File back) + { + _back = back; + } + + public void setLeft (File left) + { + _left = left; + } + + public void setRight (File right) + { + _right = right; + } + + public void setUp (File up) + { + _up = up; + } + + public void setTarget (File target) + { + _target = target; + } + + public void setSize (int size) + { + _size = size; + } + + public void execute () throws BuildException + { + try { + BuildSphereMap.execute(_front, _back, _left, _right, _up, _target, + _size); + + } catch (IOException e) { + throw new BuildException("Failure building sphere map", e); + } + } + + /** The files representing the sides of the cube map and the target. */ + protected File _front, _back, _left, _right, _up, _target; + + /** The size of the target image. */ + protected int _size; +}