gameFunctions.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "T3D/gameFunctions.h"
  24. #include "T3D/gameBase/gameConnection.h"
  25. #include "T3D/camera.h"
  26. #include "T3D/sfx/sfx3DWorld.h"
  27. #include "console/consoleTypes.h"
  28. #include "gui/3d/guiTSControl.h"
  29. #include "core/util/journal/process.h"
  30. #include "materials/materialManager.h"
  31. #include "math/mEase.h"
  32. #include "core/module.h"
  33. #include "console/engineAPI.h"
  34. #include "platform/output/IDisplayDevice.h"
  35. static void RegisterGameFunctions();
  36. static void Process3D();
  37. MODULE_BEGIN( 3D )
  38. MODULE_INIT_AFTER( Process )
  39. MODULE_INIT_AFTER( Scene )
  40. MODULE_SHUTDOWN_BEFORE( Process )
  41. MODULE_SHUTDOWN_BEFORE( Sim )
  42. MODULE_SHUTDOWN_AFTER( Scene )
  43. MODULE_INIT
  44. {
  45. Process::notify(Process3D, PROCESS_TIME_ORDER);
  46. GameConnection::smFovUpdate.notify(GameSetCameraFov);
  47. RegisterGameFunctions();
  48. }
  49. MODULE_SHUTDOWN
  50. {
  51. GameConnection::smFovUpdate.remove(GameSetCameraFov);
  52. Process::remove(Process3D);
  53. }
  54. MODULE_END;
  55. static S32 gEaseInOut = Ease::InOut;
  56. static S32 gEaseIn = Ease::In;
  57. static S32 gEaseOut = Ease::Out;
  58. static S32 gEaseLinear = Ease::Linear;
  59. static S32 gEaseQuadratic= Ease::Quadratic;
  60. static S32 gEaseCubic= Ease::Cubic;
  61. static S32 gEaseQuartic = Ease::Quartic;
  62. static S32 gEaseQuintic = Ease::Quintic;
  63. static S32 gEaseSinusoidal= Ease::Sinusoidal;
  64. static S32 gEaseExponential = Ease::Exponential;
  65. static S32 gEaseCircular = Ease::Circular;
  66. static S32 gEaseElastic = Ease::Elastic;
  67. static S32 gEaseBack = Ease::Back;
  68. static S32 gEaseBounce = Ease::Bounce;
  69. extern bool gEditingMission;
  70. extern void ShowInit();
  71. //------------------------------------------------------------------------------
  72. /// Camera and FOV info
  73. namespace CameraAndFOV{
  74. const U32 MaxZoomSpeed = 2000; ///< max number of ms to reach target FOV
  75. static F32 sConsoleCameraFov = 90.f; ///< updated to camera FOV each frame
  76. static F32 sDefaultFov = 90.f; ///< normal FOV
  77. static F32 sCameraFov = 90.f; ///< current camera FOV
  78. static F32 sTargetFov = 90.f; ///< the desired FOV
  79. static F32 sLastCameraUpdateTime = 0; ///< last time camera was updated
  80. static S32 sZoomSpeed = 500; ///< ms per 90deg fov change
  81. /// A scale to apply to the normal visible distance
  82. /// typically used for tuning performance.
  83. static F32 sVisDistanceScale = 1.0f;
  84. } // namespace {}
  85. // query
  86. static SimpleQueryList sgServerQueryList;
  87. static U32 sgServerQueryIndex = 0;
  88. //SERVER FUNCTIONS ONLY
  89. ConsoleFunctionGroupBegin( Containers, "Spatial query functions. <b>Server side only!</b>");
  90. DefineConsoleFunction( containerFindFirst, const char*, (U32 typeMask, Point3F origin, Point3F size), , "(int mask, Point3F point, float x, float y, float z)"
  91. "@brief Find objects matching the bitmask type within a box centered at point, with extents x, y, z.\n\n"
  92. "@returns The first object found, or an empty string if nothing was found. Thereafter, you can get more "
  93. "results using containerFindNext()."
  94. "@see containerFindNext\n"
  95. "@ingroup Game")
  96. {
  97. //find out what we're looking for
  98. //build the container volume
  99. Box3F queryBox;
  100. queryBox.minExtents = origin;
  101. queryBox.maxExtents = origin;
  102. queryBox.minExtents -= size;
  103. queryBox.maxExtents += size;
  104. //initialize the list, and do the query
  105. sgServerQueryList.mList.clear();
  106. gServerContainer.findObjects(queryBox, typeMask, SimpleQueryList::insertionCallback, &sgServerQueryList);
  107. //return the first element
  108. sgServerQueryIndex = 0;
  109. static const U32 bufSize = 100;
  110. char *buff = Con::getReturnBuffer(bufSize);
  111. if (sgServerQueryList.mList.size())
  112. dSprintf(buff, bufSize, "%d", sgServerQueryList.mList[sgServerQueryIndex++]->getId());
  113. else
  114. buff[0] = '\0';
  115. return buff;
  116. }
  117. DefineConsoleFunction( containerFindNext, const char*, (), , "()"
  118. "@brief Get more results from a previous call to containerFindFirst().\n\n"
  119. "@note You must call containerFindFirst() to begin the search.\n"
  120. "@returns The next object found, or an empty string if nothing else was found.\n"
  121. "@see containerFindFirst()\n"
  122. "@ingroup Game")
  123. {
  124. //return the next element
  125. static const U32 bufSize = 100;
  126. char *buff = Con::getReturnBuffer(bufSize);
  127. if (sgServerQueryIndex < sgServerQueryList.mList.size())
  128. dSprintf(buff, bufSize, "%d", sgServerQueryList.mList[sgServerQueryIndex++]->getId());
  129. else
  130. buff[0] = '\0';
  131. return buff;
  132. }
  133. ConsoleFunctionGroupEnd( Containers );
  134. //------------------------------------------------------------------------------
  135. bool GameGetCameraTransform(MatrixF *mat, Point3F *velocity)
  136. {
  137. // Return the position and velocity of the control object
  138. GameConnection* connection = GameConnection::getConnectionToServer();
  139. return connection && connection->getControlCameraTransform(0, mat) &&
  140. connection->getControlCameraVelocity(velocity);
  141. }
  142. //------------------------------------------------------------------------------
  143. DefineEngineFunction( setDefaultFov, void, ( F32 defaultFOV ),,
  144. "@brief Set the default FOV for a camera.\n"
  145. "@param defaultFOV The default field of view in degrees\n"
  146. "@ingroup CameraSystem")
  147. {
  148. CameraAndFOV::sDefaultFov = mClampF(defaultFOV, MinCameraFov, MaxCameraFov);
  149. if(CameraAndFOV::sCameraFov == CameraAndFOV::sTargetFov)
  150. CameraAndFOV::sTargetFov = CameraAndFOV::sDefaultFov;
  151. }
  152. DefineEngineFunction( setZoomSpeed, void, ( S32 speed ),,
  153. "@brief Set the zoom speed of the camera.\n"
  154. "This affects how quickly the camera changes from one field of view "
  155. "to another.\n"
  156. "@param speed The camera's zoom speed in ms per 90deg FOV change\n"
  157. "@ingroup CameraSystem")
  158. {
  159. CameraAndFOV::sZoomSpeed = mClamp(speed, 0, CameraAndFOV::MaxZoomSpeed);
  160. }
  161. DefineEngineFunction( setFov, void, ( F32 FOV ),,
  162. "@brief Set the FOV of the camera.\n"
  163. "@param FOV The camera's new FOV in degrees\n"
  164. "@ingroup CameraSystem")
  165. {
  166. CameraAndFOV::sTargetFov = mClampF(FOV, MinCameraFov, MaxCameraFov);
  167. }
  168. F32 GameGetCameraFov()
  169. {
  170. return(CameraAndFOV::sCameraFov);
  171. }
  172. void GameSetCameraFov(F32 fov)
  173. {
  174. CameraAndFOV::sTargetFov = CameraAndFOV::sCameraFov = fov;
  175. }
  176. void GameSetCameraTargetFov(F32 fov)
  177. {
  178. CameraAndFOV::sTargetFov = fov;
  179. }
  180. void GameUpdateCameraFov()
  181. {
  182. F32 time = F32(Platform::getVirtualMilliseconds());
  183. // need to update fov?
  184. if(CameraAndFOV::sTargetFov != CameraAndFOV::sCameraFov)
  185. {
  186. F32 delta = time - CameraAndFOV::sLastCameraUpdateTime;
  187. // snap zoom?
  188. if((CameraAndFOV::sZoomSpeed == 0) || (delta <= 0.0f))
  189. CameraAndFOV::sCameraFov = CameraAndFOV::sTargetFov;
  190. else
  191. {
  192. // gZoomSpeed is time in ms to zoom 90deg
  193. F32 step = 90.f * (delta / F32(CameraAndFOV::sZoomSpeed));
  194. if(CameraAndFOV::sCameraFov > CameraAndFOV::sTargetFov)
  195. {
  196. CameraAndFOV::sCameraFov -= step;
  197. if(CameraAndFOV::sCameraFov < CameraAndFOV::sTargetFov)
  198. CameraAndFOV::sCameraFov = CameraAndFOV::sTargetFov;
  199. }
  200. else
  201. {
  202. CameraAndFOV::sCameraFov += step;
  203. if(CameraAndFOV::sCameraFov > CameraAndFOV::sTargetFov)
  204. CameraAndFOV::sCameraFov = CameraAndFOV::sTargetFov;
  205. }
  206. }
  207. }
  208. // the game connection controls the vertical and the horizontal
  209. GameConnection * connection = GameConnection::getConnectionToServer();
  210. if(connection)
  211. {
  212. // check if fov is valid on control object
  213. if(connection->isValidControlCameraFov(CameraAndFOV::sCameraFov))
  214. connection->setControlCameraFov(CameraAndFOV::sCameraFov);
  215. else
  216. {
  217. // will set to the closest fov (fails only on invalid control object)
  218. if(connection->setControlCameraFov(CameraAndFOV::sCameraFov))
  219. {
  220. F32 setFov = CameraAndFOV::sCameraFov;
  221. connection->getControlCameraFov(&setFov);
  222. CameraAndFOV::sTargetFov =CameraAndFOV::sCameraFov = setFov;
  223. }
  224. }
  225. }
  226. // update the console variable
  227. CameraAndFOV::sConsoleCameraFov = CameraAndFOV::sCameraFov;
  228. CameraAndFOV::sLastCameraUpdateTime = time;
  229. }
  230. //--------------------------------------------------------------------------
  231. #ifdef TORQUE_DEBUG
  232. // ConsoleFunction(dumpTSShapes, void, 1, 1, "dumpTSShapes();")
  233. // {
  234. // argc, argv;
  235. // FindMatch match("*.dts", 4096);
  236. // gResourceManager->findMatches(&match);
  237. // for (U32 i = 0; i < match.numMatches(); i++)
  238. // {
  239. // U32 j;
  240. // Resource<TSShape> shape = ResourceManager::get().load(match.matchList[i]);
  241. // if (bool(shape) == false)
  242. // Con::errorf(" aaa Couldn't load: %s", match.matchList[i]);
  243. // U32 numMeshes = 0, numSkins = 0;
  244. // for (j = 0; j < shape->meshes.size(); j++)
  245. // if (shape->meshes[j])
  246. // numMeshes++;
  247. // for (j = 0; j < shape->skins.size(); j++)
  248. // if (shape->skins[j])
  249. // numSkins++;
  250. // Con::printf(" aaa Shape: %s (%d meshes, %d skins)", match.matchList[i], numMeshes, numSkins);
  251. // Con::printf(" aaa Meshes");
  252. // for (j = 0; j < shape->meshes.size(); j++)
  253. // {
  254. // if (shape->meshes[j])
  255. // Con::printf(" aaa %d -> nf: %d, nmf: %d, nvpf: %d (%d, %d, %d, %d, %d)",
  256. // shape->meshes[j]->meshType & TSMesh::TypeMask,
  257. // shape->meshes[j]->numFrames,
  258. // shape->meshes[j]->numMatFrames,
  259. // shape->meshes[j]->vertsPerFrame,
  260. // shape->meshes[j]->verts.size(),
  261. // shape->meshes[j]->norms.size(),
  262. // shape->meshes[j]->tverts.size(),
  263. // shape->meshes[j]->primitives.size(),
  264. // shape->meshes[j]->indices.size());
  265. // }
  266. // Con::printf(" aaa Skins");
  267. // for (j = 0; j < shape->skins.size(); j++)
  268. // {
  269. // if (shape->skins[j])
  270. // Con::printf(" aaa %d -> nf: %d, nmf: %d, nvpf: %d (%d, %d, %d, %d, %d)",
  271. // shape->skins[j]->meshType & TSMesh::TypeMask,
  272. // shape->skins[j]->numFrames,
  273. // shape->skins[j]->numMatFrames,
  274. // shape->skins[j]->vertsPerFrame,
  275. // shape->skins[j]->verts.size(),
  276. // shape->skins[j]->norms.size(),
  277. // shape->skins[j]->tverts.size(),
  278. // shape->skins[j]->primitives.size(),
  279. // shape->skins[j]->indices.size());
  280. // }
  281. // }
  282. // }
  283. #endif
  284. bool GameProcessCameraQuery(CameraQuery *query)
  285. {
  286. GameConnection* connection = GameConnection::getConnectionToServer();
  287. if (connection && connection->getControlCameraTransform(0.032f, &query->cameraMatrix))
  288. {
  289. query->object = dynamic_cast<ShapeBase*>(connection->getControlObject());
  290. query->nearPlane = gClientSceneGraph->getNearClip();
  291. // Scale the normal visible distance by the performance
  292. // tuning scale which we never let over 1.
  293. CameraAndFOV::sVisDistanceScale = mClampF( CameraAndFOV::sVisDistanceScale, 0.01f, 1.0f );
  294. query->farPlane = gClientSceneGraph->getVisibleDistance() * CameraAndFOV::sVisDistanceScale;
  295. // Provide some default values
  296. query->projectionOffset = Point2F::Zero;
  297. query->stereoTargets[0] = 0;
  298. query->stereoTargets[1] = 0;
  299. query->eyeOffset[0] = Point3F::Zero;
  300. query->eyeOffset[1] = Point3F::Zero;
  301. query->hasFovPort = false;
  302. query->hasStereoTargets = false;
  303. F32 cameraFov = 0.0f;
  304. bool fovSet = false;
  305. // Try to use the connection's display deivce, if any, but only if the editor
  306. // is not open
  307. if(!gEditingMission && connection->hasDisplayDevice())
  308. {
  309. IDisplayDevice* display = connection->getDisplayDevice();
  310. // Note: all eye values are invalid until this is called
  311. display->setDrawCanvas(query->drawCanvas);
  312. display->setCurrentConnection(connection);
  313. // Display may activate AFTER so we need to call this again just in case
  314. display->onStartFrame();
  315. // The connection's display device may want to set the projection offset
  316. if(display->providesProjectionOffset())
  317. {
  318. query->projectionOffset = display->getProjectionOffset();
  319. }
  320. // The connection's display device may want to set the eye offset
  321. if(display->providesEyeOffsets())
  322. {
  323. display->getEyeOffsets(query->eyeOffset);
  324. }
  325. // Grab field of view for both eyes
  326. if (display->providesFovPorts())
  327. {
  328. display->getFovPorts(query->fovPort);
  329. fovSet = true;
  330. query->hasFovPort = true;
  331. }
  332. // Grab the latest overriding render view transforms
  333. connection->getControlCameraEyeTransforms(display, query->eyeTransforms);
  334. display->getStereoViewports(query->stereoViewports);
  335. display->getStereoTargets(query->stereoTargets);
  336. query->hasStereoTargets = true;
  337. }
  338. else
  339. {
  340. query->eyeTransforms[0] = query->cameraMatrix;
  341. query->eyeTransforms[1] = query->cameraMatrix;
  342. }
  343. // Use the connection's FOV settings if requried
  344. if(!connection->getControlCameraFov(&cameraFov))
  345. {
  346. return false;
  347. }
  348. query->fov = mDegToRad(cameraFov);
  349. return true;
  350. }
  351. return false;
  352. }
  353. void GameRenderWorld()
  354. {
  355. PROFILE_START(GameRenderWorld);
  356. FrameAllocator::setWaterMark(0);
  357. gClientSceneGraph->renderScene( SPT_Diffuse );
  358. // renderScene leaves some states dirty, which causes problems if GameTSCtrl is the last Gui object rendered
  359. GFX->updateStates();
  360. AssertFatal(FrameAllocator::getWaterMark() == 0,
  361. "Error, someone didn't reset the water mark on the frame allocator!");
  362. FrameAllocator::setWaterMark(0);
  363. PROFILE_END();
  364. }
  365. static void Process3D()
  366. {
  367. MATMGR->updateTime();
  368. // Update the SFX world, if there is one.
  369. if( gSFX3DWorld )
  370. gSFX3DWorld->update();
  371. }
  372. static void RegisterGameFunctions()
  373. {
  374. Con::addVariable( "$pref::Camera::distanceScale", TypeF32, &CameraAndFOV::sVisDistanceScale,
  375. "A scale to apply to the normal visible distance, typically used for tuning performance.\n"
  376. "@ingroup Game");
  377. Con::addVariable( "$cameraFov", TypeF32, &CameraAndFOV::sConsoleCameraFov,
  378. "The camera's Field of View.\n\n"
  379. "@ingroup Game" );
  380. // Stuff game types into the console
  381. Con::setIntVariable("$TypeMasks::StaticObjectType", StaticObjectType);
  382. Con::setIntVariable("$TypeMasks::EnvironmentObjectType", EnvironmentObjectType);
  383. Con::setIntVariable("$TypeMasks::TerrainObjectType", TerrainObjectType);
  384. Con::setIntVariable("$TypeMasks::WaterObjectType", WaterObjectType);
  385. Con::setIntVariable("$TypeMasks::TriggerObjectType", TriggerObjectType);
  386. Con::setIntVariable("$TypeMasks::MarkerObjectType", MarkerObjectType);
  387. Con::setIntVariable("$TypeMasks::GameBaseObjectType", GameBaseObjectType);
  388. Con::setIntVariable("$TypeMasks::ShapeBaseObjectType", ShapeBaseObjectType);
  389. Con::setIntVariable("$TypeMasks::CameraObjectType", CameraObjectType);
  390. Con::setIntVariable("$TypeMasks::StaticShapeObjectType", StaticShapeObjectType);
  391. Con::setIntVariable("$TypeMasks::DynamicShapeObjectType", DynamicShapeObjectType);
  392. Con::setIntVariable("$TypeMasks::PlayerObjectType", PlayerObjectType);
  393. Con::setIntVariable("$TypeMasks::ItemObjectType", ItemObjectType);
  394. Con::setIntVariable("$TypeMasks::VehicleObjectType", VehicleObjectType);
  395. Con::setIntVariable("$TypeMasks::VehicleBlockerObjectType", VehicleBlockerObjectType);
  396. Con::setIntVariable("$TypeMasks::ProjectileObjectType", ProjectileObjectType);
  397. Con::setIntVariable("$TypeMasks::ExplosionObjectType", ExplosionObjectType);
  398. Con::setIntVariable("$TypeMasks::CorpseObjectType", CorpseObjectType);
  399. Con::setIntVariable("$TypeMasks::DebrisObjectType", DebrisObjectType);
  400. Con::setIntVariable("$TypeMasks::PhysicalZoneObjectType", PhysicalZoneObjectType);
  401. Con::setIntVariable("$TypeMasks::LightObjectType", LightObjectType);
  402. Con::addVariable("Ease::InOut", TypeS32, &gEaseInOut,
  403. "InOut ease for curve movement.\n"
  404. "@ingroup Game");
  405. Con::addVariable("Ease::In", TypeS32, &gEaseIn,
  406. "In ease for curve movement.\n"
  407. "@ingroup Game");
  408. Con::addVariable("Ease::Out", TypeS32, &gEaseOut,
  409. "Out ease for curve movement.\n"
  410. "@ingroup Game");
  411. Con::addVariable("Ease::Linear", TypeS32, &gEaseLinear,
  412. "Linear ease for curve movement.\n"
  413. "@ingroup Game");
  414. Con::addVariable("Ease::Quadratic", TypeS32, &gEaseQuadratic,
  415. "Quadratic ease for curve movement.\n"
  416. "@ingroup Game");
  417. Con::addVariable("Ease::Cubic", TypeS32, &gEaseCubic,
  418. "Cubic ease for curve movement.\n"
  419. "@ingroup Game");
  420. Con::addVariable("Ease::Quartic", TypeS32, &gEaseQuartic,
  421. "Quartic ease for curve movement.\n"
  422. "@ingroup Game");
  423. Con::addVariable("Ease::Quintic", TypeS32, &gEaseQuintic,
  424. "Quintic ease for curve movement.\n"
  425. "@ingroup Game");
  426. Con::addVariable("Ease::Sinusoidal", TypeS32, &gEaseSinusoidal,
  427. "Sinusoidal ease for curve movement.\n"
  428. "@ingroup Game");
  429. Con::addVariable("Ease::Exponential", TypeS32, &gEaseExponential,
  430. "Exponential ease for curve movement.\n"
  431. "@ingroup Game");
  432. Con::addVariable("Ease::Circular", TypeS32, &gEaseCircular,
  433. "Circular ease for curve movement.\n"
  434. "@ingroup Game");
  435. Con::addVariable("Ease::Elastic", TypeS32, &gEaseElastic,
  436. "Elastic ease for curve movement.\n"
  437. "@ingroup Game");
  438. Con::addVariable("Ease::Back", TypeS32, &gEaseBack,
  439. "Backwards ease for curve movement.\n"
  440. "@ingroup Game");
  441. Con::addVariable("Ease::Bounce", TypeS32, &gEaseBounce,
  442. "Bounce ease for curve movement.\n"
  443. "@ingroup Game");
  444. }