Blitting a rectangle part from one texture into another?

Hi,

have the problem to blit rectangle parts from one texture to one or more destination textures.

I tried to write a texture-renderer, like the following code:




import java.nio.FloatBuffer;
import com.jme.image.Image;
import com.jme.image.Texture;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.TextureRenderer;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.util.geom.BufferUtils;


public class TextureCopy
{
   private TextureRenderer mTexRenderer = null;
   private Texture         mTexture = null;
   private TextureState   mTextureState = null;
   
   private Quad mQuad = null;
   private Node mNode = null;
   
   public TextureCopy(Texture tex_src, GameRect rect_src, GameRect rect_dst)
   {
      // create a quad as geometric structure holding the source-sprite:
      mQuad = new Quad("Sprite");

      // tex_src is source texture for the sprite:
      TextureState ts = GameData.display.getRenderer().createTextureState();
      ts.setTexture(tex_src);
      mQuad.setRenderState(ts);

      // no lightning:
      LightState ls = GameData.display.getRenderer().createLightState();
        ls.setEnabled(false);
        mQuad.setRenderState(ls);
        mQuad.updateRenderState();
      
        // Render the Gui node in the Ortho Queue
      mQuad.setRenderQueueMode(Renderer.QUEUE_ORTHO);
        // don't cull the gui away
      mQuad.setCullMode(Spatial.CULL_NEVER);
        // gui needs no lighting
      mQuad.setLightCombineMode(LightState.OFF);

      // calculate cords:
      Image img = tex_src.getImage();
       SetSrcCoords(rect_src, img.getWidth(), img.getHeight());
      
      // node is a root node, not part of the "real world" tree.
      mNode = new Node("TexRender");
      mNode.setRenderQueueMode(Renderer.QUEUE_SKIP);
      mNode.attachChild(mQuad);
      
       // setup depth buffer
       ZBufferState zs = GameData.display.getRenderer().createZBufferState();
       zs.setEnabled(true);
       zs.setFunction(ZBufferState.CF_LEQUAL);
       mNode.setRenderState(zs);
      
       /*
        AlphaState as = GameData.display.getRenderer().createAlphaState();
        as.setBlendEnabled(true);
        as.setSrcFunction(AlphaState.SB_SRC_ALPHA);
        as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);
        as.setTestEnabled(false);
        as.setEnabled(true);
        mNode.setRenderState(as);
        */
      

      // create texture renderer (use size from dst-texture!):
      mTexRenderer = GameData.display.createTextureRenderer(rect_dst.w, rect_dst.h, TextureRenderer.RENDER_TEXTURE_2D);
      //mTexRenderer.setMultipleTargets(true);      
      mTexRenderer.setBackgroundColor(ColorRGBA.white.clone());
      
      mTexture = new Texture();
      mTexture.setFilter(Texture.FM_NEAREST);
      //mTexture.setFilter(Texture.FM_LINEAR);
      mTexRenderer.setupTexture(mTexture);
      
       // setup texture state:
      mTextureState = GameData.display.getRenderer().createTextureState();
      mTextureState.setEnabled(true);
      mTextureState.setTexture(mTexture);
   }
   
   private void SetSrcCoords(GameRect rect, int w, int h)
   {
       mQuad.initialize(rect.w, rect.h);
       mQuad.setLocalTranslation(rect.w/2, rect.h/2, 0);

      float lu = ((float)rect.x +0.0f) / w;
      float lv = ((float)rect.y +0.0f) / h;
      float ru = ((float)rect.x+rect.w +0.0f) / w;
      float rv = ((float)rect.y+rect.h +0.0f) / h;
       FloatBuffer texCoords = BufferUtils.createFloatBuffer(new float[] { lu, rv, lu,lv, ru,lv, ru,rv });
       mQuad.setTextureBuffer(0, texCoords);
      
   }
   
   public void Render()
   {
      mTexRenderer.render(mNode, mTexture);
   }

   public void Copy(Texture tex, int width, int height)
   {
      mTexRenderer.copyToTexture(tex, width, height);
   }
   
   public Texture GetTexture()
   {
      return mTexture;
   }

   public TextureState GetTS()
   {
      return mTextureState;
   }
   
   
}




But the problem is if i try to get the rendered data via mTexRenderer.copyToTexture(tex, width, height) into another Texture it does not work. Hope someone can help me, I'm just at the beginning of using the jme-engine.
I have read already there is maybe the possibility to use GL11.glCopyTexImage2D(...) to get the data, but don't know how to get the internal format of the texture -> TextureStateRecord.getGLPixelFormat() does not exist in my checkout, maybe there's a newer version?

Many thnx for any help,
woidl
woidl said:
...but don't know how to get the internal format of the texture -> TextureStateRecord.getGLPixelFormat() does not exist in my checkout, maybe there's a newer version?


I've needed this as well.  :)

If you're not opposed to using AWT, you can also use a combination of BufferedImage and the drawImage() function of Graphics2D.  I've been working with this the last couple of days and it's worked for me.  I don't have my code in front of me right now, but if you're interested and can't find another example, I can post some of the code I'm using.

Hi mjsimpson,



many thnx for that hint - i'll try it with drawImage() as soon as possible!

hi again,

maybe you can post some code-snip how to receive a BufferedImage from a com.jme.image.Image

and the other direction? thnx!

Hi mjsimpson,



sorry for the late answer I was lost in another stuff (OpenGL ES) to do last week.

Thank you very much for that code-snips - it helped me to solve my problems - didn't see that connection to the Graphics2D stuff :wink:



Best Regards,

Woidl