package fr.lyrgard.hexScape.model.model3d.loader;
/*
* Copyright (c) 2003, jMonkeyEngine - Mojo Monkey Coding All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions 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 the Mojo Monkey Coding, jME, jMonkey Engine, nor the
* names of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;
import com.jme3.util.BufferUtils;
import fr.lyrgard.hexScape.HexScapeCore;
import fr.lyrgard.hexScape.model.model3d.AseExternalModel;
import fr.lyrgard.hexScape.model.model3d.AseExternalModel.MeshMaterialPair;
import fr.lyrgard.hexScape.model.model3d.ExternalModel;
/**
* <code>ASEModel</code> defines a model using the ASE model format.
* This loader builds the mesh of the model but currently does not
* build any animations defined for the format. Therefore, if a
* call to <code>getAnimationController</code> is made, null will
* be returned.
*
* @author Mark Powell
* @version $Id: ASEModel.java,v 1.5 2004-02-15 20:22:39 mojomonkey Exp $
*/
public class AseModelLoader extends AbstractModelLoader {
private static final Logger LOGGER = Logger.getLogger(AseModelLoader.class.getCanonicalName());
//ASE file tags.
private static final String OBJECT = "*GEOMOBJECT";
private static final String NUM_VERTEX = "*MESH_NUMVERTEX";
private static final String NUM_FACES = "*MESH_NUMFACES";
private static final String NUM_TVERTEX = "*MESH_NUMTVERTEX";
private static final String VERTEX = "*MESH_VERTEX";
private static final String FACE = "*MESH_FACE";
// private static final String NORMALS = "*MESH_NORMALS";
// private static final String FACE_NORMAL = "*MESH_FACENORMAL";
private static final String NVERTEX = "*MESH_VERTEXNORMAL";
private static final String TVERTEX = "*MESH_TVERT";
private static final String TFACE = "*MESH_TFACE";
private static final String TEXTURE = "*BITMAP";
private static final String UTILE = "*UVW_U_TILING";
private static final String VTILE = "*UVW_V_TILING";
// private static final String UOFFSET = "*UVW_U_OFFSET";
// private static final String VOFFSET = "*UVW_V_OFFSET";
private static final String MATERIAL_ID = "*MATERIAL_REF";
private static final String MATERIAL_COUNT = "*MATERIAL_COUNT";
private static final String MATERIAL = "*MATERIAL";
private static final String MATERIAL_NAME = "*MATERIAL_NAME";
private static final String MATERIAL_DIFFUSE = "*MATERIAL_DIFFUSE";
private static final String MATERIAL_AMBIENT = "*MATERIAL_AMBIENT";
private static final String MATERIAL_SPECULAR = "*MATERIAL_SPECULAR";
private static final String MATERIAL_SHINE = "*MATERIAL_SHINE";
// private String absoluteFilePath;
// private BufferedReader reader = null;
// private StringTokenizer tokenizer;
// private String fileContents;
// private File file;
// private int numOfObjects; // The number of objects in the model
// private int numOfMaterials; // The number of materials for the model
// private ArrayList<ASEMaterialInfo> materials = new ArrayList<ASEMaterialInfo>();
// private ArrayList<ASEObject> objectList = new ArrayList<ASEObject>();
public AseModelLoader() {
super();
}
public boolean canLoad(String name) {
File file = getAseFile(name);
return file != null && file.exists();
}
private File getAseFile(String name) {
File file = null;
for (File folder : getModelsFolders()) {
File potentialFile = new File(new File(folder, name), name + ".ase");
if (potentialFile.exists()) {
file = potentialFile;
}
}
return file;
}
public ExternalModel load(String name) {
AseExternalModel model = new AseExternalModel();
File aseFile = getAseFile(name);
String fileContents = null;
ArrayList<ASEObject> objectList = new ArrayList<ASEObject>();
try {
BufferedReader reader = new BufferedReader(new FileReader(aseFile));
StringBuffer fc = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
fc.append(line + "\n");
}
fileContents = fc.toString();
reader.close();
int numOfObjects = getObjectCount(fileContents);
int numOfMaterials = getMaterialCount(fileContents);
ArrayList<ASEMaterialInfo> materials = new ArrayList<ASEMaterialInfo>();
parseFile(numOfObjects, numOfMaterials, objectList, materials, fileContents, name);
//computeNormals(numOfObjects, objectList);
} catch (IOException e) {
LOGGER.log(
Level.WARNING,
"Could not load " + name);
}
model.setName(name);
for (ASEObject object : objectList) {
MeshMaterialPair pair = new MeshMaterialPair(object.getMesh(), object.getMaterial());
model.getMeshMaterialPairs().add(pair);
}
return model;
}
/**
*
* <code>parseFile</code> reads the file contents. First, the
* number of materials and objects are read, then each material
* is read and each object is read.
*
*/
private void parseFile(int numOfObjects, int numOfMaterials, ArrayList<ASEObject> objectList, ArrayList<ASEMaterialInfo> materials, String fileContents, String name) {
ASEMaterialInfo textureInfo = new ASEMaterialInfo();
//Build texture list (not sure if this makes since, there can only be
//one texture per mesh, and the are reading it in for the entire
//object, not on a per object basis.
for (int i = 0; i < numOfMaterials; i++) {
materials.add(textureInfo);
getMaterialInfo((ASEMaterialInfo) materials.get(i), i + 1, fileContents);
}
for (int i = 0; i < numOfObjects; i++) {
ASEObject mesh = new ASEObject(name);
mesh.materialID = -1;
moveToObject(i + 1, fileContents);
readObjectInfo(mesh, i + 1, fileContents);
readObjectData(mesh, i + 1, materials, fileContents);
objectList.add(mesh);
}
}
/**
*
for (int j = 0; j < numOfMaterials; j++) {
ASEMaterialInfo mat = materials.get(j);
// if (mat.file.length() > 0) {
// MaterialState ms =
// DisplaySystem
// .getDisplaySystem()
// .getRenderer()
// .getMaterialState();
// ms.setEnabled(true);
// ms.setAmbient(
// new ColorRGBA(
// mat.ambient[0],
// mat.ambient[1],
// mat.ambient[2],
// 1));
// ms.setDiffuse(
// new ColorRGBA(
// mat.diffuse[0],
// mat.diffuse[1],
// mat.diffuse[2],
// 1));
// ms.setSpecular(
// new ColorRGBA(
// mat.specular[0],
// mat.specular[1],
// mat.specular[2],
// 1));
// ms.setEmissive(new ColorRGBA(0, 0, 0, 1));
// ms.setShininess(mat.shine);
// this.setRenderState(ms);
// }
}
for (int j = 0; j < numOfMaterials; j++) {
// Check if the current material has a file name
if ((materials.get(j)).file.length()
> 0) {
// TextureState ts =
// DisplaySystem
// .getDisplaySystem()
// .getRenderer()
// .getTextureState();
// ts.setEnabled(true);
// ts.setTexture(
// TextureManager.loadTexture(
// ((ASEModel.ASEMaterialInfo) materials.get(j)).file,
// Texture.MM_LINEAR,
// Texture.FM_LINEAR,
// true));
// this.setRenderState(ts);
}
}
}
/**
*
* <code>getObjectCount</code> counts the number of Geomobject entries
* in the ASE file. This count is then returned.
* @return the number of Geomobject entries.
*/
private int getObjectCount(String fileContents) {
int objectCount = 0;
StringTokenizer tokenizer = new StringTokenizer(fileContents);
while (tokenizer.hasMoreTokens()) {
// Check if we hit the start of an object
if (OBJECT.equals(tokenizer.nextToken())) {
objectCount++;
}
}
return objectCount;
}
/**
*
* <code>getMaterialCount</code> retrieves the number of materials in the
* ASE file. The file is read until the *MATERIAL flag is encountered. Once
* this flag is found, the value is read.
*
* @return the number of materials as defined in the ASE file.
*/
private int getMaterialCount(String fileContents) {
int materialCount = 0;
// Go to the beginning of the file
StringTokenizer tokenizer = new StringTokenizer(fileContents);
// GO through the whole file until we hit the end
while (tokenizer.hasMoreTokens()) {
if (MATERIAL_COUNT.equals(tokenizer.nextToken())) {
materialCount = Integer.parseInt(tokenizer.nextToken());
return materialCount;
}
}
//Material tag never found
return 0;
}
/**
*
* <code>getMaterialInfo</code> reads the data for a given material
* entry in the file. The material state information is read and
* set as well as the texture state information.
* @param material the material structure to store into.
* @param desiredMaterial the material to load from the file.
*/
private void getMaterialInfo(
ASEMaterialInfo material,
int desiredMaterial,
String fileContents) {
String strWord;
int materialCount = 0;
// Go to the beginning of the file
StringTokenizer tokenizer = new StringTokenizer(fileContents);
//read through the file until the correct material entry is found.
while (tokenizer.hasMoreTokens()) {
if (MATERIAL.equals(tokenizer.nextToken())) {
materialCount++;
// Check if it's the one we want to stop at, if so break
if (materialCount == desiredMaterial)
break;
}
}
while (tokenizer.hasMoreTokens()) {
strWord = tokenizer.nextToken();
if (strWord.equals(MATERIAL)) {
return;
}
//read material properites.
if (strWord.equals(MATERIAL_AMBIENT)) {
material.ambient[0] = Float.parseFloat(tokenizer.nextToken());
material.ambient[1] = Float.parseFloat(tokenizer.nextToken());
material.ambient[2] = Float.parseFloat(tokenizer.nextToken());
} else if (strWord.equals(MATERIAL_DIFFUSE)) {
material.diffuse[0] = Float.parseFloat(tokenizer.nextToken());
material.diffuse[1] = Float.parseFloat(tokenizer.nextToken());
material.diffuse[2] = Float.parseFloat(tokenizer.nextToken());
} else if (strWord.equals(MATERIAL_SPECULAR)) {
material.specular[0] = Float.parseFloat(tokenizer.nextToken());
material.specular[1] = Float.parseFloat(tokenizer.nextToken());
material.specular[2] = Float.parseFloat(tokenizer.nextToken());
} else if (strWord.equals(MATERIAL_SHINE)) {
//material.shine = Float.parseFloat(tokenizer.nextToken());
}
//read texture information.
if (strWord.equals(TEXTURE)) {
//material.file = tokenizer.nextToken().replace('"', ' ').trim();
} else if (strWord.equals(MATERIAL_NAME)) {
//material.name = tokenizer.nextToken();
} else if (strWord.equals(UTILE)) {
material.uTile = Float.parseFloat(tokenizer.nextToken());
} else if (strWord.equals(VTILE)) {
material.vTile = Float.parseFloat(tokenizer.nextToken());
}
}
}
/**
*
* <code>moveToObject</code> moves the file pointer to a specific
* GEOMOBJECT entry in the ase file.
* @param desiredObject the object number to move to.
*/
private StringTokenizer moveToObject(int desiredObject, String fileContents) {
int objectCount = 0;
StringTokenizer tokenizer = new StringTokenizer(fileContents);
while (tokenizer.hasMoreTokens()) {
if (OBJECT.equals(tokenizer.nextToken())) {
objectCount++;
if (objectCount == desiredObject)
return tokenizer;
}
}
return null;
}
/**
*
* <code>readObjectInfo</code> reads the mesh information defined by
* the GEOMOBJECT entry in the file. This information is kept in the
* ASEObject class until it is ready to be converted to a TriMesh.
* @param currentObject the object to store the data in.
* @param desiredObject the object to read.
*/
private void readObjectInfo(ASEObject currentObject, int desiredObject, String fileContents) {
String word;
StringTokenizer tokenizer = moveToObject(desiredObject, fileContents);
while (tokenizer.hasMoreTokens()) {
word = tokenizer.nextToken();
if (word.equals("*NODE_NAME")) {
currentObject.setName(tokenizer.nextToken().replaceAll("\"", ""));
}
if (word.equals(NUM_VERTEX)) {
int numOfVerts = Integer.parseInt(tokenizer.nextToken());
Vector3f[] verts = new Vector3f[numOfVerts];
currentObject.setVertices(verts);
currentObject.setNormals(new Vector3f[numOfVerts]);
} else if (word.equals(NUM_FACES)) {
int numOfFaces = Integer.parseInt(tokenizer.nextToken());
currentObject.faces = new Face[numOfFaces];
} else if (word.equals(NUM_TVERTEX)) {
int numTexVertex = Integer.parseInt(tokenizer.nextToken());
currentObject.tempTexVerts = new Vector2f[numTexVertex];
} else if (word.equals(OBJECT)) {
return;
}
}
}
/**
*
* <code>readObjectData</code> reads each bit of data defined by a
* GEOMOBJECT. Namely, material id, vertices, texture vertices, faces,
* texture faces, texture file, u and v tiling.
* @param currentObject the object to store the information in.
* @param desiredObject the object to read.
*/
private void readObjectData(ASEObject currentObject, int desiredObject, ArrayList<ASEMaterialInfo> materials, String fileContents) {
// Load the material ID for this object
getData(currentObject, MATERIAL_ID, desiredObject, materials, fileContents);
// Load the vertices for this object
getData(currentObject, VERTEX, desiredObject, materials, fileContents);
// Load the texture coordinates for this object
getData(currentObject, TVERTEX, desiredObject, materials, fileContents);
// Load the vertex faces list for this object
getData(currentObject, FACE, desiredObject, materials, fileContents);
// Load the texture face list for this object
getData(currentObject, TFACE, desiredObject, materials, fileContents);
// Load the texture for this object
getData(currentObject, TEXTURE, desiredObject, materials, fileContents);
// Load the U tile for this object
getData(currentObject, UTILE, desiredObject, materials, fileContents);
// Load the V tile for this object
getData(currentObject, VTILE, desiredObject, materials, fileContents);
// Load the VERTEX NORMAL for this object
getData(currentObject, NVERTEX, desiredObject, materials, fileContents);
}
/**
*
* <code>getData</code> reads a specified bit of data out of a GEOMOBECT
* entry in the ase file.
* @param currentObject the object to save the data in.
* @param desiredData the object type to read.
* @param desiredObject the object to read.
*/
private void getData(
ASEObject currentObject,
String desiredData,
int desiredObject,
ArrayList<ASEMaterialInfo> materials,
String fileContents) {
String word;
StringTokenizer tokenizer = moveToObject(desiredObject, fileContents);
// Go through the file until we reach the end
while (tokenizer.hasMoreTokens()) {
word = tokenizer.nextToken();
// If we reached an object tag, stop read because we went to far
if (word.equals(OBJECT)) {
// Stop reading because we are done with the current object
return;
}
// If we hit a vertex tag
else if (word.equals(VERTEX)) {
// Make sure that is the data that we want to read in
if (desiredData.equals(VERTEX)) {
// Read in a vertex
readVertex(currentObject, tokenizer);
}
}
// If we hit a texture vertex
else if (word.equals(TVERTEX)) {
// Make sure that is the data that we want to read in
if (desiredData.equals(TVERTEX)) {
// Read in a texture vertex
if (currentObject.materialID != -1) {
readTextureVertex(currentObject,materials.get(currentObject.materialID), tokenizer);
} else {
readTextureVertex(currentObject,null, tokenizer);
}
}
}
// If we hit a vertice index to a face
else if (word.equals(FACE)) {
// Make sure that is the data that we want to read in
if (desiredData.equals(FACE)) {
// Read in a face
readFace(currentObject, tokenizer);
}
}
// If we hit a texture index to a face
else if (word.equals(TFACE)) {
// Make sure that is the data that we want to read in
if (desiredData.equals(TFACE)) {
// Read in a texture indice for a face
readTextureFace(currentObject, tokenizer);
}
}
// If we hit the material ID to the object
else if (word.equals(MATERIAL_ID)) {
// Make sure that is the data that we want to read in
if (desiredData.equals(MATERIAL_ID)) {
// Read in the material ID assigned to this object
currentObject.materialID =
(int) Float.parseFloat(tokenizer.nextToken());
return;
}
}
// // If we hit the normal to vertex
// else if (word.equals(NVERTEX)) {
// // Make sure that is the data that we want to read in
// if (desiredData.equals(NVERTEX)) {
// // Read in the material ID assigned to this object
// readVertexNormal(currentObject, tokenizer);
// }
// }
}
}
/**
*
* <code>readVertex</code> reads the vertices information from a
* GEOMOBJECT entry. Some converting is required to get the
* coordinate axes into the default jme axes.
* @param currentObject the object to start the vertex in.
*/
private void readVertex(ASEObject currentObject, StringTokenizer tokenizer) {
// Read past the vertex index
int index = Integer.parseInt(tokenizer.nextToken());
float x = Float.parseFloat(tokenizer.nextToken());
float z = -Float.parseFloat(tokenizer.nextToken());
float y = Float.parseFloat(tokenizer.nextToken());
Vector3f vector = new Vector3f(x, y , z);
currentObject.getVertices()[index] = vector;
}
// /**
// *
// * <code>readVertex</code> reads the vertices information from a
// * GEOMOBJECT entry. Some converting is required to get the
// * coordinate axes into the default jme axes.
// * @param currentObject the object to start the vertex in.
// */
// private void readVertexNormal(ASEObject currentObject, StringTokenizer tokenizer) {
// // Read past the vertex index
// int index = Integer.parseInt(tokenizer.nextToken());
// float x = Float.parseFloat(tokenizer.nextToken());
// float z = -Float.parseFloat(tokenizer.nextToken());
// float y = Float.parseFloat(tokenizer.nextToken());
//
//
// Vector3f vector = new Vector3f(x, y , z);
// currentObject.getNormals()[index] = vector;
// }
/**
*
* <code>readTextureVertex</code> reads in a single texture coordinate
* from the ase file.
* @param currentObject the object that has the coordinate.
* @param texture the object that defines the texture.
*/
private void readTextureVertex(
ASEObject currentObject,
ASEMaterialInfo texture,
StringTokenizer tokenizer) {
int index = 0;
// Here we read past the index of the texture coordinate
index = Integer.parseInt(tokenizer.nextToken());
currentObject.tempTexVerts[index] = new Vector2f();
// Next, we read in the (U, V) texture coordinates.
currentObject.tempTexVerts[index].x = Float.parseFloat(tokenizer.nextToken());
currentObject.tempTexVerts[index].y = Float.parseFloat(tokenizer.nextToken());
if (texture != null) {
currentObject.tempTexVerts[index].x *= texture.uTile;
currentObject.tempTexVerts[index].y *= texture.vTile;
}
}
/**
*
* <code>readFace</code> reads the face of a triangle, that
* is how vertices are put together to
* form the mesh.
* @param currentObject the object to store the information
* in.
*/
private void readFace(ASEObject currentObject, StringTokenizer tokenizer) {
int index = 0;
// Read past the index of this Face
String temp = tokenizer.nextToken();
if (temp.indexOf(":") > 0) {
temp = temp.substring(0, temp.length() - 1);
}
index = Integer.parseInt(temp);
currentObject.faces[index] = new Face();
tokenizer.nextToken(); // "A:"
currentObject.faces[index].vertIndex[0] =
Integer.parseInt(tokenizer.nextToken());
tokenizer.nextToken(); // "B:"
currentObject.faces[index].vertIndex[1] =
Integer.parseInt(tokenizer.nextToken());
tokenizer.nextToken(); // "C:"
currentObject.faces[index].vertIndex[2] =
Integer.parseInt(tokenizer.nextToken());
}
/**
*
* <code>readFace</code> reads the face of a triangle, that
* is how texture vertices are put together to
* form the mesh.
* @param currentObject the object to store the information
* in.
*/
private void readTextureFace(ASEObject currentObject, StringTokenizer tokenizer) {
int index = 0;
// Read past the index for this texture coordinate
index = Integer.parseInt(tokenizer.nextToken());
// Now we read in the UV coordinate index for the current face.
// This will be an index into pTexCoords[] for each point in the face.
currentObject.faces[index].coordIndex[0] =
Integer.parseInt(tokenizer.nextToken());
currentObject.faces[index].coordIndex[1] =
Integer.parseInt(tokenizer.nextToken());
currentObject.faces[index].coordIndex[2] =
Integer.parseInt(tokenizer.nextToken());
}
// /**
// *
// * <code>computeNormals</code> normals are not defined in the
// * ase file, so we calculate them manually. Each vertex has a
// * matching normal. This normal is the average of all the face
// * normals surrounding the vertex.
// *
// */
// private void computeNormals(int numOfObjects, List<ASEObject> objectList) {
// if (numOfObjects <= 0) {
// return;
// }
//
// Vector3f vector1 = new Vector3f();
// Vector3f vector2 = new Vector3f();
// Vector3f[] triangle = new Vector3f[3];
//
// // Go through each of the objects to calculate their normals
// for (int index = 0; index < numOfObjects; index++) {
// // Get the current object
// ASEObject object = objectList.get(index);
// // Here we allocate all the memory we need to calculate the normals
// Vector3f[] tempNormals = new Vector3f[object.faces.length];
// Vector3f[] normals = new Vector3f[object.getVertices().length];
//
// // Go though all of the faces of this object
// for (int i = 0; i < object.faces.length; i++) {
// vector1 =
// object
// .getVertices()[object
// .faces[i]
// .vertIndex[0]]
// .subtract(
// object.getVertices()[object.faces[i].vertIndex[2]]);
// vector2 =
// object
// .getVertices()[object
// .faces[i]
// .vertIndex[2]]
// .subtract(
// object.getVertices()[object.faces[i].vertIndex[1]]);
//
// tempNormals[i] = vector1.cross(vector2).normalize();
// }
//
// Vector3f sum = new Vector3f();
// Vector3f zero = sum;
// int shared = 0;
//
// for (int i = 0; i < object.getVertices().length; i++) {
// for (int j = 0; j < object.faces.length; j++) {
// if (object.faces[j].vertIndex[0] == i
// || object.faces[j].vertIndex[1] == i
// || object.faces[j].vertIndex[2] == i) {
// sum = sum.add(tempNormals[j]);
//
// shared++;
// }
// }
//
// normals[i] = sum.divide((float) (-shared)).normalize();
//
// sum = zero; // Reset the sum
// shared = 0; // Reset the shared
// }
//
// object.setNormals(normals);
//
// }
// }
/**
*
* <code>ASEMaterialInfo</code> holds material and texture information.
*/
private class ASEMaterialInfo {
// String name; // The texture name
// public String file;
// The texture file name (If this is set it's a texture map)
public float[] diffuse = new float[3];
public float[] ambient = new float[3];
public float[] specular = new float[3];
// public float shine;
// The color of the object (R, G, B)
float uTile; // u tiling of texture (Currently not used)
float vTile; // v tiling of texture (Currently not used)
// float uOffset; // u offset of texture (Currently not used)
// float vOffset; // v offset of texture (Currently not used)
};
/**
*
* <code>ASEObject</code> holds the data for the mesh.
*/
public class ASEObject {
private ASEObject(String mainObjectName) {
super();
this.mainObjectName = mainObjectName;
}
private int materialID;
private Vector3f[] vertices;
private Vector2f[] texCoords;
private Vector3f[] normals;
private Vector2f[] tempTexVerts; // The texture's UV coordinates
private Face[] faces; // The faces information of the object
private String mainObjectName;
private String name;
public Mesh getMesh() {
Vector3f[] endVertices = new Vector3f[faces.length * 3];
Vector2f[] endTexCoord = new Vector2f[faces.length * 3];
Vector3f[] endNormals = new Vector3f[faces.length * 3];
int[] endIndices = new int[faces.length * 3];
int i = 0;
for (Face face : faces) {
Vector3f vec1 = vertices[face.vertIndex[0]].subtract(vertices[face.vertIndex[1]]);
Vector3f vec2 = vertices[face.vertIndex[2]].subtract(vertices[face.vertIndex[1]]);
Vector3f normal = vec2.cross(vec1).normalize();
for (int j = 0; j < 3; j++) {
endVertices[i] = vertices[face.vertIndex[j]];
endTexCoord[i] = tempTexVerts[face.coordIndex[j]];
endIndices[i] = i;
endNormals[i] = normal;
i++;
}
}
Mesh mesh = new Mesh();
mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(endVertices));
mesh.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(endTexCoord));
mesh.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(endIndices));
mesh.setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(endNormals));
mesh.updateBound();
return mesh;
}
private File getTextureFile(String modelName, String textureName) {
File file = null;
for (File folder : getModelsFolders()) {
File potentialFile = new File(new File(new File(folder, modelName), "Textures"),textureName + ".bmp");
if (potentialFile.exists()) {
file = potentialFile;
}
}
return file;
}
public Material getMaterial() {
AssetManager assetManager = HexScapeCore.getInstance().getHexScapeJme3Application().getAssetManager();
Material mat = new Material(assetManager,
"Common/MatDefs/Light/Lighting.j3md");
Texture TileTexture = assetManager.loadTexture(getTextureFile(mainObjectName, name).getPath());
TileTexture.setWrap(WrapMode.Repeat);
mat.setTexture("DiffuseMap", TileTexture);
mat.setBoolean("UseMaterialColors",true);
mat.setColor("Ambient", ColorRGBA.White.mult(0.5f));
mat.setColor("Diffuse",ColorRGBA.White); // minimum material color
mat.setColor("Specular",ColorRGBA.White); // for shininess
mat.setFloat("Shininess", 50f);
return mat;
}
Vector3f[] getVertices() {
return vertices;
}
public void setVertices(Vector3f[] vertices) {
this.vertices = vertices;
}
Vector2f[] getTexCoords() {
return texCoords;
}
public void setTexCoords(Vector2f[] texCoords) {
this.texCoords = texCoords;
}
Vector3f[] getNormals() {
return normals;
}
public void setNormals(Vector3f[] normals) {
this.normals = normals;
}
String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setMainObjectName(String mainObjectName) {
this.mainObjectName = mainObjectName;
}
};
public class Face {
public int[] vertIndex = new int[3];
public int[] coordIndex= new int[3];
}
}