Main Menu
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - BLadeLaRus

#1
I am developing small game on android, some kind of 3d mahjong. Currently it has two Activities:
1) MainActivity -  starting activity with list of available maps.
2) FieldActivity - playground activity with GlSurfaceView where all show begins.
When FieldActivity starts first all goes great. But when I close it and then open it again (by selecting other map) in log appears exception(on each call World.renderScene()) and display goes black:

01-16 19:53:03.645: INFO/jPCT-AE(2004): java.lang.NullPointerException
01-16 19:53:03.645: INFO/jPCT-AE(2004):     at com.threed.jpct.CompiledInstance.fill(CompiledInstance.java:823)
01-16 19:53:03.645: INFO/jPCT-AE(2004):     at com.threed.jpct.Object3DCompiler.compile(Object3DCompiler.java:134)
01-16 19:53:03.645: INFO/jPCT-AE(2004):     at com.threed.jpct.World.compile(World.java:2029)
01-16 19:53:03.645: INFO/jPCT-AE(2004):     at com.threed.jpct.World.renderScene(World.java:1060)
01-16 19:53:03.645: INFO/jPCT-AE(2004):     at com.codand.mahjong3d.renderer.PlaygroundRenderer.onDrawFrame(PlaygroundRenderer.java:113)
01-16 19:53:03.645: INFO/jPCT-AE(2004):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1127)
01-16 19:53:03.645: INFO/jPCT-AE(2004):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:975)
01-16 19:53:03.655: INFO/jPCT-AE(2004): Additional visibility list (32) created with size: 512
01-16 19:53:03.675: INFO/jPCT-AE(2004): java.lang.NullPointerException
01-16 19:53:03.675: INFO/jPCT-AE(2004):     at com.threed.jpct.CompiledInstance.fill(CompiledInstance.java:823)
01-16 19:53:03.675: INFO/jPCT-AE(2004):     at com.threed.jpct.Object3DCompiler.compile(Object3DCompiler.java:134)
01-16 19:53:03.675: INFO/jPCT-AE(2004):     at com.threed.jpct.World.compile(World.java:2029)
01-16 19:53:03.675: INFO/jPCT-AE(2004):     at com.threed.jpct.World.renderScene(World.java:1060)
01-16 19:53:03.675: INFO/jPCT-AE(2004):     at com.codand.mahjong3d.renderer.PlaygroundRenderer.onDrawFrame(PlaygroundRenderer.java:113)
01-16 19:53:03.675: INFO/jPCT-AE(2004):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1127)
01-16 19:53:03.675: INFO/jPCT-AE(2004):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:975)
01-16 19:53:03.685: INFO/jPCT-AE(2004): Additional visibility list (33) created with size: 512
01-16 19:53:03.705: INFO/jPCT-AE(2004): java.lang.NullPointerException
01-16 19:53:03.705: INFO/jPCT-AE(2004):     at com.threed.jpct.CompiledInstance.fill(CompiledInstance.java:823)
01-16 19:53:03.705: INFO/jPCT-AE(2004):     at com.threed.jpct.Object3DCompiler.compile(Object3DCompiler.java:134)
01-16 19:53:03.705: INFO/jPCT-AE(2004):     at com.threed.jpct.World.compile(World.java:2029)
01-16 19:53:03.705: INFO/jPCT-AE(2004):     at com.threed.jpct.World.renderScene(World.java:1060)
01-16 19:53:03.705: INFO/jPCT-AE(2004):     at com.codand.mahjong3d.renderer.PlaygroundRenderer.onDrawFrame(PlaygroundRenderer.java:113)
01-16 19:53:03.705: INFO/jPCT-AE(2004):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1127)
01-16 19:53:03.705: INFO/jPCT-AE(2004):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:975)
01-16 19:53:03.714: INFO/jPCT-AE(2004): Additional visibility list (34) created with size: 512

This is source code of FiledActivity

package com.codand.mahjong3d.renderer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import com.codand.mahjong3d.entity.Model;
import com.codand.mahjong3d.entity.Tile;
import com.codand.mahjong3d.utils.Utils;
import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Interact2D;
import com.threed.jpct.Light;
import com.threed.jpct.Logger;
import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.MemoryHelper;

import android.content.Context;
import android.opengl.GLSurfaceView;

