Author Topic: Optimizing memory usage by duplicated or unused Object3D  (Read 3188 times)

Offline iagofg

  • byte
  • *
  • Posts: 12
    • View Profile
Optimizing memory usage by duplicated or unused Object3D
« on: December 12, 2011, 02:04:31 am »
Hello,

I'm wish to know which is the best way to dispose the unused Object3D that is no more necesary on the scene.

Also, I wish to know how should I proceed to minimize the memory usage when I have several instances of one Object3D in the scene, with different animation positions, translations and rotations.

Thank you!!

Offline K24A3

  • long
  • ***
  • Posts: 231
    • View Profile
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #1 on: December 12, 2011, 02:13:09 am »
To remove an Object3D I believe you need to remove it from the world then null all references to the Object3D so the garbage collector frees it.

world.removeObject(myObject);
myObject = null;

Cloning objects wont work with objects that have different animations (every object will have the same animation timings because they use the same mesh), but you can remove triangle information from the animations by calling Animation.strip().

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11745
    • View Profile
    • http://www.jpct.net
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #2 on: December 12, 2011, 07:54:36 am »
It's correct that animated objects can't share meshes, but they can share the same animation instance though.

Offline iagofg

  • byte
  • *
  • Posts: 12
    • View Profile
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #3 on: December 12, 2011, 11:17:40 am »
So making:

world.removeObject(myRef);
myRef = null; // for all the references

Sure is enought to dispose everything, including all the underlaying compiled data? I suspected that there is something else to do to free all the resources. I've asked the question the first time because my app didn't not low the memory usage doing so... sure it can be the complexity of my app that hides some lost non-nulled references, but I looked for them everywhere and I didn't found more. Maybe I make some benchmarks with IRenderHook to confirm or discard :)

On the other topic (sharing data between duplicated objects)... relating cloning meshes sure that this: Object3D myRef2 = new Object3D(myRef, true); do not work to share the same mesh?

For animated object I suppose that is necesary 1 mesh per object so you can get different animated statuses per each Object3D? is it? do you refer this when you say animated objects can't share meshes? so if animated objects share meshes all of them will get the same animation status when rendering? maybe know this is usessful if i want more than 1 object animated identically at the same time?

Finally: I'm reading the doc searching for other posibility... maybe sound a little mad, but can I add more than one time the same Object3D to the world?? I'm thinking in optimizing with IRenderHook; it can solve my problem in some scene :)

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11745
    • View Profile
    • http://www.jpct.net
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #4 on: December 12, 2011, 12:32:40 pm »
Quote
Sure is enought to dispose everything, including all the underlaying compiled data? I suspected that there is something else to do to free all the resources. I've asked the question the first time because my app didn't not low the memory usage doing so... sure it can be the complexity of my app that hides some lost non-nulled references, but I looked for them everywhere and I didn't found more.
It should be sufficient. GPU will be freed once the compiled data gets garbage collected. If you are using VBOs, you'll get a log message in that case. This won't happen of course, if you are still keeping some reference to that Object3D somewhere.

Quote
On the other topic (sharing data between duplicated objects)... relating cloning meshes sure that this: Object3D myRef2 = new Object3D(myRef, true); do not work to share the same mesh?
Yes, that will make the new object use the same mesh...but i don't understand the actual question...?

Quote
For animated object I suppose that is necesary 1 mesh per object so you can get different animated statuses per each Object3D? is it? do you refer this when you say animated objects can't share meshes? so if animated objects share meshes all of them will get the same animation status when rendering? maybe know this is usessful if i want more than 1 object animated identically at the same time?
If they share the mesh, they share the animation...so calling animate() on one of them is sufficient. However, you have to make sure that this object will actually be rendered or otherwise, the mesh update doesn't happen on the other objects until you call touch() on one of them. 


Quote
Finally: I'm reading the doc searching for other posibility... maybe sound a little mad, but can I add more than one time the same Object3D to the world?? I'm thinking in optimizing with IRenderHook; it can solve my problem in some scene
No. One Object3D can't belong to a world multiple times nor can it belong to multiple worlds.
« Last Edit: December 12, 2011, 01:51:06 pm by EgonOlsen »

Offline iagofg

  • byte
  • *
  • Posts: 12
    • View Profile
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #5 on: December 12, 2011, 01:49:01 pm »
Quote

Quote
On the other topic (sharing data between duplicated objects)... relating cloning meshes sure that this: Object3D myRef2 = new Object3D(myRef, true); do not work to share the same mesh?

Yes, that won't make the new object use the same mesh...but i don't understand the actual question...?

Sorry, the actual question was:

Using myRef2 = new Object3D(myRef1, true) Does myRef2 share the mesh data so all the data is not duplicated in memory?
Does it share compiled data as well?
If not, How to make it happen? (How to get duplicated Object3D using the same mesh data without storing two times in memory?)

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11745
    • View Profile
    • http://www.jpct.net
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #6 on: December 12, 2011, 01:58:04 pm »
Sorry, my answer was wrong..."won't" should actually read "will". So yes, this will make the new Object3D use the same Mesh, but only in main memory. On the GPU, they will still be different. To change this, add a newObj.shareCompiledData(oldObj);. More info: http://www.jpct.net/wiki/index.php/Reducing_memory_usage

