mirror of
https://github.com/glest/glest-source.git
synced 2025-02-24 19:52:25 +01:00
498 lines
14 KiB
C++
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
|