Edit as of solution:
The following code in this post is now outdated to what my problem is. For the solution, scroll to the bottom. I have several snippets there of my solution.
Thanks nehon and david_bernard_31 for the replies and solutions.
Alright, so basically my goal is to replace a geometry/spatial in my rootNode.
I’m doing a sort of chunk based system, where the chunk builds an optimized spatial node of all the geometry passed in by the blocks that region contains.
I have looked through the mutli-threading area as best as I could (I used Google’s cache of the wiki as it seems to be down).
I need it multi-threaded to build the model because I don’t want the game to freeze up when the user would be playing it.
This is what I’ve tried:
In my application:
@Override public void simpleUpdate(float tpf) { for (Plot p : plots) { Spatial rebuiltSpatial = null; try { if (p.isDirty() && future == null) { future = executor.submit(p.getCallable()); } else if (future != null) { if (future.isDone()) { rebuiltSpatial = (Spatial)future.get(); future = null; } else if (future.isCancelled()) { future = null; } } } catch (Exception e) { e.printStackTrace(); } if (rebuiltSpatial != null) { if (p.getCurrentGeometry() != null) { rootNode.detachChild(p.getCurrentGeometry()); } p.setCurrentGeoemtry(rebuiltSpatial); rootNode.attachChild(p.getCurrentGeometry()); } } }
In my Plot class:
private Callable<Spatial> rebuildGeometryCallable = new Callable<Spatial>() { public Spatial call() throws Exception { Spatial rebuilt = Main.getInstance().enqueue(new Callable<Spatial>() { public Spatial call() throws Exception { return rebuildPlotGeometry(null); } }).get(); return rebuilt; } };
private synchronized Spatial rebuildPlotGeometry(Material globalMaterial) { DecimalFormat df = new DecimalFormat("#.##"); Node n = new Node(String.format("Plot_{0}_{1}", new Object[]{df.format((double) location.x), df.format((double) location.y)})); Spatial returnedSpatial = null; for (int y = 0; y < PLOT_YSIZE; y++) { for (int x = 0; x < PLOT_XSIZE; x++) { for (int z = 0; z < PLOT_ZSIZE; z++) { IBlock block = getBlockAt(x, y, z); if (block != null) { EnumMap<Side, IBlock> adjacentBlocks = new EnumMap<Side, IBlock>(Side.class); for (Side side : Side.values()) { IBlock neighborBlock = getBlockOrNullAt(x + side.getOffsetX(), y + side.getOffsetY(), z + side.getOffsetZ()); adjacentBlocks.put(side, neighborBlock); } if (block.getBlockGeometry(adjacentBlocks) != null) { Spatial g = block.getBlockGeometry(adjacentBlocks).clone(true); Vector3f offset = new Vector3f(x, y, z).add(0.5f, 0f, 0.5f); g.setLocalTranslation(offset); g.updateGeometricState(); n.attachChild(g); } } } } } returnedSpatial = GeometryBatchFactory.optimize(n); returnedSpatial.setLocalTranslation(this.location.x, 0f, this.location.y); this.isDirty = false;
if (globalMaterial != null) { returnedSpatial.setMaterial(globalMaterial); } return returnedSpatial; }
Basically, what I want to happen is that when I modify the plot’s blocks, it will rebuild the geometry/spatial and replace the already existing one that is attached to the rootNode.
I’m 100% sure that I’m either approaching this wrong, or I’m overthinking the process.
Any guidance in the right direction would be much helped.
I don’t expect anyone to spoon feed me code, as that doesn’t help me learn, but if someone could give me useful snippets with explanations or something, then I could adapt my current code to it.