Lua pioneers

All about writing scripts for Celestia in Lua and the .cel system
Topic author
adamnieman
Posts: 42
Joined: 20.10.2003
With us: 21 years 3 months
Location: Bristol, United Kingdom

Lua pioneers

Post #1by adamnieman » 19.12.2003, 13:41

I have seen the future. The future is Lua :D. It's a lovely, intuitive scripting language that complements Celestia very well. Even I (by no means an expert programmer) could get the hang of it pretty quickly.

I know that Lua isn't fully implemented even in the latest pre-release but I thought it worth sharing my first scripts and some links to documentation in case there are any other pioneers out there.

Note, however, that you will either need to compile your own version of Celestia from the latest CVS code (which is subject to change) or wait for the official release of version 1.3.1.

Documentation Links
http://www.donandcarla.com/Celestia/ - Don G's CEL scripting guide is still the first stop.

http://www.h-schmidt.net/celestia/ - Harald Schmidt has a very useful summary of Lua-support in Celestia (no doubt subject to change over the coming weeks) and some sample scripts that demonstrate the power and simplicity of the language.

http://www.lua.org/docs.html - documentation for the Lua language can be found here. The manual and the book are both very useful.

A couple of sample scripts
I should explain that Lua scripts are an integral part of a project I am working on (called Welcome to the Neighbourhood) that has Celestia at its heart. I have been working with a programmer (known on these forums as alexibu) to extend the implementation of Lua in Celestia to serve our own needs. Alex has, for instance, allowed multiple views (split screens) to be controlled from a single script and added the ability to turn orbits and labels on and off individually. Hopefully, these changes will make it into the next official release of Celestia, or the one following that.

Below are two scripts. The second has Welcome to the Neighbourhood (WTTN) extensions. The first one doesn't (and so should run with the latest version of CVS code).


