scummvm/engines/myst3/scene.cpp

191 lines
5.7 KiB
C++
Raw Normal View History

2012-01-10 20:41:51 +01:00
/* ResidualVM - A 3D game interpreter
*
2012-01-10 20:41:51 +01:00
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
2012-01-05 10:07:48 +01:00
* 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 2
* of the License, or (at your option) any later version.
2014-04-05 18:18:42 +02:00
*
2012-01-05 10:07:48 +01:00
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
2012-01-05 10:07:48 +01:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
2014-04-05 18:18:42 +02:00
*
2012-01-05 10:07:48 +01:00
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "common/math.h"
#include "common/config-manager.h"
#include "engines/myst3/scene.h"
#include "engines/myst3/myst3.h"
#include "engines/myst3/state.h"
#include "graphics/colormasks.h"
#include "math/vector2d.h"
namespace Myst3 {
Scene::Scene(Myst3Engine *vm) :
_vm(vm),
_mouseSpeed(50) {
updateMouseSpeed();
}
void Scene::updateCamera(Common::Point &mouse) {
float pitch = _vm->_state->getLookAtPitch();
float heading = _vm->_state->getLookAtHeading();
if (!_vm->_state->getCursorLocked()) {
float speed = 25 / (float)(200 - _mouseSpeed);
// Adjust the speed according to the resolution
Common::Rect screen = _vm->_gfx->viewport();
speed *= Renderer::kOriginalHeight / (float) screen.height();
pitch -= mouse.y * speed;
heading += mouse.x * speed;
}
// Keep heading within allowed values
if (_vm->_state->isCameraLimited()) {
float minHeading = _vm->_state->getMinHeading();
float maxHeading = _vm->_state->getMaxHeading();
if (minHeading < maxHeading) {
heading = CLIP(heading, minHeading, maxHeading);
} else {
if (heading < minHeading && heading > maxHeading) {
2012-01-27 14:05:20 +01:00
uint distToMin = (uint)ABS(heading - minHeading);
uint distToMax = (uint)ABS(heading - maxHeading);
if (distToMin > distToMax)
heading = maxHeading;
else
heading = minHeading;
}
}
}
// Keep heading in 0..360 range
if (heading > 360.0f)
heading -= 360.0f;
else if (heading < 0.0f)
heading += 360.0f;
// Keep pitch within allowed values
float minPitch = _vm->_state->getCameraMinPitch();
float maxPitch = _vm->_state->getCameraMaxPitch();
if (_vm->_state->isCameraLimited()) {
minPitch = _vm->_state->getMinPitch();
maxPitch = _vm->_state->getMaxPitch();
}
pitch = CLIP(pitch, minPitch, maxPitch);
_vm->_state->lookAt(pitch, heading);
2012-01-27 12:02:03 +01:00
_vm->_state->setCameraPitch((int32)pitch);
_vm->_state->setCameraHeading((int32)heading);
}
2012-01-05 17:19:15 +01:00
void Scene::drawSunspotFlare(const SunSpot &s) {
Common::Rect frame = Common::Rect(Renderer::kOriginalWidth, Renderer::kFrameHeight);
frame.translate(0, Renderer::kTopBorderHeight);
2012-01-05 17:19:15 +01:00
2012-01-27 12:02:03 +01:00
uint8 a = (uint8)(s.intensity * s.radius);
uint8 r, g, b;
Graphics::colorToRGB< Graphics::ColorMasks<888> >(s.color, r, g, b);
uint32 color = Graphics::ARGBToColor< Graphics::ColorMasks<8888> >(a, r, g, b);
2012-01-05 17:19:15 +01:00
_vm->_gfx->drawRect2D(frame, color);
2012-01-05 17:19:15 +01:00
}
static Math::Vector3d directionToVector(float pitch, float heading) {
Math::Vector3d v;
float radHeading = Common::deg2rad(heading);
float radPitch = Common::deg2rad(pitch);
v.setValue(0, cos(radPitch) * cos(radHeading));
v.setValue(1, sin(radPitch));
v.setValue(2, cos(radPitch) * sin(radHeading));
return v;
}
float Scene::distanceToZone(float spotHeading, float spotPitch, float spotRadius, float heading, float pitch) {
Math::Vector3d vLookAt = directionToVector(pitch, heading);
Math::Vector3d vSun = directionToVector(spotPitch, spotHeading);
float dotProduct = Math::Vector3d::dotProduct(vLookAt, -vSun);
float distance = (0.05 * spotRadius - (dotProduct + 1.0) * 90) / (0.05 * spotRadius);
return CLIP<float>(distance, 0.0, 1.0);
}
void Scene::updateMouseSpeed() {
_mouseSpeed = ConfMan.getInt("mouse_speed");
}
Common::Rect Scene::frameViewport() const {
Common::Rect screen = _vm->_gfx->viewport();
Common::Rect frame = Common::Rect(screen.width(), screen.height() * Renderer::kFrameHeight / Renderer::kOriginalHeight);
frame.translate(screen.left, screen.top + screen.height() * Renderer::kTopBorderHeight / Renderer::kOriginalHeight);
return frame;
}
Common::Point Scene::frameCenter() const {
Common::Rect frame = frameViewport();
return Common::Point((frame.left + frame.right) / 2, (frame.top + frame.bottom) / 2);
}
Common::Point Scene::screenPosToWindowPos(const Common::Point &screen) const {
Common::Rect frame = frameViewport();
return Common::Point(screen.x - frame.left, screen.y - frame.top);
}
void Scene::screenPosToDirection(const Common::Point screen, float &pitch, float &heading) const {
Common::Rect frame = frameViewport();
// Screen coords to window coords
Common::Point pos = screenPosToWindowPos(screen);
// Window coords to normalized coords
Math::Vector4d in;
in.x() = pos.x * 2 / (float) frame.width() - 1.0;
in.y() = 1.0 - pos.y * 2 / (float) frame.height();
in.z() = 1.0;
in.w() = 1.0;
// Normalized coords to direction
Math::Matrix4 A = _vm->_gfx->getMvpMatrix();
A.inverse();
Math::Vector4d out = A.transform(in);
Math::Vector3d direction(out.x(), out.y(), out.z());
direction.normalize();
// 3D coords to polar coords
Math::Vector2d horizontalProjection = Math::Vector2d(direction.x(), direction.z());
horizontalProjection.normalize();
pitch = 90 - Math::Angle::arcCosine(direction.y()).getDegrees();
heading = Math::Angle::arcCosine(horizontalProjection.getY()).getDegrees();
if (horizontalProjection.getX() > 0.0)
heading = 360 - heading;
}
} // end of namespace Myst3