Nice trajectory!

General discussion about Celestia that doesn't fit into other forums.
Topic author
dimavj
Posts: 4
Joined: 20.10.2010
With us: 14 years

Nice trajectory!

Post #1by dimavj » 14.11.2010, 22:38

Hi Guys,

I used Toti's script from MARS FLUG in the scripts section in the motherlode, to create a nice trajectory arround the earth, it was not easy in the beginning , but finally I've got it!

I ceated new camera coordinates and the text I changed by spaces (because text length's is used as a factor of time between points of the trajectory).

Hope you like.

A.


Code: Select all

--This is a modified version of MarsFlug.celx for a nice trajectory over the Earth. by dimaVJ.
--Thanks Toti and Celestia team!
--I changed only the coordinates, and the text by spaces. and the selected object (Earth obviously)

--***************************************************************************
-- Rundflug ?ber den Mars (MarsFlug.celx)
--
-- Lauff?hig ab Celestia 1.3.2
-- Laufzeit: etwa 7 Minuten
--
--***************************************************************************
--          An non-uniform B-Spline approximation algorithm
--            Applied to Mars touring
--
--               Coded by Toti
--               Translated by Adirondack, 23. August 2004 (v1.0) 
--         
--***************************************************************************
--***************************************************************************

--***************************************************************************
--               Constants
--***************************************************************************
DELAY      = 5
SEC_LETTER   = 0.1               -- user takes this time to read a single letter (increase if you find the text's
                     -- speed too fast)

KM_MLY   = 9466411.842
KM_AU      = 149597870.7

BODY      = "Sol/Earth"

ZERO      = celestia:newposition (0, 0, 0)
OBS      = celestia:getobserver()

ORDER      = 3                  -- order of the curve. Increase for additional smoothness
                       
IM_WIDTH   = 1000               -- texture dimensions used as input for the Control Points
IM_HEIGHT   = 500   

-- control points, given as:
--   1] flight path (x,y) as pixel positions in BODY's texture map; z as altitude (a BODY's radius multiplier)
--   2] lookat positions (x,y) as pixel positions in BODY's texture map; z as altitude (a BODY's radius multiplier)
--   3] info field (with descriptive text):

FEATURES   = {   
              {   450,   220,   8,    260,   80,     0.2,    "                                                                                                                        "},
               {   130,   100,   1.6,    180,   120,     1.1,    "                                                                                                                                       "},
              { 900,   190,   1.5,      0,   160,     1,    "                                                                                                                   "} ,
              { 700,   290,   2,      900,   260,     1,    "                                                                                                                  "},
            { 650,   290,   8,      700,   200,     1,    "                                                                                                                                     "}  ,
            { 630,   250,   18,      600,   190,     1,    "                                                                                                                                                  "} 
            
            
             }


