/*
* Copyright 2012 Benjamin Glatzel <benjamin.glatzel@me.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.terasology.rendering.world;
import java.util.Set;
import org.spout.api.geo.World;
import org.spout.api.geo.cuboid.Chunk;
import org.terasology.game.CoreRegistry;
import org.terasology.game.TerasologyEngine;
import org.terasology.logic.manager.Config;
import org.terasology.logic.world.WorldProvider;
import org.terasology.logic.world.WorldView;
import org.terasology.rendering.primitives.ChunkMesh;
import org.terasology.rendering.primitives.ChunkTessellator;
import org.terasology.teraspout.TeraChunk;
import com.google.common.collect.Sets;
/**
* Provides the mechanism for updating and generating chunks.
*
* @author Benjamin Glatzel <benjamin.glatzel@me.com>
*/
public final class ChunkUpdateManager {
public enum UPDATE_TYPE {
DEFAULT, PLAYER_TRIGGERED
}
/* CONST */
private static final int MAX_THREADS = Config.getInstance().getMaxThreads();
/* CHUNK UPDATES */
private static final Set<TeraChunk> currentlyProcessedChunks = Sets.newHashSet();
private final ChunkTessellator tessellator;
private final World worldProvider;
public ChunkUpdateManager(ChunkTessellator tessellator, World worldProvider) {
this.tessellator = tessellator;
this.worldProvider = worldProvider;
}
/**
* Updates the given chunk using a new thread from the thread pool. If the maximum amount of chunk updates
* is reached, the chunk update is ignored. Chunk updates can be forced though.
*
* @param chunk The chunk to update
* @param type The chunk update type
* @return True if a chunk update was executed
*/
// TODO: Review this system
public boolean queueChunkUpdate(TeraChunk chunk, final UPDATE_TYPE type) {
if (!currentlyProcessedChunks.contains(chunk) && (currentlyProcessedChunks.size() < MAX_THREADS || type != UPDATE_TYPE.DEFAULT)) {
executeChunkUpdate(chunk);
return true;
}
return false;
}
private void executeChunkUpdate(final TeraChunk c) {
currentlyProcessedChunks.add(c);
// Create a new thread and start processing
Runnable r = new Runnable() {
@Override
public void run() {
ChunkMesh[] newMeshes = new ChunkMesh[WorldRenderer.VERTICAL_SEGMENTS];
// WorldView worldView = worldProvider.getWorldViewAround(c.getPos());
WorldView worldView = null; // TODO use chunkmodel somehow
if (worldView != null) {
c.setDirty(false);
for (int seg = 0; seg < WorldRenderer.VERTICAL_SEGMENTS; seg++) {
newMeshes[seg] = tessellator.generateMesh(worldView, c.getPos(), Chunk.BLOCKS.SIZE / WorldRenderer.VERTICAL_SEGMENTS, seg * (Chunk.BLOCKS.SIZE / WorldRenderer.VERTICAL_SEGMENTS));
}
c.setPendingMesh(newMeshes);
}
currentlyProcessedChunks.remove(c);
}
};
CoreRegistry.get(TerasologyEngine.class).submitTask("Chunk Update", r);
}
}