125 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
package iron.data;
 | 
						|
 | 
						|
#if lnx_stream
 | 
						|
 | 
						|
import haxe.ds.Vector;
 | 
						|
import iron.data.SceneFormat;
 | 
						|
import iron.data.MaterialData;
 | 
						|
import iron.object.Object;
 | 
						|
import iron.object.MeshObject;
 | 
						|
import iron.object.CameraObject;
 | 
						|
import iron.math.Vec4;
 | 
						|
 | 
						|
class SceneStream {
 | 
						|
 | 
						|
	var checkMax = 64; // Objects checked per frame
 | 
						|
	var checkPos = 0;
 | 
						|
	var loadMax = 8; // Max objects loaded at once
 | 
						|
	var loading = 0; // Objects being loaded
 | 
						|
	var loadDistance = -1;
 | 
						|
	var unloadDistance = -1;
 | 
						|
	var sectors: Array<StreamSector>; // 100x100 groups
 | 
						|
 | 
						|
	public function sceneTotal(): Int {
 | 
						|
		return sectors[0].handles.length;
 | 
						|
	}
 | 
						|
 | 
						|
	public function new() {
 | 
						|
		sectors = [new StreamSector()];
 | 
						|
	}
 | 
						|
 | 
						|
	public function remove() {}
 | 
						|
 | 
						|
	public function add(object_file: String, data_ref: String, sceneName: String, armature: Armature, materials: Vector<MaterialData>, parent: Object, parentObject:TObj, obj: TObj) {
 | 
						|
		sectors[0].handles.push({ object_file: object_file, data_ref: data_ref, sceneName: sceneName, armature: armature, materials: materials, parent: parent, parentObject: parentObject, obj: obj, object: null, loading: false });
 | 
						|
	}
 | 
						|
 | 
						|
	function setup(camera: CameraObject) {
 | 
						|
		loadDistance = Std.int(camera.data.raw.far_plane * 1.1);
 | 
						|
		unloadDistance = Std.int(camera.data.raw.far_plane * 1.5);
 | 
						|
	}
 | 
						|
 | 
						|
	public function update(camera: CameraObject) {
 | 
						|
		if (loadDistance == -1) setup(camera);
 | 
						|
 | 
						|
		if (loading >= loadMax) return; // Busy loading..
 | 
						|
 | 
						|
		var sec = sectors[0];
 | 
						|
		var to = Std.int(Math.min(checkMax, sec.handles.length));
 | 
						|
		for (i in 0...to) {
 | 
						|
 | 
						|
			var h = sec.handles[checkPos];
 | 
						|
			checkPos++;
 | 
						|
			if (checkPos >= sec.handles.length) checkPos = 0;
 | 
						|
 | 
						|
			// Check radius in sector
 | 
						|
			var camX = camera.transform.worldx();
 | 
						|
			var camY = camera.transform.worldy();
 | 
						|
			var camZ = camera.transform.worldz();
 | 
						|
			var hx = h.obj.transform.values[3];
 | 
						|
			var hy = h.obj.transform.values[7];
 | 
						|
			var hz = h.obj.transform.values[11];
 | 
						|
			var cameraDistance = Vec4.distancef(camX, camY, camZ, hx, hy, hz);
 | 
						|
			var dim = h.obj.dimensions;
 | 
						|
			if (dim != null) {
 | 
						|
				var r = dim[0];
 | 
						|
				if (dim[1] > r) r = dim[1];
 | 
						|
				if (dim[2] > r) r = dim[2];
 | 
						|
				cameraDistance -= r;
 | 
						|
				// TODO: handle scale & rot
 | 
						|
			}
 | 
						|
 | 
						|
			if (cameraDistance < loadDistance && h.object == null && !h.loading) { // Load mesh
 | 
						|
				// Wait for the parent object to be added to scene
 | 
						|
				if (h.parent == null) {
 | 
						|
					if (Scene.active.getChild(h.parentObject.name) == null) return;
 | 
						|
					h.parent = Scene.active.getChild(h.parentObject.name);
 | 
						|
				}
 | 
						|
 | 
						|
				// Start loading
 | 
						|
				h.loading = true;
 | 
						|
				loading++;
 | 
						|
				iron.Scene.active.returnMeshObject(h.object_file, h.data_ref, h.sceneName, h.armature, h.materials, h.parent, h.parentObject, h.obj, function(object: Object) {
 | 
						|
					h.object = cast(object, MeshObject);
 | 
						|
					h.loading = false;
 | 
						|
					loading--;
 | 
						|
				});
 | 
						|
				if (loading >= loadMax) return;
 | 
						|
			}
 | 
						|
			else if (cameraDistance > unloadDistance && h.object != null) { // Unload mesh
 | 
						|
				// Remove objects
 | 
						|
				h.object.remove();
 | 
						|
				if (h.object.data.refcount <= 0) {
 | 
						|
					iron.data.Data.deleteMesh(h.object_file + h.data_ref);
 | 
						|
				}
 | 
						|
				h.object = null;
 | 
						|
 | 
						|
				// Clear parents
 | 
						|
				if (h.parent.name != Scene.active.raw.name) {
 | 
						|
					h.parent = null;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
typedef TMeshHandle = {
 | 
						|
	var object_file: String;
 | 
						|
	var data_ref: String;
 | 
						|
	var sceneName: String;
 | 
						|
	var armature: Armature;
 | 
						|
	var materials: Vector<MaterialData>;
 | 
						|
	var parent: Object;
 | 
						|
	var parentObject: TObj;
 | 
						|
	var obj: TObj;
 | 
						|
	var object: MeshObject;
 | 
						|
	var loading: Bool;
 | 
						|
}
 | 
						|
 | 
						|
class StreamSector {
 | 
						|
	public function new() {}
 | 
						|
	public var handles: Array<TMeshHandle> = []; // Mesh objects
 | 
						|
}
 | 
						|
 | 
						|
#end
 |