Offline iagofg

  • byte
  • *
  • Posts: 12
    • View Profile
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #7 on: December 12, 2011, 01:59:13 pm »
That's great!!! Thx very much :)

Offline K24A3

  • long
  • ***
  • Posts: 231
    • View Profile
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #8 on: December 13, 2011, 08:20:36 am »
Is there a faster or more memory efficient way of loading the same 3D file into multiple Object3D's with each Object3D having an independent animation?

At the moment I'm using Load3DS for every object 3D. How can I load the 3D file just once and then copy the mesh to the other Object3D's?
Does mesh.cloneMesh() actually copy the mesh or does it use the same mesh?

Here's the current code:
Code: [Select]
for(int n=0;n<MAX_CLONES;n++)
{
obj = Object3D.mergeAll(Loader.load3DS(myContext.getResources().openRawResource(R.raw.obj3s), 2f));
obj2 = Object3D.mergeAll(Loader.load3DS(myContext.getResources().openRawResource(R.raw.obj3l), 2f));
obj3 = Object3D.mergeAll(Loader.load3DS(myContext.getResources().openRawResource(R.raw.obj3r), 2f));
obj.setTexture("obj3tex");
obj.setSpecularLighting(true);
obj.calcCenter();
obj2.calcCenter();
obj3.calcCenter();
obj.calcNormals();
obj2.calcNormals();
obj3.calcNormals();
obj.calcBoundingBox();
obj2.calcBoundingBox();
obj3.calcBoundingBox();
obj2.strip();
obj3.strip();

Animation anim = new Animation(3);
               anim.createSubSequence("anim1");
               anim.addKeyFrame(obj2.getMesh());
               anim.addKeyFrame(obj.getMesh());
               anim.addKeyFrame(obj3.getMesh());
               anim.setClampingMode(Animation.USE_CLAMPING);
               obj.setAnimationSequence(anim);
               //obj.compile();
world.addObject(obj);

               // Save object reference
               myObjects3[n] = obj;

anim = null;
obj  = null;
obj2 = null;
obj3 = null;

}

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11745
    • View Profile
    • http://www.jpct.net
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #9 on: December 13, 2011, 08:34:46 am »
They are using the same mesh by default. If you don't want this, do

Code: [Select]
Object3D niu=old.cloneObject();
niu.setMesh(niu.getMesh().cloneMesh(true));

or, which i prefer:

Code: [Select]
Object3D niu=new Object3D(old, false);

Offline K24A3

  • long
  • ***
  • Posts: 231
    • View Profile
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #10 on: December 13, 2011, 09:05:24 am »
That made quite a difference, I managed to decrease the load time from 6 seconds to 4.
Cheers.

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11745
    • View Profile
    • http://www.jpct.net
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #11 on: December 13, 2011, 09:38:18 am »

Offline K24A3

  • long
  • ***
  • Posts: 231
    • View Profile
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #12 on: December 13, 2011, 11:11:56 am »
Wow serialized objects make a big difference in load time, loading just three serialized 100KB objects shaved off another 500ms. The RAM usage appears to have dropped a bit as well (yet to confirm).

I can't seem to get Eclipse to auto serialize the folder unless I go into the Project Properties and click Apply again. Clicking Refresh and changing the folder contents does nothing.

The mesh bounding box is also different (offset is wrong) now that I need to call Scale() and translateMesh().
EDIT: I found a solution, removing translateMesh() and scaling the bounding box values manually gives me the correct values.
« Last Edit: December 13, 2011, 12:11:47 pm by K24A3 »

Offline iagofg

  • byte
  • *
  • Posts: 12
    • View Profile
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #13 on: December 13, 2011, 11:44:17 am »
Yeah... xDDD I used serialialized loading since weeks :) is faster... and uses less memory because no importation process must be executed.

But above those advantages I believe the serialized format has one severe problem: it is very very big: by example for one of the animations I work:

  • source data: 60 .objs, animated: around 1'5 mb (.obj maybe are one of the bigger formats, very very redundant).
  • import with a java application and exported to serialized form. I discard redundant geometry with strip, and I apply some other optimizations (I do not remember now, but I readed everything weeks ago).
  • the result is that the serialized data: animated 60 frame object: around 4 mb.

I suspect that the matter is that serialized data include not only the geometry data, also include all the other properties so the objects do not need to be initialized again. Very very fast, but very very big. Probably there exists a better solution which picks advantages from both alternatives, ;) but for the moment I guess the serialized form is the best available, as long as you can zip the data inside jars or apks, so the size lowers.

Anyway :) maybe something is possible in this way

Offline K24A3

  • long
  • ***
  • Posts: 231
    • View Profile
Re: Optimizing memory usage by duplicated or unused Object3D
« Reply #14 on: December 13, 2011, 11:52:14 am »
Yeah I noticed the file size difference. 100KB vs 357KB, but if it only increases the APK, it's not a problem for me since my objects are mostly low poly anyway. The APK format is actually a ZIP file so it shouldn't make much difference, zipping that 357KB serialized file shrunk it to 130KB (compared to 78KB using the 7zip format :p).