306 lines
11 KiB
C
306 lines
11 KiB
C
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
// SPARK particle engine //
|
||
|
// Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com //
|
||
|
// //
|
||
|
// This software is provided 'as-is', without any express or implied //
|
||
|
// warranty. In no event will the authors be held liable for any damages //
|
||
|
// arising from the use of this software. //
|
||
|
// //
|
||
|
// Permission is granted to anyone to use this software for any purpose, //
|
||
|
// including commercial applications, and to alter it and redistribute it //
|
||
|
// freely, subject to the following restrictions: //
|
||
|
// //
|
||
|
// 1. The origin of this software must not be misrepresented; you must not //
|
||
|
// claim that you wrote the original software. If you use this software //
|
||
|
// in a product, an acknowledgment in the product documentation would be //
|
||
|
// appreciated but is not required. //
|
||
|
// 2. Altered source versions must be plainly marked as such, and must not be //
|
||
|
// misrepresented as being the original software. //
|
||
|
// 3. This notice may not be removed or altered from any source distribution. //
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
#ifndef H_SPK_GLQUADRENDERER
|
||
|
#define H_SPK_GLQUADRENDERER
|
||
|
|
||
|
#include "RenderingAPIs/OpenGL/SPK_GLRenderer.h"
|
||
|
#include "RenderingAPIs/OpenGL/SPK_GLExtHandler.h"
|
||
|
#include "Extensions/Renderers/SPK_QuadRendererInterface.h"
|
||
|
#include "Extensions/Renderers/SPK_Oriented3DRendererInterface.h"
|
||
|
#include "Core/SPK_Vector3D.h"
|
||
|
#include "Core/SPK_Particle.h"
|
||
|
#include "Core/SPK_Model.h"
|
||
|
|
||
|
namespace SPK
|
||
|
{
|
||
|
namespace GL
|
||
|
{
|
||
|
/**
|
||
|
* @class GLQuadRenderer
|
||
|
* @brief A Renderer drawing particles as OpenGL quads
|
||
|
*
|
||
|
* the orientation of the quads depends on the orientation parameters set.
|
||
|
* This orientation is computed during rendering by the CPU (further improvement of SPARK will allow to make the computation on GPU side).<br>
|
||
|
* <br>
|
||
|
* Below are the parameters of Particle that are used in this Renderer (others have no effects) :
|
||
|
* <ul>
|
||
|
* <li>SPK::PARAM_SIZE</li>
|
||
|
* <li>SPK::PARAM_RED</li>
|
||
|
* <li>SPK::PARAM_GREEN</li>
|
||
|
* <li>SPK::PARAM_BLUE</li>
|
||
|
* <li>SPK::PARAM_ALPHA (only if blending is enabled)</li>
|
||
|
* <li>SPK::PARAM_ANGLE</li>
|
||
|
* <li>SPK::PARAM_TEXTURE_INDEX (only if not in TEXTURE_NONE mode)</li>
|
||
|
* </ul>
|
||
|
*/
|
||
|
class SPK_GL_PREFIX GLQuadRenderer : public GLRenderer,
|
||
|
public QuadRendererInterface,
|
||
|
public Oriented3DRendererInterface,
|
||
|
public GLExtHandler
|
||
|
{
|
||
|
SPK_IMPLEMENT_REGISTERABLE(GLQuadRenderer)
|
||
|
|
||
|
public :
|
||
|
|
||
|
//////////////////
|
||
|
// Constructors //
|
||
|
//////////////////
|
||
|
|
||
|
/**
|
||
|
* @brief Constructor of GLQuadRenderer
|
||
|
* @param scaleX the scale of the width of the quad
|
||
|
* @param scaleY the scale of the height of the quad
|
||
|
*/
|
||
|
GLQuadRenderer(float scaleX = 1.0f,float scaleY = 1.0f);
|
||
|
|
||
|
/**
|
||
|
* @brief Creates and registers a new GLQuadRenderer
|
||
|
* @param scaleX the scale of the width of the quad
|
||
|
* @param scaleY the scale of the height of the quad
|
||
|
* @return A new registered GLQuadRenderer
|
||
|
* @since 1.04.00
|
||
|
*/
|
||
|
static inline GLQuadRenderer* create(float scaleX = 1.0f,float scaleY = 1.0f);
|
||
|
|
||
|
/////////////
|
||
|
// Setters //
|
||
|
/////////////
|
||
|
|
||
|
virtual bool setTexturingMode(TexturingMode mode);
|
||
|
|
||
|
inline void setTexture(GLuint textureIndex);
|
||
|
|
||
|
/////////////
|
||
|
// Getters //
|
||
|
/////////////
|
||
|
|
||
|
/**
|
||
|
* @brief Gets the texture of this GLQuadRenderer
|
||
|
* @return the texture of this GLQuadRenderer
|
||
|
*/
|
||
|
inline GLuint getTexture() const;
|
||
|
|
||
|
///////////////
|
||
|
// Interface //
|
||
|
///////////////
|
||
|
|
||
|
virtual void createBuffers(const Group& group);
|
||
|
virtual void destroyBuffers(const Group& group);
|
||
|
|
||
|
virtual void render(const Group& group);
|
||
|
|
||
|
protected :
|
||
|
|
||
|
virtual bool checkBuffers(const Group& group);
|
||
|
|
||
|
private :
|
||
|
|
||
|
mutable float modelView[16];
|
||
|
mutable float invModelView[16];
|
||
|
|
||
|
GLuint textureIndex;
|
||
|
|
||
|
// vertex buffers and iterators
|
||
|
static float* gpuBuffer;
|
||
|
static float* gpuIterator;
|
||
|
static float* textureBuffer;
|
||
|
static float* textureIterator;
|
||
|
|
||
|
// buffers names
|
||
|
static const std::string GPU_BUFFER_NAME;
|
||
|
static const std::string TEXTURE_BUFFER_NAME;
|
||
|
|
||
|
float* createTextureBuffer(const Group& group) const;
|
||
|
|
||
|
inline void invertModelView() const;
|
||
|
|
||
|
inline void GLCallColorAndVertex(const Particle& particle) const; // OpenGL calls for color and position
|
||
|
inline void GLCallTexture2DAtlas(const Particle& particle) const; // OpenGL calls for 2D atlastexturing
|
||
|
inline void GLCallTexture3D(const Particle& particle) const; // OpenGL calls for 3D texturing
|
||
|
|
||
|
static void (GLQuadRenderer::*renderParticle)(const Particle&) const; // pointer to the right render method
|
||
|
|
||
|
void render2D(const Particle& particle) const; // Rendering for particles with texture 2D or no texture
|
||
|
void render2DRot(const Particle& particle) const; // Rendering for particles with texture 2D or no texture and rotation
|
||
|
void render3D(const Particle& particle) const; // Rendering for particles with texture 3D
|
||
|
void render3DRot(const Particle& particle) const; // Rendering for particles with texture 3D and rotation
|
||
|
void render2DAtlas(const Particle& particle) const; // Rendering for particles with texture 2D atlas
|
||
|
void render2DAtlasRot(const Particle& particle) const; // Rendering for particles with texture 2D atlas and rotation
|
||
|
};
|
||
|
|
||
|
|
||
|
inline GLQuadRenderer* GLQuadRenderer::create(float scaleX,float scaleY)
|
||
|
{
|
||
|
GLQuadRenderer* obj = new GLQuadRenderer(scaleX,scaleY);
|
||
|
registerObject(obj);
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
inline void GLQuadRenderer::setTexture(GLuint textureIndex)
|
||
|
{
|
||
|
this->textureIndex = textureIndex;
|
||
|
}
|
||
|
|
||
|
inline GLuint GLQuadRenderer::getTexture() const
|
||
|
{
|
||
|
return textureIndex;
|
||
|
}
|
||
|
|
||
|
inline void GLQuadRenderer::GLCallColorAndVertex(const Particle& particle) const
|
||
|
{
|
||
|
float x = particle.position().x;
|
||
|
float y = particle.position().y;
|
||
|
float z = particle.position().z;
|
||
|
|
||
|
// quads are drawn in a counter clockwise order :
|
||
|
// top right vertex
|
||
|
*(gpuIterator++) = x + quadSide().x + quadUp().x;
|
||
|
*(gpuIterator++) = y + quadSide().y + quadUp().y;
|
||
|
*(gpuIterator++) = z + quadSide().z + quadUp().z;
|
||
|
gpuIterator += 4;
|
||
|
|
||
|
// top left vertex
|
||
|
*(gpuIterator++) = x - quadSide().x + quadUp().x;
|
||
|
*(gpuIterator++) = y - quadSide().y + quadUp().y;
|
||
|
*(gpuIterator++) = z - quadSide().z + quadUp().z;
|
||
|
gpuIterator += 4;
|
||
|
|
||
|
// bottom left
|
||
|
*(gpuIterator++) = x - quadSide().x - quadUp().x;
|
||
|
*(gpuIterator++) = y - quadSide().y - quadUp().y;
|
||
|
*(gpuIterator++) = z - quadSide().z - quadUp().z;
|
||
|
gpuIterator += 4;
|
||
|
|
||
|
// bottom right
|
||
|
*(gpuIterator++) = x + quadSide().x - quadUp().x;
|
||
|
*(gpuIterator++) = y + quadSide().y - quadUp().y;
|
||
|
*(gpuIterator++) = z + quadSide().z - quadUp().z;
|
||
|
|
||
|
*(gpuIterator++) = particle.getR();
|
||
|
*(gpuIterator++) = particle.getG();
|
||
|
*(gpuIterator++) = particle.getB();
|
||
|
*(gpuIterator++) = particle.getParamCurrentValue(PARAM_ALPHA);
|
||
|
}
|
||
|
|
||
|
inline void GLQuadRenderer::GLCallTexture2DAtlas(const Particle& particle) const
|
||
|
{
|
||
|
computeAtlasCoordinates(particle);
|
||
|
|
||
|
*(textureIterator++) = textureAtlasU1();
|
||
|
*(textureIterator++) = textureAtlasV0();
|
||
|
|
||
|
*(textureIterator++) = textureAtlasU0();
|
||
|
*(textureIterator++) = textureAtlasV0();
|
||
|
|
||
|
*(textureIterator++) = textureAtlasU0();
|
||
|
*(textureIterator++) = textureAtlasV1();
|
||
|
|
||
|
*(textureIterator++) = textureAtlasU1();
|
||
|
*(textureIterator++) = textureAtlasV1();
|
||
|
}
|
||
|
|
||
|
inline void GLQuadRenderer::GLCallTexture3D(const Particle& particle) const
|
||
|
{
|
||
|
float textureIndex = particle.getParamCurrentValue(PARAM_TEXTURE_INDEX);
|
||
|
|
||
|
*(textureIterator + 2) = textureIndex;
|
||
|
*(textureIterator + 5) = textureIndex;
|
||
|
*(textureIterator + 8) = textureIndex;
|
||
|
*(textureIterator + 11) = textureIndex;
|
||
|
textureIterator += 12;
|
||
|
}
|
||
|
|
||
|
inline void GLQuadRenderer::invertModelView() const
|
||
|
{
|
||
|
float tmp[12];
|
||
|
float src[16];
|
||
|
|
||
|
/* transpose matrix */
|
||
|
for (int i = 0; i < 4; ++i)
|
||
|
{
|
||
|
src[i] = modelView[i << 2];
|
||
|
src[i + 4] = modelView[(i << 2) + 1];
|
||
|
src[i + 8] = modelView[(i << 2) + 2];
|
||
|
src[i + 12] = modelView[(i << 2) + 3];
|
||
|
}
|
||
|
|
||
|
/* calculate pairs for first 8 elements (cofactors) */
|
||
|
tmp[0] = src[10] * src[15];
|
||
|
tmp[1] = src[11] * src[14];
|
||
|
tmp[2] = src[9] * src[15];
|
||
|
tmp[3] = src[11] * src[13];
|
||
|
tmp[4] = src[9] * src[14];
|
||
|
tmp[5] = src[10] * src[13];
|
||
|
tmp[6] = src[8] * src[15];
|
||
|
tmp[7] = src[11] * src[12];
|
||
|
tmp[8] = src[8] * src[14];
|
||
|
tmp[9] = src[10] * src[12];
|
||
|
tmp[10] = src[8] * src[13];
|
||
|
tmp[11] = src[9] * src[12];
|
||
|
|
||
|
/* calculate first 8 elements (cofactors) */
|
||
|
invModelView[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7] - tmp[1] * src[5] - tmp[2] * src[6] - tmp[5] * src[7];
|
||
|
invModelView[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7] - tmp[0] * src[4] - tmp[7] * src[6] - tmp[8] * src[7];
|
||
|
invModelView[2] = tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7] - tmp[3] * src[4] - tmp[6] * src[5] - tmp[11] * src[7];
|
||
|
invModelView[3] = tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6] - tmp[4] * src[4] - tmp[9] * src[5] - tmp[10] * src[6];
|
||
|
invModelView[4] = tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3] - tmp[0] * src[1] - tmp[3] * src[2] - tmp[4] * src[3];
|
||
|
invModelView[5] = tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3] - tmp[1] * src[0]- tmp[6] * src[2] - tmp[9] * src[3];
|
||
|
invModelView[6] = tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3] - tmp[2] * src[0] - tmp[7] * src[1] - tmp[10] * src[3];
|
||
|
invModelView[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2] - tmp[5]*src[0] - tmp[8]*src[1] - tmp[11]*src[2];
|
||
|
|
||
|
/* calculate pairs for second 8 elements (cofactors) */
|
||
|
tmp[0] = src[2] * src[7];
|
||
|
tmp[1] = src[3] * src[6];
|
||
|
tmp[2] = src[1] * src[7];
|
||
|
tmp[3] = src[3] * src[5];
|
||
|
tmp[4] = src[1] * src[6];
|
||
|
tmp[5] = src[2] * src[5];
|
||
|
tmp[6] = src[0] * src[7];
|
||
|
tmp[7] = src[3] * src[4];
|
||
|
tmp[8] = src[0] * src[6];
|
||
|
tmp[9] = src[2] * src[4];
|
||
|
tmp[10] = src[0] * src[5];
|
||
|
tmp[11] = src[1] * src[4];
|
||
|
|
||
|
/* calculate second 8 elements (cofactors) */
|
||
|
invModelView[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15] - tmp[1] * src[13] - tmp[2] * src[14] - tmp[5] * src[15];
|
||
|
invModelView[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15] - tmp[0] * src[12] - tmp[7] * src[14] - tmp[8] * src[15];
|
||
|
invModelView[10] = tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15] - tmp[3] * src[12] - tmp[6] * src[13] - tmp[11] * src[15];
|
||
|
invModelView[11] = tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14] - tmp[4] * src[12] - tmp[9] * src[13] - tmp[10] * src[14];
|
||
|
invModelView[12] = tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9] - tmp[4] * src[11] - tmp[0] * src[9] - tmp[3] * src[10];
|
||
|
invModelView[13] = tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10] - tmp[6] * src[10] - tmp[9] * src[11] - tmp[1] * src[8];
|
||
|
invModelView[14] = tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8] - tmp[10] * src[11] - tmp[2] * src[8] - tmp[7] * src[9];
|
||
|
invModelView[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9] - tmp[8] * src[9] - tmp[11] * src[10] - tmp[5] * src[8];
|
||
|
|
||
|
/* calculate determinant */
|
||
|
float det = src[0] * invModelView[0] + src[1] * invModelView[1] + src[2] * invModelView[2] + src[3] * invModelView[3];
|
||
|
|
||
|
/* calculate matrix inverse */
|
||
|
det = 1 / det;
|
||
|
for (int i = 0; i < 16; ++i)
|
||
|
invModelView[i] *= det;
|
||
|
}
|
||
|
}}
|
||
|
|
||
|
#endif
|