Here's the engine:
;3D Space Engine
;Copyright (C) 2005 John Judnich
;Globals
Type Engine
Field Camera
Field PlanetLOD#,PlanetLODTransition#
End Type
Global Engine.Engine=New Engine
Type Planet
Field X#,Y#,Z#
Field XR#,YR#,ZR#
Field Xv#,Yv#,Zv#
Field XRv#,YRv#,ZRv#
Field AtmosphereRadius#
Field AtmosphereDensity#
Field AtmosphereR,AtmosphereG,AtmosphereB
Field GravityPull#,Radius#
Field GlowOffset#,GlowScale#,CloudRadius#
Field Pivot
Field LowMesh,HighMesh ;Two levels of detail for the planet
Field GlowMesh,AtmosphereMesh ;Two meshes used for atmosphere effects
Field CloudMesh
Field GlowTexture,CloudTexture
Field CXRv#,CYRv#,CZRv# ;Cloud angular velocities
Field LightSource
Field TextureMap,DetailMap
End Type
;This initializes the engine
Function EngineInit()
End Function
;This sets the camera used for LOD effects, and other effects requiring camera orientation data
Function EngineCamera(camera)
Engine\Camera=camera
End Function
;This sets the distance to switch between planet LOD levels
Function EnginePlanetLOD(lodrange#,lodtransition#)
Engine\PlanetLOD=lodrange
Engine\PlanetLODTransition=lodtransition
End Function
;This creates a planet with the radius of Radius# and a mass of Mass#. GlowTexture will be used for atmosphere glows
Function PlanetCreate(Radius#,GravityPull#,GlowTexture$="Media\PlanetGlow.bmp",CloudTexture$="Media\Clouds.bmp")
this.Planet=New Planet
this\Radius=Radius
this\GravityPull=GravityPull
this\AtmosphereDensity=1
;Create planet
this\Pivot=CreatePivot()
this\LowMesh=CreateSphere(24,this\Pivot)
this\HighMesh=CreateSphere(96,this\Pivot)
;this\HighMesh=CreateCube(this\Pivot)
HideEntity this\HighMesh
EntityBlend this\HighMesh,1
ScaleEntity this\Pivot,this\Radius,this\Radius,this\Radius
;Create glow
this\GlowTexture=LoadTexture(GlowTexture,1+2)
this\GlowMesh=CreateMesh(this\Pivot)
surf=CreateSurface(this\GlowMesh)
v1=AddVertex(surf,-1,-1,0,0,0)
v2=AddVertex(surf,1,-1,0,1,0)
v3=AddVertex(surf,1,1,0,1,1)
v4=AddVertex(surf,-1,1,0,0,1)
AddTriangle(surf,v1,v2,v3)
AddTriangle(surf,v1,v3,v4)
EntityTexture this\GlowMesh,this\GlowTexture
EntityBlend this\GlowMesh,3 ;1=Alpha 2=Multiply 3=Add
EntityFX this\GlowMesh,1
;Create atmosphere
this\AtmosphereMesh=CreateSphere(16,this\Pivot)
;ScaleMesh this\AtmosphereMesh,-1,-1,-1
ScaleEntity this\AtmosphereMesh,this\AtmosphereRadius,this\AtmosphereRadius,this\AtmosphereRadius
EntityFX this\AtmosphereMesh,16
EntityBlend this\AtmosphereMesh,3 ;1=Alpha 2=Multiply 3=Add
;Create cloud layer
this\CloudMesh=CreateSphere(24,this\Pivot)
this\CloudTexture=LoadTexture(CloudTexture,1+2)
ScaleTexture this\CloudTexture,.5,.5
EntityTexture this\CloudMesh,this\CloudTexture
ScaleEntity this\CloudMesh,this\CloudRadius,this\CloudRadius,this\CloudRadius
EntityFX this\CloudMesh,16
EntityBlend this\AtmosphereMesh,3
;HideEntity this\CloudMesh
Return Handle(this)
End Function
Function PlanetTexture(planet,TextureMap,DetailMap)
this.Planet=Object.Planet(planet)
this\TextureMap=TextureMap
this\DetailMap=DetailMap
EntityTexture this\LowMesh,TextureMap
EntityTexture this\HighMesh,TextureMap
EntityTexture this\HighMesh,DetailMap,0,1
End Function
;Set this to the primary light (Sun) that is illuminating the planet for correct lighting effects
Function PlanetLightsource(planet,lightsource)
this.Planet=Object.Planet(planet)
this\LightSource=lightsource
End Function
;This positions a planet
Function PlanetPosition(planet,x#,y#,z#)
this.Planet=Object.Planet(planet)
this\X=x:this\Y=y:this\Z=z
End Function
;This rotates a planet
Function PlanetRotate(planet,xr#,yr#,zr#)
this.Planet=Object.Planet(planet)
this\XR=xr:this\YR=yr:this\ZR=zr
End Function
;This sets the planet's linear velocity
Function PlanetLinearVelocity(planet,x#,y#,z#)
this.Planet=Object.Planet(planet)
this\Xv=x:this\Yv=y:this\Zv=z
End Function
;This sets the planet's angular velocity
Function PlanetAngularVelocity(planet,xr#,yr#,zr#)
this.Planet=Object.Planet(planet)
this\XRv=xr:this\YRv=yr:this\ZRv=zr
End Function
Function PlanetCloudSwirl(planet,xr#,yr#,zr#)
this.Planet=Object.Planet(planet)
this\CXRv=xr:this\CYRv=yr:this\CZRv=zr
End Function
;This adjusts various atmosphere properties. Radius is the atmosphere radius (the distance from the surface where the air will start being tinted)
;The glowscale adjusts the amount of atmospheric glow around the surface of the planet. The density sets the atmosphere density (from 0.0 to 1.0),
;with 0 being no atmosphere at all and 1 being completely dense atmosphere. glowoffset is the amount the glow will be highlighted towards the
;planet's light source.
Function PlanetAtmosphere(planet,radius#=-1,glowscale#=-1,density#=-1,glowoffset#=-1)
this.Planet=Object.Planet(planet)
If radius<>-1 Then
this\AtmosphereRadius=radius*this\Radius
ScaleEntity this\AtmosphereMesh,radius*1.2,radius*1.2,radius*1.2 ;Atmosphere mesh is scaled slightly larger so the camera is completely inside it when it starts fading in
End If
If glowscale<>-1 Then
this\GlowScale=glowscale*1.1
ScaleEntity this\GlowMesh,this\GlowScale,this\GlowScale,this\GlowScale
End If
If density<>-1 Then this\AtmosphereDensity=density
If glowoffset<>-1 Then this\GlowOffset=glowoffset
EntityAlpha this\GlowMesh,density
End Function
;This sets the color of the planet's atmosphere
Function PlanetAtmosphereColor(planet,R,G,B)
this.Planet=Object.Planet(planet)
this\AtmosphereR=R
this\AtmosphereG=G
this\AtmosphereB=B
EntityColor this\AtmosphereMesh,R,G,B
EntityColor this\GlowMesh,R,G,B
End Function
;This sets radius of the planet's cloud layer
Function PlanetCloudRadius(planet,radius#)
this.Planet=Object.Planet(planet)
this\CloudRadius=radius
ScaleEntity this\CloudMesh,this\CloudRadius,this\CloudRadius,this\CloudRadius
End Function
Function PlanetGravity(planet,gravity#)
this.Planet=Object.Planet(planet)
this\GravityPull=gravity
End Function
Function PlanetGravityGet#(planet)
this.Planet=Object.Planet(planet)
Return this\GravityPull
End Function
Function PlanetDelete(planet)
this.Planet=Object.Planet(planet)
FreeEntity this\GlowMesh
FreeEntity this\AtmosphereMesh
FreeEntity this\Pivot
FreeEntity this\HighMesh
FreeEntity this\LowMesh
FreeTexture this\CloudTexture
FreeTexture this\GlowTexture
Delete this
End Function
Function EnginePlanetsUpdate(Speed#)
cx#=EntityX(Engine\Camera,True):cy#=EntityY(Engine\Camera,True):cz#=EntityZ(Engine\Camera,True)
For this.Planet=Each Planet
;Visual effects
dist#=Sqr((this\x-cx)^2+(this\y-cy)^2+(this\z-cz)^2)
;Fade atmosphere according to depth of camera inside the atmosphere
ShowEntity this\AtmosphereMesh
alt#=(dist-this\Radius)/(this\AtmosphereRadius-this\Radius)
a#=this\AtmosphereDensity*(1-alt)
If a<0 Then a=0
EntityAlpha this\AtmosphereMesh,a
;Make the atmospheric glow face the camera, and move it towards the sun to make it look like the sun is illuminating the atmosphere
PositionEntity this\GlowMesh,0,0,0
If this\LightSource<>0 Then
PointEntity this\GlowMesh,this\LightSource
MoveEntity this\GlowMesh,0,0,this\GlowOffset
End If
PointEntity this\GlowMesh,Engine\Camera
MoveEntity this\GlowMesh,0,0,this\Radius*.3/((dist/this\Radius)-.6) ;Try to equalize the size of the halo around the earth
;Smoothly fade between high res planet and low res planet
altitude#=dist-this\Radius
If altitude<=Engine\PlanetLOD+(Engine\PlanetLODTransition*.5) And altitude>=Engine\PlanetLOD-(Engine\PlanetLODTransition*.5) Then
alpha#=altitude-(Engine\PlanetLOD-(Engine\PlanetLODTransition*.5))
alpha=1-(alpha/Engine\PlanetLODTransition)
EntityAlpha this\HighMesh,alpha
End If
If altitude<=Engine\PlanetLOD+(Engine\PlanetLODTransition*.5) Then
ShowEntity this\HighMesh
Else
HideEntity this\HighMesh
End If
If altitude>=Engine\PlanetLOD-(Engine\PlanetLODTransition*.5) Then
ShowEntity this\LowMesh
Else
EntityAlpha this\HighMesh,1
ShowEntity this\HighMesh
End If
If altitude<Engine\PlanetLOD-(Engine\PlanetLODTransition*.6) Then
HideEntity this\LowMesh
End If
;Gravity
;acceleration = gravitational_pull / distance^2 {approximation}
xv#=this\Xv:yv#=this\Yv:zv#=this\Zv
For that.Planet=Each Planet
pull#=that\GravityPull
xd#=(that\X-this\X)
yd#=(that\Y-this\Y)
zd#=(that\Z-this\Z)
dist2#=xd^2+yd^2+zd^2
If dist2<>0 Then
xv=xv+(pull*xd/dist2)*Speed
yv=yv+(pull*yd/dist2)*Speed
zv=zv+(pull*zd/dist2)*Speed
End If
Next
this\Xv=xv:this\Yv=yv:this\Zv=zv
;Cloud swirl
RotateEntity this\CloudMesh,EntityPitch(this\CloudMesh)+this\CXRv*Speed,EntityYaw(this\CloudMesh)+this\CYRv*Speed,EntityRoll(this\CloudMesh)+this\CZRv*Speed
;Movement
this\X=this\X+this\Xv*Speed:this\Y=this\Y+this\Yv*Speed:this\Z=this\Z+this\Zv*Speed
this\XR=this\XR+this\XRv*Speed:this\YR=this\YR+this\YRv*Speed:this\ZR=this\ZR+this\ZRv*Speed
;Update planet orientation
PositionEntity this\Pivot,this\X,this\Y,this\Z
RotateEntity this\Pivot,this\XR,this\YR,this\ZR
Next
End Function
You may need to put this image file where the engine can find it:

Here's some sample code so you can get the idea how the engine works.
EngineInit()
EngineCamera(cam)
EnginePlanetLOD(.3*sc,.1*sc)
planet=PlanetCreate(sc#,.001)
PlanetCloudRadius(planet,1.02)
PlanetAngularVelocity(planet,.02,.04,.01)
PlanetLightsource(planet,light)
PlanetAtmosphere(planet,1.1,1.1,.9,.06)
PlanetAtmosphereColor(planet,60,80,255)
PlanetCloudSwirl(planet,.002,.006,.004)
;tmp.Planet=Object.Planet(planet)
;EntityParent cam,tmp\Pivot
planet2=PlanetCreate(.2,0)
PlanetAtmosphere(planet2,0,0,0)
PlanetPosition(planet2,0,0,3)
PlanetLinearVelocity(planet2,.04,0,0)
tex1=LoadTexture("Media\tex0.bmp")
tex2=LoadTexture("planet\earth.tga")
tex3=LoadTexture("Media\detail.bmp")
ScaleTexture tex3,.01,.01
TextureBlend tex3,2
ScaleTexture tex1,.3,.3
;ScaleTexture tex2,.5,.5
PlanetTexture(planet,tex2,tex3)
PlanetTexture(planet2,tex1,tex3)
If you can't figure out how to get it working, I can upload a working example (2.5MB).
Hope this helps :)