diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c77df1cf..1d54faaba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -318,11 +318,15 @@ set(FIFE_CORE_SRC ${PROJECT_SOURCE_DIR}/engine/core/video/fonts/subimagefont.cpp ${PROJECT_SOURCE_DIR}/engine/core/video/fonts/textrenderpool.cpp ${PROJECT_SOURCE_DIR}/engine/core/video/fonts/truetypefont.cpp + ${PROJECT_SOURCE_DIR}/engine/core/video/opengl/glbufferobject.cpp ${PROJECT_SOURCE_DIR}/engine/core/video/opengl/glimage.cpp + ${PROJECT_SOURCE_DIR}/engine/core/video/opengl/glrendercache.cpp ${PROJECT_SOURCE_DIR}/engine/core/video/opengl/renderbackendopengl.cpp ${PROJECT_SOURCE_DIR}/engine/core/video/sdl/renderbackendsdl.cpp ${PROJECT_SOURCE_DIR}/engine/core/video/sdl/sdlblendingfunctions.cpp + ${PROJECT_SOURCE_DIR}/engine/core/video/sdl/sdlbufferobject.cpp ${PROJECT_SOURCE_DIR}/engine/core/video/sdl/sdlimage.cpp + ${PROJECT_SOURCE_DIR}/engine/core/video/sdl/sdlrendercache.cpp ${PROJECT_SOURCE_DIR}/engine/core/view/camera.cpp ${PROJECT_SOURCE_DIR}/engine/core/view/layercache.cpp ${PROJECT_SOURCE_DIR}/engine/core/view/rendererbase.cpp @@ -536,6 +540,7 @@ set(FIFE_CORE_HDR ${PROJECT_SOURCE_DIR}/engine/core/video/image.h ${PROJECT_SOURCE_DIR}/engine/core/video/imagemanager.h ${PROJECT_SOURCE_DIR}/engine/core/video/renderbackend.h + ${PROJECT_SOURCE_DIR}/engine/core/video/rendercache.h ${PROJECT_SOURCE_DIR}/engine/core/video/fonts/fontbase.h ${PROJECT_SOURCE_DIR}/engine/core/video/fonts/ifont.h ${PROJECT_SOURCE_DIR}/engine/core/video/fonts/imagefontbase.h @@ -543,11 +548,15 @@ set(FIFE_CORE_HDR ${PROJECT_SOURCE_DIR}/engine/core/video/fonts/textrenderpool.h ${PROJECT_SOURCE_DIR}/engine/core/video/fonts/truetypefont.h ${PROJECT_SOURCE_DIR}/engine/core/video/opengl/fife_opengl.h + ${PROJECT_SOURCE_DIR}/engine/core/video/opengl/glbufferobject.h ${PROJECT_SOURCE_DIR}/engine/core/video/opengl/glimage.h + ${PROJECT_SOURCE_DIR}/engine/core/video/opengl/glrendercache.h ${PROJECT_SOURCE_DIR}/engine/core/video/opengl/renderbackendopengl.h ${PROJECT_SOURCE_DIR}/engine/core/video/sdl/renderbackendsdl.h ${PROJECT_SOURCE_DIR}/engine/core/video/sdl/sdlblendingfunctions.h + ${PROJECT_SOURCE_DIR}/engine/core/video/sdl/sdlbufferobject.h ${PROJECT_SOURCE_DIR}/engine/core/video/sdl/sdlimage.h + ${PROJECT_SOURCE_DIR}/engine/core/video/sdl/sdlrendercache.h ${PROJECT_SOURCE_DIR}/engine/core/view/camera.h ${PROJECT_SOURCE_DIR}/engine/core/view/layercache.h ${PROJECT_SOURCE_DIR}/engine/core/view/rendererbase.h diff --git a/engine/core/video/opengl/glbufferobject.cpp b/engine/core/video/opengl/glbufferobject.cpp new file mode 100644 index 000000000..11803585c --- /dev/null +++ b/engine/core/video/opengl/glbufferobject.cpp @@ -0,0 +1,136 @@ +/*************************************************************************** + * Copyright (C) 2005-2017 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +// Standard C++ library includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder + +#include "renderbackendopengl.h" +#include "glbufferobject.h" + + +namespace FIFE { + + OpenGLBufferLinesObject::OpenGLBufferLinesObject() { + m_final = false; + m_vboId = 0; + m_vboIndicesId = 0; + m_oldFinalSize = 0; + } + + OpenGLBufferLinesObject::~OpenGLBufferLinesObject() { + glDeleteBuffers(1, &m_vboId); + glDeleteBuffers(1, &m_vboIndicesId); + } + + void OpenGLBufferLinesObject::add(const std::vector& points, const Color& color) { + if (points.size() < 2) { + return; + } + m_final = false; + std::vector::const_iterator it = points.begin(); + renderDataP rd; + rd.vertex[0] = static_cast((*it).x) + 0.375; + rd.vertex[1] = static_cast((*it).y) + 0.375; + rd.color[0] = color.getR(); + rd.color[1] = color.getG(); + rd.color[2] = color.getB(); + rd.color[3] = color.getAlpha(); + m_data.push_back(rd); + ++it; + uint32_t indice = m_indices.empty() ? 0 : m_indices.back() + 1; + for (; it != points.end(); ++it) { + rd.vertex[0] = static_cast((*it).x) + 0.375; + rd.vertex[1] = static_cast((*it).y) + 0.375; + m_data.push_back(rd); + m_indices.push_back(indice++); + m_indices.push_back(indice); + } + } + + void OpenGLBufferLinesObject::clear() { + m_data.clear(); + m_indices.clear(); + /*if (m_vboId != 0) { + glDeleteBuffers(1, &m_vboId); + glDeleteBuffers(1, &m_vboIndicesId); + m_vboId = 0; + m_vboIndicesId = 0; + }*/ + m_final = false; + } + + void OpenGLBufferLinesObject::update(uint32_t position, const std::vector& points, const Color& color) { + uint32_t elements = points.size(); + for (uint32_t i = 0; i < elements; ++i) { + renderDataP& rd = m_data[position + i]; + rd.vertex[0] = static_cast(points[i].x) + 0.375; + rd.vertex[1] = static_cast(points[i].y) + 0.375; + } + + if (!m_final) { + finalize(); + } else { + glBindBuffer(GL_ARRAY_BUFFER, m_vboId); + glBufferSubData(GL_ARRAY_BUFFER, sizeof(renderDataP) * position, sizeof(renderDataP) * elements, &m_data[position].vertex); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + } + + void OpenGLBufferLinesObject::finalize() { + if (m_vboId == 0) { + glGenBuffers(1, &m_vboId); + glGenBuffers(1, &m_vboIndicesId); + } + + if (m_oldFinalSize != m_indices.size()) { + glBindBuffer(GL_ARRAY_BUFFER, m_vboId); + glBufferData(GL_ARRAY_BUFFER, sizeof(renderDataP) * m_data.size(), &m_data[0].vertex, GL_STREAM_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vboIndicesId); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t) * m_indices.size(), &m_indices[0], GL_STREAM_DRAW); + m_oldFinalSize = m_indices.size(); + } else { + glBindBuffer(GL_ARRAY_BUFFER, m_vboId); + glBufferData(GL_ARRAY_BUFFER, sizeof(renderDataP) * m_data.size(), NULL, GL_STREAM_DRAW); + GLvoid* ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + memcpy(ptr, &m_data[0].vertex, sizeof(renderDataP) * m_data.size()); + glUnmapBuffer(GL_ARRAY_BUFFER); + } + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + m_final = true; + } + + void OpenGLBufferLinesObject::render() { + if (m_data.empty()) { + return; + } + if (!m_final) { + finalize(); + } + static_cast(RenderBackend::instance())->renderVboBuffers(m_indices.size(), m_vboId, m_vboIndicesId); + } +} diff --git a/engine/core/video/opengl/glbufferobject.h b/engine/core/video/opengl/glbufferobject.h new file mode 100644 index 000000000..19542bde6 --- /dev/null +++ b/engine/core/video/opengl/glbufferobject.h @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (C) 2005-2017 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef FIFE_VIDEO_OPENGL_BUFFEROBJECT_H +#define FIFE_VIDEO_OPENGL_BUFFEROBJECT_H + +// Standard C++ library includes + +// Platform specific includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "util/structures/point.h" +#include "video/color.h" + +#include "fife_opengl.h" + +namespace FIFE { + + /** Abstract interface for all the opengl buffer objects. */ + class OpenGLBufferObject { + public: + /** Destructor + */ + virtual ~OpenGLBufferObject() {} + + /** Render + */ + virtual void render() = 0; + + }; + + // for regular primitives with color and alpha + struct renderDataP { + GLfloat vertex[2]; + GLubyte color[4]; + }; + + + class OpenGLBufferLinesObject : public OpenGLBufferObject { + public: + OpenGLBufferLinesObject(); + virtual ~OpenGLBufferLinesObject(); + void add(const std::vector& points, const Color& color); + void update(uint32_t position, const std::vector& points, const Color& color); + void clear(); + void finalize(); + void render(); + private: + bool m_final; + uint32_t m_oldFinalSize; + GLuint m_vboId; + GLuint m_vboIndicesId; + std::vector m_data; + std::vector m_indices; + }; +} + +#endif diff --git a/engine/core/video/opengl/glrendercache.cpp b/engine/core/video/opengl/glrendercache.cpp new file mode 100644 index 000000000..aa4dfbcd1 --- /dev/null +++ b/engine/core/video/opengl/glrendercache.cpp @@ -0,0 +1,84 @@ +/*************************************************************************** + * Copyright (C) 2005-2017 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +// Standard C++ library includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "renderbackendopengl.h" +#include "glbufferobject.h" +#include "glrendercache.h" + +#define BUFFER_OFFSET(i) ((void*)(i)) + +namespace FIFE { + GLRenderCache::GLRenderCache() { + m_buffer = NULL; + } + + GLRenderCache::~GLRenderCache() { + delete m_buffer; + } + + void GLRenderCache::clear() { + if (m_buffer) { + static_cast(m_buffer)->clear(); + } + + } + + void GLRenderCache::render() { + if (m_buffer) { + m_buffer->render(); + } + } + + void GLRenderCache::addLine(const Point& p1, const Point& p2, const Color& color) { + } + + void GLRenderCache::addLines(const std::vector& points, const Color& color) { + if (points.size() < 2) { + return; + } + if (!m_buffer) { + m_buffer = new OpenGLBufferLinesObject(); + } + static_cast(m_buffer)->add(points, color); + } + + void GLRenderCache::updateLines(uint32_t position, const std::vector& points, const Color& color) { + if (points.size() < 2) { + return; + } + if (!m_buffer) { + return; + } + static_cast(m_buffer)->update(position, points, color); + } + + void GLRenderCache::removeLines(uint32_t position, uint32_t elements) { + + } +} diff --git a/engine/core/video/opengl/glrendercache.h b/engine/core/video/opengl/glrendercache.h new file mode 100644 index 000000000..e18423231 --- /dev/null +++ b/engine/core/video/opengl/glrendercache.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (C) 2005-2017 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef FIFE_VIDEO_OPENGL_RENDERCACHE_H +#define FIFE_VIDEO_OPENGL_RENDERCACHE_H + +// Standard C++ library includes + +// Platform specific includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "video/rendercache.h" + +namespace FIFE { + class OpenGLBufferObject; + + class GLRenderCache : public RenderCache { + public: + /** Constructor. + */ + GLRenderCache(); + + /** Destructor. + */ + virtual ~GLRenderCache(); + + virtual void clear(); + + /** Render + */ + virtual void render(); + + virtual void addLine(const Point& p1, const Point& p2, const Color& color); + + virtual void addLines(const std::vector& points, const Color& color); + virtual void updateLines(uint32_t position, const std::vector& points, const Color& color); + virtual void removeLines(uint32_t position, uint32_t elements); + + private: + + OpenGLBufferObject* m_buffer; + }; +} + +#endif diff --git a/engine/core/video/opengl/renderbackendopengl.cpp b/engine/core/video/opengl/renderbackendopengl.cpp index 9b95e9bc3..872949b26 100644 --- a/engine/core/video/opengl/renderbackendopengl.cpp +++ b/engine/core/video/opengl/renderbackendopengl.cpp @@ -32,9 +32,11 @@ #include "video/devicecaps.h" #include "glimage.h" +#include "glrendercache.h" #include "renderbackendopengl.h" #include "SDL_image.h" +#define BUFFER_OFFSET(i) ((GLvoid*)(i)) namespace FIFE { /** Logger to use for this source file. @@ -2700,4 +2702,28 @@ namespace FIFE { glPopMatrix(); } + + RenderCache* RenderBackendOpenGL::createRenderCache() { + RenderCache* cache = new GLRenderCache(); + return cache; + } + + void RenderBackendOpenGL::renderVboBuffers(uint32_t elements, GLuint vbo, GLuint indice) { + enableColorArray(); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indice); + // VBO starting point + setVertexPointer(2, sizeof(renderDataP), BUFFER_OFFSET(0)); + // Color starting point in VBO + setColorPointer(sizeof(renderDataP), BUFFER_OFFSET(8)); + // IBO starting point + glDrawElements(GL_LINES, elements, GL_UNSIGNED_INT, BUFFER_OFFSET(0)); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + // stupid shit :P + setVertexPointer(2, 0, 0); + setColorPointer(0, 0); + } } diff --git a/engine/core/video/opengl/renderbackendopengl.h b/engine/core/video/opengl/renderbackendopengl.h index b49688f1b..0d46d5bb0 100644 --- a/engine/core/video/opengl/renderbackendopengl.h +++ b/engine/core/video/opengl/renderbackendopengl.h @@ -102,11 +102,15 @@ namespace FIFE { virtual void renderGuiGeometry(const std::vector& vertices, const std::vector& indices, const DoublePoint& translation, ImagePtr texture); + virtual RenderCache* createRenderCache(); + void enableTextures(uint32_t texUnit); void disableTextures(uint32_t texUnit); void bindTexture(uint32_t texUnit, GLuint texId); void bindTexture(GLuint textId); + void renderVboBuffers(uint32_t elements, GLuint vbo, GLuint indice); + protected: virtual void setClipArea(const Rect& cliparea, bool clear); diff --git a/engine/core/video/renderbackend.h b/engine/core/video/renderbackend.h index a7cf6afa0..d09a11e69 100644 --- a/engine/core/video/renderbackend.h +++ b/engine/core/video/renderbackend.h @@ -52,6 +52,7 @@ namespace FIFE { class Image; + class RenderCache; #ifdef HAVE_OPENGL enum GLConstants { @@ -497,6 +498,8 @@ namespace FIFE { */ void addControlPoints(const std::vector& points, std::vector& newPoints); + virtual RenderCache* createRenderCache() = 0; + protected: /** Sets given clip area into image @@ -547,6 +550,7 @@ namespace FIFE { std::stack m_clipstack; ClipInfo m_guiClip; + private: bool m_isframelimit; uint32_t m_frame_start; diff --git a/engine/core/video/rendercache.h b/engine/core/video/rendercache.h new file mode 100644 index 000000000..ae4775ca7 --- /dev/null +++ b/engine/core/video/rendercache.h @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2005-2017 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef FIFE_VIDEO_RENDERCACHE_H +#define FIFE_VIDEO_RENDERCACHE_H + +// Standard C++ library includes + +// Platform specific includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "renderbackend.h" + +namespace FIFE { + + /** Abstract interface for all the rendercaches. */ + class RenderCache { + public: + virtual ~RenderCache() {}; + + /** Clear + */ + virtual void clear() = 0; + + /** Render + */ + virtual void render() = 0; + + virtual void addLine(const Point& p1, const Point& p2, const Color& color) = 0; + + virtual void addLines(const std::vector& points, const Color& color) = 0; + + virtual void updateLines(uint32_t position, const std::vector& points, const Color& color) = 0; + + virtual void removeLines(uint32_t position, uint32_t elements) = 0; + }; +} + +#endif diff --git a/engine/core/video/sdl/renderbackendsdl.cpp b/engine/core/video/sdl/renderbackendsdl.cpp index b68b2d853..53b27f6ef 100644 --- a/engine/core/video/sdl/renderbackendsdl.cpp +++ b/engine/core/video/sdl/renderbackendsdl.cpp @@ -35,6 +35,7 @@ #include "renderbackendsdl.h" #include "sdlimage.h" +#include "sdlrendercache.h" #include "SDL_image.h" namespace FIFE { @@ -687,4 +688,9 @@ namespace FIFE { void RenderBackendSDL::renderGuiGeometry(const std::vector& vertices, const std::vector& indices, const DoublePoint& translation, ImagePtr texture) { } + + RenderCache* RenderBackendSDL::createRenderCache() { + RenderCache* cache = new SDLRenderCache(); + return cache; + } } diff --git a/engine/core/video/sdl/renderbackendsdl.h b/engine/core/video/sdl/renderbackendsdl.h index 8c2067eb8..5cb0a31eb 100644 --- a/engine/core/video/sdl/renderbackendsdl.h +++ b/engine/core/video/sdl/renderbackendsdl.h @@ -96,6 +96,8 @@ namespace FIFE { virtual void renderGuiGeometry(const std::vector& vertices, const std::vector& indices, const DoublePoint& translation, ImagePtr texture); + virtual RenderCache* createRenderCache(); + SDL_Renderer* getRenderer() { return m_renderer; } protected: diff --git a/engine/core/video/sdl/sdlbufferobject.cpp b/engine/core/video/sdl/sdlbufferobject.cpp new file mode 100644 index 000000000..ee014dc43 --- /dev/null +++ b/engine/core/video/sdl/sdlbufferobject.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (C) 2005-2017 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +// Standard C++ library includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "sdlbufferobject.h" + +namespace FIFE { + SDLBufferPrimitiveObject::SDLBufferPrimitiveObject(RenderType type, const std::vector& points, const Color& color) { + add(type, points, color); + } + + SDLBufferPrimitiveObject::~SDLBufferPrimitiveObject() { + + } + + void SDLBufferPrimitiveObject::add(RenderType type, const std::vector& points, const Color& color) { + uint32_t index = m_points.size(); + uint32_t elements = points.size(); + BufferDescriptor bc = { type, index, elements, color }; + + m_points.resize(index + elements); + for (uint32_t i = 0; i < elements; ++i) { + m_points[index + i].x = points[i].x; + m_points[index + i].y = points[i].y; + } + + m_descriptors.push_back(bc); + m_descriptorPosition[index] = m_descriptors.size() - 1; + } + + void SDLBufferPrimitiveObject::update(uint32_t position, const std::vector& points, const Color& color) { + BufferDescriptor& bd = m_descriptors[m_descriptorPosition[position]]; + bd.color = color; + uint32_t index = bd.position; + uint32_t elements = points.size(); + for (uint32_t i = 0; i < elements; ++i) { + m_points[index + i].x = points[i].x; + m_points[index + i].y = points[i].y; + } + } + + void SDLBufferPrimitiveObject::remove(uint32_t position, uint32_t elements) { + BufferDescriptor& bd = m_descriptors[m_descriptorPosition[position]]; + bd.count = 0; + } + + void SDLBufferPrimitiveObject::render() { + if (m_descriptors.empty()) return; + SDL_Point* point = NULL; + SDL_Renderer* renderer = static_cast(RenderBackend::instance())->getRenderer(); + std::vector::iterator it = m_descriptors.begin(); + for (; it != m_descriptors.end(); ++it) { + const BufferDescriptor& bd = *it; + SDL_SetRenderDrawColor(renderer, bd.color.getR(), bd.color.getG(), bd.color.getB(), bd.color.getAlpha()); + point = &m_points[bd.position]; + switch (bd.type) { + case Render_Point: + case Render_Points: + SDL_RenderDrawPoints(renderer, point, bd.count); + break; + case Render_Line: + case Render_Lines: + SDL_RenderDrawLines(renderer, point, bd.count); + break; + } + } + } +} diff --git a/engine/core/video/sdl/sdlbufferobject.h b/engine/core/video/sdl/sdlbufferobject.h new file mode 100644 index 000000000..037ec2f79 --- /dev/null +++ b/engine/core/video/sdl/sdlbufferobject.h @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (C) 2005-2017 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef FIFE_VIDEO_SDL_BUFFEROBJECT_H +#define FIFE_VIDEO_SDL_BUFFEROBJECT_H + +// Standard C++ library includes +#include +// Platform specific includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "renderbackendsdl.h" + +namespace FIFE { + /** Abstract interface for all the sdl buffer objects. */ + class SDLBufferObject { + public: + + /** Destructor + */ + virtual ~SDLBufferObject() {} + + /** Render + */ + virtual void render() = 0; + }; + + enum RenderType { + Render_Point, + Render_Points, + Render_Line, + Render_Lines, + Render_Rect, + Render_Rects + }; + + struct BufferDescriptor { + RenderType type; + uint32_t position; + uint32_t count; + Color color; + }; + + class SDLBufferPrimitiveObject : public SDLBufferObject { + public: + SDLBufferPrimitiveObject(RenderType type, const std::vector& points, const Color& color); + virtual ~SDLBufferPrimitiveObject(); + void add(RenderType type, const std::vector& points, const Color& color); + void update(uint32_t position, const std::vector& points, const Color& color); + void remove(uint32_t position, uint32_t elements); + void render(); + private: + std::vector m_points; + std::vector m_descriptors; + std::unordered_map m_descriptorPosition; + }; +} + +#endif diff --git a/engine/core/video/sdl/sdlrendercache.cpp b/engine/core/video/sdl/sdlrendercache.cpp new file mode 100644 index 000000000..3a7df6580 --- /dev/null +++ b/engine/core/video/sdl/sdlrendercache.cpp @@ -0,0 +1,98 @@ +/*************************************************************************** + * Copyright (C) 2005-2017 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +// Standard C++ library includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "sdlbufferobject.h" + +#include "sdlrendercache.h" + +namespace FIFE { + SDLRenderCache::SDLRenderCache() { + } + + SDLRenderCache::~SDLRenderCache() { + clear(); + } + + void SDLRenderCache::clear() { + std::vector::iterator it = m_objects.begin(); + for (; it != m_objects.end(); it++) { + delete *it; + } + m_objects.clear(); + m_typeBuffers.clear(); + } + + void SDLRenderCache::render() { + std::vector::iterator it = m_objects.begin(); + for (; it != m_objects.end(); it++) { + (*it)->render(); + } + } + + void SDLRenderCache::addLine(const Point& p1, const Point& p2, const Color& color) { + std::vector points(2); + points[0] = p1; + points[1] = p2; + SDLBufferObject* buffer = m_typeBuffers[PrimitiveBufferObject]; + if (!buffer) { + buffer = new SDLBufferPrimitiveObject(RenderType::Render_Line, points, color); + m_typeBuffers[PrimitiveBufferObject] = buffer; + m_objects.push_back(buffer); + } else { + static_cast(buffer)->add(RenderType::Render_Line, points, color); + } + } + + void SDLRenderCache::addLines(const std::vector& points, const Color& color) { + SDLBufferObject* buffer = m_typeBuffers[PrimitiveBufferObject]; + if (!buffer) { + buffer = new SDLBufferPrimitiveObject(FIFE::RenderType::Render_Lines, points, color); + m_typeBuffers[PrimitiveBufferObject] = buffer; + m_objects.push_back(buffer); + } else { + static_cast(buffer)->add(RenderType::Render_Lines, points, color); + } + } + + void SDLRenderCache::updateLines(uint32_t position, const std::vector& points, const Color& color) { + SDLBufferObject* buffer = m_typeBuffers[PrimitiveBufferObject]; + if (!buffer) { + return; + } + static_cast(buffer)->update(position, points, color); + } + + void SDLRenderCache::removeLines(uint32_t position, uint32_t elements) { + SDLBufferObject* buffer = m_typeBuffers[PrimitiveBufferObject]; + if (!buffer) { + return; + } + static_cast(buffer)->remove(position, elements); + } +} diff --git a/engine/core/video/sdl/sdlrendercache.h b/engine/core/video/sdl/sdlrendercache.h new file mode 100644 index 000000000..071ebe02d --- /dev/null +++ b/engine/core/video/sdl/sdlrendercache.h @@ -0,0 +1,77 @@ +/*************************************************************************** + * Copyright (C) 2005-2017 by the FIFE team * + * http://www.fifengine.net * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef FIFE_VIDEO_SDL_RENDERCACHE_H +#define FIFE_VIDEO_SDL_RENDERCACHE_H + +// Standard C++ library includes +#include +#include + +// Platform specific includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "video/rendercache.h" + +namespace FIFE { + class SDLBufferObject; + + class SDLRenderCache : public RenderCache { + public: + enum BufferObjectType { + PrimitiveBufferObject = 0 + }; + + /** Constructor. + */ + SDLRenderCache(); + + /** Destructor. + */ + virtual ~SDLRenderCache(); + + + virtual void clear(); + + /** Render + */ + virtual void render(); + + virtual void addLine(const Point& p1, const Point& p2, const Color& color); + + virtual void addLines(const std::vector& points, const Color& color); + + virtual void updateLines(uint32_t position, const std::vector& points, const Color& color); + + virtual void removeLines(uint32_t position, uint32_t elements); + + private: + std::vector m_objects; + std::map m_typeBuffers; + }; +} + +#endif diff --git a/engine/core/view/camera.cpp b/engine/core/view/camera.cpp index c5afcf61c..2816cd0df 100644 --- a/engine/core/view/camera.cpp +++ b/engine/core/view/camera.cpp @@ -955,11 +955,6 @@ namespace FIFE { } void Camera::updateRenderLists() { - if (!m_map) { - FL_ERR(_log, "No map for camera found"); - return; - } - const std::list& layers = m_map->getLayers(); std::list::const_iterator layer_it = layers.begin(); for (;layer_it != layers.end(); ++layer_it) { @@ -978,12 +973,34 @@ namespace FIFE { resetUpdates(); } - void Camera::render() { - updateRenderLists(); + bool Camera::isLayerCacheUpdated(Layer* layer) { + LayerCache* cache = m_cache[layer]; + if (!cache) { + FL_ERR(_log, LMsg("Layer Cache miss! (This shouldn't happen!)") << layer->getId()); + return false; + } + if (!cache->getUpdatedInstances().empty() || !cache->getRemovedInstances().empty()) { + return true; + } + return false; + } + + const std::set& Camera::getUpdatedInstances(Layer* layer) { + LayerCache* cache = m_cache[layer]; + return cache->getUpdatedInstances(); + } + + const std::set& Camera::getRemovedInstances(Layer* layer) { + LayerCache* cache = m_cache[layer]; + return cache->getRemovedInstances(); + } + void Camera::render() { if (!m_map) { + FL_ERR(_log, "No map for camera found"); return; } + updateRenderLists(); uint32_t lm = m_renderbackend->getLightingModel(); if (lm != 0) { @@ -1039,6 +1056,7 @@ namespace FIFE { } } } + m_cache[*layer_it]->resetCachedInstances(); } renderOverlay(); diff --git a/engine/core/view/camera.h b/engine/core/view/camera.h index 5592d2f66..db529bbcd 100644 --- a/engine/core/view/camera.h +++ b/engine/core/view/camera.h @@ -407,6 +407,13 @@ namespace FIFE { */ void render(); + /** Returns true if the LayerCache had to be recalculated, otherwise false. + */ + bool isLayerCacheUpdated(Layer* layer); + + const std::set& getUpdatedInstances(Layer* layer); + const std::set& getRemovedInstances(Layer* layer); + private: friend class MapObserver; void addLayer(Layer* layer); diff --git a/engine/core/view/camera.i b/engine/core/view/camera.i index 242d44f1e..a91594983 100644 --- a/engine/core/view/camera.i +++ b/engine/core/view/camera.i @@ -36,6 +36,7 @@ namespace FIFE { public: ~Camera(); const std::string& getId() const; + Map* getMap(); void setId(const std::string& id); void setTilt(double tilt); double getTilt() const; diff --git a/engine/core/view/layercache.cpp b/engine/core/view/layercache.cpp index f1e8377b3..289f7a71d 100644 --- a/engine/core/view/layercache.cpp +++ b/engine/core/view/layercache.cpp @@ -302,6 +302,7 @@ namespace FIFE { for (RenderList::iterator it = renderList.begin(); it != renderList.end(); ++it) { if ((*it)->instance == instance) { renderList.erase(it); + m_removedInstances.insert(instance->getFifeId()); break; } } @@ -527,11 +528,13 @@ namespace FIFE { // add to renderlist and sort renderlist.push_back(item); needSorting.push_back(item); + m_updatedInstances.insert(item->instance); } else { // remove from renderlist for (RenderList::iterator it = renderlist.begin(); it != renderlist.end(); ++it) { if ((*it)->instance == item->instance) { renderlist.erase(it); + m_removedInstances.insert(item->instance->getFifeId()); break; } } @@ -539,6 +542,7 @@ namespace FIFE { } else if (onScreenA && onScreenB && positionUpdate) { // sort needSorting.push_back(item); + m_updatedInstances.insert(item->instance); } if (!entry->forceUpdate) { @@ -810,4 +814,17 @@ namespace FIFE { void LayerCache::setCacheImage(ImagePtr image) { m_cacheImage = image; } + + void LayerCache::resetCachedInstances() { + m_updatedInstances.clear(); + m_removedInstances.clear(); + } + + const std::set& LayerCache::getUpdatedInstances() { + return m_updatedInstances; + } + + const std::set& LayerCache::getRemovedInstances() { + return m_removedInstances; + } } diff --git a/engine/core/view/layercache.h b/engine/core/view/layercache.h index 8df613cc9..6e514b856 100644 --- a/engine/core/view/layercache.h +++ b/engine/core/view/layercache.h @@ -64,6 +64,10 @@ namespace FIFE { ImagePtr getCacheImage(); void setCacheImage(ImagePtr image); + void resetCachedInstances(); + const std::set& getUpdatedInstances(); + const std::set& getRemovedInstances(); + private: enum RenderEntryUpdateType { EntryNoneUpdate = 0x00, @@ -110,6 +114,9 @@ namespace FIFE { std::set m_entriesToUpdate; std::deque m_freeEntries; + std::set m_updatedInstances; + std::set m_removedInstances; + bool m_needSorting; double m_zMin; double m_zMax; diff --git a/engine/core/view/rendererbase.cpp b/engine/core/view/rendererbase.cpp index f67cd1826..67f13082b 100644 --- a/engine/core/view/rendererbase.cpp +++ b/engine/core/view/rendererbase.cpp @@ -30,6 +30,7 @@ #include "model/structures/layer.h" #include "model/structures/map.h" #include "util/log/logger.h" +#include "video/rendercache.h" #include "rendererbase.h" namespace FIFE { @@ -61,6 +62,10 @@ namespace FIFE { m_listener(NULL) { } + RendererBase::~RendererBase() { + deleteRenderCaches(); + } + void RendererBase::setPipelinePosition(int32_t position) { if (position !=m_pipeline_position) { m_pipeline_position = position; @@ -76,6 +81,9 @@ namespace FIFE { if (m_listener) { m_listener->onRendererEnabledChanged(this); } + if (!enabled) { + deleteRenderCaches(); + } } } @@ -87,10 +95,12 @@ namespace FIFE { void RendererBase::removeActiveLayer(Layer* layer) { m_active_layers.remove(layer); + deleteRenderCache(layer); } void RendererBase::clearActiveLayers() { m_active_layers.clear(); + deleteRenderCaches(); } bool RendererBase::isActivedLayer(Layer* layer) { @@ -107,4 +117,39 @@ namespace FIFE { } } + RenderCache* RendererBase::createRenderCache(Layer* layer) { + RenderCache* cache = getRenderCache(layer); + if (cache) { + FL_WARN(_log, "RenderCache already created! Instead of a new one, the existing is returned"); + } else { + cache = m_renderbackend->createRenderCache(); + m_layerCaches.insert(std::pair(layer, cache)); + } + return cache; + } + + RenderCache* RendererBase::getRenderCache(Layer* layer) { + RenderCache* cache = NULL; + std::map::iterator it = m_layerCaches.find(layer); + if (it != m_layerCaches.end()) { + cache = it->second; + } + return cache; + } + + void RendererBase::deleteRenderCaches() { + std::map::iterator it = m_layerCaches.begin(); + for (; it != m_layerCaches.end(); ++it) { + delete it->second; + } + m_layerCaches.clear(); + } + + void RendererBase::deleteRenderCache(Layer* layer) { + std::map::iterator it = m_layerCaches.find(layer); + if (it != m_layerCaches.end()) { + delete it->second; + m_layerCaches.erase(it); + } + } } diff --git a/engine/core/view/rendererbase.h b/engine/core/view/rendererbase.h index 9b5c84f98..fe0fb6332 100644 --- a/engine/core/view/rendererbase.h +++ b/engine/core/view/rendererbase.h @@ -24,6 +24,7 @@ // Standard C++ library includes #include +#include #include // 3rd party library includes @@ -41,6 +42,7 @@ namespace FIFE { class Map; class Instance; class RenderBackend; + class RenderCache; class RendererBase; /** RendererListener allows reaction to changes in renderer @@ -93,7 +95,7 @@ namespace FIFE { /** Destructor */ - virtual ~RendererBase() {}; + virtual ~RendererBase(); /** This method is called by the view to ask renderer to draw its rendering aspect based on * given parameters. Renderers receive non-clipped instance stack since there is no @@ -151,9 +153,9 @@ namespace FIFE { */ void clearActiveLayers(); - /** Activates all layers from given elevation + /** Activates all layers for given map */ - void activateAllLayers(Map* elevation); + void activateAllLayers(Map* map); /** Returns if given layer is currently activated */ @@ -163,11 +165,19 @@ namespace FIFE { */ std::list getActiveLayers() const {return m_active_layers;} + RenderCache* createRenderCache(Layer* layer); + + RenderCache* getRenderCache(Layer* layer); + + void deleteRenderCaches(); + + void deleteRenderCache(Layer* layer); protected: RendererBase(); std::list m_active_layers; + std::map m_layerCaches; RenderBackend* m_renderbackend; private: diff --git a/engine/core/view/renderers/blockinginforenderer.cpp b/engine/core/view/renderers/blockinginforenderer.cpp index 81a6fda18..22244d4d8 100644 --- a/engine/core/view/renderers/blockinginforenderer.cpp +++ b/engine/core/view/renderers/blockinginforenderer.cpp @@ -28,6 +28,7 @@ // First block: files included from the FIFE root src directory // Second block: files included from the same folder #include "video/renderbackend.h" +#include "video/rendercache.h" #include "util/math/fife_math.h" #include "util/log/logger.h" #include "model/metamodel/grids/cellgrid.h" @@ -48,7 +49,8 @@ namespace FIFE { static Logger _log(LM_VIEWVIEW); BlockingInfoRenderer::BlockingInfoRenderer(RenderBackend* renderbackend, int32_t position): - RendererBase(renderbackend, position) { + RendererBase(renderbackend, position), + m_updated(true) { setEnabled(false); m_color.r = 0; m_color.g = 255; @@ -57,6 +59,7 @@ namespace FIFE { BlockingInfoRenderer::BlockingInfoRenderer(const BlockingInfoRenderer& old): RendererBase(old), + m_updated(true), m_color(old.m_color) { setEnabled(false); } @@ -75,78 +78,123 @@ namespace FIFE { void BlockingInfoRenderer::render(Camera* cam, Layer* layer, RenderList& instances) { CellGrid* cg = layer->getCellGrid(); if (!cg) { - FL_WARN(_log, "No cellgrid assigned to layer, cannot draw grid"); + FL_WARN(_log, "No cellgrid assigned to layer, can not draw blocking info"); return; } - Rect cv = cam->getViewPort(); + RenderCache* renderCache = getRenderCache(layer); + // full update on start, camera change or color change + if (!renderCache || cam->isUpdated() || m_updated) { + if (!renderCache) { + renderCache = createRenderCache(layer); + } + fullUpdate(cam, layer, instances, renderCache); + } else if (cam->isLayerCacheUpdated(layer)) { + // update data on Instance changes + update(cam, layer, renderCache); + } + + // render + renderCache->render(); + } + + void BlockingInfoRenderer::fullUpdate(Camera* cam, Layer* layer, RenderList& instances, RenderCache* renderCache) { + CellGrid* cg = layer->getCellGrid(); + + renderCache->clear(); + m_fifeIdToBufferId.clear(); + uint32_t pos = 0; + const uint32_t cellSideCount = cg->getCellSideCount(); + const uint32_t halfCell = cellSideCount / 2; + const uint32_t elements = cellSideCount + 2; + std::vector data(elements); + Color color(m_color.r, m_color.g, m_color.b, 255); CellCache* cache = layer->getCellCache(); if (cache) { - const std::vector >& cells = cache->getCells(); - std::vector >::const_iterator it = cells.begin(); - for (; it != cells.end(); ++it) { - std::vector::const_iterator cit = (*it).begin(); - for (; cit != (*it).end(); ++cit) { - ExactModelCoordinate emc = FIFE::intPt2doublePt((*cit)->getLayerCoordinates()); - ScreenPoint sp = cam->toScreenCoordinates(cg->toMapCoordinates(emc)); - // if it is not in cameras view continue - if (sp.x < cv.x || sp.x > cv.x + cv.w || - sp.y < cv.y || sp.y > cv.y + cv.h) { - continue; - } - if ((*cit)->getCellType() != CTYPE_NO_BLOCKER) { - std::vector vertices; - cg->getVertices(vertices, (*cit)->getLayerCoordinates()); - std::vector::const_iterator it = vertices.begin(); - int32_t halfind = vertices.size() / 2; - ScreenPoint firstpt = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - Point pt1(firstpt.x, firstpt.y); - Point pt2; - ++it; - for (; it != vertices.end(); it++) { - ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - pt2.x = pts.x; - pt2.y = pts.y; - m_renderbackend->drawLine(pt1, pt2, m_color.r, m_color.g, m_color.b); - pt1 = pt2; - } - m_renderbackend->drawLine(pt2, Point(firstpt.x, firstpt.y), m_color.r, m_color.g, m_color.b); - ScreenPoint spt1 = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[0])); - Point pt3(spt1.x, spt1.y); - ScreenPoint spt2 = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[halfind])); - Point pt4(spt2.x, spt2.y); - m_renderbackend->drawLine(pt3, pt4, m_color.r, m_color.g, m_color.b); - } + // fill render cache with cell data + Rect layerView = cam->getLayerViewPort(layer); + std::vector cells = cache->getBlockingCellsInRect(layerView); + std::vector::iterator cit = cells.begin(); + for (; cit != cells.end(); ++cit) { + // get Instances on Cell + const std::set& instances2 = (*cit)->getInstances(); + for (std::set::const_iterator it = instances2.begin(); it != instances2.end(); ++it) { + m_fifeIdToBufferId[(*it)->getFifeId()] = pos * elements; } + std::vector vertices; + cg->getVertices(vertices, (*cit)->getLayerCoordinates()); + for (uint32_t i = 0; i < cellSideCount; ++i) { + ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[i])); + data[i].x = pts.x; + data[i].y = pts.y; + } + data[cellSideCount] = data[0]; + data[cellSideCount + 1] = data[halfCell]; + renderCache->addLines(data, color); + ++pos; } } else { + // fill render cache with instance data RenderList::const_iterator instance_it = instances.begin(); - for (;instance_it != instances.end(); ++instance_it) { + for (; instance_it != instances.end(); ++instance_it) { Instance* instance = (*instance_it)->instance; if (!instance->getObject()->isBlocking() || !instance->isBlocking()) { continue; } + m_fifeIdToBufferId[instance->getFifeId()] = pos * elements; std::vector vertices; cg->getVertices(vertices, instance->getLocationRef().getLayerCoordinates()); - std::vector::const_iterator it = vertices.begin(); - int32_t halfind = vertices.size() / 2; - ScreenPoint firstpt = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - Point pt1(firstpt.x, firstpt.y); - Point pt2; - ++it; - for (; it != vertices.end(); it++) { - ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - pt2.x = pts.x; - pt2.y = pts.y; - m_renderbackend->drawLine(pt1, pt2, m_color.r, m_color.g, m_color.b); - pt1 = pt2; + for (uint32_t i = 0; i < cellSideCount; ++i) { + ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[i])); + data[i].x = pts.x; + data[i].y = pts.y; + } + data[cellSideCount] = data[0]; + data[cellSideCount + 1] = data[halfCell]; + renderCache->addLines(data, color); + ++pos; + } + } + m_updated = false; + } + + void BlockingInfoRenderer::update(Camera* cam, Layer* layer, RenderCache* renderCache) { + CellGrid* cg = layer->getCellGrid(); + const uint32_t cellSideCount = cg->getCellSideCount(); + const uint32_t halfCell = cellSideCount / 2; + const uint32_t elements = cellSideCount + 2; + + // remove data + const std::set& removedInstances = cam->getRemovedInstances(layer); + std::set::const_iterator rit = removedInstances.begin(); + for (; rit != removedInstances.end(); ++rit) { + std::unordered_map::iterator rit2 = m_fifeIdToBufferId.find(*rit); + if (rit2 == m_fifeIdToBufferId.end()) continue; + uint32_t pos = rit2->second; + renderCache->removeLines(pos, elements); + } + + // update Instance data + const std::set& updatedInstances = cam->getUpdatedInstances(layer); + if (!updatedInstances.empty()) { + Color color(m_color.r, m_color.g, m_color.b, 255); + std::vector data(elements); + std::set::const_iterator it = updatedInstances.begin(); + for (; it != updatedInstances.end(); ++it) { + std::unordered_map::iterator it2 = m_fifeIdToBufferId.find((*it)->getFifeId()); + if (it2 == m_fifeIdToBufferId.end()) continue; + uint32_t pos = it2->second; + + std::vector vertices; + cg->getVertices(vertices, (*it)->getLocationRef().getLayerCoordinates()); + for (uint32_t i = 0; i < cellSideCount; ++i) { + ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[i])); + data[i].x = pts.x; + data[i].y = pts.y; } - m_renderbackend->drawLine(pt2, Point(firstpt.x, firstpt.y), m_color.r, m_color.g, m_color.b); - ScreenPoint spt1 = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[0])); - Point pt3(spt1.x, spt1.y); - ScreenPoint spt2 = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[halfind])); - Point pt4(spt2.x, spt2.y); - m_renderbackend->drawLine(pt3, pt4, m_color.r, m_color.g, m_color.b); + data[cellSideCount] = data[0]; + data[cellSideCount + 1] = data[halfCell]; + renderCache->updateLines(pos, data, color); } } } @@ -155,5 +203,6 @@ namespace FIFE { m_color.r = r; m_color.g = g; m_color.b = b; + m_updated = true; } } diff --git a/engine/core/view/renderers/blockinginforenderer.h b/engine/core/view/renderers/blockinginforenderer.h index 27bf017f3..57c3ec5fa 100644 --- a/engine/core/view/renderers/blockinginforenderer.h +++ b/engine/core/view/renderers/blockinginforenderer.h @@ -23,6 +23,7 @@ #define FIFE_BLOCKINGINFORENDERER_H // Standard C++ library includes +#include // 3rd party library includes @@ -35,7 +36,7 @@ namespace FIFE { class RenderBackend; - class BlockingInfoRenderer: public RendererBase { + class BlockingInfoRenderer : public RendererBase { public: /** Constructor. * @@ -63,7 +64,7 @@ namespace FIFE { */ std::string getName() { return "BlockingInfoRenderer"; } - /** This method is called by the view to ask renderer to draw its rendering aspect based on + /** This method is called by the camera to ask renderer to draw its rendering aspect based on * given parameters. * * @param cam Camera view to draw @@ -85,6 +86,15 @@ namespace FIFE { static BlockingInfoRenderer* getInstance(IRendererContainer* cnt); private: + void fullUpdate(Camera* cam, Layer* layer, RenderList& instances, RenderCache* renderCache); + + void update(Camera* cam, Layer* layer, RenderCache* renderCache); + + std::unordered_map m_fifeIdToBufferId; + + //! indicates updates + bool m_updated; + //! currently used color SDL_Color m_color; };