how to detect collisions after GeometryBatchFactory.optimize() jme3 r7245

Here’s an example (code by @ehnohpe ) where I don’t know how to detect which cube (out of all 2000 of them) was hit, that is, after I ran GeometryBatchFactory.optimize() , though the cubes’ geoms are still stored in the field cube they cannot be found when getting the collided geom ie. via CollisionResult.getClosestCollision().getGeometry():

Well I mean, you are detecting the geometry but no idea of which cube it is part of, or rather which cube is it, to remove it also from the internally kept “map”

pre type="java"
package org.jme3.tests;





import java.util.ArrayList;


import java.util.Random;





import jme3tools.optimize.GeometryBatchFactory;





import com.jme3.app.SimpleApplication;


import com.jme3.collision.CollisionResult;


import com.jme3.collision.CollisionResults;


import com.jme3.font.BitmapText;


import com.jme3.input.KeyInput;


import com.jme3.input.controls.ActionListener;


import com.jme3.input.controls.KeyTrigger;


import com.jme3.input.controls.MouseButtonTrigger;


import com.jme3.light.DirectionalLight;


import com.jme3.material.Material;


import com.jme3.math.ColorRGBA;


import com.jme3.math.FastMath;


import com.jme3.math.Ray;


import com.jme3.math.Triangle;


import com.jme3.math.Vector3f;


import com.jme3.scene.Geometry;


import com.jme3.scene.Node;


import com.jme3.scene.shape.Box;


import com.jme3.scene.shape.Cylinder;


import com.jme3.system.AppSettings;





public class LotsaCubesOptimized extends SimpleApplication {





public static void main(String[] args) {


LotsaCubesOptimized app = new LotsaCubesOptimized();


settingst = new AppSettings(true);


// settingst.setFrameRate( 75 );


settingst.setResolution(1280, 700);


settingst.setVSync(true);


settingst.setFullscreen(false);


app.setSettings(settingst);


app.setShowSettings(false);


app.start();


}





private final ActionListener al = new ActionListener() {





@Override


public void onAction(String name, boolean isPressed, float tpf) {


if (name.equals(“Start Game”)) {


// randomGenerator();


}


}


};


protected Random rand = new Random();


protected int maxCubes = 2000;


protected int startAt = 0;


protected ArrayList cube = new ArrayList();


protected static int xPositions = 0, yPositions = 0, zPositions = 0;


protected int returner = 0;


protected ArrayList xPosition = new ArrayList();


protected ArrayList yPosition = new ArrayList();


protected ArrayList zPosition = new ArrayList();


protected int xLimitf = 60, xLimits = -60, yLimitf = 60, yLimits = -20,


zLimitf = 60, zLimits = -60;


protected int circ = 8; // increases


// by


// 8


// every


// time.


protected int dynamic = 4;


protected static AppSettings settingst;


protected boolean isTrue = true;


private BitmapText helloText2;


private final int lineLength = 50;


protected Node terrain;


Material mat1;


Material mat2;


Material mat3;


Material mat4;





// protected


// protected Geometry player;


@Override


public void simpleInitApp() {


// guiNode.detachAllChildren();


// guiFont = assetManager.loadFont(“Interface/Fonts/Default.fnt”);


// BitmapText helloText = new BitmapText(guiFont, false);


// helloText.setSize(guiFont.getCharSet().getRenderedSize());


// helloText.setText(“Created by: Veenen, Inc.”);


// helloText.setLocalTranslation(5, helloText.getLineHeight(), 0);


// helloText2 = new BitmapText(guiFont, false);


// helloText2.setSize(guiFont.getCharSet().getRenderedSize());


// helloText2.setText(“Cubes: " + startAt + 1);


// helloText2.move(5, 52, 0);


// fpsText.move(5, 15, 0);


// guiNode.attachChild(helloText);


// guiNode.attachChild(helloText2);


// guiNode.attachChild(fpsText);


terrain = new Node();


mat1 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);


mat1.setColor(“Color”, ColorRGBA.Blue);


mat2 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);


