224 lines
6.0 KiB
C++
224 lines
6.0 KiB
C++
#include <mitsuba/render/track.h>
|
|
#include <mitsuba/core/aabb.h>
|
|
|
|
MTS_NAMESPACE_BEGIN
|
|
|
|
AnimatedTransform::AnimatedTransform(Stream *stream) {
|
|
size_t nTracks = stream->readSize();
|
|
if (nTracks == 0) {
|
|
m_transform = Transform(stream);
|
|
} else {
|
|
for (size_t i=0; i<nTracks; ++i) {
|
|
AbstractAnimationTrack::EType type =
|
|
(AbstractAnimationTrack::EType) stream->readUInt();
|
|
AbstractAnimationTrack *track = NULL;
|
|
switch (type) {
|
|
case AbstractAnimationTrack::ETranslationX:
|
|
case AbstractAnimationTrack::ETranslationY:
|
|
case AbstractAnimationTrack::ETranslationZ:
|
|
case AbstractAnimationTrack::EScaleX:
|
|
case AbstractAnimationTrack::EScaleY:
|
|
case AbstractAnimationTrack::EScaleZ:
|
|
case AbstractAnimationTrack::ERotationX:
|
|
case AbstractAnimationTrack::ERotationY:
|
|
case AbstractAnimationTrack::ERotationZ:
|
|
track = new FloatTrack(type, stream);
|
|
break;
|
|
case AbstractAnimationTrack::ETranslationXYZ:
|
|
case AbstractAnimationTrack::EScaleXYZ:
|
|
track = new VectorTrack(type, stream);
|
|
break;
|
|
case AbstractAnimationTrack::ERotationQuat:
|
|
track = new QuatTrack(type, stream);
|
|
break;
|
|
default:
|
|
Log(EError, "Encountered an unknown animation track type (%i)!", type);
|
|
}
|
|
|
|
track->incRef();
|
|
m_tracks.push_back(track);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AnimatedTransform::addTrack(AbstractAnimationTrack *track) {
|
|
track->incRef();
|
|
m_tracks.push_back(track);
|
|
}
|
|
|
|
AABB1 AnimatedTransform::getTimeBounds() const {
|
|
if (m_tracks.size() == 0)
|
|
#if !defined(__clang__)
|
|
return AABB1(0.0f, 0.0f);
|
|
#else
|
|
// HACK Workaround for clang
|
|
{
|
|
AABB1 b;
|
|
b.min = b.max = 0.0f;
|
|
return b;
|
|
}
|
|
#endif
|
|
|
|
Float min = std::numeric_limits<Float>::infinity();
|
|
Float max = -std::numeric_limits<Float>::infinity();
|
|
|
|
for (size_t i=0; i<m_tracks.size(); ++i) {
|
|
const AbstractAnimationTrack *track = m_tracks[i];
|
|
size_t size = track->getSize();
|
|
SAssert(size > 0);
|
|
min = std::min(min, track->getTime(0));
|
|
max = std::max(max, track->getTime(size-1));
|
|
}
|
|
|
|
#if !defined(__clang__)
|
|
return AABB1(min, max);
|
|
#else
|
|
// HACK Workaround for clang
|
|
AABB1 b;
|
|
b.min = min;
|
|
b.max = max;
|
|
return b;
|
|
#endif
|
|
}
|
|
|
|
AABB AnimatedTransform::getTranslationBounds() const {
|
|
if (m_tracks.size() == 0) {
|
|
Point p = m_transform(Point(0.0f));
|
|
return AABB(p, p);
|
|
}
|
|
|
|
AABB aabb;
|
|
|
|
for (size_t i=0; i<m_tracks.size(); ++i) {
|
|
const AbstractAnimationTrack *absTrack = m_tracks[i];
|
|
switch (absTrack->getType()) {
|
|
case AbstractAnimationTrack::ETranslationX:
|
|
case AbstractAnimationTrack::ETranslationY:
|
|
case AbstractAnimationTrack::ETranslationZ: {
|
|
int idx = absTrack->getType() - AbstractAnimationTrack::ETranslationX;
|
|
const FloatTrack *track =
|
|
static_cast<const FloatTrack *>(absTrack);
|
|
for (size_t j=0; j<track->getSize(); ++j) {
|
|
Float value = track->getValue(j);
|
|
aabb.max[idx] = std::max(aabb.max[idx], value);
|
|
aabb.min[idx] = std::min(aabb.min[idx], value);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case AbstractAnimationTrack::ETranslationXYZ: {
|
|
const VectorTrack *track =
|
|
static_cast<const VectorTrack *>(absTrack);
|
|
for (size_t j=0; j<track->getSize(); ++j)
|
|
aabb.expandBy(Point(track->getValue(j)));
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
for (int i=0; i<3; ++i) {
|
|
if (aabb.min[i] > aabb.max[i])
|
|
aabb.min[i] = aabb.max[i] = 0.0f;
|
|
}
|
|
|
|
return aabb;
|
|
}
|
|
|
|
AABB AnimatedTransform::getSpatialBounds(const AABB &aabb) const {
|
|
AABB result;
|
|
|
|
if (m_tracks.size() == 0) {
|
|
for (int j=0; j<8; ++j)
|
|
result.expandBy(m_transform(aabb.getCorner(j)));
|
|
} else {
|
|
/* Compute approximate bounds */
|
|
int nSteps = 100;
|
|
AABB1 timeBounds = getTimeBounds();
|
|
Float step = timeBounds.getExtents().x / (nSteps-1);
|
|
|
|
for (int i=0; i<nSteps; ++i) {
|
|
const Transform &trafo = eval(timeBounds.min.x + step * i);
|
|
for (int j=0; j<8; ++j)
|
|
result.expandBy(trafo(aabb.getCorner(j)));
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
AnimatedTransform::~AnimatedTransform() {
|
|
for (size_t i=0; i<m_tracks.size(); ++i)
|
|
m_tracks[i]->decRef();
|
|
}
|
|
|
|
void AnimatedTransform::serialize(Stream *stream) const {
|
|
stream->writeSize(m_tracks.size());
|
|
if (m_tracks.size() == 0) {
|
|
m_transform.serialize(stream);
|
|
} else {
|
|
for (size_t i=0; i<m_tracks.size(); ++i)
|
|
m_tracks[i]->serialize(stream);
|
|
}
|
|
}
|
|
|
|
void AnimatedTransform::TransformFunctor::operator()(const Float &t, Transform &trafo) const {
|
|
Vector translation(0.0f);
|
|
Vector scale(1.0f);
|
|
Quaternion rotation;
|
|
|
|
for (size_t i=0; i<m_tracks.size(); ++i) {
|
|
AbstractAnimationTrack *track = m_tracks[i];
|
|
switch (track->getType()) {
|
|
case AbstractAnimationTrack::ETranslationX:
|
|
translation.x = static_cast<FloatTrack *>(track)->eval(t);
|
|
break;
|
|
case AbstractAnimationTrack::ETranslationY:
|
|
translation.y = static_cast<FloatTrack *>(track)->eval(t);
|
|
break;
|
|
case AbstractAnimationTrack::ETranslationZ:
|
|
translation.z = static_cast<FloatTrack *>(track)->eval(t);
|
|
break;
|
|
case AbstractAnimationTrack::ETranslationXYZ:
|
|
translation = static_cast<VectorTrack *>(track)->eval(t);
|
|
break;
|
|
case AbstractAnimationTrack::EScaleX:
|
|
scale.x = static_cast<FloatTrack *>(track)->eval(t);
|
|
break;
|
|
case AbstractAnimationTrack::EScaleY:
|
|
scale.y = static_cast<FloatTrack *>(track)->eval(t);
|
|
break;
|
|
case AbstractAnimationTrack::EScaleZ:
|
|
scale.z = static_cast<FloatTrack *>(track)->eval(t);
|
|
break;
|
|
case AbstractAnimationTrack::EScaleXYZ:
|
|
scale = static_cast<VectorTrack *>(track)->eval(t);
|
|
break;
|
|
case AbstractAnimationTrack::ERotationQuat:
|
|
rotation = static_cast<QuatTrack *>(track)->eval(t);
|
|
break;
|
|
default:
|
|
Log(EError, "Encountered an unsupported "
|
|
"animation track type: %i!", track->getType());
|
|
}
|
|
}
|
|
|
|
trafo = Transform::translate(translation) *
|
|
rotation.toTransform() *
|
|
Transform::scale(scale);
|
|
}
|
|
|
|
std::string AnimatedTransform::toString() const {
|
|
if (m_tracks.size() == 0) {
|
|
return m_transform.toString();
|
|
} else {
|
|
std::ostringstream oss;
|
|
oss << "AnimatedTransform[tracks=" << m_tracks.size() << "]";
|
|
return oss.str();
|
|
}
|
|
}
|
|
|
|
MTS_IMPLEMENT_CLASS(AbstractAnimationTrack, true, Object)
|
|
MTS_IMPLEMENT_CLASS(AnimatedTransform, false, Object)
|
|
MTS_NAMESPACE_END
|