use of com.jme3.asset.BlenderKey in project jmonkeyengine by jMonkeyEngine.
the class CombinedTexture method generateSkyTexture.
/**
* Generates a texture that will be used by the sky spatial.
* The result texture has 6 layers. Every image in each layer has equal size and its shape is a square.
* The size of each image is the maximum size (width or height) of the textures given.
* The default sky generated texture size is used (this value is set in the BlenderKey) if no picture textures
* are present or their sizes is lower than the generated texture size.
* The textures of lower sizes are properly scaled.
* All the textures are mixed into one and put as layers in the result texture.
*
* @param horizontalColor
* the horizon color
* @param zenithColor
* the zenith color
* @param blenderContext
* the blender context
* @return texture for the sky
*/
public TextureCubeMap generateSkyTexture(ColorRGBA horizontalColor, ColorRGBA zenithColor, BlenderContext blenderContext) {
LOGGER.log(Level.FINE, "Preparing sky texture from {0} applied textures.", textureDatas.size());
LOGGER.fine("Computing the texture size.");
int size = -1;
for (TextureData textureData : textureDatas) {
if (textureData.texture instanceof Texture2D) {
size = Math.max(textureData.texture.getImage().getWidth(), size);
size = Math.max(textureData.texture.getImage().getHeight(), size);
}
}
if (size < 0) {
size = blenderContext.getBlenderKey().getSkyGeneratedTextureSize();
}
LOGGER.log(Level.FINE, "The sky texture size will be: {0}x{0}.", size);
TextureCubeMap result = null;
for (TextureData textureData : textureDatas) {
TextureCubeMap texture = null;
if (textureData.texture instanceof GeneratedTexture) {
texture = ((GeneratedTexture) textureData.texture).generateSkyTexture(size, horizontalColor, zenithColor, blenderContext);
} else {
// first create a grayscale version of the image
Image image = textureData.texture.getImage();
if (image.getWidth() != image.getHeight() || image.getWidth() != size) {
image = ImageUtils.resizeTo(image, size, size);
}
Image grayscaleImage = ImageUtils.convertToGrayscaleTexture(image);
// add the sky colors to the image
PixelInputOutput sourcePixelIO = PixelIOFactory.getPixelIO(grayscaleImage.getFormat());
PixelInputOutput targetPixelIO = PixelIOFactory.getPixelIO(image.getFormat());
TexturePixel texturePixel = new TexturePixel();
for (int x = 0; x < image.getWidth(); ++x) {
for (int y = 0; y < image.getHeight(); ++y) {
sourcePixelIO.read(grayscaleImage, 0, texturePixel, x, y);
// no matter which factor we use here, in grayscale they are all equal
texturePixel.intensity = texturePixel.red;
ImageUtils.color(texturePixel, horizontalColor, zenithColor);
targetPixelIO.write(image, 0, texturePixel, x, y);
}
}
// create the cubemap texture from the coloured image
ByteBuffer sourceData = image.getData(0);
ArrayList<ByteBuffer> data = new ArrayList<ByteBuffer>(6);
for (int i = 0; i < 6; ++i) {
data.add(BufferUtils.clone(sourceData));
}
texture = new TextureCubeMap(new Image(image.getFormat(), image.getWidth(), image.getHeight(), 6, data, ColorSpace.Linear));
}
if (result == null) {
result = texture;
} else {
ImageUtils.mix(result.getImage(), texture.getImage());
}
}
return result;
}
use of com.jme3.asset.BlenderKey in project jmonkeyengine by jMonkeyEngine.
the class TextureHelper method loadImageFromFile.
/**
* This method loads the textre from outside the blend file using the
* AssetManager that the blend file was loaded with. It returns a texture
* with a full assetKey that references the original texture so it later
* doesn't need to ba packed when the model data is serialized. It searches
* the AssetManager for the full path if the model file is a relative path
* and will attempt to truncate the path if it is an absolute file path
* until the path can be found in the AssetManager. If the texture can not
* be found, it will issue a load attempt for the initial path anyway so the
* failed load can be reported by the AssetManagers callback methods for
* failed assets.
*
* @param name
* the path to the image
* @param imaflag
* the image flag
* @param blenderContext
* the blender context
* @return the loaded image or null if the image cannot be found
*/
protected Texture loadImageFromFile(String name, int imaflag, BlenderContext blenderContext) {
if (!name.contains(".")) {
// no extension means not a valid image
return null;
}
// decide if the mipmaps will be generated
boolean generateMipmaps = false;
switch(blenderContext.getBlenderKey().getMipmapGenerationMethod()) {
case ALWAYS_GENERATE:
generateMipmaps = true;
break;
case NEVER_GENERATE:
break;
case GENERATE_WHEN_NEEDED:
generateMipmaps = (imaflag & 0x04) != 0;
break;
default:
throw new IllegalStateException("Unknown mipmap generation method: " + blenderContext.getBlenderKey().getMipmapGenerationMethod());
}
AssetManager assetManager = blenderContext.getAssetManager();
name = name.replace('\\', '/');
Texture result = null;
if (name.startsWith("//")) {
// This is a relative path, so try to find it relative to the .blend file
String relativePath = name.substring(2);
// Augument the path with blender key path
BlenderKey blenderKey = blenderContext.getBlenderKey();
int idx = blenderKey.getName().lastIndexOf('/');
String blenderAssetFolder = blenderKey.getName().substring(0, idx != -1 ? idx : 0);
String absoluteName = blenderAssetFolder + '/' + relativePath;
// Directly try to load texture so AssetManager can report missing textures
try {
TextureKey key = new TextureKey(absoluteName);
key.setFlipY(true);
key.setGenerateMips(generateMipmaps);
result = assetManager.loadTexture(key);
result.setKey(key);
} catch (AssetNotFoundException | AssetLoadException e) {
LOGGER.fine(e.getLocalizedMessage());
}
} else {
// This is a full path, try to truncate it until the file can be found
// this works as the assetManager root is most probably a part of the
// image path. E.g. AssetManager has a locator at c:/Files/ and the
// texture path is c:/Files/Textures/Models/Image.jpg.
// For this we create a list with every possible full path name from
// the asset name to the root. Image.jpg, Models/Image.jpg,
// Textures/Models/Image.jpg (bingo) etc.
List<String> assetNames = new ArrayList<String>();
String[] paths = name.split("\\/");
// the asset name
StringBuilder sb = new StringBuilder(paths[paths.length - 1]);
assetNames.add(paths[paths.length - 1]);
for (int i = paths.length - 2; i >= 0; --i) {
sb.insert(0, '/');
sb.insert(0, paths[i]);
assetNames.add(0, sb.toString());
}
// Now try to locate the asset
for (String assetName : assetNames) {
try {
TextureKey key = new TextureKey(assetName);
key.setFlipY(true);
key.setGenerateMips(generateMipmaps);
AssetInfo info = assetManager.locateAsset(key);
if (info != null) {
Texture texture = assetManager.loadTexture(key);
result = texture;
// Set key explicitly here if other ways fail
texture.setKey(key);
// If texture is found return it;
return result;
}
} catch (AssetNotFoundException | AssetLoadException e) {
LOGGER.fine(e.getLocalizedMessage());
}
}
// the missing asset to subsystems.
try {
TextureKey key = new TextureKey(name);
assetManager.loadTexture(key);
} catch (AssetNotFoundException | AssetLoadException e) {
LOGGER.fine(e.getLocalizedMessage());
}
}
return result;
}
use of com.jme3.asset.BlenderKey in project jmonkeyengine by jMonkeyEngine.
the class BlenderLoader method load.
@Override
public Spatial load(AssetInfo assetInfo) throws IOException {
try {
BlenderContext blenderContext = this.setup(assetInfo);
AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.class);
animationHelper.loadAnimations();
BlenderKey blenderKey = blenderContext.getBlenderKey();
LoadedFeatures loadedFeatures = new LoadedFeatures();
for (FileBlockHeader block : blenderContext.getBlocks()) {
switch(block.getCode()) {
case BLOCK_OB00:
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
Node object = (Node) objectHelper.toObject(block.getStructure(blenderContext), blenderContext);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "{0}: {1}--> {2}", new Object[] { object.getName(), object.getLocalTranslation().toString(), object.getParent() == null ? "null" : object.getParent().getName() });
}
if (object.getParent() == null) {
loadedFeatures.objects.add(object);
}
if (object instanceof LightNode && ((LightNode) object).getLight() != null) {
loadedFeatures.lights.add(((LightNode) object).getLight());
} else if (object instanceof CameraNode && ((CameraNode) object).getCamera() != null) {
loadedFeatures.cameras.add(((CameraNode) object).getCamera());
}
break;
case // Scene
BLOCK_SC00:
loadedFeatures.sceneBlocks.add(block);
break;
case // Material
BLOCK_MA00:
MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
MaterialContext materialContext = materialHelper.toMaterialContext(block.getStructure(blenderContext), blenderContext);
loadedFeatures.materials.add(materialContext);
break;
case // Mesh
BLOCK_ME00:
MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
TemporalMesh temporalMesh = meshHelper.toTemporalMesh(block.getStructure(blenderContext), blenderContext);
loadedFeatures.meshes.add(temporalMesh);
break;
case // Image
BLOCK_IM00:
TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class);
Texture image = textureHelper.loadImageAsTexture(block.getStructure(blenderContext), 0, blenderContext);
if (image != null && image.getImage() != null) {
// render results are stored as images but are not being loaded
loadedFeatures.images.add(image);
}
break;
case BLOCK_TE00:
Structure textureStructure = block.getStructure(blenderContext);
int type = ((Number) textureStructure.getFieldValue("type")).intValue();
if (type == TextureHelper.TEX_IMAGE) {
TextureHelper texHelper = blenderContext.getHelper(TextureHelper.class);
Texture texture = texHelper.getTexture(textureStructure, null, blenderContext);
if (texture != null) {
// null is returned when texture has no image
loadedFeatures.textures.add(texture);
}
} else {
LOGGER.fine("Only image textures can be loaded as unlinked assets. Generated textures will be applied to an existing object.");
}
break;
case // World
BLOCK_WO00:
LandscapeHelper landscapeHelper = blenderContext.getHelper(LandscapeHelper.class);
Structure worldStructure = block.getStructure(blenderContext);
String worldName = worldStructure.getName();
if (blenderKey.getUsedWorld() == null || blenderKey.getUsedWorld().equals(worldName)) {
Light ambientLight = landscapeHelper.toAmbientLight(worldStructure);
if (ambientLight != null) {
loadedFeatures.objects.add(new LightNode(null, ambientLight));
loadedFeatures.lights.add(ambientLight);
}
loadedFeatures.sky = landscapeHelper.toSky(worldStructure);
loadedFeatures.backgroundColor = landscapeHelper.toBackgroundColor(worldStructure);
Filter fogFilter = landscapeHelper.toFog(worldStructure);
if (fogFilter != null) {
loadedFeatures.filters.add(landscapeHelper.toFog(worldStructure));
}
}
break;
case BLOCK_AC00:
LOGGER.fine("Loading unlinked animations is not yet supported!");
break;
default:
LOGGER.log(Level.FINEST, "Ommiting the block: {0}.", block.getCode());
}
}
LOGGER.fine("Baking constraints after every feature is loaded.");
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
constraintHelper.bakeConstraints(blenderContext);
LOGGER.fine("Loading scenes and attaching them to the root object.");
for (FileBlockHeader sceneBlock : loadedFeatures.sceneBlocks) {
loadedFeatures.scenes.add(this.toScene(sceneBlock.getStructure(blenderContext), blenderContext));
}
LOGGER.fine("Creating the root node of the model and applying loaded nodes of the scene and loaded features to it.");
Node modelRoot = new Node(blenderKey.getName());
for (Node scene : loadedFeatures.scenes) {
modelRoot.attachChild(scene);
}
if (blenderKey.isLoadUnlinkedAssets()) {
LOGGER.fine("Setting loaded content as user data in resulting sptaial.");
Map<String, Map<String, Object>> linkedData = new HashMap<String, Map<String, Object>>();
Map<String, Object> thisFileData = new HashMap<String, Object>();
thisFileData.put("scenes", loadedFeatures.scenes == null ? new ArrayList<Object>() : loadedFeatures.scenes);
thisFileData.put("objects", loadedFeatures.objects == null ? new ArrayList<Object>() : loadedFeatures.objects);
thisFileData.put("meshes", loadedFeatures.meshes == null ? new ArrayList<Object>() : loadedFeatures.meshes);
thisFileData.put("materials", loadedFeatures.materials == null ? new ArrayList<Object>() : loadedFeatures.materials);
thisFileData.put("textures", loadedFeatures.textures == null ? new ArrayList<Object>() : loadedFeatures.textures);
thisFileData.put("images", loadedFeatures.images == null ? new ArrayList<Object>() : loadedFeatures.images);
thisFileData.put("animations", loadedFeatures.animations == null ? new ArrayList<Object>() : loadedFeatures.animations);
thisFileData.put("cameras", loadedFeatures.cameras == null ? new ArrayList<Object>() : loadedFeatures.cameras);
thisFileData.put("lights", loadedFeatures.lights == null ? new ArrayList<Object>() : loadedFeatures.lights);
thisFileData.put("filters", loadedFeatures.filters == null ? new ArrayList<Object>() : loadedFeatures.filters);
thisFileData.put("backgroundColor", loadedFeatures.backgroundColor);
thisFileData.put("sky", loadedFeatures.sky);
linkedData.put("this", thisFileData);
linkedData.putAll(blenderContext.getLinkedFeatures());
modelRoot.setUserData("linkedData", linkedData);
}
return modelRoot;
} catch (BlenderFileException e) {
throw new IOException(e.getLocalizedMessage(), e);
} catch (Exception e) {
throw new IOException("Unexpected importer exception occured: " + e.getLocalizedMessage(), e);
} finally {
this.clear(assetInfo);
}
}
use of com.jme3.asset.BlenderKey in project jmonkeyengine by jMonkeyEngine.
the class AbstractBlenderHelper method loadLibrary.
/**
* The method loads library of a given ID from linked blender file.
* @param id
* the ID of the linked feature (it contains its name and blender path)
* @return loaded feature or null if none was found
* @throws BlenderFileException
* and exception is throw when problems with reading a blend file occur
*/
protected Object loadLibrary(Structure id) throws BlenderFileException {
Pointer pLib = (Pointer) id.getFieldValue("lib");
if (pLib.isNotNull()) {
// we need full name with the prefix
String fullName = id.getFieldValue("name").toString();
String nameOfFeatureToLoad = id.getName();
Structure library = pLib.fetchData().get(0);
String path = library.getFieldValue("filepath").toString();
if (!blenderContext.getLinkedFeatures().keySet().contains(path)) {
Spatial loadedAsset = null;
BlenderKey blenderKey = new BlenderKey(path);
blenderKey.setLoadUnlinkedAssets(true);
try {
loadedAsset = blenderContext.getAssetManager().loadAsset(blenderKey);
} catch (AssetNotFoundException e) {
LOGGER.log(Level.FINEST, "Cannot locate linked resource at path: {0}.", path);
}
if (loadedAsset != null) {
Map<String, Map<String, Object>> linkedData = loadedAsset.getUserData("linkedData");
for (Entry<String, Map<String, Object>> entry : linkedData.entrySet()) {
String linkedDataFilePath = "this".equals(entry.getKey()) ? path : entry.getKey();
blenderContext.getLinkedFeatures().put(linkedDataFilePath, entry.getValue());
}
} else {
LOGGER.log(Level.WARNING, "No features loaded from path: {0}.", path);
}
}
Object result = blenderContext.getLinkedFeature(path, fullName);
if (result == null) {
LOGGER.log(Level.WARNING, "Could NOT find asset named {0} in the library of path: {1}.", new Object[] { nameOfFeatureToLoad, path });
} else {
blenderContext.addLoadedFeatures(id.getOldMemoryAddress(), LoadedDataType.STRUCTURE, id);
blenderContext.addLoadedFeatures(id.getOldMemoryAddress(), LoadedDataType.FEATURE, result);
}
return result;
} else {
LOGGER.warning("Library link points to nothing!");
}
return null;
}
use of com.jme3.asset.BlenderKey in project jmonkeyengine by jMonkeyEngine.
the class BlenderLoader method setup.
/**
* 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 BlenderContext setup(AssetInfo assetInfo) throws BlenderFileException {
// registering loaders
ModelKey modelKey = (ModelKey) assetInfo.getKey();
BlenderKey blenderKey;
if (modelKey instanceof BlenderKey) {
blenderKey = (BlenderKey) modelKey;
} else {
blenderKey = new BlenderKey(modelKey.getName());
}
// opening stream
BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream());
// reading blocks
List<FileBlockHeader> blocks = new ArrayList<FileBlockHeader>();
FileBlockHeader fileBlock;
BlenderContext blenderContext = new BlenderContext();
blenderContext.setBlenderVersion(inputStream.getVersionNumber());
blenderContext.setAssetManager(assetInfo.getManager());
blenderContext.setInputStream(inputStream);
blenderContext.setBlenderKey(blenderKey);
// creating helpers
blenderContext.putHelper(AnimationHelper.class, new AnimationHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(TextureHelper.class, new TextureHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(MeshHelper.class, new MeshHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(ObjectHelper.class, new ObjectHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(CurvesHelper.class, new CurvesHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(LightHelper.class, new LightHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(CameraHelper.class, new CameraHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(ModifierHelper.class, new ModifierHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(MaterialHelper.class, new MaterialHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(ConstraintHelper.class, new ConstraintHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber(), blenderContext));
blenderContext.putHelper(LandscapeHelper.class, new LandscapeHelper(inputStream.getVersionNumber(), blenderContext));
// reading the blocks (dna block is automatically saved in the blender context when found)
FileBlockHeader sceneFileBlock = null;
do {
fileBlock = new FileBlockHeader(inputStream, blenderContext);
if (!fileBlock.isDnaBlock()) {
blocks.add(fileBlock);
// save the scene's file block
if (fileBlock.getCode() == BlockCode.BLOCK_SC00) {
sceneFileBlock = fileBlock;
}
}
} while (!fileBlock.isLastBlock());
if (sceneFileBlock != null) {
blenderContext.setSceneStructure(sceneFileBlock.getStructure(blenderContext));
}
// adding locator for linked content
assetInfo.getManager().registerLocator(assetInfo.getKey().getName(), LinkedContentLocator.class);
return blenderContext;
}
Aggregations