com.jme3.scene.plugins.blender.landscape.LandscapeHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jme3-blender Show documentation
Show all versions of jme3-blender Show documentation
jMonkeyEngine is a 3D game engine for adventurous Java developers
The newest version!
package com.jme3.scene.plugins.blender.landscape;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.light.AmbientLight;
import com.jme3.light.Light;
import com.jme3.math.ColorRGBA;
import com.jme3.post.filters.FogFilter;
import com.jme3.scene.Spatial;
import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.textures.ColorBand;
import com.jme3.scene.plugins.blender.textures.CombinedTexture;
import com.jme3.scene.plugins.blender.textures.ImageUtils;
import com.jme3.scene.plugins.blender.textures.TextureHelper;
import com.jme3.scene.plugins.blender.textures.TexturePixel;
import com.jme3.scene.plugins.blender.textures.io.PixelIOFactory;
import com.jme3.scene.plugins.blender.textures.io.PixelInputOutput;
import com.jme3.texture.Image;
import com.jme3.texture.Image.Format;
import com.jme3.texture.TextureCubeMap;
import com.jme3.util.SkyFactory;
/**
* The class that allows to load the following: the ambient light of the scene the sky of the scene (with or without texture)
*
* @author Marcin Roguski (Kaelthas)
*/
public class LandscapeHelper extends AbstractBlenderHelper {
private static final Logger LOGGER = Logger.getLogger(LandscapeHelper.class.getName());
private static final int SKYTYPE_BLEND = 1;
private static final int SKYTYPE_REAL = 2;
private static final int SKYTYPE_PAPER = 4;
private static final int MODE_MIST = 0x01;
public LandscapeHelper(String blenderVersion, BlenderContext blenderContext) {
super(blenderVersion, blenderContext);
}
/**
* Loads scene ambient light.
* @param worldStructure
* the world's blender structure
* @return the scene's ambient light
*/
public Light toAmbientLight(Structure worldStructure) {
LOGGER.fine("Loading ambient light.");
AmbientLight ambientLight = null;
float ambr = ((Number) worldStructure.getFieldValue("ambr")).floatValue();
float ambg = ((Number) worldStructure.getFieldValue("ambg")).floatValue();
float ambb = ((Number) worldStructure.getFieldValue("ambb")).floatValue();
if (ambr > 0 || ambg > 0 || ambb > 0) {
ambientLight = new AmbientLight();
ColorRGBA ambientLightColor = new ColorRGBA(ambr, ambg, ambb, 0.0f);
ambientLight.setColor(ambientLightColor);
LOGGER.log(Level.FINE, "Loaded ambient light: {0}.", ambientLightColor);
} else {
LOGGER.finer("Ambient light is set to BLACK which means: no ambient light! The ambient light node will not be included in the result.");
}
return ambientLight;
}
/**
* The method loads fog for the scene.
* NOTICE! Remember to manually set the distance and density of the fog.
* Unfortunately blender's fog parameters in no way fit to the JME.
* @param worldStructure
* the world's structure
* @return fog filter or null if scene does not define it
*/
public FogFilter toFog(Structure worldStructure) {
FogFilter result = null;
int mode = ((Number) worldStructure.getFieldValue("mode")).intValue();
if ((mode & MODE_MIST) != 0) {
LOGGER.fine("Loading fog.");
result = new FogFilter();
result.setName("FIfog");
result.setFogColor(this.toBackgroundColor(worldStructure));
}
return result;
}
/**
* Loads the background color.
* @param worldStructure
* the world's structure
* @return the horizon color of the world which is used as a background color.
*/
public ColorRGBA toBackgroundColor(Structure worldStructure) {
float horr = ((Number) worldStructure.getFieldValue("horr")).floatValue();
float horg = ((Number) worldStructure.getFieldValue("horg")).floatValue();
float horb = ((Number) worldStructure.getFieldValue("horb")).floatValue();
return new ColorRGBA(horr, horg, horb, 1);
}
/**
* Loads scene's sky. Sky can be plain or textured.
* If no sky type is selected in blender then no sky is loaded.
* @param worldStructure
* the world's structure
* @return the scene's sky
* @throws BlenderFileException
* blender exception is thrown when problems with blender file occur
*/
public Spatial toSky(Structure worldStructure) throws BlenderFileException {
int skytype = ((Number) worldStructure.getFieldValue("skytype")).intValue();
if (skytype == 0) {
return null;
}
LOGGER.fine("Loading sky.");
ColorRGBA horizontalColor = this.toBackgroundColor(worldStructure);
float zenr = ((Number) worldStructure.getFieldValue("zenr")).floatValue();
float zeng = ((Number) worldStructure.getFieldValue("zeng")).floatValue();
float zenb = ((Number) worldStructure.getFieldValue("zenb")).floatValue();
ColorRGBA zenithColor = new ColorRGBA(zenr, zeng, zenb, 1);
// jutr for this case load generated textures wheather user had set it or not because those might be needed to properly load the sky
boolean loadGeneratedTextures = blenderContext.getBlenderKey().isLoadGeneratedTextures();
blenderContext.getBlenderKey().setLoadGeneratedTextures(true);
TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class);
List loadedTextures = null;
try {
loadedTextures = textureHelper.readTextureData(worldStructure, new float[] { horizontalColor.r, horizontalColor.g, horizontalColor.b, horizontalColor.a }, true);
} finally {
blenderContext.getBlenderKey().setLoadGeneratedTextures(loadGeneratedTextures);
}
TextureCubeMap texture = null;
if (loadedTextures != null && loadedTextures.size() > 0) {
if (loadedTextures.size() > 1) {
throw new IllegalStateException("There should be only one combined texture for sky!");
}
CombinedTexture combinedTexture = loadedTextures.get(0);
texture = combinedTexture.generateSkyTexture(horizontalColor, zenithColor, blenderContext);
} else {
LOGGER.fine("Preparing colors for colorband.");
int colorbandType = ColorBand.IPO_CARDINAL;
List colorbandColors = new ArrayList(3);
colorbandColors.add(horizontalColor);
if ((skytype & SKYTYPE_BLEND) != 0) {
if ((skytype & SKYTYPE_PAPER) != 0) {
colorbandType = ColorBand.IPO_LINEAR;
}
if ((skytype & SKYTYPE_REAL) != 0) {
colorbandColors.add(0, zenithColor);
}
colorbandColors.add(zenithColor);
}
int size = blenderContext.getBlenderKey().getSkyGeneratedTextureSize();
List positions = new ArrayList(colorbandColors.size());
positions.add(0);
if (colorbandColors.size() == 2) {
positions.add(size - 1);
} else if (colorbandColors.size() == 3) {
positions.add(size / 2);
positions.add(size - 1);
}
LOGGER.fine("Generating sky texture.");
float[][] values = new ColorBand(colorbandType, colorbandColors, positions, size).computeValues();
Image image = ImageUtils.createEmptyImage(Format.RGB8, size, size, 6);
PixelInputOutput pixelIO = PixelIOFactory.getPixelIO(image.getFormat());
TexturePixel pixel = new TexturePixel();
LOGGER.fine("Creating side textures.");
int[] sideImagesIndexes = new int[] { 0, 1, 4, 5 };
for (int i : sideImagesIndexes) {
for (int y = 0; y < size; ++y) {
pixel.red = values[y][0];
pixel.green = values[y][1];
pixel.blue = values[y][2];
for (int x = 0; x < size; ++x) {
pixelIO.write(image, i, pixel, x, y);
}
}
}
LOGGER.fine("Creating top texture.");
pixelIO.read(image, 0, pixel, 0, image.getHeight() - 1);
for (int y = 0; y < size; ++y) {
for (int x = 0; x < size; ++x) {
pixelIO.write(image, 3, pixel, x, y);
}
}
LOGGER.fine("Creating bottom texture.");
pixelIO.read(image, 0, pixel, 0, 0);
for (int y = 0; y < size; ++y) {
for (int x = 0; x < size; ++x) {
pixelIO.write(image, 2, pixel, x, y);
}
}
texture = new TextureCubeMap(image);
}
LOGGER.fine("Sky texture created. Creating sky.");
return SkyFactory.createSky(blenderContext.getAssetManager(), texture, SkyFactory.EnvMapType.CubeMap);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy