1
0
Fork 0

Initial commit

This commit is contained in:
Henrik Hautakoski 2015-12-22 17:43:51 +01:00
commit edfc5298e1
252 changed files with 93965 additions and 0 deletions

22
.gitattributes vendored Normal file
View file

@ -0,0 +1,22 @@
# normalize these files. Always LF on checkout and always LF on checkin
.gitignore eol=lf
.gitattributes eol=lf
*.sh text eol=lf
*.ini text eol=lf
*.xml text eol=lf
*.c text eol=lf
*.cpp text eol=lf
*.htext eol=lf
*.txt text eol=lf
*.glsl text eol=lf
# Binary files, should never be normalized.
*.exe binary
*.dll binary
*.so binary
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary

46
.gitignore vendored Normal file
View file

@ -0,0 +1,46 @@
build/
# Thumbnail databases (Windows)
Thumbs.db
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# Visual C++ cache files
*.opensdf
*.sdf
*.aps
# Visual Studio project files.
*.sln
*.vcxproj
*.vcxproj.filters
!vsproj/*
# Compiled Object files
*.slo
*.lo
*.ko
*.o
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Fortran module files
*.mod
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# Spectre 2D Engine
A simple 2D Game engine from scratch!

BIN
assets/app.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

BIN
assets/fonts/Consolas.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,11 @@
#version 330 core
uniform sampler2D u_tex0;
in vec4 vColor; // Vertex color.
in vec2 vTexCoord; // Texture coordinate.
out vec4 fragColor;
void main() {
fragColor = vColor * texture2D(u_tex0, vTexCoord);
}

View file

@ -0,0 +1,21 @@
#version 330 core
uniform mat4 u_MVP;
layout(location = 0) in vec3 in_pos;
layout(location = 3) in vec3 in_color;
layout(location = 8) in vec2 in_texcoord;
out vec4 vColor;
out vec2 vTexCoord;
void main(void) {
gl_Position = u_MVP * vec4(in_pos, 1.0);
vColor = vec4(in_color, 1.0);
// in_texcoord is defined with (0,0) at top-left (same as in_pos)
// however, sampling in OpenGL expects bottom-left. So we must flip Y.
vTexCoord = vec2(in_texcoord.x, 1.0 - in_texcoord.y);
}

View file

@ -0,0 +1,13 @@
#version 330 core
uniform sampler2D u_tex0;
in vec2 vTexCoords; // Texture coordinates (normalized)
in vec4 vColor; // Vertex color
out vec4 fragColor; // Output frag color.
void main() {
// Sample texture red component as alpha value.
vec4 sampled = vec4(1.0f, 1.0, 1.0, texture(u_tex0, vTexCoords).r);
fragColor = vColor * sampled;
}

View file

@ -0,0 +1,21 @@
#version 330 core
uniform mat4 u_MVP;
uniform sampler2D u_tex0;
layout (location = 0) in vec2 in_pos;
layout (location = 3) in vec3 in_color;
layout (location = 8) in vec2 in_texCoords;
out vec2 vTexCoords;
out vec4 vColor;
void main() {
gl_Position = u_MVP * vec4(in_pos, 0.0f, 1.0f);
// Texture coordinates are in pixels.
// Need to convert into UV space before passing to fragment shader.
vTexCoords = in_texCoords / textureSize(u_tex0, 0);
vColor = vec4(in_color, 1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
assets/textures/debug.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
assets/textures/debug_8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

View file

@ -0,0 +1,18 @@
#ifndef SPECTRE_CORE_NONCOPYABLE_H
#define SPECTRE_CORE_NONCOPYABLE_H
class NonCopyable
{
protected :
NonCopyable() {}
private :
// Skip implementation to trigger compiler error.
NonCopyable(const NonCopyable&);
NonCopyable& operator =(const NonCopyable&);
};
#endif /* SPECTRE_CORE_NONCOPYABLE_H */

View file

@ -0,0 +1,20 @@
#ifndef SPECTRE_CORE_STRING_H
#define SPECTRE_CORE_STRING_H
// Basic string functions.
#include <string>
namespace core
{
// Convertion functions from standard c/c++ types.
std::string to_string(unsigned int value);
std::string to_string(float value);
std::string to_string(float value, unsigned int precision);
};
#endif /* SPECTRE_CORE_STRING_H */

View file

@ -0,0 +1,9 @@
#ifndef SPECTRE_DISPLAY_H
#define SPECTRE_DISPLAY_H
#include "Display/Display.h"
#include "Display/DisplayMode.h"
#include "Display/DisplayDescription.h"
#endif /* SPECTRE_DISPLAY_H */

View file

@ -0,0 +1,76 @@
#ifndef SPECTRE_DISPLAY_DISPLAY_H
#define SPECTRE_DISPLAY_DISPLAY_H
#include "DisplayMode.h"
#include "DisplayDescription.h"
#include <Spectre/Display/GLContext.h>
#include <Spectre/System/SystemEvent.h>
#include <string>
class PlatformDisplay;
class GLContext;
class Display
{
friend class PlatformDisplay;
public :
enum Mode {
WINDOWED = 0,
FULLSCREEN = 1,
WINDOWEDFULLSCREEN = 2,
};
public :
Display();
virtual ~Display();
bool create(DisplayDescription decription);
void destroy();
void setSize(unsigned int width, unsigned int height);
void setCaption(const std::string& title);
const std::string& getCaption() const;
void setIcon(const std::string& filename);
void setDisplayMode(const DisplayMode& mode);
const DisplayMode& getDisplayMode() const;
void setVideoMode(Mode mode);
enum Mode getVideoMode() const;
void showCursor(bool value);
bool activate(bool value);
// Enable/Disable Vertical Sync.
bool enableVSync(bool value);
void swapBuffers();
protected :
void init();
void onReshape(int width, int height);
protected :
enum Mode m_fmode;
DisplayDescription m_description;
DisplayDescription m_cacheDesc;
std::string m_caption;
PlatformDisplay* m_impl;
GLContext* m_context;
};
#endif /* SPECTRE_DISPLAY_DISPLAY_H */

View file

@ -0,0 +1,30 @@
#ifndef SPECTRE_DISPLAY_DISPLAYDESCRIPTION_H
#define SPECTRE_DISPLAY_DISPLAYDESCRIPTION_H
#include "DisplayMode.h"
namespace DisplayDecorate {
enum Type {
None = 0,
Menu = 1 << 0,
Resize = 1 << 1,
Close = 1 << 2,
Default = Menu | Resize | Close,
};
};
struct DisplayDescription
{
public :
DisplayDescription();
DisplayDescription(DisplayMode mode, unsigned decoration = DisplayDecorate::Default);
public :
DisplayMode mode;
unsigned int decoration;
};
#endif /* SPECTRE_DISPLAY_DISPLAYDESCRIPTION_H */

View file

@ -0,0 +1,35 @@
#ifndef SPECTRE_DISPLAY_DISPLAYMODE_H
#define SPECTRE_DISPLAY_DISPLAYMODE_H
#include <vector>
class DisplayMode
{
public :
DisplayMode();
DisplayMode(unsigned int width, unsigned int height, unsigned int bpp = 32);
static std::vector<DisplayMode> getFullscreenModes();
static DisplayMode getDesktopMode();
inline bool operator==(const DisplayMode& other)
{
return width == other.width
&& height == other.height
&& bpp == other.bpp;
}
inline bool operator!=(const DisplayMode& other)
{
return !(*this == other);
}
public :
unsigned int width;
unsigned int height;
unsigned int bpp; /* Bits per pixel. */
};
#endif /* SPECTRE_DISPLAY_DISPLAYMODE_H */

View file

@ -0,0 +1,46 @@
#ifndef DISPLAY_GLCONTEXT_H
#define DISPLAY_GLCONTEXT_H
#include <Spectre/Math/Vector2.h>
class PlatformDisplay;
// Platform independant interface for OpenGL Contexts.
class GLContext
{
public :
static GLContext* create();
virtual ~GLContext();
// Create a GLContext for this perticular display.
virtual bool create(const PlatformDisplay* display, unsigned int bpp) = 0;
virtual void destroy() = 0;
// Activate this context.
virtual bool activate() = 0;
// Deactivate this context.
virtual bool deactivate() = 0;
// Returns true if this context is the active one. false otherwise.
// There can only be one GL context active per thread.
virtual bool isActive() const = 0;
// Set the interval for when the front and back framebuffers should be swapped.
// The interval is the number of v-blanks that the gpu must wait before swapping buffers.
// 0 means that the gpu never waits, 1 means after exactly 1 v-blank and so on.
// This is usually refered to as enabling/disabling vertical synchronization.
virtual bool setSwapInterval(int interval) = 0;
// Set the size of the pixel buffer.
virtual void setSize(unsigned int width, unsigned int height) = 0;
// Swap front with back buffer and vice versa.
virtual void swapBuffers() = 0;
};
#endif /* DISPLAY_GLCONTEXT_H */

63
include/Spectre/Game.h Normal file
View file

@ -0,0 +1,63 @@
#ifndef SPECTRE_GAME_H
#define SPECTRE_GAME_H
#include <Spectre/Graphics.h>
#include <Spectre/Input/InputEvent.h>
#include <Spectre/Game/FPSCounter.h>
class InputModule;
class MessageQueue;
class MessageHandler;
class PlatformApplication;
class Game
{
public :
Game();
virtual ~Game();
void run();
void exit();
protected :
virtual void init() = 0;
virtual void update(double dt) = 0;
virtual void render() = 0;
Graphics* getGraphics() const;
InputModule* getInput() const;
FPSCounter& getFpsCounter();
private :
void setup();
void gameLoop();
void processEvents();
private :
PlatformApplication *m_platform;
Graphics *m_graphics;
InputModule* m_input;
MessageHandler* m_messageHandler;
FPSCounter m_fpsCounter;
double m_timestep;
bool m_running;
};
#endif /* SPECTRE_GAME_H */

View file

@ -0,0 +1,43 @@
#ifndef SPECTRE_FPS_COUNTER_H
#define SPECTRE_FPS_COUNTER_H
// Simple FPS counter.
class FPSCounter
{
public :
FPSCounter();
// Add a frame to the counter.
// Should be called whenever a frame has been rendered.
void addFrame();
float getFPS() const;
// Set the update rate (in seconds).
// How often the FPS should be sampled and calculated.
void setUpdateRate(unsigned int seconds);
// Update the internal time measurment.
bool update();
// Reset the frame time
void reset();
private :
// Frame counter.
unsigned int m_count;
// time (in ms)
unsigned int m_time;
// Update rate (in ms)
unsigned int m_updateRate;
// Calculated fps.
float m_fps;
};
#endif /* SPECTRE_FPS_COUNTER_H */

View file

@ -0,0 +1,45 @@
#ifndef SPECTRE_GAME_TIME_H
#define SPECTRE_GAME_TIME_H
class GameTime
{
public :
GameTime(unsigned long updates_per_sec = 60);
void setTimeStep(unsigned long updates_per_sec);
double getTimeStep() const;
unsigned long getElapsed() const;
//bool shouldTick();
bool beginFrame();
bool tick();
void reset();
protected :
void accumulateTime();
void updateTime();
protected :
// TODO: min,max framerates
// Time(in ms) when the last update occured.
unsigned long m_current;
unsigned long m_lastUpdate;
double m_acc;
// timeslice in ms.
double m_slice;
bool m_inLoop;
};
#endif /* SPECTRE_GAME_TIME_H */

View file

@ -0,0 +1,49 @@
#ifndef GRAPHICS_H
#define GRAPHICS_H
#include <Spectre/Display/Display.h>
class PlatformApplication;
class Graphics
{
public :
enum MatrixMode {
PROJECTION,
MODELVIEW,
};
enum VertexType {
TRIANGLES,
};
public :
Graphics(PlatformApplication *platform);
~Graphics();
bool init();
void shutdown();
void setDisplayMode(Display::Mode mode);
void setSize(int width, int height);
void setViewport(int x, int y, int width, int height);
void setClearColor(float r, float g, float b);
void clearBuffer();
void swapBuffers();
protected :
int m_width;
int m_height;
Display *m_display;
};
#endif /* GRAPHICS_H */

View file

@ -0,0 +1,69 @@
#ifndef SPECTRE_BATCH_RENDERER2D_H
#define SPECTRE_BATCH_RENDERER2D_H
#include "Renderer2D.h"
#include <Spectre/Scene/Camera2D.h>
#include <Spectre/Graphics/RenderState.h>
#include <Spectre/Graphics/Vertex2D.h>
#include <Spectre/Math/Matrix4.h>
#include <vector>
class ShaderProgram;
class Texture;
class BatchRenderer2D : public Renderer2D
{
public :
BatchRenderer2D();
~BatchRenderer2D();
void setBatchSize(unsigned short value);
void begin();
void end();
void submit(const Renderable2D& renderable);
void render();
protected :
struct Batch
{
RenderType type;
const Texture* texture;
unsigned int count;
unsigned int offset;
};
typedef std::vector<Batch> BatchQueue;
void prepareQueue();
unsigned int addRenderable(Vertex2D* buffer, const Renderable2D* renderable);
void uploadBatch(const Batch& batch);
void drawBatch(Batch& batch);
protected :
std::vector<const Renderable2D*> m_queue;
unsigned int m_IBO;
unsigned int m_VBO;
RenderState m_state;
unsigned short m_size;
ShaderProgram m_textShader;
ShaderProgram m_spriteShader;
};
#endif /* SPECTRE_BATCH_RENDERER2D_H */

View file

@ -0,0 +1,25 @@
#ifndef SPECTRE_DEFAULT_RENDERER2D_H
#define SPECTRE_DEFAULT_RENDERER2D_H
#include <vector>
#include "Renderer2D.h"
class DefaultRenderer2D : public Renderer2D
{
public :
DefaultRenderer2D();
virtual void submit(const Renderable2D& renderable);
virtual void render();
protected :
std::vector<const Renderable2D*> m_queue;
ShaderProgram m_shader;
};
#endif /* SPECTRE_DEFAULT_RENDERER2D_H */

View file

@ -0,0 +1,74 @@
#ifndef SPECTRE_GRAPHCIS_FONT_H
#define SPECTRE_GRAPHCIS_FONT_H
#include <map>
#include <vector>
#include <string>
#include <Spectre/Math/Vector4.h>
#include <Spectre/Math/Vector2.h>
#include <Spectre/Graphics/Texture.h>
class FontDriver;
// TODO: Fixup this api :)
class Font
{
public :
struct Info {
std::string name;
};
struct Glyph {
vec2b size; // Width, Height of bounding box.
vec2b offset; // Offset from cursor where the box begins.
unsigned char advance;
//vec4u tex_coords;
vec2u texture_origin;
const Texture* texture; // Texture atlas.
};
Font();
~Font();
bool loadFromFile(const std::string& filename, unsigned int size = 22);
bool loadFromMemory(const void *data, unsigned int size);
Glyph getGlyph(unsigned int code) const;
const Texture* getTexture() const;
protected :
bool loadData();
void loadChar(unsigned char code) const;
void createTexture();
void resizeTexture() const;
Vector2u findTextureRegion(const Image& img) const;
protected :
FontDriver *m_driver;
mutable std::map<unsigned char, Glyph> m_charset;
unsigned int m_size; // font size, in pixels. not points.
// Texture atlas used by the font.
mutable Texture m_texture;
mutable vec2u m_texpos;
mutable unsigned m_shelf;
std::vector<unsigned char> m_rawData;
};
#endif /* SPECTRE_GRAPHCIS_FONT_H */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,62 @@
#ifndef SPECTRE_GRAPHICS_IMAGE_H
#define SPECTRE_GRAPHICS_IMAGE_H
#include <string>
#include <vector>
#include <Spectre/Math/Color.h>
#include <Spectre/Math/Vector2.h>
#include <Spectre/Graphics/PixelFormat.h>
class Image
{
public :
Image();
void create(unsigned width, unsigned height, const Color& color = Color::Black);
void create(unsigned width, unsigned height, const void* pixels);
void create(PixelFormat format, unsigned width, unsigned height, const Color& color = Color::Black);
void create(PixelFormat format, unsigned width, unsigned height, const void* pixels);
const Vector2u& getSize() const;
unsigned int getWidth() const;
unsigned int getHeight() const;
unsigned int getBpp() const;
unsigned int getStride() const;
PixelFormat getFormat() const;
// Returns true if the image has a alpha channel.
bool hasAlpha() const;
bool loadFromFile(const std::string& filename);
bool loadFromMemory(const void *data, unsigned int size);
void saveToFile(const std::string& filename) const;
void setPixel(unsigned x, unsigned y, const Color& c);
Color getPixel(unsigned x, unsigned y) const;
void setPixels(const void* pixels);
const unsigned char* getPixels() const;
void flipY();
private :
Vector2u m_size;
PixelFormat m_format;
std::vector<unsigned char> m_pixels;
};
#endif /* SPECTRE_GRAPHICS_IMAGE_H */

View file

@ -0,0 +1,15 @@
#ifndef SPECTRE_OPENGL_H
#define SPECTRE_OPENGL_H
#ifdef _WIN32
#ifdef _MSC_VER
#include <Windows.h>
#endif /* !_MSC_VER */
#include "GL/glew.h"
#include "GL/wglew.h"
#endif /* !_WIN32 */
#endif /* SPECTRE_OPENGL_H */

View file

@ -0,0 +1,12 @@
#ifndef SPECTRE_GRAPHICS_PIXELFORMAT_H
#define SPECTRE_GRAPHICS_PIXELFORMAT_H
enum PixelFormat
{
PF_Unknown = 0,
PF_RGB = 1,
PF_RGBA = 2,
PF_Alpha = 3, // 1 byte alpha channel.
};
#endif SPECTRE_GRAPHICS_PIXELFORMAT_H

View file

@ -0,0 +1,27 @@
#ifndef SPECTRE_GRAPHICS_RENDERSTATE_H
#define SPECTRE_GRAPHICS_RENDERSTATE_H
class ShaderProgram;
class Texture;
class RenderState
{
public :
RenderState();
~RenderState();
void enableTexture(const Texture *texture);
void enableShader(const ShaderProgram *program);
void cleanup();
protected :
const Texture *m_texture;
const ShaderProgram *m_shader;
};
#endif /* SPECTRE_GRAPHICS_RENDERSTATE_H */

View file

@ -0,0 +1,36 @@
#ifndef SPECTRE_GRAPHICS_RENDERABLE_H
#define SPECTRE_GRAPHICS_RENDERABLE_H
#include "Vertex2D.h"
#include "Transformable.h"
#include <Spectre/Math/Matrix4.h>
#include <Spectre/Math/Vector2.h>
#include <vector>
class ShaderProgram;
class Texture;
enum RenderType
{
RenderType_Scene = 0,
RenderType_UI = 1
};
class Renderable2D : public Transformable
{
public :
Renderable2D();
Renderable2D(const Vector2f& position);
virtual ~Renderable2D();
virtual const std::vector<Vertex2D>& getVertices() const = 0;
virtual const std::vector<unsigned short>& getIndices() const = 0;
virtual const Texture* getTexture() const { return NULL; };
virtual const RenderType getRenderType() const = 0;
};
#endif /* SPECTRE_GRAPHCIS_RENDERABLE_H */

View file

@ -0,0 +1,28 @@
#ifndef SPECTRE_GRAPHICS_RENDERER2D_H
#define SPECTRE_GRAPHICS_RENDERER2D_H
#include <Spectre/Graphics/Renderable.h>
#include <Spectre/Graphics/ShaderProgram.h>
#include <Spectre/Scene/Camera2D.h>
class Renderer2D
{
public :
Renderer2D();
virtual ~Renderer2D();
void setCamera(const Camera2D& camera);
virtual void begin() {};
virtual void submit(const Renderable2D& renderable) = 0;
virtual void render() = 0;
protected :
const Camera2D* m_camera;
};
#endif /* SPECTRE_GRAPHICS_RENDERER2D_H */

View file

@ -0,0 +1,54 @@
#ifndef SPECTRE_GRAPHICS_SHADER_H
#define SPECTRE_GRAPHICS_SHADER_H
#include <string>
class Shader
{
public :
enum Type {
Vertex,
Fragment
};
Shader(Type type, const std::string& name = "");
~Shader();
unsigned int getHandle() const;
const std::string& getName() const;
// Load shader from file.
bool loadFromFile(const std::string& file);
// Load shader from memory
bool loadFromMemory(const std::string& source);
const std::string& getError() const;
// Is this shader compiled?
bool isCompiled() const;
protected :
// Compile the shader.
// Returns true if the shader compiled without errors. false otherwise.
bool compile();
std::string fetchErrorLog();
protected :
// Type of shader. Vertex, fragment, geometry etc.
Type m_type;
unsigned int m_handle; // Shader id.
// A name for the shader (usually the filename if loaded from file).
std::string m_name;
std::string m_error;
};
#endif /* SPECTRE_GRAPHICS_SHADER_H */

View file

@ -0,0 +1,86 @@
#ifndef SPECTRE_GRAPHICS_SHADER_PROGRAM_H
#define SPECTRE_GRAPHICS_SHADER_PROGRAM_H
#include <string>
#include <Spectre/Math/Matrix4.h>
#include "Shader.h"
struct Color;
class ShaderProgram
{
public :
ShaderProgram();
~ShaderProgram();
void create();
void destroy();
void addShader(const Shader& shader);
// Load a shader program from file.
//
// The following naming conventions are supported:
// <name>.glsl - Virtual file, will load all real shader files with the same name.
// <name>.vert.glsl - Vertex shader.
// <name>.frag.glsl - Fragment shader.
bool loadFromFile(const std::string& filename);
// Load a shader from file.
bool loadFromFile(const std::string& filename, Shader::Type type);
// Load a shader from memory.
bool loadFromMemory(const std::string& source, Shader::Type type);
// Link the program.
bool link();
// Returns true if the program was linked successfully
bool isLinked() const;
// Enable this shader
// All shader operations after this call will affect this shader.
void enable() const;
// Disable this shader
// Operations will no longer affect this shader after this call.
void disable() const;
// Get the last shader error.
std::string getLastError() const;
// ---------------------
// Variables.
// ---------------------
bool setMVPMatrix(const Matrix4f& matrix);
// ---------------------
// General Variables.
// ---------------------
bool setAttribute(const std::string& name, float value) const;
bool setAttribute(const std::string& name, const Matrix4f& matrix) const;
bool setUniform(const std::string& name, const Matrix4f& matrix) const;
bool setUniform(const std::string& name, const Color& color) const;
protected :
bool getAttribLoc(const std::string& name, int& loc) const;
bool getUniformLoc(const std::string& name, int& loc) const;
std::string fetchErrorLog();
protected :
unsigned int m_id; // program id
mutable std::string m_error;
};
#endif /* SPECTRE_GRAPHICS_SHADER_PROGRAM_H */

View file

@ -0,0 +1,47 @@
#ifndef SPECTRE_GRAPHICS_SPRITE_H
#define SPECTRE_GRAPHICS_SPRITE_H
#include <Spectre/Math/Color.h>
#include "Vertex2D.h"
#include "Renderable.h"
class Texture;
class Sprite : public Renderable2D
{
public :
Sprite();
Sprite(const vec2f& pos, const vec2f& size);
void init();
void setSize(vec2f size);
void setColor(const Color& color);
void setTexture(const Texture& texture);
void setTextureCoords(const vec2u& pos, const vec2u& size);
virtual const Texture* getTexture() const;
virtual const std::vector<Vertex2D>& getVertices() const;
virtual const std::vector<unsigned short>& getIndices() const;
virtual const RenderType getRenderType() const { return RenderType_Scene; };
protected :
void updateGeometry();
std::vector<unsigned short> m_indicies;
std::vector<Vertex2D> m_vertices;
const Texture* m_texture;
};
#endif /* SPECTRE_GRAPHICS_SPRITE_H */

View file

@ -0,0 +1,73 @@
#ifndef SPECTRE_GRAPHICS_TEXT_H
#define SPECTRE_GRAPHICS_TEXT_H
#include <string>
#include <Spectre/Math/Color.h>
#include <Spectre/Graphics/Font.h>
#include <Spectre/Graphics/Transformable.h>
#include <Spectre/Graphics/Renderable.h>
class Text : public Renderable2D
{
public :
/* TODO
enum Properties
{
Regular = 0,
Bold = 1 << 0,
Italic = 1 << 1,
Underline = 1 << 2,
StrikeThrough = 1 << 3
};
enum Alignment
{
Left,
Right,
Center
}; */
Text();
Text(const std::string text, const Font& font);
void setString(const std::string& string);
const std::string& getString() const;
void setFont(const Font& font);
const Font* getFont() const;
void setColor(const Color& color);
const Color& getColor() const;
Vector2f getSize() const;
virtual const std::vector<Vertex2D>& getVertices() const;
virtual const std::vector<unsigned short>& getIndices() const;
virtual const RenderType getRenderType() const { return RenderType_UI; };
virtual const Texture* getTexture() const;
private :
void updateGeometry() const;
private :
// String containing the text.
std::string m_string;
const Font* m_font;
Color m_color;
std::vector<unsigned short> m_indicies;
mutable bool m_geometryNeedsUpdate;
mutable std::vector<Vertex2D> m_vertices;
};
#endif /* SPECTRE_GRAPHICS_TEXT_H */

View file

