Skip to content

Commit

Permalink
Merge pull request Revolutionary-Games#26 from Revolutionary-Games/14…
Browse files Browse the repository at this point in the history
…_camera

Scriptable Cameras
  • Loading branch information
Daniferrito committed May 17, 2013
2 parents 1311d90 + 80632ee commit b119222
Show file tree
Hide file tree
Showing 11 changed files with 370 additions and 35 deletions.
27 changes: 27 additions & 0 deletions res/dist/scripts/sandbox/camera.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
local playerCam = Entity("playerCam")

-- Camera
playerCam.camera = OgreCameraComponent("playerCam")
playerCam:addComponent(playerCam.camera)
-- Scene node
playerCam.sceneNode = OgreSceneNodeComponent()
playerCam:addComponent(playerCam.sceneNode)
-- Transform
playerCam.transform = TransformComponent()
playerCam:addComponent(playerCam.transform)

playerCam.camera.workingCopy.nearClipDistance = 5
playerCam.camera:touch()

playerCam.transform.workingCopy.position.z = 30
playerCam.transform:touch()

-- OnUpdate
playerCam.onUpdate = OnUpdateComponent()
playerCam:addComponent(playerCam.onUpdate)
local time = 0
playerCam.onUpdate.callback = function(entityId, milliseconds)
time = time + milliseconds / 1000
playerCam.transform.workingCopy.position.z = 25 + 5 * math.sin(time)
playerCam.transform:touch()
end
2 changes: 1 addition & 1 deletion res/dist/scripts/sandbox/light.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ lightEntity = OgreEntityComponent(OgreEntityComponent.PT_SPHERE)
light:addComponent(lightEntity)
onupdate = OnUpdateComponent()
light:addComponent(onupdate)
time = 0
local time = 0
onupdate.callback = function(entityId, milliseconds)
time = time + milliseconds / 1000
light.transform.workingCopy.position.x = 5 * math.sin(time)
Expand Down
1 change: 1 addition & 0 deletions res/dist/scripts/sandbox/manifest.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
background.lua
camera.lua
light.lua
player.lua
2 changes: 2 additions & 0 deletions src/ogre/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
add_sources(
${CMAKE_CURRENT_SOURCE_DIR}/camera_system.cpp
${CMAKE_CURRENT_SOURCE_DIR}/camera_system.h
${CMAKE_CURRENT_SOURCE_DIR}/entity_system.cpp
${CMAKE_CURRENT_SOURCE_DIR}/entity_system.h
${CMAKE_CURRENT_SOURCE_DIR}/keyboard_system.cpp
Expand Down
166 changes: 166 additions & 0 deletions src/ogre/camera_system.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#include "ogre/camera_system.h"

#include "engine/component_registry.h"
#include "engine/entity_filter.h"
#include "ogre/ogre_engine.h"
#include "ogre/scene_node_system.h"
#include "scripting/luabind.h"

#include <iostream>
#include <OgreSceneManager.h>
#include <OgreCamera.h>

using namespace thrive;

////////////////////////////////////////////////////////////////////////////////
// OgreCameraComponent
////////////////////////////////////////////////////////////////////////////////

static void
OgreCameraComponent_touch(
OgreCameraComponent* self
) {
return self->m_properties.touch();
}


static OgreCameraComponent::Properties&
OgreCameraComponent_getWorkingCopy(
OgreCameraComponent* self
) {
return self->m_properties.workingCopy();
}


static const OgreCameraComponent::Properties&
OgreCameraComponent_getLatest(
OgreCameraComponent* self
) {
return self->m_properties.latest();
}


luabind::scope
OgreCameraComponent::luaBindings() {
using namespace luabind;
return class_<OgreCameraComponent, Component, std::shared_ptr<Component>>("OgreCameraComponent")
.scope [
def("TYPE_NAME", &OgreCameraComponent::TYPE_NAME),
def("TYPE_ID", &OgreCameraComponent::TYPE_ID),
class_<Properties>("Properties")
.def_readwrite("polygonMode", &Properties::polygonMode)
.def_readwrite("fovY", &Properties::fovY)
.def_readwrite("nearClipDistance", &Properties::nearClipDistance)
.def_readwrite("farClipDistance", &Properties::farClipDistance)
.def_readwrite("aspectRatio", &Properties::aspectRatio)
]
.enum_("PolygonMode") [
value("PM_POINTS", Ogre::PM_POINTS),
value("PM_WIREFRAME", Ogre::PM_WIREFRAME),
value("PM_SOLID", Ogre::PM_SOLID)
]
.def(constructor<std::string>())
.property("latest", OgreCameraComponent_getLatest)
.property("workingCopy", OgreCameraComponent_getWorkingCopy)
.def("touch", OgreCameraComponent_touch)
;
}

OgreCameraComponent::OgreCameraComponent(
std::string name
) : m_name(name)
{
}

REGISTER_COMPONENT(OgreCameraComponent)


////////////////////////////////////////////////////////////////////////////////
// OgreCameraSystem
////////////////////////////////////////////////////////////////////////////////

struct OgreCameraSystem::Implementation {

std::unordered_map<EntityId, Ogre::Camera*> m_cameras;

Ogre::SceneManager* m_sceneManager = nullptr;

EntityFilter<
OgreSceneNodeComponent,
OgreCameraComponent
> m_entities = {true};
};


OgreCameraSystem::OgreCameraSystem()
: m_impl(new Implementation())
{
}


OgreCameraSystem::~OgreCameraSystem() {}


void
OgreCameraSystem::init(
Engine* engine
) {
System::init(engine);
assert(m_impl->m_sceneManager == nullptr && "Double init of system");
OgreEngine* ogreEngine = dynamic_cast<OgreEngine*>(engine);
assert(ogreEngine != nullptr && "System requires an OgreEngine");
m_impl->m_sceneManager = ogreEngine->sceneManager();
m_impl->m_entities.setEngine(engine);
}


void
OgreCameraSystem::shutdown() {
m_impl->m_entities.setEngine(nullptr);
m_impl->m_sceneManager = nullptr;
System::shutdown();
}


void
OgreCameraSystem::update(int) {
for (auto& value : m_impl->m_entities.addedEntities()) {
EntityId entityId = value.first;
OgreSceneNodeComponent* sceneNodeComponent = std::get<0>(value.second);
OgreCameraComponent* cameraComponent = std::get<1>(value.second);
Ogre::Camera* camera = m_impl->m_sceneManager->createCamera(
cameraComponent->m_name
);
cameraComponent->m_camera = camera;
m_impl->m_cameras[entityId] = camera;
sceneNodeComponent->m_sceneNode->attachObject(camera);
// Test code for scriptable cameras
// TODO: Remove this when scriptable viewports are available (#24)
OgreEngine* ogreEngine = dynamic_cast<OgreEngine*>(this->engine());
ogreEngine->viewport()->setCamera(camera);
}
for (EntityId entityId : m_impl->m_entities.removedEntities()) {
Ogre::Camera* camera = m_impl->m_cameras[entityId];
Ogre::SceneNode* sceneNode = camera->getParentSceneNode();
sceneNode->detachObject(camera);
m_impl->m_sceneManager->destroyCamera(camera);
m_impl->m_cameras.erase(entityId);
}
m_impl->m_entities.clearChanges();
for (auto& value : m_impl->m_entities) {
OgreCameraComponent* cameraComponent = std::get<1>(value.second);
if (cameraComponent->m_properties.hasChanges()) {
const auto& properties = cameraComponent->m_properties.stable();
Ogre::Camera* camera = cameraComponent->m_camera;
// Update camera
camera->setPolygonMode(properties.polygonMode);
camera->setFOVy(properties.fovY);
camera->setNearClipDistance(properties.nearClipDistance);
camera->setFarClipDistance(properties.farClipDistance);
camera->setAspectRatio(properties.aspectRatio);
// Untouch
cameraComponent->m_properties.untouch();
}
}
}

140 changes: 140 additions & 0 deletions src/ogre/camera_system.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#pragma once

#include "engine/component.h"
#include "engine/shared_data.h"
#include "engine/system.h"

#include <memory>
#include <OgreCommon.h>
#include <OgreMath.h>

namespace luabind {
class scope;
}

namespace Ogre {
class Camera;
}

namespace thrive {

/**
* @brief A component for a camera
*
*/
class OgreCameraComponent : public Component {
COMPONENT(OgreCamera)

public:

/**
* @brief Properties
*/
struct Properties {
/**
* @brief The level of rendering detail
*/
Ogre::PolygonMode polygonMode = Ogre::PM_SOLID;

/**
* @brief The y-dimension field of view
*/
Ogre::Radian fovY = Ogre::Radian{45.0f};
/**
* @brief Near clip distance
*/
Ogre::Real nearClipDistance = 100.0f;
/**
* @brief Far clip distance
*/
Ogre::Real farClipDistance = 10000.0f;
/**
* @brief Aspect ratio of the frustum viewport
*/
Ogre::Real aspectRatio = 1.3333f;
};

/**
* @brief Lua bindings
*
* Exposes the following \ref shared_data_lua shared properties:
* - \c Properties::polygonMode
* - \c Properties::fovY
* - \c Properties::nearClipDistance
* - \c Properties::farClipDistance
* - \c Properties::aspectRatio
*
* @return
*/
static luabind::scope
luaBindings();

/**
* @brief Constructor
*
* @param name
* The camera's name
*/
OgreCameraComponent(
std::string name
);

Ogre::Camera* m_camera = nullptr;

/**
* @brief The camera's name
*/
const std::string m_name;

/**
* @brief Shared properties
*/
RenderData<Properties>
m_properties;

};


/**
* @brief Creates, updates and removes cameras
*/
class OgreCameraSystem : public System {

public:

/**
* @brief Constructor
*/
OgreCameraSystem();

/**
* @brief Destructor
*/
~OgreCameraSystem();

/**
* @brief Initializes the system
*
* @param engine
* Must be an OgreEngine
*/
void init(Engine* engine) override;

/**
* @brief Shuts the system down
*/
void shutdown() override;

/**
* @brief Updates the system
*/
void update(int) override;

private:

struct Implementation;
std::unique_ptr<Implementation> m_impl;
};

}

Loading

0 comments on commit b119222

Please sign in to comment.