⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iogrecollisionshape.cpp

📁 opcode是功能强大
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			{
				Ogre::Vector3 velocity = movementVector;
				Ogre::Vector3 base = position;

				Ogre::Real velocitySqaredLength = (Ogre::Real)velocity.squaredLength();
				Ogre::Real a,b,c;
				Ogre::Real newT;

				// for each edge or vertex a quadratic equation has to be solved:
				// a*t^2 + b*t + c = 0. We calculate a,b, and c for each test.

				// check against points
				a = velocitySqaredLength;

				// FIXME: turn these 3 into 1 function
				// p1
				b = 2.0f * (velocity.dotProduct(base - triangle.point(0)));
				c = (Ogre::Real)((triangle.point(0)-base).squaredLength() - 1.0);
				if (getLowestRoot(a,b,c,t, &newT))
				{
					t = newT;
					foundCollision = true;
					collisionPoint = triangle.point(0);
				}

				// p2
				if (!foundCollision)
				{
					b = 2.0f * (velocity.dotProduct(base - triangle.point(1)));
					c = (Ogre::Real)((triangle.point(1)-base).squaredLength() - 1.0);
					if (getLowestRoot(a,b,c,t, &newT))
					{
						t = newT;
						foundCollision = true;
						collisionPoint = triangle.point(1);
					}
				}

				// p3
				if (!foundCollision)
				{
					b = 2.0f * (velocity.dotProduct(base - triangle.point(2)));
					c = (Ogre::Real)((triangle.point(2)-base).squaredLength() - 1.0);
					if (getLowestRoot(a,b,c,t, &newT))
					{
						t = newT;
						foundCollision = true;
						collisionPoint = triangle.point(2);
					}
				}

				// check against edges:

				Ogre::Vector3 edge;
				Ogre::Vector3 baseToVertex;

				edge = triangle.point(1) - triangle.point(0);
				baseToVertex = triangle.point(0) - position;

				Vector3 point = triangle.point(0);
				sphereEdgeCheck(velocity, edge, baseToVertex, t, foundCollision, collisionPoint, point);

				edge = triangle.point(2) - triangle.point(1);
				baseToVertex = triangle.point(1) - position;

				point = triangle.point(1);
				sphereEdgeCheck(velocity, edge, baseToVertex, t, foundCollision, collisionPoint, point);

				edge = triangle.point(0) - triangle.point(2);
				baseToVertex = triangle.point(2) - position;

				point = triangle.point(2);
				sphereEdgeCheck(velocity, edge, baseToVertex, t, foundCollision, collisionPoint, point);

			}// end no collision found


			// set result:
			if (foundCollision)
			{
				// Time to scale everything back..

				// distance to collision is t
				Ogre::Real distToCollision = (Ogre::Real)(t*movementVector.length() * radius);

				// does this triangle qualify for closest hit?
				if (distToCollision	<= cp->distance)
				{
					cp->distance = distToCollision;
					cp->contact = collisionPoint * radius;
					cp->other_contact = cp->contact;
					cp->this_contact = (position + (movementVector*t))*radius;

					cp->other_normal = trianglePlane.normal;
					Ogre::Vector3 vec_to_col = cp->contact - cp->this_contact;
					cp->this_normal = vec_to_col.normalisedCopy();
				}

				return true;
			}// end found collision
		}// end if is front facing

		return false;
	}