mat2.setColor(“Color”, ColorRGBA.Brown);


mat3 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);


mat3.setColor(“Color”, ColorRGBA.Pink);


mat4 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);


mat4.setColor(“Color”, ColorRGBA.Orange);


// rootNode.attachChild(SkyFactory.createSky(


// assetManager, “Textures/SKY02.zip”, false));


inputManager.addMapping(“Start Game”, new KeyTrigger(KeyInput.KEY_J));


inputManager.addListener(al, new String[] { “Start Game” });


flyCam.setMoveSpeed(25);


// ChaseCamera c = new ChaseCamera();


// flyCam.setEnabled(false);


xPosition.add(0);


yPosition.add(0);


zPosition.add(0);


Box box1 = new Box(new Vector3f(xPosition.get(xPosition.size() - 1),


yPosition.get(yPosition.size() - 1), zPosition.get(zPosition


.size() - 1)), 1, 1, 1);


Geometry blue = new Geometry(“Box”, box1);


Material mat11 = new Material(assetManager,


“Common/MatDefs/Misc/Unshaded.j3md”);


mat11.setColor(“Color”, ColorRGBA.Cyan);


blue.setMaterial(mat11);


terrain.attachChild(blue);


DirectionalLight sun = new DirectionalLight();


sun.setDirection(new Vector3f(-0.1f, 50, -1.0f));


sun.setLastDistance(500);


rootNode.addLight(sun);


randomGenerator();


GeometryBatchFactory.optimize(terrain);


Geometry geo = new Geometry(“xx”, new Box(19, 1, 1));


geo.setMaterial(randomMaterial());


terrain.detachAllChildren();


terrain.attachChild(geo);


for (int i = 0; i < cube.size(); i++) {


terrain.attachChild(cube.get(i));


}


GeometryBatchFactory.optimize(terrain);


System.out.println(terrain.getQuantity());


rootNode.attachChild(terrain);





inputManager.addMapping(mappingBoom,


new KeyTrigger(KeyInput.KEY_SPACE), new MouseButtonTrigger(0));


inputManager.addListener(actionListener, mappingBoom);





BitmapText ch = new BitmapText(guiFont, false);


ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);


