www.jpct.net

jPCT - a 3d engine for Java => Support => Topic started by: radvani7 on December 08, 2005, 09:36:01 pm

Title: Streaming algorithm
Post by: radvani7 on December 08, 2005, 09:36:01 pm
Hi,

I was hoping to implement an applet-based application that streams polygons over the network. I have the networking code working, and manage to stream float arrays over to the client applet, which are then turned into Object3Ds and built.

The problem, of course, is the limited memory in the applet. I find I can only support roughly 200-300 Object3Ds on the applet (with an average of 15 vertices per Object).

I was hoping to resolve this problem by using a VertexController, so that I just create a fixed number of Object3Ds when I start the applet, and then whenever the camera moves, I re-use older Object3Ds that are no longer visible, transforming their vertices with the Vertex Controller (for now, I'm not worrying about textures, just dealing with wireframes). This way, I don't have to create new Object3Ds or meshes.

At last, here is my question: Using the GeneralVertexController, am I allowed to change the number of vertices in a Mesh (i.e. replace the whole SimpleVector array)? Or am I only allowed to change the vertex coordinates? Thanks! And any other suggestions would be appreciated. The JPCT framework is great, very fast and easy to use.
Title: Re: Streaming algorithm
Post by: EgonOlsen on December 09, 2005, 12:30:36 am
Quote from: "radvani7"
At last, here is my question: Using the GeneralVertexController, am I allowed to change the number of vertices in a Mesh (i.e. replace the whole SimpleVector array)? Or am I only allowed to change the vertex coordinates? Thanks! And any other suggestions would be appreciated. The JPCT framework is great, very fast and easy to use.
No, you can't change the number, but you can initialize it with a number "high enough" and simply set unused vertices to coords out of view. That what i'm doing for the fog of war in Paradroidz. However, i'm not sure that the VertexController is a good idea, because you would have to calculate normales yourself and can't modify the texture coords. Why don't you simply create new Object3Ds from your data stream and discard old ones? If you are not referencing them yourself somewhere, the garbage collector will clean them up after you've removed them from your world. Or did i get you wrong?
Title: Streaming algorithm
Post by: radvani7 on December 09, 2005, 12:37:55 am
Hi Egon,

Thanks for the quick reply. I'm going to give your latter suggestion a try; I'll just manually call the GC whenever I get new polygons. I'll let you know how it goes.
Title: Streaming algorithm
Post by: EgonOlsen on December 09, 2005, 12:47:46 am
Quote from: "radvani7"
I'll just manually call the GC whenever I get new polygons.
You don't have to. The VM will do it for you before giving an out of memory error. If it still occurs, there must be a reference somewhere to the objects that should be collected.
Title: Streaming algorithm
Post by: Anonymous on December 16, 2005, 07:55:39 pm
Hi Egon,

Thanks for the GC pointer -- manually calling the GC too often can really slow down a machine!

I had a quick question about something else, though: is there a scale() method in the Object3D class that lets you scale only along a certain axis: for example, if I just wanted to scale an Object lengthwise (x-axis) without changing its width along the y-axis.

Thanks!

Raj
Title: Streaming algorithm
Post by: EgonOlsen on December 16, 2005, 11:42:54 pm
No, there isn't! If you want that, you have you do it yourself by using the IVertexController.
Title: Streaming algorithm
Post by: radvani7 on December 18, 2005, 10:08:36 pm
I'll have to look into that VertexController!

One other question: my streaming is working fairly fast now, except in areas where there are lots of objects. So I'm still looking for ways to optimize. I currently create a new Object3D whenever a new object is streamed over the network. Since all my objects right now use the same mesh, sending a new object over the network is just a matter of calling cloneObject on any of the existing objects, and then setting the particular transformation matrices for the new object.

This process involves calling both cloneObject() and build() -- both costly operations according to the JavaDoc. Would it be more efficient, you think, if I used some kind of Object pooling (akin to Thread pooling) where I just had a pool of Objects that were re-used as more data streamed in? In this case, instead of calling cloneObject() and build(), I would call setMesh() on one of the objects in the pool that was no longer active.

If I did it this way:

1) Would I still have to rebuild the object since I changed its mesh?
2) Do you think this would increase performance?

Thanks so much!

Raj
Title: Streaming algorithm
Post by: radvani7 on December 18, 2005, 10:19:42 pm
Regarding the single-axis scaling: I'm going to try to do it by putting in a custom rotation matrix that includes the proper scale factor (I'll do the matrix multiplication on my own). I don't think the IVertexController will suit my needs because a bunch of objects share the same mesh and they all need to have different scale factors :(

But hopefully tweaking the rotation matrix to include custom scaling will work...

Raj
Title: Streaming algorithm
Post by: EgonOlsen on December 19, 2005, 12:05:31 am
Quote from: "radvani7"
Would it be more efficient, you think, if I used some kind of Object pooling (akin to Thread pooling) where I just had a pool of Objects that were re-used as more data streamed in? In this case, instead of calling cloneObject() and build(), I would call setMesh() on one of the objects in the pool that was no longer active.
That won't work, because the mesh is just the mesh. There is a lot more in an Object3D that is not part of the mesh (like texture coords etc.). You may try to play around with Config.optimizeNormalCalcTH to see if it could help to decrease the build time. It may also be save to skip the build()-call if you clone an already built object...that should work, because the information created by build() should be part of the cloned one already.
Title: Streaming algorithm
Post by: EgonOlsen on December 19, 2005, 12:07:08 am
Quote from: "radvani7"

