Browse Source

singleton TopoLoader

Malf 2 years ago
parent
commit
7abd1dce46
10 changed files with 168 additions and 178 deletions
  1. 1 4
      ChunkSystem.gd
  2. 1 1
      Main.gd
  3. 4 5
      Messenger.gd
  4. 7 2
      TextureLoader.gd
  5. 27 39
      Tile.gd
  6. 120 108
      TopoLoader.gd
  7. 1 13
      chunk.gd
  8. 3 0
      common.gd
  9. 3 6
      downloader.gd
  10. 1 0
      project.godot

+ 1 - 4
ChunkSystem.gd

@@ -18,7 +18,7 @@ func _ready():
 # Called every frame. 'delta' is the elapsed time since the previous frame.
 func _process(delta):
 	var playerSpos = Player.getSpos()
-	var playerChunkPos = posToChunPos(playerSpos)
+	var playerChunkPos = Common.posToChunkPos(playerSpos)
 	var playerInterChunkPos = Vector2(playerSpos.x - playerChunkPos.x, playerSpos.y - playerChunkPos.y)
 	
 	add_chunk(playerChunkPos)
@@ -53,9 +53,6 @@ func _process(delta):
 	#	if dist < renderDistance:
 	#		add_chunk(playerChunkPos+i)
 
-func posToChunPos(pos):
-	return Vector2(int(pos.x), int(pos.y))
-
 func add_chunk(chunkPos = Vector2()):
 	var lat = int(chunkPos.x)
 	var lon = int(chunkPos.y)

+ 1 - 1
Main.gd

@@ -16,7 +16,7 @@ extends Spatial
 
 #var resolution = 512
 var radius = 1737.4*1000
-var startPos = Vector3(10, 10,radius + 500)
+var startPos = Vector3(0, 333,radius + 500)
 
 #var curlat = 0
 #var curlon = 0

+ 4 - 5
Messenger.gd

@@ -7,16 +7,15 @@ extends Node
 
 signal statusUpdate
 signal fileDownloaded
+signal fileReady
+signal textureReady
+signal chunkCached
+signal meshLoaded
 
 # Called when the node enters the scene tree for the first time.
 func _ready():
 	pass # Replace with function body.
 
-func _on_statusUpdate(update):
-	emit_signal("statusUpdate", update)
-	
-func _on_file_downloaded(download):
-	emit_signal("fileDownloaded", download)
 # Called every frame. 'delta' is the elapsed time since the previous frame.
 #func _process(delta):
 #	pass

+ 7 - 2
TextureLoader.gd

@@ -18,13 +18,18 @@ func open(latIN, lonIN):
 	var err = file.open(getTexName(), File.READ)
 	if err == 7:
 		Downloader.download(getTexName(), "color")
-		return false
+		var dl = Downloader.Download.new()
+		while not dl._file_name == getTexName():
+			dl = yield(Messenger, "fileDownloaded")
+		file.open(getTexName(), File.READ)
+		Messenger.emit_signal("textureReady", Vector2(latIN, lonIN))
+		return Vector2(latIN, lonIN)
 	elif err != OK:
 		print("error opening tex ", err)
 		return false
 	else:
 		file.close()
-		return true
+		return Vector2(latIN, lonIN)
 
 func loadTexture():
 	var texName = getTexName()

+ 27 - 39
Tile.gd

@@ -1,20 +1,22 @@
 extends MeshInstance
 
+signal meshLoaded
+
 var Point = preload("res://point.tscn")
-var TopoLoader = preload("res://TopoLoader.gd")
-var tl
+#var TopoLoader = preload("res://TopoLoader.gd")
+#var tl
 var TextureLoader = preload("res://TextureLoader.gd")
 var texl
 
 var groundShader = preload("res://shader/ground_shader.tres") as ShaderMaterial
 
-var latMin:float = 0
-var latMax:float = 1
-var lonMin:float = 0.0
-var lonMax:float = 1.0
-var resolution:int = 512
-var radius:float = 10
-var scaleFact:int = 1
+onready var latMin:float = .get_parent().latMin
+onready var latMax:float = .get_parent().latMax
+onready var lonMin:float = .get_parent().lonMin
+onready var lonMax:float = .get_parent().lonMax
+onready var resolution:int = .get_parent().resolution
+onready var radius:float = .get_parent().radius
+onready var scaleFact:int = .get_parent().scaleFact
 
 var origin:Vector3
 var center:Vector3
