Object-centering mismatch after serialization... (summary-topic)

Started by MemphisRaines, May 03, 2016, 09:52:20 AM

Previous topic - Next topic

MemphisRaines

Dear jPCT-/jPCT-AE-followers,

I have read through quite numerous topic heres on the jPCT-forum regarding different centering problems for serialized objects, but unfortunately I havent found a real promising solution so far - so I would like to discuss a few thoughts here. However I have found a workaround though, which is good enough for the moment...

----------------------------------------------------------------------------------------------------

1. Scenario

Right now I am working on a pick-functionality within my app, which is based on 2 similar rather complex cube-objects, where one of the cube-objects (norm-cube) is considered "visible" with numerous different materials and real textures while the other cube-object (color-cube) is considered "invisible" with only basic color-materials and no additional textures. During the pick-process - in order to figure out on which face of the visible-cube-object I touched - I switch the visibility of both objects and do a basic ray-tracing and color-mapping to match the color-coded face of the color-cube (now visible) with the corresponding face of the norm-cube.

2. Status

While directly importing the respective texture-, material- and object-files without serialization, I got the pick-functionality working without any problems other further position adjustments of the objects. Both objects are placed at the bottom of the layout/screen.

When I start using compressed serialized object-files then the color-cube is always centered right in the middle of the layout/screen, while the norm-cube (which has world-camera-focus) remains at the bottom. The optimization for the importing process is quite phenomenal reducing the overall loading time from over 11 s for both objects to below 3 s, so for my app it is crucial to include the object-serialization.

3. Questions

I have learned about the importance of ensuring the usage of both the same jPCT-version on desktop and for the app, the calculations done during the build()-process when loading the models, the optional useNormalsFromOBJ-flag (which I used for the jPCT-desktop-serialization) and adjusting the TransformedCenter or RotationPivot of an imported object. However all of that didnt got me to a good solution, so here are a few questions...

a) When importing these 2 serialized objects - which both have the exact same size, are perfectly centered and overlapping in blender - how is it possible to end up with 2 different object-positions in the app using jPCT-AE?

b) Which build()-process is more important and after which should I place the position-transformations of my object?
--> Since I have one for the serialization in the desktop jPCT, one after loading the serialized-object with jPCT-AE and one after aquiring the Object3D-model (see the following code):

jPCT:

private Object3D loadModel(InputStream streamModel, InputStream streamMtl, float scale) throws IOException {
         Object3D[] model = Loader.loadOBJ(streamModel, streamMtl, scale);
         Object3D o3d = new Object3D(0);
         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.rotateZ((float) (Math.PI));
             //temp.setRotationMatrix(new Matrix());
             o3d = Object3D.mergeObjects(o3d, temp);
             o3d.getMesh().compress();
             o3d.build();
         }
         o3d.setCenter(SimpleVector.ORIGIN);
         return o3d;
}

...

model_normal_o3d = loadModel("norm-cube", 3);

...

new DeSerializer().serialize(model_normal_o3d, new FileOutputStream("models/norm-cube_ser.ser"), true);


jPCT-AE #1:

private Object3D loadModel(ZipInputStream zis) {
        Object3D[] model;
        Object3D o3d = new Object3D(0);
        Object3D temp;

        model = Loader.loadSerializedObjectArray(zis);

        for (int i = 0; i < model.length; i++) {
            temp = model[i];
            temp.setCenter(SimpleVector.ORIGIN);
            temp.rotateX((float) (-.5 * Math.PI));
            temp.rotateZ((float) (Math.PI));
            temp.rotateMesh();
            temp.setRotationMatrix(new Matrix());
            o3d = Object3D.mergeObjects(o3d, temp);
            o3d.build();
        }// for (int i = 0; i < model.length; i++)

        return o3d;
}


jPCT-AE #2:

...

mNormCube = loadModel(MODEL_COMPRESSED);
mNormCube.strip();
mNormCube.build();

...


--> So this is practically 3-times build(), while each of them does its own center-calculations (if I understood Egon correctly)!?

c) Is there some generalized coordinate-system in jPCT-AE, which each object uses or does every object have its own coordinate-system?
--> The reason I am asking is because I have done some debugging...

norm-cube (after mNormCube.build()):
# svt.set(mNormCube.getTransformedCenter())
V/Renderer/initialize:272: 11,149414 : svt: -0.004741656/0.25171804/4.3867507
# svt = -svt
V/Renderer/initialize:278: 11,152933 : svt: 0.004741656/-0.25171804/-4.3867507
# svt.set(mNormCube.getTransformedCenter())
V/Renderer/initialize:282: 11,153823 : svtTC: 0.0/0.0/0.0
# svt.set(mNormCube.getCenter())
V/Renderer/initialize:285: 11,154674 : svtC: -0.004741656/0.25171804/4.3867507
# svt.set(mNormCube.getOrigin())
V/Renderer/initialize:287: 11,155441 : svtO: 0.0/0.0/0.0
# svt.set(mNormCube.getRotationPivot())
V/Renderer/initialize:289: 11,156262 : svtRP: -0.004741656/0.25171804/4.3867507
# svt.set(mNormCube.getXAxis())
V/Renderer/initialize:291: 11,157133 : svtXAxis: 1.0/0.0/0.0
# svt.set(mNormCube.getYAxis())
V/Renderer/initialize:293: 11,157934 : svtYAxis: 0.0/1.0/0.0
# svt.set(mNormCube.getZAxis())
V/Renderer/initialize:295: 11,158756 : svtZAxis: 0.0/0.0/1.0