ch.setText(”+"); // crosshairs


ch.setLocalTranslation(


// center


settings.getWidth() / 2

  • guiFont.getCharSet().getRenderedSize() / 3 * 2,


    settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);


    guiNode.attachChild(ch);





    cylinderMat = new Material(assetManager,


    “Common/MatDefs/Misc/SolidColor.j3md”);


    cylinderMat.setColor(“Color”, ColorRGBA.Red);


    }





    private Material cylinderMat;


    private final static String mappingBoom = “boom”;


    /**




    • */


      private final ActionListener actionListener = new ActionListener() {





      @SuppressWarnings(“synthetic-access”)


      @Override


      public void onAction(String name, boolean isPressed, float tpf) {


      if ((name == mappingBoom) && (isPressed)) {


      // 1. Reset results list.


      CollisionResults results = new CollisionResults();


      // 2. Aim the ray from cam loc to cam direction.


      Ray ray = new Ray(cam.getLocation(), cam.getDirection());


      terrain.collideWith(ray, results);


      if (results.size() > 0) {


      // The closest collision point is what was truly hit:


      CollisionResult closest = results.getClosestCollision();





      Vector3f target = closest.getContactPoint().clone();


      Vector3f from = cam.getLocation().clone();


      // move 20% more in front of camera


      from = FastMath.interpolateLinear(0.2f, from, target);


      // and now calculate 50% distance of that from to target


      Vector3f halfDistance = FastMath.interpolateLinear(0.5f,


      from, target);


      float len = target.subtract(from).length();


      Cylinder l = new Cylinder(10, 10, 0.2f, len, true);


      Geometry geo = new Geometry(“ray”, l);


      geo.setMaterial(cylinderMat);


      geo.setLocalTranslation(halfDistance);


      rootNode.attachChild(geo);


      geo.lookAt(closest.getContactPoint().clone(), cam.getUp());


      // already cloned getUp()


      System.out.println("geoName: "

    • closest.getGeometry().getName() + " in cube:"

    • cube.contains(closest.getGeometry())

    • " userData:"

    • closest.getGeometry().getUserData(“a”));


      // Triangle store = null;


      // closest.getTriangle(store);


      // closest.getGeometry().getMesh().


      // mark.setLocalTranslation(closest.getContactPoint());


      }


      // for (int i = 0; i < results.size(); i++) {


      // // For each hit, we know distance, impact point, name of


      // // geometry.


      // CollisionResult cr = results.getCollision(i);


      // float dist = cr


      //


      // .getDistance();


      // Vector3f pt = cr.getContactPoint();


      // String hit = cr.getGeometry().getName();


      // System.out.println("* Collision #" + i);


      // System.out.println(" You shot " + hit + " at " + pt + “, "


      // + dist + " wu away.”);


      // Geometry oneSphere = mark.clone();


      // oneSphere.setLocalTranslation(cr.getContactPoint());


      // marks.attachChild(oneSphere);


      // }


      }


      }


      };





      public void randomGenerator() {


      for (int i = startAt; i < maxCubes - 1; i++) {


      randomize();


      Geometry box = new Geometry(“Box”, new Box(new Vector3f(


      xPosition.get(xPosition.size() - 1),


      yPosition.get(yPosition.size() - 1),


      zPosition.get(zPosition.size() - 1)), 1, 1, 1));


      box.setMaterial(randomMaterial());


      box.setUserData(“a”, “” + i);


      cube.add(box);


      // GeometryBatchFactory.optimize( box );


      terrain.attachChild(box);


      }


      }





      public Material randomMaterial() {


      Material returnermat = new Material();


      int randomn = rand.nextInt(4);


      if (randomn == 0) {


      returnermat = mat1;


      } else if (randomn == 1) {


      returnermat = mat2;


      } else if (randomn == 2) {


      returnermat = mat3;


      } else if (randomn == 3) {


      returnermat = mat4;


      }


      return returnermat;


      }





      public ColorRGBA randomColor() {


      ColorRGBA color = ColorRGBA.Black;


      int randomn = rand.nextInt(4);


      if (randomn == 0) {


      color = ColorRGBA.Orange;


      } else if (randomn == 1) {


      color = ColorRGBA.Blue;


      } else if (randomn == 2) {


      color = ColorRGBA.Brown;


      } else if (randomn == 3) {


      color = ColorRGBA.Magenta;


      }


      return color;


      }





      public void randomize() {


      int xpos = xPosition.get(xPosition.size() - 1);


      int ypos = yPosition.get(yPosition.size() - 1);


      int zpos = zPosition.get(zPosition.size() - 1);


      int x = 0;


      int y = 0;


      int z = 0;


      boolean unTrue = true;


      while (unTrue) {


      unTrue = false;


      boolean xChanged = false;


      x = 0;


      y = 0;


      z = 0;


      if (xpos >= lineLength * 2) {


      x = 2;


      xChanged = true;


      } else {


      x = xPosition.get(xPosition.size() - 1) + 2;


      }


      if (xChanged) {


      // y = yPosition.get(yPosition.size() - lineLength) + 2;


      } else {


      y = rand.nextInt(3);


      if (yPosition.size() > lineLength) {


      if (yPosition.size() > 51) {


      if (y == 0 && ypos < yLimitf


      && getym(lineLength) > ypos - 2) {


      y = ypos + 2;


      } else if (y == 1 && ypos > yLimits


      && getym(lineLength) < ypos + 2) {


      y = ypos - 2;


      } else if (y == 2 && getym(lineLength) > ypos - 2


      && getym(lineLength) < ypos + 2) {


      y = ypos;


      } else {


      if (ypos >= yLimitf) {


      y = ypos - 2;


      } else if (ypos <= yLimits) {


      y = ypos + 2;


      } else if (y == 0 && getym(lineLength) >= ypos - 4) {


      y = ypos - 2;


      } else if (y == 0 && getym(lineLength) >= ypos - 2) {


      y = ypos;


      } else if (y == 1 && getym(lineLength) >= ypos + 4) {


      y = ypos + 2;


      } else if (y == 1 && getym(lineLength) >= ypos + 2) {


      y = ypos;


      } else if (y == 2 && getym(lineLength) <= ypos - 2) {


      y = ypos - 2;


      } else if (y == 2 && getym(lineLength) >= ypos + 2) {


      y = ypos + 2;


      } else {


      System.out.println(“wtf”);


      }


      }


      } else if (yPosition.size() == lineLength) {


      if (y == 0 && ypos < yLimitf) {


      y = getym(lineLength) + 2;


      } else if (y == 1 && ypos > yLimits) {


      y = getym(lineLength) - 2;


      }


      }


      } else {


      if (y == 0 && ypos < yLimitf) {


      y = ypos + 2;


      } else if (y == 1 && ypos > yLimits) {


      y = ypos - 2;


      } else if (y == 2) {


      y = ypos;


      } else if (y == 0 && ypos >= yLimitf) {


      y = ypos - 2;


      } else if (y == 1 && ypos <= yLimits) {


      y = ypos + 2;


      }


      }


      }


      if (xChanged) {


      z = zpos + 2;


      } else {


      z = zpos;


      }


      // for (int i = 0; i < xPosition.size(); i++)


      // {


      // if (x - xPosition.get(i) <= 1 && x - xPosition.get(i) >= -1 &&


      // y - yPosition.get(i) <= 1 && y - yPosition.get(i) >= -1


      // &&z - zPosition.get(i) <= 1 && z - zPosition.get(i) >=


      // -1)


      // {


      // unTrue = true;


      // }


      // }


      }


      xPosition.add(x);


      yPosition.add(y);


      zPosition.add(z);


      }





      public int getxm(int i) {


      return xPosition.get(xPosition.size() - i);


      }





      public int getym(int i) {


      return yPosition.get(yPosition.size() - i);


      }





      public int getzm(int i) {


      return zPosition.get(zPosition.size() - i);


      }





      public int getx(int i) {


      return xPosition.get(i);


      }





      public int gety(int i) {


      return yPosition.get(i);


      }





      public int getz(int i) {


      return zPosition.get(i);


      }





      @Override


      public void simpleUpdate(float tpf) {


      // helloText2.setText("Cubes: " + xPosition.size() + ", " +


      // settingst.getWidth());


      }


      }



      /pre



      EDIT:

      meanwhile I found this:
Side-effects

Using GeometryBatchFactory merges individual Geometries into a single mesh. Thereby it becomes hard to apply specific Materials or to remove a single Geometry. Therefore it should be used for static Geometry only that does not require frequent changes or individual materials/texturing.

on this page: https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:intermediate:optimization?s[]=geometrybatchfactory&s[]=optimize

oh nevermind I got it, how silly of me, though having to re-add the nodes to the terrain and running optimize() again after removal, is taking a lot of time

here’s the code as it is now:

though clearly this is not the way to remove that stuff from terrain



pre type="java"
package org.jme3.tests;





import java.util.ArrayList;


import java.util.Random;





import jme3tools.optimize.GeometryBatchFactory;





import com.jme3.app.SimpleApplication;


import com.jme3.collision.CollisionResult;


import com.jme3.collision.CollisionResults;


import com.jme3.font.BitmapText;


import com.jme3.input.KeyInput;


import com.jme3.input.controls.ActionListener;


import com.jme3.input.controls.KeyTrigger;


import com.jme3.input.controls.MouseButtonTrigger;


import com.jme3.light.DirectionalLight;


import com.jme3.material.Material;


import com.jme3.math.ColorRGBA;


import com.jme3.math.FastMath;


import com.jme3.math.Ray;


import com.jme3.math.Triangle;


