Strange clipping

Hi everyone,



I’ve been messing around with the flag rush tutorials, and have copied over alot of it to see if I can mess around and understand it better, but i’ve gotten the strangest problem with clipping, can anyone give some insight to what is going on here?



Might you indicate what's wrong? I see a large track of land…

I thought it was obvious when I ran it, but from the picture i see how it can be misleading. I will explain, the following screenshots are me running accross the land in a straight line, notice the missing sections i’ve circled that suddenly appear the closer i get to them.











This last one is large shot of how missing elements of the landscape are appearing. This happens to all objects. I can draw a sphere and show you what it does to that if it would help.

I added a Sphere.



Code


package prototype;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;

import jmetest.terrain.TestTerrain;
import com.jme.app.BaseGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.light.DirectionalLight;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.MidPointHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;


public class Prototype extends BaseGame {
   private static final Logger logger = Logger.getLogger(Prototype.class
         .getName());
   private TerrainBlock tb;
   protected Timer timer;
   // Our camera object for viewing the scene
   private Camera cam;
   // the root node of the scene graph
   private Node scene;
   //scene graph node  for player
   private Player player;
   //handles FPS input
   private InputHandler input;


   // display attributes for the window. We will keep these values
   // to allow the user to change them
   private int width, height, depth, freq;
   private boolean fullscreen;





   /**
    * Main entry point of the application
    */
   public static void main(String[] args) {
      Prototype app = new Prototype();
      // We will load our own "fantastic" Flag Rush logo. Yes, I'm an artist.
      app.setConfigShowMode(ConfigShowMode.AlwaysShow, Prototype.class
            .getClassLoader().getResource(
            "jmetest/data/images/FlagRush.png"));
      app.start();
   }

   /**
    * During an update we only look for the escape button and update the timer
    * to get the framerate.
    *
    * @see com.jme.app.BaseGame#update(float)
    */
   protected void update(float interpolation) {
      // update the time to get the framerate
      timer.update();
      interpolation = timer.getTimePerFrame();
      // if escape was pressed, we exit
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit")) {
         finished = true;
      }

