Move CinemaPath class to the simulation helper directory, because it contains predomi...
[0ad.git] / source / simulation2 / helpers / CinemaPath.cpp
blob44031880a4775d668fd30262ba1d20ad05703b11
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"
22 #include <sstream>
23 #include <string>
25 #include "graphics/Camera.h"
26 #include "maths/MathUtil.h"
27 #include "maths/Quaternion.h"
28 #include "maths/Vector3D.h"
29 #include "ps/CLogger.h"
30 #include "ps/CStr.h"
32 CCinemaPath::CCinemaPath(const CCinemaData& data, const TNSpline& spline, const TNSpline& targetSpline)
33 : CCinemaData(data), TNSpline(spline), m_TargetSpline(targetSpline), m_TimeElapsed(0.f)
35 // Calculate curves by nodes
36 BuildSpline();
37 m_TargetSpline.BuildSpline();
39 if (m_Orientation == L"target")
41 m_LookAtTarget = true;
42 ENSURE(!m_TargetSpline.GetAllNodes().empty());
45 // Set distortion mode and style
46 if (data.m_Mode == L"ease_in")
47 DistModePtr = &CCinemaPath::EaseIn;
48 else if (data.m_Mode == L"ease_out")
49 DistModePtr = &CCinemaPath::EaseOut;
50 else if (data.m_Mode == L"ease_inout")
51 DistModePtr = &CCinemaPath::EaseInOut;
52 else if (data.m_Mode == L"ease_outin")
53 DistModePtr = &CCinemaPath::EaseOutIn;
54 else
56 LOGWARNING("Cinematic mode not found for '%s'", data.m_Mode.ToUTF8().c_str());
57 DistModePtr = &CCinemaPath::EaseInOut;
60 if (data.m_Style == L"default")
61 DistStylePtr = &CCinemaPath::EaseDefault;
62 else if (data.m_Style == L"growth")
63 DistStylePtr = &CCinemaPath::EaseGrowth;
64 else if (data.m_Style == L"expo")
65 DistStylePtr = &CCinemaPath::EaseExpo;
66 else if (data.m_Style == L"circle")
67 DistStylePtr = &CCinemaPath::EaseCircle;
68 else if (data.m_Style == L"sine")
69 DistStylePtr = &CCinemaPath::EaseSine;
70 else
72 LOGWARNING("Cinematic style not found for '%s'", data.m_Style.ToUTF8().c_str());
73 DistStylePtr = &CCinemaPath::EaseDefault;
77 CVector3D CCinemaPath::GetNodePosition(const int index) const
79 return Node[index].Position;
82 fixed CCinemaPath::GetNodeDuration(const int index) const
84 return Node[index].Distance;
87 fixed CCinemaPath::GetDuration() const
89 return MaxDistance;
92 float CCinemaPath::GetNodeFraction() const
94 return (m_TimeElapsed - m_PreviousNodeTime) / Node[m_CurrentNode].Distance.ToFloat();
97 float CCinemaPath::GetElapsedTime() const
99 return m_TimeElapsed;
102 const CStrW& CCinemaPath::GetName() const
104 return m_Name;
107 void CCinemaPath::SetTimescale(fixed scale)
109 m_Timescale = scale;
112 void CCinemaPath::MoveToPointAt(float t, float nodet, const CVector3D& startRotation, CCamera* camera) const
114 t = (this->*DistModePtr)(t);
116 CVector3D pos = GetPosition(t);
118 if (m_LookAtTarget)
120 if (m_TimeElapsed <= m_TargetSpline.MaxDistance.ToFloat())
121 camera->LookAt(pos, m_TargetSpline.GetPosition(m_TimeElapsed / m_TargetSpline.MaxDistance.ToFloat()), CVector3D(0, 1, 0));
122 else
123 camera->LookAt(pos, m_TargetSpline.GetAllNodes().back().Position, CVector3D(0, 1, 0));
125 else
127 CVector3D nodeRotation = Node[m_CurrentNode + 1].Rotation;
128 CQuaternion start, end;
129 start.FromEulerAngles(DEGTORAD(startRotation.X), DEGTORAD(startRotation.Y), DEGTORAD(startRotation.Z));
130 end.FromEulerAngles(DEGTORAD(nodeRotation.X), DEGTORAD(nodeRotation.Y), DEGTORAD(nodeRotation.Z));
131 start.Slerp(start, end, nodet);
133 camera->m_Orientation.SetIdentity();
134 camera->m_Orientation.Rotate(start);
135 camera->m_Orientation.Translate(pos);
137 camera->UpdateFrustum();
140 // Distortion mode functions
141 float CCinemaPath::EaseIn(float t) const
143 return (this->*DistStylePtr)(t);
146 float CCinemaPath::EaseOut(float t) const
148 return 1.0f - EaseIn(1.0f-t);
151 float CCinemaPath::EaseInOut(float t) const
153 if (t < m_Switch)
154 return EaseIn(1.0f/m_Switch * t) * m_Switch;
155 return EaseOut(1.0f/m_Switch * (t-m_Switch)) * m_Switch + m_Switch;
158 float CCinemaPath::EaseOutIn(float t) const
160 if (t < m_Switch)
161 return EaseOut(1.0f/m_Switch * t) * m_Switch;
162 return EaseIn(1.0f/m_Switch * (t-m_Switch)) * m_Switch + m_Switch;
165 // Distortion style functions
166 float CCinemaPath::EaseDefault(float t) const
168 return t;
171 float CCinemaPath::EaseGrowth(float t) const
173 return pow(t, m_Growth);
176 float CCinemaPath::EaseExpo(float t) const
178 if (t == 0)
179 return t;
180 return powf(m_Growth, 10*(t-1.0f));
183 float CCinemaPath::EaseCircle(float t) const
185 t = -(sqrt(1.0f - t*t) - 1.0f);
186 if (m_GrowthCount > 1.0f)
188 --m_GrowthCount;
189 return (this->*DistStylePtr)(t);
191 return t;
194 float CCinemaPath::EaseSine(float t) const
196 t = 1.0f - cos(t * (float)M_PI/2);
197 if (m_GrowthCount > 1.0f)
199 --m_GrowthCount;
200 return (this->*DistStylePtr)(t);
202 return t;
205 const CCinemaData* CCinemaPath::GetData() const
207 return CCinemaData::GetData();
210 bool CCinemaPath::Validate()
212 if (m_TimeElapsed > GetDuration().ToFloat() || m_TimeElapsed < 0.0f)
213 return false;
215 // Find current node and past "node time"
216 float previousTime = 0.0f, cumulation = 0.0f;
218 // Ignore the last node, since it is a blank (node time values are shifted down one from interface)
219 for (size_t i = 0; i < Node.size() - 1; ++i)
221 cumulation += Node[i].Distance.ToFloat();
222 if (m_TimeElapsed <= cumulation)
224 m_PreviousNodeTime = previousTime;
225 m_PreviousRotation = Node[i].Rotation;
226 m_CurrentNode = i; // We're moving toward this next node, so use its rotation
227 return true;
229 previousTime += Node[i].Distance.ToFloat();
231 debug_warn("validation of cinema path is wrong\n");
232 return false;
235 bool CCinemaPath::Play(const float deltaRealTime, CCamera* camera)
237 m_TimeElapsed += m_Timescale.ToFloat() * deltaRealTime;
238 if (!Validate())
239 return false;
241 MoveToPointAt(m_TimeElapsed / GetDuration().ToFloat(), GetNodeFraction(), m_PreviousRotation, camera);
242 return true;
245 bool CCinemaPath::Empty() const
247 return Node.empty();
250 void CCinemaPath::Reset()
252 m_TimeElapsed = 0.0f;
255 fixed CCinemaPath::GetTimescale() const
257 return m_Timescale;
260 const TNSpline& CCinemaPath::GetTargetSpline() const
262 return m_TargetSpline;