Streaming algorithm

Started by radvani7, December 08, 2005, 09:36:01 PM

Previous topic - Next topic

radvani7

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.

EgonOlsen

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?

radvani7

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.

EgonOlsen

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.

Anonymous

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

EgonOlsen

No, there isn't! If you want that, you have you do it yourself by using the IVertexController.

radvani7

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

radvani7

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

EgonOlsen

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.

EgonOlsen

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.

radvani7

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

EgonOlsen

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.

raft

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
r a f t

EgonOlsen

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?

raft

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 ?
r a f t