* Javadocs for com.jme3.material
* Formatted the blender loader files according to NetBeans * Removed any "I" prefixes on interfaces * Small javadoc fixes git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7592 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
d03683deca
commit
95cdde7f53
File diff suppressed because it is too large
Load Diff
@ -72,122 +72,123 @@ import com.jme3.scene.plugins.blender.utils.JmeConverter;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class BlenderLoader implements AssetLoader {
|
public class BlenderLoader implements AssetLoader {
|
||||||
private static final Logger LOGGER = Logger.getLogger(BlenderLoader.class.getName());
|
|
||||||
|
|
||||||
@Override
|
private static final Logger LOGGER = Logger.getLogger(BlenderLoader.class.getName());
|
||||||
public LoadingResults load(AssetInfo assetInfo) throws IOException {
|
|
||||||
try {
|
|
||||||
//registering loaders
|
|
||||||
ModelKey modelKey = (ModelKey)assetInfo.getKey();
|
|
||||||
BlenderKey blenderKey;
|
|
||||||
if(modelKey instanceof BlenderKey) {
|
|
||||||
blenderKey = (BlenderKey)modelKey;
|
|
||||||
} else {
|
|
||||||
blenderKey = new BlenderKey(modelKey.getName());
|
|
||||||
blenderKey.setAssetRootPath(modelKey.getFolder());
|
|
||||||
}
|
|
||||||
|
|
||||||
//opening stream
|
@Override
|
||||||
BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream(), assetInfo.getManager());
|
public LoadingResults load(AssetInfo assetInfo) throws IOException {
|
||||||
|
try {
|
||||||
|
//registering loaders
|
||||||
|
ModelKey modelKey = (ModelKey) assetInfo.getKey();
|
||||||
|
BlenderKey blenderKey;
|
||||||
|
if (modelKey instanceof BlenderKey) {
|
||||||
|
blenderKey = (BlenderKey) modelKey;
|
||||||
|
} else {
|
||||||
|
blenderKey = new BlenderKey(modelKey.getName());
|
||||||
|
blenderKey.setAssetRootPath(modelKey.getFolder());
|
||||||
|
}
|
||||||
|
|
||||||
//reading blocks
|
//opening stream
|
||||||
List<FileBlockHeader> blocks = new ArrayList<FileBlockHeader>();
|
BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream(), assetInfo.getManager());
|
||||||
FileBlockHeader fileBlock;
|
|
||||||
DataRepository dataRepository = new DataRepository();
|
|
||||||
dataRepository.setAssetManager(assetInfo.getManager());
|
|
||||||
dataRepository.setInputStream(inputStream);
|
|
||||||
dataRepository.setBlenderKey(blenderKey);
|
|
||||||
|
|
||||||
//creating helpers
|
//reading blocks
|
||||||
dataRepository.putHelper(ArmatureHelper.class, new ArmatureHelper(inputStream.getVersionNumber()));
|
List<FileBlockHeader> blocks = new ArrayList<FileBlockHeader>();
|
||||||
dataRepository.putHelper(TextureHelper.class, new TextureHelper(inputStream.getVersionNumber()));
|
FileBlockHeader fileBlock;
|
||||||
dataRepository.putHelper(MeshHelper.class, new MeshHelper(inputStream.getVersionNumber()));
|
DataRepository dataRepository = new DataRepository();
|
||||||
dataRepository.putHelper(ObjectHelper.class, new ObjectHelper(inputStream.getVersionNumber()));
|
dataRepository.setAssetManager(assetInfo.getManager());
|
||||||
dataRepository.putHelper(CurvesHelper.class, new CurvesHelper(inputStream.getVersionNumber()));
|
dataRepository.setInputStream(inputStream);
|
||||||
dataRepository.putHelper(LightHelper.class, new LightHelper(inputStream.getVersionNumber()));
|
dataRepository.setBlenderKey(blenderKey);
|
||||||
dataRepository.putHelper(CameraHelper.class, new CameraHelper(inputStream.getVersionNumber()));
|
|
||||||
dataRepository.putHelper(ModifierHelper.class, new ModifierHelper(inputStream.getVersionNumber()));
|
|
||||||
dataRepository.putHelper(MaterialHelper.class, new MaterialHelper(inputStream.getVersionNumber()));
|
|
||||||
dataRepository.putHelper(ConstraintHelper.class, new ConstraintHelper(inputStream.getVersionNumber(), dataRepository));
|
|
||||||
dataRepository.putHelper(IpoHelper.class, new IpoHelper(inputStream.getVersionNumber()));
|
|
||||||
dataRepository.putHelper(NoiseHelper.class, new NoiseHelper(inputStream.getVersionNumber()));
|
|
||||||
dataRepository.putHelper(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber()));
|
|
||||||
|
|
||||||
//setting additional data to helpers
|
//creating helpers
|
||||||
if(blenderKey.isFixUpAxis()) {
|
dataRepository.putHelper(ArmatureHelper.class, new ArmatureHelper(inputStream.getVersionNumber()));
|
||||||
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
|
dataRepository.putHelper(TextureHelper.class, new TextureHelper(inputStream.getVersionNumber()));
|
||||||
objectHelper.setyIsUpAxis(true);
|
dataRepository.putHelper(MeshHelper.class, new MeshHelper(inputStream.getVersionNumber()));
|
||||||
CurvesHelper curvesHelper = dataRepository.getHelper(CurvesHelper.class);
|
dataRepository.putHelper(ObjectHelper.class, new ObjectHelper(inputStream.getVersionNumber()));
|
||||||
curvesHelper.setyIsUpAxis(true);
|
dataRepository.putHelper(CurvesHelper.class, new CurvesHelper(inputStream.getVersionNumber()));
|
||||||
}
|
dataRepository.putHelper(LightHelper.class, new LightHelper(inputStream.getVersionNumber()));
|
||||||
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
|
dataRepository.putHelper(CameraHelper.class, new CameraHelper(inputStream.getVersionNumber()));
|
||||||
materialHelper.setFaceCullMode(blenderKey.getFaceCullMode());
|
dataRepository.putHelper(ModifierHelper.class, new ModifierHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(MaterialHelper.class, new MaterialHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(ConstraintHelper.class, new ConstraintHelper(inputStream.getVersionNumber(), dataRepository));
|
||||||
|
dataRepository.putHelper(IpoHelper.class, new IpoHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(NoiseHelper.class, new NoiseHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber()));
|
||||||
|
|
||||||
//reading the blocks (dna block is automatically saved in the data repository when found)//TODO: zmienić to
|
//setting additional data to helpers
|
||||||
do {
|
if (blenderKey.isFixUpAxis()) {
|
||||||
fileBlock = new FileBlockHeader(inputStream, dataRepository);
|
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
|
||||||
if(!fileBlock.isDnaBlock()) {
|
objectHelper.setyIsUpAxis(true);
|
||||||
blocks.add(fileBlock);
|
CurvesHelper curvesHelper = dataRepository.getHelper(CurvesHelper.class);
|
||||||
}
|
curvesHelper.setyIsUpAxis(true);
|
||||||
} while(!fileBlock.isLastBlock());
|
}
|
||||||
|
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
|
||||||
|
materialHelper.setFaceCullMode(blenderKey.getFaceCullMode());
|
||||||
|
|
||||||
JmeConverter converter = new JmeConverter(dataRepository);
|
//reading the blocks (dna block is automatically saved in the data repository when found)//TODO: zmienić to
|
||||||
LoadingResults loadingResults = blenderKey.prepareLoadingResults();
|
do {
|
||||||
WorldData worldData = null;//a set of data used in different scene aspects
|
fileBlock = new FileBlockHeader(inputStream, dataRepository);
|
||||||
for(FileBlockHeader block : blocks) {
|
if (!fileBlock.isDnaBlock()) {
|
||||||
switch(block.getCode()) {
|
blocks.add(fileBlock);
|
||||||
case FileBlockHeader.BLOCK_OB00://Object
|
}
|
||||||
Object object = converter.toObject(block.getStructure(dataRepository));
|
} while (!fileBlock.isLastBlock());
|
||||||
if(object instanceof Node) {
|
|
||||||
if((blenderKey.getFeaturesToLoad() & FeaturesToLoad.OBJECTS) != 0) {
|
JmeConverter converter = new JmeConverter(dataRepository);
|
||||||
LOGGER.log(Level.INFO, ((Node)object).getName() + ": " + ((Node)object).getLocalTranslation().toString() + "--> " + (((Node)object).getParent() == null ? "null" : ((Node)object).getParent().getName()));
|
LoadingResults loadingResults = blenderKey.prepareLoadingResults();
|
||||||
if(((Node)object).getParent() == null) {
|
WorldData worldData = null;//a set of data used in different scene aspects
|
||||||
loadingResults.addObject((Node)object);
|
for (FileBlockHeader block : blocks) {
|
||||||
}
|
switch (block.getCode()) {
|
||||||
}
|
case FileBlockHeader.BLOCK_OB00://Object
|
||||||
} else if(object instanceof Camera) {
|
Object object = converter.toObject(block.getStructure(dataRepository));
|
||||||
if((blenderKey.getFeaturesToLoad() & FeaturesToLoad.CAMERAS) != 0) {
|
if (object instanceof Node) {
|
||||||
loadingResults.addCamera((Camera)object);
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.OBJECTS) != 0) {
|
||||||
}
|
LOGGER.log(Level.INFO, "{0}: {1}--> {2}", new Object[]{((Node) object).getName(), ((Node) object).getLocalTranslation().toString(), ((Node) object).getParent() == null ? "null" : ((Node) object).getParent().getName()});
|
||||||
} else if(object instanceof Light) {
|
if (((Node) object).getParent() == null) {
|
||||||
if((blenderKey.getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0) {
|
loadingResults.addObject((Node) object);
|
||||||
loadingResults.addLight((Light)object);
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (object instanceof Camera) {
|
||||||
break;
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.CAMERAS) != 0) {
|
||||||
case FileBlockHeader.BLOCK_MA00://Material
|
loadingResults.addCamera((Camera) object);
|
||||||
if((blenderKey.getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0) {
|
}
|
||||||
loadingResults.addMaterial(converter.toMaterial(block.getStructure(dataRepository)));
|
} else if (object instanceof Light) {
|
||||||
}
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0) {
|
||||||
break;
|
loadingResults.addLight((Light) object);
|
||||||
case FileBlockHeader.BLOCK_SC00://Scene
|
}
|
||||||
if((blenderKey.getFeaturesToLoad() & FeaturesToLoad.SCENES) != 0) {
|
}
|
||||||
loadingResults.addScene(converter.toScene(block.getStructure(dataRepository)));
|
break;
|
||||||
}
|
case FileBlockHeader.BLOCK_MA00://Material
|
||||||
break;
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0) {
|
||||||
case FileBlockHeader.BLOCK_WO00://World
|
loadingResults.addMaterial(converter.toMaterial(block.getStructure(dataRepository)));
|
||||||
if(worldData == null) {//onlu one world data is used
|
}
|
||||||
Structure worldStructure = block.getStructure(dataRepository);
|
break;
|
||||||
String worldName = worldStructure.getName();
|
case FileBlockHeader.BLOCK_SC00://Scene
|
||||||
if(blenderKey.getUsedWorld() == null || blenderKey.getUsedWorld().equals(worldName)) {
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.SCENES) != 0) {
|
||||||
worldData = converter.toWorldData(worldStructure);
|
loadingResults.addScene(converter.toScene(block.getStructure(dataRepository)));
|
||||||
if((blenderKey.getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0) {
|
}
|
||||||
loadingResults.addLight(worldData.getAmbientLight());
|
break;
|
||||||
}
|
case FileBlockHeader.BLOCK_WO00://World
|
||||||
}
|
if (worldData == null) {//onlu one world data is used
|
||||||
}
|
Structure worldStructure = block.getStructure(dataRepository);
|
||||||
break;
|
String worldName = worldStructure.getName();
|
||||||
}
|
if (blenderKey.getUsedWorld() == null || blenderKey.getUsedWorld().equals(worldName)) {
|
||||||
}
|
worldData = converter.toWorldData(worldStructure);
|
||||||
try {
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0) {
|
||||||
inputStream.close();
|
loadingResults.addLight(worldData.getAmbientLight());
|
||||||
} catch(IOException e) {
|
}
|
||||||
LOGGER.log(Level.SEVERE, e.getMessage(), e);
|
}
|
||||||
}
|
}
|
||||||
return loadingResults;
|
break;
|
||||||
} catch(BlenderFileException e) {
|
}
|
||||||
LOGGER.log(Level.SEVERE, e.getMessage(), e);
|
}
|
||||||
}
|
try {
|
||||||
return null;
|
inputStream.close();
|
||||||
}
|
} catch (IOException e) {
|
||||||
|
LOGGER.log(Level.SEVERE, e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return loadingResults;
|
||||||
|
} catch (BlenderFileException e) {
|
||||||
|
LOGGER.log(Level.SEVERE, e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,89 +69,90 @@ import com.jme3.scene.plugins.blender.utils.JmeConverter;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class BlenderModelLoader implements AssetLoader {
|
public class BlenderModelLoader implements AssetLoader {
|
||||||
private static final Logger LOGGER = Logger.getLogger(BlenderModelLoader.class.getName());
|
|
||||||
|
|
||||||
@Override
|
private static final Logger LOGGER = Logger.getLogger(BlenderModelLoader.class.getName());
|
||||||
public Spatial load(AssetInfo assetInfo) throws IOException {
|
|
||||||
try {
|
|
||||||
//registering loaders
|
|
||||||
ModelKey modelKey = (ModelKey)assetInfo.getKey();
|
|
||||||
BlenderKey blenderKey;
|
|
||||||
if(modelKey instanceof BlenderKey) {
|
|
||||||
blenderKey = (BlenderKey)modelKey;
|
|
||||||
} else {
|
|
||||||
blenderKey = new BlenderKey(modelKey.getName());
|
|
||||||
blenderKey.setAssetRootPath(modelKey.getFolder());
|
|
||||||
}
|
|
||||||
|
|
||||||
//opening stream
|
@Override
|
||||||
BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream(), assetInfo.getManager());
|
public Spatial load(AssetInfo assetInfo) throws IOException {
|
||||||
List<FileBlockHeader> blocks = new ArrayList<FileBlockHeader>();
|
try {
|
||||||
FileBlockHeader fileBlock;
|
//registering loaders
|
||||||
DataRepository dataRepository = new DataRepository();
|
ModelKey modelKey = (ModelKey) assetInfo.getKey();
|
||||||
dataRepository.setAssetManager(assetInfo.getManager());
|
BlenderKey blenderKey;
|
||||||
dataRepository.setInputStream(inputStream);
|
if (modelKey instanceof BlenderKey) {
|
||||||
dataRepository.setBlenderKey(blenderKey);
|
blenderKey = (BlenderKey) modelKey;
|
||||||
dataRepository.putHelper(ArmatureHelper.class, new ArmatureHelper(inputStream.getVersionNumber()));
|
} else {
|
||||||
dataRepository.putHelper(TextureHelper.class, new TextureHelper(inputStream.getVersionNumber()));
|
blenderKey = new BlenderKey(modelKey.getName());
|
||||||
dataRepository.putHelper(MeshHelper.class, new MeshHelper(inputStream.getVersionNumber()));
|
blenderKey.setAssetRootPath(modelKey.getFolder());
|
||||||
dataRepository.putHelper(ObjectHelper.class, new ObjectHelper(inputStream.getVersionNumber()));
|
}
|
||||||
dataRepository.putHelper(CurvesHelper.class, new CurvesHelper(inputStream.getVersionNumber()));
|
|
||||||
dataRepository.putHelper(LightHelper.class, new LightHelper(inputStream.getVersionNumber()));
|
|
||||||
dataRepository.putHelper(CameraHelper.class, new CameraHelper(inputStream.getVersionNumber()));
|
|
||||||
dataRepository.putHelper(ModifierHelper.class, new ModifierHelper(inputStream.getVersionNumber()));
|
|
||||||
dataRepository.putHelper(MaterialHelper.class, new MaterialHelper(inputStream.getVersionNumber()));
|
|
||||||
dataRepository.putHelper(ConstraintHelper.class, new ConstraintHelper(inputStream.getVersionNumber(), dataRepository));
|
|
||||||
dataRepository.putHelper(IpoHelper.class, new IpoHelper(inputStream.getVersionNumber()));
|
|
||||||
dataRepository.putHelper(NoiseHelper.class, new NoiseHelper(inputStream.getVersionNumber()));
|
|
||||||
dataRepository.putHelper(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber()));
|
|
||||||
|
|
||||||
//setting additional data to helpers
|
//opening stream
|
||||||
if(blenderKey.isFixUpAxis()) {
|
BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream(), assetInfo.getManager());
|
||||||
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
|
List<FileBlockHeader> blocks = new ArrayList<FileBlockHeader>();
|
||||||
objectHelper.setyIsUpAxis(true);
|
FileBlockHeader fileBlock;
|
||||||
CurvesHelper curvesHelper = dataRepository.getHelper(CurvesHelper.class);
|
DataRepository dataRepository = new DataRepository();
|
||||||
curvesHelper.setyIsUpAxis(true);
|
dataRepository.setAssetManager(assetInfo.getManager());
|
||||||
}
|
dataRepository.setInputStream(inputStream);
|
||||||
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
|
dataRepository.setBlenderKey(blenderKey);
|
||||||
materialHelper.setFaceCullMode(blenderKey.getFaceCullMode());
|
dataRepository.putHelper(ArmatureHelper.class, new ArmatureHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(TextureHelper.class, new TextureHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(MeshHelper.class, new MeshHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(ObjectHelper.class, new ObjectHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(CurvesHelper.class, new CurvesHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(LightHelper.class, new LightHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(CameraHelper.class, new CameraHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(ModifierHelper.class, new ModifierHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(MaterialHelper.class, new MaterialHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(ConstraintHelper.class, new ConstraintHelper(inputStream.getVersionNumber(), dataRepository));
|
||||||
|
dataRepository.putHelper(IpoHelper.class, new IpoHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(NoiseHelper.class, new NoiseHelper(inputStream.getVersionNumber()));
|
||||||
|
dataRepository.putHelper(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber()));
|
||||||
|
|
||||||
//reading the blocks (dna block is automatically saved in the data repository when found)//TODO: zmienić to
|
//setting additional data to helpers
|
||||||
do {
|
if (blenderKey.isFixUpAxis()) {
|
||||||
fileBlock = new FileBlockHeader(inputStream, dataRepository);
|
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
|
||||||
if(!fileBlock.isDnaBlock()) {
|
objectHelper.setyIsUpAxis(true);
|
||||||
blocks.add(fileBlock);
|
CurvesHelper curvesHelper = dataRepository.getHelper(CurvesHelper.class);
|
||||||
}
|
curvesHelper.setyIsUpAxis(true);
|
||||||
} while(!fileBlock.isLastBlock());
|
}
|
||||||
|
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
|
||||||
|
materialHelper.setFaceCullMode(blenderKey.getFaceCullMode());
|
||||||
|
|
||||||
JmeConverter converter = new JmeConverter(dataRepository);
|
//reading the blocks (dna block is automatically saved in the data repository when found)//TODO: zmienić to
|
||||||
LoadingResults loadingResults = blenderKey.prepareLoadingResults();
|
do {
|
||||||
for(FileBlockHeader block : blocks) {
|
fileBlock = new FileBlockHeader(inputStream, dataRepository);
|
||||||
if(block.getCode() == FileBlockHeader.BLOCK_OB00) {
|
if (!fileBlock.isDnaBlock()) {
|
||||||
Object object = converter.toObject(block.getStructure(dataRepository));
|
blocks.add(fileBlock);
|
||||||
if(object instanceof Node) {
|
}
|
||||||
LOGGER.log(Level.INFO, ((Node)object).getName() + ": " + ((Node)object).getLocalTranslation().toString() + "--> " + (((Node)object).getParent() == null ? "null" : ((Node)object).getParent().getName()));
|
} while (!fileBlock.isLastBlock());
|
||||||
if(((Node)object).getParent() == null) {
|
|
||||||
loadingResults.addObject((Node)object);
|
JmeConverter converter = new JmeConverter(dataRepository);
|
||||||
}
|
LoadingResults loadingResults = blenderKey.prepareLoadingResults();
|
||||||
}
|
for (FileBlockHeader block : blocks) {
|
||||||
}
|
if (block.getCode() == FileBlockHeader.BLOCK_OB00) {
|
||||||
}
|
Object object = converter.toObject(block.getStructure(dataRepository));
|
||||||
inputStream.close();
|
if (object instanceof Node) {
|
||||||
List<Node> objects = loadingResults.getObjects();
|
LOGGER.log(Level.INFO, "{0}: {1}--> {2}", new Object[]{((Node) object).getName(), ((Node) object).getLocalTranslation().toString(), ((Node) object).getParent() == null ? "null" : ((Node) object).getParent().getName()});
|
||||||
if(objects.size() > 0) {
|
if (((Node) object).getParent() == null) {
|
||||||
Node modelNode = new Node(blenderKey.getName());
|
loadingResults.addObject((Node) object);
|
||||||
for(Iterator<Node> it = objects.iterator(); it.hasNext();) {
|
}
|
||||||
Node node = it.next();
|
}
|
||||||
modelNode.attachChild(node);
|
}
|
||||||
}
|
}
|
||||||
return modelNode;
|
inputStream.close();
|
||||||
} else if(objects.size() == 1) {
|
List<Node> objects = loadingResults.getObjects();
|
||||||
return objects.get(0);
|
if (objects.size() > 0) {
|
||||||
}
|
Node modelNode = new Node(blenderKey.getName());
|
||||||
} catch(BlenderFileException e) {
|
for (Iterator<Node> it = objects.iterator(); it.hasNext();) {
|
||||||
LOGGER.log(Level.SEVERE, e.getMessage(), e);
|
Node node = it.next();
|
||||||
}
|
modelNode.attachChild(node);
|
||||||
return null;
|
}
|
||||||
}
|
return modelNode;
|
||||||
|
} else if (objects.size() == 1) {
|
||||||
|
return objects.get(0);
|
||||||
|
}
|
||||||
|
} catch (BlenderFileException e) {
|
||||||
|
LOGGER.log(Level.SEVERE, e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,168 +43,168 @@ import com.jme3.scene.plugins.blender.utils.DataRepository;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class DnaBlockData {
|
public class DnaBlockData {
|
||||||
private static final int SDNA_ID = 'S' << 24 | 'D' << 16 | 'N' << 8 | 'A'; //SDNA
|
|
||||||
private static final int NAME_ID = 'N' << 24 | 'A' << 16 | 'M' << 8 | 'E'; //NAME
|
|
||||||
private static final int TYPE_ID = 'T' << 24 | 'Y' << 16 | 'P' << 8 | 'E'; //TYPE
|
|
||||||
private static final int TLEN_ID = 'T' << 24 | 'L' << 16 | 'E' << 8 | 'N'; //TLEN
|
|
||||||
private static final int STRC_ID = 'S' << 24 | 'T' << 16 | 'R' << 8 | 'C'; //STRC
|
|
||||||
|
|
||||||
/** Structures available inside the file. */
|
private static final int SDNA_ID = 'S' << 24 | 'D' << 16 | 'N' << 8 | 'A'; //SDNA
|
||||||
private final Structure[] structures;
|
private static final int NAME_ID = 'N' << 24 | 'A' << 16 | 'M' << 8 | 'E'; //NAME
|
||||||
/** A map that helps finding a structure by type. */
|
private static final int TYPE_ID = 'T' << 24 | 'Y' << 16 | 'P' << 8 | 'E'; //TYPE
|
||||||
private final Map<String, Structure> structuresMap;
|
private static final int TLEN_ID = 'T' << 24 | 'L' << 16 | 'E' << 8 | 'N'; //TLEN
|
||||||
|
private static final int STRC_ID = 'S' << 24 | 'T' << 16 | 'R' << 8 | 'C'; //STRC
|
||||||
|
/** Structures available inside the file. */
|
||||||
|
private final Structure[] structures;
|
||||||
|
/** A map that helps finding a structure by type. */
|
||||||
|
private final Map<String, Structure> structuresMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Loads the block from the given stream during instance creation.
|
* Constructor. Loads the block from the given stream during instance creation.
|
||||||
* @param inputStream
|
* @param inputStream
|
||||||
* the stream we read the block from
|
* the stream we read the block from
|
||||||
* @param dataRepository
|
* @param dataRepository
|
||||||
* the data repository
|
* the data repository
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* this exception is throw if the blend file is invalid or somehow corrupted
|
* this exception is throw if the blend file is invalid or somehow corrupted
|
||||||
*/
|
*/
|
||||||
public DnaBlockData(BlenderInputStream inputStream, DataRepository dataRepository) throws BlenderFileException {
|
public DnaBlockData(BlenderInputStream inputStream, DataRepository dataRepository) throws BlenderFileException {
|
||||||
int identifier;
|
int identifier;
|
||||||
|
|
||||||
//reading 'SDNA' identifier
|
//reading 'SDNA' identifier
|
||||||
identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16 |
|
identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16
|
||||||
inputStream.readByte() << 8 | inputStream.readByte();
|
| inputStream.readByte() << 8 | inputStream.readByte();
|
||||||
|
|
||||||
if(identifier != SDNA_ID) {
|
if (identifier != SDNA_ID) {
|
||||||
throw new BlenderFileException("Invalid identifier! '" + this.toString(SDNA_ID) + "' expected and found: " + this.toString(identifier));
|
throw new BlenderFileException("Invalid identifier! '" + this.toString(SDNA_ID) + "' expected and found: " + this.toString(identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
//reading names
|
//reading names
|
||||||
identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16 |
|
identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16
|
||||||
inputStream.readByte() << 8 | inputStream.readByte();
|
| inputStream.readByte() << 8 | inputStream.readByte();
|
||||||
if(identifier != NAME_ID) {
|
if (identifier != NAME_ID) {
|
||||||
throw new BlenderFileException("Invalid identifier! '" + this.toString(NAME_ID) + "' expected and found: " + this.toString(identifier));
|
throw new BlenderFileException("Invalid identifier! '" + this.toString(NAME_ID) + "' expected and found: " + this.toString(identifier));
|
||||||
}
|
}
|
||||||
int amount = inputStream.readInt();
|
int amount = inputStream.readInt();
|
||||||
if(amount <= 0) {
|
if (amount <= 0) {
|
||||||
throw new BlenderFileException("The names amount number should be positive!");
|
throw new BlenderFileException("The names amount number should be positive!");
|
||||||
}
|
}
|
||||||
String[] names = new String[amount];
|
String[] names = new String[amount];
|
||||||
for(int i = 0; i < amount; ++i) {
|
for (int i = 0; i < amount; ++i) {
|
||||||
names[i] = inputStream.readString();
|
names[i] = inputStream.readString();
|
||||||
}
|
}
|
||||||
|
|
||||||
//reding types
|
//reding types
|
||||||
inputStream.alignPosition(4);
|
inputStream.alignPosition(4);
|
||||||
identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16 |
|
identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16
|
||||||
inputStream.readByte() << 8 | inputStream.readByte();
|
| inputStream.readByte() << 8 | inputStream.readByte();
|
||||||
if(identifier != TYPE_ID) {
|
if (identifier != TYPE_ID) {
|
||||||
throw new BlenderFileException("Invalid identifier! '" + this.toString(TYPE_ID) + "' expected and found: " + this.toString(identifier));
|
throw new BlenderFileException("Invalid identifier! '" + this.toString(TYPE_ID) + "' expected and found: " + this.toString(identifier));
|
||||||
}
|
}
|
||||||
amount = inputStream.readInt();
|
amount = inputStream.readInt();
|
||||||
if(amount <= 0) {
|
if (amount <= 0) {
|
||||||
throw new BlenderFileException("The types amount number should be positive!");
|
throw new BlenderFileException("The types amount number should be positive!");
|
||||||
}
|
}
|
||||||
String[] types = new String[amount];
|
String[] types = new String[amount];
|
||||||
for(int i = 0; i < amount; ++i) {
|
for (int i = 0; i < amount; ++i) {
|
||||||
types[i] = inputStream.readString();
|
types[i] = inputStream.readString();
|
||||||
}
|
}
|
||||||
|
|
||||||
//reading lengths
|
//reading lengths
|
||||||
inputStream.alignPosition(4);
|
inputStream.alignPosition(4);
|
||||||
identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16 |
|
identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16
|
||||||
inputStream.readByte() << 8 | inputStream.readByte();
|
| inputStream.readByte() << 8 | inputStream.readByte();
|
||||||
if(identifier != TLEN_ID) {
|
if (identifier != TLEN_ID) {
|
||||||
throw new BlenderFileException("Invalid identifier! '" + this.toString(TLEN_ID) + "' expected and found: " + this.toString(identifier));
|
throw new BlenderFileException("Invalid identifier! '" + this.toString(TLEN_ID) + "' expected and found: " + this.toString(identifier));
|
||||||
}
|
}
|
||||||
int[] lengths = new int[amount];//theamount is the same as int types
|
int[] lengths = new int[amount];//theamount is the same as int types
|
||||||
for(int i = 0; i < amount; ++i) {
|
for (int i = 0; i < amount; ++i) {
|
||||||
lengths[i] = inputStream.readShort();
|
lengths[i] = inputStream.readShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
//reading structures
|
//reading structures
|
||||||
inputStream.alignPosition(4);
|
inputStream.alignPosition(4);
|
||||||
identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16 |
|
identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16
|
||||||
inputStream.readByte() << 8 | inputStream.readByte();
|
| inputStream.readByte() << 8 | inputStream.readByte();
|
||||||
if(identifier != STRC_ID) {
|
if (identifier != STRC_ID) {
|
||||||
throw new BlenderFileException("Invalid identifier! '" + this.toString(STRC_ID) + "' expected and found: " + this.toString(identifier));
|
throw new BlenderFileException("Invalid identifier! '" + this.toString(STRC_ID) + "' expected and found: " + this.toString(identifier));
|
||||||
}
|
}
|
||||||
amount = inputStream.readInt();
|
amount = inputStream.readInt();
|
||||||
if(amount <= 0) {
|
if (amount <= 0) {
|
||||||
throw new BlenderFileException("The structures amount number should be positive!");
|
throw new BlenderFileException("The structures amount number should be positive!");
|
||||||
}
|
}
|
||||||
structures = new Structure[amount];
|
structures = new Structure[amount];
|
||||||
structuresMap = new HashMap<String, Structure>(amount);
|
structuresMap = new HashMap<String, Structure>(amount);
|
||||||
for(int i = 0; i < amount; ++i) {
|
for (int i = 0; i < amount; ++i) {
|
||||||
structures[i] = new Structure(inputStream, names, types, dataRepository);
|
structures[i] = new Structure(inputStream, names, types, dataRepository);
|
||||||
if(structuresMap.containsKey(structures[i].getType())) {
|
if (structuresMap.containsKey(structures[i].getType())) {
|
||||||
throw new BlenderFileException("Blend file seems to be corrupted! The type " + structures[i].getType() + " is defined twice!");
|
throw new BlenderFileException("Blend file seems to be corrupted! The type " + structures[i].getType() + " is defined twice!");
|
||||||
}
|
}
|
||||||
structuresMap.put(structures[i].getType(), structures[i]);
|
structuresMap.put(structures[i].getType(), structures[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the amount of the structures.
|
* This method returns the amount of the structures.
|
||||||
* @return the amount of the structures
|
* @return the amount of the structures
|
||||||
*/
|
*/
|
||||||
public int getStructuresCount() {
|
public int getStructuresCount() {
|
||||||
return structures.length;
|
return structures.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the structure of the given index.
|
* This method returns the structure of the given index.
|
||||||
* @param index
|
* @param index
|
||||||
* the index of the structure
|
* the index of the structure
|
||||||
* @return the structure of the given index
|
* @return the structure of the given index
|
||||||
*/
|
*/
|
||||||
public Structure getStructure(int index) {
|
public Structure getStructure(int index) {
|
||||||
try {
|
try {
|
||||||
return (Structure)structures[index].clone();
|
return (Structure) structures[index].clone();
|
||||||
} catch(CloneNotSupportedException e) {
|
} catch (CloneNotSupportedException e) {
|
||||||
throw new IllegalStateException("Structure should be clonable!!!", e);
|
throw new IllegalStateException("Structure should be clonable!!!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns a structure of the given name. If the name does not exists then null is returned.
|
* This method returns a structure of the given name. If the name does not exists then null is returned.
|
||||||
* @param name
|
* @param name
|
||||||
* the name of the structure
|
* the name of the structure
|
||||||
* @return the required structure or null if the given name is inapropriate
|
* @return the required structure or null if the given name is inapropriate
|
||||||
*/
|
*/
|
||||||
public Structure getStructure(String name) {
|
public Structure getStructure(String name) {
|
||||||
try {
|
try {
|
||||||
return (Structure)structuresMap.get(name).clone();
|
return (Structure) structuresMap.get(name).clone();
|
||||||
} catch(CloneNotSupportedException e) {
|
} catch (CloneNotSupportedException e) {
|
||||||
throw new IllegalStateException(e.getMessage(), e);
|
throw new IllegalStateException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method indicates if the structure of the given name exists.
|
* This method indicates if the structure of the given name exists.
|
||||||
* @param name
|
* @param name
|
||||||
* the name of the structure
|
* the name of the structure
|
||||||
* @return true if the structure exists and false otherwise
|
* @return true if the structure exists and false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean hasStructure(String name) {
|
public boolean hasStructure(String name) {
|
||||||
return structuresMap.containsKey(name);
|
return structuresMap.containsKey(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method converts the given identifier code to string.
|
* This method converts the given identifier code to string.
|
||||||
* @param code
|
* @param code
|
||||||
* the code taht is to be converted
|
* the code taht is to be converted
|
||||||
* @return the string value of the identifier
|
* @return the string value of the identifier
|
||||||
*/
|
*/
|
||||||
private String toString(int code) {
|
private String toString(int code) {
|
||||||
char c1 = (char)((code & 0xFF000000) >> 24);
|
char c1 = (char) ((code & 0xFF000000) >> 24);
|
||||||
char c2 = (char)((code & 0xFF0000) >> 16);
|
char c2 = (char) ((code & 0xFF0000) >> 16);
|
||||||
char c3 = (char)((code & 0xFF00) >> 8);
|
char c3 = (char) ((code & 0xFF00) >> 8);
|
||||||
char c4 = (char)(code & 0xFF);
|
char c4 = (char) (code & 0xFF);
|
||||||
return String.valueOf(c1) + c2 + c3 + c4;
|
return String.valueOf(c1) + c2 + c3 + c4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder stringBuilder = new StringBuilder("=============== ").append(SDNA_ID).append('\n');
|
StringBuilder stringBuilder = new StringBuilder("=============== ").append(SDNA_ID).append('\n');
|
||||||
for(Structure structure : structures) {
|
for (Structure structure : structures) {
|
||||||
stringBuilder.append(structure.toString()).append('\n');
|
stringBuilder.append(structure.toString()).append('\n');
|
||||||
}
|
}
|
||||||
return stringBuilder.append("===============").toString();
|
return stringBuilder.append("===============").toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,305 +15,306 @@ import com.jme3.scene.plugins.blender.utils.Pointer;
|
|||||||
* another structure.
|
* another structure.
|
||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
/*package*/class Field implements Cloneable {
|
/*package*/
|
||||||
private static final int NAME_LENGTH = 24;
|
class Field implements Cloneable {
|
||||||
private static final int TYPE_LENGTH = 16;
|
|
||||||
|
|
||||||
/** The data repository. */
|
private static final int NAME_LENGTH = 24;
|
||||||
public DataRepository dataRepository;
|
private static final int TYPE_LENGTH = 16;
|
||||||
/** The type of the field. */
|
/** The data repository. */
|
||||||
public String type;
|
public DataRepository dataRepository;
|
||||||
/** The name of the field. */
|
/** The type of the field. */
|
||||||
public String name;
|
public String type;
|
||||||
/** The value of the field. Filled during data reading. */
|
/** The name of the field. */
|
||||||
public Object value;
|
public String name;
|
||||||
/** This variable indicates the level of the pointer. */
|
/** The value of the field. Filled during data reading. */
|
||||||
public int pointerLevel;
|
public Object value;
|
||||||
/**
|
/** This variable indicates the level of the pointer. */
|
||||||
* This variable determines the sizes of the array. If the value is null the n the field is not an array.
|
public int pointerLevel;
|
||||||
*/
|
/**
|
||||||
public int[] tableSizes;
|
* This variable determines the sizes of the array. If the value is null the n the field is not an array.
|
||||||
/** This variable indicates if the field is a function pointer. */
|
*/
|
||||||
public boolean function;
|
public int[] tableSizes;
|
||||||
|
/** This variable indicates if the field is a function pointer. */
|
||||||
|
public boolean function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Saves the field data and parses its name.
|
* Constructor. Saves the field data and parses its name.
|
||||||
* @param name
|
* @param name
|
||||||
* the name of the field
|
* the name of the field
|
||||||
* @param type
|
* @param type
|
||||||
* the type of the field
|
* the type of the field
|
||||||
* @param dataRepository
|
* @param dataRepository
|
||||||
* the data repository
|
* the data repository
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* this exception is thrown if the names contain errors
|
* this exception is thrown if the names contain errors
|
||||||
*/
|
*/
|
||||||
public Field(String name, String type, DataRepository dataRepository) throws BlenderFileException {
|
public Field(String name, String type, DataRepository dataRepository) throws BlenderFileException {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.dataRepository = dataRepository;
|
this.dataRepository = dataRepository;
|
||||||
this.parseField(new StringBuilder(name));
|
this.parseField(new StringBuilder(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy constructor. Used in clone method. Copying is not full. The value in the new object is not set so that we
|
* Copy constructor. Used in clone method. Copying is not full. The value in the new object is not set so that we
|
||||||
* have a clead empty copy of the filed to fill with data.
|
* have a clead empty copy of the filed to fill with data.
|
||||||
* @param field
|
* @param field
|
||||||
* the object that we copy
|
* the object that we copy
|
||||||
*/
|
*/
|
||||||
private Field(Field field) {
|
private Field(Field field) {
|
||||||
type = field.type;
|
type = field.type;
|
||||||
name = field.name;
|
name = field.name;
|
||||||
dataRepository = field.dataRepository;
|
dataRepository = field.dataRepository;
|
||||||
pointerLevel = field.pointerLevel;
|
pointerLevel = field.pointerLevel;
|
||||||
if(field.tableSizes != null) {
|
if (field.tableSizes != null) {
|
||||||
tableSizes = field.tableSizes.clone();
|
tableSizes = field.tableSizes.clone();
|
||||||
}
|
}
|
||||||
function = field.function;
|
function = field.function;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object clone() throws CloneNotSupportedException {
|
public Object clone() throws CloneNotSupportedException {
|
||||||
return new Field(this);
|
return new Field(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method fills the field wth data read from the input stream.
|
* This method fills the field wth data read from the input stream.
|
||||||
* @param blenderInputStream
|
* @param blenderInputStream
|
||||||
* the stream we read data from
|
* the stream we read data from
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* an exception is thrown when the blend file is somehow invalid or corrupted
|
* an exception is thrown when the blend file is somehow invalid or corrupted
|
||||||
*/
|
*/
|
||||||
public void fill(BlenderInputStream blenderInputStream) throws BlenderFileException {
|
public void fill(BlenderInputStream blenderInputStream) throws BlenderFileException {
|
||||||
int dataToRead = 1;
|
int dataToRead = 1;
|
||||||
if(tableSizes != null && tableSizes.length > 0) {
|
if (tableSizes != null && tableSizes.length > 0) {
|
||||||
for(int size : tableSizes) {
|
for (int size : tableSizes) {
|
||||||
if(size <= 0) {
|
if (size <= 0) {
|
||||||
throw new BlenderFileException("The field " + name + " has invalid table size: " + size);
|
throw new BlenderFileException("The field " + name + " has invalid table size: " + size);
|
||||||
}
|
}
|
||||||
dataToRead *= size;
|
dataToRead *= size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType dataType = pointerLevel == 0 ? DataType.getDataType(type, dataRepository) : DataType.POINTER;
|
DataType dataType = pointerLevel == 0 ? DataType.getDataType(type, dataRepository) : DataType.POINTER;
|
||||||
switch(dataType) {
|
switch (dataType) {
|
||||||
case POINTER:
|
case POINTER:
|
||||||
if(dataToRead == 1) {
|
if (dataToRead == 1) {
|
||||||
Pointer pointer = new Pointer(pointerLevel, function, dataRepository);
|
Pointer pointer = new Pointer(pointerLevel, function, dataRepository);
|
||||||
pointer.fill(blenderInputStream);
|
pointer.fill(blenderInputStream);
|
||||||
value = pointer;
|
value = pointer;
|
||||||
} else {
|
} else {
|
||||||
Pointer[] data = new Pointer[dataToRead];
|
Pointer[] data = new Pointer[dataToRead];
|
||||||
for(int i = 0; i < dataToRead; ++i) {
|
for (int i = 0; i < dataToRead; ++i) {
|
||||||
Pointer pointer = new Pointer(pointerLevel, function, dataRepository);
|
Pointer pointer = new Pointer(pointerLevel, function, dataRepository);
|
||||||
pointer.fill(blenderInputStream);
|
pointer.fill(blenderInputStream);
|
||||||
data[i] = pointer;
|
data[i] = pointer;
|
||||||
}
|
}
|
||||||
value = new DynamicArray<Pointer>(tableSizes, data);
|
value = new DynamicArray<Pointer>(tableSizes, data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CHARACTER:
|
case CHARACTER:
|
||||||
//character is also stored as a number, because sometimes the new blender version uses
|
//character is also stored as a number, because sometimes the new blender version uses
|
||||||
//other number type instead of character as a field type
|
//other number type instead of character as a field type
|
||||||
//and characters are very often used as byte number stores instead of real chars
|
//and characters are very often used as byte number stores instead of real chars
|
||||||
if(dataToRead == 1) {
|
if (dataToRead == 1) {
|
||||||
value = Byte.valueOf((byte)blenderInputStream.readByte());
|
value = Byte.valueOf((byte) blenderInputStream.readByte());
|
||||||
} else {
|
} else {
|
||||||
Character[] data = new Character[dataToRead];
|
Character[] data = new Character[dataToRead];
|
||||||
for(int i = 0; i < dataToRead; ++i) {
|
for (int i = 0; i < dataToRead; ++i) {
|
||||||
data[i] = Character.valueOf((char)blenderInputStream.readByte());
|
data[i] = Character.valueOf((char) blenderInputStream.readByte());
|
||||||
}
|
}
|
||||||
value = new DynamicArray<Character>(tableSizes, data);
|
value = new DynamicArray<Character>(tableSizes, data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SHORT:
|
case SHORT:
|
||||||
if(dataToRead == 1) {
|
if (dataToRead == 1) {
|
||||||
value = Integer.valueOf(blenderInputStream.readShort());
|
value = Integer.valueOf(blenderInputStream.readShort());
|
||||||
} else {
|
} else {
|
||||||
Number[] data = new Number[dataToRead];
|
Number[] data = new Number[dataToRead];
|
||||||
for(int i = 0; i < dataToRead; ++i) {
|
for (int i = 0; i < dataToRead; ++i) {
|
||||||
data[i] = Integer.valueOf(blenderInputStream.readShort());
|
data[i] = Integer.valueOf(blenderInputStream.readShort());
|
||||||
}
|
}
|
||||||
value = new DynamicArray<Number>(tableSizes, data);
|
value = new DynamicArray<Number>(tableSizes, data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
if(dataToRead == 1) {
|
if (dataToRead == 1) {
|
||||||
value = Integer.valueOf(blenderInputStream.readInt());
|
value = Integer.valueOf(blenderInputStream.readInt());
|
||||||
} else {
|
} else {
|
||||||
Number[] data = new Number[dataToRead];
|
Number[] data = new Number[dataToRead];
|
||||||
for(int i = 0; i < dataToRead; ++i) {
|
for (int i = 0; i < dataToRead; ++i) {
|
||||||
data[i] = Integer.valueOf(blenderInputStream.readInt());
|
data[i] = Integer.valueOf(blenderInputStream.readInt());
|
||||||
}
|
}
|
||||||
value = new DynamicArray<Number>(tableSizes, data);
|
value = new DynamicArray<Number>(tableSizes, data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LONG:
|
case LONG:
|
||||||
if(dataToRead == 1) {
|
if (dataToRead == 1) {
|
||||||
value = Long.valueOf(blenderInputStream.readLong());
|
value = Long.valueOf(blenderInputStream.readLong());
|
||||||
} else {
|
} else {
|
||||||
Number[] data = new Number[dataToRead];
|
Number[] data = new Number[dataToRead];
|
||||||
for(int i = 0; i < dataToRead; ++i) {
|
for (int i = 0; i < dataToRead; ++i) {
|
||||||
data[i] = Long.valueOf(blenderInputStream.readLong());
|
data[i] = Long.valueOf(blenderInputStream.readLong());
|
||||||
}
|
}
|
||||||
value = new DynamicArray<Number>(tableSizes, data);
|
value = new DynamicArray<Number>(tableSizes, data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
if(dataToRead == 1) {
|
if (dataToRead == 1) {
|
||||||
value = Float.valueOf(blenderInputStream.readFloat());
|
value = Float.valueOf(blenderInputStream.readFloat());
|
||||||
} else {
|
} else {
|
||||||
Number[] data = new Number[dataToRead];
|
Number[] data = new Number[dataToRead];
|
||||||
for(int i = 0; i < dataToRead; ++i) {
|
for (int i = 0; i < dataToRead; ++i) {
|
||||||
data[i] = Float.valueOf(blenderInputStream.readFloat());
|
data[i] = Float.valueOf(blenderInputStream.readFloat());
|
||||||
}
|
}
|
||||||
value = new DynamicArray<Number>(tableSizes, data);
|
value = new DynamicArray<Number>(tableSizes, data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DOUBLE:
|
case DOUBLE:
|
||||||
if(dataToRead == 1) {
|
if (dataToRead == 1) {
|
||||||
value = Double.valueOf(blenderInputStream.readDouble());
|
value = Double.valueOf(blenderInputStream.readDouble());
|
||||||
} else {
|
} else {
|
||||||
Number[] data = new Number[dataToRead];
|
Number[] data = new Number[dataToRead];
|
||||||
for(int i = 0; i < dataToRead; ++i) {
|
for (int i = 0; i < dataToRead; ++i) {
|
||||||
data[i] = Double.valueOf(blenderInputStream.readDouble());
|
data[i] = Double.valueOf(blenderInputStream.readDouble());
|
||||||
}
|
}
|
||||||
value = new DynamicArray<Number>(tableSizes, data);
|
value = new DynamicArray<Number>(tableSizes, data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VOID:
|
case VOID:
|
||||||
break;
|
break;
|
||||||
case STRUCTURE:
|
case STRUCTURE:
|
||||||
if(dataToRead == 1) {
|
if (dataToRead == 1) {
|
||||||
Structure structure = dataRepository.getDnaBlockData().getStructure(type);
|
Structure structure = dataRepository.getDnaBlockData().getStructure(type);
|
||||||
structure.fill(blenderInputStream);
|
structure.fill(blenderInputStream);
|
||||||
value = structure;
|
value = structure;
|
||||||
} else {
|
} else {
|
||||||
Structure[] data = new Structure[dataToRead];
|
Structure[] data = new Structure[dataToRead];
|
||||||
for(int i = 0; i < dataToRead; ++i) {
|
for (int i = 0; i < dataToRead; ++i) {
|
||||||
Structure structure = dataRepository.getDnaBlockData().getStructure(type);
|
Structure structure = dataRepository.getDnaBlockData().getStructure(type);
|
||||||
structure.fill(blenderInputStream);
|
structure.fill(blenderInputStream);
|
||||||
data[i] = structure;
|
data[i] = structure;
|
||||||
}
|
}
|
||||||
value = new DynamicArray<Structure>(tableSizes, data);
|
value = new DynamicArray<Structure>(tableSizes, data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("Unimplemented filling of type: " + type);
|
throw new IllegalStateException("Unimplemented filling of type: " + type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method parses the field name to determine how the field should be used.
|
* This method parses the field name to determine how the field should be used.
|
||||||
* @param nameBuilder
|
* @param nameBuilder
|
||||||
* the name of the field (given as StringBuilder)
|
* the name of the field (given as StringBuilder)
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* this exception is thrown if the names contain errors
|
* this exception is thrown if the names contain errors
|
||||||
*/
|
*/
|
||||||
private void parseField(StringBuilder nameBuilder) throws BlenderFileException {
|
private void parseField(StringBuilder nameBuilder) throws BlenderFileException {
|
||||||
this.removeWhitespaces(nameBuilder);
|
this.removeWhitespaces(nameBuilder);
|
||||||
//veryfying if the name is a pointer
|
//veryfying if the name is a pointer
|
||||||
int pointerIndex = nameBuilder.indexOf("*");
|
int pointerIndex = nameBuilder.indexOf("*");
|
||||||
while(pointerIndex >= 0) {
|
while (pointerIndex >= 0) {
|
||||||
++pointerLevel;
|
++pointerLevel;
|
||||||
nameBuilder.deleteCharAt(pointerIndex);
|
nameBuilder.deleteCharAt(pointerIndex);
|
||||||
pointerIndex = nameBuilder.indexOf("*");
|
pointerIndex = nameBuilder.indexOf("*");
|
||||||
}
|
}
|
||||||
//veryfying if the name is a function pointer
|
//veryfying if the name is a function pointer
|
||||||
if(nameBuilder.indexOf("(") >= 0) {
|
if (nameBuilder.indexOf("(") >= 0) {
|
||||||
function = true;
|
function = true;
|
||||||
this.removeCharacter(nameBuilder, '(');
|
this.removeCharacter(nameBuilder, '(');
|
||||||
this.removeCharacter(nameBuilder, ')');
|
this.removeCharacter(nameBuilder, ')');
|
||||||
} else {
|
} else {
|
||||||
//veryfying if the name is a table
|
//veryfying if the name is a table
|
||||||
int tableStartIndex = 0;
|
int tableStartIndex = 0;
|
||||||
List<Integer> lengths = new ArrayList<Integer>(3);//3 dimensions will be enough in most cases
|
List<Integer> lengths = new ArrayList<Integer>(3);//3 dimensions will be enough in most cases
|
||||||
do {
|
do {
|
||||||
tableStartIndex = nameBuilder.indexOf("[");
|
tableStartIndex = nameBuilder.indexOf("[");
|
||||||
if(tableStartIndex > 0) {
|
if (tableStartIndex > 0) {
|
||||||
int tableStopIndex = nameBuilder.indexOf("]");
|
int tableStopIndex = nameBuilder.indexOf("]");
|
||||||
if(tableStopIndex < 0) {
|
if (tableStopIndex < 0) {
|
||||||
throw new BlenderFileException("Invalid structure name: " + name);
|
throw new BlenderFileException("Invalid structure name: " + name);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
lengths.add(Integer.valueOf(nameBuilder.substring(tableStartIndex + 1, tableStopIndex)));
|
lengths.add(Integer.valueOf(nameBuilder.substring(tableStartIndex + 1, tableStopIndex)));
|
||||||
} catch(NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new BlenderFileException("Invalid structure name caused by invalid table length: " + name, e);
|
throw new BlenderFileException("Invalid structure name caused by invalid table length: " + name, e);
|
||||||
}
|
}
|
||||||
nameBuilder.delete(tableStartIndex, tableStopIndex + 1);
|
nameBuilder.delete(tableStartIndex, tableStopIndex + 1);
|
||||||
}
|
}
|
||||||
} while(tableStartIndex > 0);
|
} while (tableStartIndex > 0);
|
||||||
if(!lengths.isEmpty()) {
|
if (!lengths.isEmpty()) {
|
||||||
tableSizes = new int[lengths.size()];
|
tableSizes = new int[lengths.size()];
|
||||||
for(int i = 0; i < tableSizes.length; ++i) {
|
for (int i = 0; i < tableSizes.length; ++i) {
|
||||||
tableSizes[i] = lengths.get(i).intValue();
|
tableSizes[i] = lengths.get(i).intValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
name = nameBuilder.toString();
|
name = nameBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method removes the required character from the text.
|
* This method removes the required character from the text.
|
||||||
* @param text
|
* @param text
|
||||||
* the text we remove characters from
|
* the text we remove characters from
|
||||||
* @param toRemove
|
* @param toRemove
|
||||||
* the character to be removed
|
* the character to be removed
|
||||||
*/
|
*/
|
||||||
private void removeCharacter(StringBuilder text, char toRemove) {
|
private void removeCharacter(StringBuilder text, char toRemove) {
|
||||||
for(int i = 0; i < text.length(); ++i) {
|
for (int i = 0; i < text.length(); ++i) {
|
||||||
if(text.charAt(i) == toRemove) {
|
if (text.charAt(i) == toRemove) {
|
||||||
text.deleteCharAt(i);
|
text.deleteCharAt(i);
|
||||||
--i;
|
--i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method removes all whitespaces from the text.
|
* This method removes all whitespaces from the text.
|
||||||
* @param text
|
* @param text
|
||||||
* the text we remove whitespaces from
|
* the text we remove whitespaces from
|
||||||
*/
|
*/
|
||||||
private void removeWhitespaces(StringBuilder text) {
|
private void removeWhitespaces(StringBuilder text) {
|
||||||
for(int i = 0; i < text.length(); ++i) {
|
for (int i = 0; i < text.length(); ++i) {
|
||||||
if(Character.isWhitespace(text.charAt(i))) {
|
if (Character.isWhitespace(text.charAt(i))) {
|
||||||
text.deleteCharAt(i);
|
text.deleteCharAt(i);
|
||||||
--i;
|
--i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
if(function) {
|
if (function) {
|
||||||
result.append('(');
|
result.append('(');
|
||||||
}
|
}
|
||||||
for(int i = 0; i < pointerLevel; ++i) {
|
for (int i = 0; i < pointerLevel; ++i) {
|
||||||
result.append('*');
|
result.append('*');
|
||||||
}
|
}
|
||||||
result.append(name);
|
result.append(name);
|
||||||
if(tableSizes != null) {
|
if (tableSizes != null) {
|
||||||
for(int i = 0; i < tableSizes.length; ++i) {
|
for (int i = 0; i < tableSizes.length; ++i) {
|
||||||
result.append('[').append(tableSizes[i]).append(']');
|
result.append('[').append(tableSizes[i]).append(']');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(function) {
|
if (function) {
|
||||||
result.append(")()");
|
result.append(")()");
|
||||||
}
|
}
|
||||||
//insert appropriate amount of spaces to format the output corrently
|
//insert appropriate amount of spaces to format the output corrently
|
||||||
int nameLength = result.length();
|
int nameLength = result.length();
|
||||||
result.append(' ');//at least one space is a must
|
result.append(' ');//at least one space is a must
|
||||||
for(int i = 1; i < NAME_LENGTH - nameLength; ++i) {//we start from i=1 because one space is already added
|
for (int i = 1; i < NAME_LENGTH - nameLength; ++i) {//we start from i=1 because one space is already added
|
||||||
result.append(' ');
|
result.append(' ');
|
||||||
}
|
}
|
||||||
result.append(type);
|
result.append(type);
|
||||||
nameLength = result.length();
|
nameLength = result.length();
|
||||||
for(int i = 0; i < NAME_LENGTH + TYPE_LENGTH - nameLength; ++i) {
|
for (int i = 0; i < NAME_LENGTH + TYPE_LENGTH - nameLength; ++i) {
|
||||||
result.append(' ');
|
result.append(' ');
|
||||||
}
|
}
|
||||||
if(value instanceof Character) {
|
if (value instanceof Character) {
|
||||||
result.append(" = ").append((int)((Character)value).charValue());
|
result.append(" = ").append((int) ((Character) value).charValue());
|
||||||
} else {
|
} else {
|
||||||
result.append(" = ").append(value != null ? value.toString() : "null");
|
result.append(" = ").append(value != null ? value.toString() : "null");
|
||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -41,161 +41,160 @@ import com.jme3.scene.plugins.blender.utils.DataRepository;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class FileBlockHeader {
|
public class FileBlockHeader {
|
||||||
public static final int BLOCK_TE00 = 'T' << 24 | 'E' << 16; //TE00
|
|
||||||
public static final int BLOCK_ME00 = 'M' << 24 | 'E' << 16; //ME00
|
|
||||||
public static final int BLOCK_SR00 = 'S' << 24 | 'R' << 16; //SR00
|
|
||||||
public static final int BLOCK_CA00 = 'C' << 24 | 'A' << 16; //CA00
|
|
||||||
public static final int BLOCK_LA00 = 'L' << 24 | 'A' << 16; //LA00
|
|
||||||
public static final int BLOCK_OB00 = 'O' << 24 | 'B' << 16; //OB00
|
|
||||||
public static final int BLOCK_MA00 = 'M' << 24 | 'A' << 16; //MA00
|
|
||||||
public static final int BLOCK_SC00 = 'S' << 24 | 'C' << 16; //SC00
|
|
||||||
public static final int BLOCK_WO00 = 'W' << 24 | 'O' << 16; //WO00
|
|
||||||
public static final int BLOCK_TX00 = 'T' << 24 | 'X' << 16; //TX00
|
|
||||||
public static final int BLOCK_IP00 = 'I' << 24 | 'P' << 16; //IP00
|
|
||||||
public static final int BLOCK_AC00 = 'A' << 24 | 'C' << 16; //AC00
|
|
||||||
|
|
||||||
public static final int BLOCK_GLOB = 'G' << 24 | 'L' << 16 | 'O' << 8 | 'B'; //GLOB
|
public static final int BLOCK_TE00 = 'T' << 24 | 'E' << 16; //TE00
|
||||||
public static final int BLOCK_REND = 'R' << 24 | 'E' << 16 | 'N' << 8 | 'D'; //REND
|
public static final int BLOCK_ME00 = 'M' << 24 | 'E' << 16; //ME00
|
||||||
public static final int BLOCK_DATA = 'D' << 24 | 'A' << 16 | 'T' << 8 | 'A'; //DATA
|
public static final int BLOCK_SR00 = 'S' << 24 | 'R' << 16; //SR00
|
||||||
public static final int BLOCK_DNA1 = 'D' << 24 | 'N' << 16 | 'A' << 8 | '1'; //DNA1
|
public static final int BLOCK_CA00 = 'C' << 24 | 'A' << 16; //CA00
|
||||||
public static final int BLOCK_ENDB = 'E' << 24 | 'N' << 16 | 'D' << 8 | 'B'; //ENDB
|
public static final int BLOCK_LA00 = 'L' << 24 | 'A' << 16; //LA00
|
||||||
|
public static final int BLOCK_OB00 = 'O' << 24 | 'B' << 16; //OB00
|
||||||
|
public static final int BLOCK_MA00 = 'M' << 24 | 'A' << 16; //MA00
|
||||||
|
public static final int BLOCK_SC00 = 'S' << 24 | 'C' << 16; //SC00
|
||||||
|
public static final int BLOCK_WO00 = 'W' << 24 | 'O' << 16; //WO00
|
||||||
|
public static final int BLOCK_TX00 = 'T' << 24 | 'X' << 16; //TX00
|
||||||
|
public static final int BLOCK_IP00 = 'I' << 24 | 'P' << 16; //IP00
|
||||||
|
public static final int BLOCK_AC00 = 'A' << 24 | 'C' << 16; //AC00
|
||||||
|
public static final int BLOCK_GLOB = 'G' << 24 | 'L' << 16 | 'O' << 8 | 'B'; //GLOB
|
||||||
|
public static final int BLOCK_REND = 'R' << 24 | 'E' << 16 | 'N' << 8 | 'D'; //REND
|
||||||
|
public static final int BLOCK_DATA = 'D' << 24 | 'A' << 16 | 'T' << 8 | 'A'; //DATA
|
||||||
|
public static final int BLOCK_DNA1 = 'D' << 24 | 'N' << 16 | 'A' << 8 | '1'; //DNA1
|
||||||
|
public static final int BLOCK_ENDB = 'E' << 24 | 'N' << 16 | 'D' << 8 | 'B'; //ENDB
|
||||||
|
/** Identifier of the file-block [4 bytes]. */
|
||||||
|
private int code;
|
||||||
|
/** Total length of the data after the file-block-header [4 bytes]. */
|
||||||
|
private int size;
|
||||||
|
/**
|
||||||
|
* Memory address the structure was located when written to disk [4 or 8 bytes (defined in file header as a pointer
|
||||||
|
* size)].
|
||||||
|
*/
|
||||||
|
private long oldMemoryAddress;
|
||||||
|
/** Index of the SDNA structure [4 bytes]. */
|
||||||
|
private int sdnaIndex;
|
||||||
|
/** Number of structure located in this file-block [4 bytes]. */
|
||||||
|
private int count;
|
||||||
|
/** Start position of the block's data in the stream. */
|
||||||
|
private int blockPosition;
|
||||||
|
|
||||||
/** Identifier of the file-block [4 bytes]. */
|
/**
|
||||||
private int code;
|
* Constructor. Loads the block header from the given stream during instance creation.
|
||||||
/** Total length of the data after the file-block-header [4 bytes]. */
|
* @param inputStream
|
||||||
private int size;
|
* the stream we read the block header from
|
||||||
/**
|
* @param dataRepository
|
||||||
* Memory address the structure was located when written to disk [4 or 8 bytes (defined in file header as a pointer
|
* the data repository
|
||||||
* size)].
|
* @throws BlenderFileException
|
||||||
*/
|
* this exception is thrown when the pointer size is neither 4 nor 8
|
||||||
private long oldMemoryAddress;
|
*/
|
||||||
/** Index of the SDNA structure [4 bytes]. */
|
public FileBlockHeader(BlenderInputStream inputStream, DataRepository dataRepository) throws BlenderFileException {
|
||||||
private int sdnaIndex;
|
inputStream.alignPosition(4);
|
||||||
/** Number of structure located in this file-block [4 bytes]. */
|
code = inputStream.readByte() << 24 | inputStream.readByte() << 16
|
||||||
private int count;
|
| inputStream.readByte() << 8 | inputStream.readByte();
|
||||||
/** Start position of the block's data in the stream. */
|
size = inputStream.readInt();
|
||||||
private int blockPosition;
|
oldMemoryAddress = inputStream.readPointer();
|
||||||
|
sdnaIndex = inputStream.readInt();
|
||||||
|
count = inputStream.readInt();
|
||||||
|
blockPosition = inputStream.getPosition();
|
||||||
|
if (FileBlockHeader.BLOCK_DNA1 == code) {
|
||||||
|
dataRepository.setBlockData(new DnaBlockData(inputStream, dataRepository));
|
||||||
|
} else {
|
||||||
|
inputStream.setPosition(blockPosition + size);
|
||||||
|
dataRepository.addFileBlockHeader(Long.valueOf(oldMemoryAddress), this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Loads the block header from the given stream during instance creation.
|
* This method returns the structure described by the header filled with appropriate data.
|
||||||
* @param inputStream
|
* @param dataRepository
|
||||||
* the stream we read the block header from
|
* the data repository
|
||||||
* @param dataRepository
|
* @return structure filled with data
|
||||||
* the data repository
|
* @throws BlenderFileException
|
||||||
* @throws BlenderFileException
|
*/
|
||||||
* this exception is thrown when the pointer size is neither 4 nor 8
|
public Structure getStructure(DataRepository dataRepository) throws BlenderFileException {
|
||||||
*/
|
dataRepository.getInputStream().setPosition(blockPosition);
|
||||||
public FileBlockHeader(BlenderInputStream inputStream, DataRepository dataRepository) throws BlenderFileException {
|
Structure structure = dataRepository.getDnaBlockData().getStructure(sdnaIndex);
|
||||||
inputStream.alignPosition(4);
|
structure.fill(dataRepository.getInputStream());
|
||||||
code = inputStream.readByte() << 24 | inputStream.readByte() << 16 |
|
return structure;
|
||||||
inputStream.readByte() << 8 | inputStream.readByte();
|
}
|
||||||
size = inputStream.readInt();
|
|
||||||
oldMemoryAddress = inputStream.readPointer();
|
|
||||||
sdnaIndex = inputStream.readInt();
|
|
||||||
count = inputStream.readInt();
|
|
||||||
blockPosition = inputStream.getPosition();
|
|
||||||
if(FileBlockHeader.BLOCK_DNA1 == code) {
|
|
||||||
dataRepository.setBlockData(new DnaBlockData(inputStream, dataRepository));
|
|
||||||
} else {
|
|
||||||
inputStream.setPosition(blockPosition + size);
|
|
||||||
dataRepository.addFileBlockHeader(Long.valueOf(oldMemoryAddress), this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the structure described by the header filled with appropriate data.
|
* This method returns the code of this data block.
|
||||||
* @param dataRepository
|
* @return the code of this data block
|
||||||
* the data repository
|
*/
|
||||||
* @return structure filled with data
|
public int getCode() {
|
||||||
* @throws BlenderFileException
|
return code;
|
||||||
*/
|
}
|
||||||
public Structure getStructure(DataRepository dataRepository) throws BlenderFileException {
|
|
||||||
dataRepository.getInputStream().setPosition(blockPosition);
|
|
||||||
Structure structure = dataRepository.getDnaBlockData().getStructure(sdnaIndex);
|
|
||||||
structure.fill(dataRepository.getInputStream());
|
|
||||||
return structure;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the code of this data block.
|
* This method returns the size of the data stored in this block.
|
||||||
* @return the code of this data block
|
* @return the size of the data stored in this block
|
||||||
*/
|
*/
|
||||||
public int getCode() {
|
public int getSize() {
|
||||||
return code;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the size of the data stored in this block.
|
* This method returns the memory address.
|
||||||
* @return the size of the data stored in this block
|
* @return the memory address
|
||||||
*/
|
*/
|
||||||
public int getSize() {
|
public long getOldMemoryAddress() {
|
||||||
return size;
|
return oldMemoryAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the memory address.
|
* This method returns the sdna index.
|
||||||
* @return the memory address
|
* @return the sdna index
|
||||||
*/
|
*/
|
||||||
public long getOldMemoryAddress() {
|
public int getSdnaIndex() {
|
||||||
return oldMemoryAddress;
|
return sdnaIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the sdna index.
|
* This data returns the number of structure stored in the data block after this header.
|
||||||
* @return the sdna index
|
* @return the number of structure stored in the data block after this header
|
||||||
*/
|
*/
|
||||||
public int getSdnaIndex() {
|
public int getCount() {
|
||||||
return sdnaIndex;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This data returns the number of structure stored in the data block after this header.
|
* This method returns the start position of the data block in the blend file stream.
|
||||||
* @return the number of structure stored in the data block after this header
|
* @return the start position of the data block
|
||||||
*/
|
*/
|
||||||
public int getCount() {
|
public int getBlockPosition() {
|
||||||
return count;
|
return blockPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the start position of the data block in the blend file stream.
|
* This method indicates if the block is the last block in the file.
|
||||||
* @return the start position of the data block
|
* @return true if this block is the last one in the file nad false otherwise
|
||||||
*/
|
*/
|
||||||
public int getBlockPosition() {
|
public boolean isLastBlock() {
|
||||||
return blockPosition;
|
return FileBlockHeader.BLOCK_ENDB == code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method indicates if the block is the last block in the file.
|
* This method indicates if the block is the SDNA block.
|
||||||
* @return true if this block is the last one in the file nad false otherwise
|
* @return true if this block is the SDNA block and false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean isLastBlock() {
|
public boolean isDnaBlock() {
|
||||||
return FileBlockHeader.BLOCK_ENDB == code;
|
return FileBlockHeader.BLOCK_DNA1 == code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* This method indicates if the block is the SDNA block.
|
public String toString() {
|
||||||
* @return true if this block is the SDNA block and false otherwise
|
return "FILE BLOCK HEADER [" + this.codeToString(code) + " : " + size + " : " + oldMemoryAddress + " : " + sdnaIndex + " : " + count + "]";
|
||||||
*/
|
}
|
||||||
public boolean isDnaBlock() {
|
|
||||||
return FileBlockHeader.BLOCK_DNA1 == code;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public String toString() {
|
* This method transforms the coded bloch id into a string value.
|
||||||
return "FILE BLOCK HEADER [" + this.codeToString(code) + " : " + size + " : " + oldMemoryAddress + " : " + sdnaIndex + " : " + count + "]";
|
* @param code
|
||||||
}
|
* the id of the block
|
||||||
|
* @return the string value of the block id
|
||||||
/**
|
*/
|
||||||
* This method transforms the coded bloch id into a string value.
|
protected String codeToString(int code) {
|
||||||
* @param code
|
char c1 = (char) ((code & 0xFF000000) >> 24);
|
||||||
* the id of the block
|
char c2 = (char) ((code & 0xFF0000) >> 16);
|
||||||
* @return the string value of the block id
|
char c3 = (char) ((code & 0xFF00) >> 8);
|
||||||
*/
|
char c4 = (char) (code & 0xFF);
|
||||||
protected String codeToString(int code) {
|
return String.valueOf(c1) + c2 + c3 + c4;
|
||||||
char c1 = (char)((code & 0xFF000000) >> 24);
|
}
|
||||||
char c2 = (char)((code & 0xFF0000) >> 16);
|
|
||||||
char c3 = (char)((code & 0xFF00) >> 8);
|
|
||||||
char c4 = (char)(code & 0xFF);
|
|
||||||
return String.valueOf(c1) + c2 + c3 + c4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -46,266 +46,269 @@ import com.jme3.scene.plugins.blender.utils.Pointer;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class Structure implements Cloneable {
|
public class Structure implements Cloneable {
|
||||||
/** The data repository. */
|
|
||||||
private DataRepository dataRepository;
|
|
||||||
/** The address of the block that fills the structure. */
|
|
||||||
private transient Long oldMemoryAddress;
|
|
||||||
/** The type of the structure. */
|
|
||||||
private String type;
|
|
||||||
/**
|
|
||||||
* The fields of the structure. Each field consists of a pair: name-type.
|
|
||||||
*/
|
|
||||||
private Field[] fields;
|
|
||||||
|
|
||||||
/**
|
/** The data repository. */
|
||||||
* Constructor that copies the data of the structure.
|
private DataRepository dataRepository;
|
||||||
* @param structure
|
/** The address of the block that fills the structure. */
|
||||||
* the structure to copy.
|
private transient Long oldMemoryAddress;
|
||||||
* @param dataRepository
|
/** The type of the structure. */
|
||||||
* the data repository of the structure
|
private String type;
|
||||||
* @throws CloneNotSupportedException
|
/**
|
||||||
* this exception should never be thrown
|
* The fields of the structure. Each field consists of a pair: name-type.
|
||||||
*/
|
*/
|
||||||
private Structure(Structure structure, DataRepository dataRepository) throws CloneNotSupportedException {
|
private Field[] fields;
|
||||||
type = structure.type;
|
|
||||||
fields = new Field[structure.fields.length];
|
|
||||||
for(int i = 0; i < fields.length; ++i) {
|
|
||||||
fields[i] = (Field)structure.fields[i].clone();
|
|
||||||
}
|
|
||||||
this.dataRepository = dataRepository;
|
|
||||||
this.oldMemoryAddress = structure.oldMemoryAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Loads the structure from the given stream during instance creation.
|
* Constructor that copies the data of the structure.
|
||||||
* @param inputStream
|
* @param structure
|
||||||
* the stream we read the structure from
|
* the structure to copy.
|
||||||
* @param names
|
* @param dataRepository
|
||||||
* the names from which the name of structure and its fields will be taken
|
* the data repository of the structure
|
||||||
* @param types
|
* @throws CloneNotSupportedException
|
||||||
* the names of types for the structure
|
* this exception should never be thrown
|
||||||
* @param dataRepository
|
*/
|
||||||
* the data repository
|
private Structure(Structure structure, DataRepository dataRepository) throws CloneNotSupportedException {
|
||||||
* @throws BlenderFileException
|
type = structure.type;
|
||||||
* this exception occurs if the amount of fields, defined in the file, is negative
|
fields = new Field[structure.fields.length];
|
||||||
*/
|
for (int i = 0; i < fields.length; ++i) {
|
||||||
public Structure(BlenderInputStream inputStream, String[] names, String[] types, DataRepository dataRepository) throws BlenderFileException {
|
fields[i] = (Field) structure.fields[i].clone();
|
||||||
int nameIndex = inputStream.readShort();
|
}
|
||||||
type = types[nameIndex];
|
this.dataRepository = dataRepository;
|
||||||
this.dataRepository = dataRepository;
|
this.oldMemoryAddress = structure.oldMemoryAddress;
|
||||||
int fieldsAmount = inputStream.readShort();
|
}
|
||||||
if(fieldsAmount < 0) {
|
|
||||||
throw new BlenderFileException("The amount of fields of " + this.type + " structure cannot be negative!");
|
|
||||||
}
|
|
||||||
if(fieldsAmount > 0) {
|
|
||||||
fields = new Field[fieldsAmount];
|
|
||||||
for(int i = 0; i < fieldsAmount; ++i) {
|
|
||||||
int typeIndex = inputStream.readShort();
|
|
||||||
nameIndex = inputStream.readShort();
|
|
||||||
fields[i] = new Field(names[nameIndex], types[typeIndex], dataRepository);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.oldMemoryAddress = Long.valueOf(-1L);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method fills the structure with data.
|
* Constructor. Loads the structure from the given stream during instance creation.
|
||||||
* @param inputStream
|
* @param inputStream
|
||||||
* the stream we read data from, its read cursor should be placed at the start position of the data for the
|
* the stream we read the structure from
|
||||||
* structure
|
* @param names
|
||||||
* @throws BlenderFileException
|
* the names from which the name of structure and its fields will be taken
|
||||||
* an exception is thrown when the blend file is somehow invalid or corrupted
|
* @param types
|
||||||
*/
|
* the names of types for the structure
|
||||||
public void fill(BlenderInputStream inputStream) throws BlenderFileException {
|
* @param dataRepository
|
||||||
int position = inputStream.getPosition();
|
* the data repository
|
||||||
inputStream.setPosition(position - 8 - inputStream.getPointerSize());
|
* @throws BlenderFileException
|
||||||
this.oldMemoryAddress = Long.valueOf(inputStream.readPointer());
|
* this exception occurs if the amount of fields, defined in the file, is negative
|
||||||
inputStream.setPosition(position);
|
*/
|
||||||
for(Field field : fields) {
|
public Structure(BlenderInputStream inputStream, String[] names, String[] types, DataRepository dataRepository) throws BlenderFileException {
|
||||||
field.fill(inputStream);
|
int nameIndex = inputStream.readShort();
|
||||||
}
|
type = types[nameIndex];
|
||||||
}
|
this.dataRepository = dataRepository;
|
||||||
|
int fieldsAmount = inputStream.readShort();
|
||||||
|
if (fieldsAmount < 0) {
|
||||||
|
throw new BlenderFileException("The amount of fields of " + this.type + " structure cannot be negative!");
|
||||||
|
}
|
||||||
|
if (fieldsAmount > 0) {
|
||||||
|
fields = new Field[fieldsAmount];
|
||||||
|
for (int i = 0; i < fieldsAmount; ++i) {
|
||||||
|
int typeIndex = inputStream.readShort();
|
||||||
|
nameIndex = inputStream.readShort();
|
||||||
|
fields[i] = new Field(names[nameIndex], types[typeIndex], dataRepository);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.oldMemoryAddress = Long.valueOf(-1L);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the value of the filed with a given name.
|
* This method fills the structure with data.
|
||||||
* @param fieldName
|
* @param inputStream
|
||||||
* the name of the field
|
* the stream we read data from, its read cursor should be placed at the start position of the data for the
|
||||||
* @return the value of the field or null if no field with a given name is found
|
* structure
|
||||||
*/
|
* @throws BlenderFileException
|
||||||
public Object getFieldValue(String fieldName) {
|
* an exception is thrown when the blend file is somehow invalid or corrupted
|
||||||
for(Field field : fields) {
|
*/
|
||||||
if(field.name.equalsIgnoreCase(fieldName)) {
|
public void fill(BlenderInputStream inputStream) throws BlenderFileException {
|
||||||
return field.value;
|
int position = inputStream.getPosition();
|
||||||
}
|
inputStream.setPosition(position - 8 - inputStream.getPointerSize());
|
||||||
}
|
this.oldMemoryAddress = Long.valueOf(inputStream.readPointer());
|
||||||
return null;
|
inputStream.setPosition(position);
|
||||||
}
|
for (Field field : fields) {
|
||||||
|
field.fill(inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the value of the filed with a given name. The structure is considered to have flat fields
|
* This method returns the value of the filed with a given name.
|
||||||
* only (no substructures).
|
* @param fieldName
|
||||||
* @param fieldName
|
* the name of the field
|
||||||
* the name of the field
|
* @return the value of the field or null if no field with a given name is found
|
||||||
* @return the value of the field or null if no field with a given name is found
|
*/
|
||||||
*/
|
public Object getFieldValue(String fieldName) {
|
||||||
public Object getFlatFieldValue(String fieldName) {
|
for (Field field : fields) {
|
||||||
for(Field field : fields) {
|
if (field.name.equalsIgnoreCase(fieldName)) {
|
||||||
Object value = field.value;
|
return field.value;
|
||||||
if(field.name.equalsIgnoreCase(fieldName)) {
|
}
|
||||||
return value;
|
}
|
||||||
} else if(value instanceof Structure) {
|
return null;
|
||||||
value = ((Structure)value).getFlatFieldValue(fieldName);
|
}
|
||||||
if(value != null) {//we can compare references here, since we use one static object as a NULL field value
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This methos should be used on structures that are of a 'ListBase' type. It creates a List of structures that are
|
* This method returns the value of the filed with a given name. The structure is considered to have flat fields
|
||||||
* held by this structure within the blend file.
|
* only (no substructures).
|
||||||
* @param dataRepository
|
* @param fieldName
|
||||||
* the data repository
|
* the name of the field
|
||||||
* @return a list of filled structures
|
* @return the value of the field or null if no field with a given name is found
|
||||||
* @throws BlenderFileException
|
*/
|
||||||
* this exception is thrown when the blend file structure is somehow invalid or corrupted
|
public Object getFlatFieldValue(String fieldName) {
|
||||||
* @throws IllegalArgumentException
|
for (Field field : fields) {
|
||||||
* this exception is thrown if the type of the structure is not 'ListBase'
|
Object value = field.value;
|
||||||
*/
|
if (field.name.equalsIgnoreCase(fieldName)) {
|
||||||
public List<Structure> evaluateListBase(DataRepository dataRepository) throws BlenderFileException {
|
return value;
|
||||||
if(!"ListBase".equals(this.type)) {
|
} else if (value instanceof Structure) {
|
||||||
throw new IllegalStateException("This structure is not of type: 'ListBase'");
|
value = ((Structure) value).getFlatFieldValue(fieldName);
|
||||||
}
|
if (value != null) {//we can compare references here, since we use one static object as a NULL field value
|
||||||
Pointer first = (Pointer)this.getFieldValue("first");
|
return value;
|
||||||
Pointer last = (Pointer)this.getFieldValue("last");
|
}
|
||||||
long currentAddress = 0;
|
}
|
||||||
long lastAddress = last.getOldMemoryAddress();
|
}
|
||||||
List<Structure> result = new LinkedList<Structure>();
|
return null;
|
||||||
while(currentAddress != lastAddress) {
|
}
|
||||||
currentAddress = first.getOldMemoryAddress();
|
|
||||||
Structure structure = first.fetchData(dataRepository.getInputStream()).get(0);
|
|
||||||
result.add(structure);
|
|
||||||
first = (Pointer)structure.getFlatFieldValue("next");
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the type of the structure.
|
* This methos should be used on structures that are of a 'ListBase' type. It creates a List of structures that are
|
||||||
* @return the type of the structure
|
* held by this structure within the blend file.
|
||||||
*/
|
* @param dataRepository
|
||||||
public String getType() {
|
* the data repository
|
||||||
return type;
|
* @return a list of filled structures
|
||||||
}
|
* @throws BlenderFileException
|
||||||
|
* this exception is thrown when the blend file structure is somehow invalid or corrupted
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* this exception is thrown if the type of the structure is not 'ListBase'
|
||||||
|
*/
|
||||||
|
public List<Structure> evaluateListBase(DataRepository dataRepository) throws BlenderFileException {
|
||||||
|
if (!"ListBase".equals(this.type)) {
|
||||||
|
throw new IllegalStateException("This structure is not of type: 'ListBase'");
|
||||||
|
}
|
||||||
|
Pointer first = (Pointer) this.getFieldValue("first");
|
||||||
|
Pointer last = (Pointer) this.getFieldValue("last");
|
||||||
|
long currentAddress = 0;
|
||||||
|
long lastAddress = last.getOldMemoryAddress();
|
||||||
|
List<Structure> result = new LinkedList<Structure>();
|
||||||
|
while (currentAddress != lastAddress) {
|
||||||
|
currentAddress = first.getOldMemoryAddress();
|
||||||
|
Structure structure = first.fetchData(dataRepository.getInputStream()).get(0);
|
||||||
|
result.add(structure);
|
||||||
|
first = (Pointer) structure.getFlatFieldValue("next");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the amount of fields for the current structure.
|
* This method returns the type of the structure.
|
||||||
* @return the amount of fields for the current structure
|
* @return the type of the structure
|
||||||
*/
|
*/
|
||||||
public int getFieldsAmount() {
|
public String getType() {
|
||||||
return fields.length;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the field name of the given index.
|
* This method returns the amount of fields for the current structure.
|
||||||
* @param fieldIndex
|
* @return the amount of fields for the current structure
|
||||||
* the index of the field
|
*/
|
||||||
* @return the field name of the given index
|
public int getFieldsAmount() {
|
||||||
*/
|
return fields.length;
|
||||||
public String getFieldName(int fieldIndex) {
|
}
|
||||||
return fields[fieldIndex].name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the field type of the given index.
|
* This method returns the field name of the given index.
|
||||||
* @param fieldIndex
|
* @param fieldIndex
|
||||||
* the index of the field
|
* the index of the field
|
||||||
* @return the field type of the given index
|
* @return the field name of the given index
|
||||||
*/
|
*/
|
||||||
public String getFieldType(int fieldIndex) {
|
public String getFieldName(int fieldIndex) {
|
||||||
return fields[fieldIndex].type;
|
return fields[fieldIndex].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the address of the structure. The strucutre should be filled with data otherwise an exception
|
* This method returns the field type of the given index.
|
||||||
* is thrown.
|
* @param fieldIndex
|
||||||
* @return the address of the feature stored in this structure
|
* the index of the field
|
||||||
*/
|
* @return the field type of the given index
|
||||||
public Long getOldMemoryAddress() {
|
*/
|
||||||
if(oldMemoryAddress.longValue() == -1L) {
|
public String getFieldType(int fieldIndex) {
|
||||||
throw new IllegalStateException("Call the 'fill' method and fill the structure with data first!");
|
return fields[fieldIndex].type;
|
||||||
}
|
}
|
||||||
return oldMemoryAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the name of the structure. If the structure has an ID field then the name is returned.
|
* This method returns the address of the structure. The strucutre should be filled with data otherwise an exception
|
||||||
* Otherwise the name does not exists and the method returns null.
|
* is thrown.
|
||||||
* @return the name of the structure read from the ID field or null
|
* @return the address of the feature stored in this structure
|
||||||
*/
|
*/
|
||||||
public String getName() {
|
public Long getOldMemoryAddress() {
|
||||||
Structure id = (Structure)this.getFieldValue("ID");
|
if (oldMemoryAddress.longValue() == -1L) {
|
||||||
return id == null ? null : id.getFieldValue("name").toString().substring(2);//blender adds 2-charactes as a name prefix
|
throw new IllegalStateException("Call the 'fill' method and fill the structure with data first!");
|
||||||
}
|
}
|
||||||
|
return oldMemoryAddress;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public String toString() {
|
* This method returns the name of the structure. If the structure has an ID field then the name is returned.
|
||||||
StringBuilder result = new StringBuilder("struct ").append(type).append(" {\n");
|
* Otherwise the name does not exists and the method returns null.
|
||||||
for(int i = 0; i < fields.length; ++i) {
|
* @return the name of the structure read from the ID field or null
|
||||||
result.append(fields[i].toString()).append('\n');
|
*/
|
||||||
}
|
public String getName() {
|
||||||
return result.append('}').toString();
|
Structure id = (Structure) this.getFieldValue("ID");
|
||||||
}
|
return id == null ? null : id.getFieldValue("name").toString().substring(2);//blender adds 2-charactes as a name prefix
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object clone() throws CloneNotSupportedException {
|
public String toString() {
|
||||||
return new Structure(this, dataRepository);
|
StringBuilder result = new StringBuilder("struct ").append(type).append(" {\n");
|
||||||
}
|
for (int i = 0; i < fields.length; ++i) {
|
||||||
|
result.append(fields[i].toString()).append('\n');
|
||||||
|
}
|
||||||
|
return result.append('}').toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* This enum enumerates all known data types that can be found in the blend file.
|
public Object clone() throws CloneNotSupportedException {
|
||||||
* @author Marcin Roguski
|
return new Structure(this, dataRepository);
|
||||||
*/
|
}
|
||||||
/*package*/static enum DataType {
|
|
||||||
CHARACTER, SHORT, INTEGER, LONG, FLOAT, DOUBLE, VOID, STRUCTURE, POINTER;
|
|
||||||
|
|
||||||
/** The map containing the known primary types. */
|
/**
|
||||||
private static final Map<String, DataType> PRIMARY_TYPES = new HashMap<String, DataType>(10);
|
* This enum enumerates all known data types that can be found in the blend file.
|
||||||
static {
|
* @author Marcin Roguski
|
||||||
PRIMARY_TYPES.put("char", CHARACTER);
|
*/
|
||||||
PRIMARY_TYPES.put("uchar", CHARACTER);
|
/*package*/
|
||||||
PRIMARY_TYPES.put("short", SHORT);
|
static enum DataType {
|
||||||
PRIMARY_TYPES.put("ushort", SHORT);
|
|
||||||
PRIMARY_TYPES.put("int", INTEGER);
|
|
||||||
PRIMARY_TYPES.put("long", LONG);
|
|
||||||
PRIMARY_TYPES.put("ulong", LONG);
|
|
||||||
PRIMARY_TYPES.put("float", FLOAT);
|
|
||||||
PRIMARY_TYPES.put("double", DOUBLE);
|
|
||||||
PRIMARY_TYPES.put("void", VOID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
CHARACTER, SHORT, INTEGER, LONG, FLOAT, DOUBLE, VOID, STRUCTURE, POINTER;
|
||||||
* This method returns the data type that is appropriate to the given type name. WARNING! The type recognition
|
/** The map containing the known primary types. */
|
||||||
* is case sensitive!
|
private static final Map<String, DataType> PRIMARY_TYPES = new HashMap<String, DataType>(10);
|
||||||
* @param type
|
|
||||||
* the type name of the data
|
static {
|
||||||
* @param dataRepository
|
PRIMARY_TYPES.put("char", CHARACTER);
|
||||||
* the data repository
|
PRIMARY_TYPES.put("uchar", CHARACTER);
|
||||||
* @return appropriate enum value to the given type name
|
PRIMARY_TYPES.put("short", SHORT);
|
||||||
* @throws BlenderFileException
|
PRIMARY_TYPES.put("ushort", SHORT);
|
||||||
* this exception is thrown if the given type name does not exist in the blend file
|
PRIMARY_TYPES.put("int", INTEGER);
|
||||||
*/
|
PRIMARY_TYPES.put("long", LONG);
|
||||||
public static DataType getDataType(String type, DataRepository dataRepository) throws BlenderFileException {
|
PRIMARY_TYPES.put("ulong", LONG);
|
||||||
DataType result = PRIMARY_TYPES.get(type);
|
PRIMARY_TYPES.put("float", FLOAT);
|
||||||
if(result != null) {
|
PRIMARY_TYPES.put("double", DOUBLE);
|
||||||
return result;
|
PRIMARY_TYPES.put("void", VOID);
|
||||||
}
|
}
|
||||||
if(dataRepository.getDnaBlockData().hasStructure(type)) {
|
|
||||||
return STRUCTURE;
|
/**
|
||||||
}
|
* This method returns the data type that is appropriate to the given type name. WARNING! The type recognition
|
||||||
throw new BlenderFileException("Unknown data type: " + type);
|
* is case sensitive!
|
||||||
}
|
* @param type
|
||||||
}
|
* the type name of the data
|
||||||
|
* @param dataRepository
|
||||||
|
* the data repository
|
||||||
|
* @return appropriate enum value to the given type name
|
||||||
|
* @throws BlenderFileException
|
||||||
|
* this exception is thrown if the given type name does not exist in the blend file
|
||||||
|
*/
|
||||||
|
public static DataType getDataType(String type, DataRepository dataRepository) throws BlenderFileException {
|
||||||
|
DataType result = PRIMARY_TYPES.get(type);
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (dataRepository.getDnaBlockData().hasStructure(type)) {
|
||||||
|
return STRUCTURE;
|
||||||
|
}
|
||||||
|
throw new BlenderFileException("Unknown data type: " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,39 +36,41 @@ package com.jme3.scene.plugins.blender.exception;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class BlenderFileException extends Exception {
|
public class BlenderFileException extends Exception {
|
||||||
private static final long serialVersionUID = 7573482836437866767L;
|
|
||||||
|
|
||||||
/**
|
private static final long serialVersionUID = 7573482836437866767L;
|
||||||
* Constructor. Creates an exception with no description.
|
|
||||||
*/
|
|
||||||
public BlenderFileException() {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Creates an exception containing the given message.
|
* Constructor. Creates an exception with no description.
|
||||||
* @param message
|
*/
|
||||||
* the message describing the problem that occured
|
public BlenderFileException() {
|
||||||
*/
|
}
|
||||||
public BlenderFileException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Creates an exception that is based upon other thrown object. It contains the whole stacktrace then.
|
* Constructor. Creates an exception containing the given message.
|
||||||
* @param throwable
|
* @param message
|
||||||
* an exception/error that occured
|
* the message describing the problem that occured
|
||||||
*/
|
*/
|
||||||
public BlenderFileException(Throwable throwable) {
|
public BlenderFileException(String message) {
|
||||||
super(throwable);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Creates an exception with both a message and stacktrace.
|
* Constructor. Creates an exception that is based upon other thrown object. It contains the whole stacktrace then.
|
||||||
* @param message
|
* @param throwable
|
||||||
* the message describing the problem that occured
|
* an exception/error that occured
|
||||||
* @param throwable
|
*/
|
||||||
* an exception/error that occured
|
public BlenderFileException(Throwable throwable) {
|
||||||
*/
|
super(throwable);
|
||||||
public BlenderFileException(String message, Throwable throwable) {
|
}
|
||||||
super(message, throwable);
|
|
||||||
}
|
/**
|
||||||
|
* Constructor. Creates an exception with both a message and stacktrace.
|
||||||
|
* @param message
|
||||||
|
* the message describing the problem that occured
|
||||||
|
* @param throwable
|
||||||
|
* an exception/error that occured
|
||||||
|
*/
|
||||||
|
public BlenderFileException(String message, Throwable throwable) {
|
||||||
|
super(message, throwable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,87 +46,87 @@ import com.jme3.scene.plugins.blender.utils.BlenderInputStream;
|
|||||||
import com.jme3.scene.plugins.blender.utils.DataRepository;
|
import com.jme3.scene.plugins.blender.utils.DataRepository;
|
||||||
import com.jme3.scene.plugins.blender.utils.Pointer;
|
import com.jme3.scene.plugins.blender.utils.Pointer;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class defines the methods to calculate certain aspects of animation and armature functionalities.
|
* This class defines the methods to calculate certain aspects of animation and armature functionalities.
|
||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class ArmatureHelper extends com.jme3.scene.plugins.blender.helpers.v249.ArmatureHelper {
|
public class ArmatureHelper extends com.jme3.scene.plugins.blender.helpers.v249.ArmatureHelper {
|
||||||
private static final Logger LOGGER = Logger.getLogger(ArmatureHelper.class.getName());
|
|
||||||
|
|
||||||
/**
|
private static final Logger LOGGER = Logger.getLogger(ArmatureHelper.class.getName());
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
|
||||||
* different blender versions.
|
|
||||||
* @param blenderVersion
|
|
||||||
* the version read from the blend file
|
|
||||||
*/
|
|
||||||
public ArmatureHelper(String blenderVersion) {
|
|
||||||
super(blenderVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public BoneTrack[] getTracks(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException {
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
if(blenderVersion<250) {
|
* different blender versions.
|
||||||
return super.getTracks(actionStructure, dataRepository, objectName, animationName);
|
* @param blenderVersion
|
||||||
}
|
* the version read from the blend file
|
||||||
LOGGER.log(Level.INFO, "Getting tracks!");
|
*/
|
||||||
int fps = dataRepository.getBlenderKey().getFps();
|
public ArmatureHelper(String blenderVersion) {
|
||||||
int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, animationName);
|
super(blenderVersion);
|
||||||
Structure groups = (Structure)actionStructure.getFieldValue("groups");
|
}
|
||||||
List<Structure> actionGroups = groups.evaluateListBase(dataRepository);//bActionGroup
|
|
||||||
if(actionGroups != null && actionGroups.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) {
|
|
||||||
throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<BoneTrack> tracks = new ArrayList<BoneTrack>();
|
@Override
|
||||||
for(Structure actionGroup : actionGroups) {
|
public BoneTrack[] getTracks(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException {
|
||||||
String name = actionGroup.getFieldValue("name").toString();
|
if (blenderVersion < 250) {
|
||||||
Integer boneIndex = bonesMap.get(name);
|
return super.getTracks(actionStructure, dataRepository, objectName, animationName);
|
||||||
if(boneIndex != null) {
|
}
|
||||||
List<Structure> channels = ((Structure)actionGroup.getFieldValue("channels")).evaluateListBase(dataRepository);
|
LOGGER.log(Level.INFO, "Getting tracks!");
|
||||||
BezierCurve[] bezierCurves = new BezierCurve[channels.size()];
|
int fps = dataRepository.getBlenderKey().getFps();
|
||||||
int channelCounter = 0;
|
int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, animationName);
|
||||||
for(Structure c : channels) {
|
Structure groups = (Structure) actionStructure.getFieldValue("groups");
|
||||||
//reading rna path first
|
List<Structure> actionGroups = groups.evaluateListBase(dataRepository);//bActionGroup
|
||||||
BlenderInputStream bis = dataRepository.getInputStream();
|
if (actionGroups != null && actionGroups.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) {
|
||||||
int currentPosition = bis.getPosition();
|
throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!");
|
||||||
Pointer pRnaPath = (Pointer) c.getFieldValue("rna_path");
|
}
|
||||||
FileBlockHeader dataFileBlock = dataRepository.getFileBlock(pRnaPath.getOldMemoryAddress());
|
|
||||||
bis.setPosition(dataFileBlock.getBlockPosition());
|
|
||||||
String rnaPath = bis.readString();
|
|
||||||
bis.setPosition(currentPosition);
|
|
||||||
int arrayIndex = ((Number)c.getFieldValue("array_index")).intValue();
|
|
||||||
int type = this.getCurveType(rnaPath, arrayIndex);
|
|
||||||
|
|
||||||
Pointer pBezTriple = (Pointer)c.getFieldValue("bezt");
|
List<BoneTrack> tracks = new ArrayList<BoneTrack>();
|
||||||
List<Structure> bezTriples = pBezTriple.fetchData(dataRepository.getInputStream());
|
for (Structure actionGroup : actionGroups) {
|
||||||
bezierCurves[channelCounter++] = new BezierCurve(type, bezTriples, 2);
|
String name = actionGroup.getFieldValue("name").toString();
|
||||||
}
|
Integer boneIndex = bonesMap.get(name);
|
||||||
|
if (boneIndex != null) {
|
||||||
|
List<Structure> channels = ((Structure) actionGroup.getFieldValue("channels")).evaluateListBase(dataRepository);
|
||||||
|
BezierCurve[] bezierCurves = new BezierCurve[channels.size()];
|
||||||
|
int channelCounter = 0;
|
||||||
|
for (Structure c : channels) {
|
||||||
|
//reading rna path first
|
||||||
|
BlenderInputStream bis = dataRepository.getInputStream();
|
||||||
|
int currentPosition = bis.getPosition();
|
||||||
|
Pointer pRnaPath = (Pointer) c.getFieldValue("rna_path");
|
||||||
|
FileBlockHeader dataFileBlock = dataRepository.getFileBlock(pRnaPath.getOldMemoryAddress());
|
||||||
|
bis.setPosition(dataFileBlock.getBlockPosition());
|
||||||
|
String rnaPath = bis.readString();
|
||||||
|
bis.setPosition(currentPosition);
|
||||||
|
int arrayIndex = ((Number) c.getFieldValue("array_index")).intValue();
|
||||||
|
int type = this.getCurveType(rnaPath, arrayIndex);
|
||||||
|
|
||||||
Ipo ipo = new Ipo(bezierCurves);
|
Pointer pBezTriple = (Pointer) c.getFieldValue("bezt");
|
||||||
tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps));
|
List<Structure> bezTriples = pBezTriple.fetchData(dataRepository.getInputStream());
|
||||||
}
|
bezierCurves[channelCounter++] = new BezierCurve(type, bezTriples, 2);
|
||||||
}
|
}
|
||||||
return tracks.toArray(new BoneTrack[tracks.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
Ipo ipo = new Ipo(bezierCurves);
|
||||||
* This method parses the information stored inside the curve rna path and returns the proper type
|
tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps));
|
||||||
* of the curve.
|
}
|
||||||
* @param rnaPath the curve's rna path
|
}
|
||||||
* @param arrayIndex the array index of the stored data
|
return tracks.toArray(new BoneTrack[tracks.size()]);
|
||||||
* @return the type of the curve
|
}
|
||||||
*/
|
|
||||||
protected int getCurveType(String rnaPath, int arrayIndex) {
|
/**
|
||||||
if(rnaPath.endsWith(".location")) {
|
* This method parses the information stored inside the curve rna path and returns the proper type
|
||||||
return Ipo.AC_LOC_X + arrayIndex;
|
* of the curve.
|
||||||
}
|
* @param rnaPath the curve's rna path
|
||||||
if(rnaPath.endsWith(".rotation_quaternion")) {
|
* @param arrayIndex the array index of the stored data
|
||||||
return Ipo.AC_QUAT_W + arrayIndex;
|
* @return the type of the curve
|
||||||
}
|
*/
|
||||||
if(rnaPath.endsWith(".scale")) {
|
protected int getCurveType(String rnaPath, int arrayIndex) {
|
||||||
return Ipo.AC_SIZE_X + arrayIndex;
|
if (rnaPath.endsWith(".location")) {
|
||||||
}
|
return Ipo.AC_LOC_X + arrayIndex;
|
||||||
throw new IllegalStateException("Unknown curve rna path: " + rnaPath);
|
}
|
||||||
}
|
if (rnaPath.endsWith(".rotation_quaternion")) {
|
||||||
|
return Ipo.AC_QUAT_W + arrayIndex;
|
||||||
|
}
|
||||||
|
if (rnaPath.endsWith(".scale")) {
|
||||||
|
return Ipo.AC_SIZE_X + arrayIndex;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("Unknown curve rna path: " + rnaPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,40 +12,41 @@ import com.jme3.scene.plugins.blender.exception.BlenderFileException;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class CameraHelper extends com.jme3.scene.plugins.blender.helpers.v249.CameraHelper {
|
public class CameraHelper extends com.jme3.scene.plugins.blender.helpers.v249.CameraHelper {
|
||||||
private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName());
|
|
||||||
|
|
||||||
/**
|
private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName());
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
|
||||||
* different blender versions.
|
|
||||||
* @param blenderVersion
|
|
||||||
* the version read from the blend file
|
|
||||||
*/
|
|
||||||
public CameraHelper(String blenderVersion) {
|
|
||||||
super(blenderVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public Camera toCamera(Structure structure) throws BlenderFileException {
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
if(blenderVersion<250) {
|
* different blender versions.
|
||||||
return super.toCamera(structure);
|
* @param blenderVersion
|
||||||
}
|
* the version read from the blend file
|
||||||
Camera result = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT);
|
*/
|
||||||
int type = ((Number)structure.getFieldValue("type")).intValue();
|
public CameraHelper(String blenderVersion) {
|
||||||
if(type != 0 && type != 1) {
|
super(blenderVersion);
|
||||||
LOGGER.log(Level.WARNING, "Unknown camera type: " + type + ". Perspective camera is being used!");
|
}
|
||||||
type = 0;
|
|
||||||
}
|
@Override
|
||||||
//type==0 - perspective; type==1 - orthographic; perspective is used as default
|
public Camera toCamera(Structure structure) throws BlenderFileException {
|
||||||
result.setParallelProjection(type == 1);
|
if (blenderVersion < 250) {
|
||||||
float aspect = 0;
|
return super.toCamera(structure);
|
||||||
float clipsta = ((Number)structure.getFieldValue("clipsta")).floatValue();
|
}
|
||||||
float clipend = ((Number)structure.getFieldValue("clipend")).floatValue();
|
Camera result = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT);
|
||||||
if(type == 0) {
|
int type = ((Number) structure.getFieldValue("type")).intValue();
|
||||||
aspect = ((Number)structure.getFieldValue("lens")).floatValue();
|
if (type != 0 && type != 1) {
|
||||||
} else {
|
LOGGER.log(Level.WARNING, "Unknown camera type: {0}. Perspective camera is being used!", type);
|
||||||
aspect = ((Number)structure.getFieldValue("ortho_scale")).floatValue();
|
type = 0;
|
||||||
}
|
}
|
||||||
result.setFrustumPerspective(45, aspect, clipsta, clipend);
|
//type==0 - perspective; type==1 - orthographic; perspective is used as default
|
||||||
return result;
|
result.setParallelProjection(type == 1);
|
||||||
}
|
float aspect = 0;
|
||||||
|
float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue();
|
||||||
|
float clipend = ((Number) structure.getFieldValue("clipend")).floatValue();
|
||||||
|
if (type == 0) {
|
||||||
|
aspect = ((Number) structure.getFieldValue("lens")).floatValue();
|
||||||
|
} else {
|
||||||
|
aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue();
|
||||||
|
}
|
||||||
|
result.setFrustumPerspective(45, aspect, clipsta, clipend);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,27 +11,28 @@ import com.jme3.scene.plugins.blender.utils.DataRepository;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class ConstraintHelper extends com.jme3.scene.plugins.blender.helpers.v249.ConstraintHelper {
|
public class ConstraintHelper extends com.jme3.scene.plugins.blender.helpers.v249.ConstraintHelper {
|
||||||
private static final Logger LOGGER = Logger.getLogger(ConstraintHelper.class.getName());
|
|
||||||
|
|
||||||
/**
|
private static final Logger LOGGER = Logger.getLogger(ConstraintHelper.class.getName());
|
||||||
* Helper constructor. It's main task is to generate the affection functions. These functions are common to all
|
|
||||||
* ConstraintHelper instances. Unfortunately this constructor might grow large. If it becomes too large - I shall
|
|
||||||
* consider refactoring. The constructor parses the given blender version and stores the result. Some
|
|
||||||
* functionalities may differ in different blender versions.
|
|
||||||
* @param blenderVersion
|
|
||||||
* the version read from the blend file
|
|
||||||
*/
|
|
||||||
public ConstraintHelper(String blenderVersion, DataRepository dataRepository) {
|
|
||||||
super(blenderVersion, dataRepository);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void loadConstraints(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException {
|
* Helper constructor. It's main task is to generate the affection functions. These functions are common to all
|
||||||
if(blenderVersion<250) {
|
* ConstraintHelper instances. Unfortunately this constructor might grow large. If it becomes too large - I shall
|
||||||
super.loadConstraints(objectStructure, dataRepository);
|
* consider refactoring. The constructor parses the given blender version and stores the result. Some
|
||||||
} else {
|
* functionalities may differ in different blender versions.
|
||||||
LOGGER.warning("Loading of constraints not yet implemented for version 2.5x !");
|
* @param blenderVersion
|
||||||
//TODO: to implement
|
* the version read from the blend file
|
||||||
}
|
*/
|
||||||
}
|
public ConstraintHelper(String blenderVersion, DataRepository dataRepository) {
|
||||||
|
super(blenderVersion, dataRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadConstraints(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException {
|
||||||
|
if (blenderVersion < 250) {
|
||||||
|
super.loadConstraints(objectStructure, dataRepository);
|
||||||
|
} else {
|
||||||
|
LOGGER.warning("Loading of constraints not yet implemented for version 2.5x !");
|
||||||
|
//TODO: to implement
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,14 @@ package com.jme3.scene.plugins.blender.helpers;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class CurvesHelper extends com.jme3.scene.plugins.blender.helpers.v249.CurvesHelper {
|
public class CurvesHelper extends com.jme3.scene.plugins.blender.helpers.v249.CurvesHelper {
|
||||||
/**
|
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
/**
|
||||||
* different blender versions.
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
* @param blenderVersion
|
* different blender versions.
|
||||||
* the version read from the blend file
|
* @param blenderVersion
|
||||||
*/
|
* the version read from the blend file
|
||||||
public CurvesHelper(String blenderVersion) {
|
*/
|
||||||
super(blenderVersion);
|
public CurvesHelper(String blenderVersion) {
|
||||||
}
|
super(blenderVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,14 @@ package com.jme3.scene.plugins.blender.helpers;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class IpoHelper extends com.jme3.scene.plugins.blender.helpers.v249.IpoHelper {
|
public class IpoHelper extends com.jme3.scene.plugins.blender.helpers.v249.IpoHelper {
|
||||||
/**
|
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
/**
|
||||||
* different blender versions.
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
* @param blenderVersion
|
* different blender versions.
|
||||||
* the version read from the blend file
|
* @param blenderVersion
|
||||||
*/
|
* the version read from the blend file
|
||||||
public IpoHelper(String blenderVersion) {
|
*/
|
||||||
super(blenderVersion);
|
public IpoHelper(String blenderVersion) {
|
||||||
}
|
super(blenderVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,13 +36,14 @@ package com.jme3.scene.plugins.blender.helpers;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class LightHelper extends com.jme3.scene.plugins.blender.helpers.v249.LightHelper {
|
public class LightHelper extends com.jme3.scene.plugins.blender.helpers.v249.LightHelper {
|
||||||
/**
|
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
/**
|
||||||
* different blender versions.
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
* @param blenderVersion
|
* different blender versions.
|
||||||
* the version read from the blend file
|
* @param blenderVersion
|
||||||
*/
|
* the version read from the blend file
|
||||||
public LightHelper(String blenderVersion) {
|
*/
|
||||||
super(blenderVersion);
|
public LightHelper(String blenderVersion) {
|
||||||
}
|
super(blenderVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,13 +32,14 @@
|
|||||||
package com.jme3.scene.plugins.blender.helpers;
|
package com.jme3.scene.plugins.blender.helpers;
|
||||||
|
|
||||||
public class MaterialHelper extends com.jme3.scene.plugins.blender.helpers.v249.MaterialHelper {
|
public class MaterialHelper extends com.jme3.scene.plugins.blender.helpers.v249.MaterialHelper {
|
||||||
/**
|
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
/**
|
||||||
* different blender versions.
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
* @param blenderVersion
|
* different blender versions.
|
||||||
* the version read from the blend file
|
* @param blenderVersion
|
||||||
*/
|
* the version read from the blend file
|
||||||
public MaterialHelper(String blenderVersion) {
|
*/
|
||||||
super(blenderVersion);
|
public MaterialHelper(String blenderVersion) {
|
||||||
}
|
super(blenderVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,13 +36,14 @@ package com.jme3.scene.plugins.blender.helpers;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class MeshHelper extends com.jme3.scene.plugins.blender.helpers.v249.MeshHelper {
|
public class MeshHelper extends com.jme3.scene.plugins.blender.helpers.v249.MeshHelper {
|
||||||
/**
|
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
/**
|
||||||
* different blender versions.
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
* @param blenderVersion
|
* different blender versions.
|
||||||
* the version read from the blend file
|
* @param blenderVersion
|
||||||
*/
|
* the version read from the blend file
|
||||||
public MeshHelper(String blenderVersion) {
|
*/
|
||||||
super(blenderVersion);
|
public MeshHelper(String blenderVersion) {
|
||||||
}
|
super(blenderVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,13 +36,14 @@ package com.jme3.scene.plugins.blender.helpers;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class ModifierHelper extends com.jme3.scene.plugins.blender.helpers.v249.ModifierHelper {
|
public class ModifierHelper extends com.jme3.scene.plugins.blender.helpers.v249.ModifierHelper {
|
||||||
/**
|
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
/**
|
||||||
* different blender versions.
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
* @param blenderVersion
|
* different blender versions.
|
||||||
* the version read from the blend file
|
* @param blenderVersion
|
||||||
*/
|
* the version read from the blend file
|
||||||
public ModifierHelper(String blenderVersion) {
|
*/
|
||||||
super(blenderVersion);
|
public ModifierHelper(String blenderVersion) {
|
||||||
}
|
super(blenderVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,13 +39,14 @@ package com.jme3.scene.plugins.blender.helpers;
|
|||||||
* @author Marcin Roguski (Kaelthas)
|
* @author Marcin Roguski (Kaelthas)
|
||||||
*/
|
*/
|
||||||
public class NoiseHelper extends com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper {
|
public class NoiseHelper extends com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper {
|
||||||
/**
|
|
||||||
* Constructor. Stores the blender version number and loads the constants needed for computations.
|
/**
|
||||||
*
|
* Constructor. Stores the blender version number and loads the constants needed for computations.
|
||||||
* @param blenderVersion
|
*
|
||||||
* the number of blender version
|
* @param blenderVersion
|
||||||
*/
|
* the number of blender version
|
||||||
public NoiseHelper(String blenderVersion) {
|
*/
|
||||||
super(blenderVersion);
|
public NoiseHelper(String blenderVersion) {
|
||||||
}
|
super(blenderVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,13 +36,14 @@ package com.jme3.scene.plugins.blender.helpers;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class ObjectHelper extends com.jme3.scene.plugins.blender.helpers.v249.ObjectHelper {
|
public class ObjectHelper extends com.jme3.scene.plugins.blender.helpers.v249.ObjectHelper {
|
||||||
/**
|
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
/**
|
||||||
* different blender versions.
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
* @param blenderVersion
|
* different blender versions.
|
||||||
* the version read from the blend file
|
* @param blenderVersion
|
||||||
*/
|
* the version read from the blend file
|
||||||
public ObjectHelper(String blenderVersion) {
|
*/
|
||||||
super(blenderVersion);
|
public ObjectHelper(String blenderVersion) {
|
||||||
}
|
super(blenderVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,14 @@ package com.jme3.scene.plugins.blender.helpers;
|
|||||||
* @author Marcin Roguski (Kaelthas)
|
* @author Marcin Roguski (Kaelthas)
|
||||||
*/
|
*/
|
||||||
public class ParticlesHelper extends com.jme3.scene.plugins.blender.helpers.v249.ParticlesHelper {
|
public class ParticlesHelper extends com.jme3.scene.plugins.blender.helpers.v249.ParticlesHelper {
|
||||||
/**
|
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
/**
|
||||||
* different blender versions.
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
* @param blenderVersion
|
* different blender versions.
|
||||||
* the version read from the blend file
|
* @param blenderVersion
|
||||||
*/
|
* the version read from the blend file
|
||||||
public ParticlesHelper(String blenderVersion) {
|
*/
|
||||||
super(blenderVersion);
|
public ParticlesHelper(String blenderVersion) {
|
||||||
}
|
super(blenderVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,39 +44,41 @@ import com.jme3.texture.Texture;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class TextureHelper extends com.jme3.scene.plugins.blender.helpers.v249.TextureHelper {
|
public class TextureHelper extends com.jme3.scene.plugins.blender.helpers.v249.TextureHelper {
|
||||||
private static final Logger LOGGER = Logger.getLogger(TextureHelper.class.getName());
|
|
||||||
public static final int TEX_POINTDENSITY = 14;
|
|
||||||
public static final int TEX_VOXELDATA = 15;
|
|
||||||
/**
|
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
|
||||||
* different blender versions.
|
|
||||||
* @param blenderVersion
|
|
||||||
* the version read from the blend file
|
|
||||||
*/
|
|
||||||
public TextureHelper(String blenderVersion) {
|
|
||||||
super(blenderVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
private static final Logger LOGGER = Logger.getLogger(TextureHelper.class.getName());
|
||||||
public Texture getTexture(Structure tex, DataRepository dataRepository) throws BlenderFileException {
|
public static final int TEX_POINTDENSITY = 14;
|
||||||
if(blenderVersion<250) {
|
public static final int TEX_VOXELDATA = 15;
|
||||||
return super.getTexture(tex, dataRepository);
|
|
||||||
}
|
/**
|
||||||
Texture result = (Texture) dataRepository.getLoadedFeature(tex.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE);
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
if (result != null) {
|
* different blender versions.
|
||||||
return result;
|
* @param blenderVersion
|
||||||
}
|
* the version read from the blend file
|
||||||
int type = ((Number)tex.getFieldValue("type")).intValue();
|
*/
|
||||||
switch(type) {
|
public TextureHelper(String blenderVersion) {
|
||||||
case TEX_POINTDENSITY:
|
super(blenderVersion);
|
||||||
LOGGER.warning("Point density texture loading currently not supported!");
|
}
|
||||||
break;
|
|
||||||
case TEX_VOXELDATA:
|
@Override
|
||||||
LOGGER.warning("Voxel data texture loading currently not supported!");
|
public Texture getTexture(Structure tex, DataRepository dataRepository) throws BlenderFileException {
|
||||||
break;
|
if (blenderVersion < 250) {
|
||||||
default:
|
return super.getTexture(tex, dataRepository);
|
||||||
result = super.getTexture(tex, dataRepository);
|
}
|
||||||
}
|
Texture result = (Texture) dataRepository.getLoadedFeature(tex.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE);
|
||||||
return result;
|
if (result != null) {
|
||||||
}
|
return result;
|
||||||
|
}
|
||||||
|
int type = ((Number) tex.getFieldValue("type")).intValue();
|
||||||
|
switch (type) {
|
||||||
|
case TEX_POINTDENSITY:
|
||||||
|
LOGGER.warning("Point density texture loading currently not supported!");
|
||||||
|
break;
|
||||||
|
case TEX_VOXELDATA:
|
||||||
|
LOGGER.warning("Voxel data texture loading currently not supported!");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = super.getTexture(tex, dataRepository);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,311 +60,312 @@ import com.jme3.scene.plugins.blender.utils.Pointer;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class ArmatureHelper extends AbstractBlenderHelper {
|
public class ArmatureHelper extends AbstractBlenderHelper {
|
||||||
private static final Logger LOGGER = Logger.getLogger(ArmatureHelper.class.getName());
|
|
||||||
|
|
||||||
/**
|
private static final Logger LOGGER = Logger.getLogger(ArmatureHelper.class.getName());
|
||||||
* The map of the bones. Maps a bone name to its index in the armature. Should be cleared after the object had been
|
/**
|
||||||
* read. TODO: probably bones can have identical names in different armatures
|
* The map of the bones. Maps a bone name to its index in the armature. Should be cleared after the object had been
|
||||||
*/
|
* read. TODO: probably bones can have identical names in different armatures
|
||||||
protected Map<String, Integer> bonesMap = new HashMap<String, Integer>();
|
*/
|
||||||
/** A map of bones and their old memory addresses. */
|
protected Map<String, Integer> bonesMap = new HashMap<String, Integer>();
|
||||||
protected Map<Bone, Long> bonesOMAs = new HashMap<Bone, Long>();
|
/** A map of bones and their old memory addresses. */
|
||||||
/** This list contains bones hierarchy and their matrices. It is later converted into jme bones. */
|
protected Map<Bone, Long> bonesOMAs = new HashMap<Bone, Long>();
|
||||||
protected List<BoneTransformationData> boneDataRoots = new ArrayList<BoneTransformationData>();
|
/** This list contains bones hierarchy and their matrices. It is later converted into jme bones. */
|
||||||
|
protected List<BoneTransformationData> boneDataRoots = new ArrayList<BoneTransformationData>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
* different blender versions.
|
* different blender versions.
|
||||||
* @param blenderVersion
|
* @param blenderVersion
|
||||||
* the version read from the blend file
|
* the version read from the blend file
|
||||||
*/
|
*/
|
||||||
public ArmatureHelper(String blenderVersion) {
|
public ArmatureHelper(String blenderVersion) {
|
||||||
super(blenderVersion);
|
super(blenderVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the old memory address of a bone. If the bone does not exist in the blend file - zero is
|
* This method returns the old memory address of a bone. If the bone does not exist in the blend file - zero is
|
||||||
* returned.
|
* returned.
|
||||||
* @param bone
|
* @param bone
|
||||||
* the bone whose old memory address we seek
|
* the bone whose old memory address we seek
|
||||||
* @return the old memory address of the given bone
|
* @return the old memory address of the given bone
|
||||||
*/
|
*/
|
||||||
public Long getBoneOMA(Bone bone) {
|
public Long getBoneOMA(Bone bone) {
|
||||||
Long result = bonesOMAs.get(bone);
|
Long result = bonesOMAs.get(bone);
|
||||||
if(result == null) {
|
if (result == null) {
|
||||||
result = Long.valueOf(0);
|
result = Long.valueOf(0);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads the bones and returns an empty skeleton. Bones should be assigned later.
|
* This method reads the bones and returns an empty skeleton. Bones should be assigned later.
|
||||||
* @param structure
|
* @param structure
|
||||||
* armature structure
|
* armature structure
|
||||||
* @param dataRepository
|
* @param dataRepository
|
||||||
* the data repository
|
* the data repository
|
||||||
* @return an empty skeleton, bones are stored within the helper object
|
* @return an empty skeleton, bones are stored within the helper object
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* this exception is thrown when the blender file is somehow corrupted
|
* this exception is thrown when the blender file is somehow corrupted
|
||||||
*/
|
*/
|
||||||
public Skeleton toArmature(Structure structure, DataRepository dataRepository) throws BlenderFileException {
|
public Skeleton toArmature(Structure structure, DataRepository dataRepository) throws BlenderFileException {
|
||||||
LOGGER.log(Level.INFO, "Converting structure to Armature!");
|
LOGGER.log(Level.INFO, "Converting structure to Armature!");
|
||||||
Structure bonebase = (Structure)structure.getFieldValue("bonebase");
|
Structure bonebase = (Structure) structure.getFieldValue("bonebase");
|
||||||
List<Structure> bonesStructures = bonebase.evaluateListBase(dataRepository);
|
List<Structure> bonesStructures = bonebase.evaluateListBase(dataRepository);
|
||||||
for(Structure boneStructure : bonesStructures) {
|
for (Structure boneStructure : bonesStructures) {
|
||||||
BoneTransformationData rootBoneTransformationData = this.readBoneAndItsChildren(boneStructure, null, dataRepository);
|
BoneTransformationData rootBoneTransformationData = this.readBoneAndItsChildren(boneStructure, null, dataRepository);
|
||||||
boneDataRoots.add(rootBoneTransformationData);
|
boneDataRoots.add(rootBoneTransformationData);
|
||||||
}
|
}
|
||||||
return new Skeleton();//bones are assigned later
|
return new Skeleton();//bones are assigned later
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns a map where the key is the object's group index that is used by a bone and the key is the
|
* This method returns a map where the key is the object's group index that is used by a bone and the key is the
|
||||||
* bone index in the armature.
|
* bone index in the armature.
|
||||||
* @param poseStructure
|
* @param poseStructure
|
||||||
* a bPose structure of the object
|
* a bPose structure of the object
|
||||||
* @return bone group-to-index map
|
* @return bone group-to-index map
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* this exception is thrown when the blender file is somehow corrupted
|
* this exception is thrown when the blender file is somehow corrupted
|
||||||
*/
|
*/
|
||||||
public Map<Integer, Integer> getGroupToBoneIndexMap(Structure defBaseStructure, DataRepository dataRepository) throws BlenderFileException {
|
public Map<Integer, Integer> getGroupToBoneIndexMap(Structure defBaseStructure, DataRepository dataRepository) throws BlenderFileException {
|
||||||
Map<Integer, Integer> result = null;
|
Map<Integer, Integer> result = null;
|
||||||
if(bonesMap != null && bonesMap.size() != 0) {
|
if (bonesMap != null && bonesMap.size() != 0) {
|
||||||
result = new HashMap<Integer, Integer>();
|
result = new HashMap<Integer, Integer>();
|
||||||
List<Structure> deformGroups = defBaseStructure.evaluateListBase(dataRepository);//bDeformGroup
|
List<Structure> deformGroups = defBaseStructure.evaluateListBase(dataRepository);//bDeformGroup
|
||||||
int groupIndex = 0;//TODO: consider many armatures attached to one object in the future !!!
|
int groupIndex = 0;//TODO: consider many armatures attached to one object in the future !!!
|
||||||
for(Structure deformGroup : deformGroups) {
|
for (Structure deformGroup : deformGroups) {
|
||||||
String deformGroupName = deformGroup.getFieldValue("name").toString();
|
String deformGroupName = deformGroup.getFieldValue("name").toString();
|
||||||
Integer boneIndex = bonesMap.get(deformGroupName);
|
Integer boneIndex = bonesMap.get(deformGroupName);
|
||||||
if(boneIndex != null) {
|
if (boneIndex != null) {
|
||||||
result.put(Integer.valueOf(groupIndex), boneIndex);
|
result.put(Integer.valueOf(groupIndex), boneIndex);
|
||||||
}
|
}
|
||||||
++groupIndex;
|
++groupIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads the tracks of the armature object.
|
* This method reads the tracks of the armature object.
|
||||||
* @param actionStructure
|
* @param actionStructure
|
||||||
* @param dataRepository
|
* @param dataRepository
|
||||||
* the data repository
|
* the data repository
|
||||||
* @param objectName
|
* @param objectName
|
||||||
* the name of animation owner
|
* the name of animation owner
|
||||||
* @param animationName
|
* @param animationName
|
||||||
* the name of the animation
|
* the name of the animation
|
||||||
* @return a list of tracks for the armature
|
* @return a list of tracks for the armature
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* this exception is thrown when the blender file is somehow corrupted
|
* this exception is thrown when the blender file is somehow corrupted
|
||||||
*/
|
*/
|
||||||
public BoneTrack[] getTracks(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException {
|
public BoneTrack[] getTracks(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException {
|
||||||
LOGGER.log(Level.INFO, "Getting tracks!");
|
LOGGER.log(Level.INFO, "Getting tracks!");
|
||||||
IpoHelper ipoHelper = dataRepository.getHelper(IpoHelper.class);
|
IpoHelper ipoHelper = dataRepository.getHelper(IpoHelper.class);
|
||||||
int fps = dataRepository.getBlenderKey().getFps();
|
int fps = dataRepository.getBlenderKey().getFps();
|
||||||
int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, animationName);
|
int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, animationName);
|
||||||
Structure chanbase = (Structure)actionStructure.getFieldValue("chanbase");
|
Structure chanbase = (Structure) actionStructure.getFieldValue("chanbase");
|
||||||
List<Structure> actionChannels = chanbase.evaluateListBase(dataRepository);//bActionChannel
|
List<Structure> actionChannels = chanbase.evaluateListBase(dataRepository);//bActionChannel
|
||||||
if(actionChannels != null && actionChannels.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) {
|
if (actionChannels != null && actionChannels.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) {
|
||||||
throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!");
|
throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!");
|
||||||
}
|
}
|
||||||
List<BoneTrack> tracks = new ArrayList<BoneTrack>();
|
List<BoneTrack> tracks = new ArrayList<BoneTrack>();
|
||||||
for(Structure bActionChannel : actionChannels) {
|
for (Structure bActionChannel : actionChannels) {
|
||||||
String name = bActionChannel.getFieldValue("name").toString();
|
String name = bActionChannel.getFieldValue("name").toString();
|
||||||
Integer boneIndex = bonesMap.get(name);
|
Integer boneIndex = bonesMap.get(name);
|
||||||
if(boneIndex != null) {
|
if (boneIndex != null) {
|
||||||
Pointer p = (Pointer)bActionChannel.getFieldValue("ipo");
|
Pointer p = (Pointer) bActionChannel.getFieldValue("ipo");
|
||||||
if(!p.isNull()) {
|
if (!p.isNull()) {
|
||||||
Structure ipoStructure = p.fetchData(dataRepository.getInputStream()).get(0);
|
Structure ipoStructure = p.fetchData(dataRepository.getInputStream()).get(0);
|
||||||
Ipo ipo = ipoHelper.createIpo(ipoStructure, dataRepository);
|
Ipo ipo = ipoHelper.createIpo(ipoStructure, dataRepository);
|
||||||
tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps));
|
tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tracks.toArray(new BoneTrack[tracks.size()]);
|
return tracks.toArray(new BoneTrack[tracks.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This bone returns transformation matrix of the bone that is relative to
|
* This bone returns transformation matrix of the bone that is relative to
|
||||||
* its armature object.
|
* its armature object.
|
||||||
* @param boneStructure the bone's structure
|
* @param boneStructure the bone's structure
|
||||||
* @return bone's transformation matrix in armature space
|
* @return bone's transformation matrix in armature space
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected Matrix4f getArmatureMatrix(Structure boneStructure) {
|
protected Matrix4f getArmatureMatrix(Structure boneStructure) {
|
||||||
DynamicArray<Number> boneMat = (DynamicArray<Number>)boneStructure.getFieldValue("arm_mat");
|
DynamicArray<Number> boneMat = (DynamicArray<Number>) boneStructure.getFieldValue("arm_mat");
|
||||||
Matrix4f m = new Matrix4f();
|
Matrix4f m = new Matrix4f();
|
||||||
for(int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
for(int j = 0; j < 4; ++j) {
|
for (int j = 0; j < 4; ++j) {
|
||||||
m.set(i, j, boneMat.get(j, i).floatValue());
|
m.set(i, j, boneMat.get(j, i).floatValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads the bone with its children.
|
* This method reads the bone with its children.
|
||||||
* @param boneStructure
|
* @param boneStructure
|
||||||
* a structure containing the bone data
|
* a structure containing the bone data
|
||||||
* @param parent
|
* @param parent
|
||||||
* the bone parent; if null then we read the root bone
|
* the bone parent; if null then we read the root bone
|
||||||
* @param dataRepository
|
* @param dataRepository
|
||||||
* the data repository
|
* the data repository
|
||||||
* @return the bone transformation data; contains bone chierarchy and the bone's matrices
|
* @return the bone transformation data; contains bone chierarchy and the bone's matrices
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* this exception is thrown when the blender file is somehow corrupted
|
* this exception is thrown when the blender file is somehow corrupted
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected BoneTransformationData readBoneAndItsChildren(Structure boneStructure, BoneTransformationData parent, DataRepository dataRepository) throws BlenderFileException {
|
protected BoneTransformationData readBoneAndItsChildren(Structure boneStructure, BoneTransformationData parent, DataRepository dataRepository) throws BlenderFileException {
|
||||||
String name = boneStructure.getFieldValue("name").toString();
|
String name = boneStructure.getFieldValue("name").toString();
|
||||||
Bone bone = new Bone(name);
|
Bone bone = new Bone(name);
|
||||||
int bonesAmount = bonesOMAs.size();
|
int bonesAmount = bonesOMAs.size();
|
||||||
bonesOMAs.put(bone, boneStructure.getOldMemoryAddress());
|
bonesOMAs.put(bone, boneStructure.getOldMemoryAddress());
|
||||||
if(bonesAmount == bonesOMAs.size()) {
|
if (bonesAmount == bonesOMAs.size()) {
|
||||||
throw new IllegalStateException("Two bones has the same hash value and thereforw a bone was overriden in the bones<->OMA map! Improve the hash algorithm!");
|
throw new IllegalStateException("Two bones has the same hash value and thereforw a bone was overriden in the bones<->OMA map! Improve the hash algorithm!");
|
||||||
}
|
}
|
||||||
Matrix4f boneArmatureMatrix = this.getArmatureMatrix(boneStructure);
|
Matrix4f boneArmatureMatrix = this.getArmatureMatrix(boneStructure);
|
||||||
DynamicArray<Float> sizeArray = (DynamicArray<Float>) boneStructure.getFieldValue("size");
|
DynamicArray<Float> sizeArray = (DynamicArray<Float>) boneStructure.getFieldValue("size");
|
||||||
Vector3f size = new Vector3f(sizeArray.get(0), sizeArray.get(1), sizeArray.get(2));
|
Vector3f size = new Vector3f(sizeArray.get(0), sizeArray.get(1), sizeArray.get(2));
|
||||||
BoneTransformationData boneTransformationData = new BoneTransformationData(boneArmatureMatrix, size, bone, parent);
|
BoneTransformationData boneTransformationData = new BoneTransformationData(boneArmatureMatrix, size, bone, parent);
|
||||||
dataRepository.addLoadedFeatures(boneStructure.getOldMemoryAddress(), name, boneStructure, bone);
|
dataRepository.addLoadedFeatures(boneStructure.getOldMemoryAddress(), name, boneStructure, bone);
|
||||||
|
|
||||||
Structure childbase = (Structure)boneStructure.getFieldValue("childbase");
|
Structure childbase = (Structure) boneStructure.getFieldValue("childbase");
|
||||||
List<Structure> children = childbase.evaluateListBase(dataRepository);//Bone
|
List<Structure> children = childbase.evaluateListBase(dataRepository);//Bone
|
||||||
for(Structure boneChild : children) {
|
for (Structure boneChild : children) {
|
||||||
this.readBoneAndItsChildren(boneChild, boneTransformationData, dataRepository);
|
this.readBoneAndItsChildren(boneChild, boneTransformationData, dataRepository);
|
||||||
}
|
}
|
||||||
return boneTransformationData;
|
return boneTransformationData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method assigns transformations to the bone.
|
* This method assigns transformations to the bone.
|
||||||
* @param btd
|
* @param btd
|
||||||
* the bone data containing the bone we assign transformation to
|
* the bone data containing the bone we assign transformation to
|
||||||
* @param additionalRootBoneTransformation
|
* @param additionalRootBoneTransformation
|
||||||
* additional bone transformation which indicates it's mesh parent and armature object transformations
|
* additional bone transformation which indicates it's mesh parent and armature object transformations
|
||||||
* @param boneList
|
* @param boneList
|
||||||
* a list of all read bones
|
* a list of all read bones
|
||||||
*/
|
*/
|
||||||
protected void assignBonesMatrices(BoneTransformationData btd, Matrix4f additionalRootBoneTransformation, List<Bone> boneList) {
|
protected void assignBonesMatrices(BoneTransformationData btd, Matrix4f additionalRootBoneTransformation, List<Bone> boneList) {
|
||||||
LOGGER.info("[" + btd.bone.getName() + "] additionalRootBoneTransformation =\n" + additionalRootBoneTransformation);
|
LOGGER.info("[" + btd.bone.getName() + "] additionalRootBoneTransformation =\n" + additionalRootBoneTransformation);
|
||||||
Matrix4f totalInverseParentMatrix = btd.parent != null ? btd.parent.totalInverseBoneParentMatrix : Matrix4f.IDENTITY;
|
Matrix4f totalInverseParentMatrix = btd.parent != null ? btd.parent.totalInverseBoneParentMatrix : Matrix4f.IDENTITY;
|
||||||
LOGGER.info("[" + btd.bone.getName() + "] totalInverseParentMatrix =\n" + totalInverseParentMatrix);
|
LOGGER.info("[" + btd.bone.getName() + "] totalInverseParentMatrix =\n" + totalInverseParentMatrix);
|
||||||
Matrix4f restMatrix = additionalRootBoneTransformation.mult(btd.boneArmatureMatrix);
|
Matrix4f restMatrix = additionalRootBoneTransformation.mult(btd.boneArmatureMatrix);
|
||||||
LOGGER.info("[" + btd.bone.getName() + "] restMatrix =\n" + restMatrix);
|
LOGGER.info("[" + btd.bone.getName() + "] restMatrix =\n" + restMatrix);
|
||||||
btd.totalInverseBoneParentMatrix = restMatrix.clone().invert();
|
btd.totalInverseBoneParentMatrix = restMatrix.clone().invert();
|
||||||
restMatrix = totalInverseParentMatrix.mult(restMatrix);
|
restMatrix = totalInverseParentMatrix.mult(restMatrix);
|
||||||
LOGGER.info("[" + btd.bone.getName() + "] resultMatrix =\n" + restMatrix);
|
LOGGER.info("[" + btd.bone.getName() + "] resultMatrix =\n" + restMatrix);
|
||||||
btd.bone.setBindTransforms(restMatrix.toTranslationVector(), restMatrix.toRotationQuat(), btd.size);
|
btd.bone.setBindTransforms(restMatrix.toTranslationVector(), restMatrix.toRotationQuat(), btd.size);
|
||||||
boneList.add(btd.bone);
|
boneList.add(btd.bone);
|
||||||
bonesMap.put(btd.bone.getName(), Integer.valueOf(boneList.size() - 1));
|
bonesMap.put(btd.bone.getName(), Integer.valueOf(boneList.size() - 1));
|
||||||
if(btd.children != null && btd.children.size() > 0) {
|
if (btd.children != null && btd.children.size() > 0) {
|
||||||
for(BoneTransformationData child : btd.children) {
|
for (BoneTransformationData child : btd.children) {
|
||||||
this.assignBonesMatrices(child, additionalRootBoneTransformation, boneList);
|
this.assignBonesMatrices(child, additionalRootBoneTransformation, boneList);
|
||||||
btd.bone.addChild(child.bone);
|
btd.bone.addChild(child.bone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns bone transformation data for the bone of a given name.
|
* This method returns bone transformation data for the bone of a given name.
|
||||||
* @param boneName
|
* @param boneName
|
||||||
* the name of the bone
|
* the name of the bone
|
||||||
* @return bone's transformation data
|
* @return bone's transformation data
|
||||||
*/
|
*/
|
||||||
public BoneTransformationData getBoneTransformationDataRoot(int index) {
|
public BoneTransformationData getBoneTransformationDataRoot(int index) {
|
||||||
return boneDataRoots.get(index);
|
return boneDataRoots.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the amount of bones transformations roots.
|
* This method returns the amount of bones transformations roots.
|
||||||
* @return the amount of bones transformations roots
|
* @return the amount of bones transformations roots
|
||||||
*/
|
*/
|
||||||
public int getBoneTransformationDataRootsSize() {
|
public int getBoneTransformationDataRootsSize() {
|
||||||
return boneDataRoots.size();
|
return boneDataRoots.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class holds the data needed later for bone transformation calculation and to bind parent with children.
|
* This class holds the data needed later for bone transformation calculation and to bind parent with children.
|
||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
private static class BoneTransformationData {
|
private static class BoneTransformationData {
|
||||||
/** Inverse matrix of bone's parent bone. */
|
|
||||||
private Matrix4f totalInverseBoneParentMatrix;
|
|
||||||
/** Bone's matrix in armature's space. */
|
|
||||||
private Matrix4f boneArmatureMatrix;
|
|
||||||
/** Bone's size (apparently it is held outside the transformation matrix. */
|
|
||||||
private Vector3f size;
|
|
||||||
/** The bone the data applies to. */
|
|
||||||
private Bone bone;
|
|
||||||
/** The parent of the above mentioned bone (not assigned yet). */
|
|
||||||
private BoneTransformationData parent;
|
|
||||||
/** The children of the current bone. */
|
|
||||||
private List<BoneTransformationData> children;
|
|
||||||
|
|
||||||
/**
|
/** Inverse matrix of bone's parent bone. */
|
||||||
* Private constructor creates the object and assigns the given data.
|
private Matrix4f totalInverseBoneParentMatrix;
|
||||||
* @param boneArmatureMatrix
|
/** Bone's matrix in armature's space. */
|
||||||
* the matrix of the current bone
|
private Matrix4f boneArmatureMatrix;
|
||||||
* @param size
|
/** Bone's size (apparently it is held outside the transformation matrix. */
|
||||||
* the bone's size
|
private Vector3f size;
|
||||||
* @param bone
|
/** The bone the data applies to. */
|
||||||
* the current bone
|
private Bone bone;
|
||||||
* @param parent
|
/** The parent of the above mentioned bone (not assigned yet). */
|
||||||
* the parent structure of the bone
|
private BoneTransformationData parent;
|
||||||
*/
|
/** The children of the current bone. */
|
||||||
private BoneTransformationData(Matrix4f boneArmatureMatrix, Vector3f size, Bone bone, BoneTransformationData parent) {
|
private List<BoneTransformationData> children;
|
||||||
this.boneArmatureMatrix = boneArmatureMatrix;
|
|
||||||
this.size = size;
|
|
||||||
this.bone = bone;
|
|
||||||
this.parent = parent;
|
|
||||||
this.children = new ArrayList<ArmatureHelper.BoneTransformationData>();
|
|
||||||
if(this.parent != null) {
|
|
||||||
this.parent.children.add(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method creates the whole bones structure. Assignes transformations to bones and combines children with
|
* Private constructor creates the object and assigns the given data.
|
||||||
* parents.
|
* @param boneArmatureMatrix
|
||||||
* @param armatureOMA
|
* the matrix of the current bone
|
||||||
* old memory address of bones' armature object
|
* @param size
|
||||||
* @param additionalRootBoneTransformation
|
* the bone's size
|
||||||
* additional bone transformation which indicates it's mesh parent and armature object transformations
|
* @param bone
|
||||||
* @return
|
* the current bone
|
||||||
*/
|
* @param parent
|
||||||
public Bone[] buildBonesStructure(Long armatureOMA, Matrix4f additionalRootBoneTransformation) {//TODO: uwzględnić wiele szkieletów
|
* the parent structure of the bone
|
||||||
List<Bone> bones = new ArrayList<Bone>(boneDataRoots.size() + 1);
|
*/
|
||||||
bones.add(new Bone(null));
|
private BoneTransformationData(Matrix4f boneArmatureMatrix, Vector3f size, Bone bone, BoneTransformationData parent) {
|
||||||
for(BoneTransformationData btd : boneDataRoots) {
|
this.boneArmatureMatrix = boneArmatureMatrix;
|
||||||
this.assignBonesMatrices(btd, additionalRootBoneTransformation, bones);
|
this.size = size;
|
||||||
}
|
this.bone = bone;
|
||||||
return bones.toArray(new Bone[bones.size()]);
|
this.parent = parent;
|
||||||
}
|
this.children = new ArrayList<ArmatureHelper.BoneTransformationData>();
|
||||||
|
if (this.parent != null) {
|
||||||
|
this.parent.children.add(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method assigns an immovable bone to vertices that have no bone assigned. They have the bone index with the
|
* This method creates the whole bones structure. Assignes transformations to bones and combines children with
|
||||||
* value -1.
|
* parents.
|
||||||
* @param immovableBoneIndex
|
* @param armatureOMA
|
||||||
* the ondex of immovable bone
|
* old memory address of bones' armature object
|
||||||
* @param meshes
|
* @param additionalRootBoneTransformation
|
||||||
* a list of meshes whose vertices will be assigned to immovable bone
|
* additional bone transformation which indicates it's mesh parent and armature object transformations
|
||||||
*/
|
* @return
|
||||||
public void assignBoneToOrphanedVertices(byte immovableBoneIndex, Mesh[] meshes) {
|
*/
|
||||||
//bone indices are common for all the object's meshes (vertex indices specify which are to be used)
|
public Bone[] buildBonesStructure(Long armatureOMA, Matrix4f additionalRootBoneTransformation) {//TODO: uwzględnić wiele szkieletów
|
||||||
VertexBuffer boneIndices = meshes[0].getBuffer(Type.BoneIndex);//common buffer to all the meshes
|
List<Bone> bones = new ArrayList<Bone>(boneDataRoots.size() + 1);
|
||||||
ByteBuffer data = (ByteBuffer)boneIndices.getData();
|
bones.add(new Bone(null));
|
||||||
for(int i = 0; i < boneIndices.getNumElements(); ++i) {
|
for (BoneTransformationData btd : boneDataRoots) {
|
||||||
if(data.get(i) == -1) {
|
this.assignBonesMatrices(btd, additionalRootBoneTransformation, bones);
|
||||||
data.put(i, immovableBoneIndex);
|
}
|
||||||
}
|
return bones.toArray(new Bone[bones.size()]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void clearState() {
|
* This method assigns an immovable bone to vertices that have no bone assigned. They have the bone index with the
|
||||||
bonesMap.clear();
|
* value -1.
|
||||||
boneDataRoots.clear();
|
* @param immovableBoneIndex
|
||||||
}
|
* the ondex of immovable bone
|
||||||
|
* @param meshes
|
||||||
|
* a list of meshes whose vertices will be assigned to immovable bone
|
||||||
|
*/
|
||||||
|
public void assignBoneToOrphanedVertices(byte immovableBoneIndex, Mesh[] meshes) {
|
||||||
|
//bone indices are common for all the object's meshes (vertex indices specify which are to be used)
|
||||||
|
VertexBuffer boneIndices = meshes[0].getBuffer(Type.BoneIndex);//common buffer to all the meshes
|
||||||
|
ByteBuffer data = (ByteBuffer) boneIndices.getData();
|
||||||
|
for (int i = 0; i < boneIndices.getNumElements(); ++i) {
|
||||||
|
if (data.get(i) == -1) {
|
||||||
|
data.put(i, immovableBoneIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearState() {
|
||||||
|
bonesMap.clear();
|
||||||
|
boneDataRoots.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,45 +13,46 @@ import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class CameraHelper extends AbstractBlenderHelper {
|
public class CameraHelper extends AbstractBlenderHelper {
|
||||||
private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName());
|
|
||||||
|
|
||||||
protected static final int DEFAULT_CAM_WIDTH = 100;
|
private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName());
|
||||||
protected static final int DEFAULT_CAM_HEIGHT = 100;
|
protected static final int DEFAULT_CAM_WIDTH = 100;
|
||||||
/**
|
protected static final int DEFAULT_CAM_HEIGHT = 100;
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
|
||||||
* different blender versions.
|
|
||||||
* @param blenderVersion
|
|
||||||
* the version read from the blend file
|
|
||||||
*/
|
|
||||||
public CameraHelper(String blenderVersion) {
|
|
||||||
super(blenderVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads the camera object.
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
* @param structure the structure containing the camera data
|
* different blender versions.
|
||||||
* @return the camera object
|
* @param blenderVersion
|
||||||
* @throws BlenderFileException
|
* the version read from the blend file
|
||||||
*/
|
*/
|
||||||
public Camera toCamera(Structure structure) throws BlenderFileException {
|
public CameraHelper(String blenderVersion) {
|
||||||
Camera result = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT);
|
super(blenderVersion);
|
||||||
int type = ((Number)structure.getFieldValue("type")).intValue();
|
}
|
||||||
if(type != 0 && type != 1) {
|
|
||||||
LOGGER.log(Level.WARNING, "Unknown camera type: " + type + ". Perspective camera is being used!");
|
/**
|
||||||
type = 0;
|
* This method reads the camera object.
|
||||||
}
|
* @param structure the structure containing the camera data
|
||||||
//type==0 - perspective; type==1 - orthographic; perspective is used as default
|
* @return the camera object
|
||||||
result.setParallelProjection(type == 1);
|
* @throws BlenderFileException
|
||||||
float angle = ((Number)structure.getFieldValue("angle")).floatValue();
|
*/
|
||||||
float aspect = 0;
|
public Camera toCamera(Structure structure) throws BlenderFileException {
|
||||||
float clipsta = ((Number)structure.getFieldValue("clipsta")).floatValue();
|
Camera result = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT);
|
||||||
float clipend = ((Number)structure.getFieldValue("clipend")).floatValue();
|
int type = ((Number) structure.getFieldValue("type")).intValue();
|
||||||
if(type == 0) {
|
if (type != 0 && type != 1) {
|
||||||
aspect = ((Number)structure.getFieldValue("lens")).floatValue();
|
LOGGER.log(Level.WARNING, "Unknown camera type: {0}. Perspective camera is being used!", type);
|
||||||
} else {
|
type = 0;
|
||||||
aspect = ((Number)structure.getFieldValue("ortho_scale")).floatValue();
|
}
|
||||||
}
|
//type==0 - perspective; type==1 - orthographic; perspective is used as default
|
||||||
result.setFrustumPerspective(angle, aspect, clipsta, clipend);
|
result.setParallelProjection(type == 1);
|
||||||
return result;
|
float angle = ((Number) structure.getFieldValue("angle")).floatValue();
|
||||||
}
|
float aspect = 0;
|
||||||
|
float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue();
|
||||||
|
float clipend = ((Number) structure.getFieldValue("clipend")).floatValue();
|
||||||
|
if (type == 0) {
|
||||||
|
aspect = ((Number) structure.getFieldValue("lens")).floatValue();
|
||||||
|
} else {
|
||||||
|
aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue();
|
||||||
|
}
|
||||||
|
result.setFrustumPerspective(angle, aspect, clipsta, clipend);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -17,98 +17,98 @@ import com.jme3.scene.plugins.blender.utils.Pointer;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class IpoHelper extends AbstractBlenderHelper {
|
public class IpoHelper extends AbstractBlenderHelper {
|
||||||
/**
|
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
|
||||||
* different blender versions.
|
|
||||||
* @param blenderVersion
|
|
||||||
* the version read from the blend file
|
|
||||||
*/
|
|
||||||
public IpoHelper(String blenderVersion) {
|
|
||||||
super(blenderVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method creates an ipo object used for interpolation calculations.
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
* @param ipoStructure
|
* different blender versions.
|
||||||
* the structure with ipo definition
|
* @param blenderVersion
|
||||||
* @param dataRepository
|
* the version read from the blend file
|
||||||
* the data repository
|
*/
|
||||||
* @return the ipo object
|
public IpoHelper(String blenderVersion) {
|
||||||
* @throws BlenderFileException
|
super(blenderVersion);
|
||||||
* this exception is thrown when the blender file is somehow corrupted
|
}
|
||||||
*/
|
|
||||||
public Ipo createIpo(Structure ipoStructure, DataRepository dataRepository) throws BlenderFileException {
|
|
||||||
Structure curvebase = (Structure)ipoStructure.getFieldValue("curve");
|
|
||||||
|
|
||||||
//preparing bezier curves
|
/**
|
||||||
Ipo result = null;
|
* This method creates an ipo object used for interpolation calculations.
|
||||||
List<Structure> curves = curvebase.evaluateListBase(dataRepository);//IpoCurve
|
* @param ipoStructure
|
||||||
if(curves.size() > 0) {
|
* the structure with ipo definition
|
||||||
BezierCurve[] bezierCurves = new BezierCurve[curves.size()];
|
* @param dataRepository
|
||||||
int frame = 0;
|
* the data repository
|
||||||
for(Structure curve : curves) {
|
* @return the ipo object
|
||||||
Pointer pBezTriple = (Pointer)curve.getFieldValue("bezt");
|
* @throws BlenderFileException
|
||||||
List<Structure> bezTriples = pBezTriple.fetchData(dataRepository.getInputStream());
|
* this exception is thrown when the blender file is somehow corrupted
|
||||||
int type = ((Number)curve.getFieldValue("adrcode")).intValue();
|
*/
|
||||||
bezierCurves[frame++] = new BezierCurve(type, bezTriples, 2);
|
public Ipo createIpo(Structure ipoStructure, DataRepository dataRepository) throws BlenderFileException {
|
||||||
}
|
Structure curvebase = (Structure) ipoStructure.getFieldValue("curve");
|
||||||
curves.clear();
|
|
||||||
result = new Ipo(bezierCurves);
|
|
||||||
dataRepository.addLoadedFeatures(ipoStructure.getOldMemoryAddress(), ipoStructure.getName(), ipoStructure, result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
//preparing bezier curves
|
||||||
* This method creates an ipo with only a single value. No track type is specified so do not use it for calculating
|
Ipo result = null;
|
||||||
* tracks.
|
List<Structure> curves = curvebase.evaluateListBase(dataRepository);//IpoCurve
|
||||||
* @param constValue
|
if (curves.size() > 0) {
|
||||||
* the value of this ipo
|
BezierCurve[] bezierCurves = new BezierCurve[curves.size()];
|
||||||
* @return constant ipo
|
int frame = 0;
|
||||||
*/
|
for (Structure curve : curves) {
|
||||||
public Ipo createIpo(float constValue) {
|
Pointer pBezTriple = (Pointer) curve.getFieldValue("bezt");
|
||||||
return new ConstIpo(constValue);
|
List<Structure> bezTriples = pBezTriple.fetchData(dataRepository.getInputStream());
|
||||||
}
|
int type = ((Number) curve.getFieldValue("adrcode")).intValue();
|
||||||
|
bezierCurves[frame++] = new BezierCurve(type, bezTriples, 2);
|
||||||
|
}
|
||||||
|
curves.clear();
|
||||||
|
result = new Ipo(bezierCurves);
|
||||||
|
dataRepository.addLoadedFeatures(ipoStructure.getOldMemoryAddress(), ipoStructure.getName(), ipoStructure, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method creates an ipo with only a single value. No track type is specified so do not use it for calculating
|
||||||
|
* tracks.
|
||||||
|
* @param constValue
|
||||||
|
* the value of this ipo
|
||||||
|
* @return constant ipo
|
||||||
|
*/
|
||||||
|
public Ipo createIpo(float constValue) {
|
||||||
|
return new ConstIpo(constValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ipo constant curve. This is a curve with only one value and no specified type. This type of ipo cannot be used to
|
||||||
|
* calculate tracks. It should only be used to calculate single value for a given frame.
|
||||||
|
* @author Marcin Roguski
|
||||||
|
*/
|
||||||
|
private class ConstIpo extends Ipo {
|
||||||
|
|
||||||
/**
|
/** The constant value of this ipo. */
|
||||||
* Ipo constant curve. This is a curve with only one value and no specified type. This type of ipo cannot be used to
|
private float constValue;
|
||||||
* calculate tracks. It should only be used to calculate single value for a given frame.
|
|
||||||
* @author Marcin Roguski
|
|
||||||
*/
|
|
||||||
private class ConstIpo extends Ipo {
|
|
||||||
/** The constant value of this ipo. */
|
|
||||||
private float constValue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Stores the constant value of this ipo.
|
* Constructor. Stores the constant value of this ipo.
|
||||||
* @param constValue
|
* @param constValue
|
||||||
* the constant value of this ipo
|
* the constant value of this ipo
|
||||||
*/
|
*/
|
||||||
public ConstIpo(float constValue) {
|
public ConstIpo(float constValue) {
|
||||||
super(null);
|
super(null);
|
||||||
this.constValue = constValue;
|
this.constValue = constValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float calculateValue(int frame) {
|
public float calculateValue(int frame) {
|
||||||
return constValue;
|
return constValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float calculateValue(int frame, int curveIndex) {
|
public float calculateValue(int frame, int curveIndex) {
|
||||||
return constValue;
|
return constValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCurvesAmount() {
|
public int getCurvesAmount() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BoneTrack calculateTrack(int boneIndex, int startFrame, int stopFrame, int fps) {
|
public BoneTrack calculateTrack(int boneIndex, int startFrame, int stopFrame, int fps) {
|
||||||
throw new IllegalStateException("Constatnt ipo object cannot be used for calculating bone tracks!");
|
throw new IllegalStateException("Constatnt ipo object cannot be used for calculating bone tracks!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,51 +49,52 @@ import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class LightHelper extends AbstractBlenderHelper {
|
public class LightHelper extends AbstractBlenderHelper {
|
||||||
private static final Logger LOGGER = Logger.getLogger(LightHelper.class.getName());
|
|
||||||
|
|
||||||
/**
|
private static final Logger LOGGER = Logger.getLogger(LightHelper.class.getName());
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
|
||||||
* different blender versions.
|
|
||||||
* @param blenderVersion
|
|
||||||
* the version read from the blend file
|
|
||||||
*/
|
|
||||||
public LightHelper(String blenderVersion) {
|
|
||||||
super(blenderVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Light toLight(Structure structure, DataRepository dataRepository) throws BlenderFileException {
|
/**
|
||||||
Light result = (Light)dataRepository.getLoadedFeature(structure.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE);
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
if(result != null) {
|
* different blender versions.
|
||||||
return result;
|
* @param blenderVersion
|
||||||
}
|
* the version read from the blend file
|
||||||
int type = ((Number)structure.getFieldValue("type")).intValue();
|
*/
|
||||||
switch(type) {
|
public LightHelper(String blenderVersion) {
|
||||||
case 0://Lamp
|
super(blenderVersion);
|
||||||
result = new PointLight();
|
}
|
||||||
float distance = ((Number)structure.getFieldValue("dist")).floatValue();
|
|
||||||
((PointLight)result).setRadius(distance);
|
public Light toLight(Structure structure, DataRepository dataRepository) throws BlenderFileException {
|
||||||
break;
|
Light result = (Light) dataRepository.getLoadedFeature(structure.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE);
|
||||||
case 1://Sun
|
if (result != null) {
|
||||||
LOGGER.log(Level.WARNING, "'Sun' lamp is not supported in jMonkeyEngine.");
|
return result;
|
||||||
break;
|
}
|
||||||
case 2://Spot
|
int type = ((Number) structure.getFieldValue("type")).intValue();
|
||||||
LOGGER.log(Level.WARNING, "'Spot' lamp is not supported in jMonkeyEngine.");
|
switch (type) {
|
||||||
break;
|
case 0://Lamp
|
||||||
case 3://Hemi
|
result = new PointLight();
|
||||||
LOGGER.log(Level.WARNING, "'Hemi' lamp is not supported in jMonkeyEngine.");
|
float distance = ((Number) structure.getFieldValue("dist")).floatValue();
|
||||||
break;
|
((PointLight) result).setRadius(distance);
|
||||||
case 4://Area
|
break;
|
||||||
result = new DirectionalLight();
|
case 1://Sun
|
||||||
break;
|
LOGGER.log(Level.WARNING, "'Sun' lamp is not supported in jMonkeyEngine.");
|
||||||
default:
|
break;
|
||||||
throw new BlenderFileException("Unknown light source type: " + type);
|
case 2://Spot
|
||||||
}
|
LOGGER.log(Level.WARNING, "'Spot' lamp is not supported in jMonkeyEngine.");
|
||||||
if(result != null) {
|
break;
|
||||||
float r = ((Number)structure.getFieldValue("r")).floatValue();
|
case 3://Hemi
|
||||||
float g = ((Number)structure.getFieldValue("g")).floatValue();
|
LOGGER.log(Level.WARNING, "'Hemi' lamp is not supported in jMonkeyEngine.");
|
||||||
float b = ((Number)structure.getFieldValue("b")).floatValue();
|
break;
|
||||||
result.setColor(new ColorRGBA(r, g, b, 0.0f));//TODO: 0 czy 1 ???
|
case 4://Area
|
||||||
}
|
result = new DirectionalLight();
|
||||||
return result;
|
break;
|
||||||
}
|
default:
|
||||||
|
throw new BlenderFileException("Unknown light source type: " + type);
|
||||||
|
}
|
||||||
|
if (result != null) {
|
||||||
|
float r = ((Number) structure.getFieldValue("r")).floatValue();
|
||||||
|
float g = ((Number) structure.getFieldValue("g")).floatValue();
|
||||||
|
float b = ((Number) structure.getFieldValue("b")).floatValue();
|
||||||
|
result.setColor(new ColorRGBA(r, g, b, 0.0f));//TODO: 0 czy 1 ???
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -77,465 +77,466 @@ import com.jme3.scene.plugins.ogre.AnimData;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class ModifierHelper extends AbstractBlenderHelper {
|
public class ModifierHelper extends AbstractBlenderHelper {
|
||||||
private static final Logger LOGGER = Logger.getLogger(ModifierHelper.class.getName());
|
|
||||||
|
|
||||||
/**
|
private static final Logger LOGGER = Logger.getLogger(ModifierHelper.class.getName());
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
|
||||||
* different blender versions.
|
|
||||||
* @param blenderVersion
|
|
||||||
* the version read from the blend file
|
|
||||||
*/
|
|
||||||
public ModifierHelper(String blenderVersion) {
|
|
||||||
super(blenderVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method applies modifier to the object.
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in
|
||||||
* @param node
|
* different blender versions.
|
||||||
* the loaded object
|
* @param blenderVersion
|
||||||
* @param modifier
|
* the version read from the blend file
|
||||||
* the modifier to apply
|
*/
|
||||||
* @param dataRepository
|
public ModifierHelper(String blenderVersion) {
|
||||||
* the data repository
|
super(blenderVersion);
|
||||||
* @return the node to whom the modifier was applied
|
}
|
||||||
*/
|
|
||||||
public Node applyModifier(Node node, Modifier modifier, DataRepository dataRepository) {
|
|
||||||
if(Modifier.ARMATURE_MODIFIER_DATA.equals(modifier.getType())) {
|
|
||||||
return this.applyArmatureModifierData(node, modifier, dataRepository);
|
|
||||||
} else if(Modifier.ARRAY_MODIFIER_DATA.equals(modifier.getType())) {
|
|
||||||
return this.applyArrayModifierData(node, modifier, dataRepository);
|
|
||||||
} else if(Modifier.PARTICLE_MODIFIER_DATA.equals(modifier.getType())) {
|
|
||||||
return this.applyParticleSystemModifierData(node, modifier, dataRepository);
|
|
||||||
} else {
|
|
||||||
LOGGER.warning("Modifier: " + modifier.getType() + " not yet implemented!!!");
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads the given object's modifiers.
|
* This method applies modifier to the object.
|
||||||
* @param objectStructure
|
* @param node
|
||||||
* the object structure
|
* the loaded object
|
||||||
* @param dataRepository
|
* @param modifier
|
||||||
* the data repository
|
* the modifier to apply
|
||||||
* @param converter
|
* @param dataRepository
|
||||||
* the converter object (in some cases we need to read an object first before loading the modifier)
|
* the data repository
|
||||||
* @throws BlenderFileException
|
* @return the node to whom the modifier was applied
|
||||||
* this exception is thrown when the blender file is somehow corrupted
|
*/
|
||||||
*/
|
public Node applyModifier(Node node, Modifier modifier, DataRepository dataRepository) {
|
||||||
@SuppressWarnings("unchecked")
|
if (Modifier.ARMATURE_MODIFIER_DATA.equals(modifier.getType())) {
|
||||||
public void readModifiers(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException {
|
return this.applyArmatureModifierData(node, modifier, dataRepository);
|
||||||
Structure modifiersListBase = (Structure)objectStructure.getFieldValue("modifiers");
|
} else if (Modifier.ARRAY_MODIFIER_DATA.equals(modifier.getType())) {
|
||||||
List<Structure> modifiers = modifiersListBase.evaluateListBase(dataRepository);
|
return this.applyArrayModifierData(node, modifier, dataRepository);
|
||||||
for(Structure modifier : modifiers) {
|
} else if (Modifier.PARTICLE_MODIFIER_DATA.equals(modifier.getType())) {
|
||||||
Object loadedModifier = null;
|
return this.applyParticleSystemModifierData(node, modifier, dataRepository);
|
||||||
Object modifierAdditionalData = null;
|
} else {
|
||||||
if(Modifier.ARRAY_MODIFIER_DATA.equals(modifier.getType())) {//****************ARRAY MODIFIER
|
LOGGER.warning("Modifier: " + modifier.getType() + " not yet implemented!!!");
|
||||||
Map<String, Object> params = new HashMap<String, Object>();
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Number fittype = (Number) modifier.getFieldValue("fit_type");
|
/**
|
||||||
params.put("fittype", fittype);
|
* This method reads the given object's modifiers.
|
||||||
switch(fittype.intValue()) {
|
* @param objectStructure
|
||||||
case 0://FIXED COUNT
|
* the object structure
|
||||||
params.put("count", modifier.getFieldValue("count"));
|
* @param dataRepository
|
||||||
break;
|
* the data repository
|
||||||
case 1://FIXED LENGTH
|
* @param converter
|
||||||
params.put("length", modifier.getFieldValue("length"));
|
* the converter object (in some cases we need to read an object first before loading the modifier)
|
||||||
break;
|
* @throws BlenderFileException
|
||||||
case 2://FITCURVE
|
* this exception is thrown when the blender file is somehow corrupted
|
||||||
//TODO: implement after loading curves is added; warning will be generated during modifier applying
|
*/
|
||||||
break;
|
@SuppressWarnings("unchecked")
|
||||||
default:
|
public void readModifiers(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException {
|
||||||
assert false : "Unknown array modifier fit type: " + fittype;
|
Structure modifiersListBase = (Structure) objectStructure.getFieldValue("modifiers");
|
||||||
}
|
List<Structure> modifiers = modifiersListBase.evaluateListBase(dataRepository);
|
||||||
|
for (Structure modifier : modifiers) {
|
||||||
|
Object loadedModifier = null;
|
||||||
|
Object modifierAdditionalData = null;
|
||||||
|
if (Modifier.ARRAY_MODIFIER_DATA.equals(modifier.getType())) {//****************ARRAY MODIFIER
|
||||||
|
Map<String, Object> params = new HashMap<String, Object>();
|
||||||
|
|
||||||
//offset parameters
|
Number fittype = (Number) modifier.getFieldValue("fit_type");
|
||||||
int offsettype = ((Number) modifier.getFieldValue("offset_type")).intValue();
|
params.put("fittype", fittype);
|
||||||
if((offsettype & 0x01) != 0) {//Constant offset
|
switch (fittype.intValue()) {
|
||||||
DynamicArray<Number> offsetArray = (DynamicArray<Number>)modifier.getFieldValue("offset");
|
case 0://FIXED COUNT
|
||||||
float[] offset = new float[] {offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue()};
|
params.put("count", modifier.getFieldValue("count"));
|
||||||
params.put("offset", offset);
|
break;
|
||||||
}
|
case 1://FIXED LENGTH
|
||||||
if((offsettype & 0x02) != 0) {//Relative offset
|
params.put("length", modifier.getFieldValue("length"));
|
||||||
DynamicArray<Number> scaleArray = (DynamicArray<Number>)modifier.getFieldValue("scale");
|
break;
|
||||||
float[] scale = new float[] {scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()};
|
case 2://FITCURVE
|
||||||
params.put("scale", scale);
|
//TODO: implement after loading curves is added; warning will be generated during modifier applying
|
||||||
}
|
break;
|
||||||
if((offsettype & 0x04) != 0) {//Object offset
|
default:
|
||||||
Pointer pOffsetObject = (Pointer)modifier.getFieldValue("offset_ob");
|
assert false : "Unknown array modifier fit type: " + fittype;
|
||||||
if(!pOffsetObject.isNull()) {
|
}
|
||||||
params.put("offsetob", pOffsetObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//start cap and end cap
|
//offset parameters
|
||||||
Pointer pStartCap = (Pointer)modifier.getFieldValue("start_cap");
|
int offsettype = ((Number) modifier.getFieldValue("offset_type")).intValue();
|
||||||
if(!pStartCap.isNull()) {
|
if ((offsettype & 0x01) != 0) {//Constant offset
|
||||||
params.put("startcap", pStartCap);
|
DynamicArray<Number> offsetArray = (DynamicArray<Number>) modifier.getFieldValue("offset");
|
||||||
}
|
float[] offset = new float[]{offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue()};
|
||||||
Pointer pEndCap = (Pointer)modifier.getFieldValue("end_cap");
|
params.put("offset", offset);
|
||||||
if(!pEndCap.isNull()) {
|
}
|
||||||
params.put("endcap", pEndCap);
|
if ((offsettype & 0x02) != 0) {//Relative offset
|
||||||
}
|
DynamicArray<Number> scaleArray = (DynamicArray<Number>) modifier.getFieldValue("scale");
|
||||||
loadedModifier = params;
|
float[] scale = new float[]{scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()};
|
||||||
} else if(Modifier.ARMATURE_MODIFIER_DATA.equals(modifier.getType())) {//****************ARMATURE MODIFIER
|
params.put("scale", scale);
|
||||||
Pointer pArmatureObject = (Pointer)modifier.getFieldValue("object");
|
}
|
||||||
if(!pArmatureObject.isNull()) {
|
if ((offsettype & 0x04) != 0) {//Object offset
|
||||||
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
|
Pointer pOffsetObject = (Pointer) modifier.getFieldValue("offset_ob");
|
||||||
Structure armatureObject = (Structure)dataRepository.getLoadedFeature(pArmatureObject.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_STRUCTURE);
|
if (!pOffsetObject.isNull()) {
|
||||||
if(armatureObject == null) {//we check this first not to fetch the structure unnecessary
|
params.put("offsetob", pOffsetObject);
|
||||||
armatureObject = pArmatureObject.fetchData(dataRepository.getInputStream()).get(0);
|
}
|
||||||
objectHelper.toObject(armatureObject, dataRepository);
|
}
|
||||||
}
|
|
||||||
modifierAdditionalData = armatureObject.getOldMemoryAddress();
|
|
||||||
ArmatureHelper armatureHelper = dataRepository.getHelper(ArmatureHelper.class);
|
|
||||||
|
|
||||||
//changing bones matrices so that they fit the current object (taht is why we need a copy of a skeleton)
|
//start cap and end cap
|
||||||
Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject);
|
Pointer pStartCap = (Pointer) modifier.getFieldValue("start_cap");
|
||||||
Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert();
|
if (!pStartCap.isNull()) {
|
||||||
Matrix4f additionalRootBoneTransformation = inverseMeshObjectMatrix.multLocal(armatureObjectMatrix);
|
params.put("startcap", pStartCap);
|
||||||
Bone[] bones = armatureHelper.buildBonesStructure(Long.valueOf(0L), additionalRootBoneTransformation);
|
}
|
||||||
|
Pointer pEndCap = (Pointer) modifier.getFieldValue("end_cap");
|
||||||
|
if (!pEndCap.isNull()) {
|
||||||
|
params.put("endcap", pEndCap);
|
||||||
|
}
|
||||||
|
loadedModifier = params;
|
||||||
|
} else if (Modifier.ARMATURE_MODIFIER_DATA.equals(modifier.getType())) {//****************ARMATURE MODIFIER
|
||||||
|
Pointer pArmatureObject = (Pointer) modifier.getFieldValue("object");
|
||||||
|
if (!pArmatureObject.isNull()) {
|
||||||
|
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
|
||||||
|
Structure armatureObject = (Structure) dataRepository.getLoadedFeature(pArmatureObject.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_STRUCTURE);
|
||||||
|
if (armatureObject == null) {//we check this first not to fetch the structure unnecessary
|
||||||
|
armatureObject = pArmatureObject.fetchData(dataRepository.getInputStream()).get(0);
|
||||||
|
objectHelper.toObject(armatureObject, dataRepository);
|
||||||
|
}
|
||||||
|
modifierAdditionalData = armatureObject.getOldMemoryAddress();
|
||||||
|
ArmatureHelper armatureHelper = dataRepository.getHelper(ArmatureHelper.class);
|
||||||
|
|
||||||
String objectName = objectStructure.getName();
|
//changing bones matrices so that they fit the current object (taht is why we need a copy of a skeleton)
|
||||||
Set<String> animationNames = dataRepository.getBlenderKey().getAnimationNames(objectName);
|
Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject);
|
||||||
if(animationNames != null && animationNames.size() > 0) {
|
Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert();
|
||||||
ArrayList<BoneAnimation> animations = new ArrayList<BoneAnimation>();
|
Matrix4f additionalRootBoneTransformation = inverseMeshObjectMatrix.multLocal(armatureObjectMatrix);
|
||||||
List<FileBlockHeader> actionHeaders = dataRepository.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00));
|
Bone[] bones = armatureHelper.buildBonesStructure(Long.valueOf(0L), additionalRootBoneTransformation);
|
||||||
for(FileBlockHeader header : actionHeaders) {
|
|
||||||
Structure actionStructure = header.getStructure(dataRepository);
|
|
||||||
String actionName = actionStructure.getName();
|
|
||||||
if(animationNames.contains(actionName)) {
|
|
||||||
int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, actionName);
|
|
||||||
int fps = dataRepository.getBlenderKey().getFps();
|
|
||||||
float start = (float)animationFrames[0] / (float)fps;
|
|
||||||
float stop = (float)animationFrames[1] / (float)fps;
|
|
||||||
BoneAnimation boneAnimation = new BoneAnimation(actionName, stop - start);
|
|
||||||
boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, dataRepository, objectName, actionName));
|
|
||||||
animations.add(boneAnimation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loadedModifier = new AnimData(new Skeleton(bones), animations);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOGGER.warning("Unsupported modifier type: " + modifier.getType());
|
|
||||||
}
|
|
||||||
} else if(Modifier.PARTICLE_MODIFIER_DATA.equals(modifier.getType())) {//****************PARTICLES MODIFIER
|
|
||||||
Pointer pParticleSystem = (Pointer) modifier.getFieldValue("psys");
|
|
||||||
if(!pParticleSystem.isNull()) {
|
|
||||||
ParticlesHelper particlesHelper = dataRepository.getHelper(ParticlesHelper.class);
|
|
||||||
Structure particleSystem = pParticleSystem.fetchData(dataRepository.getInputStream()).get(0);
|
|
||||||
loadedModifier = particlesHelper.toParticleEmitter(particleSystem, dataRepository);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//adding modifier to the modifier's lists
|
|
||||||
if(loadedModifier != null) {
|
|
||||||
dataRepository.addModifier(objectStructure.getOldMemoryAddress(), modifier.getType(), loadedModifier, modifierAdditionalData);
|
|
||||||
modifierAdditionalData = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
String objectName = objectStructure.getName();
|
||||||
* This method applies particles emitter to the given node.
|
Set<String> animationNames = dataRepository.getBlenderKey().getAnimationNames(objectName);
|
||||||
* @param node the particles emitter node
|
if (animationNames != null && animationNames.size() > 0) {
|
||||||
* @param modifier the modifier containing the emitter data
|
ArrayList<BoneAnimation> animations = new ArrayList<BoneAnimation>();
|
||||||
* @param dataRepository the data repository
|
List<FileBlockHeader> actionHeaders = dataRepository.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00));
|
||||||
* @return node with particles' emitter applied
|
for (FileBlockHeader header : actionHeaders) {
|
||||||
*/
|
Structure actionStructure = header.getStructure(dataRepository);
|
||||||
protected Node applyParticleSystemModifierData(Node node, Modifier modifier, DataRepository dataRepository) {
|
String actionName = actionStructure.getName();
|
||||||
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
|
if (animationNames.contains(actionName)) {
|
||||||
ParticleEmitter emitter = (ParticleEmitter) modifier.getJmeModifierRepresentation();
|
int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, actionName);
|
||||||
emitter = emitter.clone();
|
int fps = dataRepository.getBlenderKey().getFps();
|
||||||
|
float start = (float) animationFrames[0] / (float) fps;
|
||||||
|
float stop = (float) animationFrames[1] / (float) fps;
|
||||||
|
BoneAnimation boneAnimation = new BoneAnimation(actionName, stop - start);
|
||||||
|
boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, dataRepository, objectName, actionName));
|
||||||
|
animations.add(boneAnimation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadedModifier = new AnimData(new Skeleton(bones), animations);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOGGER.warning("Unsupported modifier type: " + modifier.getType());
|
||||||
|
}
|
||||||
|
} else if (Modifier.PARTICLE_MODIFIER_DATA.equals(modifier.getType())) {//****************PARTICLES MODIFIER
|
||||||
|
Pointer pParticleSystem = (Pointer) modifier.getFieldValue("psys");
|
||||||
|
if (!pParticleSystem.isNull()) {
|
||||||
|
ParticlesHelper particlesHelper = dataRepository.getHelper(ParticlesHelper.class);
|
||||||
|
Structure particleSystem = pParticleSystem.fetchData(dataRepository.getInputStream()).get(0);
|
||||||
|
loadedModifier = particlesHelper.toParticleEmitter(particleSystem, dataRepository);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//adding modifier to the modifier's lists
|
||||||
|
if (loadedModifier != null) {
|
||||||
|
dataRepository.addModifier(objectStructure.getOldMemoryAddress(), modifier.getType(), loadedModifier, modifierAdditionalData);
|
||||||
|
modifierAdditionalData = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//veryfying the alpha function for particles' texture
|
/**
|
||||||
Integer alphaFunction = MaterialHelper.ALPHA_MASK_HYPERBOLE;
|
* This method applies particles emitter to the given node.
|
||||||
char nameSuffix = emitter.getName().charAt(emitter.getName().length()-1);
|
* @param node the particles emitter node
|
||||||
if(nameSuffix=='B' || nameSuffix=='N') {
|
* @param modifier the modifier containing the emitter data
|
||||||
alphaFunction = MaterialHelper.ALPHA_MASK_NONE;
|
* @param dataRepository the data repository
|
||||||
}
|
* @return node with particles' emitter applied
|
||||||
//removing the type suffix from the name
|
*/
|
||||||
emitter.setName(emitter.getName().substring(0, emitter.getName().length()-1));
|
protected Node applyParticleSystemModifierData(Node node, Modifier modifier, DataRepository dataRepository) {
|
||||||
|
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
|
||||||
|
ParticleEmitter emitter = (ParticleEmitter) modifier.getJmeModifierRepresentation();
|
||||||
|
emitter = emitter.clone();
|
||||||
|
|
||||||
//applying emitter shape
|
//veryfying the alpha function for particles' texture
|
||||||
EmitterShape emitterShape = emitter.getShape();
|
Integer alphaFunction = MaterialHelper.ALPHA_MASK_HYPERBOLE;
|
||||||
List<Mesh> meshes = new ArrayList<Mesh>();
|
char nameSuffix = emitter.getName().charAt(emitter.getName().length() - 1);
|
||||||
for(Spatial spatial : node.getChildren()) {
|
if (nameSuffix == 'B' || nameSuffix == 'N') {
|
||||||
if(spatial instanceof Geometry) {
|
alphaFunction = MaterialHelper.ALPHA_MASK_NONE;
|
||||||
Mesh mesh = ((Geometry) spatial).getMesh();
|
}
|
||||||
if(mesh != null) {
|
//removing the type suffix from the name
|
||||||
meshes.add(mesh);
|
emitter.setName(emitter.getName().substring(0, emitter.getName().length() - 1));
|
||||||
Material material = materialHelper.getParticlesMaterial(((Geometry) spatial).getMaterial(), alphaFunction, dataRepository);
|
|
||||||
emitter.setMaterial(material);//TODO: divide into several pieces
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(meshes.size()>0 && emitterShape instanceof EmitterMeshVertexShape) {
|
|
||||||
((EmitterMeshVertexShape) emitterShape).setMeshes(meshes);
|
|
||||||
}
|
|
||||||
|
|
||||||
node.attachChild(emitter);
|
//applying emitter shape
|
||||||
return node;
|
EmitterShape emitterShape = emitter.getShape();
|
||||||
}
|
List<Mesh> meshes = new ArrayList<Mesh>();
|
||||||
|
for (Spatial spatial : node.getChildren()) {
|
||||||
|
if (spatial instanceof Geometry) {
|
||||||
|
Mesh mesh = ((Geometry) spatial).getMesh();
|
||||||
|
if (mesh != null) {
|
||||||
|
meshes.add(mesh);
|
||||||
|
Material material = materialHelper.getParticlesMaterial(((Geometry) spatial).getMaterial(), alphaFunction, dataRepository);
|
||||||
|
emitter.setMaterial(material);//TODO: divide into several pieces
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (meshes.size() > 0 && emitterShape instanceof EmitterMeshVertexShape) {
|
||||||
|
((EmitterMeshVertexShape) emitterShape).setMeshes(meshes);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
node.attachChild(emitter);
|
||||||
* This method applies ArmatureModifierData to the loaded object.
|
return node;
|
||||||
* @param node
|
}
|
||||||
* the loaded object
|
|
||||||
* @param modifier
|
|
||||||
* the modifier to apply
|
|
||||||
* @param dataRepository
|
|
||||||
* the data repository
|
|
||||||
* @return the node to whom the modifier was applied
|
|
||||||
*/
|
|
||||||
protected Node applyArmatureModifierData(Node node, Modifier modifier, DataRepository dataRepository) {
|
|
||||||
AnimData ad = (AnimData)modifier.getJmeModifierRepresentation();
|
|
||||||
ArrayList<BoneAnimation> animList = ad.anims;
|
|
||||||
Long modifierArmatureObject = (Long)modifier.getAdditionalData();
|
|
||||||
if(animList != null && animList.size() > 0) {
|
|
||||||
ConstraintHelper constraintHelper = dataRepository.getHelper(ConstraintHelper.class);
|
|
||||||
Constraint[] constraints = constraintHelper.getConstraints(modifierArmatureObject);
|
|
||||||
HashMap<String, BoneAnimation> anims = new HashMap<String, BoneAnimation>();
|
|
||||||
for(int i = 0; i < animList.size(); ++i) {
|
|
||||||
BoneAnimation boneAnimation = this.cloneBoneAnimation(animList.get(i));
|
|
||||||
|
|
||||||
//baking constraints into animations
|
/**
|
||||||
if(constraints != null && constraints.length > 0) {
|
* This method applies ArmatureModifierData to the loaded object.
|
||||||
for(Constraint constraint : constraints) {
|
* @param node
|
||||||
constraint.affectAnimation(ad.skeleton, boneAnimation);
|
* the loaded object
|
||||||
}
|
* @param modifier
|
||||||
}
|
* the modifier to apply
|
||||||
|
* @param dataRepository
|
||||||
|
* the data repository
|
||||||
|
* @return the node to whom the modifier was applied
|
||||||
|
*/
|
||||||
|
protected Node applyArmatureModifierData(Node node, Modifier modifier, DataRepository dataRepository) {
|
||||||
|
AnimData ad = (AnimData) modifier.getJmeModifierRepresentation();
|
||||||
|
ArrayList<BoneAnimation> animList = ad.anims;
|
||||||
|
Long modifierArmatureObject = (Long) modifier.getAdditionalData();
|
||||||
|
if (animList != null && animList.size() > 0) {
|
||||||
|
ConstraintHelper constraintHelper = dataRepository.getHelper(ConstraintHelper.class);
|
||||||
|
Constraint[] constraints = constraintHelper.getConstraints(modifierArmatureObject);
|
||||||
|
HashMap<String, BoneAnimation> anims = new HashMap<String, BoneAnimation>();
|
||||||
|
for (int i = 0; i < animList.size(); ++i) {
|
||||||
|
BoneAnimation boneAnimation = this.cloneBoneAnimation(animList.get(i));
|
||||||
|
|
||||||
anims.put(boneAnimation.getName(), boneAnimation);
|
//baking constraints into animations
|
||||||
}
|
if (constraints != null && constraints.length > 0) {
|
||||||
|
for (Constraint constraint : constraints) {
|
||||||
|
constraint.affectAnimation(ad.skeleton, boneAnimation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//getting meshes
|
anims.put(boneAnimation.getName(), boneAnimation);
|
||||||
Mesh[] meshes = null;
|
}
|
||||||
List<Mesh> meshesList = new ArrayList<Mesh>();
|
|
||||||
List<Spatial> children = node.getChildren();
|
|
||||||
for(Spatial child : children) {
|
|
||||||
if(child instanceof Geometry) {
|
|
||||||
meshesList.add(((Geometry)child).getMesh());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(meshesList.size() > 0) {
|
|
||||||
meshes = meshesList.toArray(new Mesh[meshesList.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//applying the control to the node
|
//getting meshes
|
||||||
SkeletonControl skeletonControl = new SkeletonControl(meshes, ad.skeleton);
|
Mesh[] meshes = null;
|
||||||
AnimControl control = node.getControl(AnimControl.class);
|
List<Mesh> meshesList = new ArrayList<Mesh>();
|
||||||
|
List<Spatial> children = node.getChildren();
|
||||||
|
for (Spatial child : children) {
|
||||||
|
if (child instanceof Geometry) {
|
||||||
|
meshesList.add(((Geometry) child).getMesh());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (meshesList.size() > 0) {
|
||||||
|
meshes = meshesList.toArray(new Mesh[meshesList.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
if(control == null) {
|
//applying the control to the node
|
||||||
control = new AnimControl(ad.skeleton);
|
SkeletonControl skeletonControl = new SkeletonControl(meshes, ad.skeleton);
|
||||||
} else {
|
AnimControl control = node.getControl(AnimControl.class);
|
||||||
//merging skeletons
|
|
||||||
Skeleton controlSkeleton = control.getSkeleton();
|
|
||||||
int boneIndexIncrease = controlSkeleton.getBoneCount();
|
|
||||||
Skeleton skeleton = this.merge(controlSkeleton, ad.skeleton);
|
|
||||||
|
|
||||||
//merging animations
|
if (control == null) {
|
||||||
HashMap<String, BoneAnimation> animations = new HashMap<String, BoneAnimation>();
|
control = new AnimControl(ad.skeleton);
|
||||||
for(String animationName : control.getAnimationNames()) {
|
} else {
|
||||||
animations.put(animationName, control.getAnim(animationName));
|
//merging skeletons
|
||||||
}
|
Skeleton controlSkeleton = control.getSkeleton();
|
||||||
for(Entry<String, BoneAnimation> animEntry : anims.entrySet()) {
|
int boneIndexIncrease = controlSkeleton.getBoneCount();
|
||||||
BoneAnimation ba = animEntry.getValue();
|
Skeleton skeleton = this.merge(controlSkeleton, ad.skeleton);
|
||||||
for(int i = 0; i < ba.getTracks().length; ++i) {
|
|
||||||
BoneTrack bt = ba.getTracks()[i];
|
|
||||||
int newBoneIndex = bt.getTargetBoneIndex() + boneIndexIncrease;
|
|
||||||
ba.getTracks()[i] = new BoneTrack(newBoneIndex, bt.getTimes(), bt.getTranslations(), bt.getRotations(), bt.getScales());
|
|
||||||
}
|
|
||||||
animations.put(animEntry.getKey(), animEntry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
//replacing the control
|
//merging animations
|
||||||
node.removeControl(control);
|
HashMap<String, BoneAnimation> animations = new HashMap<String, BoneAnimation>();
|
||||||
control = new AnimControl(skeleton);
|
for (String animationName : control.getAnimationNames()) {
|
||||||
}
|
animations.put(animationName, control.getAnim(animationName));
|
||||||
control.setAnimations(anims);
|
}
|
||||||
node.addControl(control);
|
for (Entry<String, BoneAnimation> animEntry : anims.entrySet()) {
|
||||||
node.addControl(skeletonControl);
|
BoneAnimation ba = animEntry.getValue();
|
||||||
}
|
for (int i = 0; i < ba.getTracks().length; ++i) {
|
||||||
return node;
|
BoneTrack bt = ba.getTracks()[i];
|
||||||
}
|
int newBoneIndex = bt.getTargetBoneIndex() + boneIndexIncrease;
|
||||||
|
ba.getTracks()[i] = new BoneTrack(newBoneIndex, bt.getTimes(), bt.getTranslations(), bt.getRotations(), bt.getScales());
|
||||||
|
}
|
||||||
|
animations.put(animEntry.getKey(), animEntry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
//replacing the control
|
||||||
* This method applies the array modifier to the node.
|
node.removeControl(control);
|
||||||
* @param node
|
control = new AnimControl(skeleton);
|
||||||
* the object the modifier will be applied to
|
}
|
||||||
* @param modifier
|
control.setAnimations(anims);
|
||||||
* the modifier to be applied
|
node.addControl(control);
|
||||||
* @param dataRepository
|
node.addControl(skeletonControl);
|
||||||
* the data repository
|
}
|
||||||
* @return object node with arry modifier applied
|
return node;
|
||||||
*/
|
}
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected Node applyArrayModifierData(Node node, Modifier modifier, DataRepository dataRepository) {
|
|
||||||
Map<String, Object> modifierData = (Map<String, Object>) modifier.getJmeModifierRepresentation();
|
|
||||||
int fittype = ((Number)modifierData.get("fittype")).intValue();
|
|
||||||
float[] offset = (float[])modifierData.get("offset");
|
|
||||||
if(offset==null) {//the node will be repeated several times in the same place
|
|
||||||
offset = new float[] {0.0f, 0.0f, 0.0f};
|
|
||||||
}
|
|
||||||
float[] scale = (float[])modifierData.get("scale");
|
|
||||||
if(scale==null) {//the node will be repeated several times in the same place
|
|
||||||
scale = new float[] {0.0f, 0.0f, 0.0f};
|
|
||||||
} else {
|
|
||||||
//getting bounding box
|
|
||||||
node.updateModelBound();
|
|
||||||
BoundingVolume boundingVolume = node.getWorldBound();
|
|
||||||
if(boundingVolume instanceof BoundingBox) {
|
|
||||||
scale[0] *= ((BoundingBox) boundingVolume).getXExtent() * 2.0f;
|
|
||||||
scale[1] *= ((BoundingBox) boundingVolume).getYExtent() * 2.0f;
|
|
||||||
scale[2] *= ((BoundingBox) boundingVolume).getZExtent() * 2.0f;
|
|
||||||
} else if(boundingVolume instanceof BoundingSphere) {
|
|
||||||
float radius = ((BoundingSphere) boundingVolume).getRadius();
|
|
||||||
scale[0] *= radius * 2.0f;
|
|
||||||
scale[1] *= radius * 2.0f;
|
|
||||||
scale[2] *= radius * 2.0f;
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Unknown bounding volume type: " + boundingVolume.getClass().getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//adding object's offset
|
/**
|
||||||
float[] objectOffset = new float[] {0.0f, 0.0f, 0.0f};
|
* This method applies the array modifier to the node.
|
||||||
Pointer pOffsetObject = (Pointer) modifierData.get("offsetob");
|
* @param node
|
||||||
if(pOffsetObject!=null) {
|
* the object the modifier will be applied to
|
||||||
FileBlockHeader offsetObjectBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress());
|
* @param modifier
|
||||||
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
|
* the modifier to be applied
|
||||||
try {//we take the structure in case the object was not yet loaded
|
* @param dataRepository
|
||||||
Structure offsetStructure = offsetObjectBlock.getStructure(dataRepository);
|
* the data repository
|
||||||
Vector3f translation = objectHelper.getTransformation(offsetStructure).getTranslation();
|
* @return object node with arry modifier applied
|
||||||
objectOffset[0] = translation.x;
|
*/
|
||||||
objectOffset[1] = translation.y;
|
@SuppressWarnings("unchecked")
|
||||||
objectOffset[2] = translation.z;
|
protected Node applyArrayModifierData(Node node, Modifier modifier, DataRepository dataRepository) {
|
||||||
} catch (BlenderFileException e) {
|
Map<String, Object> modifierData = (Map<String, Object>) modifier.getJmeModifierRepresentation();
|
||||||
LOGGER.warning("Problems in blender file structure! Object offset cannot be applied! The problem: " + e.getMessage());
|
int fittype = ((Number) modifierData.get("fittype")).intValue();
|
||||||
}
|
float[] offset = (float[]) modifierData.get("offset");
|
||||||
}
|
if (offset == null) {//the node will be repeated several times in the same place
|
||||||
|
offset = new float[]{0.0f, 0.0f, 0.0f};
|
||||||
|
}
|
||||||
|
float[] scale = (float[]) modifierData.get("scale");
|
||||||
|
if (scale == null) {//the node will be repeated several times in the same place
|
||||||
|
scale = new float[]{0.0f, 0.0f, 0.0f};
|
||||||
|
} else {
|
||||||
|
//getting bounding box
|
||||||
|
node.updateModelBound();
|
||||||
|
BoundingVolume boundingVolume = node.getWorldBound();
|
||||||
|
if (boundingVolume instanceof BoundingBox) {
|
||||||
|
scale[0] *= ((BoundingBox) boundingVolume).getXExtent() * 2.0f;
|
||||||
|
scale[1] *= ((BoundingBox) boundingVolume).getYExtent() * 2.0f;
|
||||||
|
scale[2] *= ((BoundingBox) boundingVolume).getZExtent() * 2.0f;
|
||||||
|
} else if (boundingVolume instanceof BoundingSphere) {
|
||||||
|
float radius = ((BoundingSphere) boundingVolume).getRadius();
|
||||||
|
scale[0] *= radius * 2.0f;
|
||||||
|
scale[1] *= radius * 2.0f;
|
||||||
|
scale[2] *= radius * 2.0f;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unknown bounding volume type: " + boundingVolume.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//getting start and end caps
|
//adding object's offset
|
||||||
Node[] caps = new Node[] {null, null};
|
float[] objectOffset = new float[]{0.0f, 0.0f, 0.0f};
|
||||||
Pointer[] pCaps = new Pointer[] {(Pointer) modifierData.get("startcap"), (Pointer) modifierData.get("endcap")};
|
Pointer pOffsetObject = (Pointer) modifierData.get("offsetob");
|
||||||
for(int i=0;i<pCaps.length;++i) {
|
if (pOffsetObject != null) {
|
||||||
if(pCaps[i]!=null) {
|
FileBlockHeader offsetObjectBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress());
|
||||||
caps[i] = (Node) dataRepository.getLoadedFeature(pCaps[i].getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE);
|
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
|
||||||
if(caps[i]!=null) {
|
try {//we take the structure in case the object was not yet loaded
|
||||||
caps[i] = (Node) caps[i].clone();
|
Structure offsetStructure = offsetObjectBlock.getStructure(dataRepository);
|
||||||
} else {
|
Vector3f translation = objectHelper.getTransformation(offsetStructure).getTranslation();
|
||||||
FileBlockHeader capBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress());
|
objectOffset[0] = translation.x;
|
||||||
try {//we take the structure in case the object was not yet loaded
|
objectOffset[1] = translation.y;
|
||||||
Structure capStructure = capBlock.getStructure(dataRepository);
|
objectOffset[2] = translation.z;
|
||||||
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
|
} catch (BlenderFileException e) {
|
||||||
caps[i] = (Node) objectHelper.toObject(capStructure, dataRepository);
|
LOGGER.warning("Problems in blender file structure! Object offset cannot be applied! The problem: " + e.getMessage());
|
||||||
if(caps[i]==null) {
|
}
|
||||||
LOGGER.warning("Cap object '" + capStructure.getName() + "' couldn't be loaded!");
|
}
|
||||||
}
|
|
||||||
} catch (BlenderFileException e) {
|
|
||||||
LOGGER.warning("Problems in blender file structure! Cap object cannot be applied! The problem: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3f translationVector = new Vector3f(offset[0] + scale[0] + objectOffset[0],
|
//getting start and end caps
|
||||||
offset[1] + scale[1] + objectOffset[1],
|
Node[] caps = new Node[]{null, null};
|
||||||
offset[2] + scale[2] + objectOffset[2]);
|
Pointer[] pCaps = new Pointer[]{(Pointer) modifierData.get("startcap"), (Pointer) modifierData.get("endcap")};
|
||||||
|
for (int i = 0; i < pCaps.length; ++i) {
|
||||||
|
if (pCaps[i] != null) {
|
||||||
|
caps[i] = (Node) dataRepository.getLoadedFeature(pCaps[i].getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE);
|
||||||
|
if (caps[i] != null) {
|
||||||
|
caps[i] = (Node) caps[i].clone();
|
||||||
|
} else {
|
||||||
|
FileBlockHeader capBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress());
|
||||||
|
try {//we take the structure in case the object was not yet loaded
|
||||||
|
Structure capStructure = capBlock.getStructure(dataRepository);
|
||||||
|
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
|
||||||
|
caps[i] = (Node) objectHelper.toObject(capStructure, dataRepository);
|
||||||
|
if (caps[i] == null) {
|
||||||
|
LOGGER.warning("Cap object '" + capStructure.getName() + "' couldn't be loaded!");
|
||||||
|
}
|
||||||
|
} catch (BlenderFileException e) {
|
||||||
|
LOGGER.warning("Problems in blender file structure! Cap object cannot be applied! The problem: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//getting/calculating repeats amount
|
Vector3f translationVector = new Vector3f(offset[0] + scale[0] + objectOffset[0],
|
||||||
int count = 0;
|
offset[1] + scale[1] + objectOffset[1],
|
||||||
if(fittype==0) {//Fixed count
|
offset[2] + scale[2] + objectOffset[2]);
|
||||||
count = ((Number)modifierData.get("count")).intValue() - 1;
|
|
||||||
} else if(fittype==1) {//Fixed length
|
|
||||||
float length = ((Number)modifierData.get("length")).floatValue();
|
|
||||||
if(translationVector.length()>0.0f) {
|
|
||||||
count = (int)(length / translationVector.length()) - 1;
|
|
||||||
}
|
|
||||||
} else if(fittype==2) {//Fit curve
|
|
||||||
LOGGER.warning("Fit curve mode in array modifier not yet implemented!");//TODO: implement fit curve
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Unknown fit type: " + fittype);
|
|
||||||
}
|
|
||||||
|
|
||||||
//adding translated nodes and caps
|
//getting/calculating repeats amount
|
||||||
if(count>0) {
|
int count = 0;
|
||||||
Node[] arrayNodes = new Node[count];
|
if (fittype == 0) {//Fixed count
|
||||||
Vector3f newTranslation = node.getLocalTranslation().clone();
|
count = ((Number) modifierData.get("count")).intValue() - 1;
|
||||||
for(int i=0;i<count;++i) {
|
} else if (fittype == 1) {//Fixed length
|
||||||
newTranslation.addLocal(translationVector);
|
float length = ((Number) modifierData.get("length")).floatValue();
|
||||||
Node nodeClone = (Node) node.clone();
|
if (translationVector.length() > 0.0f) {
|
||||||
nodeClone.setLocalTranslation(newTranslation);
|
count = (int) (length / translationVector.length()) - 1;
|
||||||
arrayNodes[i] = nodeClone;
|
}
|
||||||
}
|
} else if (fittype == 2) {//Fit curve
|
||||||
for(Node nodeClone : arrayNodes) {
|
LOGGER.warning("Fit curve mode in array modifier not yet implemented!");//TODO: implement fit curve
|
||||||
node.attachChild(nodeClone);
|
} else {
|
||||||
}
|
throw new IllegalStateException("Unknown fit type: " + fittype);
|
||||||
if(caps[0]!=null) {
|
}
|
||||||
caps[0].getLocalTranslation().set(node.getLocalTranslation()).subtractLocal(translationVector);
|
|
||||||
node.attachChild(caps[0]);
|
|
||||||
}
|
|
||||||
if(caps[1]!=null) {
|
|
||||||
caps[1].getLocalTranslation().set(newTranslation).addLocal(translationVector);
|
|
||||||
node.attachChild(caps[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
//adding translated nodes and caps
|
||||||
* This class clones the bone animation data.
|
if (count > 0) {
|
||||||
* @param source
|
Node[] arrayNodes = new Node[count];
|
||||||
* the source that is to be cloned
|
Vector3f newTranslation = node.getLocalTranslation().clone();
|
||||||
* @return the copy of the given bone animation
|
for (int i = 0; i < count; ++i) {
|
||||||
*/
|
newTranslation.addLocal(translationVector);
|
||||||
protected BoneAnimation cloneBoneAnimation(BoneAnimation source) {
|
Node nodeClone = (Node) node.clone();
|
||||||
BoneAnimation result = new BoneAnimation(source.getName(), source.getLength());
|
nodeClone.setLocalTranslation(newTranslation);
|
||||||
|
arrayNodes[i] = nodeClone;
|
||||||
|
}
|
||||||
|
for (Node nodeClone : arrayNodes) {
|
||||||
|
node.attachChild(nodeClone);
|
||||||
|
}
|
||||||
|
if (caps[0] != null) {
|
||||||
|
caps[0].getLocalTranslation().set(node.getLocalTranslation()).subtractLocal(translationVector);
|
||||||
|
node.attachChild(caps[0]);
|
||||||
|
}
|
||||||
|
if (caps[1] != null) {
|
||||||
|
caps[1].getLocalTranslation().set(newTranslation).addLocal(translationVector);
|
||||||
|
node.attachChild(caps[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
//copying tracks and applying constraints
|
/**
|
||||||
BoneTrack[] sourceTracks = source.getTracks();
|
* This class clones the bone animation data.
|
||||||
BoneTrack[] boneTracks = new BoneTrack[sourceTracks.length];
|
* @param source
|
||||||
for(int i = 0; i < sourceTracks.length; ++i) {
|
* the source that is to be cloned
|
||||||
int tablesLength = sourceTracks[i].getTimes().length;
|
* @return the copy of the given bone animation
|
||||||
|
*/
|
||||||
|
protected BoneAnimation cloneBoneAnimation(BoneAnimation source) {
|
||||||
|
BoneAnimation result = new BoneAnimation(source.getName(), source.getLength());
|
||||||
|
|
||||||
Vector3f[] sourceTranslations = sourceTracks[i].getTranslations();
|
//copying tracks and applying constraints
|
||||||
Quaternion[] sourceRotations = sourceTracks[i].getRotations();
|
BoneTrack[] sourceTracks = source.getTracks();
|
||||||
Vector3f[] sourceScales = sourceTracks[i].getScales();
|
BoneTrack[] boneTracks = new BoneTrack[sourceTracks.length];
|
||||||
|
for (int i = 0; i < sourceTracks.length; ++i) {
|
||||||
|
int tablesLength = sourceTracks[i].getTimes().length;
|
||||||
|
|
||||||
Vector3f[] translations = new Vector3f[tablesLength];
|
Vector3f[] sourceTranslations = sourceTracks[i].getTranslations();
|
||||||
Quaternion[] rotations = new Quaternion[tablesLength];
|
Quaternion[] sourceRotations = sourceTracks[i].getRotations();
|
||||||
Vector3f[] scales = sourceScales == null ? null : new Vector3f[tablesLength];
|
Vector3f[] sourceScales = sourceTracks[i].getScales();
|
||||||
for(int j = 0; j < tablesLength; ++j) {
|
|
||||||
translations[j] = sourceTranslations[j].clone();
|
|
||||||
rotations[j] = sourceRotations[j].clone();
|
|
||||||
if(sourceScales != null) {//only scales may not be applied
|
|
||||||
scales[j] = sourceScales[j].clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
boneTracks[i] = new BoneTrack(sourceTracks[i].getTargetBoneIndex(), sourceTracks[i].getTimes(),//times do not change, no need to clone them,
|
|
||||||
translations, rotations, scales);
|
|
||||||
}
|
|
||||||
result.setTracks(boneTracks);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
Vector3f[] translations = new Vector3f[tablesLength];
|
||||||
* This method merges two skeletons into one. I assume that each skeleton's 0-indexed bone is objectAnimationBone so
|
Quaternion[] rotations = new Quaternion[tablesLength];
|
||||||
* only one such bone should be placed in the result
|
Vector3f[] scales = sourceScales == null ? null : new Vector3f[tablesLength];
|
||||||
* @param s1
|
for (int j = 0; j < tablesLength; ++j) {
|
||||||
* first skeleton
|
translations[j] = sourceTranslations[j].clone();
|
||||||
* @param s2
|
rotations[j] = sourceRotations[j].clone();
|
||||||
* second skeleton
|
if (sourceScales != null) {//only scales may not be applied
|
||||||
* @return merged skeleton
|
scales[j] = sourceScales[j].clone();
|
||||||
*/
|
}
|
||||||
protected Skeleton merge(Skeleton s1, Skeleton s2) {
|
}
|
||||||
List<Bone> bones = new ArrayList<Bone>(s1.getBoneCount() + s2.getBoneCount());
|
boneTracks[i] = new BoneTrack(sourceTracks[i].getTargetBoneIndex(), sourceTracks[i].getTimes(),//times do not change, no need to clone them,
|
||||||
for(int i = 0; i < s1.getBoneCount(); ++i) {
|
translations, rotations, scales);
|
||||||
bones.add(s1.getBone(i));
|
}
|
||||||
}
|
result.setTracks(boneTracks);
|
||||||
for(int i = 1; i < s2.getBoneCount(); ++i) {//ommit objectAnimationBone
|
return result;
|
||||||
bones.add(s2.getBone(i));
|
}
|
||||||
}
|
|
||||||
return new Skeleton(bones.toArray(new Bone[bones.size()]));
|
/**
|
||||||
}
|
* This method merges two skeletons into one. I assume that each skeleton's 0-indexed bone is objectAnimationBone so
|
||||||
|
* only one such bone should be placed in the result
|
||||||
|
* @param s1
|
||||||
|
* first skeleton
|
||||||
|
* @param s2
|
||||||
|
* second skeleton
|
||||||
|
* @return merged skeleton
|
||||||
|
*/
|
||||||
|
protected Skeleton merge(Skeleton s1, Skeleton s2) {
|
||||||
|
List<Bone> bones = new ArrayList<Bone>(s1.getBoneCount() + s2.getBoneCount());
|
||||||
|
for (int i = 0; i < s1.getBoneCount(); ++i) {
|
||||||
|
bones.add(s1.getBone(i));
|
||||||
|
}
|
||||||
|
for (int i = 1; i < s2.getBoneCount(); ++i) {//ommit objectAnimationBone
|
||||||
|
bones.add(s2.getBone(i));
|
||||||
|
}
|
||||||
|
return new Skeleton(bones.toArray(new Bone[bones.size()]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -21,205 +21,199 @@ import com.jme3.scene.plugins.blender.utils.Pointer;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractInfluenceFunction {
|
public abstract class AbstractInfluenceFunction {
|
||||||
protected static final Logger LOGGER = Logger.getLogger(AbstractInfluenceFunction.class.getName());
|
|
||||||
|
|
||||||
protected static final float IK_SOLVER_ERROR = 0.5f;
|
protected static final Logger LOGGER = Logger.getLogger(AbstractInfluenceFunction.class.getName());
|
||||||
|
protected static final float IK_SOLVER_ERROR = 0.5f;
|
||||||
|
//DISTLIMIT
|
||||||
|
protected static final int LIMITDIST_INSIDE = 0;
|
||||||
|
protected static final int LIMITDIST_OUTSIDE = 1;
|
||||||
|
protected static final int LIMITDIST_ONSURFACE = 2;
|
||||||
|
//CONSTRAINT_TYPE_LOCLIKE
|
||||||
|
protected static final int LOCLIKE_X = 0x01;
|
||||||
|
protected static final int LOCLIKE_Y = 0x02;
|
||||||
|
protected static final int LOCLIKE_Z = 0x04;
|
||||||
|
//ROTLIKE
|
||||||
|
protected static final int ROTLIKE_X = 0x01;
|
||||||
|
protected static final int ROTLIKE_Y = 0x02;
|
||||||
|
protected static final int ROTLIKE_Z = 0x04;
|
||||||
|
protected static final int ROTLIKE_X_INVERT = 0x10;
|
||||||
|
protected static final int ROTLIKE_Y_INVERT = 0x20;
|
||||||
|
protected static final int ROTLIKE_Z_INVERT = 0x40;
|
||||||
|
protected static final int ROTLIKE_OFFSET = 0x80;
|
||||||
|
//SIZELIKE
|
||||||
|
protected static final int SIZELIKE_X = 0x01;
|
||||||
|
protected static final int SIZELIKE_Y = 0x02;
|
||||||
|
protected static final int SIZELIKE_Z = 0x04;
|
||||||
|
protected static final int SIZELIKE_OFFSET = 0x80;
|
||||||
|
|
||||||
//DISTLIMIT
|
/* LOCLIKE_TIP is a depreceated option... use headtail=1.0f instead */
|
||||||
protected static final int LIMITDIST_INSIDE = 0;
|
//protected static final int LOCLIKE_TIP = 0x08;
|
||||||
protected static final int LIMITDIST_OUTSIDE = 1;
|
protected static final int LOCLIKE_X_INVERT = 0x10;
|
||||||
protected static final int LIMITDIST_ONSURFACE = 2;
|
protected static final int LOCLIKE_Y_INVERT = 0x20;
|
||||||
|
protected static final int LOCLIKE_Z_INVERT = 0x40;
|
||||||
|
protected static final int LOCLIKE_OFFSET = 0x80;
|
||||||
|
//LOCLIMIT, SIZELIMIT
|
||||||
|
protected static final int LIMIT_XMIN = 0x01;
|
||||||
|
protected static final int LIMIT_XMAX = 0x02;
|
||||||
|
protected static final int LIMIT_YMIN = 0x04;
|
||||||
|
protected static final int LIMIT_YMAX = 0x08;
|
||||||
|
protected static final int LIMIT_ZMIN = 0x10;
|
||||||
|
protected static final int LIMIT_ZMAX = 0x20;
|
||||||
|
//ROTLIMIT
|
||||||
|
protected static final int LIMIT_XROT = 0x01;
|
||||||
|
protected static final int LIMIT_YROT = 0x02;
|
||||||
|
protected static final int LIMIT_ZROT = 0x04;
|
||||||
|
/** The type of the constraint. */
|
||||||
|
protected ConstraintType constraintType;
|
||||||
|
/** The data repository. */
|
||||||
|
protected DataRepository dataRepository;
|
||||||
|
|
||||||
//CONSTRAINT_TYPE_LOCLIKE
|
/**
|
||||||
protected static final int LOCLIKE_X = 0x01;
|
* Constructor.
|
||||||
protected static final int LOCLIKE_Y = 0x02;
|
* @param constraintType
|
||||||
protected static final int LOCLIKE_Z = 0x04;
|
* the type of the current constraint
|
||||||
|
* @param dataRepository
|
||||||
|
* the data repository
|
||||||
|
*/
|
||||||
|
public AbstractInfluenceFunction(ConstraintType constraintType, DataRepository dataRepository) {
|
||||||
|
this.constraintType = constraintType;
|
||||||
|
this.dataRepository = dataRepository;
|
||||||
|
}
|
||||||
|
|
||||||
//ROTLIKE
|
/**
|
||||||
protected static final int ROTLIKE_X = 0x01;
|
* This method validates the constraint type. It throws an IllegalArgumentException if the constraint type of the
|
||||||
protected static final int ROTLIKE_Y = 0x02;
|
* given structure is invalid.
|
||||||
protected static final int ROTLIKE_Z = 0x04;
|
* @param constraintStructure
|
||||||
protected static final int ROTLIKE_X_INVERT = 0x10;
|
* the structure with constraint data
|
||||||
protected static final int ROTLIKE_Y_INVERT = 0x20;
|
*/
|
||||||
protected static final int ROTLIKE_Z_INVERT = 0x40;
|
protected void validateConstraintType(Structure constraintStructure) {
|
||||||
protected static final int ROTLIKE_OFFSET = 0x80;
|
if (!constraintType.getClassName().equalsIgnoreCase(constraintStructure.getType())) {
|
||||||
|
throw new IllegalArgumentException("Invalud structure type (" + constraintStructure.getType() + ") for the constraint: " + constraintType.getClassName() + '!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//SIZELIKE
|
/**
|
||||||
protected static final int SIZELIKE_X = 0x01;
|
* This method affects the bone animation tracks for the given skeleton.
|
||||||
protected static final int SIZELIKE_Y = 0x02;
|
* @param skeleton
|
||||||
protected static final int SIZELIKE_Z = 0x04;
|
* the skeleton containing the affected bones by constraint
|
||||||
protected static final int SIZELIKE_OFFSET = 0x80;
|
* @param boneAnimation
|
||||||
|
* the bone animation baked traces
|
||||||
|
* @param constraint
|
||||||
|
* the constraint
|
||||||
|
*/
|
||||||
|
public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
|
||||||
|
}
|
||||||
|
|
||||||
/* LOCLIKE_TIP is a depreceated option... use headtail=1.0f instead */
|
/**
|
||||||
//protected static final int LOCLIKE_TIP = 0x08;
|
* This method returns the bone traces for the bone that is affected by the given constraint.
|
||||||
protected static final int LOCLIKE_X_INVERT = 0x10;
|
* @param skeleton
|
||||||
protected static final int LOCLIKE_Y_INVERT = 0x20;
|
* the skeleton containing bones
|
||||||
protected static final int LOCLIKE_Z_INVERT = 0x40;
|
* @param boneAnimation
|
||||||
protected static final int LOCLIKE_OFFSET = 0x80;
|
* the bone animation that affects the skeleton
|
||||||
|
* @param constraint
|
||||||
|
* the affecting constraint
|
||||||
|
* @return the bone track for the bone that is being affected by the constraint
|
||||||
|
*/
|
||||||
|
protected BoneTrack getBoneTrack(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
|
||||||
|
Long boneOMA = constraint.getBoneOMA();
|
||||||
|
Bone bone = (Bone) dataRepository.getLoadedFeature(boneOMA, LoadedFeatureDataType.LOADED_FEATURE);
|
||||||
|
int boneIndex = skeleton.getBoneIndex(bone);
|
||||||
|
if (boneIndex != -1) {
|
||||||
|
//searching for track for this bone
|
||||||
|
for (BoneTrack boneTrack : boneAnimation.getTracks()) {
|
||||||
|
if (boneTrack.getTargetBoneIndex() == boneIndex) {
|
||||||
|
return boneTrack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
//LOCLIMIT, SIZELIMIT
|
/**
|
||||||
protected static final int LIMIT_XMIN = 0x01;
|
* This method returns the target or subtarget object (if specified).
|
||||||
protected static final int LIMIT_XMAX = 0x02;
|
* @param constraint
|
||||||
protected static final int LIMIT_YMIN = 0x04;
|
* the constraint instance
|
||||||
protected static final int LIMIT_YMAX = 0x08;
|
* @return target or subtarget feature
|
||||||
protected static final int LIMIT_ZMIN = 0x10;
|
*/
|
||||||
protected static final int LIMIT_ZMAX = 0x20;
|
protected Object getTarget(Constraint constraint, LoadedFeatureDataType loadedFeatureDataType) {
|
||||||
|
Long targetOMA = ((Pointer) constraint.getData().getFieldValue("tar")).getOldMemoryAddress();
|
||||||
|
Object targetObject = dataRepository.getLoadedFeature(targetOMA, loadedFeatureDataType);
|
||||||
|
String subtargetName = constraint.getData().getFieldValue("subtarget").toString();
|
||||||
|
if (subtargetName.length() > 0) {
|
||||||
|
return dataRepository.getLoadedFeature(subtargetName, loadedFeatureDataType);
|
||||||
|
}
|
||||||
|
return targetObject;
|
||||||
|
}
|
||||||
|
|
||||||
//ROTLIMIT
|
/**
|
||||||
protected static final int LIMIT_XROT = 0x01;
|
* This method returns target's object location.
|
||||||
protected static final int LIMIT_YROT = 0x02;
|
* @param constraint
|
||||||
protected static final int LIMIT_ZROT = 0x04;
|
* the constraint instance
|
||||||
|
* @return target's object location
|
||||||
|
*/
|
||||||
|
protected Vector3f getTargetLocation(Constraint constraint) {
|
||||||
|
Long targetOMA = ((Pointer) constraint.getData().getFieldValue("tar")).getOldMemoryAddress();
|
||||||
|
Space targetSpace = constraint.getTargetSpace();
|
||||||
|
Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
|
||||||
|
switch (targetSpace) {
|
||||||
|
case CONSTRAINT_SPACE_LOCAL:
|
||||||
|
return targetObject.getLocalTranslation();
|
||||||
|
case CONSTRAINT_SPACE_WORLD:
|
||||||
|
return targetObject.getWorldTranslation();
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** The type of the constraint. */
|
/**
|
||||||
protected ConstraintType constraintType;
|
* This method returns target's object location in the specified frame.
|
||||||
/** The data repository. */
|
* @param constraint
|
||||||
protected DataRepository dataRepository;
|
* the constraint instance
|
||||||
|
* @param frame
|
||||||
|
* the frame number
|
||||||
|
* @return target's object location
|
||||||
|
*/
|
||||||
|
protected Vector3f getTargetLocation(Constraint constraint, int frame) {
|
||||||
|
return this.getTargetLocation(constraint);//TODO: implement getting location in a specified frame
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* This method returns target's object rotation.
|
||||||
* @param constraintType
|
* @param constraint
|
||||||
* the type of the current constraint
|
* the constraint instance
|
||||||
* @param dataRepository
|
* @return target's object rotation
|
||||||
* the data repository
|
*/
|
||||||
*/
|
protected Quaternion getTargetRotation(Constraint constraint) {
|
||||||
public AbstractInfluenceFunction(ConstraintType constraintType, DataRepository dataRepository) {
|
Long targetOMA = ((Pointer) constraint.getData().getFieldValue("tar")).getOldMemoryAddress();
|
||||||
this.constraintType = constraintType;
|
Space targetSpace = constraint.getTargetSpace();
|
||||||
this.dataRepository = dataRepository;
|
Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
|
||||||
}
|
switch (targetSpace) {
|
||||||
|
case CONSTRAINT_SPACE_LOCAL:
|
||||||
|
return targetObject.getLocalRotation();
|
||||||
|
case CONSTRAINT_SPACE_WORLD:
|
||||||
|
return targetObject.getWorldRotation();
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method validates the constraint type. It throws an IllegalArgumentException if the constraint type of the
|
* This method returns target's object scale.
|
||||||
* given structure is invalid.
|
* @param constraint
|
||||||
* @param constraintStructure
|
* the constraint instance
|
||||||
* the structure with constraint data
|
* @return target's object scale
|
||||||
*/
|
*/
|
||||||
protected void validateConstraintType(Structure constraintStructure) {
|
protected Vector3f getTargetScale(Constraint constraint) {
|
||||||
if(!constraintType.getClassName().equalsIgnoreCase(constraintStructure.getType())) {
|
Long targetOMA = ((Pointer) constraint.getData().getFieldValue("tar")).getOldMemoryAddress();
|
||||||
throw new IllegalArgumentException("Invalud structure type (" + constraintStructure.getType() + ") for the constraint: " + constraintType.getClassName() + '!');
|
Space targetSpace = constraint.getTargetSpace();
|
||||||
}
|
Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
|
||||||
}
|
switch (targetSpace) {
|
||||||
|
case CONSTRAINT_SPACE_LOCAL:
|
||||||
/**
|
return targetObject.getLocalScale();
|
||||||
* This method affects the bone animation tracks for the given skeleton.
|
case CONSTRAINT_SPACE_WORLD:
|
||||||
* @param skeleton
|
return targetObject.getWorldScale();
|
||||||
* the skeleton containing the affected bones by constraint
|
default:
|
||||||
* @param boneAnimation
|
throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString());
|
||||||
* the bone animation baked traces
|
}
|
||||||
* @param constraint
|
}
|
||||||
* the constraint
|
|
||||||
*/
|
|
||||||
public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the bone traces for the bone that is affected by the given constraint.
|
|
||||||
* @param skeleton
|
|
||||||
* the skeleton containing bones
|
|
||||||
* @param boneAnimation
|
|
||||||
* the bone animation that affects the skeleton
|
|
||||||
* @param constraint
|
|
||||||
* the affecting constraint
|
|
||||||
* @return the bone track for the bone that is being affected by the constraint
|
|
||||||
*/
|
|
||||||
protected BoneTrack getBoneTrack(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
|
|
||||||
Long boneOMA = constraint.getBoneOMA();
|
|
||||||
Bone bone = (Bone)dataRepository.getLoadedFeature(boneOMA, LoadedFeatureDataType.LOADED_FEATURE);
|
|
||||||
int boneIndex = skeleton.getBoneIndex(bone);
|
|
||||||
if(boneIndex != -1) {
|
|
||||||
//searching for track for this bone
|
|
||||||
for(BoneTrack boneTrack : boneAnimation.getTracks()) {
|
|
||||||
if(boneTrack.getTargetBoneIndex() == boneIndex) {
|
|
||||||
return boneTrack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the target or subtarget object (if specified).
|
|
||||||
* @param constraint
|
|
||||||
* the constraint instance
|
|
||||||
* @return target or subtarget feature
|
|
||||||
*/
|
|
||||||
protected Object getTarget(Constraint constraint, LoadedFeatureDataType loadedFeatureDataType) {
|
|
||||||
Long targetOMA = ((Pointer)constraint.getData().getFieldValue("tar")).getOldMemoryAddress();
|
|
||||||
Object targetObject = dataRepository.getLoadedFeature(targetOMA, loadedFeatureDataType);
|
|
||||||
String subtargetName = constraint.getData().getFieldValue("subtarget").toString();
|
|
||||||
if(subtargetName.length() > 0) {
|
|
||||||
return dataRepository.getLoadedFeature(subtargetName, loadedFeatureDataType);
|
|
||||||
}
|
|
||||||
return targetObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns target's object location.
|
|
||||||
* @param constraint
|
|
||||||
* the constraint instance
|
|
||||||
* @return target's object location
|
|
||||||
*/
|
|
||||||
protected Vector3f getTargetLocation(Constraint constraint) {
|
|
||||||
Long targetOMA = ((Pointer)constraint.getData().getFieldValue("tar")).getOldMemoryAddress();
|
|
||||||
Space targetSpace = constraint.getTargetSpace();
|
|
||||||
Node targetObject = (Node)dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
|
|
||||||
switch(targetSpace) {
|
|
||||||
case CONSTRAINT_SPACE_LOCAL:
|
|
||||||
return targetObject.getLocalTranslation();
|
|
||||||
case CONSTRAINT_SPACE_WORLD:
|
|
||||||
return targetObject.getWorldTranslation();
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns target's object location in the specified frame.
|
|
||||||
* @param constraint
|
|
||||||
* the constraint instance
|
|
||||||
* @param frame
|
|
||||||
* the frame number
|
|
||||||
* @return target's object location
|
|
||||||
*/
|
|
||||||
protected Vector3f getTargetLocation(Constraint constraint, int frame) {
|
|
||||||
return this.getTargetLocation(constraint);//TODO: implement getting location in a specified frame
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns target's object rotation.
|
|
||||||
* @param constraint
|
|
||||||
* the constraint instance
|
|
||||||
* @return target's object rotation
|
|
||||||
*/
|
|
||||||
protected Quaternion getTargetRotation(Constraint constraint) {
|
|
||||||
Long targetOMA = ((Pointer)constraint.getData().getFieldValue("tar")).getOldMemoryAddress();
|
|
||||||
Space targetSpace = constraint.getTargetSpace();
|
|
||||||
Node targetObject = (Node)dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
|
|
||||||
switch(targetSpace) {
|
|
||||||
case CONSTRAINT_SPACE_LOCAL:
|
|
||||||
return targetObject.getLocalRotation();
|
|
||||||
case CONSTRAINT_SPACE_WORLD:
|
|
||||||
return targetObject.getWorldRotation();
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns target's object scale.
|
|
||||||
* @param constraint
|
|
||||||
* the constraint instance
|
|
||||||
* @return target's object scale
|
|
||||||
*/
|
|
||||||
protected Vector3f getTargetScale(Constraint constraint) {
|
|
||||||
Long targetOMA = ((Pointer)constraint.getData().getFieldValue("tar")).getOldMemoryAddress();
|
|
||||||
Space targetSpace = constraint.getTargetSpace();
|
|
||||||
Node targetObject = (Node)dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
|
|
||||||
switch(targetSpace) {
|
|
||||||
case CONSTRAINT_SPACE_LOCAL:
|
|
||||||
return targetObject.getLocalScale();
|
|
||||||
case CONSTRAINT_SPACE_WORLD:
|
|
||||||
return targetObject.getWorldScale();
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -13,125 +13,125 @@ import com.jme3.scene.plugins.blender.utils.DynamicArray;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class BezierCurve {
|
public class BezierCurve {
|
||||||
public static final int X_VALUE = 0;
|
|
||||||
public static final int Y_VALUE = 1;
|
|
||||||
public static final int Z_VALUE = 2;
|
|
||||||
|
|
||||||
/**
|
public static final int X_VALUE = 0;
|
||||||
* The type of the curve. Describes the data it modifies.
|
public static final int Y_VALUE = 1;
|
||||||
* Used in ipos calculations.
|
public static final int Z_VALUE = 2;
|
||||||
*/
|
/**
|
||||||
private int type;
|
* The type of the curve. Describes the data it modifies.
|
||||||
/** The dimension of the curve. */
|
* Used in ipos calculations.
|
||||||
private int dimension;
|
*/
|
||||||
/** A table of the bezier points. */
|
private int type;
|
||||||
private float[][][] bezierPoints;
|
/** The dimension of the curve. */
|
||||||
|
private int dimension;
|
||||||
|
/** A table of the bezier points. */
|
||||||
|
private float[][][] bezierPoints;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public BezierCurve(final int type, final List<Structure> bezTriples, final int dimension) {
|
public BezierCurve(final int type, final List<Structure> bezTriples, final int dimension) {
|
||||||
if(dimension != 2 && dimension != 3) {
|
if (dimension != 2 && dimension != 3) {
|
||||||
throw new IllegalArgumentException("The dimension of the curve should be 2 or 3!");
|
throw new IllegalArgumentException("The dimension of the curve should be 2 or 3!");
|
||||||
}
|
}
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.dimension = dimension;
|
this.dimension = dimension;
|
||||||
//first index of the bezierPoints table has the length of triples amount
|
//first index of the bezierPoints table has the length of triples amount
|
||||||
//the second index points to a table od three points of a bezier triple (handle, point, handle)
|
//the second index points to a table od three points of a bezier triple (handle, point, handle)
|
||||||
//the third index specifies the coordinates of the specific point in a bezier triple
|
//the third index specifies the coordinates of the specific point in a bezier triple
|
||||||
bezierPoints = new float[bezTriples.size()][3][dimension];
|
bezierPoints = new float[bezTriples.size()][3][dimension];
|
||||||
int i = 0, j, k;
|
int i = 0, j, k;
|
||||||
for(Structure bezTriple : bezTriples) {
|
for (Structure bezTriple : bezTriples) {
|
||||||
DynamicArray<Number> vec = (DynamicArray<Number>)bezTriple.getFieldValue("vec");
|
DynamicArray<Number> vec = (DynamicArray<Number>) bezTriple.getFieldValue("vec");
|
||||||
for(j = 0; j < 3; ++j) {
|
for (j = 0; j < 3; ++j) {
|
||||||
for(k = 0; k < dimension; ++k) {
|
for (k = 0; k < dimension; ++k) {
|
||||||
bezierPoints[i][j][k] = vec.get(j, k).floatValue();
|
bezierPoints[i][j][k] = vec.get(j, k).floatValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method evaluates the data for the specified frame. The Y value is returned.
|
* This method evaluates the data for the specified frame. The Y value is returned.
|
||||||
* @param frame
|
* @param frame
|
||||||
* the frame for which the value is being calculated
|
* the frame for which the value is being calculated
|
||||||
* @param valuePart
|
* @param valuePart
|
||||||
* this param specifies wheather we should return the X, Y or Z part of the result value; it should have
|
* this param specifies wheather we should return the X, Y or Z part of the result value; it should have
|
||||||
* one of the following values: X_VALUE - the X factor of the result Y_VALUE - the Y factor of the result
|
* one of the following values: X_VALUE - the X factor of the result Y_VALUE - the Y factor of the result
|
||||||
* Z_VALUE - the Z factor of the result
|
* Z_VALUE - the Z factor of the result
|
||||||
* @return the value of the curve
|
* @return the value of the curve
|
||||||
*/
|
*/
|
||||||
public float evaluate(int frame, int valuePart) {
|
public float evaluate(int frame, int valuePart) {
|
||||||
for(int i = 0; i < bezierPoints.length - 1; ++i) {
|
for (int i = 0; i < bezierPoints.length - 1; ++i) {
|
||||||
if(frame >= bezierPoints[i][1][0] && frame <= bezierPoints[i + 1][1][0]) {
|
if (frame >= bezierPoints[i][1][0] && frame <= bezierPoints[i + 1][1][0]) {
|
||||||
float t = (frame - bezierPoints[i][1][0]) / (bezierPoints[i + 1][1][0] - bezierPoints[i][1][0]);
|
float t = (frame - bezierPoints[i][1][0]) / (bezierPoints[i + 1][1][0] - bezierPoints[i][1][0]);
|
||||||
float oneMinusT = 1.0f - t;
|
float oneMinusT = 1.0f - t;
|
||||||
float oneMinusT2 = oneMinusT * oneMinusT;
|
float oneMinusT2 = oneMinusT * oneMinusT;
|
||||||
float t2 = t * t;
|
float t2 = t * t;
|
||||||
return bezierPoints[i][1][valuePart] * oneMinusT2 * oneMinusT + 3.0f * bezierPoints[i][2][valuePart] * t * oneMinusT2 + 3.0f * bezierPoints[i + 1][0][valuePart] * t2 * oneMinusT + bezierPoints[i + 1][1][valuePart] * t2 * t;
|
return bezierPoints[i][1][valuePart] * oneMinusT2 * oneMinusT + 3.0f * bezierPoints[i][2][valuePart] * t * oneMinusT2 + 3.0f * bezierPoints[i + 1][0][valuePart] * t2 * oneMinusT + bezierPoints[i + 1][1][valuePart] * t2 * t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(frame < bezierPoints[0][1][0]) {
|
if (frame < bezierPoints[0][1][0]) {
|
||||||
return bezierPoints[0][1][1];
|
return bezierPoints[0][1][1];
|
||||||
} else { //frame>bezierPoints[bezierPoints.length-1][1][0]
|
} else { //frame>bezierPoints[bezierPoints.length-1][1][0]
|
||||||
return bezierPoints[bezierPoints.length - 1][1][1];
|
return bezierPoints[bezierPoints.length - 1][1][1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the frame where last bezier triple center point of the bezier curve is located.
|
* This method returns the frame where last bezier triple center point of the bezier curve is located.
|
||||||
* @return the frame number of the last defined bezier triple point for the curve
|
* @return the frame number of the last defined bezier triple point for the curve
|
||||||
*/
|
*/
|
||||||
public int getLastFrame() {
|
public int getLastFrame() {
|
||||||
return (int)bezierPoints[bezierPoints.length - 1][1][0];
|
return (int) bezierPoints[bezierPoints.length - 1][1][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the type of the bezier curve. The type describes the parameter that this curve modifies
|
* This method returns the type of the bezier curve. The type describes the parameter that this curve modifies
|
||||||
* (ie. LocationX or rotationW of the feature).
|
* (ie. LocationX or rotationW of the feature).
|
||||||
* @return the type of the bezier curve
|
* @return the type of the bezier curve
|
||||||
*/
|
*/
|
||||||
public int getType() {
|
public int getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns a list of control points for this curve.
|
* This method returns a list of control points for this curve.
|
||||||
* @return a list of control points for this curve.
|
* @return a list of control points for this curve.
|
||||||
*/
|
*/
|
||||||
public List<Vector3f> getControlPoints() {
|
public List<Vector3f> getControlPoints() {
|
||||||
List<Vector3f> controlPoints = new ArrayList<Vector3f>(bezierPoints.length * 3);
|
List<Vector3f> controlPoints = new ArrayList<Vector3f>(bezierPoints.length * 3);
|
||||||
for(int i = 0;i<bezierPoints.length;++i) {
|
for (int i = 0; i < bezierPoints.length; ++i) {
|
||||||
controlPoints.add(new Vector3f(bezierPoints[i][0][0], bezierPoints[i][0][1], bezierPoints[i][0][2]));
|
controlPoints.add(new Vector3f(bezierPoints[i][0][0], bezierPoints[i][0][1], bezierPoints[i][0][2]));
|
||||||
controlPoints.add(new Vector3f(bezierPoints[i][1][0], bezierPoints[i][1][1], bezierPoints[i][1][2]));
|
controlPoints.add(new Vector3f(bezierPoints[i][1][0], bezierPoints[i][1][1], bezierPoints[i][1][2]));
|
||||||
controlPoints.add(new Vector3f(bezierPoints[i][2][0], bezierPoints[i][2][1], bezierPoints[i][2][2]));
|
controlPoints.add(new Vector3f(bezierPoints[i][2][0], bezierPoints[i][2][1], bezierPoints[i][2][2]));
|
||||||
}
|
}
|
||||||
return controlPoints;
|
return controlPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder("Bezier curve: ").append(type).append('\n');
|
StringBuilder sb = new StringBuilder("Bezier curve: ").append(type).append('\n');
|
||||||
for(int i = 0; i < bezierPoints.length; ++i) {
|
for (int i = 0; i < bezierPoints.length; ++i) {
|
||||||
sb.append(this.toStringBezTriple(i)).append('\n');
|
sb.append(this.toStringBezTriple(i)).append('\n');
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method converts the bezier triple of a specified index into text.
|
* This method converts the bezier triple of a specified index into text.
|
||||||
* @param tripleIndex
|
* @param tripleIndex
|
||||||
* index of the triple
|
* index of the triple
|
||||||
* @return text representation of the triple
|
* @return text representation of the triple
|
||||||
*/
|
*/
|
||||||
private String toStringBezTriple(int tripleIndex) {
|
private String toStringBezTriple(int tripleIndex) {
|
||||||
if(this.dimension==2) {
|
if (this.dimension == 2) {
|
||||||
return "[(" + bezierPoints[tripleIndex][0][0] + ", " + bezierPoints[tripleIndex][0][1] + ") ("
|
return "[(" + bezierPoints[tripleIndex][0][0] + ", " + bezierPoints[tripleIndex][0][1] + ") ("
|
||||||
+ bezierPoints[tripleIndex][1][0] + ", " + bezierPoints[tripleIndex][1][1] + ") ("
|
+ bezierPoints[tripleIndex][1][0] + ", " + bezierPoints[tripleIndex][1][1] + ") ("
|
||||||
+ bezierPoints[tripleIndex][2][0] + ", " + bezierPoints[tripleIndex][2][1] + ")]";
|
+ bezierPoints[tripleIndex][2][0] + ", " + bezierPoints[tripleIndex][2][1] + ")]";
|
||||||
} else {
|
} else {
|
||||||
return "[(" + bezierPoints[tripleIndex][0][0] + ", " + bezierPoints[tripleIndex][0][1] + ", " + bezierPoints[tripleIndex][0][2] + ") ("
|
return "[(" + bezierPoints[tripleIndex][0][0] + ", " + bezierPoints[tripleIndex][0][1] + ", " + bezierPoints[tripleIndex][0][2] + ") ("
|
||||||
+ bezierPoints[tripleIndex][1][0] + ", " + bezierPoints[tripleIndex][1][1] + ", " + bezierPoints[tripleIndex][1][2] + ") ("
|
+ bezierPoints[tripleIndex][1][0] + ", " + bezierPoints[tripleIndex][1][1] + ", " + bezierPoints[tripleIndex][1][2] + ") ("
|
||||||
+ bezierPoints[tripleIndex][2][0] + ", " + bezierPoints[tripleIndex][2][1] + ", " + bezierPoints[tripleIndex][2][2] + ")]";
|
+ bezierPoints[tripleIndex][2][0] + ", " + bezierPoints[tripleIndex][2][1] + ", " + bezierPoints[tripleIndex][2][2] + ")]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,151 +12,151 @@ import com.jme3.scene.plugins.blender.utils.Pointer;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class Constraint {
|
public class Constraint {
|
||||||
/** The type of this constraint. */
|
|
||||||
private final ConstraintType type;
|
|
||||||
/** The name of this constraint. */
|
|
||||||
private final String name;
|
|
||||||
/** The old memory address of the constraint's owner. */
|
|
||||||
private final Long boneOMA;
|
|
||||||
|
|
||||||
private final Space ownerSpace;
|
/** The type of this constraint. */
|
||||||
|
private final ConstraintType type;
|
||||||
|
/** The name of this constraint. */
|
||||||
|
private final String name;
|
||||||
|
/** The old memory address of the constraint's owner. */
|
||||||
|
private final Long boneOMA;
|
||||||
|
private final Space ownerSpace;
|
||||||
|
private final Space targetSpace;
|
||||||
|
/** The structure with constraint's data. */
|
||||||
|
private final Structure data;
|
||||||
|
/** The ipo object defining influence. */
|
||||||
|
private final Ipo ipo;
|
||||||
|
/** The influence function of this constraint. */
|
||||||
|
private final AbstractInfluenceFunction influenceFunction;
|
||||||
|
|
||||||
private final Space targetSpace;
|
/**
|
||||||
/** The structure with constraint's data. */
|
* This constructor creates the constraint instance.
|
||||||
private final Structure data;
|
* @param constraintStructure
|
||||||
/** The ipo object defining influence. */
|
* the constraint's structure (bConstraint clss in blender 2.49).
|
||||||
private final Ipo ipo;
|
* @param influenceFunction
|
||||||
/** The influence function of this constraint. */
|
* the constraint's influence function (taken from ConstraintHelper)
|
||||||
private final AbstractInfluenceFunction influenceFunction;
|
* @param boneOMA
|
||||||
|
* the old memory address of the constraint owner
|
||||||
|
* @param influenceIpo
|
||||||
|
* the ipo curve of the influence factor
|
||||||
|
* @param dataRepository
|
||||||
|
* the data repository
|
||||||
|
* @throws BlenderFileException
|
||||||
|
*/
|
||||||
|
public Constraint(Structure constraintStructure, AbstractInfluenceFunction influenceFunction, Long boneOMA, Space ownerSpace, Space targetSpace, Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
|
||||||
|
if (influenceFunction == null) {
|
||||||
|
throw new IllegalArgumentException("Influence function is not defined!");
|
||||||
|
}
|
||||||
|
Pointer pData = (Pointer) constraintStructure.getFieldValue("data");
|
||||||
|
if (!pData.isNull()) {
|
||||||
|
data = pData.fetchData(dataRepository.getInputStream()).get(0);
|
||||||
|
} else {
|
||||||
|
throw new BlenderFileException("The constraint has no data specified!");
|
||||||
|
}
|
||||||
|
this.boneOMA = boneOMA;
|
||||||
|
this.type = ConstraintType.valueOf(((Number) constraintStructure.getFieldValue("type")).intValue());
|
||||||
|
this.name = constraintStructure.getFieldValue("name").toString();
|
||||||
|
this.ownerSpace = ownerSpace;
|
||||||
|
this.targetSpace = targetSpace;
|
||||||
|
this.ipo = influenceIpo;
|
||||||
|
this.influenceFunction = influenceFunction;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor creates the constraint instance.
|
* This method returns the name of the constraint.
|
||||||
* @param constraintStructure
|
* @return the name of the constraint
|
||||||
* the constraint's structure (bConstraint clss in blender 2.49).
|
*/
|
||||||
* @param influenceFunction
|
public String getName() {
|
||||||
* the constraint's influence function (taken from ConstraintHelper)
|
return name;
|
||||||
* @param boneOMA
|
}
|
||||||
* the old memory address of the constraint owner
|
|
||||||
* @param influenceIpo
|
|
||||||
* the ipo curve of the influence factor
|
|
||||||
* @param dataRepository
|
|
||||||
* the data repository
|
|
||||||
* @throws BlenderFileException
|
|
||||||
*/
|
|
||||||
public Constraint(Structure constraintStructure, AbstractInfluenceFunction influenceFunction, Long boneOMA, Space ownerSpace, Space targetSpace, Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
|
|
||||||
if(influenceFunction == null) {
|
|
||||||
throw new IllegalArgumentException("Influence function is not defined!");
|
|
||||||
}
|
|
||||||
Pointer pData = (Pointer)constraintStructure.getFieldValue("data");
|
|
||||||
if(!pData.isNull()) {
|
|
||||||
data = pData.fetchData(dataRepository.getInputStream()).get(0);
|
|
||||||
} else {
|
|
||||||
throw new BlenderFileException("The constraint has no data specified!");
|
|
||||||
}
|
|
||||||
this.boneOMA = boneOMA;
|
|
||||||
this.type = ConstraintType.valueOf(((Number)constraintStructure.getFieldValue("type")).intValue());
|
|
||||||
this.name = constraintStructure.getFieldValue("name").toString();
|
|
||||||
this.ownerSpace = ownerSpace;
|
|
||||||
this.targetSpace = targetSpace;
|
|
||||||
this.ipo = influenceIpo;
|
|
||||||
this.influenceFunction = influenceFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the name of the constraint.
|
* This method returns the old memoty address of the bone this constraint affects.
|
||||||
* @return the name of the constraint
|
* @return the old memory address of the bone this constraint affects
|
||||||
*/
|
*/
|
||||||
public String getName() {
|
public Long getBoneOMA() {
|
||||||
return name;
|
return boneOMA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the old memoty address of the bone this constraint affects.
|
* This method returns owner's transform space.
|
||||||
* @return the old memory address of the bone this constraint affects
|
* @return owner's transform space
|
||||||
*/
|
*/
|
||||||
public Long getBoneOMA() {
|
public Space getOwnerSpace() {
|
||||||
return boneOMA;
|
return ownerSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns owner's transform space.
|
* This method returns target's transform space.
|
||||||
* @return owner's transform space
|
* @return target's transform space
|
||||||
*/
|
*/
|
||||||
public Space getOwnerSpace() {
|
public Space getTargetSpace() {
|
||||||
return ownerSpace;
|
return targetSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns target's transform space.
|
* This method returns the type of the constraint.
|
||||||
* @return target's transform space
|
* @return the type of the constraint
|
||||||
*/
|
*/
|
||||||
public Space getTargetSpace() {
|
public ConstraintType getType() {
|
||||||
return targetSpace;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the type of the constraint.
|
* This method returns the constraint's data structure.
|
||||||
* @return the type of the constraint
|
* @return the constraint's data structure
|
||||||
*/
|
*/
|
||||||
public ConstraintType getType() {
|
public Structure getData() {
|
||||||
return type;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the constraint's data structure.
|
* This method returns the constraint's influcence curve.
|
||||||
* @return the constraint's data structure
|
* @return the constraint's influcence curve
|
||||||
*/
|
*/
|
||||||
public Structure getData() {
|
public Ipo getIpo() {
|
||||||
return data;
|
return ipo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the constraint's influcence curve.
|
* This method affects the bone animation tracks for the given skeleton.
|
||||||
* @return the constraint's influcence curve
|
* @param skeleton
|
||||||
*/
|
* the skeleton containing the affected bones by constraint
|
||||||
public Ipo getIpo() {
|
* @param boneAnimation
|
||||||
return ipo;
|
* the bone animation baked traces
|
||||||
}
|
* @param constraint
|
||||||
|
* the constraint
|
||||||
|
*/
|
||||||
|
public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
|
||||||
|
influenceFunction.affectAnimation(skeleton, boneAnimation, this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method affects the bone animation tracks for the given skeleton.
|
* The space of target or owner transformation.
|
||||||
* @param skeleton
|
* @author Marcin Roguski
|
||||||
* the skeleton containing the affected bones by constraint
|
*/
|
||||||
* @param boneAnimation
|
public static enum Space {
|
||||||
* the bone animation baked traces
|
|
||||||
* @param constraint
|
|
||||||
* the constraint
|
|
||||||
*/
|
|
||||||
public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
|
|
||||||
influenceFunction.affectAnimation(skeleton, boneAnimation, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_INVALID;
|
||||||
* The space of target or owner transformation.
|
|
||||||
* @author Marcin Roguski
|
|
||||||
*/
|
|
||||||
public static enum Space {
|
|
||||||
CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_INVALID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the enum instance when given the appropriate value from the blend file.
|
* This method returns the enum instance when given the appropriate value from the blend file.
|
||||||
* @param c
|
* @param c
|
||||||
* the blender's value of the space modifier
|
* the blender's value of the space modifier
|
||||||
* @return the scape enum instance
|
* @return the scape enum instance
|
||||||
*/
|
*/
|
||||||
public static Space valueOf(byte c) {
|
public static Space valueOf(byte c) {
|
||||||
switch(c) {
|
switch (c) {
|
||||||
case 0:
|
case 0:
|
||||||
return CONSTRAINT_SPACE_WORLD;
|
return CONSTRAINT_SPACE_WORLD;
|
||||||
case 1:
|
case 1:
|
||||||
return CONSTRAINT_SPACE_LOCAL;
|
return CONSTRAINT_SPACE_LOCAL;
|
||||||
case 2:
|
case 2:
|
||||||
return CONSTRAINT_SPACE_POSE;
|
return CONSTRAINT_SPACE_POSE;
|
||||||
case 3:
|
case 3:
|
||||||
return CONSTRAINT_SPACE_PARLOCAL;
|
return CONSTRAINT_SPACE_PARLOCAL;
|
||||||
default:
|
default:
|
||||||
return CONSTRAINT_SPACE_INVALID;
|
return CONSTRAINT_SPACE_INVALID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,134 +10,136 @@ import java.util.Map;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public enum ConstraintType {
|
public enum ConstraintType {
|
||||||
/* Invalid/legacy constraint */
|
/* Invalid/legacy constraint */
|
||||||
CONSTRAINT_TYPE_NULL(0, "bNullConstraint"),
|
|
||||||
/* Unimplemented non longer :) - during constraints recode, Aligorith */
|
|
||||||
CONSTRAINT_TYPE_CHILDOF(1, "bChildOfConstraint"),
|
|
||||||
CONSTRAINT_TYPE_KINEMATIC(3, "bKinematicConstraint"),
|
|
||||||
CONSTRAINT_TYPE_FOLLOWPATH(4, "bFollowPathConstraint"),
|
|
||||||
/* Unimplemented no longer :) - Aligorith */
|
|
||||||
CONSTRAINT_TYPE_ROTLIMIT(5, "bRotLimitConstraint"),
|
|
||||||
/* Unimplemented no longer :) - Aligorith */
|
|
||||||
CONSTRAINT_TYPE_LOCLIMIT(6, "bLocLimitConstraint"),
|
|
||||||
/* Unimplemented no longer :) - Aligorith */
|
|
||||||
CONSTRAINT_TYPE_SIZELIMIT(7, "bSizeLimitConstraint"),
|
|
||||||
CONSTRAINT_TYPE_ROTLIKE(8, "bRotateLikeConstraint"),
|
|
||||||
CONSTRAINT_TYPE_LOCLIKE(9, "bLocateLikeConstraint"),
|
|
||||||
CONSTRAINT_TYPE_SIZELIKE(10, "bSizeLikeConstraint"),
|
|
||||||
/* Unimplemented no longer :) - Aligorith. Scripts */
|
|
||||||
CONSTRAINT_TYPE_PYTHON(11, "bPythonConstraint"),
|
|
||||||
CONSTRAINT_TYPE_ACTION(12, "bActionConstraint"),
|
|
||||||
/* New Tracking constraint that locks an axis in place - theeth */
|
|
||||||
CONSTRAINT_TYPE_LOCKTRACK(13, "bLockTrackConstraint"),
|
|
||||||
/* limit distance */
|
|
||||||
CONSTRAINT_TYPE_DISTLIMIT(14, "bDistLimitConstraint"),
|
|
||||||
/* claiming this to be mine :) is in tuhopuu bjornmose */
|
|
||||||
CONSTRAINT_TYPE_STRETCHTO(15, "bStretchToConstraint"),
|
|
||||||
/* floor constraint */
|
|
||||||
CONSTRAINT_TYPE_MINMAX(16, "bMinMaxConstraint"),
|
|
||||||
/* rigidbody constraint */
|
|
||||||
CONSTRAINT_TYPE_RIGIDBODYJOINT(17, "bRigidBodyConstraint"),
|
|
||||||
/* clampto constraint */
|
|
||||||
CONSTRAINT_TYPE_CLAMPTO(18, "bClampToConstraint"),
|
|
||||||
/* transformation (loc/rot/size -> loc/rot/size) constraint */
|
|
||||||
CONSTRAINT_TYPE_TRANSFORM(19, "bTransformConstraint"),
|
|
||||||
/* shrinkwrap (loc/rot) constraint */
|
|
||||||
CONSTRAINT_TYPE_SHRINKWRAP(20, "bShrinkwrapConstraint");
|
|
||||||
|
|
||||||
/** The constraint's id (in blender known as 'type'). */
|
CONSTRAINT_TYPE_NULL(0, "bNullConstraint"),
|
||||||
private int constraintId;
|
/* Unimplemented non longer :) - during constraints recode, Aligorith */
|
||||||
/** The name of constraint class used by blender. */
|
CONSTRAINT_TYPE_CHILDOF(1, "bChildOfConstraint"),
|
||||||
private String className;
|
CONSTRAINT_TYPE_KINEMATIC(3, "bKinematicConstraint"),
|
||||||
/** The map containing class names and types of constraints. */
|
CONSTRAINT_TYPE_FOLLOWPATH(4, "bFollowPathConstraint"),
|
||||||
private static Map<String, ConstraintType> typesMap = new HashMap<String, ConstraintType>(ConstraintType.values().length);
|
/* Unimplemented no longer :) - Aligorith */
|
||||||
/** The map containing class names and types of constraints. */
|
CONSTRAINT_TYPE_ROTLIMIT(5, "bRotLimitConstraint"),
|
||||||
private static Map<Integer, ConstraintType> idsMap = new HashMap<Integer, ConstraintType>(ConstraintType.values().length);
|
/* Unimplemented no longer :) - Aligorith */
|
||||||
static {
|
CONSTRAINT_TYPE_LOCLIMIT(6, "bLocLimitConstraint"),
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_NULL.constraintId), CONSTRAINT_TYPE_NULL);
|
/* Unimplemented no longer :) - Aligorith */
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_CHILDOF.constraintId), CONSTRAINT_TYPE_CHILDOF);
|
CONSTRAINT_TYPE_SIZELIMIT(7, "bSizeLimitConstraint"),
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_KINEMATIC.constraintId), CONSTRAINT_TYPE_KINEMATIC);
|
CONSTRAINT_TYPE_ROTLIKE(8, "bRotateLikeConstraint"),
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_FOLLOWPATH.constraintId), CONSTRAINT_TYPE_FOLLOWPATH);
|
CONSTRAINT_TYPE_LOCLIKE(9, "bLocateLikeConstraint"),
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_ROTLIMIT.constraintId), CONSTRAINT_TYPE_ROTLIMIT);
|
CONSTRAINT_TYPE_SIZELIKE(10, "bSizeLikeConstraint"),
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_LOCLIMIT.constraintId), CONSTRAINT_TYPE_LOCLIMIT);
|
/* Unimplemented no longer :) - Aligorith. Scripts */
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_SIZELIMIT.constraintId), CONSTRAINT_TYPE_SIZELIMIT);
|
CONSTRAINT_TYPE_PYTHON(11, "bPythonConstraint"),
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_ROTLIKE.constraintId), CONSTRAINT_TYPE_ROTLIKE);
|
CONSTRAINT_TYPE_ACTION(12, "bActionConstraint"),
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_LOCLIKE.constraintId), CONSTRAINT_TYPE_LOCLIKE);
|
/* New Tracking constraint that locks an axis in place - theeth */
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_SIZELIKE.constraintId), CONSTRAINT_TYPE_SIZELIKE);
|
CONSTRAINT_TYPE_LOCKTRACK(13, "bLockTrackConstraint"),
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_PYTHON.constraintId), CONSTRAINT_TYPE_PYTHON);
|
/* limit distance */
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_ACTION.constraintId), CONSTRAINT_TYPE_ACTION);
|
CONSTRAINT_TYPE_DISTLIMIT(14, "bDistLimitConstraint"),
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_LOCKTRACK.constraintId), CONSTRAINT_TYPE_LOCKTRACK);
|
/* claiming this to be mine :) is in tuhopuu bjornmose */
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_DISTLIMIT.constraintId), CONSTRAINT_TYPE_DISTLIMIT);
|
CONSTRAINT_TYPE_STRETCHTO(15, "bStretchToConstraint"),
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_STRETCHTO.constraintId), CONSTRAINT_TYPE_STRETCHTO);
|
/* floor constraint */
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_MINMAX.constraintId), CONSTRAINT_TYPE_MINMAX);
|
CONSTRAINT_TYPE_MINMAX(16, "bMinMaxConstraint"),
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_RIGIDBODYJOINT.constraintId), CONSTRAINT_TYPE_RIGIDBODYJOINT);
|
/* rigidbody constraint */
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_CLAMPTO.constraintId), CONSTRAINT_TYPE_CLAMPTO);
|
CONSTRAINT_TYPE_RIGIDBODYJOINT(17, "bRigidBodyConstraint"),
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_TRANSFORM.constraintId), CONSTRAINT_TYPE_TRANSFORM);
|
/* clampto constraint */
|
||||||
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_SHRINKWRAP.constraintId), CONSTRAINT_TYPE_SHRINKWRAP);
|
CONSTRAINT_TYPE_CLAMPTO(18, "bClampToConstraint"),
|
||||||
}
|
/* transformation (loc/rot/size -> loc/rot/size) constraint */
|
||||||
/**
|
CONSTRAINT_TYPE_TRANSFORM(19, "bTransformConstraint"),
|
||||||
* Constructor. Stores constraint type and class name.
|
/* shrinkwrap (loc/rot) constraint */
|
||||||
* @param constraintId
|
CONSTRAINT_TYPE_SHRINKWRAP(20, "bShrinkwrapConstraint");
|
||||||
* the constraint's type
|
/** The constraint's id (in blender known as 'type'). */
|
||||||
* @param className
|
private int constraintId;
|
||||||
* the constraint's type name
|
/** The name of constraint class used by blender. */
|
||||||
*/
|
private String className;
|
||||||
private ConstraintType(int constraintId, String className) {
|
/** The map containing class names and types of constraints. */
|
||||||
this.constraintId = constraintId;
|
private static final Map<String, ConstraintType> typesMap = new HashMap<String, ConstraintType>(ConstraintType.values().length);
|
||||||
this.className = className;
|
/** The map containing class names and types of constraints. */
|
||||||
}
|
private static final Map<Integer, ConstraintType> idsMap = new HashMap<Integer, ConstraintType>(ConstraintType.values().length);
|
||||||
|
|
||||||
/**
|
static {
|
||||||
* This method returns the type by given constraint id.
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_NULL.constraintId), CONSTRAINT_TYPE_NULL);
|
||||||
* @param constraintId
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_CHILDOF.constraintId), CONSTRAINT_TYPE_CHILDOF);
|
||||||
* the id of the constraint
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_KINEMATIC.constraintId), CONSTRAINT_TYPE_KINEMATIC);
|
||||||
* @return the constraint type enum value
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_FOLLOWPATH.constraintId), CONSTRAINT_TYPE_FOLLOWPATH);
|
||||||
*/
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_ROTLIMIT.constraintId), CONSTRAINT_TYPE_ROTLIMIT);
|
||||||
public static ConstraintType valueOf(int constraintId) {
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_LOCLIMIT.constraintId), CONSTRAINT_TYPE_LOCLIMIT);
|
||||||
return idsMap.get(Integer.valueOf(constraintId));
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_SIZELIMIT.constraintId), CONSTRAINT_TYPE_SIZELIMIT);
|
||||||
}
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_ROTLIKE.constraintId), CONSTRAINT_TYPE_ROTLIKE);
|
||||||
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_LOCLIKE.constraintId), CONSTRAINT_TYPE_LOCLIKE);
|
||||||
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_SIZELIKE.constraintId), CONSTRAINT_TYPE_SIZELIKE);
|
||||||
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_PYTHON.constraintId), CONSTRAINT_TYPE_PYTHON);
|
||||||
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_ACTION.constraintId), CONSTRAINT_TYPE_ACTION);
|
||||||
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_LOCKTRACK.constraintId), CONSTRAINT_TYPE_LOCKTRACK);
|
||||||
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_DISTLIMIT.constraintId), CONSTRAINT_TYPE_DISTLIMIT);
|
||||||
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_STRETCHTO.constraintId), CONSTRAINT_TYPE_STRETCHTO);
|
||||||
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_MINMAX.constraintId), CONSTRAINT_TYPE_MINMAX);
|
||||||
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_RIGIDBODYJOINT.constraintId), CONSTRAINT_TYPE_RIGIDBODYJOINT);
|
||||||
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_CLAMPTO.constraintId), CONSTRAINT_TYPE_CLAMPTO);
|
||||||
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_TRANSFORM.constraintId), CONSTRAINT_TYPE_TRANSFORM);
|
||||||
|
idsMap.put(Integer.valueOf(CONSTRAINT_TYPE_SHRINKWRAP.constraintId), CONSTRAINT_TYPE_SHRINKWRAP);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the constraint's id (type).
|
* Constructor. Stores constraint type and class name.
|
||||||
* @return the constraint's id (type)
|
* @param constraintId
|
||||||
*/
|
* the constraint's type
|
||||||
public int getConstraintId() {
|
* @param className
|
||||||
return constraintId;
|
* the constraint's type name
|
||||||
}
|
*/
|
||||||
|
private ConstraintType(int constraintId, String className) {
|
||||||
|
this.constraintId = constraintId;
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the constraint's class name.
|
* This method returns the type by given constraint id.
|
||||||
* @return the constraint's class name
|
* @param constraintId
|
||||||
*/
|
* the id of the constraint
|
||||||
public String getClassName() {
|
* @return the constraint type enum value
|
||||||
return className;
|
*/
|
||||||
}
|
public static ConstraintType valueOf(int constraintId) {
|
||||||
|
return idsMap.get(Integer.valueOf(constraintId));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns constraint enum type by the given class name.
|
* This method returns the constraint's id (type).
|
||||||
* @param className
|
* @return the constraint's id (type)
|
||||||
* the blender's constraint class name
|
*/
|
||||||
* @return the constraint enum type of the specified class name
|
public int getConstraintId() {
|
||||||
*/
|
return constraintId;
|
||||||
public static ConstraintType getByBlenderClassName(String className) {
|
}
|
||||||
ConstraintType result = typesMap.get(className);
|
|
||||||
if(result == null) {
|
|
||||||
ConstraintType[] constraints = ConstraintType.values();
|
|
||||||
for(ConstraintType constraint : constraints) {
|
|
||||||
if(constraint.className.equals(className)) {
|
|
||||||
return constraint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the type value of the last defined constraint. It can be used for allocating tables for
|
* This method returns the constraint's class name.
|
||||||
* storing constraint procedures since not all type values from 0 to the last value are used.
|
* @return the constraint's class name
|
||||||
* @return the type value of the last defined constraint
|
*/
|
||||||
*/
|
public String getClassName() {
|
||||||
public static int getLastDefinedTypeValue() {
|
return className;
|
||||||
return CONSTRAINT_TYPE_SHRINKWRAP.getConstraintId();
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* This method returns constraint enum type by the given class name.
|
||||||
|
* @param className
|
||||||
|
* the blender's constraint class name
|
||||||
|
* @return the constraint enum type of the specified class name
|
||||||
|
*/
|
||||||
|
public static ConstraintType getByBlenderClassName(String className) {
|
||||||
|
ConstraintType result = typesMap.get(className);
|
||||||
|
if (result == null) {
|
||||||
|
ConstraintType[] constraints = ConstraintType.values();
|
||||||
|
for (ConstraintType constraint : constraints) {
|
||||||
|
if (constraint.className.equals(className)) {
|
||||||
|
return constraint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the type value of the last defined constraint. It can be used for allocating tables for
|
||||||
|
* storing constraint procedures since not all type values from 0 to the last value are used.
|
||||||
|
* @return the type value of the last defined constraint
|
||||||
|
*/
|
||||||
|
public static int getLastDefinedTypeValue() {
|
||||||
|
return CONSTRAINT_TYPE_SHRINKWRAP.getConstraintId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,167 +10,167 @@ import com.jme3.math.Vector3f;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class Ipo {
|
public class Ipo {
|
||||||
public static final int AC_LOC_X = 1;
|
|
||||||
public static final int AC_LOC_Y = 2;
|
|
||||||
public static final int AC_LOC_Z = 3;
|
|
||||||
public static final int OB_ROT_X = 7;
|
|
||||||
public static final int OB_ROT_Y = 8;
|
|
||||||
public static final int OB_ROT_Z = 9;
|
|
||||||
public static final int AC_SIZE_X = 13;
|
|
||||||
public static final int AC_SIZE_Y = 14;
|
|
||||||
public static final int AC_SIZE_Z = 15;
|
|
||||||
public static final int AC_QUAT_W = 25;
|
|
||||||
public static final int AC_QUAT_X = 26;
|
|
||||||
public static final int AC_QUAT_Y = 27;
|
|
||||||
public static final int AC_QUAT_Z = 28;
|
|
||||||
|
|
||||||
/** A list of bezier curves for this interpolation object. */
|
public static final int AC_LOC_X = 1;
|
||||||
private BezierCurve[] bezierCurves;
|
public static final int AC_LOC_Y = 2;
|
||||||
/** Each ipo contains one bone track. */
|
public static final int AC_LOC_Z = 3;
|
||||||
private BoneTrack calculatedTrack;
|
public static final int OB_ROT_X = 7;
|
||||||
|
public static final int OB_ROT_Y = 8;
|
||||||
|
public static final int OB_ROT_Z = 9;
|
||||||
|
public static final int AC_SIZE_X = 13;
|
||||||
|
public static final int AC_SIZE_Y = 14;
|
||||||
|
public static final int AC_SIZE_Z = 15;
|
||||||
|
public static final int AC_QUAT_W = 25;
|
||||||
|
public static final int AC_QUAT_X = 26;
|
||||||
|
public static final int AC_QUAT_Y = 27;
|
||||||
|
public static final int AC_QUAT_Z = 28;
|
||||||
|
/** A list of bezier curves for this interpolation object. */
|
||||||
|
private BezierCurve[] bezierCurves;
|
||||||
|
/** Each ipo contains one bone track. */
|
||||||
|
private BoneTrack calculatedTrack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Stores the bezier curves.
|
* Constructor. Stores the bezier curves.
|
||||||
* @param bezierCurves
|
* @param bezierCurves
|
||||||
* a table of bezier curves
|
* a table of bezier curves
|
||||||
*/
|
*/
|
||||||
public Ipo(BezierCurve[] bezierCurves) {
|
public Ipo(BezierCurve[] bezierCurves) {
|
||||||
this.bezierCurves = bezierCurves;
|
this.bezierCurves = bezierCurves;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method calculates the ipo value for the first curve.
|
* This method calculates the ipo value for the first curve.
|
||||||
* @param frame
|
* @param frame
|
||||||
* the frame for which the value is calculated
|
* the frame for which the value is calculated
|
||||||
* @return calculated ipo value
|
* @return calculated ipo value
|
||||||
*/
|
*/
|
||||||
public float calculateValue(int frame) {
|
public float calculateValue(int frame) {
|
||||||
return this.calculateValue(frame, 0);
|
return this.calculateValue(frame, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method calculates the ipo value for the curve of the specified index. Make sure you do not exceed the
|
* This method calculates the ipo value for the curve of the specified index. Make sure you do not exceed the
|
||||||
* curves amount. Alway chech the amount of curves before calling this method.
|
* curves amount. Alway chech the amount of curves before calling this method.
|
||||||
* @param frame
|
* @param frame
|
||||||
* the frame for which the value is calculated
|
* the frame for which the value is calculated
|
||||||
* @param curveIndex
|
* @param curveIndex
|
||||||
* the index of the curve
|
* the index of the curve
|
||||||
* @return calculated ipo value
|
* @return calculated ipo value
|
||||||
*/
|
*/
|
||||||
public float calculateValue(int frame, int curveIndex) {
|
public float calculateValue(int frame, int curveIndex) {
|
||||||
return bezierCurves[curveIndex].evaluate(frame, BezierCurve.Y_VALUE);
|
return bezierCurves[curveIndex].evaluate(frame, BezierCurve.Y_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the curves amount.
|
* This method returns the curves amount.
|
||||||
* @return the curves amount
|
* @return the curves amount
|
||||||
*/
|
*/
|
||||||
public int getCurvesAmount() {
|
public int getCurvesAmount() {
|
||||||
return bezierCurves.length;
|
return bezierCurves.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the frame where last bezier triple center point of the specified bezier curve is located.
|
* This method returns the frame where last bezier triple center point of the specified bezier curve is located.
|
||||||
* @return the frame number of the last defined bezier triple point for the specified ipo
|
* @return the frame number of the last defined bezier triple point for the specified ipo
|
||||||
*/
|
*/
|
||||||
public int getLastFrame() {
|
public int getLastFrame() {
|
||||||
int result = 1;
|
int result = 1;
|
||||||
for(int i = 0; i < bezierCurves.length; ++i) {
|
for (int i = 0; i < bezierCurves.length; ++i) {
|
||||||
int tempResult = bezierCurves[i].getLastFrame();
|
int tempResult = bezierCurves[i].getLastFrame();
|
||||||
if(tempResult > result) {
|
if (tempResult > result) {
|
||||||
result = tempResult;
|
result = tempResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void modifyTranslation(int frame, Vector3f translation) {
|
public void modifyTranslation(int frame, Vector3f translation) {
|
||||||
if(calculatedTrack!=null) {
|
if (calculatedTrack != null) {
|
||||||
calculatedTrack.getTranslations()[frame].set(translation);
|
calculatedTrack.getTranslations()[frame].set(translation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void modifyRotation(int frame, Quaternion rotation) {
|
public void modifyRotation(int frame, Quaternion rotation) {
|
||||||
if(calculatedTrack!=null) {
|
if (calculatedTrack != null) {
|
||||||
calculatedTrack.getRotations()[frame].set(rotation);
|
calculatedTrack.getRotations()[frame].set(rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void modifyScale(int frame, Vector3f scale) {
|
public void modifyScale(int frame, Vector3f scale) {
|
||||||
if(calculatedTrack!=null) {
|
if (calculatedTrack != null) {
|
||||||
calculatedTrack.getScales()[frame].set(scale);
|
calculatedTrack.getScales()[frame].set(scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method calculates the value of the curves as a bone track between the specified frames.
|
* This method calculates the value of the curves as a bone track between the specified frames.
|
||||||
* @param boneIndex
|
* @param boneIndex
|
||||||
* the index of the bone for which the method calculates the tracks
|
* the index of the bone for which the method calculates the tracks
|
||||||
* @param startFrame
|
* @param startFrame
|
||||||
* the firs frame of tracks (inclusive)
|
* the firs frame of tracks (inclusive)
|
||||||
* @param stopFrame
|
* @param stopFrame
|
||||||
* the last frame of the tracks (inclusive)
|
* the last frame of the tracks (inclusive)
|
||||||
* @param fps
|
* @param fps
|
||||||
* frame rate (frames per second)
|
* frame rate (frames per second)
|
||||||
* @return bone track for the specified bone
|
* @return bone track for the specified bone
|
||||||
*/
|
*/
|
||||||
public BoneTrack calculateTrack(int boneIndex, int startFrame, int stopFrame, int fps) {
|
public BoneTrack calculateTrack(int boneIndex, int startFrame, int stopFrame, int fps) {
|
||||||
//preparing data for track
|
//preparing data for track
|
||||||
int framesAmount = stopFrame - startFrame;
|
int framesAmount = stopFrame - startFrame;
|
||||||
float start = (startFrame - 1.0f) / fps;
|
float start = (startFrame - 1.0f) / fps;
|
||||||
float timeBetweenFrames = 1.0f / fps;
|
float timeBetweenFrames = 1.0f / fps;
|
||||||
|
|
||||||
float[] times = new float[framesAmount + 1];
|
float[] times = new float[framesAmount + 1];
|
||||||
Vector3f[] translations = new Vector3f[framesAmount + 1];
|
Vector3f[] translations = new Vector3f[framesAmount + 1];
|
||||||
float[] translation = new float[3];
|
float[] translation = new float[3];
|
||||||
Quaternion[] rotations = new Quaternion[framesAmount + 1];
|
Quaternion[] rotations = new Quaternion[framesAmount + 1];
|
||||||
float[] quaternionRotation = new float[4];
|
float[] quaternionRotation = new float[4];
|
||||||
float[] objectRotation = new float[3];
|
float[] objectRotation = new float[3];
|
||||||
boolean bObjectRotation = false;
|
boolean bObjectRotation = false;
|
||||||
Vector3f[] scales = new Vector3f[framesAmount + 1];
|
Vector3f[] scales = new Vector3f[framesAmount + 1];
|
||||||
float[] scale = new float[3];
|
float[] scale = new float[3];
|
||||||
|
|
||||||
//calculating track data
|
//calculating track data
|
||||||
for(int frame = startFrame; frame <= stopFrame; ++frame) {
|
for (int frame = startFrame; frame <= stopFrame; ++frame) {
|
||||||
int index = frame - startFrame;
|
int index = frame - startFrame;
|
||||||
times[index] = start + (frame - 1) * timeBetweenFrames;
|
times[index] = start + (frame - 1) * timeBetweenFrames;
|
||||||
for(int j = 0; j < bezierCurves.length; ++j) {
|
for (int j = 0; j < bezierCurves.length; ++j) {
|
||||||
double value = bezierCurves[j].evaluate(frame, BezierCurve.Y_VALUE);
|
double value = bezierCurves[j].evaluate(frame, BezierCurve.Y_VALUE);
|
||||||
switch(bezierCurves[j].getType()) {
|
switch (bezierCurves[j].getType()) {
|
||||||
case AC_LOC_X:
|
case AC_LOC_X:
|
||||||
case AC_LOC_Y:
|
case AC_LOC_Y:
|
||||||
case AC_LOC_Z:
|
case AC_LOC_Z:
|
||||||
translation[bezierCurves[j].getType() - 1] = (float)value;
|
translation[bezierCurves[j].getType() - 1] = (float) value;
|
||||||
break;
|
break;
|
||||||
case OB_ROT_X:
|
case OB_ROT_X:
|
||||||
case OB_ROT_Y:
|
case OB_ROT_Y:
|
||||||
case OB_ROT_Z:
|
case OB_ROT_Z:
|
||||||
objectRotation[bezierCurves[j].getType() - 7] = (float)value;
|
objectRotation[bezierCurves[j].getType() - 7] = (float) value;
|
||||||
bObjectRotation = true;
|
bObjectRotation = true;
|
||||||
break;
|
break;
|
||||||
case AC_SIZE_X:
|
case AC_SIZE_X:
|
||||||
case AC_SIZE_Y:
|
case AC_SIZE_Y:
|
||||||
case AC_SIZE_Z:
|
case AC_SIZE_Z:
|
||||||
scale[bezierCurves[j].getType() - 13] = (float)value;
|
scale[bezierCurves[j].getType() - 13] = (float) value;
|
||||||
break;
|
break;
|
||||||
case AC_QUAT_W:
|
case AC_QUAT_W:
|
||||||
quaternionRotation[3] = (float)value;
|
quaternionRotation[3] = (float) value;
|
||||||
break;
|
break;
|
||||||
case AC_QUAT_X:
|
case AC_QUAT_X:
|
||||||
case AC_QUAT_Y:
|
case AC_QUAT_Y:
|
||||||
case AC_QUAT_Z:
|
case AC_QUAT_Z:
|
||||||
quaternionRotation[bezierCurves[j].getType() - 26] = (float)value;
|
quaternionRotation[bezierCurves[j].getType() - 26] = (float) value;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//TODO: error? info? warning?
|
//TODO: error? info? warning?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
translations[index] = new Vector3f(translation[0], translation[1], translation[2]);
|
translations[index] = new Vector3f(translation[0], translation[1], translation[2]);
|
||||||
rotations[index] = bObjectRotation ? new Quaternion().fromAngles(objectRotation) :
|
rotations[index] = bObjectRotation ? new Quaternion().fromAngles(objectRotation)
|
||||||
new Quaternion(quaternionRotation[0], quaternionRotation[1], quaternionRotation[2], quaternionRotation[3]);
|
: new Quaternion(quaternionRotation[0], quaternionRotation[1], quaternionRotation[2], quaternionRotation[3]);
|
||||||
scales[index] = new Vector3f(scale[0], scale[1], scale[2]);
|
scales[index] = new Vector3f(scale[0], scale[1], scale[2]);
|
||||||
}
|
}
|
||||||
calculatedTrack = new BoneTrack(boneIndex, times, translations, rotations, scales);
|
calculatedTrack = new BoneTrack(boneIndex, times, translations, rotations, scales);
|
||||||
return calculatedTrack;
|
return calculatedTrack;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,50 +7,51 @@ package com.jme3.scene.plugins.blender.structures;
|
|||||||
* @author Marcin Roguski (Kaelthas)
|
* @author Marcin Roguski (Kaelthas)
|
||||||
*/
|
*/
|
||||||
public class Modifier {
|
public class Modifier {
|
||||||
public static final String ARRAY_MODIFIER_DATA = "ArrayModifierData";
|
|
||||||
public static final String ARMATURE_MODIFIER_DATA = "ArmatureModifierData";
|
|
||||||
public static final String PARTICLE_MODIFIER_DATA = "ParticleSystemModifierData";
|
|
||||||
|
|
||||||
/** Blender's type of modifier. */
|
public static final String ARRAY_MODIFIER_DATA = "ArrayModifierData";
|
||||||
private String type;
|
public static final String ARMATURE_MODIFIER_DATA = "ArmatureModifierData";
|
||||||
/** JME modifier representation object. */
|
public static final String PARTICLE_MODIFIER_DATA = "ParticleSystemModifierData";
|
||||||
private Object jmeModifierRepresentation;
|
/** Blender's type of modifier. */
|
||||||
/** Various additional data used by modifiers.*/
|
private String type;
|
||||||
private Object additionalData;
|
/** JME modifier representation object. */
|
||||||
/**
|
private Object jmeModifierRepresentation;
|
||||||
* Constructor. Creates modifier object.
|
/** Various additional data used by modifiers.*/
|
||||||
* @param type
|
private Object additionalData;
|
||||||
* blender's type of modifier
|
|
||||||
* @param modifier
|
|
||||||
* JME modifier representation object
|
|
||||||
*/
|
|
||||||
public Modifier(String type, Object modifier, Object additionalData) {
|
|
||||||
this.type = type;
|
|
||||||
this.jmeModifierRepresentation = modifier;
|
|
||||||
this.additionalData = additionalData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns JME modifier representation object.
|
* Constructor. Creates modifier object.
|
||||||
* @return JME modifier representation object
|
* @param type
|
||||||
*/
|
* blender's type of modifier
|
||||||
public Object getJmeModifierRepresentation() {
|
* @param modifier
|
||||||
return jmeModifierRepresentation;
|
* JME modifier representation object
|
||||||
}
|
*/
|
||||||
|
public Modifier(String type, Object modifier, Object additionalData) {
|
||||||
|
this.type = type;
|
||||||
|
this.jmeModifierRepresentation = modifier;
|
||||||
|
this.additionalData = additionalData;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns blender's type of modifier.
|
* This method returns JME modifier representation object.
|
||||||
* @return blender's type of modifier
|
* @return JME modifier representation object
|
||||||
*/
|
*/
|
||||||
public String getType() {
|
public Object getJmeModifierRepresentation() {
|
||||||
return type;
|
return jmeModifierRepresentation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns additional data stored in the modifier.
|
* This method returns blender's type of modifier.
|
||||||
* @return the additional data stored in the modifier
|
* @return blender's type of modifier
|
||||||
*/
|
*/
|
||||||
public Object getAdditionalData() {
|
public String getType() {
|
||||||
return additionalData;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns additional data stored in the modifier.
|
||||||
|
* @return the additional data stored in the modifier
|
||||||
|
*/
|
||||||
|
public Object getAdditionalData() {
|
||||||
|
return additionalData;
|
||||||
|
}
|
||||||
}
|
}
|
@ -42,61 +42,63 @@ import com.jme3.util.BufferUtils;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractBlenderHelper {
|
public abstract class AbstractBlenderHelper {
|
||||||
/** The version of the blend file. */
|
|
||||||
protected final int blenderVersion;
|
|
||||||
|
|
||||||
/**
|
/** The version of the blend file. */
|
||||||
* This constructor parses the given blender version and stores the result. Some functionalities may differ in different blender
|
protected final int blenderVersion;
|
||||||
* versions.
|
|
||||||
* @param blenderVersion
|
|
||||||
* the version read from the blend file
|
|
||||||
*/
|
|
||||||
public AbstractBlenderHelper(String blenderVersion) {
|
|
||||||
this.blenderVersion = Integer.parseInt(blenderVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method clears the state of the helper so that it can be used for different calculations of another feature.
|
* This constructor parses the given blender version and stores the result. Some functionalities may differ in different blender
|
||||||
*/
|
* versions.
|
||||||
public void clearState() { }
|
* @param blenderVersion
|
||||||
|
* the version read from the blend file
|
||||||
|
*/
|
||||||
|
public AbstractBlenderHelper(String blenderVersion) {
|
||||||
|
this.blenderVersion = Integer.parseInt(blenderVersion);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method should be used to check if the text is blank. Avoid using text.trim().length()==0. This causes that more strings are
|
* This method clears the state of the helper so that it can be used for different calculations of another feature.
|
||||||
* being created and stored in the memory. It can be unwise especially inside loops.
|
*/
|
||||||
* @param text
|
public void clearState() {
|
||||||
* the text to be checked
|
}
|
||||||
* @return <b>true</b> if the text is blank and <b>false</b> otherwise
|
|
||||||
*/
|
|
||||||
protected boolean isBlank(String text) {
|
|
||||||
if (text != null) {
|
|
||||||
for (int i = 0; i < text.length(); ++i) {
|
|
||||||
if (!Character.isWhitespace(text.charAt(i))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a new FloatBuffer using the given array of float[4] objects. The FloatBuffer will be 4 * data.length
|
* This method should be used to check if the text is blank. Avoid using text.trim().length()==0. This causes that more strings are
|
||||||
* long and contain the vector data as data[0][0], data[0][1], data[0][2], data[0][3], data[1][0]... etc.
|
* being created and stored in the memory. It can be unwise especially inside loops.
|
||||||
* @param data
|
* @param text
|
||||||
* list of float[4] objects to place into a new FloatBuffer
|
* the text to be checked
|
||||||
*/
|
* @return <b>true</b> if the text is blank and <b>false</b> otherwise
|
||||||
protected FloatBuffer createFloatBuffer(List<float[]> data) {
|
*/
|
||||||
if(data == null) {
|
protected boolean isBlank(String text) {
|
||||||
return null;
|
if (text != null) {
|
||||||
}
|
for (int i = 0; i < text.length(); ++i) {
|
||||||
FloatBuffer buff = BufferUtils.createFloatBuffer(4 * data.size());
|
if (!Character.isWhitespace(text.charAt(i))) {
|
||||||
for(float[] v : data) {
|
return false;
|
||||||
if(v != null) {
|
}
|
||||||
buff.put(v[0]).put(v[1]).put(v[2]).put(v[3]);
|
}
|
||||||
} else {
|
}
|
||||||
buff.put(0).put(0).put(0).put(0);
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
buff.flip();
|
/**
|
||||||
return buff;
|
* Generate a new FloatBuffer using the given array of float[4] objects. The FloatBuffer will be 4 * data.length
|
||||||
}
|
* long and contain the vector data as data[0][0], data[0][1], data[0][2], data[0][3], data[1][0]... etc.
|
||||||
|
* @param data
|
||||||
|
* list of float[4] objects to place into a new FloatBuffer
|
||||||
|
*/
|
||||||
|
protected FloatBuffer createFloatBuffer(List<float[]> data) {
|
||||||
|
if (data == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
FloatBuffer buff = BufferUtils.createFloatBuffer(4 * data.size());
|
||||||
|
for (float[] v : data) {
|
||||||
|
if (v != null) {
|
||||||
|
buff.put(v[0]).put(v[1]).put(v[2]).put(v[3]);
|
||||||
|
} else {
|
||||||
|
buff.put(0).put(0).put(0).put(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buff.flip();
|
||||||
|
return buff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,58 +52,59 @@ import com.jme3.scene.plugins.blender.exception.BlenderFileException;
|
|||||||
* the type of material element
|
* the type of material element
|
||||||
*/
|
*/
|
||||||
//TODO: ujednolicić wyrzucane wyjątki
|
//TODO: ujednolicić wyrzucane wyjątki
|
||||||
public interface IBlenderConverter<NodeType, CameraType, LightType, ObjectType, MeshType, MaterialType> {
|
public interface BlenderConverter<NodeType, CameraType, LightType, ObjectType, MeshType, MaterialType> {
|
||||||
/**
|
|
||||||
* This method reads converts the given structure into scene. The given structure needs to be filled with the
|
|
||||||
* appropriate data.
|
|
||||||
* @param structure
|
|
||||||
* the structure we read the scene from
|
|
||||||
* @return the scene feature
|
|
||||||
*/
|
|
||||||
NodeType toScene(Structure structure);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads converts the given structure into camera. The given structure needs to be filled with the
|
* This method reads converts the given structure into scene. The given structure needs to be filled with the
|
||||||
* appropriate data.
|
* appropriate data.
|
||||||
* @param structure
|
* @param structure
|
||||||
* the structure we read the camera from
|
* the structure we read the scene from
|
||||||
* @return the camera feature
|
* @return the scene feature
|
||||||
*/
|
*/
|
||||||
CameraType toCamera(Structure structure) throws BlenderFileException;
|
NodeType toScene(Structure structure);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads converts the given structure into light. The given structure needs to be filled with the
|
* This method reads converts the given structure into camera. The given structure needs to be filled with the
|
||||||
* appropriate data.
|
* appropriate data.
|
||||||
* @param structure
|
* @param structure
|
||||||
* the structure we read the light from
|
* the structure we read the camera from
|
||||||
* @return the light feature
|
* @return the camera feature
|
||||||
*/
|
*/
|
||||||
LightType toLight(Structure structure) throws BlenderFileException;
|
CameraType toCamera(Structure structure) throws BlenderFileException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads converts the given structure into objct. The given structure needs to be filled with the
|
* This method reads converts the given structure into light. The given structure needs to be filled with the
|
||||||
* appropriate data.
|
* appropriate data.
|
||||||
* @param structure
|
* @param structure
|
||||||
* the structure we read the object from
|
* the structure we read the light from
|
||||||
* @return the object feature
|
* @return the light feature
|
||||||
*/
|
*/
|
||||||
ObjectType toObject(Structure structure) throws BlenderFileException;
|
LightType toLight(Structure structure) throws BlenderFileException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads converts the given structure into mesh. The given structure needs to be filled with the
|
* This method reads converts the given structure into objct. The given structure needs to be filled with the
|
||||||
* appropriate data.
|
* appropriate data.
|
||||||
* @param structure
|
* @param structure
|
||||||
* the structure we read the mesh from
|
* the structure we read the object from
|
||||||
* @return the mesh feature
|
* @return the object feature
|
||||||
*/
|
*/
|
||||||
MeshType toMesh(Structure structure) throws BlenderFileException;
|
ObjectType toObject(Structure structure) throws BlenderFileException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads converts the given structure into material. The given structure needs to be filled with the
|
* This method reads converts the given structure into mesh. The given structure needs to be filled with the
|
||||||
* appropriate data.
|
* appropriate data.
|
||||||
* @param structure
|
* @param structure
|
||||||
* the structure we read the material from
|
* the structure we read the mesh from
|
||||||
* @return the material feature
|
* @return the mesh feature
|
||||||
*/
|
*/
|
||||||
MaterialType toMaterial(Structure structure) throws BlenderFileException;
|
MeshType toMesh(Structure structure) throws BlenderFileException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method reads converts the given structure into material. The given structure needs to be filled with the
|
||||||
|
* appropriate data.
|
||||||
|
* @param structure
|
||||||
|
* the structure we read the material from
|
||||||
|
* @return the material feature
|
||||||
|
*/
|
||||||
|
MaterialType toMaterial(Structure structure) throws BlenderFileException;
|
||||||
}
|
}
|
@ -46,337 +46,337 @@ import com.jme3.scene.plugins.blender.exception.BlenderFileException;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class BlenderInputStream extends InputStream {
|
public class BlenderInputStream extends InputStream {
|
||||||
private static final Logger LOGGER = Logger.getLogger(BlenderInputStream.class.getName());
|
|
||||||
|
|
||||||
/** The default size of the blender buffer. */
|
private static final Logger LOGGER = Logger.getLogger(BlenderInputStream.class.getName());
|
||||||
private static final int DEFAULT_BUFFER_SIZE = 1048576; //1MB
|
/** The default size of the blender buffer. */
|
||||||
/** The application's asset manager. */
|
private static final int DEFAULT_BUFFER_SIZE = 1048576; //1MB
|
||||||
private AssetManager assetManager;
|
/** The application's asset manager. */
|
||||||
/**
|
private AssetManager assetManager;
|
||||||
* Size of a pointer; all pointers in the file are stored in this format. '_' means 4 bytes and '-' means 8 bytes.
|
/**
|
||||||
*/
|
* Size of a pointer; all pointers in the file are stored in this format. '_' means 4 bytes and '-' means 8 bytes.
|
||||||
private int pointerSize;
|
*/
|
||||||
/**
|
private int pointerSize;
|
||||||
* Type of byte ordering used; 'v' means little endian and 'V' means big endian.
|
/**
|
||||||
*/
|
* Type of byte ordering used; 'v' means little endian and 'V' means big endian.
|
||||||
private char endianess;
|
*/
|
||||||
/** Version of Blender the file was created in; '248' means version 2.48. */
|
private char endianess;
|
||||||
private String versionNumber;
|
/** Version of Blender the file was created in; '248' means version 2.48. */
|
||||||
/** The buffer we store the read data to. */
|
private String versionNumber;
|
||||||
protected byte[] cachedBuffer;
|
/** The buffer we store the read data to. */
|
||||||
/** The total size of the stored data. */
|
protected byte[] cachedBuffer;
|
||||||
protected int size;
|
/** The total size of the stored data. */
|
||||||
/** The current position of the read cursor. */
|
protected int size;
|
||||||
protected int position;
|
/** The current position of the read cursor. */
|
||||||
|
protected int position;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. The input stream is stored and used to read data.
|
* Constructor. The input stream is stored and used to read data.
|
||||||
* @param inputStream
|
* @param inputStream
|
||||||
* the stream we read data from
|
* the stream we read data from
|
||||||
* @param assetManager
|
* @param assetManager
|
||||||
* the application's asset manager
|
* the application's asset manager
|
||||||
* @param endianess
|
* @param endianess
|
||||||
* type of byte ordering used; 'v' means little endian and 'V' means big endian
|
* type of byte ordering used; 'v' means little endian and 'V' means big endian
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* this exception is thrown if the file header has some invalid data
|
* this exception is thrown if the file header has some invalid data
|
||||||
*/
|
*/
|
||||||
public BlenderInputStream(InputStream inputStream, AssetManager assetManager) throws BlenderFileException {
|
public BlenderInputStream(InputStream inputStream, AssetManager assetManager) throws BlenderFileException {
|
||||||
this.assetManager = assetManager;
|
this.assetManager = assetManager;
|
||||||
//the size value will canche while reading the file; the available() method cannot be counted on
|
//the size value will canche while reading the file; the available() method cannot be counted on
|
||||||
try {
|
try {
|
||||||
size = inputStream.available();
|
size = inputStream.available();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
if(size <= 0) {
|
if (size <= 0) {
|
||||||
size = BlenderInputStream.DEFAULT_BUFFER_SIZE;
|
size = BlenderInputStream.DEFAULT_BUFFER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//buffered input stream is used here for much faster file reading
|
//buffered input stream is used here for much faster file reading
|
||||||
BufferedInputStream bufferedInputStream;
|
BufferedInputStream bufferedInputStream;
|
||||||
if(inputStream instanceof BufferedInputStream) {
|
if (inputStream instanceof BufferedInputStream) {
|
||||||
bufferedInputStream = (BufferedInputStream)inputStream;
|
bufferedInputStream = (BufferedInputStream) inputStream;
|
||||||
} else {
|
} else {
|
||||||
bufferedInputStream = new BufferedInputStream(inputStream);
|
bufferedInputStream = new BufferedInputStream(inputStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.readStreamToCache(bufferedInputStream);
|
this.readStreamToCache(bufferedInputStream);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new BlenderFileException("Problems occured while caching the file!", e);
|
throw new BlenderFileException("Problems occured while caching the file!", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.readFileHeader();
|
this.readFileHeader();
|
||||||
} catch(BlenderFileException e) {//the file might be packed, don't panic, try one more time ;)
|
} catch (BlenderFileException e) {//the file might be packed, don't panic, try one more time ;)
|
||||||
this.decompressFile();
|
this.decompressFile();
|
||||||
this.position = 0;
|
this.position = 0;
|
||||||
this.readFileHeader();
|
this.readFileHeader();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads the whole stream into a buffer.
|
* This method reads the whole stream into a buffer.
|
||||||
* @param inputStream
|
* @param inputStream
|
||||||
* the stream to read the file data from
|
* the stream to read the file data from
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* an exception is thrown when data read from the stream is invalid or there are problems with i/o
|
* an exception is thrown when data read from the stream is invalid or there are problems with i/o
|
||||||
* operations
|
* operations
|
||||||
*/
|
*/
|
||||||
private void readStreamToCache(InputStream inputStream) throws IOException {
|
private void readStreamToCache(InputStream inputStream) throws IOException {
|
||||||
int data = inputStream.read();
|
int data = inputStream.read();
|
||||||
cachedBuffer = new byte[size];
|
cachedBuffer = new byte[size];
|
||||||
size = 0;//this will count the actual size
|
size = 0;//this will count the actual size
|
||||||
while(data != -1) {
|
while (data != -1) {
|
||||||
cachedBuffer[size++] = (byte)data;
|
cachedBuffer[size++] = (byte) data;
|
||||||
if(size >= cachedBuffer.length) {//widen the cached array
|
if (size >= cachedBuffer.length) {//widen the cached array
|
||||||
byte[] newBuffer = new byte[cachedBuffer.length + (cachedBuffer.length >> 1)];
|
byte[] newBuffer = new byte[cachedBuffer.length + (cachedBuffer.length >> 1)];
|
||||||
System.arraycopy(cachedBuffer, 0, newBuffer, 0, cachedBuffer.length);
|
System.arraycopy(cachedBuffer, 0, newBuffer, 0, cachedBuffer.length);
|
||||||
cachedBuffer = newBuffer;
|
cachedBuffer = newBuffer;
|
||||||
}
|
}
|
||||||
data = inputStream.read();
|
data = inputStream.read();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is used when the blender file is gzipped. It decompresses the data and stores it back into the
|
* This method is used when the blender file is gzipped. It decompresses the data and stores it back into the
|
||||||
* cachedBuffer field.
|
* cachedBuffer field.
|
||||||
*/
|
*/
|
||||||
private void decompressFile() {
|
private void decompressFile() {
|
||||||
GZIPInputStream gis = null;
|
GZIPInputStream gis = null;
|
||||||
try {
|
try {
|
||||||
gis = new GZIPInputStream(new ByteArrayInputStream(cachedBuffer));
|
gis = new GZIPInputStream(new ByteArrayInputStream(cachedBuffer));
|
||||||
this.readStreamToCache(gis);
|
this.readStreamToCache(gis);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IllegalStateException("IO errors occured where they should NOT! " +
|
throw new IllegalStateException("IO errors occured where they should NOT! "
|
||||||
"The data is already buffered at this point!", e);
|
+ "The data is already buffered at this point!", e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if(gis!=null) {
|
if (gis != null) {
|
||||||
gis.close();
|
gis.close();
|
||||||
}
|
}
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.warning(e.getMessage());
|
LOGGER.warning(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method loads the header from the given stream during instance creation.
|
* This method loads the header from the given stream during instance creation.
|
||||||
* @param inputStream
|
* @param inputStream
|
||||||
* the stream we read the header from
|
* the stream we read the header from
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* this exception is thrown if the file header has some invalid data
|
* this exception is thrown if the file header has some invalid data
|
||||||
*/
|
*/
|
||||||
private void readFileHeader() throws BlenderFileException {
|
private void readFileHeader() throws BlenderFileException {
|
||||||
byte[] identifier = new byte[7];
|
byte[] identifier = new byte[7];
|
||||||
int bytesRead = this.readBytes(identifier);
|
int bytesRead = this.readBytes(identifier);
|
||||||
if(bytesRead != 7) {
|
if (bytesRead != 7) {
|
||||||
throw new BlenderFileException("Error reading header identifier. Only " + bytesRead + " bytes read and there should be 7!");
|
throw new BlenderFileException("Error reading header identifier. Only " + bytesRead + " bytes read and there should be 7!");
|
||||||
}
|
}
|
||||||
String strIdentifier = new String(identifier);
|
String strIdentifier = new String(identifier);
|
||||||
if(!"BLENDER".equals(strIdentifier)) {
|
if (!"BLENDER".equals(strIdentifier)) {
|
||||||
throw new BlenderFileException("Wrong file identifier: " + strIdentifier + "! Should be 'BLENDER'!");
|
throw new BlenderFileException("Wrong file identifier: " + strIdentifier + "! Should be 'BLENDER'!");
|
||||||
}
|
}
|
||||||
char pointerSizeSign = (char)this.readByte();
|
char pointerSizeSign = (char) this.readByte();
|
||||||
if(pointerSizeSign == '-') {
|
if (pointerSizeSign == '-') {
|
||||||
pointerSize = 8;
|
pointerSize = 8;
|
||||||
} else if(pointerSizeSign == '_') {
|
} else if (pointerSizeSign == '_') {
|
||||||
pointerSize = 4;
|
pointerSize = 4;
|
||||||
} else {
|
} else {
|
||||||
throw new BlenderFileException("Invalid pointer size character! Should be '_' or '-' and there is: " + pointerSizeSign);
|
throw new BlenderFileException("Invalid pointer size character! Should be '_' or '-' and there is: " + pointerSizeSign);
|
||||||
}
|
}
|
||||||
endianess = (char)this.readByte();
|
endianess = (char) this.readByte();
|
||||||
if(endianess != 'v' && endianess != 'V') {
|
if (endianess != 'v' && endianess != 'V') {
|
||||||
throw new BlenderFileException("Unknown endianess value! 'v' or 'V' expected and found: " + endianess);
|
throw new BlenderFileException("Unknown endianess value! 'v' or 'V' expected and found: " + endianess);
|
||||||
}
|
}
|
||||||
byte[] versionNumber = new byte[3];
|
byte[] versionNumber = new byte[3];
|
||||||
bytesRead = this.readBytes(versionNumber);
|
bytesRead = this.readBytes(versionNumber);
|
||||||
if(bytesRead != 3) {
|
if (bytesRead != 3) {
|
||||||
throw new BlenderFileException("Error reading version numberr. Only " + bytesRead + " bytes read and there should be 3!");
|
throw new BlenderFileException("Error reading version numberr. Only " + bytesRead + " bytes read and there should be 3!");
|
||||||
}
|
}
|
||||||
this.versionNumber = new String(versionNumber);
|
this.versionNumber = new String(versionNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
return this.readByte();
|
return this.readByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads 1 byte from the stream.
|
* This method reads 1 byte from the stream.
|
||||||
* It works just in the way the read method does.
|
* It works just in the way the read method does.
|
||||||
* It just not throw an exception because at this moment the whole file
|
* It just not throw an exception because at this moment the whole file
|
||||||
* is loaded into buffer, so no need for IOException to be thrown.
|
* is loaded into buffer, so no need for IOException to be thrown.
|
||||||
* @return a byte from the stream (1 bytes read)
|
* @return a byte from the stream (1 bytes read)
|
||||||
*/
|
*/
|
||||||
public int readByte() {
|
public int readByte() {
|
||||||
return cachedBuffer[position++] & 0xFF;
|
return cachedBuffer[position++] & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads a bytes number big enough to fill the table.
|
* This method reads a bytes number big enough to fill the table.
|
||||||
* It does not throw exceptions so it is for internal use only.
|
* It does not throw exceptions so it is for internal use only.
|
||||||
* @param bytes
|
* @param bytes
|
||||||
* an array to be filled with data
|
* an array to be filled with data
|
||||||
* @return number of read bytes (a length of array actually)
|
* @return number of read bytes (a length of array actually)
|
||||||
*/
|
*/
|
||||||
private int readBytes(byte[] bytes) {
|
private int readBytes(byte[] bytes) {
|
||||||
for(int i=0;i<bytes.length;++i) {
|
for (int i = 0; i < bytes.length; ++i) {
|
||||||
bytes[i] = (byte) this.readByte();
|
bytes[i] = (byte) this.readByte();
|
||||||
}
|
}
|
||||||
return bytes.length;
|
return bytes.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads 2-byte number from the stream.
|
* This method reads 2-byte number from the stream.
|
||||||
* @return a number from the stream (2 bytes read)
|
* @return a number from the stream (2 bytes read)
|
||||||
*/
|
*/
|
||||||
public int readShort() {
|
public int readShort() {
|
||||||
int part1 = this.readByte();
|
int part1 = this.readByte();
|
||||||
int part2 = this.readByte();
|
int part2 = this.readByte();
|
||||||
if(endianess == 'v') {
|
if (endianess == 'v') {
|
||||||
return (part2 << 8) + part1;
|
return (part2 << 8) + part1;
|
||||||
} else {
|
} else {
|
||||||
return (part1 << 8) + part2;
|
return (part1 << 8) + part2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads 4-byte number from the stream.
|
* This method reads 4-byte number from the stream.
|
||||||
* @return a number from the stream (4 bytes read)
|
* @return a number from the stream (4 bytes read)
|
||||||
*/
|
*/
|
||||||
public int readInt() {
|
public int readInt() {
|
||||||
int part1 = this.readByte();
|
int part1 = this.readByte();
|
||||||
int part2 = this.readByte();
|
int part2 = this.readByte();
|
||||||
int part3 = this.readByte();
|
int part3 = this.readByte();
|
||||||
int part4 = this.readByte();
|
int part4 = this.readByte();
|
||||||
if(endianess == 'v') {
|
if (endianess == 'v') {
|
||||||
return (part4 << 24) + (part3 << 16) + (part2 << 8) + part1;
|
return (part4 << 24) + (part3 << 16) + (part2 << 8) + part1;
|
||||||
} else {
|
} else {
|
||||||
return (part1 << 24) + (part2 << 16) + (part3 << 8) + part4;
|
return (part1 << 24) + (part2 << 16) + (part3 << 8) + part4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads 4-byte floating point number (float) from the stream.
|
* This method reads 4-byte floating point number (float) from the stream.
|
||||||
* @return a number from the stream (4 bytes read)
|
* @return a number from the stream (4 bytes read)
|
||||||
*/
|
*/
|
||||||
public float readFloat() {
|
public float readFloat() {
|
||||||
int intValue = this.readInt();
|
int intValue = this.readInt();
|
||||||
return Float.intBitsToFloat(intValue);
|
return Float.intBitsToFloat(intValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads 8-byte number from the stream.
|
* This method reads 8-byte number from the stream.
|
||||||
* @return a number from the stream (8 bytes read)
|
* @return a number from the stream (8 bytes read)
|
||||||
*/
|
*/
|
||||||
public long readLong() {
|
public long readLong() {
|
||||||
long part1 = this.readInt();
|
long part1 = this.readInt();
|
||||||
long part2 = this.readInt();
|
long part2 = this.readInt();
|
||||||
long result = -1;
|
long result = -1;
|
||||||
if(endianess == 'v') {
|
if (endianess == 'v') {
|
||||||
result = part2 << 32 | part1;
|
result = part2 << 32 | part1;
|
||||||
} else {
|
} else {
|
||||||
result = part1 << 32 | part2;
|
result = part1 << 32 | part2;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads 8-byte floating point number (double) from the stream.
|
* This method reads 8-byte floating point number (double) from the stream.
|
||||||
* @return a number from the stream (8 bytes read)
|
* @return a number from the stream (8 bytes read)
|
||||||
*/
|
*/
|
||||||
public double readDouble() {
|
public double readDouble() {
|
||||||
long longValue = this.readLong();
|
long longValue = this.readLong();
|
||||||
return Double.longBitsToDouble(longValue);
|
return Double.longBitsToDouble(longValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads the pointer value. Depending on the pointer size defined in the header, the stream reads either
|
* This method reads the pointer value. Depending on the pointer size defined in the header, the stream reads either
|
||||||
* 4 or 8 bytes of data.
|
* 4 or 8 bytes of data.
|
||||||
* @return the pointer value
|
* @return the pointer value
|
||||||
*/
|
*/
|
||||||
public long readPointer() {
|
public long readPointer() {
|
||||||
if(pointerSize == 4) {
|
if (pointerSize == 4) {
|
||||||
return this.readInt();
|
return this.readInt();
|
||||||
}
|
}
|
||||||
return this.readLong();
|
return this.readLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads the string. It assumes the string is terminated with zero in the stream.
|
* This method reads the string. It assumes the string is terminated with zero in the stream.
|
||||||
* @return the string read from the stream
|
* @return the string read from the stream
|
||||||
*/
|
*/
|
||||||
public String readString() {
|
public String readString() {
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
int data = this.readByte();
|
int data = this.readByte();
|
||||||
while(data != 0) {
|
while (data != 0) {
|
||||||
stringBuilder.append((char)data);
|
stringBuilder.append((char) data);
|
||||||
data = this.readByte();
|
data = this.readByte();
|
||||||
}
|
}
|
||||||
return stringBuilder.toString();
|
return stringBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method sets the current position of the read cursor.
|
* This method sets the current position of the read cursor.
|
||||||
* @param position
|
* @param position
|
||||||
* the position of the read cursor
|
* the position of the read cursor
|
||||||
*/
|
*/
|
||||||
public void setPosition(int position) {
|
public void setPosition(int position) {
|
||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the position of the read cursor.
|
* This method returns the position of the read cursor.
|
||||||
* @return the position of the read cursor
|
* @return the position of the read cursor
|
||||||
*/
|
*/
|
||||||
public int getPosition() {
|
public int getPosition() {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the blender version number where the file was created.
|
* This method returns the blender version number where the file was created.
|
||||||
* @return blender version number
|
* @return blender version number
|
||||||
*/
|
*/
|
||||||
public String getVersionNumber() {
|
public String getVersionNumber() {
|
||||||
return versionNumber;
|
return versionNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the size of the pointer.
|
* This method returns the size of the pointer.
|
||||||
* @return the size of the pointer
|
* @return the size of the pointer
|
||||||
*/
|
*/
|
||||||
public int getPointerSize() {
|
public int getPointerSize() {
|
||||||
return pointerSize;
|
return pointerSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the application's asset manager.
|
* This method returns the application's asset manager.
|
||||||
* @return the application's asset manager
|
* @return the application's asset manager
|
||||||
*/
|
*/
|
||||||
public AssetManager getAssetManager() {
|
public AssetManager getAssetManager() {
|
||||||
return assetManager;
|
return assetManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method aligns cursor position forward to a given amount of bytes.
|
* This method aligns cursor position forward to a given amount of bytes.
|
||||||
* @param bytesAmount
|
* @param bytesAmount
|
||||||
* the byte amount to which we aligh the cursor
|
* the byte amount to which we aligh the cursor
|
||||||
*/
|
*/
|
||||||
public void alignPosition(int bytesAmount) {
|
public void alignPosition(int bytesAmount) {
|
||||||
if(bytesAmount <= 0) {
|
if (bytesAmount <= 0) {
|
||||||
throw new IllegalArgumentException("Alignment byte number shoulf be positivbe!");
|
throw new IllegalArgumentException("Alignment byte number shoulf be positivbe!");
|
||||||
}
|
}
|
||||||
long move = position % bytesAmount;
|
long move = position % bytesAmount;
|
||||||
if(move > 0) {
|
if (move > 0) {
|
||||||
position += bytesAmount - move;
|
position += bytesAmount - move;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
// cachedBuffer = null;
|
// cachedBuffer = null;
|
||||||
// size = position = 0;
|
// size = position = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,347 +54,347 @@ import com.jme3.scene.plugins.blender.structures.Modifier;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class DataRepository {
|
public class DataRepository {
|
||||||
/** The blender key. */
|
|
||||||
private BlenderKey blenderKey;
|
|
||||||
/** The header of the file block. */
|
|
||||||
private DnaBlockData dnaBlockData;
|
|
||||||
/** The input stream of the blend file. */
|
|
||||||
private BlenderInputStream inputStream;
|
|
||||||
/** The asset manager. */
|
|
||||||
private AssetManager assetManager;
|
|
||||||
/** A map containing the file block headers. The key is the old pointer address. */
|
|
||||||
private Map<Long, FileBlockHeader> fileBlockHeadersByOma = new HashMap<Long, FileBlockHeader>();
|
|
||||||
/** A map containing the file block headers. The key is the block code. */
|
|
||||||
private Map<Integer, List<FileBlockHeader>> fileBlockHeadersByCode = new HashMap<Integer, List<FileBlockHeader>>();
|
|
||||||
/**
|
|
||||||
* This map stores the loaded features by their old memory address. The first object in the value table is the
|
|
||||||
* loaded structure and the second - the structure already converted into proper data.
|
|
||||||
*/
|
|
||||||
private Map<Long, Object[]> loadedFeatures = new HashMap<Long, Object[]>();
|
|
||||||
/**
|
|
||||||
* This map stores the loaded features by their name. Only features with ID structure can be stored here.
|
|
||||||
* The first object in the value table is the
|
|
||||||
* loaded structure and the second - the structure already converted into proper data.
|
|
||||||
*/
|
|
||||||
private Map<String, Object[]> loadedFeaturesByName = new HashMap<String, Object[]>();
|
|
||||||
/** A stack that hold the parent structure of currently loaded feature. */
|
|
||||||
private Stack<Structure> parentStack = new Stack<Structure>();
|
|
||||||
/** A map storing loaded ipos. The key is the ipo's owner old memory address and the value is the ipo. */
|
|
||||||
private Map<Long, Ipo> loadedIpos = new HashMap<Long, Ipo>();
|
|
||||||
/** A list of modifiers for the specified object. */
|
|
||||||
protected Map<Long, List<Modifier>> modifiers = new HashMap<Long, List<Modifier>>();
|
|
||||||
/** A map og helpers that perform loading. */
|
|
||||||
private Map<String, AbstractBlenderHelper> helpers = new HashMap<String, AbstractBlenderHelper>();
|
|
||||||
|
|
||||||
/**
|
/** The blender key. */
|
||||||
* This method sets the blender key.
|
private BlenderKey blenderKey;
|
||||||
* @param blenderKey
|
/** The header of the file block. */
|
||||||
* the blender key
|
private DnaBlockData dnaBlockData;
|
||||||
*/
|
/** The input stream of the blend file. */
|
||||||
public void setBlenderKey(BlenderKey blenderKey) {
|
private BlenderInputStream inputStream;
|
||||||
this.blenderKey = blenderKey;
|
/** The asset manager. */
|
||||||
}
|
private AssetManager assetManager;
|
||||||
|
/** A map containing the file block headers. The key is the old pointer address. */
|
||||||
|
private Map<Long, FileBlockHeader> fileBlockHeadersByOma = new HashMap<Long, FileBlockHeader>();
|
||||||
|
/** A map containing the file block headers. The key is the block code. */
|
||||||
|
private Map<Integer, List<FileBlockHeader>> fileBlockHeadersByCode = new HashMap<Integer, List<FileBlockHeader>>();
|
||||||
|
/**
|
||||||
|
* This map stores the loaded features by their old memory address. The first object in the value table is the
|
||||||
|
* loaded structure and the second - the structure already converted into proper data.
|
||||||
|
*/
|
||||||
|
private Map<Long, Object[]> loadedFeatures = new HashMap<Long, Object[]>();
|
||||||
|
/**
|
||||||
|
* This map stores the loaded features by their name. Only features with ID structure can be stored here.
|
||||||
|
* The first object in the value table is the
|
||||||
|
* loaded structure and the second - the structure already converted into proper data.
|
||||||
|
*/
|
||||||
|
private Map<String, Object[]> loadedFeaturesByName = new HashMap<String, Object[]>();
|
||||||
|
/** A stack that hold the parent structure of currently loaded feature. */
|
||||||
|
private Stack<Structure> parentStack = new Stack<Structure>();
|
||||||
|
/** A map storing loaded ipos. The key is the ipo's owner old memory address and the value is the ipo. */
|
||||||
|
private Map<Long, Ipo> loadedIpos = new HashMap<Long, Ipo>();
|
||||||
|
/** A list of modifiers for the specified object. */
|
||||||
|
protected Map<Long, List<Modifier>> modifiers = new HashMap<Long, List<Modifier>>();
|
||||||
|
/** A map og helpers that perform loading. */
|
||||||
|
private Map<String, AbstractBlenderHelper> helpers = new HashMap<String, AbstractBlenderHelper>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the blender key.
|
* This method sets the blender key.
|
||||||
* @return the blender key
|
* @param blenderKey
|
||||||
*/
|
* the blender key
|
||||||
public BlenderKey getBlenderKey() {
|
*/
|
||||||
return blenderKey;
|
public void setBlenderKey(BlenderKey blenderKey) {
|
||||||
}
|
this.blenderKey = blenderKey;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method sets the dna block data.
|
* This method returns the blender key.
|
||||||
* @param dnaBlockData
|
* @return the blender key
|
||||||
* the dna block data
|
*/
|
||||||
*/
|
public BlenderKey getBlenderKey() {
|
||||||
public void setBlockData(DnaBlockData dnaBlockData) {
|
return blenderKey;
|
||||||
this.dnaBlockData = dnaBlockData;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the dna block data.
|
* This method sets the dna block data.
|
||||||
* @return the dna block data
|
* @param dnaBlockData
|
||||||
*/
|
* the dna block data
|
||||||
public DnaBlockData getDnaBlockData() {
|
*/
|
||||||
return dnaBlockData;
|
public void setBlockData(DnaBlockData dnaBlockData) {
|
||||||
}
|
this.dnaBlockData = dnaBlockData;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the asset manager.
|
* This method returns the dna block data.
|
||||||
* @return the asset manager
|
* @return the dna block data
|
||||||
*/
|
*/
|
||||||
public AssetManager getAssetManager() {
|
public DnaBlockData getDnaBlockData() {
|
||||||
return assetManager;
|
return dnaBlockData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method sets the asset manager.
|
* This method returns the asset manager.
|
||||||
* @param assetManager
|
* @return the asset manager
|
||||||
* the asset manager
|
*/
|
||||||
*/
|
public AssetManager getAssetManager() {
|
||||||
public void setAssetManager(AssetManager assetManager) {
|
return assetManager;
|
||||||
this.assetManager = assetManager;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the input stream of the blend file.
|
* This method sets the asset manager.
|
||||||
* @return the input stream of the blend file
|
* @param assetManager
|
||||||
*/
|
* the asset manager
|
||||||
public BlenderInputStream getInputStream() {
|
*/
|
||||||
return inputStream;
|
public void setAssetManager(AssetManager assetManager) {
|
||||||
}
|
this.assetManager = assetManager;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method sets the input stream of the blend file.
|
* This method returns the input stream of the blend file.
|
||||||
* @param inputStream
|
* @return the input stream of the blend file
|
||||||
* the input stream of the blend file
|
*/
|
||||||
*/
|
public BlenderInputStream getInputStream() {
|
||||||
public void setInputStream(BlenderInputStream inputStream) {
|
return inputStream;
|
||||||
this.inputStream = inputStream;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method adds a file block header to the map. Its old memory address is the key.
|
* This method sets the input stream of the blend file.
|
||||||
* @param oldMemoryAddress
|
* @param inputStream
|
||||||
* the address of the block header
|
* the input stream of the blend file
|
||||||
* @param fileBlockHeader
|
*/
|
||||||
* the block header to store
|
public void setInputStream(BlenderInputStream inputStream) {
|
||||||
*/
|
this.inputStream = inputStream;
|
||||||
public void addFileBlockHeader(Long oldMemoryAddress, FileBlockHeader fileBlockHeader) {
|
}
|
||||||
fileBlockHeadersByOma.put(oldMemoryAddress, fileBlockHeader);
|
|
||||||
List<FileBlockHeader> headers = fileBlockHeadersByCode.get(Integer.valueOf(fileBlockHeader.getCode()));
|
|
||||||
if(headers == null) {
|
|
||||||
headers = new ArrayList<FileBlockHeader>();
|
|
||||||
fileBlockHeadersByCode.put(Integer.valueOf(fileBlockHeader.getCode()), headers);
|
|
||||||
}
|
|
||||||
headers.add(fileBlockHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the block header of a given memory address. If the header is not present then null is
|
* This method adds a file block header to the map. Its old memory address is the key.
|
||||||
* returned.
|
* @param oldMemoryAddress
|
||||||
* @param oldMemoryAddress
|
* the address of the block header
|
||||||
* the address of the block header
|
* @param fileBlockHeader
|
||||||
* @return loaded header or null if it was not yet loaded
|
* the block header to store
|
||||||
*/
|
*/
|
||||||
public FileBlockHeader getFileBlock(Long oldMemoryAddress) {
|
public void addFileBlockHeader(Long oldMemoryAddress, FileBlockHeader fileBlockHeader) {
|
||||||
return fileBlockHeadersByOma.get(oldMemoryAddress);
|
fileBlockHeadersByOma.put(oldMemoryAddress, fileBlockHeader);
|
||||||
}
|
List<FileBlockHeader> headers = fileBlockHeadersByCode.get(Integer.valueOf(fileBlockHeader.getCode()));
|
||||||
|
if (headers == null) {
|
||||||
|
headers = new ArrayList<FileBlockHeader>();
|
||||||
|
fileBlockHeadersByCode.put(Integer.valueOf(fileBlockHeader.getCode()), headers);
|
||||||
|
}
|
||||||
|
headers.add(fileBlockHeader);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns a list of file blocks' headers of a specified code.
|
* This method returns the block header of a given memory address. If the header is not present then null is
|
||||||
* @param code
|
* returned.
|
||||||
* the code of file blocks
|
* @param oldMemoryAddress
|
||||||
* @return a list of file blocks' headers of a specified code
|
* the address of the block header
|
||||||
*/
|
* @return loaded header or null if it was not yet loaded
|
||||||
public List<FileBlockHeader> getFileBlocks(Integer code) {
|
*/
|
||||||
return fileBlockHeadersByCode.get(code);
|
public FileBlockHeader getFileBlock(Long oldMemoryAddress) {
|
||||||
}
|
return fileBlockHeadersByOma.get(oldMemoryAddress);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method clears the saved block headers stored in the features map.
|
* This method returns a list of file blocks' headers of a specified code.
|
||||||
*/
|
* @param code
|
||||||
public void clearFileBlocks() {
|
* the code of file blocks
|
||||||
fileBlockHeadersByOma.clear();
|
* @return a list of file blocks' headers of a specified code
|
||||||
fileBlockHeadersByCode.clear();
|
*/
|
||||||
}
|
public List<FileBlockHeader> getFileBlocks(Integer code) {
|
||||||
|
return fileBlockHeadersByCode.get(code);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method adds a helper instance to the helpers' map.
|
* This method clears the saved block headers stored in the features map.
|
||||||
* @param <T>
|
*/
|
||||||
* the type of the helper
|
public void clearFileBlocks() {
|
||||||
* @param clazz
|
fileBlockHeadersByOma.clear();
|
||||||
* helper's class definition
|
fileBlockHeadersByCode.clear();
|
||||||
* @param helper
|
}
|
||||||
* the helper instance
|
|
||||||
*/
|
|
||||||
public <T> void putHelper(Class<T> clazz, AbstractBlenderHelper helper) {
|
|
||||||
helpers.put(clazz.getSimpleName(), helper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
/**
|
||||||
public <T> T getHelper(Class<?> clazz) {
|
* This method adds a helper instance to the helpers' map.
|
||||||
return (T)helpers.get(clazz.getSimpleName());
|
* @param <T>
|
||||||
}
|
* the type of the helper
|
||||||
|
* @param clazz
|
||||||
|
* helper's class definition
|
||||||
|
* @param helper
|
||||||
|
* the helper instance
|
||||||
|
*/
|
||||||
|
public <T> void putHelper(Class<T> clazz, AbstractBlenderHelper helper) {
|
||||||
|
helpers.put(clazz.getSimpleName(), helper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T getHelper(Class<?> clazz) {
|
||||||
|
return (T) helpers.get(clazz.getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method adds a loaded feature to the map. The key is its unique old memory address.
|
* This method adds a loaded feature to the map. The key is its unique old memory address.
|
||||||
* @param oldMemoryAddress
|
* @param oldMemoryAddress
|
||||||
* the address of the feature
|
* the address of the feature
|
||||||
* @param featureName the name of the feature
|
* @param featureName the name of the feature
|
||||||
* @param structure
|
* @param structure
|
||||||
* the filled structure of the feature
|
* the filled structure of the feature
|
||||||
* @param feature
|
* @param feature
|
||||||
* the feature we want to store
|
* the feature we want to store
|
||||||
*/
|
*/
|
||||||
public void addLoadedFeatures(Long oldMemoryAddress, String featureName, Structure structure, Object feature) {
|
public void addLoadedFeatures(Long oldMemoryAddress, String featureName, Structure structure, Object feature) {
|
||||||
if(oldMemoryAddress == null || structure == null || feature == null) {
|
if (oldMemoryAddress == null || structure == null || feature == null) {
|
||||||
throw new IllegalArgumentException("One of the given arguments is null!");
|
throw new IllegalArgumentException("One of the given arguments is null!");
|
||||||
}
|
}
|
||||||
Object[] storedData = new Object[] {structure, feature};
|
Object[] storedData = new Object[]{structure, feature};
|
||||||
loadedFeatures.put(oldMemoryAddress, storedData);
|
loadedFeatures.put(oldMemoryAddress, storedData);
|
||||||
if(featureName!=null) {
|
if (featureName != null) {
|
||||||
loadedFeaturesByName.put(featureName, storedData);
|
loadedFeaturesByName.put(featureName, storedData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the feature of a given memory address. If the feature is not yet loaded then null is
|
* This method returns the feature of a given memory address. If the feature is not yet loaded then null is
|
||||||
* returned.
|
* returned.
|
||||||
* @param oldMemoryAddress
|
* @param oldMemoryAddress
|
||||||
* the address of the feature
|
* the address of the feature
|
||||||
* @param loadedFeatureDataType
|
* @param loadedFeatureDataType
|
||||||
* the type of data we want to retreive it can be either filled structure or already converted feature
|
* the type of data we want to retreive it can be either filled structure or already converted feature
|
||||||
* @return loaded feature or null if it was not yet loaded
|
* @return loaded feature or null if it was not yet loaded
|
||||||
*/
|
*/
|
||||||
public Object getLoadedFeature(Long oldMemoryAddress, LoadedFeatureDataType loadedFeatureDataType) {
|
public Object getLoadedFeature(Long oldMemoryAddress, LoadedFeatureDataType loadedFeatureDataType) {
|
||||||
Object[] result = loadedFeatures.get(oldMemoryAddress);
|
Object[] result = loadedFeatures.get(oldMemoryAddress);
|
||||||
if(result != null) {
|
if (result != null) {
|
||||||
return result[loadedFeatureDataType.getIndex()];
|
return result[loadedFeatureDataType.getIndex()];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the feature of a given name. If the feature is not yet loaded then null is
|
* This method returns the feature of a given name. If the feature is not yet loaded then null is
|
||||||
* returned.
|
* returned.
|
||||||
* @param featureName
|
* @param featureName
|
||||||
* the name of the feature
|
* the name of the feature
|
||||||
* @param loadedFeatureDataType
|
* @param loadedFeatureDataType
|
||||||
* the type of data we want to retreive it can be either filled structure or already converted feature
|
* the type of data we want to retreive it can be either filled structure or already converted feature
|
||||||
* @return loaded feature or null if it was not yet loaded
|
* @return loaded feature or null if it was not yet loaded
|
||||||
*/
|
*/
|
||||||
public Object getLoadedFeature(String featureName, LoadedFeatureDataType loadedFeatureDataType) {
|
public Object getLoadedFeature(String featureName, LoadedFeatureDataType loadedFeatureDataType) {
|
||||||
Object[] result = loadedFeaturesByName.get(featureName);
|
Object[] result = loadedFeaturesByName.get(featureName);
|
||||||
if(result != null) {
|
if (result != null) {
|
||||||
return result[loadedFeatureDataType.getIndex()];
|
return result[loadedFeatureDataType.getIndex()];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method clears the saved features stored in the features map.
|
* This method clears the saved features stored in the features map.
|
||||||
*/
|
*/
|
||||||
public void clearLoadedFeatures() {
|
public void clearLoadedFeatures() {
|
||||||
loadedFeatures.clear();
|
loadedFeatures.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method adds the structure to the parent stack.
|
* This method adds the structure to the parent stack.
|
||||||
* @param parent
|
* @param parent
|
||||||
* the structure to be added to the stack
|
* the structure to be added to the stack
|
||||||
*/
|
*/
|
||||||
public void pushParent(Structure parent) {
|
public void pushParent(Structure parent) {
|
||||||
parentStack.push(parent);
|
parentStack.push(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method removes the structure from the top of the parent's stack.
|
* This method removes the structure from the top of the parent's stack.
|
||||||
* @return the structure that was removed from the stack
|
* @return the structure that was removed from the stack
|
||||||
*/
|
*/
|
||||||
public Structure popParent() {
|
public Structure popParent() {
|
||||||
try {
|
try {
|
||||||
return parentStack.pop();
|
return parentStack.pop();
|
||||||
} catch(EmptyStackException e) {
|
} catch (EmptyStackException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method retreives the structure at the top of the parent's stack but does not remove it.
|
* This method retreives the structure at the top of the parent's stack but does not remove it.
|
||||||
* @return the structure from the top of the stack
|
* @return the structure from the top of the stack
|
||||||
*/
|
*/
|
||||||
public Structure peekParent() {
|
public Structure peekParent() {
|
||||||
try {
|
try {
|
||||||
return parentStack.peek();
|
return parentStack.peek();
|
||||||
} catch(EmptyStackException e) {
|
} catch (EmptyStackException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addIpo(Long ownerOMA, Ipo ipo) {
|
public void addIpo(Long ownerOMA, Ipo ipo) {
|
||||||
loadedIpos.put(ownerOMA, ipo);
|
loadedIpos.put(ownerOMA, ipo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Ipo removeIpo(Long ownerOma) {
|
public Ipo removeIpo(Long ownerOma) {
|
||||||
return loadedIpos.remove(ownerOma);
|
return loadedIpos.remove(ownerOma);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Ipo getIpo(Long ownerOMA) {
|
public Ipo getIpo(Long ownerOMA) {
|
||||||
return loadedIpos.get(ownerOMA);
|
return loadedIpos.get(ownerOMA);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method adds a new modifier to the list.
|
* This method adds a new modifier to the list.
|
||||||
* @param ownerOMA
|
* @param ownerOMA
|
||||||
* the owner's old memory address
|
* the owner's old memory address
|
||||||
* @param modifierType
|
* @param modifierType
|
||||||
* the type of the modifier
|
* the type of the modifier
|
||||||
* @param loadedModifier
|
* @param loadedModifier
|
||||||
* the loaded modifier object
|
* the loaded modifier object
|
||||||
*/
|
*/
|
||||||
public void addModifier(Long ownerOMA, String modifierType, Object loadedModifier, Object additionalModifierData) {
|
public void addModifier(Long ownerOMA, String modifierType, Object loadedModifier, Object additionalModifierData) {
|
||||||
List<Modifier> objectModifiers = this.modifiers.get(ownerOMA);
|
List<Modifier> objectModifiers = this.modifiers.get(ownerOMA);
|
||||||
if(objectModifiers == null) {
|
if (objectModifiers == null) {
|
||||||
objectModifiers = new ArrayList<Modifier>();
|
objectModifiers = new ArrayList<Modifier>();
|
||||||
this.modifiers.put(ownerOMA, objectModifiers);
|
this.modifiers.put(ownerOMA, objectModifiers);
|
||||||
}
|
}
|
||||||
objectModifiers.add(new Modifier(modifierType, loadedModifier, additionalModifierData));
|
objectModifiers.add(new Modifier(modifierType, loadedModifier, additionalModifierData));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns modifiers for the object specified by its old memory address and the modifier type. If no
|
* This method returns modifiers for the object specified by its old memory address and the modifier type. If no
|
||||||
* modifiers are found - empty list is returned. If the type is null - all modifiers for the object are returned.
|
* modifiers are found - empty list is returned. If the type is null - all modifiers for the object are returned.
|
||||||
* @param objectOMA
|
* @param objectOMA
|
||||||
* object's old memory address
|
* object's old memory address
|
||||||
* @param type
|
* @param type
|
||||||
* the type of the modifier
|
* the type of the modifier
|
||||||
* @return the list of object's modifiers
|
* @return the list of object's modifiers
|
||||||
*/
|
*/
|
||||||
public List<Modifier> getModifiers(Long objectOMA, String type) {
|
public List<Modifier> getModifiers(Long objectOMA, String type) {
|
||||||
List<Modifier> result = new ArrayList<Modifier>();
|
List<Modifier> result = new ArrayList<Modifier>();
|
||||||
List<Modifier> readModifiers = modifiers.get(objectOMA);
|
List<Modifier> readModifiers = modifiers.get(objectOMA);
|
||||||
if(readModifiers != null && readModifiers.size() > 0) {
|
if (readModifiers != null && readModifiers.size() > 0) {
|
||||||
for(Modifier modifier : readModifiers) {
|
for (Modifier modifier : readModifiers) {
|
||||||
if(type==null || type.isEmpty() || modifier.getType().equals(type)) {
|
if (type == null || type.isEmpty() || modifier.getType().equals(type)) {
|
||||||
result.add(modifier);
|
result.add(modifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This metod returns the default material.
|
* This metod returns the default material.
|
||||||
* @return the default material
|
* @return the default material
|
||||||
*/
|
*/
|
||||||
public synchronized Material getDefaultMaterial() {
|
public synchronized Material getDefaultMaterial() {
|
||||||
if(blenderKey.getDefaultMaterial() == null) {
|
if (blenderKey.getDefaultMaterial() == null) {
|
||||||
Material defaultMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
Material defaultMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||||
defaultMaterial.setColor("Color", ColorRGBA.DarkGray);
|
defaultMaterial.setColor("Color", ColorRGBA.DarkGray);
|
||||||
blenderKey.setDefaultMaterial(defaultMaterial);
|
blenderKey.setDefaultMaterial(defaultMaterial);
|
||||||
}
|
}
|
||||||
return blenderKey.getDefaultMaterial();
|
return blenderKey.getDefaultMaterial();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This enum defines what loaded data type user wants to retreive. It can be either filled structure or already
|
* This enum defines what loaded data type user wants to retreive. It can be either filled structure or already
|
||||||
* converted data.
|
* converted data.
|
||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public static enum LoadedFeatureDataType {
|
public static enum LoadedFeatureDataType {
|
||||||
LOADED_STRUCTURE(0), LOADED_FEATURE(1);
|
|
||||||
|
|
||||||
private int index;
|
LOADED_STRUCTURE(0), LOADED_FEATURE(1);
|
||||||
|
private int index;
|
||||||
|
|
||||||
private LoadedFeatureDataType(int index) {
|
private LoadedFeatureDataType(int index) {
|
||||||
this.index = index;
|
this.index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getIndex() {
|
public int getIndex() {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,117 +40,118 @@ import com.jme3.scene.plugins.blender.exception.BlenderFileException;
|
|||||||
* the type of stored data in the array
|
* the type of stored data in the array
|
||||||
*/
|
*/
|
||||||
public class DynamicArray<T> implements Cloneable {
|
public class DynamicArray<T> implements Cloneable {
|
||||||
/** An array object that holds the required data. */
|
|
||||||
private T[] array;
|
|
||||||
/**
|
|
||||||
* This table holds the sizes of dimetions of the dynamic table. It's length specifies the table dimension or a
|
|
||||||
* pointer level. For example: if tableSizes.length == 3 then it either specifies a dynamic table of fixed lengths:
|
|
||||||
* dynTable[a][b][c], where a,b,c are stored in the tableSizes table.
|
|
||||||
*/
|
|
||||||
private int[] tableSizes;
|
|
||||||
|
|
||||||
/**
|
/** An array object that holds the required data. */
|
||||||
* Constructor. Builds an empty array of the specified sizes.
|
private T[] array;
|
||||||
* @param tableSizes
|
/**
|
||||||
* the sizes of the table
|
* This table holds the sizes of dimetions of the dynamic table. It's length specifies the table dimension or a
|
||||||
* @throws BlenderFileException
|
* pointer level. For example: if tableSizes.length == 3 then it either specifies a dynamic table of fixed lengths:
|
||||||
* an exception is thrown if one of the sizes is not a positive number
|
* dynTable[a][b][c], where a,b,c are stored in the tableSizes table.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
private int[] tableSizes;
|
||||||
public DynamicArray(int[] tableSizes) throws BlenderFileException {
|
|
||||||
this.tableSizes = tableSizes;
|
|
||||||
int totalSize = 1;
|
|
||||||
for(int size : tableSizes) {
|
|
||||||
if(size <= 0) {
|
|
||||||
throw new BlenderFileException("The size of the table must be positive!");
|
|
||||||
}
|
|
||||||
totalSize *= size;
|
|
||||||
}
|
|
||||||
this.array = (T[])new Object[totalSize];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Builds an empty array of the specified sizes.
|
* Constructor. Builds an empty array of the specified sizes.
|
||||||
* @param tableSizes
|
* @param tableSizes
|
||||||
* the sizes of the table
|
* the sizes of the table
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* an exception is thrown if one of the sizes is not a positive number
|
* an exception is thrown if one of the sizes is not a positive number
|
||||||
*/
|
*/
|
||||||
public DynamicArray(int[] tableSizes, T[] data) throws BlenderFileException {
|
@SuppressWarnings("unchecked")
|
||||||
this.tableSizes = tableSizes;
|
public DynamicArray(int[] tableSizes) throws BlenderFileException {
|
||||||
int totalSize = 1;
|
this.tableSizes = tableSizes;
|
||||||
for(int size : tableSizes) {
|
int totalSize = 1;
|
||||||
if(size <= 0) {
|
for (int size : tableSizes) {
|
||||||
throw new BlenderFileException("The size of the table must be positive!");
|
if (size <= 0) {
|
||||||
}
|
throw new BlenderFileException("The size of the table must be positive!");
|
||||||
totalSize *= size;
|
}
|
||||||
}
|
totalSize *= size;
|
||||||
if(totalSize != data.length) {
|
}
|
||||||
throw new IllegalArgumentException("The size of the table does not match the size of the given data!");
|
this.array = (T[]) new Object[totalSize];
|
||||||
}
|
}
|
||||||
this.array = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public Object clone() throws CloneNotSupportedException {
|
* Constructor. Builds an empty array of the specified sizes.
|
||||||
return super.clone();
|
* @param tableSizes
|
||||||
}
|
* the sizes of the table
|
||||||
|
* @throws BlenderFileException
|
||||||
|
* an exception is thrown if one of the sizes is not a positive number
|
||||||
|
*/
|
||||||
|
public DynamicArray(int[] tableSizes, T[] data) throws BlenderFileException {
|
||||||
|
this.tableSizes = tableSizes;
|
||||||
|
int totalSize = 1;
|
||||||
|
for (int size : tableSizes) {
|
||||||
|
if (size <= 0) {
|
||||||
|
throw new BlenderFileException("The size of the table must be positive!");
|
||||||
|
}
|
||||||
|
totalSize *= size;
|
||||||
|
}
|
||||||
|
if (totalSize != data.length) {
|
||||||
|
throw new IllegalArgumentException("The size of the table does not match the size of the given data!");
|
||||||
|
}
|
||||||
|
this.array = data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* This method returns a value on the specified position. The dimension of the table is not taken into
|
public Object clone() throws CloneNotSupportedException {
|
||||||
* consideration.
|
return super.clone();
|
||||||
* @param position
|
}
|
||||||
* the position of the data
|
|
||||||
* @return required data
|
|
||||||
*/
|
|
||||||
public T get(int position) {
|
|
||||||
return array[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns a value on the specified position in multidimensional array. Be careful not to exceed the
|
* This method returns a value on the specified position. The dimension of the table is not taken into
|
||||||
* table boundaries. Check the table's dimension first.
|
* consideration.
|
||||||
* @param position
|
* @param position
|
||||||
* the position of the data indices of data position
|
* the position of the data
|
||||||
* @return required data required data
|
* @return required data
|
||||||
*/
|
*/
|
||||||
public T get(int... position) {
|
public T get(int position) {
|
||||||
if(position.length != tableSizes.length) {
|
return array[position];
|
||||||
throw new ArrayIndexOutOfBoundsException("The table accepts " + tableSizes.length + " indexing number(s)!");
|
}
|
||||||
}
|
|
||||||
int index = 0;
|
|
||||||
for(int i = 0; i < position.length - 1; ++i) {
|
|
||||||
index += position[i] * tableSizes[i + 1];
|
|
||||||
}
|
|
||||||
index += position[position.length - 1];
|
|
||||||
return array[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the total amount of data stored in the array.
|
* This method returns a value on the specified position in multidimensional array. Be careful not to exceed the
|
||||||
* @return the total amount of data stored in the array
|
* table boundaries. Check the table's dimension first.
|
||||||
*/
|
* @param position
|
||||||
public int getTotalSize() {
|
* the position of the data indices of data position
|
||||||
return array.length;
|
* @return required data required data
|
||||||
}
|
*/
|
||||||
|
public T get(int... position) {
|
||||||
|
if (position.length != tableSizes.length) {
|
||||||
|
throw new ArrayIndexOutOfBoundsException("The table accepts " + tableSizes.length + " indexing number(s)!");
|
||||||
|
}
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < position.length - 1; ++i) {
|
||||||
|
index += position[i] * tableSizes[i + 1];
|
||||||
|
}
|
||||||
|
index += position[position.length - 1];
|
||||||
|
return array[index];
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public String toString() {
|
* This method returns the total amount of data stored in the array.
|
||||||
StringBuilder result = new StringBuilder();
|
* @return the total amount of data stored in the array
|
||||||
if(array instanceof Character[]) {//in case of character array we convert it to String
|
*/
|
||||||
for(int i = 0; i < array.length && (Character)array[i] != '\0'; ++i) {//strings are terminater with '0'
|
public int getTotalSize() {
|
||||||
result.append(array[i]);
|
return array.length;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
result.append('[');
|
@Override
|
||||||
for(int i = 0; i < array.length; ++i) {
|
public String toString() {
|
||||||
result.append(array[i].toString());
|
StringBuilder result = new StringBuilder();
|
||||||
if(i + 1 < array.length) {
|
if (array instanceof Character[]) {//in case of character array we convert it to String
|
||||||
result.append(',');
|
for (int i = 0; i < array.length && (Character) array[i] != '\0'; ++i) {//strings are terminater with '0'
|
||||||
}
|
result.append(array[i]);
|
||||||
}
|
}
|
||||||
result.append(']');
|
} else {
|
||||||
}
|
result.append('[');
|
||||||
return result.toString();
|
for (int i = 0; i < array.length; ++i) {
|
||||||
}
|
result.append(array[i].toString());
|
||||||
|
if (i + 1 < array.length) {
|
||||||
|
result.append(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.append(']');
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
}
|
}
|
@ -55,115 +55,115 @@ import com.jme3.scene.plugins.blender.helpers.ObjectHelper;
|
|||||||
* This class converts blender file blocks into jMonkeyEngine data structures.
|
* This class converts blender file blocks into jMonkeyEngine data structures.
|
||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class JmeConverter implements IBlenderConverter<Node, Camera, Light, Object, List<Geometry>, Material> {
|
public class JmeConverter implements BlenderConverter<Node, Camera, Light, Object, List<Geometry>, Material> {
|
||||||
private static final Logger LOGGER = Logger.getLogger(JmeConverter.class.getName());
|
|
||||||
|
|
||||||
private final DataRepository dataRepository;
|
private static final Logger LOGGER = Logger.getLogger(JmeConverter.class.getName());
|
||||||
|
private final DataRepository dataRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Creates the loader and checks if the given data is correct.
|
* Constructor. Creates the loader and checks if the given data is correct.
|
||||||
* @param dataRepository
|
* @param dataRepository
|
||||||
* the data repository; it should have the following field set: - asset manager - blender key - dna block
|
* the data repository; it should have the following field set: - asset manager - blender key - dna block
|
||||||
* data - blender input stream Otherwise IllegalArgumentException will be thrown.
|
* data - blender input stream Otherwise IllegalArgumentException will be thrown.
|
||||||
* @param featuresToLoad
|
* @param featuresToLoad
|
||||||
* bitwise flag describing what features are to be loaded
|
* bitwise flag describing what features are to be loaded
|
||||||
* @see FeaturesToLoad FeaturesToLoad
|
* @see FeaturesToLoad FeaturesToLoad
|
||||||
*/
|
*/
|
||||||
public JmeConverter(DataRepository dataRepository) {
|
public JmeConverter(DataRepository dataRepository) {
|
||||||
//validating the given data first
|
//validating the given data first
|
||||||
if(dataRepository.getAssetManager() == null) {
|
if (dataRepository.getAssetManager() == null) {
|
||||||
throw new IllegalArgumentException("Cannot find asset manager!");
|
throw new IllegalArgumentException("Cannot find asset manager!");
|
||||||
}
|
}
|
||||||
if(dataRepository.getBlenderKey() == null) {
|
if (dataRepository.getBlenderKey() == null) {
|
||||||
throw new IllegalArgumentException("Cannot find blender key!");
|
throw new IllegalArgumentException("Cannot find blender key!");
|
||||||
}
|
}
|
||||||
if(dataRepository.getDnaBlockData() == null) {
|
if (dataRepository.getDnaBlockData() == null) {
|
||||||
throw new IllegalArgumentException("Cannot find dna block!");
|
throw new IllegalArgumentException("Cannot find dna block!");
|
||||||
}
|
}
|
||||||
if(dataRepository.getInputStream() == null) {
|
if (dataRepository.getInputStream() == null) {
|
||||||
throw new IllegalArgumentException("Cannot find blender file stream!");
|
throw new IllegalArgumentException("Cannot find blender file stream!");
|
||||||
}
|
}
|
||||||
this.dataRepository = dataRepository;
|
this.dataRepository = dataRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node toScene(Structure structure) {//TODO: poprawny import sceny
|
public Node toScene(Structure structure) {//TODO: poprawny import sceny
|
||||||
if((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.SCENES) == 0) {
|
if ((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.SCENES) == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Structure id = (Structure)structure.getFieldValue("id");
|
Structure id = (Structure) structure.getFieldValue("id");
|
||||||
String sceneName = id.getFieldValue("name").toString();
|
String sceneName = id.getFieldValue("name").toString();
|
||||||
|
|
||||||
//veryfying layers to be loaded
|
//veryfying layers to be loaded
|
||||||
if(dataRepository.getBlenderKey().getLayersToLoad()<0) {
|
if (dataRepository.getBlenderKey().getLayersToLoad() < 0) {
|
||||||
int lay = ((Number)structure.getFieldValue("lay")).intValue();
|
int lay = ((Number) structure.getFieldValue("lay")).intValue();
|
||||||
dataRepository.getBlenderKey().setLayersToLoad(lay);//load only current layer
|
dataRepository.getBlenderKey().setLayersToLoad(lay);//load only current layer
|
||||||
}
|
}
|
||||||
return new Node(sceneName);
|
return new Node(sceneName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Camera toCamera(Structure structure) throws BlenderFileException {
|
public Camera toCamera(Structure structure) throws BlenderFileException {
|
||||||
if((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.CAMERAS) == 0) {
|
if ((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.CAMERAS) == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
CameraHelper cameraHelper = dataRepository.getHelper(CameraHelper.class);
|
CameraHelper cameraHelper = dataRepository.getHelper(CameraHelper.class);
|
||||||
return cameraHelper.toCamera(structure);
|
return cameraHelper.toCamera(structure);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Light toLight(Structure structure) throws BlenderFileException {
|
public Light toLight(Structure structure) throws BlenderFileException {
|
||||||
if((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.LIGHTS) == 0) {
|
if ((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.LIGHTS) == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
LightHelper lightHelper = dataRepository.getHelper(LightHelper.class);
|
LightHelper lightHelper = dataRepository.getHelper(LightHelper.class);
|
||||||
return lightHelper.toLight(structure, dataRepository);
|
return lightHelper.toLight(structure, dataRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object toObject(Structure structure) throws BlenderFileException {
|
public Object toObject(Structure structure) throws BlenderFileException {
|
||||||
int lay = ((Number)structure.getFieldValue("lay")).intValue();
|
int lay = ((Number) structure.getFieldValue("lay")).intValue();
|
||||||
if((lay & dataRepository.getBlenderKey().getLayersToLoad()) == 0 ||
|
if ((lay & dataRepository.getBlenderKey().getLayersToLoad()) == 0
|
||||||
(dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.OBJECTS) == 0) {
|
|| (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.OBJECTS) == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
|
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
|
||||||
return objectHelper.toObject(structure, dataRepository);
|
return objectHelper.toObject(structure, dataRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Geometry> toMesh(Structure structure) throws BlenderFileException {
|
public List<Geometry> toMesh(Structure structure) throws BlenderFileException {
|
||||||
MeshHelper meshHelper = dataRepository.getHelper(MeshHelper.class);
|
MeshHelper meshHelper = dataRepository.getHelper(MeshHelper.class);
|
||||||
return meshHelper.toMesh(structure, dataRepository);
|
return meshHelper.toMesh(structure, dataRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Material toMaterial(Structure structure) throws BlenderFileException {
|
public Material toMaterial(Structure structure) throws BlenderFileException {
|
||||||
if((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.MATERIALS) == 0) {
|
if ((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.MATERIALS) == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
|
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
|
||||||
return materialHelper.toMaterial(structure, dataRepository);
|
return materialHelper.toMaterial(structure, dataRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the data read from the WORLD file block. The block contains data that can be stored as
|
* This method returns the data read from the WORLD file block. The block contains data that can be stored as
|
||||||
* separate jme features and therefore cannot be returned as a single jME scene feature.
|
* separate jme features and therefore cannot be returned as a single jME scene feature.
|
||||||
* @param structure
|
* @param structure
|
||||||
* the structure with WORLD block data
|
* the structure with WORLD block data
|
||||||
* @return data read from the WORLD block that can be added to the scene
|
* @return data read from the WORLD block that can be added to the scene
|
||||||
*/
|
*/
|
||||||
public WorldData toWorldData(Structure structure) {
|
public WorldData toWorldData(Structure structure) {
|
||||||
WorldData result = new WorldData();
|
WorldData result = new WorldData();
|
||||||
|
|
||||||
//reading ambient light
|
//reading ambient light
|
||||||
AmbientLight ambientLight = new AmbientLight();
|
AmbientLight ambientLight = new AmbientLight();
|
||||||
float ambr = ((Number)structure.getFieldValue("ambr")).floatValue();
|
float ambr = ((Number) structure.getFieldValue("ambr")).floatValue();
|
||||||
float ambg = ((Number)structure.getFieldValue("ambg")).floatValue();
|
float ambg = ((Number) structure.getFieldValue("ambg")).floatValue();
|
||||||
float ambb = ((Number)structure.getFieldValue("ambb")).floatValue();
|
float ambb = ((Number) structure.getFieldValue("ambb")).floatValue();
|
||||||
ambientLight.setColor(new ColorRGBA(ambr, ambg, ambb, 0.0f));
|
ambientLight.setColor(new ColorRGBA(ambr, ambg, ambb, 0.0f));
|
||||||
result.setAmbientLight(ambientLight);
|
result.setAmbientLight(ambientLight);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,133 +43,134 @@ import com.jme3.scene.plugins.blender.exception.BlenderFileException;
|
|||||||
* @author Marcin Roguski
|
* @author Marcin Roguski
|
||||||
*/
|
*/
|
||||||
public class Pointer {
|
public class Pointer {
|
||||||
/** The data repository. */
|
|
||||||
private DataRepository dataRepository;
|
|
||||||
/** The level of the pointer. */
|
|
||||||
private int pointerLevel;
|
|
||||||
/** The address in file it points to. */
|
|
||||||
private long oldMemoryAddress;
|
|
||||||
/** This variable indicates if the field is a function pointer. */
|
|
||||||
public boolean function;
|
|
||||||
|
|
||||||
/**
|
/** The data repository. */
|
||||||
* Constructr. Stores the basic data about the pointer.
|
private DataRepository dataRepository;
|
||||||
* @param pointerLevel
|
/** The level of the pointer. */
|
||||||
* the level of the pointer
|
private int pointerLevel;
|
||||||
* @param function
|
/** The address in file it points to. */
|
||||||
* this variable indicates if the field is a function pointer
|
private long oldMemoryAddress;
|
||||||
* @param dataRepository
|
/** This variable indicates if the field is a function pointer. */
|
||||||
* the repository f data; used in fetching the value that the pointer points
|
public boolean function;
|
||||||
*/
|
|
||||||
public Pointer(int pointerLevel, boolean function, DataRepository dataRepository) {
|
|
||||||
this.pointerLevel = pointerLevel;
|
|
||||||
this.function = function;
|
|
||||||
this.dataRepository = dataRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method fills the pointer with its address value (it doesn't get the actual data yet. Use the 'fetch' method
|
* Constructr. Stores the basic data about the pointer.
|
||||||
* for this.
|
* @param pointerLevel
|
||||||
* @param inputStream
|
* the level of the pointer
|
||||||
* the stream we read the pointer value from
|
* @param function
|
||||||
*/
|
* this variable indicates if the field is a function pointer
|
||||||
public void fill(BlenderInputStream inputStream) {
|
* @param dataRepository
|
||||||
oldMemoryAddress = inputStream.readPointer();
|
* the repository f data; used in fetching the value that the pointer points
|
||||||
}
|
*/
|
||||||
|
public Pointer(int pointerLevel, boolean function, DataRepository dataRepository) {
|
||||||
|
this.pointerLevel = pointerLevel;
|
||||||
|
this.function = function;
|
||||||
|
this.dataRepository = dataRepository;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method fetches the data stored under the given address.
|
* This method fills the pointer with its address value (it doesn't get the actual data yet. Use the 'fetch' method
|
||||||
* @param inputStream
|
* for this.
|
||||||
* the stream we read data from
|
* @param inputStream
|
||||||
* @param dataIndices
|
* the stream we read the pointer value from
|
||||||
* the offset of the data in the table pointed by the pointer
|
*/
|
||||||
* @return the data read from the file
|
public void fill(BlenderInputStream inputStream) {
|
||||||
* @throws BlenderFileException
|
oldMemoryAddress = inputStream.readPointer();
|
||||||
* this exception is thrown when the blend file structure is somehow invalid or corrupted
|
}
|
||||||
*/
|
|
||||||
public List<Structure> fetchData(BlenderInputStream inputStream) throws BlenderFileException {
|
|
||||||
if(oldMemoryAddress == 0) {
|
|
||||||
throw new NullPointerException("The pointer points to nothing!");
|
|
||||||
}
|
|
||||||
List<Structure> structures = null;
|
|
||||||
FileBlockHeader dataFileBlock = dataRepository.getFileBlock(oldMemoryAddress);
|
|
||||||
if(pointerLevel > 1) {
|
|
||||||
int pointersAmount = dataFileBlock.getSize() / inputStream.getPointerSize() * dataFileBlock.getCount();
|
|
||||||
for(int i = 0; i < pointersAmount; ++i) {
|
|
||||||
inputStream.setPosition(dataFileBlock.getBlockPosition() + inputStream.getPointerSize() * i);
|
|
||||||
long oldMemoryAddress = inputStream.readPointer();
|
|
||||||
if(oldMemoryAddress != 0L) {
|
|
||||||
Pointer p = new Pointer(pointerLevel - 1, this.function, dataRepository);
|
|
||||||
p.oldMemoryAddress = oldMemoryAddress;
|
|
||||||
if(structures == null) {
|
|
||||||
structures = p.fetchData(inputStream);
|
|
||||||
} else {
|
|
||||||
structures.addAll(p.fetchData(inputStream));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
inputStream.setPosition(dataFileBlock.getBlockPosition());
|
|
||||||
structures = new ArrayList<Structure>(dataFileBlock.getCount());
|
|
||||||
for(int i = 0; i < dataFileBlock.getCount(); ++i) {
|
|
||||||
Structure structure = dataRepository.getDnaBlockData().getStructure(dataFileBlock.getSdnaIndex());
|
|
||||||
structure.fill(inputStream);
|
|
||||||
structures.add(structure);
|
|
||||||
}
|
|
||||||
return structures;
|
|
||||||
}
|
|
||||||
return structures;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method indicates if this pointer points to a function.
|
* This method fetches the data stored under the given address.
|
||||||
* @return <b>true</b> if this is a function pointer and <b>false</b> otherwise
|
* @param inputStream
|
||||||
*/
|
* the stream we read data from
|
||||||
public boolean isFunction() {
|
* @param dataIndices
|
||||||
return function;
|
* the offset of the data in the table pointed by the pointer
|
||||||
}
|
* @return the data read from the file
|
||||||
|
* @throws BlenderFileException
|
||||||
|
* this exception is thrown when the blend file structure is somehow invalid or corrupted
|
||||||
|
*/
|
||||||
|
public List<Structure> fetchData(BlenderInputStream inputStream) throws BlenderFileException {
|
||||||
|
if (oldMemoryAddress == 0) {
|
||||||
|
throw new NullPointerException("The pointer points to nothing!");
|
||||||
|
}
|
||||||
|
List<Structure> structures = null;
|
||||||
|
FileBlockHeader dataFileBlock = dataRepository.getFileBlock(oldMemoryAddress);
|
||||||
|
if (pointerLevel > 1) {
|
||||||
|
int pointersAmount = dataFileBlock.getSize() / inputStream.getPointerSize() * dataFileBlock.getCount();
|
||||||
|
for (int i = 0; i < pointersAmount; ++i) {
|
||||||
|
inputStream.setPosition(dataFileBlock.getBlockPosition() + inputStream.getPointerSize() * i);
|
||||||
|
long oldMemoryAddress = inputStream.readPointer();
|
||||||
|
if (oldMemoryAddress != 0L) {
|
||||||
|
Pointer p = new Pointer(pointerLevel - 1, this.function, dataRepository);
|
||||||
|
p.oldMemoryAddress = oldMemoryAddress;
|
||||||
|
if (structures == null) {
|
||||||
|
structures = p.fetchData(inputStream);
|
||||||
|
} else {
|
||||||
|
structures.addAll(p.fetchData(inputStream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
inputStream.setPosition(dataFileBlock.getBlockPosition());
|
||||||
|
structures = new ArrayList<Structure>(dataFileBlock.getCount());
|
||||||
|
for (int i = 0; i < dataFileBlock.getCount(); ++i) {
|
||||||
|
Structure structure = dataRepository.getDnaBlockData().getStructure(dataFileBlock.getSdnaIndex());
|
||||||
|
structure.fill(inputStream);
|
||||||
|
structures.add(structure);
|
||||||
|
}
|
||||||
|
return structures;
|
||||||
|
}
|
||||||
|
return structures;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method indicates if this is a null-pointer or not.
|
* This method indicates if this pointer points to a function.
|
||||||
* @return <b>true</b> if the pointer is null and <b>false</b> otherwise
|
* @return <b>true</b> if this is a function pointer and <b>false</b> otherwise
|
||||||
*/
|
*/
|
||||||
public boolean isNull() {
|
public boolean isFunction() {
|
||||||
return oldMemoryAddress == 0;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the old memory address of the structure pointed by the pointer.
|
* This method indicates if this is a null-pointer or not.
|
||||||
* @return the old memory address of the structure pointed by the pointer
|
* @return <b>true</b> if the pointer is null and <b>false</b> otherwise
|
||||||
*/
|
*/
|
||||||
public long getOldMemoryAddress() {
|
public boolean isNull() {
|
||||||
return oldMemoryAddress;
|
return oldMemoryAddress == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public String toString() {
|
* This method returns the old memory address of the structure pointed by the pointer.
|
||||||
return oldMemoryAddress == 0 ? "{$null$}" : "{$" + oldMemoryAddress + "$}";
|
* @return the old memory address of the structure pointed by the pointer
|
||||||
}
|
*/
|
||||||
|
public long getOldMemoryAddress() {
|
||||||
|
return oldMemoryAddress;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public String toString() {
|
||||||
return 31 + (int)(oldMemoryAddress ^ oldMemoryAddress >>> 32);
|
return oldMemoryAddress == 0 ? "{$null$}" : "{$" + oldMemoryAddress + "$}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public int hashCode() {
|
||||||
if(this == obj) {
|
return 31 + (int) (oldMemoryAddress ^ oldMemoryAddress >>> 32);
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
if(obj == null) {
|
@Override
|
||||||
return false;
|
public boolean equals(Object obj) {
|
||||||
}
|
if (this == obj) {
|
||||||
if(this.getClass() != obj.getClass()) {
|
return true;
|
||||||
return false;
|
}
|
||||||
}
|
if (obj == null) {
|
||||||
Pointer other = (Pointer)obj;
|
return false;
|
||||||
if(oldMemoryAddress != other.oldMemoryAddress) {
|
}
|
||||||
return false;
|
if (this.getClass() != obj.getClass()) {
|
||||||
}
|
return false;
|
||||||
return true;
|
}
|
||||||
}
|
Pointer other = (Pointer) obj;
|
||||||
|
if (oldMemoryAddress != other.oldMemoryAddress) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,7 +347,6 @@ public final class Bone implements Savable {
|
|||||||
/**
|
/**
|
||||||
* Set user transform.
|
* Set user transform.
|
||||||
* Combine the given transforms to bone's current transforms
|
* Combine the given transforms to bone's current transforms
|
||||||
* @see setUserControl
|
|
||||||
*/
|
*/
|
||||||
public void setUserTransforms(Vector3f translation, Quaternion rotation, Vector3f scale) {
|
public void setUserTransforms(Vector3f translation, Quaternion rotation, Vector3f scale) {
|
||||||
if (!userControl) {
|
if (!userControl) {
|
||||||
@ -378,10 +377,9 @@ public final class Bone implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns teh local transform of this bone combined with the given position and rotation
|
* Returns the local transform of this bone combined with the given position and rotation
|
||||||
* @param position a position
|
* @param position a position
|
||||||
* @param rotation a rotation
|
* @param rotation a rotation
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public Transform getCombinedTransform(Vector3f position, Quaternion rotation){
|
public Transform getCombinedTransform(Vector3f position, Quaternion rotation){
|
||||||
rotation.mult(localPos, tmpTransform.getTranslation()).addLocal(position);
|
rotation.mult(localPos, tmpTransform.getTranslation()).addLocal(position);
|
||||||
|
@ -234,13 +234,11 @@ public abstract class CompactArray<T> {
|
|||||||
* deserialize object
|
* deserialize object
|
||||||
* @param compactIndex compacted object index
|
* @param compactIndex compacted object index
|
||||||
* @param store
|
* @param store
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
protected abstract T deserialize(int compactIndex, T store);
|
protected abstract T deserialize(int compactIndex, T store);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* serialized size of one object element
|
* serialized size of one object element
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
protected abstract int getTupleSize();
|
protected abstract int getTupleSize();
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
The <code>com.jme3.application</code> provides a toolset for jME3 applications
|
The <code>com.jme3.application</code> provides a toolset for jME3 applications
|
||||||
to interact with various components of the engine. Typically, the
|
to interact with various components of the engine. Typically, the
|
||||||
{@link com.jme3.app.Application} class will be extended and the update() method
|
{@link com.jme3.app.Application} class will be extended and the update() method
|
||||||
implemented to provide functionality for the main loop. <br/>
|
implemented to provide functionality for the main loop. <br>
|
||||||
<p>
|
<p>
|
||||||
An <code>Application</code> will typically provide the following services:
|
An <code>Application</code> will typically provide the following services:
|
||||||
<ul>
|
<ul>
|
||||||
@ -37,42 +37,42 @@ An <code>Application</code> will typically provide the following services:
|
|||||||
|
|
||||||
<h3>Usage</h3>
|
<h3>Usage</h3>
|
||||||
|
|
||||||
An example use of the Application class is as follows<br/>
|
An example use of the Application class is as follows<br>
|
||||||
<br/>
|
<br>
|
||||||
|
|
||||||
<code>
|
<code>
|
||||||
public class ExampleUse extends Application {<br/>
|
public class ExampleUse extends Application {<br>
|
||||||
<br/>
|
<br>
|
||||||
private Node rootNode = new Node("Root Node");<br/>
|
private Node rootNode = new Node("Root Node");<br>
|
||||||
<br/>
|
<br>
|
||||||
public static void main(String[] args){<br/>
|
public static void main(String[] args){<br>
|
||||||
ExampleUse app = new ExampleUse();<br/>
|
ExampleUse app = new ExampleUse();<br>
|
||||||
app.start();<br/>
|
app.start();<br>
|
||||||
}<br/>
|
}<br>
|
||||||
<br/>
|
<br>
|
||||||
@Override<br/>
|
@Override<br>
|
||||||
public void initialize(){<br/>
|
public void initialize(){<br>
|
||||||
super.initialize();<br/>
|
super.initialize();<br>
|
||||||
<br/>
|
<br>
|
||||||
// attach root node to viewport<br/>
|
// attach root node to viewport<br>
|
||||||
viewPort.attachScene(rootNode);<br/>
|
viewPort.attachScene(rootNode);<br>
|
||||||
}<br/>
|
}<br>
|
||||||
<br/>
|
<br>
|
||||||
@Override<br/>
|
@Override<br>
|
||||||
public void update(){<br/>
|
public void update(){<br>
|
||||||
super.update();<br/>
|
super.update();<br>
|
||||||
<br/>
|
<br>
|
||||||
float tpf = timer.getTimePerFrame();<br/>
|
float tpf = timer.getTimePerFrame();<br>
|
||||||
<br/>
|
<br>
|
||||||
// update rootNode<br/>
|
// update rootNode<br>
|
||||||
rootNode.updateLogicalState(tpf);<br/>
|
rootNode.updateLogicalState(tpf);<br>
|
||||||
rootNode.updateGeometricState();<br/>
|
rootNode.updateGeometricState();<br>
|
||||||
<br/>
|
<br>
|
||||||
// render the viewports<br/>
|
// render the viewports<br>
|
||||||
renderManager.render(tpf);<br/>
|
renderManager.render(tpf);<br>
|
||||||
}<br/>
|
}<br>
|
||||||
}<br/>
|
}<br>
|
||||||
<br/>
|
<br>
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
@ -173,7 +173,6 @@ public class AppStateManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls render for all attached states, do not call directly.
|
* Calls render for all attached states, do not call directly.
|
||||||
* @param rm The RenderManager
|
|
||||||
*/
|
*/
|
||||||
public void postRender(){
|
public void postRender(){
|
||||||
AppState[] array = getArray();
|
AppState[] array = getArray();
|
||||||
|
@ -54,7 +54,7 @@ public interface AssetLocator {
|
|||||||
*
|
*
|
||||||
* @param manager
|
* @param manager
|
||||||
* @param key
|
* @param key
|
||||||
* @return
|
* @return The {@link AssetInfo} that was located, or null if not found.
|
||||||
*/
|
*/
|
||||||
public AssetInfo locate(AssetManager manager, AssetKey key);
|
public AssetInfo locate(AssetManager manager, AssetKey key);
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ public interface AssetManager {
|
|||||||
* TGA and DDS.
|
* TGA and DDS.
|
||||||
*
|
*
|
||||||
* @param name The name of the texture to load.
|
* @param name The name of the texture to load.
|
||||||
* @return
|
* @return The texture that was loaded
|
||||||
*
|
*
|
||||||
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
||||||
*/
|
*/
|
||||||
@ -168,7 +168,7 @@ public interface AssetManager {
|
|||||||
/**
|
/**
|
||||||
* Load audio file, supported types are WAV or OGG.
|
* Load audio file, supported types are WAV or OGG.
|
||||||
* @param key
|
* @param key
|
||||||
* @return
|
* @return The audio data loaded
|
||||||
*
|
*
|
||||||
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
||||||
*/
|
*/
|
||||||
@ -178,7 +178,7 @@ public interface AssetManager {
|
|||||||
* Load audio file, supported types are WAV or OGG.
|
* Load audio file, supported types are WAV or OGG.
|
||||||
* The file is loaded without stream-mode.
|
* The file is loaded without stream-mode.
|
||||||
* @param name
|
* @param name
|
||||||
* @return
|
* @return The audio data loaded
|
||||||
*
|
*
|
||||||
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
||||||
*/
|
*/
|
||||||
@ -188,7 +188,7 @@ public interface AssetManager {
|
|||||||
* Loads a named model. Models can be jME3 object files (J3O) or
|
* Loads a named model. Models can be jME3 object files (J3O) or
|
||||||
* OgreXML/OBJ files.
|
* OgreXML/OBJ files.
|
||||||
* @param key
|
* @param key
|
||||||
* @return
|
* @return The model that was loaded
|
||||||
*
|
*
|
||||||
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
||||||
*/
|
*/
|
||||||
@ -198,7 +198,7 @@ public interface AssetManager {
|
|||||||
* Loads a named model. Models can be jME3 object files (J3O) or
|
* Loads a named model. Models can be jME3 object files (J3O) or
|
||||||
* OgreXML/OBJ files.
|
* OgreXML/OBJ files.
|
||||||
* @param name
|
* @param name
|
||||||
* @return
|
* @return The model that was loaded
|
||||||
*
|
*
|
||||||
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
||||||
*/
|
*/
|
||||||
@ -207,7 +207,7 @@ public interface AssetManager {
|
|||||||
/**
|
/**
|
||||||
* Load a material (J3M) file.
|
* Load a material (J3M) file.
|
||||||
* @param name
|
* @param name
|
||||||
* @return
|
* @return The material that was loaded
|
||||||
*
|
*
|
||||||
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
||||||
*/
|
*/
|
||||||
@ -225,7 +225,7 @@ public interface AssetManager {
|
|||||||
* and are with the extension "fnt".
|
* and are with the extension "fnt".
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name
|
||||||
* @return
|
* @return The font loaded
|
||||||
*
|
*
|
||||||
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
* @see AssetManager#loadAsset(com.jme3.asset.AssetKey)
|
||||||
*/
|
*/
|
||||||
|
@ -70,7 +70,7 @@ public class TextureKey extends AssetKey<Texture> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable smart caching for textures
|
* Enable smart caching for textures
|
||||||
* @return
|
* @return true to enable smart cache
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean useSmartCache(){
|
public boolean useSmartCache(){
|
||||||
|
@ -48,7 +48,7 @@ public interface AudioRenderer {
|
|||||||
/**
|
/**
|
||||||
* Sets the environment, used for reverb effects.
|
* Sets the environment, used for reverb effects.
|
||||||
*
|
*
|
||||||
* @see PointAudioSource#setReverbEnabled(boolean)
|
* @see AudioNode#setReverbEnabled(boolean)
|
||||||
* @param env The environment to set.
|
* @param env The environment to set.
|
||||||
*/
|
*/
|
||||||
public void setEnvironment(Environment env);
|
public void setEnvironment(Environment env);
|
||||||
|
@ -259,12 +259,8 @@ public class BoundingBox extends BoundingVolume {
|
|||||||
* <code>transform</code> modifies the center of the box to reflect the
|
* <code>transform</code> modifies the center of the box to reflect the
|
||||||
* change made via a rotation, translation and scale.
|
* change made via a rotation, translation and scale.
|
||||||
*
|
*
|
||||||
* @param rotate
|
* @param trans
|
||||||
* the rotation change.
|
* the transform to apply
|
||||||
* @param translate
|
|
||||||
* the translation change.
|
|
||||||
* @param scale
|
|
||||||
* the size change.
|
|
||||||
* @param store
|
* @param store
|
||||||
* box to store result in
|
* box to store result in
|
||||||
*/
|
*/
|
||||||
@ -570,7 +566,7 @@ public class BoundingBox extends BoundingVolume {
|
|||||||
* intersects determines if this Bounding Box intersects with another given
|
* intersects determines if this Bounding Box intersects with another given
|
||||||
* bounding volume. If so, true is returned, otherwise, false is returned.
|
* bounding volume. If so, true is returned, otherwise, false is returned.
|
||||||
*
|
*
|
||||||
* @see com.jme.bounding.BoundingVolume#intersects(com.jme.bounding.BoundingVolume)
|
* @see BoundingVolume#intersects(com.jme3.bounding.BoundingVolume)
|
||||||
*/
|
*/
|
||||||
public boolean intersects(BoundingVolume bv) {
|
public boolean intersects(BoundingVolume bv) {
|
||||||
return bv.intersectsBoundingBox(this);
|
return bv.intersectsBoundingBox(this);
|
||||||
@ -579,7 +575,7 @@ public class BoundingBox extends BoundingVolume {
|
|||||||
/**
|
/**
|
||||||
* determines if this bounding box intersects a given bounding sphere.
|
* determines if this bounding box intersects a given bounding sphere.
|
||||||
*
|
*
|
||||||
* @see com.jme.bounding.BoundingVolume#intersectsSphere(com.jme.bounding.BoundingSphere)
|
* @see BoundingVolume#intersectsSphere(com.jme3.bounding.BoundingSphere)
|
||||||
*/
|
*/
|
||||||
public boolean intersectsSphere(BoundingSphere bs) {
|
public boolean intersectsSphere(BoundingSphere bs) {
|
||||||
assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bs.center);
|
assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bs.center);
|
||||||
@ -600,7 +596,7 @@ public class BoundingBox extends BoundingVolume {
|
|||||||
* two boxes intersect in any way, true is returned. Otherwise, false is
|
* two boxes intersect in any way, true is returned. Otherwise, false is
|
||||||
* returned.
|
* returned.
|
||||||
*
|
*
|
||||||
* @see com.jme.bounding.BoundingVolume#intersectsBoundingBox(com.jme.bounding.BoundingBox)
|
* @see BoundingVolume#intersectsBoundingBox(com.jme3.bounding.BoundingBox)
|
||||||
*/
|
*/
|
||||||
public boolean intersectsBoundingBox(BoundingBox bb) {
|
public boolean intersectsBoundingBox(BoundingBox bb) {
|
||||||
assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bb.center);
|
assert Vector3f.isValidVector(center) && Vector3f.isValidVector(bb.center);
|
||||||
@ -632,7 +628,7 @@ public class BoundingBox extends BoundingVolume {
|
|||||||
* determines if this bounding box intersects with a given ray object. If an
|
* determines if this bounding box intersects with a given ray object. If an
|
||||||
* intersection has occurred, true is returned, otherwise false is returned.
|
* intersection has occurred, true is returned, otherwise false is returned.
|
||||||
*
|
*
|
||||||
* @see com.jme.bounding.BoundingVolume#intersects(com.jme.math.Ray)
|
* @see BoundingVolume#intersects(com.jme3.math.Ray)
|
||||||
*/
|
*/
|
||||||
public boolean intersects(Ray ray) {
|
public boolean intersects(Ray ray) {
|
||||||
assert Vector3f.isValidVector(center);
|
assert Vector3f.isValidVector(center);
|
||||||
@ -766,10 +762,11 @@ public class BoundingBox extends BoundingVolume {
|
|||||||
/**
|
/**
|
||||||
* C code ported from http://www.cs.lth.se/home/Tomas_Akenine_Moller/code/tribox3.txt
|
* C code ported from http://www.cs.lth.se/home/Tomas_Akenine_Moller/code/tribox3.txt
|
||||||
*
|
*
|
||||||
* @param v1
|
* @param v1 The first point in the triangle
|
||||||
* @param v2
|
* @param v2 The second point in the triangle
|
||||||
* @param v3
|
* @param v3 The third point in the triangle
|
||||||
* @return
|
* @return True if the bounding box intersects the triangle, false
|
||||||
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean intersects(Vector3f v1, Vector3f v2, Vector3f v3){
|
public boolean intersects(Vector3f v1, Vector3f v2, Vector3f v3){
|
||||||
return Intersection.intersect(this, v1, v2, v3);
|
return Intersection.intersect(this, v1, v2, v3);
|
||||||
|
@ -387,12 +387,8 @@ public class BoundingSphere extends BoundingVolume {
|
|||||||
* <code>transform</code> modifies the center of the sphere to reflect the
|
* <code>transform</code> modifies the center of the sphere to reflect the
|
||||||
* change made via a rotation, translation and scale.
|
* change made via a rotation, translation and scale.
|
||||||
*
|
*
|
||||||
* @param rotate
|
* @param trans
|
||||||
* the rotation change.
|
* the transform to apply
|
||||||
* @param translate
|
|
||||||
* the translation change.
|
|
||||||
* @param scale
|
|
||||||
* the size change.
|
|
||||||
* @param store
|
* @param store
|
||||||
* sphere to store result in
|
* sphere to store result in
|
||||||
* @return BoundingVolume
|
* @return BoundingVolume
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
package com.jme3.input.controls;
|
package com.jme3.input.controls;
|
||||||
|
|
||||||
|
import com.jme3.input.MouseInput;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A <code>MouseButtonTrigger</code> is used as a mapping to receive events
|
* A <code>MouseButtonTrigger</code> is used as a mapping to receive events
|
||||||
* from mouse buttons. It is generally expected for a mouse to have at least
|
* from mouse buttons. It is generally expected for a mouse to have at least
|
||||||
|
@ -160,7 +160,8 @@ public abstract class Light implements Savable, Cloneable {
|
|||||||
this.color.set(color);
|
this.color.set(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
|
/*
|
||||||
* Returns true if the light is enabled
|
* Returns true if the light is enabled
|
||||||
*
|
*
|
||||||
* @return true if the light is enabled
|
* @return true if the light is enabled
|
||||||
|
@ -193,8 +193,7 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clones this material. The result
|
* Clones this material. The result is returned.
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Material clone() {
|
public Material clone() {
|
||||||
@ -219,10 +218,27 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently active technique.
|
||||||
|
* <p>
|
||||||
|
* The technique is selected automatically by the {@link RenderManager}
|
||||||
|
* based on system capabilities. Users may select their own
|
||||||
|
* technique by using
|
||||||
|
* {@link #selectTechnique(java.lang.String, com.jme3.renderer.RenderManager) }.
|
||||||
|
*
|
||||||
|
* @return the currently active technique.
|
||||||
|
*
|
||||||
|
* @see #selectTechnique(java.lang.String, com.jme3.renderer.RenderManager)
|
||||||
|
*/
|
||||||
public Technique getActiveTechnique() {
|
public Technique getActiveTechnique() {
|
||||||
return technique;
|
return technique;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the transparent value marker is set on this material.
|
||||||
|
* @return True if the transparent value marker is set on this material.
|
||||||
|
* @see #setTransparent(boolean)
|
||||||
|
*/
|
||||||
public boolean isTransparent() {
|
public boolean isTransparent() {
|
||||||
return transparent;
|
return transparent;
|
||||||
}
|
}
|
||||||
@ -296,6 +312,13 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the parameter set on this material with the given name,
|
||||||
|
* returns <code>null</code> if the parameter is not set.
|
||||||
|
*
|
||||||
|
* @param name The parameter name to look up.
|
||||||
|
* @return The MatParam if set, or null if not set.
|
||||||
|
*/
|
||||||
public MatParam getParam(String name) {
|
public MatParam getParam(String name) {
|
||||||
MatParam param = paramValues.get(name);
|
MatParam param = paramValues.get(name);
|
||||||
if (param instanceof MatParam) {
|
if (param instanceof MatParam) {
|
||||||
@ -304,6 +327,13 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the texture parameter set on this material with the given name,
|
||||||
|
* returns <code>null</code> if the parameter is not set.
|
||||||
|
*
|
||||||
|
* @param name The parameter name to look up.
|
||||||
|
* @return The MatParamTexture if set, or null if not set.
|
||||||
|
*/
|
||||||
public MatParamTexture getTextureParam(String name) {
|
public MatParamTexture getTextureParam(String name) {
|
||||||
MatParam param = paramValues.get(name);
|
MatParam param = paramValues.get(name);
|
||||||
if (param instanceof MatParamTexture) {
|
if (param instanceof MatParamTexture) {
|
||||||
@ -312,6 +342,13 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a collection of all parameters set on this material.
|
||||||
|
*
|
||||||
|
* @return a collection of all parameters set on this material.
|
||||||
|
*
|
||||||
|
* @see #setParam(java.lang.String, com.jme3.shader.VarType, java.lang.Object)
|
||||||
|
*/
|
||||||
public Collection<MatParam> getParams() {
|
public Collection<MatParam> getParams() {
|
||||||
return paramValues.values();
|
return paramValues.values();
|
||||||
}
|
}
|
||||||
@ -342,10 +379,11 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass a parameter to the material shader
|
* Pass a parameter to the material shader.
|
||||||
|
*
|
||||||
* @param name the name of the parameter defined in the material definition (j3md)
|
* @param name the name of the parameter defined in the material definition (j3md)
|
||||||
* @param type the type of the parameter @see com.jme3.shaderVarType
|
* @param type the type of the parameter {@link VarType}
|
||||||
* @param value the value of the param
|
* @param value the value of the parameter
|
||||||
*/
|
*/
|
||||||
public void setParam(String name, VarType type, Object value) {
|
public void setParam(String name, VarType type, Object value) {
|
||||||
name = checkSetParam(type, name);
|
name = checkSetParam(type, name);
|
||||||
@ -363,7 +401,7 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear a parameter from this material. The param must exist
|
* Clear a parameter from this material. The parameter must exist
|
||||||
* @param name the name of the parameter to clear
|
* @param name the name of the parameter to clear
|
||||||
*/
|
*/
|
||||||
public void clearParam(String name) {
|
public void clearParam(String name) {
|
||||||
@ -416,9 +454,18 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
sortingId = -1;
|
sortingId = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a texture parameter.
|
||||||
|
*
|
||||||
|
* @param name The name of the parameter
|
||||||
|
* @param type The variable type {@link VarType}
|
||||||
|
* @param value The texture value of the parameter.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException is value is null
|
||||||
|
*/
|
||||||
public void setTextureParam(String name, VarType type, Texture value) {
|
public void setTextureParam(String name, VarType type, Texture value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new NullPointerException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
name = checkSetParam(type, name);
|
name = checkSetParam(type, name);
|
||||||
@ -438,8 +485,10 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass a texture to the material shader
|
* Pass a texture to the material shader.
|
||||||
* @param name the name of the texture defined in the material definition (j3md) (for example Texture for Lighting.j3md)
|
*
|
||||||
|
* @param name the name of the texture defined in the material definition
|
||||||
|
* (j3md) (for example Texture for Lighting.j3md)
|
||||||
* @param value the Texture object previously loaded by the asset manager
|
* @param value the Texture object previously loaded by the asset manager
|
||||||
*/
|
*/
|
||||||
public void setTexture(String name, Texture value) {
|
public void setTexture(String name, Texture value) {
|
||||||
@ -471,7 +520,8 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass a Matrix4f to the material shader
|
* Pass a Matrix4f to the material shader.
|
||||||
|
*
|
||||||
* @param name the name of the matrix defined in the material definition (j3md)
|
* @param name the name of the matrix defined in the material definition (j3md)
|
||||||
* @param value the Matrix4f object
|
* @param value the Matrix4f object
|
||||||
*/
|
*/
|
||||||
@ -480,7 +530,8 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass a boolean to the material shader
|
* Pass a boolean to the material shader.
|
||||||
|
*
|
||||||
* @param name the name of the boolean defined in the material definition (j3md)
|
* @param name the name of the boolean defined in the material definition (j3md)
|
||||||
* @param value the boolean value
|
* @param value the boolean value
|
||||||
*/
|
*/
|
||||||
@ -489,7 +540,8 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass a float to the material shader
|
* Pass a float to the material shader.
|
||||||
|
*
|
||||||
* @param name the name of the float defined in the material definition (j3md)
|
* @param name the name of the float defined in the material definition (j3md)
|
||||||
* @param value the float value
|
* @param value the float value
|
||||||
*/
|
*/
|
||||||
@ -498,7 +550,8 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass an int to the material shader
|
* Pass an int to the material shader.
|
||||||
|
*
|
||||||
* @param name the name of the int defined in the material definition (j3md)
|
* @param name the name of the int defined in the material definition (j3md)
|
||||||
* @param value the int value
|
* @param value the int value
|
||||||
*/
|
*/
|
||||||
@ -507,7 +560,8 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass a Color to the material shader
|
* Pass a Color to the material shader.
|
||||||
|
*
|
||||||
* @param name the name of the color defined in the material definition (j3md)
|
* @param name the name of the color defined in the material definition (j3md)
|
||||||
* @param value the ColorRGBA value
|
* @param value the ColorRGBA value
|
||||||
*/
|
*/
|
||||||
@ -516,7 +570,8 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass a Vector2f to the material shader
|
* Pass a Vector2f to the material shader.
|
||||||
|
*
|
||||||
* @param name the name of the Vector2f defined in the material definition (j3md)
|
* @param name the name of the Vector2f defined in the material definition (j3md)
|
||||||
* @param value the Vector2f value
|
* @param value the Vector2f value
|
||||||
*/
|
*/
|
||||||
@ -525,7 +580,8 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass a Vector3f to the material shader
|
* Pass a Vector3f to the material shader.
|
||||||
|
*
|
||||||
* @param name the name of the Vector3f defined in the material definition (j3md)
|
* @param name the name of the Vector3f defined in the material definition (j3md)
|
||||||
* @param value the Vector3f value
|
* @param value the Vector3f value
|
||||||
*/
|
*/
|
||||||
@ -534,7 +590,8 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass a Vector4f to the material shader
|
* Pass a Vector4f to the material shader.
|
||||||
|
*
|
||||||
* @param name the name of the Vector4f defined in the material definition (j3md)
|
* @param name the name of the Vector4f defined in the material definition (j3md)
|
||||||
* @param value the Vector4f value
|
* @param value the Vector4f value
|
||||||
*/
|
*/
|
||||||
@ -567,9 +624,6 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
* // or the direction of the light (for directional lights).<br/>
|
* // or the direction of the light (for directional lights).<br/>
|
||||||
* // g_LightPosition.w is the inverse radius (1/r) of the light (for attenuation) <br/>
|
* // g_LightPosition.w is the inverse radius (1/r) of the light (for attenuation) <br/>
|
||||||
* </p>
|
* </p>
|
||||||
*
|
|
||||||
* @param shader
|
|
||||||
* @param lightList
|
|
||||||
*/
|
*/
|
||||||
protected void updateLightListUniforms(Shader shader, Geometry g, int numLights) {
|
protected void updateLightListUniforms(Shader shader, Geometry g, int numLights) {
|
||||||
if (numLights == 0){ // this shader does not do lighting, ignore.
|
if (numLights == 0){ // this shader does not do lighting, ignore.
|
||||||
@ -719,6 +773,29 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select the technique to use for rendering this material.
|
||||||
|
* <p>
|
||||||
|
* If <code>name</code> is "Default", then one of the
|
||||||
|
* {@link MaterialDef#getDefaultTechniques() default techniques}
|
||||||
|
* on the material will be selected. Otherwise, the named technique
|
||||||
|
* will be found in the material definition.
|
||||||
|
* <p>
|
||||||
|
* Any candidate technique for selection (either default or named)
|
||||||
|
* must be verified to be compatible with the system, for that, the
|
||||||
|
* <code>renderManager</code> is queried for capabilities.
|
||||||
|
*
|
||||||
|
* @param name The name of the technique to select, pass "Default" to
|
||||||
|
* select one of the default techniques.
|
||||||
|
* @param renderManager The {@link RenderManager render manager}
|
||||||
|
* to query for capabilities.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException If "Default" is passed and no default
|
||||||
|
* techniques are available on the material definition, or if a name
|
||||||
|
* is passed but there's no technique by that name.
|
||||||
|
* @throws UnsupportedOperationException If no candidate technique supports
|
||||||
|
* the system capabilities.
|
||||||
|
*/
|
||||||
public void selectTechnique(String name, RenderManager renderManager) {
|
public void selectTechnique(String name, RenderManager renderManager) {
|
||||||
// check if already created
|
// check if already created
|
||||||
Technique tech = techniques.get(name);
|
Technique tech = techniques.get(name);
|
||||||
@ -730,7 +807,7 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
if (name.equals("Default")) {
|
if (name.equals("Default")) {
|
||||||
List<TechniqueDef> techDefs = def.getDefaultTechniques();
|
List<TechniqueDef> techDefs = def.getDefaultTechniques();
|
||||||
if (techDefs == null || techDefs.isEmpty()) {
|
if (techDefs == null || techDefs.isEmpty()) {
|
||||||
throw new IllegalStateException("No default techniques are available on material '" + def.getName() + "'");
|
throw new IllegalArgumentException("No default techniques are available on material '" + def.getName() + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TechniqueDef lastTech = null;
|
TechniqueDef lastTech = null;
|
||||||
@ -794,8 +871,13 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Pre-load" the material, including textures and shaders, to the
|
* Preloads this material for the given render manager.
|
||||||
* renderer.
|
* <p>
|
||||||
|
* Preloading the material can ensure that when the material is first
|
||||||
|
* used for rendering, there won't be any delay since the material has
|
||||||
|
* been already been setup for rendering.
|
||||||
|
*
|
||||||
|
* @param rm The render manager to preload for
|
||||||
*/
|
*/
|
||||||
public void preload(RenderManager rm) {
|
public void preload(RenderManager rm) {
|
||||||
autoSelectTechnique(rm);
|
autoSelectTechnique(rm);
|
||||||
@ -844,9 +926,11 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should be called after selectTechnique()
|
* Called by {@link RenderManager} to render the geometry by
|
||||||
* @param geom
|
* using this material.
|
||||||
* @param r
|
*
|
||||||
|
* @param geom The geometry to render
|
||||||
|
* @param rm The render manager requesting the rendering
|
||||||
*/
|
*/
|
||||||
public void render(Geometry geom, RenderManager rm) {
|
public void render(Geometry geom, RenderManager rm) {
|
||||||
autoSelectTechnique(rm);
|
autoSelectTechnique(rm);
|
||||||
|
@ -176,6 +176,15 @@ public class Technique implements Savable {
|
|||||||
updateUniformParam(paramName, type, value, false);
|
updateUniformParam(paramName, type, value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the technique must be reloaded.
|
||||||
|
* <p>
|
||||||
|
* If a technique needs to reload, then the {@link Material} should
|
||||||
|
* call {@link #makeCurrent(com.jme3.asset.AssetManager) } on this
|
||||||
|
* technique.
|
||||||
|
*
|
||||||
|
* @return true if the technique must be reloaded.
|
||||||
|
*/
|
||||||
public boolean isNeedReload() {
|
public boolean isNeedReload() {
|
||||||
return needReload;
|
return needReload;
|
||||||
}
|
}
|
||||||
@ -183,8 +192,10 @@ public class Technique implements Savable {
|
|||||||
/**
|
/**
|
||||||
* Prepares the technique for use by loading the shader and setting
|
* Prepares the technique for use by loading the shader and setting
|
||||||
* the proper defines based on material parameters.
|
* the proper defines based on material parameters.
|
||||||
|
*
|
||||||
|
* @param assetManager The asset manager to use for loading shaders.
|
||||||
*/
|
*/
|
||||||
public void makeCurrent(AssetManager manager) {
|
public void makeCurrent(AssetManager assetManager) {
|
||||||
// check if reload is needed..
|
// check if reload is needed..
|
||||||
if (def.isUsingShaders()) {
|
if (def.isUsingShaders()) {
|
||||||
DefineList newDefines = new DefineList();
|
DefineList newDefines = new DefineList();
|
||||||
@ -203,7 +214,7 @@ public class Technique implements Savable {
|
|||||||
defines.clear();
|
defines.clear();
|
||||||
defines.addFrom(newDefines);
|
defines.addFrom(newDefines);
|
||||||
// defines changed, recompile needed
|
// defines changed, recompile needed
|
||||||
loadShader(manager);
|
loadShader(assetManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,8 +225,8 @@ public class Technique implements Savable {
|
|||||||
allDefines.addFrom(def.getShaderPresetDefines());
|
allDefines.addFrom(def.getShaderPresetDefines());
|
||||||
allDefines.addFrom(defines);
|
allDefines.addFrom(defines);
|
||||||
|
|
||||||
ShaderKey key = new ShaderKey(def.getVertName(),
|
ShaderKey key = new ShaderKey(def.getVertexShaderName(),
|
||||||
def.getFragName(),
|
def.getFragmentShaderName(),
|
||||||
allDefines,
|
allDefines,
|
||||||
def.getShaderLanguage());
|
def.getShaderLanguage());
|
||||||
shader = manager.loadShader(key);
|
shader = manager.loadShader(key);
|
||||||
|
@ -38,6 +38,7 @@ import com.jme3.export.InputCapsule;
|
|||||||
import com.jme3.export.OutputCapsule;
|
import com.jme3.export.OutputCapsule;
|
||||||
import com.jme3.export.Savable;
|
import com.jme3.export.Savable;
|
||||||
import com.jme3.renderer.Caps;
|
import com.jme3.renderer.Caps;
|
||||||
|
import com.jme3.renderer.Renderer;
|
||||||
import com.jme3.shader.DefineList;
|
import com.jme3.shader.DefineList;
|
||||||
import com.jme3.shader.UniformBinding;
|
import com.jme3.shader.UniformBinding;
|
||||||
import com.jme3.shader.VarType;
|
import com.jme3.shader.VarType;
|
||||||
@ -47,12 +48,49 @@ import java.util.EnumSet;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes a technique definition.
|
||||||
|
*
|
||||||
|
* @author Kirill Vainer
|
||||||
|
*/
|
||||||
public class TechniqueDef implements Savable {
|
public class TechniqueDef implements Savable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes light rendering mode.
|
||||||
|
*/
|
||||||
public enum LightMode {
|
public enum LightMode {
|
||||||
|
/**
|
||||||
|
* Disable light-based rendering
|
||||||
|
*/
|
||||||
Disable,
|
Disable,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable light rendering by using a single pass.
|
||||||
|
* <p>
|
||||||
|
* An array of light positions and light colors is passed to the shader
|
||||||
|
* containing the world light list for the geometry being rendered.
|
||||||
|
*/
|
||||||
SinglePass,
|
SinglePass,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable light rendering by using multi-pass rendering.
|
||||||
|
* <p>
|
||||||
|
* The geometry will be rendered once for each light. Each time the
|
||||||
|
* light position and light color uniforms are updated to contain
|
||||||
|
* the values for the current light. The ambient light color uniform
|
||||||
|
* is only set to the ambient light color on the first pass, future
|
||||||
|
* passes have it set to black.
|
||||||
|
*/
|
||||||
MultiPass,
|
MultiPass,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable light rendering by using the
|
||||||
|
* {@link Renderer#setLighting(com.jme3.light.LightList) renderer's setLighting}
|
||||||
|
* method.
|
||||||
|
* <p>
|
||||||
|
* The specific details of rendering the lighting is up to the
|
||||||
|
* renderer implementation.
|
||||||
|
*/
|
||||||
FixedPipeline,
|
FixedPipeline,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,16 +116,257 @@ public class TechniqueDef implements Savable {
|
|||||||
private HashMap<String, String> defineParams;
|
private HashMap<String, String> defineParams;
|
||||||
private ArrayList<UniformBinding> worldBinds;
|
private ArrayList<UniformBinding> worldBinds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new technique definition.
|
||||||
|
* <p>
|
||||||
|
* Used internally by the J3M/J3MD loader.
|
||||||
|
*
|
||||||
|
* @param name The name of the technique, should be set to <code>null</code>
|
||||||
|
* for default techniques.
|
||||||
|
*/
|
||||||
public TechniqueDef(String name){
|
public TechniqueDef(String name){
|
||||||
this.name = name == null ? "Default" : name;
|
this.name = name == null ? "Default" : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do not use this constructor.
|
* Serialization only. Do not use.
|
||||||
*/
|
*/
|
||||||
public TechniqueDef(){
|
public TechniqueDef(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of this technique as specified in the J3MD file.
|
||||||
|
* Default techniques have the name "Default".
|
||||||
|
*
|
||||||
|
* @return the name of this technique
|
||||||
|
*/
|
||||||
|
public String getName(){
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the light mode.
|
||||||
|
* @return the light mode.
|
||||||
|
* @see LightMode
|
||||||
|
*/
|
||||||
|
public LightMode getLightMode() {
|
||||||
|
return lightMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the light mode
|
||||||
|
*
|
||||||
|
* @param lightMode the light mode
|
||||||
|
*
|
||||||
|
* @see LightMode
|
||||||
|
*/
|
||||||
|
public void setLightMode(LightMode lightMode) {
|
||||||
|
this.lightMode = lightMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the shadow mode.
|
||||||
|
* @return the shadow mode.
|
||||||
|
*/
|
||||||
|
public ShadowMode getShadowMode() {
|
||||||
|
return shadowMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the shadow mode.
|
||||||
|
*
|
||||||
|
* @param shadowMode the shadow mode.
|
||||||
|
*
|
||||||
|
* @see ShadowMode
|
||||||
|
*/
|
||||||
|
public void setShadowMode(ShadowMode shadowMode) {
|
||||||
|
this.shadowMode = shadowMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the render state that this technique is using
|
||||||
|
* @return the render state that this technique is using
|
||||||
|
* @see #setRenderState(com.jme3.material.RenderState)
|
||||||
|
*/
|
||||||
|
public RenderState getRenderState() {
|
||||||
|
return renderState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the render state that this technique is using.
|
||||||
|
*
|
||||||
|
* @param renderState the render state that this technique is using.
|
||||||
|
*
|
||||||
|
* @see RenderState
|
||||||
|
*/
|
||||||
|
public void setRenderState(RenderState renderState) {
|
||||||
|
this.renderState = renderState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this technique uses shaders, false otherwise.
|
||||||
|
*
|
||||||
|
* @return true if this technique uses shaders, false otherwise.
|
||||||
|
*
|
||||||
|
* @see #setShaderFile(java.lang.String, java.lang.String, java.lang.String)
|
||||||
|
*/
|
||||||
|
public boolean isUsingShaders(){
|
||||||
|
return usesShaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link Caps renderer capabilities} that are required
|
||||||
|
* by this technique.
|
||||||
|
*
|
||||||
|
* @return the required renderer capabilities
|
||||||
|
*/
|
||||||
|
public EnumSet<Caps> getRequiredCaps() {
|
||||||
|
return requiredCaps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the shaders that this technique definition will use.
|
||||||
|
*
|
||||||
|
* @param vertexShader The name of the vertex shader
|
||||||
|
* @param fragmentShader The name of the fragment shader
|
||||||
|
* @param shaderLanguage The shader language
|
||||||
|
*/
|
||||||
|
public void setShaderFile(String vertexShader, String fragmentShader, String shaderLanguage){
|
||||||
|
this.vertName = vertexShader;
|
||||||
|
this.fragName = fragmentShader;
|
||||||
|
this.shaderLang = shaderLanguage;
|
||||||
|
|
||||||
|
Caps langCap = Caps.valueOf(shaderLanguage);
|
||||||
|
requiredCaps.add(langCap);
|
||||||
|
|
||||||
|
usesShaders = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the define name which the given material parameter influences.
|
||||||
|
*
|
||||||
|
* @param paramName The parameter name to look up
|
||||||
|
* @return The define name
|
||||||
|
*
|
||||||
|
* @see #addShaderParamDefine(java.lang.String, java.lang.String)
|
||||||
|
*/
|
||||||
|
public String getShaderParamDefine(String paramName){
|
||||||
|
if (defineParams == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return defineParams.get(paramName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a define linked to a material parameter.
|
||||||
|
* <p>
|
||||||
|
* Any time the material parameter on the parent material is altered,
|
||||||
|
* the appropriate define on the technique will be modified as well.
|
||||||
|
* See the method
|
||||||
|
* {@link DefineList#set(java.lang.String, com.jme3.shader.VarType, java.lang.Object) }
|
||||||
|
* on the exact details of how the material parameter changes the define.
|
||||||
|
*
|
||||||
|
* @param paramName The name of the material parameter to link to.
|
||||||
|
* @param defineName The name of the define parameter, e.g. USE_LIGHTING
|
||||||
|
*/
|
||||||
|
public void addShaderParamDefine(String paramName, String defineName){
|
||||||
|
if (defineParams == null)
|
||||||
|
defineParams = new HashMap<String, String>();
|
||||||
|
|
||||||
|
defineParams.put(paramName, defineName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link DefineList} for the preset defines.
|
||||||
|
*
|
||||||
|
* @return the {@link DefineList} for the preset defines.
|
||||||
|
*
|
||||||
|
* @see #addShaderPresetDefine(java.lang.String, com.jme3.shader.VarType, java.lang.Object)
|
||||||
|
*/
|
||||||
|
public DefineList getShaderPresetDefines() {
|
||||||
|
return presetDefines;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a preset define.
|
||||||
|
* <p>
|
||||||
|
* Preset defines do not depend upon any parameters to be activated,
|
||||||
|
* they are always passed to the shader as long as this technique is used.
|
||||||
|
*
|
||||||
|
* @param defineName The name of the define parameter, e.g. USE_LIGHTING
|
||||||
|
* @param type The type of the define. See
|
||||||
|
* {@link DefineList#set(java.lang.String, com.jme3.shader.VarType, java.lang.Object) }
|
||||||
|
* to see why it matters.
|
||||||
|
*
|
||||||
|
* @param value The value of the define
|
||||||
|
*/
|
||||||
|
public void addShaderPresetDefine(String defineName, VarType type, Object value){
|
||||||
|
if (presetDefines == null)
|
||||||
|
presetDefines = new DefineList();
|
||||||
|
|
||||||
|
presetDefines.set(defineName, type, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the fragment shader used by the technique, or null
|
||||||
|
* if no fragment shader is specified.
|
||||||
|
*
|
||||||
|
* @return the name of the fragment shader to be used.
|
||||||
|
*/
|
||||||
|
public String getFragmentShaderName() {
|
||||||
|
return fragName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the vertex shader used by the technique, or null
|
||||||
|
* if no vertex shader is specified.
|
||||||
|
*
|
||||||
|
* @return the name of the vertex shader to be used.
|
||||||
|
*/
|
||||||
|
public String getVertexShaderName() {
|
||||||
|
return vertName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the shader language of the shaders used in this technique.
|
||||||
|
*
|
||||||
|
* @return the shader language of the shaders used in this technique.
|
||||||
|
*/
|
||||||
|
public String getShaderLanguage() {
|
||||||
|
return shaderLang;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new world parameter by the given name.
|
||||||
|
*
|
||||||
|
* @param name The world parameter to add.
|
||||||
|
* @return True if the world parameter name was found and added
|
||||||
|
* to the list of world parameters, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean addWorldParam(String name) {
|
||||||
|
if (worldBinds == null){
|
||||||
|
worldBinds = new ArrayList<UniformBinding>();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
worldBinds.add( UniformBinding.valueOf(name) );
|
||||||
|
return true;
|
||||||
|
} catch (IllegalArgumentException ex){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of world parameters that are used by this
|
||||||
|
* technique definition.
|
||||||
|
*
|
||||||
|
* @return The list of world parameters
|
||||||
|
*/
|
||||||
|
public List<UniformBinding> getWorldBindings() {
|
||||||
|
return worldBinds;
|
||||||
|
}
|
||||||
|
|
||||||
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.write(name, "name", null);
|
oc.write(name, "name", null);
|
||||||
@ -118,105 +397,4 @@ public class TechniqueDef implements Savable {
|
|||||||
usesShaders = ic.readBoolean("usesShaders", false);
|
usesShaders = ic.readBoolean("usesShaders", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName(){
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LightMode getLightMode() {
|
|
||||||
return lightMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLightMode(LightMode lightMode) {
|
|
||||||
this.lightMode = lightMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ShadowMode getShadowMode() {
|
|
||||||
return shadowMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShadowMode(ShadowMode shadowMode) {
|
|
||||||
this.shadowMode = shadowMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RenderState getRenderState() {
|
|
||||||
return renderState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRenderState(RenderState renderState) {
|
|
||||||
this.renderState = renderState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUsingShaders(){
|
|
||||||
return usesShaders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EnumSet<Caps> getRequiredCaps() {
|
|
||||||
return requiredCaps;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShaderFile(String vert, String frag, String lang){
|
|
||||||
this.vertName = vert;
|
|
||||||
this.fragName = frag;
|
|
||||||
this.shaderLang = lang;
|
|
||||||
|
|
||||||
Caps langCap = Caps.valueOf(lang);
|
|
||||||
requiredCaps.add(langCap);
|
|
||||||
|
|
||||||
usesShaders = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefineList getShaderPresetDefines() {
|
|
||||||
return presetDefines;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getShaderParamDefine(String paramName){
|
|
||||||
if (defineParams == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return defineParams.get(paramName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addShaderParamDefine(String paramName, String defineName){
|
|
||||||
if (defineParams == null)
|
|
||||||
defineParams = new HashMap<String, String>();
|
|
||||||
|
|
||||||
defineParams.put(paramName, defineName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addShaderPresetDefine(String defineName, VarType type, Object value){
|
|
||||||
if (presetDefines == null)
|
|
||||||
presetDefines = new DefineList();
|
|
||||||
|
|
||||||
presetDefines.set(defineName, type, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFragName() {
|
|
||||||
return fragName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVertName() {
|
|
||||||
return vertName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getShaderLanguage() {
|
|
||||||
return shaderLang;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addWorldParam(String name) {
|
|
||||||
if (worldBinds == null){
|
|
||||||
worldBinds = new ArrayList<UniformBinding>();
|
|
||||||
}
|
|
||||||
for (UniformBinding binding : UniformBinding.values()) {
|
|
||||||
if (binding.name().equals(name)) {
|
|
||||||
worldBinds.add(binding);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<UniformBinding> getWorldBindings() {
|
|
||||||
return worldBinds;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
The <code>com.jme3.material</code> package contains classes for manipulating
|
The <code>com.jme3.material</code> package contains classes for manipulating
|
||||||
jMonkeyEngine materials.
|
jMonkeyEngine materials.
|
||||||
Materials are applied to {@link com.jme3.scene.Geoemtry geometries} in the
|
Materials are applied to {@link com.jme3.scene.Geometry geometries} in the
|
||||||
scene.
|
scene.
|
||||||
Each geometry has a single material which is used to render that
|
Each geometry has a single material which is used to render that
|
||||||
geometry.
|
geometry.
|
||||||
|
@ -1197,8 +1197,7 @@ public final class Matrix4f implements Savable, Cloneable {
|
|||||||
*
|
*
|
||||||
* @param vec
|
* @param vec
|
||||||
* vec to multiply against.
|
* vec to multiply against.
|
||||||
* @param store
|
*
|
||||||
* a vector to store the result in. created if null is passed.
|
|
||||||
* @return the rotated vector.
|
* @return the rotated vector.
|
||||||
*/
|
*/
|
||||||
public Vector4f multAcross(Vector4f vec) {
|
public Vector4f multAcross(Vector4f vec) {
|
||||||
|
@ -455,7 +455,8 @@ public final class Ray implements Savable, Cloneable, Collidable {
|
|||||||
* <code>getLimit</code> returns the limit or the ray, aka the length.
|
* <code>getLimit</code> returns the limit or the ray, aka the length.
|
||||||
* If the limit is not infinity, then this ray is a line with length <code>
|
* If the limit is not infinity, then this ray is a line with length <code>
|
||||||
* limit</code>.
|
* limit</code>.
|
||||||
* @return
|
*
|
||||||
|
* @return the limit or the ray, aka the length.
|
||||||
*/
|
*/
|
||||||
public float getLimit(){
|
public float getLimit(){
|
||||||
return limit;
|
return limit;
|
||||||
|
@ -277,7 +277,6 @@ public class Spline implements Savable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the curve tension
|
* returns the curve tension
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public float getCurveTension() {
|
public float getCurveTension() {
|
||||||
return curveTension;
|
return curveTension;
|
||||||
@ -297,7 +296,6 @@ public class Spline implements Savable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* returns true if the spline cycle
|
* returns true if the spline cycle
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public boolean isCycle() {
|
public boolean isCycle() {
|
||||||
return cycle;
|
return cycle;
|
||||||
@ -326,7 +324,6 @@ public class Spline implements Savable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* return the total lenght of the spline
|
* return the total lenght of the spline
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public float getTotalLength() {
|
public float getTotalLength() {
|
||||||
return totalLength;
|
return totalLength;
|
||||||
@ -334,7 +331,6 @@ public class Spline implements Savable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* return the type of the spline
|
* return the type of the spline
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public SplineType getType() {
|
public SplineType getType() {
|
||||||
return type;
|
return type;
|
||||||
@ -351,7 +347,6 @@ public class Spline implements Savable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* returns this spline control points
|
* returns this spline control points
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public List<Vector3f> getControlPoints() {
|
public List<Vector3f> getControlPoints() {
|
||||||
return controlPoints;
|
return controlPoints;
|
||||||
@ -359,7 +354,6 @@ public class Spline implements Savable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* returns a list of float representing the segments lenght
|
* returns a list of float representing the segments lenght
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public List<Float> getSegmentsLength() {
|
public List<Float> getSegmentsLength() {
|
||||||
return segmentsLength;
|
return segmentsLength;
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.jme3.math;
|
package com.jme3.math;
|
||||||
|
|
||||||
import com.jme3.export.JmeExporter;
|
import com.jme3.export.JmeExporter;
|
||||||
@ -50,15 +49,13 @@ public class Triangle extends AbstractTriangle implements Savable {
|
|||||||
private Vector3f pointa = new Vector3f();
|
private Vector3f pointa = new Vector3f();
|
||||||
private Vector3f pointb = new Vector3f();
|
private Vector3f pointb = new Vector3f();
|
||||||
private Vector3f pointc = new Vector3f();
|
private Vector3f pointc = new Vector3f();
|
||||||
|
|
||||||
private transient Vector3f center;
|
private transient Vector3f center;
|
||||||
private transient Vector3f normal;
|
private transient Vector3f normal;
|
||||||
|
|
||||||
private float projection;
|
private float projection;
|
||||||
|
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
public Triangle() {}
|
public Triangle() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor instantiates a new <Code>Triangle</code> object with the
|
* Constructor instantiates a new <Code>Triangle</code> object with the
|
||||||
@ -84,22 +81,26 @@ public class Triangle extends AbstractTriangle implements Savable {
|
|||||||
*/
|
*/
|
||||||
public Vector3f get(int i) {
|
public Vector3f get(int i) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0: return pointa;
|
case 0:
|
||||||
case 1: return pointb;
|
return pointa;
|
||||||
case 2: return pointc;
|
case 1:
|
||||||
default: return null;
|
return pointb;
|
||||||
|
case 2:
|
||||||
|
return pointc;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3f get1(){
|
public Vector3f get1() {
|
||||||
return pointa;
|
return pointa;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3f get2(){
|
public Vector3f get2() {
|
||||||
return pointb;
|
return pointb;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3f get3(){
|
public Vector3f get3() {
|
||||||
return pointc;
|
return pointc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,9 +113,15 @@ public class Triangle extends AbstractTriangle implements Savable {
|
|||||||
*/
|
*/
|
||||||
public void set(int i, Vector3f point) {
|
public void set(int i, Vector3f point) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0: pointa.set(point); break;
|
case 0:
|
||||||
case 1: pointb.set(point); break;
|
pointa.set(point);
|
||||||
case 2: pointc.set(point); break;
|
break;
|
||||||
|
case 1:
|
||||||
|
pointb.set(point);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
pointc.set(point);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,29 +130,34 @@ public class Triangle extends AbstractTriangle implements Savable {
|
|||||||
* <code>set</code> sets one of the triangles points to that specified as
|
* <code>set</code> sets one of the triangles points to that specified as
|
||||||
* a parameter.
|
* a parameter.
|
||||||
* @param i the index to place the point.
|
* @param i the index to place the point.
|
||||||
* @param point the point to set.
|
|
||||||
*/
|
*/
|
||||||
public void set(int i, float x, float y, float z) {
|
public void set(int i, float x, float y, float z) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0: pointa.set(x,y,z); break;
|
case 0:
|
||||||
case 1: pointb.set(x,y,z); break;
|
pointa.set(x, y, z);
|
||||||
case 2: pointc.set(x,y,z); break;
|
break;
|
||||||
|
case 1:
|
||||||
|
pointb.set(x, y, z);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
pointc.set(x, y, z);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set1(Vector3f v){
|
public void set1(Vector3f v) {
|
||||||
pointa.set(v);
|
pointa.set(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set2(Vector3f v){
|
public void set2(Vector3f v) {
|
||||||
pointb.set(v);
|
pointb.set(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set3(Vector3f v){
|
public void set3(Vector3f v) {
|
||||||
pointc.set(v);
|
pointc.set(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(Vector3f v1, Vector3f v2, Vector3f v3){
|
public void set(Vector3f v1, Vector3f v2, Vector3f v3) {
|
||||||
pointa.set(v1);
|
pointa.set(v1);
|
||||||
pointb.set(v2);
|
pointb.set(v2);
|
||||||
pointc.set(v3);
|
pointc.set(v3);
|
||||||
@ -156,9 +168,11 @@ public class Triangle extends AbstractTriangle implements Savable {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void calculateCenter() {
|
public void calculateCenter() {
|
||||||
if (center == null)
|
if (center == null) {
|
||||||
center = new Vector3f(pointa);
|
center = new Vector3f(pointa);
|
||||||
else center.set(pointa);
|
} else {
|
||||||
|
center.set(pointa);
|
||||||
|
}
|
||||||
center.addLocal(pointb).addLocal(pointc).multLocal(FastMath.ONE_THIRD);
|
center.addLocal(pointb).addLocal(pointc).multLocal(FastMath.ONE_THIRD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,10 +181,12 @@ public class Triangle extends AbstractTriangle implements Savable {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void calculateNormal() {
|
public void calculateNormal() {
|
||||||
if (normal == null)
|
if (normal == null) {
|
||||||
normal = new Vector3f(pointb);
|
normal = new Vector3f(pointb);
|
||||||
else normal.set(pointb);
|
} else {
|
||||||
normal.subtractLocal(pointa).crossLocal(pointc.x-pointa.x, pointc.y-pointa.y, pointc.z-pointa.z);
|
normal.set(pointb);
|
||||||
|
}
|
||||||
|
normal.subtractLocal(pointa).crossLocal(pointc.x - pointa.x, pointc.y - pointa.y, pointc.z - pointa.z);
|
||||||
normal.normalizeLocal();
|
normal.normalizeLocal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,9 +195,9 @@ public class Triangle extends AbstractTriangle implements Savable {
|
|||||||
* @return the center point.
|
* @return the center point.
|
||||||
*/
|
*/
|
||||||
public Vector3f getCenter() {
|
public Vector3f getCenter() {
|
||||||
if(center == null) {
|
if (center == null) {
|
||||||
calculateCenter();
|
calculateCenter();
|
||||||
}
|
}
|
||||||
return center;
|
return center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,9 +216,9 @@ public class Triangle extends AbstractTriangle implements Savable {
|
|||||||
* @return the normal vector
|
* @return the normal vector
|
||||||
*/
|
*/
|
||||||
public Vector3f getNormal() {
|
public Vector3f getNormal() {
|
||||||
if(normal == null) {
|
if (normal == null) {
|
||||||
calculateNormal();
|
calculateNormal();
|
||||||
}
|
}
|
||||||
return normal;
|
return normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,13 +262,14 @@ public class Triangle extends AbstractTriangle implements Savable {
|
|||||||
this.index = index;
|
this.index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector3f computeTriangleNormal(Vector3f v1, Vector3f v2, Vector3f v3, Vector3f store){
|
public static Vector3f computeTriangleNormal(Vector3f v1, Vector3f v2, Vector3f v3, Vector3f store) {
|
||||||
if (store == null)
|
if (store == null) {
|
||||||
store = new Vector3f(v2);
|
store = new Vector3f(v2);
|
||||||
else
|
} else {
|
||||||
store.set(v2);
|
store.set(v2);
|
||||||
|
}
|
||||||
|
|
||||||
store.subtractLocal(v1).crossLocal(v3.x-v1.x, v3.y-v1.y, v3.z-v1.z);
|
store.subtractLocal(v1).crossLocal(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z);
|
||||||
return store.normalizeLocal();
|
return store.normalizeLocal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,9 +280,9 @@ public class Triangle extends AbstractTriangle implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void read(JmeImporter e) throws IOException {
|
public void read(JmeImporter e) throws IOException {
|
||||||
pointa = (Vector3f)e.getCapsule(this).readSavable("pointa", Vector3f.ZERO.clone());
|
pointa = (Vector3f) e.getCapsule(this).readSavable("pointa", Vector3f.ZERO.clone());
|
||||||
pointb = (Vector3f)e.getCapsule(this).readSavable("pointb", Vector3f.ZERO.clone());
|
pointb = (Vector3f) e.getCapsule(this).readSavable("pointb", Vector3f.ZERO.clone());
|
||||||
pointc = (Vector3f)e.getCapsule(this).readSavable("pointc", Vector3f.ZERO.clone());
|
pointc = (Vector3f) e.getCapsule(this).readSavable("pointc", Vector3f.ZERO.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -320,7 +320,8 @@ public final class Vector2f implements Savable, Cloneable {
|
|||||||
* <code>distanceSquared</code> calculates the distance squared between
|
* <code>distanceSquared</code> calculates the distance squared between
|
||||||
* this vector and vector v.
|
* this vector and vector v.
|
||||||
*
|
*
|
||||||
* @param v the second vector to determine the distance squared.
|
* @param otherX The X coordinate of the v vector
|
||||||
|
* @param otherY The Y coordinate of the v vector
|
||||||
* @return the distance squared between the two vectors.
|
* @return the distance squared between the two vectors.
|
||||||
*/
|
*/
|
||||||
public float distanceSquared(float otherX, float otherY) {
|
public float distanceSquared(float otherX, float otherY) {
|
||||||
|
@ -677,7 +677,7 @@ public final class Vector4f implements Savable, Cloneable {
|
|||||||
* the y value to subtract.
|
* the y value to subtract.
|
||||||
* @param subtractZ
|
* @param subtractZ
|
||||||
* the z value to subtract.
|
* the z value to subtract.
|
||||||
* @param subtract@
|
* @param subtractW
|
||||||
* the w value to subtract.
|
* the w value to subtract.
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
|
@ -189,9 +189,10 @@ public abstract class Filter implements Savable {
|
|||||||
public abstract void cleanUpFilter(Renderer r);
|
public abstract void cleanUpFilter(Renderer r);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this method should return the material used for this filter.
|
* Returns the material used for this filter.
|
||||||
* this method is called every frames
|
* this method is called every frame.
|
||||||
* @return
|
*
|
||||||
|
* @return the material used for this filter.
|
||||||
*/
|
*/
|
||||||
public abstract Material getMaterial();
|
public abstract Material getMaterial();
|
||||||
|
|
||||||
@ -232,16 +233,14 @@ public abstract class Filter implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override this method if you want to load extra properties when the filter is loaded else only basic properties of the filter will be loaded
|
* Override this method if you want to load extra properties when the filter
|
||||||
* This method should always begin by super.read(ex);
|
* is loaded else only basic properties of the filter will be loaded
|
||||||
* @param ex
|
* This method should always begin by super.read(im);
|
||||||
* @throws IOException
|
|
||||||
*/
|
*/
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
InputCapsule ic = im.getCapsule(this);
|
InputCapsule ic = im.getCapsule(this);
|
||||||
name = ic.readString("name", "");
|
name = ic.readString("name", "");
|
||||||
enabled = ic.readBoolean("enabled", true);
|
enabled = ic.readBoolean("enabled", true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@ -269,8 +268,9 @@ public abstract class Filter implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override this method and retrun true if your Filter need the depth texture
|
* Override this method and return true if your Filter need the depth texture
|
||||||
* @return
|
*
|
||||||
|
* @return true if your Filter need the depth texture
|
||||||
*/
|
*/
|
||||||
public boolean isRequiresDepthTexture() {
|
public boolean isRequiresDepthTexture() {
|
||||||
return false;
|
return false;
|
||||||
@ -278,7 +278,8 @@ public abstract class Filter implements Savable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Override this method and return false if your Filter does not need the scene texture
|
* Override this method and return false if your Filter does not need the scene texture
|
||||||
* @return
|
*
|
||||||
|
* @return false if your Filter does not need the scene texture
|
||||||
*/
|
*/
|
||||||
public boolean isRequiresSceneTexture() {
|
public boolean isRequiresSceneTexture() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -599,7 +599,6 @@ public class Camera implements Savable, Cloneable {
|
|||||||
* <code>setLocation</code> sets the position of the camera.
|
* <code>setLocation</code> sets the position of the camera.
|
||||||
*
|
*
|
||||||
* @param location the position of the camera.
|
* @param location the position of the camera.
|
||||||
* @see Camera#setLocation(com.jme.math.Vector3f)
|
|
||||||
*/
|
*/
|
||||||
public void setLocation(Vector3f location) {
|
public void setLocation(Vector3f location) {
|
||||||
this.location.set(location);
|
this.location.set(location);
|
||||||
@ -660,7 +659,8 @@ public class Camera implements Savable, Cloneable {
|
|||||||
* @param left the left axis of the camera.
|
* @param left the left axis of the camera.
|
||||||
* @param up the up axis of the camera.
|
* @param up the up axis of the camera.
|
||||||
* @param direction the direction the camera is facing.
|
* @param direction the direction the camera is facing.
|
||||||
* @see Camera#setAxes(com.jme.math.Vector3f,com.jme.math.Vector3f,com.jme.math.Vector3f)
|
*
|
||||||
|
* @see Camera#setAxes(com.jme3.math.Quaternion)
|
||||||
*/
|
*/
|
||||||
public void setAxes(Vector3f left, Vector3f up, Vector3f direction) {
|
public void setAxes(Vector3f left, Vector3f up, Vector3f direction) {
|
||||||
this.rotation.fromAxes(left, up, direction);
|
this.rotation.fromAxes(left, up, direction);
|
||||||
|
@ -154,9 +154,8 @@ public abstract class GLObject implements Cloneable {
|
|||||||
/**
|
/**
|
||||||
* This should create a deep clone. For a shallow clone, use
|
* This should create a deep clone. For a shallow clone, use
|
||||||
* createDestructableClone().
|
* createDestructableClone().
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected GLObject clone(){
|
protected GLObject clone(){
|
||||||
try{
|
try{
|
||||||
GLObject obj = (GLObject) super.clone();
|
GLObject obj = (GLObject) super.clone();
|
||||||
|
@ -181,9 +181,6 @@ public class RenderManager {
|
|||||||
/**
|
/**
|
||||||
* Creates a new viewport, to display the given camera's content.
|
* Creates a new viewport, to display the given camera's content.
|
||||||
* The view will be processed before the primary viewport.
|
* The view will be processed before the primary viewport.
|
||||||
* @param viewName
|
|
||||||
* @param cam
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public ViewPort createPreView(String viewName, Camera cam) {
|
public ViewPort createPreView(String viewName, Camera cam) {
|
||||||
ViewPort vp = new ViewPort(viewName, cam);
|
ViewPort vp = new ViewPort(viewName, cam);
|
||||||
@ -491,9 +488,6 @@ public class RenderManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Render scene graph
|
* Render scene graph
|
||||||
* @param s
|
|
||||||
* @param r
|
|
||||||
* @param cam
|
|
||||||
*/
|
*/
|
||||||
public void renderScene(Spatial scene, ViewPort vp) {
|
public void renderScene(Spatial scene, ViewPort vp) {
|
||||||
if (scene.getParent() == null) {
|
if (scene.getParent() == null) {
|
||||||
|
@ -99,7 +99,7 @@ public interface Renderer {
|
|||||||
public void onFrame();
|
public void onFrame();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param transform The world transform to use. This changes
|
* @param worldMatrix The world transform to use. This changes
|
||||||
* the world matrix given in the shader.
|
* the world matrix given in the shader.
|
||||||
*/
|
*/
|
||||||
public void setWorldMatrix(Matrix4f worldMatrix);
|
public void setWorldMatrix(Matrix4f worldMatrix);
|
||||||
@ -171,7 +171,6 @@ public interface Renderer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a texture from the GPU.
|
* Deletes a texture from the GPU.
|
||||||
* @param tex
|
|
||||||
*/
|
*/
|
||||||
public void deleteImage(Image image);
|
public void deleteImage(Image image);
|
||||||
|
|
||||||
|
@ -70,10 +70,10 @@ public class GeometryList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a spatial to the list. List size is doubled if there is no room.
|
* Adds a geometry to the list. List size is doubled if there is no room.
|
||||||
*
|
*
|
||||||
* @param s
|
* @param g
|
||||||
* The spatial to add.
|
* The geometry to add.
|
||||||
*/
|
*/
|
||||||
public void add(Geometry g) {
|
public void add(Geometry g) {
|
||||||
if (size == geometries.length) {
|
if (size == geometries.length) {
|
||||||
|
@ -177,7 +177,7 @@ public class Geometry extends Spatial {
|
|||||||
* this geometry. The location of the geometry is based on the location of
|
* this geometry. The location of the geometry is based on the location of
|
||||||
* all this node's parents.
|
* all this node's parents.
|
||||||
*
|
*
|
||||||
* @see com.jme.scene.Spatial#updateWorldBound()
|
* @see Spatial#updateWorldBound()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void updateWorldBound() {
|
protected void updateWorldBound() {
|
||||||
@ -282,7 +282,6 @@ public class Geometry extends Spatial {
|
|||||||
* Exception: if the mesh is marked as being a software
|
* Exception: if the mesh is marked as being a software
|
||||||
* animated mesh, (bind pose is set) then the positions
|
* animated mesh, (bind pose is set) then the positions
|
||||||
* and normals are deep copied.
|
* and normals are deep copied.
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Geometry clone(boolean cloneMaterial){
|
public Geometry clone(boolean cloneMaterial){
|
||||||
@ -308,8 +307,8 @@ public class Geometry extends Spatial {
|
|||||||
* Exception: if the mesh is marked as being a software
|
* Exception: if the mesh is marked as being a software
|
||||||
* animated mesh, (bind pose is set) then the positions
|
* animated mesh, (bind pose is set) then the positions
|
||||||
* and normals are deep copied.
|
* and normals are deep copied.
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Geometry clone(){
|
public Geometry clone(){
|
||||||
return clone(true);
|
return clone(true);
|
||||||
}
|
}
|
||||||
@ -318,7 +317,6 @@ public class Geometry extends Spatial {
|
|||||||
* Creates a deep clone of the geometry,
|
* Creates a deep clone of the geometry,
|
||||||
* this creates an identical copy of the mesh
|
* this creates an identical copy of the mesh
|
||||||
* with the vertexbuffer data duplicated.
|
* with the vertexbuffer data duplicated.
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Spatial deepClone(){
|
public Spatial deepClone(){
|
||||||
|
@ -526,7 +526,7 @@ public class Node extends Spatial implements Savable {
|
|||||||
* @return Non-null, but possibly 0-element, list of matching Spatials (also Instances extending Spatials).
|
* @return Non-null, but possibly 0-element, list of matching Spatials (also Instances extending Spatials).
|
||||||
*
|
*
|
||||||
* @see java.util.regex.Pattern
|
* @see java.util.regex.Pattern
|
||||||
* @see Spatial#matches(Class<? extends Spatial>, String)
|
* @see Spatial#matches(java.lang.Class, java.lang.String)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends Spatial>List<T> descendantMatches(
|
public <T extends Spatial>List<T> descendantMatches(
|
||||||
@ -546,7 +546,7 @@ public class Node extends Spatial implements Savable {
|
|||||||
/**
|
/**
|
||||||
* Convenience wrapper.
|
* Convenience wrapper.
|
||||||
*
|
*
|
||||||
* @see #descendantMatches(Class<? extends Spatial>, String)
|
* @see #descendantMatches(java.lang.Class, java.lang.String)
|
||||||
*/
|
*/
|
||||||
public <T extends Spatial>List<T> descendantMatches(
|
public <T extends Spatial>List<T> descendantMatches(
|
||||||
Class<T> spatialSubclass) {
|
Class<T> spatialSubclass) {
|
||||||
@ -556,7 +556,7 @@ public class Node extends Spatial implements Savable {
|
|||||||
/**
|
/**
|
||||||
* Convenience wrapper.
|
* Convenience wrapper.
|
||||||
*
|
*
|
||||||
* @see #descendantMatches(Class<? extends Spatial>, String)
|
* @see #descendantMatches(java.lang.Class, java.lang.String)
|
||||||
*/
|
*/
|
||||||
public <T extends Spatial>List<T> descendantMatches(String nameRegex) {
|
public <T extends Spatial>List<T> descendantMatches(String nameRegex) {
|
||||||
return descendantMatches(null, nameRegex);
|
return descendantMatches(null, nameRegex);
|
||||||
|
@ -784,9 +784,6 @@ public abstract class Spatial implements Savable, Cloneable, Collidable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>setLocalScale</code> sets the local scale of this node.
|
* <code>setLocalScale</code> sets the local scale of this node.
|
||||||
*
|
|
||||||
* @param localScale
|
|
||||||
* the new local scale
|
|
||||||
*/
|
*/
|
||||||
public void setLocalScale(float x, float y, float z) {
|
public void setLocalScale(float x, float y, float z) {
|
||||||
localTransform.setScale(x, y, z);
|
localTransform.setScale(x, y, z);
|
||||||
|
@ -664,11 +664,6 @@ public class VertexBuffer extends GLObject implements Savable, Cloneable {
|
|||||||
* of the parameters. The buffer will be of the type specified by
|
* of the parameters. The buffer will be of the type specified by
|
||||||
* {@link Format format} and would be able to contain the given number
|
* {@link Format format} and would be able to contain the given number
|
||||||
* of elements with the given number of components in each element.
|
* of elements with the given number of components in each element.
|
||||||
*
|
|
||||||
* @param format
|
|
||||||
* @param components
|
|
||||||
* @param numElements
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static Buffer createBuffer(Format format, int components, int numElements){
|
public static Buffer createBuffer(Format format, int components, int numElements){
|
||||||
if (components < 1 || components > 4)
|
if (components < 1 || components > 4)
|
||||||
|
@ -48,7 +48,7 @@ public interface Control extends Savable {
|
|||||||
* Creates a clone of the Control, the given Spatial is the cloned
|
* Creates a clone of the Control, the given Spatial is the cloned
|
||||||
* version of the spatial to which this control is attached to.
|
* version of the spatial to which this control is attached to.
|
||||||
* @param spatial
|
* @param spatial
|
||||||
* @return
|
* @return A clone of this control for the spatial
|
||||||
*/
|
*/
|
||||||
public Control cloneForSpatial(Spatial spatial);
|
public Control cloneForSpatial(Spatial spatial);
|
||||||
|
|
||||||
|
@ -76,14 +76,14 @@ public class LightControl extends AbstractControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param camera The Camera to be synced.
|
* @param light The light to be synced.
|
||||||
*/
|
*/
|
||||||
public LightControl(Light light) {
|
public LightControl(Light light) {
|
||||||
this.light = light;
|
this.light = light;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param camera The Camera to be synced.
|
* @param light The light to be synced.
|
||||||
*/
|
*/
|
||||||
public LightControl(Light light, ControlDirection controlDir) {
|
public LightControl(Light light, ControlDirection controlDir) {
|
||||||
this.light = light;
|
this.light = light;
|
||||||
|
@ -380,7 +380,6 @@ public final class Shader extends GLObject implements Savable {
|
|||||||
/**
|
/**
|
||||||
* Returns true if this program and all it's shaders have been compiled,
|
* Returns true if this program and all it's shaders have been compiled,
|
||||||
* linked and validated successfuly.
|
* linked and validated successfuly.
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public boolean isUsable(){
|
public boolean isUsable(){
|
||||||
return usable;
|
return usable;
|
||||||
@ -417,7 +416,6 @@ public final class Shader extends GLObject implements Savable {
|
|||||||
/**
|
/**
|
||||||
* Called by the object manager to reset all object IDs. This causes
|
* Called by the object manager to reset all object IDs. This causes
|
||||||
* the shader to be reuploaded to the GPU incase the display was restarted.
|
* the shader to be reuploaded to the GPU incase the display was restarted.
|
||||||
* @param r
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void resetObject() {
|
public void resetObject() {
|
||||||
|
@ -37,6 +37,7 @@ import com.jme3.input.KeyInput;
|
|||||||
import com.jme3.input.MouseInput;
|
import com.jme3.input.MouseInput;
|
||||||
import com.jme3.input.TouchInput;
|
import com.jme3.input.TouchInput;
|
||||||
import com.jme3.renderer.Renderer;
|
import com.jme3.renderer.Renderer;
|
||||||
|
import com.jme3.system.JmeCanvasContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a rendering context within the engine.
|
* Represents a rendering context within the engine.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user