-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathcamera.cpp
More file actions
153 lines (130 loc) · 4.13 KB
/
camera.cpp
File metadata and controls
153 lines (130 loc) · 4.13 KB
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
152
153
#include "camera.hpp"
#include "chunkworld.hpp"
namespace BigWorld
{
Camera::Camera(ChunkWorld* world, Urho3D::IntVector2 const& chunk_pos, unsigned baseheight, Urho3D::Vector3 const& pos, float yaw, float pitch, float roll, unsigned viewdistance_in_chunks) :
world(world),
chunk_pos(chunk_pos),
baseheight(baseheight),
pos(pos),
yaw(yaw),
pitch(pitch),
roll(roll),
viewdistance_in_chunks(viewdistance_in_chunks),
water_refl_camera_raw(NULL)
{
node = world->getScene()->CreateChild();
camera_raw = node->CreateComponent<Urho3D::Camera>();
}
Urho3D::Quaternion Camera::getRotation() const
{
Urho3D::Quaternion rot(roll, Urho3D::Vector3::FORWARD);
rot = Urho3D::Quaternion(pitch, Urho3D::Vector3::RIGHT) * rot;
rot = Urho3D::Quaternion(yaw, Urho3D::Vector3::UP) * rot;
return rot;
}
void Camera::applyRelativeMovement(Urho3D::Vector3 const& movement)
{
applyAbsoluteMovement(getRotation() * movement);
}
void Camera::applyAbsoluteMovement(Urho3D::Vector3 const& movement)
{
pos += movement;
// TODO: Check if chunk_pos/baseheight should be updated!
updateNodeTransform();
}
void Camera::setTransform(Urho3D::IntVector2 const& chunk_pos, unsigned baseheight, Urho3D::Vector3 const& pos, float yaw, float pitch, float roll)
{
float const CHUNK_W_F = world->getChunkWidthFloat();
float const HEIGHTSTEP = world->getHeightstep();
// Only update position for now
// TODO: Fix this in future! Right now it causes some strange problems where viewarea building is started at every frame.
Urho3D::Vector3 pos_diff = pos - this->pos;
pos_diff.x_ += (chunk_pos.x_ - this->chunk_pos.x_) * CHUNK_W_F;
pos_diff.z_ += (chunk_pos.y_ - this->chunk_pos.y_) * CHUNK_W_F;
pos_diff.y_ += (int(baseheight) - int(this->baseheight)) * HEIGHTSTEP;
this->pos += pos_diff;
this->yaw = yaw;
this->pitch = pitch;
this->roll = roll;
updateNodeTransform();
}
void Camera::setRotation(float yaw, float pitch, float roll)
{
this->yaw = yaw;
this->pitch = pitch;
this->roll = roll;
updateNodeTransform();
}
void Camera::setNearAndFarClip(float near, float far)
{
camera_raw->SetNearClip(near);
camera_raw->SetFarClip(far);
if (water_refl_camera_raw) {
water_refl_camera_raw->SetNearClip(near);
water_refl_camera_raw->SetFarClip(far);
}
}
void Camera::updateNodeTransform()
{
float const CHUNK_W_F = world->getChunkWidthFloat();
float const HEIGHTSTEP = world->getHeightstep();
Urho3D::IntVector2 origin = world->getOrigin();
int origin_height = world->getOriginHeight();
Urho3D::IntVector2 diff_xz = chunk_pos - origin;
int diff_y = baseheight - origin_height;
Urho3D::Vector3 final_pos = pos;
final_pos.x_ += diff_xz.x_ * CHUNK_W_F;
final_pos.y_ += diff_y * HEIGHTSTEP;
final_pos.z_ += diff_xz.y_ * CHUNK_W_F;
node->SetPosition(final_pos);
node->SetRotation(getRotation());
}
bool Camera::fixIfOutsideOrigin()
{
float const CHUNK_W_F = world->getChunkWidthFloat();
float const CHUNK_HALF_W_F = CHUNK_W_F / 2;
float const HEIGHTSTEP = world->getHeightstep();
float CHUNK_THRESHOLD = 1.5;
unsigned const HEIGHT_THRESHOLD = 500;
bool fixed = false;
if (pos.x_ < -CHUNK_HALF_W_F * CHUNK_THRESHOLD) {
pos.x_ += CHUNK_W_F;
-- chunk_pos.x_;
fixed = true;
} else if (pos.x_ > CHUNK_HALF_W_F * CHUNK_THRESHOLD) {
pos.x_ -= CHUNK_W_F;
++ chunk_pos.x_;
fixed = true;
}
if (pos.z_ < -CHUNK_HALF_W_F * CHUNK_THRESHOLD) {
pos.z_ += CHUNK_W_F;
-- chunk_pos.y_;
fixed = true;
} else if (pos.z_ > CHUNK_HALF_W_F * CHUNK_THRESHOLD) {
pos.z_ -= CHUNK_W_F;
++ chunk_pos.y_;
fixed = true;
}
if (pos.y_ > HEIGHTSTEP * HEIGHT_THRESHOLD) {
pos.y_ -= HEIGHTSTEP * HEIGHT_THRESHOLD;
baseheight += HEIGHT_THRESHOLD;
fixed = true;
} else if (pos.y_ < -HEIGHTSTEP * HEIGHT_THRESHOLD && baseheight > 0) {
int mod = Urho3D::Min<int>(baseheight, HEIGHT_THRESHOLD);
pos.y_ += HEIGHTSTEP * mod;
baseheight -= mod;
fixed = true;
}
return fixed;
}
Urho3D::Camera* Camera::createWaterReflectionCamera()
{
if (water_refl_camera_raw) {
throw std::runtime_error("Reflection camera already created!");
}
Urho3D::Node* water_refl_camera_node = node->CreateChild();
water_refl_camera_raw = water_refl_camera_node->CreateComponent<Urho3D::Camera>();
return water_refl_camera_raw;
}
}