@@ -22,35 +24,16 @@ var center:Vector3
 var heightmap:Image
 var overlay_heightmap = false
 var mat:ShaderMaterial
-
-var initialized = false
-
-func initialize(latMinIN, latMaxIN, lonMinIN, lonMaxIN, resolutionIN, radiusIN:float, scaleIN):	
-	latMin = latMinIN
-	latMax = latMaxIN
-	lonMin = lonMinIN
-	lonMax = lonMaxIN
-	resolution = resolutionIN
-	radius = radiusIN
-	scaleFact = scaleIN
-	tl = TopoLoader.new()
-	add_child(tl)
-	var fileReady = tl.open(latMin, lonMin)
-	if fileReady and not fileReady is GDScriptFunctionState :
-		initialized = true
-		return true
-	else:
-		return false
-
+	
 func _ready():
-	pass
-	#genMesh called from chunk
-	#self.genMesh()
+	init()
 	
-func initTexture():
+func init():
 	texl = TextureLoader.new()
-	var exists = texl.open(latMin, lonMin)
-	return exists
+	var texPos = texl.open(latMin, lonMin)
+	while texPos != Vector2(latMin, lonMin):
+		texPos = yield(Messenger, "textureReady")
+	self.genMesh()
 	
 func _process(delta):
 	if Input.is_action_just_pressed("overlay"):
@@ -64,6 +47,11 @@ func genMesh():
 	#print("lonMin: " + str(lonMin))
 	#print("lonMax: " + str(lonMax))
 	#print("resolution: " + str(resolution))
+	var chunkPos = Common.posToChunkPos(Vector2(latMin,lonMin))
+	
+	var tc = TopoLoader.cacheChunk(chunkPos)
+	while tc.get_class() != "Reference" and tc.chunkPos != chunkPos and not tc.chunkCached:
+		tc = yield(Messenger, "chunkCached")
 	
 	var verts = convertToCartesian(genSphereCoords())
 	var arr = []
@@ -77,13 +65,15 @@ func genMesh():
 	mat = groundShader.duplicate()
 	#mat.albedo_color = Color(0.7,0.7,0.7,1)
 	mat.set_shader_param("texture_albedo_big", texl.loadTexture())
-	heightmap = tl.createHeightmap()
+	heightmap = TopoLoader.createHeightmap(chunkPos)
 	var heighttex = ImageTexture.new()
 	heighttex.create_from_image(heightmap, 0)
 	mat.set_shader_param("texture_heightmap", heighttex)
 	mesh.surface_set_material(0,mat)
 	.create_trimesh_collision()
 	
+	Messenger.emit_signal("meshLoaded")
+	
 	var drawBubbles = false
 	if drawBubbles:
 		var i = 0.0
@@ -156,7 +146,6 @@ func genIndex():
 	return indices
 		
 func genSphereCoords():
-	tl.cacheArea(latMin, latMax, lonMin, lonMax)
 	var verts = PoolVector3Array()
 	var size = (resolution+1) * (resolution+1)#(lonMax-lonMin)*resolution * (latMax-latMin)*resolution
 	verts.resize(size)
@@ -168,13 +157,12 @@ func genSphereCoords():
 		for x in range(0,resolution+1):
 			var lat = latMin+latStep*y
 			var lon = lonMin+lonStep*x
-			var height = tl.read(lat,lon)
+			var height = TopoLoader.read(lat,lon)
 			if not height and height != 0:
 				push_error("could not get height")
 				return
 			verts[v_idx] = Vector3(lat, lon, radius+height*scaleFact)
 			v_idx+=1
-	tl.close()
 	return verts
 
 

+ 120 - 108
TopoLoader.gd

@@ -1,111 +1,136 @@
 extends Node
 
 #var Downloader = preload("res://downloader.gd")
+var cache = {}
+
+
+var topoChunks = {}
 
