//---------------------------------------------------------------------------- Node* Game::LoadAndInitializeScene() { Importer importer("Data/Scene/"); Node* pScene = importer.LoadSceneFromXml("Scene.xml", mspPhysicsWorld); if (!pScene) { return NULL; } NodeCamera* pCameraNode = pScene->FindChild<NodeCamera>(); WIRE_ASSERT(pCameraNode /* No Camera in scene.xml */); mspSceneCamera = pCameraNode->Get(); mSortingCuller.SetCamera(mspSceneCamera); // The maximum number of objects that are going to be culled is the // number of objects we imported. If we don't set the size of the set now, // the culler will dynamically increase it during runtime. This is not // a big deal, however it is better to avoid memory allocations during the // render loop. UInt renderObjectCount = importer.GetStatistics()->RenderObjectCount; mSortingCuller.SetMaxQuantity(renderObjectCount); // Create and configure probe robot controller SpatialPtr spRedHealthBar = mspGUI->FindChild("RedHealthBar"); WIRE_ASSERT(spRedHealthBar /* No RedHealthBar in GUI.xml */); Node* pProbeRobotSpatial = DynamicCast<Node>(pScene->FindChild("Probe Robot")); WIRE_ASSERT(pProbeRobotSpatial /* No Probe Robot in Scene.xml */); // Detach red energy/health bar and attach it robot probe as a billboard NodeBillboard* pBillboard = WIRE_NEW NodeBillboard; pProbeRobotSpatial->AttachChild(pBillboard); Node* pParent = DynamicCast<Node>(spRedHealthBar->GetParent()); WIRE_ASSERT(pParent); pParent->DetachChild(spRedHealthBar); pBillboard->AttachChild(spRedHealthBar); Spatial* pPlayerSpatial = pScene->FindChild("Player"); WIRE_ASSERT(pPlayerSpatial /* No Player in Scene.xml */); mspProbeRobot = WIRE_NEW ProbeRobot(mspPhysicsWorld, pPlayerSpatial, spRedHealthBar); pProbeRobotSpatial->AttachController(mspProbeRobot); // Create and configure player controller mspPlayer = WIRE_NEW Player(mspSceneCamera, mspPhysicsWorld); pPlayerSpatial->AttachController(mspPlayer); Spatial* pPlatform = pScene->FindChild("Platform"); WIRE_ASSERT(pPlatform /* Platform object missing in scene */); pPlatform->AttachController(WIRE_NEW Elevator(mspPhysicsWorld)); pScene->Bind(GetRenderer()); pScene->WarmUpRendering(GetRenderer()); return pScene; }
//---------------------------------------------------------------------------- SpatialPtr Node::SetChild(UInt i, Spatial* pChild) { // Some folks are under the impression that a node can have multiple // parents, the scene graph therefore being a DAG. That is not the case. // The parent-child relationships form a tree. This assertion is to let // folks know this and to warn them that a child is being kidnapped from // another parent. To be safe, you should really call DetachChild before // you reattach somewhere else with AttachChild or SetChild. If you do // call DetachChild first, be aware that the child might self-destruct. // If you want this not to happen, hang onto the child via a smart // pointer. For example, // // Node* pNode0 = WIRE_NEW Node; // Spatial* pChild0 = <...>; // pNode0->AttachChild(pChild0); // child at index 0 // Node* pNode1 = <...>; // // // This asserts because pChild0 already has a parent (pNode0). // pNode1->AttachChild(pChild0); // // // Instead do this and avoid the potential self-destruction of // // pChild0). // SpatialPtr spSaveChild = pNode0->GetChild(0); // pNode0->DetachChild(spSaveChild); // pNode1->AttachChild(spSaveChild); if (pChild) { WIRE_ASSERT(!pChild->GetParent()); } if (i < GetQuantity()) { // detach child currently in slot SpatialPtr spPreviousChild = mChildren[i]; if (spPreviousChild) { spPreviousChild->SetParent(0); } // attach new child to slot if (pChild) { pChild->SetParent(this); } mChildren[i] = pChild; return spPreviousChild; } // index out of range, increase array size and attach new child pChild->SetParent(this); mChildren.Append(pChild); return NULL; }
//---------------------------------------------------------------------------- SpatialPtr Node::DetachChildAt (int i) { if (0 <= i && i < m_kChild.GetQuantity()) { SpatialPtr spkChild = m_kChild[i]; if ( spkChild ) { // child exists in slot, detach it spkChild->SetParent(0); m_kChild[i] = 0; m_iUsed--; } return spkChild; } return 0; }
//---------------------------------------------------------------------------- SpatialPtr Node::DetachChildAt(UInt i) { if (i < GetQuantity()) { SpatialPtr spChild = mChildren[i]; if (spChild) { // child exists in slot, detach it spChild->SetParent(NULL); mChildren[i] = NULL; } return spChild; } return NULL; }
//---------------------------------------------------------------------------- SpatialPtr Node::SetChild (int i, Spatial* pkChild) { // Some folks are of the impression that a node can have multiple parents, // the scene graph therefore being a DAG. That is not the case. The // parent-child relationships form a tree. This assertion is to let folks // know this and to warn them that a child is being kidnapped from another // parent. To be safe, you should really call DetachChild before you // reattach somewhere else with AttachChild or SetChild. if (pkChild) { assert(!pkChild->GetParent()); } if (0 <= i && i < m_kChild.GetQuantity()) { // detach child currently in slot SpatialPtr spkPreviousChild = m_kChild[i]; if (spkPreviousChild) { spkPreviousChild->SetParent(0); m_iUsed--; } // attach new child to slot if (pkChild) { pkChild->SetParent(this); m_iUsed++; } m_kChild[i] = pkChild; return spkPreviousChild; } // index out of range, increase array size and attach new child pkChild->SetParent(this); m_kChild.SetElement(i,pkChild); m_iUsed++; return 0; }
//---------------------------------------------------------------------------- void BspNode::GetVisibleSet (Culler& culler, bool noCull) { // Get visible Geometry in back-to-front order. If a global effect is // active, the Geometry objects in the subtree will be drawn using it. SpatialPtr posChild = GetPositiveChild(); SpatialPtr copChild = GetCoplanarChild(); SpatialPtr negChild = GetNegativeChild(); const Camera* camera = culler.GetCamera(); int positionSide = mWorldPlane.WhichSide(camera->GetPosition()); int frustumSide = culler.WhichSide(mWorldPlane); if (positionSide > 0) { // Camera origin on positive side of plane. if (frustumSide <= 0) { // The frustum is on the negative side of the plane or straddles // the plane. In either case, the negative child is potentially // visible. if (negChild) { negChild->OnGetVisibleSet(culler, noCull); } } if (frustumSide == 0) { // The frustum straddles the plane. The coplanar child is // potentially visible. if (copChild) { copChild->OnGetVisibleSet(culler, noCull); } } if (frustumSide >= 0) { // The frustum is on the positive side of the plane or straddles // the plane. In either case, the positive child is potentially // visible. if (posChild) { posChild->OnGetVisibleSet(culler, noCull); } } } else if (positionSide < 0) { // Camera origin on negative side of plane. if (frustumSide >= 0) { // The frustum is on the positive side of the plane or straddles // the plane. In either case, the positive child is potentially // visible. if (posChild) { posChild->OnGetVisibleSet(culler, noCull); } } if (frustumSide == 0) { // The frustum straddles the plane. The coplanar child is // potentially visible. if (copChild) { copChild->OnGetVisibleSet(culler, noCull); } } if (frustumSide <= 0) { // The frustum is on the negative side of the plane or straddles // the plane. In either case, the negative child is potentially // visible. if (negChild) { negChild->OnGetVisibleSet(culler, noCull); } } } else { // Camera origin on plane itself. Both sides of the plane are // potentially visible as well as the plane itself. Select the // first-to-be-drawn half space to be the one to which the camera // direction points. float NdD = mWorldPlane.GetNormal().Dot(camera->GetDVector()); if (NdD >= 0.0f) { if (posChild) { posChild->OnGetVisibleSet(culler, noCull); } if (copChild) { copChild->OnGetVisibleSet(culler, noCull); } if (negChild) { negChild->OnGetVisibleSet(culler, noCull); } } else { if (negChild) { negChild->OnGetVisibleSet(culler, noCull); } if (copChild) { copChild->OnGetVisibleSet(culler, noCull); } if (posChild) { posChild->OnGetVisibleSet(culler, noCull); } } } }