miscellaneous bugfixes, animated instance
parent
bed9d8228e
commit
ceaa1907c0
|
@ -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'])
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue