Reflected Quad

I previously used JOGL to do the reflected image look that Apple user interfaces use extensively.  I did it by doing something like:


texture.enable();
texture.bind();
gl.glLoadName(id);
gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
gl.glBegin(GL_QUADS);
gl.glTexCoord2f(left, top); gl.glVertex3f(-half_width * scale,  half_height * scale, 0f);
gl.glTexCoord2f(right, top); gl.glVertex3f(half_width * scale,  half_height * scale, 0f);
gl.glTexCoord2f(right, bottom); gl.glVertex3f(half_width * scale, -half_height * scale, 0f);
gl.glTexCoord2f(left, bottom); gl.glVertex3f(-half_width * scale, -half_height * scale, 0f);
gl.glEnd();

gl.glBegin(GL_QUADS);
gl.glColor4f(alpha * 0.4f, alpha * 0.4f, alpha * 0.4f, alpha * 0.4f);
gl.glTexCoord2f(left, bottom); gl.glVertex3f(-half_width,  -half_height, 0f);
gl.glTexCoord2f(right, bottom); gl.glVertex3f(half_width,  -half_height, 0f);
gl.glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
gl.glTexCoord2f(right, top); gl.glVertex3f(half_width, -half_height -height*reflection_size, 0f);
gl.glTexCoord2f(left, top); gl.glVertex3f(-half_width, -half_height -height*reflection_size, 0f);
gl.glEnd();    

texture.disable();



I'd like to create an object that inherits from Node that would create the two quads above, with the alpha blending, etc.  I'd much appreciate it if somebody could point me in the right direction.

Thanks!

You should check the Hello* mini-tutorials, in particular the HelloTrimesh and HelloStates in the wiki page: http://www.jmonkeyengine.com/wiki/doku.php?id=starter:jme_wiki

Thanks for the tip.  Here’s what I managed to do:







This is an image on the left, and a video on the right (video courtesy of FOBS code provided on this forum).  Code, just in case anybody is interested:



import com.jme.bounding.BoundingBox;
import com.jme.bounding.BoundingSphere;
import com.jme.image.Texture;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.TriMesh;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jme.util.geom.BufferUtils;

public class ImageWithReflection extends Node {

   private static final long serialVersionUID = -6228054783295086126L;
   private int width;
   private int height;
   private DisplaySystem display;
   private Texture tex;

   public ImageWithReflection(String name, DisplaySystem display, String imageResource, int width, int height) {
      this(name, display, ResourceManager.getImageURL(imageResource), width, height);
   }
   
   public ImageWithReflection(String name, DisplaySystem display, URL imageResource, int width, int height) {
      super(name);      
      this.display = display;
      this.width = width;
      this.height = height;
      createContent(imageResource);
   }

   private void createContent(URL imageResource) {      
      tex = TextureManager.loadTexture(imageResource,
            Texture.MM_LINEAR,
            Texture.FM_LINEAR);
      
        TriMesh t = getUpperTriMesh();
        t.setModelBound(new BoundingSphere());
        t.updateModelBound();

        // do the reflection
        TriMesh t2 = getLowerTriMesh();
        t2.setLocalTranslation(0f, -(height/2f), 0f);
        t2.setModelBound(new BoundingSphere());
        t2.updateModelBound();

        AlphaState as1 = display.getRenderer().createAlphaState();
        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);

        t2.setRenderState(as1);
        this.attachChild(t);
        this.attachChild(t2);
   }

   private TriMesh getUpperTriMesh() {
      TriMesh m=new TriMesh(getName() + "_image");

      Vector3f[] vertexes={
            new Vector3f(0,0,0),
            new Vector3f(width,0,0),
            new Vector3f(0,height,0),
            new Vector3f(width,height,0)
      };

      ColorRGBA[] colors={
            new ColorRGBA(1,1,1,1f),
            new ColorRGBA(1,1,1,1f),
            new ColorRGBA(1,1,1,1f),
            new ColorRGBA(1,1,1,1f)
      };

      Vector2f[] texCoords={
            new Vector2f(0,0),
            new Vector2f(1,0),
            new Vector2f(0,1),
            new Vector2f(1,1)
      };

      int[] indexes={
            0,1,2,1,2,3
      };

      m.reconstruct(
            BufferUtils.createFloatBuffer(vertexes),
            null,
            BufferUtils.createFloatBuffer(colors),
            BufferUtils.createFloatBuffer(texCoords),
            BufferUtils.createIntBuffer(indexes));

      TextureState ts=display.getRenderer().createTextureState();
      ts.setTexture(tex);
      m.setRenderState(ts);
      m.setModelBound(new BoundingBox());
      m.updateModelBound();
      return m;
   }

   private TriMesh getLowerTriMesh() {
      TriMesh m=new TriMesh(getName() + "_reflection");
      
      Vector3f[] vertexes={
            new Vector3f(0,0,0),
            new Vector3f(width,0,0),
            new Vector3f(0,height/2,0),
            new Vector3f(width,height/2,0)
      };

      ColorRGBA[] colors={
            new ColorRGBA(1,1,1,0.0f),
            new ColorRGBA(1,1,1,0.0f),
            new ColorRGBA(1,1,1,0.4f),
            new ColorRGBA(1,1,1,0.4f)
      };

      Vector2f[] texCoords={
            new Vector2f(0,1),
            new Vector2f(1,1),
            new Vector2f(0,0),
            new Vector2f(1,0)
      };

      int[] indexes={
            0,1,2,1,2,3
      };

      m.reconstruct(
            BufferUtils.createFloatBuffer(vertexes),
            null,
            BufferUtils.createFloatBuffer(colors),
            BufferUtils.createFloatBuffer(texCoords),
            BufferUtils.createIntBuffer(indexes));

      TextureState ts=display.getRenderer().createTextureState();
      ts.setTexture(tex);
      m.setRenderState(ts);
      m.setModelBound(new BoundingBox());
      m.updateModelBound();
      return m;
   }
}



Also, make sure lighting is switched on (L key?)

Very sweet… A couple of comments, I would recommend using the ResourceLocatorTool instead of the ResourceManager. Also, the DisplaySystem is a singleton, and can be obtained directly with

DisplaySystem.getDisplaySystem();





Thanks for the contribution.

Thanks for the top tips - still very much on the bottom-end of the learning curve!