Page MenuHomePhorge

Scene.cpp
No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None

Scene.cpp

#include <echo/Graphics/Scene.h>
#include <echo/Graphics/Viewport.h>
#include <echo/Graphics/Camera.h>
#include <echo/Graphics/Light.h>
#include <echo/Graphics/RenderTarget.h>
#include <echo/Graphics/SceneRenderable.h>
#include <boost/foreach.hpp>
#include <iostream>
#include <string>
#include <sstream>
namespace Echo
{
Scene::Scene() : TaskGroup("Scene"), mCurrentCamera(0)
{
}
Scene::Scene(const std::string& name) : TaskGroup(name)
{
}
Scene::~Scene()
{
}
void Scene::SetSkyBox(shared_ptr< SceneRenderable > skyBox)
{
mSkyBox=skyBox;
}
shared_ptr<Camera> Scene::CreateCamera()
{
std::stringstream name;
name << mCameras.size();
return CreateCamera(name.str());
}
shared_ptr<Camera> Scene::CreateCamera(const std::string& name)
{
if(mCameras.find(name)!=mCameras.end())
{
std::cout << "Scene::CreateCamera(): Error Camera named '" << name << "' already exists" << std::endl;
return shared_ptr<Camera>();
}
shared_ptr<Camera> camera=shared_ptr<Camera>(new Camera(name, *this));
mCameras[name]=camera;
return camera;
}
shared_ptr<Camera> Scene::GetCamera(const std::string& name)
{
std::map< std::string, shared_ptr<Camera> >::iterator cit=mCameras.find(name);
if(cit==mCameras.end())
{
std::cout << "Scene::CreateCamera(): Error Camera named '" << name << "' not found" << std::endl;
return shared_ptr<Camera>();
}
return cit->second;
}
shared_ptr<Light> Scene::CreateLight()
{
std::stringstream name;
name << mLights.size();
shared_ptr<Light> light=shared_ptr<Light>(new Light(name.str()));
mLights[name.str()]=light;
return light;
}
shared_ptr<Light> Scene::CreateLight(const std::string& name)
{
if(mLights.find(name)!=mLights.end())
{
std::cout << "Scene::CreateLight(): Error Light named '" << name << "' already exists" << std::endl;
return shared_ptr<Light>();
}
shared_ptr<Light> camera=shared_ptr<Light>(new Light(name));
mLights[name]=camera;
return camera;
}
shared_ptr<Light> Scene::GetLight(const std::string& name)
{
std::map< std::string, shared_ptr<Light> >::iterator it=mLights.find(name);
if(it==mLights.end())
{
std::cout << "Scene::CreateLight(): Error Light named '" << name << "' not found" << std::endl;
return shared_ptr<Light>();
}
return it->second;
}
void Scene::AddRenderable(shared_ptr< SceneRenderable > sceneRenderable, bool pickable)
{
mRenderables.push_back(sceneRenderable);
if(pickable)
{
mPickableRenderables.push_back(sceneRenderable);
}
}
void Scene::RemoveRenderable(shared_ptr<SceneRenderable> sceneRenderable)
{
mRenderables.erase(std::remove(mRenderables.begin(), mRenderables.end(), sceneRenderable), mRenderables.end());
mPickableRenderables.erase(std::remove(mPickableRenderables.begin(), mPickableRenderables.end(), sceneRenderable), mPickableRenderables.end());
}
shared_ptr< SceneRenderable > Scene::Pick(const Camera& camera, const Ray& ray)
{
typedef std::pair< AxisAlignedBox, shared_ptr< SceneRenderable > > BoxRenderablePair;
std::vector< BoxRenderablePair > visibleCameraBoxes;
visibleCameraBoxes.reserve(mPickableRenderables.size());
const Matrix4& viewMatrix = camera.GetViewMatrix();
// Transform each SceneRenderable scene AABB into camera space.
BOOST_FOREACH(shared_ptr< SceneRenderable >& renderable, mPickableRenderables)
{
AxisAlignedBox sceneAABB=renderable->GetSceneAxisAlignedBox();
if (camera.IsVisible(sceneAABB))
{
visibleCameraBoxes.push_back(std::make_pair(sceneAABB, renderable));
}
}
// Check if the ray intersects the visible objects' AABB. If so then check the
// intersect distance and return the closest.
shared_ptr<SceneRenderable> closestRenderable;
f32 closestDistance = 0.f;
BOOST_FOREACH(const BoxRenderablePair& boxRenderablePair, visibleCameraBoxes)
{
std::pair<bool, f32> intersection = ray.intersects(boxRenderablePair.first);
if(intersection.first)
{
if(!closestRenderable)
{
closestDistance = intersection.second;
closestRenderable = boxRenderablePair.second;
}else
{
if(intersection.second < closestDistance)
{
closestRenderable = boxRenderablePair.second;
}
}
}
}
return closestRenderable;
}
void Scene::BuildRenderQueue(const Camera& camera)
{
mRenderQueue.resize(0);
mCurrentCamera = &camera;
BOOST_FOREACH(shared_ptr< SceneRenderable >& renderable, mRenderables)
{
renderable->Accept(*this);
}
std::sort(mRenderQueue.begin(),mRenderQueue.end(),DistanceCompare);
mCurrentCamera = 0;
}
void Scene::SceneRenderableVisit(SceneRenderable& renderable)
{
// Transform each SceneRenderable scene AABB into camera space.
AxisAlignedBox sceneAABB=renderable.GetSceneAxisAlignedBox();
if (mCurrentCamera->IsVisible(sceneAABB))
{
f32 squaredDistance = sceneAABB.GetCenter().DistanceSquared(mCurrentCamera->GetPosition());
mRenderQueue.push_back(std::make_pair(squaredDistance, &renderable));
}
}
const Camera* Scene::GetCurrentCamera()
{
return mCurrentCamera;
}
void Scene::Render(RenderTarget& renderTarget, const Camera& camera)
{
// There is room for optimisation here by caching the results so if you want
// render the same scene twice you don't need to build it every time.
BuildRenderQueue(camera);
ApplyLights(renderTarget,camera);
const Matrix4& viewMatrix = camera.GetViewMatrix();
if(mSkyBox)
{
mSkyBox->SetPosition(camera.GetPosition());
mSkyBox->Render(viewMatrix, renderTarget);
}
//Need to sort the renderables.
BOOST_REVERSE_FOREACH(DistanceRenderablePair& renderable, mRenderQueue)
{
renderable.second->Render(viewMatrix, renderTarget);
}
BOOST_FOREACH(DistanceRenderablePair& renderable, mRenderQueue)
{
renderable.second->Leave(*this);
}
}
bool Scene::DistanceCompare(const DistanceRenderablePair& a, const DistanceRenderablePair& b)
{
return (a.first<b.first);
}
void Scene::ApplyLights(RenderTarget& renderTarget, const Camera& camera)
{
u32 lightNumber = 0;
renderTarget.SetModelViewMatrix(camera.GetViewMatrix());
BOOST_FOREACH(NamedLightPair& lightPair, mLights)
{
shared_ptr< Light >& light=lightPair.second;
renderTarget.SetLight(lightNumber,light.get());
++lightNumber;
}
}
}

File Metadata

Mime Type
text/x-c++
Expires
Thu, Dec 5, 7:41 PM (13 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
62758
Default Alt Text
Scene.cpp (6 KB)

Event Timeline