[ODE] Huge slowdown with just few boxes

I modified the basic jME physics ‘SimpleTest’ to do the traditional physics stress test - a big stack o boxes suspended above each other. Let gravity kick in and watch the resulting mess.

Now with 100 boxes the framerate is initially quite high - 100+ as they all start falling, before (understandably) plummiting down to 20ish when they all start to collide. Then the framerate will climb back up to the 80-100 while the whole thing comes crashing down. All as expected.

Except, when the boxes start coming to rest on the floor the framerate just sinks lower and lower. I can see that theres only a couple of boxes left actually moving yet I’m getting single digit fps. :o

Don’t ODE objects go to sleep if idle? Shouldn’t I be seeing nice high framerates at this point?

I’m not sure, but I dont think autodisable is implemented in odejava just yet. You could however implement a quick hack by checking if the linear and angular velocity of an object is below a certain limit and disable it yourself with Ode.dBodyDisable( bodyId ).

Oh well, javaODE is unusable for me then. Time to dust off the C++ compiler…

well the method I described works quite well since ode will automaticly enable any disabled box if it collides. Since it is so easy to implement I would give it a shot before dusting of anything :wink:

maybe this should go then into the cvs?

we (jme-physics) have created our own natives, fixed alot of exception_violations from odejava.dll, added autodisable and some other stuff. Once we are happy, we will file quite an extensive bug report(s) with odejava for them to rectify.

In the mean time, checkout the natives in our own respiratory. The test you mentioned on the board gives me a solid 200+ FPS (on a pretty crap machine).

DP :slight_smile:

[quote]we (jme-physics) have created our own natives, fixed alot of exception_violations from odejava.dll, added autodisable and some other stuff. Once we are happy, we will file quite an extensive bug report(s) with odejava for them to rectify.
[/quote]
darkprophet,

I’m glad you’ve found and fixed some bugs. That would be excellent if you filed the bug reports, thank you.

At one stage Jani did create the autodisable code but he has yet to add it in, so your code would be welcomed.

Once your improvements have been added back into Odejava, will you be maintaining your fork or again use the Odejava natives? Personally I can’t see a reason for two separate versions. Would you like to just make your changes directly to Odejava?

I would really welcome another developer to Odejava, especially someone who is knowledgeable about the native code and can compile the natives.

Cheers,

Will.

Neither can I. However, because the sources for the natives are not available in CVS, i see very little point in me getting access to CVS directly and changing code. So the only real option left for us is to change our fork and send you bug reports, diffs and patches and you sort it out. This way, you Xith people can still be happy that our jme changes will not affect yours.

Also, we have made changes to Geom to suit our own physics library. E.g. “setPhysicsObject” and “isParticle”, stuff like that that wont be useful for other people not using jme-physics.

I appreciate the gesture william, but there really is not much point in me gaining access to your respiratory.

DP

darkprophet,

I understand what you mean with the natives not being in CVS, I had hoped to keep them out of CVS and just maintain a bunch of patch files which are automatically applied to ODE as part of the build process. The reason being is that I didn’t want to maintain a fork of ODE. However, this may be unavoidable. So how do you keep your ODE sources up to date with ODE? Do you just apply patches as they are added to ODE?

I am happy to review and apply any patches you send this way, and the effort you put into doing this will be appreciated. Laziness was not a driving factor for my suggestion.

Is there a need for jme customisations in the org.odejava package? Is there no way they can be separated? I have been carefully not to make Odejava dependent on any particular display method.

Can you see no way at all for a unified core Odejava code base? I just think it makes so much sense, as we can help each other without the hassle of applying each others patches.

Cheers,

Will.

We have based our current source from the latest native sources you have released. So if you keep up to date, so will we :slight_smile:

You do have a “setUserObject” method in there, but that really just isnt enough. We could make a class, “GeomEntry” or something, but that would require another object instantiated per geom, and that is an overhead thats not really needed. In total, there are 3 new needed methods in Geom, “set/getPhysicsObject” “getGraphics” “set/isParticle”. Also, the constructors for the Geom was changed to take a Spatial as well. We do need tight coupling between the physics and the rendering, but we do try to keep them as seperate as possible. Those additions were necessary.

