Initial commit
This commit is contained in:
93
engines/zvision/graphics/cursors/cursor.cpp
Normal file
93
engines/zvision/graphics/cursors/cursor.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/file.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
#include "zvision/graphics/cursors/cursor.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
ZorkCursor::ZorkCursor()
|
||||
: _width(0),
|
||||
_height(0),
|
||||
_hotspotX(0),
|
||||
_hotspotY(0) {
|
||||
}
|
||||
|
||||
ZorkCursor::ZorkCursor(ZVision *engine, const Common::Path &fileName)
|
||||
: _width(0),
|
||||
_height(0),
|
||||
_hotspotX(0),
|
||||
_hotspotY(0) {
|
||||
Common::File file;
|
||||
if (!file.open(fileName))
|
||||
error("Cursor file %s does not exist", fileName.toString().c_str());
|
||||
|
||||
uint32 magic = file.readUint32BE();
|
||||
if (magic != MKTAG('Z', 'C', 'R', '1')) {
|
||||
warning("%s is not a Zork Cursor file", fileName.toString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
_hotspotX = file.readUint16LE();
|
||||
_hotspotY = file.readUint16LE();
|
||||
_width = file.readUint16LE();
|
||||
_height = file.readUint16LE();
|
||||
|
||||
uint dataSize = _width * _height * sizeof(uint16);
|
||||
_surface.create(_width, _height, engine->_resourcePixelFormat);
|
||||
uint32 bytesRead = file.read(_surface.getPixels(), dataSize);
|
||||
assert(bytesRead == dataSize);
|
||||
|
||||
#ifndef SCUMM_LITTLE_ENDIAN
|
||||
int16 *buffer = (int16 *)_surface.getPixels();
|
||||
for (uint32 i = 0; i < dataSize / 2; ++i)
|
||||
buffer[i] = FROM_LE_16(buffer[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZorkCursor::ZorkCursor(const ZorkCursor &other) {
|
||||
_width = other._width;
|
||||
_height = other._height;
|
||||
_hotspotX = other._hotspotX;
|
||||
_hotspotY = other._hotspotY;
|
||||
|
||||
_surface.copyFrom(other._surface);
|
||||
}
|
||||
|
||||
ZorkCursor &ZorkCursor::operator=(const ZorkCursor &other) {
|
||||
_width = other._width;
|
||||
_height = other._height;
|
||||
_hotspotX = other._hotspotX;
|
||||
_hotspotY = other._hotspotY;
|
||||
|
||||
_surface.free();
|
||||
_surface.copyFrom(other._surface);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZorkCursor::~ZorkCursor() {
|
||||
_surface.free();
|
||||
}
|
||||
|
||||
} // End of namespace ZVision
|
||||
77
engines/zvision/graphics/cursors/cursor.h
Normal file
77
engines/zvision/graphics/cursors/cursor.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ZVISION_CURSOR_H
|
||||
#define ZVISION_CURSOR_H
|
||||
|
||||
#include "graphics/surface.h"
|
||||
#include "zvision/zvision.h"
|
||||
|
||||
namespace Common {
|
||||
class String;
|
||||
}
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
/**
|
||||
* Utility class to parse and hold cursor data
|
||||
* Modeled off Graphics::Cursor
|
||||
*/
|
||||
class ZorkCursor {
|
||||
public:
|
||||
ZorkCursor();
|
||||
ZorkCursor(ZVision *engine, const Common::Path &fileName);
|
||||
ZorkCursor(const ZorkCursor &other);
|
||||
~ZorkCursor();
|
||||
|
||||
private:
|
||||
uint16 _width;
|
||||
uint16 _height;
|
||||
uint16 _hotspotX;
|
||||
uint16 _hotspotY;
|
||||
Graphics::Surface _surface;
|
||||
|
||||
public:
|
||||
ZorkCursor &operator=(const ZorkCursor &other);
|
||||
|
||||
uint16 getWidth() const {
|
||||
return _width;
|
||||
}
|
||||
uint16 getHeight() const {
|
||||
return _height;
|
||||
}
|
||||
uint16 getHotspotX() const {
|
||||
return _hotspotX;
|
||||
}
|
||||
uint16 getHotspotY() const {
|
||||
return _hotspotY;
|
||||
}
|
||||
byte getKeyColor() const {
|
||||
return 0;
|
||||
}
|
||||
const byte *getSurface() const {
|
||||
return (const byte *)_surface.getPixels();
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace ZVision
|
||||
|
||||
#endif
|
||||
153
engines/zvision/graphics/cursors/cursor_manager.cpp
Normal file
153
engines/zvision/graphics/cursors/cursor_manager.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/system.h"
|
||||
#include "graphics/cursorman.h"
|
||||
#include "graphics/pixelformat.h"
|
||||
#include "zvision/zvision.h"
|
||||
#include "zvision/graphics/cursors/cursor_manager.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
const char *CursorManager::_cursorNames[NUM_CURSORS] = { "active", "arrow", "backward", "downarrow", "forward", "handpt", "handpu", "hdown", "hleft",
|
||||
"hright", "hup", "idle", "leftarrow", "rightarrow", "suggest_surround", "suggest_tilt", "turnaround", "zuparrow"
|
||||
};
|
||||
|
||||
const char *CursorManager::_zgiCursorFileNames[NUM_CURSORS] = { "g0gbc011.zcr", "g0gac011.zcr", "g0gac021.zcr", "g0gac031.zcr", "g0gac041.zcr", "g0gac051.zcr", "g0gac061.zcr", "g0gac071.zcr", "g0gac081.zcr",
|
||||
"g0gac091.zcr", "g0gac101.zcr", "g0gac011.zcr", "g0gac111.zcr", "g0gac121.zcr", "g0gac131.zcr", "g0gac141.zcr", "g0gac151.zcr", "g0gac161.zcr"
|
||||
};
|
||||
|
||||
const char *CursorManager::_zNemCursorFileNames[NUM_CURSORS] = { "00act", "arrow", "back", "down", "forw", "handpt", "handpu", "hdown", "hleft",
|
||||
"hright", "hup", "00idle", "left", "right", "ssurr", "stilt", "turn", "up"
|
||||
};
|
||||
|
||||
CursorManager::CursorManager(ZVision *engine, const Graphics::PixelFormat &pixelFormat)
|
||||
: _engine(engine),
|
||||
_pixelFormat(pixelFormat),
|
||||
_cursorIsPushed(false),
|
||||
_item(0),
|
||||
_lastitem(0),
|
||||
_currentCursor(CursorIndex_Idle) {
|
||||
for (int i = 0; i < NUM_CURSORS; i++) {
|
||||
if (_engine->getGameId() == GID_NEMESIS) {
|
||||
Common::Path name;
|
||||
if (i == 1) {
|
||||
// Cursors "arrowa.zcr" and "arrowb.zcr" are missing
|
||||
_cursors[i][0] = _cursors[i][1] = ZorkCursor();
|
||||
continue;
|
||||
}
|
||||
name = Common::Path(Common::String::format("%sa.zcr", _zNemCursorFileNames[i]));
|
||||
_cursors[i][0] = ZorkCursor(_engine, name); // Up cursor
|
||||
name = Common::Path(Common::String::format("%sb.zcr", _zNemCursorFileNames[i]));
|
||||
_cursors[i][1] = ZorkCursor(_engine, name); // Down cursor
|
||||
} else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
|
||||
_cursors[i][0] = ZorkCursor(_engine, _zgiCursorFileNames[i]); // Up cursor
|
||||
char buffer[25];
|
||||
memset(buffer, 0, 25);
|
||||
strncpy(buffer, _zgiCursorFileNames[i], 24);
|
||||
buffer[3] += 2;
|
||||
_cursors[i][1] = ZorkCursor(_engine, buffer); // Down cursor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CursorManager::setItemID(int id) {
|
||||
if (id != _item) {
|
||||
if (id) {
|
||||
Common::Path file;
|
||||
if (_engine->getGameId() == GID_NEMESIS) {
|
||||
file = Common::Path(Common::String::format("%2.2d%s%c.zcr", id, "idle", 'a'));
|
||||
_cursors[NUM_CURSORS][0] = ZorkCursor(_engine, file);
|
||||
file = Common::Path(Common::String::format("%2.2d%s%c.zcr", id, "idle", 'b'));
|
||||
_cursors[NUM_CURSORS][1] = ZorkCursor(_engine, file);
|
||||
file = Common::Path(Common::String::format("%2.2d%s%c.zcr", id, "act", 'a'));
|
||||
_cursors[NUM_CURSORS + 1][0] = ZorkCursor(_engine, file);
|
||||
file = Common::Path(Common::String::format("%2.2d%s%c.zcr", id, "act", 'b'));
|
||||
_cursors[NUM_CURSORS + 1][0] = ZorkCursor(_engine, file);
|
||||
} else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
|
||||
file = Common::Path(Common::String::format("g0b%cc%2.2x1.zcr", 'a' , id));
|
||||
_cursors[NUM_CURSORS][0] = ZorkCursor(_engine, file);
|
||||
file = Common::Path(Common::String::format("g0b%cc%2.2x1.zcr", 'c' , id));
|
||||
_cursors[NUM_CURSORS][1] = ZorkCursor(_engine, file);
|
||||
file = Common::Path(Common::String::format("g0b%cc%2.2x1.zcr", 'b' , id));
|
||||
_cursors[NUM_CURSORS + 1][0] = ZorkCursor(_engine, file);
|
||||
file = Common::Path(Common::String::format("g0b%cc%2.2x1.zcr", 'd' , id));
|
||||
_cursors[NUM_CURSORS + 1][1] = ZorkCursor(_engine, file);
|
||||
} else
|
||||
return;
|
||||
}
|
||||
_item = id;
|
||||
changeCursor(CursorIndex_Idle);
|
||||
}
|
||||
}
|
||||
|
||||
void CursorManager::initialize() {
|
||||
changeCursor(_cursors[CursorIndex_Idle][_cursorIsPushed]);
|
||||
showMouse(true);
|
||||
}
|
||||
|
||||
void CursorManager::changeCursor(const ZorkCursor &cursor) {
|
||||
CursorMan.replaceCursor(cursor.getSurface(), cursor.getWidth(), cursor.getHeight(), cursor.getHotspotX(), cursor.getHotspotY(), cursor.getKeyColor(), false, &_pixelFormat);
|
||||
}
|
||||
|
||||
void CursorManager::cursorDown(bool pushed) {
|
||||
if (_cursorIsPushed == pushed)
|
||||
return;
|
||||
|
||||
_cursorIsPushed = pushed;
|
||||
|
||||
changeCursor(_cursors[_currentCursor][_cursorIsPushed]);
|
||||
}
|
||||
|
||||
void CursorManager::changeCursor(int id) {
|
||||
if (_item && (id == CursorIndex_Active ||
|
||||
id == CursorIndex_Idle ||
|
||||
id == CursorIndex_HandPu)) {
|
||||
if (id == CursorIndex_Idle) {
|
||||
id = CursorIndex_ItemIdle;
|
||||
} else {
|
||||
id = CursorIndex_ItemAct;
|
||||
}
|
||||
}
|
||||
|
||||
if (_currentCursor != id || ((id == CursorIndex_ItemAct || id == CursorIndex_ItemIdle) && _lastitem != _item)) {
|
||||
_currentCursor = id;
|
||||
_lastitem = _item;
|
||||
changeCursor(_cursors[_currentCursor][_cursorIsPushed]);
|
||||
}
|
||||
}
|
||||
|
||||
int CursorManager::getCursorId(const Common::String &name) {
|
||||
for (int i = 0; i < NUM_CURSORS; i++) {
|
||||
if (name.equals(_cursorNames[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return CursorIndex_Idle;
|
||||
}
|
||||
|
||||
void CursorManager::showMouse(bool vis) {
|
||||
CursorMan.showMouse(vis);
|
||||
}
|
||||
|
||||
} // End of namespace ZVision
|
||||
132
engines/zvision/graphics/cursors/cursor_manager.h
Normal file
132
engines/zvision/graphics/cursors/cursor_manager.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ZVISION_CURSOR_MANAGER_H
|
||||
#define ZVISION_CURSOR_MANAGER_H
|
||||
|
||||
#include "common/str.h"
|
||||
#include "zvision/graphics/cursors/cursor.h"
|
||||
|
||||
namespace Graphics {
|
||||
struct PixelFormat;
|
||||
}
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
class ZVision;
|
||||
|
||||
/**
|
||||
* Mostly usable cursors
|
||||
*/
|
||||
enum CursorIndex {
|
||||
CursorIndex_Active = 0,
|
||||
CursorIndex_DownArr = 3,
|
||||
CursorIndex_HandPu = 6,
|
||||
CursorIndex_Idle = 11,
|
||||
CursorIndex_Left = 12,
|
||||
CursorIndex_Right = 13,
|
||||
CursorIndex_UpArr = 17,
|
||||
CursorIndex_ItemIdle = 18,
|
||||
CursorIndex_ItemAct = 19
|
||||
};
|
||||
|
||||
/**
|
||||
* Class to manage cursor changes. The actual changes have to be done
|
||||
* through CursorMan. Otherwise the cursor will disappear after GMM
|
||||
* or debug console.
|
||||
* TODO: Figure out a way to get rid of the extraneous data copying due to having to use CursorMan
|
||||
*/
|
||||
class CursorManager {
|
||||
public:
|
||||
CursorManager(ZVision *engine, const Graphics::PixelFormat &pixelFormat);
|
||||
|
||||
private:
|
||||
static const int NUM_CURSORS = 18;
|
||||
|
||||
// 18 default cursors in up/down states, +2 for items idle/act cursors
|
||||
ZorkCursor _cursors[NUM_CURSORS + 2][2];
|
||||
|
||||
ZVision *_engine;
|
||||
const Graphics::PixelFormat _pixelFormat;
|
||||
bool _cursorIsPushed;
|
||||
int _item;
|
||||
int _lastitem;
|
||||
int _currentCursor;
|
||||
|
||||
static const char *_cursorNames[];
|
||||
static const char *_zgiCursorFileNames[];
|
||||
static const char *_zNemCursorFileNames[];
|
||||
|
||||
public:
|
||||
/** Creates the idle cursor and shows it */
|
||||
void initialize();
|
||||
|
||||
/**
|
||||
* Change cursor to specified cursor ID. If item setted to not 0 and cursor id idle/acrive/handpu change cursor to item.
|
||||
*
|
||||
* @param id Wanted cursor id.
|
||||
*/
|
||||
|
||||
void changeCursor(int id);
|
||||
|
||||
/**
|
||||
* Return founded id for string contains cursor name
|
||||
*
|
||||
* @param name Cursor name
|
||||
* @return Id of cursor or idle cursor id if not found
|
||||
*/
|
||||
|
||||
int getCursorId(const Common::String &name);
|
||||
|
||||
/**
|
||||
* Load cursor for item by id, and try to change cursor to item cursor if it's not 0
|
||||
*
|
||||
* @param id Item id or 0 for no item cursor
|
||||
*/
|
||||
|
||||
void setItemID(int id);
|
||||
|
||||
/**
|
||||
* Change the cursor to a certain push state. If the cursor is already in the specified push state, nothing will happen.
|
||||
*
|
||||
* @param pushed Should the cursor be pushed (true) or not pushed (false) (Another way to say it: down or up)
|
||||
*/
|
||||
void cursorDown(bool pushed);
|
||||
|
||||
/**
|
||||
* Show or hide mouse cursor.
|
||||
*
|
||||
* @param vis Should the cursor be showed (true) or hide (false)
|
||||
*/
|
||||
void showMouse(bool vis);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Calls CursorMan.replaceCursor() using the data in cursor
|
||||
*
|
||||
* @param cursor The cursor to show
|
||||
*/
|
||||
void changeCursor(const ZorkCursor &cursor);
|
||||
};
|
||||
|
||||
} // End of namespace ZVision
|
||||
|
||||
#endif
|
||||
170
engines/zvision/graphics/effects/fog.cpp
Normal file
170
engines/zvision/graphics/effects/fog.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "zvision/zvision.h"
|
||||
#include "zvision/graphics/render_manager.h"
|
||||
#include "zvision/graphics/effects/fog.h"
|
||||
#include "zvision/scripting/script_manager.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
FogFx::FogFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, const Common::Path &clouds):
|
||||
GraphicsEffect(engine, key, region, ported) {
|
||||
|
||||
_map = Map;
|
||||
|
||||
_r = 0;
|
||||
_g = 0;
|
||||
_b = 0;
|
||||
|
||||
_pos = 0;
|
||||
|
||||
if (SearchMan.hasFile(clouds))
|
||||
_engine->getRenderManager()->readImageToSurface(clouds, _fog);
|
||||
else
|
||||
_engine->getRenderManager()->readImageToSurface("cloud.tga", _fog);
|
||||
|
||||
_mp.resize(_fog.h);
|
||||
for (int16 i = 0; i < _fog.h; i++) {
|
||||
_mp[i].resize(_fog.w);
|
||||
for (int16 j = 0; j < _fog.w; j++)
|
||||
_mp[i][j] = true;
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < 32; i++)
|
||||
_colorMap[i] = 0;
|
||||
}
|
||||
|
||||
FogFx::~FogFx() {
|
||||
if (_map)
|
||||
delete _map;
|
||||
|
||||
for (uint16 i = 0; i < _mp.size(); i++)
|
||||
_mp[i].clear();
|
||||
_mp.clear();
|
||||
}
|
||||
|
||||
const Graphics::Surface *FogFx::draw(const Graphics::Surface &srcSubRect) {
|
||||
_surface.copyFrom(srcSubRect);
|
||||
EffectMap::iterator it = _map->begin();
|
||||
|
||||
uint32 cnt = 0;
|
||||
|
||||
for (uint16 j = 0; j < _surface.h; j++) {
|
||||
uint16 *lineBuf = (uint16 *)_surface.getBasePtr(0, j);
|
||||
|
||||
for (uint16 i = 0; i < _surface.w; i++) {
|
||||
if (it->inEffect) {
|
||||
// Not 100% equivalent, but looks nice and not buggy
|
||||
uint8 sr, sg, sb;
|
||||
_engine->_resourcePixelFormat.colorToRGB(lineBuf[i], sr, sg, sb);
|
||||
uint16 fogColor = *(uint16 *)_fog.getBasePtr((i + _pos) % _fog.w, j);
|
||||
uint8 dr, dg, db;
|
||||
_engine->_resourcePixelFormat.colorToRGB(_colorMap[fogColor & 0x1F], dr, dg, db);
|
||||
uint16 fr = dr + sr;
|
||||
if (fr > 255)
|
||||
fr = 255;
|
||||
uint16 fg = dg + sg;
|
||||
if (fg > 255)
|
||||
fg = 255;
|
||||
uint16 fb = db + sb;
|
||||
if (fb > 255)
|
||||
fb = 255;
|
||||
lineBuf[i] = _engine->_resourcePixelFormat.RGBToColor(fr, fg, fb);
|
||||
}
|
||||
cnt++;
|
||||
if (cnt >= it->count) {
|
||||
it++;
|
||||
cnt = 0;
|
||||
}
|
||||
if (it == _map->end())
|
||||
break;
|
||||
}
|
||||
if (it == _map->end())
|
||||
break;
|
||||
}
|
||||
|
||||
return &_surface;
|
||||
}
|
||||
|
||||
void FogFx::update() {
|
||||
_pos += _engine->getScriptManager()->getStateValue(StateKey_EF9_Speed);
|
||||
_pos %= _fog.w;
|
||||
debugC(2, kDebugEffect, "Updating fog effect");
|
||||
uint8 dr = _engine->getScriptManager()->getStateValue(StateKey_EF9_R);
|
||||
uint8 dg = _engine->getScriptManager()->getStateValue(StateKey_EF9_G);
|
||||
uint8 db = _engine->getScriptManager()->getStateValue(StateKey_EF9_B);
|
||||
dr = CLIP((int)dr, 0, 31);
|
||||
dg = CLIP((int)dg, 0, 31);
|
||||
db = CLIP((int)db, 0, 31);
|
||||
|
||||
if (dr != _r || dg != _g || db != _b) {
|
||||
if (_r > dr)
|
||||
_r--;
|
||||
else if (_r < dr)
|
||||
_r++;
|
||||
|
||||
if (_g > dg)
|
||||
_g--;
|
||||
else if (_g < dg)
|
||||
_g++;
|
||||
|
||||
if (_b > db)
|
||||
_b--;
|
||||
else if (_b < db)
|
||||
_b++;
|
||||
|
||||
// Not 100% equivalent, but looks nice and not buggy
|
||||
|
||||
_colorMap[31] = _engine->_resourcePixelFormat.RGBToColor(_r << 3, _g << 3, _b << 3);
|
||||
|
||||
for (uint8 i = 0; i < 31; i++) {
|
||||
float perc = (float)i / 31.0;
|
||||
uint8 cr = (uint8)((float)_r * perc);
|
||||
uint8 cg = (uint8)((float)_g * perc);
|
||||
uint8 cb = (uint8)((float)_b * perc);
|
||||
_colorMap[i] = _engine->_resourcePixelFormat.RGBToColor(cr << 3, cg << 3, cb << 3);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint16 j = 0; j < _fog.h; j++) {
|
||||
uint16 *pix = (uint16 *)_fog.getBasePtr(0, j);
|
||||
|
||||
for (uint16 i = 0; i < _fog.w; i++) {
|
||||
if (_mp[j][i]) {
|
||||
if ((pix[i] & 0x1F) == 0x1F) {
|
||||
pix[i]--;
|
||||
_mp[j][i] = false;
|
||||
} else
|
||||
pix[i]++;
|
||||
} else {
|
||||
if ((pix[i] & 0x1F) == 0) {
|
||||
pix[i]++;
|
||||
_mp[j][i] = true;
|
||||
} else
|
||||
pix[i]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace ZVision
|
||||
52
engines/zvision/graphics/effects/fog.h
Normal file
52
engines/zvision/graphics/effects/fog.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ZVISION_FOG_H
|
||||
#define ZVISION_FOG_H
|
||||
|
||||
#include "zvision/graphics/graphics_effect.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
class ZVision;
|
||||
|
||||
// Used by Zork: Nemesis for the mixing chamber gas effect in the gas puzzle (location tt5e, when the blinds are down)
|
||||
class FogFx : public GraphicsEffect {
|
||||
public:
|
||||
|
||||
FogFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, const Common::Path &clouds);
|
||||
~FogFx() override;
|
||||
|
||||
const Graphics::Surface *draw(const Graphics::Surface &srcSubRect) override;
|
||||
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
EffectMap *_map;
|
||||
Graphics::Surface _fog;
|
||||
uint8 _r, _g, _b;
|
||||
int32 _pos;
|
||||
Common::Array< Common::Array< bool > > _mp;
|
||||
uint16 _colorMap[32];
|
||||
};
|
||||
} // End of namespace ZVision
|
||||
|
||||
#endif // ZVISION_FOG_H
|
||||
106
engines/zvision/graphics/effects/light.cpp
Normal file
106
engines/zvision/graphics/effects/light.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "zvision/zvision.h"
|
||||
#include "zvision/graphics/render_manager.h"
|
||||
#include "zvision/graphics/effects/light.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
LightFx::LightFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, int8 delta, int8 minD, int8 maxD):
|
||||
GraphicsEffect(engine, key, region, ported) {
|
||||
_map = Map;
|
||||
_delta = delta;
|
||||
_up = true;
|
||||
_pos = 0;
|
||||
|
||||
_minD = minD;
|
||||
if (_minD < -delta)
|
||||
_minD = -delta;
|
||||
|
||||
_maxD = maxD;
|
||||
if (_maxD > delta)
|
||||
_maxD = delta;
|
||||
}
|
||||
|
||||
LightFx::~LightFx() {
|
||||
if (_map)
|
||||
delete _map;
|
||||
}
|
||||
|
||||
const Graphics::Surface *LightFx::draw(const Graphics::Surface &srcSubRect) {
|
||||
_surface.copyFrom(srcSubRect);
|
||||
EffectMap::iterator it = _map->begin();
|
||||
uint32 cnt = 0;
|
||||
|
||||
uint32 dcolor = 0;
|
||||
|
||||
if (_pos < 0) {
|
||||
uint8 cc = ((-_pos) & 0x1F) << 3;
|
||||
dcolor = _engine->_resourcePixelFormat.RGBToColor(cc, cc, cc);
|
||||
} else {
|
||||
uint8 cc = (_pos & 0x1F) << 3;
|
||||
dcolor = _engine->_resourcePixelFormat.RGBToColor(cc, cc, cc);
|
||||
}
|
||||
|
||||
for (uint16 j = 0; j < _surface.h; j++) {
|
||||
uint16 *lineBuf = (uint16 *)_surface.getBasePtr(0, j);
|
||||
|
||||
for (uint16 i = 0; i < _surface.w; i++) {
|
||||
if (it->inEffect) {
|
||||
if (_pos < 0) {
|
||||
lineBuf[i] -= dcolor;
|
||||
} else {
|
||||
lineBuf[i] += dcolor;
|
||||
}
|
||||
}
|
||||
cnt++;
|
||||
if (cnt >= it->count) {
|
||||
it++;
|
||||
cnt = 0;
|
||||
}
|
||||
if (it == _map->end())
|
||||
break;
|
||||
}
|
||||
if (it == _map->end())
|
||||
break;
|
||||
}
|
||||
|
||||
return &_surface;
|
||||
}
|
||||
|
||||
void LightFx::update() {
|
||||
if (_up)
|
||||
_pos++;
|
||||
else
|
||||
_pos--;
|
||||
|
||||
if (_pos <= _minD) {
|
||||
_up = !_up;
|
||||
_pos = _minD;
|
||||
} else if (_pos >= _maxD) {
|
||||
_up = !_up;
|
||||
_pos = _maxD;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace ZVision
|
||||
52
engines/zvision/graphics/effects/light.h
Normal file
52
engines/zvision/graphics/effects/light.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LIGHTFX_H_INCLUDED
|
||||
#define LIGHTFX_H_INCLUDED
|
||||
|
||||
#include "zvision/graphics/graphics_effect.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
class ZVision;
|
||||
|
||||
class LightFx : public GraphicsEffect {
|
||||
public:
|
||||
|
||||
LightFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, int8 delta, int8 minD = -127, int8 maxD = 127);
|
||||
~LightFx() override;
|
||||
|
||||
const Graphics::Surface *draw(const Graphics::Surface &srcSubRect) override;
|
||||
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
EffectMap *_map;
|
||||
int32 _delta;
|
||||
bool _up;
|
||||
int32 _pos;
|
||||
|
||||
int8 _minD;
|
||||
int8 _maxD;
|
||||
};
|
||||
} // End of namespace ZVision
|
||||
|
||||
#endif // LIGHTFX_H_INCLUDED
|
||||
142
engines/zvision/graphics/effects/wave.cpp
Normal file
142
engines/zvision/graphics/effects/wave.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "zvision/zvision.h"
|
||||
#include "zvision/graphics/render_manager.h"
|
||||
#include "zvision/graphics/effects/wave.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
WaveFx::WaveFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, int16 frames, int16 centerX, int16 centerY, float ampl, float waveln, float spd):
|
||||
GraphicsEffect(engine, key, region, ported) {
|
||||
|
||||
_frame = 0;
|
||||
_frameCount = frames;
|
||||
|
||||
_ampls.resize(_frameCount);
|
||||
_halfWidth = _region.width() / 2;
|
||||
_halfHeight = _region.height() / 2;
|
||||
|
||||
int32 frmsize = _halfWidth * _halfHeight;
|
||||
|
||||
float phase = 0;
|
||||
|
||||
int16 quarterWidth = _halfWidth / 2;
|
||||
int16 quarterHeight = _halfHeight / 2;
|
||||
|
||||
for (int16 i = 0; i < _frameCount; i++) {
|
||||
_ampls[i].resize(frmsize);
|
||||
|
||||
for (int16 y = 0; y < _halfHeight; y++)
|
||||
for (int16 x = 0; x < _halfWidth; x++) {
|
||||
int16 dx = (x - quarterWidth);
|
||||
int16 dy = (y - quarterHeight);
|
||||
|
||||
_ampls[i][x + y * _halfWidth] = (int8)(ampl * sin(sqrt(dx * dx / (float)centerX + dy * dy / (float)centerY) / (-waveln * 3.1415926) + phase));
|
||||
}
|
||||
phase += spd;
|
||||
}
|
||||
}
|
||||
|
||||
WaveFx::~WaveFx() {
|
||||
for (uint16 i = 0; i < _ampls.size(); i++)
|
||||
_ampls[i].clear();
|
||||
_ampls.clear();
|
||||
}
|
||||
|
||||
const Graphics::Surface *WaveFx::draw(const Graphics::Surface &srcSubRect) {
|
||||
for (int16 y = 0; y < _halfHeight; y++) {
|
||||
uint16 *abc = (uint16 *)_surface.getBasePtr(0, y);
|
||||
uint16 *abc2 = (uint16 *)_surface.getBasePtr(0, _halfHeight + y);
|
||||
uint16 *abc3 = (uint16 *)_surface.getBasePtr(_halfWidth, y);
|
||||
uint16 *abc4 = (uint16 *)_surface.getBasePtr(_halfWidth, _halfHeight + y);
|
||||
|
||||
for (int16 x = 0; x < _halfWidth; x++) {
|
||||
int8 amnt = _ampls[_frame][x + _halfWidth * y];
|
||||
|
||||
int16 nX = x + amnt;
|
||||
int16 nY = y + amnt;
|
||||
|
||||
if (nX < 0)
|
||||
nX = 0;
|
||||
if (nX >= _region.width())
|
||||
nX = _region.width() - 1;
|
||||
if (nY < 0)
|
||||
nY = 0;
|
||||
if (nY >= _region.height())
|
||||
nY = _region.height() - 1;
|
||||
*abc = *(const uint16 *)srcSubRect.getBasePtr(nX, nY);
|
||||
|
||||
nX = x + amnt + _halfWidth;
|
||||
nY = y + amnt;
|
||||
|
||||
if (nX < 0)
|
||||
nX = 0;
|
||||
if (nX >= _region.width())
|
||||
nX = _region.width() - 1;
|
||||
if (nY < 0)
|
||||
nY = 0;
|
||||
if (nY >= _region.height())
|
||||
nY = _region.height() - 1;
|
||||
*abc3 = *(const uint16 *)srcSubRect.getBasePtr(nX, nY);
|
||||
|
||||
nX = x + amnt;
|
||||
nY = y + amnt + _halfHeight;
|
||||
|
||||
if (nX < 0)
|
||||
nX = 0;
|
||||
if (nX >= _region.width())
|
||||
nX = _region.width() - 1;
|
||||
if (nY < 0)
|
||||
nY = 0;
|
||||
if (nY >= _region.height())
|
||||
nY = _region.height() - 1;
|
||||
*abc2 = *(const uint16 *)srcSubRect.getBasePtr(nX, nY);
|
||||
|
||||
nX = x + amnt + _halfWidth;
|
||||
nY = y + amnt + _halfHeight;
|
||||
|
||||
if (nX < 0)
|
||||
nX = 0;
|
||||
if (nX >= _region.width())
|
||||
nX = _region.width() - 1;
|
||||
if (nY < 0)
|
||||
nY = 0;
|
||||
if (nY >= _region.height())
|
||||
nY = _region.height() - 1;
|
||||
*abc4 = *(const uint16 *)srcSubRect.getBasePtr(nX, nY);
|
||||
|
||||
abc++;
|
||||
abc2++;
|
||||
abc3++;
|
||||
abc4++;
|
||||
}
|
||||
}
|
||||
|
||||
return &_surface;
|
||||
}
|
||||
|
||||
void WaveFx::update() {
|
||||
_frame = (_frame + 1) % _frameCount;
|
||||
}
|
||||
|
||||
} // End of namespace ZVision
|
||||
50
engines/zvision/graphics/effects/wave.h
Normal file
50
engines/zvision/graphics/effects/wave.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WAVEFX_H_INCLUDED
|
||||
#define WAVEFX_H_INCLUDED
|
||||
|
||||
#include "common/array.h"
|
||||
#include "zvision/graphics/graphics_effect.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
class ZVision;
|
||||
|
||||
class WaveFx : public GraphicsEffect {
|
||||
public:
|
||||
|
||||
WaveFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, int16 frames, int16 centerX, int16 centerY, float ampl, float waveln, float spd);
|
||||
~WaveFx() override;
|
||||
|
||||
const Graphics::Surface *draw(const Graphics::Surface &srcSubRect) override;
|
||||
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
int16 _frame;
|
||||
int16 _frameCount;
|
||||
int16 _halfWidth, _halfHeight;
|
||||
Common::Array< Common::Array< int8 > > _ampls;
|
||||
};
|
||||
} // End of namespace ZVision
|
||||
|
||||
#endif // WAVEFX_H_INCLUDED
|
||||
84
engines/zvision/graphics/graphics_effect.h
Normal file
84
engines/zvision/graphics/graphics_effect.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_EFFECT_H_INCLUDED
|
||||
#define GRAPHICS_EFFECT_H_INCLUDED
|
||||
|
||||
#include "common/list.h"
|
||||
#include "common/rect.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "zvision/zvision.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
class ZVision;
|
||||
|
||||
class GraphicsEffect {
|
||||
public:
|
||||
|
||||
GraphicsEffect(ZVision *engine, uint32 key, Common::Rect region, bool ported) : _engine(engine), _key(key), _region(region), _ported(ported) {
|
||||
_surface.create(_region.width(), _region.height(), _engine->_resourcePixelFormat);
|
||||
}
|
||||
virtual ~GraphicsEffect() {}
|
||||
|
||||
uint32 getKey() {
|
||||
return _key;
|
||||
}
|
||||
|
||||
Common::Rect getRegion() {
|
||||
return _region;
|
||||
}
|
||||
|
||||
// If true, effect is applied to the current background image prior to panoramic warping
|
||||
// If false, effect is applied to the effects buffer, which corresponds directly to the working window
|
||||
bool isPort() {
|
||||
return _ported;
|
||||
}
|
||||
|
||||
// Make a copy of supplied surface, draw effect on it, then return that altered surface
|
||||
virtual const Graphics::Surface *draw(const Graphics::Surface &srcSubRect) {
|
||||
return &_surface;
|
||||
}
|
||||
|
||||
virtual void update() {}
|
||||
|
||||
protected:
|
||||
ZVision *_engine;
|
||||
uint32 _key;
|
||||
Common::Rect _region;
|
||||
bool _ported;
|
||||
Graphics::Surface _surface;
|
||||
|
||||
// Static member functions
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
struct EffectMapUnit {
|
||||
uint32 count;
|
||||
bool inEffect;
|
||||
};
|
||||
|
||||
typedef Common::List<EffectMapUnit> EffectMap;
|
||||
|
||||
} // End of namespace ZVision
|
||||
|
||||
#endif // GRAPHICS_EFFECT_H_INCLUDED
|
||||
1123
engines/zvision/graphics/render_manager.cpp
Normal file
1123
engines/zvision/graphics/render_manager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
376
engines/zvision/graphics/render_manager.h
Normal file
376
engines/zvision/graphics/render_manager.h
Normal file
@@ -0,0 +1,376 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ZVISION_RENDER_MANAGER_H
|
||||
#define ZVISION_RENDER_MANAGER_H
|
||||
|
||||
#include "common/hashmap.h"
|
||||
#include "common/rect.h"
|
||||
#include "graphics/framelimiter.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
#include "graphics/screen.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "zvision/graphics/graphics_effect.h"
|
||||
#include "zvision/graphics/render_table.h"
|
||||
#include "zvision/text/truetype_font.h"
|
||||
|
||||
class OSystem;
|
||||
|
||||
namespace Common {
|
||||
class String;
|
||||
class SeekableReadStream;
|
||||
}
|
||||
|
||||
namespace Video {
|
||||
class VideoDecoder;
|
||||
}
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
class RenderManager {
|
||||
public:
|
||||
RenderManager(ZVision *engine, const ScreenLayout layout, const Graphics::PixelFormat pixelFormat, bool doubleFPS, bool widescreen = false);
|
||||
~RenderManager();
|
||||
|
||||
|
||||
typedef Common::List<GraphicsEffect *> EffectsList;
|
||||
|
||||
private:
|
||||
ZVision *_engine;
|
||||
OSystem *_system;
|
||||
const Graphics::PixelFormat _pixelFormat;
|
||||
const ScreenLayout _layout;
|
||||
bool _hiRes = false;
|
||||
Graphics::FrameLimiter _frameLimiter;
|
||||
|
||||
/**
|
||||
* A Rectangle representing the screen/window resolution.
|
||||
*/
|
||||
Common::Rect _screenArea;
|
||||
|
||||
Common::Rect _HDscreenArea = Common::Rect(800, 600);
|
||||
Common::Rect _HDscreenAreaWide = Common::Rect(720, 377);
|
||||
|
||||
Common::Point _textOffset; //Position vector of text area origin relative to working window origin
|
||||
|
||||
/**
|
||||
* A Rectangle placed inside _screenArea All in-game coordinates
|
||||
* are given in this coordinate space. Also, all images are clipped to the
|
||||
* edges of this Rectangle
|
||||
*/
|
||||
Common::Rect _workingArea;
|
||||
|
||||
Common::Point _workingAreaCenter; //Center of the working area in working area coordinates
|
||||
|
||||
/**
|
||||
Managed surface representing physical screen; dirty rectangles will be handled automatically by this from now on
|
||||
*/
|
||||
Graphics::Screen _screen;
|
||||
|
||||
/** A buffer for background image that's being used to create the background */
|
||||
Graphics::Surface _currentBackgroundImage;
|
||||
Common::Rect _backgroundDirtyRect;
|
||||
|
||||
/**
|
||||
* The x1 or y1 offset of the subRectangle of the background that is currently displayed on the screen
|
||||
* It will be x1 if PANORAMA, or y1 if TILT
|
||||
*/
|
||||
int16 _backgroundOffset;
|
||||
/** The width of the current background image */
|
||||
uint16 _backgroundWidth;
|
||||
/** The height of the current background image */
|
||||
uint16 _backgroundHeight;
|
||||
|
||||
// A buffer that holds the portion of the background that is used to render the final image
|
||||
// If it's a normal scene, the pixels will be blitted directly to the screen
|
||||
// If it's a panorma / tilt scene, the pixels will be first warped to _warpedSceneSurface
|
||||
Graphics::Surface _backgroundSurface;
|
||||
Graphics::ManagedSurface _workingManagedSurface;
|
||||
Common::Rect _backgroundSurfaceDirtyRect;
|
||||
|
||||
//TODO: Migrate this functionality to SubtitleManager to improve encapsulation
|
||||
//*
|
||||
// Buffer for drawing subtitles & other messages
|
||||
Graphics::Surface _textSurface;
|
||||
Graphics::ManagedSurface _textManagedSurface;
|
||||
Common::Rect _textSurfaceDirtyRect;
|
||||
//*/
|
||||
|
||||
// Rectangle for subtitles & other messages
|
||||
Common::Rect _textArea; //NB Screen coordinates
|
||||
Common::Rect _textLetterbox; //Section of text area outside working window, to be filled with black when blanked
|
||||
Common::Rect _textOverlay; //Section of text area to be filled with colorkey when blanked (may potentially intersect text letterbox area if screen/window is wider than working area!)
|
||||
|
||||
// Buffer for drawing menu
|
||||
Graphics::Surface _menuSurface;
|
||||
Graphics::ManagedSurface _menuManagedSurface;
|
||||
Common::Rect _menuSurfaceDirtyRect; //subrectangle of menu area outside working area
|
||||
|
||||
// Rectangle for menu area
|
||||
Common::Rect _menuArea; //Screen coordinates
|
||||
Common::Rect _menuLetterbox; //Section of menu area to be filled with black when blanked
|
||||
Common::Rect _menuOverlay; //Section of menu area to be filled with colorkey when blanked (may potentially intersect menu letterbox area if screen/window is wider than working area!)
|
||||
|
||||
//Buffer for streamed video playback
|
||||
//*
|
||||
Graphics::ManagedSurface _vidManagedSurface;
|
||||
/*/
|
||||
Graphics::Surface _vidSurface;
|
||||
//*/
|
||||
|
||||
//Area of streamed video playback
|
||||
Common::Rect _vidArea;
|
||||
|
||||
// A buffer used for apply graphics effects
|
||||
Graphics::Surface _effectSurface;
|
||||
|
||||
// A buffer to store the result of the panorama / tilt warps
|
||||
Graphics::Surface _warpedSceneSurface;
|
||||
|
||||
|
||||
/** Used to warp the background image */
|
||||
RenderTable _renderTable;
|
||||
|
||||
|
||||
|
||||
// Visual effects list
|
||||
EffectsList _effects;
|
||||
|
||||
//Pointer to currently active backbuffer output surface
|
||||
Graphics::Surface *_outputSurface;
|
||||
bool _doubleFPS;
|
||||
bool _widescreen;
|
||||
|
||||
public:
|
||||
void initialize(bool hiRes = false);
|
||||
|
||||
/**
|
||||
* Renders the scene to the screen
|
||||
* Returns true if screen was updated
|
||||
* If streamMode is set true, all background processing is skipped and the previous framebuffer is used
|
||||
*/
|
||||
bool renderSceneToScreen(bool immediate = false, bool overlayOnly = false, bool preStream = false);
|
||||
|
||||
Graphics::ManagedSurface &getVidSurface(Common::Rect dstRect); //dstRect is defined relative to working area origin
|
||||
|
||||
const Common::Rect &getMenuArea() const {
|
||||
return _menuArea;
|
||||
}
|
||||
const Common::Rect &getWorkingArea() const {
|
||||
return _workingArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blits the image or a portion of the image to the background.
|
||||
*
|
||||
* @param fileName Name of the image file
|
||||
* @param destinationX X position where the image should be put. Coords are in working window space, not screen space!
|
||||
* @param destinationY Y position where the image should be put. Coords are in working window space, not screen space!
|
||||
*/
|
||||
void renderImageToBackground(const Common::Path &fileName, int16 destinationX, int16 destinationY);
|
||||
|
||||
/**
|
||||
* Blits the image or a portion of the image to the background.
|
||||
*
|
||||
* @param fileName Name of the image file
|
||||
* @param destX X position where the image should be put. Coords are in working window space, not screen space!
|
||||
* @param destY Y position where the image should be put. Coords are in working window space, not screen space!
|
||||
* @param colorkey Transparent color
|
||||
*/
|
||||
void renderImageToBackground(const Common::Path &fileName, int16 destX, int16 destY, uint32 colorkey);
|
||||
|
||||
/**
|
||||
* Blits the image or a portion of the image to the background.
|
||||
*
|
||||
* @param fileName Name of the image file
|
||||
* @param destX X position where the image should be put. Coords are in working window space, not screen space!
|
||||
* @param destY Y position where the image should be put. Coords are in working window space, not screen space!
|
||||
* @param keyX X position of transparent color
|
||||
* @param keyY Y position of transparent color
|
||||
*/
|
||||
void renderImageToBackground(const Common::Path &fileName, int16 destX, int16 destY, int16 keyX, int16 keyY);
|
||||
|
||||
/**
|
||||
* Sets the current background image to be used by the RenderManager and immediately
|
||||
* blits it to the screen. (It won't show up until the end of the frame)
|
||||
*
|
||||
* @param fileName The name of the image file
|
||||
*/
|
||||
void setBackgroundImage(const Common::Path &fileName);
|
||||
|
||||
/**
|
||||
* Set the background position (_backgroundOffset). If the current RenderState is PANORAMA, the offset
|
||||
* will be in the horizontal direction. If the current RenderState is TILT, the offset will be in the
|
||||
* vertical direction.
|
||||
*
|
||||
* This method will not render anything on the screen. So if nothing else is called that renders the
|
||||
* background, the change won't be seen until next frame.
|
||||
*
|
||||
* @param offset The amount to offset the background
|
||||
*/
|
||||
void setBackgroundPosition(int offset);
|
||||
|
||||
/**
|
||||
* Converts a point in screen coordinate space to image coordinate space
|
||||
*
|
||||
* @param point Point in screen coordinate space
|
||||
* @return Point in image coordinate space
|
||||
*/
|
||||
const Common::Point screenSpaceToImageSpace(const Common::Point &point);
|
||||
|
||||
// Return pointer of RenderTable object
|
||||
RenderTable *getRenderTable();
|
||||
|
||||
// Return current background offset
|
||||
uint32 getCurrentBackgroundOffset();
|
||||
|
||||
/**
|
||||
* Creates a copy of surface and transposes the data.
|
||||
*
|
||||
* Note: The user is responsible for calling free() on the returned surface
|
||||
* and then deleting it
|
||||
*
|
||||
* @param surface The data to be transposed
|
||||
* @return A copy of the surface with the data transposed
|
||||
*/
|
||||
static Graphics::Surface *tranposeSurface(const Graphics::Surface *surface);
|
||||
|
||||
// Scale buffer (nearest)
|
||||
void scaleBuffer(const void *src, void *dst, uint32 srcWidth, uint32 srcHeight, byte bytesPerPixel, uint32 dstWidth, uint32 dstHeight);
|
||||
|
||||
/**
|
||||
* Blit from one surface to another surface
|
||||
*
|
||||
* @param src Source surface
|
||||
* @param srcRect Rectangle defining area of source surface to blit; if this rectangle is empty or not supplied, entire source surface is blitted
|
||||
* @param dst Destination surface
|
||||
* @param x Destination surface x coordinate
|
||||
* @param y Destination surface y coordinate
|
||||
*/
|
||||
|
||||
void blitSurfaceToSurface(const Graphics::Surface &src, Common::Rect srcRect, Graphics::Surface &dst, int _x, int _y);
|
||||
void blitSurfaceToSurface(const Graphics::Surface &src, Common::Rect srcRect, Graphics::Surface &dst, int _x, int _y, uint32 colorkey);
|
||||
void blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int _x, int _y) {blitSurfaceToSurface(src, Common::Rect(src.w, src.h), dst, _x, _y);}
|
||||
void blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int _x, int _y, uint32 colorkey) {blitSurfaceToSurface(src, Common::Rect(src.w, src.h), dst, _x, _y, colorkey);}
|
||||
|
||||
// Blitting surface-to-background methods
|
||||
void blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, int32 colorkey = -1);
|
||||
|
||||
// Blitting surface-to-background methods with scale
|
||||
void blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &dstRect, int32 colorkey = -1);
|
||||
|
||||
/**
|
||||
* Blit from source surface to menu area
|
||||
*
|
||||
* @param src Source surface
|
||||
* @param x x coordinate relative to menu area origin
|
||||
* @param y y coordinate relative to menu area origin
|
||||
*/
|
||||
void blitSurfaceToMenu(const Graphics::Surface &src, int16 x, int16 y, int32 colorkey = 0);
|
||||
|
||||
/**
|
||||
* Blit from source surface to text area
|
||||
*
|
||||
* @param src Source surface
|
||||
* @param x x coordinate relative to text area origin
|
||||
* @param y y coordinate relative to text area origin
|
||||
*/
|
||||
void blitSurfaceToText(const Graphics::Surface &src, int16 x, int16 y, int32 colorkey = 0);
|
||||
|
||||
// Return background size
|
||||
Common::Point getBkgSize();
|
||||
|
||||
// Return portion of background as new surface
|
||||
Graphics::Surface *getBkgRect(Common::Rect &rect);
|
||||
|
||||
// Load image into new surface
|
||||
Graphics::Surface *loadImage(const Common::Path &file);
|
||||
Graphics::Surface *loadImage(const Common::Path &file, bool transposed);
|
||||
|
||||
// Clear whole/area of menu backbuffer
|
||||
void clearMenuSurface(bool force = false, int32 colorkey = -1);
|
||||
|
||||
// Clear whole/area of subtitle backbuffer
|
||||
void clearTextSurface(bool force = false, int32 colorkey = -1);
|
||||
|
||||
// Copy needed portion of background surface to workingArea surface
|
||||
void prepareBackground();
|
||||
|
||||
/**
|
||||
* Reads an image file pixel data into a Surface buffer. Also, if the image
|
||||
* is transposed, it will un-transpose the pixel data. The function will
|
||||
* call destination::create() if the dimensions of destination do not match
|
||||
* up with the dimensions of the image.
|
||||
*
|
||||
* @param fileName The name of a .tga file
|
||||
* @param destination A reference to the Surface to store the pixel data in
|
||||
*/
|
||||
void readImageToSurface(const Common::Path &fileName, Graphics::Surface &destination);
|
||||
|
||||
/**
|
||||
* Reads an image file pixel data into a Surface buffer. Also, if the image
|
||||
* is transposed, it will un-transpose the pixel data. The function will
|
||||
* call destination::create() if the dimensions of destination do not match
|
||||
* up with the dimensions of the image.
|
||||
*
|
||||
* @param fileName The name of a .tga file
|
||||
* @param destination A reference to the Surface to store the pixel data in
|
||||
* @param transposed Transpose flag
|
||||
*/
|
||||
void readImageToSurface(const Common::Path &fileName, Graphics::Surface &destination, bool transposed);
|
||||
|
||||
// Add visual effect to effects list
|
||||
void addEffect(GraphicsEffect *_effect);
|
||||
|
||||
// Delete effect(s) by ID (ID equal to slot of action:region that create this effect)
|
||||
void deleteEffect(uint32 ID);
|
||||
|
||||
// Create "mask" for effects - (color +/- depth) will be selected as not transparent. Like color selection
|
||||
// xy - base color
|
||||
// depth - +/- of base color
|
||||
// rect - rectangle where select pixels
|
||||
// minD - if not NULL will receive real bottom border of depth
|
||||
// maxD - if not NULL will receive real top border of depth
|
||||
EffectMap *makeEffectMap(const Common::Point &xy, int16 depth, const Common::Rect &rect, int8 *minD, int8 *maxD);
|
||||
|
||||
// Create "mask" for effects by simple transparent color
|
||||
EffectMap *makeEffectMap(const Graphics::Surface &surf, uint16 transp);
|
||||
|
||||
// Return background rectangle in screen coordinates
|
||||
Common::Rect transformBackgroundSpaceRectToScreenSpace(const Common::Rect &src);
|
||||
|
||||
// Mark whole background surface as dirty
|
||||
void markDirty();
|
||||
|
||||
/*
|
||||
// Fill background surface by color
|
||||
void bkgFill(uint8 r, uint8 g, uint8 b);
|
||||
*/
|
||||
|
||||
void checkBorders();
|
||||
void rotateTo(int16 to, int16 time);
|
||||
void updateRotation();
|
||||
void upscaleRect(Common::Rect &rect);
|
||||
};
|
||||
|
||||
} // End of namespace ZVision
|
||||
|
||||
#endif
|
||||
345
engines/zvision/graphics/render_table.cpp
Normal file
345
engines/zvision/graphics/render_table.cpp
Normal file
@@ -0,0 +1,345 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/system.h"
|
||||
#include "math/utils.h"
|
||||
#include "zvision/graphics/render_table.h"
|
||||
#include "zvision/scripting/script_manager.h"
|
||||
|
||||
namespace ZVision {
|
||||
|
||||
RenderTable::RenderTable(ZVision *engine, uint16 numColumns, uint16 numRows, const Graphics::PixelFormat &pixelFormat)
|
||||
: _engine(engine),
|
||||
_system(engine->_system),
|
||||
_numRows(numRows),
|
||||
_numColumns(numColumns),
|
||||
_renderState(FLAT),
|
||||
_pixelFormat(pixelFormat) {
|
||||
assert(numRows != 0 && numColumns != 0);
|
||||
|
||||
_internalBuffer = new FilterPixel[numRows * numColumns];
|
||||
|
||||
memset(&_panoramaOptions, 0, sizeof(_panoramaOptions));
|
||||
memset(&_tiltOptions, 0, sizeof(_tiltOptions));
|
||||
_halfRows = floor((_numRows - 1) / 2);
|
||||
_halfColumns = floor((_numColumns - 1) / 2);
|
||||
_halfWidth = (float)_numColumns / 2.0f - 0.5f;
|
||||
_halfHeight = (float)_numRows / 2.0f - 0.5f;
|
||||
}
|
||||
|
||||
RenderTable::~RenderTable() {
|
||||
delete[] _internalBuffer;
|
||||
}
|
||||
|
||||
void RenderTable::setRenderState(RenderState newState) {
|
||||
_renderState = newState;
|
||||
|
||||
switch (newState) {
|
||||
case PANORAMA:
|
||||
_panoramaOptions.verticalFOV = Math::deg2rad<float>(27.0f);
|
||||
_panoramaOptions.linearScale = 0.55f;
|
||||
_panoramaOptions.reverse = false;
|
||||
_panoramaOptions.zeroPoint = 0;
|
||||
break;
|
||||
case TILT:
|
||||
_tiltOptions.verticalFOV = Math::deg2rad<float>(27.0f);
|
||||
_tiltOptions.linearScale = 0.65f;
|
||||
_tiltOptions.reverse = false;
|
||||
break;
|
||||
case FLAT:
|
||||
// Intentionally left empty
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const Common::Point RenderTable::convertWarpedCoordToFlatCoord(const Common::Point &point) {
|
||||
// If we're outside the range of the RenderTable, no warping is happening. Return the maximum image coords
|
||||
if (point.x >= (int16)_numColumns || point.y >= (int16)_numRows || point.x < 0 || point.y < 0) {
|
||||
int16 x = CLIP<int16>(point.x, 0, (int16)_numColumns);
|
||||
int16 y = CLIP<int16>(point.y, 0, (int16)_numRows);
|
||||
return Common::Point(x, y);
|
||||
}
|
||||
|
||||
uint32 index = point.y * _numColumns + point.x;
|
||||
|
||||
Common::Point newPoint(point);
|
||||
newPoint.x += (_internalBuffer[index]._xDir ? _internalBuffer[index]._src.right : _internalBuffer[index]._src.left);
|
||||
newPoint.y += (_internalBuffer[index]._yDir ? _internalBuffer[index]._src.bottom : _internalBuffer[index]._src.top);
|
||||
|
||||
return newPoint;
|
||||
}
|
||||
|
||||
// Disused at present; potentially useful for future rendering efficient improvements.
|
||||
/*/
|
||||
void RenderTable::mutateImage(uint16 *sourceBuffer, uint16 *destBuffer, uint32 destWidth, const Common::Rect &subRect) {
|
||||
uint32 destOffset = 0;
|
||||
uint32 sourceXIndex = 0;
|
||||
uint32 sourceYIndex = 0;
|
||||
if(highQuality) {
|
||||
// TODO - convert to high quality pixel filtering
|
||||
for (int16 y = subRect.top; y < subRect.bottom; ++y) {
|
||||
uint32 sourceOffset = y * _numColumns;
|
||||
for (int16 x = subRect.left; x < subRect.right; ++x) {
|
||||
uint32 normalizedX = x - subRect.left;
|
||||
uint32 index = sourceOffset + x;
|
||||
// RenderTable only stores offsets from the original coordinates
|
||||
sourceYIndex = y + _internalBuffer[index]._src.top;
|
||||
sourceXIndex = x + _internalBuffer[index]._src.left;
|
||||
destBuffer[destOffset + normalizedX] = sourceBuffer[sourceYIndex * _numColumns + sourceXIndex];
|
||||
}
|
||||
destOffset += destWidth;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int16 y = subRect.top; y < subRect.bottom; ++y) {
|
||||
uint32 sourceOffset = y * _numColumns;
|
||||
for (int16 x = subRect.left; x < subRect.right; ++x) {
|
||||
uint32 normalizedX = x - subRect.left;
|
||||
uint32 index = sourceOffset + x;
|
||||
// RenderTable only stores offsets from the original coordinates
|
||||
sourceYIndex = y + _internalBuffer[index]._src.top;
|
||||
sourceXIndex = x + _internalBuffer[index]._src.left;
|
||||
destBuffer[destOffset + normalizedX] = sourceBuffer[sourceYIndex * _numColumns + sourceXIndex];
|
||||
}
|
||||
destOffset += destWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
// */
|
||||
|
||||
void RenderTable::mutateImage(Graphics::Surface *dstBuf, Graphics::Surface *srcBuf, bool highQuality) {
|
||||
uint32 destOffset = 0;
|
||||
uint32 sourceOffset = 0;
|
||||
uint16 *sourceBuffer = (uint16 *)srcBuf->getPixels();
|
||||
uint16 *destBuffer = (uint16 *)dstBuf->getPixels();
|
||||
if (highQuality != _highQuality) {
|
||||
_highQuality = highQuality;
|
||||
generateRenderTable();
|
||||
}
|
||||
uint32 mutationTime = _system->getMillis();
|
||||
if (_highQuality) {
|
||||
// Apply bilinear interpolation
|
||||
for (int16 y = 0; y < srcBuf->h; ++y) {
|
||||
sourceOffset = y * _numColumns;
|
||||
for (int16 x = 0; x < srcBuf->w; ++x) {
|
||||
const FilterPixel &curP = _internalBuffer[sourceOffset + x];
|
||||
const uint32 srcIndexYT = y + curP._src.top;
|
||||
const uint32 srcIndexYB = y + curP._src.bottom;
|
||||
const uint32 srcIndexXL = x + curP._src.left;
|
||||
const uint32 srcIndexXR = x + curP._src.right;
|
||||
uint32 rTL, rTR, rBL, rBR;
|
||||
uint32 gTL, gTR, gBL, gBR;
|
||||
uint32 bTL, bTR, bBL, bBR;
|
||||
splitColor(sourceBuffer[srcIndexYT * _numColumns + srcIndexXL], rTL, gTL, bTL);
|
||||
splitColor(sourceBuffer[srcIndexYT * _numColumns + srcIndexXR], rTR, gTR, bTR);
|
||||
splitColor(sourceBuffer[srcIndexYB * _numColumns + srcIndexXL], rBL, gBL, bBL);
|
||||
splitColor(sourceBuffer[srcIndexYB * _numColumns + srcIndexXR], rBR, gBR, bBR);
|
||||
const uint32 rF = curP._fTL * rTL + curP._fTR * rTR + curP._fBL * rBL + curP._fBR * rBR;
|
||||
const uint32 gF = curP._fTL * gTL + curP._fTR * gTR + curP._fBL * gBL + curP._fBR * gBR;
|
||||
const uint32 bF = curP._fTL * bTL + curP._fTR * bTR + curP._fBL * bBL + curP._fBR * bBR;
|
||||
destBuffer[destOffset] = mergeColor(rF, gF, bF);
|
||||
destOffset++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Apply nearest-neighbour interpolation
|
||||
for (int16 y = 0; y < srcBuf->h; ++y) {
|
||||
sourceOffset = y * _numColumns;
|
||||
for (int16 x = 0; x < srcBuf->w; ++x) {
|
||||
const uint32 index = sourceOffset + x;
|
||||
// RenderTable only stores offsets from the original coordinates
|
||||
const uint32 srcIndexX = x + (_internalBuffer[index]._xDir ? _internalBuffer[index]._src.right : _internalBuffer[index]._src.left);
|
||||
const uint32 srcIndexY = y + (_internalBuffer[index]._yDir ? _internalBuffer[index]._src.bottom : _internalBuffer[index]._src.top);
|
||||
destBuffer[destOffset] = sourceBuffer[srcIndexY * _numColumns + srcIndexX];
|
||||
destOffset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
mutationTime = _system->getMillis() - mutationTime;
|
||||
debugC(5, kDebugGraphics, "\tPanorama mutation time %dms, %s quality", mutationTime, _highQuality ? "high" : "low");
|
||||
}
|
||||
|
||||
void RenderTable::generateRenderTable() {
|
||||
switch (_renderState) {
|
||||
case RenderTable::PANORAMA: {
|
||||
generateLookupTable(false);
|
||||
break;
|
||||
}
|
||||
case RenderTable::TILT:
|
||||
generateLookupTable(true);
|
||||
break;
|
||||
case RenderTable::FLAT:
|
||||
// Intentionally left empty
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTable::generateLookupTable(bool tilt) {
|
||||
debugC(1, kDebugGraphics, "Generating %s lookup table.", tilt ? "tilt" : "panorama");
|
||||
debugC(5, kDebugGraphics, "_halfWidth %f, _halfHeight %f", _halfWidth, _halfHeight);
|
||||
debugC(5, kDebugGraphics, "_halfRows %d, _halfColumns %d", _halfRows, _halfColumns);
|
||||
uint32 generationTime = _system->getMillis();
|
||||
float cosAlpha, polarCoordInCylinderCoords, cylinderRadius, xOffset, yOffset;
|
||||
uint32 indexTL, indexBL, indexTR, indexBR;
|
||||
auto outerLoop = [&](uint & polarCoord, float & halfPolarSize, float & scale) {
|
||||
// polarCoord is the coordinate of the working window pixel parallel to the direction of camera rotation
|
||||
// halfPolarSize is the distance from the central axis to the outermost working window pixel in the direction of camera rotation
|
||||
// alpha represents the angle in the direction of camera rotation between the view axis and the centre of a pixel at the given polar coordinate
|
||||
const float alpha = atan(((float)polarCoord - halfPolarSize) / cylinderRadius);
|
||||
// To map the polar coordinate to the cylinder surface coordinates, we just need to calculate the arc length
|
||||
// We also scale it by linearScale
|
||||
polarCoordInCylinderCoords = (cylinderRadius * scale * alpha) + halfPolarSize;
|
||||
cosAlpha = cos(alpha);
|
||||
};
|
||||
auto innerLoop = [&](uint & polarCoord, uint & linearCoord, float & halfLinearSize, float & polarOffset, float & linearOffset) {
|
||||
// To calculate linear coordinate in cylinder coordinates, we can do similar triangles comparison,
|
||||
// comparing the triangle from the center to the screen and from the center to the edge of the cylinder
|
||||
const float linearCoordInCylinderCoords = halfLinearSize + ((float)linearCoord - halfLinearSize) * cosAlpha;
|
||||
linearOffset = linearCoordInCylinderCoords - linearCoord;
|
||||
polarOffset = polarCoordInCylinderCoords - polarCoord;
|
||||
_internalBuffer[indexTL] = FilterPixel(xOffset, yOffset, _highQuality);
|
||||
// Transformation is both horizontally and vertically symmetrical about the camera axis,
|
||||
// We can thus save on trigonometric calculations by computing one quarter of the transformation matrix and then mirroring it in both X & Y:
|
||||
_internalBuffer[indexBL] = _internalBuffer[indexTL];
|
||||
_internalBuffer[indexBL].flipV();
|
||||
_internalBuffer[indexTR] = _internalBuffer[indexTL];
|
||||
_internalBuffer[indexTR].flipH();
|
||||
_internalBuffer[indexBR] = _internalBuffer[indexBL];
|
||||
_internalBuffer[indexBR].flipH();
|
||||
};
|
||||
if (tilt) {
|
||||
cylinderRadius = (_halfWidth + 0.5f) / tan(_tiltOptions.verticalFOV);
|
||||
_tiltOptions.gap = cylinderRadius * atan2((float)(_halfHeight / cylinderRadius), 1.0f) * _tiltOptions.linearScale;
|
||||
for (uint y = 0; y <= _halfRows; ++y) {
|
||||
outerLoop(y, _halfHeight, _tiltOptions.linearScale);
|
||||
const uint32 columnIndexTL = y * _numColumns;
|
||||
const uint32 columnIndexBL = (_numRows - (y + 1)) * _numColumns;
|
||||
const uint32 columnIndexTR = columnIndexTL + (_numColumns - 1);
|
||||
const uint32 columnIndexBR = columnIndexBL + (_numColumns - 1);
|
||||
for (uint x = 0; x <= _halfColumns; ++x) {
|
||||
indexTL = columnIndexTL + x;
|
||||
indexBL = columnIndexBL + x;
|
||||
indexTR = columnIndexTR - x;
|
||||
indexBR = columnIndexBR - x;
|
||||
innerLoop(y, x, _halfWidth, yOffset, xOffset);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cylinderRadius = (_halfHeight + 0.5f) / tan(_panoramaOptions.verticalFOV);
|
||||
for (uint x = 0; x <= _halfColumns; ++x) {
|
||||
const uint32 columnIndexL = x;
|
||||
const uint32 columnIndexR = (_numColumns - 1) - x;
|
||||
uint32 rowIndexT = 0;
|
||||
uint32 rowIndexB = _numColumns * (_numRows - 1);
|
||||
outerLoop(x, _halfWidth, _panoramaOptions.linearScale);
|
||||
for (uint y = 0; y <= _halfRows; ++y) {
|
||||
indexTL = rowIndexT + columnIndexL;
|
||||
indexBL = rowIndexB + columnIndexL;
|
||||
indexTR = rowIndexT + columnIndexR;
|
||||
indexBR = rowIndexB + columnIndexR;
|
||||
innerLoop(x, y, _halfHeight, xOffset, yOffset);
|
||||
rowIndexT += _numColumns;
|
||||
rowIndexB -= _numColumns;
|
||||
}
|
||||
}
|
||||
}
|
||||
generationTime = _system->getMillis() - generationTime;
|
||||
debugC(1, kDebugGraphics, "Render table generated, %s quality", _highQuality ? "high" : "low");
|
||||
debugC(1, kDebugGraphics, "\tRender table generation time %dms", generationTime);
|
||||
}
|
||||
|
||||
void RenderTable::setPanoramaFoV(float fov) {
|
||||
assert(fov > 0.0f);
|
||||
|
||||
_panoramaOptions.verticalFOV = Math::deg2rad<float>(fov);
|
||||
}
|
||||
|
||||
void RenderTable::setPanoramaScale(float scale) {
|
||||
assert(scale > 0.0f);
|
||||
|
||||
_panoramaOptions.linearScale = scale;
|
||||
}
|
||||
|
||||
void RenderTable::setPanoramaReverse(bool reverse) {
|
||||
_panoramaOptions.reverse = reverse;
|
||||
}
|
||||
|
||||
bool RenderTable::getPanoramaReverse() {
|
||||
return _panoramaOptions.reverse;
|
||||
}
|
||||
|
||||
void RenderTable::setPanoramaZeroPoint(uint16 point) {
|
||||
_panoramaOptions.zeroPoint = point;
|
||||
}
|
||||
|
||||
uint16 RenderTable::getPanoramaZeroPoint() {
|
||||
return _panoramaOptions.zeroPoint;
|
||||
}
|
||||
|
||||
void RenderTable::setTiltFoV(float fov) {
|
||||
assert(fov > 0.0f);
|
||||
|
||||
_tiltOptions.verticalFOV = Math::deg2rad<float>(fov);
|
||||
}
|
||||
|
||||
void RenderTable::setTiltScale(float scale) {
|
||||
assert(scale > 0.0f);
|
||||
|
||||
_tiltOptions.linearScale = scale;
|
||||
}
|
||||
|
||||
void RenderTable::setTiltReverse(bool reverse) {
|
||||
_tiltOptions.reverse = reverse;
|
||||
}
|
||||
|
||||
float RenderTable::getTiltGap() {
|
||||
return _tiltOptions.gap;
|
||||
}
|
||||
|
||||
float RenderTable::getAngle() {
|
||||
switch (_renderState) {
|
||||
case TILT:
|
||||
return Math::rad2deg<float>(_tiltOptions.verticalFOV);
|
||||
case PANORAMA:
|
||||
return Math::rad2deg<float>(_panoramaOptions.verticalFOV);
|
||||
default:
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
float RenderTable::getLinscale() {
|
||||
switch (_renderState) {
|
||||
case TILT:
|
||||
return _tiltOptions.linearScale;
|
||||
case PANORAMA:
|
||||
return _panoramaOptions.linearScale;
|
||||
default:
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace ZVision
|
||||
169
engines/zvision/graphics/render_table.h
Normal file
169
engines/zvision/graphics/render_table.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ZVISION_RENDER_TABLE_H
|
||||
#define ZVISION_RENDER_TABLE_H
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "zvision/zvision.h"
|
||||
|
||||
class OSystem;
|
||||
namespace ZVision {
|
||||
|
||||
class FilterPixel {
|
||||
public:
|
||||
// Bitfields representing sequential direction of contraction
|
||||
bool _xDir = false; // false left, true right
|
||||
bool _yDir = false; // false up, true down
|
||||
Common::Rect _src = Common::Rect(0, 0); // Coordinates of four panorama image pixels around actual working window pixel
|
||||
|
||||
float _fX, _fY, _fTL, _fTR, _fBL, _fBR;
|
||||
|
||||
FilterPixel() {}
|
||||
FilterPixel(float x, float y, bool highQuality = false) {
|
||||
_src.left = int16(floor(x));
|
||||
_src.right = int16(ceil(x));
|
||||
_src.top = int16(floor(y));
|
||||
_src.bottom = int16(ceil(y));
|
||||
if (highQuality) {
|
||||
_fX = x - (float)_src.left;
|
||||
_fY = y - (float)_src.top;
|
||||
_fTL = (1 - _fX) * (1 - _fY);
|
||||
_fTR = _fX * (1 - _fY);
|
||||
_fBL = (1 - _fX) * _fY;
|
||||
_fBR = _fX * _fY;
|
||||
} else {
|
||||
// Nearest neighbour
|
||||
_xDir = (x - _src.left) > 0.5f;
|
||||
_yDir = (y - _src.top) > 0.5f;
|
||||
}
|
||||
}
|
||||
~FilterPixel() {}
|
||||
inline void flipH() {
|
||||
_src.left = -_src.left;
|
||||
_src.right = -_src.right;
|
||||
}
|
||||
inline void flipV() {
|
||||
_src.top = -_src.top;
|
||||
_src.bottom = -_src.bottom;
|
||||
}
|
||||
};
|
||||
|
||||
class RenderTable {
|
||||
public:
|
||||
RenderTable(ZVision *engine, uint16 numRows, uint16 numColumns, const Graphics::PixelFormat &pixelFormat);
|
||||
~RenderTable();
|
||||
|
||||
// Common::Point testPixel = Common::Point(255,0);
|
||||
public:
|
||||
enum RenderState {
|
||||
PANORAMA,
|
||||
TILT,
|
||||
FLAT
|
||||
};
|
||||
|
||||
private:
|
||||
ZVision *_engine;
|
||||
OSystem *_system;
|
||||
uint16 _numRows, _numColumns, _halfRows, _halfColumns; // Working area width, height; half width, half height, in whole pixels
|
||||
float _halfWidth, _halfHeight; // Centre axis to midpoint of outermost pixel
|
||||
FilterPixel *_internalBuffer;
|
||||
RenderState _renderState;
|
||||
bool _highQuality = false;
|
||||
const Graphics::PixelFormat _pixelFormat;
|
||||
|
||||
inline void splitColor(uint16 &color, uint32 &r, uint32 &g, uint32 &b) const {
|
||||
// NB Left & right shifting unnecessary for interpolating & recombining, so not bothering in order to save cycles
|
||||
r = color & 0x001f;
|
||||
g = color & 0x03e0;
|
||||
b = color & 0x7c00;
|
||||
}
|
||||
inline uint16 mergeColor(const uint32 &r, const uint32 &g, const uint32 &b) const {
|
||||
// NB Red uses the lowest bits in RGB555 and so doesn't need its fractional bits masked away after averaging
|
||||
return r | (g & 0x03e0) | (b & 0x7c00);
|
||||
}
|
||||
|
||||
|
||||
struct {
|
||||
float verticalFOV; // Radians
|
||||
float linearScale;
|
||||
bool reverse;
|
||||
uint16 zeroPoint;
|
||||
} _panoramaOptions;
|
||||
|
||||
struct {
|
||||
float verticalFOV; // Radians
|
||||
float linearScale;
|
||||
bool reverse;
|
||||
float gap;
|
||||
} _tiltOptions;
|
||||
|
||||
public:
|
||||
RenderState getRenderState() {
|
||||
return _renderState;
|
||||
}
|
||||
void setRenderState(RenderState newState);
|
||||
|
||||
const Common::Point convertWarpedCoordToFlatCoord(const Common::Point &point); // input point in working area coordinates
|
||||
|
||||
// void mutateImage(uint16 *sourceBuffer, uint16 *destBuffer, uint32 destWidth, const Common::Rect &subRect);
|
||||
void mutateImage(Graphics::Surface *dstBuf, Graphics::Surface *srcBuf, bool filter = false);
|
||||
template <typename I>
|
||||
Common::String pixelToBinary(const I &pixel, bool splitColors = true) const {
|
||||
uint8 bits = sizeof(pixel) << 3;
|
||||
Common::String str("0b");
|
||||
I spaceMask = 0;
|
||||
for (uint8 i = 0; i < 3; i++)
|
||||
spaceMask = (spaceMask << 5) + 0x10;
|
||||
for (I mask = 0x01 << (bits - 1); mask; mask >>= 1) {
|
||||
if (splitColors && (spaceMask & mask))
|
||||
str += " ";
|
||||
str += mask & pixel ? "1" : "0";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
void generateRenderTable();
|
||||
|
||||
void setPanoramaFoV(float fov); // Degrees
|
||||
void setPanoramaScale(float scale);
|
||||
void setPanoramaReverse(bool reverse);
|
||||
void setPanoramaZeroPoint(uint16 point);
|
||||
uint16 getPanoramaZeroPoint();
|
||||
bool getPanoramaReverse();
|
||||
|
||||
void setTiltFoV(float fov); // Degrees
|
||||
void setTiltScale(float scale);
|
||||
void setTiltReverse(bool reverse);
|
||||
|
||||
float getTiltGap();
|
||||
float getAngle();
|
||||
float getLinscale();
|
||||
|
||||
private:
|
||||
void generateLookupTable(bool tilt = false);
|
||||
void generatePanoramaLookupTable();
|
||||
void generateTiltLookupTable();
|
||||
};
|
||||
|
||||
} // End of namespace ZVision
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user