mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-08 02:42:34 +00:00
811 lines
17 KiB
C++
811 lines
17 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/>.
|
|
*
|
|
*/
|
|
|
|
#include "common/math.h"
|
|
|
|
#include "petka/walk.h"
|
|
#include "petka/petka.h"
|
|
#include "petka/q_manager.h"
|
|
#include "petka/q_system.h"
|
|
#include "petka/objects/heroes.h"
|
|
|
|
namespace Petka {
|
|
|
|
const char *const wayPrefixes[] = {"-w-n.", "-w-ne.", "-w-e.", "-w-se.", "-w-s.", "-w-sw.", "-w-w.", "-w-nw."};
|
|
|
|
const double kPI = M_PI;
|
|
const double k2PI = M_PI * 2;
|
|
const double kHalfPI = M_PI_2;
|
|
|
|
const double kPiArray[] = {M_PI_2, M_PI_4, 0.0, -M_PI_4, -M_PI_2, -3 * M_PI_4, M_PI, 3 * M_PI_4};
|
|
|
|
Walk::Walk(int id) { // CHECKED
|
|
QManager *mgr = g_vm->resMgr();
|
|
|
|
Common::String res = mgr->findResourceName(id);
|
|
res.toLowercase();
|
|
res = res.substr(0, res.find(wayPrefixes[0]));
|
|
for (int i = 0; i < 8; ++i) {
|
|
waysSizes[i] = readWayFile(res + Common::String(wayPrefixes[i]) + "off", &_off1[i], &_off2[i]) - 1;
|
|
readWayFile(res + Common::String(wayPrefixes[i]) + "leg", &_leg1[i], &_leg2[i]);
|
|
}
|
|
|
|
for (int i = 0; i < 8; ++i) {
|
|
_offleg1[i] = new int[waysSizes[i] + 1];
|
|
_offleg2[i] = new int[waysSizes[i] + 1];
|
|
for (int j = 1; j <= waysSizes[i]; ++j) {
|
|
_offleg1[i][j] = _leg1[i][j] + _off1[i][j] - _leg1[i][j - 1];
|
|
_offleg2[i][j] = _leg2[i][j] + _off2[i][j] - _leg2[i][j - 1];
|
|
}
|
|
_offleg1[i][0] = _offleg1[i][waysSizes[i]];
|
|
_offleg2[i][0] = _offleg2[i][waysSizes[i]];
|
|
}
|
|
for (int i = 0; i < 8; ++i) {
|
|
int v16 = 0;
|
|
int v18 = 0;
|
|
int idx = 1;
|
|
for (int j = 0; j < 150; ++j) {
|
|
v16 += _offleg1[i][idx];
|
|
v18 += _offleg2[i][idx];
|
|
idx = (idx + 1) % waysSizes[i];
|
|
}
|
|
field_D0[i] = (double)v18 / v16;
|
|
}
|
|
|
|
currX = 0.0;
|
|
currY = 0.0;
|
|
_bkg3Count = 0;
|
|
_edgesCount = 0;
|
|
field_134 = 0;
|
|
_verticesCount = 0;
|
|
_bkg3_1 = nullptr;
|
|
_bkg3_2 = nullptr;
|
|
_edges = nullptr;
|
|
_bkg3_3 = nullptr;
|
|
_bkg3_4 = nullptr;
|
|
_bkg3_5 = nullptr;
|
|
_vertices = nullptr;
|
|
field_190 = 0;
|
|
resId = 0;
|
|
|
|
field_170 = field_178 = 0.0;
|
|
field_180 = field_181 = field_182 = field_183 = field_184 = field_185 =
|
|
field_186 = field_187 = field_188 = field_189 = field_18A = field_18B =
|
|
field_18C = field_18D = field_18E = field_18F = 0;
|
|
field_194 = 0;
|
|
field_198 = 0.0;
|
|
destX = destY = 0;
|
|
field_1C4 = field_1C5 = field_1C6 = field_1C7 = 0;
|
|
}
|
|
|
|
Walk::~Walk() { // CHECKED
|
|
clearBackground();
|
|
reset();
|
|
for (int i = 0; i < 8; ++i) {
|
|
delete[] _leg1[i];
|
|
delete[] _leg2[i];
|
|
delete[] _off1[i];
|
|
delete[] _off2[i];
|
|
delete[] _offleg1[i];
|
|
delete[] _offleg2[i];
|
|
|
|
_leg1[i] = nullptr;
|
|
_leg2[i] = nullptr;
|
|
_off1[i] = nullptr;
|
|
_off2[i] = nullptr;
|
|
_offleg1[i] = nullptr;
|
|
_offleg2[i] = nullptr;
|
|
|
|
waysSizes[i] = 0;
|
|
}
|
|
}
|
|
|
|
void Walk::init(Point start, Point end) {
|
|
reset();
|
|
field_134 = 1;
|
|
|
|
int v5 = sub_424230(&end) ? moveInside(&end) : sub_423600(end);
|
|
_bkg3_4[0] = sub_424230(&start) ? moveInside(&start) : sub_423600(start);
|
|
|
|
|
|
destX = end.x;
|
|
destY = end.y;
|
|
|
|
currX = end.x;
|
|
currY = end.y;
|
|
|
|
if (start == end)
|
|
return;
|
|
|
|
if (sub_424160(&start, &end) || v5 != _bkg3_4[0]) {
|
|
for (int i = 0; i < _bkg3Count; ++i)
|
|
_bkg3_5[i] = -1;
|
|
|
|
field_134 = 1;
|
|
if (_bkg3_4[0] != v5) {
|
|
do {
|
|
_bkg3_4[field_134] = sub_423970(_bkg3_4[field_134 - 1], _bkg3_5[field_134 - 1]);
|
|
if (_bkg3_4[field_134] >= 0) {
|
|
_bkg3_5[field_134 - 1] = _bkg3_4[field_134];
|
|
if (field_134 <= 1 || _bkg3_4[field_134 - 2] != _bkg3_4[field_134])
|
|
field_134++;
|
|
} else {
|
|
field_134--;
|
|
_bkg3_4[field_134] = -1;
|
|
_bkg3_5[field_134] = -1;
|
|
}
|
|
|
|
} while (_bkg3_4[field_134 - 1] != v5);
|
|
}
|
|
|
|
int v20 = 1;
|
|
int v21 = 4;
|
|
int v22 = 1;
|
|
int a2 = 4;
|
|
_bkg3_3[0] = start;
|
|
if (field_134 > 1) {
|
|
do {
|
|
int v23 = sub_423A30(_bkg3_4[(v21 - 4) / 4], _bkg3_4[v21 / 4]);
|
|
_bkg3_3[v22].x = (_vertices[_edges[v23].x].x + _vertices[_edges[v23].y].x) / 2;
|
|
_bkg3_3[v22].y = (_vertices[_edges[v23].x].y + _vertices[_edges[v23].y].y) / 2;
|
|
|
|
if (v22 > 1 && !sub_424160(&_bkg3_3[v22 - 2], &_bkg3_3[v22])) {
|
|
v20--;
|
|
|
|
_bkg3_3[v22 - 1] = _bkg3_3[v22];
|
|
|
|
v22--;
|
|
field_134--;
|
|
}
|
|
|
|
v21 = a2 + 4;
|
|
v20++;
|
|
v22++;
|
|
a2 += 4;
|
|
} while (v20 < field_134);
|
|
}
|
|
|
|
_bkg3_3[v20] = end;
|
|
if (v20 > 1 && !sub_424160(_bkg3_3 + v20 - 2, _bkg3_3 + v20)) {
|
|
_bkg3_3[v20 - 1] = _bkg3_3[v20];
|
|
field_134--;
|
|
}
|
|
field_134++;
|
|
} else {
|
|
_bkg3_3[0] = start;
|
|
_bkg3_3[1] = end;
|
|
field_134 = 2;
|
|
}
|
|
|
|
sub_422EA0(_bkg3_3[0], _bkg3_3[1]);
|
|
field_14C = 1;
|
|
}
|
|
|
|
void Walk::clearBackground() { // CHECKED
|
|
delete[] _vertices;
|
|
_vertices = nullptr;
|
|
_verticesCount = 0;
|
|
|
|
|
|
if (_bkg3_1) {
|
|
if (_bkg3_2) {
|
|
for (int i = 0; i < _bkg3Count; ++i) {
|
|
delete[] _bkg3_2[i];
|
|
_bkg3_2[i] = nullptr;
|
|
}
|
|
delete[] _bkg3_2;
|
|
_bkg3_2 = nullptr;
|
|
}
|
|
delete[] _bkg3_1;
|
|
_bkg3_1 = nullptr;
|
|
_bkg3Count = 0;
|
|
}
|
|
|
|
delete[] _edges;
|
|
_edges = nullptr;
|
|
_edgesCount = 0;
|
|
|
|
delete[] _bkg3_3;
|
|
_bkg3_3 = nullptr;
|
|
|
|
delete[] _bkg3_4;
|
|
_bkg3_4 = nullptr;
|
|
|
|
delete[] _bkg3_5;
|
|
_bkg3_5 = nullptr;
|
|
}
|
|
|
|
void Walk::setBackground(Common::String name) { // CHECKED
|
|
clearBackground();
|
|
|
|
name.toLowercase();
|
|
name.replace(name.size() - 3, 3, "cvx");
|
|
|
|
Common::SeekableReadStream *stream = g_vm->openFile(name, false);
|
|
if (!stream)
|
|
return;
|
|
|
|
_verticesCount = stream->readUint32LE();
|
|
_vertices = new Point[_verticesCount];
|
|
|
|
for (int i = 0; i < _verticesCount; ++i) {
|
|
_vertices[i].x = stream->readUint32LE();
|
|
_vertices[i].y = stream->readUint32LE();
|
|
}
|
|
|
|
_edgesCount = stream->readUint32LE();
|
|
_edges = new Point[_edgesCount];
|
|
|
|
for (int i = 0; i < _edgesCount; ++i) {
|
|
_edges[i].x = stream->readUint32LE();
|
|
_edges[i].y = stream->readUint32LE();
|
|
}
|
|
|
|
_bkg3Count = stream->readUint32LE();
|
|
_bkg3_1 = new int[_bkg3Count];
|
|
|
|
stream->read(_bkg3_1, 4 * _bkg3Count);
|
|
|
|
_bkg3_2 = new int*[_bkg3Count];
|
|
|
|
for (int i = 0; i < _bkg3Count; ++i) {
|
|
_bkg3_2[i] = new int[_bkg3_1[i]];
|
|
stream->read(_bkg3_2[i], 4 * _bkg3_1[i]);
|
|
}
|
|
|
|
delete stream;
|
|
_bkg3_3 = new Point[_bkg3Count + 1];
|
|
_bkg3_4 = new int[_bkg3Count + 1];
|
|
_bkg3_5 = new int[_bkg3Count + 1];
|
|
|
|
}
|
|
|
|
void Walk::reset() { // CHECKED
|
|
field_140 = 0.0;
|
|
field_138 = 0.0;
|
|
currX = 0;
|
|
currY = 0;
|
|
resId = 0;
|
|
field_14C = 0;
|
|
field_190 = 0;
|
|
field_194 = 0;
|
|
}
|
|
|
|
Common::Point Walk::currPos() { // CHECKED
|
|
return Common::Point(currX, currY);
|
|
}
|
|
|
|
int Walk::getSpriteId() { // CHECKED
|
|
return resId;
|
|
}
|
|
|
|
int Walk::commonPoint(int idx1, int idx2) { // CHECKED
|
|
if (_edges[idx1].x == _edges[idx2].x || _edges[idx1].x == _edges[idx2].y)
|
|
return _edges[idx1].x;
|
|
|
|
if (_edges[idx1].y == _edges[idx2].x || _edges[idx1].y == _edges[idx2].y)
|
|
return _edges[idx1].y;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Walk::readWayFile(const Common::String &name, int **p1, int **p2) { // CHECKED
|
|
Common::SeekableReadStream *stream = g_vm->openFile(name, false);
|
|
if (!stream) {
|
|
p1 = nullptr;
|
|
p2 = nullptr;
|
|
return 0;
|
|
}
|
|
|
|
const uint items = (uint)stream->size() / 8;
|
|
|
|
*p1 = new int[items];
|
|
*p2 = new int[items];
|
|
|
|
stream->skip(4);
|
|
for (uint i = 0; i < items; ++i) {
|
|
stream->read(&(*p1)[i], 4);
|
|
stream->read(&(*p2)[i], 4);
|
|
}
|
|
|
|
delete stream;
|
|
return items;
|
|
}
|
|
|
|
int Walk::sub_422EA0(Point p1, Point p2) {
|
|
if (p1 == p2)
|
|
return 0;
|
|
|
|
Point p = p1;
|
|
p.x += 150;
|
|
|
|
double v5 = angle(p1, p, p2);
|
|
double v6;
|
|
if (v5 >= 0.0)
|
|
v6 = k2PI - v5;
|
|
else
|
|
v6 = v5 + k2PI;
|
|
|
|
double v30 = 4.0;
|
|
for (uint i = 0; i < ARRAYSIZE(kPiArray); ++i) {
|
|
double v9 = v5 - kPiArray[i];
|
|
if (v9 < 0.0)
|
|
v9 = -v9;
|
|
if (v9 < v30) {
|
|
v30 = v9;
|
|
resId = i;
|
|
}
|
|
|
|
double v10 = v6 - kPiArray[i];
|
|
if (v10 < 0.0)
|
|
v10 = -v10;
|
|
if (v10 < v30) {
|
|
v30 = v10;
|
|
resId = i;
|
|
}
|
|
}
|
|
|
|
double v28 = p2.x - p1.x;
|
|
double v26 = p2.y - p1.y;
|
|
double v12 = Common::hypotenuse(p2.x - p1.x, p2.y - p1.y);
|
|
|
|
double v39 = 1.0 / sqrt(field_D0[resId] * field_D0[resId] - -1.0);
|
|
if (v39 == 0.0)
|
|
field_140 = v28 / v12;
|
|
else
|
|
field_140 = (field_D0[resId] - -1.0 / (v26 / v28)) * (v26 / v12) * v39;
|
|
|
|
DBLPoint a1;
|
|
DBLPoint a2;
|
|
DBLPoint a3;
|
|
|
|
a1.x = p1.x;
|
|
a1.y = p1.y;
|
|
|
|
a2.x = p2.x;
|
|
a2.y = p2.y;
|
|
|
|
a3.x = p2.x;
|
|
a3.y = field_D0[resId] * v28 + p1.y;
|
|
|
|
double v13 = angle(a1, a2, a3);
|
|
field_140 = cos(v13);
|
|
field_138 = sin(v13);
|
|
|
|
double v16 = v13;
|
|
if (v13 < -kHalfPI)
|
|
v16 = v13 + kPI;
|
|
if (v13 > kHalfPI)
|
|
v16 = v13 - kPI;
|
|
|
|
field_140 = cos(v16);
|
|
field_138 = sin(v16);
|
|
|
|
int v32 = 1;
|
|
double v34 = 0.0;
|
|
double v35 = 0.0;
|
|
double v36 = p1.y;
|
|
v39 = v28 * v28 + v26 * v26 - -1.0;
|
|
|
|
int j = 0;
|
|
for (int i = 0; i < 10;) {
|
|
double k = g_vm->getQSystem()->getPetka()->calcPerspective(v36);
|
|
|
|
v34 += _offleg1[resId][v32] * k;
|
|
v35 += _offleg2[resId][v32] * k;
|
|
|
|
j++;
|
|
|
|
v32 = (v32 + 1) % waysSizes[resId];
|
|
|
|
v36 = v35 * field_140 + v34 * field_138 + p1.y;
|
|
|
|
double v22 = v34 * field_140 - v35 * field_138 + p1.x - p2.x;
|
|
double v38 = v36 - p2.y;
|
|
|
|
double v23 = v22 * v22 + v38 * v38;
|
|
if (v23 >= v39) {
|
|
i++;
|
|
} else {
|
|
v39 = v23;
|
|
field_194 = j;
|
|
i = 0;
|
|
}
|
|
}
|
|
|
|
field_170 = 0;
|
|
field_178 = 0;
|
|
|
|
currX = p1.x;
|
|
currY = p1.y;
|
|
|
|
field_150 = p1.x;
|
|
field_158 = p1.y;
|
|
|
|
field_190 = 0;
|
|
field_198 = g_vm->getQSystem()->getPetka()->calcPerspective(p1.y);
|
|
return resId;
|
|
}
|
|
|
|
int Walk::sub_423350() { // CHECKED
|
|
field_190 = (field_190 + 1) % waysSizes[resId];
|
|
|
|
--field_194;
|
|
if (field_194 < 0) {
|
|
field_14C++;
|
|
if (field_14C < field_134) {
|
|
int t = field_190;
|
|
int id = resId;
|
|
if (id == sub_422EA0(_bkg3_3[field_14C - 1], _bkg3_3[field_14C])) {
|
|
field_190 = t;
|
|
return 1;
|
|
}
|
|
return 2;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
field_198 = g_vm->getQSystem()->getPetka()->calcPerspective(currY);
|
|
field_170 = _offleg1[resId][field_190] * field_198 + field_170;
|
|
field_178 = _offleg2[resId][field_190] * field_198 + field_178;
|
|
|
|
currX = field_140 * field_170 - field_178 * field_138 + field_150;
|
|
currY = field_140 * field_178 + field_138 * field_170 + field_158;
|
|
|
|
return 1;
|
|
}
|
|
|
|
Common::Point Walk::sub_4234B0() { // CHECKED
|
|
Common::Point p;
|
|
field_198 = g_vm->getQSystem()->getPetka()->calcPerspective(currY);
|
|
p.x = currX - _leg1[resId][field_190] * field_198;
|
|
p.y = currY - _leg2[resId][field_190] * field_198;
|
|
return p;
|
|
}
|
|
|
|
bool Walk::areEdgesAdjacent(int first_index, int second_index) { // CHECKED
|
|
if (first_index != second_index) {
|
|
if (_edges[first_index].x == _edges[second_index].x ||
|
|
_edges[first_index].x == _edges[second_index].y ||
|
|
_edges[first_index].y == _edges[second_index].x ||
|
|
_edges[first_index].y == _edges[second_index].y) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int Walk::sub_423600(Point p) {
|
|
int j = 0;
|
|
for (int i = 0; i < _bkg3Count; ++i, ++j) {
|
|
int *v4 = new int[_bkg3_1[j]];
|
|
v4[0] = _bkg3_2[j][0];
|
|
|
|
for (int k = 0; k < _bkg3_1[j]; ++k) {
|
|
if (areEdgesAdjacent(v4[0], _bkg3_2[j][k])) {
|
|
v4[1] = _bkg3_2[j][k];
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (int k = 2; k < _bkg3_1[j]; ++k) {
|
|
for (int l = 0; l < _bkg3_1[j]; ++l) {
|
|
if (areEdgesAdjacent(v4[k - 1], _bkg3_2[j][l]) && v4[k - 2] != _bkg3_2[j][l]) {
|
|
v4[k] = _bkg3_2[j][l];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
int v11 = commonPoint(v4[_bkg3_1[j] - 1], v4[0]);
|
|
int v31 = commonPoint(v4[0], v4[1]);
|
|
|
|
double v12 = angle(p, _vertices[v11], _vertices[v31]);
|
|
if (p == _vertices[v11] || p == _vertices[v31]) {
|
|
delete[] v4;
|
|
return i;
|
|
}
|
|
|
|
|
|
int k;
|
|
for (k = 1; k < _bkg3_1[j] - 1; ++k) {
|
|
int v16 = commonPoint(v4[k - 1], v4[k]);
|
|
int v32 = commonPoint(v4[k], v4[k + 1]);
|
|
|
|
v12 += angle(p, _vertices[v16], _vertices[v32]);
|
|
if (p == _vertices[v16] || p == _vertices[v32]) {
|
|
delete[] v4;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
int v19 = commonPoint(v4[k - 1], v4[k]);
|
|
int v20 = commonPoint(v4[k], v4[0]);
|
|
|
|
delete[] v4;
|
|
|
|
double v23 = angle(p, _vertices[v19], _vertices[v20]);
|
|
v12 += v23;
|
|
|
|
if (p == _vertices[v19] || p == _vertices[v20])
|
|
return i;
|
|
|
|
if (v12 < 0.0)
|
|
v12 = -v12;
|
|
|
|
if (v12 > kPI)
|
|
return i;
|
|
}
|
|
debug("Walk bug: Point doesn't belong to any convex");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Walk::sub_423970(int a1, int a2) { // CHECKED
|
|
int index = 0;
|
|
if (a2 >= 0) {
|
|
int v5 = sub_423A30(a1, a2);
|
|
for (int i = 0; i < _bkg3_1[a1]; ++i) {
|
|
if (_bkg3_2[a1][i] == v5) {
|
|
index = i + 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = index; i < _bkg3_1[a1]; ++i) {
|
|
for (int j = 0; j < _bkg3Count; ++j) {
|
|
if (j == a1)
|
|
continue;
|
|
|
|
for (int k = 0; k < _bkg3_1[j]; ++k) {
|
|
if (_bkg3_2[j][k] == _bkg3_2[a1][i]) {
|
|
return j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int Walk::sub_423A30(int idx1, int idx2) { // CHECKED
|
|
for (int i = 0; i < _bkg3_1[idx1]; ++i) {
|
|
for (int j = 0; j < _bkg3_1[idx2]; ++j) {
|
|
if (_bkg3_2[idx1][i] == _bkg3_2[idx2][j])
|
|
return _bkg3_2[idx1][i];
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
double Walk::angle(Point p1, Point p2, Point p3) { // CHECKED
|
|
return angle(DBLPoint(p1), DBLPoint(p2), DBLPoint(p3));
|
|
}
|
|
|
|
double Walk::angle(DBLPoint p1, DBLPoint p2, DBLPoint p3) { // CHECKED
|
|
if (p1 == p2 || p1 == p3)
|
|
return 0.0;
|
|
|
|
double xv1 = p2.x - p1.x;
|
|
double xv2 = p3.x - p1.x;
|
|
|
|
double yv1 = p2.y - p1.y;
|
|
double yv2 = p3.y - p1.y;
|
|
|
|
double mv1 = Common::hypotenuse(xv1, yv1);
|
|
double mv2 = Common::hypotenuse(xv2, yv2);
|
|
double v13 = (xv1 * xv2 + yv1 * yv2) / (mv1 * mv2);
|
|
if ((xv2 / mv2 * (yv1 / mv1) - yv2 / mv2 * (xv1 / mv1)) < 0.0) // Not sure
|
|
return -acos(v13);
|
|
return acos(v13);
|
|
}
|
|
|
|
int Walk::sub_423E00(Point p1, Point p2, Point p3, Point p4, Point &p5) {
|
|
if (p1.x > p2.x) {
|
|
SWAP(p2, p1);
|
|
}
|
|
|
|
if (p3.x > p4.x) {
|
|
SWAP(p3, p4);
|
|
}
|
|
|
|
double v11 = (p2.y - p1.y) * (p4.x - p3.x);
|
|
double v12 = (p2.x - p1.x) * (p4.y - p3.y);
|
|
if (v11 == v12)
|
|
return 0;
|
|
|
|
double v30;
|
|
if (p2.x - p1.x) {
|
|
if (p4.x - p3.x) {
|
|
v30 = ((double)(p3.y - p1.y) * (p4.x - p3.x) * (p2.x - p1.x) + (v11 * p1.x) - (v12 * p3.x)) / (v11 - v12);
|
|
if (v30 < p1.x || p3.x > v30 || p2.x < v30 || p4.x < v30)
|
|
return 0;
|
|
} else {
|
|
v30 = p3.x;
|
|
if (p3.x < p1.x || p2.x < p3.x)
|
|
return 0;
|
|
}
|
|
} else {
|
|
v30 = p1.x;
|
|
if (p1.x < p3.x)
|
|
return 0;
|
|
if (p4.x < p1.x)
|
|
return 0;
|
|
}
|
|
|
|
if (p1.y > p2.y) {
|
|
SWAP(p1, p2);
|
|
}
|
|
|
|
if (p3.y > p4.y) {
|
|
SWAP(p3, p4);
|
|
}
|
|
|
|
if (p2.y - p1.y) {
|
|
if (p4.y - p3.y) {
|
|
double v21;
|
|
if (p2.x - p1.x) {
|
|
v21 = (v30 - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y;
|
|
} else {
|
|
v21 = (v30 - p3.x) * (p4.y - p3.y) / (p4.x - p3.x) + p3.y;
|
|
}
|
|
|
|
if (v21 >= p1.y && v21 >= p3.y && v21 <= p2.y && v21 <= p4.y) {
|
|
p5.x = v30;
|
|
p5.y = v21;
|
|
return 1;
|
|
}
|
|
|
|
} else {
|
|
if (p3.y >= p1.y) {
|
|
if (p3.y > p2.y)
|
|
return 0;
|
|
p5.x = v30;
|
|
p5.y = p3.y;
|
|
return 1;
|
|
}
|
|
}
|
|
} else {
|
|
if (p1.y >= p3.y) {
|
|
if (p1.y <= p4.y) {
|
|
p5.x = v30;
|
|
p5.y = p1.y;
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool Walk::sub_424160(Point *p1, Point *p2) { // CHECKED
|
|
if (*p1 == *p2)
|
|
return false;
|
|
|
|
Point p;
|
|
int v = 1;
|
|
if (_verticesCount <= 1)
|
|
return sub_423E00(_vertices[v - 1], _vertices[0], *p1, *p2, p) != 0;
|
|
|
|
while (!sub_423E00(_vertices[v - 1], _vertices[v], *p1, *p2, p)) {
|
|
if (++v >= _verticesCount)
|
|
return sub_423E00(_vertices[v - 1], _vertices[0], *p1, *p2, p) != 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Walk::sub_424230(Point *p1) { // CHECKED
|
|
Point p(0, 0);
|
|
int v = sub_424320(p1, &p);
|
|
|
|
p.y = p1->y;
|
|
v = (sub_424320(p1, &p) & 1) + (v & 1);
|
|
|
|
p.y = 480;
|
|
v = (sub_424320(p1, &p) & 1) + v;
|
|
v = (sub_424320(p1, &p) & 1) + v;
|
|
|
|
p.x = 640;
|
|
v = (sub_424320(p1, &p) & 1) + v;
|
|
|
|
p.y = p1->y;
|
|
v = (sub_424320(p1, &p) & 1) + v;
|
|
|
|
p.y = 0;
|
|
v = (sub_424320(p1, &p) & 1) + v;
|
|
|
|
p.x = p1->x;
|
|
return (sub_424320(p1, &p) & 1) + v < 4;
|
|
}
|
|
|
|
int Walk::sub_424320(Point *p1, Point *p2) { // CHECKED
|
|
if (*p1 == *p2)
|
|
return 0;
|
|
|
|
int ret = 0;
|
|
|
|
Point p;
|
|
|
|
int i;
|
|
for (i = 1; i < _verticesCount; ++i) {
|
|
if (sub_423E00(_vertices[i - 1], _vertices[i], *p1, *p2, p) && *p1 != p && *p2 != p) {
|
|
ret++;
|
|
}
|
|
}
|
|
|
|
if (sub_423E00(_vertices[i - 1], _vertices[0], *p1, *p2, p) && *p1 != p && *p2 != p) {
|
|
ret++;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int Walk::moveInside(Point *p) { // CHECKED
|
|
DBLPoint dp = sub_424610(_vertices[_edges->x], _vertices[_edges->y].x, _vertices[_edges->y].y, *p);
|
|
|
|
int index = 0;
|
|
|
|
double min = (dp.y - p->y) * (dp.y - p->y) + (dp.x - p->x) * (dp.x - p->x);
|
|
for (int i = 1; i < _verticesCount; ++i) {
|
|
DBLPoint dp1 = sub_424610(_vertices[_edges[i].x], _vertices[_edges[i].y].x, _vertices[_edges[i].y].y, *p);
|
|
double curr = (dp1.y - p->y) * (dp1.y - p->y) + (dp1.x - p->x) * (dp1.x - p->x);
|
|
if (curr < min) {
|
|
dp = dp1;
|
|
min = curr;
|
|
index = i;
|
|
}
|
|
|
|
}
|
|
|
|
p->x = dp.x;
|
|
p->y = dp.y;
|
|
|
|
|
|
for (int i = 0; i < _verticesCount; ++i) {
|
|
for (int j = 0; j < _bkg3_1[i]; ++j) {
|
|
if (_bkg3_2[i][j] == index)
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
DBLPoint Walk::sub_424610(Point p1, int x, int y, Point p2) { // CHECKED
|
|
DBLPoint p;
|
|
double v13;
|
|
double v14;
|
|
if (p1.x == x) {
|
|
v13 = p1.x;
|
|
v14 = p2.y;
|
|
} else {
|
|
double v6 = (double)(y - p1.y) / (x - p1.x);
|
|
double v7 = p1.y - v6 * p1.x;
|
|
v13 = ((p2.y - v7) * v6 + p2.x) / (v6 * v6 - -1.0);
|
|
v14 = v13 * v6 + v7;
|
|
}
|
|
p.x = CLIP<double>(v13, MIN<int>(x, p1.x), MAX<int>(x, p1.x));
|
|
p.y = CLIP<double>(v14, MIN<int>(y, p1.y), MAX<int>(y, p1.y));
|
|
return p;
|
|
}
|
|
|
|
} // End of namespace Petka
|