Drawing lines help!

hello guys!



really need help on some noobie stuff, i've been trying to build a grid for my tactical game.

i've tried building one from boxes and decided that it's not what i should be doing.

but then, the lines really bother me too much, been here coding for 2 hours but no luck.

here's what i have so far:



        com.jme.scene.Line lb = new com.jme.scene.Line();

        lb.setMode(com.jme.scene.Line.SEGMENTS);
        lb.setVertexBuffer(0, BufferUtils.createFloatBuffer(12 * size * size));
        lb.setNormalBuffer(0, BufferUtils.createFloatBuffer(12 * size * size));
        lb.setIndexBuffer(BufferUtils.createIntBuffer(8 * size * size), 0);

        FloatBuffer vb = lb.getVertexBuffer(0), nb = lb.getNormalBuffer(0);
        IntBuffer ib = lb.getIndexBuffer(0);
        vb.rewind(); nb.rewind(); ib.rewind();

        for(int i=0; i<size; i++) {
            for(int j=0; j<size; j++) {
                float x = i*cellSize; float z = j*cellSize;

                // vertex
                vb.put(x).put(getHeight(x,z)).put(z);
                vb.put(x).put(getHeight(x,z+cellSize)).put(z+cellSize);
                vb.put(x+cellSize).put(getHeight(x+cellSize,z+cellSize)).put(z+cellSize);
                vb.put(x+cellSize).put(getHeight(x+cellSize,z)).put(z);

                // index
                int n = (i*size*4) + (j*4);
                ib.put(n).put(n+1);
                ib.put(n+1).put(n+2);
                ib.put(n+2).put(n+3);
                ib.put(n+3).put(n);

                // normal
                Vector3f normal = new Vector3f();
                tb.getSurfaceNormal(x, z, normal);
                nb.put(normal.getX()).put(normal.getY()).put(normal.getZ());
                tb.getSurfaceNormal(x, z+cellSize, normal);
                nb.put(normal.getX()).put(normal.getY()).put(normal.getZ());
                tb.getSurfaceNormal(x+cellSize, z+cellSize, normal);
                nb.put(normal.getX()).put(normal.getY()).put(normal.getZ());
                tb.getSurfaceNormal(x+cellSize, z+cellSize, normal);
                nb.put(normal.getX()).put(normal.getY()).put(normal.getZ());

                // quad
                Quad q = new Quad("cell_"+i+"_"+j, cellSize, cellSize);
                q.setColorBuffer(0, null);
                q.setLightCombineMode(LightState.OFF);
                q.setDefaultColor(new ColorRGBA(0.4f,0.7f,1.0f,0.4f));
                q.setLocalTranslation(x+cellSize/2, getHeight(x+cellSize/2,z+cellSize/2)-1f, z+cellSize/2);
                q.getLocalRotation().fromAngleAxis(90.0f * FastMath.DEG_TO_RAD, Vector3f.UNIT_X);
                attachChild(q);
            }
        }
        lb.setAntialiased(true);
        attachChild(lb);



i've used the same loop to generate quads to shows the problem clearer:



it just shows a size X size/2 grid. (opposed to should be being size X size).
anybody help me! i'm a noobie on vertices/indices/normals and the like.

also, is there any more efficient way to create a grid?
i've tried Boxes, but when i reach 50x50++ it really starts to get slow.

thanks a lot!

Andrew

well, i really think i need the indices to make it look like a grid.

but still it bothers me, it doesn't render correctly. (still size x size/2).

the vertices and indices increment correctly though.

What's the effect of your code?



With line object you can simply use the recontruct function, with all null except vertex, and setLightCombineMode(LightState.OFF), if you have set normalBuffer to null.

public void buildGrid(int size, float cellSize, float heightOffset, TerrainBlock tb);



it should build a (size by size) grid, having a cellSize width and length (x,z).

the effect of this is that it only creates half of the intended (size by size/2).

the boxes on the X axis were half of that on the Z axis.



i've printed the coordinates for x and z and they were correct, i think even the index numbers were too.

