[Scummvm-git-logs] scummvm master -> a981967321b34a233fc0dfee5cfa1b1b7092a6ea
mduggan
noreply at scummvm.org
Sun Mar 5 22:29:37 UTC 2023
This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
7baf3da962 TETRAEDGE: Fix potential OOB access
e88685a379 TETRAEDGE: Don't apply spot cutoff in Syberia 2
48de219950 TETRAEDGE: Fix some bugs in Syberia 2 light config
68e14e6558 TETRAEDGE: Implement collisionSlide for Syberia 2
a981967321 TETRAEDGE: Implement proper pathfinding for Syberia 2
Commit: 7baf3da9621c2c9414f493cbae2df95bb85d9d9c
https://github.com/scummvm/scummvm/commit/7baf3da9621c2c9414f493cbae2df95bb85d9d9c
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2023-03-06T07:28:56+09:00
Commit Message:
TETRAEDGE: Fix potential OOB access
Changed paths:
engines/tetraedge/game/lua_binds.cpp
diff --git a/engines/tetraedge/game/lua_binds.cpp b/engines/tetraedge/game/lua_binds.cpp
index bec4a1aeb4e..749e47af820 100644
--- a/engines/tetraedge/game/lua_binds.cpp
+++ b/engines/tetraedge/game/lua_binds.cpp
@@ -1135,7 +1135,7 @@ static int tolua_ExportedFunctions_RotateGroundObject00(lua_State *L) {
static void EnableLight(uint lightno, bool enable) {
Game *game = g_engine->getGame();
- if (lightno > game->scene().lights().size()) {
+ if (lightno >= game->scene().lights().size()) {
error("[EnableLight] Light not found %d", lightno);
}
Common::SharedPtr<TeLight> light = game->scene().lights()[lightno];
Commit: e88685a3793dcc4b7c5026b50e4553ed94fc21f5
https://github.com/scummvm/scummvm/commit/e88685a3793dcc4b7c5026b50e4553ed94fc21f5
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2023-03-06T07:28:57+09:00
Commit Message:
TETRAEDGE: Don't apply spot cutoff in Syberia 2
Changed paths:
engines/tetraedge/te/te_light.cpp
engines/tetraedge/te/te_light.h
engines/tetraedge/te/te_light_opengl.cpp
engines/tetraedge/te/te_light_tinygl.cpp
diff --git a/engines/tetraedge/te/te_light.cpp b/engines/tetraedge/te/te_light.cpp
index d8e8b2f584c..915a7b16f87 100644
--- a/engines/tetraedge/te/te_light.cpp
+++ b/engines/tetraedge/te/te_light.cpp
@@ -89,6 +89,11 @@ Common::String TeLight::dump() const {
_quadraticAtten, _cutoff, _exponent, _displaySize);
}
+void TeLight::correctAttenuation() {
+ if (!_constAtten && !_linearAtten && !_quadraticAtten)
+ _constAtten = 1.0;
+}
+
/*static*/
TeLight *TeLight::makeInstance() {
Graphics::RendererType r = g_engine->preferredRendererType();
diff --git a/engines/tetraedge/te/te_light.h b/engines/tetraedge/te/te_light.h
index 64b75f5c31c..85838637c9b 100644
--- a/engines/tetraedge/te/te_light.h
+++ b/engines/tetraedge/te/te_light.h
@@ -72,6 +72,7 @@ public:
const TeVector3f32 &position3d() const { return _position3d; }
Common::String dump() const;
+ void correctAttenuation();
static TeLight *makeInstance();
diff --git a/engines/tetraedge/te/te_light_opengl.cpp b/engines/tetraedge/te/te_light_opengl.cpp
index 4d94992fa1e..8dfe56fe5fe 100644
--- a/engines/tetraedge/te/te_light_opengl.cpp
+++ b/engines/tetraedge/te/te_light_opengl.cpp
@@ -22,6 +22,7 @@
#include "common/math.h"
#include "tetraedge/te/te_light_opengl.h"
+#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_quaternion.h"
#include "tetraedge/te/te_vector3f32.h"
@@ -69,11 +70,11 @@ void TeLightOpenGL::update(uint lightno) {
const uint glLight = _toGlLight(lightno);
const float ambient[4] = {_colAmbient.r() / 255.0f, _colAmbient.g() / 255.0f,
- _colAmbient.b() / 255.0f, 1.0};
+ _colAmbient.b() / 255.0f, 1.0f};
glLightfv(glLight, GL_AMBIENT, ambient);
const float diff[4] = {_colDiffuse.r() / 255.0f, _colDiffuse.g() / 255.0f,
- _colDiffuse.b() / 255.0f, 1.0};
+ _colDiffuse.b() / 255.0f, 1.0f};
glLightfv(glLight, GL_DIFFUSE, diff);
// WORKAROUND: Original game sets 0.01 as threshold here to avoid enabling
@@ -84,7 +85,7 @@ void TeLightOpenGL::update(uint lightno) {
glDisable(glLight);
const float spec[4] = {_colSpecular.r() / 255.0f, _colSpecular.g() / 255.0f,
- _colSpecular.b() / 255.0f, 1.0};
+ _colSpecular.b() / 255.0f, 1.0f};
glLightfv(glLight, GL_SPECULAR, spec);
if (_type == LightTypeSpot || _type == LightTypePoint) {
@@ -105,10 +106,12 @@ void TeLightOpenGL::update(uint lightno) {
const TeVector3f32 dirv = directionVector();
const float dir[4] = {dirv.x(), dirv.y(), dirv.z(), 0.0f};
glLightfv(glLight, GL_SPOT_DIRECTION, dir);
- glLightf(glLight, GL_SPOT_CUTOFF, (_cutoff * 180.0) / M_PI);
- glLightf(glLight, GL_SPOT_EXPONENT, _exponent);
+ glLightf(glLight, GL_SPOT_CUTOFF, (_cutoff * 180.0f) / M_PI);
+ // Exponent doesn't get set in Syberia 2
+ if (g_engine->gameType() == TetraedgeEngine::kSyberia)
+ glLightf(glLight, GL_SPOT_EXPONENT, _exponent);
} else {
- glLightf(glLight, GL_SPOT_CUTOFF, 180.0);
+ glLightf(glLight, GL_SPOT_CUTOFF, 180.0f);
}
}
@@ -116,7 +119,7 @@ void TeLightOpenGL::update(uint lightno) {
void TeLightOpenGL::updateGlobal() {
const TeColor globalAmbient(_globalAmbientColor);
const float col[4] = {globalAmbient.r() / 255.0f,
- globalAmbient.g() / 255.0f, globalAmbient.b() / 255.0f, 1.0};
+ globalAmbient.g() / 255.0f, globalAmbient.b() / 255.0f, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
}
diff --git a/engines/tetraedge/te/te_light_tinygl.cpp b/engines/tetraedge/te/te_light_tinygl.cpp
index b4cedd1f472..3d6c3d04210 100644
--- a/engines/tetraedge/te/te_light_tinygl.cpp
+++ b/engines/tetraedge/te/te_light_tinygl.cpp
@@ -24,6 +24,7 @@
#include "graphics/tinygl/tinygl.h"
#include "tetraedge/te/te_light_tinygl.h"
+#include "tetraedge/tetraedge.h"
#include "tetraedge/te/te_color.h"
#include "tetraedge/te/te_quaternion.h"
#include "tetraedge/te/te_vector3f32.h"
@@ -68,11 +69,11 @@ void TeLightTinyGL::update(uint lightno) {
const uint glLight = _toGlLight(lightno);
const float ambient[4] = {_colAmbient.r() / 255.0f, _colAmbient.g() / 255.0f,
- _colAmbient.b() / 255.0f, 1.0};
+ _colAmbient.b() / 255.0f, 1.0f};
tglLightfv(glLight, TGL_AMBIENT, ambient);
const float diff[4] = {_colDiffuse.r() / 255.0f, _colDiffuse.g() / 255.0f,
- _colDiffuse.b() / 255.0f, 1.0};
+ _colDiffuse.b() / 255.0f, 1.0f};
tglLightfv(glLight, TGL_DIFFUSE, diff);
// WORKAROUND: Original game sets 0.01 as threshold here to avoid enabling
@@ -83,7 +84,7 @@ void TeLightTinyGL::update(uint lightno) {
tglDisable(glLight);
const float spec[4] = {_colSpecular.r() / 255.0f, _colSpecular.g() / 255.0f,
- _colSpecular.b() / 255.0f, 1.0};
+ _colSpecular.b() / 255.0f, 1.0f};
tglLightfv(glLight, TGL_SPECULAR, spec);
if (_type == LightTypeSpot || _type == LightTypePoint) {
@@ -104,10 +105,12 @@ void TeLightTinyGL::update(uint lightno) {
const TeVector3f32 dirv = directionVector();
const float dir[4] = {dirv.x(), dirv.y(), dirv.z(), 0.0f};
tglLightfv(glLight, TGL_SPOT_DIRECTION, dir);
- tglLightf(glLight, TGL_SPOT_CUTOFF, (_cutoff * 180.0) / M_PI);
- tglLightf(glLight, TGL_SPOT_EXPONENT, _exponent);
+ tglLightf(glLight, TGL_SPOT_CUTOFF, (_cutoff * 180.0f) / M_PI);
+ // Exponent doesn't get set in Syberia 2
+ if (g_engine->gameType() == TetraedgeEngine::kSyberia)
+ tglLightf(glLight, TGL_SPOT_EXPONENT, _exponent);
} else {
- tglLightf(glLight, TGL_SPOT_CUTOFF, 180.0);
+ tglLightf(glLight, TGL_SPOT_CUTOFF, 180.0f);
}
}
@@ -115,7 +118,7 @@ void TeLightTinyGL::update(uint lightno) {
void TeLightTinyGL::updateGlobal() {
const TeColor globalAmbient(_globalAmbientColor);
const float col[4] = {globalAmbient.r() / 255.0f,
- globalAmbient.g() / 255.0f, globalAmbient.b() / 255.0f, 1.0};
+ globalAmbient.g() / 255.0f, globalAmbient.b() / 255.0f, 1.0f};
tglLightModelfv(TGL_LIGHT_MODEL_AMBIENT, col);
}
Commit: 48de219950797dd680677b194f33d24677635a51
https://github.com/scummvm/scummvm/commit/48de219950797dd680677b194f33d24677635a51
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2023-03-06T07:28:57+09:00
Commit Message:
TETRAEDGE: Fix some bugs in Syberia 2 light config
Changed paths:
engines/tetraedge/game/in_game_scene.cpp
engines/tetraedge/game/scene_lights_xml_parser.cpp
diff --git a/engines/tetraedge/game/in_game_scene.cpp b/engines/tetraedge/game/in_game_scene.cpp
index 9b69000e778..3584b6c2cc6 100644
--- a/engines/tetraedge/game/in_game_scene.cpp
+++ b/engines/tetraedge/game/in_game_scene.cpp
@@ -862,8 +862,6 @@ bool InGameScene::loadXml(const Common::String &zone, const Common::String &scen
if (lightsNode.isReadable())
loadLights(lightsNode);
- // TODO: Should we set particle matrix to current cam matrix here?
- // If we are loading a new scene it seems redundant..
Common::Path pxmlpath = _sceneFileNameBase(zone, scene).joinInPlace("particles.xml");
Common::FSNode pnode = g_engine->getCore()->findFile(pxmlpath);
if (pnode.isReadable()) {
@@ -875,7 +873,6 @@ bool InGameScene::loadXml(const Common::String &zone, const Common::String &scen
error("InGameScene::loadXml: Can't parse %s", pnode.getPath().c_str());
}
-
TeMatrix4x4 camMatrix = currentCamera() ?
currentCamera()->worldTransformationMatrix() : TeMatrix4x4();
for (auto &particle : _particles) {
@@ -969,9 +966,21 @@ bool InGameScene::loadLights(const Common::FSNode &node) {
g_engine->getRenderer()->enableAllLights();
for (uint i = 0; i < _lights.size(); i++) {
+ //
+ // WORKAROUND: Some lights in Syberia 2 have 0 for all attenuation
+ // values, which causes textures to all be black. eg,
+ // scenes/A2_Sommet/25210/lights.xml, light 0.
+ // Correct them to have the default attenuation of 1, 0, 0.
+ //
+ _lights[i]->correctAttenuation();
_lights[i]->enable(i);
}
+ if (_shadowLightNo >= (int)_lights.size()) {
+ warning("Disabling scene shadows: invalid shadow light no.");
+ _shadowLightNo = -1;
+ }
+
#ifdef TETRAEDGE_DEBUG_LIGHTS
debug("--- Scene lights ---");
debug("Shadow: %s no:%d far:%.02f near:%.02f fov:%.02f", _shadowColor.dump().c_str(), _shadowLightNo, _shadowFarPlane, _shadowNearPlane, _shadowFov);
diff --git a/engines/tetraedge/game/scene_lights_xml_parser.cpp b/engines/tetraedge/game/scene_lights_xml_parser.cpp
index c6b01c8ee77..48ff45c6f85 100644
--- a/engines/tetraedge/game/scene_lights_xml_parser.cpp
+++ b/engines/tetraedge/game/scene_lights_xml_parser.cpp
@@ -112,8 +112,11 @@ bool SceneLightsXmlParser::parserCallback_Cutoff(ParserNode *node) {
bool SceneLightsXmlParser::parserCallback_Exponent(ParserNode *node) {
float expon = parseDouble(node);
- if (expon < 0.0f || expon > 128.0f)
- warning("Loaded invalid lighting exponent value %f", expon);
+ if (expon < 0.0f || expon > 128.0f) {
+ // Print debug but don't bother warning - the value is not used anyway.
+ debug("Loaded invalid lighting exponent value %f, default to 1.0", expon);
+ expon = 1.0;
+ }
_lights->back()->setExponent(expon);
return true;
}
Commit: 68e14e655896054e1c8065477f609dcf239e6b2b
https://github.com/scummvm/scummvm/commit/68e14e655896054e1c8065477f609dcf239e6b2b
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2023-03-06T07:28:57+09:00
Commit Message:
TETRAEDGE: Implement collisionSlide for Syberia 2
Changed paths:
engines/tetraedge/game/in_game_scene.cpp
engines/tetraedge/game/in_game_scene.h
engines/tetraedge/game/in_game_scene_xml_parser.cpp
engines/tetraedge/te/te_free_move_zone.cpp
engines/tetraedge/te/te_free_move_zone.h
engines/tetraedge/te/te_pick_mesh2.cpp
engines/tetraedge/te/te_pick_mesh2.h
diff --git a/engines/tetraedge/game/in_game_scene.cpp b/engines/tetraedge/game/in_game_scene.cpp
index 3584b6c2cc6..b69cafea936 100644
--- a/engines/tetraedge/game/in_game_scene.cpp
+++ b/engines/tetraedge/game/in_game_scene.cpp
@@ -49,9 +49,6 @@
namespace Tetraedge {
-/*static*/
-bool InGameScene::_collisionSlide = false;
-
/*static*/
const int InGameScene::MAX_FIRE = 50;
const int InGameScene::MAX_SNOW = 250;
@@ -800,8 +797,7 @@ bool InGameScene::loadXml(const Common::String &zone, const Common::String &scen
_sceneName = scene;
_blockers.clear();
_rectBlockers.clear();
- _collisionSlide = false;
- loadActZones();
+ TeFreeMoveZone::setCollisionSlide(false);
loadBlockers();
Common::Path xmlpath = _sceneFileNameBase(zone, scene).joinInPlace("Scene")
diff --git a/engines/tetraedge/game/in_game_scene.h b/engines/tetraedge/game/in_game_scene.h
index 1498d9c56ac..01653c96aa4 100644
--- a/engines/tetraedge/game/in_game_scene.h
+++ b/engines/tetraedge/game/in_game_scene.h
@@ -277,7 +277,6 @@ public:
const Common::String getZoneName() const { return _zoneName; }
const Common::String getSceneName() const { return _sceneName; }
- void setCollisionSlide(bool val) { _collisionSlide = val; }
void activateMask(const Common::String &name, bool val);
YoukiManager &youkiManager() { return _youkiManager; }
diff --git a/engines/tetraedge/game/in_game_scene_xml_parser.cpp b/engines/tetraedge/game/in_game_scene_xml_parser.cpp
index be34e3added..267ea3d3f13 100644
--- a/engines/tetraedge/game/in_game_scene_xml_parser.cpp
+++ b/engines/tetraedge/game/in_game_scene_xml_parser.cpp
@@ -113,7 +113,7 @@ bool InGameSceneXmlParser::parserCallback_light(ParserNode *node) {
}
bool InGameSceneXmlParser::parserCallback_collisionSlide(ParserNode *node) {
- _scene->setCollisionSlide(true);
+ TeFreeMoveZone::setCollisionSlide(true);
return true;
}
@@ -122,12 +122,12 @@ bool InGameSceneXmlParser::parserCallback_collisionSlide(ParserNode *node) {
// for collisionSlide. Fix it to do what it was intended to do.
//
bool InGameSceneXmlParser::parserCallback_coliisionSlide(ParserNode *node) {
- _scene->setCollisionSlide(true);
+ TeFreeMoveZone::setCollisionSlide(true);
return true;
}
bool InGameSceneXmlParser::parserCallback_noCollisionSlide(ParserNode *node) {
- _scene->setCollisionSlide(false);
+ TeFreeMoveZone::setCollisionSlide(false);
return true;
}
diff --git a/engines/tetraedge/te/te_free_move_zone.cpp b/engines/tetraedge/te/te_free_move_zone.cpp
index 462fadc4ebd..c396fc4af0a 100644
--- a/engines/tetraedge/te/te_free_move_zone.cpp
+++ b/engines/tetraedge/te/te_free_move_zone.cpp
@@ -35,6 +35,9 @@ namespace Tetraedge {
/*static*/
//TeIntrusivePtr<TeCamera> TeFreeMoveZone::_globalCamera;
+/*static*/
+bool TeFreeMoveZone::_collisionSlide = false;
+
class TeFreeMoveZoneGraph : micropather::Graph {
friend class TeFreeMoveZone;
@@ -264,9 +267,13 @@ TeVector3f32 TeFreeMoveZone::correctCharacterPosition(const TeVector3f32 &pos, b
TeVector3f32 testPos(pos.x(), 0, pos.z());
if (!intersect(testPos, TeVector3f32(0, -1, 0), intersectPoint, f, intersectFlag, nullptr)) {
if (!intersect(testPos, TeVector3f32(0, 1, 0), intersectPoint, f, intersectFlag, nullptr)) {
- if (*flagout)
- *flagout = false;
- return pos;
+ // Note: This flag should only ever get set in Syberia 2.
+ if (!_collisionSlide) {
+ if (*flagout)
+ *flagout = false;
+ return pos;
+ }
+ return slide(pos);
}
}
if (flagout)
diff --git a/engines/tetraedge/te/te_free_move_zone.h b/engines/tetraedge/te/te_free_move_zone.h
index e2b77ce7660..ee111ab04fd 100644
--- a/engines/tetraedge/te/te_free_move_zone.h
+++ b/engines/tetraedge/te/te_free_move_zone.h
@@ -124,6 +124,8 @@ public:
const Common::Array<TeVector3f32> freeMoveZoneVerticies() const { return _freeMoveZoneVerticies; }
+ static void setCollisionSlide(bool val) { _collisionSlide = val; }
+
private:
TeVector2s32 aStarResolution() const;
@@ -162,6 +164,8 @@ private:
TeTimer _updateTimer;
Common::Path _aszGridPath;
+
+ static bool _collisionSlide;
};
} // end namespace Tetraedge
diff --git a/engines/tetraedge/te/te_pick_mesh2.cpp b/engines/tetraedge/te/te_pick_mesh2.cpp
index 5b3cca60128..f73c774885b 100644
--- a/engines/tetraedge/te/te_pick_mesh2.cpp
+++ b/engines/tetraedge/te/te_pick_mesh2.cpp
@@ -176,6 +176,66 @@ void TePickMesh2::setTriangle(uint num, const TeVector3f32 &v1, const TeVector3f
_verticies[num * 3 + 2] = v3;
}
+static float linePointIntersection(const TeVector3f32 &v1, const TeVector3f32 &v2, const TeVector3f32 &v3) {
+ const TeVector3f32 line = v2 - v1;
+ float dot = line.dotProduct(line);
+ float retval = 0;
+ if (dot != 0) {
+ const TeVector3f32 segment = v3 - v1;
+ retval = segment.dotProduct(line);
+ }
+ return retval;
+}
+
+static float segmentPointIntersection(const TeVector3f32 &v1, const TeVector3f32 &v2, const TeVector3f32 &v3) {
+ float intersect = linePointIntersection(v1, v2, v3);
+ float retval;
+ if (intersect < 0)
+ retval = 0;
+ else if (intersect > 1)
+ retval = 1;
+ else
+ retval = intersect;
+ return retval;
+}
+
+TeVector3f32 TePickMesh2::slide(const TeVector3f32 &pos) {
+ const TeMatrix4x4 worldTransform = worldTransformationMatrix();
+ float shortest = 0;
+ TeVector3f32 retval;
+ for (uint i = 0; i < _verticies.size() / 3; i += 3) {
+ TeVector3f32 v1 = _verticies[i];
+ TeVector3f32 v2 = _verticies[i + 1];
+ TeVector3f32 v3 = _verticies[i + 2];
+
+ v1 = worldTransform * v1;
+ v2 = worldTransform * v2;
+ v3 = worldTransform * v3;
+
+ const TeVector3f32 pt1 = (v1 + (v2 - v1) * segmentPointIntersection(v1, v2, pos));
+ const TeVector3f32 off1 = pos - pt1;
+ if (i == 0 || off1.squaredLength() < shortest) {
+ retval = pt1;
+ shortest = off1.squaredLength();
+ }
+
+ const TeVector3f32 pt2 = v2 + (v3 - v2) * segmentPointIntersection(v2, v3, pos);
+ const TeVector3f32 off2 = pos - pt2;
+ if (off2.squaredLength() < shortest) {
+ retval = pt2;
+ shortest = off2.squaredLength();
+ }
+
+ const TeVector3f32 pt3 = v3 + (v1 - v3) * segmentPointIntersection(v3, v1, pos);
+ const TeVector3f32 off3 = pos - pt3;
+ if (off3.squaredLength() < shortest) {
+ retval = pt3;
+ shortest = off3.squaredLength();
+ }
+ }
+ return retval;
+}
+
/*static*/
void TePickMesh2::serialize(Common::WriteStream &stream, const TePickMesh2 &mesh) {
error("TODO: Implement TePickMesh2::serialize");
diff --git a/engines/tetraedge/te/te_pick_mesh2.h b/engines/tetraedge/te/te_pick_mesh2.h
index 929478fbda1..b384b071b17 100644
--- a/engines/tetraedge/te/te_pick_mesh2.h
+++ b/engines/tetraedge/te/te_pick_mesh2.h
@@ -47,6 +47,8 @@ public:
void setTriangle(uint num, const TeVector3f32 &v1, const TeVector3f32 &v2, const TeVector3f32 &v3);
void triangle(uint num, TeVector3f32 &v1out, TeVector3f32 &v2out, TeVector3f32 &v3out) const;
+ TeVector3f32 slide(const TeVector3f32 &pos);
+
static void serialize(Common::WriteStream &stream, const TePickMesh2 &mesh);
static void deserialize(Common::ReadStream &stream, TePickMesh2 &mesh);
Commit: a981967321b34a233fc0dfee5cfa1b1b7092a6ea
https://github.com/scummvm/scummvm/commit/a981967321b34a233fc0dfee5cfa1b1b7092a6ea
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2023-03-06T07:28:57+09:00
Commit Message:
TETRAEDGE: Implement proper pathfinding for Syberia 2
Changed paths:
engines/tetraedge/te/te_camera.cpp
engines/tetraedge/te/te_camera.h
engines/tetraedge/te/te_free_move_zone.cpp
engines/tetraedge/te/te_free_move_zone.h
engines/tetraedge/te/te_renderer_opengl.cpp
engines/tetraedge/te/te_renderer_tinygl.cpp
diff --git a/engines/tetraedge/te/te_camera.cpp b/engines/tetraedge/te/te_camera.cpp
index 0b8af94cc62..59d7ff37bea 100644
--- a/engines/tetraedge/te/te_camera.cpp
+++ b/engines/tetraedge/te/te_camera.cpp
@@ -227,8 +227,17 @@ TeMatrix4x4 TeCamera::projectionMatrix() {
return _projectionMatrix;
}
-TeVector3f32 TeCamera::projectPoint(const TeVector3f32 &pt) {
- error("TODO: Implement TeCamera::projectPoint");
+TeVector2f32 TeCamera::projectPoint(const TeVector3f32 &pt) {
+ _rotation.normalize();
+ TeMatrix4x4 worldInverse = worldTransformationMatrix();
+ worldInverse.inverse();
+ const TeVector3f32 projectedPt = _projectionMatrix * worldInverse * pt;
+ int halfViewportW = (int)_viewportW / 2;
+ int halfViewportH = (int)_viewportH / 2;
+
+ float projectedX = halfViewportW * (projectedPt.x() + 1.0) + _viewportX;
+ float projectedY = halfViewportH * (1.0 - projectedPt.y()) + _viewportY;
+ return TeVector2f32(projectedX, projectedY);
}
TeVector3f32 TeCamera::projectPoint3f32(const TeVector3f32 &pt) {
diff --git a/engines/tetraedge/te/te_camera.h b/engines/tetraedge/te/te_camera.h
index 320189e003c..aa89b35e80f 100644
--- a/engines/tetraedge/te/te_camera.h
+++ b/engines/tetraedge/te/te_camera.h
@@ -62,7 +62,7 @@ public:
void orthogonalParams(float f1, float f2, float f3, float f4);
TeMatrix4x4 projectionMatrix();
- TeVector3f32 projectPoint(const TeVector3f32 &pt);
+ TeVector2f32 projectPoint(const TeVector3f32 &pt);
TeVector3f32 projectPoint3f32(const TeVector3f32 &pt);
static void restore();
@@ -87,6 +87,8 @@ public:
float orthoFarPlane() const { return _orthFarVal; }
void setOrthoNear(float f) { _orthNearVal = f; }
void setOrthoFar(float f) { _orthFarVal = f; }
+ float getViewportHeight() const { return _viewportH; }
+ float getViewportWidth() const { return _viewportW; }
private:
void updateProjectionMatrix();
diff --git a/engines/tetraedge/te/te_free_move_zone.cpp b/engines/tetraedge/te/te_free_move_zone.cpp
index c396fc4af0a..d5d6615a141 100644
--- a/engines/tetraedge/te/te_free_move_zone.cpp
+++ b/engines/tetraedge/te/te_free_move_zone.cpp
@@ -30,6 +30,8 @@
#include "tetraedge/te/te_ray_intersection.h"
#include "tetraedge/te/te_core.h"
+//#define TETRAEDGE_DUMP_PATHFINDING_DATA 1
+
namespace Tetraedge {
/*static*/
@@ -144,7 +146,7 @@ void TeFreeMoveZone::buildAStar() {
else
_graph->_flags[graphSize._x * y + x] = 0;
} else {
- _graph->_flags[graphSize._x * y + x] = 2;
+ _graph->_flags[graphSize._x * y + x] = 2;
}
}
}
@@ -281,6 +283,7 @@ TeVector3f32 TeFreeMoveZone::correctCharacterPosition(const TeVector3f32 &pos, b
return intersectPoint;
}
+
TeIntrusivePtr<TeBezierCurve> TeFreeMoveZone::curve(const TeVector3f32 &startpt, const TeVector2s32 &clickPt, float param_5, bool findMeshFlag) {
updateGrid(false);
Common::Array<TePickMesh2 *> meshes;
@@ -288,8 +291,13 @@ TeIntrusivePtr<TeBezierCurve> TeFreeMoveZone::curve(const TeVector3f32 &startpt,
meshes.push_back(this);
TePickMesh2 *nearest = findNearestMesh(_camera, clickPt, meshes, &newend, findMeshFlag);
- if (!nearest)
- return TeIntrusivePtr<TeBezierCurve>();
+ if (!nearest) {
+ if (g_engine->gameType() == TetraedgeEngine::kSyberia2) {
+ newend = findNearestPointOnBorder(TeVector2f32(clickPt));
+ } else {
+ return TeIntrusivePtr<TeBezierCurve>();
+ }
+ }
return curve(startpt, newend);
}
@@ -301,7 +309,6 @@ TeIntrusivePtr<TeBezierCurve> TeFreeMoveZone::curve(const TeVector3f32 &startpt,
const int xsize = _graph->_size._x;
char *graphData = _graph->_flags.data();
float cost = 0;
- // Passing an int to void*, yuck? but it's what the original does..
Common::Array<void *> path;
int pathResult = _micropather->Solve(graphData + xsize * projectedStart._y + projectedStart._x,
graphData + xsize * projectedEnd._y + projectedEnd._x, &path, &cost);
@@ -325,10 +332,27 @@ TeIntrusivePtr<TeBezierCurve> TeFreeMoveZone::curve(const TeVector3f32 &startpt,
}
pts3d.push_back(endpt);
+#ifdef TETRAEDGE_DUMP_PATHFINDING_DATA
+ debug("curve: pathfind from %s to %s", startpt.dump().c_str(), endpt.dump().c_str());
+ debug("curve: %d grid points:", points.size());
+ for (uint i = 0; i < points.size(); i++)
+ debug("curve: gridpt %2d: %d, %d", i, points[i]._x, points[i]._y);
+ debug("curve: %d 3d (world) points:", pts3d.size());
+ for (uint i = 0; i < pts3d.size(); i++)
+ debug("curve: wrldpt %2d: %s", i, pts3d[i].dump().c_str());
+ uint firstsz = pts3d.size();
+#endif
+
removeInsignificantPoints(pts3d);
+
+#ifdef TETRAEDGE_DUMP_PATHFINDING_DATA
+ debug("curve: removed insignificant pts, %d -> %d", firstsz, pts3d.size());
+#endif
+
retval = new TeBezierCurve();
retval->setControlPoints(pts3d);
} else {
+ // No path found, just use start and end points.
Common::Array<TeVector3f32> points;
points.push_back(startpt);
points.push_back(endpt);
@@ -391,46 +415,116 @@ void TeFreeMoveZone::draw() {
renderer->multiplyMatrix(worldTransformationMatrix());
renderer->setCurrentColor(TeColor(0, 0x80, 0xff, 0xff));
mesh->draw();
- renderer->popMatrix();
- renderer->setCurrentColor(prevColor);
- // TODO: do a bunch of other drawing stuff here.
+ if (!_loadedFromBin)
+ renderer->popMatrix();
+
+ if (!_gridDirty && false) {
+ const TeVector2s32 aStarRes = aStarResolution();
+ // Note: original iterates through the graph first here and
+ // calls flag but doesn't do anything with it.. not sure why?
+ for (int x = 0; x < aStarRes._x; x++) {
+ for (int y = 0; y < aStarRes._y; y++) {
+ float left = _gridSquareSize.getX() * x + _gridTopLeft.getX();
+ float top = _gridSquareSize.getY() * y + _gridTopLeft.getY();
+ const TeVector3f32 tl(left, _gridWorldY, top);
+ const TeVector3f32 tr(left + _gridSquareSize.getX(), _gridWorldY, top);
+ const TeVector3f32 bl(left, _gridWorldY, top + _gridSquareSize.getY());
+ const TeVector3f32 br(left + _gridSquareSize.getX(), _gridWorldY, top + _gridSquareSize.getY());
+
+ int flag = _graph->flag(TeVector2s32(x, y));
+ if (flag == 1) {
+ renderer->setCurrentColor(TeColor(0xff, 0xff, 0xff, 0xff));
+ } else if (flag == 2) {
+ renderer->setCurrentColor(TeColor(0xff, 0xff, 0, 0xff));
+ } else {
+ renderer->setCurrentColor(TeColor(0, 0xff, 0, 0xff));
+ }
- renderer->disableWireFrame();
-}
+ renderer->drawLine(tl, tr);
+ renderer->drawLine(tr, br);
+ renderer->drawLine(tl, br);
+ renderer->drawLine(tr, bl);
+ }
+ }
+ }
-TeVector3f32 TeFreeMoveZone::findNearestPointOnBorder(const TeVector2f32 &pt) {
- error("TODO: Implement TeFreeMoveZone::findNearestPointOnBorder");
+ // TODO: do a bunch of other drawing stuff here (line 294 on)
+
+ if (_loadedFromBin)
+ renderer->popMatrix();
+ renderer->setCurrentColor(prevColor);
+ renderer->disableWireFrame();
}
static int segmentIntersection(const TeVector2f32 &s1start, const TeVector2f32 &s1end,
const TeVector2f32 &s2start, const TeVector2f32 &s2end,
TeVector2f32 *sout, float *fout1, float *fout2) {
- TeVector2f32 s1len = s1end - s1start;
- TeVector2f32 s2len = s2end - s2start;
- float squarelen = s1len.getX() * s2len.getX() + s1len.getY() * s2len.getY();
+ const TeVector2f32 s1len = s1end - s1start;
+ const TeVector2f32 s2len = s2end - s2start;
+ float dotprod = s1len.getX() * s2len.getX() + s1len.getY() * s2len.getY();
int result = 0;
- if (squarelen != 0) {
+ if (dotprod != 0) {
result = 1;
- float intersection1 = -((s1len.getY() * s1start.getX() +
+ float intersect1 = -((s1len.getY() * s1start.getX() +
(s1len.getX() * s2start.getY() - s1len.getX() * s1start.getY())) -
- s1len.getY() * s2start.getX()) / squarelen;
- if (intersection1 >= 0.0f && intersection1 <= 1.0f) {
- float intersection2 = -((s2len.getY() * s2start.getY() +
+ s1len.getY() * s2start.getX()) / dotprod;
+ if (intersect1 >= 0.0f && intersect1 <= 1.0f) {
+ float intersect2 = -((s2len.getY() * s2start.getY() +
(s2len.getX() * s1start.getX() - s2len.getX() * s2start.getX())) -
- s2len.getY() * s1start.getY()) / squarelen;
- if (intersection2 >= 0.0f && intersection2 <= 1.0f) {
+ s2len.getY() * s1start.getY()) / dotprod;
+ if (intersect2 >= 0.0f && intersect2 <= 1.0f) {
result = 2;
- if (sout || fout1 || fout2) {
- // Seems like these are always null?
- error("TODO: implement output in segmentIntersection");
- }
+ if (sout)
+ *sout = s1start + s1len * intersect2;
+ if (fout1)
+ *fout1 = intersect2;
+ if (fout2)
+ *fout2 = intersect1;
}
}
}
return result;
}
+TeVector3f32 TeFreeMoveZone::findNearestPointOnBorder(const TeVector2f32 &pt) {
+ TeVector3f32 retval;
+ const TeVector2f32 pt_x0(pt.getX(), 0);
+ const TeVector2f32 pt_x1(pt.getX(), _camera->getViewportHeight());
+ const TeVector2f32 pt_y0(0, pt.getY());
+ const TeVector2f32 pt_y1(_camera->getViewportWidth(), pt.getY());
+
+ updateProjectedPoints();
+ updateBorders();
+
+ float leastDist = FLT_MAX;
+ for (uint i = 0; i < _borders.size() / 2; i++) {
+ uint b1 = _borders[i * 2];
+ uint b2 = _borders[i * 2 + 1];
+ const TeVector2f32 &projb1 = _projectedPoints[b1];
+ const TeVector2f32 &projb2 = _projectedPoints[b2];
+ const TeVector3f32 &transb1 = _transformedVerticies[_pickMesh[b1]];
+ const TeVector3f32 &transb2 = _transformedVerticies[_pickMesh[b2]];
+ float dist = 0;
+ TeVector2f32 dir;
+ if (segmentIntersection(pt_x0, pt_x1, projb1, projb2, &dir, nullptr, &dist) == 2) {
+ float sqLen = (dir - pt).getSquareMagnitude();
+ if (sqLen < leastDist) {
+ retval = transb1 + (transb2 - transb1) * dist;
+ leastDist = sqLen;
+ }
+ }
+ if (segmentIntersection(pt_y0, pt_y1, projb1, projb2, &dir, nullptr, &dist) == 2) {
+ float sqLen = (dir - pt).getSquareMagnitude();
+ if (sqLen < leastDist) {
+ retval = transb1 + (transb2 - transb1) * dist;
+ leastDist = sqLen;
+ }
+ }
+ }
+ return retval;
+}
+
byte TeFreeMoveZone::hasBlockerIntersection(const TeVector2s32 &pt) {
TeVector2f32 borders[4];
@@ -655,7 +749,7 @@ TeVector2s32 TeFreeMoveZone::projectOnAStarGrid(const TeVector3f32 &pt) {
invGrid.inverse();
TeVector3f32 transPt = invGrid * (_inverseWorldTransform * pt);
offsetpt.setX(transPt.x() - _gridTopLeft.getX());
- offsetpt.setY(transPt.y() - _gridTopLeft.getY());
+ offsetpt.setY(transPt.z() - _gridTopLeft.getY());
}
const TeVector2f32 projected = offsetpt / _gridSquareSize;
return TeVector2s32((int)projected.getX(), (int)projected.getY());
@@ -740,9 +834,9 @@ void TeFreeMoveZone::setVertex(uint offset, const TeVector3f32 &vertex) {
TeVector3f32 TeFreeMoveZone::transformAStarGridInWorldSpace(const TeVector2s32 &gridpt) {
float offsetx = (float)gridpt._x * _gridSquareSize.getX() + _gridTopLeft.getX() +
- _gridSquareSize.getX() / 2;
+ _gridSquareSize.getX() / 2.0f;
float offsety = (float)gridpt._y * _gridSquareSize.getY() + _gridTopLeft.getY() +
- _gridSquareSize.getY() / 2;
+ _gridSquareSize.getY() / 2.0f;
if (!_loadedFromBin) {
return TeVector3f32(offsetx, _gridWorldY, offsety);
} else {
@@ -848,7 +942,20 @@ void TeFreeMoveZone::updateProjectedPoints() {
if (!_projectedPointsDirty)
return;
- error("TODO: Implement TeFreeMoveZone::updateProjectedPoints");
+ updateTransformedVertices();
+ updatePickMesh();
+ if (!_camera) {
+ _projectedPoints.clear();
+ _projectedPointsDirty = false;
+ return;
+ }
+
+ _projectedPoints.resize(_pickMesh.size());
+ for (uint i = 0; i < _pickMesh.size(); i++) {
+ _projectedPoints[i] = _camera->projectPoint(_transformedVerticies[_pickMesh[i]]);
+ _projectedPoints[i].setY(_camera->getViewportHeight() - _projectedPoints[i].getY());
+ }
+ _projectedPointsDirty = false;
}
void TeFreeMoveZone::updateTransformedVertices() {
diff --git a/engines/tetraedge/te/te_free_move_zone.h b/engines/tetraedge/te/te_free_move_zone.h
index ee111ab04fd..3f9e6eba982 100644
--- a/engines/tetraedge/te/te_free_move_zone.h
+++ b/engines/tetraedge/te/te_free_move_zone.h
@@ -137,6 +137,7 @@ private:
Common::Array<uint> _pickMesh;
Common::Array<TeVector3f32> _transformedVerticies;
Common::Array<uint> _borders;
+ Common::Array<TeVector2f32> _projectedPoints;
TeVector2f32 _gridSquareSize;
TeVector2f32 _gridTopLeft;
diff --git a/engines/tetraedge/te/te_renderer_opengl.cpp b/engines/tetraedge/te/te_renderer_opengl.cpp
index c21b0fb4162..0f373b24120 100644
--- a/engines/tetraedge/te/te_renderer_opengl.cpp
+++ b/engines/tetraedge/te/te_renderer_opengl.cpp
@@ -71,7 +71,20 @@ void TeRendererOpenGL::disableZBuffer() {
}
void TeRendererOpenGL::drawLine(const TeVector3f32 &from, const TeVector3f32 &to) {
- error("TODO: Implement TeRenderer::drawLine");
+ const TeVector3f32 pts[2] = {from, to};
+ const TeVector3f32 norms(0, 0, 1);
+ const unsigned short idxs[2] = {0, 1};
+ setMatrixMode(MM_GL_MODELVIEW);
+ glPushMatrix();
+ loadCurrentMatrixToGL();
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(TeVector3f32), pts);
+ glNormalPointer(GL_FLOAT, sizeof(TeVector3f32), &norms);
+ glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, idxs);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glPopMatrix();
}
void TeRendererOpenGL::enableAllLights() {
diff --git a/engines/tetraedge/te/te_renderer_tinygl.cpp b/engines/tetraedge/te/te_renderer_tinygl.cpp
index 8e0c9626ffc..eaa1dce076c 100644
--- a/engines/tetraedge/te/te_renderer_tinygl.cpp
+++ b/engines/tetraedge/te/te_renderer_tinygl.cpp
@@ -72,7 +72,7 @@ void TeRendererTinyGL::disableZBuffer() {
}
void TeRendererTinyGL::drawLine(const TeVector3f32 &from, const TeVector3f32 &to) {
- error("TODO: Implement TeRenderer::drawLine");
+ error("TODO: Implement TeRendererTinyGL::drawLine");
}
void TeRendererTinyGL::enableAllLights() {
More information about the Scummvm-git-logs
mailing list