forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			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 |