-var filePrefix = "user://topo/"
-var formatString = "SLDEM2015_%s_%02d%s_%02d%s_%03d_%03d_FLOAT.IMG"
-#              example sldem2015_512_00n_30n_000_045_float.img
-var datafile = "user://topo/sldem2015_512_00n_30n_000_045_float.img"
-var samplesPerLine = 23040
-var lines = 15360
-var offset = 1737.4*1000
-var scaleFact = 1
-var resolution = 512
-var orientation: String = "N"
 var maxheight = 10.783
 var minheight = -8.719
 
-var latMin = 0
-var latMax = 30
-var lonMin = 0
-var lonMax = 45
-
-var cache = {}
-var file: File
-var fileReady = false
+signal fileReady
+signal chunkCached
 
-onready var heightmap = Image.new()
+class topoChunk:
+	var chunkPos: Vector2
+	var filePrefix = "user://topo/"
+	var formatString = "SLDEM2015_%s_%02d%s_%02d%s_%03d_%03d_FLOAT.IMG"
 
-signal fileReady
+	var samplesPerLine = 23040
+	var lines = 15360
+	var offset = 1737.4*1000
+	var scaleFact = 1
+	var resolution = 512
+	var orientation: String = "N"
+	var latMin = 0
+	var latMax = 30
+	var lonMin = 0
+	var lonMax = 45
+	var chunkCached = false
+	var fileReady = false
+	var file: File
 
-# Called when the node enters the scene tree for the first time.
-func open(latMinIN, lonMinIn):
-	latMin = (int(latMinIN)/30) * 30
-	if latMinIN >= 0:
-		orientation = "N"
-		latMax = latMin+30
-	else:
-		orientation = "S"
-		latMax = latMin-30
-	lonMin = (int(lonMinIn)/45) * 45
-	lonMax = lonMin+45
+	# Called when the node enters the scene tree for the first time.
+	func open(latMinIN, lonMinIN):
+		chunkPos = Vector2(latMinIN, lonMinIN)
+		latMin = (int(latMinIN)/30) * 30
+		if latMinIN >= 0:
+			orientation = "N"
+			latMax = latMin+30
+		else:
+			orientation = "S"
+			latMax = latMin-30
+		lonMin = (int(lonMinIN)/45) * 45
+		lonMax = lonMin+45
 		
-	file = File.new()
-	print("opening topo: "+getFilepath())
-	var err = file.open(getFilepath(), File.READ)
-	if err == 7:
-		Downloader.connect("file_downloaded", self, "_http_request_completed")
-		Downloader.download(getFilename(), "topo")
-		var dl = Downloader.Download.new()
-		while not dl._file_name == getFilepath():
-			dl = yield(Messenger, "fileDownloaded")
-		file.open(getFilepath(), File.READ)
-		fileReady = true
-		emit_signal("fileReady")
-		return true
-	elif err != 0:
-		push_error("error opening file err:%s" %err)
-		return false
-	else:
-		fileReady = true
-		return true
+		file = File.new()
+		print("opening topo: "+getFilepath())
+		var err = file.open(getFilepath(), File.READ)
+		if err == 7:
+			Downloader.download(getFilename(), "topo")
+			var dl = Downloader.Download.new()
+			while not dl._file_name == getFilepath():
+				dl = yield(Messenger, "fileDownloaded")
+			file.open(getFilepath(), File.READ)
+			_fileReady()
+			return true
+		elif err != 0:
+			push_error("error opening file err:%s" %err)
+			return false
+		else:
+			fileReady = true
+			return true
+			
+	func getFilename():
+	# example sldem2015_512_00n_30n_000_045_float.img
+	#     "%s/sldem2015_%s_%0*d%s_%0*d%s_%00*d_%00*d_float.img"
+		var properties
+		if orientation == "S":
+			properties = [resolution, abs(latMax), orientation, abs(latMin), orientation, lonMin, lonMax]
+		else:
+			properties = [resolution, latMin, orientation, latMax, orientation, lonMin, lonMax]
+		return formatString % properties
+	
+	func getFilepath():
+		return filePrefix+getFilename()
 
-func _http_request_completed(download):
-	fileReady = true
-	emit_signal("fileReady")
+	func _fileReady():
+		fileReady = true
+		Messenger.emit_signal("fileReady", self)
 
-func close():
-	file.close()
-	#queue_free()
+	func close():
+		file.close()
+		#queue_free()
 	
 func clear():
