Exemplo n.º 1
0
// Called before every render.
void update(DWORD milli)
{
	if(displayError)
		return;

	static DWORD time = 0;
	if(numSpheres > 0)
	{
		// Manually set the velocity of the user sphere.
		sphereData[0].m_velocity = Vector3(0);
		
		// left arrow
		if(keysDown[37] || keysDown['A'])
			sphereData[0].m_velocity += Vector3(-USER_SPHERE_SPEED, 0.0, 0.0);
		// right arrow
		if(keysDown[39] || keysDown['D'])
			sphereData[0].m_velocity += Vector3(USER_SPHERE_SPEED, 0.0, 0.0);

		// up arrow
		if(keysDown[38] || keysDown['W'])
			sphereData[0].m_velocity += Vector3(0.0f, 0.0, -USER_SPHERE_SPEED);
		// down arrow
		if(keysDown[40] || keysDown['S'])
			sphereData[0].m_velocity += Vector3(0.0f, 0.0, USER_SPHERE_SPEED);

		// page up
		if(keysDown[33] || keysDown['Q'])
			sphereData[0].m_velocity += Vector3(0.0f, USER_SPHERE_SPEED, 0);
		// page down
		if(keysDown[34] || keysDown['E'])
			sphereData[0].m_velocity += Vector3(0.0f, -USER_SPHERE_SPEED, 0.0);
	}

	// Rough second counter by adding up all the previous dt times.
	time += milli;

	if(time > 1000)
	{
		framesPerSecond = renderFrameCounter;

		// Average the physics frame counter.
		physicsPerSecond = 0.0f;

		for(int i = 0; i < numPhysicsThreads; i++)
		{
			physicsPerSecond += physicsFrames[i];
			physicsFrames[i] = 0;
		}

		renderFrameCounter = 0;
		physicsPerSecond /= numPhysicsThreads;
		
		time -= 1000;
	}

#if _USE_MT != 1
	// If we are not using multi threads. Then we need to call the physics
	// function here, after we're done the user input and before the scene
	// is rendered.
	physicsThread(0);
#endif
}
Exemplo n.º 2
0
void Engine::Engine::mainLoop()
{
    m_Factory.test_createObjects();

    btPairCachingGhostObject *pGhostObject = new btPairCachingGhostObject();
    pGhostObject->activate();
    btConvexShape *pShape = new btSphereShape(1.0f);
    m_pCharacterController = new btKinematicCharacterController(pGhostObject, pShape, 1.0f);
    //m_PhysicsSystem.world()->addCharacter(m_pCharacterController);

	// Define the updaterate for the game-logic
    const float update_fps = 64;
    auto update_dt = std::chrono::duration<double>(1 / update_fps);
	auto max_dt_seconds = std::chrono::duration<double>(0.2f);
	std::chrono::duration<double> accumulator = std::chrono::duration<double>::zero();
	std::chrono::duration<double> delta = std::chrono::duration<double>::zero();
	// Start the timer
	m_MainLoopTimer.update();

	bool isRunning = true;
    std::thread physicsThread([this, &isRunning]()
    {
        Utils::Timer<double> timer;
        std::chrono::duration<double> delta = std::chrono::duration<double>::zero();
		double acc = 0.0;
        while(isRunning)
        {
			timer.update();
			acc += timer.getAvgDelta().count();
			if(acc < 1.0 / 60.0)
			{			
				std::this_thread::sleep_for(std::chrono::nanoseconds(static_cast<long>((1.0 / 60.0) * 1000000000.0)));
				continue;
			}

			acc = 0.0;

            m_PhysicsSystem.updateRigidBodies();
            // Let bullet do it's own fixed timestamp
            updatePhysics(delta);
        }
    });

    
    while(isRunning)
    {
		delta =  m_MainLoopTimer.update();
        accumulator += delta;

        if(accumulator > max_dt_seconds)
            accumulator = max_dt_seconds;

		// Update the physics as often as we have to
        while(accumulator > update_dt)
            accumulator -= update_dt;

		//updatePhysics(accumulator);
		//accumulator = std::chrono::duration<double>::zero();

		// Generate interpolation value for the renderer
        const float alpha = static_cast<float>(accumulator / update_dt);

		// Draw the current frame
        isRunning = render(alpha);
    }

    physicsThread.join();
}
Exemplo n.º 3
0
void Driver::drive(int argc, char* argv[]) {

    // Make sure that this function is called just once
    SIM_ASSERT_RUNS_JUST_ONCE();

    // Before anything else, create the Time object
    T();

    // Then, determine the runId (just datetime for now)
    std::string runId = SimUtilities::timestampToDatetimeString(
        T()->startTimestamp()
    );

    // Then, initiliaze logging (before calling P() or S())
    Logging::initialize(runId);

    // Initialize the State object in order to:
    // 1) Set the runId
    // 2) Avoid a race condition (between threads)
    // 3) Initialize the Param object
    S()->setRunId(runId);

    // Remove any excessive archived runs
    SimUtilities::removeExcessArchivedRuns();

    // Generate the glut functions in a static context
    GlutFunctions functions = {
        []() {
            m_view->refresh();
        },
        [](int width, int height) {
            m_view->updateWindowSize(width, height);
        },
        [](unsigned char key, int x, int y) {
            m_view->keyPress(key, x, y);
        },
        [](int key, int x, int y) {
            m_view->specialKeyPress(key, x, y);
        },
        [](int key, int x, int y) {
            m_view->specialKeyRelease(key, x, y);
        }
    };

    // Initialize the model, view, and controller
    m_model = new Model();
    m_view = new View(m_model, argc, argv, functions);
    m_controller = new Controller(m_model, m_view);

    // Initialize mouse algorithm values in the model and view
    m_model->getWorld()->setOptions(
        m_controller->getOptions()
    );
    m_view->setMouseAlgorithmAndOptions(
        m_controller->getMouseAlgorithm(),
        m_controller->getOptions()
    );

    // Initialize the tile text, now that the options have been set
    m_view->initTileGraphicText();

    // Lastly, we need to populate the graphics buffers with maze information,
    // but only after we've initialized the tile graphic text
    m_view->getMazeGraphic()->draw();

    // Start the physics loop
    std::thread physicsThread([]() {
        m_model->getWorld()->simulate();
    });

    // Start the solving loop
    std::thread solvingThread([]() {

        // If the maze is invalid, don't let the algo do anything
        if (!m_model->getMaze()->isValidMaze()) {
            return;
        }

        // Wait for the window to appear
        SimUtilities::sleep(Seconds(P()->glutInitDuration()));

        // Begin execution of the mouse algorithm
        m_controller->getMouseAlgorithm()->solve(
            m_model->getMaze()->getWidth(),
            m_model->getMaze()->getHeight(),
            m_model->getMaze()->isOfficialMaze(),
            DIRECTION_TO_CHAR.at(m_model->getMouse()->getCurrentDiscretizedRotation()),
            m_controller->getMouseInterface());
    });

    // Start the graphics loop
    glutMainLoop();
}
Exemplo n.º 4
0
int OgreOculus::go(void)
{
	// Create Root object
	root = new Ogre::Root("plugin.cfg", "ogre.cfg");

	// OpenGL
    root->loadPlugin("RenderSystem_GL_d");
    root->setRenderSystem(root->getRenderSystemByName("OpenGL Rendering Subsystem"));

	// Initialize Root
	root->initialise(false);

	// Initialize Oculus
	ovrHmd hmd;
	ovrHmdDesc hmdDesc;
	ovrGraphicsLuid luid;
	ovr_Initialize(nullptr);
	if(ovr_Create(&hmd, &luid) != ovrSuccess)
		exit(-1);
	hmdDesc = ovr_GetHmdDesc(hmd);
	if(ovr_ConfigureTracking(hmd,
		ovrTrackingCap_Orientation |ovrTrackingCap_MagYawCorrection |ovrTrackingCap_Position,
		0) != ovrSuccess)
		exit(-2);

	// Turn off HUD
	ovr_SetInt(hmd, "PerfHudMode", ovrPerfHud_Off);

	// Create a window
	window = root->createRenderWindow("Ogre + Oculus = <3", hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2, false);

	// Create scene manager and cameras
	smgr = root->createSceneManager(Ogre::ST_GENERIC);

	// Load Ogre resource paths from config file
    Ogre::ConfigFile cf;
    cf.load("resources_d.cfg");

    // Go through all sections & settings in the file and add resources
    Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();

    Ogre::String secName, typeName, archName;
    while (seci.hasMoreElements())
    {
        secName = seci.peekNextKey();
        Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
        Ogre::ConfigFile::SettingsMultiMap::iterator i;
        for (i = settings->begin(); i != settings->end(); ++i)
        {
            typeName = i->first;
            archName = i->second;

            Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
                archName, typeName, secName);
        }
    }

	// Set resources
	Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

	// Create the model itself via OgreModel.cpp
	createOgreModel(smgr);

	// Create camera
	createCamera();

	// Set viewport and background color
	Ogre::Viewport* vp = window->addViewport(mCamera);
	vp->setBackgroundColour(Ogre::ColourValue(34, 89, 0)); // Yellow

	// Set aspect ratio
	mCamera->setAspectRatio(
    Ogre::Real(vp->getActualWidth()) /
    Ogre::Real(vp->getActualHeight()));

	// Initialize glew
	if(glewInit() != GLEW_OK)
		exit(-3);

	// Get texture sizes
	ovrSizei texSizeL, texSizeR;
	texSizeL = ovr_GetFovTextureSize(hmd, ovrEye_Left, hmdDesc.DefaultEyeFov[left], 1);
	texSizeR = ovr_GetFovTextureSize(hmd, ovrEye_Right, hmdDesc.DefaultEyeFov[right], 1);

	// Calculate render buffer size
	ovrSizei bufferSize;
	bufferSize.w = texSizeL.w + texSizeR.w;
	bufferSize.h = max(texSizeL.h, texSizeR.h);

	// Create render texture set
	ovrSwapTextureSet* textureSet;
	if(ovr_CreateSwapTextureSetGL(hmd, GL_RGB, bufferSize.w, bufferSize.h, &textureSet) != ovrSuccess)
		exit(-4);

	// Create Ogre render texture
	Ogre::GLTextureManager* textureManager = static_cast<Ogre::GLTextureManager*>(Ogre::GLTextureManager::getSingletonPtr());
	Ogre::TexturePtr rtt_texture(textureManager->createManual("RttTex", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
		Ogre::TEX_TYPE_2D, bufferSize.w, bufferSize.h, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET));
	Ogre::RenderTexture* rttEyes = rtt_texture->getBuffer(0, 0)->getRenderTarget();
	Ogre::GLTexture* gltex = static_cast<Ogre::GLTexture*>(Ogre::GLTextureManager::getSingleton().getByName("RttTex").getPointer());
	GLuint renderTextureID = gltex->getGLID();

	// Put camera viewport on the ogre render texture
	Ogre::Viewport* vpts[nbEyes];
	vpts[left]=rttEyes->addViewport(cams[left], 0, 0, 0, 0.5f);
	vpts[right]=rttEyes->addViewport(cams[right], 1, 0.5f, 0, 0.5f);
	vpts[left]->setBackgroundColour(Ogre::ColourValue(34, 89, 0)); // Black background
	vpts[right]->setBackgroundColour(Ogre::ColourValue(34, 89, 0));

	ovrTexture* mirrorTexture;
	if(ovr_CreateMirrorTextureGL(hmd, GL_RGB, hmdDesc.Resolution.w, hmdDesc.Resolution.h, &mirrorTexture) != ovrSuccess)
		exit(-5);
	Ogre::TexturePtr mirror_texture(textureManager->createManual("MirrorTex", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
		Ogre::TEX_TYPE_2D, hmdDesc.Resolution.w, hmdDesc.Resolution.h, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET));

	// Get GLIDs
	GLuint ogreMirrorTextureID = static_cast<Ogre::GLTexture*>(Ogre::GLTextureManager::getSingleton().getByName("MirrorTex").getPointer())->getGLID();
	GLuint oculusMirrorTextureID = ((ovrGLTexture*)mirrorTexture)->OGL.TexId;

	// Create EyeRenderDesc
	ovrEyeRenderDesc EyeRenderDesc[nbEyes];
	EyeRenderDesc[left] = ovr_GetRenderDesc(hmd, ovrEye_Left, hmdDesc.DefaultEyeFov[left]);
	EyeRenderDesc[right] = ovr_GetRenderDesc(hmd, ovrEye_Right, hmdDesc.DefaultEyeFov[right]);

	// Get offsets
	ovrVector3f offset[nbEyes];
	offset[left]=EyeRenderDesc[left].HmdToEyeViewOffset;
	offset[right]=EyeRenderDesc[right].HmdToEyeViewOffset;

	// Compositor layer
	ovrLayerEyeFov layer;
	layer.Header.Type = ovrLayerType_EyeFov;
	layer.Header.Flags = 0;
	layer.ColorTexture[left] = textureSet;
	layer.ColorTexture[right] = textureSet;
	layer.Fov[left] = EyeRenderDesc[left].Fov;
	layer.Fov[right] = EyeRenderDesc[right].Fov;
	layer.Viewport[left] = OVR::Recti(0, 0, bufferSize.w/2, bufferSize.h);
	layer.Viewport[right] = OVR::Recti(bufferSize.w/2, 0, bufferSize.w/2, bufferSize.h);

	// Get projection matrices
	for(size_t eyeIndex(0); eyeIndex < ovrEye_Count; eyeIndex++)
	{
		// Get the projection matrix
		OVR::Matrix4f proj = ovrMatrix4f_Projection(EyeRenderDesc[eyeIndex].Fov,
			static_cast<float>(0.01f),
			4000,
			true);

		// Convert it to Ogre matrix
		Ogre::Matrix4 OgreProj;
		for(size_t x(0); x < 4; x++)
			for(size_t y(0); y < 4; y++)
				OgreProj[x][y] = proj.M[x][y];

		// Set the matrix
		cams[eyeIndex]->setCustomProjectionMatrix(true, OgreProj);
	}

	// Variables for render loop
	bool render(true);
	ovrFrameTiming hmdFrameTiming;
	ovrTrackingState ts;
	OVR::Posef pose;
	ovrLayerHeader* layers;

	// Create event listener for handling user input
	createEventListener();

	//Run physics loop in a new thread
	std::map<Ogre::Entity*, Ogre::Vector3> positionRequests;
	std::map<Ogre::Entity*, std::string> animationRequests;
	std::map<Ogre::Entity*, std::vector<int>> rotationRequests;
	std::map<std::string, std::string> message;
	std::thread physicsThread(physicsLoop, smgr, &message, &positionRequests, &animationRequests, &rotationRequests);

	// Render loop
	while(render)
	{
		// Suspend physics loop and perform requested movement/rotations/animations
		if(positionRequests.size() > 0 || animationRequests.size() > 0 || rotationRequests.size() > 0){
			message.insert(std::pair<std::string, std::string>("", ""));
		
			for(auto const &request : positionRequests) {
				Ogre::Vector3 pos = request.second;
				Ogre::SceneNode* sceneNode = request.first->getParentSceneNode();
				sceneNode->setPosition(pos);
			}

			for(auto const &request : animationRequests) {
				request.first->getAnimationState(request.second)->addTime(0.1);
			}

			for(auto const &request : rotationRequests) {
				Ogre::SceneNode* sceneNode = request.first->getParentSceneNode();
				sceneNode->roll(Ogre::Degree(request.second[0]));
				sceneNode->pitch(Ogre::Degree(request.second[1]));
				sceneNode->yaw(Ogre::Degree(request.second[2]));
			}

			positionRequests.clear();
			animationRequests.clear();
			rotationRequests.clear();

			// Resume physics loop
			message.clear();
		}

		// Update Ogre window
		Ogre::WindowEventUtilities::messagePump();

		// Advance textureset index
		textureSet->CurrentIndex = (textureSet->CurrentIndex + 1) % textureSet->TextureCount;
		
		// Capture user input
		mKeyboard->capture();
		mMouse->capture();

		// Movement calculations
		mPlayerNode->translate(mDirection, Ogre::Node::TS_LOCAL);
		hmdFrameTiming = ovr_GetFrameTiming(hmd, 0);
		ts = ovr_GetTrackingState(hmd, hmdFrameTiming.DisplayMidpointSeconds);
		pose = ts.HeadPose.ThePose;
		ovr_CalcEyePoses(pose, offset, layer.RenderPose);
		oculusOrient = pose.Rotation;
		oculusPos = pose.Translation;
		mHeadNode->setOrientation(Ogre::Quaternion(oculusOrient.w, oculusOrient.x, oculusOrient.y, oculusOrient.z) * initialOculusOrientation.Inverse());
		
		// Apply head tracking
		mHeadNode->setPosition(headPositionTrackingSensitivity * Ogre::Vector3(oculusPos.x, oculusPos.y,oculusPos.z));
		
		// Update Ogre viewports
		root->_fireFrameRenderingQueued();
		vpts[left]->update();
		vpts[right]->update();

		// Copy the rendered image to the Oculus Swap Texture
		glCopyImageSubData(renderTextureID, GL_TEXTURE_2D, 0, 0, 0, 0,
		((ovrGLTexture*)(&textureSet->Textures[textureSet->CurrentIndex]))->OGL.TexId, GL_TEXTURE_2D, 0, 0, 0, 0,
		bufferSize.w,bufferSize.h, 1);
		layers = &layer.Header;

		// Submit new frame to the Oculus and update window
		ovr_SubmitFrame(hmd, 0, nullptr, &layers, 1);
		window->update();

		// Exit loop when window is closed
		if(window->isClosed()) render = false;
	}

	// Shud down Oculus
	ovr_Destroy(hmd);
	ovr_Shutdown();

	// Delete Ogre root and return
	delete root;
	return EXIT_SUCCESS;
}