As in title. Any suggestion is welcome !!!
[java]
import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey;
import com.jme3.asset.plugins.HttpZipLocator;
import com.jme3.asset.plugins.ZipLocator;
import com.jme3.bounding.BoundingBox;
import com.jme3.font.BitmapText;
import com.jme3.input.ChaseCamera;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Sphere;
import com.jme3.terrain.geomipmap.TerrainLodControl;
import com.jme3.terrain.geomipmap.TerrainQuad;
import com.jme3.terrain.heightmap.AbstractHeightMap;
import com.jme3.terrain.heightmap.ImageBasedHeightMap;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;
import com.jme3.util.SkyFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import jme3tools.converters.ImageToAwt;
public class TestRainLoading extends SimpleApplication {
private Sphere sphereMesh = new Sphere(32, 32, 10, false, true);
private Geometry sphere = new Geometry("Sky", sphereMesh);
private Rain rain;
private float angle1;
private Geometry ballGeom;
private ChaseCamera chaser;
private TerrainQuad terrain;
private Material matRock;
private Material matWire;
private BitmapText hintText;
protected boolean wireframe;
protected boolean rainTarget;
public static void main(String[] args) {
TestRainLoading app = new TestRainLoading();
app.start();
}
@Override
public void simpleUpdate(float tpf){
sphere.setLocalTranslation(cam.getLocation());
angle1 += tpf * 1.25f;
angle1 %= FastMath.TWO_PI;
ballGeom.setLocalTranslation(new Vector3f(FastMath.cos(angle1) * 240f, 20.5f, FastMath.sin(angle1) * 240f));
}
public void simpleInitApp() {
loadHintText();
setupKeys();
this.flyCam.setMoveSpeed(10);
flyCam.setEnabled(false);
cam.setLocation(new Vector3f(0,1000,0));
buildTerrain();
// load sky
rootNode.attachChild(SkyFactory.createSky(assetManager, "Textures/Sky/Bright/BrightSky.dds", false));
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-0.4790551f, -0.39247334f, -0.7851566f));
sun.setColor(ColorRGBA.White.clone().multLocal(2));
terrain.addLight(sun);
rain =new Rain(assetManager,cam,1);
rootNode.attachChild(rain);
Sphere ball = new Sphere(32, 32, 2f);
ballGeom = new Geometry("Ball Name", ball);
Material mat3 = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
mat3.setColor("m_Color", new ColorRGBA(0, 0, 1, 0.6f));
mat3.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
ballGeom.setMaterial(mat3);
ballGeom.setQueueBucket(Bucket.Transparent);
rootNode.attachChild(ballGeom);
chaser = new ChaseCamera(cam,ballGeom,inputManager);
chaser.setMaxDistance(1200);
chaser.setSmoothMotion(true);
rain.setTarget(ballGeom);
}
public void loadHintText() {
hintText = new BitmapText(guiFont, false);
hintText.setSize(guiFont.getCharSet().getRenderedSize());
hintText.setLocalTranslation(0, getCamera().getHeight(), 0);
hintText.setText("Hit R to switch rain targetrnHit T to switch to wireframe");
guiNode.attachChild(hintText);
}
private void setupKeys() {
flyCam.setMoveSpeed(50);
inputManager.addMapping("rain", new KeyTrigger(KeyInput.KEY_R));
inputManager.addListener(actionListener, "rain");
inputManager.addMapping("wireframe", new KeyTrigger(KeyInput.KEY_T));
inputManager.addListener(actionListener, "wireframe");
}
private ActionListener actionListener = new ActionListener() {
public void onAction(String name, boolean pressed, float tpf) {
if (name.equals("wireframe") && !pressed) {
wireframe = !wireframe;
if (!wireframe) {
terrain.setMaterial(matWire);
} else {
terrain.setMaterial(matRock);
}
}
if (name.equals("rain") && !pressed) {
rainTarget = !rainTarget;
if (!rainTarget) {
rain.setTarget(ballGeom);
chaser.setEnabled(true);
flyCam.setEnabled(false);
} else {
rain.setTarget(null);
chaser.setEnabled(false);
flyCam.setEnabled(true);
}
}
}
};
private void buildTerrain(){
// First, we load up our textures and the heightmap texture for the terrain
// TERRAIN TEXTURE material
matRock = new Material(assetManager, "Common/MatDefs/Terrain/Terrain.j3md");
// ALPHA map (for splat textures)
matRock.setTexture("m_Alpha", assetManager.loadTexture("Textures/Terrain/splat/alphamap.png"));
// HEIGHTMAP image (for the terrain heightmap)
Texture heightMapImage = assetManager.loadTexture("Textures/Terrain/splat/mountains512.png");
// GRASS texture
Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
grass.setWrap(WrapMode.Repeat);
matRock.setTexture("m_Tex1", grass);
matRock.setFloat("m_Tex1Scale", 64f);
// DIRT texture
Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
dirt.setWrap(WrapMode.Repeat);
matRock.setTexture("m_Tex2", dirt);
matRock.setFloat("m_Tex2Scale", 32f);
// ROCK texture
Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg");
rock.setWrap(WrapMode.Repeat);
matRock.setTexture("m_Tex3", rock);
matRock.setFloat("m_Tex3Scale", 128f);
// WIREFRAME material
matWire = new Material(assetManager, "Common/MatDefs/Misc/WireColor.j3md");
matWire.setColor("m_Color", ColorRGBA.Green);
// CREATE HEIGHTMAP
AbstractHeightMap heightmap = null;
try {
//heightmap = new HillHeightMap(1025, 1000, 50, 100, (byte) 3);
heightmap = new ImageBasedHeightMap(ImageToAwt.convert(heightMapImage.getImage(), false, true, 0), 1f);
heightmap.load();
} catch (Exception e) {
e.printStackTrace();
}
/*
- Here we create the actual terrain. The tiles will be 65x65, and the total size of the
- terrain will be 513x513. It uses the heightmap we created to generate the height values.
*/
/**
- Optimal terrain patch size is 65 (64x64)
- If you go for small patch size, it will definitely slow down because the depth of
- the quad tree will increase, and more is done on the CPU then to traverse it.
- I plan to give each node in the tree a reference to its neighbours so that should
- resolve any of these slowdowns. -Brent
*
- The total size is up to you. At 1025 it ran fine for me (200+FPS), however at
- size=2049, it got really slow. But that is a jump from 2 million to 8 million triangles…
/
terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap());
List<Camera> cameras = new ArrayList<Camera>();
cameras.add(getCamera());
TerrainLodControl control = new TerrainLodControl(terrain, cameras);
terrain.addControl(control);
terrain.setMaterial(matRock);
terrain.setModelBound(new BoundingBox());
terrain.updateModelBound();
terrain.setLocalTranslation(0, -100, 0);
terrain.setLocalScale(2f, 1f, 2f);
rootNode.attachChild(terrain);
}
}
[/java]
where Rain.java is:
[java]
package mypackage;
import java.util.Properties;
import java.util.logging.Logger;
import com.jme3.asset.AssetManager;
import com.jme3.bounding.BoundingSphere;
import com.jme3.effect.EmitterSphereShape;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.effect.ParticleMesh.Type;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Plane;
import com.jme3.math.Ray;
import com.jme3.math.Ring;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Sphere;
public class Rain extends Node {
private static final long serialVersionUID = -1057124936652689175L;
private static Logger log = Logger.getLogger(Rain.class.getCanonicalName());
private ParticleEmitter points;
private boolean useGravity = false;
private Node _rootNode;
private AssetManager assetManager;
private Camera cam;
private int height=440;
private Spatial target;
public Rain(AssetManager assetManager,Camera cam, int weather) {
super("rain");
this.assetManager=assetManager;
this.cam=cam;
applyParameters(weather);
Sphere ball = new Sphere(32, 32, 20f);
Geometry ballGeom = new Geometry("Ball Name", ball);
Material mat3 = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
mat3.setColor("m_Color", new ColorRGBA(1, 1, 0, 0.2f));
mat3.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
ballGeom.setMaterial(mat3);
ballGeom.setQueueBucket(Bucket.Transparent);
this.attachChild(ballGeom);
}
public void applyParameters(int weather) {
points = new ParticleEmitter("rainPoints", Type.Triangle, 800weather);
points.setShape(new EmitterSphereShape(Vector3f.ZERO, 600f));
// points.setLocalTranslation(new Vector3f(0f, height, 0f));
points.setInitialVelocity(new Vector3f(0.0f, -1.0f, 0.0f));
//points.setMaximumAngle(3.1415927f);
//points.setMinimumAngle(0.0f);
//points.setImagesX(1);
//points.setImagesY(1);
points.setGravity(1159.9fweather);
// points.setLowLife(1626.0f);
points.setLowLife(2);
points.setHighLife(5);
points.setStartSize(1.8f);
points.setEndSize(1.6f);
points.setStartColor(new ColorRGBA(0.8f, 0.8f, 1.0f, 0.8f));
points.setEndColor(new ColorRGBA(0.8f, 0.8f, 1.0f, 0.6f));
//points.setRandomAngle(randomAngle)Mod(0.0f);
points.setFacingVelocity(false);
//points.setFaceNormal(new Vector3f(0,0,1));
points.setParticlesPerSec(80000weather);
points.setVelocityVariation(20.0f);
//points.setInitialVelocity(0.58f);
points.setRotateSpeed(0.0f);
points.setShadowMode(ShadowMode.CastAndReceive);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
mat.setTexture("m_Texture", assetManager.loadTexture("textures/raindrop.png"));
points.setMaterial(mat);
points.setQueueBucket(Bucket.Transparent);
points.updateLogicalState(0);
points.updateGeometricState();
}
public void updateLogicalState(float tpf){
super.updateLogicalState(tpf);
float far=800f;
Vector3f intersection=Vector3f.ZERO;
if(target==null){
Vector3f loc=new Vector3f(cam.getLocation());
Plane piano=new Plane(loc,far);
Ray ray=new Ray(loc,cam.getDirection());
intersection=new Vector3f(cam.getLocation());
ray.intersectsWherePlane(piano, intersection);
}
else{
intersection=new Vector3f(target.getLocalTranslation());
}
intersection.y=height;
this.setLocalTranslation(intersection);
}
public Spatial getTarget() {
return target;
}
public void setTarget(Spatial target) {
this.target = target;
}
}
[/java]
just pressing R, you can switch rain follows target or cam