package detectiongame.dungen;
import engine.Entity;
import engine.model.Material;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import static engine.GfxEngine.appSpeed;
import static engine.GfxEngine.PointInFrustum;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import static org.lwjgl.opengl.GL11.*;
import static engine.GfxEngine.loadMaterial;
import static engine.GfxEngine.loadModel;
import engine.Vec3f;
import engine.model.ObjModel;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import org.lwjgl.BufferUtils;
/**
*
* @author
* knasaari
*/
public class World {
private HashMap<Material, Chunk> chunks;
private HashMap<Material, Integer> processedEntities;
private Vector<ObjModel> modelList;
private HashMap<Material, Vector<Entity>> materialgroups;
private HashMap<Material, Vector<Entity>> materialgroupsFresh;
private Vec3f center;
private int buildStatus;
private String worldName;
/** The World isn't being generated and hasn't been bound to GPU. */
public static final int EMPTY = 0;
/** A new version of the World is being generated. */
public static final int IN_PROGRESS = 1;
/** The World has been generated. It is made of the Entities it had when rebuild() was last called. */
public static final int READY = 2;
public World(String name){
worldName = name;
center = new Vec3f();
buildStatus = 0;
chunks = new HashMap<>();
processedEntities = new HashMap<>();
materialgroups = new HashMap<>();
materialgroupsFresh = new HashMap<>();
modelList = new Vector<>();
}
public void clearEntityGroups(){
this.materialgroupsFresh.clear();
this.materialgroups.clear();
}
public void free(){
for(Chunk chunk : this.chunks.values()){
chunk.reset();
}
this.chunks.clear();
for(Material mat : this.materialgroupsFresh.keySet()){
this.chunks.put(mat, new Chunk());
}
this.processedEntities.clear();
this.materialgroups.clear();
this.center.set(0f);
this.buildStatus = 0;
}
public int getBuildStatus(){
return this.buildStatus;
}
public void addEntity(Entity ent){
if(ent == null){
return;
}
if(this.materialgroupsFresh.containsKey(ent.material) == false){
this.materialgroupsFresh.put(ent.material, new Vector<Entity>());
if(this.chunks.containsKey(ent.material) == false) {
this.chunks.put(ent.material, new Chunk());
}
this.processedEntities.put(ent.material, 0);
}
if(this.modelList.contains(ent.model) == false){
this.modelList.add(ent.model);
}
if(this.materialgroupsFresh.get(ent.material).contains(ent) == false) {
this.materialgroupsFresh.get(ent.material).add(ent);
}
}
public void build(){
this.buildStatus = IN_PROGRESS;
this.materialgroups.clear();
this.materialgroups = (HashMap<Material, Vector<Entity>>)this.materialgroupsFresh.clone();
this.processGroupsToWorld(true);
}
public void rebuild(){
this.buildStatus = IN_PROGRESS;
this.materialgroups.clear();
this.materialgroups = (HashMap<Material, Vector<Entity>>)this.materialgroupsFresh.clone();
for(Chunk chunk : this.chunks.values()){
chunk.clearFloatBuffer();
}
//System.gc();
}
public void refresh(){
if(this.buildStatus == READY) {
return;
}
this.processGroupsToWorld(false);
}
private void processGroupsToWorld(boolean completeBuild){
int loops = 0, loopBeginning = 0;
/*
for(Material mat:this.materialgroups.keySet()){
Vector<Entity> group = this.materialgroups.get(mat);
for(int entcount = 0; entcount<group.size(); entcount++){
}
}*/
Set materialkeyset = this.materialgroups.keySet();
Iterator itr = materialkeyset.iterator();
while(itr.hasNext()){
Material mat = (Material)itr.next();
if(this.chunks.get(mat).getBuildStatus() == true){
this.processedEntities.put(mat, 0);
int chunkBufferSize = 0;
for(int entcount = 0; entcount<this.materialgroups.get(mat).size(); entcount++){
chunkBufferSize += this.materialgroups.get(mat).get(entcount).model.VBO.capacity();
}
this.chunks.get(mat).createFloatBuffer(chunkBufferSize);
System.out.println("Created "+this.worldName+" FloatBuffer "+chunkBufferSize);
}
loopBeginning = this.processedEntities.get(mat);
for(int entcount = loopBeginning; entcount<this.materialgroups.get(mat).size(); entcount++){
this.chunks.get(mat).addEntityToChunk(this.materialgroups.get(mat).get(entcount));
this.processedEntities.put(mat, this.processedEntities.get(mat)+1);
if(this.processedEntities.get(mat) >= this.materialgroups.get(mat).size()){
this.chunks.get(mat).swap();
break;
}
if(completeBuild == false){
loops++;
if(loops >= 10){
//System.out.println(mat.getMatFilePath()+": "+Math.round((float)this.processedEntities.get(mat)/(float)this.materialgroups.get(mat).size()*100f)+"%");
return;
}
}
}
// All the entities belonging to this Material have been processed.
}
// All the entities belonging to all Materials have been processed.
for(Chunk chunk : this.chunks.values()){
chunk.clearFloatBuffer();
}
this.buildStatus = READY;
this.center.set(0f);
for(Material mat : this.materialgroups.keySet()){
this.center.set(this.center.x+this.chunks.get(mat).getCenter().x,
this.center.y+this.chunks.get(mat).getCenter().y,
this.center.z+this.chunks.get(mat).getCenter().z);
}
this.center.set(
this.center.x/this.materialgroups.keySet().size(),
this.center.y/this.materialgroups.keySet().size(),
this.center.z/this.materialgroups.keySet().size()
);
System.out.println(this.worldName+": complete");
//System.gc();
}
public Vec3f getCenter(){
return this.center;
}
public void exist(){
for(Material mat:this.chunks.keySet()){
if(PointInFrustum(this.chunks.get(mat).getCenter(), this.chunks.get(mat).getSphereRadius()) == false) {
//System.out.println(this.worldName+": notinfrustrum");
continue;
}
glPushMatrix();
this.chunks.get(mat).draw(mat);
glPopMatrix();
this.chunks.get(mat).drawBoundingBox();
}
}
public String getAllMaterialPaths(){
String paths = new String();
for(Material mat:this.materialgroupsFresh.keySet()){
paths = paths+mat.getMatFilePath();
paths = paths+'\t';
}
return paths+'\n';
}
public String getAllModelPaths(){
String paths = new String();
for(ObjModel model:this.modelList){
paths = paths+model.getFilePath();
paths = paths+'\t';
}
return paths+'\n';
}
public void saveToFile() throws FileNotFoundException, IOException{
int matIndex = 0, bufferSize = 0;
DataOutputStream dos = new DataOutputStream(new FileOutputStream("save/"+this.worldName+".bin"));
for(Vector<Entity> group:this.materialgroupsFresh.values()){
bufferSize += group.size();
}
char[] modelPaths = this.getAllModelPaths().toCharArray();
char[] materialPaths = this.getAllMaterialPaths().toCharArray();
byte[] actual = new byte[(modelPaths.length+materialPaths.length)*2+bufferSize*4*4+bufferSize*2*4];
ByteBuffer buffer = ByteBuffer.wrap(actual);
buffer.position((modelPaths.length+materialPaths.length)*2);
for(Vector<Entity> group:this.materialgroupsFresh.values()){
for (int x = 0; x < group.size(); x++) {
Entity ent = group.get(x);
buffer.putFloat(ent.getPos().x);
buffer.putFloat(ent.getPos().y);
buffer.putFloat(ent.getPos().z);
buffer.putFloat(ent.getRot().y);
buffer.putInt(this.modelList.indexOf(ent.model));
buffer.putInt(matIndex);
}
matIndex++;
}
buffer.position(0);
buffer.asCharBuffer().put(modelPaths);
buffer.position(modelPaths.length*2);
buffer.asCharBuffer().put(materialPaths);
//dos.writeChars(this.getAllModelPaths(models)+'\n'+this.getAllMaterialPaths()+'\n');
dos.write(actual);
dos.close();
actual = null;
}
public void readFromFile() throws FileNotFoundException, IOException{
Vector<ObjModel> models = new Vector<>(); // = this.readObjectPathsFromFile("save/ModelPaths_7-7.bin", true);
Vector<Material> materials = new Vector<>(); // = this.readObjectPathsFromFile("save/MaterialPaths_7-7.bin", false);
DataInputStream dis = new DataInputStream(new FileInputStream("save/"+this.worldName+".bin"));
StringBuffer item;
char lineSep = '\t';
boolean eol = false;
char chr;
this.materialgroupsFresh.clear();
try {
for(int i=0;i<2;i++){
while (eol == false){
item = new StringBuffer(200);
while ((chr = dis.readChar()) != lineSep) {
if(chr == '\n'){
eol = true;
break;
}
item.append(chr);
}
if(item.length() > 1) {
if(i == 0){
models.add(loadModel(item.toString()));
}
else{
materials.add(loadMaterial(item.toString()));
}
}
}
eol = false;
}
byte[] bulk = new byte[dis.available()];
dis.read(bulk);
ByteBuffer entities = ByteBuffer.wrap(bulk);
for(int i=0;i<bulk.length;i=i+24){
Entity ent = new Entity();
ent.setPos(entities.getFloat(),entities.getFloat(),entities.getFloat());
ent.setRot(0f, entities.getFloat(), 0f);
ent.setModel((ObjModel)models.get(entities.getInt()));
ent.setMaterial((Material)materials.get(materials.size()-1-entities.getInt()));
this.addEntity(ent);
}
/*
while (true){
Entity ent = new Entity();
ent.setPos(dis.readFloat(), dis.readFloat(),dis.readFloat());
ent.setRot(0f, dis.readFloat(), 0f);
ent.setModel((ObjModel)models.get(dis.readInt()));
ent.setMaterial((Material)materials.get(materials.size()-1-dis.readInt()));
this.addEntity(ent);
}
*/
} catch (IOException ex) {
} finally {
dis.close();
}
}
}