Weird error with GeometryBatchFactory.optimise()

Hi there,



I am building a game that incorporates a randomly generated tile-based maze. It does this by first generating a grid of characters using a dungeon generator algorithm, and then steps through each character in turn generating boxes or quads (walls or floors) for each cell in the grid depending on its value.



I’ve had the algorithm working before fine, even using the GeometryBatchFactory however this time I get a really weird effect. Since the last version I have rewritten most of the engine around it (it only displays the map so far), but the core class for generating the 3D map has remained much the same.



Without optimising the nodes it works fine, however after calling optimise I get the following:





It is meant to look like this (sorry about the poor paint job, it takes fiddling to generate the same map twice):





This is just a small section of the map and I am splitting the map into nodes that incorporate a 10x10 section of the grid before optimising each node. If I optimise the entire map as one node I lose the bottom 3/4 rows from the map in much the same way as these small sections.



The weird thing is the meshes are still there, they just lose the material and turn black.



[java]

Node currentNode = new Node();

int xCount = 0;

int yCount = 0;



for (int row = 0; row < cells.length; row++){

xCount++;

for (int col = 0; col < cells[row].length; col++){

yCount++;

//Optimize and attach node every 100 cells

if (xCount >= 10 && yCount >= 10){

mapNode.attachChild((Node) GeometryBatchFactory.optimize(currentNode));

currentNode = new Node();

xCount = 0;

yCount = 0;

}



Spatial child = processCell(cells, row, col);

if (child != null) {

currentNode.attachChild(child);

}

}

}



//Attach the final node

mapNode.attachChild((Node) GeometryBatchFactory.optimize(currentNode));

[/java]



Note:

processCell() returns a spatial generated based on the value of that cell in the cells array.

Wall boxes all have the same material, and floor quads all have another same material

mapNode is a node that is later attached to the rootNode.

If I just attach currentNode without optimising all works.



Is there just something obvious I’m missing here, or is this a bug?



One other thing I notice as well is that the walls flicker when moving around as if they are overlapping each other, the floors do not.

meant to say thanks in advance for any help. Also it’s weird that you can’t preview or edit posts.

Gaz

I don’t think you need to re attach the nodes after optimizing, the optimize method re-attaches the newly created geomtetry by istelf, so you may be doubling up on your geom, which would explain your flickering.



so rather than calling :



[java]mapNode.attachChild((Node) GeometryBatchFactory.optimize(currentNode));[/java]



try just using



[java]GeometryBatchFactory.optimize(currentNode);[/java]



… also you should be able to edit your own posts if you ‘Join Group’ at the top of the page.



-James

I think you misunderstood the code, I attach the currentNode to the mapNode for the first and only time at the same time as optimising it.



[java]mapNode.attachChild((Node) GeometryBatchFactory.optimize(currentNode));[/java]



I then create a new node to work from the next time round the loop



[java]currentNode = new Node();[/java]



Then at the end of the loop I add the last “currentNode” to the map node.



Is this not right?

I’m not going to lie, I only glanced over your code looking for quick wins, sorry :stuck_out_tongue:



I see what your doing now, it looks kinda of awkward , are you sure it’s attaching 10x10 blocks ? … since your x count only increases at the end of each row, I think you may be adding at at least 9 full rows before optimizing.



I would recommend you try pulling out all the optimize code and putting it after you have generated all your geometry, I think it could be complicating the issue where it is, and how its done. This should also result in better code separation.

oh sorry, and to answer your question, what you’re doing does look correct, but I think your code is just not working how you expect.

Oh yeah you have a good point there, rookie mistake. Don’t think this is the issue though as if I optimise it all as one node I get this at the bottom of the map:







[java]

for (int row = 0; row < cells.length; row++){

for (int col = 0; col < cells[row].length; col++){

Spatial child = processCell(cells, row, col);

if (child != null) {

mapNode.attachChild(child);

}

}

}



return (Node) GeometryBatchFactory.optimize(mapNode);

[/java]



Notice how the wall is still there just has no material. The right edge is fine just to try and narrow it down a bit.



Edit: Oh and the flicker is still there, but that may be another problem entirely.

And without walls to a) see if that solved it, and b) to make the issue clearer



can you please make double sure it’s all working fine without any optimization, then adding following :



[java]GeometryBatchFactory.optimize(mapNode);[/java]



… and confirm that causes it to break (make sure you do the optimizing that way, not your original way, simply so I can eliminate possible causes). It just feels like there is duplicate un-optimized geometry floating around there somewhere.



Are you using the Unshaded material with no lights ?

Works fine, and has no flickering without optimisation.



Still breaks with optimisation, commenting out GeometryBatchFactory.optimize(mapNode); fixes the problem.



[java]

for (int row = 0; row < cells.length; row++){

for (int col = 0; col < cells[row].length; col++){

Spatial child = processCell(cells, row, col);



if (child != null) {

mapNode.attachChild(child);

}

}

}



//Commenting out the following line fixes all problems

GeometryBatchFactory.optimize(mapNode);

return mapNode;

[/java]



Thanks for your help by the way, really appreciate this.

Oh and no I’m using “Common/MatDefs/Light/Lighting.j3md” for both, and a directional light facing straight down.

What does processCell() do?

cells is an array of chars that represents the generated map. processCell() takes a char and, depending on the character, creates either a box (wall) or a quad (floor) for that cell on the map. It then positions it accordingly with setLocalTranslation() and returns it so it can be added to the mapNode.

The floor for example is:



[java]

Material mat = floorMaterial;



Quad q = new Quad(cellWidth, cellLength);

q.scaleTextureCoordinates(new Vector2f(4,4));

Geometry geom = new Geometry(“Cell” + curRow + “-” + curCol, q);

geom.getLocalRotation().fromAngleAxis(-90*FastMath.DEG_TO_RAD, Vector3f.UNIT_X);

geom.setLocalTranslation(

(-curCol * cellWidth), //X Centre

0, //Y Centre

(-curRow * cellLength) + (CELL_LENGTH / 2) //Z Centre

);



geom.setMaterial(mat);

[/java]



Where floorMaterial is a static variable declared at the top of the class as:

[java]

floorMaterial = new Material(assetManager, “Common/MatDefs/Light/Lighting.j3md”);

Texture floorDiffuse = assetManager.loadTexture(“Textures/Map/floor.jpg”);

floorDiffuse.setWrap(Texture.WrapMode.Repeat);

floorMaterial.setTexture(“DiffuseMap”, floorDiffuse);

Texture floorNormal = assetManager.loadTexture(“Textures/Map/floor_normal.png”);

floorNormal.setWrap(Texture.WrapMode.Repeat);

floorMaterial.setTexture(“NormalMap”, floorNormal);



//floorMaterial.setFloat(“Shininess”, 2f);

floorMaterial.setColor(“Ambient”, ColorRGBA.White);

floorMaterial.setColor(“Diffuse”, ColorRGBA.White);

floorMaterial.setColor(“Specular”, ColorRGBA.White);

floorMaterial.setFloat(“Shininess”, 0.2f);

[/java]



Alot of those settings are just the result of me fiddling, but I know it worked when I tried it before so I am 90% certain it’s not a problem with that code.