/** * @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()); } } } }
/** * @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 } } }
/** * @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(); }
/** * @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; } } } } }