Version 17 vs 18
Version 17 vs 18
Edits
Edits
- Edit by Timotheos, Version 18
- Sep 15 2017 10:08 PM
- ·Fixed links and grammar
- Edit by Timotheos, Version 17
- Sep 15 2017 9:57 PM
- ·Updated build instructions
« Previous Change | Next Change » |
Edit Older Version 17... | Edit Older Version 18... |
Content Changes
Content Changes
The official Echo project uses the [[tools/netbeans/|NetBeans Integrated Development Environment (IDE)]]. Please [[tools/netbeans/|download and install NetBeans]] before continuing.
Please [[projects/echo_3/building/|install and build the Echo engine]]. You can begin doing this while waiting for NetBeans to install.
Please see the page [[/w/projects/echo_3/netbeans_template/|NetBeans Template]] and [[/w/projects/echo_3/setting_up_your_environment/|Setting Up Your Environment]] for information on setting up your development environment so that you do not have to manually configure project settings.
==Project settings==
NOTE: These project settings are set automatically now. I need to clean this page up.
These categories specify the NetBeans project property pages.
**C++ Compiler**
**All Configurations** Includes: ${ECHO_ENGINE_INSTALL_DIR}/include
**All Configurations** Preprocessors: ECHO_PLATFORM_LINUX ECHO_USING_BOOST
**All Configurations** Additional Options: $$(pkg-config --cflags gtkmm-2.4 gtkglextmm-1.2 sigc++-2.0 freetype2 bullet libmodplug ogg)
**Linker**
**Debug** Additional Library Directories: ${ECHO_ENGINE_INSTALL_DIR}/dist/Debug/GNU-Linux-x86
**Debug** Runtime Search Directories: ${ECHO_ENGINE_INSTALL_DIR}/dist/Debug/GNU-Linux-x86
**Release** Additional Library Directories: ${ECHO_ENGINE_INSTALL_DIR}/dist/Debug/GNU-Linux-x86
**Release** Runtime Search Directories: ${ECHO_ENGINE_INSTALL_DIR}/dist/Debug/GNU-Linux-x86
**All Configurations** Libraries: -lecho3 -lpng12 -lboost_system -lboost_filesystem -lboost_timer -lboost_thread -lboost_chrono `pkg-config --libs protobuf libmodplug vorbis gl gtkmm-2.4 gtkglextmm-1.2 sigc++-2.0 libmodplug ogg openal tinyxml glew vorbisfile`
=Basic examples=
Echo provides the components you need to write an application that can be built without modification on multiple platforms. An application is based around creating at least one `Kernel` object and executing it. How a `Kernel` is executed depends on the platform your application will run on, because of this your application does not have an entry point, such as `main()`, that you would be familiar with.
Instead, the equivalent of your main entry point is the method `EchoInitialise()` which should return a smart pointer to a `Kernel` object. The actual entry point is dictated by `echo/PlatformStub.h` which must be `#include`d. You will need to create a `Kernel` object (or an instance of a class that inherits from `Kernel`) and return it. If your application is going to have multimedia functionality, such as a game, then you may like to use the `Application` class for this. The following is a simple example:
```
#include <echo/Application.h>
// This includes the main() entry point as appropriate for the platform:
#include <echo/PlatformStub.h>
class MyApplication : public Application
{
public:
MyApplication() : mTask("MyTask")
{
//Application inherits from Kernel. If the Kernel doesn't have any tasks to process then it will not
//continue the program loop which is why we give it a Task to process even though the Task
//does not do anything.
AddTask(mTask);
}
private:
Task mTask;
};
shared_ptr<Kernel> EchoInitialise()
{
//Create an instance of MyApplication, initialise it and return.
shared_ptr<Application> application(new MyApplication());
if(application->Initialise("ApplicationTest", 800,600,false))
{
return application;
}
//Failure to initialise an Application object will occur if the target platform has an incomplete configuration.
return shared_ptr<Kernel>();
}
```
This example uses a custom `SceneRenderable` object that renders a cube mesh. The cube is created manually rather than loading a file to keep this example simple (i.e. be contained in one source file and not use external resources). This example renders the cube through two different `Viewport` objects, using a `MultiRenderer`.
```
// General Application includes:
#include <echo/Application.h>
#include <echo/Platform.h>
#include <echo/Graphics/MultiRenderer.h>
#include <echo/Graphics/Viewport.h>
#include <echo/Graphics/Scene.h>
#include <echo/Graphics/Camera.h>
// Spinning Cube includes:
#include <echo/Graphics/Mesh.h>
#include <echo/Graphics/SubMesh.h>
#include <echo/Graphics/SceneRenderable.h>
// This includes the main() entry point as appropriate for the platform:
#include <echo/PlatformStub.h>
using namespace Echo;
// A basic custom scene renderable.
class SpinningCube : public SceneRenderable
{
public:
SpinningCube()
:
mMesh(),
mAngle(0)
{
// Create a cube:
shared_ptr<SubMesh> subMesh = mMesh.CreateSubMesh();
subMesh->AddVertex(Vector3(-2,2,-2));
subMesh->AddColour(Colour(1,0,0));
subMesh->AddVertex(Vector3(2,2,-2));
subMesh->AddColour(Colour(0,1,0));
subMesh->AddVertex(Vector3(-2,-2,-2));
subMesh->AddColour(Colour(0,0,1));
subMesh->AddVertex(Vector3(2,-2,-2));
subMesh->AddColour(Colour(1,1,0));
subMesh->AddVertex(Vector3(-2,2,2));
subMesh->AddColour(Colour(1,1,0));
subMesh->AddVertex(Vector3(2,2,2));
subMesh->AddColour(Colour(0,0,1));
subMesh->AddVertex(Vector3(-2,-2,2));
subMesh->AddColour(Colour(0,1,0));
subMesh->AddVertex(Vector3(2,-2,2));
subMesh->AddColour(Colour(1,0,0));
subMesh->AddFace(IndexedTriangle(0,1,2));
subMesh->AddFace(IndexedTriangle(2,1,3));
subMesh->AddFace(IndexedTriangle(5,4,6));
subMesh->AddFace(IndexedTriangle(5,6,7));
subMesh->AddFace(IndexedTriangle(4,0,6));
subMesh->AddFace(IndexedTriangle(6,0,2));
subMesh->AddFace(IndexedTriangle(0,4,5));
subMesh->AddFace(IndexedTriangle(0,5,1));
subMesh->AddFace(IndexedTriangle(1,5,3));
subMesh->AddFace(IndexedTriangle(3,5,7));
subMesh->AddFace(IndexedTriangle(2,3,7));
subMesh->AddFace(IndexedTriangle(2,7,6));
mMesh.CalculateAABB();
// Create a basic material for the cube:
shared_ptr<Material> material(new Material());
RenderPass pass;
pass.SetCullMode(RenderPass::CullModes::BACK);
pass.SetVertexColouringEnabled(true);
material->AddPass(pass);
// Set the mesh material:
mMesh.SetMaterial(material);
}
AxisAlignedBox GetLocalAxisAlignedBox()
{
AxisAlignedBox box;
box.setMinimum(mMesh.GetMin());
box.setMaximum(mMesh.GetMax());
return box;
}
void Render(const Matrix4& transform, RenderTarget& renderTarget)
{
SetOrientation(Quaternion(Radian(mAngle),Vector3(0.4,0.5,1)));
mAngle += 0.1f;
mMesh.Render(transform * GetTransform(), renderTarget);
}
private:
Mesh mMesh;
f32 mAngle;
};
class MyApplication : public Application
{
public:
MyApplication(void)
: scene()
{
}
bool Initialise(void)
{
if (!Application::Initialise("ApplicationTest", 800, 300, false))
{
return false;
}
shared_ptr<Camera> camera = scene.CreateCamera();
camera->SetPosition(-1,10,10);
camera->LookAt(0,0,0);
shared_ptr<Camera> camera2 = scene.CreateCamera();
camera2->SetPosition(1,10,10);
camera2->LookAt(0,0,0);
GetRenderer()->ClearRenderers();
GetRenderer()->CreateRenderer(make_shared<Viewport>(0,0,0.5,1), camera);
GetRenderer()->CreateRenderer(make_shared<Viewport>(0.5,0,1,1), camera2);
shared_ptr<SpinningCube> spinningCube(new SpinningCube());
scene.AddRenderable(spinningCube);
return AddTask(GetRenderer().get());
}
private:
Scene scene;
};
shared_ptr<Kernel> EchoInitialise()
{
// Create an instance of MyApplication, initialise it and return.
shared_ptr<MyApplication> application(new MyApplication());
if (application->Initialise())
{
return application;
}
// Failure to initialise an Application object will occur if the target platform has an incomplete configuration.
return shared_ptr<Kernel>();
}
```
=== Manual application control (not recommended) ===
This is a simple example to show how you could use Echo for rendering by manually managing the application's execution. The downside to this method is that your code won't be as easily portable to some platforms. The advantage is that it gives you finer control over kernel execution which can be useful if you're trying to integrate Echo components into an existing framework or application.
```
int main(int argc, char** argv)
{
Kernel kernel;
kernel.SetExecutionModel(Platform::CreateExecutionModel());
shared_ptr<RenderTarget> target = Platform::CreateRenderTarget("Window",kernel,800,300,32,false);
MultiRenderer renderer(target);
Scene scene;
shared_ptr<Camera> camera = scene.CreateCamera();
camera->SetPosition(-1,10,10);
camera->LookAt(0,0,0);
shared_ptr<Camera> camera2 = scene.CreateCamera();
camera2->SetPosition(1,10,10);
camera2->LookAt(0,0,0);
renderer.CreateRenderer(make_shared<Viewport>(0,0,0.5,1),camera);
renderer.CreateRenderer(make_shared<Viewport>(0.5,0,1,1),camera2);
kernel.AddTask(renderer);
kernel.Execute();
return 0;
}
```
This example uses a custom `SceneRenderable` object that renders a cube mesh. The cube is created manually rather than loading a file to keep this example simple (i.e. be contained in one source file and not use external resources). This example renders the cube through two different `Viewport` objects, using a `MultiRenderer`.
```
//Platform and Kernel includes
#include <echo/Platform.h>
#include <echo/Kernel/Kernel.h>
//Rendering includes
#include <echo/Graphics/Renderer.h>
#include <echo/Graphics/MultiRenderer.h>
#include <echo/Graphics/Scene.h>
#include <echo/Graphics/Camera.h>
#include <echo/Graphics/Viewport.h>
#include <echo/Graphics/SceneRenderable.h>
//Graphics object includes
#include <echo/Graphics/Mesh.h>
#include <echo/Graphics/SubMesh.h>
//To make this example a little easier on the eyes.
using namespace Echo;
//A basic custom scene renderable.
class SpinningCube : public SceneRenderable
{
public:
SpinningCube() : mAngle(0)
{
//Create a cube
shared_ptr<SubMesh> subMesh = mMesh.CreateSubMesh();
subMesh->AddVertex(Vector3(-2,2,-2));
subMesh->AddColour(Colour(1,0,0));
subMesh->AddVertex(Vector3(2,2,-2));
subMesh->AddColour(Colour(0,1,0));
subMesh->AddVertex(Vector3(-2,-2,-2));
subMesh->AddColour(Colour(0,0,1));
subMesh->AddVertex(Vector3(2,-2,-2));
subMesh->AddColour(Colour(1,1,0));
subMesh->AddVertex(Vector3(-2,2,2));
subMesh->AddColour(Colour(1,1,0));
subMesh->AddVertex(Vector3(2,2,2));
subMesh->AddColour(Colour(0,0,1));
subMesh->AddVertex(Vector3(-2,-2,2));
subMesh->AddColour(Colour(0,1,0));
subMesh->AddVertex(Vector3(2,-2,2));
subMesh->AddColour(Colour(1,0,0));
subMesh->AddFace(IndexedTriangle(0,1,2));
subMesh->AddFace(IndexedTriangle(2,1,3));
subMesh->AddFace(IndexedTriangle(5,4,6));
subMesh->AddFace(IndexedTriangle(5,6,7));
subMesh->AddFace(IndexedTriangle(4,0,6));
subMesh->AddFace(IndexedTriangle(6,0,2));
subMesh->AddFace(IndexedTriangle(0,4,5));
subMesh->AddFace(IndexedTriangle(0,5,1));
subMesh->AddFace(IndexedTriangle(1,5,3));
subMesh->AddFace(IndexedTriangle(3,5,7));
subMesh->AddFace(IndexedTriangle(2,3,7));
subMesh->AddFace(IndexedTriangle(2,7,6));
mMesh.CalculateAABB();
//Create a basic material for the cube
shared_ptr<Material> material(new Material());
RenderPass pass;
pass.SetCullMode(RenderPass::CullModes::BACK);
pass.SetVertexColouringEnabled(true);
material->AddPass(pass);
//Set the mesh material
mMesh.SetMaterial(material);
}
AxisAlignedBox GetLocalAxisAlignedBox()
{
AxisAlignedBox box;
box.setMinimum(mMesh.GetMin());
box.setMaximum(mMesh.GetMax());
return box;
}
void Render(const Matrix4& transform, RenderTarget& renderTarget)
{
SetOrientation(Quaternion(Radian(mAngle),Vector3(0.4,0.5,1)));
mAngle+=0.1f;
mMesh.Render(transform * GetTransform(),renderTarget);
}
private:
Mesh mMesh;
f32 mAngle;
};
int main(int argc, const char* args[])
{
//You don't have to use a kernel object if you want to manage frame updates yourself.
Kernel kernel;
kernel.SetExecutionModel(Platform::CreateExecutionModel());
//Create a render window
shared_ptr<RenderTarget> target = Platform::CreateRenderTarget("Window",kernel,800,300,32,false);
// Renderers are used to render a camera (which renders a scene) in a viewport on a render target. They act as simple mapping
// objects and perform screen clearing and buffer swapping.
//
// A multirenderer will render multiple Renderer objects and control the screen clearing and buffer swapping (otherwise you would
// need to configure each Renderer yourself (which is entirely possible).
MultiRenderer renderer(target);
// Create a scene with a camera.
Scene scene;
shared_ptr<Camera> camera = scene.CreateCamera();
camera->SetPosition(0,0,10);
// Create two renderers taking half of the screen each.
renderer.CreateRenderer(make_shared<Viewport>(0,0,0.5,1),camera);
renderer.CreateRenderer(make_shared<Viewport>(0.5,0,1,1),camera);
// Add our multi-renderer as a task to the Kernel. The Renderer's Update() method will render the
// screen so you may need to set the priority of the task so it updates last.
kernel.AddTask(renderer);
// Create a spinning cube object, defined above.
shared_ptr< SpinningCube > spinningCube(new SpinningCube());
scene.AddRenderable(spinningCube);
// Start program loop
kernel.Execute();
return 0;
}
```
The official Echo project uses the NetBeans Integrated Development Environment (IDE). Please [[tools/netbeans/|download and install NetBeans]] before continuing.
Please [[projects/echo_3/building/|install and build the Echo engine]]. You can begin doing this while waiting for NetBeans to install.
Please see the pages [[/projects/echo_3/netbeans_template/|NetBeans Template]] and [[/projects/echo_3/setting_up_your_environment/|Setting Up Your Environment]] for information on setting up your development environment so that you do not have to manually configure project settings.
==Project settings==
NOTE: These project settings are set automatically now. I need to clean this page up.
These categories specify the NetBeans project property pages.
**C++ Compiler**
**All Configurations** Includes: ${ECHO_ENGINE_INSTALL_DIR}/include
**All Configurations** Preprocessors: ECHO_PLATFORM_LINUX ECHO_USING_BOOST
**All Configurations** Additional Options: $$(pkg-config --cflags gtkmm-2.4 gtkglextmm-1.2 sigc++-2.0 freetype2 bullet libmodplug ogg)
**Linker**
**Debug** Additional Library Directories: ${ECHO_ENGINE_INSTALL_DIR}/dist/Debug/GNU-Linux-x86
**Debug** Runtime Search Directories: ${ECHO_ENGINE_INSTALL_DIR}/dist/Debug/GNU-Linux-x86
**Release** Additional Library Directories: ${ECHO_ENGINE_INSTALL_DIR}/dist/Debug/GNU-Linux-x86
**Release** Runtime Search Directories: ${ECHO_ENGINE_INSTALL_DIR}/dist/Debug/GNU-Linux-x86
**All Configurations** Libraries: -lecho3 -lpng12 -lboost_system -lboost_filesystem -lboost_timer -lboost_thread -lboost_chrono `pkg-config --libs protobuf libmodplug vorbis gl gtkmm-2.4 gtkglextmm-1.2 sigc++-2.0 libmodplug ogg openal tinyxml glew vorbisfile`
=Basic examples=
Echo provides the components you need to write an application that can be built without modification on multiple platforms. An application is based around creating at least one `Kernel` object and executing it. How a `Kernel` is executed depends on the platform your application will run on, because of this your application does not have an entry point, such as `main()`, that you would be familiar with.
Instead, the equivalent of your main entry point is the method `EchoInitialise()` which should return a smart pointer to a `Kernel` object. The actual entry point is dictated by `echo/PlatformStub.h` which must be `#include`d. You will need to create a `Kernel` object (or an instance of a class that inherits from `Kernel`) and return it. If your application is going to have multimedia functionality, such as a game, then you may like to use the `Application` class for this. The following is a simple example:
```
#include <echo/Application.h>
// This includes the main() entry point as appropriate for the platform:
#include <echo/PlatformStub.h>
class MyApplication : public Application
{
public:
MyApplication() : mTask("MyTask")
{
//Application inherits from Kernel. If the Kernel doesn't have any tasks to process then it will not
//continue the program loop which is why we give it a Task to process even though the Task
//does not do anything.
AddTask(mTask);
}
private:
Task mTask;
};
shared_ptr<Kernel> EchoInitialise()
{
//Create an instance of MyApplication, initialise it and return.
shared_ptr<Application> application(new MyApplication());
if(application->Initialise("ApplicationTest", 800,600,false))
{
return application;
}
//Failure to initialise an Application object will occur if the target platform has an incomplete configuration.
return shared_ptr<Kernel>();
}
```
This example uses a custom `SceneRenderable` object that renders a cube mesh. The cube is created manually rather than loading a file to keep this example simple (i.e. be contained in one source file and not use external resources). This example renders the cube through two different `Viewport` objects, using a `MultiRenderer`.
```
// General Application includes:
#include <echo/Application.h>
#include <echo/Platform.h>
#include <echo/Graphics/MultiRenderer.h>
#include <echo/Graphics/Viewport.h>
#include <echo/Graphics/Scene.h>
#include <echo/Graphics/Camera.h>
// Spinning Cube includes:
#include <echo/Graphics/Mesh.h>
#include <echo/Graphics/SubMesh.h>
#include <echo/Graphics/SceneRenderable.h>
// This includes the main() entry point as appropriate for the platform:
#include <echo/PlatformStub.h>
using namespace Echo;
// A basic custom scene renderable.
class SpinningCube : public SceneRenderable
{
public:
SpinningCube()
:
mMesh(),
mAngle(0)
{
// Create a cube:
shared_ptr<SubMesh> subMesh = mMesh.CreateSubMesh();
subMesh->AddVertex(Vector3(-2,2,-2));
subMesh->AddColour(Colour(1,0,0));
subMesh->AddVertex(Vector3(2,2,-2));
subMesh->AddColour(Colour(0,1,0));
subMesh->AddVertex(Vector3(-2,-2,-2));
subMesh->AddColour(Colour(0,0,1));
subMesh->AddVertex(Vector3(2,-2,-2));
subMesh->AddColour(Colour(1,1,0));
subMesh->AddVertex(Vector3(-2,2,2));
subMesh->AddColour(Colour(1,1,0));
subMesh->AddVertex(Vector3(2,2,2));
subMesh->AddColour(Colour(0,0,1));
subMesh->AddVertex(Vector3(-2,-2,2));
subMesh->AddColour(Colour(0,1,0));
subMesh->AddVertex(Vector3(2,-2,2));
subMesh->AddColour(Colour(1,0,0));
subMesh->AddFace(IndexedTriangle(0,1,2));
subMesh->AddFace(IndexedTriangle(2,1,3));
subMesh->AddFace(IndexedTriangle(5,4,6));
subMesh->AddFace(IndexedTriangle(5,6,7));
subMesh->AddFace(IndexedTriangle(4,0,6));
subMesh->AddFace(IndexedTriangle(6,0,2));
subMesh->AddFace(IndexedTriangle(0,4,5));
subMesh->AddFace(IndexedTriangle(0,5,1));
subMesh->AddFace(IndexedTriangle(1,5,3));
subMesh->AddFace(IndexedTriangle(3,5,7));
subMesh->AddFace(IndexedTriangle(2,3,7));
subMesh->AddFace(IndexedTriangle(2,7,6));
mMesh.CalculateAABB();
// Create a basic material for the cube:
shared_ptr<Material> material(new Material());
RenderPass pass;
pass.SetCullMode(RenderPass::CullModes::BACK);
pass.SetVertexColouringEnabled(true);
material->AddPass(pass);
// Set the mesh material:
mMesh.SetMaterial(material);
}
AxisAlignedBox GetLocalAxisAlignedBox()
{
AxisAlignedBox box;
box.setMinimum(mMesh.GetMin());
box.setMaximum(mMesh.GetMax());
return box;
}
void Render(const Matrix4& transform, RenderTarget& renderTarget)
{
SetOrientation(Quaternion(Radian(mAngle),Vector3(0.4,0.5,1)));
mAngle += 0.1f;
mMesh.Render(transform * GetTransform(), renderTarget);
}
private:
Mesh mMesh;
f32 mAngle;
};
class MyApplication : public Application
{
public:
MyApplication(void)
: scene()
{
}
bool Initialise(void)
{
if (!Application::Initialise("ApplicationTest", 800, 300, false))
{
return false;
}
shared_ptr<Camera> camera = scene.CreateCamera();
camera->SetPosition(-1,10,10);
camera->LookAt(0,0,0);
shared_ptr<Camera> camera2 = scene.CreateCamera();
camera2->SetPosition(1,10,10);
camera2->LookAt(0,0,0);
GetRenderer()->ClearRenderers();
GetRenderer()->CreateRenderer(make_shared<Viewport>(0,0,0.5,1), camera);
GetRenderer()->CreateRenderer(make_shared<Viewport>(0.5,0,1,1), camera2);
shared_ptr<SpinningCube> spinningCube(new SpinningCube());
scene.AddRenderable(spinningCube);
return AddTask(GetRenderer().get());
}
private:
Scene scene;
};
shared_ptr<Kernel> EchoInitialise()
{
// Create an instance of MyApplication, initialise it and return.
shared_ptr<MyApplication> application(new MyApplication());
if (application->Initialise())
{
return application;
}
// Failure to initialise an Application object will occur if the target platform has an incomplete configuration.
return shared_ptr<Kernel>();
}
```
=== Manual application control (not recommended) ===
This is a simple example to show how you could use Echo for rendering by manually managing the application's execution. The downside to this method is that your code won't be as easily portable to some platforms. The advantage is that it gives you finer control over kernel execution which can be useful if you're trying to integrate Echo components into an existing framework or application.
```
int main(int argc, char** argv)
{
Kernel kernel;
kernel.SetExecutionModel(Platform::CreateExecutionModel());
shared_ptr<RenderTarget> target = Platform::CreateRenderTarget("Window",kernel,800,300,32,false);
MultiRenderer renderer(target);
Scene scene;
shared_ptr<Camera> camera = scene.CreateCamera();
camera->SetPosition(-1,10,10);
camera->LookAt(0,0,0);
shared_ptr<Camera> camera2 = scene.CreateCamera();
camera2->SetPosition(1,10,10);
camera2->LookAt(0,0,0);
renderer.CreateRenderer(make_shared<Viewport>(0,0,0.5,1),camera);
renderer.CreateRenderer(make_shared<Viewport>(0.5,0,1,1),camera2);
kernel.AddTask(renderer);
kernel.Execute();
return 0;
}
```
This example uses a custom `SceneRenderable` object that renders a cube mesh. The cube is created manually rather than loading a file to keep this example simple (i.e. be contained in one source file and not use external resources). This example renders the cube through two different `Viewport` objects, using a `MultiRenderer`.
```
//Platform and Kernel includes
#include <echo/Platform.h>
#include <echo/Kernel/Kernel.h>
//Rendering includes
#include <echo/Graphics/Renderer.h>
#include <echo/Graphics/MultiRenderer.h>
#include <echo/Graphics/Scene.h>
#include <echo/Graphics/Camera.h>
#include <echo/Graphics/Viewport.h>
#include <echo/Graphics/SceneRenderable.h>
//Graphics object includes
#include <echo/Graphics/Mesh.h>
#include <echo/Graphics/SubMesh.h>
//To make this example a little easier on the eyes.
using namespace Echo;
//A basic custom scene renderable.
class SpinningCube : public SceneRenderable
{
public:
SpinningCube() : mAngle(0)
{
//Create a cube
shared_ptr<SubMesh> subMesh = mMesh.CreateSubMesh();
subMesh->AddVertex(Vector3(-2,2,-2));
subMesh->AddColour(Colour(1,0,0));
subMesh->AddVertex(Vector3(2,2,-2));
subMesh->AddColour(Colour(0,1,0));
subMesh->AddVertex(Vector3(-2,-2,-2));
subMesh->AddColour(Colour(0,0,1));
subMesh->AddVertex(Vector3(2,-2,-2));
subMesh->AddColour(Colour(1,1,0));
subMesh->AddVertex(Vector3(-2,2,2));
subMesh->AddColour(Colour(1,1,0));
subMesh->AddVertex(Vector3(2,2,2));
subMesh->AddColour(Colour(0,0,1));
subMesh->AddVertex(Vector3(-2,-2,2));
subMesh->AddColour(Colour(0,1,0));
subMesh->AddVertex(Vector3(2,-2,2));
subMesh->AddColour(Colour(1,0,0));
subMesh->AddFace(IndexedTriangle(0,1,2));
subMesh->AddFace(IndexedTriangle(2,1,3));
subMesh->AddFace(IndexedTriangle(5,4,6));
subMesh->AddFace(IndexedTriangle(5,6,7));
subMesh->AddFace(IndexedTriangle(4,0,6));
subMesh->AddFace(IndexedTriangle(6,0,2));
subMesh->AddFace(IndexedTriangle(0,4,5));
subMesh->AddFace(IndexedTriangle(0,5,1));
subMesh->AddFace(IndexedTriangle(1,5,3));
subMesh->AddFace(IndexedTriangle(3,5,7));
subMesh->AddFace(IndexedTriangle(2,3,7));
subMesh->AddFace(IndexedTriangle(2,7,6));
mMesh.CalculateAABB();
//Create a basic material for the cube
shared_ptr<Material> material(new Material());
RenderPass pass;
pass.SetCullMode(RenderPass::CullModes::BACK);
pass.SetVertexColouringEnabled(true);
material->AddPass(pass);
//Set the mesh material
mMesh.SetMaterial(material);
}
AxisAlignedBox GetLocalAxisAlignedBox()
{
AxisAlignedBox box;
box.setMinimum(mMesh.GetMin());
box.setMaximum(mMesh.GetMax());
return box;
}
void Render(const Matrix4& transform, RenderTarget& renderTarget)
{
SetOrientation(Quaternion(Radian(mAngle),Vector3(0.4,0.5,1)));
mAngle+=0.1f;
mMesh.Render(transform * GetTransform(),renderTarget);
}
private:
Mesh mMesh;
f32 mAngle;
};
int main(int argc, const char* args[])
{
//You don't have to use a kernel object if you want to manage frame updates yourself.
Kernel kernel;
kernel.SetExecutionModel(Platform::CreateExecutionModel());
//Create a render window
shared_ptr<RenderTarget> target = Platform::CreateRenderTarget("Window",kernel,800,300,32,false);
// Renderers are used to render a camera (which renders a scene) in a viewport on a render target. They act as simple mapping
// objects and perform screen clearing and buffer swapping.
//
// A multirenderer will render multiple Renderer objects and control the screen clearing and buffer swapping (otherwise you would
// need to configure each Renderer yourself (which is entirely possible).
MultiRenderer renderer(target);
// Create a scene with a camera.
Scene scene;
shared_ptr<Camera> camera = scene.CreateCamera();
camera->SetPosition(0,0,10);
// Create two renderers taking half of the screen each.
renderer.CreateRenderer(make_shared<Viewport>(0,0,0.5,1),camera);
renderer.CreateRenderer(make_shared<Viewport>(0.5,0,1,1),camera);
// Add our multi-renderer as a task to the Kernel. The Renderer's Update() method will render the
// screen so you may need to set the priority of the task so it updates last.
kernel.AddTask(renderer);
// Create a spinning cube object, defined above.
shared_ptr< SpinningCube > spinningCube(new SpinningCube());
scene.AddRenderable(spinningCube);
// Start program loop
kernel.Execute();
return 0;
}
```
The official Echo project uses the [[tools/netbeans/|NetBeans Integrated Development Environment (IDE)]]. Please [[tools/netbeans/|download and install NetBeans]] before continuing.
Please [[projects/echo_3/building/|install and build the Echo engine]]. You can begin doing this while waiting for NetBeans to install.
Please see the page [[/ws [[/projects/echo_3/netbeans_template/|NetBeans Template]] and [[/w/projects/echo_3/setting_up_your_environment/|Setting Up Your Environment]] for information on setting up your development environment so that you do not have to manually configure project settings.
==Project settings==
NOTE: These project settings are set automatically now. I need to clean this page up.
These categories specify the NetBeans project property pages.
**C++ Compiler**
**All Configurations** Includes: ${ECHO_ENGINE_INSTALL_DIR}/include
**All Configurations** Preprocessors: ECHO_PLATFORM_LINUX ECHO_USING_BOOST
**All Configurations** Additional Options: $$(pkg-config --cflags gtkmm-2.4 gtkglextmm-1.2 sigc++-2.0 freetype2 bullet libmodplug ogg)
**Linker**
**Debug** Additional Library Directories: ${ECHO_ENGINE_INSTALL_DIR}/dist/Debug/GNU-Linux-x86
**Debug** Runtime Search Directories: ${ECHO_ENGINE_INSTALL_DIR}/dist/Debug/GNU-Linux-x86
**Release** Additional Library Directories: ${ECHO_ENGINE_INSTALL_DIR}/dist/Debug/GNU-Linux-x86
**Release** Runtime Search Directories: ${ECHO_ENGINE_INSTALL_DIR}/dist/Debug/GNU-Linux-x86
**All Configurations** Libraries: -lecho3 -lpng12 -lboost_system -lboost_filesystem -lboost_timer -lboost_thread -lboost_chrono `pkg-config --libs protobuf libmodplug vorbis gl gtkmm-2.4 gtkglextmm-1.2 sigc++-2.0 libmodplug ogg openal tinyxml glew vorbisfile`
=Basic examples=
Echo provides the components you need to write an application that can be built without modification on multiple platforms. An application is based around creating at least one `Kernel` object and executing it. How a `Kernel` is executed depends on the platform your application will run on, because of this your application does not have an entry point, such as `main()`, that you would be familiar with.
Instead, the equivalent of your main entry point is the method `EchoInitialise()` which should return a smart pointer to a `Kernel` object. The actual entry point is dictated by `echo/PlatformStub.h` which must be `#include`d. You will need to create a `Kernel` object (or an instance of a class that inherits from `Kernel`) and return it. If your application is going to have multimedia functionality, such as a game, then you may like to use the `Application` class for this. The following is a simple example:
```
#include <echo/Application.h>
// This includes the main() entry point as appropriate for the platform:
#include <echo/PlatformStub.h>
class MyApplication : public Application
{
public:
MyApplication() : mTask("MyTask")
{
//Application inherits from Kernel. If the Kernel doesn't have any tasks to process then it will not
//continue the program loop which is why we give it a Task to process even though the Task
//does not do anything.
AddTask(mTask);
}
private:
Task mTask;
};
shared_ptr<Kernel> EchoInitialise()
{
//Create an instance of MyApplication, initialise it and return.
shared_ptr<Application> application(new MyApplication());
if(application->Initialise("ApplicationTest", 800,600,false))
{
return application;
}
//Failure to initialise an Application object will occur if the target platform has an incomplete configuration.
return shared_ptr<Kernel>();
}
```
This example uses a custom `SceneRenderable` object that renders a cube mesh. The cube is created manually rather than loading a file to keep this example simple (i.e. be contained in one source file and not use external resources). This example renders the cube through two different `Viewport` objects, using a `MultiRenderer`.
```
// General Application includes:
#include <echo/Application.h>
#include <echo/Platform.h>
#include <echo/Graphics/MultiRenderer.h>
#include <echo/Graphics/Viewport.h>
#include <echo/Graphics/Scene.h>
#include <echo/Graphics/Camera.h>
// Spinning Cube includes:
#include <echo/Graphics/Mesh.h>
#include <echo/Graphics/SubMesh.h>
#include <echo/Graphics/SceneRenderable.h>
// This includes the main() entry point as appropriate for the platform:
#include <echo/PlatformStub.h>
using namespace Echo;
// A basic custom scene renderable.
class SpinningCube : public SceneRenderable
{
public:
SpinningCube()
:
mMesh(),
mAngle(0)
{
// Create a cube:
shared_ptr<SubMesh> subMesh = mMesh.CreateSubMesh();
subMesh->AddVertex(Vector3(-2,2,-2));
subMesh->AddColour(Colour(1,0,0));
subMesh->AddVertex(Vector3(2,2,-2));
subMesh->AddColour(Colour(0,1,0));
subMesh->AddVertex(Vector3(-2,-2,-2));
subMesh->AddColour(Colour(0,0,1));
subMesh->AddVertex(Vector3(2,-2,-2));
subMesh->AddColour(Colour(1,1,0));
subMesh->AddVertex(Vector3(-2,2,2));
subMesh->AddColour(Colour(1,1,0));
subMesh->AddVertex(Vector3(2,2,2));
subMesh->AddColour(Colour(0,0,1));
subMesh->AddVertex(Vector3(-2,-2,2));
subMesh->AddColour(Colour(0,1,0));
subMesh->AddVertex(Vector3(2,-2,2));
subMesh->AddColour(Colour(1,0,0));
subMesh->AddFace(IndexedTriangle(0,1,2));
subMesh->AddFace(IndexedTriangle(2,1,3));
subMesh->AddFace(IndexedTriangle(5,4,6));
subMesh->AddFace(IndexedTriangle(5,6,7));
subMesh->AddFace(IndexedTriangle(4,0,6));
subMesh->AddFace(IndexedTriangle(6,0,2));
subMesh->AddFace(IndexedTriangle(0,4,5));
subMesh->AddFace(IndexedTriangle(0,5,1));
subMesh->AddFace(IndexedTriangle(1,5,3));
subMesh->AddFace(IndexedTriangle(3,5,7));
subMesh->AddFace(IndexedTriangle(2,3,7));
subMesh->AddFace(IndexedTriangle(2,7,6));
mMesh.CalculateAABB();
// Create a basic material for the cube:
shared_ptr<Material> material(new Material());
RenderPass pass;
pass.SetCullMode(RenderPass::CullModes::BACK);
pass.SetVertexColouringEnabled(true);
material->AddPass(pass);
// Set the mesh material:
mMesh.SetMaterial(material);
}
AxisAlignedBox GetLocalAxisAlignedBox()
{
AxisAlignedBox box;
box.setMinimum(mMesh.GetMin());
box.setMaximum(mMesh.GetMax());
return box;
}
void Render(const Matrix4& transform, RenderTarget& renderTarget)
{
SetOrientation(Quaternion(Radian(mAngle),Vector3(0.4,0.5,1)));
mAngle += 0.1f;
mMesh.Render(transform * GetTransform(), renderTarget);
}
private:
Mesh mMesh;
f32 mAngle;
};
class MyApplication : public Application
{
public:
MyApplication(void)
: scene()
{
}
bool Initialise(void)
{
if (!Application::Initialise("ApplicationTest", 800, 300, false))
{
return false;
}
shared_ptr<Camera> camera = scene.CreateCamera();
camera->SetPosition(-1,10,10);
camera->LookAt(0,0,0);
shared_ptr<Camera> camera2 = scene.CreateCamera();
camera2->SetPosition(1,10,10);
camera2->LookAt(0,0,0);
GetRenderer()->ClearRenderers();
GetRenderer()->CreateRenderer(make_shared<Viewport>(0,0,0.5,1), camera);
GetRenderer()->CreateRenderer(make_shared<Viewport>(0.5,0,1,1), camera2);
shared_ptr<SpinningCube> spinningCube(new SpinningCube());
scene.AddRenderable(spinningCube);
return AddTask(GetRenderer().get());
}
private:
Scene scene;
};
shared_ptr<Kernel> EchoInitialise()
{
// Create an instance of MyApplication, initialise it and return.
shared_ptr<MyApplication> application(new MyApplication());
if (application->Initialise())
{
return application;
}
// Failure to initialise an Application object will occur if the target platform has an incomplete configuration.
return shared_ptr<Kernel>();
}
```
=== Manual application control (not recommended) ===
This is a simple example to show how you could use Echo for rendering by manually managing the application's execution. The downside to this method is that your code won't be as easily portable to some platforms. The advantage is that it gives you finer control over kernel execution which can be useful if you're trying to integrate Echo components into an existing framework or application.
```
int main(int argc, char** argv)
{
Kernel kernel;
kernel.SetExecutionModel(Platform::CreateExecutionModel());
shared_ptr<RenderTarget> target = Platform::CreateRenderTarget("Window",kernel,800,300,32,false);
MultiRenderer renderer(target);
Scene scene;
shared_ptr<Camera> camera = scene.CreateCamera();
camera->SetPosition(-1,10,10);
camera->LookAt(0,0,0);
shared_ptr<Camera> camera2 = scene.CreateCamera();
camera2->SetPosition(1,10,10);
camera2->LookAt(0,0,0);
renderer.CreateRenderer(make_shared<Viewport>(0,0,0.5,1),camera);
renderer.CreateRenderer(make_shared<Viewport>(0.5,0,1,1),camera2);
kernel.AddTask(renderer);
kernel.Execute();
return 0;
}
```
This example uses a custom `SceneRenderable` object that renders a cube mesh. The cube is created manually rather than loading a file to keep this example simple (i.e. be contained in one source file and not use external resources). This example renders the cube through two different `Viewport` objects, using a `MultiRenderer`.
```
//Platform and Kernel includes
#include <echo/Platform.h>
#include <echo/Kernel/Kernel.h>
//Rendering includes
#include <echo/Graphics/Renderer.h>
#include <echo/Graphics/MultiRenderer.h>
#include <echo/Graphics/Scene.h>
#include <echo/Graphics/Camera.h>
#include <echo/Graphics/Viewport.h>
#include <echo/Graphics/SceneRenderable.h>
//Graphics object includes
#include <echo/Graphics/Mesh.h>
#include <echo/Graphics/SubMesh.h>
//To make this example a little easier on the eyes.
using namespace Echo;
//A basic custom scene renderable.
class SpinningCube : public SceneRenderable
{
public:
SpinningCube() : mAngle(0)
{
//Create a cube
shared_ptr<SubMesh> subMesh = mMesh.CreateSubMesh();
subMesh->AddVertex(Vector3(-2,2,-2));
subMesh->AddColour(Colour(1,0,0));
subMesh->AddVertex(Vector3(2,2,-2));
subMesh->AddColour(Colour(0,1,0));
subMesh->AddVertex(Vector3(-2,-2,-2));
subMesh->AddColour(Colour(0,0,1));
subMesh->AddVertex(Vector3(2,-2,-2));
subMesh->AddColour(Colour(1,1,0));
subMesh->AddVertex(Vector3(-2,2,2));
subMesh->AddColour(Colour(1,1,0));
subMesh->AddVertex(Vector3(2,2,2));
subMesh->AddColour(Colour(0,0,1));
subMesh->AddVertex(Vector3(-2,-2,2));
subMesh->AddColour(Colour(0,1,0));
subMesh->AddVertex(Vector3(2,-2,2));
subMesh->AddColour(Colour(1,0,0));
subMesh->AddFace(IndexedTriangle(0,1,2));
subMesh->AddFace(IndexedTriangle(2,1,3));
subMesh->AddFace(IndexedTriangle(5,4,6));
subMesh->AddFace(IndexedTriangle(5,6,7));
subMesh->AddFace(IndexedTriangle(4,0,6));
subMesh->AddFace(IndexedTriangle(6,0,2));
subMesh->AddFace(IndexedTriangle(0,4,5));
subMesh->AddFace(IndexedTriangle(0,5,1));
subMesh->AddFace(IndexedTriangle(1,5,3));
subMesh->AddFace(IndexedTriangle(3,5,7));
subMesh->AddFace(IndexedTriangle(2,3,7));
subMesh->AddFace(IndexedTriangle(2,7,6));
mMesh.CalculateAABB();
//Create a basic material for the cube
shared_ptr<Material> material(new Material());
RenderPass pass;
pass.SetCullMode(RenderPass::CullModes::BACK);
pass.SetVertexColouringEnabled(true);
material->AddPass(pass);
//Set the mesh material
mMesh.SetMaterial(material);
}
AxisAlignedBox GetLocalAxisAlignedBox()
{
AxisAlignedBox box;
box.setMinimum(mMesh.GetMin());
box.setMaximum(mMesh.GetMax());
return box;
}
void Render(const Matrix4& transform, RenderTarget& renderTarget)
{
SetOrientation(Quaternion(Radian(mAngle),Vector3(0.4,0.5,1)));
mAngle+=0.1f;
mMesh.Render(transform * GetTransform(),renderTarget);
}
private:
Mesh mMesh;
f32 mAngle;
};
int main(int argc, const char* args[])
{
//You don't have to use a kernel object if you want to manage frame updates yourself.
Kernel kernel;
kernel.SetExecutionModel(Platform::CreateExecutionModel());
//Create a render window
shared_ptr<RenderTarget> target = Platform::CreateRenderTarget("Window",kernel,800,300,32,false);
// Renderers are used to render a camera (which renders a scene) in a viewport on a render target. They act as simple mapping
// objects and perform screen clearing and buffer swapping.
//
// A multirenderer will render multiple Renderer objects and control the screen clearing and buffer swapping (otherwise you would
// need to configure each Renderer yourself (which is entirely possible).
MultiRenderer renderer(target);
// Create a scene with a camera.
Scene scene;
shared_ptr<Camera> camera = scene.CreateCamera();
camera->SetPosition(0,0,10);
// Create two renderers taking half of the screen each.
renderer.CreateRenderer(make_shared<Viewport>(0,0,0.5,1),camera);
renderer.CreateRenderer(make_shared<Viewport>(0.5,0,1,1),camera);
// Add our multi-renderer as a task to the Kernel. The Renderer's Update() method will render the
// screen so you may need to set the priority of the task so it updates last.
kernel.AddTask(renderer);
// Create a spinning cube object, defined above.
shared_ptr< SpinningCube > spinningCube(new SpinningCube());
scene.AddRenderable(spinningCube);
// Start program loop
kernel.Execute();
return 0;
}
```