/*! Sorts game objects by material This method traverses the scenegraph and adds game objects their respective material's render queues \param root The root of the scenegraph to be sorted */ void Renderer::buildRenderQueue(Transform *root){ HBVC_CULLTESTS++; DefaultBoundingVolume rootBoundingSphere; GameObject* obj; Material* m; if (is_leaf(root, &obj, &m)) { rootBoundingSphere = root->getWorldMatrix() * obj->getCachedBoundingVolume(); if (camera->contains(rootBoundingSphere) != BoundingVolumeIntersects::Outside) { m->addToQueue(obj); } } else { rootBoundingSphere = root->getWorldMatrix() * root->getBoundingVolume(); switch (camera->contains(rootBoundingSphere)) { //if the object is completely outside the view frustum, //do not add it to the render queue and do not recursively cull test its children case BoundingVolumeIntersects::Outside: return; //if the object is completely inside the view frustum, //add everything to the render queue and stop cull testing case BoundingVolumeIntersects::Inside: //start the fast path buildRenderQueueDontCull(root); return; case BoundingVolumeIntersects::Overlap: //if the object overlaps with the view frustum, //recursively cull test /* GameObject* obj = root->gameObject; if (obj) { //if (camera->contains(obj->getBoundingSphere()) != Camera::None) { Material* m = obj->getMaterial(); if (m) m->addToQueue(obj); //} }*/ for (auto child : root->children) { buildRenderQueue(child); //update the HBVC_depth variable (inductive) } } } }
/*! Sorts game objects by material This method traverses the scenegraph and adds game objects their respective material's render queues \param root The root of the scenegraph to be sorted */ void Renderer::buildRenderQueue(Transform *root){ if (root->gameObject) { Material* m = root->gameObject->getMaterial(); if (m) m->addToQueue(root->gameObject); } if(!root->children.empty()) { for(unsigned int i = 0; i < root->children.size(); ++i) { if(NULL != root->children[i]) { buildRenderQueue(root->children[i]); } } } }
/*! Renders the scenegraph This method is responsible for sorting by material and rendering game objects in material priority order \param root The root of the scenegraph to be rendered */ void Renderer::render(Transform *root){ Vector3 cameraPos; float distance; GameObject *object; std::vector<Material*>::iterator mit; // Single common camera for all rendering if (camera) cameraPos = camera->gameObject->getTransform()->getWorldPosition(); else cameraPos = Vector3(0,0,0); buildRenderQueue(root); for (int i=0; i<PRIORITY_LEVELS; i++) { // temp list of objects requiring sorted draw order (if any) std::priority_queue<GameObject*, std::vector<GameObject*>, GameObjectCameraDistanceCompare> sorted; for (mit = materials[i].begin(); mit!=materials[i].end(); mit++){ std::queue<GameObject*> &q = (*mit)->getQueue(); // objects to be drawn if (!(*mit)->getSortedDraw()) { // objects for normal unsorted materials are drawn immediately loadMaterial(*mit); while (!q.empty()) { object = q.front(); if (object->isVisible()) { draw(object); } q.pop(); } unloadMaterial(*mit); } else { // objects to be sorted and drawn later while (!q.empty()) { object = q.front(); if (object->isVisible()) { // Note using squared distance as we only care about relative distance distance = cameraPos.squaredDistance(object->getTransform()->getWorldPosition()); object->setDistanceToCamera(distance); sorted.push(object); } q.pop(); } } } // Draw sorted objects (if any) Material *loaded = NULL; // current loaded material while (!sorted.empty()) { object = sorted.top(); if (loaded != object->getMaterial()) { // only load material if changed loaded = object->getMaterial(); loadMaterial(loaded); } draw(object); sorted.pop(); } } }