setDetailTexture in ProjectedGrid

Hello - I'm trying to create a ProjectedGrid (representing the sea) and apply a detail texture to it - in the same way as a detail is applied to the Terrain in flagrush tutorial and elsehere (which work fine). There is a setDetailTexture method in projectedGrid but it doesn't seem to do anything, so far as I can see. I expect I'm doing something wrong but don't know what - or is there something inherent in ProjectedGrid which means it can only have one texture? I know about the WaterEffectRenderPass stuff, but don't want to use that (it's too reflective and too slow for what I want).



Thanks for any help. JME is a great engine by the way - I'm having fun learning it.

Some code might help:




ProjecteGrid projectedGrid = new ProjectedGrid( "ProjectedGrid", cam, 50, 50, 0.01f, new HeightGenerator() { // waves stuff } );

TextureState ts = display.getRenderer().createTextureState();

// The main water texture
Texture t1 = TextureManager.loadTexture(
   MyTest.class.getClassLoader().getResource(
   "texture/water.jpg"),
   Texture.MM_LINEAR_LINEAR,
   Texture.FM_LINEAR);
ts.setTexture(t1, 0);
t1.setWrap(Texture.WM_WRAP_S_WRAP_T);
  
// The water detail texture
Texture t2 = TextureManager.loadTexture(
   MyTest.class.getClassLoader().getResource(
   "texture/detail.jpg"),
   Texture.MM_LINEAR_LINEAR,
   Texture.FM_LINEAR);
ts.setTexture(t2, 1);
t2.setWrap(Texture.WM_WRAP_S_WRAP_T);

t1.setApply(Texture.AM_COMBINE);
t1.setCombineFuncRGB(Texture.ACF_MODULATE);
t1.setCombineSrc0RGB(Texture.ACS_TEXTURE);
t1.setCombineOp0RGB(Texture.ACO_SRC_COLOR);
t1.setCombineSrc1RGB(Texture.ACS_PRIMARY_COLOR);
t1.setCombineOp1RGB(Texture.ACO_SRC_COLOR);
t1.setCombineScaleRGB(1.0f);

t2.setApply(Texture.AM_COMBINE);
t2.setCombineFuncRGB(Texture.ACF_ADD_SIGNED);
t2.setCombineSrc0RGB(Texture.ACS_TEXTURE);
t2.setCombineOp0RGB(Texture.ACO_SRC_COLOR);
t2.setCombineSrc1RGB(Texture.ACS_PREVIOUS);
t2.setCombineOp1RGB(Texture.ACO_SRC_COLOR);
t2.setCombineScaleRGB(1.0f);

projectedGrid.setRenderState(ts);

// set the detail to the projectedGrid
projectedGrid.setDetailTexture(1, 16);

projectedGrid.setRenderQueueMode(Renderer.QUEUE_OPAQUE);

scene.attachChild(projectedGrid);



The detail texture never appears. No doubt I've missed out some step, but I can't work out what.

I threw your code into a SimpleGame and got the following:







The “detail” texture stayed relative to my camera as I turned, because only the tex coords in the first slot are updated, but as you can see, the detail texture is there.

OK thanks for testing it - unfortunately it still doesn’t work for me  :’(  I put that code into a SimpleGame, get the main texture, no detail texture. Still, if the coords don’t get updated as the camera moves it probably wouldn’t work the way I want anyway, so it’s back to square one…





Sorry to ask another newbie question but I also have a problem with ProjectedGrid and culling. Using the code below creates a ProjectedGrid that works fine, but if I add an object eg Sphere to the scene, then when the camera moves off the Sphere, the ProjectedGrid (and the SkyBox too if I add a SkyBox) all disappear, giving a blank screen (‘Counts: nothing displaying’). I can solve that by setting root node to CULL_NEVER; but doing that isn’t practical in a complex scene with loads of models, as I hope to have. It doesn’t seem to be be possible to set CULL_NEVER just on the ProjectedGrid.



public class MyDebug extends SimpleGame {

   public static void main(String[] args) {
      MyDebug app = new MyDebug();
       app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
       app.start();
   }


     protected void simpleInitGame() {

        display.setTitle("Debug");

        HeightGenerator hg = new HeightGenerator() { public float getHeight(float x, float z, float time) {return 0;}};

        ProjectedGrid projectedGrid = new ProjectedGrid( "ProjectedGrid", cam, 50, 50, 0.01f, hg);

        TextureState ts = display.getRenderer().createTextureState();

        // The main water texture
        Texture t1 = TextureManager.loadTexture(
         MyDebug.class.getClassLoader().getResource(
         "texture/water.jpg"),
         Texture.MM_LINEAR_LINEAR,
         Texture.FM_LINEAR);
        ts.setTexture(t1, 0);
        t1.setWrap(Texture.WM_WRAP_S_WRAP_T);

        // The water detail texture
        Texture t2 = TextureManager.loadTexture(
         MyDebug.class.getClassLoader().getResource(
         "texture/detail.jpg"),
         Texture.MM_LINEAR_LINEAR,
         Texture.FM_LINEAR);
        ts.setTexture(t2, 1);
        t2.setWrap(Texture.WM_WRAP_S_WRAP_T);

        t1.setApply(Texture.AM_COMBINE);
        t1.setCombineFuncRGB(Texture.ACF_MODULATE);
        t1.setCombineSrc0RGB(Texture.ACS_TEXTURE);
        t1.setCombineOp0RGB(Texture.ACO_SRC_COLOR);
        t1.setCombineSrc1RGB(Texture.ACS_PRIMARY_COLOR);
        t1.setCombineOp1RGB(Texture.ACO_SRC_COLOR);
        t1.setCombineScaleRGB(1.0f);

        t2.setApply(Texture.AM_COMBINE);
        t2.setCombineFuncRGB(Texture.ACF_ADD_SIGNED);
        t2.setCombineSrc0RGB(Texture.ACS_TEXTURE);
        t2.setCombineOp0RGB(Texture.ACO_SRC_COLOR);
        t2.setCombineSrc1RGB(Texture.ACS_PREVIOUS);
        t2.setCombineOp1RGB(Texture.ACO_SRC_COLOR);
        t2.setCombineScaleRGB(1.0f);

        projectedGrid.setRenderState(ts);

        // set the detail to the projectedGrid
        projectedGrid.setDetailTexture(1, 16);

        projectedGrid.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
        rootNode.attachChild(projectedGrid);


        Sphere s = new Sphere("Sphere", 30, 30, 25);
        s.setLocalTranslation(new Vector3f(0,0,-40));
        s.setModelBound(new BoundingBox());
        s.updateModelBound();
        s.setRenderState(ts);
        rootNode.attachChild(s);


        // rootNode.setCullMode(SceneElement.CULL_NEVER);

     }

}


Apoliges if these are dumb questions, but they have me completely stymied.

Make sure you are setting bounding boxes on your objects :wink:



Try pressing the 'B' key to see if your seen has the correct bounding boxes, everything should be surrounded by white lines that show where the bounding boxes are.



spatial.setBoundingBox( new BoundingSphere() ); // Or BoundingBox()
spatial.updateModelBound();



As for your texturing issue, try creating a copy of one of the examples.  Then replacing the texturing code with your own, that often helps me to figure out where I went wrong...

Thanks for the replies and sorry to bring this up again, but I still can't figure out why I'm not getting the detail texture. I can see from renanse's screenshot that he does, but I've tried the code below on two different PCs with the same result (no detail on the ProjectedGrid, but the TerrainBlock does show the detail). Could anyone look at or run this code and point out my stupid mistake?



import com.jme.app.*;
import com.jme.bounding.*;
import com.jme.scene.*;
import com.jme.scene.shape.*;
import com.jme.scene.state.*;
import com.jme.image.*;
import com.jme.math.*;
import com.jme.renderer.*;
import com.jme.util.*;
import com.jmex.terrain.*;
import com.jmex.terrain.util.*;
import com.jmex.effects.water.*;
import com.jme.util.geom.*;

public class MyDebug extends SimpleGame {

public static void main(String[] args) {
   MyDebug app = new MyDebug();
             app.setDialogBehaviour(AbstractGame.ALWAYS_SHOW_PROPS_DIALOG);
   app.start();
}

protected void simpleInitGame() {

   //////////////////////////////////////////////////////////////////
   // Make a TextureState with two textures
   //////////////////////////////////////////////////////////////////

   TextureState ts = display.getRenderer().createTextureState();

   // The main texture
   Texture t1 = TextureManager.loadTexture(
      MyDebug.class.getClassLoader().getResource("images/main.jpg"), Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR);
   ts.setTexture(t1, 0);
   t1.setWrap(Texture.WM_WRAP_S_WRAP_T);

   // The detail texture
   Texture t2 = TextureManager.loadTexture(
      MyDebug.class.getClassLoader().getResource("images/detail.jpg"), Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR);
   ts.setTexture(t2, 1);
   t2.setWrap(Texture.WM_WRAP_S_WRAP_T);

   ///////////////////////////////////////
   // Make a ProjectedGrid
   ///////////////////////////////////////

   HeightGenerator hg = new HeightGenerator() { public float getHeight(float x, float z, float time) {return 0;}};
   ProjectedGrid pg = new ProjectedGrid( "ProjectedGrid", cam, 50, 50, 0.01f, hg);
   pg.setModelBound(new BoundingBox());
   pg.updateModelBound();


   ///////////////////////////////////////
   // Make a TerrainBlock
   ///////////////////////////////////////

   MidPointHeightMap heightMap = new MidPointHeightMap(64, 1f);
   Vector3f terrainScale = new Vector3f(4, 0.0575f, 4);
   TerrainBlock tb = new TerrainBlock("Terrain", heightMap.getSize(), terrainScale,   heightMap.getHeightMap(), new Vector3f(0, 0, 0), false);
   tb.setModelBound(new BoundingBox());
   tb.updateModelBound();


   /////////////////////////////////////////////////////////////////////////////////
   // Assign the TextureState to both, as detail texture
   /////////////////////////////////////////////////////////////////////////////////

   pg.setRenderState(ts);
   pg.setDetailTexture(1, 16);
   pg.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
   rootNode.attachChild(pg);

   tb.setRenderState(ts);
   tb.setDetailTexture(1, 16);
   tb.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
   rootNode.attachChild(tb);


}

}





(The bounding issue I have a workaround for, by ensuring that the camera is always within the bound of another object - if it ever isn't and no other object is on screen, the PG disappears, but I assume this is a feature not a bug.)

There's a bug in cvs for ProjectedGrid's setDetailTexture method…  it's using the wrong arguments to copyTextureCoords.  I'll check in a fix.

One other note, you can keep your detail texture aligned with the pg's main texture unit by simply throwing a pg.setDetailTexture(1, 16); in your update method.

Excellent - thanks renanse! I'm glad it wasn't just me going mad.

A little madness never hurt anyone. :slight_smile: