Code archives/3D Graphics - Effects/Infinite Starfield / Infinite Asteroid Belt

This code has been declared by its author to be Public Domain code.

Download source code

Infinite Starfield / Infinite Asteroid Belt by Krischan2010
This creates an really infinite starfield or asteroid belt using a single surface entity. The stars are recycled when they are too far away from the camera. This can be used for 3D stars, space dust or even asteroid belts.

The main code shows the starfield which is cube-shaped in X/Y/Z dimensions while the asteroid belt is a starfield with very small Y dimensions, no recycling in Y direction and different Y random positioning. Movement with mouse/arrow keys, which is different in both demos.

Oh, and I am sure this can be improved!

Starfield


Asteroid Belt (see codebox below)


AppTitle "Infinite Starfield"

Graphics3D 800,600,32,2

Global SCALEX#		= 2.0				; starfield scale X
Global SCALEY#		= 2.0				; starfield scale Y
Global SCALEZ#		= 2.0				; starfield scale Z

Global TurnSpeed#	= 4.0				; cam turn speed
Global RollSpeed#	= 0.5				; cam roll speed
Global CameraSpeed#	= 0.01				; cam move speed

Global WIDTH%		= GraphicsWidth()	; grab screen width
Global HEIGHT%		= GraphicsHeight()	; grab screen height
Global TIMER%		= CreateTimer(60)	; timer

Type star
	
	Field col%
	Field x#,y#,z#
	
End Type

; camera
Global cam=CreateCamera()
CameraRange cam,0.01,10
PositionEntity cam,0,0,0

; starfield mesh
Global starfield=CreateMesh()
Global surf=CreateSurface(starfield)
Global star=CreateQuad()
EntityTexture starfield,CreateStarTexture()
EntityFX starfield,1+2+32
EntityBlend starfield,3

; add stars to starfield
AddStars(20000,0.001,0.005)

MoveMouse WIDTH/2,HEIGHT/2

; main loop
While Not KeyHit(1)
	
	; camera movement
	Movement(cam)
	
	; update stars
	UpdateStarfield(cam,2,1)

	RenderWorld()
	
	WaitTimer TIMER
	
	Flip 0
	
Wend

End

; create a simple star texture
Function CreateStarTexture(size%=256,flags%=3)
	
	Local tex%=CreateTexture(size,size,flags)
	Local tb%=TextureBuffer(tex)
	
	Local i#,j%,col%,rgb%
	
	SetBuffer tb
	LockBuffer tb
	
	For j=0 To 255
		
		col=255-j
		If col>255 Then col=255
		rgb=col*$1000000+col*$10000+col*$100+col
		
		For i=0 To 360 Step 0.1
			
			WritePixelFast (size/2)+(Sin(i)*(j*size/512)),(size/2)+(Cos(i)*(j*size/512)),rgb,tb
			
		Next
		
	Next
	
	UnlockBuffer tb
	SetBuffer BackBuffer()
	
	Return tex
	
End Function

; rebuild starfield mesh
Function UpdateStarfield(parent%,maxdist#=2.0,fade%=False)
	
	Local s.star,px#,py#,pz#,d#,a#
	
	ClearSurface(surf)
	
	For s.star = Each star
		
		; calc star position
		px=EntityX(parent)-s\x
		py=EntityY(parent)-s\y
		pz=EntityZ(parent)-s\z
		
		; check if star must be moved
		If px<-SCALEX Then s\x=s\x-(SCALEX*2)
		If px>+SCALEX Then s\x=s\x+(SCALEX*2)
		If py<-SCALEY Then s\y=s\y-(SCALEY*2)
		If py>+SCALEY Then s\y=s\y+(SCALEY*2)
		If pz<-SCALEZ Then s\z=s\z-(SCALEZ*2)
		If pz>+SCALEZ Then s\z=s\z+(SCALEZ*2)
		
		; reposition star
		PositionEntity star,s\x,s\y,s\z
		
		; star is visible?
		If EntityInView(star,cam) Then
			
			; get distance
			d=EntityDistance(star,cam)
			
			; check if not to far away
			If d<maxdist Then
				
				; align star to cam
				PointEntity star,cam
				
				; add alpha
				a=1.0 : If fade Then a=Normalize(d,maxdist*0.5,maxdist,1,0)
				
				; add star to starfield again
				AddToSurface(star,surf,starfield,s\col,s\col,s\col,a)
				
			EndIf
			
		EndIf
		
	Next
	
End Function

; add stars to starfield mesh
Function AddStars(amount%=1,min#=0.01,max#=0.02)
	
	Local i%,s.star,size#
	
	For i=1 To amount
		
		s.star = New star
		
		size#=Rnd(min,max)
		
		s\col=Rand(64,255)
		s\x=Rnd(-SCALEX,SCALEX)
		s\y=Rnd(-SCALEY,SCALEY)
		s\z=Rnd(-SCALEZ,SCALEZ)
		
		PositionEntity(star,s\x,s\y,s\z,1)
		ScaleEntity star,size,size,size
		AddToSurface(star,surf,starfield,255,255,255,1)
		
	Next
	
End Function

; simple spaceship freeflight
Function Movement(cam%,sensitivity#=1.0)
	
	Local roll#,cx#,cz#,tx#,ty#
	
	cx=(KeyDown(205)-KeyDown(203))*CameraSpeed
	cz=(KeyDown(200)-KeyDown(208))*CameraSpeed
	roll=(MouseDown(2)-MouseDown(1))*RollSpeed
	
	tx=Normalize(MouseX(),0,WIDTH , 1,-1)
	ty=Normalize(MouseY(),0,HEIGHT,-1, 1)
	
	If ty<0 Then ty=(Abs(ty)^sensitivity)*-1 Else ty=ty^sensitivity
	If tx<0 Then tx=(Abs(tx)^sensitivity)*-1 Else tx=tx^sensitivity
	
	TurnEntity cam,ty*TurnSpeed,tx*TurnSpeed,roll*TurnSpeed
	MoveEntity cam,cx,0,cz
	
End Function

; normalize a value
Function Normalize#(value#=128.0,value_min#=0.0,value_max#=255.0,norm_min#=0.0,norm_max#=1.0)
	
	Return ((value-value_min)/(value_max-value_min))*(norm_max-norm_min)+norm_min
	
End Function

; add a mesh to another mesh's surface
Function AddToSurface(mesh,surf,singlesurfaceentity,r%,g%,b%,a#) 
	
	Local vert%[2],vr%[2],vg%[2],vb%[2],va#[2]
	Local surface%,oldvert%,i%,i2%
	
	surface = GetSurface(mesh,1) 
	
	For i = 0 To CountTriangles(surface)-1
		
		For i2 = 0 To 2 
			
			oldvert = TriangleVertex(surface,i,i2)
			
			vr[i2]=r
			vg[i2]=g
			vb[i2]=b
			va[i2]=a
			
			TFormPoint VertexX(surface,oldvert),VertexY(surface,oldvert),VertexZ(surface,oldvert), mesh,singlesurfaceentity 
			vert[i2] = AddVertex(surf,TFormedX(),TFormedY(),TFormedZ(),VertexU(surface,oldvert),VertexV(surface,oldvert)) 
			VertexColor surf,vert[i2],r,g,b,a
			
		Next 
		
		AddTriangle(surf,vert[0],vert[1],vert[2])
		
	Next 
	
End Function

; create a quad
Function CreateQuad(r%=255,g%=255,b%=255,a#=1.0)
	
	Local mesh%,surf%,v1%,v2%,v3%,v4%
	
	mesh=CreateMesh()
	surf=CreateSurface(mesh)
	
	v1=AddVertex(surf,-1,1,0,1,0)
	v2=AddVertex(surf,1,1,0,0,0)
	v3=AddVertex(surf,-1,-1,0,1,1)
	v4=AddVertex(surf,1,-1,0,0,1)
	
	VertexColor surf,v1,r,g,b,a
	VertexColor surf,v3,r,g,b,a
	VertexColor surf,v2,r,g,b,a
	VertexColor surf,v4,r,g,b,a
	
	AddTriangle(surf,0,1,2)
	AddTriangle(surf,3,2,1)
	
	FlipMesh mesh
	
	Return mesh
	
End Function

Comments

Krischan2010
Here is an update, now you can set a density to simulate different amounts of objects, enter/leave a starfield/asteroid field or whatever. Use arrows and mouse to move, SHIFT=faster and the Mouse buttons increase/decrease the density in percent. Watch the radar to see how the density changes (only noticable while moving).

EDIT: I am not very happy with the Createquad / AddToSurface solution here, any suggestions how to improve it are welcome...




ClayPigeon2010
It MAV's when you move. I'm assuming this is probably because when you move, it tries to draw pixels outside the buffer.


Krischan2010
Interesting, never happened here. I changed the writepixel line, should work now so please test it again.


puki2010
It all works for me. All very exciting.

I found it a bit grey so I just applied 'super-lighting' which is where you nonce the lighting to 512 rather than the "Andy Pandy" 255 that most people use.


MErren2010
very cool !!


Code Archives Forum