BspCollision.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. -----------------------------------------------------------------------------
  3. This source file is part of OGRE
  4. (Object-oriented Graphics Rendering Engine)
  5. For the latest info, see http://www.ogre3d.org/
  6. Copyright (c) 2000-2006 Torus Knot Software Ltd
  7. Also see acknowledgements in Readme.html
  8. You may use this sample code for anything you like, it is not covered by the
  9. LGPL like the rest of the engine.
  10. -----------------------------------------------------------------------------
  11. */
  12. /*
  13. -----------------------------------------------------------------------------
  14. Filename: BspCollision.cpp
  15. Description: Somewhere to play in the sand...
  16. -----------------------------------------------------------------------------
  17. */
  18. #include "OgreReferenceAppLayer.h"
  19. #include "ExampleRefAppApplication.h"
  20. #include "OgreStringConverter.h"
  21. // Hacky globals
  22. ApplicationObject *ball;
  23. SceneNode* targetNode;
  24. RaySceneQuery* rsq = 0;
  25. static const int num_rows = 3;
  26. // RakNet: Logger includes.
  27. #include "SQLiteClientLoggerPlugin.h"
  28. #include "PacketizedTCP.h"
  29. #include "Ogre3D_DX9_BackbufferGrabber.h"
  30. #include "RakNetTime.h"
  31. #include "GetTime.h"
  32. // Event handler to add ability to alter curvature
  33. class BspCollisionListener : public ExampleRefAppFrameListener
  34. {
  35. protected:
  36. // RakNet: For logging video
  37. PacketizedTCP packetizedTCP;
  38. RakNet::SQLiteClientLoggerPlugin loggerPlugin;
  39. Ogre3D_DX9_BackbufferGrabber backbufferGrabber;
  40. RakNet::TimeMS lastScreenshotTime;
  41. // Also save the world * so we can log it out
  42. World* mWorld;
  43. public:
  44. BspCollisionListener(RenderWindow* win, CollideCamera* cam, World* world)
  45. : ExampleRefAppFrameListener(win, cam)
  46. {
  47. // RakNet: Connect to server using TCP, for logging video
  48. packetizedTCP.AttachPlugin(&loggerPlugin);
  49. packetizedTCP.Start(0,0);
  50. loggerPlugin.SetServerParameters(packetizedTCP.Connect("127.0.0.1", 38123, true), "ogrevideo.sqlite");
  51. // For testing, I'm using 512x512 with a huge memory constraint at 30 FPS
  52. // For a real game, you probably want to limit this to 256x256, with a 8MB memory constraint, at 15-20 FPS
  53. loggerPlugin.SetMemoryConstraint(128000000);
  54. backbufferGrabber.InitBackbufferGrabber(mWindow, 512, 512);
  55. lastScreenshotTime=0;
  56. mWorld=world;
  57. }
  58. bool frameEnded(const FrameEvent& evt)
  59. {
  60. // local just to stop toggles flipping too fast
  61. static Real timeUntilNextToggle = 0;
  62. // Deal with time delays that are too large
  63. // If we exceed this limit, we ignore
  64. static const Real MAX_TIME_INCREMENT = 0.5f;
  65. if (evt.timeSinceLastEvent > MAX_TIME_INCREMENT)
  66. {
  67. return true;
  68. }
  69. if (timeUntilNextToggle >= 0)
  70. timeUntilNextToggle -= evt.timeSinceLastFrame;
  71. // Call superclass
  72. bool ret = ExampleRefAppFrameListener::frameEnded(evt);
  73. if (mKeyboard->isKeyDown(OIS::KC_SPACE) && timeUntilNextToggle <= 0)
  74. {
  75. timeUntilNextToggle = 2;
  76. ball->setPosition(mCamera->getPosition() +
  77. mCamera->getDirection() * mCamera->getNearClipDistance() * 2);
  78. ball->setLinearVelocity(mCamera->getDirection() * 200);
  79. ball->setAngularVelocity(Vector3::ZERO);
  80. // RakNet: Log events, which in this case is only firing the ball. Give the event a color so we can plot it
  81. rakSqlLog("EventData", "x,y,z,name,color",
  82. (mCamera->getPosition().x, mCamera->getPosition().y, mCamera->getPosition().z, "Fired Ball", "green"));
  83. }
  84. // Move the targeter
  85. rsq->setRay(mCamera->getRealCamera()->getCameraToViewportRay(0.5, 0.5));
  86. RaySceneQueryResult& rsqResult = rsq->execute();
  87. RaySceneQueryResult::iterator ri = rsqResult.begin();
  88. if (ri != rsqResult.end())
  89. {
  90. RaySceneQueryResultEntry& res = *ri;
  91. targetNode->setPosition(rsq->getRay().getPoint(res.distance));
  92. }
  93. // RakNet: Send screenshot and FPS info to server if connected, at most once every 30 milliseconds
  94. // This is constrained so we don't overflow the server with screenshots
  95. // Also only do it if we connected to the server
  96. RakNet::TimeMS timeSinceLastLog=RakNet::GetTimeMS()-lastScreenshotTime;
  97. if (packetizedTCP.GetConnectionCount()>0 && timeSinceLastLog>30)
  98. {
  99. RakNet::RGBImageBlob blob;
  100. backbufferGrabber.LockBackbufferCopy(&blob);
  101. RakAssert(blob.data!=0);
  102. // RakNet: Log frame data, including screenshot and FPS
  103. RakNet::SQLLogResult logResult = rakSqlLog("FrameData", "screenshot,averageFPS,lastFPS,bestFPS,worstFPS,numTris,DebugText",
  104. ( &blob,mWindow->getAverageFPS(),mWindow->getLastFPS(),mWindow->getBestFPS(),mWindow->getWorstFPS(),(int) mWindow->getTriangleCount(),mDebugText.c_str() ));
  105. // Release backbuffer as soon as possible, after sending frame data
  106. backbufferGrabber.ReleaseBackbufferCopy();
  107. if ( logResult==RakNet::SQLLR_WOULD_EXCEED_MEMORY_CONSTRAINT )
  108. {
  109. /// Sending too large of screenshots, or can't transfer data fast enough. See loggerPlugin.SetMemoryConstraint
  110. }
  111. // Also log out position of all world objects
  112. Entity *entity;
  113. SceneNode *sceneNode;
  114. entity = mWorld->getSceneManager()->getEntity("ball");
  115. sceneNode = entity->getParentSceneNode();
  116. // RakNet: Log object position data over time
  117. rakSqlLog("ObjectData", "x,y,z,name,color",
  118. (sceneNode->getPosition().x, sceneNode->getPosition().y, sceneNode->getPosition().z, entity->getName().c_str(), "blue"));
  119. for (int row = 0; row < num_rows; ++row)
  120. {
  121. for (int i = 0; i < (num_rows-row); ++i)
  122. {
  123. String name = "box";
  124. name += StringConverter::toString((row*num_rows) + i);
  125. entity = mWorld->getSceneManager()->getEntity(name);
  126. sceneNode = entity->getParentSceneNode();
  127. rakSqlLog("ObjectData", "x,y,z,name,color",
  128. (sceneNode->getPosition().x, sceneNode->getPosition().y, sceneNode->getPosition().z, entity->getName().c_str(), "red"));
  129. }
  130. }
  131. lastScreenshotTime=RakNet::GetTimeMS();
  132. }
  133. return ret;
  134. }
  135. };
  136. class BspCollisionApplication : public ExampleRefAppApplication
  137. {
  138. public:
  139. BspCollisionApplication() {
  140. }
  141. ~BspCollisionApplication()
  142. {
  143. delete rsq;
  144. }
  145. protected:
  146. void chooseSceneManager(void)
  147. {
  148. mSceneMgr = mRoot->createSceneManager("BspSceneManager");
  149. }
  150. void createWorld(void)
  151. {
  152. // Create BSP-specific world
  153. mWorld = new World(mSceneMgr, World::WT_REFAPP_BSP);
  154. }
  155. void createScene(void)
  156. {
  157. mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);
  158. // Set ambient light
  159. mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
  160. // Create a point light
  161. Light* l = mSceneMgr->createLight("MainLight");
  162. l->setPosition(-100,50,100);
  163. l->setAttenuation(8000,1,0,0);
  164. // Setup World
  165. mWorld->setGravity(Vector3(0, 0, -60));
  166. mWorld->getSceneManager()->setWorldGeometry("ogretestmap.bsp");
  167. // modify camera for close work
  168. mCamera->setNearClipDistance(10);
  169. mCamera->setFarClipDistance(20000);
  170. // Also change position, and set Quake-type orientation
  171. // Get random player start point
  172. ViewPoint vp = mSceneMgr->getSuggestedViewpoint(true);
  173. mCamera->setPosition(vp.position);
  174. mCamera->pitch(Degree(90)); // Quake uses X/Y horizon, Z up
  175. mCamera->rotate(vp.orientation);
  176. // Don't yaw along variable axis, causes leaning
  177. mCamera->setFixedYawAxis(true, Vector3::UNIT_Z);
  178. // Look at the boxes
  179. mCamera->lookAt(-150,40,30);
  180. ball = mWorld->createBall("ball", 7, vp.position + Vector3(0,0,80));
  181. ball->setDynamicsEnabled(true);
  182. ball->getEntity()->setMaterialName("Ogre/Eyes");
  183. OgreRefApp::Box* box = mWorld->createBox("shelf", 75, 125, 5, Vector3(-150, 40, 30));
  184. box->getEntity()->setMaterialName("Examples/Rocky");
  185. static const Real BOX_SIZE = 15.0f;
  186. for (int row = 0; row < num_rows; ++row)
  187. {
  188. for (int i = 0; i < (num_rows-row); ++i)
  189. {
  190. Real row_size = (num_rows - row) * BOX_SIZE * 1.25;
  191. String name = "box";
  192. name += StringConverter::toString((row*num_rows) + i);
  193. box = mWorld->createBox(name, BOX_SIZE,BOX_SIZE,BOX_SIZE ,
  194. Vector3(-150,
  195. 40 - (row_size * 0.5) + (i * BOX_SIZE * 1.25) ,
  196. 32.5 + (BOX_SIZE / 2) + (row * BOX_SIZE)));
  197. box->setDynamicsEnabled(false, true);
  198. box->getEntity()->setMaterialName("Examples/10PointBlock");
  199. }
  200. }
  201. mCamera->setCollisionEnabled(false);
  202. mCamera->getRealCamera()->setQueryFlags(0);
  203. // Create the targeting sphere
  204. Entity* targetEnt = mSceneMgr->createEntity("testray", "sphere.mesh");
  205. MaterialPtr mat = MaterialManager::getSingleton().create("targeter",
  206. ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
  207. Pass* pass = mat->getTechnique(0)->getPass(0);
  208. TextureUnitState* tex = pass->createTextureUnitState();
  209. tex->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT,
  210. ColourValue::Red);
  211. pass->setLightingEnabled(false);
  212. pass->setSceneBlending(SBT_ADD);
  213. pass->setDepthWriteEnabled(false);
  214. targetEnt->setMaterialName("targeter");
  215. targetEnt->setCastShadows(false);
  216. targetEnt->setQueryFlags(0);
  217. targetNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
  218. targetNode->scale(0.025, 0.025, 0.025);
  219. targetNode->attachObject(targetEnt);
  220. rsq = mSceneMgr->createRayQuery(Ray());
  221. rsq->setSortByDistance(true, 1);
  222. rsq->setWorldFragmentType(SceneQuery::WFT_SINGLE_INTERSECTION);
  223. }
  224. // Create new frame listener
  225. void createFrameListener(void)
  226. {
  227. mFrameListener= new BspCollisionListener(mWindow, mCamera, mWorld);
  228. mRoot->addFrameListener(mFrameListener);
  229. }
  230. public:
  231. };
  232. #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
  233. #define WIN32_LEAN_AND_MEAN
  234. #include "windows.h"
  235. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
  236. #else
  237. int main(int argc, char **argv)
  238. #endif
  239. {
  240. // Create application object
  241. BspCollisionApplication app;
  242. try {
  243. app.go();
  244. } catch( Exception& e ) {
  245. #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
  246. MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
  247. #else
  248. std::cerr << "An exception has occured: " << e.getFullDescription();
  249. #endif
  250. }
  251. return 0;
  252. }
粤ICP备19079148号