Пример #1
0
void Physics::collisionDetectionTute()
{
	if (glfwGetMouseButton(m_window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS && timer > timerLimit)
	{
		int width = 0, height = 0;
		glfwGetWindowSize(glfwGetCurrentContext(), &width, &height);
		float aspectRatio = (float)width / (float)height;
		double mouseX;
		double mouseY;
		glfwGetCursorPos(m_window, &mouseX, &mouseY);
		float mouseZ;
		glReadPixels(mouseX, mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &mouseZ);
		glm::vec3 screenCoord(mouseX, mouseY, mouseZ);

		glm::mat4 projectionM = m_camera.view * m_camera.proj;
		glm::mat4 invPM = glm::inverse(projectionM);

		glm::vec4 viewport;
		float winZ = 1.0f;

		viewport.x = (2.0f*((float)(mouseX - 0) / ((float)width - 0))) - 1.0f;
		viewport.y = 1.0f - (2.0f*((float)(mouseY - 0) / ((float)height - 0)));
		viewport.z = 2.0f * winZ - 1.0f;
		viewport.w = 1.0f;

		glm::vec4 worldPos = viewport * invPM;

		worldPos.x *= simSize;
		worldPos.y *= simSize;

		glm::vec3 endPos = glm::vec3(whiteBall->position, 0);
		direction = worldPos.xy - endPos.xy;
		selectedPower = glm::length(direction);
		direction = glm::normalize(direction);
		if (selectedPower > MAX_SHOT_POWER)
		{
			selectedPower = MAX_SHOT_POWER;
		}
		Gizmos::add2DLine(whiteBall->position, whiteBall->position+ direction.xy * selectedPower, glm::vec4(1, 1, 1, 1));
		shot = true;
	}
	if (glfwGetMouseButton(m_window, GLFW_MOUSE_BUTTON_1) == GLFW_RELEASE && shot && timer > timerLimit)
	{
		whiteBall->velocity += -1.0f*direction.xy * selectedPower * selectedPower;
		shot = false;
		timer = 0.0f;
	}
}
Пример #2
0
	void BasicRaytracer::Raytrace()
	{
		assert(nullptr != m_Camera);
		assert(nullptr != m_FrameBuffer);

		const float screenWidth = (float)m_FrameBuffer->GetWidth();
		const float screenHeight = (float)m_FrameBuffer->GetHeight();

		const float nearClipPlaneDistance = m_Camera->GetNearClipPlaneDistance();
		const float aspectRatio = screenWidth / screenHeight;
		const float halfFov = m_Camera->GetYFov() * 0.5f;

		const float top = nearClipPlaneDistance * tan(MATHLIB_DEG_TO_RAD(halfFov));
		const float right = top * aspectRatio;

		// Now we need to transform the direction into world space.
		vector4& camera_xAxis = m_Camera->GetXAxis();
		vector4& camera_yAxis = m_Camera->GetYAxis();
		vector4& camera_zAxis = m_Camera->GetZAxis();

		matrix4x4 rotationMatrix
		(
			camera_xAxis.extractX(), camera_yAxis.extractX(), camera_zAxis.extractX(), 0.0f,
			camera_xAxis.extractY(), camera_yAxis.extractY(), camera_zAxis.extractY(), 0.0f,
			camera_xAxis.extractZ(), camera_yAxis.extractZ(), camera_zAxis.extractZ(), 0.0f,
			0.0f, 0.0f, 0.0f, 1.0f
		);

		// First project the point onto the near clip plane (in camera space of course)
		matrix4x4 screenCoordToNearPlaneB
		(
			right, 0.0f, 0.0f, 0.0f,
			0.0f, top, 0.0f, 0.0f,
			0.0f, 0.0f, 1.0f, 0.0f,
			0.0f, 0.0f, 0.0f, 1.0f
		);

		matrix4x4 screenCoordToNearPlaneA
		(
			2.0f / (screenWidth - 1.0f), 0.0f, 0.0f, -1.0f,
			0.0f, -2.0f / (screenHeight - 1.0f), 0.0f, +1.0f,
			0.0f, 0.0f, 0.0f, -nearClipPlaneDistance,
			0.0f, 0.0f, 0.0f, 1.0f
		);

		matrix4x4 transform;
		matrix4x4_mul(screenCoordToNearPlaneB, screenCoordToNearPlaneA, transform);

		float* currentFrameBufferPosition = m_FrameBuffer->GetData();

		HighPerformanceTimer timer;
		timer.Start();

		auto& debugManager = Debugging::DebugManager::GetInstance();

		for (int y = 0; y < screenHeight; y++)
		{
			for (int x = 0; x < screenWidth; x++)
			{
				if (x == (screenWidth * 0.5f) && y == (screenHeight * 0.5f))
					debugManager.SetEnabled(false);

				vector4 screenCoord((float)x, (float)y, 0.0f, 1.0f);
				vector4 cameraSpaceDirection;

				matrix4x4_vectorMul(transform, screenCoord, cameraSpaceDirection);
				vector4_setToVector(cameraSpaceDirection);

				matrix4x4_vectorMul(rotationMatrix, cameraSpaceDirection, cameraSpaceDirection);
				vector4_normalize(cameraSpaceDirection);

				// Transfer position and direction across to ray.
				ray worldSpaceRay;
				worldSpaceRay.setPosition(m_Camera->GetPosition());
				worldSpaceRay.setDirection(cameraSpaceDirection);

				// Intersect world with ray.
				float t;
				m_Scene->Trace(worldSpaceRay, &t, currentFrameBufferPosition);

				currentFrameBufferPosition += 4;

				//printf("[%i][%i] traced...\n", x, y);

				debugManager.SetEnabled(false);
			}
		}

		timer.Stop();
		printf("Total trace time: %4.2Lf msecs\n", timer.GetTimeMilliseconds());
		printf("Average ray time: %4.5Lf microseconds\n", timer.GetTimeMicroseconds() / (screenWidth * screenHeight));
		getchar();
	}
void NewXZRotExperimentHCI::update(const std::vector<MinVR::EventRef> &events){

	//later to be pass into closestTouchPair function
	glm::dvec3 pos1;
	glm::dvec3 pos2;
	double minDistance = DBL_MAX; 
	MinVR::TimeStamp timestamp;

	//boolean flags
	bool xzTrans = false;
	glm::dmat4 xzTransMat = dmat4(0.0);
	bool yTrans = false;
	glm::dmat4 yTransMat = dmat4(0.0);
	bool yRotScale = false;

	numTouchForHand1 = 0;
	numTouchForHand2 = 0;

	 //only update the map and other variables first
	for(int p = 0; p < events.size(); p++) {

		
		timestamp = events[p]->getTimestamp();
		std::string name = events[p]->getName();
		int id = events[p]->getId();


		if (boost::algorithm::starts_with(name, "TUIO_Cursor_up")) {
			 //delete the cursor down associated with this up event
			std::map<int, TouchDataRef>::iterator it = registeredTouchData.find(id); 

			if (it != registeredTouchData.end()) { // if id is found
				registeredTouchData.erase(it);	   //erase value associate with that it
				//std::cout << "UP" <<std::endl;
			} else {
				std::cout<<"ERROR: Received touch up for a cursor not in the registered touch data!"<<std::endl;
				std::cout << events[p]->toString() << std::endl;
				for (auto iter = registeredTouchData.begin(); iter != registeredTouchData.end(); iter++) {
					std::cout << "\t" << iter->second->toString() << std::endl;
				}
			}

		} else if (boost::algorithm::starts_with(name, "TUIO_Cursor_down")) {
			// always add a new one on DOWN
			glm::dvec3 roomCoord = convertScreenToRoomCoordinates(events[p]->get2DData());
			TouchDataRef datum(new TouchData(events[p], roomCoord));
			registeredTouchData.insert(std::pair<int, TouchDataRef>(id, datum));
			//std::cout << "DOWN " << glm::to_string(events[p]->get2DData()) <<std::endl;


		} else if (boost::algorithm::starts_with(name, "TUIO_CursorMove")) {
			 //update the map with the move event
			// if the corresponding id was down, make it a move event
			std::map<int, TouchDataRef>::iterator it = registeredTouchData.find(id); 
			//std::cout << "Move " << events[p]->getId() <<std::endl;

			if (it != registeredTouchData.end()) { // if id is found
				glm::dvec2 screenCoord (events[p]->get4DData());
				glm::dvec3 roomCoord = convertScreenToRoomCoordinates(glm::dvec2(events[p]->get4DData()));

				// update map
				it->second->setCurrentEvent(events[p]);
				it->second->setCurrRoomPos(roomCoord);
			}

		}
		// end of TUIO events

		// Update hand positions
		if (name == "Hand_Tracker1") {
			//std::cout << "Inside hand tracking 1 event (xz) " << std::endl;
			//only enter one time to init prevHandPos1
			if (prevHandPos1.y == -1.0) {
				glm::dvec3 currHandPos1 (events[p]->getCoordinateFrameData()[3]);
				prevHandPos1 = currHandPos1;
				initRoomPos = true;
			} else {
				//std::cout << "updating hand 1 curr and prev position  " << std::endl;
				prevHandPos1 = currHandPos1;
				currHandPos1 = glm::dvec3(events[p]->getCoordinateFrameData()[3]);
			} 
		} 
		

		//std::cout<<"currHandPos1: "<<glm::to_string(currHandPos1)<<std::endl;
		//std::cout<<"prevHandPos1: "<<glm::to_string(prevHandPos1)<<std::endl;

		if(name == "Hand_Tracker2") {
			//std::cout << "Inside hand tracking 2 event (xz) " << std::endl;
			if (prevHandPos2.y == -1.0) {
				glm::dvec3 currHandPos2 (events[p]->getCoordinateFrameData()[3]);
				prevHandPos2 = currHandPos2;
			} else {
				//std::cout << "updating hand 2 curr and prev position  " << std::endl;
				prevHandPos2 = currHandPos2;
				currHandPos2 = glm::dvec3(events[p]->getCoordinateFrameData()[3]);
			} 
		}
	} // end of data-updating for loop
	
	// give feedback object the touch data so
	 //it can draw touch positions
	feedback->registeredTouchData = registeredTouchData;

	// At this point, the touch data should be updated, and hand positions
	std::map<int, TouchDataRef>::iterator iter;
	for (iter = registeredTouchData.begin(); iter != registeredTouchData.end(); iter++) {

		glm::dvec3 currRoomPos (iter->second->getCurrRoomPos());
		bool belongsToHand1 = (glm::length(currHandPos1 - currRoomPos) <  glm::length(currHandPos2 - currRoomPos));
		
		if (belongsToHand1) {
			numTouchForHand1++;
			if(iter->second->getBelongTo() == -1){
				iter->second->setBelongTo(1);
			}
		} 
		else { // belongs to hand 2
			numTouchForHand2++;
			if(iter->second->getBelongTo() == -1){
				iter->second->setBelongTo(2);
			}
		}
	} // end touch enumeration
	 //from TUIO move
	

	
	//std::cout << "Touch size: " << registeredTouchData.size() << std::endl;
	 //find closest pair of TouchPoints
	if (registeredTouchData.size() > 1) {
		closestTouchPair(registeredTouchData , pos1, pos2, minDistance);

		//std::cout << "Min distance: " << minDistance << std::endl;
		
	}

	
	

	if (minDistance < 0.06 && currHandPos1 != prevHandPos1) {
		
		xzRotFlag = true;
		//std::cout << "Inside XZRot Mode" << std::endl;

	}

	if (xzRotFlag && liftedFingers) { // might have to be xzRotFlag and not any other flag 

		feedback->displayText = "rotating";

		if(initRoomPos){
			// pos1 and pos2 are where you put your fingers down. We're finding the centroid
			 //to calculate the box boundary for xzRotMode
			initRoomTouchCentre = 0.5*(pos1 + pos2); 
			initRoomPos = false;

		}

		// try to change around center of origin
		glm::dvec3 centOfRot (glm::dvec3((glm::column(cFrameMgr->getVirtualToRoomSpaceFrame(), 3))));
		//calculate the current handToTouch vector
		
		if(registeredTouchData.size() > 1 && !centerRotMode) {
			roomTouchCentre = 0.5*(pos1 + pos2);
		}
		
		//std::cout << "Touch Center: " << glm::to_string(roomTouchCentre) << std::endl; 

		//Should not be equal in XZRotMode but just in case.
		 //for choosing the hand that rotates
		/*std::cout<<"currHandPos1: "<<glm::to_string(currHandPos1)<<std::endl;*/


		if (numTouchForHand1 >= numTouchForHand2) { 
			//std::cout << "Using right hand: " << std::endl; 
			if (roomTouchCentre - currHandPos1 != glm::dvec3(0.0)) {//zero guard
				currHandToTouch = roomTouchCentre - currHandPos1;
			}

			if (roomTouchCentre - prevHandPos1 != glm::dvec3(0.0)) {//zero guard
				prevHandToTouch = roomTouchCentre - prevHandPos1;
			}

		} else {
			//std::cout << "Using Left hand: " << std::endl;

			if (roomTouchCentre - currHandPos2 != glm::dvec3(0.0)) { //zero guard
				currHandToTouch = roomTouchCentre - currHandPos2;
			}

			if (roomTouchCentre - prevHandPos2 != glm::dvec3(0.0)) { //zero guard
				prevHandToTouch = roomTouchCentre - prevHandPos2;
			}
		}


		//set up the 2 vertices for a square boundry for the gesture
		glm::dvec3 upRight = glm::dvec3(initRoomTouchCentre.x+0.2, 0.0, initRoomTouchCentre.z+0.2);
		glm::dvec3 lowLeft = glm::dvec3(initRoomTouchCentre.x-0.2, 0.0, initRoomTouchCentre.z-0.2);


		 //this if-else block for setting xzRotFlag,
		 //also for grabbing xzCentOfRot
		if(registeredTouchData.size() == 0) { //if no touch on screen then automatically exit the xzrot mode
			xzRotFlag = false;
			initRoomPos = true;
			liftedFingers = true;
			feedback->displayText = "";
			feedback->centOfRot.x = DBL_MAX;
			//std::cout<<"no touchyyy so I quit"<<std::endl;
		}
		else { //if there are touch(s) then check if the touch is in bound of the rectangle

			bool setxzRotFlag = true;
			std::map<int, TouchDataRef>::iterator iter;
			int countFingers = 0;
			for (iter = registeredTouchData.begin(); iter != registeredTouchData.end(); iter++) {
				

				// not exactly sure why roomPos. > upRight.z , I think it should be <. but that doesn't work
				if(!(iter->second->getCurrRoomPos().x > upRight.x || iter->second->getCurrRoomPos().z > upRight.z ||iter->second->getCurrRoomPos().x < lowLeft.x ||iter->second->getCurrRoomPos().z < lowLeft.z)){ //you are in the box

					//std::cout << "fingers in bound so STILL IN XZRot Mode" << std::endl;
					setxzRotFlag = false; 
					countFingers += 1;

				} //else{ // touch point not in box, assume as center of rotation
				//	centOfRot = iter->second->getCurrRoomPos();
				//	centerRotMode = true;
				//	//std::cout << "Cent of Rot set" << std::endl;
				//	feedback->centOfRot = centOfRot;
				//}

				// only tries to change the xzRotFlag at the end of the data in the map
				if(iter == std::prev(registeredTouchData.end(),1) && setxzRotFlag) {
					xzRotFlag = false;
					initRoomPos = true;
					feedback->displayText = ""; 
					feedback->centOfRot.x = DBL_MAX;
					//std::cout << "all fingers went out of bound so Out of XZRot Mode" << std::endl;

					// found bug where person just drags their fingers across the table, and it reinitiates xzRotMode
					liftedFingers = false;
				}
			} // end for loop over registeredTouchData

			if(countFingers == registeredTouchData.size()){//all fingers in bound 
				centerRotMode = false;
				feedback->centOfRot.x = DBL_MAX;
			}

		} // end if/else block

		
		//std::cout<<"currHandToTouch: "<<glm::to_string(currHandToTouch)<<std::endl;
		//std::cout<<"prevHandToTouch: "<<glm::to_string(prevHandToTouch)<<std::endl;
		//std::cout<<"dot product of them: "<< glm::to_string(glm::dot(glm::normalize(currHandToTouch), glm::normalize(prevHandToTouch))) << std::endl;
		
			
			//std::cout<<"what we clamping: "<<glm::clamp(glm::dot(currHandToTouch, prevHandToTouch),-1.0,1.0)<<std::endl;

			double alpha = glm::acos(glm::clamp(glm::dot(glm::normalize(currHandToTouch), glm::normalize(prevHandToTouch)),-1.0,1.0)); // from 0 to pi
			//std::cout<<"alpha: " << alpha << std::endl;

			// get cross prod
			
			glm::dvec3 cross = glm::normalize(glm::cross(currHandToTouch, prevHandToTouch)); 
			//std::cout<<"cross: "<<glm::to_string(cross)<<std::endl;
			glm::dvec3 projCross = glm::normalize(glm::dvec3(cross.x, 0.0, cross.z)); // projection
			//std::cout<<"projcross: "<<glm::to_string(projCross)<<std::endl;

			// project cross prod onto the screen, get a length
			
			double lengthOfProjection = glm::dot(cross, projCross); 
			//std::cout<<"lengthOfProjection: "<<glm::to_string(lengthOfProjection)<<std::endl;
			// projected cross prod 
			//glm::dvec3 projectedCrossProd = lengthOfProjection * normProjCross; 

			//std::cout<<"lengthOfProjection: "<<lengthOfProjection<<std::endl;
			//std::cout<<"alpha in degree before times lengthofprojection: "<<glm::degrees(alpha)<<std::endl;

			alpha = alpha * lengthOfProjection;

			//std::cout<<"alpha in degree after: "<<glm::degrees(alpha)<<std::endl;
			//std::cout<<"normProjCross: "<<glm::to_string(normProjCross)<<std::endl;

			glm::dmat4 XZRotMat = glm::rotate(glm::dmat4(1.0), glm::degrees(alpha) /* * 2.0 */, glm::normalize(projCross));

			// have translations when we have a touch point not in the bounding box

			// translate to origin
			glm::dmat4 transMat(glm::translate(glm::dmat4(1.0), -1.0*centOfRot));
			 //translate back
			glm::dmat4 transBack(glm::translate(glm::dmat4(1.0), centOfRot));	

			 //put it into the matrix stack	
			//std::cout<<"XZRotMat: "<<glm::to_string(XZRotMat) <<std::endl;
			
			cFrameMgr->setRoomToVirtualSpaceFrame(cFrameMgr->getRoomToVirtualSpaceFrame() * transBack * XZRotMat * transMat);
		

	} // end xzRot Gesture

	
	

	



	if(registeredTouchData.size() == 0) {
		feedback->displayText = "";
		liftedFingers = true;
	}

	 //this is bret's commented out line
	//updateHandPos(events);
}