scriptrotation.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:7k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // scriptrotation.cpp
  2. // 
  3. // Copyright (C) 2006, Chris Laurel <claurel@shatters.net>
  4. //
  5. // Interface for a Celestia rotation model implemented via a Lua script.
  6. //
  7. // This program is free software; you can redistribute it and/or
  8. // modify it under the terms of the GNU General Public License
  9. // as published by the Free Software Foundation; either version 2
  10. // of the License, or (at your option) any later version.
  11. #include <cstdio>
  12. #include <cassert>
  13. #include "scriptobject.h"
  14. #include "scriptrotation.h"
  15. using namespace std;
  16. ScriptedRotation::ScriptedRotation() :
  17.     luaState(NULL),
  18.     period(0.0),
  19.     validRangeBegin(0.0),
  20.     validRangeEnd(0.0),
  21.     lastTime(-1.0e50),
  22.     lastOrientation(1.0),
  23.     cacheable(true) // non-cacheable rotations not yet supported
  24. {
  25. }
  26. ScriptedRotation::~ScriptedRotation()
  27. {
  28. }
  29. /*! Initialize the script rotation
  30.  *  moduleName is the name of a module that contains the rotation factory
  31.  *  function. The module will be loaded with Lua's require function before
  32.  *  creating the Lua rotation object.
  33.  *
  34.  *  funcName is the name of some factory function in the specified luaState
  35.  *  that will produce a Lua rotation object from the parameter list.
  36.  *
  37.  *  The Lua factory function accepts a single table parameter containg
  38.  *  all the rotation properties. It returns a table with the following
  39.  *  properties:
  40.  *
  41.  *      period - A number giving the period of the rotation. If not present,
  42.  *         the rotation is assumed to be aperiodic.
  43.  *      beginDate, endDate - optional values that specify the time span over
  44.  *         which the rotation model is valid. If not given, the rotation model
  45.  *         is assumed to be valid over all time. The rotation model is invalid
  46.  *         if end < begin.
  47.  *      orientation(time) - The orientation function takes a time value as
  48.  *         input (TDB Julian day) and returns three values which are the the
  49.  *         quaternion (w, x, y, z).
  50.  */
  51. bool
  52. ScriptedRotation::initialize(const std::string& moduleName,
  53.                              const std::string& funcName,
  54.                              Hash* parameters)
  55. {
  56.     if (parameters == NULL)
  57.         return false;
  58.     luaState = GetScriptedObjectContext();
  59.     if (luaState == NULL)
  60.     {
  61.         clog << "ScriptedRotations are currently disabled.n";
  62.         return false;
  63.     }
  64.     if (!moduleName.empty())
  65.     {
  66.         lua_pushstring(luaState, "require");
  67.         lua_gettable(luaState, LUA_GLOBALSINDEX);
  68.         if (!lua_isfunction(luaState, -1))
  69.         {
  70.             clog << "Cannot load ScriptedRotation package: 'require' function is unavailablen";
  71.             lua_pop(luaState, 1);
  72.             return false;
  73.         }
  74.         lua_pushstring(luaState, moduleName.c_str());
  75.         if (lua_pcall(luaState, 1, 1, 0) != 0)
  76.         {
  77.             clog << "Failed to load module for ScriptedRotation: " << lua_tostring(luaState, -1) << "n";
  78.             lua_pop(luaState, 1);
  79.             return false;
  80.         }
  81.     }
  82.     // Get the rotation generator function
  83.     lua_pushstring(luaState, funcName.c_str());
  84.     lua_gettable(luaState, LUA_GLOBALSINDEX);
  85.     if (lua_isfunction(luaState, -1) == 0)
  86.     {
  87.         // No function with the requested name; pop whatever value we 
  88.         // did receive along with the table of arguments.
  89.         lua_pop(luaState, 1);
  90.         clog << "No Lua function named " << funcName << " found.n";
  91.         return false;
  92.     }
  93.     // Construct the table that we'll pass to the rotation generator function
  94.     lua_newtable(luaState);
  95.     SetLuaVariables(luaState, parameters);
  96.     // Call the generator function
  97.     if (lua_pcall(luaState, 1, 1, 0) != 0)
  98.     {
  99.         // Some sort of error occurred--the error message is atop the stack
  100.         clog << "Error calling ScriptedRotation generator function: " <<
  101.             lua_tostring(luaState, -1) << "n";
  102.         lua_pop(luaState, 1);
  103.         return false;
  104.     }
  105.     if (lua_istable(luaState, -1) == 0)
  106.     {
  107.         // We have an object, but it's not a table. Pop it off the
  108.         // stack and report failure.
  109.         clog << "ScriptedRotation generator function returned bad value.n";
  110.         lua_pop(luaState, 1);
  111.         return false;
  112.     }
  113.     luaRotationObjectName = GenerateScriptObjectName();
  114.     // Attach the name to the script rotation
  115.     lua_pushstring(luaState, luaRotationObjectName.c_str());
  116.     lua_pushvalue(luaState, -2); // dup the rotation object on top of stack
  117.     lua_settable(luaState, LUA_GLOBALSINDEX);
  118.     // Get the rest of the rotation parameters; they are all optional.
  119.     period          = SafeGetLuaNumber(luaState, -1, "period", 0.0);
  120.     validRangeBegin = SafeGetLuaNumber(luaState, -1, "beginDate", 0.0);
  121.     validRangeEnd   = SafeGetLuaNumber(luaState, -1, "endDate", 0.0);
  122.     // Pop the rotations object off the stack
  123.     lua_pop(luaState, 1);
  124.     // Perform some sanity checks on the rotation parameters
  125.     if (validRangeEnd < validRangeBegin)
  126.     {
  127.         clog << "Bad script rotation: valid range end < beginn";
  128.         return false;
  129.     }
  130.     return true;
  131. }
  132. // Call the position method of the ScriptedRotation object
  133. Quatd
  134. ScriptedRotation::spin(double tjd) const
  135. {
  136.     if (tjd != lastTime || !cacheable)
  137.     {
  138.         lua_pushstring(luaState, luaRotationObjectName.c_str());
  139.         lua_gettable(luaState, LUA_GLOBALSINDEX);
  140.         if (lua_istable(luaState, -1))
  141.         {
  142.             lua_pushstring(luaState, "orientation");
  143.             lua_gettable(luaState, -2);
  144.             if (lua_isfunction(luaState, -1))
  145.             {
  146.                 lua_pushvalue(luaState, -2); // push 'self' on stack
  147.                 lua_pushnumber(luaState, tjd);
  148.                 if (lua_pcall(luaState, 2, 4, 0) == 0)
  149.                 {
  150.                     lastOrientation.w = lua_tonumber(luaState, -4);
  151.                     lastOrientation.x = lua_tonumber(luaState, -3);
  152.                     lastOrientation.y = lua_tonumber(luaState, -2);
  153.                     lastOrientation.z = lua_tonumber(luaState, -1);
  154.                     lua_pop(luaState, 4);
  155.                     lastTime = tjd;
  156.                 }
  157.                 else
  158.                 {
  159.                     // Function call failed for some reason
  160.                     //clog << "ScriptedRotation failed: " << lua_tostring(luaState, -1) << "n";
  161.                     lua_pop(luaState, 1);
  162.                 }
  163.             }
  164.             else
  165.             {
  166.                 // Bad orientation function
  167.                 lua_pop(luaState, 1);
  168.             }
  169.         }
  170.         else
  171.         {
  172.             // The script rotation object disappeared. OOPS.
  173.         }
  174.     
  175.         // Pop the script rotation object
  176.         lua_pop(luaState, 1);
  177.     }
  178.     return lastOrientation;
  179. }
  180. double
  181. ScriptedRotation::getPeriod() const
  182. {
  183.     if (period == 0.0)
  184.     {
  185.         return validRangeEnd - validRangeBegin;
  186.     }
  187.     else
  188.     {
  189.         return period;
  190.     }
  191. }
  192. bool
  193. ScriptedRotation::isPeriodic() const
  194. {
  195.     return period != 0.0;
  196. }
  197. void
  198. ScriptedRotation::getValidRange(double& begin, double& end) const
  199. {
  200.     begin = validRangeBegin;
  201.     end = validRangeEnd;
  202. }