My goal is to create an entire GameEngine, Physics, Rendering, Sound and Entity management, all knowing about the others prescence. I.e. a slip of a car tyres on a road will generate a different sound than on gravel while still keeping them seperate enough to maintain the other without intimate knowledge of the other library. Hence the required additions.

I can definetly see a unified base, but that would require extra object overhead for anyone using it. Would you be willing to sacrifice an new object per geom? E.g. the creation of an “Entry”.

I dont think maintaining a fork of ODE necessary, just the patch files is needed. I really do hope that Odejava and Jme can be closer and work together to provide a better physics library, both in java and in the natives.

I’l speak to the other developers of jme-physics. See if we can arrange a way in which both parties are happy.

Speak soon,
DP

You could let an app register a GeomFactory which ODE would use when it needed a new Geom. Then you could create and return app-specific classes derived from Geom with all the extra fancyness without the overhead of the extra object.

ODE could use a default factory for people who don’t need this.

I had a little chit chat with kevin. And it seems the only solution to unify these two bases in Geom is to create this “GeomEntry” or “GeomProperties”.

Have a dummy interface which the properties should implement…and instead of “setUserObject” have it as “setGeomProperties”. For me, it would be like:

((JmeGeomProperties)getGeomProperties).isParticle();

I think its an elegant solution and is much faster than the registery that OT talked about (if I understood you correctly). 1 extra object isn’t that big of a deal…

DP

darkprophet,

That sounds like a good solution, I’m really glad there is a way we can work together and keep the codebase unified! ;D I agree, one object extra per geom won’t make a difference. I too use the setUserObject methods for integration with my game (especially useful I find with collisions, where I can quickly get the relevent game Unit).

So what steps do we need to take to realign the codebases? Do you want [set/get]GeomProperties methods in addition to the [set/get]UserObject methods? I guess that could be useful for jme users who still want to use the [set/get]UserObject methods for their own thing. Will you apply for developer access? It’s probably a good idea we keep each other informed of any proposed changes. One thing I am looking at is cleaning up the log statements and the delete/remove funtions (but we’ve hijacked this thread enough already I guess ;), sorry Orangy Tang).

Cheers,

Will.

If you already have a “setGeomProperties”, you wont need to have a setUserObject" as the properties file can contain anything you like.

Jme users dont have access to Geom. Well, they “technically” do, but our own classes make that very very unnecessary.

E.g.


DynamicPhysicsObject obj = new DynamicPhysicsObject(carSpatial, 10f);
Vector3f force = obj.getForce();

Things like that. Everything "odejava"nified is hidden away.

Also, in an attempt to bring jme and ode closer, we changed the logging statements to use jme’s own and we changed the math library to use jme’s. Hence, we removed two jars and we integrated ode’s source into our own jar. So in total, you only need 1 jar to run physics. So all is not going to be unified as you expected :wink:

We pretty much done all the cleaning for you william in our own copy, so when all the “diffs” come out, everything will be there :slight_smile:

DP

It’s good design that you have hidden the Odejava objects from the user. Both Geom and Body have set/getUserData methods which can be used to store an Object (and are not used by Odejava itself).

Regarding the logging, I was planning on moving Odejava to Apache’s logging commons which is an ultra lightweight logging wrapper that can be used with any number of API’s. Would this work well with jMe? If you’re not using the commons logging yourself, it’s possible to write a bridge so the log statements end up in jMe as you like them. In fact this is exactly for this reason that I’m doing the conversion, as it gives me freedom of choice for my game project too.

With the math incompatability, is it possible to have javax.vecmath stubs which simply extend the jMe equivilent (and transalate any methods which are different)? For most cases, this would add zero overhead (unless the method’s name is different or non-existant in jMe, and even then only slightly). This way you are still using jMe’s math classes. Alternativly, it’s probably not too hard to write some regex to automatically convert the source, though personally I like the first option better.

Cheers,

Will.

Jme uses the in-built java logging system and it works fine. I dont see any reason to use any other library…


