* Fixed Blender loader crash when "Image" texture mode is specified but actual image is not selected
* Replaced oracle proprietary exception with UnsupportedOperationException * Shared Geometry Patch - Still need detection mechanism for old versions! * Binary/J3O format will now write signature and version * Binary/J3O format now has version numbers for exported class hierarchies * Fix crash in TestHoveringTank * ListMap now uses backing array and a map - increased lookup performance for uniforms/matparams and faster iteration too. Only insertion became slower git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7726 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
090e57b224
commit
348b1d638a
@ -177,8 +177,10 @@ public class TextureHelper extends AbstractBlenderHelper {
|
|||||||
break;
|
break;
|
||||||
case TEX_IMAGE:// (it is first because probably this will be most commonly used)
|
case TEX_IMAGE:// (it is first because probably this will be most commonly used)
|
||||||
Pointer pImage = (Pointer) tex.getFieldValue("ima");
|
Pointer pImage = (Pointer) tex.getFieldValue("ima");
|
||||||
Structure image = pImage.fetchData(dataRepository.getInputStream()).get(0);
|
if (pImage.isNotNull()){
|
||||||
result = this.getTextureFromImage(image, dataRepository);
|
Structure image = pImage.fetchData(dataRepository.getInputStream()).get(0);
|
||||||
|
result = this.getTextureFromImage(image, dataRepository);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TEX_CLOUDS:
|
case TEX_CLOUDS:
|
||||||
result = this.clouds(tex, width, height, dataRepository);
|
result = this.clouds(tex, width, height, dataRepository);
|
||||||
@ -212,7 +214,7 @@ public class TextureHelper extends AbstractBlenderHelper {
|
|||||||
break;
|
break;
|
||||||
case TEX_PLUGIN:
|
case TEX_PLUGIN:
|
||||||
case TEX_ENVMAP:// TODO: implement envmap texture
|
case TEX_ENVMAP:// TODO: implement envmap texture
|
||||||
LOGGER.log(Level.WARNING, "Unsupported texture type: " + type + " for texture: " + tex.getName());
|
LOGGER.log(Level.WARNING, "Unsupported texture type: {0} for texture: {1}", new Object[]{type, tex.getName()});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new BlenderFileException("Unknown texture type: " + type + " for texture: " + tex.getName());
|
throw new BlenderFileException("Unknown texture type: " + type + " for texture: " + tex.getName());
|
||||||
|
@ -6,9 +6,6 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
|
|
||||||
|
|
||||||
import com.jme3.export.InputCapsule;
|
import com.jme3.export.InputCapsule;
|
||||||
import com.jme3.export.JmeExporter;
|
import com.jme3.export.JmeExporter;
|
||||||
import com.jme3.export.JmeImporter;
|
import com.jme3.export.JmeImporter;
|
||||||
@ -158,7 +155,7 @@ public class Properties implements Cloneable, Savable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IDP_NUMTYPES:
|
case IDP_NUMTYPES:
|
||||||
throw new NotImplementedException();
|
throw new UnsupportedOperationException();
|
||||||
// case IDP_ID://not yet implemented in blender
|
// case IDP_ID://not yet implemented in blender
|
||||||
// return null;
|
// return null;
|
||||||
default:
|
default:
|
||||||
|
@ -42,5 +42,5 @@ class BinaryClassObject {
|
|||||||
|
|
||||||
byte[] alias;
|
byte[] alias;
|
||||||
String className;
|
String className;
|
||||||
|
int[] classHierarchyVersions;
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ package com.jme3.export.binary;
|
|||||||
|
|
||||||
import com.jme3.export.JmeExporter;
|
import com.jme3.export.JmeExporter;
|
||||||
import com.jme3.export.Savable;
|
import com.jme3.export.Savable;
|
||||||
|
import com.jme3.export.FormatVersion;
|
||||||
|
import com.jme3.export.SavableClassUtil;
|
||||||
import com.jme3.math.FastMath;
|
import com.jme3.math.FastMath;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -43,6 +45,7 @@ import java.io.OutputStream;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -179,32 +182,44 @@ public class BinaryExporter implements JmeExporter {
|
|||||||
locationTable.clear();
|
locationTable.clear();
|
||||||
contentKeys.clear();
|
contentKeys.clear();
|
||||||
|
|
||||||
|
// write signature and version
|
||||||
|
os.write(ByteUtils.convertToBytes(FormatVersion.SIGNATURE));
|
||||||
|
os.write(ByteUtils.convertToBytes(FormatVersion.VERSION));
|
||||||
|
|
||||||
int id = processBinarySavable(object);
|
int id = processBinarySavable(object);
|
||||||
|
|
||||||
// write out tag table
|
// write out tag table
|
||||||
int ttbytes = 0;
|
int classTableSize = 0;
|
||||||
int classNum = classes.keySet().size();
|
int classNum = classes.keySet().size();
|
||||||
int aliasWidth = ((int) FastMath.log(classNum, 256) + 1); // make all
|
int aliasSize = ((int) FastMath.log(classNum, 256) + 1); // make all
|
||||||
// aliases a
|
// aliases a
|
||||||
// fixed width
|
// fixed width
|
||||||
|
|
||||||
os.write(ByteUtils.convertToBytes(classNum));
|
os.write(ByteUtils.convertToBytes(classNum));
|
||||||
for (String key : classes.keySet()) {
|
for (String key : classes.keySet()) {
|
||||||
BinaryClassObject bco = classes.get(key);
|
BinaryClassObject bco = classes.get(key);
|
||||||
|
|
||||||
// write alias
|
// write alias
|
||||||
byte[] aliasBytes = fixClassAlias(bco.alias,
|
byte[] aliasBytes = fixClassAlias(bco.alias,
|
||||||
aliasWidth);
|
aliasSize);
|
||||||
os.write(aliasBytes);
|
os.write(aliasBytes);
|
||||||
ttbytes += aliasWidth;
|
classTableSize += aliasSize;
|
||||||
|
|
||||||
|
// jME3 NEW: Write class hierarchy version numbers
|
||||||
|
os.write( bco.classHierarchyVersions.length );
|
||||||
|
for (int version : bco.classHierarchyVersions){
|
||||||
|
os.write(ByteUtils.convertToBytes(version));
|
||||||
|
}
|
||||||
|
classTableSize += 1 + bco.classHierarchyVersions.length * 4;
|
||||||
|
|
||||||
// write classname size & classname
|
// write classname size & classname
|
||||||
byte[] classBytes = key.getBytes();
|
byte[] classBytes = key.getBytes();
|
||||||
os.write(ByteUtils.convertToBytes(classBytes.length));
|
os.write(ByteUtils.convertToBytes(classBytes.length));
|
||||||
os.write(classBytes);
|
os.write(classBytes);
|
||||||
ttbytes += 4 + classBytes.length;
|
classTableSize += 4 + classBytes.length;
|
||||||
|
|
||||||
|
// for each field, write alias, type, and name
|
||||||
os.write(ByteUtils.convertToBytes(bco.nameFields.size()));
|
os.write(ByteUtils.convertToBytes(bco.nameFields.size()));
|
||||||
|
|
||||||
for (String fieldName : bco.nameFields.keySet()) {
|
for (String fieldName : bco.nameFields.keySet()) {
|
||||||
BinaryClassField bcf = bco.nameFields.get(fieldName);
|
BinaryClassField bcf = bco.nameFields.get(fieldName);
|
||||||
os.write(bcf.alias);
|
os.write(bcf.alias);
|
||||||
@ -214,7 +229,7 @@ public class BinaryExporter implements JmeExporter {
|
|||||||
byte[] fNameBytes = fieldName.getBytes();
|
byte[] fNameBytes = fieldName.getBytes();
|
||||||
os.write(ByteUtils.convertToBytes(fNameBytes.length));
|
os.write(ByteUtils.convertToBytes(fNameBytes.length));
|
||||||
os.write(fNameBytes);
|
os.write(fNameBytes);
|
||||||
ttbytes += 2 + 4 + fNameBytes.length;
|
classTableSize += 2 + 4 + fNameBytes.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,9 +257,9 @@ public class BinaryExporter implements JmeExporter {
|
|||||||
alreadySaved.put(savableName + getChunk(pair), bucket);
|
alreadySaved.put(savableName + getChunk(pair), bucket);
|
||||||
}
|
}
|
||||||
bucket.add(pair);
|
bucket.add(pair);
|
||||||
byte[] aliasBytes = fixClassAlias(classes.get(savableName).alias, aliasWidth);
|
byte[] aliasBytes = fixClassAlias(classes.get(savableName).alias, aliasSize);
|
||||||
out.write(aliasBytes);
|
out.write(aliasBytes);
|
||||||
location += aliasWidth;
|
location += aliasSize;
|
||||||
BinaryOutputCapsule cap = contentTable.get(savable).getContent();
|
BinaryOutputCapsule cap = contentTable.get(savable).getContent();
|
||||||
out.write(ByteUtils.convertToBytes(cap.bytes.length));
|
out.write(ByteUtils.convertToBytes(cap.bytes.length));
|
||||||
location += 4; // length of bytes
|
location += 4; // length of bytes
|
||||||
@ -254,13 +269,13 @@ public class BinaryExporter implements JmeExporter {
|
|||||||
|
|
||||||
// write out location table
|
// write out location table
|
||||||
// tag/location
|
// tag/location
|
||||||
int locNum = locationTable.keySet().size();
|
int numLocations = locationTable.keySet().size();
|
||||||
os.write(ByteUtils.convertToBytes(locNum));
|
os.write(ByteUtils.convertToBytes(numLocations));
|
||||||
int locbytes = 0;
|
int locationTableSize = 0;
|
||||||
for (Integer key : locationTable.keySet()) {
|
for (Integer key : locationTable.keySet()) {
|
||||||
os.write(ByteUtils.convertToBytes(key));
|
os.write(ByteUtils.convertToBytes(key));
|
||||||
os.write(ByteUtils.convertToBytes(locationTable.get(key)));
|
os.write(ByteUtils.convertToBytes(locationTable.get(key)));
|
||||||
locbytes += 8;
|
locationTableSize += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write out number of root ids - hardcoded 1 for now
|
// write out number of root ids - hardcoded 1 for now
|
||||||
@ -278,11 +293,11 @@ public class BinaryExporter implements JmeExporter {
|
|||||||
|
|
||||||
if (debug ) {
|
if (debug ) {
|
||||||
logger.info("Stats:");
|
logger.info("Stats:");
|
||||||
logger.info("classes: " + classNum);
|
logger.log(Level.INFO, "classes: {0}", classNum);
|
||||||
logger.info("class table: " + ttbytes + " bytes");
|
logger.log(Level.INFO, "class table: {0} bytes", classTableSize);
|
||||||
logger.info("objects: " + locNum);
|
logger.log(Level.INFO, "objects: {0}", numLocations);
|
||||||
logger.info("location table: " + locbytes + " bytes");
|
logger.log(Level.INFO, "location table: {0} bytes", locationTableSize);
|
||||||
logger.info("data: " + location + " bytes");
|
logger.log(Level.INFO, "data: {0} bytes", location);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -331,17 +346,38 @@ public class BinaryExporter implements JmeExporter {
|
|||||||
return contentTable.get(object).getContent();
|
return contentTable.get(object).getContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BinaryClassObject createClassObject(Class clazz) throws IOException{
|
||||||
|
BinaryClassObject bco = new BinaryClassObject();
|
||||||
|
bco.alias = generateTag();
|
||||||
|
bco.nameFields = new HashMap<String, BinaryClassField>();
|
||||||
|
|
||||||
|
ArrayList<Integer> versionList = new ArrayList<Integer>();
|
||||||
|
Class superclass = clazz;
|
||||||
|
do {
|
||||||
|
versionList.add(SavableClassUtil.getSavableVersion(superclass));
|
||||||
|
superclass = superclass.getSuperclass();
|
||||||
|
} while (superclass != null && SavableClassUtil.isImplementingSavable(superclass));
|
||||||
|
|
||||||
|
int[] versions = new int[versionList.size()];
|
||||||
|
for (int i = 0; i < versionList.size(); i++){
|
||||||
|
versions[i] = versionList.get(i);
|
||||||
|
}
|
||||||
|
bco.classHierarchyVersions = versions;
|
||||||
|
|
||||||
|
classes.put(clazz.getName(), bco);
|
||||||
|
|
||||||
|
return bco;
|
||||||
|
}
|
||||||
|
|
||||||
public int processBinarySavable(Savable object) throws IOException {
|
public int processBinarySavable(Savable object) throws IOException {
|
||||||
if (object == null) {
|
if (object == null) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Class<? extends Savable> clazz = object.getClass();
|
||||||
BinaryClassObject bco = classes.get(object.getClass().getName());
|
BinaryClassObject bco = classes.get(object.getClass().getName());
|
||||||
// is this class been looked at before? in tagTable?
|
// is this class been looked at before? in tagTable?
|
||||||
if (bco == null) {
|
if (bco == null) {
|
||||||
bco = new BinaryClassObject();
|
bco = createClassObject(object.getClass());
|
||||||
bco.alias = generateTag();
|
|
||||||
bco.nameFields = new HashMap<String, BinaryClassField>();
|
|
||||||
classes.put(object.getClass().getName(), bco);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// is object in contentTable?
|
// is object in contentTable?
|
||||||
|
@ -32,9 +32,11 @@
|
|||||||
|
|
||||||
package com.jme3.export.binary;
|
package com.jme3.export.binary;
|
||||||
|
|
||||||
import com.jme3.export.SavableClassFinder;
|
import com.jme3.export.SavableClassUtil;
|
||||||
import com.jme3.asset.AssetInfo;
|
import com.jme3.asset.AssetInfo;
|
||||||
import com.jme3.asset.AssetManager;
|
import com.jme3.asset.AssetManager;
|
||||||
|
import com.jme3.export.FormatVersion;
|
||||||
|
import com.jme3.export.InputCapsule;
|
||||||
import com.jme3.export.JmeImporter;
|
import com.jme3.export.JmeImporter;
|
||||||
import com.jme3.export.ReadListener;
|
import com.jme3.export.ReadListener;
|
||||||
import com.jme3.export.Savable;
|
import com.jme3.export.Savable;
|
||||||
@ -57,6 +59,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Joshua Slack
|
* @author Joshua Slack
|
||||||
|
* @author Kirill Vainer - Version number, Fast buffer reading
|
||||||
*/
|
*/
|
||||||
public final class BinaryImporter implements JmeImporter {
|
public final class BinaryImporter implements JmeImporter {
|
||||||
private static final Logger logger = Logger.getLogger(BinaryImporter.class
|
private static final Logger logger = Logger.getLogger(BinaryImporter.class
|
||||||
@ -81,6 +84,7 @@ public final class BinaryImporter implements JmeImporter {
|
|||||||
|
|
||||||
private byte[] dataArray;
|
private byte[] dataArray;
|
||||||
private int aliasWidth;
|
private int aliasWidth;
|
||||||
|
private int formatVersion;
|
||||||
|
|
||||||
private static final boolean fastRead = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
|
private static final boolean fastRead = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
|
||||||
|
|
||||||
@ -89,6 +93,10 @@ public final class BinaryImporter implements JmeImporter {
|
|||||||
public BinaryImporter() {
|
public BinaryImporter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getFormatVersion(){
|
||||||
|
return formatVersion;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canUseFastBuffers(){
|
public static boolean canUseFastBuffers(){
|
||||||
return fastRead;
|
return fastRead;
|
||||||
}
|
}
|
||||||
@ -139,7 +147,31 @@ public final class BinaryImporter implements JmeImporter {
|
|||||||
public Savable load(InputStream is, ReadListener listener, ByteArrayOutputStream baos) throws IOException {
|
public Savable load(InputStream is, ReadListener listener, ByteArrayOutputStream baos) throws IOException {
|
||||||
contentTable.clear();
|
contentTable.clear();
|
||||||
BufferedInputStream bis = new BufferedInputStream(is);
|
BufferedInputStream bis = new BufferedInputStream(is);
|
||||||
int numClasses = ByteUtils.readInt(bis);
|
|
||||||
|
int numClasses;
|
||||||
|
|
||||||
|
// Try to read signature
|
||||||
|
int maybeSignature = ByteUtils.readInt(bis);
|
||||||
|
if (maybeSignature == FormatVersion.SIGNATURE){
|
||||||
|
// this is a new version J3O file
|
||||||
|
formatVersion = ByteUtils.readInt(bis);
|
||||||
|
numClasses = ByteUtils.readInt(bis);
|
||||||
|
|
||||||
|
// check if this binary is from the future
|
||||||
|
if (formatVersion > FormatVersion.VERSION){
|
||||||
|
throw new IOException("The binary file is of newer version than expected! " +
|
||||||
|
formatVersion + " > " + FormatVersion.VERSION);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
// this is an old version J3O file
|
||||||
|
// the signature was actually the class count
|
||||||
|
numClasses = maybeSignature;
|
||||||
|
|
||||||
|
// 0 indicates version before we started adding
|
||||||
|
// version numbers
|
||||||
|
formatVersion = 0;
|
||||||
|
}
|
||||||
|
|
||||||
int bytes = 4;
|
int bytes = 4;
|
||||||
aliasWidth = ((int)FastMath.log(numClasses, 256) + 1);
|
aliasWidth = ((int)FastMath.log(numClasses, 256) + 1);
|
||||||
|
|
||||||
@ -147,11 +179,26 @@ public final class BinaryImporter implements JmeImporter {
|
|||||||
for(int i = 0; i < numClasses; i++) {
|
for(int i = 0; i < numClasses; i++) {
|
||||||
String alias = readString(bis, aliasWidth);
|
String alias = readString(bis, aliasWidth);
|
||||||
|
|
||||||
|
// jME3 NEW: Read class version number
|
||||||
|
int[] classHierarchyVersions;
|
||||||
|
if (formatVersion >= 1){
|
||||||
|
int classHierarchySize = bis.read();
|
||||||
|
classHierarchyVersions = new int[classHierarchySize];
|
||||||
|
for (int j = 0; j < classHierarchySize; j++){
|
||||||
|
classHierarchyVersions[j] = ByteUtils.readInt(bis);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
classHierarchyVersions = new int[]{ 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// read classname and classname size
|
||||||
int classLength = ByteUtils.readInt(bis);
|
int classLength = ByteUtils.readInt(bis);
|
||||||
String className = readString(bis, classLength);
|
String className = readString(bis, classLength);
|
||||||
|
|
||||||
BinaryClassObject bco = new BinaryClassObject();
|
BinaryClassObject bco = new BinaryClassObject();
|
||||||
bco.alias = alias.getBytes();
|
bco.alias = alias.getBytes();
|
||||||
bco.className = className;
|
bco.className = className;
|
||||||
|
bco.classHierarchyVersions = classHierarchyVersions;
|
||||||
|
|
||||||
int fields = ByteUtils.readInt(bis);
|
int fields = ByteUtils.readInt(bis);
|
||||||
bytes += (8 + aliasWidth + classLength);
|
bytes += (8 + aliasWidth + classLength);
|
||||||
@ -210,9 +257,9 @@ public final class BinaryImporter implements JmeImporter {
|
|||||||
Savable rVal = readObject(id);
|
Savable rVal = readObject(id);
|
||||||
if (debug) {
|
if (debug) {
|
||||||
logger.info("Importer Stats: ");
|
logger.info("Importer Stats: ");
|
||||||
logger.info("Tags: "+numClasses);
|
logger.log(Level.INFO, "Tags: {0}", numClasses);
|
||||||
logger.info("Objects: "+numLocs);
|
logger.log(Level.INFO, "Objects: {0}", numLocs);
|
||||||
logger.info("Data Size: "+dataArray.length);
|
logger.log(Level.INFO, "Data Size: {0}", dataArray.length);
|
||||||
}
|
}
|
||||||
dataArray = null;
|
dataArray = null;
|
||||||
return rVal;
|
return rVal;
|
||||||
@ -247,7 +294,8 @@ public final class BinaryImporter implements JmeImporter {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BinaryInputCapsule getCapsule(Savable id) {
|
@Override
|
||||||
|
public InputCapsule getCapsule(Savable id) {
|
||||||
return capsuleTable.get(id);
|
return capsuleTable.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,10 +339,10 @@ public final class BinaryImporter implements JmeImporter {
|
|||||||
int dataLength = ByteUtils.convertIntFromBytes(dataArray, loc);
|
int dataLength = ByteUtils.convertIntFromBytes(dataArray, loc);
|
||||||
loc+=4;
|
loc+=4;
|
||||||
|
|
||||||
BinaryInputCapsule cap = new BinaryInputCapsule(this, bco);
|
Savable out = SavableClassUtil.fromName(bco.className, loaders);
|
||||||
cap.setContent(dataArray, loc, loc+dataLength);
|
|
||||||
|
|
||||||
Savable out = SavableClassFinder.fromName(bco.className, cap, loaders);
|
BinaryInputCapsule cap = new BinaryInputCapsule(this, out, bco);
|
||||||
|
cap.setContent(dataArray, loc, loc+dataLength);
|
||||||
|
|
||||||
capsuleTable.put(out, cap);
|
capsuleTable.put(out, cap);
|
||||||
contentTable.put(id, out);
|
contentTable.put(id, out);
|
||||||
|
@ -39,7 +39,6 @@ import com.jme3.util.IntMap;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
@ -60,13 +59,15 @@ final class BinaryInputCapsule implements InputCapsule {
|
|||||||
|
|
||||||
protected BinaryImporter importer;
|
protected BinaryImporter importer;
|
||||||
protected BinaryClassObject cObj;
|
protected BinaryClassObject cObj;
|
||||||
|
protected Savable savable;
|
||||||
protected HashMap<Byte, Object> fieldData;
|
protected HashMap<Byte, Object> fieldData;
|
||||||
|
|
||||||
protected int index = 0;
|
protected int index = 0;
|
||||||
|
|
||||||
public BinaryInputCapsule(BinaryImporter importer, BinaryClassObject bco) {
|
public BinaryInputCapsule(BinaryImporter importer, Savable savable, BinaryClassObject bco) {
|
||||||
this.importer = importer;
|
this.importer = importer;
|
||||||
this.cObj = bco;
|
this.cObj = bco;
|
||||||
|
this.savable = savable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContent(byte[] content, int start, int limit) {
|
public void setContent(byte[] content, int start, int limit) {
|
||||||
@ -256,6 +257,26 @@ final class BinaryInputCapsule implements InputCapsule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSavableVersion(Class<? extends Savable> desiredClass){
|
||||||
|
Class thisClass = savable.getClass();
|
||||||
|
int count = 0;
|
||||||
|
while (thisClass != null && thisClass != desiredClass){
|
||||||
|
thisClass = thisClass.getSuperclass();
|
||||||
|
count ++;
|
||||||
|
}
|
||||||
|
if (thisClass == null){
|
||||||
|
throw new IllegalArgumentException(savable.getClass().getName() +
|
||||||
|
" does not extend " +
|
||||||
|
desiredClass.getName() + "!");
|
||||||
|
}else if (count > cObj.classHierarchyVersions.length){
|
||||||
|
throw new IllegalArgumentException(savable.getClass().getName() +
|
||||||
|
" cannot access version of " +
|
||||||
|
desiredClass.getName() +
|
||||||
|
" because it doesn't implement Savable");
|
||||||
|
}
|
||||||
|
return cObj.classHierarchyVersions[count];
|
||||||
|
}
|
||||||
|
|
||||||
public BitSet readBitSet(String name, BitSet defVal) throws IOException {
|
public BitSet readBitSet(String name, BitSet defVal) throws IOException {
|
||||||
BinaryClassField field = cObj.nameFields.get(name);
|
BinaryClassField field = cObj.nameFields.get(name);
|
||||||
if (field == null || !fieldData.containsKey(field.alias))
|
if (field == null || !fieldData.containsKey(field.alias))
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
|
||||||
* 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 'jMonkeyEngine' 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.jme3.export.binary;
|
|
||||||
|
|
||||||
import com.jme3.export.InputCapsule;
|
|
||||||
import com.jme3.export.Savable;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BinaryLoaderModule defines two methods, the first provides a key value to
|
|
||||||
* look for to issue the load command. This key is typically (and should be)
|
|
||||||
* the class name the loader is responsible for. While load handles creating
|
|
||||||
* a new instance of the class.
|
|
||||||
* @author mpowell
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
interface BinaryLoaderModule {
|
|
||||||
|
|
||||||
String getKey();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The inputCapsule parameter is not used at all.
|
|
||||||
*
|
|
||||||
* The DOMOutputStream class calls this method with a null parameter, so
|
|
||||||
* if you make use of the parameter, either handle null 'inputCapsule'
|
|
||||||
* or rearrange the class hierarchy to satisfy DOMOuptutStream.
|
|
||||||
*
|
|
||||||
* @param inputCapsule A value which is currently ignored by all
|
|
||||||
* implementation classes.
|
|
||||||
*/
|
|
||||||
Savable load(InputCapsule inputCapsule) throws IOException;
|
|
||||||
}
|
|
@ -39,7 +39,6 @@ import com.jme3.export.Savable;
|
|||||||
import com.jme3.renderer.RenderManager;
|
import com.jme3.renderer.RenderManager;
|
||||||
import com.jme3.renderer.ViewPort;
|
import com.jme3.renderer.ViewPort;
|
||||||
import com.jme3.scene.Mesh;
|
import com.jme3.scene.Mesh;
|
||||||
import com.jme3.scene.Node;
|
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
import com.jme3.scene.control.AbstractControl;
|
import com.jme3.scene.control.AbstractControl;
|
||||||
import com.jme3.scene.control.Control;
|
import com.jme3.scene.control.Control;
|
||||||
@ -68,7 +67,7 @@ import java.util.HashMap;
|
|||||||
*
|
*
|
||||||
* @author Kirill Vainer
|
* @author Kirill Vainer
|
||||||
*/
|
*/
|
||||||
public final class AnimControl extends AbstractControl implements Savable, Cloneable {
|
public final class AnimControl extends AbstractControl implements Cloneable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skeleton object must contain corresponding data for the targets' weight buffers.
|
* Skeleton object must contain corresponding data for the targets' weight buffers.
|
||||||
@ -351,16 +350,17 @@ public final class AnimControl extends AbstractControl implements Savable, Clone
|
|||||||
skeleton = (Skeleton) in.readSavable("skeleton", null);
|
skeleton = (Skeleton) in.readSavable("skeleton", null);
|
||||||
animationMap = (HashMap<String, BoneAnimation>) in.readStringSavableMap("animations", null);
|
animationMap = (HashMap<String, BoneAnimation>) in.readStringSavableMap("animations", null);
|
||||||
|
|
||||||
//changed for backward compatibility with j3o files generated before the AnimControl/SkeletonControl split
|
if (im.getFormatVersion() == 0){
|
||||||
//if we find a target mesh array the AnimControl creates the SkeletonControl for old files and add it to the spatial.
|
//changed for backward compatibility with j3o files generated before the AnimControl/SkeletonControl split
|
||||||
//When backward compatibility won't be needed anymore this can deleted
|
//if we find a target mesh array the AnimControl creates the SkeletonControl for old files and add it to the spatial.
|
||||||
Savable[] sav = in.readSavableArray("targets", null);
|
//When backward compatibility won't be needed anymore this can deleted
|
||||||
if (sav != null) {
|
Savable[] sav = in.readSavableArray("targets", null);
|
||||||
Mesh[] tg = null;
|
if (sav != null) {
|
||||||
tg = new Mesh[sav.length];
|
Mesh[] targets = new Mesh[sav.length];
|
||||||
System.arraycopy(sav, 0, tg, 0, sav.length);
|
System.arraycopy(sav, 0, targets, 0, sav.length);
|
||||||
skeletonControl = new SkeletonControl(tg, skeleton);
|
skeletonControl = new SkeletonControl(targets, skeleton);
|
||||||
spatial.addControl(skeletonControl);
|
spatial.addControl(skeletonControl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,27 +268,27 @@ public final class BoneTrack implements Savable {
|
|||||||
|
|
||||||
|
|
||||||
//Backward compatibility for old j3o files generated before revision 6807
|
//Backward compatibility for old j3o files generated before revision 6807
|
||||||
if (translations == null) {
|
if (im.getFormatVersion() == 0){
|
||||||
Savable[] sav = ic.readSavableArray("translations", null);
|
if (translations == null) {
|
||||||
if (sav != null) {
|
Savable[] sav = ic.readSavableArray("translations", null);
|
||||||
translations = new CompactVector3Array();
|
if (sav != null) {
|
||||||
Vector3f[] transCopy = new Vector3f[sav.length];
|
translations = new CompactVector3Array();
|
||||||
System.arraycopy(sav, 0, transCopy, 0, sav.length);
|
Vector3f[] transCopy = new Vector3f[sav.length];
|
||||||
translations.add(transCopy);
|
System.arraycopy(sav, 0, transCopy, 0, sav.length);
|
||||||
translations.freeze();
|
translations.add(transCopy);
|
||||||
|
translations.freeze();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rotations == null) {
|
||||||
|
Savable[] sav = ic.readSavableArray("rotations", null);
|
||||||
|
if (sav != null) {
|
||||||
|
rotations = new CompactQuaternionArray();
|
||||||
|
Quaternion[] rotCopy = new Quaternion[sav.length];
|
||||||
|
System.arraycopy(sav, 0, rotCopy, 0, sav.length);
|
||||||
|
rotations.add(rotCopy);
|
||||||
|
rotations.freeze();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rotations == null) {
|
|
||||||
Savable[] sav = ic.readSavableArray("rotations", null);
|
|
||||||
if (sav != null) {
|
|
||||||
rotations = new CompactQuaternionArray();
|
|
||||||
Quaternion[] rotCopy = new Quaternion[sav.length];
|
|
||||||
System.arraycopy(sav, 0, rotCopy, 0, sav.length);
|
|
||||||
rotations.add(rotCopy);
|
|
||||||
rotations.freeze();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import com.jme3.scene.Geometry;
|
|||||||
import com.jme3.scene.Mesh;
|
import com.jme3.scene.Mesh;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
|
import com.jme3.scene.UserData;
|
||||||
import com.jme3.scene.VertexBuffer;
|
import com.jme3.scene.VertexBuffer;
|
||||||
import com.jme3.scene.VertexBuffer.Type;
|
import com.jme3.scene.VertexBuffer.Type;
|
||||||
import com.jme3.scene.control.AbstractControl;
|
import com.jme3.scene.control.AbstractControl;
|
||||||
@ -25,14 +26,16 @@ import com.jme3.util.TempVars;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Skeleton control deforms a model according to a skeleton,
|
* The Skeleton control deforms a model according to a skeleton,
|
||||||
* It handles the computation of the deformtation matrices and performs the transformations on the mesh
|
* It handles the computation of the deformation matrices and performs
|
||||||
|
* the transformations on the mesh
|
||||||
*
|
*
|
||||||
* @author Rémy Bouquet Based on AnimControl by Kirill Vainer
|
* @author Rémy Bouquet Based on AnimControl by Kirill Vainer
|
||||||
*/
|
*/
|
||||||
public class SkeletonControl extends AbstractControl implements Savable, Cloneable {
|
public class SkeletonControl extends AbstractControl implements Cloneable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The skeleton of the model
|
* The skeleton of the model
|
||||||
@ -49,21 +52,90 @@ public class SkeletonControl extends AbstractControl implements Savable, Cloneab
|
|||||||
private boolean wasMeshUpdated = false;
|
private boolean wasMeshUpdated = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* for serialization only
|
* Serialization only. Do not use.
|
||||||
*/
|
*/
|
||||||
public SkeletonControl() {
|
public SkeletonControl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a skeleton control
|
* Creates a skeleton control.
|
||||||
* @param targets the meshes controled by the skeleton
|
* The list of targets will be acquired automatically when
|
||||||
|
* the control is attached to a node.
|
||||||
|
*
|
||||||
* @param skeleton the skeleton
|
* @param skeleton the skeleton
|
||||||
*/
|
*/
|
||||||
public SkeletonControl(Mesh[] targets, Skeleton skeleton) {
|
public SkeletonControl(Skeleton skeleton) {
|
||||||
|
this.skeleton = skeleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a skeleton control.
|
||||||
|
*
|
||||||
|
* @param targets the meshes controlled by the skeleton
|
||||||
|
* @param skeleton the skeleton
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public SkeletonControl(Mesh[] targets, Skeleton skeleton){
|
||||||
this.skeleton = skeleton;
|
this.skeleton = skeleton;
|
||||||
this.targets = targets;
|
this.targets = targets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isMeshAnimated(Mesh mesh){
|
||||||
|
return mesh.getBuffer(Type.BindPosePosition) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mesh[] findTargets(Node node){
|
||||||
|
Mesh sharedMesh = null;
|
||||||
|
ArrayList<Mesh> animatedMeshes = new ArrayList<Mesh>();
|
||||||
|
|
||||||
|
for (Spatial child : node.getChildren()){
|
||||||
|
if (!(child instanceof Geometry)){
|
||||||
|
continue; // could be an attachment node, ignore.
|
||||||
|
}
|
||||||
|
|
||||||
|
Geometry geom = (Geometry) child;
|
||||||
|
|
||||||
|
// is this geometry using a shared mesh?
|
||||||
|
Mesh childSharedMesh = geom.getUserData(UserData.JME_SHAREDMESH);
|
||||||
|
|
||||||
|
if (childSharedMesh != null){
|
||||||
|
|
||||||
|
// Don't bother with non-animated shared meshes
|
||||||
|
if (isMeshAnimated(childSharedMesh)){
|
||||||
|
|
||||||
|
// child is using shared mesh,
|
||||||
|
// so animate the shared mesh but ignore child
|
||||||
|
if (sharedMesh == null){
|
||||||
|
sharedMesh = childSharedMesh;
|
||||||
|
}else if (sharedMesh != childSharedMesh){
|
||||||
|
throw new IllegalStateException("Two conflicting shared meshes for " + node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Mesh mesh = geom.getMesh();
|
||||||
|
if (isMeshAnimated(mesh)){
|
||||||
|
animatedMeshes.add(mesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sharedMesh != null){
|
||||||
|
animatedMeshes.add(sharedMesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
return animatedMeshes.toArray(new Mesh[animatedMeshes.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpatial(Spatial spatial){
|
||||||
|
if (spatial != null){
|
||||||
|
Node node = (Node) spatial;
|
||||||
|
targets = findTargets(node);
|
||||||
|
}else{
|
||||||
|
targets = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
protected void controlRender(RenderManager rm, ViewPort vp) {
|
||||||
if (!wasMeshUpdated) {
|
if (!wasMeshUpdated) {
|
||||||
@ -87,13 +159,11 @@ public class SkeletonControl extends AbstractControl implements Savable, Cloneab
|
|||||||
@Override
|
@Override
|
||||||
protected void controlUpdate(float tpf) {
|
protected void controlUpdate(float tpf) {
|
||||||
wasMeshUpdated = false;
|
wasMeshUpdated = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetToBind() {
|
void resetToBind() {
|
||||||
for (int i = 0; i < targets.length; i++) {
|
for (Mesh mesh : targets){
|
||||||
Mesh mesh = targets[i];
|
if (isMeshAnimated(mesh)) {
|
||||||
if (targets[i].getBuffer(Type.BindPosePosition) != null) {
|
|
||||||
VertexBuffer bi = mesh.getBuffer(Type.BoneIndex);
|
VertexBuffer bi = mesh.getBuffer(Type.BoneIndex);
|
||||||
ByteBuffer bib = (ByteBuffer) bi.getData();
|
ByteBuffer bib = (ByteBuffer) bi.getData();
|
||||||
if (!bib.hasArray()) {
|
if (!bib.hasArray()) {
|
||||||
@ -177,12 +247,12 @@ public class SkeletonControl extends AbstractControl implements Savable, Cloneab
|
|||||||
* sets the skeleton for this control
|
* sets the skeleton for this control
|
||||||
* @param skeleton
|
* @param skeleton
|
||||||
*/
|
*/
|
||||||
public void setSkeleton(Skeleton skeleton) {
|
// public void setSkeleton(Skeleton skeleton) {
|
||||||
this.skeleton = skeleton;
|
// this.skeleton = skeleton;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* retuns the targets meshes of this ocntrol
|
* returns the targets meshes of this control
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Mesh[] getTargets() {
|
public Mesh[] getTargets() {
|
||||||
@ -193,9 +263,9 @@ public class SkeletonControl extends AbstractControl implements Savable, Cloneab
|
|||||||
* sets the target meshes of this control
|
* sets the target meshes of this control
|
||||||
* @param targets
|
* @param targets
|
||||||
*/
|
*/
|
||||||
public void setTargets(Mesh[] targets) {
|
// public void setTargets(Mesh[] targets) {
|
||||||
this.targets = targets;
|
// this.targets = targets;
|
||||||
}
|
// }
|
||||||
|
|
||||||
private void softwareSkinUpdate(Mesh mesh, Matrix4f[] offsetMatrices) {
|
private void softwareSkinUpdate(Mesh mesh, Matrix4f[] offsetMatrices) {
|
||||||
int maxWeightsPerVert = mesh.getMaxNumWeights();
|
int maxWeightsPerVert = mesh.getMaxNumWeights();
|
||||||
|
@ -61,7 +61,7 @@ import java.util.logging.Logger;
|
|||||||
*
|
*
|
||||||
* @author Nehon
|
* @author Nehon
|
||||||
*/
|
*/
|
||||||
public class Cinematic extends AbstractCinematicEvent implements Savable, AppState {
|
public class Cinematic extends AbstractCinematicEvent implements AppState {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(Application.class.getName());
|
private static final Logger logger = Logger.getLogger(Application.class.getName());
|
||||||
private String niftyXmlPath = null;
|
private String niftyXmlPath = null;
|
||||||
|
@ -48,7 +48,7 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author Nehon
|
* @author Nehon
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractCinematicEvent implements CinematicEvent, Savable {
|
public abstract class AbstractCinematicEvent implements CinematicEvent {
|
||||||
|
|
||||||
protected PlayState playState = PlayState.Stopped;
|
protected PlayState playState = PlayState.Stopped;
|
||||||
protected float speed = 1;
|
protected float speed = 1;
|
||||||
|
@ -35,12 +35,13 @@ import com.jme3.animation.LoopMode;
|
|||||||
import com.jme3.app.Application;
|
import com.jme3.app.Application;
|
||||||
import com.jme3.cinematic.Cinematic;
|
import com.jme3.cinematic.Cinematic;
|
||||||
import com.jme3.cinematic.PlayState;
|
import com.jme3.cinematic.PlayState;
|
||||||
|
import com.jme3.export.Savable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Nehon
|
* @author Nehon
|
||||||
*/
|
*/
|
||||||
public interface CinematicEvent {
|
public interface CinematicEvent extends Savable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the animation
|
* Starts the animation
|
||||||
|
@ -1118,23 +1118,25 @@ public class ParticleEmitter extends Geometry {
|
|||||||
|
|
||||||
particleInfluencer = (ParticleInfluencer) ic.readSavable("influencer", DEFAULT_INFLUENCER);
|
particleInfluencer = (ParticleInfluencer) ic.readSavable("influencer", DEFAULT_INFLUENCER);
|
||||||
|
|
||||||
// compatibility before the control inside particle emitter
|
if (im.getFormatVersion() == 0){
|
||||||
// was changed:
|
// compatibility before the control inside particle emitter
|
||||||
// find it in the controls and take it out, then add the proper one in
|
// was changed:
|
||||||
for (int i = 0; i < controls.size(); i++) {
|
// find it in the controls and take it out, then add the proper one in
|
||||||
Object obj = controls.get(i);
|
for (int i = 0; i < controls.size(); i++){
|
||||||
if (obj instanceof ParticleEmitter) {
|
Object obj = controls.get(i);
|
||||||
controls.remove(i);
|
if (obj instanceof ParticleEmitter){
|
||||||
// now add the proper one in
|
controls.remove(i);
|
||||||
controls.add(control);
|
// now add the proper one in
|
||||||
break;
|
controls.add(control);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// compatability before gravity was not a vector but a float
|
// compatability before gravity was not a vector but a float
|
||||||
if (gravity == null) {
|
if (gravity == null){
|
||||||
gravity = new Vector3f();
|
gravity = new Vector3f();
|
||||||
gravity.y = ic.readFloat("gravity", 0);
|
gravity.y = ic.readFloat("gravity", 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ public class DefaultParticleInfluencer implements ParticleInfluencer {
|
|||||||
@Override
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
InputCapsule ic = im.getCapsule(this);
|
InputCapsule ic = im.getCapsule(this);
|
||||||
startVelocity = (Vector3f) ic.readSavable("startVelocity", Vector3f.ZERO);
|
startVelocity = (Vector3f) ic.readSavable("startVelocity", Vector3f.ZERO.clone());
|
||||||
velocityVariation = ic.readFloat("variation", 0.2f);
|
velocityVariation = ic.readFloat("variation", 0.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.jme3.effect.shapes;
|
package com.jme3.effect.shapes;
|
||||||
|
|
||||||
|
import com.jme3.export.InputCapsule;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -141,11 +142,18 @@ public class EmitterMeshVertexShape implements EmitterShape {
|
|||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
OutputCapsule oc = ex.getCapsule(this);
|
OutputCapsule oc = ex.getCapsule(this);
|
||||||
oc.writeSavableArrayList((ArrayList<List<Vector3f>>) vertices, "vertices", null);
|
oc.writeSavableArrayList((ArrayList<List<Vector3f>>) vertices, "vertices", null);
|
||||||
|
oc.writeSavableArrayList((ArrayList<List<Vector3f>>) normals, "normals", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
this.vertices = im.getCapsule(this).readSavableArrayList("vertices", null);
|
InputCapsule ic = im.getCapsule(this);
|
||||||
|
this.vertices = ic.readSavableArrayList("vertices", null);
|
||||||
|
|
||||||
|
List<List<Vector3f>> tmpNormals = ic.readSavableArrayList("normals", null);
|
||||||
|
if (tmpNormals != null){
|
||||||
|
this.normals = tmpNormals;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,8 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public interface InputCapsule {
|
public interface InputCapsule {
|
||||||
|
|
||||||
|
public int getSavableVersion(Class<? extends Savable> clazz);
|
||||||
|
|
||||||
// byte primitive
|
// byte primitive
|
||||||
|
|
||||||
public byte readByte(String name, byte defVal) throws IOException;
|
public byte readByte(String name, byte defVal) throws IOException;
|
||||||
|
@ -38,4 +38,12 @@ import com.jme3.asset.AssetManager;
|
|||||||
public interface JmeImporter extends AssetLoader {
|
public interface JmeImporter extends AssetLoader {
|
||||||
public InputCapsule getCapsule(Savable id);
|
public InputCapsule getCapsule(Savable id);
|
||||||
public AssetManager getAssetManager();
|
public AssetManager getAssetManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the version number written in the header of the J3O/XML
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* @return Global version number for the file
|
||||||
|
*/
|
||||||
|
public int getFormatVersion();
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,8 @@ import java.io.IOException;
|
|||||||
/**
|
/**
|
||||||
* <code>Savable</code> is an interface for objects that can be serialized
|
* <code>Savable</code> is an interface for objects that can be serialized
|
||||||
* using jME's serialization system.
|
* using jME's serialization system.
|
||||||
* @author Dany
|
*
|
||||||
|
* @author Kirill Vainer
|
||||||
*/
|
*/
|
||||||
public interface Savable {
|
public interface Savable {
|
||||||
void write(JmeExporter ex) throws IOException;
|
void write(JmeExporter ex) throws IOException;
|
||||||
|
@ -41,23 +41,24 @@ import java.io.IOException;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import com.jme3.export.InputCapsule;
|
|
||||||
import com.jme3.export.Savable;
|
|
||||||
import com.jme3.material.MatParamTexture;
|
import com.jme3.material.MatParamTexture;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>SavableClassFinder</code> is used to find classes referenced
|
* <code>SavableClassUtil</code> contains various utilities to handle
|
||||||
* by savables.
|
* Savable classes. The methods are general enough to not be specific to any
|
||||||
|
* particular implementation.
|
||||||
* Currently it will remap any classes from old paths to new paths
|
* Currently it will remap any classes from old paths to new paths
|
||||||
* so that old J3O models can still be loaded.
|
* so that old J3O models can still be loaded.
|
||||||
*
|
*
|
||||||
* @author mpowell
|
* @author mpowell
|
||||||
* @author Kirill Vainer
|
* @author Kirill Vainer
|
||||||
*/
|
*/
|
||||||
public class SavableClassFinder {
|
public class SavableClassUtil {
|
||||||
|
|
||||||
private final static HashMap<String, String> classRemappings = new HashMap<String, String>();
|
private final static HashMap<String, String> classRemappings = new HashMap<String, String>();
|
||||||
|
|
||||||
@ -84,6 +85,31 @@ public class SavableClassFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isImplementingSavable(Class clazz){
|
||||||
|
Class[] interfaces = clazz.getInterfaces();
|
||||||
|
for (Class interfaceClass : interfaces){
|
||||||
|
if (interfaceClass == Savable.class){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getSavableVersion(Class<? extends Savable> clazz) throws IOException{
|
||||||
|
try {
|
||||||
|
Field field = clazz.getField("SAVABLE_VERSION");
|
||||||
|
return field.getInt(null);
|
||||||
|
} catch (IllegalAccessException ex) {
|
||||||
|
IOException ioEx = new IOException();
|
||||||
|
ioEx.initCause(ex);
|
||||||
|
throw ioEx;
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
throw ex; // can happen if SAVABLE_VERSION is not static
|
||||||
|
} catch (NoSuchFieldException ex) {
|
||||||
|
return 0; // not using versions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fromName creates a new Savable from the provided class name. First registered modules
|
* fromName creates a new Savable from the provided class name. First registered modules
|
||||||
* are checked to handle special cases, if the modules do not handle the class name, the
|
* are checked to handle special cases, if the modules do not handle the class name, the
|
||||||
@ -96,29 +122,29 @@ public class SavableClassFinder {
|
|||||||
* @throws ClassNotFoundException thrown if the class name is not in the classpath.
|
* @throws ClassNotFoundException thrown if the class name is not in the classpath.
|
||||||
* @throws IOException when loading ctor parameters fails
|
* @throws IOException when loading ctor parameters fails
|
||||||
*/
|
*/
|
||||||
public static Savable fromName(String className, InputCapsule inputCapsule) throws InstantiationException,
|
public static Savable fromName(String className) throws InstantiationException,
|
||||||
IllegalAccessException, ClassNotFoundException, IOException {
|
IllegalAccessException, ClassNotFoundException, IOException {
|
||||||
|
|
||||||
className = remapClass(className);
|
className = remapClass(className);
|
||||||
try {
|
try {
|
||||||
return (Savable) Class.forName(className).newInstance();
|
return (Savable) Class.forName(className).newInstance();
|
||||||
} catch (InstantiationException e) {
|
} catch (InstantiationException e) {
|
||||||
Logger.getLogger(SavableClassFinder.class.getName()).log(
|
Logger.getLogger(SavableClassUtil.class.getName()).log(
|
||||||
Level.SEVERE, "Could not access constructor of class ''{0}" + "''! \n"
|
Level.SEVERE, "Could not access constructor of class ''{0}" + "''! \n"
|
||||||
+ "Some types need to have the BinaryImporter set up in a special way. Please doublecheck the setup.", className);
|
+ "Some types need to have the BinaryImporter set up in a special way. Please doublecheck the setup.", className);
|
||||||
throw e;
|
throw e;
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
Logger.getLogger(SavableClassFinder.class.getName()).log(
|
Logger.getLogger(SavableClassUtil.class.getName()).log(
|
||||||
Level.SEVERE, "{0} \n"
|
Level.SEVERE, "{0} \n"
|
||||||
+ "Some types need to have the BinaryImporter set up in a special way. Please doublecheck the setup.", e.getMessage());
|
+ "Some types need to have the BinaryImporter set up in a special way. Please doublecheck the setup.", e.getMessage());
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Savable fromName(String className, InputCapsule inputCapsule, List<ClassLoader> loaders) throws InstantiationException,
|
public static Savable fromName(String className, List<ClassLoader> loaders) throws InstantiationException,
|
||||||
IllegalAccessException, ClassNotFoundException, IOException {
|
IllegalAccessException, ClassNotFoundException, IOException {
|
||||||
if (loaders == null) {
|
if (loaders == null) {
|
||||||
return fromName(className, inputCapsule);
|
return fromName(className);
|
||||||
}
|
}
|
||||||
|
|
||||||
String newClassName = remapClass(className);
|
String newClassName = remapClass(className);
|
||||||
@ -131,6 +157,6 @@ public class SavableClassFinder {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fromName(className, inputCapsule);
|
return fromName(className);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -53,6 +53,12 @@ public final class UserData implements Savable {
|
|||||||
*/
|
*/
|
||||||
public static final String JME_PHYSICSIGNORE = "JmePhysicsIgnore";
|
public static final String JME_PHYSICSIGNORE = "JmePhysicsIgnore";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For geometries using shared mesh, this will specify the shared
|
||||||
|
* mesh reference.
|
||||||
|
*/
|
||||||
|
public static final String JME_SHAREDMESH = "JmeSharedMesh";
|
||||||
|
|
||||||
protected byte type;
|
protected byte type;
|
||||||
protected Object value;
|
protected Object value;
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ import java.nio.IntBuffer;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* implements all writeXXXXArray methods to reduce boilerplate code
|
* implements all writeXXXXArray methods to reduce boilerplate code
|
||||||
* Geomap implementations are encourged to extend this class
|
* Geomap implementations are encouraged to extend this class
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractGeomap implements Geomap {
|
public abstract class AbstractGeomap implements Geomap {
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ public abstract class AbstractGeomap implements Geomap {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* Subclasses are encourged to provide a better implementation
|
* Subclasses are encouraged to provide a better implementation
|
||||||
* which directly accesses the data rather than using getHeight
|
* which directly accesses the data rather than using getHeight
|
||||||
*/
|
*/
|
||||||
public FloatBuffer writeVertexArray(FloatBuffer store, Vector3f scale, boolean center){
|
public FloatBuffer writeVertexArray(FloatBuffer store, Vector3f scale, boolean center){
|
||||||
|
@ -33,9 +33,8 @@
|
|||||||
package com.jme3.util;
|
package com.jme3.util;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -92,35 +91,48 @@ public final class ListMap<K, V> implements Map<K, V>, Cloneable, Serializable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ArrayList<ListMapEntry<K,V>> entries;
|
private final HashMap<K, V> backingMap;
|
||||||
|
private ListMapEntry<K, V>[] entries;
|
||||||
|
|
||||||
|
// private final ArrayList<ListMapEntry<K,V>> entries;
|
||||||
|
|
||||||
public ListMap(){
|
public ListMap(){
|
||||||
entries = new ArrayList<ListMapEntry<K,V>>();
|
entries = new ListMapEntry[4];
|
||||||
|
backingMap = new HashMap<K, V>(4);
|
||||||
|
// entries = new ArrayList<ListMapEntry<K,V>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListMap(int initialCapacity){
|
public ListMap(int initialCapacity){
|
||||||
entries = new ArrayList<ListMapEntry<K, V>>(initialCapacity);
|
entries = new ListMapEntry[initialCapacity];
|
||||||
|
backingMap = new HashMap<K, V>(initialCapacity);
|
||||||
|
// entries = new ArrayList<ListMapEntry<K, V>>(initialCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListMap(Map<? extends K, ? extends V> map){
|
public ListMap(Map<? extends K, ? extends V> map){
|
||||||
entries = new ArrayList<ListMapEntry<K, V>>(map.size());
|
entries = new ListMapEntry[map.size()];
|
||||||
|
backingMap = new HashMap<K, V>(map.size());
|
||||||
|
// entries = new ArrayList<ListMapEntry<K, V>>(map.size());
|
||||||
putAll(map);
|
putAll(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return entries.size();
|
// return entries.size();
|
||||||
|
return backingMap.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entry<K, V> getEntry(int index){
|
public Entry<K, V> getEntry(int index){
|
||||||
return entries.get(index);
|
// return entries.get(index);
|
||||||
|
return entries[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public V getValue(int index){
|
public V getValue(int index){
|
||||||
return entries.get(index).value;
|
// return entries.get(index).value;
|
||||||
|
return entries[index].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public K getKey(int index){
|
public K getKey(int index){
|
||||||
return entries.get(index).key;
|
// return entries.get(index).key;
|
||||||
|
return entries[index].key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
@ -130,93 +142,142 @@ public final class ListMap<K, V> implements Map<K, V>, Cloneable, Serializable {
|
|||||||
private static boolean keyEq(Object keyA, Object keyB){
|
private static boolean keyEq(Object keyA, Object keyB){
|
||||||
return keyA.hashCode() == keyB.hashCode() ? (keyA == keyB) || keyA.equals(keyB) : false;
|
return keyA.hashCode() == keyB.hashCode() ? (keyA == keyB) || keyA.equals(keyB) : false;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
private static boolean valEq(Object a, Object b){
|
// private static boolean valEq(Object a, Object b){
|
||||||
return a == null ? (b == null) : a.equals(b);
|
// return a == null ? (b == null) : a.equals(b);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public boolean containsKey(Object key) {
|
public boolean containsKey(Object key) {
|
||||||
if (key == null)
|
return backingMap.containsKey( (K) key);
|
||||||
throw new IllegalArgumentException();
|
// if (key == null)
|
||||||
|
// throw new IllegalArgumentException();
|
||||||
for (int i = 0; i < entries.size(); i++){
|
//
|
||||||
ListMapEntry<K,V> entry = entries.get(i);
|
// for (int i = 0; i < entries.size(); i++){
|
||||||
if (keyEq(entry.key, key))
|
// ListMapEntry<K,V> entry = entries.get(i);
|
||||||
return true;
|
// if (keyEq(entry.key, key))
|
||||||
}
|
// return true;
|
||||||
return false;
|
// }
|
||||||
|
// return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsValue(Object value) {
|
public boolean containsValue(Object value) {
|
||||||
for (int i = 0; i < entries.size(); i++){
|
return backingMap.containsValue( (V) value);
|
||||||
if (valEq(entries.get(i).value, value))
|
// for (int i = 0; i < entries.size(); i++){
|
||||||
return true;
|
// if (valEq(entries.get(i).value, value))
|
||||||
}
|
// return true;
|
||||||
return false;
|
// }
|
||||||
|
// return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public V get(Object key) {
|
public V get(Object key) {
|
||||||
if (key == null)
|
return backingMap.get( (K) key);
|
||||||
throw new IllegalArgumentException();
|
// if (key == null)
|
||||||
|
// throw new IllegalArgumentException();
|
||||||
for (int i = 0; i < entries.size(); i++){
|
//
|
||||||
ListMapEntry<K,V> entry = entries.get(i);
|
// for (int i = 0; i < entries.size(); i++){
|
||||||
if (keyEq(entry.key, key))
|
// ListMapEntry<K,V> entry = entries.get(i);
|
||||||
return entry.value;
|
// if (keyEq(entry.key, key))
|
||||||
}
|
// return entry.value;
|
||||||
return null;
|
// }
|
||||||
|
// return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public V put(K key, V value) {
|
public V put(K key, V value) {
|
||||||
if (key == null)
|
if (backingMap.containsKey(key)){
|
||||||
throw new IllegalArgumentException();
|
// set the value on the entry
|
||||||
|
int size = size();
|
||||||
// check if entry exists, if yes, overwrite it with new value
|
for (int i = 0; i < size; i++){
|
||||||
for (int i = 0; i < entries.size(); i++){
|
ListMapEntry<K, V> entry = entries[i];
|
||||||
ListMapEntry<K,V> entry = entries.get(i);
|
if (keyEq(entry.key, key)){
|
||||||
if (keyEq(entry.key, key)){
|
entry.value = value;
|
||||||
V prevValue = entry.value;
|
break;
|
||||||
entry.value = value;
|
}
|
||||||
return prevValue;
|
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
int size = size();
|
||||||
|
// expand list as necessary
|
||||||
|
if (size == entries.length){
|
||||||
|
ListMapEntry<K, V>[] tmpEntries = entries;
|
||||||
|
entries = new ListMapEntry[size * 2];
|
||||||
|
System.arraycopy(tmpEntries, 0, entries, 0, size);
|
||||||
|
}
|
||||||
|
entries[size] = new ListMapEntry<K, V>(key, value);
|
||||||
}
|
}
|
||||||
|
return backingMap.put(key, value);
|
||||||
// add a new entry
|
// if (key == null)
|
||||||
entries.add(new ListMapEntry<K, V>(key, value));
|
// throw new IllegalArgumentException();
|
||||||
return null;
|
//
|
||||||
|
// // check if entry exists, if yes, overwrite it with new value
|
||||||
|
// for (int i = 0; i < entries.size(); i++){
|
||||||
|
// ListMapEntry<K,V> entry = entries.get(i);
|
||||||
|
// if (keyEq(entry.key, key)){
|
||||||
|
// V prevValue = entry.value;
|
||||||
|
// entry.value = value;
|
||||||
|
// return prevValue;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // add a new entry
|
||||||
|
// entries.add(new ListMapEntry<K, V>(key, value));
|
||||||
|
// return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public V remove(Object key) {
|
public V remove(Object key) {
|
||||||
if (key == null)
|
V element = backingMap.remove( (K) key);
|
||||||
throw new IllegalArgumentException();
|
if (element != null){
|
||||||
|
// find removed element
|
||||||
|
int size = size() + 1; // includes removed element
|
||||||
|
int removedIndex = -1;
|
||||||
|
for (int i = 0; i < size; i++){
|
||||||
|
ListMapEntry<K, V> entry = entries[i];
|
||||||
|
if (keyEq(entry.key, key)){
|
||||||
|
removedIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert removedIndex >= 0;
|
||||||
|
|
||||||
for (int i = 0; i < entries.size(); i++){
|
size --;
|
||||||
ListMapEntry<K,V> entry = entries.get(i);
|
for (int i = removedIndex; i < size; i++){
|
||||||
if (keyEq(entry.key, key)){
|
entries[i] = entries[i+1];
|
||||||
return entries.remove(i).value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return element;
|
||||||
|
// if (key == null)
|
||||||
|
// throw new IllegalArgumentException();
|
||||||
|
//
|
||||||
|
// for (int i = 0; i < entries.size(); i++){
|
||||||
|
// ListMapEntry<K,V> entry = entries.get(i);
|
||||||
|
// if (keyEq(entry.key, key)){
|
||||||
|
// return entries.remove(i).value;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putAll(Map<? extends K, ? extends V> map) {
|
public void putAll(Map<? extends K, ? extends V> map) {
|
||||||
if (map instanceof ListMap){
|
for (Entry<? extends K, ? extends V> entry : map.entrySet()){
|
||||||
ListMap<K, V> listMap = (ListMap<K, V>) map;
|
put(entry.getKey(), entry.getValue());
|
||||||
ArrayList<ListMapEntry<K, V>> otherEntries = listMap.entries;
|
|
||||||
for (int i = 0; i < otherEntries.size(); i++){
|
|
||||||
ListMapEntry<K, V> entry = otherEntries.get(i);
|
|
||||||
put(entry.key, entry.value);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()){
|
|
||||||
put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if (map instanceof ListMap){
|
||||||
|
// ListMap<K, V> listMap = (ListMap<K, V>) map;
|
||||||
|
// ArrayList<ListMapEntry<K, V>> otherEntries = listMap.entries;
|
||||||
|
// for (int i = 0; i < otherEntries.size(); i++){
|
||||||
|
// ListMapEntry<K, V> entry = otherEntries.get(i);
|
||||||
|
// put(entry.key, entry.value);
|
||||||
|
// }
|
||||||
|
// }else{
|
||||||
|
// for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()){
|
||||||
|
// put(entry.getKey(), entry.getValue());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
entries.clear();
|
backingMap.clear();
|
||||||
|
// entries.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -227,27 +288,30 @@ public final class ListMap<K, V> implements Map<K, V>, Cloneable, Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Set<K> keySet() {
|
public Set<K> keySet() {
|
||||||
HashSet<K> keys = new HashSet<K>();
|
return backingMap.keySet();
|
||||||
for (int i = 0; i < entries.size(); i++){
|
// HashSet<K> keys = new HashSet<K>();
|
||||||
ListMapEntry<K,V> entry = entries.get(i);
|
// for (int i = 0; i < entries.size(); i++){
|
||||||
keys.add(entry.key);
|
// ListMapEntry<K,V> entry = entries.get(i);
|
||||||
}
|
// keys.add(entry.key);
|
||||||
return keys;
|
// }
|
||||||
|
// return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<V> values() {
|
public Collection<V> values() {
|
||||||
ArrayList<V> values = new ArrayList<V>();
|
return backingMap.values();
|
||||||
for (int i = 0; i < entries.size(); i++){
|
// ArrayList<V> values = new ArrayList<V>();
|
||||||
ListMapEntry<K,V> entry = entries.get(i);
|
// for (int i = 0; i < entries.size(); i++){
|
||||||
values.add(entry.value);
|
// ListMapEntry<K,V> entry = entries.get(i);
|
||||||
}
|
// values.add(entry.value);
|
||||||
return values;
|
// }
|
||||||
|
// return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Entry<K, V>> entrySet() {
|
public Set<Entry<K, V>> entrySet() {
|
||||||
HashSet<Entry<K, V>> entryset = new HashSet<Entry<K, V>>();
|
return backingMap.entrySet();
|
||||||
entryset.addAll(entries);
|
// HashSet<Entry<K, V>> entryset = new HashSet<Entry<K, V>>();
|
||||||
return entryset;
|
// entryset.addAll(entries);
|
||||||
|
// return entryset;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ import com.jme3.scene.Geometry;
|
|||||||
import com.jme3.scene.Mesh;
|
import com.jme3.scene.Mesh;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
import com.jme3.scene.Spatial.CullHint;
|
import com.jme3.scene.Spatial.CullHint;
|
||||||
|
import com.jme3.scene.UserData;
|
||||||
import com.jme3.scene.VertexBuffer;
|
import com.jme3.scene.VertexBuffer;
|
||||||
import com.jme3.scene.VertexBuffer.Format;
|
import com.jme3.scene.VertexBuffer.Format;
|
||||||
import com.jme3.scene.VertexBuffer.Type;
|
import com.jme3.scene.VertexBuffer.Type;
|
||||||
@ -101,27 +102,29 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
private String folderName;
|
private String folderName;
|
||||||
private AssetManager assetManager;
|
private AssetManager assetManager;
|
||||||
private MaterialList materialList;
|
private MaterialList materialList;
|
||||||
|
|
||||||
|
// Data per submesh/sharedgeom
|
||||||
private ShortBuffer sb;
|
private ShortBuffer sb;
|
||||||
private IntBuffer ib;
|
private IntBuffer ib;
|
||||||
private FloatBuffer fb;
|
private FloatBuffer fb;
|
||||||
private VertexBuffer vb;
|
private VertexBuffer vb;
|
||||||
private Mesh mesh;
|
private Mesh mesh;
|
||||||
private Geometry geom;
|
private Geometry geom;
|
||||||
private Mesh sharedmesh;
|
|
||||||
private Geometry sharedgeom;
|
|
||||||
private int geomIdx = 0;
|
|
||||||
private int texCoordIdx = 0;
|
|
||||||
private static volatile int nodeIdx = 0;
|
|
||||||
private String ignoreUntilEnd = null;
|
|
||||||
private boolean bigindices = false;
|
|
||||||
private int vertCount;
|
|
||||||
private int triCount;
|
|
||||||
private List<Geometry> geoms = new ArrayList<Geometry>();
|
|
||||||
private List<Boolean> usesSharedGeom = new ArrayList<Boolean>();
|
|
||||||
private IntMap<List<VertexBuffer>> lodLevels = new IntMap<List<VertexBuffer>>();
|
|
||||||
private AnimData animData;
|
|
||||||
private ByteBuffer indicesData;
|
private ByteBuffer indicesData;
|
||||||
private FloatBuffer weightsFloatData;
|
private FloatBuffer weightsFloatData;
|
||||||
|
private int vertCount;
|
||||||
|
private boolean usesSharedVerts;
|
||||||
|
private boolean usesBigIndices;
|
||||||
|
|
||||||
|
// Global data
|
||||||
|
private Mesh sharedMesh;
|
||||||
|
private int meshIndex = 0;
|
||||||
|
private int texCoordIndex = 0;
|
||||||
|
private String ignoreUntilEnd = null;
|
||||||
|
|
||||||
|
private List<Geometry> geoms = new ArrayList<Geometry>();
|
||||||
|
private IntMap<List<VertexBuffer>> lodLevels = new IntMap<List<VertexBuffer>>();
|
||||||
|
private AnimData animData;
|
||||||
|
|
||||||
public MeshLoader() {
|
public MeshLoader() {
|
||||||
super();
|
super();
|
||||||
@ -130,7 +133,6 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
@Override
|
@Override
|
||||||
public void startDocument() {
|
public void startDocument() {
|
||||||
geoms.clear();
|
geoms.clear();
|
||||||
usesSharedGeom.clear();
|
|
||||||
lodLevels.clear();
|
lodLevels.clear();
|
||||||
|
|
||||||
sb = null;
|
sb = null;
|
||||||
@ -139,14 +141,12 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
vb = null;
|
vb = null;
|
||||||
mesh = null;
|
mesh = null;
|
||||||
geom = null;
|
geom = null;
|
||||||
sharedgeom = null;
|
sharedMesh = null;
|
||||||
sharedmesh = null;
|
|
||||||
|
|
||||||
|
usesSharedVerts = false;
|
||||||
vertCount = 0;
|
vertCount = 0;
|
||||||
triCount = 0;
|
meshIndex = 0;
|
||||||
geomIdx = 0;
|
texCoordIndex = 0;
|
||||||
texCoordIdx = 0;
|
|
||||||
nodeIdx = 0;
|
|
||||||
ignoreUntilEnd = null;
|
ignoreUntilEnd = null;
|
||||||
|
|
||||||
animData = null;
|
animData = null;
|
||||||
@ -172,27 +172,22 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isUsingSharedVerts(Geometry geom){
|
||||||
|
return geom.getUserData(UserData.JME_SHAREDMESH) != null;
|
||||||
|
}
|
||||||
|
|
||||||
private void startFaces(String count) throws SAXException {
|
private void startFaces(String count) throws SAXException {
|
||||||
int numFaces = parseInt(count);
|
int numFaces = parseInt(count);
|
||||||
int numIndices;
|
int numIndices;
|
||||||
|
|
||||||
if (mesh.getMode() == Mesh.Mode.Triangles) {
|
if (mesh.getMode() == Mesh.Mode.Triangles) {
|
||||||
//mesh.setTriangleCount(numFaces);
|
|
||||||
numIndices = numFaces * 3;
|
numIndices = numFaces * 3;
|
||||||
} else {
|
} else {
|
||||||
throw new SAXException("Triangle strip or fan not supported!");
|
throw new SAXException("Triangle strip or fan not supported!");
|
||||||
}
|
}
|
||||||
|
|
||||||
int numVerts;
|
|
||||||
if (usesSharedGeom.size() > 0 && usesSharedGeom.get(geoms.size() - 1)) {
|
|
||||||
// sharedgeom.getMesh().updateCounts();
|
|
||||||
numVerts = sharedmesh.getVertexCount();
|
|
||||||
} else {
|
|
||||||
// mesh.updateCounts();
|
|
||||||
numVerts = mesh.getVertexCount();
|
|
||||||
}
|
|
||||||
vb = new VertexBuffer(VertexBuffer.Type.Index);
|
vb = new VertexBuffer(VertexBuffer.Type.Index);
|
||||||
if (!bigindices) {
|
if (!usesBigIndices) {
|
||||||
sb = BufferUtils.createShortBuffer(numIndices);
|
sb = BufferUtils.createShortBuffer(numIndices);
|
||||||
ib = null;
|
ib = null;
|
||||||
vb.setupData(Usage.Static, 3, Format.UnsignedShort, sb);
|
vb.setupData(Usage.Static, 3, Format.UnsignedShort, sb);
|
||||||
@ -226,16 +221,11 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
if (mat.isTransparent()) {
|
if (mat.isTransparent()) {
|
||||||
geom.setQueueBucket(Bucket.Transparent);
|
geom.setQueueBucket(Bucket.Transparent);
|
||||||
}
|
}
|
||||||
// else
|
|
||||||
// geom.setShadowMode(ShadowMode.CastAndReceive);
|
|
||||||
|
|
||||||
// if (mat.isReceivesShadows())
|
|
||||||
|
|
||||||
|
|
||||||
geom.setMaterial(mat);
|
geom.setMaterial(mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startMesh(String matName, String usesharedvertices, String use32bitIndices, String opType) throws SAXException {
|
private void startSubMesh(String matName, String usesharedvertices, String use32bitIndices, String opType) throws SAXException {
|
||||||
mesh = new Mesh();
|
mesh = new Mesh();
|
||||||
if (opType == null || opType.equals("triangle_list")) {
|
if (opType == null || opType.equals("triangle_list")) {
|
||||||
mesh.setMode(Mesh.Mode.Triangles);
|
mesh.setMode(Mesh.Mode.Triangles);
|
||||||
@ -245,24 +235,25 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
mesh.setMode(Mesh.Mode.TriangleFan);
|
mesh.setMode(Mesh.Mode.TriangleFan);
|
||||||
}
|
}
|
||||||
|
|
||||||
bigindices = parseBool(use32bitIndices, false);
|
usesBigIndices = parseBool(use32bitIndices, false);
|
||||||
boolean sharedverts = parseBool(usesharedvertices, false);
|
usesSharedVerts = parseBool(usesharedvertices, false);
|
||||||
if (sharedverts) {
|
if (usesSharedVerts) {
|
||||||
usesSharedGeom.add(true);
|
|
||||||
// import vertexbuffers from shared geom
|
// import vertexbuffers from shared geom
|
||||||
IntMap<VertexBuffer> sharedBufs = sharedmesh.getBuffers();
|
IntMap<VertexBuffer> sharedBufs = sharedMesh.getBuffers();
|
||||||
for (Entry<VertexBuffer> entry : sharedBufs) {
|
for (Entry<VertexBuffer> entry : sharedBufs) {
|
||||||
mesh.setBuffer(entry.getValue());
|
mesh.setBuffer(entry.getValue());
|
||||||
}
|
}
|
||||||
// this mesh is shared!
|
|
||||||
} else {
|
|
||||||
usesSharedGeom.add(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (meshName == null) {
|
if (meshName == null) {
|
||||||
geom = new Geometry("OgreSubmesh-" + (++geomIdx), mesh);
|
geom = new Geometry("OgreSubmesh-" + (++meshIndex), mesh);
|
||||||
} else {
|
} else {
|
||||||
geom = new Geometry(meshName + "-geom-" + (++geomIdx), mesh);
|
geom = new Geometry(meshName + "-geom-" + (++meshIndex), mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usesSharedVerts){
|
||||||
|
// this mesh is shared!
|
||||||
|
geom.setUserData(UserData.JME_SHAREDMESH, sharedMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyMaterial(geom, matName);
|
applyMaterial(geom, matName);
|
||||||
@ -270,27 +261,16 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startSharedGeom(String vertexcount) throws SAXException {
|
private void startSharedGeom(String vertexcount) throws SAXException {
|
||||||
sharedmesh = new Mesh();
|
sharedMesh = new Mesh();
|
||||||
vertCount = parseInt(vertexcount);
|
vertCount = parseInt(vertexcount);
|
||||||
// sharedmesh.setVertexCount(vertCount);
|
usesSharedVerts = false;
|
||||||
|
|
||||||
if (meshName == null) {
|
geom = null;
|
||||||
sharedgeom = new Geometry("Ogre-SharedGeom", sharedmesh);
|
mesh = sharedMesh;
|
||||||
} else {
|
|
||||||
sharedgeom = new Geometry(meshName + "-sharedgeom", sharedmesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
sharedgeom.setCullHint(CullHint.Always);
|
|
||||||
geoms.add(sharedgeom);
|
|
||||||
usesSharedGeom.add(false); // shared geometry doesnt use shared geometry (?)
|
|
||||||
|
|
||||||
geom = sharedgeom;
|
|
||||||
mesh = sharedmesh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startGeometry(String vertexcount) throws SAXException {
|
private void startGeometry(String vertexcount) throws SAXException {
|
||||||
vertCount = parseInt(vertexcount);
|
vertCount = parseInt(vertexcount);
|
||||||
// mesh.setVertexCount(vertCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -298,7 +278,7 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
* for all vertices in the buffer.
|
* for all vertices in the buffer.
|
||||||
*/
|
*/
|
||||||
private void endBoneAssigns() {
|
private void endBoneAssigns() {
|
||||||
if (mesh != sharedmesh && usesSharedGeom.get(geoms.size() - 1)) {
|
if (mesh != sharedMesh && isUsingSharedVerts(geom)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,7 +321,7 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startBoneAssigns() {
|
private void startBoneAssigns() {
|
||||||
if (mesh != sharedmesh && usesSharedGeom.get(geoms.size() - 1)) {
|
if (mesh != sharedMesh && usesSharedVerts) {
|
||||||
// will use bone assignments from shared mesh (?)
|
// will use bone assignments from shared mesh (?)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -424,7 +404,7 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startVertex() {
|
private void startVertex() {
|
||||||
texCoordIdx = 0;
|
texCoordIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pushAttrib(Type type, Attributes attribs) throws SAXException {
|
private void pushAttrib(Type type, Attributes attribs) throws SAXException {
|
||||||
@ -450,10 +430,10 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void pushTexCoord(Attributes attribs) throws SAXException {
|
private void pushTexCoord(Attributes attribs) throws SAXException {
|
||||||
if (texCoordIdx >= 8) {
|
if (texCoordIndex >= 8) {
|
||||||
return; // More than 8 not supported by ogre.
|
return; // More than 8 not supported by ogre.
|
||||||
}
|
}
|
||||||
Type type = TEXCOORD_TYPES[texCoordIdx];
|
Type type = TEXCOORD_TYPES[texCoordIndex];
|
||||||
|
|
||||||
VertexBuffer tcvb = mesh.getBuffer(type);
|
VertexBuffer tcvb = mesh.getBuffer(type);
|
||||||
FloatBuffer buf = (FloatBuffer) tcvb.getData();
|
FloatBuffer buf = (FloatBuffer) tcvb.getData();
|
||||||
@ -469,7 +449,7 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
texCoordIdx++;
|
texCoordIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pushColor(Attributes attribs) throws SAXException {
|
private void pushColor(Attributes attribs) throws SAXException {
|
||||||
@ -529,7 +509,6 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startLodGenerated(String depthsqr) {
|
private void startLodGenerated(String depthsqr) {
|
||||||
// dist = Float.parseFloat(depthsqr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pushBoneAssign(String vertIndex, String boneIndex, String weight) throws SAXException {
|
private void pushBoneAssign(String vertIndex, String boneIndex, String weight) throws SAXException {
|
||||||
@ -560,10 +539,6 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
|
|
||||||
private void startSkeleton(String name) {
|
private void startSkeleton(String name) {
|
||||||
animData = (AnimData) assetManager.loadAsset(folderName + name + ".xml");
|
animData = (AnimData) assetManager.loadAsset(folderName + name + ".xml");
|
||||||
//TODO:workaround for meshxml / mesh.xml
|
|
||||||
if (animData == null) {
|
|
||||||
animData = (AnimData) assetManager.loadAsset(folderName + name + "xml");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startSubmeshName(String indexStr, String nameStr) {
|
private void startSubmeshName(String indexStr, String nameStr) {
|
||||||
@ -620,7 +595,7 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
} else if (qName.equals("boneassignments")) {
|
} else if (qName.equals("boneassignments")) {
|
||||||
startBoneAssigns();
|
startBoneAssigns();
|
||||||
} else if (qName.equals("submesh")) {
|
} else if (qName.equals("submesh")) {
|
||||||
startMesh(attribs.getValue("material"),
|
startSubMesh(attribs.getValue("material"),
|
||||||
attribs.getValue("usesharedvertices"),
|
attribs.getValue("usesharedvertices"),
|
||||||
attribs.getValue("use32bitindexes"),
|
attribs.getValue("use32bitindexes"),
|
||||||
attribs.getValue("operationtype"));
|
attribs.getValue("operationtype"));
|
||||||
@ -653,18 +628,18 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
if (ignoreUntilEnd.equals(qName)) {
|
if (ignoreUntilEnd.equals(qName)) {
|
||||||
ignoreUntilEnd = null;
|
ignoreUntilEnd = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qName.equals("submesh")) {
|
if (qName.equals("submesh")) {
|
||||||
bigindices = false;
|
usesBigIndices = false;
|
||||||
geom = null;
|
geom = null;
|
||||||
mesh = null;
|
mesh = null;
|
||||||
} else if (qName.equals("submeshes")) {
|
} else if (qName.equals("submeshes")) {
|
||||||
// IMPORTANT: restore sharedgeoemtry, for use with shared boneweights
|
// IMPORTANT: restore sharedmesh, for use with shared boneweights
|
||||||
geom = sharedgeom;
|
geom = null;
|
||||||
mesh = sharedmesh;
|
mesh = sharedMesh;
|
||||||
|
usesSharedVerts = false;
|
||||||
} else if (qName.equals("faces")) {
|
} else if (qName.equals("faces")) {
|
||||||
if (ib != null) {
|
if (ib != null) {
|
||||||
ib.flip();
|
ib.flip();
|
||||||
@ -711,56 +686,64 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Node compileModel() {
|
private Node compileModel() {
|
||||||
String nodeName;
|
Node model = new Node(meshName + "-ogremesh");
|
||||||
if (meshName == null) {
|
|
||||||
nodeName = "OgreMesh" + (++nodeIdx);
|
for (int i = 0; i < geoms.size(); i++) {
|
||||||
} else {
|
Geometry g = geoms.get(i);
|
||||||
nodeName = meshName + "-ogremesh";
|
Mesh m = g.getMesh();
|
||||||
|
if (sharedMesh != null && isUsingSharedVerts(geom)) {
|
||||||
|
m.setBound(sharedMesh.getBound().clone());
|
||||||
|
}
|
||||||
|
model.attachChild(geoms.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
Node model = new Node(nodeName);
|
// Do not attach shared geometry to the node!
|
||||||
if (animData != null) {
|
|
||||||
ArrayList<Mesh> newMeshes = new ArrayList<Mesh>(geoms.size());
|
|
||||||
|
|
||||||
// generate bind pose for mesh and add to skin-list
|
if (animData != null) {
|
||||||
|
// This model uses animation
|
||||||
|
|
||||||
|
// generate bind pose for mesh
|
||||||
// ONLY if not using shared geometry
|
// ONLY if not using shared geometry
|
||||||
// This includes the shared geoemtry itself actually
|
// This includes the shared geoemtry itself actually
|
||||||
|
if (sharedMesh != null){
|
||||||
|
sharedMesh.generateBindPose(!HARDWARE_SKINNING);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < geoms.size(); i++) {
|
for (int i = 0; i < geoms.size(); i++) {
|
||||||
Geometry g = geoms.get(i);
|
Geometry g = geoms.get(i);
|
||||||
Mesh m = geoms.get(i).getMesh();
|
Mesh m = geoms.get(i).getMesh();
|
||||||
boolean useShared = usesSharedGeom.get(i);
|
boolean useShared = isUsingSharedVerts(g);
|
||||||
// create bind pose
|
|
||||||
|
|
||||||
if (!useShared) {
|
if (!useShared) {
|
||||||
|
// create bind pose
|
||||||
m.generateBindPose(!HARDWARE_SKINNING);
|
m.generateBindPose(!HARDWARE_SKINNING);
|
||||||
newMeshes.add(m);
|
// } else {
|
||||||
} else {
|
// Inherit animation data from shared mesh
|
||||||
VertexBuffer bindPos = sharedmesh.getBuffer(Type.BindPosePosition);
|
// VertexBuffer bindPos = sharedMesh.getBuffer(Type.BindPosePosition);
|
||||||
VertexBuffer bindNorm = sharedmesh.getBuffer(Type.BindPoseNormal);
|
// VertexBuffer bindNorm = sharedMesh.getBuffer(Type.BindPoseNormal);
|
||||||
VertexBuffer boneIndex = sharedmesh.getBuffer(Type.BoneIndex);
|
// VertexBuffer boneIndex = sharedMesh.getBuffer(Type.BoneIndex);
|
||||||
VertexBuffer boneWeight = sharedmesh.getBuffer(Type.BoneWeight);
|
// VertexBuffer boneWeight = sharedMesh.getBuffer(Type.BoneWeight);
|
||||||
|
//
|
||||||
if (bindPos != null) {
|
// if (bindPos != null) {
|
||||||
m.setBuffer(bindPos);
|
// m.setBuffer(bindPos);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (bindNorm != null) {
|
// if (bindNorm != null) {
|
||||||
m.setBuffer(bindNorm);
|
// m.setBuffer(bindNorm);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (boneIndex != null) {
|
// if (boneIndex != null) {
|
||||||
m.setBuffer(boneIndex);
|
// m.setBuffer(boneIndex);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (boneWeight != null) {
|
// if (boneWeight != null) {
|
||||||
m.setBuffer(boneWeight);
|
// m.setBuffer(boneWeight);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Mesh[] meshes = new Mesh[newMeshes.size()];
|
|
||||||
for (int i = 0; i < meshes.length; i++) {
|
|
||||||
meshes[i] = newMeshes.get(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Put the animations in the AnimControl
|
||||||
HashMap<String, BoneAnimation> anims = new HashMap<String, BoneAnimation>();
|
HashMap<String, BoneAnimation> anims = new HashMap<String, BoneAnimation>();
|
||||||
ArrayList<BoneAnimation> animList = animData.anims;
|
ArrayList<BoneAnimation> animList = animData.anims;
|
||||||
for (int i = 0; i < animList.size(); i++) {
|
for (int i = 0; i < animList.size(); i++) {
|
||||||
@ -768,21 +751,15 @@ public class MeshLoader extends DefaultHandler implements AssetLoader {
|
|||||||
anims.put(anim.getName(), anim);
|
anims.put(anim.getName(), anim);
|
||||||
}
|
}
|
||||||
|
|
||||||
//AnimControl ctrl = new AnimControl(model, meshes, animData.skeleton);
|
|
||||||
AnimControl ctrl = new AnimControl(animData.skeleton);
|
AnimControl ctrl = new AnimControl(animData.skeleton);
|
||||||
ctrl.setAnimations(anims);
|
ctrl.setAnimations(anims);
|
||||||
model.addControl(ctrl);
|
model.addControl(ctrl);
|
||||||
SkeletonControl skeletonControl = new SkeletonControl(meshes, animData.skeleton);
|
|
||||||
model.addControl(skeletonControl);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < geoms.size(); i++) {
|
// Put the skeleton in the skeleton control
|
||||||
Geometry g = geoms.get(i);
|
SkeletonControl skeletonControl = new SkeletonControl(animData.skeleton);
|
||||||
Mesh m = g.getMesh();
|
|
||||||
if (sharedmesh != null && usesSharedGeom.get(i)) {
|
// This will acquire the targets from the node
|
||||||
m.setBound(sharedmesh.getBound().clone());
|
model.addControl(skeletonControl);
|
||||||
}
|
|
||||||
model.attachChild(geoms.get(i));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
|
@ -270,7 +270,7 @@ public class TestHoveringTank extends SimpleApplication implements AnalogListene
|
|||||||
rock.setWrap(WrapMode.Repeat);
|
rock.setWrap(WrapMode.Repeat);
|
||||||
matRock.setTexture("DiffuseMap_2", rock);
|
matRock.setTexture("DiffuseMap_2", rock);
|
||||||
matRock.setFloat("DiffuseMap_2_scale", 128);
|
matRock.setFloat("DiffuseMap_2_scale", 128);
|
||||||
Texture normalMap0 = assetManager.loadTexture("Textures/Terrain/splat/grass_normal.png");
|
Texture normalMap0 = assetManager.loadTexture("Textures/Terrain/splat/grass_normal.jpg");
|
||||||
normalMap0.setWrap(WrapMode.Repeat);
|
normalMap0.setWrap(WrapMode.Repeat);
|
||||||
Texture normalMap1 = assetManager.loadTexture("Textures/Terrain/splat/dirt_normal.png");
|
Texture normalMap1 = assetManager.loadTexture("Textures/Terrain/splat/dirt_normal.png");
|
||||||
normalMap1.setWrap(WrapMode.Repeat);
|
normalMap1.setWrap(WrapMode.Repeat);
|
||||||
|
@ -34,7 +34,7 @@ package com.jme3.export.xml;
|
|||||||
|
|
||||||
import com.jme3.export.InputCapsule;
|
import com.jme3.export.InputCapsule;
|
||||||
import com.jme3.export.Savable;
|
import com.jme3.export.Savable;
|
||||||
import com.jme3.export.SavableClassFinder;
|
import com.jme3.export.SavableClassUtil;
|
||||||
import com.jme3.util.BufferUtils;
|
import com.jme3.util.BufferUtils;
|
||||||
import com.jme3.util.IntMap;
|
import com.jme3.util.IntMap;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -78,6 +78,10 @@ public class DOMInputCapsule implements InputCapsule {
|
|||||||
currentElem = doc.getDocumentElement();
|
currentElem = doc.getDocumentElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSavableVersion(Class<? extends Savable> clazz) {
|
||||||
|
return 0; // TODO: figure this out ...
|
||||||
|
}
|
||||||
|
|
||||||
private static String decodeString(String s) {
|
private static String decodeString(String s) {
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -973,7 +977,7 @@ public class DOMInputCapsule implements InputCapsule {
|
|||||||
} else if (currentElem.hasAttribute("class")) {
|
} else if (currentElem.hasAttribute("class")) {
|
||||||
className = currentElem.getAttribute("class");
|
className = currentElem.getAttribute("class");
|
||||||
}
|
}
|
||||||
tmp = SavableClassFinder.fromName(className, null);
|
tmp = SavableClassUtil.fromName(className, null);
|
||||||
String refID = currentElem.getAttribute("reference_ID");
|
String refID = currentElem.getAttribute("reference_ID");
|
||||||
if (refID.length() < 1) refID = currentElem.getAttribute("id");
|
if (refID.length() < 1) refID = currentElem.getAttribute("id");
|
||||||
if (refID.length() > 0) referencedSavables.put(refID, tmp);
|
if (refID.length() > 0) referencedSavables.put(refID, tmp);
|
||||||
|
@ -52,11 +52,15 @@ public class XMLImporter implements JmeImporter {
|
|||||||
|
|
||||||
private AssetManager assetManager;
|
private AssetManager assetManager;
|
||||||
private DOMInputCapsule domIn;
|
private DOMInputCapsule domIn;
|
||||||
// A single-load-state base URI for texture-loading.
|
|
||||||
|
|
||||||
public XMLImporter() {
|
public XMLImporter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: .......
|
||||||
|
public int getFormatVersion() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public AssetManager getAssetManager(){
|
public AssetManager getAssetManager(){
|
||||||
return assetManager;
|
return assetManager;
|
||||||
}
|
}
|
||||||
@ -73,10 +77,7 @@ public class XMLImporter implements JmeImporter {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized public Savable load(InputStream f) throws IOException {
|
public Savable load(InputStream f) throws IOException {
|
||||||
/* Leave this method synchronized. Calling this method from more than
|
|
||||||
* one thread at a time for the same XMLImporter instance will clobber
|
|
||||||
* the XML Document instantiated here. */
|
|
||||||
try {
|
try {
|
||||||
domIn = new DOMInputCapsule(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(f), this);
|
domIn = new DOMInputCapsule(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(f), this);
|
||||||
return domIn.readSavable(null, null);
|
return domIn.readSavable(null, null);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user