4 //#include "PredictedState.h"
5 #include <OgreMeshManager.h>
6 #include <Utils/OgreBulletCollisionsMeshToShapeConverter.h>
10 #define CAMERA_STEP 20
11 //-------------------------------------------------------------------------------------
16 //-------------------------------------------------------------------------------------
19 // OgreBullet physic delete - RigidBodies
20 std::deque<OgreBulletDynamics::RigidBody *>::iterator itBody = mBodies.begin();
21 while (mBodies.end() != itBody)
26 // OgreBullet physic delete - Shapes
27 std::deque<OgreBulletCollisions::CollisionShape *>::iterator itShape = mShapes.begin();
28 while (mShapes.end() != itShape)
35 delete mWorld->getDebugDrawer();
36 mWorld->setDebugDrawer(0);
40 //-------------------------------------------------------------------------------------
44 mNumEntitiesInstanced = 0; // how many shapes are created
47 Ogre::Vector3 gravityVector = Ogre::Vector3(0,-1500,0); // gravity vector for Bullet
48 mWorld = new OgreBulletDynamics::DynamicsWorld(mSceneMgr, Ogre::AxisAlignedBox (Ogre::Vector3 (-10000, -10000, -10000),Ogre::Vector3 (10000, 10000, 10000)), gravityVector);
50 // add Debug info display tool
51 debugDrawer = new OgreBulletCollisions::DebugDrawer();
52 debugDrawer->setDrawWireframe(true); // we want to see the Bullet containers
54 mWorld->setDebugDrawer(debugDrawer);
55 mWorld->setShowDebugShapes(true); // enable it if you want to see the Bullet containers
56 Ogre::SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("debugDrawer", Ogre::Vector3::ZERO);
57 node->attachObject(static_cast <Ogre::SimpleRenderable *> (debugDrawer));
59 btDynamicsWorld *bulletWorld = mWorld->getBulletDynamicsWorld();
60 btWorld = bulletWorld;
61 btDispatcher *dispatcher = btWorld->getDispatcher();
63 for (i = 0; i < numPlayers; i++)
74 Client *clientobject = new Client("localhost");
75 client = clientobject;
79 int res = client->connectToServer(5001);
83 if ((res = client->getId((char *)&myPlayerId)) < (sizeof(int)))
85 std::cout << "Failed to receive player id. Not connected.";
88 std::cout << "\n\nPlayer id: " << myPlayerId << "\n\n";
91 pthread_mutexattr_init(&errorcheck);
92 pthread_mutexattr_settype(&errorcheck, PTHREAD_MUTEX_ERRORCHECK);
94 pthread_mutex_init(&po_mutex,&errorcheck);
95 pthread_mutex_init(&an_mutex,&errorcheck);
97 pthread_mutex_init(&players_mutex,&errorcheck);
98 pthread_mutex_init(&log_mutex,&errorcheck);
100 pthread_mutex_init(&send,NULL);
101 pthread_cond_init(&time2send,NULL);
103 /*//-------------------------------------------------------------------------------------
104 void Game::initPhysics()
106 // btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50));
107 // m_collisionShapes.push_back(groundShape);
108 m_collisionConfiguration = new btDefaultCollisionConfiguration();
109 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
110 btVector3 worldMin(-100000,-100000,-100000);
111 btVector3 worldMax(100000,100000,100000);
112 btAxisSweep3* sweepBP = new btAxisSweep3(worldMin,worldMax);
113 m_overlappingPairCache = sweepBP;
115 m_constraintSolver = new btSequentialImpulseConstraintSolver();
116 m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration);
117 m_dynamicsWorld->getDispatchInfo().m_allowedCcdPenetration=0.0001f;
119 #ifdef DYNAMIC_CHARACTER_CONTROLLER
120 m_character = new DynamicCharacterController ();
123 btTransform startTransform;
124 startTransform.setIdentity();
125 //startTransform.setOrigin (btVector3(0.0, 4.0, 0.0));
126 startTransform.setOrigin (btVector3(10.210098,-1.6433364,16.453260));
129 m_ghostObject = new btPairCachingGhostObject();
130 m_ghostObject->setWorldTransform(startTransform);
131 sweepBP->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
132 btScalar characterHeight=1.75;
133 btScalar characterWidth =1.75;
134 btConvexShape* capsule = new btCapsuleShape(characterWidth,characterHeight);
135 m_ghostObject->setCollisionShape (capsule);
136 m_ghostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT);
138 btScalar stepHeight = btScalar(0.35);
139 m_character = new btKinematicCharacterController (m_ghostObject,capsule,stepHeight);
145 void Game::createCamera(void)
148 mCamera = mSceneMgr->createCamera("PlayerCam");
149 // set its position, direction
150 mCamera->setPosition(Ogre::Vector3(0,300,-500));
151 mCamera->lookAt(Ogre::Vector3(0,0,0));
152 // set the near clip distance
153 mCamera->setNearClipDistance(5);
156 //-------------------------------------------------------------------------------------
157 void Game::createViewports(void)
159 // Create one viewport, entire window
160 Ogre::Viewport* vp = mWindow->addViewport(mCamera);
161 vp->setBackgroundColour(Ogre::ColourValue(0, 0, 0));
162 // Alter the camera aspect ratio to match the viewport
163 mCamera->setAspectRatio(Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight()));
165 //-------------------------------------------------------------------------------------
166 void Game::createScene(void)
170 mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);
171 mSceneMgr->setShadowTextureSettings(1000, 2, Ogre::PF_FLOAT16_R);
172 mSceneMgr->setShadowTextureSelfShadow(true);
173 mSceneMgr->setAmbientLight(Ogre::ColourValue(0.45f, 0.45f, 0.45f));
176 Ogre::Plane plane(Ogre::Vector3::UNIT_Y, 0);
177 Ogre::MeshManager::getSingleton().createPlane("ground", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
178 plane, 15000, 15000, 20, 20, true, 1, 5, 5, Ogre::Vector3::UNIT_Z);
180 Ogre::Entity* entGround = mSceneMgr->createEntity("GroundEntity", "ground");
181 mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(entGround);
183 entGround->setMaterialName("Examples/GrassFloor");
184 entGround->setMaterialLodBias(2.0, 5, 20);
185 entGround->setCastShadows(false);
186 mSceneMgr->setSkyDome(true, "Examples/CloudySky", 1, 10 );
188 Ogre::ColourValue fadeColour(0.9, 0.9, 0.9);
189 mSceneMgr->setFog(Ogre::FOG_EXP, fadeColour, 0.000005);
191 Ogre::Light* daylight = mSceneMgr->createLight("dayLight");
192 daylight->setType(Ogre::Light::LT_DIRECTIONAL);
194 daylight->setDirection(0.1f, 0.9f, 0.9f);
195 daylight->setDiffuseColour(0.15f, 0.15f, 0.18f);
196 daylight->setSpecularColour(0, 0, 0);
197 daylight->setCastShadows(true);
199 Ogre::Light* sunlight = mSceneMgr->createLight("sunLight");
200 sunlight->setType(Ogre::Light::LT_DIRECTIONAL);
201 sunlight->setDirection(0.1f, 0.9f, 0.9f);
202 sunlight->setDiffuseColour(0.15f, 0.15f, 0.18f);
203 sunlight->setSpecularColour(0, 0, 0);
204 sunlight->setCastShadows(true);
207 // add collision detection to the ground
208 OgreBulletCollisions::CollisionShape *Shape;
209 Shape = new OgreBulletCollisions::StaticPlaneCollisionShape(Ogre::Vector3(0,1,0), 0); // (normal vector, distance)
210 // a body is needed for the shape
211 OgreBulletDynamics::RigidBody *defaultPlaneBody = new OgreBulletDynamics::RigidBody("BasePlane",
213 defaultPlaneBody->setStaticShape(Shape, 0.1, 0.8);// (shape, restitution, friction)
214 // push the created objects to the deques
215 mShapes.push_back(Shape);
216 mBodies.push_back(defaultPlaneBody);
221 // create Maya temple :)
222 Ogre::Entity *entTemple = mSceneMgr->createEntity("TempleEntity", "MayanTemple.mesh");
223 Ogre::SceneNode *nodeTemple = mSceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(1000,0,0));
224 nodeTemple->attachObject(entTemple);
225 nodeTemple->scale(50,50,50);
227 Ogre::AxisAlignedBox templeB = entTemple->getWorldBoundingBox(true);
228 Ogre::Vector3 templeSize = templeB.getSize();
231 OgreBulletCollisions::BoxCollisionShape *templeBox = new OgreBulletCollisions::BoxCollisionShape(templeSize);
233 OgreBulletCollisions::StaticMeshToShapeConverter *stConverter = new OgreBulletCollisions::StaticMeshToShapeConverter(entTemple);
234 OgreBulletCollisions::TriangleMeshCollisionShape *templeShape = stConverter->createTrimesh();
235 OgreBulletDynamics::RigidBody *templeBody = new OgreBulletDynamics::RigidBody("Temple", mWorld);
236 templeBody->setStaticShape(templeBox, 0.1, 0.8);
237 /* templeBody->setShape(nodeTemple,
239 100.0f, // dynamic body restitution
240 100.6f, // dynamic body friction
241 1.0f, // dynamic bodymass
242 Ogre::Vector3::ZERO, // starting position of the box
243 nodeTemple->getOrientation());// orientation of the box*/
244 mNumEntitiesInstanced++;
245 Ogre::Vector3 move = Ogre::Vector3::ZERO;
247 nodeTemple->translate(move);
248 btRigidBody *btTemple = templeBody->getBulletRigidBody();
249 btTemple->clearForces();
250 mShapes.push_back(templeShape);
251 mShapes.push_back(templeBox);
252 mBodies.push_back(templeBody);
256 // create local player and attach camera to it
257 createPlayer(myPlayerId);
258 playerNodes[myPlayerId]->attachObject(daylight);
259 playerNodes[myPlayerId]->attachObject(sunlight);
262 //predictionHandler = new PredictedState(localPlayer, collisionObjects);
264 std::cout << "created players\n";
267 pthread_cond_signal(&send_start);
268 pthread_cond_signal(&update_start);
271 //-------------------------------------------------------------------------------------
272 void Game::createFrameListener(void){
274 mToggle = 0.0; // The time left until next toggle
275 mRotate = 0.0; // The rotate constant
276 mMove = 160; // The movement constant
278 BaseApplication::createFrameListener();
281 //-------------------------------------------------------------------------------------
282 bool Game::frameRenderingQueued(const Ogre::FrameEvent &evt)
284 // set idle animation immediately if stopped walking
285 if (anStates[myPlayerId]->getAnimationName() == "walk")
287 if (!mKeyboard->isKeyDown(OIS::KC_J) && !mKeyboard->isKeyDown(OIS::KC_L) && !mKeyboard->isKeyDown(OIS::KC_I) && !mKeyboard->isKeyDown(OIS::KC_K))
289 pthread_mutex_lock(&an_mutex);
291 pthread_mutex_unlock(&an_mutex);
292 pthread_cond_signal(&time2send);
293 animate("idle",&anStates[myPlayerId], players[myPlayerId]);
297 else if (anStates[myPlayerId]->getAnimationName() == "handshake")
299 if (anStates[myPlayerId]->hasEnded())
301 animate("idle",&anStates[myPlayerId], players[myPlayerId]);
302 restoreCameraPosition();
305 else if(anStates[myPlayerId]->getTimePosition() == 0)
307 cameraPos = mCamera->getPosition();
308 cameraOrient = mCamera->getOrientation();
310 Ogre::Vector3 moveCamera = cameraPos;
313 mCamera->setPosition(moveCamera);
314 mCamera->lookAt(playerNodes[myPlayerId]->getPosition());
318 // update animation states of all players
319 anStates[myPlayerId]->addTime(evt.timeSinceLastFrame);
320 // anStates[6]->addTime(evt.timeSinceLastFrame);
322 // std::cerr << "main thread taking the lock\n\n\n";
323 pthread_mutex_lock(&players_mutex);
324 // std::cerr << "main thread taken the lock\n\n\n";
325 for (i = 0; i < numPlayers; i++)
328 if (playersAlive[i] == 1)
330 anStates[i]->addTime(evt.timeSinceLastFrame);
331 // if (anStates[i]->getAnimationName() == "walk")
335 // predictionHandler->correct(orientationUpdate[i],positionUpdate[i],anStates[i]->getAnimationName(), playerNodes[i], evt);
336 // playerNodes[i]->setOrientation(orientationUpdate[i]);
337 // playerNodes[i]->setPosition(positionUpdate[i]);
341 // predictionHandler->predictNext(anStates[i]->getAnimationName(), playerNodes[i], evt);
346 pthread_mutex_unlock(&players_mutex);
347 // std::cerr << "main thread released the lock\n\n\n";
350 if(!processUnbufferedInput(evt)) {
352 std::cerr << "processUnbufferedInput == false\n";
356 // write my position and orientation to use by sending thread
357 pthread_mutex_lock(&po_mutex);
358 position = playerNodes[myPlayerId]->getPosition();
359 orientation = playerNodes[myPlayerId]->getOrientation();
360 pthread_mutex_unlock(&po_mutex);
362 mWorld->stepSimulation(evt.timeSinceLastFrame); // update Bullet Physics animation
364 bool ret = BaseApplication::frameRenderingQueued(evt);
367 //-------------------------------------------------------------------------------------
368 bool Game::keyPressed( const OIS::KeyEvent &arg )
371 if (arg.key == OIS::KC_ESCAPE)
373 int res = client->sendMessage("exit",4);
376 else if (arg.key == OIS::KC_F1)
378 mWorld->setShowDebugShapes(true);
380 if (arg.key == OIS::KC_F2)
382 mWorld->setShowDebugShapes(false);
388 //-------------------------------------------------------------------------------------
389 bool Game::keyReleased( const OIS::KeyEvent &arg )
393 //-------------------------------------------------------------------------------------
394 bool Game::processUnbufferedInput(const Ogre::FrameEvent& evt)
396 mToggle -= evt.timeSinceLastFrame;
397 Ogre::Vector3 transVector = Ogre::Vector3::ZERO;
399 if (mKeyboard->isKeyDown(OIS::KC_K)) // Forward
402 if (anStates[myPlayerId]->getAnimationName() != "walk" || !anStates[myPlayerId]->getEnabled())
404 pthread_mutex_lock(&an_mutex);
406 pthread_mutex_unlock(&an_mutex);
407 pthread_cond_signal(&time2send);
408 animate("walk",&anStates[myPlayerId], players[myPlayerId]);
411 transVector.z -= mMove;
414 if (mKeyboard->isKeyDown(OIS::KC_I)) // Backward
417 if (anStates[myPlayerId]->getAnimationName() != "walk" || !anStates[myPlayerId]->getEnabled())
419 pthread_mutex_lock(&an_mutex);
421 pthread_mutex_unlock(&an_mutex);
422 pthread_cond_signal(&time2send);
423 animate("walk",&anStates[myPlayerId], players[myPlayerId]);
425 transVector.z += mMove;
426 //transVector.y += mMove;
429 // MC_RBody->applyForce((MC_RBody->getCenterOfMassPosition() + transVector), MC_RBody->getCenterOfMassPosition());
432 if (mKeyboard->isKeyDown(OIS::KC_J)) // Left
435 if (anStates[myPlayerId]->getAnimationName() != "walk" || !anStates[myPlayerId]->getEnabled())
437 pthread_mutex_lock(&an_mutex);
439 pthread_mutex_unlock(&an_mutex);
440 pthread_cond_signal(&time2send);
441 animate("walk",&anStates[myPlayerId], players[myPlayerId]);
446 if (mKeyboard->isKeyDown(OIS::KC_L)) // Right
449 if (anStates[myPlayerId]->getAnimationName() != "walk" || !anStates[myPlayerId]->getEnabled())
451 pthread_mutex_lock(&an_mutex);
453 pthread_mutex_unlock(&an_mutex);
454 pthread_cond_signal(&time2send);
455 animate("walk",&anStates[myPlayerId], players[myPlayerId]);
463 if (mKeyboard->isKeyDown(OIS::KC_1))
465 pthread_mutex_lock(&an_mutex);
467 pthread_mutex_unlock(&an_mutex);
468 pthread_cond_signal(&time2send);
469 animate("wave",&anStates[myPlayerId], players[myPlayerId]);
471 else if (mKeyboard->isKeyDown(OIS::KC_N)) //nod
473 pthread_mutex_lock(&an_mutex);
475 pthread_mutex_unlock(&an_mutex);
476 pthread_cond_signal(&time2send);
477 animate("nod",&anStates[myPlayerId], players[myPlayerId]);
479 else if (mKeyboard->isKeyDown(OIS::KC_P)) // punch
481 pthread_mutex_lock(&an_mutex);
483 pthread_mutex_unlock(&an_mutex);
484 pthread_cond_signal(&time2send);
485 animate("punch",&anStates[myPlayerId], players[myPlayerId]);
487 else if (mKeyboard->isKeyDown(OIS::KC_Q)) // kick
491 else if (mKeyboard->isKeyDown(OIS::KC_3)) // headshake
494 pthread_mutex_lock(&an_mutex);
496 pthread_mutex_unlock(&an_mutex);
497 pthread_cond_signal(&time2send);
498 animate("headshake",&anStates[myPlayerId], players[myPlayerId]);
500 else if (mKeyboard->isKeyDown(OIS::KC_2)) // smth
502 // animate("punch",&p2AnimationState, entP2);
504 else if (mKeyboard->isKeyDown(OIS::KC_H)) // smth
506 // restoreCameraPosition();
507 if (anStates[myPlayerId]->getAnimationName() != "handshake")
509 pthread_mutex_lock(&an_mutex);
511 pthread_mutex_unlock(&an_mutex);
512 pthread_cond_signal(&time2send);
513 animate("handshake",&anStates[myPlayerId], players[myPlayerId]);
514 animate("handshake",&anStates[6], players[6]);
515 std::cout << playerNodes[myPlayerId]->getOrientation() << " me\n";
516 std::cout << playerNodes[6]->getOrientation() << " other\n";
518 //mCamera->yaw(Ogre::Degree(-20));
521 else if(mKeyboard->isKeyDown(OIS::KC_Z))
526 else if(mKeyboard->isKeyDown(OIS::KC_B))
528 Ogre::Vector3 size = Ogre::Vector3::ZERO; // size of the box
529 // starting position of the box
530 Ogre::Vector3 position = (playerNodes[myPlayerId]->getPosition() + 10);
531 // starting orientation of the box
532 Ogre::Quaternion orientation = (playerNodes[myPlayerId]->getOrientation());
534 // create an ordinary, Ogre mesh with texture
535 Ogre::Entity *entity = mSceneMgr->createEntity(
536 "Box" + Ogre::StringConverter::toString(mNumEntitiesInstanced),
538 entity->setCastShadows(true);
539 // we need the bounding box of the box to be able to set the size of the Bullet-box
540 Ogre::AxisAlignedBox boundingB = entity->getBoundingBox();
541 size = boundingB.getSize(); size /= 2.0f; // only the half needed
542 size *= 0.95f; // Bullet margin is a bit bigger so we need a smaller size
543 // (Bullet 2.76 Physics SDK Manual page 18)
544 entity->setMaterialName("Examples/Rockwall");
545 Ogre::SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
546 node->attachObject(entity);
547 node->scale(0.2f, 0.2f, 0.2f); // the cube is too big for us
548 size *= 0.2f; // don't forget to scale down the Bullet-box too
550 // after that create the Bullet shape with the calculated size
551 OgreBulletCollisions::BoxCollisionShape *sceneBoxShape = new OgreBulletCollisions::BoxCollisionShape(size);
552 // and the Bullet rigid body
553 OgreBulletDynamics::RigidBody *defaultBody = new OgreBulletDynamics::RigidBody(
554 "defaultBoxRigid" + Ogre::StringConverter::toString(mNumEntitiesInstanced),
556 defaultBody->setShape(node,
558 0.0f, // dynamic body restitution
559 0.6f, // dynamic body friction
560 1.01f, // dynamic bodymass
561 position, // staring position of the box
562 playerNodes[myPlayerId]->convertLocalToWorldOrientation(orientation));// orientation of the box
563 mNumEntitiesInstanced++;
565 defaultBody->setLinearVelocity(
566 playerNodes[myPlayerId]->getPosition().normalisedCopy() * 7.0f ); // shooting speed
567 // push the created objects to the deque
568 mShapes.push_back(sceneBoxShape);
569 mBodies.push_back(defaultBody);
571 else if (mKeyboard->isKeyDown(OIS::KC_PGUP))
573 cameraNode->pitch(Ogre::Degree(CAMERA_STEP*evt.timeSinceLastFrame), Ogre::Node::TS_LOCAL);
575 else if (mKeyboard->isKeyDown(OIS::KC_PGDOWN))
577 cameraNode->pitch(Ogre::Degree(-CAMERA_STEP*evt.timeSinceLastFrame), Ogre::Node::TS_LOCAL);
579 else if (mKeyboard->isKeyDown(OIS::KC_RIGHT))
581 cameraNode->yaw(Ogre::Degree(-CAMERA_STEP*evt.timeSinceLastFrame), Ogre::Node::TS_LOCAL);
583 else if (mKeyboard->isKeyDown(OIS::KC_LEFT))
585 cameraNode->yaw(Ogre::Degree(CAMERA_STEP*evt.timeSinceLastFrame), Ogre::Node::TS_LOCAL);
587 else if (mKeyboard->isKeyDown(OIS::KC_UP))
589 transVector.z -= CAMERA_STEP;
590 cameraNode->translate(transVector * evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL);
593 else if (mKeyboard->isKeyDown(OIS::KC_DOWN))
595 transVector.z += CAMERA_STEP;
596 cameraNode->translate(transVector * evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL);
602 playerNodes[myPlayerId]->translate(transVector * evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL);
603 playerNodes[myPlayerId]->yaw(Ogre::Degree(mRotate) * evt.timeSinceLastFrame);
609 //-------------------------------------------------------------------------------------
610 void Game::animate(const Ogre::String &an, Ogre::AnimationState** anState, Ogre::Entity *ent)
612 (*anState)->setEnabled(false);
613 (*anState) = ent->getAnimationState(an);
614 (*anState)->setTimePosition(0);
615 (*anState)->setEnabled(true);
617 (*anState)->setLoop(true);
619 (*anState)->setLoop(false);
621 //-------------------------------------------------------------------------------------
622 void Game::sendUpdate()
630 rc = gettimeofday(&tp, NULL);
632 // Convert from timeval to timespec
633 if (ts.tv_nsec < WAIT_TIME_NSECONDS)
635 ts.tv_sec = tp.tv_sec;
636 ts.tv_nsec = tp.tv_usec * 1000;
637 ts.tv_nsec += WAIT_TIME_NSECONDS;
639 else // if less a half second left until next second
641 ts.tv_sec = tp.tv_sec + 1;
642 ts.tv_nsec = tp.tv_usec * 1000;
646 int res = pthread_cond_timedwait(&time2send, &send, &ts);
647 /* if (res == ETIMEDOUT)
648 std::cerr << "ETIMEDOUT\n";
649 else if(res == EINVAL)
650 std::cerr << "EINVAL: value is not correct";
651 else if(res == EPERM)
652 std::cerr << "EPERM: mutex not locked";
654 std::cerr << "SIGNAL\n"; */
655 memset(sendbuffer, 0, BUFFERSIZE);
657 pthread_mutex_lock(&po_mutex);
658 memcpy(&sendbuffer[size],(void*)&position, sizeof(Ogre::Vector3));
659 size += sizeof(Ogre::Vector3);
660 memcpy(&sendbuffer[size],(void*)&orientation, sizeof(Ogre::Quaternion));
661 pthread_mutex_unlock(&po_mutex);
662 size += sizeof(Ogre::Quaternion);
664 pthread_mutex_lock(&an_mutex);
665 memcpy(&sendbuffer[size],(void*)&animation, sizeof(int));
667 pthread_mutex_unlock(&an_mutex);
669 client->sendMessage(sendbuffer, size);
674 //-------------------------------------------------------------------------------------
679 memset(recvbuffer, 0, BUFFERSIZE);
680 int bytesreceived = client->readMessage(recvbuffer);
684 Ogre::Quaternion orient;
688 //memcpy(&activePlayers,&recvbuffer[sizeread], sizeof(int));
689 // sizeread += sizeof(int);
691 //std::cout << "Active players: " << activePlayers << "\n";
693 //if (activePlayers > 1)
695 int nr = bytesreceived/36;
696 std::cout << "number of updates: " << nr << "\n";
698 for (i = 0; i < nr; i++)
700 memcpy(&pid,&recvbuffer[sizeread], sizeof(int));
701 sizeread += sizeof(int);
702 if (pid > numPlayers)
704 std::cerr << "Bad player id. dropping update\n";
707 std::cout << "pid " << pid << "\n";
708 if (pid == myPlayerId)
710 sizeread += ( sizeof(Ogre::Vector3) + sizeof(Ogre::Quaternion) + sizeof(int));
714 std::cerr << "taking lock\n";
715 pthread_mutex_lock(&players_mutex);
716 std::cerr << "taken lock\n";
717 if (playersAlive[pid] != 1)
719 std::cout << "new player \n\n\n";
721 playersAlive[pid] = 1;
725 memcpy(&pos, &recvbuffer[sizeread], sizeof(Ogre::Vector3));
726 std::cout << pos << "\n";
727 sizeread += sizeof(Ogre::Vector3);
728 memcpy(&orient, &recvbuffer[sizeread], sizeof(Ogre::Quaternion));
729 std::cout << orient << "\n";
730 sizeread += sizeof(Ogre::Quaternion);
731 memcpy(&an, &recvbuffer[sizeread], sizeof(int));
732 sizeread += sizeof(int);
733 std::cout << an << "\n";
735 positionUpdate[pid] = pos;
736 orientationUpdate[pid] = orient;
737 // predictionHandler->setLastUpdate(orient,pos);
738 // position_log[pid].push_front(pos);
739 // orientation_log[pid].push_front(orient);
748 std::cout << "idle\n";
749 animate("idle", &anStates[pid], players[pid]);
753 std::cout << "walk\n";
754 animate("walk", &anStates[pid], players[pid]);
758 std::cout << "wave\n";
759 animate("wave", &anStates[pid], players[pid]);
763 std::cout << "nod\n";
764 animate("nod", &anStates[pid], players[pid]);
768 std::cout << "punch\n";
769 animate("punch", &anStates[pid], players[pid]);
773 std::cout << "headshake\n";
774 animate("headshake", &anStates[pid], players[pid]);
778 std::cout << "handshake\n";
779 animate("handshake", &anStates[pid], players[pid]);
787 pthread_mutex_unlock(&players_mutex);
788 std::cerr << "updating thread released the lock\n\n\n";
793 //-------------------------------------------------------------------------------------
794 void Game::handlePlayers()
801 //-------------------------------------------------------------------------------------
802 void* Game::sendThread(void* empt)
804 pthread_cond_wait(&send_start,&send_mutex);
806 Game* th = (Game *) empt;
809 //-------------------------------------------------------------------------------------
810 void* Game::receiveThread(void* empt)
812 pthread_cond_wait(&update_start,&update_mutex);
814 Game* th = (Game *) empt;
817 //-------------------------------------------------------------------------------------
818 void Game::createPlayer(int id)
820 std::cout << "\n creating new player " << id << "\n";
821 playerNodes[id] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3( 0, 100.5, 0 ));
822 players[id] = mSceneMgr->createEntity("player" + Ogre::StringConverter::toString(id), "MCMesh.mesh");
823 players[id]->setCastShadows(true);
824 playerNodes[id]->attachObject(players[id]);
825 playerNodes[id]->setScale(30,30,30);
826 anStates[id] = players[id]->getAnimationState("idle");
827 anStates[id]->setEnabled(true);
828 anStates[id]->setLoop(true);
830 if (id == myPlayerId)
832 Ogre::SceneNode* cameraNode = playerNodes[myPlayerId]->createChildSceneNode();
833 cameraNode->attachObject(mCamera);
836 //create a converter to make containers for animated mesh
837 OgreBulletCollisions::AnimatedMeshToShapeConverter *cont = new OgreBulletCollisions::AnimatedMeshToShapeConverter(players[myPlayerId], *(players[myPlayerId]->_getBoneMatrices()));
838 Ogre::SkeletonInstance *skel = players[id]->getSkeleton();
839 Ogre::Bone *bone = skel->getBone("hip.R");
840 //OgreBulletCollisions::CapsuleCollisionShape *boneShape = cont->createOrientedCapsuleCollisionShape(bone->getHandle(), bone->convertLocalToWorldPosition(bone->getPosition()), bone->convertLocalToWorldOrientation(bone->getOrientation()));
842 std::cout << "bone position (local): " << bone->getPosition() << "\n";
843 std::cout << "bone position (world): " << bone->convertLocalToWorldPosition(bone->getPosition()) << "\n";
844 std::cout << "handle: " << bone->getHandle() << "\n";
845 std::cout << "name: " << bone->getName() << "\n";
846 // int numBones = skel->getNumBones();
848 // we need the bounding box of the box to be able to set the size getCenterOfMassPosition the Bullet-box
849 Ogre::AxisAlignedBox BoundingBox = players[id]->getWorldBoundingBox(true);
850 Ogre::Vector3 s = Ogre::Vector3::ZERO; // size of the box
851 s = BoundingBox.getSize();
852 //adjust the size of the box to best fit manually
856 BoundingBox.scale(s);
857 // s *= 0.95f; // Bullet margin is a bit bigger so we need a smaller size
858 // (Bullet 2.76 Physics SDK Manual page 18)
861 // after that create the Bullet shape with the calculated size
862 OgreBulletCollisions::BoxCollisionShape *boxShape = new OgreBulletCollisions::BoxCollisionShape(s);
863 Ogre::Real radius = 10;
864 Ogre::Real height = 50;
865 // OgreBulletCollisions::CapsuleCollisionShape *charShape = new OgreBulletCollisions::CapsuleCollisionShape(radius,height,Ogre::Vector3::ZERO);
867 // create compound collision shape to attach all created shapes to
868 // btCompoundShape *bshape = new btCompoundShape();
869 // OgreBulletCollisions::CompoundCollisionShape *cShape = new OgreBulletCollisions::CompoundCollisionShape(bshape);
871 // cShape->addChildShape(boxShape);
872 //cShape->addChildShape(boneShape);
874 // create a rigid body for the player
875 //OgreBulletDynamics::RigidBody *RBody
878 RBodies[id] = new OgreBulletDynamics::RigidBody(
879 "MCRigid" + Ogre::StringConverter::toString(mNumEntitiesInstanced),
880 mWorld, CG_PLAYERS, CM_PLAYERS);
881 RBodies[id]->setShape(playerNodes[id],
882 boxShape, // compound shapes containing all child shapes
883 0.6f, // dynamic body restitution
884 0.6f, // dynamic body friction
885 100.0f, // dynamic bodymass
886 Ogre::Vector3::ZERO, // starting position of the box
887 playerNodes[id]->getOrientation());// orientation of the box
888 mNumEntitiesInstanced++;
889 RBodies[id]->enableActiveState();
890 RBodies[id]->disableDeactivation();
891 // kinematic object setting allows to control the body manually
892 RBodies[id]->setKinematicObject(true);
893 btRigidBodies[id] = RBodies[id]->getBulletRigidBody();
895 // push the created objects to the deque
896 // mShapes.push_back(boneShape);
897 mShapes.push_back(boxShape);
898 // mShapes.push_back(cShape);
899 mBodies.push_back(RBodies[id]);
901 // for some reason, the entity appears at wrong position (too low), correct that manually
902 Ogre::Vector3 lift = Ogre::Vector3::ZERO;
904 playerNodes[id]->translate(lift);
906 if (id == myPlayerId)
908 btVector3 worldMin(-100000,-100000,-100000);
909 btVector3 worldMax(100000,100000,100000);
910 btAxisSweep3* sweepBP = new btAxisSweep3(worldMin,worldMax);
911 //m_overlappingPairCache = sweepBP;
914 btTransform startTransform;
915 startTransform.setIdentity();
916 //startTransform.setOrigin (btVector3(0.0, 4.0, 0.0));
917 startTransform.setOrigin (btVector3(10.210098,-1.6433364,16.453260));
920 m_ghostObject = new btPairCachingGhostObject();
921 m_ghostObject->setWorldTransform(startTransform);
922 sweepBP->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
923 btScalar characterHeight=1.75;
924 btScalar characterWidth =1.75;
925 btConvexShape* capsule = new btCapsuleShape(characterWidth,characterHeight);
926 m_ghostObject->setCollisionShape (capsule);
927 m_ghostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT);
930 //-------------------------------------------------------------------------------------
931 void Game::predictNext(int id, const Ogre::FrameEvent &evt)
934 Ogre::Vector3 transVector = Ogre::Vector3::ZERO;
935 transVector.z += mMove;
936 if (anStates[id]->getAnimationName() == "walk")
937 playerNodes[id]->translate(transVector * evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL);
940 //-------------------------------------------------------------------------------------
941 void Game::restoreCameraPosition()
943 mCamera->setOrientation(cameraOrient);
944 mCamera->setPosition(cameraPos);
946 //-------------------------------------------------------------------------------------
947 bool Game::CollisionCheck()
949 int numManifolds = btWorld->getDispatcher()->getNumManifolds();
950 btSimpleBroadphase *simplebp = new btSimpleBroadphase();
951 bool overlap = simplebp->testAabbOverlap(btRigidBodies[myPlayerId]->getBroadphaseProxy(), btRigidBodies[6]->getBroadphaseProxy());
953 std::cout << "overlap\n";
954 for (int i = 0; i < numManifolds; i++)
956 btPersistentManifold* contactManifold = btWorld->getDispatcher()->getManifoldByIndexInternal(i);
957 btRigidBody* obA = static_cast<btRigidBody*>(contactManifold->getBody0());
958 btRigidBody* obB = static_cast<btRigidBody*>(contactManifold->getBody1());
959 if (obA->isKinematicObject())
960 // std::cout << "kinematic\n";
962 if (obA == btRigidBodies[myPlayerId])
965 int numContacts = contactManifold->getNumContacts();
966 std::cout << numContacts << " numContacts\n";
967 for (int j=0;j<numContacts;j++)
969 btManifoldPoint& pt = contactManifold->getContactPoint(j);
970 if (pt.getDistance()<0.f)
972 const btVector3& ptA = pt.getPositionWorldOnA();
973 const btVector3& ptB = pt.getPositionWorldOnB();
974 const btVector3& normalOnB = pt.m_normalWorldOnB;
975 std::cout << "collision\n";
976 std::cout << pt.getDistance() << "\n";
977 pt.setDistance(50.0f);
982 std::cout << pt.getDistance() << "\n";
990 /*void Game::createPlayer(int id)
995 SceneNode* playerNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3( 0, 100.5, id*100));
996 Entity* playerEnt = mSceneMgr->createEntity("player" + StringConverter::toString(id), "MCMesh.mesh");
997 std::string playerCaption = "Player " + StringConverter::toString(id);
998 if (id == myPlayerId) // local player
1000 p = new Player(id, playerNode, playerEnt, mCamera);
1002 cameraNode = playerNode->createChildSceneNode();
1003 cameraNode->attachObject(mCamera);
1004 SceneNode* msgBoardNode = cameraNode->createChildSceneNode("MsgBoard",Vector3( -0.5, 2, -14.5));
1005 msgBoard = new MovableText("msgBoard", " . ");
1006 msgBoard->setTextAlignment(MovableText::H_CENTER, MovableText::V_ABOVE);
1007 msgBoard->setColor(ColourValue::White);
1008 msgBoard->setCharacterHeight(0.8);
1009 msgBoard->setFontName("BlueHighway-12");
1010 msgBoardNode->attachObject(msgBoard);
1011 SceneNode* scoreNode = cameraNode->createChildSceneNode(Vector3(-3.5, 21.4, -8.5));
1012 scoreBoard = new MovableText("scoreBoard", "H:+" +
1013 StringConverter::toString(localPlayer->HandshakesDone) + "-" +
1014 StringConverter::toString(localPlayer->HandshakesReceived) + " R:+" +
1015 StringConverter::toString(localPlayer->RPSDone) + "-" +
1016 StringConverter::toString(localPlayer->RPSReceived) + " P:+" +
1017 StringConverter::toString(localPlayer->PunchesDone) + "-" +
1018 StringConverter::toString(localPlayer->PunchesReceived) + " W:+" +
1019 StringConverter::toString(localPlayer->WavesDone) + "-" +
1020 StringConverter::toString(localPlayer->WavesReceived));
1022 scoreBoard->setTextAlignment(MovableText::H_LEFT, MovableText::V_ABOVE);
1023 scoreBoard->setColor(ColourValue::Black);
1024 scoreBoard->setCharacterHeight(0.8);
1025 scoreBoard->showOnTop();
1026 scoreBoard->setFontName("BlueHighway-12");
1027 scoreNode->attachObject(scoreBoard);
1029 SceneNode* stepsBoardNode = cameraNode->createChildSceneNode(Vector3( 11, 21.4, -8.5));
1030 stepsBoard = new MovableText("stepsBoard", " . " );
1031 stepsBoard->setTextAlignment(MovableText::H_LEFT, MovableText::V_ABOVE);
1032 stepsBoard->setColor(ColourValue::Black);
1033 stepsBoard->setCharacterHeight(0.8);
1034 stepsBoard->showOnTop();
1035 stepsBoard->setFontName("BlueHighway-12");
1036 stepsBoardNode->attachObject(stepsBoard);
1038 SceneNode* timeBoardNode = cameraNode->createChildSceneNode(Vector3( 5, 21.4, -8.5));
1039 timeBoard = new MovableText("timeBoard", " . " );
1040 timeBoard->setTextAlignment(MovableText::H_LEFT, MovableText::V_ABOVE);
1041 timeBoard->setColor(ColourValue::Black);
1042 timeBoard->setCharacterHeight(0.8);
1043 timeBoard->showOnTop();
1044 timeBoard->setFontName("BlueHighway-12");
1045 timeBoardNode->attachObject(timeBoard);
1048 if (nickName.length() > 0)
1049 playerCaption = nickName;
1050 playerCaption += " (you)";
1052 cameraPos = cameraNode->getPosition();
1053 cameraOrient = cameraNode->getOrientation();
1054 absoluteCameraPos = cameraNode->getPosition();
1055 absoluteCameraOrient = cameraNode->getOrientation();
1060 Camera* playerCam = mSceneMgr->createCamera("PlayerCam" + StringConverter::toString(id));
1061 playerCam->setPosition(Vector3(0,650,-1100+id*100));
1062 playerCam->lookAt(Vector3(0,250,id*100));
1063 playerCam->setNearClipDistance(5);
1064 playerNode->createChildSceneNode()->attachObject(playerCam);
1067 for (last = localPlayer; last->next != NULL; last = last->next)
1069 if (last == localPlayer)
1070 cout << "appending to local player\n";
1071 p = new Player(id, playerNode, playerEnt, playerCam);
1076 SceneNode* captionNode = playerNode->createChildSceneNode(Vector3(-0.5,3,0));
1077 p->idCaption = new MovableText("idCaption" + StringConverter::toString(id) , playerCaption);
1078 p->idCaption->setTextAlignment(MovableText::H_CENTER, MovableText::V_ABOVE);
1079 p->idCaption->setColor(ColourValue::Black);
1080 p->idCaption->setCharacterHeight(0.6);
1081 captionNode->attachObject(p->idCaption);
1084 //-------------------------------------------------------------------------------------
1087 #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
1088 #define WIN32_LEAN_AND_MEAN
1089 #include "windows.h"
1096 #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
1097 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
1099 int main(int argc, char *argv[])
1102 // Create application object
1106 pthread_mutex_init(&send_mutex, NULL);
1107 pthread_mutex_init(&update_mutex, NULL);
1108 pthread_cond_init(&send_start, NULL);
1109 pthread_cond_init(&update_start, NULL);
1110 pthread_t thread_id=0;
1111 pthread_create(&thread_id,0,&Game::sendThread,(void*)&app);
1112 pthread_detach(thread_id);
1113 pthread_create(&thread_id,NULL,&Game::receiveThread,(void*)&app);
1114 pthread_detach(thread_id);
1122 } catch( Ogre::Exception& e ) {
1123 #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
1124 MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
1126 std::cerr << "An exception has occured: " <<
1127 e.getFullDescription().c_str() << std::endl;
1153 - saks, stein, papir