Commits

Anonymous committed 445351b

more fixes

  • Participants
  • Parent commits 41f2f27
  • Branches collision

Comments (0)

Files changed (7)

File src/CMakeLists.txt

 endif()
 
 if (CMAKE_BUILD_TYPE STREQUAL "Debug")
-	ADD_DEFINITIONS(-DTESTING)
+	# uncoment for debug output to console
+	#ADD_DEFINITIONS(-DTESTING)
 endif()
 
 SET_TARGET_PROPERTIES(Game PROPERTIES DEBUG_POSTFIX _d)

File src/GameObjects/CCharacter.cpp

 		bbox.setExtents(-1, boundingRect.bottom, boundingRect.left, 1, boundingRect.top, boundingRect.right );
 		temp->SetBoundingBox(bbox);
 
-/*
+
 		if (!bJumping) {
 			// EXPERIMENTAL: stairs
 
 			translation = goLevel->ResolveCollision(temp, Ogre::Vector2(0, 4.0f));
-			boundingRect.left += translation.x;
-			boundingRect.right += translation.x;
-			boundingRect.top += translation.y;
-			boundingRect.bottom += translation.y;
+			temp->SetPosition(temp->GetPosition() + Ogre::Vector3(0.0f, translation.y, translation.x));
 
 			Ogre::Vector2 trans = goLevel->ResolveCollision(temp, Ogre::Vector2(deltaTime*fSpeed, 0));
-			boundingRect.left += trans.x;
-			boundingRect.right += trans.x;
-			boundingRect.top += trans.y;
-			boundingRect.bottom += trans.y;
+			temp->SetPosition(temp->GetPosition() + Ogre::Vector3(0.0f, trans.y, trans.x));
+
 			translation = translation+trans;
 
 			trans = goLevel->ResolveCollision(temp, Ogre::Vector2(0, -translation.y + deltaTime*fVerticalVelocity));
 			translation = translation + trans;
-		} else {*/
+		} else {
 			translation = Ogre::Vector2(deltaTime * fSpeed, deltaTime * fVerticalVelocity);
 			translation = goLevel->ResolveCollision(temp, translation);
-		//}
+		}
 
 		ogreBodyNode->translate(0.0f, translation.y, translation.x, Ogre::Node::TS_LOCAL);
 		CheckFloatZero(translation.x); CheckFloatZero(translation.y);

