/
cameramaster.cpp
152 lines (127 loc) · 5.4 KB
/
cameramaster.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <Urho3D/Urho3D.h>
#include <Urho3D/Core/CoreEvents.h>
#include <Urho3D/Scene/SceneEvents.h>
#include <Urho3D/Graphics/Camera.h>
#include <Urho3D/Graphics/Viewport.h>
#include <Urho3D/Graphics/RenderPath.h>
#include <Urho3D/Graphics/Light.h>
#include <Urho3D/Physics/CollisionShape.h>
#include <Urho3D/Physics/RigidBody.h>
#include <Urho3D/Scene/Scene.h>
#include <Urho3D/Resource/ResourceCache.h>
#include <Urho3D/Resource/XMLFile.h>
#include <Urho3D/Math/MathDefs.h>
#include <Urho3D/Input/Input.h>
#include "cameramaster.h"
template <class T>
inline int MyClamp(T value, T min, T max) noexcept
{
if (value < min)
return min;
else if (value > max)
return max;
else
return value;
}
Vector3 Scale(const Vector3& lhs, const Vector3& rhs)
{
return Vector3(
lhs.x_ * rhs.x_,
lhs.y_ * rhs.y_,
lhs.z_ * rhs.z_
);
}
CameraMaster::CameraMaster(
Context *context,
MasterControl *masterControl
) :
Object(context),
masterControl_{masterControl}
{
SubscribeToEvent(E_SCENEUPDATE, URHO3D_HANDLER(CameraMaster, HandleSceneUpdate));
//Create the camera. Limit far clip distance to match the fog
translationNode_ = masterControl_->world_.scene->CreateChild("CamTrans");
rotationNode_ = translationNode_->CreateChild("CamRot");
camera_ = rotationNode_->CreateComponent<Camera>();
camera_->SetFarClip(1024.0f);
//Set an initial position for the camera scene node above the origin
//translationNode_->SetPosition(Vector3(0.0f, 3.0f, 0.0f));
translationNode_->SetPosition(Vector3(0.0, 3.0,-20.0));
rotationNode_->SetRotation(Quaternion(0.0f, 90.0f, 0.0f));
rigidBody_ = translationNode_->CreateComponent<RigidBody>();
rigidBody_->SetAngularDamping(10.0f);
CollisionShape* collisionShape = translationNode_->CreateComponent<CollisionShape>();
collisionShape->SetSphere(0.1f);
rigidBody_->SetMass(1.0f);
Node* lightNode = translationNode_->CreateChild("DirectionalLight");
lightNode->SetDirection(Vector3(0.0f, -1.0f, 0.0f));
Light* light = lightNode->CreateComponent<Light>();
light->SetLightType(LIGHT_POINT);
light->SetBrightness(0.5f);
light->SetColor(Color(0.7f, 0.9f, 0.6f));
light->SetCastShadows(false);
SetupViewport();
}
void CameraMaster::Start()
{
}
void CameraMaster::Stop()
{
}
void CameraMaster::SetupViewport()
{
Renderer * const renderer = GetSubsystem<Renderer>();
//Set up a viewport to the Renderer subsystem so that the 3D scene can be seen
SharedPtr<Viewport> viewport(new Viewport(context_, masterControl_->world_.scene, camera_));
viewport_ = viewport;
//Add anti-aliasing
viewport_->SetRenderPath(effectRenderPath);
renderer->SetViewport(0, viewport);
}
Vector3 CameraMaster::GetWorldPosition()
{
return translationNode_->GetWorldPosition();
}
Quaternion CameraMaster::GetRotation()
{
return rotationNode_->GetRotation();
}
void CameraMaster::HandleSceneUpdate(StringHash /* eventType */, VariantMap &eventData)
{
using namespace Update;
//Take the frame time step, which is stored as a double
double timeStep = eventData[P_TIMESTEP].GetFloat();
//Movement speed as world units per second
const double MOVE_SPEED = 2000.0;
//Mouse sensitivity as degrees per pixel
const double MOUSE_SENSITIVITY = 0.1;
//Use this frame's mouse motion to adjust camera node yaw and pitch. Clamp the pitch between -90 and 90 degrees. Only move the camera when the cursor is hidden.
Input* input = GetSubsystem<Input>();
IntVector2 mouseMove = input->GetMouseMove();
yawDelta_ = 0.5*(yawDelta_ + MOUSE_SENSITIVITY * mouseMove.x_);
pitchDelta_ = 0.5*(pitchDelta_ + MOUSE_SENSITIVITY * mouseMove.y_);
yaw_ += yawDelta_;
pitch_ += pitchDelta_;
pitch_ = MyClamp(pitch_, -89.0, 89.0);
//Construct new orientation for the camera scene node from yaw and pitch. Roll is fixed to zero
translationNode_->SetRotation(Quaternion(0.0f, 0.0f, 0.0f));
rotationNode_->SetRotation(Quaternion(pitch_, yaw_, 0.0f));
//Read WASD keys and move the camera scene node to the corresponding direction if they are pressed
Vector3 camForce = Vector3::ZERO;
if (input->GetKeyDown(Urho3D::KEY_W)) camForce += Scale(rotationNode_->GetDirection(), Vector3(1.0f,0.0f,1.0f) ).Normalized();
if (input->GetKeyDown(Urho3D::KEY_S)) camForce += Scale(rotationNode_->GetDirection(), Vector3(-1.0f,0.0f,-1.0f) ).Normalized();
if (input->GetKeyDown(Urho3D::KEY_D)) camForce += Scale(rotationNode_->GetRight(), Vector3(1.0f,0.0f,1.0f) ).Normalized();
if (input->GetKeyDown(Urho3D::KEY_A)) camForce += Scale(rotationNode_->GetRight(), Vector3(-1.0f,0.0f,-1.0f) ).Normalized();
if (input->GetKeyDown(Urho3D::KEY_E)) camForce += Vector3::UP;
if (input->GetKeyDown(Urho3D::KEY_Q) && translationNode_->GetPosition().y_ > 1.0f) camForce += Vector3::DOWN;
camForce = camForce.Normalized() * MOVE_SPEED * timeStep;
if ( forceMultiplier < 8.0 && (input->GetKeyDown(KEY_LSHIFT)||input->GetKeyDown(KEY_RSHIFT)) ){
forceMultiplier += 0.23;
} else forceMultiplier = pow(forceMultiplier, 0.75);
rigidBody_->ApplyForce( (forceMultiplier * camForce) - (2.3f * rigidBody_->GetLinearVelocity()) );
if (translationNode_->GetPosition().y_ < 1.0f)
{
translationNode_->SetPosition(Vector3(translationNode_->GetPosition().x_, 1.0f, translationNode_->GetPosition().z_));
rigidBody_->SetLinearVelocity(Vector3(rigidBody_->GetLinearVelocity().x_, 0.0f, rigidBody_->GetLinearVelocity().z_));
}
}