/////////////////////////////////////////////////////////////////////////////////////




	//------------------------------------------------------------------------
	/// Check contact of a sphere with shape.
	/// The collType is interpreted as follows:
	/// - COLLTYPE_IGNORE:        illegal (makes no sense)
	/// - COLLTYPE_QUICK:         first contact check only
	/// - COLLTYPE_CONTACT:       return closest contact
	/// - COLLTYPE_EXACT:         return a sorted list of contacts
	/// Currently, sphere checks always work in first constact mode (COLLTYPE_QUICK).
	/// @param  collType        see above
	/// @param  ownMatrix       position/orientation of this shape
	/// @param  ball          sphere definition in world space
	/// @param  collPair      will be filled with result
	/// @return                 true if line intersects shape
	bool ICollisionShape::sphereCheck(CollisionType collType,
		const Matrix4& ownMatrix,
		const Sphere& ball,
		CollisionPair& collPair)
	{
		assert(COLLTYPE_IGNORE != collType);

		// setup sphere collider
		Opcode::SphereCollider& collider = CollisionManager::getSingletonPtr()->opcSphereCollider;
		Opcode::SphereCache& cache = CollisionManager::getSingletonPtr()->opcSphereCache;

		switch (collType)
		{
		case COLLTYPE_QUICK:
		case COLLTYPE_CONTACT:
			collider.SetFirstContact(true);
			break;

		case COLLTYPE_EXACT:
			collider.SetFirstContact(false);
			break;

		default:
			break;
		}

		// convert Matrix4 to Opcode Matrix4x4
		IceMaths::Matrix4x4 opcMatrix;
		IceMaths::Matrix4x4 *ptrOpcMatrix = &opcMatrix;
		OgreOpcodeUtils::ogreToIceMatrix4( ownMatrix, opcMatrix);

		// build identity matrix because sphere is already in world space
		IceMaths::Matrix4x4 identity;
		IceMaths::Matrix4x4 *ptrIdentity = &identity;
		identity.Identity();

		IceMaths::Sphere opcSphere;
		OgreOpcodeUtils::ogreToIceSphere(ball, opcSphere);

		// validate settings: asserts that we can check collision
		// another option is to display some annoying error windows using: Ogre::String(collider.ValidateSettings() )
		assert( collider.ValidateSettings() == 0 );

		// perform collision
		if( !collider.Collide(cache, opcSphere, opcModel, ptrIdentity, ptrOpcMatrix) )
			return false;

		collPair.numBVBVTests = collider.GetNbVolumeBVTests();
		collPair.numBVPrimTests = collider.GetNbVolumePrimTests();
		collPair.numPrimPrimTests = 0;

		// get collision result
		if (collider.GetContactStatus())
		{
			// fill out contact point and collision normal of closest contact
			const udword* collFaces = collider.GetTouchedPrimitives();
			int numFaces = collider.GetNbTouchedPrimitives();
			//LogManager::getSingleton().logMessage("sphereCheck returned " + StringConverter::toString(numFaces) + " numfaces");
			if (numFaces > 0)
			{
				for(int i = 0; i < numFaces; i++)
				{
					//assert(1 == numFaces);

					// build triangle from from faceIndex
					Vector3 v0,v1,v2;
					getTriCoords(collFaces[i], v0, v1, v2);

					// Compute the centered normal
					Vector3 vCenter = (v0+v1+v2)*0.33333333333333333333f;
					Vector3 vNormal = (v1-v0).crossProduct(v2-v0);
					vNormal.normalise();
					Vector3 thePoint = ownMatrix * vCenter;
					Plane thePlane(vNormal, thePoint);
					Real theDist = thePlane.getDistance(ball.getCenter());
					// fill collide report
					if(0 == i)
					{
						collPair.this_normal = vNormal;
						collPair.other_normal = -collPair.this_normal;
						collPair.contact = ownMatrix * vCenter;//ball.getCenter() + collPair.this_normal * theDist;
					}
					CollisionInfo collInfo;
					collInfo.this_normal = vNormal;
					collInfo.other_normal = -collPair.this_normal;
					collInfo.contact = ownMatrix * vCenter;
					collPair.collInfos.push_back(collInfo);
				}
				return true;
			}
			else
			{
				//n_printf("nOpcodeShape::sphereCheck(): contact but no faces!\n");
				return false;
			}
		}

		// FIXME!
		return false;
	}

	//------------------------------------------------------------------------
	/// Render a AABBCollisionNode and recurse.
	///  @param [in, out]  node const Opcode::AABBCollisionNode * AABBCollisionNode to visualize.
	void ICollisionShape::visualizeAABBCollisionNode(const Opcode::AABBCollisionNode* node)
	{
		assert(node);

		Vector3 center(node->mAABB.mCenter.x, node->mAABB.mCenter.y, node->mAABB.mCenter.z);
		Vector3 extent(node->mAABB.mExtents.x, node->mAABB.mExtents.y, node->mAABB.mExtents.z);

		Vector3 v00(center.x - extent.x, center.y - extent.y, center.z - extent.z);
		Vector3 v01(center.x - extent.x, center.y - extent.y, center.z + extent.z);
		Vector3 v02(center.x + extent.x, center.y - extent.y, center.z + extent.z);
		Vector3 v03(center.x + extent.x, center.y - extent.y, center.z - extent.z);

		Vector3 v10(center.x - extent.x, center.y + extent.y, center.z - extent.z);
		Vector3 v11(center.x - extent.x, center.y + extent.y, center.z + extent.z);
		Vector3 v12(center.x + extent.x, center.y + extent.y, center.z + extent.z);
		Vector3 v13(center.x + extent.x, center.y + extent.y, center.z - extent.z);

		const Matrix4 &m = getFullTransform();
		v00 = m * v00;
		v01 = m * v01;
		v02 = m * v02;
		v03 = m * v03;
		v10 = m * v10;
		v11 = m * v11;
		v12 = m * v12;
		v13 = m * v13;

		//// render ground rect
		mActiveDebugger->addAABBLine(v00.x, v00.y, v00.z, v01.x, v01.y, v01.z);
		mActiveDebugger->addAABBLine(v01.x, v01.y, v01.z, v02.x, v02.y, v02.z);
		mActiveDebugger->addAABBLine(v02.x, v02.y, v02.z, v03.x, v03.y, v03.z);
		mActiveDebugger->addAABBLine(v03.x, v03.y, v03.z, v00.x, v00.y, v00.z);

		//// render top rect
		mActiveDebugger->addAABBLine(v10.x, v10.y, v10.z, v11.x, v11.y, v11.z);
		mActiveDebugger->addAABBLine(v11.x, v11.y, v11.z, v12.x, v12.y, v12.z);
		mActiveDebugger->addAABBLine(v12.x, v12.y, v12.z, v13.x, v13.y, v13.z);
		mActiveDebugger->addAABBLine(v13.x, v13.y, v13.z, v10.x, v10.y, v10.z);

		//// render vertical lines
		mActiveDebugger->addAABBLine(v00.x, v00.y, v00.z, v10.x, v10.y, v10.z);
		mActiveDebugger->addAABBLine(v01.x, v01.y, v01.z, v11.x, v11.y, v11.z);
		mActiveDebugger->addAABBLine(v02.x, v02.y, v02.z, v12.x, v12.y, v12.z);
		mActiveDebugger->addAABBLine(v03.x, v03.y, v03.z, v13.x, v13.y, v13.z);

		if (!node->IsLeaf())
		{
			const Opcode::AABBCollisionNode* neg = node->GetNeg();
			const Opcode::AABBCollisionNode* pos = node->GetPos();
			if (neg)
				visualizeAABBCollisionNode(neg);
			if (pos)
				visualizeAABBCollisionNode(pos);
		}
	}

	//------------------------------------------------------------------------
	/// Render a AABBCollisionNode and recurse.
	///  @param [in, out]  node const Opcode::AABBNoLeafNode * AABBNoLeafNode to visualize.
	void ICollisionShape::visualizeAABBNoLeafNode(const Opcode::AABBNoLeafNode* node)
	{
		assert(node);

		Vector3 center(node->mAABB.mCenter.x, node->mAABB.mCenter.y, node->mAABB.mCenter.z);
		Vector3 extent(node->mAABB.mExtents.x, node->mAABB.mExtents.y, node->mAABB.mExtents.z);

		Vector3 v00(center.x - extent.x, center.y - extent.y, center.z - extent.z);
		Vector3 v01(center.x - extent.x, center.y - extent.y, center.z + extent.z);
		Vector3 v02(center.x + extent.x, center.y - extent.y, center.z + extent.z);
		Vector3 v03(center.x + extent.x, center.y - extent.y, center.z - extent.z);

		Vector3 v10(center.x - extent.x, center.y + extent.y, center.z - extent.z);
		Vector3 v11(center.x - extent.x, center.y + extent.y, center.z + extent.z);
		Vector3 v12(center.x + extent.x, center.y + extent.y, center.z + extent.z);
		Vector3 v13(center.x + extent.x, center.y + extent.y, center.z - extent.z);

		const Matrix4 &m = getFullTransform();
		v00 = m * v00;
		v01 = m * v01;
		v02 = m * v02;
		v03 = m * v03;
		v10 = m * v10;
		v11 = m * v11;
		v12 = m * v12;
		v13 = m * v13;

		//// render ground rect
		mActiveDebugger->addAABBLine(v00.x, v00.y, v00.z, v01.x, v01.y, v01.z);
		mActiveDebugger->addAABBLine(v01.x, v01.y, v01.z, v02.x, v02.y, v02.z);
		mActiveDebugger->addAABBLine(v02.x, v02.y, v02.z, v03.x, v03.y, v03.z);
		mActiveDebugger->addAABBLine(v03.x, v03.y, v03.z, v00.x, v00.y, v00.z);

		//// render top rect
		mActiveDebugger->addAABBLine(v10.x, v10.y, v10.z, v11.x, v11.y, v11.z);
		mActiveDebugger->addAABBLine(v11.x, v11.y, v11.z, v12.x, v12.y, v12.z);
		mActiveDebugger->addAABBLine(v12.x, v12.y, v12.z, v13.x, v13.y, v13.z);
		mActiveDebugger->addAABBLine(v13.x, v13.y, v13.z, v10.x, v10.y, v10.z);

		//// render vertical lines
		mActiveDebugger->addAABBLine(v00.x, v00.y, v00.z, v10.x, v10.y, v10.z);
		mActiveDebugger->addAABBLine(v01.x, v01.y, v01.z, v11.x, v11.y, v11.z);
		mActiveDebugger->addAABBLine(v02.x, v02.y, v02.z, v12.x, v12.y, v12.z);
		mActiveDebugger->addAABBLine(v03.x, v03.y, v03.z, v13.x, v13.y, v13.z);

		if (!node->HasNegLeaf())
		{
			const Opcode::AABBNoLeafNode* neg = node->GetNeg();
			visualizeAABBNoLeafNode(neg);
		}
		if (!node->HasPosLeaf())
		{
			const Opcode::AABBNoLeafNode* pos = node->GetPos();
			visualizeAABBNoLeafNode(pos);
		}
	}

	//------------------------------------------------------------------------
	/// Renders the collide model triangle soup.
	void ICollisionShape::visualize(Details::OgreOpcodeDebugger* activeDebugger)
	{
		if(!mDebugObject->isAttached())
			mParentNode->attachObject(mDebugObject);

		mDebugObject->begin("OgreOpcodeDebug/Shapes", Ogre::RenderOperation::OT_LINE_LIST);

		mActiveDebugger = activeDebugger;


		assert(mVertexBuf && mFaceBuf);

		// render the triangle soup
		size_t i;
		for (i = 0; i < numFaces; i++)
		{
			size_t* indexPtr = mFaceBuf + 3 * i;
			float* v0 = mVertexBuf + 3 * indexPtr[0];
			float* v1 = mVertexBuf + 3 * indexPtr[1];
			float* v2 = mVertexBuf + 3 * indexPtr[2];

			//const Matrix4 &m = getFullTransform();

			Vector3 vect0(v0[0],v0[1],v0[2]);
			Vector3 vect1(v1[0],v1[1],v1[2]);
			Vector3 vect2(v2[0],v2[1],v2[2]);
			//vect0 = m * vect0;
			//vect1 = m * vect1;
			//vect2 = m * vect2;

			mDebugObject->position(vect0.x, vect0.y, vect0.z);
			mDebugObject->position(vect1.x, vect1.y, vect1.z);
			mDebugObject->position(vect1.x, vect1.y, vect1.z);
			mDebugObject->position(vect2.x, vect2.y, vect2.z);
			mDebugObject->position(vect2.x, vect2.y, vect2.z);
			mDebugObject->position(vect0.x, vect0.y, vect0.z);
		}
		mDebugObject->end();
	}


	//------------------------------------------------------------------------
	/// <TODO: insert function description here>
	void ICollisionShape::visualizeAABBs(Details::OgreOpcodeDebugger* activeDebugger)
	{
		mActiveDebugger = activeDebugger;
		// render the AABB tree
		if (opcModel.HasLeafNodes())
		{
			const Opcode::AABBCollisionTree* tree = static_cast<const Opcode::AABBCollisionTree*>(opcModel.GetTree());
			visualizeAABBCollisionNode(tree->GetNodes());
		}
		else
		{
			const Opcode::AABBNoLeafTree* tree = static_cast<const Opcode::AABBNoLeafTree*>(opcModel.GetTree());
			visualizeAABBNoLeafNode(tree->GetNodes());
		}
	}

	//------------------------------------------------------------------------
	void ICollisionShape::_prepareOpcodeCreateParams(Opcode::OPCODECREATE& opcc)
	{
		opcc.mIMesh = &opcMeshAccess;
		//opcc.mSettings.mRules = Opcode::SPLIT_BEST_AXIS;//Opcode::SPLIT_SPLATTER_POINTS;   // split by splattering primitive centers (???)
		opcc.mSettings.mRules = Opcode::SPLIT_GEOM_CENTER | Opcode::SPLIT_SPLATTER_POINTS; // Recommended by Opcode manual
		opcc.mSettings.mLimit = 1;             // build a complete tree, 1 primitive/node
		opcc.mNoLeaf    = true; // false;
		opcc.mQuantized = false; // true;
	}

}

//------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -