Lack of generic object in TempVars

Hey monkeys,



Just noticed there wasn’t a generic object in TempVars and I decided to implement something simple. It’s nothing very complicated, but it works.



I’m currently using this because many of my geometry spatials have user data set to them, but only those that have certain capabilities have it set. So when iterating through a node I’ve got to check if the user data is null. By using a generic object all I have to do is check if it’s null. If it isn’t then I can apply whatever “transformation”, if it is, I simply ignore the geometry.



Maybe that could be helpful to someone?



I’m not sure if more than 1 could be useful…

[patch]

+++ Locally Modified (Based On LOCAL)

@@ -227,4 +227,8 @@

*/

public final float[] bihSwapTmp = new float[9];

public final ArrayList<BIHStackData> bihStack = new ArrayList<BIHStackData>();

  • /**
  • * Generic Object<br />
    
  • */<br />
    
  • public final MiscObject object = new MiscObject();

    }

    [/patch]



    The generic object itself.

    [java]

    /*
  • Copyright © 2009-2010 jMonkeyEngine
  • 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 ‘jMonkeyEngine’ 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.jme3.util;



    /**

    *
  • @author MadJack

    */

    public class MiscObject {



    private Object self;



    public MiscObject() {

    }



    public Object get() {

    return self;

    }



    public void set(Object self) {

    this.self = self;

    }

    }

    [/java]



    I can commit it if accepted.

I’m still not sure I understand what it’s for.



The two statements here seem to be saying the same thing:

“So when iterating through a node I’ve got to check if the user data is null. By using a generic object all I have to do is check if it’s null.”

Every frame I have to do something like this:



[java]

Object blah = geom.getUserData(“Something”);

if (blah != null) {

// do this

}

[/java]



Using a TempVars.object.get/set I don’t have to instantiate a new object every frame to check. The “Something” only exists for geometries which support rotation (rotation period and orbital period). If I don’t do this check and hit a spatial without that userData I’ll get a crash if I try to cast it to a float.



Hopefully it’s clearer.

aaa… :frowning: sorry, still its not clear.

It can’t be that bad. :stuck_out_tongue:



If you call getUserData(“Thing”) on a spatial with a “Thing” that isn’t set you get a null when you fetch it. Right? So, if I want to rotate a node by X radian every frame, or a spatial (planet, sun, moon, etc) I have to check if that userData has been set on the spatial if I want to apply a rotation to it. To do so I would do the above:



[java]

Object blah = geom.getUserData(“Something”);

if (blah != null) {

// do this

}

[/java]



But that means that every frame I have to make an Object that I have to discard immediately after. By using a TempVars it’s MUCH easier on the GC.



The rotation method looks like this:

[java]

private void rotateNodeObjects(GameNode gn, float tpf) {

TempVars tmp = TempVars.get();

for (Spatial sp : gn.getChildren()) {

tmp.object.set(sp.getUserData(“RotationPeriod”));

if (tmp.object.get() != null) {

sp.rotate(0, 0, -(float) tmp.object.get() * tpf);

}

}

tmp.release();

}

[/java]

Object blah = geom.getUserData(“Something”);



That does not create a new object, exepct if getUserData creates one, in wich case your idea will result in the same.

Java uses normally ONLY references to objects, you usually have not the object itself.

Yeah, as empire phoenix says, this:

“But that means that every frame I have to make an Object that I have to discard immediately after. By using a TempVars it’s MUCH easier on the GC”



Is completely false. No GC at all. No object is created. You are referencing a null. If you don’t call “new” then no object is created.



Ok, there is one exception to that rule because of the stupid auto-boxing.



Long myVal = 123;



Will instantiate a new Long(123);



But that is so far and away from this use-case that it doesn’t matter here. Since anything in UserData would have already been an object.

Honestly it doesn’t really matter if it creates an object or not. I can only check for its existence with an object.



Primitives can’t be null as you all know, so I have to cast it to an Object, afterward I cast it to its real type if it’s not null.



I’m sure there’s occasions where Object could be interesting to use, I just haven’t been looking for that except for the way I’m doing things.



Oh and btw, I resent that thumb down.

The point is that there is no reason to have your temporary container object. It just creates extra garbage on the stack and extra method calls at best and creates a needless object at worst.



Object obj = spatial.getUserData( “foo” )



Will never cause additional GC because no object is created.

@pspeed said:
The point is that there is no reason to have your temporary container object. It just creates extra garbage on the stack and extra method calls at best and creates a needless object at worst.

Object obj = spatial.getUserData( "foo" )

Will never cause additional GC because no object is created.


So in a solar system with 10 planets (each with a potential of 0-5 moons) and up to 2 stars, each of these having a "PeriodRotation" and "OrbitRotation" set as UserData won't be creating new objects when fetched (to check for their existence) so I can rotate them when they do exist?

Considering that right now the game runs around 500FPS and assuming an average # of moons, all ~35 000 calls are not benefiting from this?

You are confusing references with instances.



Object obj = spatial.getUserData( “foo” );



Creates no instances… it only grabs a reference. Which is all you would have been doing with your extra wrapper… plus two extra method calls and two extra field dereferences.



For example:



Object obj = new Object();



Creates one object.



Object obj1 = new Object();

Object obj2 = obj1;

Object obj3 = obj1;



…creates one object.

1 Like

And more specifically…


@madjack said:
Considering that right now the game runs around 500FPS and assuming an average # of moons, all ~35 000 calls are not benefiting from this?


No, they are actually suffering a little when you use the wrapper. A hardly noticeable amount but you are doing more work with the wrapper version... about 5 times as much.
1 Like

Alrighty then. I’ll defer to your better knowledge.



As usual, thanks.