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
							 |