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
 |