|
|
|
@ -47,6 +47,7 @@ import com.jme3.asset.ModelKey; |
|
|
|
|
import com.jme3.light.Light; |
|
|
|
|
import com.jme3.renderer.Camera; |
|
|
|
|
import com.jme3.scene.Node; |
|
|
|
|
import com.jme3.scene.Spatial; |
|
|
|
|
import com.jme3.scene.plugins.blender.animations.ArmatureHelper; |
|
|
|
|
import com.jme3.scene.plugins.blender.animations.IpoHelper; |
|
|
|
|
import com.jme3.scene.plugins.blender.cameras.CameraHelper; |
|
|
|
@ -70,121 +71,153 @@ import com.jme3.scene.plugins.blender.textures.TextureHelper; |
|
|
|
|
*/ |
|
|
|
|
public class BlenderLoader implements AssetLoader { |
|
|
|
|
|
|
|
|
|
private static final Logger LOGGER = Logger.getLogger(BlenderLoader.class.getName()); |
|
|
|
|
private static final Logger LOGGER = Logger.getLogger(BlenderLoader.class.getName()); |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
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()); |
|
|
|
|
} |
|
|
|
|
/** Converter for blender structures. */ |
|
|
|
|
protected JmeConverter converter; |
|
|
|
|
/** The data repository. */ |
|
|
|
|
protected DataRepository dataRepository; |
|
|
|
|
/** The blender key to use. */ |
|
|
|
|
protected BlenderKey blenderKey; |
|
|
|
|
/** The blocks read from the file. */ |
|
|
|
|
protected List<FileBlockHeader> blocks; |
|
|
|
|
/** Blender input stream. */ |
|
|
|
|
protected BlenderInputStream inputStream; |
|
|
|
|
|
|
|
|
|
//opening stream
|
|
|
|
|
BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream(), assetInfo.getManager()); |
|
|
|
|
@Override |
|
|
|
|
public Spatial load(AssetInfo assetInfo) throws IOException { |
|
|
|
|
try { |
|
|
|
|
this.setup(assetInfo); |
|
|
|
|
|
|
|
|
|
//reading blocks
|
|
|
|
|
List<FileBlockHeader> blocks = new ArrayList<FileBlockHeader>(); |
|
|
|
|
FileBlockHeader fileBlock; |
|
|
|
|
DataRepository dataRepository = new DataRepository(); |
|
|
|
|
dataRepository.setAssetManager(assetInfo.getManager()); |
|
|
|
|
dataRepository.setInputStream(inputStream); |
|
|
|
|
dataRepository.setBlenderKey(blenderKey); |
|
|
|
|
LoadingResults loadingResults = blenderKey.prepareLoadingResults(); |
|
|
|
|
WorldData worldData = null;// a set of data used in different scene aspects
|
|
|
|
|
for (FileBlockHeader block : blocks) { |
|
|
|
|
switch (block.getCode()) { |
|
|
|
|
case FileBlockHeader.BLOCK_OB00:// Object
|
|
|
|
|
Object object = converter.toObject(block.getStructure(dataRepository)); |
|
|
|
|
if (object instanceof Node) { |
|
|
|
|
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() }); |
|
|
|
|
if (((Node) object).getParent() == null) { |
|
|
|
|
loadingResults.addObject((Node) object); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (object instanceof Camera) { |
|
|
|
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.CAMERAS) != 0) { |
|
|
|
|
loadingResults.addCamera((Camera) object); |
|
|
|
|
} |
|
|
|
|
} else if (object instanceof Light) { |
|
|
|
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0) { |
|
|
|
|
loadingResults.addLight((Light) object); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case FileBlockHeader.BLOCK_MA00:// Material
|
|
|
|
|
if (blenderKey.isLoadUnlinkedAssets() && (blenderKey.getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0) { |
|
|
|
|
loadingResults.addMaterial(converter.toMaterial(block.getStructure(dataRepository))); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case FileBlockHeader.BLOCK_SC00:// Scene
|
|
|
|
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.SCENES) != 0) { |
|
|
|
|
loadingResults.addScene(converter.toScene(block.getStructure(dataRepository))); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case FileBlockHeader.BLOCK_WO00:// World
|
|
|
|
|
if (blenderKey.isLoadUnlinkedAssets() && worldData == null) {// onlu one world data is used
|
|
|
|
|
Structure worldStructure = block.getStructure(dataRepository); |
|
|
|
|
String worldName = worldStructure.getName(); |
|
|
|
|
if (blenderKey.getUsedWorld() == null || blenderKey.getUsedWorld().equals(worldName)) { |
|
|
|
|
worldData = converter.toWorldData(worldStructure); |
|
|
|
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0) { |
|
|
|
|
loadingResults.addLight(worldData.getAmbientLight()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
try { |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//creating helpers
|
|
|
|
|
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(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber())); |
|
|
|
|
/** |
|
|
|
|
* This method sets up the loader. |
|
|
|
|
* @param assetInfo |
|
|
|
|
* the asset info |
|
|
|
|
* @throws BlenderFileException |
|
|
|
|
* an exception is throw when something wrong happens with blender file |
|
|
|
|
*/ |
|
|
|
|
protected void setup(AssetInfo assetInfo) throws BlenderFileException { |
|
|
|
|
// registering loaders
|
|
|
|
|
ModelKey modelKey = (ModelKey) assetInfo.getKey(); |
|
|
|
|
if (modelKey instanceof BlenderKey) { |
|
|
|
|
blenderKey = (BlenderKey) modelKey; |
|
|
|
|
} else { |
|
|
|
|
blenderKey = new BlenderKey(modelKey.getName()); |
|
|
|
|
blenderKey.setAssetRootPath(modelKey.getFolder()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//setting additional data to helpers
|
|
|
|
|
if (blenderKey.isFixUpAxis()) { |
|
|
|
|
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); |
|
|
|
|
objectHelper.setyIsUpAxis(true); |
|
|
|
|
CurvesHelper curvesHelper = dataRepository.getHelper(CurvesHelper.class); |
|
|
|
|
curvesHelper.setyIsUpAxis(true); |
|
|
|
|
} |
|
|
|
|
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class); |
|
|
|
|
materialHelper.setFaceCullMode(blenderKey.getFaceCullMode()); |
|
|
|
|
// opening stream
|
|
|
|
|
inputStream = new BlenderInputStream(assetInfo.openStream(), assetInfo.getManager()); |
|
|
|
|
|
|
|
|
|
//reading the blocks (dna block is automatically saved in the data repository when found)//TODO: zmienić to
|
|
|
|
|
do { |
|
|
|
|
fileBlock = new FileBlockHeader(inputStream, dataRepository); |
|
|
|
|
if (!fileBlock.isDnaBlock()) { |
|
|
|
|
blocks.add(fileBlock); |
|
|
|
|
} |
|
|
|
|
} while (!fileBlock.isLastBlock()); |
|
|
|
|
// reading blocks
|
|
|
|
|
blocks = new ArrayList<FileBlockHeader>(); |
|
|
|
|
FileBlockHeader fileBlock; |
|
|
|
|
dataRepository = new DataRepository(); |
|
|
|
|
dataRepository.setAssetManager(assetInfo.getManager()); |
|
|
|
|
dataRepository.setInputStream(inputStream); |
|
|
|
|
dataRepository.setBlenderKey(blenderKey); |
|
|
|
|
|
|
|
|
|
JmeConverter converter = new JmeConverter(dataRepository); |
|
|
|
|
LoadingResults loadingResults = blenderKey.prepareLoadingResults(); |
|
|
|
|
WorldData worldData = null;//a set of data used in different scene aspects
|
|
|
|
|
for (FileBlockHeader block : blocks) { |
|
|
|
|
switch (block.getCode()) { |
|
|
|
|
case FileBlockHeader.BLOCK_OB00://Object
|
|
|
|
|
Object object = converter.toObject(block.getStructure(dataRepository)); |
|
|
|
|
if (object instanceof Node) { |
|
|
|
|
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()}); |
|
|
|
|
if (((Node) object).getParent() == null) { |
|
|
|
|
loadingResults.addObject((Node) object); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (object instanceof Camera) { |
|
|
|
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.CAMERAS) != 0) { |
|
|
|
|
loadingResults.addCamera((Camera) object); |
|
|
|
|
} |
|
|
|
|
} else if (object instanceof Light) { |
|
|
|
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0) { |
|
|
|
|
loadingResults.addLight((Light) object); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case FileBlockHeader.BLOCK_MA00://Material
|
|
|
|
|
if (blenderKey.isLoadUnlinkedAssets() && (blenderKey.getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0) { |
|
|
|
|
loadingResults.addMaterial(converter.toMaterial(block.getStructure(dataRepository))); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case FileBlockHeader.BLOCK_SC00://Scene
|
|
|
|
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.SCENES) != 0) { |
|
|
|
|
loadingResults.addScene(converter.toScene(block.getStructure(dataRepository))); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case FileBlockHeader.BLOCK_WO00://World
|
|
|
|
|
if (blenderKey.isLoadUnlinkedAssets() && worldData == null) {//onlu one world data is used
|
|
|
|
|
Structure worldStructure = block.getStructure(dataRepository); |
|
|
|
|
String worldName = worldStructure.getName(); |
|
|
|
|
if (blenderKey.getUsedWorld() == null || blenderKey.getUsedWorld().equals(worldName)) { |
|
|
|
|
worldData = converter.toWorldData(worldStructure); |
|
|
|
|
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0) { |
|
|
|
|
loadingResults.addLight(worldData.getAmbientLight()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
try { |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
// creating helpers
|
|
|
|
|
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(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber())); |
|
|
|
|
|
|
|
|
|
// setting additional data to helpers
|
|
|
|
|
if (blenderKey.isFixUpAxis()) { |
|
|
|
|
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); |
|
|
|
|
objectHelper.setyIsUpAxis(true); |
|
|
|
|
CurvesHelper curvesHelper = dataRepository.getHelper(CurvesHelper.class); |
|
|
|
|
curvesHelper.setyIsUpAxis(true); |
|
|
|
|
} |
|
|
|
|
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class); |
|
|
|
|
materialHelper.setFaceCullMode(blenderKey.getFaceCullMode()); |
|
|
|
|
|
|
|
|
|
// reading the blocks (dna block is automatically saved in the data repository when found)//TODO: zmienić to
|
|
|
|
|
FileBlockHeader sceneFileBlock = null; |
|
|
|
|
do { |
|
|
|
|
fileBlock = new FileBlockHeader(inputStream, dataRepository); |
|
|
|
|
if (!fileBlock.isDnaBlock()) { |
|
|
|
|
blocks.add(fileBlock); |
|
|
|
|
// save the scene's file block
|
|
|
|
|
if (fileBlock.getCode() == FileBlockHeader.BLOCK_SC00 && blenderKey.getLayersToLoad() < 0) { |
|
|
|
|
sceneFileBlock = fileBlock; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} while (!fileBlock.isLastBlock()); |
|
|
|
|
// VERIFY LAYERS TO BE LOADED BEFORE LOADING FEATURES
|
|
|
|
|
if (sceneFileBlock != null) { |
|
|
|
|
int lay = ((Number) sceneFileBlock.getStructure(dataRepository).getFieldValue("lay")).intValue(); |
|
|
|
|
dataRepository.getBlenderKey().setLayersToLoad(lay);// load only current layer
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
converter = new JmeConverter(dataRepository); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|