Code: Select all

      --
      -- Script to visit a target object via a refernce object (e.g. Earth)
      -- This script is based on one designed for Welcome to the Neighbourhood. All the new classes added for WTTN have been removed (which is why this isn't a very exciting script :)
      -- By Adam Nieman, Dec 2003 (http://www.adamnieman.co.uk/neighbourhood)
      -- You are free to use, copy, modify, redistribute or do whatever you want with this script. :-)
      --
     
     
      local refobject = celestia:find("Sol/Earth")  -- refernce object
      local myobject = celestia:find("Sol/Neptune") -- target object
     

      --
      -- Part 0: Set up display
      --
     
     
      celestia:settimescale(1)
     
      -- show/hide syntax: celestia:show("renderflag1","renderflag2", etc)
      -- show/hide renderflags: orbits, cloudmaps, constellations, galaxies, planets, stars, nightmaps, eclipseshadows, ringshadows, comettails, boundaries, markers, automagm, atmospheres, grid
     
      celestia:show("cloudmaps", "galaxies", "planets", "stars", "nightmaps", "eclipseshadows", "ringshadows", "comettails", "atmospheres")
      celestia:hide("markers", "grid", "constellations", "boundaries", "orbits")
     
      -- showlabel/hidelabel syntax: celestia:showlabel("labelflag1", "labelflag2", etc)
      -- showlabel/hidelabel labelflags: planets, moons, spacecraft, asteroids, comets, constellations, stars, galaxies
     
      celestia:showlabel("planets")
      celestia:hidelabel("moons")
     
     
      -- Make an observer
     
      obs1 = celestia:getobserver()

     

 
      --
      -- Part 1, go to reference object
      --
     

      -- For consistency, we go approach the reference object from the target object rather than where ever the observer happens to be (that is, we go to the target object first)
     

      obs1:goto(myobject, 0)     
      while (obs1:travelling()) do
        wait(0)
      end

     

      obs1:goto(refobject, 0)
     
      while (obs1:travelling()) do
        wait(0)
      end
     

     
     
     
      --
      -- Part 2, go to target object
      --
     
     

      celestia:select(myobject)
      local sel = celestia:getselection()
     
     
      -- Make flight time proportional to distance
      local p0 = sel:getposition()
      local p1 = obs1:getposition()
      local km = p0:distanceto(p1)

     
      local c = 299792.458 -- speed of light (km/s)
      local warp = 500 -- warp factor
     
      local flighttime = km/(c*warp)
     
      local flighttimedisplay = flighttime
     
     
     
      -- Make flighttime neater for display (I should really round the number up but that seems like too much of a faff at the moment)
 
      if flighttime >1
      then
         flighttimedisplay = string.sub(flighttime, 1, 4)
      else
         flighttimedisplay = string.sub(flighttime, 1, 6)
      end
     
     
      celestia:print("flight time to " .. myobject:name() .. " = " .. flighttimedisplay .. " seconds at " .. warp .." times the speed of light", 15)
     


     
      -- goto reference object
     
      obs1:follow(myobject)
      obs1:goto(myobject, flighttime) -- WTTN
       
     
      while (obs1:travelling()) do
   wait(0)
      end
         
      celestia:hidelabel("planets")
     

     
     
     



     
      -- To do: orient the view of the target object so that it corresponds to the orientation that would be seen from a particular point on Earth.
      -- (That is, I want the view of the Moon, say, to be the right way up relative to the view somebody has at a particular location on Earth or, as another example, I want the view of the Earth as seen from the direction of the Moon to be oriented such that it corresponds to the view from the Apollo 11 landing site, or something :)


And now a script with WTTN extensions (to show the kind of functionality they add)

Code: Select all

      --
      -- Script to split the screen and display two objects: a refernce object (e.g. Earth) and a target object
      -- View 1: the reference object viewed from a fixed distance in the direction of the target object
      -- View 2: the target object viewed from the same distance in the direction of the reference object
      -- The script uses several classes that, at the time of writing, work only in a version of Celestia written for Welcome to the Neighbourhood
      -- By Adam Nieman, Dec 2003 (http://www.adamnieman.co.uk/neighbourhood)
      -- You are free to use, copy, modify, redistribute or do whatever you want with this script. :-)
      --
     
     
      local refobject = celestia:find("Sol/Earth")  -- refernce object
      local myobject = celestia:find("Sol/Neptune") -- target object
     

      --
      -- Part 0: Set up display
      --
     
      celestia:singleview() -- WTTN
      celestia:settimescale(1)
     
      -- show/hide syntax: celestia:show("renderflag1","renderflag2", etc)
      -- show/hide renderflags: orbits, cloudmaps, constellations, galaxies, planets, stars, nightmaps, eclipseshadows, ringshadows, comettails, boundaries, markers, automagm, atmospheres, grid
     
      celestia:show("cloudmaps", "galaxies", "planets", "stars", "nightmaps", "eclipseshadows", "ringshadows", "comettails", "atmospheres")
      celestia:hide("markers", "grid", "constellations", "boundaries", "orbits")
     
      -- showlabel/hidelabel syntax: celestia:showlabel("labelflag1", "labelflag2", etc)
      -- showlabel/hidelabel labelflags: planets, moons, spacecraft, asteroids, comets, constellations, stars, galaxies
     
      celestia:showlabel("planets")
      celestia:hidelabel("moons")
     
      -- Clear any specific labels still turned on
      -- (Specific labels/orbits only work in Celestia for WTTN at the time of writing this script)
   
      celestia:clearallspecificlabels() -- WTTN
      celestia:clearallspecificorbits() -- WTTN
     
      -- Turn on the reference object's label
     
      refobject:showlabel(refobject) -- WTTN
     
     
      -- Split view and make two observers (at the time of writing, splitview() only works in Celestia for WTTN)
      -- splitview() syntax: splitview("vertical") or splitview("horizontal") (default: verical)
     
      celestia:splitview("vertical") -- WTTN
      obs0 = celestia:getobserver(0)
      obs1 = celestia:getobserver(1)
     
      -- Set field of view (at the time of writing, setfov([angle in radians]) only works in Celestia for WTTN)
     
      obs0:setfov(math.rad(45)) -- WTTN
      obs1:setfov(math.rad(45)) -- WTTN
     
     
      -- Set up standard distance to view objects from (with a FOV of 45degs, 18378 km is a good distance for objects smaller than Earth as it places us 12000 km above the surface of Earth and Earth fills the screen nicely)
     
      if myobject:radius() < 6400
      then standarddistance = 18378 -- good distance for terrestrial planets
      elseif myobject:radius() < 72000
      then standarddistance = 206378 -- good distance for gas giants
      else standarddistance = 2006378 -- good distance for the Sun
      end
     
     
     
      --
      -- Part 1, go to reference object
      --
     

      -- For consistency, we go approach the reference object from the target object rather than where ever the observer happens to be (that is, we go to the target object first)
     
      obs0:goto(myobject, 0)
      obs1:goto(myobject, 0)     
      while (obs0:travelling() or obs1:travelling()) do
        wait(0)
      end

     
      -- gotowithdistance syntax: observer:gotowithdistance(target,time,distance(km) from centre of object)     
      -- (At the time of writing, gotowithdistance works only in Celestia for WTTN)
     
      obs0:gotowithdistance(refobject, 0, standarddistance)
      obs1:gotowithdistance(refobject, 0, standarddistance)
     
      while (obs0:travelling() or obs1:travelling()) do
        wait(0)
      end
     
      obs0:follow(refobject)
     
     
     
      --
      -- Part 2, go to target object
      --
     
     

      celestia:select(myobject)
      local sel = celestia:getselection()
     
     
      -- Make flight time proportional to distance
      local p0 = sel:getposition()
      local p1 = obs1:getposition()
      local km = p0:distanceto(p1)

     
      local c = 299792.458 -- speed of light (km/s)
      local warp = 500 -- warp factor
     
      local flighttime = km/(c*warp)
     
      local flighttimedisplay = flighttime
     
     
     
      -- Make flighttime neater for display
 
      if flighttime >1
      then
         flighttimedisplay = string.sub(flighttime, 1, 4)
      else
         flighttimedisplay = string.sub(flighttime, 1, 6)
      end
     
     
      celestia:print("flight time to " .. myobject:name() .. " = " .. flighttimedisplay .. " seconds at " .. warp .." times the speed of light", 15)
     

      -- Show labels and orbits of target object's moons unless the object is a star
     
      if myobject:type() ~= "star"
     
      then          
        local i, v
   celestia:select(myobject)
   local children = myobject:getchildren()
   for i, v in ipairs(children) do
      v:showlabel(v)
      v:showorbit(v)
      
   end
       end
     
     
      -- goto reference object
     
      obs1:follow(myobject)
      obs1:gotowithdistance(myobject, flighttime, standarddistance) -- WTTN
       
     
      while (obs1:travelling()) do
   wait(0)
      end
         
      celestia:hidelabel("planets")
     
      if myobject:type() ~= "star"
      then myobject:showlabel()
      end
     
     
     



     
      -- To do: orient the view of the target object so that it corresponds to the orientation that would be seen from a particular point on Earth.
      -- (That is, I want the view of the Moon, say, to be the right way up relative to the view somebody has at a particular location on Earth or, as another example, I want the view of the Earth as seen from the direction of the Moon to be oriented such that it corresponds to the view from the Apollo 11 landing site, or something :)
     

don
Posts: 1709
Joined: 12.07.2003
With us: 21 years 6 months
Location: Colorado, USA (7000 ft)

Post #2by don » 21.12.2003, 07:40

Howdy Adam,

Thanks for posting your sample scripts.

I have not built CVS with Lua yet, so I'll have to wait until final is out to try them. I am looking forward to both, final and trying out your scripts. Been real busy with holiday stuff lately.

Happy Holidays!

-Don G.


Return to “Scripting”