-- *********************************************************
--            Touring functions
-- *********************************************************
function buildControlPts (L, bRad, oAmb)
-- builds a table of UCS control points where the flightpath & 'look at' positions will pass through
   local size   = table.getn (L)
   local P   = {}
   local i
   for i = 1, size do
      -- adapt to Celestia's Prime Meridian conventions:
      local long   = ( L[i][1] / IM_WIDTH * 360 ) - 180
      local lat   = 90 - ( L[i][2] / IM_HEIGHT * 180 )
      local r   = bRad * L[i][3]
      local pos   = sphe2cart (r, long, lat)

      long   = ( L[i][4] / IM_WIDTH * 360 ) - 180
      lat   = 90 - ( L[i][5] / IM_HEIGHT * 180 )
      r   = bRad * L[i][6]
      local view   = sphe2cart (r, long, lat)

      -- include ambient light curve directly in the BSpline (this is done so all features are shown, including those
      -- in the planet's dark side:
      if i==1 or i==size then   
         P[i]   = {pos.x, pos.y, pos.z, view.x, view.y, view.z, i, oldAmb}       
      else
         P[i]   = {pos.x, pos.y, pos.z, view.x, view.y, view.z, i, oldAmb}
      end
   end
   -- add a blank point so there is room at the end of the fitting scheme (so next-to-last point shows up):
   L[size+1]   = {L[size][1], L[size][2], L[size][3], L[size][4], L[size][5], L[size][6], ""}
   P[size+1]   = {P[size][1], P[size][2], P[size][3], P[size][4], P[size][5], P[size][6], size+1, oAmb}
   return P
end

-- *********************************************************
--            B-Spline functions
-- *********************************************************
function getDuration (L, size)
-- returns total time of the tour, based on info field in table L
   local j
   local length   = 0
   for j = 1, size do
      length   = length + string.len ( L[j][7] )
   end
   return (length * SEC_LETTER)
end

function buildKnots (L, ord, size, dur)
-- builds a table of non-uniform knots as a function of L info field length
   local j
   local K   = {}
   local kn   = size + ord

   local plength    = 0
   for j = 1, kn do
      if j <= ord then
         K[j]   = 0
      elseif j > size then
         K[j]   =  dur+1
      else
         plength   = plength + string.len( L[j-ord][7] )
         K[j]      = plength * SEC_LETTER
      end
   end
   return K
end

function N (K, i, ord, curr)
-- returns the blending factor for 'curr' position along the curve, using 'K' as knot vector. Uses recursion
   local blend
   if ord == 1 then                              -- definition 1st case
      if K[i] <= curr and curr < K[i+1] then
         blend   = 1
      else
         blend   = 0
      end
   else
      local k1   = i+ord-1
      local k2   = i+ord
      if  K[k1] == K[i] and K[k2] == K[i+1] then            -- be careful with 'division by zero' errors at the extremes
         blend   = 0
      elseif K[k1] == K[i] then
         blend   = (K[k2] - curr)  / (K[k2] - K[i+1]) * N(K, i+1, ord-1, curr)
      elseif K[k2] == K[i+1] then
         blend   = (curr - K[i]) / (K[k1] - K[i]) * N(K, i, ord-1, curr)
      else                                 -- definition 2nd case
         blend   = (curr - K[i]) / (K[k1] - K[i]) * N(K, i, ord-1, curr) + (K[k2] - curr) / (K[k2] - K[i+1]) *  N(K, i+1, ord-1, curr)
      end
   end
   return blend
end

function buildSpline (K, CP, rows, cols, ord, curr)
-- returns the B-Spline value for 'curr' knot position
   local i, j
   local S   = {}
   for j = 1, cols do
      S[j]   = 0
   end   
   for i = 1, rows do
      local w   = N(K, i, ord, curr)
      for j = 1, cols do
         S[j]   = CP[i][j] * w + S[j]
      end
   end
   return S
end

--***************************************************************************
--               Other functions
--***************************************************************************
function sphe2cart (rad, rho, phi)
-- converts from spherical to cartesian coordinates. Returns a POSITION
   local   r   = rad / KM_MLY
   local x   = - r * math.cos (math.rad (rho)) * math.cos (math.rad (phi))
   local y   = r * math.sin (math.rad (phi))
   local z   = r * math.sin (math.rad (rho)) * math.cos (math.rad (phi))
   return celestia:newposition (x,y,z)
end

function celestia_cleanup_callback()
-- restores user's preferred settings
   celestia:setambient (oldAmb)
end


--***************************************************************************
--               Main routine
--***************************************************************************
oldAmb    = celestia:getambient()

body      = celestia:find(BODY)
bodyRad   = body:radius()
bodyFrame   = celestia:newframe("planetographic", body)

TOUR      = buildControlPts (FEATURES, bodyRad, oldAmb)

celestia:select (body)

tableSize   = table.getn (TOUR)
datumSize   = table.getn (TOUR[1])

duration   = getDuration (FEATURES, tableSize)
Knots      = buildKnots (FEATURES, ORDER, tableSize, duration)

t0      = celestia:getscripttime()
t1      = 0

repeat

   pos      = buildSpline (Knots, TOUR, tableSize, datumSize, ORDER, t1)

   obsPos   = bodyFrame:from (celestia:newposition (pos[1], pos[2], pos[3]))   -- body is rotating, so UCS won't work OK
   lookAtPos   = bodyFrame:from (celestia:newposition (pos[4], pos[5], pos[6]))   -- same here
   normalVect   = obsPos-body:getposition()

   OBS:setposition (obsPos)
   OBS:lookat (lookAtPos, normalVect)

   celestia:setambient (pos[8])

   celestia:flash (string.format("%s", FEATURES[math.floor(pos[7])][7]), DELAY)

   wait()

   t1      = celestia:getscripttime() - t0   -- put this here so old computers (like mine) can run the code fine

until t1 > duration

Return to “Celestia Users”