mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
505 lines
14 KiB
C++
505 lines
14 KiB
C++
/* 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 QDENGINE_QDCORE_QD_CAMERA_H
|
||
#define QDENGINE_QDCORE_QD_CAMERA_H
|
||
|
||
#include "qdengine/qdcore/qd_d3dutils.h"
|
||
#include "qdengine/qdcore/qd_camera_mode.h"
|
||
|
||
namespace Common {
|
||
class WriteStream;
|
||
}
|
||
|
||
namespace QDEngine {
|
||
|
||
class sGridCell {
|
||
public:
|
||
//! Атрибуты
|
||
enum cell_attribute_t {
|
||
//! ячейка выделена
|
||
CELL_SELECTED = 0x01,
|
||
//! ячейка непроходима
|
||
CELL_IMPASSABLE = 0x02,
|
||
//! ячейка занята объектом
|
||
CELL_OCCUPIED = 0x04,
|
||
//! ячейка занята персонажем
|
||
CELL_PERSONAGE_OCCUPIED = 0x08,
|
||
//! по ячейке проходит путь персонажа
|
||
CELL_PERSONAGE_PATH = 0x10
|
||
};
|
||
|
||
sGridCell() {
|
||
_attributes = CELL_IMPASSABLE;
|
||
}
|
||
sGridCell(uint16 atr, int16 h) {
|
||
_attributes = atr;
|
||
}
|
||
~sGridCell() { }
|
||
|
||
bool is_walkable() const {
|
||
return check_attribute(CELL_IMPASSABLE);
|
||
}
|
||
void make_impassable() {
|
||
set_attribute(CELL_IMPASSABLE);
|
||
}
|
||
void make_walkable() {
|
||
drop_attribute(CELL_IMPASSABLE);
|
||
}
|
||
|
||
void select() {
|
||
set_attribute(CELL_SELECTED);
|
||
}
|
||
void deselect() {
|
||
drop_attribute(CELL_SELECTED);
|
||
}
|
||
void toggle_select() {
|
||
toggle_attribute(CELL_SELECTED);
|
||
}
|
||
bool is_selected() const {
|
||
return check_attribute(CELL_SELECTED);
|
||
}
|
||
|
||
int16 height() const {
|
||
return 0;
|
||
}
|
||
void set_height(int16 h) { }
|
||
|
||
void set_attribute(uint32 attr) {
|
||
_attributes |= attr;
|
||
}
|
||
void toggle_attribute(uint32 attr) {
|
||
_attributes ^= attr;
|
||
}
|
||
void drop_attribute(uint32 attr) {
|
||
_attributes &= ~attr;
|
||
}
|
||
bool check_attribute(uint32 attr) const {
|
||
if (_attributes & attr) return true;
|
||
else return false;
|
||
}
|
||
|
||
uint32 attributes() const {
|
||
return _attributes;
|
||
}
|
||
void set_attributes(uint32 attr) {
|
||
_attributes = attr;
|
||
}
|
||
|
||
bool clear() {
|
||
_attributes = 0;
|
||
return true;
|
||
}
|
||
|
||
private:
|
||
byte _attributes;
|
||
};
|
||
|
||
enum qdCameraRedrawMode {
|
||
QDCAM_GRID_ABOVE,
|
||
QDCAM_GRID_ZBUFFER,
|
||
QDCAM_GRID_NONE
|
||
};
|
||
|
||
class qdCamera {
|
||
public:
|
||
qdCamera();
|
||
~qdCamera();
|
||
|
||
// Устанавливет параметры клетки с координатами cell_pos
|
||
// по параметрам клетки cell
|
||
bool set_grid_cell(const Vect2s &cell_pos, const sGridCell &cell);
|
||
bool set_grid_cell_attributes(const Vect2s &cell_pos, int attr);
|
||
|
||
//! Устанавливает атрибуты для клеток из прямоугольника на сетке с ценром center_pos и размерами size.
|
||
bool set_grid_attributes(const Vect2s ¢er_pos, const Vect2s &size, int attr);
|
||
//! Очищает атрибуты для клеток из прямоугольника на сетке с ценром center_pos и размерами size.
|
||
bool drop_grid_attributes(const Vect2s ¢er_pos, const Vect2s &size, int attr);
|
||
//! Возвращает true, если в прямоугольнике на сетке ЕСТЬ ХОТЯ БЫ ОДНА ячейка с атрибутами attr.
|
||
bool check_grid_attributes(const Vect2s ¢er_pos, const Vect2s &size, int attr) const;
|
||
//! Возвращает количество ячеек в заданной области, имеющих именно аттрибуты attr
|
||
int cells_num_with_exact_attributes(const Vect2s ¢er_pos, const Vect2s &size, int attr) const;
|
||
|
||
//! Устанавливает атрибуты для линии клеток.
|
||
bool set_grid_line_attributes(const Vect2s &start_pos, const Vect2s &end_pos, const Vect2s &size, int attr);
|
||
//! Очищает атрибуты для линии клеток.
|
||
bool drop_grid_line_attributes(const Vect2s &start_pos, const Vect2s &end_pos, const Vect2s &size, int attr);
|
||
//! Возвращает true, если в линии на сетке есть хотя бы одна ячейка с атрибутами attr.
|
||
bool check_grid_line_attributes(const Vect2s &start_pos, const Vect2s &end_pos, const Vect2s &size, int attr) const;
|
||
|
||
bool is_walkable(const Vect2s ¢er_pos, const Vect2s &size, bool ignore_personages = false) const;
|
||
|
||
//! Устанавливает атрибуты attr для всех клеток сетки.
|
||
bool set_grid_attributes(int attr);
|
||
//! Очищает атрибуты attr для всех клеток сетки.
|
||
bool drop_grid_attributes(int attr);
|
||
|
||
sGridCell *get_cell(const Vect2s &cell_pos);
|
||
const sGridCell *get_cell(const Vect2s &cell_pos) const;
|
||
|
||
// Восстанавливает параметры клетки (сейчас - делает ее непроходимой
|
||
// с нулевой высотой)
|
||
bool restore_grid_cell(const Vect2s cell_pos);
|
||
|
||
void cycle_coords(int &x, int &y) const;
|
||
|
||
void set_redraw_mode(int md) const {
|
||
_redraw_mode = md;
|
||
}
|
||
int get_redraw_mode() const {
|
||
return _redraw_mode;
|
||
}
|
||
|
||
void set_grid_size(int xs, int ys);
|
||
|
||
void scale_grid(int sx, int sy, int csx, int csy);
|
||
void resize_grid(int sx, int sy);
|
||
|
||
int get_grid_sx() const {
|
||
return _GSX;
|
||
}
|
||
int get_grid_sy() const {
|
||
return _GSY;
|
||
}
|
||
|
||
const sGridCell *get_grid() const {
|
||
return _grid;
|
||
}
|
||
|
||
int get_cell_sx() const {
|
||
return _cellSX;
|
||
}
|
||
int get_cell_sy() const {
|
||
return _cellSY;
|
||
}
|
||
|
||
void set_cell_size(int csx, int csy) {
|
||
_cellSX = csx;
|
||
_cellSY = csy;
|
||
}
|
||
|
||
void clear_grid();
|
||
|
||
// rotateAndScaling
|
||
void rotate_and_scale(float XA, float YA, float ZA, float kX, float kY, float kZ);
|
||
|
||
float get_focus() const {
|
||
return _focus;
|
||
}
|
||
void set_focus(float focus) {
|
||
_focus = focus;
|
||
}
|
||
|
||
void set_R(const float r);
|
||
float get_R() const {
|
||
return _m_fR;
|
||
}
|
||
|
||
float get_x_angle() const {
|
||
return _xAngle;
|
||
}
|
||
float get_y_angle() const {
|
||
return _yAngle;
|
||
}
|
||
float get_z_angle() const {
|
||
return _zAngle;
|
||
}
|
||
|
||
inline void set_scr_size(int xs, int ys) {
|
||
_scrSize.x = xs;
|
||
_scrSize.y = ys;
|
||
}
|
||
|
||
const Vect2i &get_scr_size() const {
|
||
return _scrSize;
|
||
}
|
||
|
||
// getScrSizeX
|
||
int get_scr_sx() const {
|
||
return _scrSize.x;
|
||
}
|
||
// getScrSizeY
|
||
int get_scr_sy() const {
|
||
return _scrSize.y;
|
||
}
|
||
|
||
void set_scr_center(int xc, int yc) {
|
||
_scrCenter.x = xc;
|
||
_scrCenter.y = yc;
|
||
}
|
||
|
||
const Vect2i &get_scr_center() const {
|
||
return _scrCenter;
|
||
}
|
||
|
||
int get_scr_center_x() const {
|
||
return _scrCenter.x;
|
||
}
|
||
int get_scr_center_y() const {
|
||
return _scrCenter.y;
|
||
}
|
||
|
||
const Vect2i screen_center_limit_x() const;
|
||
const Vect2i screen_center_limit_y() const;
|
||
|
||
const Vect2i &get_scr_offset() const {
|
||
return _scrOffset;
|
||
}
|
||
void set_scr_offset(const Vect2i &offs) {
|
||
_scrOffset = offs;
|
||
}
|
||
|
||
const Vect2i &get_scr_center_initial() const {
|
||
return _scrCenterInitial;
|
||
}
|
||
void set_scr_center_initial(const Vect2i &v) {
|
||
_scrCenterInitial = v;
|
||
}
|
||
|
||
void move_scr_center(int dxc, int dyc);
|
||
|
||
float scrolling_phase_x() const;
|
||
float scrolling_phase_y() const;
|
||
|
||
const Vect3f scr2plane(const Vect2s &scrPoint) const;
|
||
const Vect3f rscr2plane(const Vect2s &rscrPoint) const;
|
||
|
||
const Vect3f scr2plane_camera_coord(const Vect2s &scrPoint) const;
|
||
const Vect3f rscr2plane_camera_coord(const Vect2s &scrPoint) const;
|
||
const Vect2s plane2scr(const Vect3f &plnPoint) const;
|
||
const Vect2s plane2rscr(const Vect3f &plnPoint) const;
|
||
|
||
const Vect3f rscr2camera_coord(const Vect2s &rScrPoint, float z) const;
|
||
const Vect2s camera_coord2rscr(const Vect3f &coord) const;
|
||
|
||
const Vect2s rscr2scr(const Vect2s &v) const;
|
||
const Vect2s scr2rscr(const Vect2s &v) const;
|
||
|
||
const Vect2s camera_coord2scr(const Vect3f &coord) const;
|
||
|
||
const Vect3f scr2global(const Vect2s &vScrPoint, float zInCameraCoord) const;
|
||
const Vect3f rscr2global(const Vect2s rScrPoint, const float zInCameraCoord) const;
|
||
const Vect3f global2camera_coord(const Vect3f &glCoord) const;
|
||
const Vect3f camera_coord2global(const Vect3f &v) const;
|
||
|
||
const Vect2s global2scr(const Vect3f &glCoord) const;
|
||
const Vect2s global2rscr(const Vect3f &glCoord) const;
|
||
|
||
//обрезание отрезка по плоскости отсечения камеры
|
||
//возвращает false, если отрезок вообеще невидим
|
||
bool line_cutting(Vect3f &b, Vect3f &e) const;
|
||
//! Обрезка линиии, так чтобы она за сетку не выходила.
|
||
/**
|
||
Все координаты - сеточные, т.е. индексы ячеек сетки.
|
||
*/
|
||
bool clip_grid_line(Vect2s &v0, Vect2s &v1) const;
|
||
|
||
// getKScale
|
||
float get_scale(const Vect3f &glCoord) const;
|
||
|
||
const Vect3f &get_grid_center() const {
|
||
return _gridCenter;
|
||
}
|
||
void set_grid_center(const Vect3f &v) {
|
||
_gridCenter = v;
|
||
}
|
||
|
||
const sGridCell *get_cell(float X, float Y) const;
|
||
const Vect2s get_cell_index(float X, float Y, bool grid_crop = true) const;
|
||
const Vect2s get_cell_index(const Vect3f &v, bool grid_crop = true) const;
|
||
const Vect3f get_cell_coords(int x_idx, int y_idx) const;
|
||
const Vect3f get_cell_coords(const Vect2s &idxs) const;
|
||
|
||
void reset_all_select();
|
||
//принимает глобальные координаты
|
||
bool select_cell(int x, int y);
|
||
|
||
//принимает глобальные координаты
|
||
bool deselect_cell(int x, int y);
|
||
|
||
void load_script(const xml::tag *p);
|
||
bool save_script(Common::WriteStream &fh, int indent = 0) const;
|
||
|
||
//! Загрузка данных из сэйва.
|
||
bool load_data(Common::SeekableReadStream &fh, int save_version);
|
||
//! Запись данных в сэйв.
|
||
bool save_data(Common::WriteStream &fh) const;
|
||
|
||
//! Инициализация данных, вызывается при старте и перезапуске игры.
|
||
bool init();
|
||
|
||
bool draw_grid() const;
|
||
bool draw_cell(int x, int y, int z, int penWidth, uint32 color) const;
|
||
|
||
//! Установка текущего режима камеры.
|
||
/**
|
||
Если объект нулевой, то берется объект по-умолчанию.
|
||
*/
|
||
bool set_mode(const qdCameraMode &mode, qdGameObjectAnimated *object = NULL);
|
||
//! Возвращает true, если в данный момент можно менять режим камеры.
|
||
bool can_change_mode() const;
|
||
|
||
//! Установка объекта, за которым камера следит по умолчанию.
|
||
void set_default_object(qdGameObjectAnimated *p) {
|
||
_default_object = p;
|
||
}
|
||
|
||
//! Обсчет логики (движения камеры и т.д), параметр - время в секундах.
|
||
bool quant(float dt);
|
||
|
||
//! Возвращает false, если вся рабочая область камеры находится за пределами экрана.
|
||
/**
|
||
Параметр - дополнительное смещение центра рабочей области камеры.
|
||
*/
|
||
bool is_visible(const Vect2i ¢er_offs = Vect2i(0, 0)) const;
|
||
|
||
void set_cycle(bool cx, bool cy) {
|
||
_cycle_x = cx;
|
||
_cycle_y = cy;
|
||
}
|
||
|
||
void dump_grid(const char *file_name) const;
|
||
|
||
//! Параметры функции масштабирования
|
||
float scale_pow() const {
|
||
return _scale_pow;
|
||
}
|
||
void set_scale_pow(float sp) {
|
||
_scale_pow = sp;
|
||
}
|
||
float scale_z_offset() const {
|
||
return _scale_z_offset;
|
||
};
|
||
void set_scale_z_offset(float szo) {
|
||
_scale_z_offset = szo;
|
||
};
|
||
|
||
bool need_perspective_correction() const {
|
||
return (fabs(_scale_pow - 1) > 0.001 || fabs(_scale_z_offset) > 0.001);
|
||
}
|
||
|
||
//! Возвращает режим работы камеры по умолчанию.
|
||
const qdCameraMode &default_mode() const {
|
||
return _default_mode;
|
||
}
|
||
//! Установка режима работы камеры по умолчанию.
|
||
void set_default_mode(const qdCameraMode &mode) {
|
||
_default_mode = mode;
|
||
}
|
||
|
||
static qdCamera *current_camera() {
|
||
return _current_camera;
|
||
}
|
||
static void set_current_camera(qdCamera *p) {
|
||
_current_camera = p;
|
||
}
|
||
|
||
MATRIX3D const &get_view_matrix() const {
|
||
return _m_cam;
|
||
}
|
||
|
||
private:
|
||
|
||
MATRIX3D _m_cam;
|
||
float _m_fR;
|
||
float _xAngle, _yAngle, _zAngle;
|
||
|
||
int _GSX, _GSY;
|
||
sGridCell *_grid;
|
||
|
||
bool _cycle_x;
|
||
bool _cycle_y;
|
||
|
||
int _cellSX, _cellSY;
|
||
float _focus;//! расстояние до ближней плоскости отсечения
|
||
// расстояние от центра рабочей области до
|
||
// верхнего левого угла окна
|
||
Vect2i _scrCenter;
|
||
|
||
// начальное расстояние от центра рабочей области до
|
||
// верхнего левого угла окна
|
||
Vect2i _scrCenterInitial;
|
||
|
||
// размер рабочей области
|
||
Vect2i _scrSize;
|
||
// смещение рабочей области
|
||
Vect2i _scrOffset;
|
||
|
||
// Координаты центра сетки
|
||
Vect3f _gridCenter;
|
||
|
||
mutable int _redraw_mode;
|
||
|
||
//! Текущий режим работы камеры.
|
||
qdCameraMode _current_mode;
|
||
|
||
//! Время в секуднах с установки текущего режима.
|
||
float _current_mode_work_time;
|
||
bool _current_mode_switch;
|
||
|
||
//! Объект, за которым следит камера.
|
||
qdGameObjectAnimated *_current_object;
|
||
|
||
//! Объект, за которым камера следит по умолчанию.
|
||
qdGameObjectAnimated *_default_object;
|
||
//! Режим работы камеры по умолчанию.
|
||
qdCameraMode _default_mode;
|
||
|
||
//! Параметры функции ускоренного масштабирования из get_scale()
|
||
float _scale_pow;
|
||
float _scale_z_offset;
|
||
|
||
static qdCamera *_current_camera;
|
||
|
||
static const float _NEAR_PLANE; //ближная плоскость отсечения
|
||
static const float _FAR_PLANE; //дальняя
|
||
|
||
enum {
|
||
clLEFT = 1,
|
||
clRIGHT = 2,
|
||
clBOTTOM = 4,
|
||
clTOP = 8
|
||
};
|
||
|
||
inline int clip_out_code(const Vect2s &v) const {
|
||
int code = 0;
|
||
if (v.y >= _GSY)
|
||
code |= clTOP;
|
||
else if (v.y < 0)
|
||
code |= clBOTTOM;
|
||
if (v.x >= _GSX)
|
||
code |= clRIGHT;
|
||
else if (v.x < 0)
|
||
code |= clLEFT;
|
||
|
||
return code;
|
||
}
|
||
|
||
void clip_center_coords(int &x, int &y) const;
|
||
};
|
||
|
||
inline Vect3f To3D(const Vect2f &v) {
|
||
return Vect3f(v.x, v.y, 0);
|
||
}
|
||
|
||
} // namespace QDEngine
|
||
|
||
#endif // QDENGINE_QDCORE_QD_CAMERA_H
|