import com.jme3.math.Vector3f;


import com.jme3.scene.Geometry;


import com.jme3.scene.Node;


import com.jme3.scene.shape.Box;


import com.jme3.scene.shape.Cylinder;


import com.jme3.system.AppSettings;





public class LotsaCubesOptimized extends SimpleApplication {





    public static void main(String[] args) {


LotsaCubesOptimized app = new LotsaCubesOptimized();


settingst = new AppSettings(true);


// settingst.setFrameRate( 75 );


settingst.setResolution(1280, 700);


settingst.setVSync(true);


settingst.setFullscreen(false);


app.setSettings(settingst);


app.setShowSettings(false);


app.start();


    }





    private final ActionListener al = new ActionListener() {





@Override


public void onAction(String name, boolean isPressed, float tpf) {


    if (name.equals(“Start Game”)) {


// randomGenerator();


    }


}


    };


    protected Random rand = new Random();


    protected int maxCubes = 2000;


    protected int startAt = 0;


    protected ArrayList<Geometry> cube = new ArrayList<Geometry>();


    protected static int xPositions = 0, yPositions = 0, zPositions = 0;


    protected int returner = 0;


    protected ArrayList<Integer> xPosition = new ArrayList<Integer>();


    protected ArrayList<Integer> yPosition = new ArrayList<Integer>();


    protected ArrayList<Integer> zPosition = new ArrayList<Integer>();


    protected int xLimitf = 60, xLimits = -60, yLimitf = 60, yLimits = -20,


    zLimitf = 60, zLimits = -60;


    protected int circ = 8; // increases


    // by


    // 8


    // every


    // time.


    protected int dynamic = 4;


    protected static AppSettings settingst;


    protected boolean isTrue = true;


    private BitmapText helloText2;


    private final int lineLength = 50;


    protected Node terrain;


    Material mat1;


    Material mat2;


    Material mat3;


    Material mat4;





    // protected


    // protected Geometry player;


    @Override


    public void simpleInitApp() {


// guiNode.detachAllChildren();


// guiFont = assetManager.loadFont(“Interface/Fonts/Default.fnt”);


// BitmapText helloText = new BitmapText(guiFont, false);


// helloText.setSize(guiFont.getCharSet().getRenderedSize());


// helloText.setText(“Created by: Veenen, Inc.”);


// helloText.setLocalTranslation(5, helloText.getLineHeight(), 0);


// helloText2 = new BitmapText(guiFont, false);


// helloText2.setSize(guiFont.getCharSet().getRenderedSize());


// helloText2.setText(“Cubes: " + startAt + 1);


// helloText2.move(5, 52, 0);


// fpsText.move(5, 15, 0);


// guiNode.attachChild(helloText);


// guiNode.attachChild(helloText2);


// guiNode.attachChild(fpsText);


terrain = new Node();


mat1 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);


mat1.setColor(“Color”, ColorRGBA.Blue);


mat2 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);


mat2.setColor(“Color”, ColorRGBA.Brown);


mat3 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);


mat3.setColor(“Color”, ColorRGBA.Pink);


mat4 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);


mat4.setColor(“Color”, ColorRGBA.Orange);


// rootNode.attachChild(SkyFactory.createSky(


// assetManager, “Textures/SKY02.zip”, false));


inputManager.addMapping(“Start Game”, new KeyTrigger(KeyInput.KEY_J));


inputManager.addListener(al, new String[] { “Start Game” });


flyCam.setMoveSpeed(25);


