Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F96999
Scene.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
Scene.cpp
View Options
#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
Details
Attached
Mime Type
text/x-c++
Expires
Thu, Dec 5, 7:41 PM (1 d, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
62758
Default Alt Text
Scene.cpp (6 KB)
Attached To
Mode
rEE Echo 3
Attached
Detach File
Event Timeline
Log In to Comment