-	file.close()
 	cache = {}
 	
-func cacheArea(latMinIN, latMaxIN, lonMinIN, lonMaxIN):
-	if not _validate(latMinIN,lonMinIN) and not _validate(latMaxIN,lonMaxIN) :
-		print("out of scope!")
-		return
-	
-	if not file.is_open():
-		var err = file.open(getFilepath(), File.READ)
+func cacheChunk(chunkPos: Vector2):
+	var tc
+	if topoChunks.has(chunkPos.x) and topoChunks[chunkPos.x].has(chunkPos.y):
+		tc = cache[chunkPos.y][chunkPos.x]
+		return tc
+		
+	tc = topoChunk.new()
+	tc.open(chunkPos.x, chunkPos.y)
+	while tc.get_class() != topoChunk.get_class() and not tc.fileReady and tc.chunkPos != chunkPos:
+		tc = yield(Messenger, "fileReady")
 		
-	var lat = latMinIN
-	while lat <= latMaxIN:
+	var lat = chunkPos.x
+	while lat <= chunkPos.x + 1.0:
 		cache[lat]={}
-		var line = abs(lat)*resolution*samplesPerLine*4
+		var line = abs(lat)*tc.resolution*tc.samplesPerLine*4
 		# the origin of each .img file lies in it's upper left corner
 		# so we need to read the files from the end on the northern hemisphere
 		if lat >= 0:
-			var origin = latMax*resolution*samplesPerLine*4
-			file.seek((origin - line) + lonMinIN*resolution*4)
+			var origin = (chunkPos.x + 1.0)*tc.resolution*tc.samplesPerLine*4
+			tc.file.seek((origin - line) + chunkPos.y*tc.resolution*4)
 		else:
-			file.seek(line + lonMinIN*resolution*4)
-		var lon = lonMinIN
-		while lon <= lonMaxIN:
-			cache[lat][lon] = file.get_float()
-			lon += 1.0/float(resolution)
-		lat += 1.0/float(resolution)
-	return
+			tc.file.seek(line + chunkPos.y*tc.resolution*4)
+		var lon = chunkPos.y
+		while lon <= chunkPos.y + 1.0:
+			cache[lat][lon] = tc.file.get_float()
+			lon += 1.0/float(tc.resolution)
+		lat += 1.0/float(tc.resolution)
+	tc.chunkCached = true
 	
-func createHeightmap():
-	var minLat
-	var minLon
-	var maxLat
-	var maxLon
+	if not topoChunks.has(chunkPos.x):
+		topoChunks[chunkPos.x] = {}
+	topoChunks[chunkPos.x][chunkPos.y] = tc
+	tc.file.close()
+	Messenger.emit_signal("chunkCached", tc)
+	return tc
+	
+func createHeightmap(chunkPos:Vector2):
+	var minLat:float = chunkPos.x
+	var minLon:float = chunkPos.y
+	var maxLat:float = chunkPos.x + 1.0
+	var maxLon:float = chunkPos.y + 1.0
 	var idxX = 0
 	var idxY = 0
-	var value = 0.0
+	var value = 0.0	
+	var heightmap = Image.new()
 	heightmap.create(len(cache[cache.keys()[0]]), len(cache), false, Image.FORMAT_RF)
 	heightmap.lock()
 	for y in cache.keys():
@@ -127,41 +152,28 @@ func createHeightmap():
 	return heightmap
 
 func read(lat,lon):
-	if _validate(lat,lon):
+	if cache.has(lat) and cache[lat].has(lon):
 		return cache[lat][lon]
 	else:
 		print("out of scope!")
 
-func _validate(lat,lon):
-	var condition = true
-	if abs(lat) > latMax:
-		condition = false
-	if abs(lat) < latMin:
-		condition = false
-	if lon > lonMax:
-		condition = false
-	if lon < lonMin:
-		condition = false
-		
-	return condition
+#func _validate(lat,lon):
+#	var condition = true
+#	if abs(lat) > latMax:
+#		condition = false
+#	if abs(lat) < latMin:
+#		condition = false
+#	if lon > lonMax:
+#		condition = false
+#	if lon < lonMin:
+#		condition = false
+#		
+#	return condition
 		
 	#if abs(lat) <= latMax and abs(lat) >= latMin and lon <= lonMax and lon >= lonMin:
 	#	return true
 	#return false
 
