Find a good way to store objects

1 view
Skip to first unread message

Bay

unread,
Oct 19, 2010, 11:02:43 AM10/19/10
to Open Wonderland Forum
Dear All:

Related to some question before.
I developed a module to let users add a table(using codes to import a
model from outside) to the world. Users can add boxes onto table. Now
I just use an array to store all Vector3f locations of all boxes. So
boxes belong to the table. When I create many tables and with its own
many boxes on it, I have a big trouble loading them! When user logs
into the world he would need to synchronize all the objects existed,
but usually failed when synchronizing. Below is my method:

public void setStatus(CellStatus status, boolean increasing) {
.......
.......

TableCellChangeMessage msg = new TableCellChangeMessage(getCellID());
msg.setAction(Action.SYNC);
sendCellMessage(msg);

......
......
}

I send a "SYNC" action when client initializing. And then server class
send back the array of boxes' locations back to the client. Then
client use this information to render every table and it's boxes.

in renderer class:
"public void sync(List<Vector3f> boxesLocation){
for(Vector3f location: boxesLocation)
addObject(location);
"

The problem is I usually get stuck when doing these sync things. If
there are more users and more tables and boxes are being created, this
problem is getting worse.
But I notices that even I put a lot of model,for example,thirty houses
into the world I still can login smoothly.
I think my case is different and maybe because the storage of my
object is inefficient.
Anyone have ideas about my case?
Any suggestion?

Many thanks!

Bernard

unread,
Oct 20, 2010, 4:49:56 AM10/20/10
to Open Wonderland Forum
Bay

what does your addObject() method do? More specifically, are you
adding the boxes on the right thread?

Also, when you say that your client gets "stuck", could you do a
jstack on the client to see where it's getting stuck?

cheers

Bernard

Bob Potter

unread,
Oct 20, 2010, 7:06:34 AM10/20/10
to openwon...@googlegroups.com
Bay

Does your server state object contain the box objects as well?  If so they maybe already passed to the client and you are trying to render them a second time and have a synchronization issue.

Bob 

Bay

unread,
Nov 10, 2010, 5:25:46 AM11/10/10
to Open Wonderland Forum
To Bernard:
I've noticed that the line will get stuck is the "updateRenderState".
Below I show part of error messages:
java.util.EmptyStackException
at java.util.Stack.peek(Unknown Source)
at java.util.Stack.pop(Unknown Source)
at com.jme.scene.Spatial.updateRenderState(Spatial.java:1670)
at com.jme.scene.Node.applyRenderState(Node.java:604)
at com.jme.scene.Spatial.updateRenderState(Spatial.java:1663)
at com.jme.scene.Node.applyRenderState(Node.java:604)
at com.jme.scene.Spatial.updateRenderState(Spatial.java:1663)
at com.jme.scene.Spatial.updateRenderState(Spatial.java:1632)
at
org.jdesktop.wonderland.modules.mathroom.client.jme.cellrenderer.TableCellRenderer
$3.run(TableCellRenderer.java:560)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown
Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown
Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)


To Bob:
Yes, both the server side and client side contain boxes'
List<Vector3f> location. Do I need to send a SYNC message to sever
side in the Cell's setStatus method? I mean I do this:
public void setStatus(CellStatus status, boolean increasing) {
super.setStatus(status, increasing);
................
TableCellChangeMessage msg = new TableCellChangeMessage(getCellID());
msg.setAction(Action.SYNC);
sendCellMessage(msg);
.....
}

And server send back the location of all boxes to let client use
CellRender to add boxes.
In Cell : case SYNC:
if
(sccm.getSenderID().equals(getCellCache().getSession().getID())) {
renderer.sync(sccm.getBoxesLocation());
In Renderer:
public void sync(List<Vector3f> boxesLocation) {
for (Vector3f location : boxesLocation) {
addObject(location);
}
}

public void addObject(final Vector3f location) {
final Runnable run = new Runnable() {

public final void run() {
if (boxes == null) {
boxes = new ArrayList<Node>();
}
int id = boxes.size();
Node boxNode = createObject(id, location);
boxes.add(boxNode);

ClientContextJME.getWorldManager().addToUpdateList(boxNode);
collisionSystem.addReportingNode(boxNode, cc);
tableNode.attachChild(boxNode);
try {
tableNode.updateRenderState();
} catch (Throwable t) {

Logger.getLogger(TableCellRenderer.class.getName()).log(Level.WARNING,
null, t);
}
}
};

SwingUtilities.invokeLater(run);


Is it right to send SYNCHONIZE message to server in Cell's setStatus
method? Will this action cause synchronizing twice?

Bernard

unread,
Nov 15, 2010, 4:40:12 AM11/15/10
to Open Wonderland Forum
Bay

why do you call updateRenderState() in the addObject() method?

Bernard



On Nov 10, 10:25 am, Bay <leave...@gmail.com> wrote:
> ToBernard:

Bay

unread,
Nov 15, 2010, 5:26:07 AM11/15/10
to Open Wonderland Forum
Bernard:

Is it wrong to call updateRenderState() if created mesh objects
attached to the root node?

Bay

Jonathan Kaplan

unread,
Nov 15, 2010, 11:36:28 AM11/15/10
to openwon...@googlegroups.com
I believe the issue here is with threading -- all calls to change live JME objects (like updateRenderState() and attachChild()) must be made on the MT Game render thread. So instead of using "SwingUtilities.invokeLater(run)"to do this work, use a SceneWorker:

SceneWorker.addWorker(new WorkCommit(run));

That should fix the issue with empty stack exceptions. I have an updated version of JME that checks for these type of mistakes, which I plan to put back shortly.

Bay

unread,
Nov 17, 2010, 3:05:11 AM11/17/10
to Open Wonderland Forum
Jonathan:

I modify the code enclosed with SceneWorker.addWorker(..... and
everything seems to go fine.
But what's the meaning of " all calls to change live JME object must
be nade on the MTGame"?
When should I use SceneWorker? There are too many ways can be operated
with the object in
OWL: setModelBound、setTranslation、attachChild、......

Bay

Jonathan Kaplan

unread,
Nov 17, 2010, 12:12:50 PM11/17/10
to openwon...@googlegroups.com
The rules for JME objects are very similar to the rules for Swing objects:

- any time you make a change to a live JME object, it should be done on the MTGame renderer thread. This goes for changing bounds, setting translation, attaching children, etc, etc. Basically any method calls on Spatial or Node must be made on the MTGame render thread. A JME object is live once it has been added to the scenegraph -- so you can create a Node and set it up on any thread, but once you attach it to a parent or an MTGame entity, it is part of the scene graph and must be modified from the render thread.

- any time you make a change to a JME Spatial object, you should call WorldManager.addToUpdateList()

- you can guarantee you are running on the MTGame render thread using a SceneWorker, a ProcessorComponent or a 3D event listener. All of these objects have process() and commit() methods. Changes to JME objects must be made from the commit() method.

Reply all
Reply to author
Forward
0 new messages