// ChaseCamera c = new ChaseCamera();


// flyCam.setEnabled(false);


xPosition.add(0);


yPosition.add(0);


zPosition.add(0);


Box box1 = new Box(new Vector3f(xPosition.get(xPosition.size() - 1),


yPosition.get(yPosition.size() - 1), zPosition.get(zPosition


.size() - 1)), 1, 1, 1);


Geometry blue = new Geometry(“Box”, box1);


Material mat11 = new Material(assetManager,


“Common/MatDefs/Misc/Unshaded.j3md”);


mat11.setColor(“Color”, ColorRGBA.Cyan);


blue.setMaterial(mat11);


terrain.attachChild(blue);


DirectionalLight sun = new DirectionalLight();


sun.setDirection(new Vector3f(-0.1f, 50, -1.0f));


sun.setLastDistance(500);


rootNode.addLight(sun);


randomGenerator();


GeometryBatchFactory.optimize(terrain);


Geometry geo = new Geometry(“xx”, new Box(19, 1, 1));


geo.setMaterial(randomMaterial());


terrain.detachAllChildren();


terrain.attachChild(geo);


for (int i = 0; i < cube.size(); i++) {


    terrain.attachChild(cube.get(i));


}


GeometryBatchFactory.optimize(terrain);


System.out.println(terrain.getQuantity());


rootNode.attachChild(terrain);





inputManager.addMapping(mappingBoom,


new KeyTrigger(KeyInput.KEY_SPACE), new MouseButtonTrigger(0));


inputManager.addListener(actionListener, mappingBoom);





BitmapText ch = new BitmapText(guiFont, false);


ch.setSize(guiFont.getCharSet().getRenderedSize()  2);


ch.setText("+"); // crosshairs


ch.setLocalTranslation(


// center


settings.getWidth() / 2


- guiFont.getCharSet().getRenderedSize() / 3 
 2,


settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);


guiNode.attachChild(ch);





cylinderMat = new Material(assetManager,


“Common/MatDefs/Misc/SolidColor.j3md”);


