Initial commit: Final state of the master project
This commit is contained in:
119
Research/core/Util/Path.h
Normal file
119
Research/core/Util/Path.h
Normal file
@@ -0,0 +1,119 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include "../Defines.h"
|
||||
#include "../Serializer.h"
|
||||
|
||||
// Path stores a recording detailing any type.
|
||||
// Interpolator should be a functor with a method specification:
|
||||
// T operator()(const T& a, const T& b, double time)
|
||||
// Where a and b should be interpolated between, and time is a value between 0 and 1, indicating the interpolation value
|
||||
template<typename T, typename Interpolator>
|
||||
class Path
|
||||
{
|
||||
private:
|
||||
std::vector<T> mFrames;
|
||||
std::vector<double> mFrameTimes;
|
||||
|
||||
public:
|
||||
Path() : mFrames(std::vector<T>()), mFrameTimes(std::vector<double>()) {}
|
||||
~Path() {}
|
||||
|
||||
void SetStateAtTime(const double& time, const T& state)
|
||||
{
|
||||
// Find the position of this new state:
|
||||
auto pos = std::lower_bound(mFrameTimes.begin(), mFrameTimes.end(), time);
|
||||
size_t idx = pos - mFrameTimes.begin();
|
||||
mFrames.insert(mFrames.begin() + idx, state);
|
||||
mFrameTimes.insert(pos, time);
|
||||
}
|
||||
|
||||
T GetStateAtTime(const double& time) const
|
||||
{
|
||||
// Find the frames between which the requested time takes place
|
||||
size_t afterIdx = std::upper_bound(mFrameTimes.begin(), mFrameTimes.end(), time) - mFrameTimes.begin();
|
||||
size_t beforeIdx = afterIdx - 1;
|
||||
if (afterIdx == mFrameTimes.size()) // End of the recording, return the last camera state
|
||||
return mFrames.back();
|
||||
if (afterIdx == 0)
|
||||
return mFrames.front();
|
||||
|
||||
// Now linearly interpolate the frames:
|
||||
double t = ((time - mFrameTimes[beforeIdx]) / (mFrameTimes[afterIdx] - mFrameTimes[beforeIdx]));
|
||||
|
||||
const T& before = mFrames[beforeIdx];
|
||||
const T& after = mFrames[afterIdx];
|
||||
|
||||
return Interpolator()(before, after, t);
|
||||
}
|
||||
|
||||
double GetLength() const {
|
||||
if (Empty()) return 0;
|
||||
return mFrameTimes.back() - mFrameTimes.front();
|
||||
}
|
||||
|
||||
size_t Size() const { return mFrames.size(); }
|
||||
|
||||
/// Removes the camera path node at index i
|
||||
void RemoveAt(size_t i)
|
||||
{
|
||||
mFrames.erase(mFrames.begin() + i);
|
||||
mFrameTimes.erase(mFrames.begin() + i);
|
||||
}
|
||||
|
||||
/// Removes the last stored camera path node
|
||||
void RemoveLast()
|
||||
{
|
||||
mFrames.pop_back();
|
||||
mFrameTimes.pop_back();
|
||||
}
|
||||
|
||||
// Makes sure the frametimes go from 0 to the length of the recording
|
||||
void Normalize()
|
||||
{
|
||||
if (Empty()) return;
|
||||
double offset = mFrameTimes[0];
|
||||
for (size_t i = 0; i < mFrameTimes.size(); i++)
|
||||
mFrameTimes[i] = mFrameTimes[i] - offset;
|
||||
}
|
||||
bool Empty() const { return mFrames.empty(); }
|
||||
void Clear()
|
||||
{
|
||||
mFrames.clear();
|
||||
mFrameTimes.clear();
|
||||
}
|
||||
|
||||
void WriteToFile(const std::string& filename)
|
||||
{
|
||||
std::ofstream file(filename, std::ios::binary);
|
||||
unsigned32 recordingLength = (unsigned32)mFrames.size();
|
||||
Serializer<unsigned32>::Serialize(recordingLength, file);
|
||||
if (recordingLength > 0)
|
||||
{
|
||||
Serializer<T*>::Serialize(&mFrames[0], mFrames.size(), file);
|
||||
Serializer<double*>::Serialize(&mFrameTimes[0], mFrames.size(), file);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
bool ReadFromFile(const std::string& filename)
|
||||
{
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
if (file.good()) {
|
||||
unsigned32 recordingLength = 0;
|
||||
Serializer<unsigned32>::Deserialize(recordingLength, file);
|
||||
mFrames.resize(recordingLength);
|
||||
mFrameTimes.resize(recordingLength);
|
||||
if (recordingLength > 0)
|
||||
{
|
||||
Serializer<T*>::Deserialize(&mFrames[0], mFrames.size(), file);
|
||||
Serializer<double*>::Deserialize(&mFrameTimes[0], mFrames.size(), file);
|
||||
}
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user