Преглед на файлове

persist elements, allow cleanup

ncannasse преди 9 години
родител
ревизия
fde1721ead
променени са 1 файла, в които са добавени 64 реда и са изтрити 18 реда
  1. 64 18
      h3d/scene/World.hx

+ 64 - 18
h3d/scene/World.hx

@@ -1,5 +1,22 @@
 package h3d.scene;
 
+class WorldElement {
+	public var model : WorldModel;
+	public var x : Float;
+	public var y : Float;
+	public var z : Float;
+	public var scale : Float;
+	public var rotation : Float;
+	public function new( model, x, y, z, scale = 1., rotation = 0. ) {
+		this.model = model;
+		this.x = x;
+		this.y = y;
+		this.z = z;
+		this.scale = scale;
+		this.rotation = rotation;
+	}
+}
+
 class WorldChunk {
 
 	public var cx : Int;
@@ -12,10 +29,12 @@ class WorldChunk {
 	public var bounds : h3d.col.Bounds;
 	public var initialized = false;
 	public var lastFrame : Int;
+	public var elements : Array<WorldElement>;
 
 	public function new(cx, cy) {
 		this.cx = cx;
 		this.cy = cy;
+		elements = [];
 		root = new h3d.scene.Object();
 		buffers = new Map();
 		bounds = new h3d.col.Bounds();
@@ -92,7 +111,7 @@ class World extends Object {
 	var textures : Map<String, WorldMaterial>;
 	public var enableSpecular = false;
 
-	public function new( chunkSize : Int, worldSize : Int, ?parent ) {
+	public function new( chunkSize : Int, worldSize : Int, ?parent, ?autoCollect = true ) {
 		super(parent);
 		chunks = [];
 		bigTextures = [];
@@ -104,6 +123,17 @@ class World extends Object {
 		this.chunkSize = 1 << chunkBits;
 		this.worldSize = worldSize;
 		this.worldStride = Math.ceil(worldSize / chunkSize);
+		if( autoCollect )
+			h3d.Engine.getCurrent().mem.garbage = garbage;
+	}
+
+	public function garbage() {
+		var last : WorldChunk = null;
+		for( c in allChunks )
+			if( c.initialized && (last == null || c.lastFrame < last.lastFrame) )
+				last = c;
+		if( last != null )
+			cleanChunk(last);
 	}
 
 	function buildFormat() {
@@ -294,7 +324,7 @@ class World extends Object {
 			}
 	}
 
-	function initChunk( c : WorldChunk ) {
+	function initChunkSoil( c : WorldChunk ) {
 		var cube = new h3d.prim.Cube(chunkSize, chunkSize, 0);
 		cube.addNormals();
 		cube.addUVs();
@@ -305,6 +335,33 @@ class World extends Object {
 		soil.material.shadows = true;
 	}
 
+	function initChunkElements( c : WorldChunk ) {
+		for( e in c.elements ) {
+			var model = e.model;
+			for( g in model.geometries ) {
+				var b = c.buffers.get(g.m.bits);
+				if( b == null ) {
+					b = new h3d.scene.Mesh(new h3d.prim.BigPrimitive(getStride(model), true), c.root);
+					b.name = g.m.name;
+					c.buffers.set(g.m.bits, b);
+					initMaterial(b, g.m);
+				}
+				var p = Std.instance(b.primitive, h3d.prim.BigPrimitive);
+				p.addSub(model.buf, model.idx, g.startVertex, Std.int(g.startIndex / 3), g.vertexCount, Std.int(g.indexCount / 3), e.x, e.y, e.z, e.rotation, e.scale, model.stride);
+			}
+		}
+	}
+
+	function cleanChunk( c : WorldChunk ) {
+		if( !c.initialized ) return;
+		c.initialized = false;
+		for( b in c.buffers ) {
+			b.dispose();
+			b.remove();
+		}
+		c.buffers = new Map();
+	}
+
 	function updateChunkBounds(c : WorldChunk, model : WorldModel, rotation : Float, scale : Float) {
 		var cosR = Math.cos(rotation);
 		var sinR = Math.sin(rotation);
@@ -362,19 +419,7 @@ class World extends Object {
 
 	public function add( model : WorldModel, x : Float, y : Float, z : Float, scale = 1., rotation = 0. ) {
 		var c = getChunk(x, y, true);
-
-		for( g in model.geometries ) {
-			var b = c.buffers.get(g.m.bits);
-			if( b == null ) {
-				b = new h3d.scene.Mesh(new h3d.prim.BigPrimitive(getStride(model), true), c.root);
-				b.name = g.m.name;
-				c.buffers.set(g.m.bits, b);
-				initMaterial(b, g.m);
-			}
-			var p = Std.instance(b.primitive, h3d.prim.BigPrimitive);
-			p.addSub(model.buf, model.idx, g.startVertex, Std.int(g.startIndex / 3), g.vertexCount, Std.int(g.indexCount / 3), x, y, z, rotation, scale, model.stride);
-		}
-
+		c.elements.push(new WorldElement(model, x, y, z, scale, rotation));
 		updateChunkBounds(c, model, rotation, scale);
 	}
 
@@ -384,11 +429,12 @@ class World extends Object {
 		for( c in allChunks ) {
 			c.root.visible = c.bounds.inFrustum(ctx.camera.m);
 			if( c.root.visible ) {
-				if( !c.initialized) {
+				c.lastFrame = ctx.frame;
+				if( !c.initialized ) {
 					c.initialized = true;
-					initChunk(c);
+					initChunkSoil(c);
+					initChunkElements(c);
 				}
-				c.lastFrame = ctx.frame;
 			}
 		}
 	}