But hopefully tweaking the rotation matrix to include custom scaling will work...
Interesting...i'm sure that it will interfere with jPCT's own scale method but as long as you don't use them, it may work to a degree...but i'm not really sure. Let me know how it works out, please.
Title: Streaming algorithm
Post by: radvani7 on December 20, 2005, 09:39:52 pm
Hi Egon,

The custom scaling worked out very well; I just multiplied a single-axis scale matrix with the rotation matrix, and set that composite matrix as the Object's rotation matrix.

Since I don't use the build-in scaling it doesn't cause any problems there! Thanks for all the help on the streaming topic (I'm going to try some of your suggestions now)

Raj
Title: Streaming algorithm
Post by: EgonOlsen on December 21, 2005, 12:52:18 am
Quote from: "radvani7"
The custom scaling worked out very well; I just multiplied a single-axis scale matrix with the rotation matrix, and set that composite matrix as the Object's rotation matrix.
Interesting! Good to know that it works fine.
Title: Streaming algorithm
Post by: raft on May 14, 2006, 02:32:37 pm
Quote from: "EgonOlsen"
The VM will do it for you before giving an out of memory error. If it still occurs, there must be a reference somewhere to the objects that should be collected.


i'm not that sure about this. during a test i was quickly switching between nodes in karga and hence creating a new world and forgetting the old one. i've got OutOfMemoryError for a couple times. this never happens if i put some time between node switches

i guess java vm doesnt try to make a complete garbage collection on a request for memory. (or maybe buggy) otherwise i cant explain why this happens
Code: [Select]
r a f t
Title: Streaming algorithm
Post by: EgonOlsen on May 14, 2006, 06:57:42 pm
Quote from: "raft"
i guess java vm doesnt try to make a complete garbage collection on a request for memory. (or maybe buggy) otherwise i cant explain why this happens
Very very unlikely IMHO. That would be a severe flaw in the VM's memory management. Couldn't it be that some other thread (like the event thread) was still holding references to the world or the framebuffer or something like that?
Title: Streaming algorithm
Post by: raft on May 14, 2006, 10:31:15 pm
of course, it's much and much more likely that my code is buggy rather than the vm itself ;)

what i was trying to say that i'm not sure if java spec dictates to perform a complete garbage collection if no memory is available, does it ? or does vm simply throw an OutOfMemoryError even if there are some objects waiting to be collected ?
Code: [Select]
r a f t
Title: Streaming algorithm
Post by: EgonOlsen on May 14, 2006, 11:39:22 pm
Quote from: "raft"
what i was trying to say that i'm not sure if java spec dictates to perform a complete garbage collection if no memory is available, does it ?
As fas as i know, i doesn't even dictate a garbage collection at all, i.e. you could write a VM according to the specs that doesn't do any garbage collection (as pointless as such a VM would be). The SUN-VM should perform a complete collection before throwing an out of memory. Everything else would be just plain stupid.
Title: Streaming algorithm
Post by: raft on May 15, 2006, 01:16:10 am
ehm, so i have an un-generatable memory leak somewhere, thanks for the gift :roll:
Code: [Select]
r a f t
Title: Streaming algorithm
Post by: raft on May 15, 2006, 05:49:36 pm
later, i've remembered an article i read about garbage collection stuff. here is a part from it:

Quote
One case where a finalize method delayed GC was discovered by the quality assurance (QA) team working on Swing. The QA team created a stress testing application that simulated user input by using a thread to send artificial events to the GUI. Running on one version of the toolkit, the application reported an OutOfMemoryError after just a few minutes of testing. The problem was finally traced back to the fact that the thread sending the events was running at a higher priority than the finalizer thread. The program ran out of memory because about 10,000 Graphics objects were held in the finalizer queue waiting for a chance to run their finalizers.


i do not have any finalizers and jpct neither has as far as i know. on the other hand this writing means that one can have an OutOfMemoryError even if there are some objects waiting to be collected

plain stupid ? yeah, kind of :roll:

for the curious here is the article by sun: http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html

Quote
r a f t
Title: Streaming algorithm
Post by: EgonOlsen on May 15, 2006, 08:01:15 pm
Just great... :?
Title: Streaming algorithm
Post by: rolz on May 16, 2006, 12:24:25 pm
Try increasing heap size with -Xmx / -Xms params to jvm. If it works fine then:
 - leave as is, update memory requirements ;)
 - review you code for possible optimizations that will reduce memory usage

If not, then you may say you've got a memory leak. You will have to review the code / launch application under profiler to discover the problem. From the past experience the problem is most likely that there are references to "obsolete" objects stored inside your "active" objects in a running threads:

- in object's properties
- in hashmaps/collections (caches, "listeners", etc.)
- in another thread, that is still alive (daemons, launching actions in new thread)
- non-static inner classes - they still carry a reference to outer class instance
- AWT/Swing elements. They might have your objects in model/listeners
- double check static objects - 90% of problems go there

If i were you, I'd use JProfiler (it's commercial but you may find a workarond at astalavista.box.sk if you need it badly) and it's memory monitor to find out more about memory usage in your application.
Title: Streaming algorithm
Post by: eye1 on December 11, 2006, 05:47:24 pm
Quote from: "radvani7"

The custom scaling worked out very well; I just multiplied a single-axis scale matrix with the rotation matrix, and set that composite matrix as the Object's rotation matrix.

Since I don't use the build-in scaling it doesn't cause any problems there!


Hm.. Don't really know how to do that  :? ...