/*
* License goes here.
* GPL?
*/
package edu.ups.gamedev.terrain;
import com.jme.math.Vector2f;
import com.jme.util.TextureManager;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.PixelGrabber;
import java.awt.image.WritableRaster;
import java.util.HashMap;
import java.util.Random;
/**
*
* @author scanfield
*/
public class MaterialMap {
static private class ImageConverter {
// Posted by DrLaszloJamf to Java Technology Forums
//
// Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistribution of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// Redistribution in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// Neither the name of Sun Microsystems, Inc. or the names of
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// This software is provided "AS IS," without a warranty of any kind.
// ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
// INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
// MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
// ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
// DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
// OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
// FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
// DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
// ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
// SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
//
//
// You acknowledge that this software is not designed, licensed or
// intended for use in the design, construction, operation or
// maintenance of any nuclear facility.
// preserves image's colormodel. Assumes image is loaded
public static BufferedImage toBufferedImage(Image image) {
if (image instanceof BufferedImage)
return (BufferedImage) image;
ColorModel cm = getColorModel(image);
int width = image.getWidth(null);
int height = image.getHeight(null);
return copy(createBufferedImage(cm, width, height), image);
}
public static BufferedImage toBufferedImage(Image image, int type) {
if (image instanceof BufferedImage
&& ((BufferedImage) image).getType() == type)
return (BufferedImage) image;
int width = image.getWidth(null);
int height = image.getHeight(null);
return copy(new BufferedImage(width, height, type), image);
}
// Returns target. Assumes source is loaded
public static BufferedImage copy(BufferedImage target, Image source) {
Graphics2D g = target.createGraphics();
g.drawImage(source, 0, 0, null);
g.dispose();
return target;
}
public static ColorModel getColorModel(Image image) {
try {
PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
pg.grabPixels();
return pg.getColorModel();
} catch (InterruptedException e) {
throw new RuntimeException("Unexpected interruption", e);
}
}
public static BufferedImage createBufferedImage(ColorModel cm, int w,
int h) {
WritableRaster raster = cm.createCompatibleWritableRaster(w, h);
boolean isRasterPremultiplied = cm.isAlphaPremultiplied();
return new BufferedImage(cm, raster, isRasterPremultiplied, null);
}
}
private int size;
private int[] matData;
private int textureSize;
public MaterialMap(Image map, int textureSize) {
BufferedImage colorBufferedImage = ImageConverter.toBufferedImage(map,
BufferedImage.TYPE_3BYTE_BGR);
boolean hasAlpha = TextureManager.hasAlpha(colorBufferedImage);
int imageWidth = colorBufferedImage.getWidth();
int imageHeight = colorBufferedImage.getHeight();
if (imageWidth != imageHeight)
throw new RuntimeException("imageWidth: " + imageWidth
+ " != imageHeight: " + imageHeight);
size = imageWidth;
this.textureSize = textureSize;
byte data[] = (byte[]) colorBufferedImage.getRaster().getDataElements(
0, 0, imageWidth, imageHeight, null);
int bytesPerPixel = 3;
int blueBase = 0;
if (hasAlpha) {
bytesPerPixel = 4;
blueBase = 1;
}
/* Need a mapping from color to index */
HashMap<Color, Integer> colorToIndex = new HashMap<Color, Integer>();
colorToIndex.put(Color.red, new Integer(1));
colorToIndex.put(Color.green, new Integer(3));
colorToIndex.put(Color.blue, new Integer(0));
colorToIndex.put(Color.white, new Integer(2));
matData = new int[(imageWidth * imageHeight)];
int[] counts = new int[4];
int index = 0;
for (int h = 0; h < imageHeight; ++h)
for (int w = 0; w < imageWidth; ++w) {
int baseIndex = (h * imageWidth * bytesPerPixel)
+ (w * bytesPerPixel) + blueBase;
int blue = data[baseIndex] >= 0 ? data[baseIndex]
: (256 + (data[baseIndex]));
int green = data[baseIndex + 1] >= 0 ? data[baseIndex + 1]
: (256 + (data[baseIndex + 1]));
int red = data[baseIndex + 2] >= 0 ? data[baseIndex + 2]
: (256 + (data[baseIndex + 2]));
Color c = new Color(blue, green, red);
// System.out.println( c.toString() );
Integer colorIndex = colorToIndex.get(c);
if (colorIndex == null) {
matData[index] = 0;
} else {
matData[h * imageWidth + w] = colorIndex.intValue();
counts[colorIndex.intValue()]++;
}
index++;
}
}
private float TILE_SIZE = 128.0f;
public Vector2f textureForMap(Vector2f mapCoordinate) {
int mapIndex = (int) mapCoordinate.y * size + (int) mapCoordinate.x;
if (mapIndex >= matData.length) {
mapIndex = matData.length - 1;
}
int index = 0;
try {
index = (int) matData[mapIndex];
} catch ( ArrayIndexOutOfBoundsException e ) {
System.out.println( matData.length + " vs " + mapIndex);
}
float a, b;
a = 0.0f;
b = 0.0f;
switch (index) {
case 0:
break;
case 1:
a = 0.5f;
break;
case 2:
b = 0.5f;
break;
case 3:
a = 0.5f;
b = 0.5f;
break;
}
float x = (float) (index) * TILE_SIZE / (float) size;
float y = (float) (index) * TILE_SIZE / (float) size;
x += a;
y += b;
return new Vector2f(a, b);
}
public float getTileSize() {
return 0.25f;
}
}