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
This commit is contained in:
Andrzej Kapolka
2005-11-07 02:20:13 +00:00
parent 6e9687ac9b
commit 365634146c
2 changed files with 253 additions and 0 deletions
@@ -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;
}