I'm trying to render a model for the main character but no matter which vector or rotation I put in he is hanging in the air, all I see are his feet and they are turned the wrong way:
When I press walk, the green person moves but backwards and I couldn't fix it with a rotation around the Y:
character = new CharacterControl(capsule, 0.01f);
model = (Node) assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
model.setLocalScale(0.15f);
Quaternion yaw90 = new Quaternion();
Quaternion roll90 = new Quaternion();
Quaternion pitch90 = new Quaternion();
yaw90.fromAngles(1, 0, 0);
roll90.fromAngles(0, 1, 0);
pitch90.fromAngles(0, 0, 1);
model.rotate(roll90);
model.addControl(character);
character.setPhysicsLocation(new Vector3f(-140, 15, -10));
rootNode.attachChild(model);
The complete code for the entire scene is
package adventure;
import java.applet.Applet;
import com.jme3.math.Quaternion;
import com.jme3.math.FastMath;
import java.applet.AudioClip;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.TextArea;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import com.jme3.material.RenderState.FaceCullMode;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.BlenderKey;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.bullet.collision.PhysicsCollisionListener;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh.Type;
import com.jme3.effect.shapes.EmitterSphereShape;
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.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.BloomFilter;
import com.jme3.renderer.Camera;
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.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.scene.shape.Sphere.TextureMode;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeCanvasContext;
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;
public class MountainWorld extends SimpleApplication implements ActionListener,
PhysicsCollisionListener, AnimEventListener, Playable {
private static World world;
private static Person person;
private static Player dplayer;
private static TextArea textarea;
private BulletAppState bulletAppState;
private AnimChannel channel;
private AnimControl control;
// character
CharacterControl character;
Node model;
// temp vectors
Vector3f walkDirection = new Vector3f();
// terrain
TerrainQuad terrain;
RigidBodyControl terrainPhysicsNode;
// Materials
Material matRock;
Material matBullet;
// animation
AnimChannel animationChannel;
AnimChannel shootingChannel;
AnimControl animationControl;
float airTime = 0;
// camera
boolean left = false, right = false, up = false, down = false;
ChaseCamera chaseCam;
// bullet
Sphere bullet;
SphereCollisionShape bulletCollisionShape;
// explosion
ParticleEmitter effect;
// brick wall
Box brick;
float bLength = 0.8f;
float bWidth = 0.4f;
float bHeight = 0.4f;
FilterPostProcessor fpp;
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
AppSettings settings = new AppSettings(true);
settings.setWidth(850);
settings.setHeight(440);
MountainWorld canvasApplication = new MountainWorld();
canvasApplication.setSettings(settings);
canvasApplication.createCanvas(); // create canvas!
JmeCanvasContext ctx = (JmeCanvasContext) canvasApplication
.getContext();
ctx.setSystemListener(canvasApplication);
Dimension dim = new Dimension(640, 480);
ctx.getCanvas().setPreferredSize(dim);
JFrame window = new JFrame("Mountain World");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout()); // a panel
world = new DungeonWorld(canvasApplication);
person = new Person(world, "You", null);
dplayer = new Player(world, person);
Commands commands = new Commands(person);
textarea = new TextArea("", 10, 60,
TextArea.SCROLLBARS_VERTICAL_ONLY);
textarea.append("You are in a mountain. The trolls live here.\n");
textarea.setEditable(false);
panel.add("West", ctx.getCanvas());
panel.add("East", commands);
panel.add("South", textarea);
window.add(panel);
window.pack();
window.setVisible(true);
canvasApplication.startCanvas();
}
});
}
@Override
public void simpleInitApp() {
bulletAppState = new BulletAppState();
bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL);
stateManager.attach(bulletAppState);
setupKeys();
prepareBullet();
prepareEffect();
createLight();
createSky();
createTerrain();
createWall();
createCharacters();
setupChaseCamera();
setupAnimationController();
setupFilter();
}
private void setupFilter() {
FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
BloomFilter bloom = new BloomFilter(BloomFilter.GlowMode.Objects);
fpp.addFilter(bloom);
viewPort.addProcessor(fpp);
}
private PhysicsSpace getPhysicsSpace() {
return bulletAppState.getPhysicsSpace();
}
private void setupKeys() {
inputManager.addMapping("wireframe", new KeyTrigger(KeyInput.KEY_T));
inputManager.addListener(this, "wireframe");
inputManager.addMapping("CharLeft", new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping("CharRight", new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping("CharUp", new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping("CharDown", new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping("CharSpace",
new KeyTrigger(KeyInput.KEY_RETURN));
inputManager
.addMapping("CharShoot", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addListener(this, "CharLeft");
inputManager.addListener(this, "CharRight");
inputManager.addListener(this, "CharUp");
inputManager.addListener(this, "CharDown");
inputManager.addListener(this, "CharSpace");
inputManager.addListener(this, "CharShoot");
}
private void createWall() {
float xOff = -144;
float zOff = -40;
float startpt = bLength / 4 - xOff;
float height = 6.1f;
brick = new Box(Vector3f.ZERO, bLength, bHeight, bWidth);
brick.scaleTextureCoordinates(new Vector2f(1f, .5f));
for (int j = 0; j < 15; j++) {
for (int i = 0; i < 4; i++) {
Vector3f vt = new Vector3f(i * bLength * 2 + startpt, bHeight
+ height, zOff);
addBrick(vt);
}
startpt = -startpt;
height += 1.01f * bHeight;
}
}
private void addBrick(Vector3f ori) {
Geometry reBoxg = new Geometry("brick", brick);
reBoxg.setMaterial(matBullet);
reBoxg.setLocalTranslation(ori);
reBoxg.addControl(new RigidBodyControl(1.5f));
reBoxg.setShadowMode(ShadowMode.CastAndReceive);
this.rootNode.attachChild(reBoxg);
this.getPhysicsSpace().add(reBoxg);
}
private void prepareBullet() {
bullet = new Sphere(32, 32, 0.4f, true, false);
bullet.setTextureMode(TextureMode.Projected);
bulletCollisionShape = new SphereCollisionShape(0.4f);
matBullet = new Material(getAssetManager(),
"Common/MatDefs/Misc/Unshaded.j3md");
matBullet.setColor("Color", ColorRGBA.Green);
// matBullet.setColor("m_GlowColor", ColorRGBA.Green);
getPhysicsSpace().addCollisionListener(this);
}
private void prepareEffect() {
int COUNT_FACTOR = 1;
float COUNT_FACTOR_F = 1f;
effect = new ParticleEmitter("Flame", Type.Triangle, 32 * COUNT_FACTOR);
effect.setSelectRandomImage(true);
effect.setStartColor(new ColorRGBA(1f, 0.4f, 0.05f,
(float) (1f / COUNT_FACTOR_F)));
effect.setEndColor(new ColorRGBA(.4f, .22f, .12f, 0f));
effect.setStartSize(1.3f);
effect.setEndSize(2f);
effect.setShape(new EmitterSphereShape(Vector3f.ZERO, 1f));
effect.setParticlesPerSec(0);
effect.setGravity(0, -5, 0);
effect.setLowLife(.4f);
effect.setHighLife(.5f);
effect.setInitialVelocity(new Vector3f(0, 7, 0));
effect.setVelocityVariation(1f);
effect.setImagesX(2);
effect.setImagesY(2);
Material mat = new Material(assetManager,
"Common/MatDefs/Misc/Particle.j3md");
mat.setTexture("Texture",
assetManager.loadTexture("Effects/Explosion/flame.png"));
effect.setMaterial(mat);
// effect.setLocalScale(100);
rootNode.attachChild(effect);
}
private void createLight() {
Vector3f direction = new Vector3f(-0.1f, -0.7f, -1).normalizeLocal();
DirectionalLight dl = new DirectionalLight();
dl.setDirection(direction);
dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));
rootNode.addLight(dl);
}
private void createSky() {
rootNode.attachChild(SkyFactory.createSky(assetManager,
"Textures/Sky/Bright/BrightSky.dds", false));
}
private void createTerrain() {
matRock = new Material(assetManager,
"Common/MatDefs/Terrain/TerrainLighting.j3md");
matRock.setBoolean("useTriPlanarMapping", false);
matRock.setBoolean("WardIso", true);
matRock.setTexture("AlphaMap",
assetManager.loadTexture("Textures/Terrain/splat/alphamap.png"));
Texture heightMapImage = assetManager
.loadTexture("Textures/Terrain/splat/mountains512.png");
Texture grass = assetManager
.loadTexture("Textures/Terrain/splat/grass.jpg");
grass.setWrap(WrapMode.Repeat);
matRock.setTexture("DiffuseMap", grass);
matRock.setFloat("DiffuseMap_0_scale", 64);
Texture dirt = assetManager
.loadTexture("Textures/Terrain/splat/dirt.jpg");
dirt.setWrap(WrapMode.Repeat);
matRock.setTexture("DiffuseMap_1", dirt);
matRock.setFloat("DiffuseMap_1_scale", 16);
Texture rock = assetManager
.loadTexture("Textures/Terrain/splat/road.jpg");
rock.setWrap(WrapMode.Repeat);
matRock.setTexture("DiffuseMap_2", rock);
matRock.setFloat("DiffuseMap_2_scale", 128);
Texture normalMap0 = assetManager
.loadTexture("Textures/Terrain/splat/grass_normal.jpg");
normalMap0.setWrap(WrapMode.Repeat);
Texture normalMap1 = assetManager
.loadTexture("Textures/Terrain/splat/dirt_normal.png");
normalMap1.setWrap(WrapMode.Repeat);
Texture normalMap2 = assetManager
.loadTexture("Textures/Terrain/splat/road_normal.png");
normalMap2.setWrap(WrapMode.Repeat);
matRock.setTexture("NormalMap", normalMap0);
matRock.setTexture("NormalMap_1", normalMap2);
matRock.setTexture("NormalMap_2", normalMap2);
AbstractHeightMap heightmap = null;
try {
heightmap = new ImageBasedHeightMap(heightMapImage.getImage(),
0.25f);
heightmap.load();
} catch (Exception e) {
e.printStackTrace();
}
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.setLocalScale(new Vector3f(2, 2, 2));
terrainPhysicsNode = new RigidBodyControl(
CollisionShapeFactory.createMeshShape(terrain), 0);
terrain.addControl(terrainPhysicsNode);
rootNode.attachChild(terrain);
getPhysicsSpace().add(terrainPhysicsNode);
}
private void createCharacters() {
CapsuleCollisionShape capsule = new CapsuleCollisionShape(3f, 4f);
character = new CharacterControl(capsule, 0.01f);
model = (Node) assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
model.setLocalScale(0.15f);
Quaternion yaw90 = new Quaternion();
Quaternion roll90 = new Quaternion();
Quaternion pitch90 = new Quaternion();
yaw90.fromAngles(1, 0, 0);
roll90.fromAngles(0, 1, 0);
pitch90.fromAngles(0, 0, 1);
model.rotate(roll90);
model.addControl(character);
character.setPhysicsLocation(new Vector3f(-140, 15, -10));
rootNode.attachChild(model);
getPhysicsSpace().add(character);
BlenderKey blenderKey = new BlenderKey(
"objects/creatures/alien/alien.mesh.xml");
Node alien = (Node) assetManager.loadModel(blenderKey);
alien.setLocalTranslation(new Vector3f(-145, 15, -10));
//Geometry geom=(Geometry)alien.getChild("myGeometry");
//geom.getMaterial().getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);
rootNode.attachChild(alien);
BlenderKey blenderKey2 = new BlenderKey(
"objects/creatures/spaceman/man.mesh.xml");
Spatial man = (Spatial) assetManager.loadModel(blenderKey2);
man.setLocalTranslation(new Vector3f(-140, 15, -10));
rootNode.attachChild(man);
}
private void setupChaseCamera() {
flyCam.setEnabled(false);
chaseCam = new ChaseCamera(cam, model, inputManager);
}
private void setupAnimationController() {
animationControl = model.getControl(AnimControl.class);
animationControl.addListener(this);
animationChannel = animationControl.createChannel();
//shootingChannel = animationControl.createChannel();
//shootingChannel.addBone(animationControl.getSkeleton().getBone(
// "uparm.right"));
//shootingChannel.addBone(animationControl.getSkeleton().getBone(
// "arm.right"));
//shootingChannel.addBone(animationControl.getSkeleton().getBone(
// "hand.right"));
}
@Override
public void simpleUpdate(float tpf) {
Vector3f camDir = cam.getDirection().clone().multLocal(0.1f);
Vector3f camLeft = cam.getLeft().clone().multLocal(0.1f);
camDir.y = 0;
camLeft.y = 0;
walkDirection.set(0, 0, 0);
if (left) {
walkDirection.addLocal(camLeft);
}
if (right) {
walkDirection.addLocal(camLeft.negate());
}
if (up) {
walkDirection.addLocal(camDir);
}
if (down) {
walkDirection.addLocal(camDir.negate());
}
if (!character.onGround()) {
airTime = airTime + tpf;
} else {
airTime = 0;
}
if (walkDirection.length() == 0) {
if (!"Idle1".equals(animationChannel.getAnimationName())) {
animationChannel.setAnim("Idle1", 1f);
}
} else {
character.setViewDirection(walkDirection);
if (airTime > .3f) {
if (!"stand".equals(animationChannel.getAnimationName())) {
animationChannel.setAnim("stand");
}
} else if (!"Walk".equals(animationChannel.getAnimationName())) {
animationChannel.setAnim("Walk", 0.7f);
}
}
character.setWalkDirection(walkDirection);
}
public void onAction(String binding, boolean value, float tpf) {
if (binding.equals("CharLeft")) {
if (value) {
left = true;
} else {
left = false;
}
} else if (binding.equals("CharRight")) {
if (value) {
right = true;
} else {
right = false;
}
} else if (binding.equals("CharUp")) {
if (value) {
up = true;
} else {
up = false;
}
} else if (binding.equals("CharDown")) {
if (value) {
down = true;
} else {
down = false;
}
} else if (binding.equals("CharSpace")) {
character.jump();
} else if (binding.equals("CharShoot") && !value) {
bulletControl();
}
}
private void bulletControl() {
shootingChannel.setAnim("Dodge", 0.1f);
shootingChannel.setLoopMode(LoopMode.DontLoop);
Geometry bulletg = new Geometry("bullet", bullet);
bulletg.setMaterial(matBullet);
bulletg.setShadowMode(ShadowMode.CastAndReceive);
bulletg.setLocalTranslation(character.getPhysicsLocation().add(
cam.getDirection().mult(5)));
RigidBodyControl bulletControl = new BombControl(bulletCollisionShape,
1);
bulletControl.setCcdMotionThreshold(0.1f);
bulletControl.setLinearVelocity(cam.getDirection().mult(80));
bulletg.addControl(bulletControl);
rootNode.attachChild(bulletg);
getPhysicsSpace().add(bulletControl);
}
public void collision(PhysicsCollisionEvent event) {
if (event.getObjectA() instanceof BombControl) {
final Spatial node = event.getNodeA();
effect.killAllParticles();
effect.setLocalTranslation(node.getLocalTranslation());
effect.emitAllParticles();
} else if (event.getObjectB() instanceof BombControl) {
final Spatial node = event.getNodeB();
effect.killAllParticles();
effect.setLocalTranslation(node.getLocalTranslation());
effect.emitAllParticles();
}
}
public void onAnimCycleDone(AnimControl control, AnimChannel channel,
String animName) {
if (channel == shootingChannel) {
channel.setAnim("stand");
}
}
public void onAnimChange(AnimControl control, AnimChannel channel,
String animName) {
}
// Load an image from the net, making sure it has already been
// loaded when the method returns
public Image loadPicture(String imageName) {
return null;
}
// Load and play a sound from /usr/local/hacks/sounds/
public void playSound(String name) {
URL u = null;
try {
u = new URL("file:" + "/usr/local/hacks/sounds/" + name + ".au");
} catch (MalformedURLException e) {
}
AudioClip a = Applet.newAudioClip(u);
a.play();
}
}
I'm wondering how to render my green ninja with the back natural towards the camer an player being able to control the ninja and walk the ninja which now works but with wrong location (in the air) and I can't seem to adjust the position.
Any suggestions?
Update
The following code appears the improve the position of the green person:
private void createCharacters() {
CapsuleCollisionShape capsule = new CapsuleCollisionShape(3f, 4f);
character = new CharacterControl(capsule, 0.01f);
model = (Node) assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
model.setLocalScale(0.15f);
model.addControl(character);
character.setPhysicsLocation(new Vector3f(-140, 20, -9));
character.setViewDirection(new Vector3f(1, 1, 1));
rootNode.attachChild(model);
getPhysicsSpace().add(character);
BlenderKey blenderKey = new BlenderKey(
"objects/creatures/alien/alien.mesh.xml");
Node alien = (Node) assetManager.loadModel(blenderKey);
alien.setLocalTranslation(new Vector3f(-145, 15, -10));
rootNode.attachChild(alien);
BlenderKey blenderKey2 = new BlenderKey(
"objects/creatures/spaceman/man.mesh.xml");
Spatial man = (Spatial) assetManager.loadModel(blenderKey2);
man.setLocalTranslation(new Vector3f(-140, 15, -10));
rootNode.attachChild(man);
}
But walking still works somewhat like the opposite of what it should. But I'm glad that I at least could improve the scene so that the main character is rotated properly. I'll update with another screenshot and more details a.s.a.p.
Please answer or comment with any improvement suggestion.
Update
I could rotate the green person but will harmonize the models in blender also:
private void createCharacters() {
CapsuleCollisionShape capsule = new CapsuleCollisionShape(3f, 4f);
character = new CharacterControl(capsule, 0.01f);
model = (Node) assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
model.setLocalScale(0.15f);
model.addControl(character);
character.setPhysicsLocation(new Vector3f(-140, 20, -9));
character.setViewDirection(new Vector3f(1, 1, 1));
rootNode.attachChild(model);
getPhysicsSpace().add(character);
BlenderKey blenderKey = new BlenderKey(
"objects/creatures/alien/alien.mesh.xml");
Node alien = (Node) assetManager.loadModel(blenderKey);
alien.setLocalTranslation(new Vector3f(-145, 15, -10));
rootNode.attachChild(alien);
BlenderKey blenderKey2 = new BlenderKey(
"objects/creatures/spaceman/man.mesh.xml");
Spatial man = (Spatial) assetManager.loadModel(blenderKey2);
man.setLocalTranslation(new Vector3f(-140, 15, -10));
rootNode.attachChild(man);
}