# Redesigned the camera control system.

Add shift+wheel (and Q/E, and ctrl+arrows, and ctrl+WASD) to rotate the
camera.
Restrict the rotation and zoom to narrow ranges. (Constraints can be
disabled in the dev overlay).
Smooth the movement and rotation.
Fix some stupid whitespace.
Fix some const correctness.

This was SVN commit r7930.
This commit is contained in:
Ykkrosh 2010-08-13 13:26:29 +00:00
parent 7ddfb18fe7
commit 6c7b82130c
21 changed files with 492 additions and 581 deletions

View File

@ -72,15 +72,25 @@ max_players = 8
sound.mastergain = 0.5
; selection.outline.quality = 9; ( higher => very slightly slower, better quality)
; view.scroll.speed = 60
; view.rotate.speed = 0.002
; view.rotate.abouttarget.speed = 0.01
; view.drag.speed = 0.5
; view.zoom.speed = 256.0
; view.zoom.wheel.speed = 16.0
; view.zoom.smoothness = 0.02 ; between 0 and 1
; view.snap.smoothness = 0.02 ; less is sharper, more is softer
; Camera control settings
view.scroll.speed = 120.0
view.rotate.x.speed = 1.2
view.rotate.x.min = 20
view.rotate.x.max = 60
view.rotate.x.default = 30
view.rotate.y.speed = 2.0
view.rotate.y.speed.wheel = 0.1
view.rotate.y.default 0.0
view.drag.speed = 0.5
view.zoom.speed = 256.0
view.zoom.speed.wheel = 32.0
view.zoom.min = 96.0
view.zoom.max = 256.0
view.zoom.default = 192.0
view.pos.smoothness = 0.1
view.zoom.smoothness = 0.4
view.rotate.x.smoothness = 0.5
view.rotate.y.smoothness = 0.3
; HOTKEY MAPPINGS:
@ -108,12 +118,12 @@ hotkey.camera.zoom.in = Plus, Equals, NumPlus ; Zoom camera in.
hotkey.camera.zoom.out = Minus, NumMinus ; Zoom camera out.
hotkey.camera.zoom.wheel.in = WheelUp ; Zoom camera in (wheel speed).
hotkey.camera.zoom.wheel.out = WheelDown ; Zoom camera out (wheel speed).
hotkey.camera.rotate = "Ctrl+MouseMiddle" ; Rotate view by moving mouse, maintaining the
; absolute position of the camera
hotkey.camera.rotate.keyboard = "Shift" ;
hotkey.camera.rotate.abouttarget = "MouseLeft+MouseRight" ; Rotate view by moving mouse, maintaining the
; world coordinates of the centre of the viewport
hotkey.camera.rotate.abouttarget.keyboard = "Ctrl" ;
hotkey.camera.rotate.wheel.cw = "Shift+WheelUp"
hotkey.camera.rotate.wheel.ccw = "Shift+WheelDown"
hotkey.camera.rotate.cw = "Ctrl+LeftArrow", "Ctrl+A", Q
hotkey.camera.rotate.ccw = "Ctrl+RightArrow", "Ctrl+D", E
hotkey.camera.rotate.up = "Ctrl+UpArrow", "Ctrl+W"
hotkey.camera.rotate.down = "Ctrl+DownArrow", "Ctrl+S"
hotkey.camera.pan = MouseMiddle, ForwardSlash ; Scroll by moving mouse.
hotkey.camera.pan.keyboard = "~Shift+~Ctrl" ; = holding neither Ctrl nor Shift
@ -121,12 +131,6 @@ hotkey.camera.left = A, LeftArrow ; Scroll or rotate left.
hotkey.camera.right = D, RightArrow ; Scroll or rotate right.
hotkey.camera.up = W, UpArrow ; Scroll or rotate up/forwards.
hotkey.camera.down = S, DownArrow ; Scroll or rotate down/backwards.
hotkey.camera.bookmark.0 = F5 ; Saved bookmark 1.
hotkey.camera.bookmark.1 = F6 ; Saved bookmark 2.
hotkey.camera.bookmark.2 = F7 ; Saved bookmark 3.
hotkey.camera.bookmark.3 = F8 ; Saved bookmark 4.
hotkey.camera.bookmark.save = Ctrl ; +bookmark: Save screen as bookmark.
hotkey.camera.bookmark.snap = Alt ; +bookmark: "check up" on bookmark.
;camera.cinema.add = "L"
;camera.cinema.delete = "U"

View File

@ -5,6 +5,20 @@ Thank you for installing 0 A.D.! This page will give a brief overview of the fea
[font="serif-bold-16"]Graphics settings
[font="serif-14"]You can switch between fullscreen and windowed mode by pressing Alt+Enter. In windowed mode, you can resize the window. If the game runs too slowly, you can change some settings in the configuration file: look for binaries/data/config/default.cfg in the location where the game is installed, which gives instructions for editing, and try disabling the "fancywater" and "shadows" options.
[font="serif-bold-16"]Playing the game
[font="serif-14"]The controls and gameplay should be familiar to players of traditional RTS games. There are currently a lot of missing features and poorly-balanced stats – you will probably have to wait until a beta release for it to work well.
Basic controls:
• Left-click to select units.
• Left-click-and-drag to select groups of units.
• Right-click to order units to the target.
• Arrow keys or WASD keys to move the camera.
• Ctrl + arrow keys, or shift + mouse wheel, to rotate the camera.
• Mouse wheel, or "+" and "-" keys, to zoom.
• F2 to save a screenshot (into %appdata%\0ad\screenshots\ on Windows, and ~/.local/share/0ad/screenshots/ on Unix).
• Ctrl+Alt+F2 to save a very high-resolution screenshot.
• F11 to view the built-in performance profiler.
[font="serif-bold-16"]Modes
[font="serif-14"]The main menu gives access to two game modes:
@ -23,17 +37,4 @@ Next, you can use the drop-down lists in the player list to select who controls
When you are ready to start, click the "Start game" button.
[font="serif-bold-16"]Playing the game
[font="serif-14"]The controls and gameplay should be familiar to players of traditional RTS games. There are currently a lot of missing features and poorly-balanced stats – you will probably have to wait until a beta release for it to work well.
Basic controls:
• Left-click to select units.
• Left-click-and-drag to select groups of units.
• Right-click to order units to the target.
• Arrow keys or WASD keys to move the camera.
• Ctrl + arrow keys to rotate the camera.
• F2 to save a screenshot (into %appdata%\0ad\screenshots\ on Windows, and ~/.local/share/0ad/screenshots/ on Unix).
• Ctrl+Alt+F2 to save a very high-resolution screenshot.
• F11 to view the built-in performance profiler.
Use the "X" button in the top-right corner of this window to close it.

View File

@ -77,7 +77,7 @@
/>
<!-- Dev/cheat commands -->
<object name="devCommands" size="100%-155 50 100%-16 146" z="200" type="image" sprite="devCommandsBackground"
<object name="devCommands" size="100%-155 50 100%-16 162" z="200" type="image" sprite="devCommandsBackground"
hidden="true" hotkey="session.devcommands.toggle">
<action on="Press">
this.hidden = !this.hidden;
@ -108,6 +108,11 @@
<object size="100%-16 80 100% 96" type="checkbox" style="wheatCrossBox">
<action on="Press">Engine.GuiInterfaceCall("SetRangeDebugOverlay", this.checked);</action>
</object>
<object size="0 96 100%-18 112" type="text" style="devCommandsText">Restrict camera</object>
<object size="100%-16 96 100% 112" type="checkbox" style="wheatCrossBox" checked="true">
<action on="Press">gameView.constrainCamera = this.checked;</action>
</object>
</object>
<!-- ================================ ================================ -->

View File

@ -161,7 +161,7 @@ void CCamera::GetCameraPlanePoints(float dist,CVector3D pts[4]) const
pts[3].Z=dist;
}
void CCamera::BuildCameraRay( int px, int py, CVector3D& origin, CVector3D& dir )
void CCamera::BuildCameraRay(int px, int py, CVector3D& origin, CVector3D& dir) const
{
CVector3D cPts[4];
GetCameraPlanePoints(m_FarPlane, cPts);
@ -200,7 +200,7 @@ void CCamera::GetScreenCoordinates( const CVector3D& world, float& x, float& y )
y = (1 - y) * 0.5f * g_Renderer.GetHeight();
}
CVector3D CCamera::GetWorldCoordinates( int px, int py, bool aboveWater )
CVector3D CCamera::GetWorldCoordinates(int px, int py, bool aboveWater) const
{
CHFTracer tracer(g_Game->GetWorld()->GetTerrain());
int x, z;
@ -268,7 +268,7 @@ CVector3D CCamera::GetWorldCoordinates( int px, int py, bool aboveWater )
}
CVector3D CCamera::GetWorldCoordinates(int px, int py, float h)
CVector3D CCamera::GetWorldCoordinates(int px, int py, float h) const
{
CPlane plane;
plane.Set(CVector3D(0.f, 1.f, 0.f), CVector3D(0.f, h, 0.f)); // upwards normal, passes through h
@ -289,7 +289,8 @@ CVector3D CCamera::GetFocus()
{
// Basically the same as GetWorldCoordinates
CHFTracer tracer( g_Game->GetWorld()->GetTerrain() ); int x, z;
CHFTracer tracer(g_Game->GetWorld()->GetTerrain());
int x, z;
CVector3D origin, dir, delta, currentTarget;

View File

@ -52,7 +52,7 @@ class CCamera
// everytime the view or projection matrices are
// altered.
void UpdateFrustum ();
const CFrustum& GetFrustum () { return m_ViewFrustum; }
const CFrustum& GetFrustum () const { return m_ViewFrustum; }
void SetViewPort (const SViewPort& viewport);
const SViewPort& GetViewPort () const { return m_ViewPort; }
@ -69,7 +69,7 @@ class CCamera
/////////////////////////////////////////////////////////////////////////////////////////
// BuildCameraRay: calculate origin and ray direction of a ray through
// the pixel (px,py) on the screen
void BuildCameraRay(int px, int py, CVector3D& origin, CVector3D& dir);
void BuildCameraRay(int px, int py, CVector3D& origin, CVector3D& dir) const;
// General helpers that seem to fit here
@ -78,9 +78,9 @@ class CCamera
// Get the point on the terrain corresponding to pixel (px,py) (or the mouse coordinates)
// The aboveWater parameter determines whether we want to stop at the water plane or also get underwater points
CVector3D GetWorldCoordinates(int px, int py, bool aboveWater=false);
CVector3D GetWorldCoordinates(int px, int py, bool aboveWater=false) const;
// Get the point on the plane at height h corresponding to pixel (px,py)
CVector3D GetWorldCoordinates(int px, int py, float h);
CVector3D GetWorldCoordinates(int px, int py, float h) const;
// Get the point on the terrain the camera is pointing towards
CVector3D GetFocus();

View File

@ -54,21 +54,84 @@
#include "simulation/LOSManager.h"
#include "simulation2/Simulation2.h"
float g_MaxZoomHeight=350.0f; //note: Max terrain height is this minus YMinOffset
float g_YMinOffset=15.0f;
extern int g_xres, g_yres;
static CVector3D cameraBookmarks[10];
static bool bookmarkInUse[10] = { false, false, false, false, false, false, false, false, false, false };
static i8 currentBookmark = -1;
const float CGameView::defaultFOV = DEGTORAD(20.f);
const float CGameView::defaultNear = 4.f;
const float CGameView::defaultFar = 4096.f;
const float CGameView::defaultCullFOV = CGameView::defaultFOV + DEGTORAD(6.0f); //add 6 degrees to the default FOV for use with the culling frustum
/**
* A value with exponential decay towards the target value.
*/
class CSmoothedValue
{
public:
CSmoothedValue(float value, float smoothness, float minDelta)
: m_Target(value), m_Current(value), m_Smoothness(smoothness), m_MinDelta(minDelta)
{
}
float GetSmoothedValue()
{
return m_Current;
}
void SetValueSmoothly(float value)
{
m_Target = value;
}
void AddSmoothly(float value)
{
m_Target += value;
}
void Add(float value)
{
m_Target += value;
m_Current += value;
}
float GetValue()
{
return m_Target;
}
void SetValue(float value)
{
m_Target = value;
m_Current = value;
}
float Update(float time)
{
if (fabs(m_Target - m_Current) < m_MinDelta)
return 0.0f;
double p = pow((double)m_Smoothness, 10.0 * (double)time);
// (add the factor of 10 so that smoothnesses don't have to be tiny numbers)
double delta = (m_Target - m_Current) * (1.0 - p);
m_Current += delta;
return (float)delta;
}
void ClampSmoothly(float min, float max)
{
m_Target = Clamp(m_Target, (double)min, (double)max);
}
private:
double m_Target; // the value which m_Current is tending towards
double m_Current;
// (We use double because the extra precision is worthwhile here)
float m_MinDelta; // cutoff where we stop moving (to avoid ugly shimmering effects)
public:
float m_Smoothness;
};
class CGameViewImpl : public CJSObject<CGameViewImpl>
{
NONCOPYABLE(CGameViewImpl);
@ -80,20 +143,31 @@ public:
ViewCamera(),
CullCamera(),
LockCullCamera(false),
ConstrainCamera(true),
Culling(true),
ViewScrollSpeed(60),
ViewRotateSensitivity(0.002f),
ViewRotateSensitivityKeyboard(1.0f),
ViewRotateAboutTargetSensitivity(0.010f),
ViewRotateAboutTargetSensitivityKeyboard(2.0f),
ViewDragSensitivity(0.5f),
ViewZoomSensitivityWheel(16.0f),
ViewZoomSensitivity(256.0f),
ViewZoomSmoothness(0.02f),
ViewSnapSmoothness(0.02f),
CameraDelta(),
CameraPivot(),
ZoomDelta(0)
// Dummy values (these will be filled in by the config file)
ViewScrollSpeed(0),
ViewRotateXSpeed(0),
ViewRotateXMin(0),
ViewRotateXMax(0),
ViewRotateXDefault(0),
ViewRotateYSpeed(0),
ViewRotateYSpeedWheel(0),
ViewRotateYDefault(0),
ViewDragSpeed(0),
ViewZoomSpeed(0),
ViewZoomSpeedWheel(0),
ViewZoomMin(0),
ViewZoomMax(0),
ViewZoomDefault(0),
PosX(0, 0, 0.01f),
PosY(0, 0, 0.01f),
PosZ(0, 0, 0.01f),
Zoom(0, 0, 0.1f),
RotateX(0, 0, 0.001f),
RotateY(0, 0, 0.001f)
{
}
@ -135,6 +209,12 @@ public:
*/
bool Culling;
/**
* Whether the camera movement should be constrained by min/max limits
* and terrain avoidance.
*/
bool ConstrainCamera;
/**
* Cache global lighting environment. This is used to check whether the
* environment has changed during the last frame, so that vertex data can be updated etc.
@ -146,32 +226,40 @@ public:
////////////////////////////////////////
// Settings
float ViewScrollSpeed;
float ViewRotateSensitivity;
float ViewRotateSensitivityKeyboard;
float ViewRotateAboutTargetSensitivity;
float ViewRotateAboutTargetSensitivityKeyboard;
float ViewDragSensitivity;
float ViewZoomSensitivityWheel;
float ViewZoomSensitivity;
float ViewZoomSmoothness; // 0.0 = instantaneous zooming, 1.0 = so slow it never moves
float ViewSnapSmoothness; // Just the same.
float ViewRotateXSpeed;
float ViewRotateXMin;
float ViewRotateXMax;
float ViewRotateXDefault;
float ViewRotateYSpeed;
float ViewRotateYSpeedWheel;
float ViewRotateYDefault;
float ViewDragSpeed;
float ViewZoomSpeed;
float ViewZoomSpeedWheel;
float ViewZoomMin;
float ViewZoomMax;
float ViewZoomDefault;
////////////////////////////////////////
// Camera Controls State
CVector3D CameraDelta;
CVector3D CameraPivot;
// CEntity* UnitAttach;
//float m_CameraZoom;
std::vector<CVector3D> CameraTargets;
// Accumulate zooming changes across frames for smoothness
float ZoomDelta;
CSmoothedValue PosX;
CSmoothedValue PosY;
CSmoothedValue PosZ;
CSmoothedValue Zoom;
CSmoothedValue RotateX; // inclination around x axis (relative to camera)
CSmoothedValue RotateY; // rotation around y (vertical) axis
static void ScriptingInit();
};
static void SetupCameraMatrix(CGameViewImpl* m, CMatrix3D* orientation)
{
orientation->SetIdentity();
orientation->RotateX(m->RotateX.GetSmoothedValue());
orientation->RotateY(m->RotateY.GetSmoothedValue());
orientation->Translate(m->PosX.GetSmoothedValue(), m->PosY.GetSmoothedValue(), m->PosZ.GetSmoothedValue());
}
CGameView::CGameView(CGame *pGame):
m(new CGameViewImpl(pGame))
{
@ -183,9 +271,9 @@ CGameView::CGameView(CGame *pGame):
m->ViewCamera.SetViewPort(vp);
m->ViewCamera.SetProjection(defaultNear, defaultFar, defaultFOV);
m->ViewCamera.m_Orientation.SetXRotation(DEGTORAD(30));
m->ViewCamera.m_Orientation.RotateY(DEGTORAD(0));
m->ViewCamera.m_Orientation.Translate (100, 150, -100);
SetupCameraMatrix(m, &m->ViewCamera.m_Orientation);
m->ViewCamera.UpdateFrustum();
m->CullCamera = m->ViewCamera;
g_Renderer.SetSceneCamera(m->ViewCamera, m->CullCamera);
}
@ -240,6 +328,7 @@ void CGameViewImpl::ScriptingInit()
{
AddProperty(L"culling", &CGameViewImpl::Culling);
AddProperty(L"lockCullCamera", &CGameViewImpl::LockCullCamera);
AddProperty(L"constrainCamera", &CGameViewImpl::ConstrainCamera);
CJSObject<CGameViewImpl>::ScriptingInit("GameView");
}
@ -247,20 +336,29 @@ void CGameViewImpl::ScriptingInit()
int CGameView::Initialize()
{
CFG_GET_SYS_VAL("view.scroll.speed", Float, m->ViewScrollSpeed);
CFG_GET_SYS_VAL( "view.rotate.speed", Float, m->ViewRotateSensitivity );
CFG_GET_SYS_VAL( "view.rotate.keyboard.speed", Float, m->ViewRotateSensitivityKeyboard );
CFG_GET_SYS_VAL( "view.rotate.abouttarget.speed", Float, m->ViewRotateAboutTargetSensitivity );
CFG_GET_SYS_VAL( "view.rotate.keyboard.abouttarget.speed", Float, m->ViewRotateAboutTargetSensitivityKeyboard );
CFG_GET_SYS_VAL( "view.drag.speed", Float, m->ViewDragSensitivity );
CFG_GET_SYS_VAL( "view.zoom.speed", Float, m->ViewZoomSensitivity );
CFG_GET_SYS_VAL( "view.zoom.wheel.speed", Float, m->ViewZoomSensitivityWheel );
CFG_GET_SYS_VAL( "view.zoom.smoothness", Float, m->ViewZoomSmoothness );
CFG_GET_SYS_VAL( "view.snap.smoothness", Float, m->ViewSnapSmoothness );
CFG_GET_SYS_VAL("view.rotate.x.speed", Float, m->ViewRotateXSpeed);
CFG_GET_SYS_VAL("view.rotate.x.min", Float, m->ViewRotateXMin);
CFG_GET_SYS_VAL("view.rotate.x.max", Float, m->ViewRotateXMax);
CFG_GET_SYS_VAL("view.rotate.x.default", Float, m->ViewRotateXDefault);
CFG_GET_SYS_VAL("view.rotate.y.speed", Float, m->ViewRotateYSpeed);
CFG_GET_SYS_VAL("view.rotate.y.speed.wheel", Float, m->ViewRotateYSpeedWheel);
CFG_GET_SYS_VAL("view.rotate.y.default", Float, m->ViewRotateYDefault);
CFG_GET_SYS_VAL("view.drag.speed", Float, m->ViewDragSpeed);
CFG_GET_SYS_VAL("view.zoom.speed", Float, m->ViewZoomSpeed);
CFG_GET_SYS_VAL("view.zoom.speed.wheel", Float, m->ViewZoomSpeedWheel);
CFG_GET_SYS_VAL("view.zoom.min", Float, m->ViewZoomMin);
CFG_GET_SYS_VAL("view.zoom.max", Float, m->ViewZoomMax);
CFG_GET_SYS_VAL("view.zoom.default", Float, m->ViewZoomDefault);
if( ( m->ViewZoomSmoothness < 0.0f ) || ( m->ViewZoomSmoothness > 1.0f ) )
m->ViewZoomSmoothness = 0.02f;
if( ( m->ViewSnapSmoothness < 0.0f ) || ( m->ViewSnapSmoothness > 1.0f ) )
m->ViewSnapSmoothness = 0.02f;
CFG_GET_SYS_VAL("view.pos.smoothness", Float, m->PosX.m_Smoothness);
CFG_GET_SYS_VAL("view.pos.smoothness", Float, m->PosY.m_Smoothness);
CFG_GET_SYS_VAL("view.pos.smoothness", Float, m->PosZ.m_Smoothness);
CFG_GET_SYS_VAL("view.zoom.smoothness", Float, m->Zoom.m_Smoothness);
CFG_GET_SYS_VAL("view.rotate.x.smoothness", Float, m->RotateX.m_Smoothness);
CFG_GET_SYS_VAL("view.rotate.y.smoothness", Float, m->RotateY.m_Smoothness);
m->RotateX.SetValue(DEGTORAD(m->ViewRotateXDefault));
m->RotateY.SetValue(DEGTORAD(m->ViewRotateYDefault));
return 0;
}
@ -381,34 +479,6 @@ void CGameView::EnumerateObjects(const CFrustum& frustum, SceneCollector* c)
}
//locks the camera in place
void CGameView::CameraLock(const CVector3D& Trans, bool smooth)
{
CameraLock(Trans.X, Trans.Y, Trans.Z, smooth);
}
void CGameView::CameraLock(float x, float y, float z, bool smooth)
{
CTerrain* pTerrain = m->Game->GetWorld()->GetTerrain();
float height = pTerrain->GetExactGroundLevel(
m->ViewCamera.m_Orientation._14 + x, m->ViewCamera.m_Orientation._34 + z) +
g_YMinOffset;
//is requested position within limits?
if (m->ViewCamera.m_Orientation._24 + y <= g_MaxZoomHeight)
{
if( m->ViewCamera.m_Orientation._24 + y >= height)
{
m->ViewCamera.m_Orientation.Translate(x, y, z);
}
else if (m->ViewCamera.m_Orientation._24 + y < height && smooth == true)
{
m->ViewCamera.m_Orientation.Translate(x, y, z);
m->ViewCamera.m_Orientation._24=height;
}
}
}
static void MarkUpdateColorRecursive(CModel& model)
{
model.SetDirty(RENDERDATA_UPDATE_COLOR);
@ -449,37 +519,41 @@ void CGameView::UnloadResources()
}
void CGameView::ResetCamera()
static void ClampDistance(CGameViewImpl* m, bool smooth)
{
// quick hack to return camera home, for screenshots (after alt+tabbing)
m->ViewCamera.SetProjection (defaultNear, defaultFar, defaultFOV);
m->ViewCamera.m_Orientation.SetXRotation(DEGTORAD(30));
m->ViewCamera.m_Orientation.RotateY(DEGTORAD(-45));
m->ViewCamera.m_Orientation.Translate (100, 150, -100);
if (!m->ConstrainCamera)
return;
CCamera targetCam = m->ViewCamera;
targetCam.m_Orientation.SetIdentity();
targetCam.m_Orientation.RotateX(m->RotateX.GetSmoothedValue());
targetCam.m_Orientation.RotateY(m->RotateY.GetSmoothedValue());
// Use non-smoothed position:
targetCam.m_Orientation.Translate(m->PosX.GetValue(), m->PosY.GetValue(), m->PosZ.GetValue());
CVector3D forwards = targetCam.m_Orientation.GetIn();
CVector3D delta = targetCam.GetFocus() - targetCam.m_Orientation.GetTranslation();
float dist = delta.Dot(forwards);
float clampedDist = Clamp(dist, m->ViewZoomMin, m->ViewZoomMax);
float diff = clampedDist - dist;
if (!diff)
return;
if (smooth)
{
m->PosX.AddSmoothly(forwards.X * -diff);
m->PosY.AddSmoothly(forwards.Y * -diff);
m->PosZ.AddSmoothly(forwards.Z * -diff);
}
void CGameView::ResetCameraOrientation()
else
{
CVector3D origin = m->ViewCamera.m_Orientation.GetTranslation();
CVector3D dir = m->ViewCamera.m_Orientation.GetIn();
CVector3D target = origin + dir * ( ( 50.0f - origin.Y ) / dir.Y );
target -= CVector3D( -22.474480f, 50.0f, 22.474480f );
m->ViewCamera.SetProjection (defaultNear, defaultFar, defaultFOV);
m->ViewCamera.m_Orientation.SetXRotation(DEGTORAD(30));
m->ViewCamera.m_Orientation.RotateY(DEGTORAD(-45));
target += CVector3D( 100.0f, 150.0f, -100.0f );
m->ViewCamera.m_Orientation.Translate( target );
m->PosX.Add(forwards.X * -diff);
m->PosY.Add(forwards.Y * -diff);
m->PosZ.Add(forwards.Z * -diff);
}
void CGameView::RotateAboutTarget()
{
m->CameraPivot = m->ViewCamera.GetWorldCoordinates(g_mouse_x, g_mouse_y, true);
}
void CGameView::Update(float DeltaTime)
@ -491,33 +565,15 @@ void CGameView::Update(float DeltaTime)
// in a CCmpWaterManager or some such thing (once such a thing exists)
g_Renderer.GetWaterManager()->m_WaterTexTimer += DeltaTime;
/*
if (m->UnitAttach)
{
CVector3D ToMove = m->UnitAttach->m_position - m->ViewCamera.GetFocus();
m->ViewCamera.m_Orientation._14 += ToMove.X;
m->ViewCamera.m_Orientation._34 += ToMove.Z;
m->ViewCamera.UpdateFrustum();
return;
}
*/
if (m->TrackManager.IsActive() && m->TrackManager.IsPlaying())
{
if (! m->TrackManager.Update(DeltaTime))
ResetCamera();
{
// ResetCamera();
}
return;
}
float delta = powf( m->ViewSnapSmoothness, DeltaTime );
m->ViewCamera.m_Orientation.Translate( m->CameraDelta * ( 1.0f - delta ) );
m->CameraDelta *= delta;
// This could be rewritten much more reliably, so it doesn't e.g. accidentally tilt
// the camera, assuming we know exactly what limits the camera should have.
// Calculate mouse movement
static int mouse_last_x = 0;
static int mouse_last_y = 0;
@ -526,228 +582,194 @@ void CGameView::Update(float DeltaTime)
mouse_last_x = g_mouse_x;
mouse_last_y = g_mouse_y;
// Miscellaneous vectors
CVector3D forwards = m->ViewCamera.m_Orientation.GetIn();
CVector3D rightwards = m->ViewCamera.m_Orientation.GetLeft() * -1.0f; // upwards.Cross(forwards);
CVector3D upwards( 0.0f, 1.0f, 0.0f );
// rightwards.Normalize();
if (hotkeys[HOTKEY_CAMERA_ROTATE_CW])
m->RotateY.AddSmoothly(m->ViewRotateYSpeed * DeltaTime);
if (hotkeys[HOTKEY_CAMERA_ROTATE_CCW])
m->RotateY.AddSmoothly(-m->ViewRotateYSpeed * DeltaTime);
if (hotkeys[HOTKEY_CAMERA_ROTATE_UP])
m->RotateX.AddSmoothly(-m->ViewRotateXSpeed * DeltaTime);
if (hotkeys[HOTKEY_CAMERA_ROTATE_DOWN])
m->RotateX.AddSmoothly(m->ViewRotateXSpeed * DeltaTime);
CVector3D forwards_horizontal = forwards;
forwards_horizontal.Y = 0.0f;
forwards_horizontal.Normalize();
float moveRightward = 0.f;
float moveForward = 0.f;
if( hotkeys[HOTKEY_CAMERA_ROTATE] || hotkeys[HOTKEY_CAMERA_ROTATE_KEYBOARD] )
if (hotkeys[HOTKEY_CAMERA_PAN])
{
// Ctrl + middle-drag or left-and-right-drag to rotate view
// Untranslate the camera, so it rotates around the correct point
CVector3D position = m->ViewCamera.m_Orientation.GetTranslation();
m->ViewCamera.m_Orientation.Translate(position*-1);
// Sideways rotation
float rightways = 0.0f;
if( hotkeys[HOTKEY_CAMERA_ROTATE] )
rightways = (float)mouse_dx * m->ViewRotateSensitivity;
if( hotkeys[HOTKEY_CAMERA_ROTATE_KEYBOARD] )
{
if( hotkeys[HOTKEY_CAMERA_LEFT] )
rightways -= m->ViewRotateSensitivityKeyboard * DeltaTime;
if( hotkeys[HOTKEY_CAMERA_RIGHT] )
rightways += m->ViewRotateSensitivityKeyboard * DeltaTime;
moveRightward += m->ViewDragSpeed * mouse_dx;
moveForward += m->ViewDragSpeed * -mouse_dy;
}
m->ViewCamera.m_Orientation.RotateY( rightways );
// Up/down rotation
float upways = 0.0f;
if( hotkeys[HOTKEY_CAMERA_ROTATE] )
upways = (float)mouse_dy * m->ViewRotateSensitivity;
if( hotkeys[HOTKEY_CAMERA_ROTATE_KEYBOARD] )
{
if( hotkeys[HOTKEY_CAMERA_UP] )
upways -= m->ViewRotateSensitivityKeyboard * DeltaTime;
if( hotkeys[HOTKEY_CAMERA_DOWN] )
upways += m->ViewRotateSensitivityKeyboard * DeltaTime;
}
CQuaternion temp;
temp.FromAxisAngle(rightwards, upways);
m->ViewCamera.m_Orientation.Rotate(temp);
// Retranslate back to the right position
m->ViewCamera.m_Orientation.Translate(position);
}
else if( hotkeys[HOTKEY_CAMERA_ROTATE_ABOUT_TARGET] )
{
CVector3D origin = m->ViewCamera.m_Orientation.GetTranslation();
CVector3D delta = origin - m->CameraPivot;
CQuaternion rotateH, rotateV; CMatrix3D rotateM;
// Sideways rotation
float rightways = (float)mouse_dx * m->ViewRotateAboutTargetSensitivity;
rotateH.FromAxisAngle( upwards, rightways );
// Up/down rotation
float upways = (float)mouse_dy * m->ViewRotateAboutTargetSensitivity;
rotateV.FromAxisAngle( rightwards, upways );
rotateH *= rotateV;
rotateH.ToMatrix( rotateM );
delta = rotateM.Rotate( delta );
// Lock the inclination to a rather arbitrary values (for the sake of graphical decency)
float scan = sqrt( delta.X * delta.X + delta.Z * delta.Z ) / delta.Y;
if( ( scan >= 0.5f ) )
{
// Move the camera to the origin (in preparation for rotation )
m->ViewCamera.m_Orientation.Translate( origin * -1.0f );
m->ViewCamera.m_Orientation.Rotate( rotateH );
// Move the camera back to where it belongs
m->ViewCamera.m_Orientation.Translate( m->CameraPivot + delta );
}
}
else if( hotkeys[HOTKEY_CAMERA_ROTATE_ABOUT_TARGET_KEYBOARD] )
{
// Split up because the keyboard controls use the centre of the screen, not the mouse position.
CVector3D origin = m->ViewCamera.m_Orientation.GetTranslation();
CVector3D pivot = m->ViewCamera.GetFocus();
CVector3D delta = origin - pivot;
CQuaternion rotateH, rotateV; CMatrix3D rotateM;
// Sideways rotation
float rightways = 0.0f;
if( hotkeys[HOTKEY_CAMERA_LEFT] )
rightways -= m->ViewRotateAboutTargetSensitivityKeyboard * DeltaTime;
if( hotkeys[HOTKEY_CAMERA_RIGHT] )
rightways += m->ViewRotateAboutTargetSensitivityKeyboard * DeltaTime;
rotateH.FromAxisAngle( upwards, rightways );
// Up/down rotation
float upways = 0.0f;
if( hotkeys[HOTKEY_CAMERA_UP] )
upways -= m->ViewRotateAboutTargetSensitivityKeyboard * DeltaTime;
if( hotkeys[HOTKEY_CAMERA_DOWN] )
upways += m->ViewRotateAboutTargetSensitivityKeyboard * DeltaTime;
rotateV.FromAxisAngle( rightwards, upways );
rotateH *= rotateV;
rotateH.ToMatrix( rotateM );
delta = rotateM.Rotate( delta );
// Lock the inclination to a rather arbitrary values (for the sake of graphical decency)
float scan = sqrt( delta.X * delta.X + delta.Z * delta.Z ) / delta.Y;
if( ( scan >= 0.5f ) )
{
// Move the camera to the origin (in preparation for rotation )
m->ViewCamera.m_Orientation.Translate( origin * -1.0f );
m->ViewCamera.m_Orientation.Rotate( rotateH );
// Move the camera back to where it belongs
m->ViewCamera.m_Orientation.Translate( pivot + delta );
}
}
else if( hotkeys[HOTKEY_CAMERA_PAN] )
{
// Middle-drag to pan
//keep camera in bounds
CameraLock(rightwards * (m->ViewDragSensitivity * mouse_dx));
CameraLock(forwards_horizontal * (-m->ViewDragSensitivity * mouse_dy));
}
// Mouse movement
if( g_mouse_active && !hotkeys[HOTKEY_CAMERA_ROTATE] && !hotkeys[HOTKEY_CAMERA_ROTATE_ABOUT_TARGET] )
if (g_mouse_active)
{
if (g_mouse_x >= g_xres - 2 && g_mouse_x < g_xres)
CameraLock(rightwards * (m->ViewScrollSpeed * DeltaTime));
moveRightward += m->ViewScrollSpeed * DeltaTime;
else if (g_mouse_x <= 3 && g_mouse_x >= 0)
CameraLock(-rightwards * (m->ViewScrollSpeed * DeltaTime));
moveRightward -= m->ViewScrollSpeed * DeltaTime;
if (g_mouse_y >= g_yres - 2 && g_mouse_y < g_yres)
CameraLock(-forwards_horizontal * (m->ViewScrollSpeed * DeltaTime));
moveForward -= m->ViewScrollSpeed * DeltaTime;
else if (g_mouse_y <= 3 && g_mouse_y >= 0)
CameraLock(forwards_horizontal * (m->ViewScrollSpeed * DeltaTime));
moveForward += m->ViewScrollSpeed * DeltaTime;
}
// Keyboard movement (added to mouse movement, so you can go faster if you want)
if (hotkeys[HOTKEY_CAMERA_PAN_KEYBOARD])
{
if (hotkeys[HOTKEY_CAMERA_RIGHT])
CameraLock(rightwards * (m->ViewScrollSpeed * DeltaTime));
moveRightward += m->ViewScrollSpeed * DeltaTime;
if (hotkeys[HOTKEY_CAMERA_LEFT])
CameraLock(-rightwards * (m->ViewScrollSpeed * DeltaTime));
if( hotkeys[HOTKEY_CAMERA_DOWN] )
CameraLock(-forwards_horizontal * (m->ViewScrollSpeed * DeltaTime));
moveRightward -= m->ViewScrollSpeed * DeltaTime;
if (hotkeys[HOTKEY_CAMERA_UP])
CameraLock(forwards_horizontal * (m->ViewScrollSpeed * DeltaTime));
moveForward += m->ViewScrollSpeed * DeltaTime;
if (hotkeys[HOTKEY_CAMERA_DOWN])
moveForward -= m->ViewScrollSpeed * DeltaTime;
}
// Smoothed zooming (move a certain percentage towards the desired zoom distance every frame)
// Note that scroll wheel zooming is event-based and handled in game_view_handler
if (moveRightward || moveForward)
{
float s = sin(m->RotateY.GetSmoothedValue());
float c = cos(m->RotateY.GetSmoothedValue());
m->PosX.AddSmoothly(c * moveRightward);
m->PosZ.AddSmoothly(-s * moveRightward);
m->PosX.AddSmoothly(s * moveForward);
m->PosZ.AddSmoothly(c * moveForward);
}
if (hotkeys[HOTKEY_CAMERA_ZOOM_IN])
m->ZoomDelta += m->ViewZoomSensitivity*DeltaTime;
else if( hotkeys[HOTKEY_CAMERA_ZOOM_OUT] )
m->ZoomDelta -= m->ViewZoomSensitivity*DeltaTime;
m->Zoom.AddSmoothly(m->ViewZoomSpeed * DeltaTime);
if (hotkeys[HOTKEY_CAMERA_ZOOM_OUT])
m->Zoom.AddSmoothly(-m->ViewZoomSpeed * DeltaTime);
if (fabsf(m->ZoomDelta) > 0.1f) // use a fairly high limit to avoid nasty flickering when zooming
float zoomDelta = m->Zoom.Update(DeltaTime);
if (zoomDelta)
{
float zoom_proportion = powf(m->ViewZoomSmoothness, DeltaTime);
CameraLock(forwards * (m->ZoomDelta * (1.0f-zoom_proportion)), false);
m->ZoomDelta *= zoom_proportion;
CVector3D forwards = m->ViewCamera.m_Orientation.GetIn();
m->PosX.AddSmoothly(forwards.X * zoomDelta);
m->PosY.AddSmoothly(forwards.Y * zoomDelta);
m->PosZ.AddSmoothly(forwards.Z * zoomDelta);
}
if (m->ConstrainCamera)
m->RotateX.ClampSmoothly(DEGTORAD(m->ViewRotateXMin), DEGTORAD(m->ViewRotateXMax));
ClampDistance(m, true);
m->PosX.Update(DeltaTime);
m->PosY.Update(DeltaTime);
m->PosZ.Update(DeltaTime);
// Handle rotation around the Y (vertical) axis
{
CCamera targetCam = m->ViewCamera;
SetupCameraMatrix(m, &targetCam.m_Orientation);
float rotateYDelta = m->RotateY.Update(DeltaTime);
if (rotateYDelta)
{
// We've updated RotateY, and need to adjust Pos so that it's still
// facing towards the original focus point (the terrain in the center
// of the screen).
CVector3D upwards(0.0f, 1.0f, 0.0f);
CVector3D pivot = targetCam.GetFocus();
CVector3D delta = targetCam.m_Orientation.GetTranslation() - pivot;
CQuaternion q;
q.FromAxisAngle(upwards, rotateYDelta);
CVector3D d = q.Rotate(delta) - delta;
m->PosX.Add(d.X);
m->PosY.Add(d.Y);
m->PosZ.Add(d.Z);
}
}
// Handle rotation around the X (sideways, relative to camera) axis
{
CCamera targetCam = m->ViewCamera;
SetupCameraMatrix(m, &targetCam.m_Orientation);
float rotateXDelta = m->RotateX.Update(DeltaTime);
if (rotateXDelta)
{
CVector3D rightwards = targetCam.m_Orientation.GetLeft() * -1.0f;
CVector3D pivot = m->ViewCamera.GetFocus();
CVector3D delta = targetCam.m_Orientation.GetTranslation() - pivot;
CQuaternion q;
q.FromAxisAngle(rightwards, rotateXDelta);
CVector3D d = q.Rotate(delta) - delta;
m->PosX.Add(d.X);
m->PosY.Add(d.Y);
m->PosZ.Add(d.Z);
}
}
/* This is disabled since it doesn't seem necessary:
// Ensure the camera's near point is never inside the terrain
if (m->ConstrainCamera)
{
CMatrix3D target;
target.SetIdentity();
target.RotateX(m->RotateX.GetValue());
target.RotateY(m->RotateY.GetValue());
target.Translate(m->PosX.GetValue(), m->PosY.GetValue(), m->PosZ.GetValue());
CVector3D nearPoint = target.GetTranslation() + target.GetIn() * defaultNear;
float ground = m->Game->GetWorld()->GetTerrain()->GetExactGroundLevel(nearPoint.X, nearPoint.Z);
float limit = ground + 16.f;
if (nearPoint.Y < limit)
m->PosY.AddSmoothly(limit - nearPoint.Y);
}
*/
// Update the camera matrix
SetupCameraMatrix(m, &m->ViewCamera.m_Orientation);
m->ViewCamera.UpdateFrustum();
}
void CGameView::PushCameraTarget( const CVector3D& target )
{
// Save the current position
m->CameraTargets.push_back( m->ViewCamera.m_Orientation.GetTranslation() );
// And set the camera
SetCameraTarget( target );
}
void CGameView::SetCameraTarget( const CVector3D& target )
void CGameView::MoveCameraTarget(const CVector3D& target)
{
// Maintain the same orientation and level of zoom, if we can
// (do this by working out the point the camera is looking at, saving
// the difference between that position and the camera point, and restoring
// that difference to our new target)
CVector3D CurrentTarget = m->ViewCamera.GetFocus();
m->CameraDelta = target - CurrentTarget;
CCamera targetCam = m->ViewCamera;
targetCam.m_Orientation.SetIdentity();
targetCam.m_Orientation.RotateX(m->RotateX.GetValue());
targetCam.m_Orientation.RotateY(m->RotateY.GetValue());
targetCam.m_Orientation.Translate(m->PosX.GetValue(), m->PosY.GetValue(), m->PosZ.GetValue());
CVector3D pivot = targetCam.GetFocus();
CVector3D delta = target - pivot;
m->PosX.SetValueSmoothly(delta.X + m->PosX.GetValue());
m->PosY.SetValueSmoothly(delta.Y + m->PosY.GetValue());
m->PosZ.SetValueSmoothly(delta.Z + m->PosZ.GetValue());
ClampDistance(m, false);
}
void CGameView::PopCameraTarget()
void CGameView::ResetCameraTarget(const CVector3D& target)
{
m->CameraDelta = m->CameraTargets.back() - m->ViewCamera.m_Orientation.GetTranslation();
m->CameraTargets.pop_back();
CMatrix3D orientation;
orientation.SetIdentity();
orientation.RotateX(DEGTORAD(m->ViewRotateXDefault));
orientation.RotateY(DEGTORAD(m->ViewRotateYDefault));
CVector3D delta = orientation.GetIn() * m->ViewZoomDefault;
m->PosX.SetValue(target.X - delta.X);
m->PosY.SetValue(target.Y - delta.Y);
m->PosZ.SetValue(target.Z - delta.Z);
ClampDistance(m, false);
SetupCameraMatrix(m, &m->ViewCamera.m_Orientation);
m->ViewCamera.UpdateFrustum();
}
InReaction game_view_handler(const SDL_Event_* ev)
@ -786,73 +808,27 @@ InReaction CGameView::HandleEvent(const SDL_Event_* ev)
g_Renderer.SetTerrainRenderMode(SOLID);
g_Renderer.SetModelRenderMode(SOLID);
}
return( IN_HANDLED );
case HOTKEY_CAMERA_RESET_ORIGIN:
ResetCamera();
return( IN_HANDLED );
case HOTKEY_CAMERA_RESET:
ResetCameraOrientation();
return( IN_HANDLED );
case HOTKEY_CAMERA_ROTATE_ABOUT_TARGET:
RotateAboutTarget();
return( IN_HANDLED );
return IN_HANDLED;
// Mouse wheel must be treated using events instead of polling,
// because SDL auto-generates a sequence of mousedown/mouseup events
// and we never get to see the "down" state inside Update().
case HOTKEY_CAMERA_ZOOM_WHEEL_IN:
m->ZoomDelta += m->ViewZoomSensitivityWheel;
return( IN_HANDLED );
m->Zoom.AddSmoothly(m->ViewZoomSpeedWheel);
return IN_HANDLED;
case HOTKEY_CAMERA_ZOOM_WHEEL_OUT:
m->ZoomDelta -= m->ViewZoomSensitivityWheel;
return( IN_HANDLED );
m->Zoom.AddSmoothly(-m->ViewZoomSpeedWheel);
return IN_HANDLED;
default:
case HOTKEY_CAMERA_ROTATE_WHEEL_CW:
m->RotateY.AddSmoothly(m->ViewRotateYSpeedWheel);
return IN_HANDLED;
if( ( ev->ev.user.code >= HOTKEY_CAMERA_BOOKMARK_0 ) && ( ev->ev.user.code <= HOTKEY_CAMERA_BOOKMARK_9 ) )
{
// The above test limits it to 10 bookmarks, so don't worry about overflowing
i8 id = (i8)( ev->ev.user.code - HOTKEY_CAMERA_BOOKMARK_0 );
if( hotkeys[HOTKEY_CAMERA_BOOKMARK_SAVE] )
{
// Attempt to track the ground we're looking at
cameraBookmarks[id] = GetCamera()->GetFocus();
bookmarkInUse[id] = true;
case HOTKEY_CAMERA_ROTATE_WHEEL_CCW:
m->RotateY.AddSmoothly(-m->ViewRotateYSpeedWheel);
return IN_HANDLED;
}
else if( hotkeys[HOTKEY_CAMERA_BOOKMARK_SNAP] )
{
if( bookmarkInUse[id] && ( currentBookmark == -1 ) )
{
PushCameraTarget( cameraBookmarks[id] );
currentBookmark = id;
}
}
else
{
if( bookmarkInUse[id] )
SetCameraTarget( cameraBookmarks[id] );
}
return( IN_HANDLED );
}
}
case SDL_HOTKEYUP:
switch( ev->ev.user.code )
{
case HOTKEY_CAMERA_BOOKMARK_SNAP:
if( currentBookmark != -1 )
PopCameraTarget();
currentBookmark = -1;
break;
default:
return( IN_PASS );
}
return( IN_HANDLED );
}
return IN_PASS;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -81,22 +81,8 @@ public:
InReaction HandleEvent(const SDL_Event_* ev);
//Keep the camera in between boundaries/smooth camera scrolling/translating
//Should call this whenever moving (translating) the camera
void CameraLock(const CVector3D& Trans, bool smooth=true);
void CameraLock(float x, float y, float z, bool smooth=true);
// Camera Control Functions (used by input handler)
void ResetCamera();
void ResetCameraOrientation();
void RotateAboutTarget();
void PushCameraTarget( const CVector3D& target );
void SetCameraTarget( const CVector3D& target );
void PopCameraTarget();
//Keep view the same but follow the unit
// void AttachToUnit(CEntity* target); // TODO: reimplement this for new sim system
void MoveCameraTarget(const CVector3D& target);
void ResetCameraTarget(const CVector3D& target);
CCamera *GetCamera();
CCinemaManager* GetCinema();

View File

@ -21,6 +21,7 @@
#include "graphics/Camera.h"
#include "graphics/CinemaTrack.h"
#include "graphics/GameView.h"
#include "graphics/Patch.h"
#include "graphics/Terrain.h"
#include "graphics/TextureEntry.h"
@ -56,13 +57,13 @@ CMapReader::CMapReader()
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
WaterManager* pWaterMan_, SkyManager* pSkyMan_,
CLightEnv *pLightEnv_, CCamera *pCamera_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_,
CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_,
CSimulation2 *pSimulation2_, int playerID_)
{
// latch parameters (held until DelayedLoadFinished)
pTerrain = pTerrain_;
pLightEnv = pLightEnv_;
pCamera = pCamera_;
pGameView = pGameView_;
pWaterMan = pWaterMan_;
pSkyMan = pSkyMan_;
pCinema = pCinema_;
@ -220,22 +221,13 @@ int CMapReader::ApplyData()
*pLightEnv = m_LightEnv;
}
if (m_CameraStartupTarget != INVALID_ENTITY && pCamera)
if (m_CameraStartupTarget != INVALID_ENTITY && pGameView)
{
CmpPtr<ICmpPosition> cmpPosition(*pSimulation2, m_CameraStartupTarget);
if (!cmpPosition.null())
{
pCamera->m_Orientation.SetIdentity();
pCamera->m_Orientation.Translate(CVector3D(0.f, 0.f, -200.f)); // move backwards from the target entity
pCamera->m_Orientation.RotateX(DEGTORAD(30));
pCamera->m_Orientation.RotateY(DEGTORAD(0));
CFixedVector3D pos = cmpPosition->GetPosition();
pCamera->m_Orientation.Translate(CVector3D(pos.X.ToFloat(), pos.Y.ToFloat(), pos.Z.ToFloat()));
pCamera->UpdateFrustum();
pGameView->ResetCameraTarget(CVector3D(pos.X.ToFloat(), pos.Y.ToFloat(), pos.Z.ToFloat()));
}
}
@ -695,12 +687,12 @@ void CXMLReader::ReadCamera(XMBElement parent)
debug_warn(L"Invalid map XML data");
}
if (m_MapReader.pCamera)
if (m_MapReader.pGameView)
{
m_MapReader.pCamera->m_Orientation.SetXRotation(declination);
m_MapReader.pCamera->m_Orientation.RotateY(rotation);
m_MapReader.pCamera->m_Orientation.Translate(translation);
m_MapReader.pCamera->UpdateFrustum();
m_MapReader.pGameView->GetCamera()->m_Orientation.SetXRotation(declination);
m_MapReader.pGameView->GetCamera()->m_Orientation.RotateY(rotation);
m_MapReader.pGameView->GetCamera()->m_Orientation.Translate(translation);
m_MapReader.pGameView->GetCamera()->UpdateFrustum();
}
}

