/*
* $RCSfile: ObjectFile.java,v $
*
* Copyright (c) 2007 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.
*
* $Revision: 1.6 $
* $Date: 2009/12/21 13:55:05 $
* $State: Exp $
*/
package org.mt4j.util.modelImporter.fileObj;
import java.awt.Image;
import java.awt.image.ImageObserver;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import javax.media.opengl.GL;
import org.mt4j.components.visibleComponents.shapes.AbstractShape;
import org.mt4j.util.MT4jSettings;
import org.mt4j.util.math.Tools3D;
import org.mt4j.util.opengl.GLMaterial;
import org.mt4j.util.opengl.GLTexture;
import org.mt4j.util.opengl.GLTextureSettings;
import org.mt4j.util.opengl.GLTexture.EXPANSION_FILTER;
import org.mt4j.util.opengl.GLTexture.SHRINKAGE_FILTER;
import org.mt4j.util.opengl.GLTexture.TEXTURE_TARGET;
import org.mt4j.util.opengl.GLTexture.WRAP_MODE;
import processing.core.PApplet;
import processing.core.PImage;
class ObjectFileMaterials implements ImageObserver {
// DEBUG
// 1 = Name of materials
// 16 = Tokens
private static final int DEBUG = 0;
private String curName = null;
private ObjectFileMaterial cur = null;
private HashMap materials; // key=String name of material
// value=ObjectFileMaterial
private Map<String, PImage> textureCache = new WeakHashMap<String, PImage>();
PApplet pa;
private String basePath;
private boolean fromUrl;
private class ObjectFileMaterial {
// public Color3f Ka;
// public Color3f Kd;
// public Color3f Ks;
public float[] Ka;
public float[] Kd;
public float[] Ks;
public int illum;
public float Ns;
// public Texture2D t;
public PImage t;
public boolean transparent;
public float transparencyLevel;
public PImage d;
}
void assignMaterial(GL gl, String matName, AbstractShape shape) {
ObjectFileMaterial p = null;
if ((DEBUG & 1) != 0)
System.out.println("Color " + matName);
GLMaterial m = new GLMaterial(gl);
p = (ObjectFileMaterial)materials.get(matName);
// Appearance a = new Appearance();
if (p != null) {
// Set ambient & diffuse color
if (p.Ka != null)
// m.setAmbient(p.Ka);
m.setAmbient(new float[]{p.Ka[0],p.Ka[1],p.Ka[2], 1.0f}); //we have to add the last value, else material will not be opaque
if (p.Kd != null)
// m.setDiffuse(p.Kd);
m.setDiffuse(new float[]{p.Kd[0],p.Kd[1],p.Kd[2], 1.0f});
// Set specular color
if ((p.Ks != null) && (p.illum != 1))
// m.setSpecular(p.Ks);
m.setSpecular(new float[]{p.Ks[0],p.Ks[1],p.Ks[2], 1.0f});
else if (p.illum == 1)
m.setSpecular(new float[]{0.0f, 0.0f, 0.0f, 1.0f});
// if (p.illum >= 1) m.setLightingEnable(true);
// else if (p.illum == 0) m.setLightingEnable(false);
if (p.Ns != -1.0f)
m.setShininess(p.Ns);
if (p.t != null) {
PImage tex = p.t;
// /*
//Apply alpha mask from transparancy map to the texture
if (p.d != null){
//System.out.println("Trying to add alpha mask for material: " + matName);
PImage alphaMap = p.d;
if (alphaMap.width == tex.width && alphaMap.height == tex.height){
tex.mask(alphaMap);
if (tex instanceof GLTexture) {
GLTexture glTex = (GLTexture) tex;
// glTex.putPixelsIntoTexture(tex);
glTex.loadGLTexture(tex);
}
}else{
//System.out.println("Alpha map isnt the same size as the texture for material: " + matName);
}
}
// */
shape.setTexture(tex);
System.out.println("Texture assigned to object: " + shape.getName());
}
// if (p.transparent)
// a.setTransparencyAttributes(new TransparencyAttributes(TransparencyAttributes.NICEST,p.transparencyLevel));
shape.setMaterial(m);
}else{
System.err.println("No material \"" + matName + "\" found for object " + shape.getName());
}
if ((DEBUG & 1) != 0)
System.out.println(m);
} // End of assignMaterial
private void readName(ObjectFileParser st) throws ParsingErrorException {
st.getToken();
if (st.ttype == ObjectFileParser.TT_WORD) {
if (curName != null) materials.put(curName, cur);
curName = new String(st.sval);
cur = new ObjectFileMaterial();
}
st.skipToNextLine();
} // End of readName
private void readAmbient(ObjectFileParser st) throws ParsingErrorException {
// Color3f p = new Color3f();
float[] p = new float[3];
st.getNumber();
p[0] = (float)st.nval;
st.getNumber();
p[1] = (float)st.nval;
st.getNumber();
p[2] = (float)st.nval;
cur.Ka = p;
st.skipToNextLine();
} // End of readAmbient
private void readDiffuse(ObjectFileParser st) throws ParsingErrorException {
// Color3f p = new Color3f();
float[] p = new float[3];
st.getNumber();
p[0] = (float)st.nval;
st.getNumber();
p[1] = (float)st.nval;
st.getNumber();
p[2] = (float)st.nval;
cur.Kd = p;
st.skipToNextLine();
} // End of readDiffuse
private void readSpecular(ObjectFileParser st) throws ParsingErrorException {
// Color3f p = new Color3f();
float[] p = new float[3];
st.getNumber();
p[0] = (float)st.nval;
st.getNumber();
p[1] = (float)st.nval;
st.getNumber();
p[2] = (float)st.nval;
cur.Ks = p;
st.skipToNextLine();
} // End of readSpecular
private void readIllum(ObjectFileParser st) throws ParsingErrorException {
st.getNumber();
cur.illum = (int)st.nval;
st.skipToNextLine();
} // End of readSpecular
private void readTransparency(ObjectFileParser st) throws ParsingErrorException {
st.getNumber();
cur.transparencyLevel = (float)st.nval;
if ( cur.transparencyLevel < 1.0f ){
cur.transparent = true;
}
st.skipToNextLine();
} // End of readTransparency
private void readShininess(ObjectFileParser st) throws ParsingErrorException {
float f;
st.getNumber();
cur.Ns = (float)st.nval;
if (cur.Ns < 1.0f) cur.Ns = 1.0f;
else if (cur.Ns > 128.0f) cur.Ns = 128.0f;
st.skipToNextLine();
} // End of readSpecular
public void readMapKd(ObjectFileParser st) {
// Filenames are case sensitive
st.lowerCaseMode(false);
// Get name of texture file (skip path)
String tFile = "";
do {
st.getToken();
// if (st.ttype == ObjectFileParser.TT_WORD){
// tFile += st.sval;
//
// }
if (st.ttype != ObjectFileParser.TT_EOL ){
tFile += st.sval;
}
} while (st.ttype != ObjectFileParser.TT_EOL);
st.lowerCaseMode(true);
if (tFile != "") {
PImage texture = null;
// Check for filename with no extension
if (tFile.lastIndexOf('.') != -1) {
try {
// Convert filename to lower case for extension comparisons
String suffix = tFile.substring(tFile.lastIndexOf('.') + 1).toLowerCase();
// TextureLoader t = null;
tFile = toLowerCase(tFile);
if ((suffix.equals("int")) || (suffix.equals("inta")) ||
(suffix.equals("rgb")) || (suffix.equals("rgba")) ||
(suffix.equals("bw")) || (suffix.equals("sgi"))
) {
PImage cachedImage = textureCache.get(tFile);
if (cachedImage != null){
texture = cachedImage;
//System.out.println("->Loaded texture from CACHE : \"" + tFile + "\"");
}else{
File textureFile = new File(basePath + tFile);
if (textureFile.exists()){
boolean success = textureFile.renameTo(new File(basePath + tFile));
if (!success) {
// File was not successfully renamed
System.out.println("failed to RENAME file: " + textureFile.getAbsolutePath());
}
if (MT4jSettings.getInstance().isOpenGlMode()){
PImage img = pa.loadImage(basePath + tFile);
if (Tools3D.isPowerOfTwoDimension(img)){
texture = new GLTexture(pa, img, new GLTextureSettings(TEXTURE_TARGET.TEXTURE_2D, SHRINKAGE_FILTER.Trilinear, EXPANSION_FILTER.Bilinear, WRAP_MODE.REPEAT, WRAP_MODE.REPEAT));
}else{
texture = new GLTexture(pa, img, new GLTextureSettings(TEXTURE_TARGET.RECTANGULAR, SHRINKAGE_FILTER.Trilinear, EXPANSION_FILTER.Bilinear, WRAP_MODE.REPEAT, WRAP_MODE.REPEAT));
// ((GLTexture)texture).setFilter(SHRINKAGE_FILTER.BilinearNoMipMaps, EXPANSION_FILTER.Bilinear);
}
}else{
texture = pa.loadImage(basePath + tFile);
}
textureCache.put(tFile, texture);
}else{
System.out.println("Trying to load obj texture from: " + basePath + tFile);
if (MT4jSettings.getInstance().isOpenGlMode()){
PImage img = pa.loadImage(basePath + tFile);
if (Tools3D.isPowerOfTwoDimension(img)){
texture = new GLTexture(pa, img, new GLTextureSettings(TEXTURE_TARGET.TEXTURE_2D, SHRINKAGE_FILTER.Trilinear, EXPANSION_FILTER.Bilinear, WRAP_MODE.REPEAT, WRAP_MODE.REPEAT));
}else{
texture = new GLTexture(pa, img, new GLTextureSettings(TEXTURE_TARGET.RECTANGULAR, SHRINKAGE_FILTER.Trilinear, EXPANSION_FILTER.Bilinear, WRAP_MODE.REPEAT, WRAP_MODE.REPEAT));
// ((GLTexture)texture).setFilter(SHRINKAGE_FILTER.BilinearNoMipMaps, EXPANSION_FILTER.Bilinear);
}
}else{
texture = pa.loadImage(basePath + tFile);
}
textureCache.put(tFile, texture);
}
}
// RgbFile f;
// if (fromUrl) {
// f = new RgbFile(new URL(basePath + tFile).openStream());
// } else {
// f = new RgbFile(new FileInputStream(basePath + tFile));
// }
// BufferedImage bi = f.getImage();
boolean luminance = suffix.equals("int") || suffix.equals("inta");
boolean alpha = suffix.equals("inta") || suffix.equals("rgba");
cur.transparent = alpha;
String s = null;
if (luminance && alpha) s = "LUM8_ALPHA8";
else if (luminance) s = "LUMINANCE";
else if (alpha) s = "RGBA";
else s = "RGB";
// t = new TextureLoader(bi, s, TextureLoader.GENERATE_MIPMAP);
} else {
// tFile.toLowerCase();
// tFile.toLowerCase(Locale.ENGLISH);
// basePath.toLowerCase();
PImage cachedImage = textureCache.get(tFile);
if (cachedImage != null){
texture = cachedImage;
//System.out.println("->Loaded texture from CACHE : \"" + tFile + "\"");
}else{
File textureFile = new File(basePath + tFile);
if (textureFile.exists()){
boolean success = textureFile.renameTo(new File(basePath + tFile));
if (!success) {
// File was not successfully renamed
System.out.println("failed to RENAME file: " + textureFile.getAbsolutePath());
}
if (MT4jSettings.getInstance().isOpenGlMode()){
PImage img = pa.loadImage(basePath + tFile);
if (Tools3D.isPowerOfTwoDimension(img)){
texture = new GLTexture(pa, img, new GLTextureSettings(TEXTURE_TARGET.TEXTURE_2D, SHRINKAGE_FILTER.Trilinear, EXPANSION_FILTER.Bilinear, WRAP_MODE.REPEAT, WRAP_MODE.REPEAT));
}else{
texture = new GLTexture(pa, img, new GLTextureSettings(TEXTURE_TARGET.RECTANGULAR, SHRINKAGE_FILTER.Trilinear, EXPANSION_FILTER.Bilinear, WRAP_MODE.REPEAT, WRAP_MODE.REPEAT));
// ((GLTexture)texture).setFilter(SHRINKAGE_FILTER.BilinearNoMipMaps, EXPANSION_FILTER.Bilinear);
}
}else{
texture = pa.loadImage(basePath + tFile);
}
textureCache.put(tFile, texture);
}else{
System.out.println("Trying to load obj texture from: " + basePath + tFile);
if (MT4jSettings.getInstance().isOpenGlMode()){
PImage img = pa.loadImage(basePath + tFile);
if (Tools3D.isPowerOfTwoDimension(img)){
texture = new GLTexture(pa, img, new GLTextureSettings(TEXTURE_TARGET.TEXTURE_2D, SHRINKAGE_FILTER.Trilinear, EXPANSION_FILTER.Bilinear, WRAP_MODE.REPEAT, WRAP_MODE.REPEAT));
}else{
texture = new GLTexture(pa, img, new GLTextureSettings(TEXTURE_TARGET.RECTANGULAR, SHRINKAGE_FILTER.Trilinear, EXPANSION_FILTER.Bilinear, WRAP_MODE.REPEAT, WRAP_MODE.REPEAT));
// ((GLTexture)texture).setFilter(SHRINKAGE_FILTER.BilinearNoMipMaps, EXPANSION_FILTER.Bilinear);
}
}else{
texture = pa.loadImage(basePath + tFile);
}
textureCache.put(tFile, texture);
}
}
// if (ConstantsAndSettings.getInstance().isOpenGlMode()){
// GLTexture glTex = new GLTexture(pa, basePath + tFile);
// texture = glTex;
// }else{
// texture = pa.loadImage(basePath + tFile);
// }
// // For all other file types, use the TextureLoader
// if (fromUrl) {
// t = new TextureLoader(new URL(basePath + tFile), "RGB",
// TextureLoader.GENERATE_MIPMAP, null);
// } else {
// t = new TextureLoader(basePath + tFile, "RGB",
// TextureLoader.GENERATE_MIPMAP, null);
// }
}
// Texture2D texture = (Texture2D)t.getTexture();
if (texture != null)
cur.t = texture;
}
catch (Exception e) {
// Texture won't get loaded if file can't be found
e.printStackTrace();
}
// catch (MalformedURLException e) {
// // Texture won't get loaded if file can't be found
// }
// catch (IOException e) {
// // Texture won't get loaded if file can't be found
// }
}
}
st.skipToNextLine();
} // End of readMapKd
/**
*
* @param string
* @return
*/
public String toLowerCase(String string){
char[] chars = new char[string.length()];
for (int i = 0; i < chars.length; i++) {
char c = string.charAt(i);
c = Character.toLowerCase(c);
chars[i] = c;
}
return new String(chars);
}
public void readMapD(ObjectFileParser st) {
// Filenames are case sensitive
st.lowerCaseMode(false);
// Get name of texture file (skip path)
String tFile = "";
do {
st.getToken();
// if (st.ttype == ObjectFileParser.TT_WORD){
// tFile += st.sval;
// }
if (st.ttype != ObjectFileParser.TT_EOL ){
tFile += st.sval;
}
}while (st.ttype != ObjectFileParser.TT_EOL);
st.lowerCaseMode(true);
if (tFile != "") {
PImage alphaMap;
// Check for filename with no extension
if (tFile.lastIndexOf('.') != -1) {
try {
// Convert filename to lower case for extension comparisons
String suffix = tFile.substring(tFile.lastIndexOf('.') + 1).toLowerCase();
if ((suffix.equals("int")) || (suffix.equals("inta")) ||
(suffix.equals("rgb")) || (suffix.equals("rgba")) ||
(suffix.equals("bw")) || (suffix.equals("sgi"))
) {
tFile = toLowerCase(tFile);
alphaMap = pa.loadImage(basePath + tFile);
} else {
tFile = toLowerCase(tFile);
alphaMap = pa.loadImage(basePath + tFile);
}
if (alphaMap != null){
cur.d = alphaMap;
}
}catch (Exception e) {
// Texture won't get loaded if file can't be found
e.printStackTrace();
}
}
}
st.skipToNextLine();
} // End of readMapKd
/**
*
* @param st
* @throws ParsingErrorException
*/
private void readFile(ObjectFileParser st) throws ParsingErrorException {
int t;
st.getToken();
while (st.ttype != ObjectFileParser.TT_EOF) {
// Print out one token for each line
if ((DEBUG & 16) != 0) {
System.out.print("Token ");
if (st.ttype == ObjectFileParser.TT_EOL) System.out.println("EOL");
else if (st.ttype == ObjectFileParser.TT_WORD)
System.out.println(st.sval);
else System.out.println((char)st.ttype);
}
if (st.ttype == ObjectFileParser.TT_WORD) {
if (st.sval.equals("newmtl")) {
readName(st);
} else if (st.sval.equals("ka")) {
readAmbient(st);
} else if (st.sval.equals("kd")) {
readDiffuse(st);
} else if (st.sval.equals("ks")) {
readSpecular(st);
} else if (st.sval.equals("illum")) {
readIllum(st);
} else if (st.sval.equals("d")) {
readTransparency(st);
} else if (st.sval.equals("ns")) {
readShininess(st);
} else if (st.sval.equals("tf")) {
st.skipToNextLine();
} else if (st.sval.equals("sharpness")) {
st.skipToNextLine();
} else if (st.sval.equals("map_kd")) {
readMapKd(st);
} else if (st.sval.equals("map_ka")) {
st.skipToNextLine();
} else if (st.sval.equals("map_ks")) {
st.skipToNextLine();
} else if (st.sval.equals("map_ns")) {
st.skipToNextLine();
} else if (st.sval.equals("bump")) {
st.skipToNextLine();
}else if (st.sval.equals("map_d")) {
readMapD(st);
}
}
st.skipToNextLine();
// Get next token
st.getToken();
}
if (curName != null) materials.put(curName, cur);
} // End of readFile
/**
*
* @param basePath
* @param fileName
* @throws ParsingErrorException
*/
void readMaterialFile(String basePath, String fileName) throws ParsingErrorException {
Reader reader;
this.basePath = basePath;
// this.fromUrl = fromUrl;
try {
if (fromUrl) {
reader = (Reader)
(new InputStreamReader(
new BufferedInputStream(
(new URL(basePath + fileName).openStream()))));
} else {
File f = new File(basePath+fileName);
if (f.exists()){
reader = new BufferedReader(new FileReader(basePath + fileName));
}else{
InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(basePath + fileName);
if (stream == null){
stream = pa.getClass().getResourceAsStream(basePath + fileName);
}
if (stream == null){
throw new FileNotFoundException("File not found: " + basePath + fileName);
}
reader = new BufferedReader(new InputStreamReader(stream));
}
}
}
catch (IOException e) {
// couldn't find it - ignore mtllib
e.printStackTrace();
return;
}
if ((DEBUG & 1) != 0)
System.out.println("Material file: " + basePath + fileName);
ObjectFileParser st = new ObjectFileParser(reader);
readFile(st);
} // End of readMaterialFile
ObjectFileMaterials() throws ParsingErrorException {
// Reader reader = new StringReader(DefaultMaterials.materials);
//
// ObjectFileParser st = new ObjectFileParser(reader);
materials = new HashMap(50);
// readFile(st);
} // End of ObjectFileMaterials
/**
* Implement the ImageObserver interface. Needed to load jpeg and gif
* files using the Toolkit.
*/
public boolean imageUpdate(Image img, int flags,
int x, int y, int w, int h) {
return (flags & (ALLBITS | ABORT)) == 0;
} // End of imageUpdate
} // End of class ObjectFileMaterials
// End of file ObjectFileMaterials.java