File src/GameObjects/CLevelData.cpp

 
 	while (!bResolveFinished) {
 
-		if (AlmostEqual(currentTranslation.x, 0.0f) && AlmostEqual(currentTranslation.y, 0.0f)) {
+		if (approximatelyEqual(currentTranslation.x, 0.0f) && approximatelyEqual(currentTranslation.y, 0.0f)) {
 			bResolveFinished = true;
 			continue;
 		}
 
 		// III. get maximum translation without collision
 
-		Game::Face* nearestFace;
+		Game::Face nearestFace;
 		PLevelObject nearestObj;
 		float nearestFactor;
 		bool bNotFound = true;
 
 					Game::Polygon facePoly(objFaces[i]);
 					std::pair<bool, float> result = objectPolygon.TranslationIntersect(facePoly, currentTranslation);
-					TEST_LOG(result.first << ", " << result.second);
-					if (result.first && result.second >= 0.0f) {
+					TEST_LOG(result.first << ", " << result.second << " " << objFaces[i]);
+					if (result.first && result.second >= -0.0f) {
 						 // find nearest collision
 						if (bNotFound || fabs(nearestFactor) > fabs(result.second)) {
 							bNotFound = false;
-							nearestFace = &objFaces[i];
+							nearestFace = objFaces[i];
 							nearestFactor = result.second;
 							nearestObj = obj;
 							TEST_LOG("found collision");
 			}
 
 			if (!bNotFound) {
-				/*if (AlmostEqual(nearestFactor, 0.0f)) {
+				/*if (approximatelyEqual(nearestFactor, 0.0f)) {
 					// can't move; abort
 					TEST_LOG("nearestFactor = 0");
 					currentTranslation = Ogre::Vector2::ZERO;
 		 * if any collision occurs along our way, we cancel and try to resolve that collision.
 		 */
 
-		Ogre::Vector2 faceDirection = nearestFace->v2 - nearestFace->v1;
-		Game::Polygon facePoly(*nearestFace);
+		TEST_LOG("nearestface= " << nearestFace);
+
+		Ogre::Vector2 faceDirection = nearestFace.v2 - nearestFace.v1;
+		Game::Polygon facePoly(nearestFace);
 
 		// possible separating axes are UNIT_X, UNIT_Y, facedirection
 		std::vector<Ogre::Vector2> separatingAxes;
 		separatingAxes.push_back(Ogre::Vector2::UNIT_Y);
 
 		// make sure faceDirection is not a mulitple of UNIT_X or UNIT_Y
-		if (!(AlmostEqual(faceDirection.x, 0.0f)) && !AlmostEqual(faceDirection.y, 0.0f))
+		if (!approximatelyEqual(faceDirection.x, 0.0f) && !approximatelyEqual(faceDirection.y, 0.0f))
 			separatingAxes.push_back(faceDirection);
 
 		// find separating axis
 		Ogre::Vector2 separatingAxis(0.0f, 0.0f);
 		for (int i = 0; i < separatingAxes.size(); i++) {
-			SATResult result = objectPolygon.IsSeparatingAxis(facePoly, separatingAxes[i]);
-			if (result.IsSeparating || AlmostEqual(result.MinimumOverlap, 0.0f)) {
+			SATResult satResult = objectPolygon.IsSeparatingAxis(facePoly, separatingAxes[i]);
+			if (satResult.IsSeparating || approximatelyEqual(satResult.MinimumOverlap, 0.0f)) {
 				separatingAxis = separatingAxes[i].normalisedCopy();
 				separatingAxes.erase(separatingAxes.begin() + i);
+				TEST_LOG("sep axis = " << separatingAxis);
+				TEST_LOG("SAT Result: " << satResult.IsSeparating << "; " << satResult.MinimumOverlap << "; " << satResult.MaximumOverlap);
 				break;
 			}
 		}
 
-		TEST_LOG("sep axis = " << separatingAxis);
+		TEST_LOG("remaining axes: " << separatingAxes.size());
 
 		// make separatingAxis face in same direction as currentTranslation
 		if (separatingAxis.dotProduct(currentTranslation) < 0.0f)
 		// find minimum translation to "create" a new separating axis
 		float minFactor = std::numeric_limits<float>::infinity();
 		for (int i = 0; i < separatingAxes.size(); i++) {
-			SATResult result = objectPolygon.IsSeparatingAxis(facePoly, separatingAxes[i]);
-			if (!result.IsSeparating) {
+			SATResult satResult = objectPolygon.IsSeparatingAxis(facePoly, separatingAxes[i]);
+			if (!satResult.IsSeparating) {
 				// get minimum translation vector in direction of currentTranslation
 				Ogre::Vector2 axisNormal = LeftHandNormal(separatingAxes[i]);
-				Ogre::Vector2 MTV = result.MinimumOverlap * axisNormal;
+				Ogre::Vector2 MTV = satResult.MinimumOverlap * axisNormal;
 				if (MTV.dotProduct(currentTranslation) < 0)
-					MTV = result.MaximumOverlap * axisNormal;
+					MTV = satResult.MaximumOverlap * axisNormal;
 
 				float factor;
-				if (AlmostEqual(separatingAxis.y, 0.0f) || (MTV.x > MTV.y && !AlmostEqual(separatingAxis.x, 0.0f)))
+				if (approximatelyEqual(separatingAxis.y, 0.0f) || (MTV.x > MTV.y && !approximatelyEqual(separatingAxis.x, 0.0f)))
 					factor = MTV.x / separatingAxis.x;
 				else
 					factor = MTV.y / separatingAxis.y;
 
 				if (fabs(minFactor) > fabs(factor))
 					minFactor = factor;
+			} else {
+				TEST_LOG("found another sep. axis: " << separatingAxes[i]);
+				TEST_LOG("SAT Result: " << satResult.IsSeparating << "; " << satResult.MinimumOverlap << "; " << satResult.MaximumOverlap);
 			}
 		}
 
 		if (minFactor == std::numeric_limits<float>::infinity()) {
 			// error, abort
-			TEST_LOG("minFactur=inf");
+			TEST_LOG("minFactor=inf");
 			bResolveFinished = true;
 			continue;
 		}
 		currentTranslation = factor*separatingAxis*(1.0f + TOLERANCE);
 
 		// if we already visited that face, we dont want to move in opposite direction
-		if (visitedFaces.find(*nearestFace) != visitedFaces.end()) {
+		if (visitedFaces.find(nearestFace) != visitedFaces.end()) {
 			// check if we are moving backwards
-			float dp = visitedFaces[*nearestFace].dotProduct(currentTranslation);
+			float dp = visitedFaces[nearestFace].dotProduct(currentTranslation);
 			if (dp < 0) {
 				// cancel
 				TEST_LOG("dotProduct < 0");
 				return result;
 			}
 		} else {
-			visitedFaces[*nearestFace] = currentTranslation;
+			visitedFaces[nearestFace] = currentTranslation;
 		}
 
 		TEST_LOG("currentTranslation = " << currentTranslation);

File src/GameObjects/Geometry.cpp

 /** Performs separating axis test for a given axis and polygon
 @return Test Result; see Polygon::SATResult */
 SATResult Polygon::IsSeparatingAxis(const Polygon& polygon, const Ogre::Vector2& axis) const {
-	if (this->FaceCount() < 1 || polygon.FaceCount() < 1) {
+	if (this->Points.size() < 1 || polygon.Points.size() < 1) {
 		return SATResult(true, 0.0f, 0.0f);
 	}
 
 	float det =  -(this->Direction.x * ray.Direction.y) + (this->Direction.y * ray.Direction.x);
 
 	// if det(A) is 0 the rays are parallel
-	if (AlmostEqual(det, 0.0f))
+	if (approximatelyEqual(det, 0.0f))
 		return std::pair<bool, float>(false, 0.0f);
 
 	Ogre::Vector2 y = ray.Origin - this->Origin;

File src/GameObjects/Geometry.h

 #ifndef GEOMETRY_H_
 #define GEOMETRY_H_
 
+#include "../testlog.h"
 #include "Ogre.h"
 #include <vector>
 
 /** Maximum allowed absolute rounding error */
 const float TOLERANCE = 0.001f;
 
-/** Maximum allowed ULPs (Units of Least Precision) when comparing floats */
-const int MAX_ULPS = 10000;
-
-/** Check if two floats are almost equal
-Sources:
-* http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
-* http://stackoverflow.com/questions/17333/most-effective-way-for-float-and-double-comparison */
-/*inline bool AlmostEqual(float A, float B)
-{
-    // If A or B are infinity (positive or negative) then
-    // only return true if they are exactly equal to each other -
-    // that is, if they are both infinities of the same sign.
-    // This check is only needed if you will be generating
-    // infinities and you don't want them 'close' to numbers
-    // near FLT_MAX.
-    if (std::isinf(A) || std::isinf(B))
-        return A == B;
-
-    int aInt = *(int*)&A;
-    // Make aInt lexicographically ordered as a twos-complement int
-    if (aInt < 0)
-        aInt = 0x80000000 - aInt;
-    // Make bInt lexicographically ordered as a twos-complement int
-    int bInt = *(int*)&B;
-    if (bInt < 0)
-        bInt = 0x80000000 - bInt;
-
-    // Now we can compare aInt and bInt to find out how far apart A and B
-    // are.
-    int intDiff = abs(aInt - bInt);
-    if (intDiff <= MAX_ULPS)
-        return true;
-    return false;
-}
-*/
-inline bool AlmostEqual(float A, float B)
-{
-    if (A == B)
-        return true;
-
-    float relativeError;
-
-    if (fabs(B) > fabs(A))
-        relativeError = fabs((A - B) / B);
-    else
-        relativeError = fabs((A - B) / A);
-
-    if (relativeError <= TOLERANCE)
-        return true;
-    return false;
-}
-
 /** Source: The Art of computer programming Vol 2 */
 
 inline bool approximatelyEqual(float a, float b) {

File test/GeometryTest.cpp

 	result2 = poly2.SeparatingAxesTest(poly1);
 	BOOST_CHECK_EQUAL(result2.first, false);
 	FLOAT_CHECK_EQUAL(result2.second, Ogre::Vector2::UNIT_X*0.5f);
+
+
+	//202: ResolveCollision: (286.962, -5.5, 289.962, -14.5) Vector2(0.880605, -0.07865)
+	//337: 1, -0 Face( Vector2(290, -14.5); Vector2(280, -14.5); Vector2(0, 1) )
+	rect.left = 286.583f; rect.top = -5.5f;
+	rect.right = 289.583f; rect.bottom = -14.5f;
+	poly1 = Game::Polygon(rect);
+	Game::Face fc(Ogre::Vector2(290.0f, -14.5f), Ogre::Vector2(280.0f, -14.5f), Ogre::Vector2(0,1));
+	poly2 = Game::Polygon(fc);
+
+	// both axes should not be separating, but minimum overlap should be near zero
+	result = poly1.IsSeparatingAxis(poly2, Ogre::Vector2::UNIT_X);
+	BOOST_CHECK_EQUAL(result.IsSeparating, false);
+	FLOAT_CHECK_EQUAL(result.MinimumOverlap, 0.0f);
+	result = poly1.IsSeparatingAxis(poly2, Ogre::Vector2::UNIT_Y);
+	BOOST_CHECK_EQUAL(result.IsSeparating, false);
+	result = poly1.IsSeparatingAxis(poly2, Ogre::Vector2::NEGATIVE_UNIT_X);
+	BOOST_CHECK_EQUAL(result.IsSeparating, false);
+	FLOAT_CHECK_EQUAL(result.MinimumOverlap, 0.0f);
+	result = poly1.IsSeparatingAxis(poly2, Ogre::Vector2::NEGATIVE_UNIT_Y);
+	BOOST_CHECK_EQUAL(result.IsSeparating, false);
 }
 
 BOOST_AUTO_TEST_CASE( polygon_intersection_test2 )
 };
 
 #define FLOAT_WARN_EQUAL(A, B) \
-    BOOST_WARN_WITH_ARGS_IMPL(::Test::check_float_equality(), \
-        "", WARN, WARN_EQUAL, (A)(B));
+	BOOST_CHECK_WITH_ARGS_IMPL(::Test::check_float_equality(), \
+        "", WARN, CHECK_EQUAL, (A)(B));
 
 #define FLOAT_CHECK_EQUAL(A, B) \
     BOOST_CHECK_WITH_ARGS_IMPL(::Test::check_float_equality(), \
         "", CHECK, CHECK_EQUAL, (A)(B));
 
 #define FLOAT_REQUIRE_EQUAL(A, B) \
-    BOOST_REQUIRE_WITH_ARGS_IMPL(::Test::check_float_equality(), \
+	BOOST_CHECK_WITH_ARGS_IMPL(::Test::check_float_equality(), \
         "", REQUIRE, CHECK_EQUAL, (A)(B));
 
 }