First step towards graphics abstraction and added a TinyGL driver.

This commit is contained in:
Jordi Vilalta Prat 2010-01-25 17:42:19 +01:00
parent 23ac0019e7
commit d0380d3ea3
9 changed files with 1181 additions and 116 deletions

51
gfx/driver.cpp Normal file
View file

@ -0,0 +1,51 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This library 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
*
* $URL$
* $Id$
*
*/
#include "engines/stark/gfx/driver.h"
#include "engines/stark/gfx/opengl.h"
#include "engines/stark/gfx/tinygl.h"
namespace Stark {
GfxDriver *GfxDriver::create() {
GfxDriver *driver = NULL;
#ifdef USE_OPENGL
// OpenGL
driver = new OpenGLGfxDriver();
if (driver)
return driver;
#endif // USE_OPENGL
// TinyGL
driver = new TinyGLGfxDriver();
if (driver)
return driver;
error("Couldn't instance any graphics driver");
return NULL;
}
} // End of namespace Stark

View file

@ -23,49 +23,41 @@
*
*/
#ifndef STARK_GFX_BASE_H
#define STARK_GFX_BASE_H
#ifndef STARK_GFX_DRIVER_H
#define STARK_GFX_DRIVER_H
#include "engines/stark/color.h"
//#include "engines/stark/color.h"
#include "graphics/surface.h"
#include "graphics/vector3d.h"
//#include "graphics/vector3d.h"
namespace Stark {
struct Shadow;
class GfxBase {
class GfxDriver {
public:
GfxBase() { }
virtual ~GfxBase() { }
static GfxDriver *create();
struct TextObjectHandle {
uint16 *bitmapData;
void *surface;
int numTex;
void *texIds;
int width;
int height;
};
virtual ~GfxDriver() {}
virtual byte *setupScreen(int screenW, int screenH, bool fullscreen) = 0;
virtual const char *getVideoDeviceName() = 0;
virtual bool isHardwareAccelerated() = 0;
virtual void setupCamera(float fov, float nclip, float fclip, float roll) = 0;
virtual void positionCamera(Graphics::Vector3d pos, Graphics::Vector3d interest) = 0;
virtual void setupScreen(int screenW, int screenH, bool fullscreen) = 0;
virtual void clearScreen() = 0;
virtual void flipBuffer() = 0;
virtual void drawSurface(Graphics::Surface *surface) = 0;
/*
virtual bool isHardwareAccelerated() = 0;
virtual void set3DMode() = 0;
virtual void setupCamera(float fov, float nclip, float fclip, float roll) = 0;
virtual void positionCamera(Graphics::Vector3d pos, Graphics::Vector3d interest) = 0;
virtual void translateViewpointStart(Graphics::Vector3d pos, float pitch, float yaw, float roll) = 0;
virtual void translateViewpointFinish() = 0;
virtual void drawSurface(Graphics::Surface* surface) = 0;
/*
virtual void disableLights() = 0;
virtual void setupLight(Scene::Light *light, int lightId) = 0;
@ -84,24 +76,20 @@ public:
virtual void copyStoredToDisplay() = 0;
virtual void dimScreen() = 0;
virtual void dimRegion(int x, int y, int w, int h, float level) = 0;
*/
/* virtual void drawRectangle(PrimitiveObject *primitive) = 0;
virtual void drawRectangle(PrimitiveObject *primitive) = 0;
virtual void drawLine(PrimitiveObject *primitive) = 0;
virtual void drawPolygon(PrimitiveObject *primitive) = 0;
virtual void prepareSmushFrame(int width, int height, byte *bitmap) = 0;
virtual void drawSmushFrame(int offsetX, int offsetY) = 0;
virtual void releaseSmushFrame() = 0;
*/
virtual const char *getVideoDeviceName() = 0;
*/
protected:
int _screenWidth, _screenHeight, _screenBPP;
bool _isFullscreen;
};
extern GfxBase *g_driver;
} // End of namespace Stark
#endif // STARK_GFX_BASE_H
#endif // STARK_GFX_DRIVER_H

View file

@ -23,55 +23,66 @@
*
*/
#include "engines/stark/gfx_opengl.h"
#ifdef USE_OPENGL
#include "engines/stark/gfx/opengl.h"
#include "common/system.h"
#ifdef USE_OPENGL
#ifdef SDL_BACKEND
#include <SDL_opengl.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
//#include <GL/glu.h>
#endif
namespace Stark {
GfxOpenGL::GfxOpenGL() {
_storedDisplay = NULL;
OpenGLGfxDriver::OpenGLGfxDriver() {
}
GfxOpenGL::~GfxOpenGL() {
delete[] _storedDisplay;
OpenGLGfxDriver::~OpenGLGfxDriver() {
}
byte *GfxOpenGL::setupScreen(int screenW, int screenH, bool fullscreen) {
const char *OpenGLGfxDriver::getVideoDeviceName() {
return "OpenGL Renderer";
}
void OpenGLGfxDriver::setupScreen(int screenW, int screenH, bool fullscreen) {
g_system->setupScreen(screenW, screenH, fullscreen, true);
_screenWidth = screenW;
_screenHeight = screenH;
_screenBPP = 24;
/*
_isFullscreen = g_system->getFeatureState(OSystem::kFeatureFullscreenMode);
char GLDriver[1024];
sprintf(GLDriver, "Residual: %s/%s", glGetString(GL_VENDOR), glGetString(GL_RENDERER));
g_system->setWindowCaption(GLDriver);
_storedDisplay = new byte[_screenWidth * _screenHeight * 4];
memset(_storedDisplay, 0, _screenWidth * _screenHeight * 4);
GLfloat ambientSource[] = { 0.6f, 0.6f, 0.6f, 1.0f };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientSource);
return NULL;
*/
}
const char *GfxOpenGL::getVideoDeviceName() {
return "OpenGL Renderer";
void OpenGLGfxDriver::clearScreen() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void GfxOpenGL::setupCamera(float fov, float nclip, float fclip, float roll) {
void OpenGLGfxDriver::flipBuffer() {
g_system->updateScreen();
}
void OpenGLGfxDriver::drawSurface(Graphics::Surface *surface) {
glPixelZoom(1.0f, -1.0f);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glRasterPos2f(-1.0f, 0.75f);
glDrawPixels(surface->w, surface->h, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels);
}
/*
void OpenGLGfxDriver::setupCamera(float fov, float nclip, float fclip, float roll) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
@ -84,7 +95,7 @@ void GfxOpenGL::setupCamera(float fov, float nclip, float fclip, float roll) {
glRotatef(roll, 0, 0, -1);
}
void GfxOpenGL::positionCamera(Graphics::Vector3d pos, Graphics::Vector3d interest) {
void OpenGLGfxDriver::positionCamera(Graphics::Vector3d pos, Graphics::Vector3d interest) {
Graphics::Vector3d up_vec(0, 0, 1);
if (pos.x() == interest.x() && pos.y() == interest.y())
@ -93,15 +104,7 @@ void GfxOpenGL::positionCamera(Graphics::Vector3d pos, Graphics::Vector3d intere
gluLookAt(pos.x(), pos.y(), pos.z(), interest.x(), interest.y(), interest.z(), up_vec.x(), up_vec.y(), up_vec.z());
}
void GfxOpenGL::clearScreen() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void GfxOpenGL::flipBuffer() {
g_system->updateScreen();
}
bool GfxOpenGL::isHardwareAccelerated() {
bool OpenGLGfxDriver::isHardwareAccelerated() {
return true;
}
@ -154,13 +157,13 @@ static void glShadowProjection(Graphics::Vector3d light, Graphics::Vector3d plan
glMultMatrixf((GLfloat *)mat);
}
void GfxOpenGL::set3DMode() {
void OpenGLGfxDriver::set3DMode() {
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
}
void GfxOpenGL::translateViewpointStart(Graphics::Vector3d pos, float pitch, float yaw, float roll) {
void OpenGLGfxDriver::translateViewpointStart(Graphics::Vector3d pos, float pitch, float yaw, float roll) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
@ -170,16 +173,10 @@ void GfxOpenGL::translateViewpointStart(Graphics::Vector3d pos, float pitch, flo
glRotatef(roll, 0, 1, 0);
}
void GfxOpenGL::translateViewpointFinish() {
void OpenGLGfxDriver::translateViewpointFinish() {
glPopMatrix();
}
void GfxOpenGL::drawSurface(Graphics::Surface* surface) {
glPixelZoom(1.0f, -1.0f);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glRasterPos2f(-1.0f, 0.75f);
glDrawPixels(surface->w, surface->h, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels);
}
*/
} // End of namespace Stark

View file

@ -26,38 +26,37 @@
#ifndef STARK_GFX_OPENGL_H
#define STARK_GFX_OPENGL_H
#include "engines/stark/gfx_base.h"
#ifdef USE_OPENGL
#include "engines/stark/gfx/driver.h"
namespace Stark {
class GfxOpenGL : public GfxBase {
class OpenGLGfxDriver : public GfxDriver {
public:
GfxOpenGL();
virtual ~GfxOpenGL();
byte *setupScreen(int screenW, int screenH, bool fullscreen);
OpenGLGfxDriver();
~OpenGLGfxDriver();
const char *getVideoDeviceName();
void setupCamera(float fov, float nclip, float fclip, float roll);
void positionCamera(Graphics::Vector3d pos, Graphics::Vector3d interest);
void setupScreen(int screenW, int screenH, bool fullscreen);
void clearScreen();
void flipBuffer();
void drawSurface(Graphics::Surface *surface);
/*
bool isHardwareAccelerated();
void set3DMode();
void setupCamera(float fov, float nclip, float fclip, float roll);
void positionCamera(Graphics::Vector3d pos, Graphics::Vector3d interest);
void translateViewpointStart(Graphics::Vector3d pos, float pitch, float yaw, float roll);
void translateViewpointFinish();
void drawSurface(Graphics::Surface *bmp);
private:
byte *_storedDisplay;
*/
};
} // End of namespace Stark

928
gfx/tinygl.cpp Normal file
View file

@ -0,0 +1,928 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This library 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
*
* $URL: https://residual.svn.sourceforge.net/svnroot/residual/residual/trunk/engines/grim/gfx_tinygl.cpp $
* $Id: gfx_tinygl.cpp 1499 2009-06-26 16:13:11Z aquadran $
*
*/
//#include "common/endian.h"
#include "common/system.h"
//#include "engines/stark/actor.h"
//#include "engines/stark/colormap.h"
//#include "engines/stark/material.h"
//#include "engines/stark/font.h"
#include "engines/stark/gfx/tinygl.h"
namespace Stark {
TinyGLGfxDriver::TinyGLGfxDriver() {
_zb = NULL;
//_storedDisplay = NULL;
}
TinyGLGfxDriver::~TinyGLGfxDriver() {
//delete[] _storedDisplay;
if (_zb) {
TinyGL::glClose();
ZB_close(_zb);
}
}
const char *TinyGLGfxDriver::getVideoDeviceName() {
return "TinyGL Software Renderer";
}
void TinyGLGfxDriver::setupScreen(int screenW, int screenH, bool fullscreen) {
byte *buffer = g_system->setupScreen(screenW, screenH, fullscreen, false);
_screenWidth = screenW;
_screenHeight = screenH;
_screenBPP = 15;
//_isFullscreen = g_system->getFeatureState(OSystem::kFeatureFullscreenMode);
//g_system->setWindowCaption("Residual: Software 3D Renderer");
_zb = TinyGL::ZB_open(screenW, screenH, ZB_MODE_5R6G5B, buffer);
TinyGL::glInit(_zb);
/*
//_storedDisplay = new byte[640 * 480 * 2];
//memset(_storedDisplay, 0, 640 * 480 * 2);
_currentShadowArray = NULL;
TGLfloat ambientSource[] = { 0.6f, 0.6f, 0.6f, 1.0f };
tglLightModelfv(TGL_LIGHT_MODEL_AMBIENT, ambientSource);
return buffer;
*/
}
void TinyGLGfxDriver::clearScreen() {
memset(_zb->pbuf, 0, 640 * 480 * 2);
memset(_zb->zbuf, 0, 640 * 480 * 2);
memset(_zb->zbuf2, 0, 640 * 480 * 4);
}
void TinyGLGfxDriver::flipBuffer() {
g_system->updateScreen();
}
void TinyGLGfxDriver::drawSurface(Graphics::Surface *surface) {
for (int i = 0; i < surface->w * surface->h; i++) {
byte *pixel = (byte *)surface->pixels + (i * 3);
byte r = pixel[0];
byte g = pixel[1];
byte b = pixel[2];
uint16 color = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
_zb->pbuf[i] = color;
}
//memcpy(_zb->pbuf, surface->pixels, numPixels);
}
#if 0
// below funcs lookAt, transformPoint and tgluProject are from Mesa glu sources
static void lookAt(TGLfloat eyex, TGLfloat eyey, TGLfloat eyez, TGLfloat centerx,
TGLfloat centery, TGLfloat centerz, TGLfloat upx, TGLfloat upy, TGLfloat upz) {
TGLfloat m[16];
TGLfloat x[3], y[3], z[3];
TGLfloat mag;
z[0] = eyex - centerx;
z[1] = eyey - centery;
z[2] = eyez - centerz;
mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
if (mag) {
z[0] /= mag;
z[1] /= mag;
z[2] /= mag;
}
y[0] = upx;
y[1] = upy;
y[2] = upz;
x[0] = y[1] * z[2] - y[2] * z[1];
x[1] = -y[0] * z[2] + y[2] * z[0];
x[2] = y[0] * z[1] - y[1] * z[0];
y[0] = z[1] * x[2] - z[2] * x[1];
y[1] = -z[0] * x[2] + z[2] * x[0];
y[2] = z[0] * x[1] - z[1] * x[0];
mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
if (mag) {
x[0] /= mag;
x[1] /= mag;
x[2] /= mag;
}
mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
if (mag) {
y[0] /= mag;
y[1] /= mag;
y[2] /= mag;
}
#define M(row,col) m[col * 4 + row]
M(0, 0) = x[0];
M(0, 1) = x[1];
M(0, 2) = x[2];
M(0, 3) = 0.0;
M(1, 0) = y[0];
M(1, 1) = y[1];
M(1, 2) = y[2];
M(1, 3) = 0.0;
M(2, 0) = z[0];
M(2, 1) = z[1];
M(2, 2) = z[2];
M(2, 3) = 0.0;
M(3, 0) = 0.0;
M(3, 1) = 0.0;
M(3, 2) = 0.0;
M(3, 3) = 1.0;
#undef M
tglMultMatrixf(m);
tglTranslatef(-eyex, -eyey, -eyez);
}
static void transformPoint(TGLfloat out[4], const TGLfloat m[16], const TGLfloat in[4]) {
#define M(row,col) m[col * 4 + row]
out[0] = M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
out[1] = M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
out[2] = M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
out[3] = M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
#undef M
}
TGLint tgluProject(TGLfloat objx, TGLfloat objy, TGLfloat objz, const TGLfloat model[16], const TGLfloat proj[16],
const TGLint viewport[4], TGLfloat *winx, TGLfloat *winy, TGLfloat *winz) {
TGLfloat in[4], out[4];
in[0] = objx;
in[1] = objy;
in[2] = objz;
in[3] = 1.0;
transformPoint(out, model, in);
transformPoint(in, proj, out);
if (in[3] == 0.0)
return TGL_FALSE;
in[0] /= in[3];
in[1] /= in[3];
in[2] /= in[3];
*winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
*winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
*winz = (1 + in[2]) / 2;
return TGL_TRUE;
}
void TinyGLGfxDriver::setupCamera(float fov, float nclip, float fclip, float roll) {
tglMatrixMode(TGL_PROJECTION);
tglLoadIdentity();
float right = nclip * tan(fov / 2 * (LOCAL_PI / 180));
tglFrustum(-right, right, -right * 0.75, right * 0.75, nclip, fclip);
tglMatrixMode(TGL_MODELVIEW);
tglLoadIdentity();
tglRotatef(roll, 0, 0, -1);
}
void TinyGLGfxDriver::positionCamera(Graphics::Vector3d pos, Graphics::Vector3d interest) {
Graphics::Vector3d up_vec(0, 0, 1);
if (pos.x() == interest.x() && pos.y() == interest.y())
up_vec = Graphics::Vector3d(0, 1, 0);
lookAt(pos.x(), pos.y(), pos.z(), interest.x(), interest.y(), interest.z(), up_vec.x(), up_vec.y(), up_vec.z());
}
bool TinyGLGfxDriver::isHardwareAccelerated() {
return false;
}
static void tglShadowProjection(Graphics::Vector3d light, Graphics::Vector3d plane, Graphics::Vector3d normal, bool dontNegate) {
// Based on GPL shadow projection example by
// (c) 2002-2003 Phaetos <phaetos@gaffga.de>
float d, c;
float mat[16];
float nx, ny, nz, lx, ly, lz, px, py, pz;
// for some unknown for me reason normal need negation
nx = -normal.x();
ny = -normal.y();
nz = -normal.z();
if (dontNegate) {
nx = -nx;
ny = -ny;
nz = -nz;
}
lx = light.x();
ly = light.y();
lz = light.z();
px = plane.x();
py = plane.y();
pz = plane.z();
d = nx * lx + ny * ly + nz * lz;
c = px * nx + py * ny + pz * nz - d;
mat[0] = lx * nx + c;
mat[4] = ny * lx;
mat[8] = nz * lx;
mat[12] = -lx * c - lx * d;
mat[1] = nx * ly;
mat[5] = ly * ny + c;
mat[9] = nz * ly;
mat[13] = -ly * c - ly * d;
mat[2] = nx * lz;
mat[6] = ny * lz;
mat[10] = lz * nz + c;
mat[14] = -lz * c - lz * d;
mat[3] = nx;
mat[7] = ny;
mat[11] = nz;
mat[15] = -d;
tglMultMatrixf(mat);
}
void TinyGLGfxDriver::getBoundingBoxPos(const Model::Mesh *model, int *x1, int *y1, int *x2, int *y2) {
if (_currentShadowArray) {
*x1 = -1;
*y1 = -1;
*x2 = -1;
*y2 = -1;
return;
}
TGLfloat top = 1000;
TGLfloat right = -1000;
TGLfloat left = 1000;
TGLfloat bottom = -1000;
TGLfloat winX, winY, winZ;
for (int i = 0; i < model->_numFaces; i++) {
Graphics::Vector3d v;
float* pVertices;
for (int j = 0; j < model->_faces[i]._numVertices; j++) {
TGLfloat modelView[16], projection[16];
TGLint viewPort[4];
tglGetFloatv(TGL_MODELVIEW_MATRIX, modelView);
tglGetFloatv(TGL_PROJECTION_MATRIX, projection);
tglGetIntegerv(TGL_VIEWPORT, viewPort);
pVertices = model->_vertices + 3 * model->_faces[i]._vertices[j];
v.set(*(pVertices), *(pVertices + 1), *(pVertices + 2));
tgluProject(v.x(), v.y(), v.z(), modelView, projection, viewPort, &winX, &winY, &winZ);
if (winX > right)
right = winX;
if (winX < left)
left = winX;
if (winY < top)
top = winY;
if (winY > bottom)
bottom = winY;
}
}
float t = bottom;
bottom = 480 - top;
top = 480 - t;
if (left < 0)
left = 0;
if (right > 639)
right = 639;
if (top < 0)
top = 0;
if (bottom > 479)
bottom = 479;
if (top > 479 || left > 639 || bottom < 0 || right < 0) {
*x1 = -1;
*y1 = -1;
*x2 = -1;
*y2 = -1;
return;
}
*x1 = (int)left;
*y1 = (int)top;
*x2 = (int)right;
*y2 = (int)bottom;
/*
uint16 *dst = (uint16 *)_zb->pbuf;
uint16 c = 0xffff;
for (int x = left; x <= right; x++) {
WRITE_LE_UINT16(dst + 640 * (int)top + x, c);
}
for (int x = left; x <= right; x++) {
WRITE_LE_UINT16(dst + 640 * (int)bottom + x, c);
}
for (int y = top; y <= bottom; y++) {
WRITE_LE_UINT16(dst + 640 * y + (int)left, c);
}
for (int y = top; y <= bottom; y++) {
WRITE_LE_UINT16(dst + 640 * y + (int)right, c);
}*/
}
void TinyGLGfxDriver::startActorDraw(Graphics::Vector3d pos, float yaw, float pitch, float roll) {
tglEnable(TGL_TEXTURE_2D);
tglMatrixMode(TGL_MODELVIEW);
tglPushMatrix();
if (_currentShadowArray) {
// TODO find out why shadowMask at device in woods is null
if (!_currentShadowArray->shadowMask) {
_currentShadowArray->shadowMask = new byte[_screenWidth * _screenHeight];
}
assert(_currentShadowArray->shadowMask);
//tglSetShadowColor(255, 255, 255);
tglSetShadowColor(_shadowColorR, _shadowColorG, _shadowColorB);
tglSetShadowMaskBuf(_currentShadowArray->shadowMask);
SectorListType::iterator i = _currentShadowArray->planeList.begin();
Sector *shadowSector = *i;
tglShadowProjection(_currentShadowArray->pos, shadowSector->getVertices()[0], shadowSector->getNormal(), _currentShadowArray->dontNegate);
}
tglTranslatef(pos.x(), pos.y(), pos.z());
tglRotatef(yaw, 0, 0, 1);
tglRotatef(pitch, 1, 0, 0);
tglRotatef(roll, 0, 1, 0);
}
void TinyGLGfxDriver::finishActorDraw() {
tglMatrixMode(TGL_MODELVIEW);
tglPopMatrix();
tglDisable(TGL_TEXTURE_2D);
if (_currentShadowArray) {
tglSetShadowMaskBuf(NULL);
}/* else {
uint16 *dst = (uint16 *)_zb->pbuf;
uint16 c = 0xffff;
for (int x = g_winX1; x <= g_winX2; x++) {
WRITE_LE_UINT16(dst + 640 * g_winY1 + x, c);
}
for (int x = g_winX1; x <= g_winX2; x++) {
WRITE_LE_UINT16(dst + 640 * g_winY2 + x, c);
}
for (int y = g_winY1; y <= g_winY2; y++) {
WRITE_LE_UINT16(dst + 640 * y + g_winX1, c);
}
for (int y = g_winY1; y <= g_winY2; y++) {
WRITE_LE_UINT16(dst + 640 * y + g_winX2, c);
}
}*/
}
void TinyGLGfxDriver::drawShadowPlanes() {
tglEnable(TGL_SHADOW_MASK_MODE);
if (!_currentShadowArray->shadowMask) {
_currentShadowArray->shadowMask = new byte[_screenWidth * _screenHeight];
}
memset(_currentShadowArray->shadowMask, 0, _screenWidth * _screenHeight);
tglSetShadowMaskBuf(_currentShadowArray->shadowMask);
_currentShadowArray->planeList.begin();
for (SectorListType::iterator i = _currentShadowArray->planeList.begin(); i != _currentShadowArray->planeList.end(); i++) {
Sector *shadowSector = *i;
tglBegin(TGL_POLYGON);
for (int k = 0; k < shadowSector->getNumVertices(); k++) {
tglVertex3f(shadowSector->getVertices()[k].x(), shadowSector->getVertices()[k].y(), shadowSector->getVertices()[k].z());
}
tglEnd();
}
tglSetShadowMaskBuf(NULL);
tglDisable(TGL_SHADOW_MASK_MODE);
}
void TinyGLGfxDriver::setShadowMode() {
tglEnable(TGL_SHADOW_MODE);
}
void TinyGLGfxDriver::clearShadowMode() {
tglDisable(TGL_SHADOW_MODE);
}
void TinyGLGfxDriver::set3DMode() {
tglMatrixMode(TGL_MODELVIEW);
tglEnable(TGL_DEPTH_TEST);
}
void TinyGLGfxDriver::setShadow(Shadow *shadow) {
_currentShadowArray = shadow;
if (shadow)
tglDisable(TGL_LIGHTING);
else
tglEnable(TGL_LIGHTING);
}
void TinyGLGfxDriver::setShadowColor(byte r, byte g, byte b) {
_shadowColorR = r;
_shadowColorG = g;
_shadowColorB = b;
}
void TinyGLGfxDriver::drawModelFace(const Model::Face *face, float *vertices, float *vertNormals, float *textureVerts) {
tglNormal3fv((float *)face->_normal._coords);
tglBegin(TGL_POLYGON);
for (int i = 0; i < face->_numVertices; i++) {
tglNormal3fv(vertNormals + 3 * face->_vertices[i]);
if (face->_texVertices)
tglTexCoord2fv(textureVerts + 2 * face->_texVertices[i]);
tglVertex3fv(vertices + 3 * face->_vertices[i]);
}
tglEnd();
}
void TinyGLGfxDriver::translateViewpointStart(Graphics::Vector3d pos, float pitch, float yaw, float roll) {
tglPushMatrix();
tglTranslatef(pos.x(), pos.y(), pos.z());
tglRotatef(yaw, 0, 0, 1);
tglRotatef(pitch, 1, 0, 0);
tglRotatef(roll, 0, 1, 0);
}
void TinyGLGfxDriver::translateViewpointFinish() {
tglPopMatrix();
}
void TinyGLGfxDriver::drawHierachyNode(const Model::HierNode *node) {
translateViewpointStart(node->_animPos / node->_totalWeight, node->_animPitch / node->_totalWeight, node->_animYaw / node->_totalWeight, node->_animRoll / node->_totalWeight);
if (node->_hierVisible) {
if (node->_mesh && node->_meshVisible) {
tglPushMatrix();
tglTranslatef(node->_pivot.x(), node->_pivot.y(), node->_pivot.z());
node->_mesh->draw();
tglMatrixMode(TGL_MODELVIEW);
tglPopMatrix();
}
if (node->_child) {
node->_child->draw();
tglMatrixMode(TGL_MODELVIEW);
}
}
translateViewpointFinish();
if (node->_sibling)
node->_sibling->draw();
}
void TinyGLGfxDriver::disableLights() {
tglDisable(TGL_LIGHTING);
}
void TinyGLGfxDriver::setupLight(Scene::Light *light, int lightId) {
assert(lightId < T_MAX_LIGHTS);
tglEnable(TGL_LIGHTING);
float lightColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
float lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
float lightDir[] = { 0.0f, 0.0f, 0.0f };
float intensity = light->_intensity / 1.3f;
lightColor[0] = ((float)light->_color.red() / 15.0f) * intensity;
lightColor[1] = ((float)light->_color.blue() / 15.0f) * intensity;
lightColor[2] = ((float)light->_color.green() / 15.0f) * intensity;
if (strcmp(light->_type.c_str(), "omni") == 0) {
lightPos[0] = light->_pos.x();
lightPos[1] = light->_pos.y();
lightPos[2] = light->_pos.z();
tglDisable(TGL_LIGHT0 + lightId);
tglLightfv(TGL_LIGHT0 + lightId, TGL_DIFFUSE, lightColor);
tglLightfv(TGL_LIGHT0 + lightId, TGL_POSITION, lightPos);
tglEnable(TGL_LIGHT0 + lightId);
} else if (strcmp(light->_type.c_str(), "direct") == 0) {
tglDisable(TGL_LIGHT0 + lightId);
lightDir[0] = -light->_dir.x();
lightDir[1] = -light->_dir.y();
lightDir[2] = -light->_dir.z();
tglLightfv(TGL_LIGHT0 + lightId, TGL_DIFFUSE, lightColor);
tglLightfv(TGL_LIGHT0 + lightId, TGL_POSITION, lightDir);
tglEnable(TGL_LIGHT0 + lightId);
} else if (strcmp(light->_type.c_str(), "spot") == 0) {
tglDisable(TGL_LIGHT0 + lightId);
lightPos[0] = light->_pos.x();
lightPos[1] = light->_pos.y();
lightPos[2] = light->_pos.z();
lightDir[0] = light->_dir.x();
lightDir[1] = light->_dir.y();
lightDir[2] = light->_dir.z();
tglLightfv(TGL_LIGHT0 + lightId, TGL_DIFFUSE, lightColor);
tglLightfv(TGL_LIGHT0 + lightId, TGL_POSITION, lightPos);
tglLightfv(TGL_LIGHT0 + lightId, TGL_SPOT_DIRECTION, lightDir);
tglLightf(TGL_LIGHT0 + lightId, TGL_SPOT_CUTOFF, 90);
tglEnable(TGL_LIGHT0 + lightId);
} else {
error("Scene::setupLights() Unknown type of light: %s", light->_type.c_str());
}
}
void TinyGLGfxDriver::createBitmap(Bitmap *bitmap) {
if (bitmap->_format != 1) {
for (int pic = 0; pic < bitmap->_numImages; pic++) {
uint16 *bufPtr = reinterpret_cast<uint16 *>(bitmap->_data[pic]);
for (int i = 0; i < (bitmap->_width * bitmap->_height); i++) {
uint16 val = READ_LE_UINT16(bitmap->_data[pic] + 2 * i);
bufPtr[i] = ((uint32) val) * 0x10000 / 100 / (0x10000 - val);
}
}
}
}
void TinyGLBlit(byte *dst, byte *src, int x, int y, int width, int height, bool trans) {
int srcPitch = width * 2;
int dstPitch = 640 * 2;
int srcX, srcY;
int l, r;
if (x > 639 || y > 479)
return;
if (x < 0) {
x = 0;
srcX = -x;
} else {
srcX = 0;
}
if (y < 0) {
y = 0;
srcY = -y;
} else {
srcY = 0;
}
if (x + width > 640)
width -= (x + width) - 640;
if (y + height > 480)
height -= (y + height) - 480;
dst += (x + (y * 640)) * 2;
src += (srcX + (srcY * width)) * 2;
int copyWidth = width * 2;
if (!trans) {
for (l = 0; l < height; l++) {
memcpy(dst, src, copyWidth);
dst += dstPitch;
src += srcPitch;
}
} else {
for (l = 0; l < height; l++) {
for (r = 0; r < copyWidth; r += 2) {
uint16 pixel = READ_LE_UINT16(src + r);
if (pixel != 0xf81f)
WRITE_LE_UINT16(dst + r, pixel);
}
dst += dstPitch;
src += srcPitch;
}
}
}
void TinyGLGfxDriver::drawBitmap(const Bitmap *bitmap) {
assert(bitmap->_currImage > 0);
if (bitmap->_format == 1)
TinyGLBlit((byte *)_zb->pbuf, (byte *)bitmap->_data[bitmap->_currImage - 1],
bitmap->x(), bitmap->y(), bitmap->width(), bitmap->height(), true);
else
TinyGLBlit((byte *)_zb->zbuf, (byte *)bitmap->_data[bitmap->_currImage - 1],
bitmap->x(), bitmap->y(), bitmap->width(), bitmap->height(), false);
}
void TinyGLGfxDriver::destroyBitmap(Bitmap *) { }
void TinyGLGfxDriver::drawDepthBitmap(int, int, int, int, char *) { }
void TinyGLGfxDriver::createMaterial(Material *material, const char *data, const CMap *cmap) {
material->_textures = new TGLuint[material->_numImages];
tglGenTextures(material->_numImages, (TGLuint *)material->_textures);
char *texdata = new char[material->_width * material->_height * 4];
for (int i = 0; i < material->_numImages; i++) {
char *texdatapos = texdata;
for (int y = 0; y < material->_height; y++) {
for (int x = 0; x < material->_width; x++) {
int col = *(uint8 *)(data);
if (col == 0)
memset(texdatapos, 0, 4); // transparent
else {
memcpy(texdatapos, cmap->_colors + 3 * (*(uint8 *)(data)), 3);
texdatapos[3] = '\xff'; // fully opaque
}
texdatapos += 4;
data++;
}
}
TGLuint *textures = (TGLuint *)material->_textures;
tglBindTexture(TGL_TEXTURE_2D, textures[i]);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_S, TGL_REPEAT);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_WRAP_T, TGL_REPEAT);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MAG_FILTER, TGL_LINEAR);
tglTexParameteri(TGL_TEXTURE_2D, TGL_TEXTURE_MIN_FILTER, TGL_LINEAR);
tglTexImage2D(TGL_TEXTURE_2D, 0, 3, material->_width, material->_height, 0, TGL_RGBA, TGL_UNSIGNED_BYTE, texdata);
data += 24;
}
delete[] texdata;
}
void TinyGLGfxDriver::selectMaterial(const Material *material) {
TGLuint *textures = (TGLuint *)material->_textures;
tglBindTexture(TGL_TEXTURE_2D, textures[material->_currImage]);
tglPushMatrix();
tglMatrixMode(TGL_TEXTURE);
tglLoadIdentity();
tglScalef(1.0f / material->_width, 1.0f / material->_height, 1);
tglMatrixMode(TGL_MODELVIEW);
tglPopMatrix();
}
void TinyGLGfxDriver::destroyMaterial(Material *material) {
tglDeleteTextures(material->_numImages, (TGLuint *)material->_textures);
delete[] (TGLuint *)material->_textures;
}
void TinyGLGfxDriver::prepareSmushFrame(int width, int height, byte *bitmap) {
_smushWidth = width;
_smushHeight = height;
_smushBitmap = bitmap;
}
void TinyGLGfxDriver::drawSmushFrame(int offsetX, int offsetY) {
if (_smushWidth == 640 && _smushHeight == 480) {
memcpy(_zb->pbuf, _smushBitmap, 640 * 480 * 2);
} else {
TinyGLBlit((byte *)_zb->pbuf, _smushBitmap, offsetX, offsetY, _smushWidth, _smushHeight, false);
}
}
void TinyGLGfxDriver::releaseSmushFrame() {
}
void TinyGLGfxDriver::loadEmergFont() {
}
void TinyGLGfxDriver::drawEmergString(int x, int y, const char *text, const Color &fgColor) {
uint16 color = ((fgColor.red() & 0xF8) << 8) | ((fgColor.green() & 0xFC) << 3) | (fgColor.blue() >> 3);
for (int l = 0; l < (int)strlen(text); l++) {
int c = text[l];
assert(c >= 32 && c <= 127);
const uint8 *ptr = Font::emerFont[c - 32];
for (int py = 0; py < 13; py++) {
if ((py + y) < 480 && (py + y) >= 0) {
int line = ptr[12 - py];
for (int px = 0; px < 8; px++) {
if ((px + x) < 640 && (px + x) >= 0) {
int pixel = line & 0x80;
line <<= 1;
if (pixel)
WRITE_LE_UINT16(_zb->pbuf + ((py + y) * 640) + (px + x), color);
}
}
}
}
x += 10;
}
}
GfxBase::TextObjectHandle *TinyGLGfxDriver::createTextBitmap(uint8 *data, int width, int height, const Color &fgColor) {
TextObjectHandle *handle = new TextObjectHandle;
handle->width = width;
handle->height = height;
handle->numTex = 0;
handle->texIds = NULL;
// Convert data to 16-bit RGB 565 format
uint16 *texData = new uint16[width * height];
uint16 *texDataPtr = texData;
handle->bitmapData = texData;
uint8 *bitmapData = data;
uint8 r = fgColor.red();
uint8 g = fgColor.green();
uint8 b = fgColor.blue();
uint16 color = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
if (color == 0xf81f)
color = 0xf81e;
for (int i = 0; i < width * height; i++, texDataPtr++, bitmapData++) {
byte pixel = *bitmapData;
if (pixel == 0x00) {
WRITE_LE_UINT16(texDataPtr, 0xf81f);
} else if (pixel == 0x80) {
*texDataPtr = 0;
} else if (pixel == 0xFF) {
WRITE_LE_UINT16(texDataPtr, color);
}
}
return handle;
}
void TinyGLGfxDriver::drawTextBitmap(int x, int y, TextObjectHandle *handle) {
TinyGLBlit((byte *)_zb->pbuf, (byte *)handle->bitmapData, x, y, handle->width, handle->height, true);
}
void TinyGLGfxDriver::destroyTextBitmap(TextObjectHandle *handle) {
delete[] handle->bitmapData;
}
Bitmap *TinyGLGfxDriver::getScreenshot(int w, int h) {
uint16 *buffer = new uint16[w * h];
//uint16 *src = (uint16 *)_storedDisplay;
assert(buffer);
int step = 0;
for (int y = 0; y <= 479; y++) {
for (int x = 0; x <= 639; x++) {
uint16 pixel = *(src + y * 640 + x);
uint8 r = (pixel & 0xF800) >> 8;
uint8 g = (pixel & 0x07E0) >> 3;
uint8 b = (pixel & 0x001F) << 3;
uint32 color = (r + g + b) / 3;
src[step++] = ((color & 0xF8) << 8) | ((color & 0xFC) << 3) | (color >> 3);
}
}
float step_x = 640.0 / w;
float step_y = 480.0 / h;
step = 0;
for (float y = 0; y < 479; y += step_y) {
for (float x = 0; x < 639; x += step_x) {
uint16 pixel = *(src + (int)y * 640 + (int)x);
buffer[step++] = pixel;
}
}
Bitmap *screenshot = g_grim->registerBitmap((char *)buffer, w, h, "screenshot");
delete[] buffer;
return screenshot;
}
void TinyGLGfxDriver::storeDisplay() {
//memcpy(_storedDisplay, _zb->pbuf, 640 * 480 * 2);
}
void TinyGLGfxDriver::copyStoredToDisplay() {
//memcpy(_zb->pbuf, _storedDisplay, 640 * 480 * 2);
}
void TinyGLGfxDriver::dimScreen() {
//uint16 *data = (uint16 *)_storedDisplay;
for (int l = 0; l < 640 * 480; l++) {
uint16 pixel = data[l];
uint8 r = (pixel & 0xF800) >> 8;
uint8 g = (pixel & 0x07E0) >> 3;
uint8 b = (pixel & 0x001F) << 3;
uint32 color = (r + g + b) / 10;
data[l] = ((color & 0xF8) << 8) | ((color & 0xFC) << 3) | (color >> 3);
}
}
void TinyGLGfxDriver::dimRegion(int x, int y, int w, int h, float level) {
uint16 *data = (uint16 *)_zb->pbuf;
for (int ly = y; ly < y + h; ly++) {
for (int lx = x; lx < x + w; lx++) {
uint16 pixel = data[ly * 640 + lx];
uint8 r = (pixel & 0xF800) >> 8;
uint8 g = (pixel & 0x07E0) >> 3;
uint8 b = (pixel & 0x001F) << 3;
uint16 color = (uint16)(((r + g + b) / 3) * level);
data[ly * 640 + lx] = ((color & 0xF8) << 8) | ((color & 0xFC) << 3) | (color >> 3);
}
}
}
void TinyGLGfxDriver::drawRectangle(PrimitiveObject *primitive) {
uint16 *dst = (uint16 *)_zb->pbuf;
int x1 = primitive->getP1().x;
int y1 = primitive->getP1().y;
int x2 = primitive->getP2().x;
int y2 = primitive->getP2().y;
Color color = primitive->getColor();
uint16 c = ((color.red() & 0xF8) << 8) | ((color.green() & 0xFC) << 3) | (color.blue() >> 3);
if (primitive->isFilled()) {
for (; y1 <= y2; y1++)
if (y1 >= 0 && y1 < 480)
for (int x = x1; x <= x2; x++)
if (x >= 0 && x < 640)
WRITE_LE_UINT16(dst + 640 * y1 + x, c);
} else {
if (y1 >= 0 && y1 < 480)
for (int x = x1; x <= x2; x++)
if (x >= 0 && x < 640)
WRITE_LE_UINT16(dst + 640 * y1 + x, c);
if (y2 >= 0 && y2 < 480)
for (int x = x1; x <= x2; x++)
if (x >= 0 && x < 640)
WRITE_LE_UINT16(dst + 640 * y2 + x, c);
if (x1 >= 0 && x1 < 640)
for (int y = y1; y <= y2; y++)
if (y >= 0 && y < 480)
WRITE_LE_UINT16(dst + 640 * y + x1, c);
if (x2 >= 0 && x2 < 640)
for (int y = y1; y <= y2; y++)
if (y >= 0 && y < 480)
WRITE_LE_UINT16(dst + 640 * y + x2, c);
}
}
void TinyGLGfxDriver::drawLine(PrimitiveObject *primitive) {
uint16 *dst = (uint16 *)_zb->pbuf;
int x1 = primitive->getP1().x;
int y1 = primitive->getP1().y;
int x2 = primitive->getP2().x;
int y2 = primitive->getP2().y;
float m = (y2 - y1) / (x2 - x1);
int b = (int)(-m * x1 + y1);
Color color = primitive->getColor();
uint16 c = ((color.red() & 0xF8) << 8) | ((color.green() & 0xFC) << 3) | (color.blue() >> 3);
for (int x = x1; x <= x2; x++) {
int y = (int)(m * x) + b;
if (x >= 0 && x < 640 && y >= 0 && y < 480)
WRITE_LE_UINT16(dst + 640 * y + x, c);
}
}
void TinyGLGfxDriver::drawPolygon(PrimitiveObject *primitive) {
uint16 *dst = (uint16 *)_zb->pbuf;
int x1 = primitive->getP1().x;
int y1 = primitive->getP1().y;
int x2 = primitive->getP2().x;
int y2 = primitive->getP2().y;
int x3 = primitive->getP3().x;
int y3 = primitive->getP3().y;
int x4 = primitive->getP4().x;
int y4 = primitive->getP4().y;
float m;
int b;
Color color = primitive->getColor();
uint16 c = ((color.red() & 0xF8) << 8) | ((color.green() & 0xFC) << 3) | (color.blue() >> 3);
m = (y2 - y1) / (x2 - x1);
b = (int)(-m * x1 + y1);
for (int x = x1; x <= x2; x++) {
int y = (int)(m * x) + b;
if (x >= 0 && x < 640 && y >= 0 && y < 480)
WRITE_LE_UINT16(dst + 640 * y + x, c);
}
m = (y4 - y3) / (x4 - x3);
b = (int)(-m * x3 + y3);
for (int x = x3; x <= x4; x++) {
int y = (int)(m * x) + b;
if (x >= 0 && x < 640 && y >= 0 && y < 480)
WRITE_LE_UINT16(dst + 640 * y + x, c);
}
}
#endif
} // End of namespace Stark

119
gfx/tinygl.h Normal file
View file

@ -0,0 +1,119 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This library 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
*
* $URL: https://residual.svn.sourceforge.net/svnroot/residual/residual/trunk/engines/grim/gfx_tinygl.h $
* $Id: gfx_tinygl.h 1452 2009-06-08 10:27:20Z aquadran $
*
*/
#ifndef STARK_GFX_TINYGL_H
#define STARK_GFX_TINYGL_H
#include "engines/stark/gfx/driver.h"
#include "graphics/tinygl/zgl.h"
namespace Stark {
class TinyGLGfxDriver : public GfxDriver {
public:
TinyGLGfxDriver();
~TinyGLGfxDriver();
const char *getVideoDeviceName();
void setupScreen(int screenW, int screenH, bool fullscreen);
void clearScreen();
void flipBuffer();
void drawSurface(Graphics::Surface *surface);
/*
bool isHardwareAccelerated();
void set3DMode();
void setupCamera(float fov, float nclip, float fclip, float roll);
void positionCamera(Graphics::Vector3d pos, Graphics::Vector3d interest);
void translateViewpointStart(Graphics::Vector3d pos, float pitch, float yaw, float roll);
void translateViewpointFinish();
void getBoundingBoxPos(const Model::Mesh *model, int *x1, int *y1, int *x2, int *y2);
void startActorDraw(Graphics::Vector3d pos, float yaw, float pitch, float roll);
void finishActorDraw();
void setShadow(Shadow *shadow);
void drawShadowPlanes();
void setShadowMode();
void clearShadowMode();
void setShadowColor(byte r, byte g, byte b);
void drawHierachyNode(const Model::HierNode *node);
void drawModelFace(const Model::Face *face, float *vertices, float *vertNormals, float *textureVerts);
void disableLights();
void setupLight(Scene::Light *light, int lightId);
void createMaterial(Material *material, const char *data, const CMap *cmap);
void selectMaterial(const Material *material);
void destroyMaterial(Material *material);
void createBitmap(Bitmap *bitmap);
void drawBitmap(const Bitmap *bitmap);
void destroyBitmap(Bitmap *bitmap);
void drawDepthBitmap(int x, int y, int w, int h, char *data);
void drawBitmap();
void dimScreen();
void dimRegion(int x, int y, int w, int h, float level);
Bitmap *getScreenshot(int w, int h);
void storeDisplay();
void copyStoredToDisplay();
void drawEmergString(int x, int y, const char *text, const Color &fgColor);
void loadEmergFont();
TextObjectHandle *createTextBitmap(uint8 *bitmap, int width, int height, const Color &fgColor);
void drawTextBitmap(int x, int y, TextObjectHandle *handle);
void destroyTextBitmap(TextObjectHandle *handle);
void drawRectangle(PrimitiveObject *primitive);
void drawLine(PrimitiveObject *primitive);
void drawPolygon(PrimitiveObject *primitive);
void prepareSmushFrame(int width, int height, byte *bitmap);
void drawSmushFrame(int offsetX, int offsetY);
void releaseSmushFrame();
*/
private:
TinyGL::ZBuffer *_zb;
byte *_screen;
byte *_smushBitmap;
int _smushWidth;
int _smushHeight;
byte *_storedDisplay;
};
} // End of namespace Stark
#endif // STARK_GFX_TINYGL_H

View file

@ -4,7 +4,9 @@ MODULE_OBJS := \
adpcm.o \
archive.o \
detection.o \
gfx_opengl.o \
gfx/driver.o \
gfx/opengl.o \
gfx/tinygl.o \
sound.o \
stark.o \
xmg.o \

View file

@ -24,7 +24,6 @@
*/
#include "engines/stark/stark.h"
#include "engines/stark/gfx_opengl.h"
#include "engines/stark/xmg.h"
#include "common/config-manager.h"
@ -33,9 +32,7 @@
namespace Stark {
GfxBase *g_driver = NULL;
StarkEngine::StarkEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
StarkEngine::StarkEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _gfx(NULL) {
_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, 127);
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
@ -47,24 +44,10 @@ StarkEngine::~StarkEngine() {
}
Common::Error StarkEngine::run() {
bool fullscreen = false;//(tolower(g_registry->get("fullscreen", "FALSE")[0]) == 't');
//#ifdef USE_OPENGL
//else
//#else
//else
// error("gfx backend doesn't support hardware rendering");
//#endif
if (g_system->hasFeature(OSystem::kFeatureOpenGL))
g_driver = new GfxOpenGL();
else
error("Only OpenGL hardware rendering at the moment");
_gfx = GfxDriver::create();
// Get the screen prepared
g_driver->setupScreen(640, 480, fullscreen);
g_driver->clearScreen();
_gfx->setupScreen(640, 480, ConfMan.getBool("fullscreen"));
// Start running
mainLoop();
@ -97,13 +80,12 @@ void StarkEngine::mainLoop() {
}
updateDisplayScene();
doFlip();
g_system->delayMillis(50);
}
}
void StarkEngine::updateDisplayScene() {
g_driver->clearScreen();
_gfx->clearScreen();
// Draw bg
@ -114,7 +96,7 @@ void StarkEngine::updateDisplayScene() {
Common::SeekableReadStream *dat = _f.readStream(_f.size());
Graphics::Surface *surf;
surf = xmg->decodeImage(dat);
g_driver->drawSurface(surf);
_gfx->drawSurface(surf);
delete xmg;
delete surf;
delete dat;
@ -123,7 +105,7 @@ void StarkEngine::updateDisplayScene() {
// setup cam
g_driver->set3DMode();
//_gfx->set3DMode();
// setup lights
@ -131,10 +113,8 @@ void StarkEngine::updateDisplayScene() {
// draw overlay
}
void StarkEngine::doFlip() {
g_driver->flipBuffer();
// Swap buffers
_gfx->flipBuffer();
}
} // End of namespace Stark

View file

@ -30,6 +30,7 @@
#include "engines/engine.h"
#include "engines/stark/archive.h"
#include "engines/stark/gfx/driver.h"
namespace Stark {
@ -54,10 +55,10 @@ protected:
virtual Common::Error run();
private:
void updateDisplayScene();
void doFlip();
void mainLoop();
void updateDisplayScene();
GfxDriver *_gfx;
const ADGameDescription *_gameDescription;