      float characterMinHeight = tb.getHeight(player
            .getLocalTranslation())+((BoundingBox)player.getWorldBound()).yExtent;
      if (!Float.isInfinite(characterMinHeight) && !Float.isNaN(characterMinHeight)) {
         player.getLocalTranslation().y = characterMinHeight+5;
      }
      Vector3f normal = null;
      //get the normal of the terrain at our current location. We then apply it to the up vector
      //of the player.
      tb.getSurfaceNormal(player.getLocalTranslation(), normal);
      if(normal != null) {
         player.rotateUpTo(normal);
      }
      /** Check for key/mouse updates. */
      input.update(timer.getTimePerFrame());
      player.setLocalTranslation(cam.getLocation());
      scene.updateGeometricState(interpolation, true);
      
   }

   /**
    * draws the scene graph
    *
    * @see com.jme.app.BaseGame#render(float)
    */
   protected void render(float interpolation) {
      // Clear the screen
      display.getRenderer().clearBuffers();

      display.getRenderer().draw(scene);

   }

   /**
    * initializes the display and camera.
    *
    * @see com.jme.app.BaseGame#initSystem()
    */
   protected void initSystem() {
      // store the settings information
      width = settings.getWidth();
      height = settings.getHeight();
      depth = settings.getDepth();
      freq = settings.getFrequency();
      fullscreen = settings.isFullscreen();

      try {
         display = DisplaySystem.getDisplaySystem(settings.getRenderer());
         display.createWindow(width, height, depth, freq, fullscreen);

         cam = display.getRenderer().createCamera(width, height);
      } catch (JmeException e) {
         logger.log(Level.SEVERE, "Could not create displaySystem", e);
         System.exit(1);
      }

      // set the background to black
      display.getRenderer().setBackgroundColor(ColorRGBA.black.clone());


      /** Get a high resolution timer for FPS updates. */
      timer = Timer.getTimer();

      display.getRenderer().setCamera(cam);

      KeyBindingManager.getKeyBindingManager().set("exit",
            KeyInput.KEY_ESCAPE);
   }
   private void buildCamera(){      
      // initialize the camera
      cam.setFrustumPerspective(45.0f, (float) width / (float) height, 1,
            5000);
      Vector3f loc = new Vector3f(0.0f, 0.0f, 0.0f);
      Vector3f left = new Vector3f(-0.5f, 0.0f, 0.5f);
      Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
      Vector3f dir = new Vector3f(-0.5f, 0.0f, -0.5f);
      // Move our camera to a correct place and orientation.
      cam.setFrame(loc, left, up, dir);
      /** Signal that we've changed our camera's location/frustum. */
      cam.update();
      input = new FirstPersonHandler(cam, 50, 1);
   }

   /**
    * initializes the scene
    *
    * @see com.jme.app.BaseGame#initGame()
    */
   protected void initGame() {
      scene = new Node("Scene graph node");
      buildTerrain();
      scene.attachChild(tb);

      buildLighting();
      buildPlayer();
      buildCamera();
      // update the scene graph for rendering
      scene.updateGeometricState(0.0f, true);
      scene.updateRenderState();
   }

   private void buildPlayer() {
      player = new Player(input);
      //player.setLocalTranslation(new Vector3f(100,0, 100));
      //scene.attachChild(player);
      player.updateWorldBound();   
      Bullet b = new Bullet();
      scene.attachChild(b);   
            
      b.updateWorldBound();
   }

   /**
    * creates a light for the terrain.
    */
   private void buildLighting() {
      /** Set up a basic, default light. */
      DirectionalLight light = new DirectionalLight();
      light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
      light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
      light.setDirection(new Vector3f(1,-1,1));
      light.setEnabled(true);

      /** Set up a basic, default light. */
      DirectionalLight light2 = new DirectionalLight();
      light2.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
      light2.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
      light2.setDirection(new Vector3f(-1,-1,-1));
      light2.setEnabled(true);

      /** Attach the light to a lightState and the lightState to rootNode. */
      LightState lightState = display.getRenderer().createLightState();
      lightState.setEnabled(true);
      lightState.attach(light);
      lightState.attach(light2);
      scene.setRenderState(lightState);
      
   }

   /**
    * build the height map and terrain block.
    */
   private void buildTerrain() {
      // Generate a random terrain data
      MidPointHeightMap heightMap = new MidPointHeightMap(64, 1f);   // Scale the data
      Vector3f terrainScale = new Vector3f(4, .0575f, 4);
      // create a terrainblock
      tb = new TerrainBlock("Terrain", heightMap.getSize(), terrainScale,
            heightMap.getHeightMap(), new Vector3f(0, 0, 0));

      tb.setModelBound(new BoundingBox());
      tb.updateModelBound();

      // generate a terrain texture with 3 textures
      ProceduralTextureGenerator pt = new ProceduralTextureGenerator(
            heightMap);
      pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
            .getResource("data/images/256px-Dirttexture.jpg")), -128, 0, 128);
      pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
            .getResource("data/images/rock.jpg")), 0, 128, 255);
      pt.addTexture(new ImageIcon(TestTerrain.class.getClassLoader()
            .getResource("data/images/ice.jpg")), 128, 255,
            384);
      pt.createTexture(32);

      // assign the texture to the terrain
      TextureState ts = display.getRenderer().createTextureState();
      ts.setEnabled(true);
      Texture t1 = TextureManager.loadTexture(pt.getImageIcon().getImage(),
            Texture.MinificationFilter.Trilinear, Texture.MagnificationFilter.Bilinear, true);
      ts.setTexture(t1, 0);

      //load a detail texture and set the combine modes for the two terrain textures.
      Texture t2 = TextureManager.loadTexture(
            TestTerrain.class.getClassLoader().getResource(
                  "data/images/256px-Dirttexture.jpg"),
                  Texture.MinificationFilter.Trilinear,
                  Texture.MagnificationFilter.Bilinear);

      ts.setTexture(t2, 1);
      t2.setWrap(Texture.WrapMode.Repeat);

      t1.setApply(Texture.ApplyMode.Combine);
      t1.setCombineFuncRGB(Texture.CombinerFunctionRGB.Modulate);
      t1.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
      t1.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
      t1.setCombineSrc1RGB(Texture.CombinerSource.PrimaryColor);
      t1.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);

      t2.setApply(Texture.ApplyMode.Combine);
      t2.setCombineFuncRGB(Texture.CombinerFunctionRGB.AddSigned);
      t2.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
      t2.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
      t2.setCombineSrc1RGB(Texture.CombinerSource.Previous);
      t2.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);

      tb.setRenderState(ts);
      //set the detail parameters.
      tb.setDetailTexture(1, 16);
      tb.setRenderQueueMode(Renderer.QUEUE_OPAQUE);

      tb.setRenderState(ts);
   }

   /**
    * will be called if the resolution changes
    *
    * @see com.jme.app.BaseGame#reinit()
    */
   protected void reinit() {
      display.recreateWindow(width, height, depth, freq, fullscreen);
   }

   /**
    * close the window and also exit the program.
    */
   protected void quit() {
      super.quit();
      System.exit(0);
   }

   /**
    * clean up the textures.
    *
    * @see com.jme.app.BaseGame#cleanup()
    */
   protected void cleanup() {

   }
}

I added just the terrain building code to my project and everything is fine. Look around in the Player code to see what's happened there, if anything. Looks like you've got Shadows, which is a mystery to me (since I see no SRP).

it looks like the in and outside of the sphere are showing, are you missing a correct z-buffer state in your scene ?

Here is the player code as requested, nothing that should affect anything.


package prototype;

import com.jme.bounding.BoundingBox;
import com.jme.bounding.BoundingSphere;
import com.jme.input.InputHandler;
import com.jme.math.Vector3f;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;

public class Player extends Node{   
   InputHandler input;

   
   public Player(InputHandler input){
      this.input = input;
      Box b = new Box("", new Vector3f(0f,.0f,0f),1f,3.5f,1f);
      b.setModelBound(new BoundingBox());
        b.updateModelBound();       
      this.attachChild(b);
   
   }
   
}



Core-Dump said:

it looks like the in and outside of the sphere are showing, are you missing a correct z-buffer state in your scene ?


I barley understand what a Z buffer is, yet alone what a z-buffer state is. What do I look for?

He's right. I hadn't noticed you're missing a Z-Buf state. Anyway, the problem isn't in your Player code.



A ZBufferState performs Z-testing, which determines if particular geometry is closer than other geometry to the camera. It's what lets the computer render the front of images and not the back. You should execute something like this at the end-ish of your initGame(), but before you call updateGeometricState(…) and updateRenderState();


ZBufferState zbuf = DisplaySystem.getDisplaySystem().getRenderer.createZBufferState();
zbuf.setEnabled(true);
scene.setRenderState(zbuf);



Link to ZBuf Wiki

Thanks! That solved it.