@ -0,0 +1,91 @@
#ifndef SPECTRE_GRAPHICS_TEXTURE_H
#define SPECTRE_GRAPHICS_TEXTURE_H
#include <Spectre/Core/NonCopyable.h>
#include <Spectre/Math/Vector2.h>
#include <Spectre/Graphics/PixelFormat.h>
#include <Spectre/Graphics/Image.h>
#include <string>
// Basic OpenGL Texture object.
class Texture : public NonCopyable
{
public:
enum Filter {
Nearest = 0x2600,
Linear = 0x2601,
NearestMipmapNearest = 0x2700,
NearestMipmapLinear = 0x2702,
LinearMipmapNearest = 0x2701,
LinearMipmapLinear = 0x2703,
};
enum WrapMode {
Repeat = 0x2901,
RepeatMirror = 0x8370,
ClampToEdge = 0x812F,
ClampToBorder = 0x812D,
};
Texture();
~Texture();
void create(unsigned width, unsigned heigth, PixelFormat format = PixelFormat::PF_RGB);
void create(const Vector2u& size, PixelFormat format = PixelFormat::PF_RGB);
// Create texture from image.
void create(const Image& image);
// Create a texture from a image file on disk.
void create(const std::string& filename, bool isTopDown = true);
// Destroy the texture.
void destroy();
bool isEmpty() const;
const Vector2u& getSize() const;
void update();
void update(vec2u pos, const Image& image);
void update(const Image& image);
// TODO: Fixme
Image copyToImage() const;
void setMinFilter(enum Filter filter);
void setMagFilter(enum Filter filter);
void setSmooth(bool value);
void setWrapMode(enum WrapMode mode);
void setRepeat(bool value);
void enable() const;
void disable() const;
static unsigned int getMaxSize();
// Operators
bool operator<(const Texture* other) const;
bool operator!=(const Texture* other) const;
protected :
unsigned int m_id;
Vector2u m_size;
PixelFormat m_format;
};
#endif /* SPECTRE_GRAPHICS_TEXTURE_H */

View file

@ -0,0 +1,59 @@
#ifndef SPECTRE_GRAPHICS_TRANSFORMABLE_H
#define SPECTRE_GRAPHICS_TRANSFORMABLE_H
#include <Spectre/Math/Transform.h>
#include <Spectre/Math/Vector2.h>
class Transformable
{
public :
Transformable();
Transformable(const Vector2f& position);
virtual ~Transformable();
// Position
void setPosition(const Vector2f& position);
void setPosition(float x, float y);
void move(const Vector2f& offset);
const Vector2f& getPosition() const;
// Rotation
void setRotation(float angle);
void rotate(float angle);
float getRotation() const;
// Scale
void setScale(const Vector2f& offset);
void setScale(float scale);
void scale(const Vector2f& offset);
void scale(float scale);
const Vector2f getScale() const;
const Transform& getTransform() const;
private :
Vector2f m_position;
float m_rotation;
Vector2f m_scale;
mutable bool m_transformNeedsUpdate;
mutable Transform m_transform;
};
#endif /* SPECTRE_GRAPHICS_TRANSFORMABLE_H */

View file

@ -0,0 +1,30 @@
#ifndef SPECTRE_GRAPHICS_VERTEX2D_H
#define SPECTRE_GRAPHICS_VERTEX2D_H
#include <Spectre/Math/Vector2.h>
#include <Spectre/Math/Vector3.h>
// Based on https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/attributes.php
enum VertexAttrib
{
VertexAttribPosition = 0,
VertexAttribColor0 = 3,
VertexAttribColor1 = 4,
VertexAttribTexCoord0 = 8,
};
// Simple POD structure for vertex attributes.
struct Vertex2D
{
Vector2f position;
Vector3f color;
Vector2f uv;
Vertex2D();
Vertex2D(Vector2f pos);
Vertex2D(Vector2f pos, Vector2f uv);
Vertex2D(Vector2f pos, Vector3f color, Vector2f uv = 0.0f);
};
#endif /* SPECTRE_GRAPHICS_VERTEX2D_H */

View file

@ -0,0 +1,19 @@
#ifndef SPECTRE_INTPUT_DEVICE_H
#define SPECTRE_INTPUT_DEVICE_H
class InputDevice
{
friend class InputModule;
public :
virtual ~InputDevice();
virtual void init();
protected :
virtual void update(InputModule *input) = 0;
};
#endif /* SPECTRE_INTPUT_DEVICE_H */

View file

@ -0,0 +1,153 @@
#ifndef SPECTRE_INPUT_EVENT_H
#define SPECTRE_INPUT_EVENT_H
#include <string>
#include <vector>
namespace MouseButton {
enum Type {
Unknown,
Left,
Right,
Middle,
Button1,
Button2,
NUM_MBUTTONS,
};
};
namespace Key {
enum Type {
Unknown,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
One,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Zero,
Period,
Comma,
Enter,
Backspace,
Escape,
Space,
Capslock,
Up,
Down,
Left,
Right,
NUMPAD_1,
NUMPAD_2,
NUMPAD_3,
NUMPAD_4,
NUMPAD_5,
NUMPAD_6,
NUMPAD_7,
NUMPAD_8,
NUMPAD_9,
NUMPAD_0,
NUMPAD_Enter,
Home,
End,
Insert,
Delete,
PageUp,
PageDown,
Pause,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
Tab,
LShift,
RShift,
LCtrl,
RCtrl,
LAlt,
RAlt,
NUM_KEYS,
};
}
typedef struct InputEvent
{
enum Type
{
None,
Key,
MouseButton,
MousePosition
};
struct KeyEvent {
Key::Type code;
bool pressed; /* true if pressed, false if released. */
std::string getKeyName() const; /* Get the key name */
};
struct MouseButtonEvent {
MouseButton::Type button;
bool pressed; /* true if pressed, false if released. */
std::string getName() const;
};
struct MouseEvent {
unsigned int x;
unsigned int y;
};
Type type;
union {
struct KeyEvent key;
struct MouseEvent mouse;
struct MouseButtonEvent mouseButton;
};
InputEvent(Type type = None);
} InputEvent;
#endif /* SPECTRE_INPUT_EVENT_H */

View file

@ -0,0 +1,13 @@
#ifndef SPECTRE_INPUT_LISTENER_H
#define SPECTRE_INPUT_LISTENER_H
#include "InputEvent.h"
class InputListener
{
public :
virtual void onInputEvent(const InputEvent& event);
};
#endif /* SPECTRE_INPUT_LISTENER_H */

View file

@ -0,0 +1,57 @@
#ifndef SPECTRE_INPUT_MODULE_H
#define SPECTRE_INPUT_MODULE_H
#include <deque>
#include <vector>
#include "InputListener.h"
#include "InputEvent.h"
class Mouse;
class Keyboard;
class InputDevice;
class PlatformInput;
class InputModule
{
public :
InputModule(PlatformInput *platform);
virtual ~InputModule();
Mouse* getMouse();
Keyboard* getKeyboard();
void addInputDevice(InputDevice *device);
void registerListener(InputListener* listener);
void removeListener(InputListener* listener);
void postInputEvent(const InputEvent& event);
// NOTE: Update devices here! (for winapi, process keyboard/mouse messages)
void update();
protected :
void dispatch();
typedef std::vector<InputDevice*> InputDeviceVec;
InputDeviceVec m_devices;
Mouse *m_mouse;
Keyboard *m_keyboard;
// Buffered input queue.
std::deque<InputEvent> m_buffer;
std::vector<InputListener*> m_listeners;
PlatformInput *m_platform;
};
#endif /* SPECTRE_INPUT_MODULE_H */

View file

@ -0,0 +1,19 @@
#ifndef SPECTRE_INPUT_KEYBOARD_H
#define SPECTRE_INPUT_KEYBOARD_H
#include <string>
#include "InputEvent.h"
#include "InputDevice.h"
class Keyboard : public InputDevice
{
public :
virtual ~Keyboard() {};
virtual bool isKeyDown(Key::Type key) = 0;
static std::string getKeyName(Key::Type key);
};
#endif /* SPECTRE_INPUT_KEYBOARD_H */

View file

@ -0,0 +1,25 @@
#ifndef SPECTRE_INPUT_MOUSE_H
#define SPECTRE_INPUT_MOUSE_H
#include <string>
#include <Spectre/Math/Vector2.h>
#include "InputEvent.h"
#include "InputDevice.h"
class Mouse : public InputDevice
{
public :
virtual ~Mouse();
// Get mouse position
virtual Vector2f getPosition() const = 0;
//virtual Vector2i getPositionAbs() const = 0;
virtual bool isButtonDown(MouseButton::Type button) const = 0;
static std::string getButtonName(MouseButton::Type button);
};
#endif /* SPECTRE_INPUT_MOUSE_H */

View file

@ -0,0 +1,65 @@
#ifndef SPECTRE_MATH_COLOR_H
#define SPECTRE_MATH_COLOR_H
#include "Vector3.h"
#include "Vector4.h"
// Basic structure representing a color in 32bit RGBA
struct Color
{
public :
unsigned char r, g, b, a;
// Predefined colors
static const Color Black;
static const Color White;
static const Color Red;
static const Color Green;
static const Color Blue;
static const Color Transparant;
Color(unsigned char red = 0, unsigned char green = 0, unsigned char blue = 0, unsigned char alpha = 255);
// Assignment
Color(const Color& color);
Color& operator=(const Color& color);
// Convert to RGB float.
// Each component is clamped to the range [0.0f, 1.0f]
Vector3f toRGBf() const;
// Convert to RGBA float.
// Each component is clamped to the range [0.0f, 1.0f]
Vector4f toRGBAf() const;
};
// ---------
// Compare
// ---------
bool operator ==(const Color& a, const Color& b);
bool operator !=(const Color& a, const Color& b);
// ------------
// Arithmetic
// ------------
Color operator +(const Color& a, const Color& b);
Color operator -(const Color& a, const Color& b);
Color operator /(const Color& a, const Color& b);
Color operator *(const Color& a, const Color& b);
Color& operator +=(Color& a, const Color& b);
Color& operator -=(Color& a, const Color& b);
Color& operator /=(Color& a, const Color& b);
Color& operator *=(Color& a, const Color& b);
// -------------------
// Scalar arithmetic
// -------------------
Color operator +(const Color& a, unsigned int s);
Color operator -(const Color& a, unsigned int s);
Color operator /(const Color& a, unsigned int s);
Color operator *(const Color& a, unsigned int s);
#endif /* SPECTRE_MATH_COLOR_H */

View file

@ -0,0 +1,52 @@
#ifndef SPECTRE_MATH_MATH_H
#define SPECTRE_MATH_MATH_H
#include "Vector3.h"
#include "Vector2.h"
#include "Matrix4.h"
namespace math
{
float rand(float min, float max);
// Convert degrees to radians.
float deg2rad(float deg);
// ------------------------------
// Logarithmic functions.
// ------------------------------
double log(double base, double value);
double log2(double value);
unsigned int nextPowerOfTwo(unsigned int value);
// ------------------------------
// Matrix Projection functions.
// ------------------------------
// Create a orthographic projection matrix.
Matrix4f orthoProjection(float left, float right,
float bottom, float top,
float zNear = -1.0f, float zFar = 1.0f);
// Create a 2D rotation matrix. (rotation around Z-axis)
Matrix4f rotation(float theta);
// Create a 2D translation matrix.
Matrix4f translate(const Vector2f& v);
// Create a 2D scale matrix.
Matrix4f scale(const Vector2f& f);
// Get translation part of a matrix.
Vector3f getTranslate(const Matrix4f matrix);
Vector3f getUpVector(const Matrix4f matrix);
Vector3f getForwardVector(const Matrix4f matrix);
};
#endif /* SPECTRE_MATH_MATH_H */

View file

@ -0,0 +1,79 @@
#ifndef SPECTRE_MATH_MATRIX3_H
#define SPECTRE_MATH_MATRIX3_H
// 3x3 matrix implementation.
#include <iostream>
#include <Spectre/Math/Vector2.h>
template<typename T>
struct Matrix3
{
/* Column-major order are used for the matrices here to be compatible with OpenGL.
_ _
| |
| 0 3 6 |
| 1 4 7 |
| 2 5 8 |
|_ _|
*/
union {
T m[3][3]; // format: [col][row]
T v[9];
};
static Matrix3<T> Identity;
static Matrix3<T> Zero;
inline Matrix3();
inline Matrix3( T a, T b, T c,
T d, T e, T f,
T g, T h, T i);
inline Matrix3(T *a);
// -----------------
// Copy & Assignment.
// -----------------
inline Matrix3<T>& operator=(const Matrix3<T>& mat);
// -----------------
// Compare
// -----------------
inline bool operator==(const Matrix3<T>& mat) const;
inline bool operator!=(const Matrix3<T>& mat) const;
// -----------------
// Arithmetic: Matrix-Matrix
// -----------------
inline Matrix3<T> operator*(const Matrix3<T>& mat) const;
inline Matrix3<T> operator*=(const Matrix3<T>& mat);
// Need scalar, vector arithmetic?
// -----------------
// Named operations.
// -----------------
// Determinant.
float det() const;
// Transpose matrix.
Matrix3<T> transpose() const;
};
template <typename T>
inline std::ostream& operator<<(std::ostream &s, const Matrix3<T>& v);
typedef Matrix3<float> Matrix3f;
typedef Matrix3<double> Matrix3d;
typedef Matrix3<int> Matrix3i;
typedef Matrix3<unsigned> Matrix3u;
#include "Matrix3.inl"
#endif /* SPECTRE_MATH_MATRIX3_H */

View file

