Type TStarmap

	Field s:TQuad
	Field sun:TQuad
	Field n:TQuad
	
	Field mesh:TMesh
	Field surf:TSurface
		
	Field xspeed:Float
	Field yspeed:Float
	Field zspeed:Float
	
	Field sectorx:Int = 127  '1016/8
	Field sectory:Int = 177 '1408/8
	Field sectorsize:Int = 8
	Field sectordensity:Int = 0
	Field sectorcontrast:Int = 0
	
	Field loopinit:Int = 0
	Field add:Int = 0
	
	Field Raster1RGBA:Int[] = [0, 0, 255, 32]
	Field Raster2RGBA:Int[] = [0, 0, 255, 64]
	Field Raster3RGBA:Int[] = [0, 0, 255, 96]
	Field Raster4RGBA:Int[] = [0, 0, 255, 255]
	Field NebulaRadar:Int[] = [255, 0, 128, 0]
	Field RasterRadar:Int[] = [255, 0, 255, 0]
	
	Field class:String[] = ["M", "K", "G", "F", "A", "B", "O", "D"]
	
	Field classcolor:Int[][] = [[255, 64, 0], [255, 192, 0], [255, 255, 0], [0, 255, 0], [255, 255, 255], [0, 255, 255], [0, 0, 255], [128, 128, 128]]

	Field PIVOT_STARMAP:TPivot								' Starmap Pivot
	Field PIVOT_STARMAP_RASTER:TPivot						' Starmap Raster Pivot
	Field PIVOT_PLANETS:TPivot
	
	Field STARMAP_RASTER1:TMesh								' Starmap Large Raster
	Field STARMAP_RASTER2:TMesh								' Starmap Medium Raster
	Field STARMAP_RASTER3:TMesh								' Starmap Small Raster

	Field STARMAP_STARS:TMesh								' Starmap Star Mesh
	Field STARMAP_SURF:TSurface

	Field STARMAP_SUN:TMesh									' Starmap Sun Mesh
	Field STARMAP_SUNSURF:TSurface

	Field STARMAP_NEBULAMESH:TMesh							' Starmap Nebula Mesh
	Field STARMAP_NEBULASURF:TSurface
	
	Field STARMAP_MILKYWAY:TMesh
	Field STARMAP_MILKYSURF:TSurface

	Field STARMAP_MILKYWAYDETAIL:TMesh
	Field STARMAP_MILKYWAYDETAILSURF:TSurface
		
	Field STARMAP_PLANETS:Int = 9
	Field STARMAP_ORBIT:TMesh[99]
	Field STARMAP_PLANET:TMesh[99]
	Field STARMAP_PLANETPIVOT:TPivot[99]
	Field STARMAP_ORBITROTATIONSPEED:Float[99]
	Field STARMAP_SYSTEMROTATION:Float = 60
	Field STARMAP_ORBITRASTER:TMesh
	Field STARMAP_PLANETLIGHT:TLight
	
	

	' --------------------------------------------------------------------------------------------
	' Create Starmap Objects
	' --------------------------------------------------------------------------------------------
	Method _Init()
			
		' ----------------------------------------------------------------------------------------
		' Create Sun Raster
		' ----------------------------------------------------------------------------------------
		TIME.Start()
		
		_CreateStarmapTextures()
		
		TIME.Stop("Sun Textures created")
	
		' ----------------------------------------------------------------------------------------
		' Create Starmap Raster
		' ----------------------------------------------------------------------------------------
		TIME.Start()

		PIVOT_STARMAP = CreatePivot()
		PIVOT_STARMAP_RASTER = CreatePivot(PIVOT_STARMAP)
		PIVOT_PLANETS = CreatePivot(PIVOT_STARMAP)

		Local RASTER1:TTexture = MEDIA.GetTexture("STARMAP_RASTER1")
		ScaleTexture RASTER1, 100.0 / GAME_SIZE, 100.0 / GAME_SIZE
		TextureBlend RASTER1, 5
		
		Local RASTER2:TTexture = MEDIA.GetTexture("STARMAP_RASTER2")
		ScaleTexture RASTER2, 10.0 / GAME_SIZE, 10.0 / GAME_SIZE
		TextureBlend RASTER2, 5
		
		Local RASTER3:TTexture = MEDIA.GetTexture("STARMAP_RASTER3")
		ScaleTexture RASTER3, 1.0 / GAME_SIZE, 1.0 / GAME_SIZE
		TextureBlend RASTER3, 5

		Local RASTER4:TTexture = MEDIA.GetTexture("STARMAP_RASTER4")
		ScaleTexture RASTER4, 20.0 / GAME_SIZE, 20.0 / GAME_SIZE
		TextureBlend RASTER4, 5

		Local MILKYWAY:TTexture = MEDIA.GetTexture("STARMAP_MILKYWAY")
				
		' Create Mesh #1
		STARMAP_RASTER1 = CreateQuad(PIVOT_STARMAP_RASTER)
		ScaleMesh STARMAP_RASTER1, GAME_SIZE / 2.0, GAME_SIZE / 2.0, GAME_SIZE / 2.0
		RotateMesh STARMAP_RASTER1, 90, 0, 0
		PositionEntity STARMAP_RASTER1, 0, 0, 0
		EntityFX STARMAP_RASTER1, 1
		EntityTexture STARMAP_RASTER1, RASTER1
		EntityColor STARMAP_RASTER1, Raster1RGBA[0], Raster1RGBA[1], Raster1RGBA[2]
		EntityAlpha STARMAP_RASTER1, RASTER1RGBA[3]
				
		' Create Mesh #2
		STARMAP_RASTER2 = CreateQuad(PIVOT_STARMAP_RASTER)
		ScaleMesh STARMAP_RASTER2, GAME_SIZE / 2.0, GAME_SIZE / 2.0, GAME_SIZE / 2.0
		RotateMesh STARMAP_RASTER2, 90, 0, 0
		PositionEntity STARMAP_RASTER2, 0, 0, 0
		EntityFX STARMAP_RASTER2, 1
		EntityTexture STARMAP_RASTER2, RASTER2
		EntityColor STARMAP_RASTER2, Raster2RGBA[0], Raster2RGBA[1], Raster2RGBA[2]
		EntityAlpha STARMAP_RASTER2, RASTER2RGBA[3]
		
		' Create Mesh #3
		STARMAP_RASTER3 = CreateQuad(PIVOT_STARMAP_RASTER)
		ScaleMesh STARMAP_RASTER3, GAME_SIZE / 2.0, GAME_SIZE / 2.0, GAME_SIZE / 2.0
		RotateMesh STARMAP_RASTER3, 90, 0, 0
		PositionEntity STARMAP_RASTER3, 0, 0, 0
		EntityFX STARMAP_RASTER3, 1
		EntityTexture STARMAP_RASTER3, RASTER3
		EntityColor STARMAP_RASTER3, Raster3RGBA[0], Raster3RGBA[1], Raster3RGBA[2]
		EntityAlpha STARMAP_RASTER3, RASTER3RGBA[3]
		
		STARMAP_MILKYWAY = CreateQuad(PIVOT_STARMAP)
		ScaleMesh STARMAP_MILKYWAY, 2048 * 64.0, 2048 * 64.0, 2048 * 64.0
		RotateMesh STARMAP_MILKYWAY, 90, 0, 0
		EntityFX STARMAP_MILKYWAY, 1
		EntityOrder STARMAP_MILKYWAY, -10000
		TextureBlend MILKYWAY, 5
		EntityBlend STARMAP_MILKYWAY, 3
		EntityColor STARMAP_MILKYWAY, 128, 128, 128
		
		STARMAP_MILKYWAYDETAIL = CreateQuad(PIVOT_STARMAP)
		ScaleMesh STARMAP_MILKYWAYDETAIL, 2048 * 64.0, 2048 * 64.0, 2048 * 64.0
		RotateMesh STARMAP_MILKYWAYDETAIL, 90, 0, 0
		EntityFX STARMAP_MILKYWAYDETAIL, 1
		EntityOrder STARMAP_MILKYWAYDETAIL, -5000
		EntityBlend STARMAP_MILKYWAYDETAIL, 3
		EntityColor STARMAP_MILKYWAYDETAIL, 0, 16, 32
		
		Local scale:Float = 2.0 / SCREEN_WIDTH
		STARMAP_PLANETLIGHT = CreateLight(2)
		LightRange STARMAP_PLANETLIGHT, 1
		AmbientLight 0, 0, 0'4, 8, 16

		LightColor STARMAP_PLANETLIGHT, classcolor[1][0], classcolor[1][1], classcolor[1][2]
				
	'	RotateEntity PIVOT_PLANETS, STARMAP_SYSTEMROTATION, 0, 0
		
		For Local i:Int = 0 To STARMAP_PLANETS - 1
		
			Local r:Float = 0.15 + (0.05 * i)
			Local s:Float = scale
			Local size:Float = 1.0 / 128.0' * Rnd(0.5, 1.5)
			
			STARMAP_ORBITROTATIONSPEED[i] = (STARMAP_PLANETS - i) * 1.0 / (1 + i)
			
			STARMAP_PLANETPIVOT[i] = CreatePivot()
			EntityParent STARMAP_PLANETPIVOT[i], PIVOT_PLANETS
			PositionEntity STARMAP_PLANETPIVOT[i], 0, 0, 0
		
			' single orbit
			STARMAP_ORBIT[i] = CreateGlow(PIVOT_PLANETS, r - (s / 2.0), r + (s / 2.0), 90, 1)
			RotateMesh STARMAP_ORBIT[i], -90, 0, 0
			EntityFX STARMAP_ORBIT[i], 1' + 16
			EntityColor STARMAP_ORBIT[i], 128, 192, 255'64, 128, 255
			EntityTexture STARMAP_ORBIT[i], MEDIA.GetTexture("STARMAP_ORBIT")
			
			' single planet
			STARMAP_PLANET[i] = CreateSphere(16)
			EntityParent STARMAP_PLANET[i], STARMAP_PLANETPIVOT[i]
			PositionEntity STARMAP_PLANET[i], 0, 0, 0
			EntityFX STARMAP_PLANET[i], 2
			'EntityColor STARMAP_PLANET[i], 128, 128, 128
			UpdateMeshColor(STARMAP_PLANET[i], 128, 128, 128, 1)
			ScaleEntity STARMAP_PLANET[i], size, size, size
			MoveEntity STARMAP_PLANET[i], 0, 0, r
			EntityTexture STARMAP_PLANET[i], MEDIA.GetTexture("STARMAP_PLANET")
			TextureBlend MEDIA.GetTexture("STARMAP_PLANET"), 5
			
			RotateEntity STARMAP_PLANETPIVOT[i], 0, Rnd(360), 0
						
		Next
		

		' Create Mesh #3
		STARMAP_ORBITRASTER = CreateQuad(PIVOT_PLANETS)
		PositionEntity STARMAP_ORBITRASTER, 0, 0, 0
		EntityFX STARMAP_ORBITRASTER, 1 + 2 + 32
		EntityTexture STARMAP_ORBITRASTER, RASTER4
		UpdateMeshColor(STARMAP_ORBITRASTER, Raster4RGBA[0], Raster4RGBA[1], Raster4RGBA[2], RASTER4RGBA[3])
		ScaleEntity STARMAP_ORBITRASTER, 0.6, 0.6, 0.6
		RotateMesh STARMAP_ORBITRASTER, 90, 0, 0
		EntityOrder STARMAP_ORBITRASTER,1
		
		
		EntityBlend STARMAP_RASTER1, 3
		EntityBlend STARMAP_RASTER2, 3
		EntityBlend STARMAP_RASTER3, 3
		
		TIME.Stop("Starmap: Raster created")
				
		' ----------------------------------------------------------------------------------------
		' Randomize Starmap
		' ----------------------------------------------------------------------------------------
		_Randomize()
			
	End Method
	


	' --------------------------------------------------------------------------------------------
	' METHOD: Create new randomized Starmesh
	' --------------------------------------------------------------------------------------------
	Method _Randomize()

		TIME.Start()
				
		SeedRnd GAME_SEED
		CreateRandomArray(GAME_SIZE)
				
		_Update()

		TIME.Stop("Starmap: Random Starmap created (SEED: " + GAME_SEED + ")")
		
	End Method
	
	
	
	' --------------------------------------------------------------------------------------------
	' METHOD: Starmap Key Mouse/Keyboard Input
	' --------------------------------------------------------------------------------------------
	Method _PollInput()
				
		Local factor:Float = 0.25 * FPS.multi
		Local speedup:Int = (1 + (KeyDown(KEY_RSHIFT) Or KeyDown(KEY_LSHIFT)) * Log(Camera.Y))
	
		xspeed:-(((KeyDown(KEY_LEFT) - KeyDown(KEY_RIGHT))) + (KeyDown(KEY_A) - KeyDown(KEY_D)) * Camera.factor1 * factor) * speedup
		yspeed:+((MouseDown(2) - MouseDown(1)) * CAMERA.factor2 * factor) * speedup * 1'0.25
		zspeed:+(((KeyDown(KEY_UP) - KeyDown(KEY_DOWN)) + ((KeyDown(KEY_W) - KeyDown(KEY_S)))) * Camera.factor1 * factor) * speedup
				
		If KeyHit(KEY_G) Then FLAG.Switch("RADAR") ; loopinit = 0
		If KeyHit(KEY_R) Then FLAG.Switch("RASTER")
		If KeyHit(KEY_N) Then FLAG.Switch("NEBULA")
		If KeyHit(KEY_Q) Then FLAG.Switch("STARS")
		If KeyHit(KEY_I) Then FLAG.Switch("STARINFO")
		If KeyHit(KEY_1) Then FLAG.Switch("GALAXY")
		If KeyHit(KEY_2) Then FLAG.Switch("GALAXYDETAIL")
		
		If KeyHit(KEY_SPACE) Then

			GAME_SEED:+1
			STARMAP._Randomize()
			STARMAP.loopinit = 0
			Print "New Seed: " + GAME_SEED
		
		End If
		
		RotateEntity PIVOT_PLANETS, Normalize(MouseY(), 0, SCREEN_HEIGHT - 1, 80 * 1.0 / CAMERA.Y, 0), 0, 0
		Turn PIVOT_PLANETS, 0, Normalize(MouseX(), 0, SCREEN_WIDTH - 1, -180, 180), 0

		
	End Method



	' --------------------------------------------------------------------------------------------
	' METHOD: Update Starmesh Stars
	' --------------------------------------------------------------------------------------------
	Method _Update()
	
		Local i:Int
		
		' delete old meshes
		If STARMAP_STARS Then FreeEntity STARMAP_STARS
		If STARMAP_SUN Then FreeEntity STARMAP_SUN
		If STARMAP_NEBULAMESH Then FreeEntity STARMAP_NEBULAMESH
		
		' ----------------------------------------------------------------------
		' Create Star Mesh
		' ----------------------------------------------------------------------
		STARMAP_STARS = CreateMesh(PIVOT_STARMAP)
		STARMAP_SURF = CreateSurface(STARMAP_STARS)
		PositionEntity STARMAP_STARS, 0, 0, 0
		EntityFX STARMAP_STARS, 1 + 2 + 32
		EntityTexture STARMAP_STARS, MEDIA.GetTexture("STARMAP_STARSTRIP")
		ScaleTexture MEDIA.GetTexture("STARMAP_STARSTRIP"), 8, 1
		TextureBlend MEDIA.GetTexture("STARMAP_STARSTRIP"), 5
		EntityBlend STARMAP_STARS, 3
		EntityOrder STARMAP_STARS, -50

		' ----------------------------------------------------------------------
		' Create Sun Mesh
		' ----------------------------------------------------------------------
		STARMAP_SUN = CreateMesh(PIVOT_STARMAP)
		STARMAP_SUNSURF = CreateSurface(STARMAP_SUN)
		PositionEntity STARMAP_SUN, 0, 0, 0
		EntityFX STARMAP_SUN, 1
		EntityTexture STARMAP_SUN, MEDIA.GetTexture("STARMAP_SUNSTRIP")
		ScaleTexture MEDIA.GetTexture("STARMAP_SUNSTRIP"), 8, 2
		'EntityColor STARMAP_SUN,255,128,128
		'TextureBlend MEDIA.GetTexture("STARMAP_SUNSTRIP"), 2
		'EntityBlend STARMAP_SUN, 3
		'EntityOrder STARMAP_SUN, -50
		
		' ----------------------------------------------------------------------
		' Create Nebula Mesh
		' ----------------------------------------------------------------------
		STARMAP_NEBULAMESH:TMesh = CreateMesh(PIVOT_STARMAP)
		STARMAP_NEBULASURF = CreateSurface(STARMAP_NEBULAMESH)
		ScaleTexture MEDIA.GetTexture("STARMAP_NEBULAE"), NEBULA_ROWS, NEBULA_ROWS
		EntityBlend STARMAP_NEBULAMESH, 3
		EntityFX STARMAP_NEBULAMESH, 1 + 2 + 32
		EntityPickMode STARMAP_NEBULAMESH, 2
		EntityOrder STARMAP_NEBULAMESH, 1

		
					
		' ----------------------------------------------------------------------
		' delete all star quad entries
		' ----------------------------------------------------------------------
		For s = EachIn TQuad.List
		
			s.Remove()
		
		Next

		' ----------------------------------------------------------------------
		' delete all nebula quad entries
		' ----------------------------------------------------------------------
		For n = EachIn TQuad.List
		
			n.Remove()
		
		Next
				
		' ----------------------------------------------------------------------
		' populate starmesh with stars				
		' ----------------------------------------------------------------------
		SeedRnd GAME_SEED
		For i = 1 To GAME_STARS
			
			_AddStar(i)

		Next
		
		Local oldsector:TPixmap = CreatePixmap(sectorsize, sectorsize, PF_RGB888)
		Local newsector:TPixmap = CreatePixmap(sectorsize, sectorsize, PF_RGB888)
		Local nebulamap:TPixmap = CreatePixmap(sectorsize, sectorsize, PF_RGB888)
		Local sector:TPixmap = MEDIA.GetTexture("STARMAP_MILKYWAY").Pixmap
		
		Local mn:Float = 255, mx:Float = 0
		
		sectordensity = 0
		sectorcontrast = 0
				
		For Local x:Int = 0 To sectorsize - 1
			
			For Local y:Int = 0 To sectorsize - 1
			
				Local rgb:Int = ReadPixel(sector, (sectorx * sectorsize) + x, (sectory * sectorsize) + y)
				WritePixel oldsector, x, y, rgb
				
				Local r:Int = GetR(rgb)
				Local g:Int = GetG(rgb)
				Local b:Int = GetB(rgb)

				Local c:Int = 0.299 * R + 0.578 * G + 0.114 * B
												
				If c < mn Then mn = c Else If c > mx Then mx = c
								
				If c < 0 Then c = 0
				If c > 255 Then c = 255

				sectordensity:+c
				
				WritePixel(newsector, x, y, CombineRGB(c, c, c))
				
			Next
		
		Next
		
		sectordensity = Int(sectordensity * 1.0 / sectorsize ^ 2)
		sectorcontrast = Abs(mx - mn)
						
		For Local x:Int = 0 To sectorsize - 1
			
			For Local y:Int = 0 To sectorsize - 1
			
				Local rgb1:Int = ReadPixel(newsector, x, y)
				Local rgb2:Int = ReadPixel(oldsector, x, y)

				Local c:Int = GetR(rgb1)
				
				c = Levels(c, mn, 1.0, mx, 0, 255)
				
				If c < 0 Then c = 0
				If c > 255 Then c = 255

				WritePixel(nebulamap, x, y, CombineRGB(0, 0, 0))
								
				If c > sectorcontrast Then

					WritePixel(nebulamap, x, y, CombineRGB(c, c, c))
					
					Local nb:Int = Rand(0, 15)

					Local sx:Float = Normalize(x + Rnd(-0.5, 0.5), 0, sectorsize - 1, -GAME_SIZE / 2.0, GAME_SIZE / 2.0)
					Local sy:Float = Normalize(y + Rnd(-0.5, 0.5), 0, sectorsize - 1, GAME_SIZE / 2.0, -GAME_SIZE / 2.0)
					
					Local r:Int = GetR(rgb2)
					Local g:Int = GetG(rgb2)
					Local b:Int = GetB(rgb2)
															
					_AddNebula(sx, sy, nb, c / 255.0, r, g, b)
				
				
				End If
							
			Next
			
		Next
				
		SavePixmapPNG(oldsector, "temp/oldsector.png", 0)
		SavePixmapPNG(newsector, "temp/newsector.png", 0)
		SavePixmapPNG(nebulamap, "temp/nebulamap.png", 0)
		
		'SavePixmapPNG(sector, "sector.png", 0)
			
		' ----------------------------------------------------------------------
		' reset flag
		' ----------------------------------------------------------------------
		'loopinit = 0
	
	End Method
	


	' ----------------------------------------------------------------------
	' METHOD: Add a single Star to Starmesh
	' ----------------------------------------------------------------------
	Method _AddStar(i:Int)
			
		Local addx:Float = 0.0
		Local x:Int, y:Int
		Local ss:Float
		Local m:Int
		Local starid:String
	
		' pick random coordinates from array
		x = Array[i + add] / GAME_SIZE
		y = Array[i + add] - (x * GAME_SIZE)
		
		' dont use central star again, skip position
		If (x = 500 And y = 500) Then
			add = 1
			x = Array[i + add] / GAME_SIZE
			y = Array[i + add] - (x * GAME_SIZE)
		EndIf
				
		' create new object
		s:TQuad = New TQuad
		sun:TQuad = New TQuad

		' flag for multiple star system
		s.multi = 1
		If Rnd(1) > 0.5 Then s.multi = 2

		' multiple star system distance scale
		ss = Sqr(s.size / 500.0)
		
		' first star = left star
		If s.multi > 1 Then addx = -ss
		
		' prime star always "x.0"
		_CreateStar(i + ".0", x, y, addx)

		' a dwarf can't be a giant, too
		If s.dwarf = 1 Then s.giant = 0
						
		' second star = right star
		If s.multi > 1 Then
		
			addx = ss
		
			For m = 2 To s.multi

				s:TQuad = New TQuad
				sun:TQuad = New TQuad
					
				' substar counter
				starid = i + "." + (m - 1)
	
				_CreateStar(starid, x, y, addx)
				
				If s.dwarf = 1 Then s.giant = 0
	
			Next

		EndIf
								
	End Method
	

		
	' --------------------------------------------------------------------------------------------
	' METHOD: Create a single star
	' --------------------------------------------------------------------------------------------
	Method _CreateStar(i:String, x:Int, y:Int, ss:Float = 1.0)
							
		' calculate pseudorandom noise values
		s.p = Rnd(0, 1)
		s.c = Rnd(0, 1)
		s.n = Rnd(0, 1)
	
		' define star size
		s.size = (0.5 + Exp(s.p)) * s.c
		If s.size < 0.2 Then s.size = Rnd(0.2, 0.25)
		
		' create some giants
		If (s.c < 0.4 And s.p > 0.9) Or (s.c > 0.65 And s.p > 0.9) Then s.giant = 1
		If s.giant = 1 Then s.size = Rnd(3, 10)

		' create some white dwards
		If s.c > 0.8 Then s.dwarf = 1
		If s.dwarf = 1 Then s.size = Rnd(0.01, 0.02)
								
		' categorize and place star
		s.id = i
		s.category = "Star"
		
		s.x = x - (GAME_SIZE / 2) + ss
		s.y = 0
		s.z = y - (GAME_SIZE / 2)
				
		' Fixed homeworld values
		If s.id = "1.0" Then
			s.x = 0			' Position X
			s.z = 0			' Position Z
			s.size = 1		' Size = 1
			s.giant = 0		' No Giant
			s.dwarf = 0		' No White DWarf
			s.multi = 1		' Single Star
			s.c = 0.5		' Glass G Star
		EndIf
				
		' spectral classification
		Local sid:Int = 0
		If s.c >= 0.00 And s.c < 0.20 Then sid = 0		' M
		If s.c >= 0.20 And s.c < 0.40 Then sid = 1		' K
		If s.c >= 0.40 And s.c < 0.60 Then sid = 2		' G
		If s.c >= 0.60 And s.c < 0.65 Then sid = 3		' F
		If s.c >= 0.65 And s.c < 0.70 Then sid = 4		' A
		If s.c >= 0.70 And s.c < 0.75 Then sid = 5		' B
		If s.c >= 0.75 And s.c < 0.80 Then sid = 6		' O
		If s.c >= 0.80 And s.c <= 1.00 Then sid = 7		' D
		s.sid = sid
		s.starclass = class[sid]
		s.RGB = [128, 128, 128]'255, 255, 255]
					
		' Add star quad to mesh
		s.mesh = STARMAP_STARS
		s.surf = STARMAP_SURF
		s.add(sid)
						
		' Add sun quad to mesh
		sun.x = s.x
		sun.y = s.y
		sun.z = s.z
		
		sun.c = s.c
		sun.p = s.p
		sun.starclass = s.starclass
		
		sun.size = s.size
		sun.giant = s.giant
		sun.dwarf = s.dwarf
		
		sun.category = "Sun"
		sun.id = s.id
		
		sun.hash = s.hash
		
		sun.mesh = STARMAP_SUN
		sun.surf = STARMAP_SUNSURF
		
		sun.Add(sid, sun.giant)
	
	End Method
	


	' --------------------------------------------------------------------------------------------
	' METHOD: Add Nebula
	' --------------------------------------------------------------------------------------------
	Method _AddNebula(x:Float, z:Float, id:Int = 0, alpha:Float = 1.0, r:Int = 128, g:Int = 128, b:Int = 128)
	
		Local u:Int, v:Int
		Local f:Float = GAME_SIZE * 1.0 / 1000
		
		Local r1:Int, r2:Int, r3:Int, r4:Int
		Local g1:Int, g2:Int, g3:Int, g4:Int
		Local b1:Int, b2:Int, b3:Int, b4:Int
			
		n = New TQuad
			
		n.category = "Nebula"
			
		n.x = x
		n.y = 0
		n.z = z
			
		n.rotation = Rnd(0, 360)
			
		n.scalex = Rnd(64, 192) * f * (1 + alpha)
		n.scaley = n.scalex * Rnd(0.75, 1.25)
			
		n.id = id
			
		u = Int(n.id) / NEBULA_ROWS
		v = Int(id) - (u * NEBULA_ROWS)
			
		n.mesh = STARMAP_NEBULAMESH
		n.surf = STARMAP_NEBULASURF

		n.alpha1 = Rnd(0.0, 1.0) * alpha
		n.alpha2 = Rnd(0.0, 1.0) * alpha
		n.alpha3 = Rnd(0.0, 1.0) * alpha
		n.alpha4 = Rnd(0.0, 1.0) * alpha
		
		r1 = (Rand(255) + r) / 2
		r2 = (Rand(255) + r) / 2
		r3 = (Rand(255) + r) / 2
		r4 = (Rand(255) + r) / 2

		g1 = (Rand(255) + r) / 2
		g2 = (Rand(255) + r) / 2
		g3 = (Rand(255) + r) / 2
		g4 = (Rand(255) + r) / 2

		b1 = (Rand(255) + r) / 2
		b2 = (Rand(255) + r) / 2
		b3 = (Rand(255) + r) / 2
		b4 = (Rand(255) + r) / 2
		
		n.RGB1 = [Rand(n.alpha1 * r1, r1), Rand(n.alpha1 * g1, g1), Rand(n.alpha1 * b1, b1)]
		n.RGB2 = [Rand(n.alpha2 * r2, r2), Rand(n.alpha2 * g2, g2), Rand(n.alpha2 * b2, b2)]
		n.RGB3 = [Rand(n.alpha3 * r3, r3), Rand(n.alpha3 * g3, g3), Rand(n.alpha3 * b3, b3)]
		n.RGB4 = [Rand(n.alpha4 * r4, r4), Rand(n.alpha4 * g4, g4), Rand(n.alpha4 * b4, b4)]
										
		n.add(u, v)
		n.UpdateRotation(CAMERA.cam)
	
	End Method
	

	
	' --------------------------------------------------------------------------------------------
	' METHOD: Things to do BEFORE Renderworld
	' --------------------------------------------------------------------------------------------
	Method _Loop()
	
		'Local s:TQuad
		Local dx:Int, dy:Int
		Local r:Int, g:Int, b:Int
	
		_PollInput()
	
		If CAMERA.y + (yspeed * 0.95 * FPS.multi) >= 1.0 Then CAMERA.y:+yspeed

		'If CAMERA.Y > 1000 Then xspeed = 0;zspeed = 0
		
		' increase speed
		CAMERA.x:+xspeed
		CAMERA.Z:+zspeed
		
		' reduce speed
		xspeed:*(0.95 * FPS.Multi)
		yspeed:*(0.95 * FPS.Multi)
		zspeed:*(0.95 * FPS.Multi)
		
		' limit camera Y position
		If CAMERA.Y < 1 Then CAMERA.Y = 1
		If CAMERA.Y > 10000000 Then CAMERA.Y = 10000000
		
		
		' update camera with values
		CAMERA.Update()

		' big galaxy alpha and stars alpha (1-a1)
		Local a1:Float = Normalize(CAMERA.Y, 500, 3000, 0, 1)
		If a1 < 0 Then a1 = 0
		If a1 > 1 Then a1 = 1
		
		' general sector alpha (nebula)
		Local a2:Float = Normalize(CAMERA.Y, 0, 1000000, 1, 0)
		If a2 < 0 Then a2 = 0
		If a2 > 1 Then a2 = 1

		' galaxy detail alpha
		Local a3:Float
		If CAMERA.y > 1500 Then a3 = Normalize(CAMERA.y, 1500, 100000, 1, 0)
		If CAMERA.Y <= 1500 Then a3 = Normalize(CAMERA.Y, 500, 1500, 0, 1)
		If a3 < 0 Then a3 = 0
		If a3 > 1 Then a3 = 1

		' raster alpha
		Local a4:Float = Normalize(CAMERA.Y, 500, 1500, 1, 0)
		If a4 < 0 Then a4 = 0
		If a4 > 1 Then a4 = 1
		
		a2 = 1
		'a3 = 1
			
		Local sx:Int = 131072 - ((sectorx + 0.5) * sectorsize * 128)
		Local sy:Int = ((sectory + 0.5) * sectorsize * 128) - 131072
		
		EntityAlpha STARMAP_MILKYWAY, a1
		EntityAlpha STARMAP_MILKYWAYDETAIL, a3 * sectordensity / 128.0
		PositionEntity STARMAP_MILKYWAY, sx, 0,sy'(CAMERA.Y) / 2.0, sy
		PositionEntity STARMAP_MILKYWAYDETAIL, sx, 0, sy
		
		' planets and orbits
		Local a:Float = 0.0
		PositionEntity PIVOT_PLANETS, Camera.X, 0, Camera.Z
		If CAMERA.Y < 2 Then a = Normalize(CAMERA.Y, 1, 2, 1, 0)
		ScaleEntity PIVOT_PLANETS, a * 2, a * 2, a * 2
		
		UpdateMeshColor(STARMAP_ORBITRASTER, Raster4RGBA[0], Raster4RGBA[1], Raster4RGBA[2], a)
		PositionEntity STARMAP_PLANETLIGHT, CAMERA.X, 0, CAMERA.Z

		' adjust orbit alpha and move planets
		For Local i:Int = 0 To STARMAP_PLANETS - 1

			If CAMERA.y < 2 Then
						
				EntityAlpha STARMAP_ORBIT[i], a * 0.25
				EntityAlpha STARMAP_PLANET[i], a
				TurnEntity STARMAP_PLANETPIVOT[i], 0, STARMAP_ORBITROTATIONSPEED[i] * FPS.multi * (CAMERA.Y ^ 2 - 0.95) Mod 360.0, 0
						
			Else
		
				EntityAlpha STARMAP_ORBIT[i], 0
				EntityAlpha STARMAP_PLANET[i], 0
				RotateEntity STARMAP_PLANETPIVOT[i], 0, Rnd(360), 0
			
			EndIf
			
		'	If i = 1 Then Print EntityYaw(STARMAP_PLANETPIVOT[i])

		Next
	
		
		' only execute if camera has been moved or first init occurs			
		If CAMERA.Moved() Or loopinit = 0 Then
		
			loopinit = 1
							
			For s = EachIn TQuad.List
		
				' plot star position to screen coordinates
				CAMERA.Project(s.x, s.y, s.z)
				s.sx = CAMERA.PX
				s.sy = CAMERA.PY
				
				' screen check dimensions
				dx = SCREEN_WIDTH * 0.125
				dy = SCREEN_HEIGHT * 0.125
										
				' if object lies within frustum
				If (s.sx > - dx And s.sx < SCREEN_WIDTH + dx And s.sy >= - dy And s.sy < SCREEN_HEIGHT + dy) Or s.category = "Nebula" Then
			
					'PositionEntity PIVOT, s.x, s.y, s.z
					's.distance = EntityDistance(PIVOT, CAMERA.cam)
					Local f:Float = CAMERA.Y
	
					' quad is a star?
					If s.category = "Star" Then
																	
						' adjust star size according to cam Y axis height
						s.scalex = Sqr(f * 1.0 / 40.0 * (1 - a1) * s.size) * Exp(Log10((1 + f) * 1.0 / s.size) * 1.0 / f)

						' adjust color and size in radar gui mode
						If FLAG.Get("RADAR") Then
						
							r = classcolor[s.sid][0]
							g = classcolor[s.sid][1]
							b = classcolor[s.sid][2]
						
							s.RGB = [r, g, b]
					
							s.scalex = Sqr(f) / 5.0
						
						Else
						
							s.RGB = [255, 255, 255]
						
						End If
																								
						' hide star if too small
						If s.scalex < 0 Then s.scalex = 0
						s.scaley = s.scalex
						
						' adjust star alpha
						s.alpha = 1
						If f < 10 Then s.alpha = Normalize(f, 10.0, 1.0, 1.0, 0.0)
						If Right(s.id, 1) = "1" And f > 10 Then s.alpha = Normalize(f, 50.0, 1.0, 0.0, 1.0)
						
						s.Alpha:*(1 - a1)
						
						' update star
						s.Update(CAMERA.cam)
							
					EndIf
	
					' calculations for zoomed star mode
					If s.category = "Sun" Then
														
						' adjust sun size according to cam Y axis height
						s.scalex = Sqr(f * 1.0 * s.size) * Exp(Log10((1 + f) * 1.0 / s.size) * 1.0 / f) / 25.0
						
						If s.dwarf = 1 Then s.scalex:*0.25
						
						' hide star if too small
						If s.scalex < 0 Then s.scalex = 0
						s.scaley = s.scalex
						
						' adjust sun alpha
						s.alpha = 0
						If f < 10 Then s.alpha = Normalize(f, 10.0, 1.0, 0.0, 1.0)
						If Right(s.id, 1) = "1" And f > 10 Then s.alpha = Normalize(f, 50.0, 1.0, 0.0, 1.0)

						s.Alpha:*(1 - a1)

						' update star
						s.Update(CAMERA.cam)
													
					End If
					
					' special update for nebulas
					If s.category = "Nebula" Then s.UpdateRotation(CAMERA.cam)
					
				Else
					
					' hide object
					s.Hide()
														
				EndIf
			
			Next
		
		EndIf
							
		' show/hide star mesh
		If FLAG.Get("STARS") Then
			
			ShowEntity STARMAP_STARS
			ShowEntity STARMAP_SUN
			
		Else

			HideEntity STARMAP_STARS
			HideEntity STARMAP_SUN
		
		End If

		' show/hide nebula mesh
		If FLAG.Get("NEBULA") Then
			
			ShowEntity STARMAP_NEBULAMESH
			UpdateMeshAlpha(STARMAP_NEBULAMESH, Log10(1 + CAMERA.y / 5.0) * a2)
			
		Else

			HideEntity STARMAP_NEBULAMESH
		
		End If
		
		' switch between real color mode and gui color mode
		If FLAG.Get("RADAR") Then
		
			Local brush:TBrush = CreateBrush()
			TextureBlend MEDIA.GetTexture("STARMAP_NEBULACOLOR"), 5
			BrushTexture brush, MEDIA.GetTexture("STARMAP_NEBULAE"), 0, 0
			BrushTexture brush, MEDIA.GetTexture("STARMAP_NEBULACOLOR"), 0, 1
			PaintMesh(STARMAP_NEBULAMESH, brush)
			FreeBrush brush

			brush:TBrush = CreateBrush()
			TextureBlend MEDIA.GetTexture("STARMAP_NEBULACOLOR"), 5
			BrushTexture brush, MEDIA.GetTexture("STARMAP_MILKYWAY"), 0, 0
			BrushTexture brush, MEDIA.GetTexture("STARMAP_NEBULACOLOR"), 0, 1
			PaintMesh(STARMAP_MILKYWAY, brush)
			FreeBrush brush
			
			brush = CreateBrush()
			BrushTexture brush, MEDIA.GetTexture("STARMAP_DETAIL"), 0, 0
			BrushTexture brush, MEDIA.GetTexture("STARMAP_NEBULACOLOR"), 0, 1
			ScaleTexture MEDIA.GetTexture("STARMAP_DETAIL"), 1.0 / 32, 1.0 / 32
			TextureBlend MEDIA.GetTexture("STARMAP_DETAIL"), 5
			PaintMesh(STARMAP_MILKYWAYDETAIL, brush)
			FreeBrush brush			
							
			' star gui color mode
			EntityTexture STARMAP_STARS, MEDIA.GetTexture("STARMAP_DOT")
			TextureBlend MEDIA.GetTexture("STARMAP_DOT"), 2
			
			' raster gui color mode
			EntityColor STARMAP_RASTER1, RasterRadar[1], RasterRadar[2], RasterRadar[3]
			EntityColor STARMAP_RASTER2, RasterRadar[1], RasterRadar[2], RasterRadar[3]
			EntityColor STARMAP_RASTER3, RasterRadar[1], RasterRadar[2], RasterRadar[3]
			
			EntityAlpha STARMAP_RASTER1, RasterRadar[0] / 255.0 * (1 - a1)
			EntityAlpha STARMAP_RASTER2, RasterRadar[0] / 255.0 * (1 - a1)
			EntityAlpha STARMAP_RASTER3, RasterRadar[0] / 255.0 * (1 - a1)
			
		Else
		
			' nebula real color mode
			Local brush:TBrush = CreateBrush()
			BrushTexture brush, MEDIA.GetTexture("STARMAP_NEBULAE"), 0, 0
			PaintMesh(STARMAP_NEBULAMESH, brush)
			FreeBrush brush

			brush = CreateBrush()
			BrushTexture brush, MEDIA.GetTexture("STARMAP_MILKYWAY"), 0, 0
			PaintMesh(STARMAP_MILKYWAY, brush)
			FreeBrush brush

			brush = CreateBrush()
			BrushTexture brush, MEDIA.GetTexture("STARMAP_DETAIL"), 0, 0
			ScaleTexture MEDIA.GetTexture("STARMAP_DETAIL"), 1.0 / 32, 1.0 / 32
			TextureBlend MEDIA.GetTexture("STARMAP_DETAIL"), 3
			PaintMesh(STARMAP_MILKYWAYDETAIL, brush)
			FreeBrush brush

			' star real color mode
			EntityTexture STARMAP_STARS, MEDIA.GetTexture("STARMAP_STARSTRIP")

			' raster real color mode
			EntityColor STARMAP_RASTER1, Raster1RGBA[0], Raster1RGBA[1], Raster1RGBA[2]
			EntityColor STARMAP_RASTER2, Raster2RGBA[0], Raster2RGBA[1], Raster2RGBA[2]
			EntityColor STARMAP_RASTER3, Raster3RGBA[0], Raster3RGBA[1], Raster3RGBA[2]
					
		End If
		
		' show/hide raster
		If FLAG.Get("RASTER") Then
			
			' adaptive blending of raster
			EntityAlpha STARMAP_RASTER1, (Raster1RGBA[3] / 255.0) * Log(CAMERA.y / 10.0) * a4
			EntityAlpha STARMAP_RASTER2, (Raster2RGBA[3] / 255.0) * Log(CAMERA.y / 5.0) * a4
			EntityAlpha STARMAP_RASTER3, (Raster3RGBA[3] / 255.0) * Log(CAMERA.y / 2.5) * a4

			ShowEntity PIVOT_STARMAP_RASTER
			
		Else
		
			HideEntity PIVOT_STARMAP_RASTER
					
		End If
		
		' show/hide galaxy mesh
		If FLAG.Get("GALAXY") Then ShowEntity STARMAP_MILKYWAY Else HideEntity STARMAP_MILKYWAY

		' show/hide galaxy detail mesh
		If FLAG.Get("GALAXYDETAIL") Then ShowEntity STARMAP_MILKYWAYDETAIL Else HideEntity STARMAP_MILKYWAYDETAIL

		
						
	End Method
	


	' --------------------------------------------------------------------------------------------
	' METHOD: Create sun texture with different color gradients
	' --------------------------------------------------------------------------------------------
	Method _CreateStarmapTextures()

		Local path:String = "textures/Starmap/"
	
		Local file_star:String = "sunstrip.tga"
		Local file_nebula:String = "nebulacolor.tga"
		Local file_starstrip:String = "starstrip.tga"

		Local rgb:Int
		Local c:Int, a:Int
		Local red:Int, green:Int, blue:Int
		Local x:Int, y:Int
		Local xx:Int, yy:Int
	
		Local sunpixmap:TPixmap
		Local starpixmap:TPixmap
		Local nebulapixmap:TPixmap

		Local star:TPixmap, sun:TPixmap, giant:TPixmap
		Local width:Int, height:Int
		
		Local g:TGradient
		
		' skip creation if starstrip file already exists
		If FileType(path + file_starstrip) Then
		
			starpixmap = LoadPixmap(path + file_starstrip)
			
		Else
		
			star = MEDIA.GetPixmap("STARMAP_STAR")
			width = star.width
			height = star.height
			
			starpixmap = CreatePixmap(width * 8, height, PF_RGBA8888)

			g = New TGradient
				
			For x = 0 To 7
				
				g.Generate(class[x] + "S")
				
				For xx = 0 To width - 1
	
					For yy = 0 To height - 1
						
						rgb = ReadPixel(star, xx, yy)
													
						c = GetR(rgb)
							
						a = GetA(rgb)
						red = g.R[c]
						green = g.g[c]
						blue = g.B[c]
					
						rgb = CombineARGB(a, red, green, blue)
					
						WritePixel(starpixmap, xx + (x * width), yy, rgb)
						
					Next
						
				Next
					
			Next
			
			' save stars texture to disk
			SavePixmapTGA(starpixmap, path + file_starstrip)

		EndIf
	
		' skip creation if sunstrip file already exists
		If FileType(path + file_star) Then
		
			sunpixmap = LoadPixmap(path + file_star)
			
		Else
		
			sun = MEDIA.GetPixmap("STARMAP_STARBODY")
			giant = MEDIA.GetPixmap("STARMAP_STARGIANT")
		
			width = sun.width
			height = sun.height
			
			sunpixmap = CreatePixmap(width * 8, height * 2, PF_RGBA8888)
	
			g = New TGradient
				
			For y = 0 To 1
				
				For x = 0 To 7
				
					g.Generate(class[x])
					
					For xx = 0 To width - 1
	
						For yy = 0 To height - 1
						
							If y = 0 Then rgb = ReadPixel(sun, xx, yy)
							If y = 1 Then rgb = ReadPixel(giant, xx, yy)
													
							c = GetR(rgb)
							
							a = GetA(rgb)
							red = g.R[c]
							green = g.g[c]
							blue = g.B[c]
					
							rgb = CombineARGB(a, red, green, blue)
					
							WritePixel(sunpixmap, xx + (x * width), yy + (y * height), rgb)
						
						Next
						
					Next
					
				Next
			
			Next
			
			' save stars texture to disk
			SavePixmapTGA(sunpixmap, path + file_star)
				
		EndIf
		
		nebulapixmap = CreatePixmap(32, 32, PF_RGBA8888)
		rgb = CombineARGB(NebulaRadar[0], NebulaRadar[1], NebulaRadar[2], NebulaRadar[3])
		
		For x = 0 To 31
		
			For y = 0 To 31
			
				WritePixel nebulapixmap, x, y, rgb
				
			Next
			
		Next
		
		' save stars texture to disk
		SavePixmapTGA(nebulapixmap, path + file_nebula, 0)
							
		' load textures
		MEDIA.Add("X", "STARMAP_NEBULACOLOR", "", 2 + 8 + 16 + 32, nebulapixmap)
		MEDIA.add("X", "STARMAP_SUNSTRIP", "", 2 + 8 + 16 + 32, sunpixmap)
		MEDIA.add("X", "STARMAP_STARSTRIP", "", 2 + 8 + 16 + 32, starpixmap)
	
	End Method	

	
	
	' --------------------------------------------------------------------------------------------
	' Show Starmap
	' --------------------------------------------------------------------------------------------
	Method _Show()
	
		ShowEntity PIVOT_STARMAP
	
	End Method



	' --------------------------------------------------------------------------------------------
	' Hide Starmap
	' --------------------------------------------------------------------------------------------
	Method _Hide()
	
		HideEntity PIVOT_STARMAP
	
	End Method
	


	' --------------------------------------------------------------------------------------------
	' METHOD: Things to do AFTER Renderworld
	' --------------------------------------------------------------------------------------------
	Method _GUI()
	
		Local i:String, p:String
		Local dx:Int, dy:Int
		
		Local active:Int, hide:Int
		
		Local s:TQuad
			
		INFO.add("Starmap Module")
		INFO.add("FPS/Avg/Drops.: " + FPS.FPS + "/" + FPS.averagefps + "/" + FPS.framedrops,10)
		INFO.add("Distance......: " + Roundint(CAMERA.y) + " Light Years")
		INFO.Add("Galaxy Sector.: " + sectorx + "," + sectory)
		INFO.Add("Sector Density: " + sectordensity)
		
		If CAMERA.y < 2 Then
		
			For Local i:Int = 0 To STARMAP_PLANETS - 1
			
				Local x:Float = EntityX(STARMAP_PLANET[i], 1)
				Local y:Float = EntityY(STARMAP_PLANET[i], 1)
				Local z:Float = EntityZ(STARMAP_PLANET[i], 1)
			
				CameraProject CAMERA.cam, x, y, z
				'DrawText (i + 1), ProjectedX() - 4, ProjectedY() - 8
		
			
			Next
		
		EndIf

		'DrawRect 0, 120, (SCREEN_WIDTH / 2.0) / 10.0, 10
		'DrawText "<" + Round(CAMERA.Y / 10.0, 1) + "LJ>", 0, 130
		
		If FLAG.Get("STARINFO") Then
		
			For s:TQuad = EachIn TQuad.List
			
					If s.hidden = 0 Then active:+1
					If s.hidden = 1 Then hide:+1
	
					' screen check dimensions
					dx = SCREEN_WIDTH * 0.125
					dy = SCREEN_HEIGHT * 0.125
											
					' if object lies within frustum
					If (s.sx > - dx And s.sx < SCREEN_WIDTH + dx And s.sy >= - dy And s.sy < SCREEN_HEIGHT + dy) Then
									
						SetColor 0, 255, 0
						If s.dwarf = 1 Then SetColor 255, 0, 0
						
						If s.category = "Star" Then
						
							i = "[" + s.starclass + "]"
							
							If s.giant = 1 Then i:+" [Giant]"
							If s.dwarf = 1 Then i:+" [Dwarf]"
							
							i:+" [" + s.id + "]"
														
							p = Right(s.id, 1)
							
							If p = "0" Then DrawText i, s.sx - TextWidth(i) - s.scalex, s.sy - (TextHeight(i) * 2.0)
							If p = "1" Then DrawText i, s.sx + s.scalex, s.sy - (TextHeight(i) * 2.0)
						EndIf
						
					EndIf
			
			Next

		EndIf
				
	End Method

	
		
End Type