/**
*  @brief
*    Draws recursive
*/
void SRPDebugWireframesFixedFunctions::DrawRec(Renderer &cRenderer, const SQCull &cCullQuery) const
{
	// Get the fixed functions interface (when we're in here, we know that it must exist!)
	FixedFunctions *pFixedFunctions = cRenderer.GetFixedFunctions();

	// Get scene container
	SceneContainer &cSceneContainer = cCullQuery.GetSceneContainer();
	const VisContainer &cVisContainer = cCullQuery.GetVisContainer();

	// Set the new scissor rectangle
	cRenderer.SetScissorRect(&cVisContainer.GetProjection().cRectangle);

	// Draw the container scene node
	if (cSceneContainer.GetMeshHandler())
		DrawMesh(cRenderer, cVisContainer, *cSceneContainer.GetMeshHandler());

	// Render all visible scene nodes of this scene container
	Iterator<VisNode*> cIterator = cVisContainer.GetVisNodes().GetIterator();
	while (cIterator.HasNext()) {
		// Get visibility node and scene node
		const VisNode   *pVisNode   = cIterator.Next();
			  SceneNode *pSceneNode = pVisNode->GetSceneNode();
		if (pSceneNode) {
			// Set the current world matrix
			pFixedFunctions->SetTransformState(FixedFunctions::Transform::World, pVisNode->GetWorldMatrix());

			// Is this scene node a portal?
			if (pVisNode->IsPortal()) {
				// Get the target cell visibility container
				const VisContainer *pVisCell = static_cast<const VisPortal*>(pVisNode)->GetTargetVisContainer();
				if (pVisCell && pVisCell->GetCullQuery()) {
					// Draw the target cell
					DrawRec(cRenderer, *pVisCell->GetCullQuery());

					// Set the previous scissor rectangle
					cRenderer.SetScissorRect(&cVisContainer.GetProjection().cRectangle);
				}

				// Draw the portal itself
				if (pSceneNode->GetMeshHandler())
					DrawMesh(cRenderer, *pVisNode, *pSceneNode->GetMeshHandler());

			// Is this scene node a container? We do not need to check for cells because we will
			// NEVER receive cells from SQCull directly, they are ONLY visible through portals! (see above)
			} else if (pVisNode->IsContainer()) {
				// Draw this container without special processing
				if (static_cast<const VisContainer*>(pVisNode)->GetCullQuery())
					DrawRec(cRenderer, *static_cast<const VisContainer*>(pVisNode)->GetCullQuery());

				// Set the previous scissor rectangle
				cRenderer.SetScissorRect(&cVisContainer.GetProjection().cRectangle);

			// This must just be a quite boring scene node :)
			} else {
				if (pSceneNode->GetMeshHandler())
					DrawMesh(cRenderer, *pVisNode, *pSceneNode->GetMeshHandler());
			}
		}
	}
}
Пример #2
0
/**
*  @brief
*    Called when a scene node was found
*/
void Picking::OnSceneNode(SceneQuery &cQuery, SceneNode &cSceneNode)
{
	// First at all, call the picking filter function
	if (m_pPickingResult->m_pSceneContainer && OnPickingCandidate(cSceneNode)) {
		// Is there a mesh handler with a mesh?
		if (cSceneNode.GetMeshHandler() && cSceneNode.GetMeshHandler()->GetMesh()) {
			// We KNOW that it's a SQLine!
			SQLine &cLineQuery = static_cast<SQLine&>(cQuery);

			// Get line start/end position in node space
			const Vector3 vLineStartPos = cSceneNode.GetTransform().GetInverseMatrix()*cLineQuery.GetLine().vStart;
			const Vector3 vLineEndPos   = cSceneNode.GetTransform().GetInverseMatrix()*cLineQuery.GetLine().vEnd;

			// Perform mesh intersection
			MeshIntersection(cSceneNode, vLineStartPos, vLineEndPos, nullptr, cLineQuery.GetCull());
		} else {
			// There's no mesh we can use for an intersection test

			// [TODO] Currently it's impossible to pick something which does not have a polygonal mesh, think
			//        of a way to handle this case properly, especially when dealing with overlapping scene nodes
		}
	}
}
Пример #3
0
/**
*  @brief
*    Constructor
*/
SNMMeshJoint::SNMMeshJoint(SceneNode &cSceneNode) : SNMMesh(cSceneNode),
	Name(this),
	Rotation(this),
	RotationFrom(this),
	Min(this),
	Max(this),
	Speed(this),
	MaxDifference(this),
	FallbackRotation(this),
	Flags(this),
	SlotOnUpdate(this),
	SlotOnDrawDebug(this)
{
	// Create the mesh animation manager
	MeshHandler *pMeshHandler = cSceneNode.GetMeshHandler();
	if (pMeshHandler) {
		MeshAnimationManager *pAniManager = pMeshHandler->GetMeshAnimationManager();
		if (!pAniManager)
			pAniManager = pMeshHandler->CreateMeshAnimationManager();
	}

	// Ensure that there's a "PLScene::SNMMeshUpdate" instance within the owner scene node which takes care of the frequent mesh update
	GetSNMMeshUpdate();
}
Пример #4
0
/**
*  @brief
*    Perform mesh intersection
*/
void Picking::MeshIntersection(SceneNode &cSceneNode, const Vector3 &vLineStartPos, const Vector3 &vLineEndPos,
							   Array<uint32> *plstGeometries, Cull::Enum nCull)
{
	// First of all, check the intersection distance against the axis aligned bounding box of the scene node
	float fIntersection;
	const AABoundingBox &cAABoundngBox = cSceneNode.GetAABoundingBox();
	if (Intersect::AABoxLine(cAABoundngBox.vMin, cAABoundngBox.vMax, vLineStartPos, vLineEndPos, &fIntersection)) {
		// Get the mesh handler of the scene node
		MeshHandler *pMeshHandler = cSceneNode.GetMeshHandler();
		if (pMeshHandler) {
			// Transform matrix to bring something into the same container space the original line start position is in
			Matrix3x4 matTransform;
			if (cSceneNode.GetContainer() && m_pPickingResult->m_pSceneContainer)
				cSceneNode.GetContainer()->GetTransformMatrixTo(*m_pPickingResult->m_pSceneContainer, matTransform);

			// Before we perform the expensive triangle intersection test we check the found axis aligned bounding box
			// intersection distance against the current nearest intersection distance... maybe we're in luck and can
			// skip further tests if we detect that no triangle inside the box can be nearer than the current nearest
			// distance...
			if (fIntersection >= 0.0f && m_pPickingResult->m_fNearestSquaredDistance >= 0.0f) {
				// Our start point is outside the axis aligned bounding box of the scene node and there's already a previous picking result available

				// Get intersection point in node space
				Vector3 vIntersectionPos = vLineStartPos + (vLineEndPos-vLineStartPos).Normalize()*fIntersection;

				// Transform intersection point into container space
				vIntersectionPos *= cSceneNode.GetTransform().GetMatrix();

				// Bring the intersection point into the same container space the original line start position is in
				vIntersectionPos *= matTransform;

				// Do the early escape test
				if ((m_pPickingResult->m_vLineStartPos-vIntersectionPos).GetSquaredLength() > m_pPickingResult->m_fNearestSquaredDistance)
					return; // Get us out of this method right now, there's no change that any triangle intersection point is closer as the previous picking result
			} else {
				// Our start point is inside the axis aligned bounding box of the scene node or we have nothing to early escape test against
			}

			// We ran out of possible early escape tests... now find intersection triangle - this may be quite slow...
			Vector3 vCollisionPoint;
			uint32 nTriangle, nGeometry;
			if (pMeshHandler->FindTriangle(vLineStartPos, vLineEndPos, nTriangle, &nGeometry, &vCollisionPoint, plstGeometries, nCull)) {
				// Lookout! If our start point is inside the axis aligned bounding box of the scene node, we need to take care of "backfiring"
				if (fIntersection < 0) {
					// Our start point is inside the axis aligned bounding box of the scene node

					// Get the normalized line direction in scene node space
					Vector3 vLineDirection = vLineEndPos;
					vLineDirection -= vLineStartPos;
					vLineDirection.Normalize();

					// Get the normalized collision point to line start point direction in scene node space
					Vector3 vCollisionPointDirection = vCollisionPoint;
					vCollisionPointDirection -= vLineStartPos;
					vCollisionPointDirection.Normalize();

					// Is the collision point within the correct direction?
					if (vLineDirection.DotProduct(vCollisionPointDirection) < 0)
						return;	// Get us out of this method right now, the found collision point is behind us and so we are not interested in it
				}

				// Backup the node space collision point
				const Vector3 vNodeSpaceCollisionPoint = vCollisionPoint;

				// Transform collision point into container space
				vCollisionPoint *= cSceneNode.GetTransform().GetMatrix();

				// Bring the collision point into the same container space the original line start position is in
				vCollisionPoint *= matTransform;

				// Calculate the squared distance between the two positions (that are now within the same vector space)
				const float fSquaredDistance = (m_pPickingResult->m_vLineStartPos-vCollisionPoint).GetSquaredLength();

				// Is this collision point nearer?
				if (m_pPickingResult->m_fNearestSquaredDistance < 0.0f || m_pPickingResult->m_fNearestSquaredDistance > fSquaredDistance) {
					m_pPickingResult->m_pSceneNode				= &cSceneNode;
					m_pPickingResult->m_nGeometry				= nGeometry;
					m_pPickingResult->m_nTriangle				= nTriangle;
					m_pPickingResult->m_vPoint					= vNodeSpaceCollisionPoint;
					m_pPickingResult->m_fNearestSquaredDistance = fSquaredDistance;
				}
			}
		}
	}
}