2018-06-29 02:35:12 +02:00

498 lines
14 KiB
C++

// ==============================================================
// This file is part of MegaGlest (www.glest.org)
//
// Copyright (C) 2011 - by Mark Vejvoda <mark_vejvoda@hotmail.com>
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "renderer.h"
#include "graphics_factory_gl.h"
#include "graphics_interface.h"
#include "config.h"
#include "platform_common.h"
//#include <memory>
using namespace Shared::Graphics;
using namespace Shared::Graphics::Gl;
using namespace Glest::Game;
using namespace Shared::Util;
namespace Shared {
namespace G3dViewer {
int Renderer::windowX = 100;
int Renderer::windowY = 100;
int Renderer::windowW = 640;
int Renderer::windowH = 480;
// ===============================================
// class Renderer
// ===============================================
Renderer::Renderer() {
normals = false;
wireframe = false;
grid = true;
modelRenderer = NULL;
textureManager = NULL;
particleRenderer = NULL;
modelManager = NULL;
width = 0;
height = 0;
red = 0.3f;
green = 0.3f;
blue = 0.3f;
alpha = 1.0f;
customTextureRed = NULL;
customTextureBlue = NULL;
customTextureGreen = NULL;
customTextureYellow = NULL;
customTextureWhite = NULL;
customTextureCyan = NULL;
customTextureOrange = NULL;
customTextureMagenta = NULL;
particleManager = NULL;
}
Renderer::~Renderer() {
delete modelRenderer;
delete textureManager;
delete particleRenderer;
//resources
delete particleManager;
delete modelManager;
if (GraphicsInterface::getInstance().getFactory() != NULL) {
delete GraphicsInterface::getInstance().getFactory();
GraphicsInterface::getInstance().setFactory(NULL);
}
}
Renderer * Renderer::getInstance() {
static Renderer * renderer = new Renderer();
return renderer;
}
void Renderer::transform(float rotX, float rotY, float zoom) {
assertGl();
glMatrixMode(GL_MODELVIEW);
glRotatef(rotY, 1.0f, 0.0f, 0.0f);
glRotatef(rotX, 0.0f, 1.0f, 0.0f);
glScalef(zoom, zoom, zoom);
Vec4f pos(-8.0f, 5.0f, 10.0f, 0.0f);
glLightfv(GL_LIGHT0, GL_POSITION, pos.ptr());
assertGl();
}
void Renderer::checkGlCaps() {
if (glActiveTexture == NULL) {
string message;
message += "Your system supports OpenGL version \"";
message += getGlVersion() + string("\"\n");
message += "ZetaGlest needs a version that supports\n";
message += "glActiveTexture (OpenGL 1.3) or the ARB_multitexture extension.";
throw megaglest_runtime_error(message.c_str());
}
//opengl 1.3
//if(!isGlVersionSupported(1, 3, 0)) {
if (glewIsSupported("GL_VERSION_1_3") == false) {
string message;
message += "Your system supports OpenGL version \"";
message += getGlVersion() + string("\"\n");
message += "ZetaGlest needs at least version 1.3 to work\n";
message += "You may solve this problem by installing your latest video card drivers";
throw megaglest_runtime_error(message.c_str());
}
//opengl 1.4 or extension
//if(isGlVersionSupported(1, 4, 0) == false) {
if (glewIsSupported("GL_VERSION_1_4") == false) {
checkExtension("GL_ARB_texture_env_crossbar", "ZetaGlest");
}
}
void Renderer::checkExtension(const string &extension, const string &msg) {
if (isGlExtensionSupported(extension.c_str()) == false) {
string str = "OpenGL extension not supported: " + extension + ", required for " + msg;
throw megaglest_runtime_error(str);
}
}
Texture2D * Renderer::getNewTexture2D() {
Texture2D *newTexture = textureManager->newTexture2D();
return newTexture;
}
Model * Renderer::newModel(ResourceScope rs, const string &path, bool deletePixMapAfterLoad, std::map<string, vector<pair<string, string> > > *loadedFileList, string *sourceLoader) {
return modelManager->newModel(path, deletePixMapAfterLoad, loadedFileList, sourceLoader);
}
void Renderer::endModel(ResourceScope rs, Model *model) {
modelManager->endModel(model);
}
void Renderer::init() {
assertGl();
GraphicsFactory *gf = GraphicsInterface::getInstance().getFactory();
if (gf == NULL) {
gf = new GraphicsFactoryGl();
GraphicsInterface::getInstance().setFactory(gf);
}
Config &config = Config::getInstance();
if (config.getBool("CheckGlCaps")) {
if (SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s %d]\n", extractFileFromDirectoryPath(__FILE__).c_str(), __FUNCTION__, __LINE__);
checkGlCaps();
}
if (glActiveTexture == NULL) {
char szBuf[8096] = "";
snprintf(szBuf, 8096, "Error: glActiveTexture == NULL\nglActiveTexture is only supported if the GL version is 1.3 or greater,\nor if the ARB_multitexture extension is supported!");
throw megaglest_runtime_error(szBuf);
}
modelRenderer = gf->newModelRenderer();
textureManager = gf->newTextureManager();
particleRenderer = gf->newParticleRenderer();
//resources
particleManager = gf->newParticleManager();
modelManager = gf->newModelManager();
modelManager->setTextureManager(textureManager);
//red tex
customTextureRed = textureManager->newTexture2D();
customTextureRed->getPixmap()->init(1, 1, 4);
customTextureRed->getPixmap()->setPixel(0, 0, Vec4f(1.f, 0.f, 0.f, 1.0f));
//blue tex
customTextureBlue = textureManager->newTexture2D();
customTextureBlue->getPixmap()->init(1, 1, 4);
customTextureBlue->getPixmap()->setPixel(0, 0, Vec4f(0.f, 0.f, 1.f, 1.0f));
//green tex
customTextureGreen = textureManager->newTexture2D();
customTextureGreen->getPixmap()->init(1, 1, 4);
customTextureGreen->getPixmap()->setPixel(0, 0, Vec4f(0.f, 0.5f, 0.f, 1.0f));
//yellow tex
customTextureYellow = textureManager->newTexture2D();
customTextureYellow->getPixmap()->init(1, 1, 4);
customTextureYellow->getPixmap()->setPixel(0, 0, Vec4f(1.f, 1.f, 0.f, 1.0f));
//white tex
customTextureWhite = textureManager->newTexture2D();
customTextureWhite->getPixmap()->init(1, 1, 4);
customTextureWhite->getPixmap()->setPixel(0, 0, Vec4f(1.f, 1.f, 1.f, 1.0f));
//cyan tex
customTextureCyan = textureManager->newTexture2D();
customTextureCyan->getPixmap()->init(1, 1, 4);
customTextureCyan->getPixmap()->setPixel(0, 0, Vec4f(0.f, 1.f, 0.8f, 1.0f));
//orange tex
customTextureOrange = textureManager->newTexture2D();
customTextureOrange->getPixmap()->init(1, 1, 4);
customTextureOrange->getPixmap()->setPixel(0, 0, Vec4f(1.f, 0.5f, 0.f, 1.0f));
//magenta tex
customTextureMagenta = textureManager->newTexture2D();
customTextureMagenta->getPixmap()->init(1, 1, 4);
customTextureMagenta->getPixmap()->setPixel(0, 0, Vec4f(1.f, 0.5f, 1.f, 1.0f));
glClearColor(red, green, blue, alpha); //backgroundcolor constant 0.3
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* once the GL context is valid : */
//GLint alpha_bits;
//glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
//printf("#1 The framebuffer uses %d bit(s) per the alpha component\n", alpha_bits);
glEnable(GL_TEXTURE_2D);
glFrontFace(GL_CW);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_ALPHA_TEST);
//glAlphaFunc(GL_GREATER, 0.5f);
glAlphaFunc(GL_GREATER, 0.0f);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
Vec4f diffuse = Vec4f(1.0f, 1.0f, 1.0f, 1.0f);
Vec4f ambient = Vec4f(0.3f, 0.3f, 0.3f, 1.0f);
Vec4f specular = Vec4f(0.1f, 0.1f, 0.1f, 1.0f);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient.ptr());
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse.ptr());
glLightfv(GL_LIGHT0, GL_SPECULAR, specular.ptr());
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
assertGl();
}
void Renderer::reset(int w, int h, PlayerColor playerColor) {
assertGl();
width = w;
height = h;
//glClearColor(red, green, blue, alpha); //backgroundcolor constant 0.3
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* once the GL context is valid : */
//GLint alpha_bits;
//glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
//printf("#2 The framebuffer uses %d bit(s) per the alpha component\n", alpha_bits);
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, static_cast<float>(w) / h, 1.0f, 200.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, -1.5, -5);
Texture2D *customTexture = NULL;
switch (playerColor) {
case pcRed:
customTexture = customTextureRed;
break;
case pcBlue:
customTexture = customTextureBlue;
break;
case pcGreen:
customTexture = customTextureGreen;
break;
case pcYellow:
customTexture = customTextureYellow;
break;
case pcWhite:
customTexture = customTextureWhite;
break;
case pcCyan:
customTexture = customTextureCyan;
break;
case pcOrange:
customTexture = customTextureOrange;
break;
case pcMagenta:
customTexture = customTextureMagenta;
break;
default:
assert(false);
break;
}
meshCallback.setTeamTexture(customTexture);
if (wireframe) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
} else {
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
assertGl();
}
void Renderer::renderGrid() {
if (grid) {
float i = 0;
assertGl();
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glColor3f(1.0f, 1.0f, 1.0f); // gridcolor constant
for (i = -10.0f; i <= 10.0f; i += 1.0f) {
glVertex3f(i, 0.0f, 10.0f);
glVertex3f(i, 0.0f, -10.0f);
}
for (i = -10.0f; i <= 10.0f; i += 1.0f) {
glVertex3f(10.f, 0.0f, i);
glVertex3f(-10.f, 0.0f, i);
}
glEnd();
glPopAttrib();
assertGl();
}
}
void Renderer::toggleNormals() {
normals = normals ? false : true;
}
void Renderer::toggleWireframe() {
wireframe = wireframe ? false : true;
}
void Renderer::toggleGrid() {
grid = grid ? false : true;
}
void Renderer::renderTheModel(Model *model, float f) {
if (model != NULL) {
modelRenderer->begin(true, true, !wireframe, false, &meshCallback);
model->updateInterpolationData(f, true);
modelRenderer->render(model);
if (normals) {
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glColor3f(1.0f, 1.0f, 1.0f); //normalscolor constant
modelRenderer->renderNormalsOnly(model);
glPopAttrib();
}
modelRenderer->end();
}
}
void Renderer::manageParticleSystem(ParticleSystem *particleSystem) {
particleManager->manage(particleSystem);
}
void Renderer::updateParticleManager() {
particleManager->update();
}
bool Renderer::hasActiveParticleSystem(ParticleSystem::ParticleSystemType type) const {
return particleManager->hasActiveParticleSystem(type);
}
void Renderer::renderParticleManager() {
glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glDepthFunc(GL_LESS);
particleRenderer->renderManager(particleManager, modelRenderer);
glPopAttrib();
}
Texture2D * Renderer::getPlayerColorTexture(PlayerColor playerColor) {
Texture2D *customTexture = NULL;
switch (playerColor) {
case pcRed:
customTexture = customTextureRed;
break;
case pcBlue:
customTexture = customTextureBlue;
break;
case pcGreen:
customTexture = customTextureGreen;
break;
case pcYellow:
customTexture = customTextureYellow;
break;
case pcWhite:
customTexture = customTextureWhite;
break;
case pcCyan:
customTexture = customTextureCyan;
break;
case pcOrange:
customTexture = customTextureOrange;
break;
case pcMagenta:
customTexture = customTextureMagenta;
break;
default:
throw megaglest_runtime_error("Unknown playercolor: " + intToStr(playerColor));
break;
}
return customTexture;
}
void Renderer::initTextureManager() {
textureManager->init();
}
void Renderer::initModelManager() {
modelManager->init();
}
void Renderer::end() {
//delete resources
//textureManager->end();
particleManager->end();
modelManager->end();
}
void Renderer::setBackgroundColor(float red, float green, float blue) {
this->red = red;
this->green = green;
this->blue = blue;
glClearColor(red, green, blue, alpha); //backgroundcolor constant 0.3
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* once the GL context is valid : */
//GLint alpha_bits;
//glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
//printf("#3 The framebuffer uses %d bit(s) per the alpha component\n", alpha_bits);
}
void Renderer::setAlphaColor(float alpha) {
this->alpha = alpha;
glClearColor(red, green, blue, alpha); //backgroundcolor constant 0.3
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* once the GL context is valid : */
//GLint alpha_bits;
//glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
//printf("#3.1 The framebuffer uses %d bit(s) per the alpha component\n", alpha_bits);
}
void Renderer::saveScreen(const string &path, std::pair<int, int> *overrideSize) {
Pixmap2D *pixmapScreenShot = new Pixmap2D(width, height, 4);
//glFinish();
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, pixmapScreenShot->getW(), pixmapScreenShot->getH(),
GL_RGBA, GL_UNSIGNED_BYTE, pixmapScreenShot->getPixels());
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
//if(overrideSize != NULL && overrideSize->first > 0 && overrideSize->second > 0) {
// pixmapScreenShot->Scale(GL_RGBA,overrideSize->first,overrideSize->second);
//}
pixmapScreenShot->save(path);
delete pixmapScreenShot;
}
}
}//end namespace