1 /* Copyright (C) 2017 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
18 #include "precompiled.h"
20 #include "CinemaPath.h"
26 #include "CinemaManager.h"
29 #include "gui/GUIManager.h"
30 #include "gui/IGUIObject.h"
32 #include "maths/MathUtil.h"
33 #include "maths/Quaternion.h"
34 #include "maths/Vector3D.h"
35 #include "maths/Vector4D.h"
36 #include "ps/CLogger.h"
39 #include "renderer/Renderer.h"
42 CCinemaPath::CCinemaPath(const CCinemaData
& data
, const TNSpline
& spline
, const TNSpline
& targetSpline
)
43 : CCinemaData(data
), TNSpline(spline
), m_TargetSpline(targetSpline
), m_TimeElapsed(0.f
)
45 // Calculate curves by nodes
47 m_TargetSpline
.BuildSpline();
49 if (m_Orientation
== L
"target")
51 m_LookAtTarget
= true;
52 ENSURE(!m_TargetSpline
.GetAllNodes().empty());
55 // Set distortion mode and style
56 if (data
.m_Mode
== L
"ease_in")
57 DistModePtr
= &CCinemaPath::EaseIn
;
58 else if (data
.m_Mode
== L
"ease_out")
59 DistModePtr
= &CCinemaPath::EaseOut
;
60 else if (data
.m_Mode
== L
"ease_inout")
61 DistModePtr
= &CCinemaPath::EaseInOut
;
62 else if (data
.m_Mode
== L
"ease_outin")
63 DistModePtr
= &CCinemaPath::EaseOutIn
;
66 LOGWARNING("Cinematic mode not found for '%s'", data
.m_Mode
.ToUTF8().c_str());
67 DistModePtr
= &CCinemaPath::EaseInOut
;
70 if (data
.m_Style
== L
"default")
71 DistStylePtr
= &CCinemaPath::EaseDefault
;
72 else if (data
.m_Style
== L
"growth")
73 DistStylePtr
= &CCinemaPath::EaseGrowth
;
74 else if (data
.m_Style
== L
"expo")
75 DistStylePtr
= &CCinemaPath::EaseExpo
;
76 else if (data
.m_Style
== L
"circle")
77 DistStylePtr
= &CCinemaPath::EaseCircle
;
78 else if (data
.m_Style
== L
"sine")
79 DistStylePtr
= &CCinemaPath::EaseSine
;
82 LOGWARNING("Cinematic style not found for '%s'", data
.m_Style
.ToUTF8().c_str());
83 DistStylePtr
= &CCinemaPath::EaseDefault
;
87 CVector3D
CCinemaPath::GetNodePosition(const int index
) const
89 return Node
[index
].Position
;
92 fixed
CCinemaPath::GetNodeDuration(const int index
) const
94 return Node
[index
].Distance
;
97 fixed
CCinemaPath::GetDuration() const
102 float CCinemaPath::GetNodeFraction() const
104 return (m_TimeElapsed
- m_PreviousNodeTime
) / Node
[m_CurrentNode
].Distance
.ToFloat();
107 float CCinemaPath::GetElapsedTime() const
109 return m_TimeElapsed
;
112 const CStrW
& CCinemaPath::GetName() const
117 void CCinemaPath::SetTimescale(fixed scale
)
122 void CCinemaPath::MoveToPointAt(float t
, float nodet
, const CVector3D
& startRotation
, CCamera
* camera
) const
124 t
= (this->*DistModePtr
)(t
);
126 CVector3D pos
= GetPosition(t
);
130 if (m_TimeElapsed
<= m_TargetSpline
.MaxDistance
.ToFloat())
131 camera
->LookAt(pos
, m_TargetSpline
.GetPosition(m_TimeElapsed
/ m_TargetSpline
.MaxDistance
.ToFloat()), CVector3D(0, 1, 0));
133 camera
->LookAt(pos
, m_TargetSpline
.GetAllNodes().back().Position
, CVector3D(0, 1, 0));
137 CVector3D nodeRotation
= Node
[m_CurrentNode
+ 1].Rotation
;
138 CQuaternion start
, end
;
139 start
.FromEulerAngles(DEGTORAD(startRotation
.X
), DEGTORAD(startRotation
.Y
), DEGTORAD(startRotation
.Z
));
140 end
.FromEulerAngles(DEGTORAD(nodeRotation
.X
), DEGTORAD(nodeRotation
.Y
), DEGTORAD(nodeRotation
.Z
));
141 start
.Slerp(start
, end
, nodet
);
143 camera
->m_Orientation
.SetIdentity();
144 camera
->m_Orientation
.Rotate(start
);
145 camera
->m_Orientation
.Translate(pos
);
147 camera
->UpdateFrustum();
150 // Distortion mode functions
151 float CCinemaPath::EaseIn(float t
) const
153 return (this->*DistStylePtr
)(t
);
156 float CCinemaPath::EaseOut(float t
) const
158 return 1.0f
- EaseIn(1.0f
-t
);
161 float CCinemaPath::EaseInOut(float t
) const
164 return EaseIn(1.0f
/m_Switch
* t
) * m_Switch
;
165 return EaseOut(1.0f
/m_Switch
* (t
-m_Switch
)) * m_Switch
+ m_Switch
;
168 float CCinemaPath::EaseOutIn(float t
) const
171 return EaseOut(1.0f
/m_Switch
* t
) * m_Switch
;
172 return EaseIn(1.0f
/m_Switch
* (t
-m_Switch
)) * m_Switch
+ m_Switch
;
175 // Distortion style functions
176 float CCinemaPath::EaseDefault(float t
) const
181 float CCinemaPath::EaseGrowth(float t
) const
183 return pow(t
, m_Growth
);
186 float CCinemaPath::EaseExpo(float t
) const
190 return powf(m_Growth
, 10*(t
-1.0f
));
193 float CCinemaPath::EaseCircle(float t
) const
195 t
= -(sqrt(1.0f
- t
*t
) - 1.0f
);
196 if (m_GrowthCount
> 1.0f
)
199 return (this->*DistStylePtr
)(t
);
204 float CCinemaPath::EaseSine(float t
) const
206 t
= 1.0f
- cos(t
* (float)M_PI
/2);
207 if (m_GrowthCount
> 1.0f
)
210 return (this->*DistStylePtr
)(t
);
215 const CCinemaData
* CCinemaPath::GetData() const
217 return CCinemaData::GetData();
220 bool CCinemaPath::Validate()
222 if (m_TimeElapsed
> GetDuration().ToFloat() || m_TimeElapsed
< 0.0f
)
225 // Find current node and past "node time"
226 float previousTime
= 0.0f
, cumulation
= 0.0f
;
228 // Ignore the last node, since it is a blank (node time values are shifted down one from interface)
229 for (size_t i
= 0; i
< Node
.size() - 1; ++i
)
231 cumulation
+= Node
[i
].Distance
.ToFloat();
232 if (m_TimeElapsed
<= cumulation
)
234 m_PreviousNodeTime
= previousTime
;
235 m_PreviousRotation
= Node
[i
].Rotation
;
236 m_CurrentNode
= i
; // We're moving toward this next node, so use its rotation
239 previousTime
+= Node
[i
].Distance
.ToFloat();
241 debug_warn("validation of cinema path is wrong\n");
245 bool CCinemaPath::Play(const float deltaRealTime
, CCamera
* camera
)
247 m_TimeElapsed
+= m_Timescale
.ToFloat() * deltaRealTime
;
251 MoveToPointAt(m_TimeElapsed
/ GetDuration().ToFloat(), GetNodeFraction(), m_PreviousRotation
, camera
);
255 bool CCinemaPath::Empty() const
260 void CCinemaPath::Reset()
262 m_TimeElapsed
= 0.0f
;
265 fixed
CCinemaPath::GetTimescale() const
270 const TNSpline
& CCinemaPath::GetTargetSpline() const
272 return m_TargetSpline
;