Odd behavior of the translation

Started by gucky, January 26, 2011, 10:35:24 PM

Previous topic - Next topic

gucky

Since I'm actually about to learn how to use the engine, I tried to order 4 cubes in a pattern shown below in the "intended" image. For doing this I first created an object which extends the Object3D class:
public class Field extends com.threed.jpct.Object3D

Then I overrided the constructor:

public Field(int posX, int posY, Field next){
        super(Primitives.getCube(10));
        setXY(); //<-stuff for the getX / getY functions
matrix.translate(getX()*30,0 , getY()*30);
this.setTranslationMatrix(matrix);
}


In onSurfaceChanged I add the 4 fields to the scene:


for (com.theDiceGame.Field f : fields){
f.strip();
f.build();
System.out.println("Translation: "+f.getTranslation());
world.addObject(f);
}


That seems to work. In the simulator will be 4 cubes visible. But they are not positioned as I intended them to.

How I intended them to be positioned.


How they are positioned

The System.out reads like this, which should be the correct translations:
Translation: (0.0,0.0,0.0)
Translation: (30.0,0.0,0.0)
Translation: (30.0,0.0,30.0)
Translation: (0.0,0.0,30.0)


I also checked the rotation (because It looks like they where rotated by 45° and then translated) but the rotation Matrix is 0 except on the diagonal which should be a zero rotation.


EgonOlsen

It would have helped if it would be somehow recognizable which box is which...however, i'm not really sure what i'm seeing here nor how and where the camera is located. But you should keep two things in mind:


  • cubes and boxes returned by the Primitives class aren't axis aligned but rotated 45° around y (the geometry itself, not by the rotation matrix). This has no impact on translations but it should be visible in the rendering...which it isn't in your screen shot. Are you doing anything to compensate for this?
  • What you do is to shift the cubes along x and z. I not sure that this is what you want to do. Wouldn't you rather shift them in the x/y-plane? Or are you viewing them from the top?

EgonOlsen

Here's some hacky four-cube-example derived from HelloWorld. Maybe it helps to find out what you are doing wrong. Is there any chance that you have some child/parent relations defined between the cubes?


package com.threed.jpct.example;

import java.lang.reflect.Field;

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

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Logger;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.BitmapHelper;
import com.threed.jpct.util.MemoryHelper;

/**
* @author EgonOlsen
*
*/
public class HelloWorld extends Activity {

private static HelloWorld master = null;

private GLSurfaceView mGLView;
private MyRenderer renderer = null;
private FrameBuffer fb = null;
private World world = null;
private RGBColor back = new RGBColor(50, 50, 100);

private float touchTurn = 0;
private float touchTurnUp = 0;

private float xpos = -1;
private float ypos = -1;

private Object3D cube0 = null;
private Object3D cube1 = null;
private Object3D cube2 = null;
private Object3D cube3 = null;
private Object3D dummy = null;

private int fps = 0;

protected void onCreate(Bundle savedInstanceState) {

Logger.log("onCreate");

if (master != null) {
copy(master);
}

super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(getApplication());

mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE };
EGLConfig[] configs = new EGLConfig[1];
int[] result = new int[1];
egl.eglChooseConfig(display, attributes, configs, 1, result);
return configs[0];
}
});

renderer = new MyRenderer();
mGLView.setRenderer(renderer);
setContentView(mGLView);
}

@Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}

@Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}

protected void onStop() {
super.onStop();
}

private void copy(Object src) {
try {
Logger.log("Copying data from master Activity!");
Field[] fs = src.getClass().getDeclaredFields();
for (Field f : fs) {
f.setAccessible(true);
f.set(this, f.get(src));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public boolean onTouchEvent(MotionEvent me) {

if (me.getAction() == MotionEvent.ACTION_DOWN) {
xpos = me.getX();
ypos = me.getY();
return true;
}

if (me.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
touchTurn = 0;
touchTurnUp = 0;
return true;
}

if (me.getAction() == MotionEvent.ACTION_MOVE) {
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;

xpos = me.getX();
ypos = me.getY();

touchTurn = xd / -100f;
touchTurnUp = yd / -100f;
return true;
}

try {
Thread.sleep(15);
} catch (Exception e) {
// No need for this...
}

return super.onTouchEvent(me);
}

protected boolean isFullscreenOpaque() {
return true;
}

class MyRenderer implements GLSurfaceView.Renderer {

private long time = System.currentTimeMillis();
private boolean stop = false;

public MyRenderer() {
}

public void stop() {
stop = true;
}

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

if (master == null) {

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

Texture texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.icon)), 64, 64));
TextureManager.getInstance().addTexture("texture", texture);

dummy=Object3D.createDummyObj();

cube0 = Primitives.getCube(10);
cube0.rotateY(-(float) Math.PI / 4f);
cube0.rotateMesh();
cube0.clearRotation();
cube0.calcTextureWrapSpherical();
cube0.setTexture("texture");
cube0.strip();
cube0.build();

cube1 = cube0.cloneObject();
cube2 = cube0.cloneObject();
cube3 = cube0.cloneObject();

world.addObject(cube0);
world.addObject(cube1);
world.addObject(cube2);
world.addObject(cube3);

cube0.translate(-20, -20, 0);
cube1.translate(20, -20, 0);
cube2.translate(-20, 20, 0);
cube3.translate(20, 20, 0);

cube0.setAdditionalColor(RGBColor.WHITE);
cube1.setAdditionalColor(RGBColor.BLUE);
cube2.setAdditionalColor(RGBColor.GREEN);
cube3.setAdditionalColor(RGBColor.RED);

cube0.addParent(dummy);
cube1.addParent(dummy);
cube2.addParent(dummy);
cube3.addParent(dummy);

Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 100);

MemoryHelper.compact();

if (master == null) {
Logger.log("Saving master Activity!");
master = HelloWorld.this;
}
}
}

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}

public void onDrawFrame(GL10 gl) {

try {
if (!stop) {
if (touchTurn != 0) {
dummy.rotateY(touchTurn);
touchTurn = 0;
}

if (touchTurnUp != 0) {
dummy.rotateX(touchTurnUp);
touchTurnUp = 0;
}

fb.clear(back);
world.renderScene(fb);
world.draw(fb);
fb.display();

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);
}
}
}
}


gucky

Yes you are correct, I'm viewing them from the top. And I think the 45° rotation of the primitive might explains my problem. When turning the cubes by 45° in my mind and then also turn the camera by 45° it should be correct. Is there a way to create a cube without the pre-rotation?

I now rotate the cube when creating it (and before translating it) , but this feels a bit off. Or is it the best way to deal with the Problem? And it looks odd as well.




This is the camera setting:
Camera cam = world.getCamera();
cam.setPosition(20, -60, 20);
cam.lookAt(game.getFields().getFirst().getTransformedCenter());


@Second post:
No there shouldn't be any relations and I create them all in a LinkedList. Thank you for the example, I will have a look at it!

EgonOlsen

My example shows how to deal with the pre-rotation. It's an artifact of the way in which the primitives are created. I'm not going to change this anymore, because it would break too much of existing code. It's documented behaviour though.
Be careful with using lookAt. For beginners, i suggest to rotate the camera yourself. lookAt can cause rotations to the camera that you wouldn't expect in the first place.

gucky

Great, I got it to work now. Thank you for your fast and accurate help!