//---------------------------------------------------------------------------- void NodeBillboard::UpdateWorldData(Double appTime, Bool updateControllers) { // Compute billboard's world transforms based on its parent's world // transform and its local transforms. Notice that you should not call // Node::UpdateWorldData since that function updates its children. The // children of a NodeBillboard cannot be updated until the billboard is // aligned with the camera. Spatial::UpdateWorldData(appTime, updateControllers); if (mspCamera) { // Inverse-transform the camera to the model space of the billboard. Vector3F camLocation = World.ApplyInverse(mspCamera->GetLocation()); // To align the billboard, the projection of the camera to the // xz-plane of the billboard's model space determines the angle of // rotation about the billboard's model y-axis. If the projected // camera is on the model axis (x = 0 and z = 0), ATan2 returns zero // (rather than NaN), so there is no need to trap this degenerate // case and handle it separately. Float angle = MathF::ATan2(camLocation.X(), camLocation.Z()); Matrix34F orientation(Vector3F::UNIT_Y, angle); World.SetRotate(World.GetMatrix() * orientation); } // update the children now that the billboard orientation is known for (UInt i = 0; i < mChildren.GetQuantity(); i++) { Spatial* pChild = mChildren[i]; if (pChild) { pChild->UpdateGS(appTime, false, updateControllers); } } }
//---------------------------------------------------------------------------- void Node::WarmUpRendering(Renderer* pRenderer) { #ifndef WIRE_WII // Wii does not need to warm up by submitting draw calls WIRE_ASSERT(pRenderer); UpdateGS(0, true, false); Vector3F cameraLocation = WorldBound->GetCenter(); cameraLocation.Z() += WorldBound->GetRadius(); Vector3F viewDirection = -Vector3F::UNIT_Z; Vector3F up = Vector3F::UNIT_Y; Vector3F right = viewDirection.Cross(up); CameraPtr spCamera = WIRE_NEW Camera; spCamera->SetFrame(cameraLocation, viewDirection, up, right); Float fieldOfView = 60.0F; Float aspectRatio = 2; Float nearPlane = 0.1F; Float farPlane = WorldBound->GetRadius() * 2.0F; spCamera->SetFrustum(fieldOfView, aspectRatio, nearPlane, farPlane); CullerSorting culler; culler.SetCamera(spCamera); culler.ComputeVisibleSet(this); pRenderer->PreDraw(spCamera); // draw scene to warm up batching buffers pRenderer->Draw(culler.GetVisibleSets()); // collect and draw all materials separately so none will be missed // by CULL_ALWAYS or Switch/LOD nodes. THashSet<Material*> materials; TStack<Node*> scene(1000); scene.Push(this); while (!scene.IsEmpty()) { Node* pNode = NULL; scene.Pop(pNode); RenderObject* pRenderObject = pNode->GetRenderObject(); if (pRenderObject && pRenderObject->GetMaterial()) { materials.Insert(pRenderObject->GetMaterial()); } for (UInt i = 0; i < pNode->GetQuantity(); i++) { Node* pChild = DynamicCast<Node>(pNode->GetChild(i)); if (pChild) { scene.Push(pChild); } } } RenderObjectPtr spCube = StandardMesh::CreateCube24(4, pRenderer-> GetMaxTextureStages(), true); THashSet<Material*>::Iterator it(&materials); Transformation transformation; transformation.SetTranslate(cameraLocation - Vector3F(0, 0, 3)); for (Material** pMaterial = it.GetFirst(); pMaterial; pMaterial = it.GetNext()) { spCube->SetMaterial(*pMaterial); pRenderer->Draw(spCube, transformation); } pRenderer->PostDraw(); #endif }