I have not checked this through, but It could be that it is rendered, but it is depth-fighting, and thus some parts are invisible… If so, try using a polygon offset when rendering (search the forums for it… it was done over a month ago).

i tried the setPolygonOffset function and i doubt it is depth-fighting… it always shows a grid n by (n/2) everytime on any integer n. maybe its because of the duplicate vertices? i have editted the index grabbing ( made it into int n = ( i * cellSize * 8 ) + ( j * 4 ); ) and it showed an alternating grid through the X axis. i fairly believe its because of my noob-levelled vertices and indices programming. :stuck_out_tongue:

Have you tried geometry instancing for the boxes?  Look in the tests for jmetest.scene.geometryinstancing.TestGeometryInstancing.java



See if that helps you with the boxes.  If it looks better let me know and there's a newer version I can send you, or just PM Snylt about it - he created most/all of it.

wow thanks for the tip chirstius! forgot about that one.

geometry instancing is really fast!

made 10,000 boxes of grid cells and its still smooth. :slight_smile:



still, the Line stuff is persistently weird. :smiley:



~ follow up:

is there an easier way to update an instance's color?

like for example from a BoundingPickResult?

kinda sick, but the only way i did it was through manual editing of the ColorBuffer…:



// box has 24 vertices so… ID starts from 0

for(int i=24boxID; i<24(boxID+1); i++)

    ((FloatBuffer)results.getPickData(0).getTargetMesh()

    .getColorBuffer().position(4*i)).put(new float[]{1,1,1,0.5f});

// white a=0.5



its actually better than the sluggish slow lots-a-boxes.



thanks guys! hope this thread helps somebody out. :slight_smile:



although i'll appreciate a help about the Line problem above.

gam3r_3xtr3m3 said:

wow thanks for the tip chirstius! forgot about that one.


Thank me for the tip, but thank Snylt for the hard work.  Geometry instancing saved me as well allowing me to make very large game boards for my project.

gam3r_3xtr3m3 said:

~ follow up:
is there an easier way to update an instance's color?
like for example from a BoundingPickResult?


Can you use a texture for this or must it be done through vertex coloring/color buffer only?

I ended up using a texture atlas to change certain tiles in my game from default to "selected" to "marked for movement" and so on.  I just flip the texcoords on the instance that's picked and it goes from green to red, or red to yellow, or whatever section of the texture atlas I want it to be.  Once again thanks goes to Snylt for pointing me in the direction of this technique.  It works very well for what I needed.  If you think it'll work for you let me know via PM and I'll see if I can throw together a demo and send it to you.  It does require the newer GeometryInstancing classes to work though.  I can include a copy of those as well since I do not think they are incorporated into the mainline jME distro yet.

yey thanks Snylt!  :smiley:



sure do, i'll be more than glad to try out that one!

just sent you the PM. thanks a lot!  :slight_smile:

ok i have solved the 'everthing in a single mesh picking' problem and had a custom picker: (not picking by bounds but by points)



Camera camera = DisplaySystem.getDisplaySystem().getRenderer().getCamera();
Vector3f worldCoords = camera.getWorldCoordinates(mousePos, 1.0f);
Ray ray = new Ray(camera.getLocation(), worldCoords
        .subtractLocal(camera.getLocation())
        .normalizeLocal());

float terrainWidth = tb.getStepScale().x * tb.getSize();
float terrainLength = tb.getStepScale().z * tb.getSize();
Vector3f location = new Vector3f();
ray.intersectWherePlanarQuad(new Vector3f(0,0,0), new Vector3f(terrainWidth,0,0), new Vector3f(0,0,terrainLength), location);
int selX = (int)(terrainWidth*location.y)/(cellSize+cellSpace);
int selZ = (int)(terrainLength*location.z)/(cellSize+cellSpace);

int boxID = selX*terrainLength + selY;
for(int i=24*boxID; i<24*(boxID+1); i++)
    ((FloatBuffer)results.getPickData(0).getTargetMesh()
    .getColorBuffer().position(4*i)).put(new float[]{1,1,1,0.5f});



in case this would help someone. :)