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

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

Loading…
Cancel
Save