355 lines
9.9 KiB
C++
355 lines
9.9 KiB
C++
|
/**
|
||
|
* \file nelrenderer.cpp
|
||
|
* \date November 2004
|
||
|
* \author Matt Raykowski
|
||
|
* \author Henri Kuuste
|
||
|
*/
|
||
|
|
||
|
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||
|
// Copyright (C) 2010 Winch Gate Property Limited
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU Affero General Public License as
|
||
|
// published by the Free Software Foundation, either version 3 of the
|
||
|
// License, or (at your option) any later version.
|
||
|
//
|
||
|
// This program 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 Affero General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Affero General Public License
|
||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
|
||
|
/************************************************************************
|
||
|
purpose: Implementation of Renderer class for Nevrax engine
|
||
|
|
||
|
For use with GUI Library:
|
||
|
Crazy Eddie's GUI System (http://crayzedsgui.sourceforge.net)
|
||
|
Copyright (C)2004 Paul D Turner (crayzed@users.sourceforge.net)
|
||
|
|
||
|
This file contains code that is specific to NeL (http://www.nevrax.org)
|
||
|
*************************************************************************/
|
||
|
|
||
|
#include "CEGUIImagesetManager.h"
|
||
|
#include "CEGUIImageset.h"
|
||
|
#include "CEGUIImage.h"
|
||
|
#include "CEGUIExceptions.h"
|
||
|
#include "CEGUISystem.h"
|
||
|
#include "CEGUIEventArgs.h"
|
||
|
#include "CEGUIImageCodec.h"
|
||
|
#include "CEGUIDynamicModule.h"
|
||
|
|
||
|
#include <nel/misc/dynloadlib.h>
|
||
|
|
||
|
//#include <nel/cegui/inelrenderer.h>
|
||
|
#include <nel/cegui/nelrenderer.h>
|
||
|
#include <nel/cegui/neltexture.h>
|
||
|
#include <nel/cegui/nelresourceprovider.h>
|
||
|
|
||
|
#include <nel/3d/u_material.h>
|
||
|
#include <nel/3d/u_driver.h>
|
||
|
|
||
|
#include <nel/cegui/inellibrary.h>
|
||
|
|
||
|
#include <algorithm>
|
||
|
|
||
|
#ifdef NL_OS_WINDOWS
|
||
|
# define NOMINMAX
|
||
|
# include <windows.h>
|
||
|
#endif
|
||
|
|
||
|
#define S_(X) #X
|
||
|
#define STRINGIZE(X) S_(X)
|
||
|
|
||
|
#ifndef NL_STATIC
|
||
|
|
||
|
//class CCeguiRendererNelLibrary : public NLMISC::INelLibrary {
|
||
|
// void onLibraryLoaded(bool /* firstTime */) { }
|
||
|
// void onLibraryUnloaded(bool /* lastTime */) { }
|
||
|
//};
|
||
|
NLMISC_DECL_PURE_LIB(CCeguiRendererNelLibrary)
|
||
|
|
||
|
#endif /* #ifndef NL_STATIC */
|
||
|
|
||
|
/*
|
||
|
* Sound driver instance creation
|
||
|
*/
|
||
|
#ifdef NL_OS_WINDOWS
|
||
|
|
||
|
// ******************************************************************
|
||
|
|
||
|
#ifdef NL_STATIC
|
||
|
Renderer* createNeLRendererInstance
|
||
|
#else
|
||
|
__declspec(dllexport) CEGUI::Renderer *createNeLRendererInstance
|
||
|
#endif
|
||
|
(NL3D::UDriver *driver, bool withRP=true)
|
||
|
{
|
||
|
return new CEGUI::NeLRenderer(driver, withRP);
|
||
|
}
|
||
|
|
||
|
// ******************************************************************
|
||
|
|
||
|
#elif defined (NL_OS_UNIX)
|
||
|
|
||
|
extern "C"
|
||
|
{
|
||
|
CEGUI::Renderer *createNeLRendererInstance(NL3D::UDriver *driver, bool withRP=true)
|
||
|
{
|
||
|
return new CEGUI::NeLRenderer(driver, withRP);
|
||
|
}
|
||
|
} // extern "C"
|
||
|
|
||
|
#endif // NL_OS_UNIX
|
||
|
|
||
|
// Start of CEGUI namespace section
|
||
|
namespace CEGUI
|
||
|
{
|
||
|
class NeLTexture;
|
||
|
|
||
|
/*************************************************************************
|
||
|
Constants definitions
|
||
|
*************************************************************************/
|
||
|
const int NeLRenderer::VERTEX_PER_QUAD = 4;
|
||
|
const int NeLRenderer::VERTEX_PER_TRIANGLE = 3;
|
||
|
const int NeLRenderer::VERTEXBUFFER_CAPACITY = 4096;
|
||
|
|
||
|
NeLRenderer::NeLRenderer(NL3D::UDriver *driver, bool withRP, ImageCodec* codec)
|
||
|
{
|
||
|
m_Driver=driver;
|
||
|
d_queueing=true;
|
||
|
NL3D::UDriver::CMode mode;
|
||
|
driver->getCurrentScreenMode(mode);
|
||
|
d_display_area.d_left=0;
|
||
|
d_display_area.d_top=0;
|
||
|
d_display_area.d_right=(float)driver->getWindowWidth();
|
||
|
d_display_area.d_bottom=(float)driver->getWindowHeight();
|
||
|
m_InputDriver.addToServer(m_Driver->EventServer);
|
||
|
m_InputDriver.setScreenMode(d_display_area.getWidth(),d_display_area.getHeight(),(float)mode.Depth);
|
||
|
m_InputDriver.setDriver(m_Driver);
|
||
|
NLMISC::CHTimer::startBench();
|
||
|
m_NelProvider=withRP;
|
||
|
m_FrameCount=0;
|
||
|
m_ImageCodec = codec;
|
||
|
m_ImageCodecModule = NULL;
|
||
|
|
||
|
if(!m_ImageCodec)
|
||
|
setupImageCodec("");
|
||
|
}
|
||
|
|
||
|
NeLRenderer::~NeLRenderer(void)
|
||
|
{
|
||
|
destroyAllTextures();
|
||
|
cleanupImageCodec();
|
||
|
m_InputDriver.removeFromServer(m_Driver->EventServer);
|
||
|
NLMISC::CHTimer::clear();
|
||
|
}
|
||
|
|
||
|
// void NeLRenderer::addSearchPath(const std::string &path, bool recurse, bool alternative, class NLMISC::IProgressCallback *progressCallBack) {
|
||
|
// NLMISC::CPath::addSearchPath(path.c_str(),recurse,alternative,progressCallBack);
|
||
|
// }
|
||
|
|
||
|
void NeLRenderer::addQuad(const Rect& dest_rect, float z, const Texture* tex, const Rect& texture_rect, const ColourRect& colours, QuadSplitMode quad_split_mode)
|
||
|
{
|
||
|
using namespace NLMISC;
|
||
|
H_AUTO(NeLRenderer_addQuad);
|
||
|
|
||
|
/*
|
||
|
* Special note: quad splitting is not yet supported.
|
||
|
*/
|
||
|
|
||
|
NLMISC::CQuadColorUV nelquad;
|
||
|
|
||
|
NeLTexture *text=(NeLTexture *)tex;
|
||
|
// set quad position, flipping y co-ordinates, and applying appropriate texel origin offset
|
||
|
Rect position=dest_rect;
|
||
|
position.offset(Point(-0.5f, -0.5f));
|
||
|
// upper left
|
||
|
nelquad.V0.set(position.d_left, position.d_top, z);
|
||
|
nelquad.Uv0.set(texture_rect.d_left, texture_rect.d_top);
|
||
|
nelquad.Color0=colorToNeL(colours.d_bottom_left);
|
||
|
|
||
|
// upper right
|
||
|
nelquad.V1.set(position.d_right, position.d_top, z);
|
||
|
nelquad.Uv1.set(texture_rect.d_right, texture_rect.d_top);
|
||
|
nelquad.Color1=colorToNeL(colours.d_bottom_right);
|
||
|
|
||
|
// lower right
|
||
|
nelquad.V2.set(position.d_right, position.d_bottom, z);
|
||
|
nelquad.Uv2.set(texture_rect.d_right, texture_rect.d_bottom);
|
||
|
nelquad.Color2=colorToNeL(colours.d_top_right);
|
||
|
|
||
|
// lower left
|
||
|
nelquad.V3.set(position.d_left, position.d_bottom, z);
|
||
|
nelquad.Uv3.set(texture_rect.d_left, texture_rect.d_bottom);
|
||
|
nelquad.Color3=colorToNeL(colours.d_top_left);
|
||
|
|
||
|
if(!d_queueing) {
|
||
|
renderQuad(nelquad,text->getNeLTexture());
|
||
|
} else {
|
||
|
QuadVector::reverse_iterator itr = d_quadlist.rbegin();
|
||
|
if((d_quadlist.size() > 0) && ((*itr).texture == text)) {
|
||
|
(*itr).quads.push_back(nelquad);
|
||
|
} else {
|
||
|
QuadInfo qI;
|
||
|
qI.texture = text;
|
||
|
qI.quads.push_back(nelquad);
|
||
|
d_quadlist.push_back(qI);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void NeLRenderer::renderQuad(NLMISC::CQuadColorUV quad, NL3D::UMaterial mat) {
|
||
|
using namespace NLMISC;
|
||
|
H_AUTO(NeLRenderer_renderQuad);
|
||
|
m_Driver->setFrustum(NL3D::CFrustum(0, d_display_area.getWidth(), d_display_area.getHeight(), 0, -1, 1, false));
|
||
|
m_Driver->drawQuad(quad,mat);
|
||
|
}
|
||
|
|
||
|
void NeLRenderer::doRender(void)
|
||
|
{
|
||
|
using namespace NLMISC;
|
||
|
H_AUTO(NeLRenderer_doRender);
|
||
|
|
||
|
// set the culling frustrum
|
||
|
m_Driver->setFrustum(NL3D::CFrustum(0, d_display_area.getWidth(), d_display_area.getHeight(), 0, -1, 1, false));
|
||
|
|
||
|
// and go through the list.
|
||
|
for(QuadVector::iterator itr=d_quadlist.begin();itr!=d_quadlist.end();itr++) {
|
||
|
NL3D::UMaterial mat = (*itr).texture->getNeLTexture();
|
||
|
m_Driver->drawQuads((*itr).quads,mat);
|
||
|
}
|
||
|
|
||
|
m_FrameCount++;
|
||
|
if(m_FrameCount==200) {
|
||
|
#ifdef _DEBUG
|
||
|
NLMISC::CHTimer::displaySummary();
|
||
|
nlinfo("Quad list size: %d", d_quadlist.size());
|
||
|
#endif
|
||
|
m_FrameCount=0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void NeLRenderer::clearRenderList(void)
|
||
|
{
|
||
|
d_quadlist.clear();
|
||
|
}
|
||
|
|
||
|
Texture *NeLRenderer::createTexture(void)
|
||
|
{
|
||
|
|
||
|
NeLTexture *tex=new NeLTexture(this);
|
||
|
d_texturelist.push_back((NeLTexture *const)tex);
|
||
|
return tex;
|
||
|
}
|
||
|
|
||
|
Texture *NeLRenderer::createTexture(const String &filename, const String &resourceGroup)
|
||
|
{
|
||
|
NeLTexture *tex=(NeLTexture*)createTexture();
|
||
|
tex->loadFromFile(filename, resourceGroup);
|
||
|
return tex;
|
||
|
}
|
||
|
|
||
|
Texture *NeLRenderer::createTexture(float size)
|
||
|
{
|
||
|
NeLTexture* tex = (NeLTexture*)createTexture();
|
||
|
return tex;
|
||
|
}
|
||
|
|
||
|
|
||
|
void NeLRenderer::destroyTexture(Texture* texture)
|
||
|
{
|
||
|
if (texture != NULL)
|
||
|
{
|
||
|
NeLTexture *tex=(NeLTexture *)texture;
|
||
|
d_texturelist.remove((NeLTexture *const)tex);
|
||
|
delete tex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void NeLRenderer::destroyAllTextures(void)
|
||
|
{
|
||
|
while(!d_texturelist.empty())
|
||
|
{
|
||
|
destroyTexture((Texture *)*(d_texturelist.begin()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void NeLRenderer::sortQuads(void)
|
||
|
{
|
||
|
;
|
||
|
}
|
||
|
|
||
|
void NeLRenderer::setQueueingEnabled(bool setting) {
|
||
|
d_queueing = setting;
|
||
|
}
|
||
|
|
||
|
bool NeLRenderer::isQueueingEnabled(void) const {
|
||
|
return d_queueing;
|
||
|
}
|
||
|
|
||
|
NLMISC::CRGBA NeLRenderer::colorToNeL(CEGUI::colour color) {
|
||
|
NLMISC::CRGBA ctmp;
|
||
|
ctmp.set((uint8)(color.getRed()*255),(uint8)(color.getGreen()*255),(uint8)(color.getBlue()*255),(uint8)(color.getAlpha()*255));
|
||
|
return ctmp;
|
||
|
}
|
||
|
|
||
|
ResourceProvider* NeLRenderer::createResourceProvider(void)
|
||
|
{
|
||
|
if(d_resourceProvider==0) {
|
||
|
//if(m_NelProvider) {
|
||
|
d_resourceProvider = new NeLResourceProvider();
|
||
|
//} else {
|
||
|
// d_resourceProvider = new DefaultResourceProvider();
|
||
|
//}
|
||
|
}
|
||
|
return d_resourceProvider;
|
||
|
}
|
||
|
|
||
|
ImageCodec &NeLRenderer::getImageCodec(void) {
|
||
|
return *m_ImageCodec;
|
||
|
}
|
||
|
|
||
|
void NeLRenderer::setImageCodec(const String &codecName) {
|
||
|
setupImageCodec(codecName);
|
||
|
}
|
||
|
|
||
|
void NeLRenderer::setImageCodec(ImageCodec *codec) {
|
||
|
if(codec) {
|
||
|
cleanupImageCodec();
|
||
|
m_ImageCodec = codec;
|
||
|
m_ImageCodecModule = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void NeLRenderer::setupImageCodec(const String& codecName) {
|
||
|
// Cleanup the old image codec
|
||
|
if(m_ImageCodec)
|
||
|
cleanupImageCodec();
|
||
|
|
||
|
// Test whether we should use the default codec or not
|
||
|
if(codecName.empty())
|
||
|
m_ImageCodecModule = new DynamicModule(String("CEGUI") + m_DefaultImageCodecName);
|
||
|
else
|
||
|
m_ImageCodecModule = new DynamicModule(String("CEGUI") + codecName);
|
||
|
|
||
|
// Create the codec object itself
|
||
|
ImageCodec* (*createFunc)(void) = (ImageCodec* (*)(void))m_ImageCodecModule->getSymbolAddress("createImageCodec");
|
||
|
m_ImageCodec = createFunc();
|
||
|
}
|
||
|
|
||
|
void NeLRenderer::cleanupImageCodec() {
|
||
|
if (m_ImageCodec && m_ImageCodecModule) {
|
||
|
void(*deleteFunc)(ImageCodec*) = (void(*)(ImageCodec*))m_ImageCodecModule->getSymbolAddress("destroyImageCodec");
|
||
|
deleteFunc(m_ImageCodec);
|
||
|
m_ImageCodec = 0;
|
||
|
delete m_ImageCodecModule;
|
||
|
m_ImageCodecModule = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
String NeLRenderer::m_DefaultImageCodecName("DevILImageCodec");
|
||
|
} // end namespace CEGUI
|