miscellaneous bugfixes, animated instance

metadata
Wenzel Jakob 2010-11-16 14:59:52 +01:00
parent bed9d8228e
commit ceaa1907c0
7 changed files with 186 additions and 13 deletions

View File

@ -530,6 +530,7 @@ plugins += env.SharedLibrary('plugins/cylinder', ['src/shapes/cylinder.cpp'])
plugins += env.SharedLibrary('plugins/hair', ['src/shapes/hair.cpp'])
plugins += env.SharedLibrary('plugins/shapegroup', ['src/shapes/shapegroup.cpp'])
plugins += env.SharedLibrary('plugins/instance', ['src/shapes/instance.cpp'])
plugins += env.SharedLibrary('plugins/animatedinstance', ['src/shapes/animatedinstance.cpp'])
# Samplers
plugins += env.SharedLibrary('plugins/independent', ['src/samplers/independent.cpp'])

View File

@ -295,12 +295,19 @@ template <typename T> struct TQuaternion {
m.m[0][0] = 1.f - 2.f * (yy + zz);
m.m[0][1] = 2.f * (xy + wz);
m.m[0][2] = 2.f * (xz - wy);
m.m[0][3] = 0.0f;
m.m[1][0] = 2.f * (xy - wz);
m.m[1][1] = 1.f - 2.f * (xx + zz);
m.m[1][2] = 2.f * (yz + wx);
m.m[1][3] = 0.0f;
m.m[2][0] = 2.f * (xz + wy);
m.m[2][1] = 2.f * (yz - wx);
m.m[2][2] = 1.f - 2.f * (xx + yy);
m.m[2][3] = 0.0f;
m.m[3][0] = 0.0f;
m.m[3][1] = 0.0f;
m.m[3][2] = 0.0f;
m.m[3][3] = 1.0f;
Matrix4x4 transp;
m.transpose(transp);

View File

@ -65,6 +65,7 @@ MTS_NAMESPACE_BEGIN
class MTS_EXPORT_RENDER KDTree : public GenericKDTree<AABB, KDTree> {
friend class GenericKDTree<AABB, KDTree>;
friend class Instance;
friend class AnimatedInstance;
public:
/// Create an empty kd-tree
KDTree();

View File

@ -87,6 +87,7 @@ public:
/// Serialize to a binary data stream
void serialize(Stream *stream) const {
stream->writeUInt(m_type);
stream->writeUInt((uint32_t) m_times.size());
stream->writeFloatArray(&m_times[0], m_times.size());
for (size_t i=0; i<m_values.size(); ++i)
@ -95,6 +96,7 @@ public:
/// Evaluate the animation track at an arbitrary time value
inline value_type eval(Float time) const {
SAssert(m_times.size() > 0);
std::vector<Float>::const_iterator entry =
std::lower_bound(m_times.begin(), m_times.end(), time);
int idx0 = (int) (entry - m_times.begin()) - 1;
@ -172,11 +174,25 @@ public:
void addTrack(AbstractAnimationTrack *track);
/// Compute the transformation at the specified time value
void eval(Float t, Transform &trafo);
void eval(Float t, Transform &trafo) const;
/// Serialize to a binary data stream
void serialize(Stream *stream) const;
/// Return the extents along the time axis
void computeTimeBounds(Float &min, Float &max) const {
min = std::numeric_limits<Float>::infinity();
max = -std::numeric_limits<Float>::infinity();
for (size_t i=0; i<m_tracks.size(); ++i) {
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));
}
}
MTS_DECLARE_CLASS()
protected:
/// Virtual destructor

View File

@ -1504,7 +1504,7 @@ void mergeRotations(ColladaContext &ctx) {
it2 != times.end(); ++it2) {
Float time = *it2, rot[3];
for (int i=0; i<3; ++i)
rot[i] = tracks[i] ? tracks[i]->eval(time) : (Float) 0;
rot[i] = tracks[i] ? (tracks[i]->eval(time) * (M_PI/180)) : (Float) 0;
newTrack->setTime(idx, time);
newTrack->setValue(idx, Quaternion::fromEulerAngles(
@ -1532,8 +1532,7 @@ GLvoid __stdcall tessVertex(void *data) {
GLvoid __stdcall tessCombine(GLdouble coords[3], void *vertex_data[4],
GLfloat weight[4], void **outData) {
const domUint **raw = (const domUint **) vertex_data;
domUint *result = new domUint[tess_nSources];
domUint *result = new domUint[tess_nSources], size = 0;
tess_cleanup.push_back(result);
for (size_t i=0; i<tess_nSources; ++i) {
@ -1542,6 +1541,7 @@ GLvoid __stdcall tessCombine(GLdouble coords[3], void *vertex_data[4],
for (int j=0; j<ELast; ++j) {
if (tess_vdata->typeToOffsetInStream[j] == (int) i) {
offset = tess_vdata->typeToOffset[j];
size = tess_vdata->typeToCount[j];
found = true;
break;
}
@ -1549,14 +1549,16 @@ GLvoid __stdcall tessCombine(GLdouble coords[3], void *vertex_data[4],
SAssert(found);
// this will be very slow -- let's hope that it happens rarely
domUint size = tess_vdata->typeToCount[offset];
Vec4 *oldVec = tess_vdata->data[offset];
Vec4 *newVec = new Vec4[size+1];
memcpy(newVec, oldVec, size * sizeof(Vec4));
newVec[size] = Vec4(0.0f);
for (int j=0; j<4; ++j) {
domUint idx = raw[j][i];
void *ptr = vertex_data[j];
if (!ptr)
continue;
domUint idx = ((domUint *) ptr)[i];
newVec[size] += newVec[idx] * weight[j];
}
tess_vdata->data[offset] = newVec;

View File

@ -7,7 +7,7 @@ AnimatedTransform::AnimatedTransform(Stream *stream) {
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:
@ -18,18 +18,21 @@ AnimatedTransform::AnimatedTransform(Stream *stream) {
case AbstractAnimationTrack::ERotationX:
case AbstractAnimationTrack::ERotationY:
case AbstractAnimationTrack::ERotationZ:
m_tracks.push_back(new FloatTrack(type, stream));
track = new FloatTrack(type, stream);
break;
case AbstractAnimationTrack::ETranslationXYZ:
case AbstractAnimationTrack::EScaleXYZ:
m_tracks.push_back(new VectorTrack(type, stream));
track = new VectorTrack(type, stream);
break;
case AbstractAnimationTrack::ERotationQuat:
m_tracks.push_back(new QuatTrack(type, stream));
track = new QuatTrack(type, stream);
break;
default:
Log(EError, "Encountered an unknown animation track type!");
Log(EError, "Encountered an unknown animation track type (%i)!", type);
}
track->incRef();
m_tracks.push_back(track);
}
}
@ -50,7 +53,7 @@ void AnimatedTransform::serialize(Stream *stream) const {
}
/// Compute the transformation at the specified time value
void AnimatedTransform::eval(Float t, Transform &trafo) {
void AnimatedTransform::eval(Float t, Transform &trafo) const {
Vector translation(0.0f);
Vector scale(1.0f);
Quaternion rotation;
@ -90,8 +93,11 @@ void AnimatedTransform::eval(Float t, Transform &trafo) {
"animation track type: %i!", track->getType());
}
}
//cout << "T:" << translation.toString() << " R:" << rotation.toString() << " S:" << scale.toString() << endl;
trafo = Transform::translate(translation) *
rotation.toTransform() * Transform::scale(scale);
rotation.toTransform() *
Transform::scale(scale);
}
MTS_IMPLEMENT_CLASS(AbstractAnimationTrack, true, Object)

View File

@ -0,0 +1,140 @@
/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2010 by Wenzel Jakob and others.
Mitsuba is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License Version 3
as published by the Free Software Foundation.
Mitsuba is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mitsuba/render/track.h>
#include <mitsuba/core/fresolver.h>
#include <mitsuba/core/fstream.h>
#include "shapegroup.h"
MTS_NAMESPACE_BEGIN
#define TIME 0
class AnimatedInstance : public Shape {
public:
AnimatedInstance(const Properties &props) : Shape(props) {
FileResolver *fResolver = Thread::getThread()->getFileResolver();
fs::path path = fResolver->resolve(props.getString("filename"));
m_name = path.filename();
Log(EInfo, "Loading animation track from \"%s\"", m_name.c_str());
ref<FileStream> fs = new FileStream(path, FileStream::EReadOnly);
m_transform = new AnimatedTransform(fs);
}
AnimatedInstance(Stream *stream, InstanceManager *manager)
: Shape(stream, manager) {
m_shapeGroup = static_cast<ShapeGroup *>(manager->getInstance(stream));
m_transform = new AnimatedTransform(stream);
}
void serialize(Stream *stream, InstanceManager *manager) const {
Shape::serialize(stream, manager);
manager->serialize(stream, m_shapeGroup.get());
m_transform->serialize(stream);
}
void configure() {
if (!m_shapeGroup)
Log(EError, "A reference to a 'shapegroup' must be specified!");
const KDTree *kdtree = m_shapeGroup->getKDTree();
const AABB &aabb = kdtree->getAABB();
Float minT, maxT;
m_transform->computeTimeBounds(minT, maxT);
/* Compute approximate bounds */
int nSteps = 100;
Float step = (maxT-minT) / (nSteps-1);
Transform objectToWorld;
for (int i=0; i<nSteps; ++i) {
m_transform->eval(minT + step * i, objectToWorld);
for (int j=0; j<8; ++j)
m_aabb.expandBy(objectToWorld(aabb.getCorner(j)));
}
}
AABB getAABB() const {
return m_aabb;
}
std::string getName() const {
return m_name;
}
Float getSurfaceArea() const {
Log(EError, "AnimatedInstance::getSurfaceArea(): not supported!");
return 0.0f;
}
void addChild(const std::string &name, ConfigurableObject *child) {
const Class *cClass = child->getClass();
if (cClass->getName() == "ShapeGroup") {
m_shapeGroup = static_cast<ShapeGroup *>(child);
} else {
Shape::addChild(name, child);
}
}
bool rayIntersect(const Ray &_ray, Float mint,
Float maxt, Float &t, void *temp) const {
const KDTree *kdtree = m_shapeGroup->getKDTree();
Ray ray;
Transform objectToWorld, worldToObject;
m_transform->eval(TIME, objectToWorld);
worldToObject = objectToWorld.inverse();
worldToObject(_ray, ray);
return kdtree->rayIntersect(ray, mint, maxt, t, temp);
}
bool rayIntersect(const Ray &_ray, Float mint, Float maxt) const {
const KDTree *kdtree = m_shapeGroup->getKDTree();
Ray ray;
Transform objectToWorld, worldToObject;
m_transform->eval(TIME, objectToWorld);
worldToObject = objectToWorld.inverse();
worldToObject(_ray, ray);
return kdtree->rayIntersect(ray, mint, maxt);
}
void fillIntersectionRecord(const Ray &ray,
const void *temp, Intersection &its) const {
const KDTree *kdtree = m_shapeGroup->getKDTree();
Transform objectToWorld;
m_transform->eval(TIME, objectToWorld);
kdtree->fillIntersectionRecord<false>(ray, temp, its);
its.shFrame.n = normalize(objectToWorld(its.shFrame.n));
its.shFrame.s = normalize(objectToWorld(its.shFrame.s));
its.shFrame.t = normalize(objectToWorld(its.shFrame.t));
its.geoFrame = Frame(normalize(objectToWorld(its.geoFrame.n)));
its.wi = its.shFrame.toLocal(-ray.d);
its.dpdu = objectToWorld(its.dpdu);
its.dpdv = objectToWorld(its.dpdv);
}
MTS_DECLARE_CLASS()
private:
ref<ShapeGroup> m_shapeGroup;
ref<AnimatedTransform> m_transform;
AABB m_aabb;
std::string m_name;
};
MTS_IMPLEMENT_CLASS_S(AnimatedInstance, false, Shape)
MTS_EXPORT_PLUGIN(AnimatedInstance, "AnimatedInstanced geometry");
MTS_NAMESPACE_END