@ -0,0 +1,129 @@
#include <string>
#include "Matrix3.h"
template <>
Matrix3f Matrix3f::Identity(
1, 0, 0,
0, 1, 0,
0, 0, 1
);
template <>
Matrix3f Matrix3f::Zero(
0, 0, 0,
0, 0, 0,
0, 0, 0
);
template<typename T>
inline Matrix3<T>::Matrix3()
{
v[0] = T(0); v[3] = T(0); v[6] = T(0);
v[1] = T(0); v[4] = T(0); v[7] = T(0);
v[2] = T(0); v[5] = T(0); v[8] = T(0);
}
template<typename T>
inline Matrix3<T>::Matrix3(T a, T b, T c, T d, T e, T f, T g, T h, T i)
{
v[0] = a; v[3] = d; v[6] = g;
v[1] = b; v[4] = e; v[7] = h;
v[2] = c; v[5] = f; v[8] = i;
}
template<typename T>
inline Matrix3<T>::Matrix3(T *a)
{
v[0] = a[0]; v[3] = a[3]; v[6] = a[6];
v[1] = a[1]; v[4] = a[4]; v[7] = a[7];
v[2] = a[2]; v[5] = a[5]; v[8] = a[8];
}
template<typename T>
inline Matrix3<T>& Matrix3<T>::operator=(const Matrix3<T>& mat)
{
if (this != &mat) {
v[0] = mat.v[0]; v[3] = mat.v[3]; v[6] = mat.v[6];
v[1] = mat.v[1]; v[4] = mat.v[4]; v[7] = mat.v[7];
v[2] = mat.v[2]; v[5] = mat.v[5]; v[8] = mat.v[8];
}
return *this;
}
template<typename T>
inline bool Matrix3<T>::operator==(const Matrix3<T>& mat) const
{
for(int i = 0; i < 9; i++) {
if (v[i] != mat.v[i]) {
return false;
}
}
return true;
}
template<typename T>
inline bool Matrix3<T>::operator!=(const Matrix3<T>& mat) const
{
return !(*this == mat);
}
template<typename T>
inline Matrix3<T> Matrix3<T>::operator*(const Matrix3<T>& mat) const
{
Matrix3<T> c;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
T s = T(0);
for(int k = 0; k < 3; k++) {
s += m[k][i] * mat.m[j][k];
}
c.m[j][i] = s;
}
}
return c;
}
template<typename T>
inline Matrix3<T> Matrix3<T>::operator*=(const Matrix3<T>& mat)
{
*this = *this * mat;
return *this;
}
template<typename T>
float Matrix3<T>::det() const
{
float det = 0.0f;
det += v[0] * v[4] * v[8];
det += v[3] * v[7] * v[2];
det += v[6] * v[1] * v[5];
det -= v[6] * v[4] * v[2];
det -= v[3] * v[1] * v[8];
det -= v[0] * v[7] * v[5];
return det;
}
template<typename T>
Matrix3<T> Matrix3<T>::transpose() const
{
Matrix3<T> t;
t.v[0] = v[0]; t.v[3] = v[1]; t.v[6] = v[2];
t.v[1] = v[3]; t.v[4] = v[4]; t.v[7] = v[5];
t.v[2] = v[6]; t.v[5] = v[7]; t.v[8] = v[8];
return t;
}
template <typename T>
inline std::ostream& operator<<(std::ostream &s, const Matrix3<T>& mat)
{
return s << mat.v[0] << " " << mat.v[3] << " " << mat.v[6] << std::endl
<< mat.v[1] << " " << mat.v[4] << " " << mat.v[7] << std::endl
<< mat.v[2] << " " << mat.v[5] << " " << mat.v[8] << std::endl;
}

View file

@ -0,0 +1,109 @@
#ifndef SPECTRE_MATH_MATRIX4_H
#define SPECTRE_MATH_MATRIX4_H
// 4x4 matrix implementation.
#include <string>
#include <iostream>
#include <Spectre/Math/Vector3.h>
#include <Spectre/Math/Vector2.h>
template<typename T>
struct Matrix4
{
// Column-major order are used for the matrices here to be compatible with OpenGL.
union {
T m[4][4]; // format: [col][row]
/* Indicies to use for accessing elements.
_ _
| |
| 0 4 8 12 |
| 1 5 9 13 |
| 2 6 10 14 |
| 3 7 11 15 |
|_ _|
*/
T e[16];
};
static const Matrix4<T> Identity;
inline Matrix4();
inline Matrix4(
T a00, T a01, T a02, T a03,
T a10, T a11, T a12, T a13,
T a20, T a21, T a22, T a23,
T a30, T a31, T a32, T a33);
inline Matrix4(T *a);
// -------------------
// Copy & Assignment
// -------------------
template <typename U>
inline Matrix4(const Matrix4<U>& mat);
inline Matrix4<T>& operator=(const Matrix4<T>& mat);
// ------------------
// Named operations
// ------------------
// Transpose matrix.
Matrix4<T> transpose() const;
std::string toString() const;
};
// -----------------
// Compare
// -----------------
template <typename T>
inline bool operator==(const Matrix4<T>& a, const Matrix4<T>& b);
template <typename T>
inline bool operator!=(const Matrix4<T>& a, const Matrix4<T>& b);
// --------------------------
// Arithmetic: Matrix-Matrix
// --------------------------
template <typename T>
inline Matrix4<T> operator*(const Matrix4<T>& a, const Matrix4<T>& b);
template <typename T>
inline Matrix4<T>& operator*=(Matrix4<T>& a, const Matrix4<T>& b);
// --------------------------
// Arithmetic: Matrix-Vector
// --------------------------
template <typename T>
inline Vector3<T> operator*(const Matrix4<T>& mat, const Vector3<T>& vec);
template <typename T>
inline std::ostream& operator<<(std::ostream &s, const Matrix4<T>& mat);
// -----------------------------
// Common specialization types
// -----------------------------
typedef Matrix4<float> Matrix4f;
typedef Matrix4<double> Matrix4d;
typedef Matrix4<int> Matrix4i;
typedef Matrix4<unsigned> Matrix4u;
typedef Matrix4<float> mat4f;
typedef Matrix4<double> mat4d;
typedef Matrix4<int> mat4i;
typedef Matrix4<unsigned> mat4u;
// ----------------
// Implementation
// ----------------
#include "Matrix4.inl"
#endif /* SPECTRE_MATH_MATRIX4_H */

View file

@ -0,0 +1,149 @@
#include <iomanip>
#include <sstream>
#include <string.h>
#include "Matrix4.h"
const Matrix4f Matrix4f::Identity(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
);
template<typename T>
inline Matrix4<T>::Matrix4()
{
}
template<typename T>
inline Matrix4<T>::Matrix4(
T a00, T a01, T a02, T a03,
T a10, T a11, T a12, T a13,
T a20, T a21, T a22, T a23,
T a30, T a31, T a32, T a33)
{
e[0] = a00; e[4] = a01; e[8] = a02; e[12] = a03;
e[1] = a10; e[5] = a11; e[9] = a12; e[13] = a13;
e[2] = a20; e[6] = a21; e[10] = a22; e[14] = a23;
e[3] = a30; e[7] = a31; e[11] = a32; e[15] = a33;
}
template<typename T>
inline Matrix4<T>::Matrix4(T *a)
{
// Note. array is passed as row-major
m[0][0] = a[0]; m[1][0] = a[1]; m[2][0] = a[2]; m[3][0] = a[3];
m[0][1] = a[4]; m[1][1] = a[5]; m[2][1] = a[6]; m[3][1] = a[7];
m[0][2] = a[8]; m[1][2] = a[9]; m[2][2] = a[10]; m[3][2] = a[11];
m[0][3] = a[12]; m[1][3] = a[13]; m[2][3] = a[14]; m[3][3] = a[15];
}
template<typename T>
inline Matrix4<T>& Matrix4<T>::operator=(const Matrix4<T>& mat)
{
if (*this != mat) {
memcpy(e, mat.e, sizeof(T) * 16);
}
return *this;
}
template<typename T>
Matrix4<T> Matrix4<T>::transpose() const
{
return Matrix4<T>(
m[0][0], m[1][0], m[2][0], m[3][0],
m[0][1], m[1][1], m[2][1], m[3][1],
m[0][2], m[1][2], m[2][2], m[3][2],
m[0][3], m[1][3], m[2][3], m[3][3]);
}
template <typename T>
std::string Matrix4<T>::toString() const
{
std::stringstream ss;
ss << std::setprecision(2)
<< "[ " << e[0 ] << "\t" << e[1 ] << "\t" << e[2 ] << "\t" << e[3 ] << " ]" << std::endl
<< "| " << e[4 ] << "\t" << e[5 ] << "\t" << e[6 ] << "\t" << e[7 ] << " |" << std::endl
<< "| " << e[8 ] << "\t" << e[9 ] << "\t" << e[10] << "\t" << e[11] << " |" << std::endl
<< "[ " << e[12] << "\t" << e[13] << "\t" << e[14] << "\t" << e[15] << " ]" << std::endl;
return ss.str();
}
template<typename T>
inline bool operator==(const Matrix4<T>& a, const Matrix4<T>& b)
{
return a.e[0 ] == b.e[0 ]
&& a.e[1 ] == b.e[1 ]
&& a.e[2 ] == b.e[2 ]
&& a.e[3 ] == b.e[3 ]
&& a.e[4 ] == b.e[4 ]
&& a.e[5 ] == b.e[5 ]
&& a.e[6 ] == b.e[6 ]
&& a.e[7 ] == b.e[7 ]
&& a.e[8 ] == b.e[8 ]
&& a.e[9 ] == b.e[9 ]
&& a.e[10] == b.e[10]
&& a.e[11] == b.e[11]
&& a.e[12] == b.e[12]
&& a.e[13] == b.e[13]
&& a.e[14] == b.e[14]
&& a.e[15] == b.e[15];
}
template<typename T>
inline bool operator!=(const Matrix4<T>& a, const Matrix4<T>& b)
{
return !(a == b);
}
// -----------------
// Arithmetic: Matrix-Matrix
// -----------------
template<typename T>
inline Matrix4<T> operator*(const Matrix4<T>& a, const Matrix4<T>& b)
{
Matrix4<T> c;
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
T s = T(0);
for(int k = 0; k < 4; k++) {
s += a.m[k][i] * b.m[j][k];
}
c.m[j][i] = s;
}
}
return c;
}
template<typename T>
inline Matrix4<T>& operator*=(Matrix4<T>& a, const Matrix4<T>& b)
{
a = a * b;
return a;
}
// -----------------
// Arithmetic: Matrix-Vector
// -----------------
template <typename T>
inline Vector3<T> operator*(const Matrix4<T>& mat, const Vector3<T>& vec)
{
return Vextor3<T>(
mat.m[0][0] * vec.x + mat.m[1][0] * vec.y + mat[2][0] * vec.z,
mat.m[0][1] * vec.x + mat.m[1][1] * vec.y + mat[2][1] * vec.z,
mat.m[0][2] * vec.x + mat.m[1][2] * vec.y + mat[2][2] * vec.z,
);
}
template <typename T>
inline std::ostream& operator<<(std::ostream &s, const Matrix4<T>& mat)
{
return s << mat.toString();
}

View file

@ -0,0 +1,78 @@
#ifndef SPECTRE_MATH_TRANSFORM_H
#define SPECTRE_MATH_TRANSFORM_H
#include "Vector2.h"
#include "Matrix4.h"
// Class representing a transformation matrix.
class Transform
{
public :
// Constructors
Transform();
Transform(const Matrix4f& matrix);
Transform(float a00, float a01, float a02,
float a10, float a11, float a12,
float a20, float a21, float a22);
// Shorthand for applying translate/rotate/scale.
// Order of operations:
// 1. translate
// 2. rotate
// 3. scale
void set(Vector2f translate, float rotate, Vector2f scale);
void setMatrix(const Matrix4f& matrix);
// Reset the transformation (Identity matrix).
void reset();
// Axis.
Vector2f getUpVector() const;
Vector2f getRightVector() const;
// Translation
Transform& translate(float x, float y);
Transform& translate(Vector2f offset);
// Rotation
Transform& rotate(float theta);
// Scale
Transform& scale(float x, float y);
Transform& scale(Vector2f offset);
Transform& scale(float s);
Transform& multiply(const Transform& other);
Vector2f transformPoint(float x, float y) const;
Vector2f transformPoint(const Vector2f& v) const;
// Get the transformation as a 4x4 matrix.
Matrix4f& getMatrix();
const Matrix4f& getMatrix() const;
Matrix4f getRotationMatrix() const;
float* getRawMatrix();
const float* getRawMatrix() const;
protected :
Matrix4f m_matrix;
};
Transform operator*(const Transform& a, const Transform& b);
Transform& operator*=(Transform& a, const Transform& b);
Vector2f operator*(const Transform& t, const Vector2f& v);
#endif /* SPECTRE_MATH_TRANSFORM_H */

View file

