package org.osm2world.core.target.common.material;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.osm2world.core.target.common.TextureData;
/**
* describes the material/surface properties of an object for lighting
*/
public abstract class Material {
public static enum Interpolation {FLAT, SMOOTH};
public static enum Transparency {
/** arbitrary transparency, including partially transparent pixels */
TRUE,
/** only allow pixels to be either fully transparent or fully opaque */
BINARY,
/** all pixels are opaque */
FALSE
}
public static enum Shadow {
/** casts shadows */
TRUE,
/** casts no shadows */
FALSE
}
public static enum AmbientOcclusion {
/** casts AO */
TRUE,
/** casts no AO */
FALSE
}
/**
* Interpolation of normals
*/
protected Interpolation interpolation;
protected Color color;
protected float ambientFactor;
protected float diffuseFactor;
protected float specularFactor;
protected int shininess;
protected Transparency transparency;
protected Shadow shadow;
protected AmbientOcclusion ambientOcclusion;
protected List<TextureData> textureDataList;
protected TextureData bumpMap;
protected int bumpMapInd;
public Material(Interpolation interpolation, Color color,
float ambientFactor, float diffuseFactor, float specularFactor, int shininess,
Transparency transparency, Shadow shadow, AmbientOcclusion ao, List<TextureData> textureDataList) {
this.interpolation = interpolation;
this.color = color;
this.ambientFactor = ambientFactor;
this.diffuseFactor = diffuseFactor;
this.specularFactor = specularFactor;
this.shininess = shininess;
this.transparency = transparency;
this.shadow = shadow;
this.ambientOcclusion = ao;
this.textureDataList = textureDataList;
updateBumpMap();
}
protected void updateBumpMap() {
this.bumpMap = null;
this.bumpMapInd = -1;
if (textureDataList == null) {
return;
}
int i = 0;
for (TextureData t : textureDataList) {
if (t.isBumpMap) {
this.bumpMap = t;
this.bumpMapInd = i;
}
i++;
}
}
public Material(Interpolation interpolation, Color color,
Transparency transparency, List<TextureData> textureDataList) {
this(interpolation, color, 0.5f, 0.5f, 0.0f, 1, transparency,
Shadow.TRUE, AmbientOcclusion.TRUE, textureDataList);
}
public Material(Interpolation interpolation, Color color) {
this(interpolation, color, Transparency.FALSE,
Collections.<TextureData>emptyList());
}
public Interpolation getInterpolation() {
return interpolation;
}
public Color getColor() {
return color;
}
public float getAmbientFactor() {
return ambientFactor;
}
public float getDiffuseFactor() {
return diffuseFactor;
}
public float getSpecularFactor() {
return specularFactor;
}
public int getShininess() {
return shininess;
}
public Color ambientColor() {
return multiplyColor(getColor(), getAmbientFactor());
}
public Color diffuseColor() {
return multiplyColor(getColor(), getDiffuseFactor());
}
public Material brighter() {
return new ImmutableMaterial(interpolation, getColor().brighter(),
getAmbientFactor(), getDiffuseFactor(), getSpecularFactor(), getShininess(),
getTransparency(), getShadow(), getAmbientOcclusion(), getTextureDataList());
}
public Material darker() {
return new ImmutableMaterial(interpolation, getColor().darker(),
getAmbientFactor(), getDiffuseFactor(), getSpecularFactor(), getShininess(),
getTransparency(), getShadow(), getAmbientOcclusion(), getTextureDataList());
}
public static final Color multiplyColor(Color c, float factor) {
float[] colorComponents = new float[3];
c.getColorComponents(colorComponents);
return new Color(
colorComponents[0] * factor,
colorComponents[1] * factor,
colorComponents[2] * factor);
}
public Material makeSmooth() {
return new ImmutableMaterial(Interpolation.SMOOTH, getColor(),
getAmbientFactor(), getDiffuseFactor(), getSpecularFactor(), getShininess(),
getTransparency(), getShadow(), getAmbientOcclusion(), getTextureDataList());
}
/**
* returns a material that is the same as this one,
* except with additional texture data layers stacked on top
*/
public Material withAddedLayers(List<TextureData> textureLayers) {
if (textureLayers.isEmpty()) return this;
List<TextureData> textureDataList =
new ArrayList<TextureData>(getTextureDataList());
textureDataList.addAll(textureLayers);
return new ImmutableMaterial(getInterpolation(), getColor(),
getAmbientFactor(), getDiffuseFactor(), getSpecularFactor(), getShininess(),
getTransparency(), getShadow(), getAmbientOcclusion(), textureDataList);
}
public Transparency getTransparency() {
return transparency;
}
public Shadow getShadow() {
return shadow;
}
public AmbientOcclusion getAmbientOcclusion() {
return ambientOcclusion;
}
public List<TextureData> getTextureDataList() {
return textureDataList;
}
public int getNumTextureLayers() {
if (textureDataList == null) {
return 0;
} else {
return textureDataList.size();
}
}
public boolean hasBumpMap() {
return this.bumpMap != null;
}
public TextureData getBumpMap() {
return this.bumpMap;
}
public int getBumpMapInd() {
return this.bumpMapInd;
}
public String toString() {
return String.format("{%s, #%06x, a%3f, d%3f, s%3f, sh%d, %d tex, ",
interpolation, color.getRGB() & 0x00ffffff, ambientFactor,
diffuseFactor, specularFactor, shininess, textureDataList.size())
+ transparency + shadow + ambientOcclusion
+ "}";
}
/*
* some possible later additions: specular (obvious ...),
* as well as brilliance, phong, metallic, reflection, crand and iridescence for POVRay
*/
}