#include #include 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; ireadUInt(); 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::infinity(); Float max = -std::numeric_limits::infinity(); for (size_t i=0; igetSize(); 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; igetType()) { case AbstractAnimationTrack::ETranslationX: case AbstractAnimationTrack::ETranslationY: case AbstractAnimationTrack::ETranslationZ: { int idx = absTrack->getType() - AbstractAnimationTrack::ETranslationX; const FloatTrack *track = static_cast(absTrack); for (size_t j=0; jgetSize(); ++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(absTrack); for (size_t j=0; jgetSize(); ++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; idecRef(); } 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; iserialize(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; igetType()) { case AbstractAnimationTrack::ETranslationX: translation.x = static_cast(track)->eval(t); break; case AbstractAnimationTrack::ETranslationY: translation.y = static_cast(track)->eval(t); break; case AbstractAnimationTrack::ETranslationZ: translation.z = static_cast(track)->eval(t); break; case AbstractAnimationTrack::ETranslationXYZ: translation = static_cast(track)->eval(t); break; case AbstractAnimationTrack::EScaleX: scale.x = static_cast(track)->eval(t); break; case AbstractAnimationTrack::EScaleY: scale.y = static_cast(track)->eval(t); break; case AbstractAnimationTrack::EScaleZ: scale.z = static_cast(track)->eval(t); break; case AbstractAnimationTrack::EScaleXYZ: scale = static_cast(track)->eval(t); break; case AbstractAnimationTrack::ERotationQuat: rotation = static_cast(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