* Ported .material loader to use BlockLanguageParser. Also made it more reliable in terms of detecting lightmaps and strange texture setups.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8164 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
sha..rd 14 years ago
parent f421e2a876
commit cfbb444b97
  1. 310
      engine/src/ogre/com/jme3/scene/plugins/ogre/MaterialLoader.java
  2. 80
      engine/src/ogre/com/jme3/scene/plugins/ogre/matext/MaterialExtensionLoader.java

@ -49,8 +49,13 @@ import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode; import com.jme3.texture.Texture.WrapMode;
import com.jme3.texture.Texture2D; import com.jme3.texture.Texture2D;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import com.jme3.util.blockparser.BlockLanguageParser;
import com.jme3.util.blockparser.Statement;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Scanner; import java.util.Scanner;
import java.util.logging.Level; import java.util.logging.Level;
@ -62,9 +67,8 @@ public class MaterialLoader implements AssetLoader {
private String folderName; private String folderName;
private AssetManager assetManager; private AssetManager assetManager;
private Scanner scan;
private ColorRGBA ambient, diffuse, specular, emissive; private ColorRGBA ambient, diffuse, specular, emissive;
private Texture texture; private Texture[] textures = new Texture[4];
private String texName; private String texName;
private String matName; private String matName;
private float shinines; private float shinines;
@ -72,48 +76,43 @@ public class MaterialLoader implements AssetLoader {
private boolean blend = false; private boolean blend = false;
private boolean twoSide = false; private boolean twoSide = false;
private boolean noLight = false; private boolean noLight = false;
private boolean readTexUnit = false; private boolean separateTexCoord = false;
private int texUnit = 0;
private String readString(String end){ private ColorRGBA readColor(String content){
scan.useDelimiter(end); String[] split = content.split(" ");
String str = scan.next();
scan.useDelimiter("\\p{javaWhitespace}+");
return str.trim();
}
private ColorRGBA readColor(){
ColorRGBA color = new ColorRGBA(); ColorRGBA color = new ColorRGBA();
color.r = scan.nextFloat(); color.r = Float.parseFloat(split[0]);
color.g = scan.nextFloat(); color.g = Float.parseFloat(split[1]);
color.b = scan.nextFloat(); color.b = Float.parseFloat(split[2]);
if (scan.hasNextFloat()){ if (split.length >= 4){
color.a = scan.nextFloat(); color.a = Float.parseFloat(split[3]);
} }
return color; return color;
} }
private void readTextureImage(){ private void readTextureImage(String content){
// texture image def // texture image def
String ln = scan.nextLine();
String path = null; String path = null;
// find extension // find extension
int extStart = ln.lastIndexOf("."); int extStart = content.lastIndexOf(".");
for (int i = extStart; i < ln.length(); i++){ for (int i = extStart; i < content.length(); i++){
char c = ln.charAt(i); char c = content.charAt(i);
if (Character.isWhitespace(c)){ if (Character.isWhitespace(c)){
// extension ends here // extension ends here
path = ln.substring(0, i).trim(); path = content.substring(0, i).trim();
ln = ln.substring(i+1).trim(); content = content.substring(i+1).trim();
break; break;
} }
} }
if (path == null){ if (path == null){
path = ln.trim(); path = content.trim();
ln = ""; content = "";
} }
Scanner lnScan = new Scanner(ln); Scanner lnScan = new Scanner(content);
String mips = null; String mips = null;
String type = null; String type = null;
if (lnScan.hasNext()){ if (lnScan.hasNext()){
@ -145,144 +144,129 @@ public class MaterialLoader implements AssetLoader {
if (loadedTexture == null){ if (loadedTexture == null){
ByteBuffer tempData = BufferUtils.createByteBuffer(3); ByteBuffer tempData = BufferUtils.createByteBuffer(3);
tempData.put((byte)0xFF).put((byte)0x00).put((byte)0x00); tempData.put((byte)0xFF).put((byte)0x00).put((byte)0x00);
texture = new Texture2D(new Image(Format.RGB8, 1,1,tempData)); textures[texUnit].setImage(new Image(Format.RGB8, 1,1,tempData));
logger.log(Level.WARNING, "Using RED texture instead of {0}", path); logger.log(Level.WARNING, "Using RED texture instead of {0}", path);
}else{ }else{
texture.setImage(loadedTexture.getImage()); textures[texUnit].setImage(loadedTexture.getImage());
texture.setMinFilter(loadedTexture.getMinFilter()); textures[texUnit].setMinFilter(loadedTexture.getMinFilter());
texture.setKey(loadedTexture.getKey()); textures[texUnit].setKey(loadedTexture.getKey());
// XXX: Is this really neccessary? // XXX: Is this really neccessary?
texture.setWrap(WrapMode.Repeat); textures[texUnit].setWrap(WrapMode.Repeat);
if (texName != null){ if (texName != null){
texture.setName(texName); textures[texUnit].setName(texName);
texName = null; texName = null;
}else{ }else{
texture.setName(key.getName()); textures[texUnit].setName(key.getName());
} }
} }
} }
private void readTextureUnitStatement(){ private void readTextureUnitStatement(Statement statement){
String keyword = scan.next(); String[] split = statement.getLine().split(" ", 2);
String keyword = split[0];
if (keyword.equals("texture")){ if (keyword.equals("texture")){
readTextureImage(); readTextureImage(split[1]);
}else if (keyword.equals("tex_address_mode")){ }else if (keyword.equals("tex_address_mode")){
String mode = scan.next(); String mode = split[1];
if (mode.equals("wrap")){ if (mode.equals("wrap")){
texture.setWrap(WrapMode.Repeat); textures[texUnit].setWrap(WrapMode.Repeat);
}else if (mode.equals("clamp")){ }else if (mode.equals("clamp")){
texture.setWrap(WrapMode.Clamp); textures[texUnit].setWrap(WrapMode.Clamp);
}else if (mode.equals("mirror")){ }else if (mode.equals("mirror")){
texture.setWrap(WrapMode.MirroredRepeat); textures[texUnit].setWrap(WrapMode.MirroredRepeat);
}else if (mode.equals("border")){ }else if (mode.equals("border")){
texture.setWrap(WrapMode.BorderClamp); textures[texUnit].setWrap(WrapMode.BorderClamp);
} }
}else if (keyword.equals("filtering")){ }else if (keyword.equals("filtering")){
// ignored.. only anisotropy is considered // ignored.. only anisotropy is considered
readString("\n"); }else if (keyword.equals("tex_coord_set")){
int texCoord = Integer.parseInt(split[1]);
if (texCoord == 1){
separateTexCoord = true;
}
}else if (keyword.equals("max_anisotropy")){ }else if (keyword.equals("max_anisotropy")){
int amount = scan.nextInt(); int amount = Integer.parseInt(split[1]);
texture.setAnisotropicFilter(amount); textures[texUnit].setAnisotropicFilter(amount);
}else{ }else{
logger.log(Level.WARNING, "Unsupported texture_unit directive: {0}", keyword); logger.log(Level.WARNING, "Unsupported texture_unit directive: {0}", keyword);
readString("\n");
} }
} }
private void readTextureUnit(boolean skipIt){ private void readTextureUnit(Statement statement){
String[] split = statement.getLine().split(" ", 2);
// name is optional // name is optional
if (!scan.hasNext("\\{")){ if (split.length == 2){
texName = readString("\\{"); texName = split[1];
}else{ }else{
texName = null; texName = null;
} }
scan.next(); // skip "{"
if (!skipIt){ textures[texUnit] = new Texture2D();
texture = new Texture2D(); for (Statement texUnitStat : statement.getContents()){
readTextureUnitStatement(texUnitStat);
} }
if (textures[texUnit].getImage() != null){
while (!scan.hasNext("\\}")){ texUnit++;
if (skipIt){ }else{
readString("\n"); // no image was loaded, ignore
}else{ textures[texUnit] = null;
readTextureUnitStatement();
}
} }
scan.next(); // skip "}"
} }
private void readPassStatement(){ private void readPassStatement(Statement statement){
// read until newline // read until newline
String keyword = scan.next(); String[] split = statement.getLine().split(" ", 2);
if (keyword.equals("")) String keyword = split[0];
return;
if (keyword.equals("diffuse")){ if (keyword.equals("diffuse")){
if (scan.hasNext("vertexcolour")){ if (split[1].equals("vertexcolour")){
// use vertex colors // use vertex colors
diffuse = ColorRGBA.White; diffuse = ColorRGBA.White;
vcolor = true; vcolor = true;
scan.next(); // skip it
}else{ }else{
diffuse = readColor(); diffuse = readColor(split[1]);
} }
}else if(keyword.equals("ambient")) { }else if(keyword.equals("ambient")) {
if (scan.hasNext("vertexcolour")){ if (split[1].equals("vertexcolour")){
// use vertex colors // use vertex colors
ambient = ColorRGBA.White; ambient = ColorRGBA.White;
scan.next(); // skip it
}else{ }else{
ambient = readColor(); ambient = readColor(split[1]);
} }
}else if (keyword.equals("emissive")){ }else if (keyword.equals("emissive")){
emissive = readColor(); emissive = readColor(split[1]);
}else if (keyword.equals("specular")){ }else if (keyword.equals("specular")){
String[] subsplit = split[1].split(" ");
specular = new ColorRGBA(); specular = new ColorRGBA();
specular.r = scan.nextFloat(); specular.r = Float.parseFloat(subsplit[0]);
specular.g = scan.nextFloat(); specular.g = Float.parseFloat(subsplit[1]);
specular.b = scan.nextFloat(); specular.b = Float.parseFloat(subsplit[2]);
float unknown = scan.nextFloat(); float unknown = Float.parseFloat(subsplit[3]);
if (scan.hasNextFloat()){ if (subsplit.length >= 5){
// using 5 float values // using 5 float values
specular.a = unknown; specular.a = unknown;
shinines = scan.nextFloat(); shinines = Float.parseFloat(subsplit[4]);
}else{ }else{
// using 4 float values // using 4 float values
specular.a = 1f; specular.a = 1f;
shinines = unknown; shinines = unknown;
} }
}else if (keyword.equals("texture_unit")){ }else if (keyword.equals("texture_unit")){
readTextureUnit(readTexUnit); readTextureUnit(statement);
// After reading the first texunit, ignore the rest
if (!readTexUnit) {
readTexUnit = true;
}
}else if (keyword.equals("scene_blend")){ }else if (keyword.equals("scene_blend")){
if (scan.hasNextInt()){ String mode = split[1];
readString("\n"); // blender2ogre workaround
return;
}
String mode = scan.next();
if (mode.equals("alpha_blend")){ if (mode.equals("alpha_blend")){
blend = true; blend = true;
}else{
// skip the rest
readString("\n");
} }
}else if (keyword.equals("cull_hardware")){ }else if (keyword.equals("cull_hardware")){
String mode = scan.next(); String mode = split[1];
if (mode.equals("none")){ if (mode.equals("none")){
twoSide = true; twoSide = true;
} }
}else if (keyword.equals("cull_software")){ }else if (keyword.equals("cull_software")){
// ignore // ignore
scan.next();
}else if (keyword.equals("lighting")){ }else if (keyword.equals("lighting")){
String isOn = scan.next(); String isOn = split[1];
if (isOn.equals("on")){ if (isOn.equals("on")){
noLight = false; noLight = false;
}else if (isOn.equals("off")){ }else if (isOn.equals("off")){
@ -290,75 +274,55 @@ public class MaterialLoader implements AssetLoader {
} }
}else{ }else{
logger.log(Level.WARNING, "Unsupported pass directive: {0}", keyword); logger.log(Level.WARNING, "Unsupported pass directive: {0}", keyword);
readString("\n");
} }
} }
private void readPass(){ private void readPass(Statement statement){
scan.next(); // skip "pass"
// name is optional
String name; String name;
if (scan.hasNext("\\{")){ String[] split = statement.getLine().split(" ", 2);
if (split.length == 1){
// no name // no name
name = null; name = null;
}else{ }else{
name = readString("\\{"); name = split[1];
} }
scan.next(); // skip "{"
// Has not yet read a tex unit for this pass for (Statement passStat : statement.getContents()){
readTexUnit = false; readPassStatement(passStat);
while (!scan.hasNext("\\}")){
readPassStatement();
} }
scan.next(); // skip "}"
texUnit = 0;
} }
private void readTechnique(){ private void readTechnique(Statement statement){
scan.next(); // skip "technique" String[] split = statement.getLine().split(" ", 2);
// name is optional
String name; String name;
if (scan.hasNext("\\{")){ if (split.length == 1){
// no name // no name
name = null; name = null;
}else{ }else{
name = readString("\\{"); name = split[1];
} }
scan.next(); // skip "{" for (Statement techStat : statement.getContents()){
while (!scan.hasNext("\\}")){ readPass(techStat);
readPass();
} }
scan.next();
} }
private boolean readMaterialStatement(){ private void readMaterialStatement(Statement statement){
if (scan.hasNext("technique")){ if (statement.getLine().startsWith("technique")){
readTechnique(); readTechnique(statement);
return true; }else if (statement.getLine().startsWith("receive_shadows")){
}else if (scan.hasNext("receive_shadows")){ String isOn = statement.getLine().split(" ")[1];
// skip "receive_shadows"
scan.next();
String isOn = scan.next();
if (isOn != null && isOn.equals("true")){ if (isOn != null && isOn.equals("true")){
} }
return true;
}else{
return false;
} }
} }
@SuppressWarnings("empty-statement") @SuppressWarnings("empty-statement")
private void readMaterial(){ private void readMaterial(Statement statement){
scan.next(); // skip "material" for (Statement materialStat : statement.getContents()){
// read name readMaterialStatement(materialStat);
matName = readString("\\{");
scan.next(); // skip "{"
while (!scan.hasNext("\\}")){
readMaterialStatement();
} }
scan.next();
} }
private Material compileMaterial(){ private Material compileMaterial(){
@ -396,8 +360,8 @@ public class MaterialLoader implements AssetLoader {
if (vcolor) if (vcolor)
mat.setBoolean("UseVertexColor", true); mat.setBoolean("UseVertexColor", true);
if (texture != null) if (textures[0] != null)
mat.setTexture("DiffuseMap", texture); mat.setTexture("DiffuseMap", textures[0]);
mat.setBoolean("UseMaterialColors", true); mat.setBoolean("UseMaterialColors", true);
if(diffuse != null){ if(diffuse != null){
@ -426,10 +390,21 @@ public class MaterialLoader implements AssetLoader {
mat.setBoolean("VertexColor", true); mat.setBoolean("VertexColor", true);
} }
if (texture != null) { if (textures[0] != null && textures[1] == null){
mat.setTexture("ColorMap", texture); if (separateTexCoord){
mat.setTexture("LightMap", textures[0]);
mat.setBoolean("SeparateTexCoord", true);
}else{
mat.setTexture("ColorMap", textures[0]);
}
}else if (textures[1] != null){
mat.setTexture("ColorMap", textures[0]);
mat.setTexture("LightMap", textures[1]);
if (separateTexCoord){
mat.setBoolean("SeparateTexCoord", true);
}
} }
if(diffuse != null){ if(diffuse != null){
mat.setColor("Color", diffuse); mat.setColor("Color", diffuse);
} }
@ -440,13 +415,14 @@ public class MaterialLoader implements AssetLoader {
} }
noLight = false; noLight = false;
texture = null; Arrays.fill(textures, null);
diffuse = null; diffuse = null;
specular = null; specular = null;
texture = null;
shinines = 0f; shinines = 0f;
vcolor = false; vcolor = false;
blend = false; blend = false;
texUnit = 0;
separateTexCoord = false;
return mat; return mat;
} }
@ -454,31 +430,37 @@ public class MaterialLoader implements AssetLoader {
folderName = info.getKey().getFolder(); folderName = info.getKey().getFolder();
assetManager = info.getManager(); assetManager = info.getManager();
MaterialList list; MaterialList list = null;
scan = new Scanner(info.openStream()); InputStream in = info.openStream();
scan.useLocale(Locale.US); List<Statement> statements = BlockLanguageParser.parse(in);
if (scan.hasNext("import")){
MaterialExtensionSet matExts = null; for (Statement statement : statements){
if (info.getKey() instanceof OgreMaterialKey){ if (statement.getLine().startsWith("import")){
matExts = ((OgreMaterialKey)info.getKey()).getMaterialExtensionSet(); MaterialExtensionSet matExts = null;
} if (info.getKey() instanceof OgreMaterialKey){
matExts = ((OgreMaterialKey)info.getKey()).getMaterialExtensionSet();
if (matExts == null){ }
throw new IOException("Must specify MaterialExtensionSet when loading\n"+
"Ogre3D materials with extended materials"); if (matExts == null){
} throw new IOException("Must specify MaterialExtensionSet when loading\n"+
"Ogre3D materials with extended materials");
list = new MaterialExtensionLoader().load(assetManager, matExts, scan); }
}else{
list = new MaterialList(); list = new MaterialExtensionLoader().load(assetManager, matExts, statements);
while (scan.hasNext("material")){ break;
readMaterial(); }else if (statement.getLine().startsWith("material")){
if (list == null){
list = new MaterialList();
}
String[] split = statement.getLine().split(" ", 2);
matName = split[1].trim();
readMaterial(statement);
Material mat = compileMaterial(); Material mat = compileMaterial();
list.put(matName, mat); list.put(matName, mat);
} }
} }
scan.close(); in.close();
return list; return list;
} }

@ -39,6 +39,7 @@ import com.jme3.material.MaterialList;
import com.jme3.scene.plugins.ogre.MaterialLoader; import com.jme3.scene.plugins.ogre.MaterialLoader;
import com.jme3.texture.Texture; import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode; import com.jme3.texture.Texture.WrapMode;
import com.jme3.util.blockparser.Statement;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Scanner; import java.util.Scanner;
@ -53,26 +54,17 @@ public class MaterialExtensionLoader {
private static final Logger logger = Logger.getLogger(MaterialExtensionLoader.class.getName()); private static final Logger logger = Logger.getLogger(MaterialExtensionLoader.class.getName());
private AssetManager assetManager; private AssetManager assetManager;
private Scanner scan;
private MaterialList list; private MaterialList list;
private MaterialExtensionSet matExts; private MaterialExtensionSet matExts;
private MaterialExtension matExt; private MaterialExtension matExt;
private String matName; private String matName;
private Material material; private Material material;
private String readString(String end){ private void readExtendingMaterialStatement(Statement statement) throws IOException {
scan.useDelimiter(end); if (statement.getLine().startsWith("set_texture_alias")){
String str = scan.next(); String[] split = statement.getLine().split(" ", 3);
scan.useDelimiter("\\p{javaWhitespace}+"); String aliasName = split[1];
return str.trim(); String texturePath = split[2];
}
private boolean readExtendingMaterialStatement() throws IOException{
if (scan.hasNext("set_texture_alias")){
scan.next(); // skip "set_texture_alias"
String aliasName = scan.next();
String texturePath = readString("\n");
String jmeParamName = matExt.getTextureMapping(aliasName); String jmeParamName = matExt.getTextureMapping(aliasName);
@ -85,69 +77,51 @@ public class MaterialExtensionLoader {
tex.setWrap(WrapMode.Repeat); tex.setWrap(WrapMode.Repeat);
material.setTexture(jmeParamName, tex); material.setTexture(jmeParamName, tex);
return true;
}else{
return false;
} }
} }
private Material readExtendingMaterial() throws IOException{ private Material readExtendingMaterial(Statement statement) throws IOException{
scan.next(); // skip "material" String[] split = statement.getLine().split(" ", 2);
matName = readString(":").trim(); String[] subsplit = split[1].split(":");
scan.next(); matName = subsplit[0].trim();
String extendedMat = readString("\\{").trim(); String extendedMat = subsplit[1].trim();
scan.next();
matExt = matExts.getMaterialExtension(extendedMat); matExt = matExts.getMaterialExtension(extendedMat);
if (matExt == null){ if (matExt == null){
logger.log(Level.WARNING, "Cannot find MaterialExtension for: {0}. Ignoring material.", extendedMat); logger.log(Level.WARNING, "Cannot find MaterialExtension for: {0}. Ignoring material.", extendedMat);
readString("\\}");
scan.next();
matExt = null; matExt = null;
return null; return null;
} }
material = new Material(assetManager, matExt.getJmeMatDefName()); material = new Material(assetManager, matExt.getJmeMatDefName());
for (Statement extMatStat : statement.getContents()){
material.setFloat("Shininess", 16f); readExtendingMaterialStatement(extMatStat);
while (!scan.hasNext("\\}")){
readExtendingMaterialStatement();
} }
return material; return material;
} }
public MaterialList load(AssetManager assetManager, MaterialExtensionSet matExts, Scanner scan) throws IOException{ public MaterialList load(AssetManager assetManager, MaterialExtensionSet matExts,
List<Statement> statements) throws IOException{
this.assetManager = assetManager; this.assetManager = assetManager;
this.matExts = matExts; this.matExts = matExts;
this.scan = scan;
list = new MaterialList(); list = new MaterialList();
if (scan.hasNext("import")){ for (Statement statement : statements){
scan.nextLine(); // skip this line if (statement.getLine().startsWith("import")){
} // ignore
continue;
toploop: while (scan.hasNext()){ }else if (statement.getLine().startsWith("material")){
while (!scan.hasNext("material")){ Material material = readExtendingMaterial(statement);
if (!scan.hasNext()) list.put(matName, material);
break toploop; List<String> matAliases = matExts.getNameMappings(matName);
if(matAliases != null){
scan.next(); for (String string : matAliases) {
} list.put(string, material);
}
Material material = readExtendingMaterial();
list.put(matName, material);
List<String> matAliases = matExts.getNameMappings(matName);
if(matAliases != null){
for (String string : matAliases) {
list.put(string, material);
} }
} }
} }
return list; return list;
} }
} }

Loading…
Cancel
Save