setRotationPivot / Config.useRotationPivotFrom3DS on AE

Started by lomac, February 14, 2013, 08:51:48 PM

Previous topic - Next topic

lomac

Hi, I have set up my projects in such a way that I can run my game on both PC and on android for easy testing and debugging. I did this by separating out the game code from the Activity code. Say I created a class called Game. I then created a desktop project and linked it to the android project. It then uses the Game class (and all related..) from the android project.

For things that differ that differ between android and desktop and jpct-ae and jpct, like file loading, I created an interface called GLoader, with an implementation in each project (DLoader and MLoader), and pass the instance in, and this instance is then used to load files in the generic game code.  (I did the same for control input, mouse<>touchscreen, gsens<>keyboard arrows). This is working great.

The problem I have is that my player model does not rotate around it's .3ds center in the android jpct-ae version, but it works in the desktop jpct version. All the code is identical, except the InputStream creation. Here in my MLoader code. The function that loads the model, private Object3D loadModel(InputStream is, float scale) is identical in both desktop and and AE versions. (Adding o3d.setRotationPivot(SimpleVector.ORIGIN); is what made the desktop version work, but adding it does not work in the AE version.)

   
package com.example.mrunner;

import java.io.IOException;
import java.io.InputStream;

import android.content.res.AssetManager;

import com.threed.jpct.Loader;
import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;

public class MLoader implements GLoader {

AssetManager assets;

public MLoader(AssetManager assets) {
this.assets = assets;
}

@Override
public Object3D loadModel(String file, float scale) {
InputStream is = null;
try {
is = assets.open(file);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(file.endsWith(".3ds")) {
return loadModel(is, scale);
}
else if(file.endsWith(".ser")) {
return loadSerializedModel(is, scale);
}
return null;
}

@Override
public Texture loadTexture(String file) {
InputStream is = null;
try {
is = assets.open(file);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Texture tex = new Texture(is);
TextureManager.getInstance().addTexture(file, tex);
return tex;
}

    private Object3D loadModel(InputStream is, float scale) {
   
        Object3D[] model = Loader.load3DS(is, scale);
        Object3D o3d = new Object3D(1);
        Object3D temp = null;
        for (int i = 0; i < model.length; i++) {
            temp = model[i];
            temp.setCenter(SimpleVector.ORIGIN);
            temp.rotateX((float)( -.5*Math.PI));
            temp.rotateMesh();
            temp.setRotationMatrix(new Matrix());
            o3d = Object3D.mergeObjects(o3d, temp);
            o3d.build();
        }
        o3d.setRotationPivot(SimpleVector.ORIGIN);
        return o3d;
    }

    private Object3D loadSerializedModel(InputStream is, float scale) {
   
        Object3D o3d = Loader.loadSerializedObject(is);
        o3d.scale(scale);
        Object3D temp = o3d;
        temp.setCenter(SimpleVector.ORIGIN);
        temp.rotateX((float)( -.5*Math.PI));
        temp.rotateMesh();
        temp.setRotationMatrix(new Matrix());
        o3d = Object3D.mergeObjects(o3d, temp);
        o3d.build();
        o3d.setRotationPivot(SimpleVector.ORIGIN);
        return o3d;
    }
}



In the ae version the model does not rotate around the correct pivot, in the desktop version it does. I also tried setting Config.useRotationPivotFrom3DS which did not fix it. I do not call build again. The funny thing is that getRotationPivot() returns 0.0,0.0,0.0 on ae but it still does not rotate right.

EgonOlsen

And both versions are loading the 3ds version of the file? Apart from that, the loadSerializedModel-method looks wrong to me. It merges the object with itself... ???

lomac

Yes, both are loading the 3ds version.

p.s. Thanks, I will fix the serialized loading.

EgonOlsen

I don't see any reason why it shouldn't work then. If there would be general problem with setting the rotation pivot, almost everything would go boom. Can you provide a simple Test-Activity that shows the problem?

lomac


lomac

OK, I have found the circumstances that cause the problem. It only happens if you extend Object3D to make for instance your player class, as you did in the car demo.

So if my player class looks like this
public class Player {
Actions actions;

Object3D model;

public SimpleVector lastFramePos;

public Player(Actions actions, Object3D model) {
this.model = model;
this.actions = actions;

actions.world.addObject(model);
}
}


and I call player.model.rotateY(), then it works correctly everywhere.

But, if my player class looks like this:
public class Player extends Object3D {
Actions actions;

public SimpleVector lastFramePos;

public Player(Actions actions, Object3D model) {
super(model);
this.actions = actions;

actions.world.addObject(this);
}
}


and I call player.rotateY(), then the player does not rotate correctly in ae, but does in desktop. The only way to fix it in AE is to call player.setRotationPivot(SimpleVector.ORIGIN); EVERY FRAME in the rendering loop. (It does not matter where in the frame loop, beginning or end, it fixes it)



EgonOlsen

WTF... ??? I'll have a look, but this is really strange...

EgonOlsen

Are you getting the log flooded with messages like


Object <some name> hasn't been build yet. Forcing build()!


??

lomac


EgonOlsen

Have to tried to simply build() all objects (obviously you aren't doing this) before setting the pivots, then set the pivots once, then render? There's a difference between desktop an AE in the default build()-behaviour. AE auto-builds at runtime if your code forgot to do it, desktop doesn't, at least not by default.

lomac

Ah, if I call build on the player object (that extends Object3D), and then player.setRotationPivot after that then it works! Previously I only called build on the Object3D "model" prior to it being passed into the constructor of the Player class.

So the bottom line is if you extend Object3D and construct an instance if the class that inherits Object3D, then you have to call build() on this instance, even if the "model" in super(model) already had build() called on it.

Thank you very much for your time to help me sort this out.

EgonOlsen

Quote from: lomac on February 16, 2013, 03:19:01 PM
So the bottom line is if you extend Object3D and construct an instance if the class that inherits Object3D, then you have to call build() on this instance, even if the "model" in super(model) already had build() called on it.
Yes. That's because you can't be sure that you haven't changed anything in the copy that would affect the build() outcome.