forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			158 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			158 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
|  | package iron.data; | ||
|  | 
 | ||
|  | import haxe.ds.Vector; | ||
|  | import kha.arrays.Int16Array; | ||
|  | import kha.arrays.Uint32Array; | ||
|  | import iron.data.SceneFormat; | ||
|  | import iron.object.Object; | ||
|  | import iron.object.CameraObject; | ||
|  | import iron.object.MeshObject; | ||
|  | import iron.object.Uniforms; | ||
|  | import iron.Scene; | ||
|  | 
 | ||
|  | #if lnx_terrain | ||
|  | 
 | ||
|  | class TerrainStream { | ||
|  | 
 | ||
|  | 	public var sectors: Array<MeshObject> = []; | ||
|  | 	public var heightTextures: Array<kha.Image> = []; | ||
|  | 	public var ready = false; | ||
|  | 	public var onReady: Void->Void = null; | ||
|  | 
 | ||
|  | 	var raw: TTerrainData; | ||
|  | 	var planes: Array<MeshData> = []; | ||
|  | 	var materials: Vector<MaterialData>; | ||
|  | 
 | ||
|  | 	public function new(raw: TTerrainData) { | ||
|  | 		this.raw = raw; | ||
|  | 
 | ||
|  | 		Data.getMaterial(Scene.active.raw.name, raw.material_ref, function(mat: MaterialData) { | ||
|  | 			materials = Vector.fromData([mat]); | ||
|  | 
 | ||
|  | 			var imagesLoaded = 0; | ||
|  | 			var numSectors = raw.sectors_x * raw.sectors_y; | ||
|  | 			for (i in 0...numSectors) { | ||
|  | 				var j = i + 1; | ||
|  | 				var ext = j < 10 ? "0" + j : "" + j; | ||
|  | 				Data.getImage("heightmap_" + ext + ".png", function(image: kha.Image) { | ||
|  | 					heightTextures[i] = image; | ||
|  | 					imagesLoaded++; | ||
|  | 					if (imagesLoaded == numSectors) { | ||
|  | 						loaded(); | ||
|  | 					} | ||
|  | 				}, true); // Readable | ||
|  | 			} | ||
|  | 		}); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public function notifyOnReady(f: Void->Void) { | ||
|  | 		onReady = f; | ||
|  | 		if (ready) onReady(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function loaded() { | ||
|  | 		for (i in 0...4) { | ||
|  | 			makePlane(i, raw.sector_size, raw.sector_size, heightTextures[0].width, heightTextures[0].height); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		for (i in 0...raw.sectors_x * raw.sectors_y) { | ||
|  | 			makeSector(i); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		iron.App.notifyOnInit(function() { | ||
|  | 			Uniforms.externalTextureLinks.push(textureLink); | ||
|  | 		}); | ||
|  | 
 | ||
|  | 		ready = true; | ||
|  | 		if (onReady != null) onReady(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function makePlane(index: Int, sizeX: Float, sizeY: Float, vertsX: Int, vertsY: Int) { | ||
|  | 		// Pack positions to (-1, 1) range | ||
|  | 		var halfX = sizeX / 2; | ||
|  | 		var halfY = sizeY / 2; | ||
|  | 		var halfZ = raw.height_scale / 2; | ||
|  | 		var scalePos = Math.max(halfX, Math.max(halfY, halfZ)); | ||
|  | 		var inv = 1 / scalePos; | ||
|  | 
 | ||
|  | 		var posa = new Int16Array(vertsX * vertsY * 4); | ||
|  | 		var nora = new Int16Array(vertsX * vertsY * 2); | ||
|  | 		var texa = new Int16Array(vertsX * vertsY * 2); | ||
|  | 		var inda = new Uint32Array((vertsX - 1) * (vertsY - 1) * 6); | ||
|  | 		var stepX = sizeX / (vertsX - 1); | ||
|  | 		var stepY = sizeY / (vertsY - 1); | ||
|  | 		for (i in 0...vertsX * vertsY) { | ||
|  | 			var x = (i % vertsX) * stepX - halfX; | ||
|  | 			var y = Std.int(i / vertsX) * stepY - halfY; | ||
|  | 			posa[i * 4    ] = Std.int(x * 32767 * inv); | ||
|  | 			posa[i * 4 + 1] = Std.int(y * 32767 * inv); | ||
|  | 			posa[i * 4 + 2] = Std.int(-halfZ * 32767 * inv); | ||
|  | 			nora[i * 2    ] = 0; | ||
|  | 			nora[i * 2 + 1] = 0; | ||
|  | 			posa[i * 4 + 3] = 32767; | ||
|  | 			x = (i % vertsX) / vertsX; | ||
|  | 			y = (Std.int(i / vertsX)) / vertsY; | ||
|  | 			texa[i * 2    ] = Std.int(x * 32767); | ||
|  | 			texa[i * 2 + 1] = Std.int(y * 32767); | ||
|  | 		} | ||
|  | 		for (i in 0...(vertsX - 1) * (vertsY - 1)) { | ||
|  | 			var x = i % (vertsX - 1); | ||
|  | 			var y = Std.int(i / (vertsY - 1)); | ||
|  | 			inda[i * 6    ] = y * vertsX + x; | ||
|  | 			inda[i * 6 + 1] = y * vertsX + x + 1; | ||
|  | 			inda[i * 6 + 2] = (y + 1) * vertsX + x; | ||
|  | 			inda[i * 6 + 3] = y * vertsX + x + 1; | ||
|  | 			inda[i * 6 + 4] = (y + 1) * vertsX + x + 1; | ||
|  | 			inda[i * 6 + 5] = (y + 1) * vertsX + x; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Positions, normals and indices | ||
|  | 		var pos: TVertexArray = { attrib: "pos", values: posa, data: "short4norm" }; | ||
|  | 		var nor: TVertexArray = { attrib: "nor", values: nora, data: "short2norm" }; | ||
|  | 		var tex: TVertexArray = { attrib: "tex", values: texa, data: "short2norm" }; | ||
|  | 		var ind: TIndexArray = { material: 0, values: inda }; | ||
|  | 
 | ||
|  | 		var rawmeshData: TMeshData = { | ||
|  | 			name: "Terrain", | ||
|  | 			vertex_arrays: [pos, nor, tex], | ||
|  | 			index_arrays: [ind], | ||
|  | 			scale_pos: scalePos, | ||
|  | 			scale_tex: 1.0 | ||
|  | 		}; | ||
|  | 
 | ||
|  | 		new MeshData(rawmeshData, function(data: MeshData) { | ||
|  | 			planes[index] = data; | ||
|  | 			data.geom.calculateAABB(); | ||
|  | 		}); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function makeSector(index: Int) { | ||
|  | 		var object = Scene.active.addMeshObject(planes[0], materials); | ||
|  | 		sectors[index] = object; | ||
|  | 		object.uid = index; | ||
|  | 		object.name = "Terrain." + index; | ||
|  | 		object.transform.loc.x = (index % raw.sectors_x) * 2; | ||
|  | 		object.transform.loc.y = Std.int(index / raw.sectors_x) * 2; | ||
|  | 		object.transform.loc.z = 0; | ||
|  | 		object.transform.buildMatrix(); | ||
|  | 		object.transform.dim.x = raw.sector_size; | ||
|  | 		object.transform.dim.y = raw.sector_size; | ||
|  | 		object.transform.dim.z = raw.height_scale; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public function remove() {} | ||
|  | 
 | ||
|  | 	public function update(camera: CameraObject) { | ||
|  | 		if (!ready) return; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	function textureLink(object: Object, mat: MaterialData, link: String): kha.Image { | ||
|  | 		if (link == "_TerrainHeight") { | ||
|  | 			return heightTextures[object.uid]; | ||
|  | 		} | ||
|  | 		return null; | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | #end |