@ -0,0 +1,195 @@
#ifndef SPECTRE_MATH_VECTOR2_H
#define SPECTRE_MATH_VECTOR2_H
#include <string>
#include <iostream>
template <typename T>
struct Vector2
{
union {
struct {
T x, y;
};
T v[2];
};
inline Vector2();
inline Vector2(T s);
inline Vector2(T x, T y);
template <typename U>
inline Vector2(const Vector2<U>& vec);
// -----------------
// Named operations.
// -----------------
inline float length() const;
inline Vector2<T>& normalize();
// Dot product
inline T dot(const Vector2<T>& vec) const;
inline Vector2<T>& reflect(const Vector2<T>& n);
std::string toString() const;
};
// ------------
// Compare
// ------------
template<typename T>
inline bool operator==(const Vector2<T>& a, const Vector2<T>& b);
template<typename T>
inline bool operator!=(const Vector2<T>& a, const Vector2<T>& b);
template<typename T>
inline bool operator<(const Vector2<T>& a, const Vector2<T>& b);
template<typename T>
inline bool operator<=(const Vector2<T>& a, const Vector2<T>& b);
template<typename T>
inline bool operator>(const Vector2<T>& a, const Vector2<T>& b);
template<typename T>
inline bool operator>=(const Vector2<T>& a, const Vector2<T>& b);
// ------------------
// Unary arithmetic
// ------------------
template <typename T>
inline Vector2<T> operator+(const Vector2<T>& v);
template <typename T>
inline Vector2<T> operator-(const Vector2<T>& v);
// ------------
// Arithmetic
// ------------
template<typename T>
inline Vector2<T> operator+(const Vector2<T>& a, const Vector2<T>& b);
template<typename T>
inline Vector2<T> operator-(const Vector2<T>& a, const Vector2<T>& b);
template<typename T>
inline Vector2<T> operator/(const Vector2<T>& a, const Vector2<T>& b);
template<typename T>
inline Vector2<T> operator*(const Vector2<T>& a, const Vector2<T>& b);
template<typename T>
inline Vector2<T>& operator+=(Vector2<T>& a, const Vector2<T>& b);
template<typename T>
inline Vector2<T>& operator-=(Vector2<T>& a, const Vector2<T>& b);
template<typename T>
inline Vector2<T>& operator/=(Vector2<T>& a, const Vector2<T>& b);
template<typename T>
inline Vector2<T>& operator*=(Vector2<T>& a, const Vector2<T>& b);
// -------------------
// Scalar Arithmetic
// -------------------
template <typename T>
inline Vector2<T> operator+(const Vector2<T>& v, T s);
template <typename T>
inline Vector2<T> operator+(T s, const Vector2<T>& v);
template <typename T>
inline Vector2<T> operator-(const Vector2<T>& v,T s);
template <typename T>
inline Vector2<T> operator-(T s, const Vector2<T>& v);
template <typename T>
inline Vector2<T> operator/(const Vector2<T>& v, T s);
template <typename T>
inline Vector2<T> operator/(T s, const Vector2<T>& v);
template <typename T>
inline Vector2<T> operator*(const Vector2<T>& v, T s);
template <typename T>
inline Vector2<T> operator*(T s, const Vector2<T>& v);
template <typename T>
inline Vector2<T>& operator+=(Vector2<T>& v, T s);
template <typename T>
inline Vector2<T>& operator-=(Vector2<T>& v,T s);
template <typename T>
inline Vector2<T>& operator/=(Vector2<T>& v, T s);
template <typename T>
inline Vector2<T>& operator*=(Vector2<T>& v, T s);
// ----------------
// Scalar compare
// ----------------
template <typename T>
inline bool operator<(const Vector2<T>& v, T s);
template <typename T>
inline bool operator<(T s, const Vector2<T>& v);
template <typename T>
inline bool operator<=(const Vector2<T>& v, T s);
template <typename T>
inline bool operator<=(T s, const Vector2<T>& v);
template <typename T>
inline bool operator>(const Vector2<T>& v, T s);
template <typename T>
inline bool operator>(T s, const Vector2<T>& v);
template <typename T>
inline bool operator>=(const Vector2<T>& v, T s);
template <typename T>
inline bool operator>=(T s, const Vector2<T>& v);
// -------------------
// Stream operations
// -------------------
template <typename T>
inline std::ostream& operator<<(std::ostream &s, const Vector2<T>& v);
// -----------------------------
// Common specialization types
// -----------------------------
typedef Vector2<float> Vector2f;
typedef Vector2<int> Vector2i;
typedef Vector2<unsigned> Vector2u;
typedef Vector2<unsigned char> Vector2b;
typedef Vector2<float> vec2f;
typedef Vector2<int> vec2i;
typedef Vector2<unsigned> vec2u;
typedef Vector2<unsigned char> vec2b;
#include "Vector2.inl"
#endif /* SPECTRE_MATH_VECTOR2_H */

View file

@ -0,0 +1,316 @@
#include <Spectre/Core/String.h>
#include <math.h>
#include "Vector2.h"
template <typename T>
Vector2<T>::Vector2()
{
x = T(0); y = T(0);
}
template <typename T>
Vector2<T>::Vector2(T x, T y)
{
v[0] = x; v[1] = y;
}
template <typename T>
Vector2<T>::Vector2(T s)
{
x = s; y = s;
}
template <typename T>
template <typename U>
inline Vector2<T>::Vector2(const Vector2<U>& vec)
{
x = T(vec.x); y = T(vec.y);
}
template <typename T>
inline float Vector2<T>::length() const
{
return std::sqrt((x * x) + (y * y));
}
template <typename T>
inline Vector2<T>& Vector2<T>::normalize()
{
float il = 1.0f / length();
x *= il; y *= il;
return *this;
}
template <typename T>
inline T Vector2<T>::dot(const Vector2<T>& vec) const
{
return x * vec.x + y * vec.y;
}
template <typename T>
inline Vector2<T>& Vector2<T>::reflect(const Vector2<T>& n)
{
*this = T(2) * n * dot(n) - *this;
return *this;
}
template <typename T>
std::string Vector2<T>::toString() const
{
return core::to_string(x) + ", " + core::to_string(y);
}
// ---------
// Compare
// ---------
template <typename T>
inline bool operator==(const Vector2<T>& a, const Vector2<T>& b)
{
return a.x == b.x && a.y == b.y;
}
template <typename T>
inline bool operator!=(const Vector2<T>& a, const Vector2<T>& b)
{
return !(a == b);
}
template<typename T>
inline bool operator<(const Vector2<T>& a, const Vector2<T>& b)
{
return a.x < b.x && a.y < b.y;
}
template<typename T>
inline bool operator<=(const Vector2<T>& a, const Vector2<T>& b)
{
return a.x =< b.x && a.y <= b.y;
}
template<typename T>
inline bool operator>(const Vector2<T>& a, const Vector2<T>& b)
{
return a.x > b.x && a.y > b.y;
}
template<typename T>
inline bool operator>=(const Vector2<T>& a, const Vector2<T>& b)
{
return a.x >= b.x && a.y >= b.y
}
// ------------------
// Unary arithmetic
// ------------------
template <typename T>
inline Vector2<T> operator+(const Vector2<T>& v)
{
return v;
}
template <typename T>
inline Vector2<T> operator-(const Vector2<T>& v)
{
return Vector2<T>(-v.x, -v.y);
}
// ------------
// Arithmetic
// ------------
template<typename T>
inline Vector2<T> operator+(const Vector2<T>& a, const Vector2<T>& b)
{
return Vector2<T>(a.x + b.x, a.y + b.y);
}
template <typename T>
inline Vector2<T> operator-(const Vector2<T>& a, const Vector2<T>& b)
{
return Vector2<T>(a.x - b.x, a.y - b.y);
}
template <typename T>
inline Vector2<T> operator/(const Vector2<T>& a, const Vector2<T>& b)
{
return Vector2<T>(a.x / b.x, a.y / b.y);
}
template <typename T>
inline Vector2<T> operator*(const Vector2<T>& a, const Vector2<T>& b)
{
return Vector2<T>(a.x * b.x, a.y * b.y);
}
template <typename T>
inline Vector2<T>& operator+=(Vector2<T>& a, const Vector2<T>& b)
{
a.x += b.x; a.y += b.y;
return a;
}
template <typename T>
inline Vector2<T>& operator-=(Vector2<T>& a, const Vector2<T>& b)
{
a.x -= b.x; a.y -= b.y;
return a;
}
template <typename T>
inline Vector2<T>& operator/=(Vector2<T>& a, const Vector2<T>& b)
{
a.x /= b.x; a.y /= b.y;
return a;
};
template <typename T>
inline Vector2<T>& operator*=(Vector2<T>& a, const Vector2<T>& b)
{
a.x *= b.x; a.y *= b.y;
return a;
}
// ------------
// Scalar Arithmetic
// ------------
template <typename T>
inline Vector2<T> operator+(const Vector2<T>& v, T s)
{
return Vector2<T>(v.x + s, v.y + s);
}
template <typename T>
inline Vector2<T> operator+(T s, const Vector2<T>& v)
{
return v + s;
}
template <typename T>
inline Vector2<T> operator-(const Vector2<T>& v, T s)
{
return Vector2<T>(v.x - s, v.y - s);
}
template <typename T>
inline Vector2<T> operator-(T s, const Vector2<T>& v)
{
return Vector2<T>(s - v.x, s - v.y);
}
template <typename T>
inline Vector2<T> operator/(const Vector2<T>& v, T s)
{
return Vector2<T>(v.x / s, v.y / s);
}
template <typename T>
inline Vector2<T> operator/(T s, const Vector2<T>& v)
{
return Vector2<T>(s / v.x, s / v.y);
}
template <typename T>
inline Vector2<T> operator*(const Vector2<T>& v, T s)
{
return Vector2<T>(v.x * s, v.y * s);
}
template <typename T>
inline Vector2<T> operator*(T s, const Vector2<T>& v)
{
return v * s;
}
template <typename T>
inline Vector2<T>& operator+=(Vector2<T>& v, T s)
{
v.x += s; v.y += s;
return v;
}
template <typename T>
inline Vector2<T>& operator-=(Vector2<T>& v,T s)
{
v.x -= s; v.y -= s;
return v;
}
template <typename T>
inline Vector2<T>& operator/=(Vector2<T>& v, T s)
{
v.x /= s; v.y /= s;
return v;
}
template <typename T>
inline Vector2<T>& operator*=(Vector2<T>& v, T s)
{
v.x *= s; v.y *= s;
return v;
}
// ----------------
// Scalar compare
// ----------------
template <typename T>
inline bool operator<(const Vector2<T>& v, T s)
{
return v.x < s && v.y < s;
}
template <typename T>
inline bool operator<(T s, const Vector2<T>& v)
{
return s < v.x && s < v.y;
}
template <typename T>
inline bool operator<=(const Vector2<T> v, T s)
{
return v.x <= s && v.y <= s;
}
template <typename T>
inline bool operator<=(T s, const Vector2<T>& v)
{
return s <= v.x && s <= v.y;
}
template <typename T>
inline bool operator>(const Vector2<T> v, T s)
{
return x > s && y > s;
}
template <typename T>
inline bool operator>(T s, const Vector2<T>& v)
{
return s < v.x && s < v.y;
}
template <typename T>
inline bool operator>=(const Vector2<T> v, T s)
{
return v.x >= s && v.y >= s;
}
template <typename T>
inline bool operator>=(T s, const Vector2<T>& v)
{
return s >= v.x && s >= v.y;
}
// -------------------
// Stream operations
// -------------------
template <typename T>
inline std::ostream& operator<<(std::ostream &s, const Vector2<T>& v)
{
return s << "(" << v.x << "," << v.y << ")";
}

View file

@ -0,0 +1,172 @@
#ifndef SPECTRE_MATH_VECTOR3_H
#define SPECTRE_MATH_VECTOR3_H
#include "Vector2.h"
#include <iostream>
template <typename T>
struct Vector3
{
union {
struct {
T x, y, z;
};
T v[3];
};
inline Vector3();
inline Vector3(T s);
inline Vector3(T x, T y);
inline Vector3(T x, T y, T z);
template <typename U>
inline Vector3(const Vector3<U>& vec);
template <typename U>
inline Vector3(const Vector2<U>& vec);
// -----------------
// Named operations.
// -----------------
inline float length() const;
inline Vector3<T>& normalize();
inline Vector2<T> toVec2();
};
// ---------
// Compare
// ---------
template <typename T>
inline bool operator==(const Vector3<T>& a, const Vector3<T>& b);
template <typename T>
inline bool operator!=(const Vector3<T>& a, const Vector3<T>& b);
template <typename T>
inline bool operator<(const Vector3<T>& a, const Vector3<T>& b);
template <typename T>
inline bool operator<=(const Vector3<T>& a, const Vector3<T>& b);
template <typename T>
inline bool operator>(const Vector3<T>& a, const Vector3<T>& b);
template <typename T>
inline bool operator>=(const Vector3<T>& a, const Vector3<T>& b);
// ------------
// Arithmetic
// ------------
template <typename T>
inline Vector3<T> operator+(const Vector3<T>& a, const Vector3<T>& b);
template <typename T>
inline Vector3<T> operator-(const Vector3<T>& a, const Vector3<T>& b);
template <typename T>
inline Vector3<T> operator/(const Vector3<T>& a, const Vector3<T>& b);
template <typename T>
inline Vector3<T> operator*(const Vector3<T>& a, const Vector3<T>& b);
template <typename T>
inline Vector3<T>& operator+=(Vector3<T>& a, const Vector3<T>& b);
template <typename T>
inline Vector3<T>& operator-=(Vector3<T>& a, const Vector3<T>& b);
template <typename T>
inline Vector3<T>& operator/=(Vector3<T>& a, const Vector3<T>& b);
template <typename T>
inline Vector3<T>& operator*=(Vector3<T>& a, const Vector3<T>& b);
// -------------------
// Scalar Arithmetic
// -------------------
template <typename T>
inline Vector3<T> operator+(const Vector3<T>& v, T s);
template <typename T>
inline Vector3<T> operator+(T s, const Vector3<T>& v);
template <typename T>
inline Vector3<T> operator-(const Vector3<T>& v, T s);
template <typename T>
inline Vector3<T> operator-(T s, const Vector3<T>& v);
template <typename T>
inline Vector3<T> operator/(const Vector3<T>& v, T s);
template <typename T>
inline Vector3<T> operator/(T s, const Vector3<T>& v);
template <typename T>
inline Vector3<T> operator*(const Vector3<T>& v, T s);
template <typename T>
inline Vector3<T> operator*(T s, const Vector3<T>& v);
// ----------------
// Scalar compare
// ----------------
template <typename T>
inline bool operator<(const Vector3<T>& v, T s);
template <typename T>
inline bool operator<(T s, const Vector3<T>& v);
template <typename T>
inline bool operator<=(const Vector3<T>& v, T s);
template <typename T>
inline bool operator<=(T s, const Vector3<T>& v);
template <typename T>
inline bool operator>(const Vector3<T>& v, T s);
template <typename T>
inline bool operator>(T s, const Vector3<T>& v);
template <typename T>
inline bool operator>=(const Vector3<T>& v, T s);
template <typename T>
inline bool operator>=(T s, const Vector3<T>& v);
// -------------------
// Stream operations
// -------------------
template <typename T>
inline std::ostream& operator<<(std::ostream &s, const Vector3<T>& v);
// -----------------------------
// Common specialization types
// -----------------------------
typedef Vector3<float> Vector3f;
typedef Vector3<int> Vector3i;
typedef Vector3<unsigned> Vector3u;
typedef Vector3<unsigned char> Vector3b;
typedef Vector3<float> vec3f;
typedef Vector3<int> vec3i;
typedef Vector3<unsigned> vec3u;
typedef Vector3<unsigned char> vec3b;
#include "Vector3.inl"
#endif /* SPECTRE_MATH_VECTOR3_H */