View File

@ -30,13 +30,13 @@ class CTerrain;
class WaterManager;
class SkyManager;
class CLightEnv;
class CCamera;
class CCinemaManager;
class CTriggerManager;
class CSimulation2;
class CTextureEntry;
class CScriptValRooted;
class ScriptInterface;
class CGameView;
class CXMLReader;
@ -49,7 +49,7 @@ public:
CMapReader();
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
void LoadMap(const VfsPath& pathname, CTerrain*,
WaterManager*, SkyManager*, CLightEnv*, CCamera*,
WaterManager*, SkyManager*, CLightEnv*, CGameView*,
CCinemaManager*, CTriggerManager*, CSimulation2*, int playerID);
private:
@ -89,7 +89,7 @@ private:
WaterManager* pWaterMan;
SkyManager* pSkyMan;
CLightEnv* pLightEnv;
CCamera* pCamera;
CGameView* pGameView;
CCinemaManager* pCinema;
CTriggerManager* pTrigMan;
CSimulation2* pSimulation2;

View File

@ -19,6 +19,7 @@
#include "Camera.h"
#include "CinemaTrack.h"
#include "GameView.h"
#include "LightEnv.h"
#include "MapReader.h"
#include "MapWriter.h"
@ -501,7 +502,7 @@ void CMapWriter::WriteTrigger(XMLWriter_File& xml_file_, const MapTrigger& trigg
// RewriteAllMaps
void CMapWriter::RewriteAllMaps(CTerrain* pTerrain,
WaterManager* pWaterMan, SkyManager* pSkyMan,
CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema,
CLightEnv* pLightEnv, CGameView* pGameView, CCinemaManager* pCinema,
CTriggerManager* pTrigMan, CSimulation2* pSimulation2)
{
VfsPaths pathnames;
@ -510,13 +511,13 @@ void CMapWriter::RewriteAllMaps(CTerrain* pTerrain,
{
CMapReader* reader = new CMapReader;
LDR_BeginRegistering();
reader->LoadMap(pathnames[i], pTerrain, pWaterMan, pSkyMan, pLightEnv, pCamera, pCinema, pTrigMan, pSimulation2, -1);
reader->LoadMap(pathnames[i], pTerrain, pWaterMan, pSkyMan, pLightEnv, pGameView, pCinema, pTrigMan, pSimulation2, -1);
LDR_EndRegistering();
LDR_NonprogressiveLoad();
CStrW newPathname(pathnames[i].string());
newPathname.Replace(L"scenarios/", L"scenarios/new/");
CMapWriter writer;
writer.SaveMap(newPathname, pTerrain, pWaterMan, pSkyMan, pLightEnv, pCamera, pCinema, pSimulation2);
writer.SaveMap(newPathname, pTerrain, pWaterMan, pSkyMan, pLightEnv, pGameView->GetCamera(), pCinema, pSimulation2);
}
}

View File

@ -51,7 +51,7 @@ public:
// RewriteAllMaps: for use during development: load/save all maps, to
// update them to the newest format.
static void RewriteAllMaps(CTerrain* pTerrain, WaterManager* pWaterMan,
SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera,
SkyManager* pSkyMan, CLightEnv* pLightEnv, CGameView* pGameView,
CCinemaManager* pCinema, CTriggerManager* pTrigMan,
CSimulation2* pSimulation2);

View File

@ -124,41 +124,14 @@ void CMiniMap::HandleMessage(const SGUIMessage &Message)
void CMiniMap::SetCameraPos()
{
CTerrain *MMTerrain=g_Game->GetWorld()->GetTerrain();
CVector3D CamOrient=m_Camera->m_Orientation.GetTranslation();
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
//get center point of screen
int x = g_Renderer.GetWidth()/2;
int y = g_Renderer.GetHeight()/2;
CVector3D ScreenMiddle=m_Camera->GetWorldCoordinates(x,y);
//Get Vector required to go from camera position to ScreenMiddle
CVector3D TransVector;
TransVector.X=CamOrient.X-ScreenMiddle.X;
TransVector.Z=CamOrient.Z-ScreenMiddle.Z;
//world position of where mouse clicked
CVector3D Destination;
CPos MousePos = GetMousePos();
//X and Z according to proportion of mouse position and minimap
Destination.X = CELL_SIZE * m_MapSize *
( (MousePos.x - m_CachedActualSize.left) / m_CachedActualSize.GetWidth() );
Destination.Z = CELL_SIZE * m_MapSize * ( (m_CachedActualSize.bottom - MousePos.y) /
m_CachedActualSize.GetHeight() );
m_Camera->m_Orientation._14=Destination.X;
m_Camera->m_Orientation._34=Destination.Z;
m_Camera->m_Orientation._14+=TransVector.X;
m_Camera->m_Orientation._34+=TransVector.Z;
//Lock Y coord. No risk of zoom exceeding limit-Y does not increase
float Height=MMTerrain->GetExactGroundLevel(
m_Camera->m_Orientation._14, m_Camera->m_Orientation._34) + g_YMinOffset;
if (m_Camera->m_Orientation._24 < Height)
{
m_Camera->m_Orientation._24=Height;
}
m_Camera->UpdateFrustum();
CVector3D target;
CPos mousePos = GetMousePos();
target.X = CELL_SIZE * m_MapSize * ((mousePos.x - m_CachedActualSize.left) / m_CachedActualSize.GetWidth());
target.Z = CELL_SIZE * m_MapSize * ((m_CachedActualSize.bottom - mousePos.y) / m_CachedActualSize.GetHeight());
target.Y = terrain->GetExactGroundLevel(target.X, target.Z);
g_Game->GetView()->MoveCameraTarget(target);
}
void CMiniMap::FireWorldClickEvent(int button, int clicks)

View File

@ -55,8 +55,7 @@ protected:
// the terrain we are mini-mapping
const CTerrain* m_Terrain;
// not const: camera is moved by clicking on minimap
CCamera* m_Camera;
const CCamera* m_Camera;
//Whether or not the mouse is currently down
bool m_Clicking;

View File

@ -73,36 +73,22 @@ static SHotkeyInfo hotkeyInfo[] =
{ HOTKEY_BIGSCREENSHOT, "bigscreenshot", 0, 0 },
{ HOTKEY_WIREFRAME, "wireframe", SDLK_w, 0 },
{ HOTKEY_TOGGLEFULLSCREEN, "togglefullscreen", 0, 0 },
{ HOTKEY_CAMERA_RESET, "camera.reset", 0, 0 },
{ HOTKEY_CAMERA_RESET_ORIGIN, "camera.reset.origin", SDLK_h, 0 },
{ HOTKEY_CAMERA_ZOOM_IN, "camera.zoom.in", SDLK_PLUS, SDLK_KP_PLUS },
{ HOTKEY_CAMERA_ZOOM_OUT, "camera.zoom.out", SDLK_MINUS, SDLK_KP_MINUS },
{ HOTKEY_CAMERA_ZOOM_WHEEL_IN, "camera.zoom.wheel.in", MOUSE_WHEELUP, 0 },
{ HOTKEY_CAMERA_ZOOM_WHEEL_OUT, "camera.zoom.wheel.out", MOUSE_WHEELDOWN, 0 },
{ HOTKEY_CAMERA_ROTATE, "camera.rotate", 0, 0 },
{ HOTKEY_CAMERA_ROTATE_KEYBOARD, "camera.rotate.keyboard", 0, 0 },
{ HOTKEY_CAMERA_ROTATE_ABOUT_TARGET, "camera.rotate.abouttarget", 0, 0 },
{ HOTKEY_CAMERA_ROTATE_ABOUT_TARGET_KEYBOARD, "camera.rotate.abouttarget.keyboard", 0, 0 },
{ HOTKEY_CAMERA_ROTATE_CW, "camera.rotate.cw", 0, 0 },
{ HOTKEY_CAMERA_ROTATE_CCW, "camera.rotate.ccw", 0, 0 },
{ HOTKEY_CAMERA_ROTATE_UP, "camera.rotate.up", 0, 0 },
{ HOTKEY_CAMERA_ROTATE_DOWN, "camera.rotate.down", 0, 0 },
{ HOTKEY_CAMERA_ROTATE_WHEEL_CW, "camera.rotate.wheel.cw", 0, 0 },
{ HOTKEY_CAMERA_ROTATE_WHEEL_CCW, "camera.rotate.wheel.ccw", 0, 0 },
{ HOTKEY_CAMERA_PAN, "camera.pan", MOUSE_MIDDLE, 0 },
{ HOTKEY_CAMERA_PAN_KEYBOARD, "camera.pan.keyboard", 0, 0 },
{ HOTKEY_CAMERA_LEFT, "camera.left", SDLK_LEFT, 0 },
{ HOTKEY_CAMERA_RIGHT, "camera.right", SDLK_RIGHT, 0 },
{ HOTKEY_CAMERA_UP, "camera.up", SDLK_UP, 0 },
{ HOTKEY_CAMERA_DOWN, "camera.down", SDLK_DOWN, 0 },
{ HOTKEY_CAMERA_UNIT_VIEW, "camera.unit.view", SDLK_u, 0 },
{ HOTKEY_CAMERA_UNIT_ATTACH, "camera.unit.attach", SDLK_l, 0 },
{ HOTKEY_CAMERA_BOOKMARK_0, "camera.bookmark.0", SDLK_F5, 0, },
{ HOTKEY_CAMERA_BOOKMARK_1, "camera.bookmark.1", SDLK_F6, 0, },
{ HOTKEY_CAMERA_BOOKMARK_2, "camera.bookmark.2", SDLK_F7, 0, },
{ HOTKEY_CAMERA_BOOKMARK_3, "camera.bookmark.3", SDLK_F8, 0, },
{ HOTKEY_CAMERA_BOOKMARK_4, "camera.bookmark.4", 0, 0, },
{ HOTKEY_CAMERA_BOOKMARK_5, "camera.bookmark.5", 0, 0, },
{ HOTKEY_CAMERA_BOOKMARK_6, "camera.bookmark.6", 0, 0, },
{ HOTKEY_CAMERA_BOOKMARK_7, "camera.bookmark.7", 0, 0, },
{ HOTKEY_CAMERA_BOOKMARK_8, "camera.bookmark.8", 0, 0, },
{ HOTKEY_CAMERA_BOOKMARK_9, "camera.bookmark.9", 0, 0, },
{ HOTKEY_CAMERA_BOOKMARK_SAVE, "camera.bookmark.save", 0, 0 },
{ HOTKEY_CAMERA_BOOKMARK_SNAP, "camera.bookmark.snap", 0, 0 },
{ HOTKEY_CAMERA_CINEMA_ADD, "camera.cinema.add", SDLK_l, 0 },
{ HOTKEY_CAMERA_CINEMA_DELETE, "camera.cinema.delete", SDLK_u, 0 },
{ HOTKEY_CAMERA_CINEMA_DELETE_ALL, "camera.cinema.delete.all", SDLK_r, 0 },

View File

@ -54,36 +54,22 @@ enum
HOTKEY_BIGSCREENSHOT,
HOTKEY_WIREFRAME,
HOTKEY_TOGGLEFULLSCREEN,
HOTKEY_CAMERA_RESET,
HOTKEY_CAMERA_RESET_ORIGIN,
HOTKEY_CAMERA_ZOOM_IN,
HOTKEY_CAMERA_ZOOM_OUT,
HOTKEY_CAMERA_ZOOM_WHEEL_IN,
HOTKEY_CAMERA_ZOOM_WHEEL_OUT,
HOTKEY_CAMERA_ROTATE,
HOTKEY_CAMERA_ROTATE_KEYBOARD,
HOTKEY_CAMERA_ROTATE_ABOUT_TARGET,
HOTKEY_CAMERA_ROTATE_ABOUT_TARGET_KEYBOARD,
HOTKEY_CAMERA_ROTATE_CW,
HOTKEY_CAMERA_ROTATE_CCW,
HOTKEY_CAMERA_ROTATE_UP,
HOTKEY_CAMERA_ROTATE_DOWN,
HOTKEY_CAMERA_ROTATE_WHEEL_CW,
HOTKEY_CAMERA_ROTATE_WHEEL_CCW,
HOTKEY_CAMERA_PAN,
HOTKEY_CAMERA_PAN_KEYBOARD,
HOTKEY_CAMERA_LEFT,
HOTKEY_CAMERA_RIGHT,
HOTKEY_CAMERA_UP,
HOTKEY_CAMERA_DOWN,
HOTKEY_CAMERA_UNIT_VIEW,
HOTKEY_CAMERA_UNIT_ATTACH,
HOTKEY_CAMERA_BOOKMARK_0,
HOTKEY_CAMERA_BOOKMARK_1,
HOTKEY_CAMERA_BOOKMARK_2,
HOTKEY_CAMERA_BOOKMARK_3,
HOTKEY_CAMERA_BOOKMARK_4,
HOTKEY_CAMERA_BOOKMARK_5,
HOTKEY_CAMERA_BOOKMARK_6,
HOTKEY_CAMERA_BOOKMARK_7,
HOTKEY_CAMERA_BOOKMARK_8,
HOTKEY_CAMERA_BOOKMARK_9,
HOTKEY_CAMERA_BOOKMARK_SAVE,
HOTKEY_CAMERA_BOOKMARK_SNAP,
HOTKEY_CAMERA_CINEMA_ADD,
HOTKEY_CAMERA_CINEMA_DELETE,
HOTKEY_CAMERA_CINEMA_DELETE_ALL,

View File

@ -81,8 +81,7 @@ void CWorld::RegisterInit(const CStrW& mapFile, int playerID)
reader->LoadMap(mapfilename, m_Terrain,
CRenderer::IsInitialised() ? g_Renderer.GetWaterManager() : NULL,
CRenderer::IsInitialised() ? g_Renderer.GetSkyManager() : NULL,
&g_LightEnv,
m_pGame->GetView() ? m_pGame->GetView()->GetCamera() : NULL,
&g_LightEnv, m_pGame->GetView(),
m_pGame->GetView() ? m_pGame->GetView()->GetCinema() : NULL,
pTriggerManager, m_pGame->GetSimulation2(), playerID);
// fails immediately, or registers for delay loading
@ -117,7 +116,7 @@ void CWorld::RewriteMap()
{
CMapWriter::RewriteAllMaps(m_Terrain,
g_Renderer.GetWaterManager(), g_Renderer.GetSkyManager(),
&g_LightEnv, m_pGame->GetView()->GetCamera(),
&g_LightEnv, m_pGame->GetView(),
m_pGame->GetView()->GetCinema(), NULL,
m_pGame->GetSimulation2());
}

View File

@ -435,7 +435,7 @@ void TerrainRenderer::RenderWater()
}
//(Crappy) fresnel effect
CCamera* Camera=g_Game->GetView()->GetCamera();
const CCamera* Camera=g_Game->GetView()->GetCamera();
CVector3D CamFace=Camera->m_Orientation.GetIn();
CamFace.Normalize();
float FresnelScalar = CamFace.Dot( CVector3D(0.0f, -1.0f, 0.0f) );

View File

@ -398,7 +398,7 @@ JSBool SetCameraTarget( JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval*
JS_ReportError( cx, "Invalid camera target" );
return( JS_TRUE );
}
g_Game->GetView()->SetCameraTarget( *target );
g_Game->GetView()->ResetCameraTarget( *target );
*rval = JSVAL_TRUE;
return( JS_TRUE );

View File

@ -25,7 +25,7 @@
#include "simulation2/components/ICmpSelectable.h"
#include "simulation2/components/ICmpVisual.h"
std::vector<entity_id_t> EntitySelection::PickEntitiesAtPoint(CSimulation2& simulation, CCamera& camera, int screenX, int screenY)
std::vector<entity_id_t> EntitySelection::PickEntitiesAtPoint(CSimulation2& simulation, const CCamera& camera, int screenX, int screenY)
{
CVector3D origin, dir;
camera.BuildCameraRay(screenX, screenY, origin, dir);
@ -71,7 +71,7 @@ std::vector<entity_id_t> EntitySelection::PickEntitiesAtPoint(CSimulation2& simu
return hitEnts;
}
std::vector<entity_id_t> EntitySelection::PickEntitiesInRect(CSimulation2& simulation, CCamera& camera, int sx0, int sy0, int sx1, int sy1, int owner)
std::vector<entity_id_t> EntitySelection::PickEntitiesInRect(CSimulation2& simulation, const CCamera& camera, int sx0, int sy0, int sx1, int sy1, int owner)
{
// Make sure sx0 <= sx1, and sy0 <= sy1
if (sx0 > sx1)

View File

@ -37,14 +37,14 @@ namespace EntitySelection
* Finds all selectable entities under the given screen coordinates.
* Returns list ordered by closeness of picking, closest first.
*/
std::vector<entity_id_t> PickEntitiesAtPoint(CSimulation2& simulation, CCamera& camera, int screenX, int screenY);
std::vector<entity_id_t> PickEntitiesAtPoint(CSimulation2& simulation, const CCamera& camera, int screenX, int screenY);
/**
* Finds all selectable entities within the given screen coordinate rectangle,
* that belong to player @p owner.
* Returns unordered list.
*/
std::vector<entity_id_t> PickEntitiesInRect(CSimulation2& simulation, CCamera& camera, int sx0, int sy0, int sx1, int sy1, int owner);
std::vector<entity_id_t> PickEntitiesInRect(CSimulation2& simulation, const CCamera& camera, int sx0, int sy0, int sx1, int sy1, int owner);
} // namespace

View File

@ -161,7 +161,9 @@ MESSAGEHANDLER(CinemaEvent)
else if ( msg->mode == eCinemaEventMode::IMMEDIATE_PATH )
manager->MoveToPointAt(msg->t);
else if ( msg->mode == eCinemaEventMode::RESET )
g_Game->GetView()->ResetCamera();
{
// g_Game->GetView()->ResetCamera();
}
else if ( msg->mode == eCinemaEventMode::SELECT )
manager->SetCurrentPath(*msg->path, msg->drawCurrent, msg->lines);
else