/*
 * Copyright (c) 2003-2004, jMonkeyEngine - Mojo Monkey Coding
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the Mojo Monkey Coding, jME, jMonkey Engine, nor the
 * names of its contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

package com.jme.util;

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import com.jme.system.JmeException;


/**
 * <code>LoggingSystem</code> maintains a system for logging using the Logging
 * API in JDK 1.4 and higher. <code>LoggingSystem</code> is a singleton and
 * is created via the <code>getLoggingSystem</code> method. This initializes a
 * default logger that can be retrieved via the <code>getLogger</code> method.
 * The logger object is final so can not be directly altered. To change the
 * attributes of the logger, use the built in methods in <code>LoggingSystem</code>.
 * Once the <code>LoggingSystem</code> is created, the logging object can be
 * used normally.
 *
 * @see java.util.logging.Logger
 *
 * @author Mark Powell
 * @version $Id: LoggingSystem.java,v 1.3 2004/04/22 22:27:09 renanse Exp $
 */
public class LoggingSystem {
    //Singleton object for the logging sytem.
    private static LoggingSystem logSystem = null;

    //the logger.
    private final static Logger logger = Logger.getLogger("jme");

    //handler for the logger
    private Handler handler;

    /**
     * Private constructor is called by the <code>getLoggingSystem</code> method.
     * Since this is the initial creation of the logger, it's attributes are set
     * to a default of: All levels, output to debug.txt and a simple formatter.
     */
    private LoggingSystem() {
        loggerOn(true);

        try {
            handler = new FileHandler("debug.txt");
            handler.setFormatter(new SimpleFormatter());
            logger.addHandler(handler);
        } catch (IOException e) {
            throw new JmeException("Could not start Logging System");
        }
    }

    /**
     * <code>getLogger</code> returns the logger object maintained by the
     * <code>LoggingSystem</code>. This reference is null until the
     * <code>LoggingSystem</code> is initialized with a call to
     * <code>getLoggingSystem</code>.
     *
     * @return logger the logging object.
     */
    public static Logger getLogger() {
        if(null == logSystem) {
            logSystem = new LoggingSystem();
        }
        return logger;
    }

    /**
     *
     * <code>loggerOn</code> turns the logger on and off. If true is passed
     * the filter level is set to fine allowing all message to display, false
     * filters all messages.
     * @param value true allows messages to display, false does not.
     */
    public void loggerOn(boolean value) {
        if(value) {
           logger.setLevel(Level.FINE);
        } else {
           logger.setLevel(Level.OFF);
        }
    }

    /**
     * <code>setHandler</code> sets the <code>Handler</code> of the logger.
     * By default the Handler is a simple <code>FileHandler</code> that
     * writes to debug.txt.
     *
     * @param handler the new handler to use for log handling.
     */
    public void setHandler(Handler handler) {
        this.handler = handler;
        logger.addHandler(handler);
    }

    /**
     * <code>setLevel</code> sets the filtering level to be used for this
     * logger. By default it is set to ALL.
     *
     * @param level the new level to set the logger to.
     */
    public void setLevel(Level level) {
        logger.setLevel(level);
    }

    /**
     * <code>setFormatter</code> sets the formatter to use for this logger.
     * By default it is set to simple formatter.
     *
     * @param formatter the new formatter to use for the logger.
     */
    public void setFormatter(Formatter formatter) {
        handler.setFormatter(formatter);
    }

    /**
     * <code>getLoggingSystem</code> is the entry point for the
     * <code>LoggingSystem</code> class. This creates a new
     * <code>LoggingSystem</code> object if need be, or returns the reference
     * if one is already created.
     *
     * @return the singleton reference to the <code>LoggingSystem</code>
     */
    public static LoggingSystem getLoggingSystem() {
        if(null == logSystem) {
                return logSystem = new LoggingSystem();
        } else {
            return logSystem;
        }
    }
}

Thats the source for it straight from the respiratory. Maybe you can use that…Cant get any lighter than this :slight_smile:

About the math stuff, our conversions only take a couple of minutes anyway. Its not that big of a deal…dont worry about this one :wink:

Looks like we have a good compromise here…i’l start making the adjustments needed on jme-physics to accomodate for setGeomProperties and see if there are any problems from there…

DP

[quote] Looks like we have a good compromise here…i’l start making the adjustments needed on jme-physics to accomodate for setGeomProperties and see if there are any problems from there…
[/quote]
Yes, excellent.

Regarding the Logging, this should work well with what you already have for jme, so that’s good.

Will.

Done. No problems. I am yet to profile it see how much extra garbage we’re gonna have to sustain in a stress test. But fundementally, it was easy. Thats in our CVS now and everything is groovy :slight_smile:

Regarding the logging, will you be using it too in Odejava?

DP