View file

@ -0,0 +1,267 @@
#include <math.h>
#include "Vector3.h"
template <typename T>
Vector3<T>::Vector3()
{
x = y = z = T(0);
}
template <typename T>
Vector3<T>::Vector3(T x, T y, T z)
{
v[0] = x; v[1] = y; v[2] = z;
}
template <typename T>
Vector3<T>::Vector3(T x, T y)
{
v[0] = x; v[1] = y; v[2] = T(0);
}
template <typename T>
Vector3<T>::Vector3(T s)
{
x = y = z = s;
}
template <typename T>
template <typename U>
inline Vector3<T>::Vector3(const Vector3<U>& vec)
{
x = T(vec.x); y = T(vec.y); z = T(vec.z);
}
template <typename T>
template <typename U>
inline Vector3<T>::Vector3(const Vector2<U>& vec)
{
x = T(vec.x); y = T(vec.y); z = T(0);
}
template <typename T>
inline float Vector3<T>::length() const
{
return std::sqrt((x * x) + (y * y) + (z * z));
}
template <typename T>
Vector2<T> Vector3<T>::toVec2()
{
return Vector2<T>(x, y);
}
template <typename T>
inline Vector3<T>& Vector3<T>::normalize()
{
float il = 1.0f / length();
x *= il; y *= il; z *= il;
return *this;
}
// ---------
// Compare
// ---------
template <typename T>
inline bool operator==(const Vector3<T>& a, const Vector3<T>& b)
{
return a.x == b.x && a.y == b.y && a.z == b.z;
}
template <typename T>
inline bool operator!=(const Vector3<T>& a, const Vector3<T>& b)
{
return !(a == b);
}
template <typename T>
inline bool operator<(const Vector3<T>& a, const Vector3<T>& b)
{
return a.x < b.x && a.y < b.y && a.z < b.z;
}
template <typename T>
inline bool operator<=(const Vector3<T>& a, const Vector3<T>& b)
{
return !(a > b);
}
template <typename T>
inline bool operator>(const Vector3<T>& a, const Vector3<T>& b)
{
return a.x > b.x && a.y > b.y && a.z > b.z;
}
template <typename T>
inline bool operator>=(const Vector3<T>& a, const Vector3<T>& b)
{
return !(a < b);
}
// ------------
// Arithmetic
// ------------
template <typename T>
inline Vector3<T> operator+(const Vector3<T>& a, const Vector3<T>& b)
{
return Vector3<T>(a.x + b.x, a.y + b.y, a.z + b.z);
}
template <typename T>
inline Vector3<T> operator-(const Vector3<T>& a, const Vector3<T>& b)
{
return Vector3<T>(a.x - b.x, a.y - b.y, a.z - b.z);
}
template <typename T>
inline Vector3<T> operator/(const Vector3<T>& a, const Vector3<T>& b)
{
return Vector3<T>(a.x / b.x, a.y / b.y, a.z / b.z);
}
template <typename T>
inline Vector3<T> operator*(const Vector3<T>& a, const Vector3<T>& b)
{
return Vector3<T>(a.x * b.x, a.y * b.y, a.z * b.z);
}
template <typename T>
inline Vector3<T>& operator+=(Vector3<T>& a, const Vector3<T>& b)
{
a.x += b.x; a.y += b.y; a.z += b.z;
return a;
}
template <typename T>
inline Vector3<T>& operator-=(Vector3<T>& a, const Vector3<T>& b)
{
a.x -= b.x; a.y -= b.y; a.z -= b.z;
return a;
}
template <typename T>
inline Vector3<T>& operator/=(Vector3<T>& a, const Vector3<T>& b)
{
a.x /= b.x; a.y /= b.y; a.z /= b.z;
return a;
};
template <typename T>
inline Vector3<T>& operator*=(Vector3<T>& a, const Vector3<T>& b)
{
a.x *= b.x; a.y *= b.y; a.z *= b.z;
return a;
}
// -------------------
// Scalar Arithmetic
// -------------------
template <typename T>
inline Vector3<T> operator+(const Vector3<T>& v, T s)
{
return Vector3<T>(v.x + s, v.y + s, v.z + s);
}
template <typename T>
inline Vector3<T> operator+(T s, const Vector3<T>& v)
{
return v + s;
}
template <typename T>
inline Vector3<T> operator-(const Vector3<T>& v, T s)
{
return Vector3<T>(v.x - s, v.y - s, v.z - s);
}
template <typename T>
inline Vector3<T> operator-(T s, const Vector3<T>& v)
{
return Vector3<T>(s - v.x, s - v.y, s - v.z);
}
template <typename T>
inline Vector3<T> operator/(const Vector3<T>& v, T s)
{
return Vector3<T>(v.x / s, v.y / s, v.z / s);
}
template <typename T>
inline Vector3<T> operator/(T s, const Vector3<T>& v)
{
return Vector3<T>(s / v.x, s / v.y, s / v.z);
}
template <typename T>
inline Vector3<T> operator*(const Vector3<T>& v, T s)
{
return Vector3<T>(v.x * s, v.y * s, v.z * s);
}
template <typename T>
inline Vector3<T> operator*(T s, const Vector3<T>& v)
{
return v * s;
}
// ----------------
// Scalar compare
// ----------------
template <typename T>
inline bool operator<(const Vector3<T>& v, T s)
{
return v.x < s && v.y < s && v.z < s;
}
template <typename T>
inline bool operator<(T s, const Vector3<T>& v)
{
return s < v.x && s < v.y && s < v.z;
}
template <typename T>
inline bool operator<=(const Vector3<T>& v, T s)
{
return v.x <= s && v.y <= s && v.z <= s;
}
template <typename T>
inline bool operator<=(T s, const Vector3<T>& v)
{
return s <= v.x && s <= v.y && s <= v.z;
}
template <typename T>
inline bool operator>(const Vector3<T>& v, T s)
{
return v.x > s && v.y > s && v.z > s;
}
template <typename T>
inline bool operator>(T s, const Vector3<T>& v)
{
return s > v.x && s > v.y && s > v.z;
}
template <typename T>
inline bool operator>=(const Vector3<T>& v, T s)
{
return v.x >= s && v.y >= s && v.z >= s;
}
template <typename T>
inline bool operator>=(T s, const Vector3<T>& v)
{
return s >= v.x && s >= v.y && s >= v.z;
}
template <typename T>
inline std::ostream& operator<<(std::ostream &s, const Vector3<T>& v)
{
return s << "(" << v.x << "," << v.y << "," << v.z << ")";
}

View file

@ -0,0 +1,158 @@
#ifndef SPECTRE_MATH_VECTOR4_H
#define SPECTRE_MATH_VECTOR4_H
#include <iostream>
template <typename T>
struct Vector4
{
union {
struct {
T x, y, z, w;
};
T v[4];
};
inline Vector4();
inline Vector4(T s);
inline Vector4(T x, T y, T z);
inline Vector4(T x, T y, T z, T w);
template <typename U>
inline Vector4(const Vector4<U>& vec);
// Named operations
inline float length() const;
inline Vector4<T>& normalize();
};
// ---------
// Compare
// ---------
template <typename T>
inline bool operator==(const Vector4<T>& a, const Vector4<T>& b);
template <typename T>
inline bool operator!=(const Vector4<T>& a, const Vector4<T>& b);
template <typename T>
inline bool operator<(const Vector4<T>& a, const Vector4<T>& b);
template <typename T>
inline bool operator<=(const Vector4<T>& a, const Vector4<T>& b);
template <typename T>
inline bool operator>(const Vector4<T>& a, const Vector4<T>& b);
template <typename T>
inline bool operator>=(const Vector4<T>& a, const Vector4<T>& b);
// ------------
// Arithmetic
// ------------
template <typename T>
inline Vector4<T> operator+(const Vector4<T>& a, const Vector4<T>& b);
template <typename T>
inline Vector4<T> operator-(const Vector4<T>& a, const Vector4<T>& b);
template <typename T>
inline Vector4<T> operator/(const Vector4<T>& a, const Vector4<T>& b);
template <typename T>
inline Vector4<T> operator*(const Vector4<T>& a, const Vector4<T>& b);
template <typename T>
inline Vector4<T>& operator+=(Vector4<T>& a, const Vector4<T>& b);
template <typename T>
inline Vector4<T>& operator-=(Vector4<T>& a, const Vector4<T>& b);
template <typename T>
inline Vector4<T>& operator/=(Vector4<T>& a, const Vector4<T>& b);
template <typename T>
inline Vector4<T>& operator*=(Vector4<T>& a, const Vector4<T>& b);
// -------------------
// Scalar Arithmetic
// -------------------
template <typename T>
inline Vector4<T> operator+(const Vector4<T>& v, T s);
template <typename T>
inline Vector4<T> operator+(T s, const Vector4<T>& v);
template <typename T>
inline Vector4<T> operator-(const Vector4<T>& v, T s);
template <typename T>
inline Vector4<T> operator-(T s, const Vector4<T>& v);
template <typename T>
inline Vector4<T> operator/(const Vector4<T>& v, T s);
template <typename T>
inline Vector4<T> operator/(T s, const Vector4<T>& v);
template <typename T>
inline Vector4<T> operator*(const Vector4<T>& v, T s);
template <typename T>
inline Vector4<T> operator*(T s, const Vector4<T>& v);
// ----------------
// Scalar compare
// ----------------
template <typename T>
inline bool operator<(const Vector4<T>& v, T s);
template <typename T>
inline bool operator<(T s, const Vector4<T>& v);
template <typename T>
inline bool operator<=(const Vector4<T>& v, T s);
template <typename T>
inline bool operator<=(T s, const Vector4<T>& v);
template <typename T>
inline bool operator>(const Vector4<T>& v, T s);
template <typename T>
inline bool operator>(T s, const Vector4<T>& v);
template <typename T>
inline bool operator>=(const Vector4<T>& v, T s);
template <typename T>
inline bool operator>=(T s, const Vector4<T>& v);
// Stream
template <typename T>
inline std::ostream& operator<<(std::ostream &s, const Vector4<T>& v);
typedef Vector4<float> Vector4f;
typedef Vector4<int> Vector4i;
typedef Vector4<unsigned> Vector4u;
typedef Vector4<unsigned char> Vector4b;
typedef Vector4<float> vec4f;
typedef Vector4<int> vec4i;
typedef Vector4<unsigned> vec4u;
typedef Vector4<unsigned char> vec4b;
#include "Vector4.inl"
#endif /* SPECTRE_MATH_VECTOR4_H */

View file

