//---------------------------------------------------------------------------- BspNode* BspNodes::CreateNode (const Vector2f& v0, const Vector2f& v1, VertexColor3Effect* effect, const Float3& color) { // Create the model-space separating plane. Vector2f dir = v1 - v0; AVector normal(dir[1], -dir[0], 0.0f); normal.Normalize(); float constant = normal[0]*v0[0] + normal[1]*v0[1]; HPlane modelPlane(normal, constant); // Create the BSP node. BspNode* bsp = new0 BspNode(modelPlane); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); // Create the rectangle representation of the model plane and set the // vertex colors to the specified color. float xExtent = 0.5f*dir.Length(); float yExtent = 0.125f; TriMesh* rect = StandardMesh(vformat).Rectangle(2, 2, xExtent, yExtent); VertexBufferAccessor vba(rect); for (int i = 0; i < 4; ++i) { vba.Color<Float3>(0, i) = color; } rect->SetEffectInstance(effect->CreateInstance()); // Set the position and orientation for the world-space plane. APoint trn(0.5f*(v0[0] + v1[0]), 0.5f*(v0[1] + v1[1]), yExtent + 0.001f); HMatrix zRotate(AVector::UNIT_Z, Mathf::ATan2(dir.Y(),dir.X())); HMatrix xRotate(AVector::UNIT_X, Mathf::HALF_PI); HMatrix rotate = zRotate*xRotate; rect->LocalTransform.SetTranslate(trn); rect->LocalTransform.SetRotate(rotate); bsp->AttachCoplanarChild(rect); return bsp; }
//---------------------------------------------------------------------------- Spatial* BspNode::GetContainingNode (const APoint& point) { SpatialPtr posChild = GetPositiveChild(); SpatialPtr negChild = GetNegativeChild(); if (posChild || negChild) { BspNode* bspChild; if (mWorldPlane.WhichSide(point) < 0) { bspChild = DynamicCast<BspNode>(negChild); if (bspChild) { return bspChild->GetContainingNode(point); } else { return negChild; } } else { bspChild = DynamicCast<BspNode>(posChild); if (bspChild) { return bspChild->GetContainingNode(point); } else { return posChild; } } } return this; }
Spatial* BspNode::GetContainingNode(Vector4<float> const& point) { std::shared_ptr<Spatial> posChild = GetPositiveChild(); std::shared_ptr<Spatial> negChild = GetNegativeChild(); if (posChild || negChild) { BspNode* bspChild; if (WhichSide(point) < 0) { bspChild = dynamic_cast<BspNode*>(negChild.get()); if (bspChild) { return bspChild->GetContainingNode(point); } else { return negChild.get(); } } else { bspChild = dynamic_cast<BspNode*>(posChild.get()); if (bspChild) { return bspChild->GetContainingNode(point); } else { return posChild.get(); } } } return this; }
void BspIntersectionSceneQuery::execute(IntersectionSceneQueryListener* listener) { /* Go through each leaf node in BspLevel and check movables against each other and world Issue: some movable-movable intersections could be reported twice if 2 movables overlap 2 leaves? */ const BspLevelPtr& lvl = ((BspSceneManager*)mParentSceneMgr)->getLevel(); if (lvl.isNull()) return; BspNode* leaf = lvl->getLeafStart(); int numLeaves = lvl->getNumLeaves(); while (numLeaves--) { const BspNode::IntersectingObjectSet& objects = leaf->getObjects(); int numObjects = (int)objects.size(); BspNode::IntersectingObjectSet::const_iterator a, b, theEnd; theEnd = objects.end(); a = objects.begin(); for (int oi = 0; oi < numObjects; ++oi, ++a) { const MovableObject* aObj = *a; // Skip this object if collision not enabled if (!(aObj->getQueryFlags() & mQueryMask) || !(aObj->getTypeFlags() & mQueryTypeMask) || !aObj->isInScene()) continue; if (oi < (numObjects-1)) { // Check object against others in this node b = a; for (++b; b != theEnd; ++b) { const MovableObject* bObj = *b; // Apply mask to b (both must pass) if ((bObj->getQueryFlags() & mQueryMask) && (bObj->getTypeFlags() & mQueryTypeMask) && bObj->isInScene()) { const AxisAlignedBox& box1 = aObj->getWorldBoundingBox(); const AxisAlignedBox& box2 = bObj->getWorldBoundingBox(); if (box1.intersects(box2)) { if (!listener->queryResult(const_cast<MovableObject*>(aObj), const_cast<MovableObject*>(bObj))) return; } } } } // Check object against brushes if (mQueryTypeMask & SceneManager::WORLD_GEOMETRY_TYPE_MASK) { const BspNode::NodeBrushList& brushes = leaf->getSolidBrushes(); BspNode::NodeBrushList::const_iterator bi, biend; biend = brushes.end(); Real radius = aObj->getBoundingRadius(); const Vector3& pos = aObj->getParentNode()->_getDerivedPosition(); for (bi = brushes.begin(); bi != biend; ++bi) { list<Plane>::type::const_iterator planeit, planeitend; planeitend = (*bi)->planes.end(); bool brushIntersect = true; // Assume intersecting for now for (planeit = (*bi)->planes.begin(); planeit != planeitend; ++planeit) { Real dist = planeit->getDistance(pos); if (dist > radius) { // Definitely excluded brushIntersect = false; break; } } if (brushIntersect) { // report this brush as it's WorldFragment assert((*bi)->fragment.fragmentType == SceneQuery::WFT_PLANE_BOUNDED_REGION); if (!listener->queryResult(const_cast<MovableObject*>(aObj), const_cast<WorldFragment*>(&((*bi)->fragment)))) return; } } } } ++leaf; } }
//----------------------------------------------------------------------- //----------------------------------------------------------------------- //----------------------------------------------------------------------- BspNode* BspSceneManager::walkTree(Camera* camera, VisibleObjectsBoundsInfo *visibleBounds, bool onlyShadowCasters) { if (mLevel.isNull()) return 0; // Locate the leaf node where the camera is located BspNode* cameraNode = mLevel->findLeaf(camera->getDerivedPosition()); mMatFaceGroupMap.clear(); mFaceGroupSet.clear(); // Scan through all the other leaf nodes looking for visibles int i = mLevel->mNumNodes - mLevel->mLeafStart; BspNode* nd = mLevel->mRootNode + mLevel->mLeafStart; /* if (firstTime) { camera->getViewMatrix(); // Force update view before report of.open("BspSceneManager.log"); of << *camera << std::endl; of << "Camera Node: " << *cameraNode << std::endl; of << "Vertex Data: " << std::endl; for (int testi = 0; testi < mLevel->mNumVertices; ++testi) { of << " " << testi << ": pos(" << mLevel->mVertices[testi].position[0] << ", " << mLevel->mVertices[testi].position[1] << ", " << mLevel->mVertices[testi].position[2] << ")" << " uv(" << mLevel->mVertices[testi].texcoords[0] << ", " << mLevel->mVertices[testi].texcoords[1] << ")" << " lm(" << mLevel->mVertices[testi].lightmap[0] << ", " << mLevel->mVertices[testi].lightmap[1] << ")" << std::endl; } of << "Element data:" << std::endl; for (testi = 0; testi < mLevel->mNumElements; ++testi) { of << " " << testi << ": " << mLevel->mElements[testi] << std::endl; } } */ while (i--) { if (mLevel->isLeafVisible(cameraNode, nd)) { // Visible according to PVS, check bounding box against frustum FrustumPlane plane; if (camera->isVisible(nd->getBoundingBox(), &plane)) { //if (firstTime) //{ // of << "Visible Node: " << *nd << std::endl; //} processVisibleLeaf(nd, camera, visibleBounds, onlyShadowCasters); if (mShowNodeAABs) addBoundingBox(nd->getBoundingBox(), true); } } nd++; } // TEST //if (firstTime) //{ // of.close(); // firstTime = false; //} return cameraNode; }