TaskQueueUtil and TextureCache for StandardGame users

Hey there!



As I had a few problems with the StandardGame in the beginning, I decided to make myself a few nice convenience-methods which became convenience-classes quite soon. Thought I should share. Maybe someone can use them.



TaskQueueUtil:

Provides a few convenience-methods for getting things from the OpenGL-thread.

usage: TextureState tsTmp = TaskQueueUtil.getTextureState(game);



TextureCache:

I am using a lot of textures multiple times, and (stupid as I was) loaded them everytime I needed them anew. So I made a TextureCache (Singleton) that, if you provide an URL-object and the StandardGame, gives you a TextureState with the texture already set. Whenever you want to use the same texture again, it simple gives you a reference to the same TextureState you used before. From like 500 textures down to 20 :wink:

usage: TextureCache.getInstance().getTexture(new URL(…), game);



have phun!



<code>

/**********************************************************************************************************************

  • TaskQueueUtil

    *
  • created Mar 22, 2007 by andgra

    **********************************************************************************************************************/



    import java.util.concurrent.Callable;

    import java.util.concurrent.ExecutionException;

    import java.util.concurrent.Future;



    import com.jme.renderer.Camera;

    import com.jme.scene.state.AlphaState;

    import com.jme.scene.state.CullState;

    import com.jme.scene.state.FogState;

    import com.jme.scene.state.LightState;

    import com.jme.scene.state.TextureState;

    import com.jme.scene.state.ZBufferState;

    import com.jme.util.GameTaskQueueManager;

    import com.jmex.game.StandardGame;





    /**
  • Offers functionality (convenience methods) for getting stuff from the OpenGL thread

    *
  • @author andgra

    /

    public class TaskQueueUtil {



      /

      * private constructor, so the class can not be instantiated

      */

      private TaskQueueUtil() {

        // must not be instantiated

      } // TaskQueueUtil





      /


      * Gives the OpenGL thread an anonymous inner class Callable<> that is run by the OpenGL thread. The OpenGL thread

      * creates an AlphaState and returns it to the current thread.

     

      * @param game

      * @return

      /

      public static AlphaState getAlphaState(final StandardGame game) {

        Future<AlphaState> future = GameTaskQueueManager.getManager().update(new Callable<AlphaState>() {



          public AlphaState call() throws Exception {

            return game.getDisplay().getRenderer().createAlphaState();

          } // call()

        }); // Callable



        try {

          AlphaState as1 = future.get();

          as1.setBlendEnabled(true);

          as1.setSrcFunction(AlphaState.SB_SRC_ALPHA);

          as1.setDstFunction(AlphaState.DB_ONE);

          as1.setTestEnabled(true);

          as1.setTestFunction(AlphaState.TF_GREATER);

          as1.setEnabled(true);



          return as1;



        } catch(InterruptedException e) {

          e.printStackTrace();

        } catch(ExecutionException e) {

          e.printStackTrace();

        } // catch

        return null;

      } // getAlphaState





      /

      * Gives the OpenGL thread an anonymous inner class Callable<> that is run by the OpenGL thread. The OpenGL thread

      * creates a TextureState and returns it to the current thread.

      *

      * @param game

      * @return

      */

      public static TextureState getTextureState(final StandardGame game) {

        Future<TextureState> future = GameTaskQueueManager.getManager().update(new Callable<TextureState>() {



          public TextureState call() throws Exception {

            return game.getDisplay().getRenderer().createTextureState();

          } // call()

        }); // Callable



        try {

          return future.get();

        } catch(InterruptedException e) {

          e.printStackTrace();

        } catch(ExecutionException e) {

          e.printStackTrace();

        } // catch

        return null; // should not happen

      } // getTextureState





      /


      * Gives the OpenGL thread an anonymous inner class Callable<> that is run by the OpenGL thread. The OpenGL thread

      * creates a ZBufferState and returns it to the current thread.

     

      * @param game

      * @return

      /

      public static ZBufferState getZBufferState(final StandardGame game) {

        Future<ZBufferState> future = GameTaskQueueManager.getManager().update(new Callable<ZBufferState>() {



          public ZBufferState call() throws Exception {

            return game.getDisplay().getRenderer().createZBufferState();

          } // call()

        }); // Callable



        try {

          return future.get();

        } catch(InterruptedException e) {

          e.printStackTrace();

        } catch(ExecutionException e) {

          e.printStackTrace();

        } // catch

        return null; // should not happen

      } // getZBufferState





      /

      * Gives the OpenGL thread an anonymous inner class Callable<> that is run by the OpenGL thread. The OpenGL thread

      * creates a CullState and returns it to the current thread.

      *

      * @param game

      * @return

      */

      public static CullState getCullState(final StandardGame game) {

        Future<CullState> future = GameTaskQueueManager.getManager().update(new Callable<CullState>() {



          public CullState call() throws Exception {

            return game.getDisplay().getRenderer().createCullState();

          } // call()

        }); // Callable



        try {

          return future.get();

        } catch(InterruptedException e) {

          e.printStackTrace();

        } catch(ExecutionException e) {

          e.printStackTrace();

        } // catch

        return null; // should not happen

      } // getCullState





      /


      * Gives the OpenGL thread an anonymous inner class Callable<> that is run by the OpenGL thread. The OpenGL thread

      * creates a FogState and returns it to the current thread.

     

      * @param game

      * @return

      /

      public static FogState getFogState(final StandardGame game) {

        Future<FogState> future = GameTaskQueueManager.getManager().update(new Callable<FogState>() {



          public FogState call() throws Exception {

            return game.getDisplay().getRenderer().createFogState();

          } // call()

        }); // Callable



        try {

          return future.get();

        } catch(InterruptedException e) {

          e.printStackTrace();

        } catch(ExecutionException e) {

          e.printStackTrace();

        } // catch

        return null; // should not happen

      } // getFogState





      /

      * Gives the OpenGL thread an anonymous inner class Callable<> that is run by the OpenGL thread. The OpenGL thread

      * creates a LightState and returns it to the current thread.

      *

      * @param game

      * @return

      */

      public static LightState getLightState(final StandardGame game) {

        Future<LightState> future = GameTaskQueueManager.getManager().update(new Callable<LightState>() {



          public LightState call() throws Exception {

            return game.getDisplay().getRenderer().createLightState();

          } // call()

        }); // Callable



        try {

          return future.get();

        } catch(InterruptedException e) {

          e.printStackTrace();

        } catch(ExecutionException e) {

          e.printStackTrace();

        } // catch

        return null; // should not happen

      } // getLightState





      /


      * Gives the OpenGL thread an anonymous inner class Callable<> that is run by the OpenGL thread. The OpenGL thread

      * returns its Camera to the current thread.

     

      * @param game

      * @return

      /

      public static Camera getCamera(final StandardGame game) {

        Future<Camera> future = GameTaskQueueManager.getManager().update(new Callable<Camera>() {



          public Camera call() throws Exception {

            return game.getCamera();

          } // call()

        }); // Callable



        try {

          return future.get();

        } catch(InterruptedException e) {

          e.printStackTrace();

        } catch(ExecutionException e) {

          e.printStackTrace();

        } // catch

        return null; // should not happen

      } // getCamera

    } // TaskQueueUtil



    </code>









    <code>



    /
    *************************************************************************************************************
  • TextureCache

    *
  • created Apr 30, 2007 by andgra

    **********************************************************************************************************************/



    import java.net.URL;

    import java.util.WeakHashMap;



    import org.apache.log4j.Logger;



    import com.jme.image.Texture;

    import com.jme.scene.state.TextureState;

    import com.jme.util.TextureManager;

    import com.jmex.game.StandardGame;





    /**
  • Class realizes a TextureCache. The data is organized in a WeakHashMap that maps from the URL of the texture to the
  • TextureState. If the TextureState was already created with the desired texture, it is simply returned. If the
  • TextureState does not exist, it will be created.

    *
  • @author andgra

    */

    public class TextureCache {



      private static final Logger logger = Logger.getLogger(TextureCache.class);



      /

      * the WeakHashMap that holds the URLs and referenced TextureStates

      */

      private WeakHashMap<URL, TextureState> map;



      /


      * the Singleton-pattern

      */

      private static TextureCache instance = null;





      /

      * private Constructor so the class can not be instantiated

      */

      private TextureCache() {

        map = new WeakHashMap<URL, TextureState>();

      } // TextureCache





      /


      * returns the instance-object

      *

      * @return

      */

      public static TextureCache getInstance() {

        if (instance == null) {

          instance = new TextureCache();

        } // if



        return instance;

      } // getInstance





      /**

      * does all teh w0rk. loads the texture if needed and/or returns it

      *

      * @param path

      * @param game

      * @return

      */

      public TextureState getTexture(URL path, StandardGame game) {



        if (!map.containsKey(path)) {



          TextureState tsTmp = TaskQueueUtil.getTextureState(game);

          Texture tTmp = null;

          try {

            tTmp = TextureManager.loadTexture(path, Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR, 20f, false);

          } catch(Exception e) {

            logger.error("texture not found", e);

          } // catch



          tsTmp.setTexture(tTmp);

          map.put(path, tsTmp);



          return tsTmp;



        } else {



          return map.get(path);



        } // else

      } // getTexture

    } // TextureCache





    </code>

Being virtually killed by a virtual laser in virtual space is just as effective as the real thing,
because you are as dead as you think you are!

I thought the Texture Manager already came with built in texture caching?

yep, TextureManager caches textures.



but it seems like what his class does is caching the texture states(which reference textures). i don't think this is such a good idea because this way the texture states (including the textures) will always be referenced and the texture manager's caching becomes useless and will never release textures.



another problem is that when you use multi texturing you have more than one texture per texture state.

it also limits you in using a single state per texture which is quite bad if you intend to use a texture in different contexts.

thats strange, because everytime i loaded the same texture again, it took the same amount of time as the first loading when i used the TextureManager. I just assumed that it is loading the texture all over again.



sfera: i have to agree with you. seems i have to work it over  :expressionless:


Being virtually killed by a virtual laser in virtual space is just as effective as the real thing,
because you are as dead as you think you are!