public class PlaygroundRenderer implements GLSurfaceView.Renderer,Model.ModelListener{

private static final float TILE_SCALE = (float)10.1;
private static final float TILE_MARGIN = (float)0.0;

private static final int TILE_ICON_SIZE = 60;
private static final int TILE_ICON_X = 10;
private static final int TILE_ICON_Y = 10;

private static final float MIN_CAMERA_MOVE = 150;
private static final float CAMERA_MOVE_STEP = 2;
private static final float BORDER_SIZE = 40;

private static final float SUN_DISTANCE = 1000;

private static final int START_TRANSPARENCY = 4;
private static final int TRANSPARENCY_DECREASE = 3;

private Context context;

private Model model;

private Object3D model3D;
private ArrayList<Object3D> tiles3D;
private HashMap<String,Object3D> tileMap = new HashMap<String,Object3D>();
private float[] boundingBox;
private boolean calcBoundingBox = false;

private Object3D skyPlane;

private long time = System.currentTimeMillis();
private long lastFrameTime;
private float period = 0; // time after last frame in sec


private World world;
private Light sun;
private FrameBuffer fb;
private ArrayList<Object3D> removingObjects = new ArrayList<Object3D>();

private boolean stop;
private boolean isWorldInited = false;

private RGBColor back = new RGBColor(0, 0, 0);
private RGBColor selectionColor = new RGBColor(0,500,0);

private float xImpulse = 0;
private float yImpulse = 0;
private float resist   = (float)0.02;

private int fps = 0;

public PlaygroundRenderer(Context context,Model model) {
super();
this.context = context;
this.model = model;
this.model.addListener(this);
}



public Model getModel() {
return model;
}

public void stop(){
stop = true;
}

@Override
public void onDrawFrame(GL10 arg0) {
try {
if (!stop) {
//long testTime = System.currentTimeMillis();
updatePeriod();
processCameraMovement();
removeMarkedObjects();

//Logger.log((System.currentTimeMillis() - testTime) + " dirst functions");
//testTime = System.currentTimeMillis();
fb.clear(back);
//Logger.log((System.currentTimeMillis() - testTime) + " fb.clear(back)");
//testTime = System.currentTimeMillis();
world.renderScene(fb);
//Logger.log((System.currentTimeMillis() - testTime) + " world.renderScene(fb)");
//testTime = System.currentTimeMillis();
world.draw(fb);
//Logger.log((System.currentTimeMillis() - testTime) + " world.draw(fb)");
//testTime = System.currentTimeMillis();
drawSelectionBlitting();
adjustFitness();
//Logger.log((System.currentTimeMillis() - testTime) + " adjustFitness()");
//testTime = System.currentTimeMillis();
fb.display();
//Logger.log((System.currentTimeMillis() - testTime) + " fb.display()");
//testTime = System.currentTimeMillis();
if(Math.abs(xImpulse) > 2*resist){
xImpulse = xImpulse - Math.signum(xImpulse)*resist*period;
}
if (Math.abs(yImpulse) > 2*resist ) {
yImpulse = yImpulse - Math.signum(yImpulse)*resist*period;
}

if (System.currentTimeMillis() - time >= 1000) {
Logger.log(fps + " fps");
fps = 0;
time = System.currentTimeMillis();
}
fps++;
} else {
if (fb != null) {
fb.dispose();
fb = null;
}
}
} catch (Exception e) {
Logger.log(e, Logger.MESSAGE);
}

}

@Override
public void onSurfaceChanged(GL10 gl, int w, int h) {
if (fb != null) {
fb.dispose();
}
fb = new FrameBuffer(gl, w, h);

initWorld();

/*
fb = new FrameBuffer(gl, w, h);

world = new World();
world.setAmbientLight(200, 10, 10);

sun = new Light(world);
sun.setIntensity(250, 250, 250);

// Create a texture out of the icon...:-)
if(!TextureManager.getInstance().containsTexture("texture")){
Texture texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(context.getResources().getDrawable(R.drawable.test)), 64, 64));
TextureManager.getInstance().addTexture("texture", texture);
}
cube = Primitives.getCube(10);
cube.calcTextureWrapSpherical();
cube.setTexture("texture");
cube.strip();
cube.build();

world.addObject(cube);

Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.lookAt(cube.getTransformedCenter());

SimpleVector sv = new SimpleVector();
sv.set(cube.getTransformedCenter());
sv.y -= 100;
sv.z -= 100;
sun.setPosition(sv);
MemoryHelper.compact();
*/
}

@Override
public void onSurfaceCreated(GL10 arg0, EGLConfig arg1) {
//Utils.loadTextures(context);

}

private void initWorld(){
if(model == null) return;

if(world != null){
world.removeAll();
}

world = new World();
world.setAmbientLight(200, 200, 200);

initModel();
initSky();

Camera cam = world.getCamera();

cam.setPosition(model3D.getTransformedCenter());
cam.moveCamera(Camera.CAMERA_MOVEOUT, MIN_CAMERA_MOVE);
cam.lookAt(model3D.getTransformedCenter());

sun = new Light(world);
sun.setIntensity(10, 10, 10);

SimpleVector center = model3D.getTransformedCenter();
SimpleVector dir = cam.getDirection();
dir.scalarMul(-1);
dir.add(cam.getUpVector());
SimpleVector tmp = cam.getSideVector();
tmp.scalarMul(-1);
dir.add(tmp);
dir.scalarMul(SUN_DISTANCE);
center.add(dir);
sun.setPosition(center);

MemoryHelper.compact();
isWorldInited = true;
}

private void initSky(){
skyPlane = new Object3D(2);
float offset = 1000;
skyPlane.addTriangle(new SimpleVector(-offset,-offset,0), 0, 0,
new SimpleVector(-offset,offset,0), 0, 1,
new SimpleVector(offset,offset,0), 1, 1,
TextureManager.getInstance().getTextureID(Utils.SKY_TEXTURE_NAME));

skyPlane.addTriangle(new SimpleVector(offset,offset,0), 1, 1,
new SimpleVector(offset,-offset,0), 1, 0,
new SimpleVector(-offset,-offset,0), 0, 0,
TextureManager.getInstance().getTextureID(Utils.SKY_TEXTURE_NAME));
//skyPlane.setBillboarding(Object3D.BILLBOARDING_ENABLED);
skyPlane.build();
SimpleVector center = model3D.getTransformedCenter();
center.z += 500;
skyPlane.translate(center);

world.addObject(skyPlane);
}

private void deinitModel(){
if(model3D != null){
world.removeObject(model3D);
model3D = null;
}
if(tiles3D != null){
for(int i = 0; i < tiles3D.size();i++){
world.removeObject(tiles3D.get(i));
}
tiles3D.clear();
tileMap.clear();
removingObjects.clear();
}
}

private void initModel(){
deinitModel();
model3D = Object3D.createDummyObj();

List<Tile> tiles = model.getTiles();
Object3D tile3D;
Tile tile;
tiles3D = new ArrayList<Object3D>();
tileMap.clear();
for(int i = 0;i < tiles.size();i++){
tile = tiles.get(i);
tile3D = createTile(tile);
if(i != 0){
tile3D.shareCompiledData(tiles3D.get(0));
}
//tile3D = Primitives.getCube(TILE_SCALE);
//tile3D.setUserObject(tile);
//tile3D.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
//tile3D.rotateY((float)Math.PI/4);
//tile3D.setTransparency(10);
//tile3D.translate(getTileX(tile), getTileY(tile), getTileZ(tile));
//tile3D.calcTextureWrapSpherical();
//tile3D.setTexture(Utils.getTextureByType(tile.type));

//tile3D.strip();
//tile3D.build();
tiles3D.add(tile3D);
tileMap.put(Tile.getTileKey(tile), tile3D);
world.addObject(tile3D);

}
calculateModelBoundingBox();
model3D.translate((boundingBox[1]+boundingBox[0])/2,(boundingBox[2]+boundingBox[3])/2,(boundingBox[4]+boundingBox[5])/2);
//model3D.rotateY((float)Math.PI/4);
world.addObject(model3D);
for(int i = 0;i < tiles3D.size();i++){
model3D.addChild(tiles3D.get(i));
tiles3D.get(i).translate(-(boundingBox[1]+boundingBox[0])/2, -(boundingBox[2]+boundingBox[3])/2, -(boundingBox[4]+boundingBox[5])/2);
}
}

private Object3D createTile(Tile tile){
//Object3D[] objs;
Object3D tile3D = Utils.getNewTile3D(context);
//objs = new Object3D[1];
//tile3D = Primitives.getCube(TILE_SCALE);
//tile3D.rotateY((float)Math.PI/4);
int polygonCount = tile3D.getPolygonManager().getMaxPolygonID();
Logger.log(polygonCount + " polygons in tile");
tile3D.setUserObject(tile);
tile3D.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
tile3D.translate(getTileX(tile), getTileY(tile), getTileZ(tile));
//tile3D.setTransparency(100);
//tile3D.calcTextureWrapSpherical();
tile3D.setTexture(Utils.getTextureByType(tile.type));

//tile3D.setTexture(Utils.getTextureInfoByType(tile.type));
tile3D.strip();
tile3D.build();

return tile3D;
}

private void updatePeriod(){
long curTime = System.currentTimeMillis();
if(lastFrameTime != 0){
period = (float)(curTime-lastFrameTime)/1000;
}
lastFrameTime = curTime;
}

private Object3D get(Tile tile){
String key = Tile.getTileKey(tile);
if(!tileMap.containsKey(key)) return null;

return tileMap.get(key);
}

private void remove(Tile tile){
Object3D tile3D = get(tile);
if(tile3D == null) return;
tile3D.setCollisionMode(Object3D.COLLISION_CHECK_NONE);
removingObjects.add(tile3D);
tiles3D.remove(tile3D);
tileMap.remove(Tile.getTileKey(tile));
}

private void select(Tile tile){
Object3D tile3D = get(tile);
if(tile3D == null) return;
tile3D.setAdditionalColor(selectionColor);
}

private void deselect(Tile tile){
Object3D tile3D = get(tile);
if(tile3D == null) return;

tile3D.clearAdditionalColor();
}

private void calculateModelBoundingBox(){
calcBoundingBox = true;
boundingBox = new float[]{Float.MAX_VALUE,Float.MIN_VALUE,
  Float.MAX_VALUE,Float.MIN_VALUE,
  Float.MAX_VALUE,Float.MIN_VALUE};
float[] bb;
Object3D tile3D;
for(int i = 0;i < tiles3D.size();i++){
tile3D = tiles3D.get(i);
bb = getBoundingBoxInWorld(tile3D);

boundingBox[0] = bb[0] < boundingBox[0] ? bb[0] : boundingBox[0];
boundingBox[1] = bb[1] > boundingBox[1] ? bb[1] : boundingBox[1];
boundingBox[2] = bb[2] < boundingBox[2] ? bb[2] : boundingBox[2];
boundingBox[3] = bb[3] > boundingBox[3] ? bb[3] : boundingBox[3];
boundingBox[4] = bb[4] < boundingBox[4] ? bb[4] : boundingBox[4];
boundingBox[5] = bb[5] > boundingBox[5] ? bb[5] : boundingBox[5];
}
calcBoundingBox = false;
}

private float[] getBoundingBoxInWorld(Object3D model){
float[] bb = model.getMesh().getBoundingBox();
float[] result = new float[]{Float.MAX_VALUE,Float.MIN_VALUE,
  Float.MAX_VALUE,Float.MIN_VALUE,
  Float.MAX_VALUE,Float.MIN_VALUE};
SimpleVector tmp;
Matrix trans = model.getWorldTransformation();
tmp = new SimpleVector(bb[0],bb[2],bb[4]);
tmp.matMul(trans);
updateBoundingBox(result,tmp.x,tmp.y,tmp.z);

tmp.set(bb[0],bb[2],bb[5]);
tmp.matMul(trans);
updateBoundingBox(result,tmp.x,tmp.y,tmp.z);

tmp.set(bb[0],bb[3],bb[4]);
tmp.matMul(trans);
updateBoundingBox(result,tmp.x,tmp.y,tmp.z);

tmp.set(bb[0],bb[3],bb[5]);
tmp.matMul(trans);
updateBoundingBox(result,tmp.x,tmp.y,tmp.z);

tmp.set(bb[1],bb[2],bb[4]);
tmp.matMul(trans);
updateBoundingBox(result,tmp.x,tmp.y,tmp.z);

tmp.set(bb[1],bb[2],bb[5]);
tmp.matMul(trans);
updateBoundingBox(result,tmp.x,tmp.y,tmp.z);

tmp.set(bb[1],bb[3],bb[4]);
tmp.matMul(trans);
updateBoundingBox(result,tmp.x,tmp.y,tmp.z);

tmp.set(bb[1],bb[3],bb[5]);
tmp.matMul(trans);
updateBoundingBox(result,tmp.x,tmp.y,tmp.z);

return result;
}

private void updateBoundingBox(float[] result, float x, float y, float z){
result[0] = x < result[0] ? x : result[0];
result[1] = x > result[1] ? x : result[1];
result[2] = y < result[2] ? y : result[2];
result[3] = y > result[3] ? y : result[3];
result[4] = z < result[4] ? z : result[4];
result[5] = z > result[5] ? z : result[5];
}

private void removeMarkedObjects(){
if(removingObjects.isEmpty()) return;
Object3D obj;
int tr;
for(int i = 0;i < removingObjects.size();i++){
obj = removingObjects.get(i);
tr = obj.getTransparency();
if(tr == -1){
obj.setTransparency(START_TRANSPARENCY);
}else{
tr = tr - TRANSPARENCY_DECREASE;
if(tr < 0){
world.removeObject(obj);
removingObjects.remove(obj);
i--;
}else{
obj.setTransparency(tr);
}
}
}
}

private void drawSelectionBlitting(){
Tile tile = model.getSelected();
if(tile == null) return;

String texName = Utils.getTextureByType(tile.type);
Texture tex = TextureManager.getInstance().getTexture(texName);
fb.blit(tex,
0, 0,
TILE_ICON_X, TILE_ICON_Y,
tex.getWidth(), tex.getHeight(),
TILE_ICON_SIZE, TILE_ICON_SIZE, -1, false, null);
}

private void adjustFitness(){
if(calcBoundingBox || isCameraRotating() || boundingBox == null || fb == null) return;
if(world == null) return;

Camera cam = world.getCamera();
float width = fb.getWidth();
float height = fb.getHeight();
boolean moveOut = false;
boolean moveIn = true;
SimpleVector tmp = new SimpleVector();
SimpleVector result = new SimpleVector();
tmp.set(boundingBox[0],boundingBox[2],boundingBox[4]);
Interact2D.project3D2D(cam, fb,tmp,result);
if(!isInBounds(result,0,width,0,height)){
moveOut = true;// we need to move camera out
moveIn = false;
}else if(moveIn && !isInBounds(result,BORDER_SIZE,width - BORDER_SIZE,BORDER_SIZE,height - BORDER_SIZE)){
moveIn = false;
}

tmp.set(boundingBox[0],boundingBox[2],boundingBox[5]);
Interact2D.project3D2D(cam, fb,tmp,result);
if(!moveOut && !isInBounds(result,0,width,0,height)){
moveOut = true;
moveIn = false;
}else if(moveIn && !isInBounds(result,BORDER_SIZE,width - BORDER_SIZE,BORDER_SIZE,height - BORDER_SIZE)){
moveIn = false;
}

tmp.set(boundingBox[0],boundingBox[3],boundingBox[4]);
Interact2D.project3D2D(cam, fb,tmp,result);
if(!moveOut && !isInBounds(result,0,width,0,height)){
moveOut = true;
moveIn = false;
}else if(moveIn && !isInBounds(result,BORDER_SIZE,width - BORDER_SIZE,BORDER_SIZE,height - BORDER_SIZE)){
moveIn = false;
}

tmp.set(boundingBox[0],boundingBox[3],boundingBox[5]);
Interact2D.project3D2D(cam, fb,tmp,result);
if(!moveOut && !isInBounds(result,0,width,0,height)){
moveOut = true;
moveIn = false;
}else if(moveIn && !isInBounds(result,BORDER_SIZE,width - BORDER_SIZE,BORDER_SIZE,height - BORDER_SIZE)){
moveIn = false;
}

tmp.set(boundingBox[1],boundingBox[2],boundingBox[4]);
Interact2D.project3D2D(cam, fb,tmp,result);
if(!moveOut && !isInBounds(result,0,width,0,height)){
moveOut = true;
moveIn = false;
}else if(moveIn && !isInBounds(result,BORDER_SIZE,width - BORDER_SIZE,BORDER_SIZE,height - BORDER_SIZE)){
moveIn = false;
}

tmp.set(boundingBox[1],boundingBox[2],boundingBox[5]);
Interact2D.project3D2D(cam, fb,tmp,result);
if(!moveOut && !isInBounds(result,0,width,0,height)){
moveOut = true;
moveIn = false;
}else if(moveIn && !isInBounds(result,BORDER_SIZE,width - BORDER_SIZE,BORDER_SIZE,height - BORDER_SIZE)){
moveIn = false;
}

tmp.set(boundingBox[1],boundingBox[3],boundingBox[4]);
Interact2D.project3D2D(cam, fb,tmp,result);
if(!moveOut && !isInBounds(result,0,width,0,height)){
moveOut = true;
moveIn = false;
}else if(moveIn && !isInBounds(result,BORDER_SIZE,width - BORDER_SIZE,BORDER_SIZE,height - BORDER_SIZE)){
moveIn = false;
}

tmp.set(boundingBox[1],boundingBox[3],boundingBox[5]);
Interact2D.project3D2D(cam, fb,tmp,result);
if(!moveOut && !isInBounds(result,0,width,0,height)){
moveOut = true;
moveIn = false;
}else if(moveIn && !isInBounds(result,BORDER_SIZE,width - BORDER_SIZE,BORDER_SIZE,height - BORDER_SIZE)){
moveIn = false;
}

if(moveOut){
cam.moveCamera(Camera.CAMERA_MOVEOUT, CAMERA_MOVE_STEP);
}else if(moveIn){
cam.moveCamera(Camera.CAMERA_MOVEIN, CAMERA_MOVE_STEP);
}
}

private boolean isInBounds(SimpleVector point,float minx,float maxx,float miny, float maxy){
if(point == null) return false;
if(point.x < minx || point.x > maxx || point.y < miny || point.y > maxy)return false;
return true;
}


private float getTileX(Tile tile){
return tile.x*(TILE_MARGIN + 2*TILE_SCALE);
}

private float getTileY(Tile tile){
return tile.y*(TILE_MARGIN + 2*TILE_SCALE);
}

private float getTileZ(Tile tile){
return tile.z*(TILE_MARGIN + 2*TILE_SCALE);
}

private void processCameraMovement(){
if(world == null || Math.abs(xImpulse) <= 2*resist && Math.abs(yImpulse) <= 2*resist) return;
float xDir = 0;
if (isCameraRotatingX()) {
xDir = xImpulse*period;
}
float yDir = 0;
if (isCameraRotatingY() ) {
yDir = yImpulse*period;
}
rotateCamera(xDir, yDir);
}

private void rotateCamera(float xDir, float yDir){
Camera cam = world.getCamera();
SimpleVector center = model3D.getTransformedCenter();
float dist = center.distance(cam.getPosition());
float skyDist = center.distance(skyPlane.getTransformedCenter());
cam.setPosition(center);

center = model3D.getTransformedCenter();
center.sub(skyPlane.getTransformedCenter());
skyPlane.translate(center);

cam.rotateX(xDir);
cam.rotateY(yDir);

cam.moveCamera(Camera.CAMERA_MOVEOUT, dist);

center = model3D.getTransformedCenter();
SimpleVector dir = cam.getDirection();
dir.scalarMul(-1);
dir.add(cam.getUpVector());
SimpleVector tmp = cam.getSideVector();
tmp.scalarMul(-1);
dir.add(tmp);
dir.scalarMul(SUN_DISTANCE);
center.add(dir);
sun.setPosition(center);

dir = cam.getDirection();
dir.scalarMul(skyDist);
skyPlane.translate(dir);
skyPlane.align(cam);
}

public Tile pick(int x, int y){
Camera cam = world.getCamera();
SimpleVector dir=Interact2D.reproject2D3DWS(cam, fb, x, y);
Object[] res=world.calcMinDistanceAndObject3D(cam.getPosition(), dir, 10000 /*or whatever*/);
if(res[1] == null) return null;
return (Tile)((Object3D)res[1]).getUserObject();
}


private boolean isCameraRotatingX(){
return Math.abs(xImpulse) > 2*resist ? true: false;
}

private boolean isCameraRotatingY(){
return Math.abs(yImpulse) > 2*resist ? true: false;
}

private boolean isCameraRotating(){
return isCameraRotatingX() || isCameraRotatingY();
}

public void handleMove(float xDir,float yDir){
rotateCamera(xDir, yDir);
}

public void handlePush(float xImp,float yImp){
xImpulse = xImp;
yImpulse = yImp;
}

public void handleStop(){
xImpulse = 0;
yImpulse = 0;
}
// ------------------- listeners --------------------------------
@Override
public void onTileDeselected(Tile tile) {
deselect(tile);
}

@Override
public void onTilePareRemoved(Tile tile0, Tile tile1) {
remove(tile0);
remove(tile1);
}

@Override
public void onTileSelected(Tile tile) {
select(tile);
}

@Override
public void onModelShuffaled() {
if(isWorldInited){
initModel();
}

}

}


I have some experience in developing apps for android but am really confused with this exception, so any help will be great.