Lua pioneers
Posted: 19.12.2003, 13:41
I have seen the future. The future is Lua . 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).
And now a script with WTTN extensions (to show the kind of functionality they add)
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 :)