Throwing Thousands of Points

I'm working on a sensor project for our search and rescue robots.  We have a rotating laser that provides points in space in a cone shape.  In one rotation, we see about 25000 unique points.



I would like to create a dynamic 3D scene using these points - culling the older points and showing the newer ones.  However, trying to create even 8000 points bombs out jme.  Is there a better way to display this many points?  Will they be as easy to remove as a point attached to a GameState?



Thanks!



-Jeff Kramer

www.crasar.org

Looking at the console and the exception, it appears to blow up at right around 516 points.

Are you making a new Point object per point?  Try using a single Point object with multiple vertices.

Yes, PointBatch is your friend here…

PointBatch? I'll look into it. :slight_smile:



Does code like this generate a new Point every time?


for (int i=0; i<NumPoints; i++) {
           PointList[i] = new Point("p"+i,vertexes,null,null,null);
           gameState.getRootNode().attachChild(PointList[i]);
        }

Yes, instead you want to populate your 'vertexes' variable with all your points, then put it in a single Point object.

TestBatchMesh also does something like this (escp. useful if you have several groups of points).

Ah, I was trying to create 80008000 points (each Point call was calling 8000 verticies).



516
8000 = 4.128 M points…



Thanks for all the help folks! :)  You've won me (and most of my lab) over.



We may have some visualization code to add sometime soon (as in a visualization library).



Thanks!



-Jeff

great to hear! got any nice photos of the robots or something? :slight_smile:

Soon!  Our laser data will be accurate enough to show millimeter accuracy on things near the laser - expect shots of our faces made of points, etc. :slight_smile:





Another question:



I have all these points - can I color them individually?



What's the best method?



I'm currently throwing a ColorRGBA[] to the Point constructor at the same time I send the vertexes.  However, this causes the "disco strobe" effect. :frowning:



Any thoughts?

The ColorRGBA should be fine, you just need to be sure you are assigning the same color value to the same vert each time.  Also, eventually you might consider editting the FloatBuffer directly instead of recreating each time passing in the arrays.

doing something like coloring based on distance from laser etc would be fastest if calculated in a shader directly…



another possibility could be to texture the point mesh…in the normal way or with some texture generation used…

It's still strobing.  Am I using it wrong?


package jmetest.LaserTest;

import java.util.Random;
import javax.vecmath.*;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Point;
import com.jme.scene.shape.Box;
import com.jme.scene.state.LightState;
import com.jme.system.DisplaySystem;
import com.jmex.game.StandardGame;
import com.jmex.game.state.DebugGameState;
import com.jmex.game.state.GameStateManager;

/**
 * Laser Draw Test
 *
 * @author Jeff Kramer
 */


public class LaserTest {
   static final int NUMPOINTS = 72200;
   static StandardGame game;
   
   public static void main(String[] args) throws Exception {
        DebugGameState gameState = StartGame("game");
       
       
       
        Random r = new Random();
       
        Vector3f[] vertexes = new Vector3f[NUMPOINTS];
        ColorRGBA[] colors = new ColorRGBA[NUMPOINTS];
        for (int v = 0; v<NUMPOINTS; v++) {vertexes[v] = new Vector3f();} //Set to zero
        for (int v = 0; v<NUMPOINTS; v++) {colors[v] = colors[v].white;}
        int iTrack = 0;
        int RotSize = 5000;
        double LaserScanTime = 0.053; //seconds per scan
        int LaserValues = 361;
        int LaserRange = 10; //in m
        double RotRate = 1.5; //Rev/Sec
        double RotPush = LaserScanTime*RotRate*RotSize; //points/scan
        double RotStep = (RotPush/LaserValues)*((2*Math.PI)/RotSize); //rads/dp
        double phi = 0;
        float color = 0;
        ColorRGBA cWhite = ColorRGBA.white;
        double ldist = 0.0;
       
        while (true){
           
           for (int i=0; i<LaserValues; i++) {
              
               ldist = r.nextDouble()*LaserRange;
              javax.vecmath.Point3d p3d = AngleToCartesian(ldist, (i*Math.PI)/360, phi);
              //System.out.println("X = " + p3d.x + " Y = " + p3d.y + " Z = "+ p3d.z);
              vertexes[iTrack].set((float)p3d.x, (float)p3d.y, (float)p3d.z);
              color = (float)(ldist/LaserRange);
              colors[iTrack].set(color, (float)(color), (float)(color), 1);
              //colors[iTrack].set(cWhite);
              phi = phi+RotStep;
              if (phi >= 2*Math.PI) phi = 0;
              if (iTrack < NUMPOINTS-1) {
                 iTrack++;
              } else {
                 iTrack = 0;
              }
              //DrawScene(gameState, vertexes, colors);
           }
           DrawScene(gameState, vertexes, colors);
        //   Thread.sleep(4000);
        }
       
    }
   
    static DebugGameState StartGame (String GameName) {
      game = new StandardGame(GameName); //Create the Game
      game.start(); //Start the thread
      
      DebugGameState DGS = new DebugGameState(); //create game state
      GameStateManager.getInstance().attachChild(DGS); //Attach it
      DGS.setActive(true); //Turn it on!
      //Box Push
      Box box = new Box("TestBox", new Vector3f(), 0.1f, 0.1f, 0.1f);      // Create a Box
        box.setRandomColors();   // Set random colors on it
        box.updateRenderState();   // Update the render state so the colors appear (the game is already running, so this must always be done)
        DGS.getRootNode().attachChild(box);   // Attach the box to rootNode in DebugGameState
      
      //Lighting Section
      LightState lightState = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
      lightState.setEnabled(false);
      DGS.getRootNode().setRenderState(lightState);
      DGS.getRootNode().setLightCombineMode(LightState.REPLACE);
       
       return DGS;   
    }
   
    static boolean DrawScene(DebugGameState DGS, Vector3f[] vPoints, ColorRGBA[] cColor) {
       game.lock();
       DGS.getRootNode().detachChildNamed("p");
       Point A = new Point("p", vPoints, null, cColor, null);
       DGS.getRootNode().attachChild(A);
       game.unlock();
       return true;
    }
   
    static javax.vecmath.Point3d AngleToCartesian(double dRadius, double dLaserAngle, double dRotAngle) {
       //System.out.println("In AngleToCartesian");
       javax.vecmath.Point3d pCalc = new javax.vecmath.Point3d(dRadius*Math.cos(dLaserAngle), dRadius*Math.sin(dLaserAngle), 0);
       Matrix4d mRot = new Matrix4d();
       mRot.rotY(dRotAngle);
       mRot.transform(pCalc);
       //System.out.println(pCalc.x + " " + pCalc.y + " "+ pCalc.z);
       return pCalc;
    }
   
   
}



Thanks for the suggestions - I need to read more about the different parts. :)

-Jeff