-func getFilename():
-	# example sldem2015_512_00n_30n_000_045_float.img
-	#     "%s/sldem2015_%s_%0*d%s_%0*d%s_%00*d_%00*d_float.img"
-	var properties
-	if orientation == "S":
-		properties = [resolution, abs(latMax), orientation, abs(latMin), orientation, lonMin, lonMax]
-	else:
-		properties = [resolution, latMin, orientation, latMax, orientation, lonMin, lonMax]
-	return formatString % properties
-	
-func getFilepath():
-	return filePrefix+getFilename()
-
 # Called every frame. 'delta' is the elapsed time since the previous frame.
 #func _process(delta):
 #	pass

+ 1 - 13
chunk.gd

@@ -33,19 +33,7 @@ func _ready():
 
 func initialize():
 	print("chunk %s,%s initializing" %[latMin, lonMin])
-	var initialized = .get_node("Mesh").initialize(latMin, latMax, lonMin, lonMax, resolution, radius, scaleFact)
-	if not initialized:
-		var download = Downloader.Download.new()
-		while not download._file_name == .get_node("Mesh").tl.getFilepath():
-			print("awaiting file download for %s" %.get_node("Mesh").tl.getFilepath())
-			download = yield(Messenger, "fileDownloaded")
-	var texInitialized = .get_node("Mesh").initTexture()
-	if not texInitialized:
-		var dl = Downloader.Download.new()
-		while not dl._file_name == .get_node("Mesh").texl.getTexName():
-			print("awaiting file download for %s" %.get_node("Mesh").texl.getTexName())
-			dl = yield(Messenger, "fileDownloaded")
-	.get_node("Mesh").genMesh()
+	yield(Messenger, "meshLoaded")
 	.get_node("Origin").transform.origin = .get_node("Mesh").origin
 	.get_node("Center").transform.origin = .get_node("Mesh").center
 	print("chunk %s,%s ready" %[latMin, lonMin])

+ 3 - 0
common.gd

@@ -31,6 +31,9 @@ func relativeToAbsolute(rel = float()):
 	absolute = rel+180-(sign(rel)*180)
 	return absolute
 
+func posToChunkPos(pos):
+	return Vector2(int(pos.x), int(pos.y))
+	
 #func globalToRad(pos: Vector3):
 #	var floor_normal = pos - Vector3()
 #	floor_normal = floor_normal.normalized()

+ 3 - 6
downloader.gd

@@ -12,7 +12,7 @@ onready var UI = get_node("/root/Main/UI/Downloader")
 
 signal file_downloaded
 signal downloads_finished
-signal stats_updated
+# signal stats_updated -> now via Messenger:statusUpdate
 signal downloads_started
 
 export(bool)            var blind_mode : bool   = false
@@ -38,9 +38,6 @@ class Download:
 func _init() -> void:
 	set_process(false)
 	connect("request_completed", self, "_on_request_completed")
-	
-func _ready():
-	connect("stats_updated", Messenger, "_on_statusUpdate")
 
 func get_stats() -> Download:
 	return currentDownload
@@ -60,7 +57,7 @@ func _downloads_done() -> void:
 func _update_stats() -> void:
 	if blind_mode == false:
 		_calculate_percentage()
-		emit_signal("stats_updated",currentDownload)
+		Messenger.emit_signal("statusUpdate",currentDownload)
 	
 func _process(delta):
 	if not downloading:
@@ -151,7 +148,7 @@ func _on_request_completed(p_result,
 			print("file download complete %s"%currentDownload._current_url)
 			_file.close()
 			emit_signal("file_downloaded", currentDownload)
-			Messenger._on_file_downloaded(currentDownload)
+			Messenger.emit_signal("fileDownloaded", currentDownload)
 			downloading = false
 			remove_download()
 				

+ 1 - 0
project.godot

@@ -19,6 +19,7 @@ config/icon="res://icon.png"
 Common="*res://common.gd"
 Downloader="*res://downloader.gd"
 Messenger="*res://Messenger.gd"
+TopoLoader="*res://TopoLoader.gd"
 
 [input]