cylinderMat.setColor(“Color”, ColorRGBA.Red);


    }





    private Material cylinderMat;


    private final static String mappingBoom = “boom”;


    /**


      


     
/


    private final ActionListener actionListener = new ActionListener() {





@SuppressWarnings(“synthetic-access”)


@Override


public void onAction(String name, boolean isPressed, float tpf) {


    if ((name == mappingBoom) && (isPressed)) {


// 1. Reset results list.


CollisionResults results = new CollisionResults();


// 2. Aim the ray from cam loc to cam direction.


Ray ray = new Ray(cam.getLocation(), cam.getDirection());


// terrain.collideWith(ray, results);


for (int i = 0; i < cube.size(); i++) {


    cube.get(i).collideWith(ray, results);


}


if (results.size() > 0) {


    // The closest collision point is what was truly hit:


    CollisionResult closest = results.getClosestCollision();





    Vector3f target = closest.getContactPoint().clone();


    Vector3f from = cam.getLocation().clone();


    // move 20% more in front of camera


    from = FastMath.interpolateLinear(0.2f, from, target);


    // and now calculate 50% distance of that from to target


    Vector3f halfDistance = FastMath.interpolateLinear(0.5f,


    from, target);


    float len = target.subtract(from).length();


    Cylinder l = new Cylinder(10, 10, 0.2f, len, true);


    Geometry geo = new Geometry(“ray”, l);


    geo.setMaterial(cylinderMat);


    geo.setLocalTranslation(halfDistance);


    rootNode.attachChild(geo);


    geo.lookAt(closest.getContactPoint().clone(), cam.getUp());


    // already cloned getUp()


    System.out.println(“geoName: "


    + closest.getGeometry().getName() + " in cube:”


    + cube.contains(closest.getGeometry())


    + " userData:”


    + closest.getGeometry().getUserData(“a”));


    cube.remove(closest.getGeometry());


    terrain.detachAllChildren();


    for (int i = 0; i < cube.size(); i++) {


terrain.attachChild(cube.get(i));


    }


    GeometryBatchFactory.optimize(terrain);


    // Triangle store = null;


    // closest.getTriangle(store);


    // closest.getGeometry().getMesh().


    // mark.setLocalTranslation(closest.getContactPoint());


}


// for (int i = 0; i < results.size(); i++) {


// // For each hit, we know distance, impact point, name of


// // geometry.


// CollisionResult cr = results.getCollision(i);


// float dist = cr


//


// .getDistance();


// Vector3f pt = cr.getContactPoint();


// String hit = cr.getGeometry().getName();


// System.out.println(" Collision #" + i);


// System.out.println("  You shot " + hit + " at " + pt + “, "


// + dist + " wu away.”);


// Geometry oneSphere = mark.clone();


// oneSphere.setLocalTranslation(cr.getContactPoint());


// marks.attachChild(oneSphere);


// }


    }


}


    };





    public void randomGenerator() {


for (int i = startAt; i < maxCubes - 1; i++) {


    randomize();


    Geometry box = new Geometry(“Box”, new Box(new Vector3f(


    xPosition.get(xPosition.size() - 1),


    yPosition.get(yPosition.size() - 1),


    zPosition.get(zPosition.size() - 1)), 1, 1, 1));


    box.setMaterial(randomMaterial());


    box.setUserData(“a”, “” + i);


    cube.add(box);


    // GeometryBatchFactory.optimize( box );


    terrain.attachChild(box);


}


    }





    public Material randomMaterial() {


Material returnermat = new Material();


int randomn = rand.nextInt(4);


if (randomn == 0) {


    returnermat = mat1;


} else if (randomn == 1) {


    returnermat = mat2;


} else if (randomn == 2) {


    returnermat = mat3;


} else if (randomn == 3) {


    returnermat = mat4;


}


return returnermat;


    }





    public ColorRGBA randomColor() {


ColorRGBA color = ColorRGBA.Black;


int randomn = rand.nextInt(4);


if (randomn == 0) {


    color = ColorRGBA.Orange;


} else if (randomn == 1) {


    color = ColorRGBA.Blue;


} else if (randomn == 2) {


    color = ColorRGBA.Brown;


} else if (randomn == 3) {


    color = ColorRGBA.Magenta;


}


return color;


    }





    public void randomize() {


int xpos = xPosition.get(xPosition.size() - 1);


int ypos = yPosition.get(yPosition.size() - 1);


int zpos = zPosition.get(zPosition.size() - 1);


int x = 0;


int y = 0;


int z = 0;


boolean unTrue = true;


while (unTrue) {


    unTrue = false;


    boolean xChanged = false;


    x = 0;


    y = 0;


    z = 0;


    if (xpos >= lineLength 
 2) {


x = 2;


xChanged = true;


    } else {


x = xPosition.get(xPosition.size() - 1) + 2;


    }


    if (xChanged) {


// y = yPosition.get(yPosition.size() - lineLength) + 2;


    } else {


y = rand.nextInt(3);


if (yPosition.size() > lineLength) {


    if (yPosition.size() > 51) {


if (y == 0 && ypos < yLimitf


&& getym(lineLength) > ypos - 2) {


    y = ypos + 2;


} else if (y == 1 && ypos > yLimits


&& getym(lineLength) < ypos + 2) {


    y = ypos - 2;


} else if (y == 2 && getym(lineLength) > ypos - 2


&& getym(lineLength) < ypos + 2) {


    y = ypos;


} else {


    if (ypos >= yLimitf) {


y = ypos - 2;


    } else if (ypos <= yLimits) {


y = ypos + 2;


    } else if (y == 0 && getym(lineLength) >= ypos - 4) {


y = ypos - 2;


    } else if (y == 0 && getym(lineLength) >= ypos - 2) {


y = ypos;


    } else if (y == 1 && getym(lineLength) >= ypos + 4) {


y = ypos + 2;


    } else if (y == 1 && getym(lineLength) >= ypos + 2) {


y = ypos;


    } else if (y == 2 && getym(lineLength) <= ypos - 2) {


y = ypos - 2;


    } else if (y == 2 && getym(lineLength) >= ypos + 2) {


y = ypos + 2;


    } else {


System.out.println(“wtf”);


    }


}


    } else if (yPosition.size() == lineLength) {


if (y == 0 && ypos < yLimitf) {


    y = getym(lineLength) + 2;


} else if (y == 1 && ypos > yLimits) {


    y = getym(lineLength) - 2;


}


    }


} else {


    if (y == 0 && ypos < yLimitf) {


y = ypos + 2;


    } else if (y == 1 && ypos > yLimits) {


y = ypos - 2;


    } else if (y == 2) {


y = ypos;


    } else if (y == 0 && ypos >= yLimitf) {


y = ypos - 2;


    } else if (y == 1 && ypos <= yLimits) {


y = ypos + 2;


    }


}


    }


    if (xChanged) {


z = zpos + 2;


    } else {


z = zpos;


    }


    // for (int i = 0; i < xPosition.size(); i++)


    // {


    // if (x - xPosition.get(i) <= 1 && x - xPosition.get(i) >= -1 &&


    // y - yPosition.get(i) <= 1 && y - yPosition.get(i) >= -1


    // &&z - zPosition.get(i) <= 1 && z - zPosition.get(i) >=


    // -1)


    // {


    // unTrue = true;


    // }


    // }


}


xPosition.add(x);


yPosition.add(y);


zPosition.add(z);


    }





    public int getxm(int i) {


return xPosition.get(xPosition.size() - i);


    }





    public int getym(int i) {


return yPosition.get(yPosition.size() - i);


    }





    public int getzm(int i) {


return zPosition.get(zPosition.size() - i);


    }





    public int getx(int i) {


return xPosition.get(i);


    }





    public int gety(int i) {


return yPosition.get(i);


    }





    public int getz(int i) {


return zPosition.get(i);


    }





    @Override


    public void simpleUpdate(float tpf) {


// helloText2.setText("Cubes: " + xPosition.size() + ", " +


// settingst.getWidth());


    }


}



/pre

In this case, doing your own intersects against the block data is a pretty easy math problem and you can bypass jme altogether.



It will be an order of magnitude more efficient memory and processor-wise as well, I think.

I don’t know how to do that, mathematically, I’m no good at maths :slight_smile:

But even if supposedly I can do a faster intersect, I would still have to recreate&optimize() again, I guess, which is the bottleneck here I believe…

I mean the fact that GeometryBatchFactory.optimize(terrain); has only 6 nodes or so after optimize, while it had 2000+ prior… I just cannot fathom how to remove only the geometry of the hit cube from the already optimized terrain



The optimize is kinda necessary because it can be like 20k cubes… I think I should take a closer look at how collideWith() works and optimize() and maybe find some way to keep terrain optimized and also remove the hit cube, maybe a new type of optimize()

Yes, I’m not sure what your end state is supposed to be but you will hit limitations with this approach long before you get to Minecraft, for example. At a minimum, the world would need to be broken into chunks.



But for just intersection testing, you shouldn’t have to recreate the geometry. You might need to do that as a result of the intersection (if you are adding or removing blocks) but that may not be the only reason to intersect the world (say, for collision detection with the player’s feet).



Even a brute force approach may be better in this case. Presuming your world data comes from some array, pick a step size smaller than a block (1/4 at most), scale a direction vector to that size and step a position along that vector until you are in a block. Then you’ve intersected. You won’t catch the edges of blocks but it will be fast and is hopefully straight forward.

1 Like