@ -0,0 +1,254 @@
#include <math.h>
#include "Vector4.h"
template <typename T>
Vector4<T>::Vector4()
{
x = y = z = w = T(0);
}
template <typename T>
Vector4<T>::Vector4(T s)
{
x = y = z = w = s;
}
template <typename T>
Vector4<T>::Vector4(T _x, T _y, T _z)
{
x = _x; y = _y; z = _z; w = T(1);
}
template <typename T>
Vector4<T>::Vector4(T _x, T _y, T _z, T _w)
{
x = _x; y = _y; z = _z; w = _w;
}
template <typename T>
template <typename U>
Vector4<T>::Vector4(const Vector4<U>& vec)
{
x = T(vec.x); y = T(vec.y); z = T(vec.z); w = T(vec.w);
}
template <typename T>
float Vector4<T>::length() const
{
return std::sqrt((x * x) + (y * y) + (z * z) + (w * w));
}
template <typename T>
Vector4<T>& Vector4<T>::normalize()
{
float il = 1.0f / length();
x *= il; y *= il; z *= il; w *= il;
return *this;
}
// ---------
// Compare
// ---------
template <typename T>
bool operator==(const Vector4<T>& a, const Vector4<T>& b)
{
return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w;
}
template <typename T>
bool operator!=(const Vector4<T>& a, const Vector4<T>& b)
{
return !(a == b);
}
template <typename T>
bool operator<(const Vector4<T>& a, const Vector4<T>& b)
{
return a.x < b.x && a.y < b.y && a.z < b.z && a.w < b.w;
}
template <typename T>
bool operator<=(const Vector4<T>& a, const Vector4<T>& b)
{
return !(a > b);
}
template <typename T>
bool operator>(const Vector4<T>& a, const Vector4<T>& b)
{
return a.x > b.x && a.y > b.y && a.z > b.z && a.w > b.w;
}
template <typename T>
bool operator>=(const Vector4<T>& a, const Vector4<T>& b)
{
return !(a < b);
}
// ------------
// Arithmetic
// ------------
template <typename T>
inline Vector4<T> operator+(const Vector4<T>& a, const Vector4<T>& b)
{
return Vector4<T>(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
}
template <typename T>
inline Vector4<T> operator-(const Vector4<T>& a, const Vector4<T>& b)
{
return Vector4<T>(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
}
template <typename T>
inline Vector4<T> operator/(const Vector4<T>& a, const Vector4<T>& b)
{
return Vector4<T>(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
}
template <typename T>
inline Vector4<T> operator*(const Vector4<T>& a, const Vector4<T>& b)
{
return Vector4<T>(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
}
template <typename T>
inline Vector4<T>& operator+=(Vector4<T>& a, const Vector4<T>& b)
{
a.x += b.x; a.y += b.y; a.z += b.z; a.w += b.w;
return a;
}
template <typename T>
inline Vector4<T>& operator-=(Vector4<T>& a, const Vector4<T>& b)
{
a.x -= b.x; a.y -= b.y; a.z -= b.z; a.w -= b.w;
return a;
}
template <typename T>
inline Vector4<T>& operator/=(Vector4<T>& a, const Vector4<T>& b)
{
a.x /= b.x; a.y /= b.y; a.z /= b.z; a.w /= b.w;
return a;
}
template <typename T>
inline Vector4<T>& operator*=(Vector4<T>& a, const Vector4<T>& b)
{
a.x *= b.x; a.y *= b.y; a.z *= b.z; a.w *= b.w;
return a;
}
// -------------------
// Scalar Arithmetic
// -------------------
template <typename T>
inline Vector4<T> operator+(const Vector4<T>& v, T s)
{
return Vector4<T>(v.x + s, v.y + s, v.z + s, v.w + s);
}
template <typename T>
inline Vector4<T> operator+(T s, const Vector4<T>& v)
{
return v + s;
}
template <typename T>
inline Vector4<T> operator-(const Vector4<T>& v, T s)
{
return Vector4<T>(v.x - s, v.y - s, v.z - s, v.w - s);
}
template <typename T>
inline Vector4<T> operator-(T s, const Vector4<T>& v)
{
return Vector4<T>(s - v.x, s - v.y, s - v.z, s - v.w);
}
template <typename T>
inline Vector4<T> operator/(const Vector4<T>& v, T s)
{
return Vector4<T>(v.x / s, v.y / s, v.z / s, v.w / s);
}
template <typename T>
inline Vector4<T> operator/(T s, const Vector4<T>& v)
{
return Vector4<T>(s / v.x, s / v.y, s / v.z, s / v.w);
}
template <typename T>
inline Vector4<T> operator*(const Vector4<T>& v, T s)
{
return Vector4<T>(v.x * s, v.y * s, v.z * s, v.w * s);
}
template <typename T>
inline Vector4<T> operator*(T s, const Vector4<T>& v)
{
return v * s;
}
// ----------------
// Scalar compare
// ----------------
template <typename T>
inline bool operator<(const Vector4<T>& v, T s)
{
return v.x < s && v.y < s && v.z < s && v.w < s;
}
template <typename T>
inline bool operator<(T s, const Vector4<T>& v)
{
return s < v.x && s < v.y && s < v.z && s < v.w;
}
template <typename T>
inline bool operator<=(const Vector4<T>& v, T s)
{
return v.x <= s && v.y <= s && v.z <= s && v.w <= s;
}
template <typename T>
inline bool operator<=(T s, const Vector4<T>& v)
{
return s <= v.x && s <= v.y && s <= v.z && s <= v.w;
}
template <typename T>
inline bool operator>(const Vector4<T>& v, T s)
{
return v.x > s && v.y > s && v.z > s && v.w > s;
}
template <typename T>
inline bool operator>(T s, const Vector4<T>& v)
{
return s > v.x && s > v.y && s > v.z && s > v.w;
}
template <typename T>
inline bool operator>=(const Vector4<T>& v, T s)
{
return v.x >= s && v.y >= s && v.z >= s && v.w >= s;
}
template <typename T>
inline bool operator>=(T s, const Vector4<T>& v)
{
return s >= v.x && s >= v.y && s >= v.z && s >= v.w;
}
template <typename T>
inline std::ostream& operator<<(std::ostream &s, const Vector4<T>& v)
{
return s << "(" << v.x << "," << v.y << "," << v.z << "," << v.w << ")";
}

View file

@ -0,0 +1,78 @@
#ifndef SPECTRE_SCENE_CAMERA2D_H
#define SPECTRE_SCENE_CAMERA2D_H
#include "ICamera.h"
#include <Spectre/Math/Transform.h>
// 2D camera implementation.
// TODO: Support unprojection, from Screenspace -> Worldspace.
// TODO: Zoom is implemented using a scale matrix.
// It's abit weird to control. Must be a better solution.
class Camera2D : public ICamera
{
public :
Camera2D();
Camera2D(const Vector2f& position, const Vector2f& size);
void reset(const Vector2f& position, const Vector2f& size);
// Position
void setPosition(float x, float y);
void setPosition(const Vector2f& position);
const Vector2f& getPosition() const;
void move(float x, float y);
void move(const Vector2f& vec);
void moveUp(float delta);
void moveRight(float delta);
// Size
void setSize(unsigned int w, unsigned int h);
void setSize(const Vector2u& size);
const Vector2u& getSize() const;
// Zoom
void setZoom(float factor);
void zoom(float factor);
// Rotation
void setRotation(float angle);
void rotate(float delta);
float getRotation() const;
// Current view matrix.
const Matrix4f& getViewMatrix() const;
const Matrix4f& getProjectionMatrix() const;
const Transform& getTransform() const;
protected :
Vector2f m_position;
float m_rotation;
float m_zoom;
Vector2u m_size;
// View matrix. should transform world <-> eye space.
mutable Transform m_view;
mutable bool m_viewNeedsUpdate;
// Projection matrix. transforms eye -> Clipping space.
mutable Matrix4f m_proj;
mutable bool m_projNeedsUpdate;
};
#endif /* SPECTRE_SCENE_CAMERA2D_H */

View file

@ -0,0 +1,18 @@
#ifndef SPECTRE_SCENE_ICAMERA_H
#define SPECTRE_SCENE_ICAMERA_H
#include <Spectre/Math/Matrix4.h>
// Camera interface.
class ICamera
{
public :
virtual ~ICamera() {};
virtual const Matrix4f& getViewMatrix() const = 0;
virtual const Matrix4f& getProjectionMatrix() const = 0;
};
#endif /* SPECTRE_SCENE_ICAMERA_H */

View file

@ -0,0 +1,19 @@
#ifndef SPECTRE_SYSTEM_FILE_H
#define SPECTRE_SYSTEM_FILE_H
#include <vector>
#include <string>
namespace File
{
std::string getBasename(const std::string& path);
std::string getExtension(const std::string& path);
std::string getPathname(const std::string& path);
std::vector<unsigned char> read(const std::string& path);
};
#endif /* SPECTRE_SYSTEM_FILE_H */

View file

@ -0,0 +1,7 @@
#ifndef SYSTEM_LOG_H
#define SYSTEM_LOG_H
void log(const char *fmt, ...);
#endif /* SYSTEM_LOG_H */

View file

@ -0,0 +1,15 @@
#ifndef SPECTRE_SYSTEM_MESSAGEHANDLER_H
#define SPECTRE_SYSTEM_MESSAGEHANDLER_H
#include "SystemEvent.h"
class Display;
class MessageHandler
{
public :
virtual void onSizeChanged(Display* display, int width, int height);
};
#endif /* SPECTRE_SYSTEM_MESSAGEHANDLER_H */

View file

@ -0,0 +1,21 @@
#ifndef SPECTRE_MESSAGE_QUEUE_H
#define SPECTRE_MESSAGE_QUEUE_H
#include <Spectre/System/SystemEvent.h>
#include <queue>
class MessageQueue
{
public :
void postEvent(SysEvent& event);
bool pollEvent(SysEvent& event);
bool isEmpty() const;
protected :
std::deque<SysEvent> m_queue;
};
#endif /* SPECTRE_MESSAGE_QUEUE_H */

View file

@ -0,0 +1,12 @@
#ifndef SPECTRE_SYSTEM_SYSTEM_H
#define SPECTRE_SYSTEM_SYSTEM_H
namespace System
{
unsigned long getMilliseconds();
void sleep(int milliseconds);
};
#endif /* SPECTRE_SYSTEM_SYSTEM_H */

View file

@ -0,0 +1,38 @@
#ifndef SYSTEM_EVENT_H
#define SYSTEM_EVENT_H
class Display;
struct SysEvent
{
public :
enum Type {
None,
Quit,
Size,
};
Type type;
struct Size
{
Display *display;
int width;
int height;
};
union {
struct Size size;
};
SysEvent(Type type = None);
// Helper methods
static SysEvent sizeEvent(Display *display, int width, int height);
};
#endif /* SYSTEM_EVENT_H */

25
source/Core/String.cpp Normal file
View file

@ -0,0 +1,25 @@
#include <cstdio>
#include <Spectre/Core/String.h>
std::string core::to_string(unsigned int value)
{
char buf[32];
sprintf(buf, "%u", value);
return std::string(buf);
}
std::string core::to_string(float value)
{
char buf[32];
sprintf(buf, "%f", value);
return std::string(buf);
}
std::string core::to_string(float value, unsigned int precision)
{
char buf[32];
std::string format = "%." + to_string(precision) + "f";
sprintf(buf, format.c_str(), value);
return std::string(buf);
}

150
source/Display/Display.cpp Normal file
View file

@ -0,0 +1,150 @@
#include <iostream>
#include <Spectre/Display/Display.h>
#include <Spectre/Display/GLContext.h>
#include <Spectre/System/SystemEvent.h>
#include <Platform/PlatformDisplay.h>
#define CAPTION_DEFAULT "Spectre"
#define ICON_DEFAULT "./assets/app.ico"
Display::Display()
{
m_caption = CAPTION_DEFAULT;
m_fmode = WINDOWED;
m_context = GLContext::create();
m_impl = PlatformDisplay::make(this);
}
Display::~Display()
{
delete m_context;
delete m_impl;
}
bool Display::create(DisplayDescription description)
{
destroy();
if (!m_impl->create(description)) {
return false;
}
if (!m_context->create(m_impl, description.mode.bpp)) {
return false;
}
init();
m_description = description;
return true;
}
void Display::init()
{
m_impl->setCaption(m_caption);
setIcon(ICON_DEFAULT);
activate(true);
enableVSync(false);
showCursor(true);
}
void Display::destroy()
{
m_context->destroy();
m_impl->destroy();
}
void Display::setCaption(const std::string& caption)
{
m_caption = caption;
m_impl->setCaption(m_caption);
}
const std::string& Display::getCaption() const
{
return m_caption;
}
void Display::setIcon(const std::string& filename)
{
m_impl->setIcon(filename);
}
void Display::setSize(unsigned int width, unsigned int height)
{
m_description.mode.width = width;
m_description.mode.height = height;
m_impl->setSize(width, height);
}
void Display::setVideoMode(Mode mode)
{
DisplayDescription desc;
if (m_fmode == mode) {
return;
}
if (mode == FULLSCREEN || mode == WINDOWEDFULLSCREEN) {
// True fullscreen
if (mode == FULLSCREEN) {
desc.mode = m_description.mode;
} else {
desc.mode = DisplayMode::getDesktopMode();
m_cacheDesc = m_description;
}
desc.decoration = DisplayDecorate::None;
} else {
desc = m_cacheDesc;
}
create(desc);
m_fmode = mode;
}
enum Display::Mode Display::getVideoMode() const
{
return m_fmode;
}
void Display::showCursor(bool value)
{
m_impl->showCursor(value);
}
bool Display::activate(bool value)
{
if (value) {
return m_context->activate();
}
return m_context->deactivate();
}
bool Display::enableVSync(bool value)
{
return m_context->setSwapInterval(value ? 1 : 0);
}
void Display::swapBuffers()
{
if (activate(true)) {
m_context->swapBuffers();
}
}
void Display::onReshape(int width, int height)
{
// Resize context if the windows resizes.
m_context->setSize(width, height);
}

View file

@ -0,0 +1,14 @@
#include <Spectre/Display/DisplayDescription.h>
DisplayDescription::DisplayDescription() :
mode (),
decoration (DisplayDecorate::Default)
{
}
DisplayDescription::DisplayDescription(DisplayMode mode, unsigned decoration) :
mode (mode),
decoration (decoration)
{
}

View file

@ -0,0 +1,54 @@
#include <Spectre/Display/DisplayMode.h>
#include <Platform/PlatformMisc.h>
#include <algorithm>
struct DisplayModeCmp
{
inline bool operator() (const DisplayMode& a, const DisplayMode& b)
{
if (a.bpp == b.bpp) {
if (a.width == b.width) {
return a.height > b.height;
}
return a.width > b.width;
}
return a.bpp > b.bpp;
}
};
DisplayMode::DisplayMode() :
width (0),
height (0),
bpp (32)
{
}
DisplayMode::DisplayMode(unsigned int width, unsigned int height, unsigned int bpp) :
width (width),
height (height),
bpp (bpp)
{
}
std::vector<DisplayMode> DisplayMode::getFullscreenModes()
{
static std::vector<DisplayMode> modes;
if (modes.size() < 1) {
PlatformMisc::GetDisplayModes(modes);
// Sort.
std::sort(modes.begin(), modes.end(), DisplayModeCmp());
// remove duplicates
modes.erase(std::unique(modes.begin(), modes.end()), modes.end());
}
return modes;
}
DisplayMode DisplayMode::getDesktopMode()
{
return PlatformMisc::GetDesktopMode();
}

View file

@ -0,0 +1,19 @@
#include <Spectre/Display/GLContext.h>
#ifdef _WIN32
#include <Platform/Win32/Win32GLContext.h>
typedef Win32GLContext ContextType;
#else
#error "No GLContext implementation exists"
#endif
GLContext* GLContext::create()
{
return new ContextType();
}
GLContext::~GLContext()
{
// Nothing to do.
}

109
source/Game.cpp Normal file
View file

@ -0,0 +1,109 @@
#include <iostream>
#include <Spectre/Game/GameTime.h>
#include <Spectre/Game/FPSCounter.h>
#include <Spectre/Input/InputModule.h>
#include <Spectre/System/MessageHandler.h>
#include <Platform/PlatformMisc.h>
#include <Platform/Win32/Win32Application.h>
#include <Spectre/Game.h>
Game::Game()
{
m_platform = new Win32Application();
m_running = false;
m_graphics = new Graphics(m_platform);
m_input = new InputModule(&m_platform->getInput());
m_messageHandler = new MessageHandler();
}
Game::~Game()
{
delete m_input;
delete m_graphics;
delete m_platform;
delete m_messageHandler;
}
void Game::setup()
{
m_graphics->init();
m_graphics->setClearColor(0.0f, 0.0f, 0.0f);
init();
}
void Game::run()
{
setup();
gameLoop();
}
void Game::gameLoop()
{
GameTime time;
time.setTimeStep(120);
m_running = true;
while(m_running) {
processEvents();
if (time.beginFrame()) {
while(time.tick()) {
update(time.getTimeStep());
}
render();
m_fpsCounter.addFrame();
}
}
}
void Game::processEvents()
{
MessageQueue& queue = m_platform->getMessageQueue();
SysEvent event;
m_platform->update();
while(queue.pollEvent(event)) {
if (event.type == SysEvent::Quit) {
exit();
break;
}
// Call message handler.
if (event.type == SysEvent::Size) {
m_messageHandler->onSizeChanged(event.size.display, event.size.width, event.size.height);
}
}
}
void Game::exit()
{
m_running = false;
}
Graphics* Game::getGraphics() const
{
return m_graphics;
}
InputModule* Game::getInput() const
{
return m_input;
}
FPSCounter& Game::getFpsCounter()
{
return m_fpsCounter;
}

View file

@ -0,0 +1,55 @@
#include <Spectre/Game/FPSCounter.h>
#include <Spectre/System/System.h>
FPSCounter::FPSCounter() :
m_fps (60.0f),
m_updateRate (2000)
{
reset();
}
void FPSCounter::addFrame()
{
m_count++;
}
float FPSCounter::getFPS() const
{
return m_fps;
}
void FPSCounter::setUpdateRate(unsigned int ups)
{
// Clamp to 1.
if (ups < 1) {
ups = 1;
}
m_updateRate = ups * 1000;
// Must reset the counter.
reset();
}
bool FPSCounter::update()
{
unsigned int current = System::getMilliseconds();
unsigned int elapsed = current - m_time;
if (elapsed >= m_updateRate) {
float fraction = m_count / ((float) elapsed);
m_fps = fraction * 1000.f;
m_time = current;
m_count = 0;
return true;
}
return false;
}
void FPSCounter::reset()
{
m_time = System::getMilliseconds();
m_count = 0;
}

76
source/Game/GameTime.cpp Normal file
View file

@ -0,0 +1,76 @@
#include <iostream>
#include <Spectre/Game/GameTime.h>
#include <Spectre/System/System.h>
GameTime::GameTime(unsigned long updates_per_sec)
{
m_acc = 0;
m_current = System::getMilliseconds();
m_lastUpdate = m_current;
setTimeStep(updates_per_sec);
}
double GameTime::getTimeStep() const
{
return m_slice;
}
void GameTime::setTimeStep(unsigned long updates_per_sec)
{
m_slice = (1000.0f / ((double) updates_per_sec));
reset();
}
unsigned long GameTime::getElapsed() const
{
return m_current - m_lastUpdate;
}
bool GameTime::beginFrame()
{
reset();
accumulateTime();
if (m_acc > m_slice) {
m_inLoop = true;
}
return m_inLoop;
}
bool GameTime::tick()
{
if (m_acc > m_slice) {
m_acc -= m_slice;
return true;
}
return false;
}
void GameTime::reset()
{
m_lastUpdate = m_current;
m_inLoop = false;
}
void GameTime::accumulateTime()
{
updateTime();
m_acc += (double) (m_current - m_lastUpdate);
if (m_acc > (1000.f / m_slice)) {
m_acc = 1000.f / m_slice;
}
}
void GameTime::updateTime()
{
m_current = System::getMilliseconds();
// Just to be safe. check so we don't get a negative interval.
if (m_current < m_lastUpdate) {
m_lastUpdate = m_current;
}
}

View file

@ -0,0 +1,259 @@
#include <Spectre/System/Log.h>
#include <Spectre/Graphics/OpenGL.h>
#include <Spectre/Graphics/Renderable.h>
#include <Spectre/Graphics/RenderState.h>
#include <Spectre/Graphics/ShaderProgram.h>
#include <Spectre/Graphics/Texture.h>
#include <Spectre/Graphics/BatchRenderer2D.h>
#include <Spectre/Math/Math.h>
#include <algorithm>
static bool compare_renderable(const Renderable2D* a, const Renderable2D* b) {
if (a->getRenderType() != b->getRenderType()) {
return a->getRenderType() < b->getRenderType();
}
if (a->getTexture() != b->getTexture()) {
return a->getTexture() < b->getTexture();
}
return false;
}
BatchRenderer2D::BatchRenderer2D()
{
// Generate buffer objects.
glGenBuffers(1, &m_IBO);
glGenBuffers(1, &m_VBO);
setBatchSize(10000);
m_textShader.create();
if (!m_textShader.loadFromFile("assets/shaders/text.shader.glsl")) {
std::cout << "Failed to load shader: " << m_textShader.getLastError() << std::endl;
}
if (!m_textShader.link()) {
std::cout << "Failed to link shader: " << m_textShader.getLastError() << std::endl;
}
m_spriteShader.create();
if (!m_spriteShader.loadFromFile("assets/shaders/standard.shader.glsl")) {
std::cout << "Failed to load shader: " << m_spriteShader.getLastError() << std::endl;
}
if (!m_spriteShader.link()) {
std::cout << "Failed to link shader: " << m_spriteShader.getLastError() << std::endl;
}
}
BatchRenderer2D::~BatchRenderer2D()
{
glDeleteBuffers(1, &m_VBO);
glDeleteBuffers(1, &m_IBO);
}
void BatchRenderer2D::setBatchSize(unsigned short size)
{
std::vector<unsigned short> indices;
int vtx = 0;
if (size > 10000) {
size = 10000;
}
m_size = size;
indices.resize(size * 6);
for(int i = 0; i < m_size * 6; i += 6) {
indices[i + 0] = vtx + 0;
indices[i + 1] = vtx + 1;
indices[i + 2] = vtx + 2;
indices[i + 3] = vtx + 2;
indices[i + 4] = vtx + 3;
indices[i + 5] = vtx + 0;
vtx += 4;
}
// Upload to GPU
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Allocate memory for vertex buffer.
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
glBufferData(GL_ARRAY_BUFFER, m_size * sizeof(Vertex2D), NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Log
log("BatchRenderer - BatchSize\n");
log(" num sprites: %i\n", m_size);
log(" num indices: %i\n", m_size * 6);
log(" num vertices: %i\n", m_size);
log("------\n");
}
void BatchRenderer2D::begin()
{
}
void BatchRenderer2D::end()
{
}
void BatchRenderer2D::submit(const Renderable2D& renderable)
{
m_queue.push_back(&renderable);
}
void BatchRenderer2D::render()
{
Matrix4f viewMatrix = m_camera ? m_camera->getViewMatrix() : Matrix4f::Identity;
Matrix4f projMatrix = m_camera ? m_camera->getProjectionMatrix() : Matrix4f::Identity;
Matrix4f guiMatrix = math::orthoProjection(0.0f, 800.0f, 600.0f, 0.0f);
Matrix4f MVP = projMatrix * viewMatrix;
// Nothing to render.
if (m_queue.size() < 1) {
return;
}
// Bind buffers.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IBO);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
// Setup position.
glEnableVertexAttribArray(VertexAttribPosition);
glVertexAttribPointer(VertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void*) 0);
// Setup color
glEnableVertexAttribArray(VertexAttribColor0);
glVertexAttribPointer(VertexAttribColor0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void*) 8);
glEnableVertexAttribArray(VertexAttribTexCoord0);
glVertexAttribPointer(VertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void*) 20);
// Set shader uniforms.
m_textShader.enable();
m_textShader.setUniform("u_MVP", MVP);
m_textShader.disable();
m_spriteShader.enable();
m_spriteShader.setUniform("u_MVP", MVP);
m_spriteShader.disable();
prepareQueue();
glDisableVertexAttribArray(VertexAttribPosition);
glDisableVertexAttribArray(VertexAttribColor0);
glDisableVertexAttribArray(VertexAttribTexCoord0);
// Unbind all buffers.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
m_queue.clear();
m_state.cleanup();
}
void BatchRenderer2D::prepareQueue()
{
Vertex2D *buffer = static_cast<Vertex2D*>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
Batch current;
std::sort(m_queue.begin(), m_queue.end(), compare_renderable);
current.type = m_queue[0]->getRenderType();
current.texture = m_queue[0]->getTexture();
current.count = 0;
current.offset = 0;
for(int i = 0; i < m_queue.size(); i++) {
const Texture *tex = m_queue[i]->getTexture();
RenderType type = m_queue[i]->getRenderType();
unsigned int num_vert = m_queue[i]->getVertices().size();
// TODO: Only upload and draw if buffer is full :)
if (current.type != type || current.texture != tex || current.count >= m_size) {
glUnmapBuffer(GL_ARRAY_BUFFER);
drawBatch(current);
buffer = static_cast<Vertex2D*>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
current.type = m_queue[i]->getRenderType();
current.count = 0;
current.offset = 0;
current.texture = tex;
}
buffer += addRenderable(buffer, m_queue[i]);
current.count += num_vert;
}
glUnmapBuffer(GL_ARRAY_BUFFER);
if (current.count > 0) {
drawBatch(current);
}
}
void BatchRenderer2D::uploadBatch(const Batch& batch)
{
Vertex2D *buffer = static_cast<Vertex2D*>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
unsigned int count = 0;
for(int i = 0; i < batch.count; i++) {
buffer += addRenderable(buffer, m_queue[batch.offset + i]);
}
// Upload gpu data and draw.
glUnmapBuffer(GL_ARRAY_BUFFER);
}
unsigned int BatchRenderer2D::addRenderable(Vertex2D* buffer, const Renderable2D* renderable)
{
const Transform& transform = renderable->getTransform();
const std::vector<Vertex2D>& vertices = renderable->getVertices();
// Pretransform vertex positions to skip setting a uniform model
// matrix in the shader for each renderable reducing the number of draw calls.
for(int i = 0; i < vertices.size(); i++) {
buffer[i].position = transform * vertices[i].position;
buffer[i].color = vertices[i].color;
buffer[i].uv = vertices[i].uv;
}
return vertices.size();
}
void BatchRenderer2D::drawBatch(Batch& batch)
{
const ShaderProgram* shader;
if (batch.type == RenderType_UI) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
shader = &m_textShader;
} else {
shader = &m_spriteShader;
}
// enable shader.
m_state.enableShader(shader);
// enable batch texture
m_state.enableTexture(batch.texture);
glDrawElements(GL_TRIANGLES, (batch.count / 4) * 6, GL_UNSIGNED_SHORT, 0);
if (batch.type == RenderType_UI) {
glDisable(GL_BLEND);
}
}

Some files were not shown because too many files have changed in this diff Show more