color-cube (procedure similar to norm-cube):
V/Renderer/initialize:308: 13,760970 : svt2: -0.0078143/0.31546545/3.189215
V/Renderer/initialize:313: 13,762340 : svt2: 0.0078143/-0.31546545/-3.189215
V/Renderer/initialize:325: 13,763051 : svt2TC: 0.0/0.0/0.0
V/Renderer/initialize:327: 13,763729 : svt2C: -0.0078143/0.31546545/3.189215
V/Renderer/initialize:329: 13,764364 : svt2O: 0.0/0.0/0.0
V/Renderer/initialize:331: 13,765034 : svt2RP: -0.0078143/0.31546545/3.189215
V/Renderer/initialize:333: 13,765719 : svt2XAxis: 1.0/0.0/0.0
V/Renderer/initialize:335: 13,766433 : svt2YAxis: 0.0/1.0/0.0
V/Renderer/initialize:337: 13,767216 : svt2ZAxis: 0.0/0.0/1.0

translated norm-cube on top of color-cube:
V/Renderer/initialize:341: 13,768009 : svt3TC: 0.0/0.0/0.0
V/Renderer/initialize:349: 13,768862 : svt3TC: 0.0/-0.060000002/1.2

--> After inverting the TransformedCenter of each object to 0.0/0.0/0.0, their are at least placed in the same plane, leaving just the minor adjustments of 0.0/-0.060000002/1.2 for the translation (calculated by numerous manual rebuilds)...
--> But where on earth does this offset come from and can it be calculated directly somehow?
--> Why is the toString-function for the Matrix of getWorldTransformation() not showing any result?

test without serialization and no additional translations:
V/Renderer/initialize:272: 11,163593 : svt: -0.004741656/0.25171804/4.3867507
V/Renderer/initialize:276: 11,166357 : svt: -0.004741656/0.25171804/4.3867507
V/Renderer/initialize:279: 11,167121 : svtTC: -0.004741656/0.25171804/4.3867507
V/Renderer/initialize:281: 11,167871 : svtC: -0.004741656/0.25171804/4.3867507
V/Renderer/initialize:283: 11,168652 : svtO: 0.0/0.0/0.0
V/Renderer/initialize:285: 11,169475 : svtRP: -0.004741656/0.25171804/4.3867507
V/Renderer/initialize:287: 11,170271 : svtXAxis: 1.0/0.0/0.0
V/Renderer/initialize:289: 11,171252 : svtYAxis: 0.0/1.0/0.0
V/Renderer/initialize:291: 11,172057 : svtZAxis: 0.0/0.0/1.0
V/Renderer/initialize:303: 13,764091 : svt2: -0.0078143/0.31546545/3.189215
V/Renderer/initialize:307: 13,765323 : svt2: -0.0078143/0.31546545/3.189215
V/Renderer/initialize:310: 13,766455 : svt2TC: -0.0078143/0.31546545/3.189215
V/Renderer/initialize:312: 13,770065 : svt2C: -0.0078143/0.31546545/3.189215
V/Renderer/initialize:314: 13,770942 : svt2O: 0.0/0.0/0.0
V/Renderer/initialize:316: 13,771878 : svt2RP: -0.0078143/0.31546545/3.189215
V/Renderer/initialize:318: 13,772956 : svt2XAxis: 1.0/0.0/0.0
V/Renderer/initialize:320: 13,774073 : svt2YAxis: 0.0/1.0/0.0
V/Renderer/initialize:322: 13,775075 : svt2ZAxis: 0.0/0.0/1.0
V/Renderer/initialize:326: 13,776178 : svt3TC: -0.004741656/0.25171804/4.3867507
V/Renderer/initialize:332: 13,777553 : svt3TC: -0.004741656/0.25171804/4.3867507

--> Apparently I do have the same TransformedCenter- and RotationPivot-positions like before, but both non-serialized objects overlap even without any additional translations. This is so mysterious, that I am almost believing in some dark-force here... :(

additional info:
--> Tried mNormCube.align(mColorCube) but it has no effect on the scenario using serialized objects!

----------------------------------------------------------------------------------------------------

If you have any thoughts on the problem, I would very much appreciate it!

Kind Regards,

Ray

EgonOlsen

This was quite a long text to read and I'm not sure, if I got everything correctly... ;)

Anyway...I'm not sure what's your issue is here. What should happen is this:


  • You load the object in desktop jPCT, call build() and maybe set a new rotation pivot.
  • You serialize the object, which includes the rotation pivot either calculated by build() or your set one.
  • You load the serialized object in jPCT-AE, which will load the serialized pivot as well. This will also flag the rotation pivot as fixed.
  • You call build() on the deserialized object, but it won't do much because most operations have been done by desktop's build()-call already.
  • You translate your objects as you wish.

What this basically means: The rotation pivot of a deserialized object should stay the same that is stored in the file. Even calling build() or calcCenter() shouldn't change it. You can set it to some other value by hand though.
This remains true until you call translateMesh() or rotateMesh() on the object, which will both clear this "skip pivot calculation" flag. Another build() on such an object would calculate the pivot from scratch.

Hope this helps somehow...

MemphisRaines

Hey Egon,

first of all thank you for your fast reply and sorry for my late response!

Unfortunately I was kept kinda busy at work and on top of that I crashed my laptop, so I had to take care of that first...

After taking your thoughts into account and sticking only to pre-serialization-transformations, I was able to achieve the
same model-placement upon loading and deserialization. It was essential not to include any additional transformations
before the 2nd build()-call on the deserialized model.

So everything works as it should now! :)

Regards,

Ray