Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzExt includes
Toshihiro Shimizu 890ddd
#include "ext/plasticskeleton.h"
Toshihiro Shimizu 890ddd
#include "ext/plasticskeletondeformation.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STD includes
Toshihiro Shimizu 890ddd
#include <limits></limits>
Toshihiro Shimizu 890ddd
#include <map></map>
Toshihiro Shimizu 890ddd
#include <algorithm></algorithm>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Boost includes
Toshihiro Shimizu 890ddd
#include <boost shared_ptr.hpp=""></boost>
Toshihiro Shimizu 890ddd
#include <boost make_shared.hpp=""></boost>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <boost multi_index_container.hpp=""></boost>
Toshihiro Shimizu 890ddd
#include <boost multi_index="" ordered_index.hpp=""></boost>
Toshihiro Shimizu 890ddd
#include <boost member.hpp="" multi_index=""></boost>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qmutex></qmutex>
Toshihiro Shimizu 890ddd
#include <qmutexlocker></qmutexlocker>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ext/plasticdeformerstorage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Storage multi-index map  definition
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef PlasticDeformerDataGroup DataGroup;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::pair<const *,="" int="" skd=""> DeformedSkeleton;</const>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct Key {
Toshihiro Shimizu 890ddd
	const TMeshImage *m_mi;
Toshihiro Shimizu 890ddd
	DeformedSkeleton m_ds;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	boost::shared_ptr<datagroup> m_dataGroup;</datagroup>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Key(const TMeshImage *mi, const SkD *sd, int skelId)
Toshihiro Shimizu 890ddd
		: m_mi(mi), m_ds(sd, skelId), m_dataGroup() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool operator<(const Key &other) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return (m_mi < other.m_mi) || ((!(other.m_mi < m_mi)) && (m_ds < other.m_ds));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace boost::multi_index;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef boost::multi_index_container
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
											  ordered_unique<identity<key>>,</identity<key>
Toshihiro Shimizu 890ddd
											  ordered_non_unique<
Toshihiro Shimizu 890ddd
												  tag<tmeshimage>, member<key, &key::m_mi="" *,="" const="" tmeshimage="">>,</key,></tmeshimage>
Toshihiro Shimizu 890ddd
											  ordered_non_unique<
Toshihiro Shimizu 890ddd
												  tag<deformedskeleton>, member<key, &key::m_ds="" deformedskeleton,="">></key,></deformedskeleton>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
											  >> DeformersSet;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef DeformersSet::nth_index<0>::type DeformersByKey;
Toshihiro Shimizu 890ddd
typedef DeformersSet::index<tmeshimage>::type DeformersByMeshImage;</tmeshimage>
Toshihiro Shimizu 890ddd
typedef DeformersSet::index<deformedskeleton>::type DeformersByDeformedSkeleton;</deformedskeleton>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Initialization stage  functions
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void initializeSO(PlasticDeformerData &data, const TTextureMeshP &mesh)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	data.m_so = new double[mesh->facesCount()];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void initializeDeformerData(PlasticDeformerData &data, const TTextureMeshP &mesh)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	initializeSO(data, mesh); // Allocates SO data
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Also, allocate suitable input-output arrays for the deformation
Toshihiro Shimizu 890ddd
	data.m_output = new double[2 * mesh->verticesCount()];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void initializeDeformersData(DataGroup *group, const TMeshImage *meshImage)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	group->m_datas = new PlasticDeformerData[meshImage->meshes().size()];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Push a PlasticDeformer for each mesh in the image
Toshihiro Shimizu 890ddd
	const std::vector<ttexturemeshp> &meshes = meshImage->meshes();</ttexturemeshp>
Toshihiro Shimizu 890ddd
	int fTotal = 0; // Also count total # of faces
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m, mCount = meshes.size();
Toshihiro Shimizu 890ddd
	for (m = 0; m != mCount; ++m) {
Toshihiro Shimizu 890ddd
		fTotal += meshes[m]->facesCount();
Toshihiro Shimizu 890ddd
		initializeDeformerData(group->m_datas[m], meshes[m]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Initialize the vector of sorted faces
Toshihiro Shimizu 890ddd
	std::vector<std::pair<int, int="">> &sortedFaces = group->m_sortedFaces;</std::pair<int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	sortedFaces.reserve(fTotal);
Toshihiro Shimizu 890ddd
	for (m = 0; m != mCount; ++m) {
Toshihiro Shimizu 890ddd
		const TTextureMesh &mesh = *meshes[m];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int f, fCount = mesh.facesCount();
Toshihiro Shimizu 890ddd
		for (f = 0; f != fCount; ++f)
Toshihiro Shimizu 890ddd
			sortedFaces.push_back(std::make_pair(f, m));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Handle processing  functions
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void transformHandles(std::vector<plastichandle> &handles, const TAffine &aff)</plastichandle>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Transforms handles through deformAff AND applies mi's dpi scale inverse
Toshihiro Shimizu 890ddd
	std::vector<plastichandle>::size_type h, hCount = handles.size();</plastichandle>
Toshihiro Shimizu 890ddd
	for (h = 0; h != hCount; ++h)
Toshihiro Shimizu 890ddd
		handles[h].m_pos = aff * handles[h].m_pos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void transformHandles(std::vector<tpointd> &handles, const TAffine &aff)</tpointd>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Transforms handles through deformAff AND applies mi's dpi scale inverse
Toshihiro Shimizu 890ddd
	std::vector<plastichandle>::size_type h, hCount = handles.size();</plastichandle>
Toshihiro Shimizu 890ddd
	for (h = 0; h != hCount; ++h)
Toshihiro Shimizu 890ddd
		handles[h] = aff * handles[h];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void processHandles(DataGroup *group, double frame, const TMeshImage *meshImage,
Toshihiro Shimizu 890ddd
					const SkD *sd, int skelId, const TAffine &deformationAffine)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(sd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const PlasticSkeletonP &skeleton = sd->skeleton(skelId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!skeleton || skeleton->verticesCount() == 0) {
Toshihiro Shimizu 890ddd
		group->m_handles.clear();
Toshihiro Shimizu 890ddd
		group->m_dstHandles.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		group->m_compiled |= PlasticDeformerStorage::HANDLES;
Toshihiro Shimizu 890ddd
		group->m_upToDate |= PlasticDeformerStorage::HANDLES;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int mCount = meshImage->meshes().size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!(group->m_upToDate & PlasticDeformerStorage::HANDLES)) {
Toshihiro Shimizu 890ddd
		// Compile handles if necessary
Toshihiro Shimizu 890ddd
		if (!(group->m_compiled & PlasticDeformerStorage::HANDLES)) {
Toshihiro Shimizu 890ddd
			// Build and transform handles
Toshihiro Shimizu 890ddd
			group->m_handles = skeleton->verticesToHandles();
Toshihiro Shimizu 890ddd
			::transformHandles(group->m_handles, deformationAffine);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Prepare a vector for handles' face hints
Toshihiro Shimizu 890ddd
			for (int m = 0; m != mCount; ++m)
Toshihiro Shimizu 890ddd
				group->m_datas[m].m_faceHints.resize(group->m_handles.size(), -1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			group->m_compiled |= PlasticDeformerStorage::HANDLES;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Then, build destination handles
Toshihiro Shimizu 890ddd
		PlasticSkeleton deformedSkeleton; // NOTE: Could this be moved to the group as well?
Toshihiro Shimizu 890ddd
		sd->storeDeformedSkeleton(skelId, frame, deformedSkeleton);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Copy deformed skeleton data into input deformation parameters
Toshihiro Shimizu 890ddd
		group->m_dstHandles = std::vector<tpointd>(deformedSkeleton.vertices().begin(), deformedSkeleton.vertices().end());</tpointd>
Toshihiro Shimizu 890ddd
		::transformHandles(group->m_dstHandles, deformationAffine);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		group->m_upToDate |= PlasticDeformerStorage::HANDLES;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Stacking Order processing  functions
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool updateHandlesSO(DataGroup *group, const SkD *sd, int skelId, double frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(sd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const PlasticSkeletonP &skeleton = sd->skeleton(skelId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!skeleton || skeleton->verticesCount() == 0) {
Toshihiro Shimizu 890ddd
		group->m_soMin = group->m_soMax = 0.0;
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Copy SO values to data's handles
Toshihiro Shimizu 890ddd
	// Return whether values changed with respect to previous ones
Toshihiro Shimizu 890ddd
	bool changed = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(group->m_handles.size() == skeleton->verticesCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int h, hCount = group->m_handles.size();
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		tcg::list<plasticskeletonvertex>::iterator vt = skeleton->vertices().begin();</plasticskeletonvertex>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (h = 0; h != hCount; ++h, ++vt) {
Toshihiro Shimizu 890ddd
			const SkVD *vd = sd->vertexDeformation(vt->name());
Toshihiro Shimizu 890ddd
			if (!vd)
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			double so = vd->m_params[SkVD::SO]->getValue(frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			PlasticHandle &handle = group->m_handles[h];
Toshihiro Shimizu 890ddd
			if (handle.m_so != so) {
Toshihiro Shimizu 890ddd
				group->m_handles[h].m_so = so;
Toshihiro Shimizu 890ddd
				changed = true;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (changed) {
Toshihiro Shimizu 890ddd
		// Rebuild SO minmax
Toshihiro Shimizu 890ddd
		group->m_soMax = -(group->m_soMin = (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (h = 0; h != hCount; ++h) {
Toshihiro Shimizu 890ddd
			const double &so = group->m_handles[h].m_so;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			group->m_soMin = tmin(group->m_soMin, so);
Toshihiro Shimizu 890ddd
			group->m_soMax = tmax(group->m_soMax, so);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return changed;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void interpolateSO(DataGroup *group, const TMeshImage *meshImage)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int m, mCount = meshImage->meshes().size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (group->m_handles.size() == 0) {
Toshihiro Shimizu 890ddd
		// No handles case, fill in with 0s
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (m = 0; m != mCount; ++m) {
Toshihiro Shimizu 890ddd
			const TTextureMesh &mesh = *meshImage->meshes()[m];
Toshihiro Shimizu 890ddd
			PlasticDeformerData &data = group->m_datas[m];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			std::fill(data.m_so, data.m_so + mesh.facesCount(), 0.0);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Apply handles' SO values to each mesh
Toshihiro Shimizu 890ddd
	for (m = 0; m != mCount; ++m) {
Toshihiro Shimizu 890ddd
		const TTextureMesh &mesh = *meshImage->meshes()[m];
Toshihiro Shimizu 890ddd
		PlasticDeformerData &data = group->m_datas[m];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Interpolate so values
Toshihiro Shimizu 890ddd
		double *verticesSO = new double[mesh.verticesCount()];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		::buildSO(verticesSO, mesh, group->m_handles, &data.m_faceHints.front());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Make the mean of each face's vertex values and store that
Toshihiro Shimizu 890ddd
		int f, fCount = mesh.facesCount();
Toshihiro Shimizu 890ddd
		for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
			int v0, v1, v2;
Toshihiro Shimizu 890ddd
			mesh.faceVertices(f, v0, v1, v2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			data.m_so[f] = (verticesSO[v0] + verticesSO[v1] + verticesSO[v2]) / 3.0;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		delete[] verticesSO;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct FaceLess {
Toshihiro Shimizu 890ddd
	const PlasticDeformerDataGroup *m_group;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	FaceLess(const PlasticDeformerDataGroup *group) : m_group(group) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool operator()(const std::pair<int, int=""> &a, const std::pair<int, int=""> &b)</int,></int,>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return (m_group->m_datas[a.second].m_so[a.first] < m_group->m_datas[b.second].m_so[b.first]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Must be invoked after updateSO
Toshihiro Shimizu 890ddd
void updateSortedFaces(PlasticDeformerDataGroup *group)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FaceLess comp(group);
Toshihiro Shimizu 890ddd
	std::sort(group->m_sortedFaces.begin(), group->m_sortedFaces.end(), comp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void processSO(DataGroup *group, double frame, const TMeshImage *meshImage,
Toshihiro Shimizu 890ddd
			   const SkD *sd, int skelId, const TAffine &deformationAffine)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// SO re-interpolate values along the mesh if either:
Toshihiro Shimizu 890ddd
	//  1. Recompilation was requested (ie some vertex may have been added/removed)
Toshihiro Shimizu 890ddd
	//  2. OR the value of one of the handle has changed
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool interpolate = !(group->m_compiled & PlasticDeformerStorage::SO);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!(group->m_upToDate & PlasticDeformerStorage::SO)) // implied by (interpolate == true)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		interpolate = updateHandlesSO(group, sd, skelId, frame) || interpolate; // Order is IMPORTANT
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (interpolate) {
Toshihiro Shimizu 890ddd
			interpolateSO(group, meshImage);
Toshihiro Shimizu 890ddd
			updateSortedFaces(group);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		group->m_compiled |= PlasticDeformerStorage::SO;
Toshihiro Shimizu 890ddd
		group->m_upToDate |= PlasticDeformerStorage::SO;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Mesh Deform processing  functions
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void processMesh(DataGroup *group, double frame, const TMeshImage *meshImage,
Toshihiro Shimizu 890ddd
				 const SkD *sd, int skelId, const TAffine &deformationAffine)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!(group->m_upToDate & PlasticDeformerStorage::MESH)) {
Toshihiro Shimizu 890ddd
		int m, mCount = meshImage->meshes().size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!(group->m_compiled & PlasticDeformerStorage::MESH)) {
Toshihiro Shimizu 890ddd
			for (m = 0; m != mCount; ++m) {
Toshihiro Shimizu 890ddd
				const TTextureMeshP &mesh = meshImage->meshes()[m];
Toshihiro Shimizu 890ddd
				PlasticDeformerData &data = group->m_datas[m];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				data.m_deformer.initialize(mesh);
Toshihiro Shimizu 890ddd
				data.m_deformer.compile(group->m_handles, data.m_faceHints.empty() ? 0 : &data.m_faceHints.front());
Toshihiro Shimizu 890ddd
				data.m_deformer.releaseInitializedData();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			group->m_compiled |= PlasticDeformerStorage::MESH;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const TPointD *dstHandlePos = group->m_dstHandles.empty() ? 0 : &group->m_dstHandles.front();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (m = 0; m != mCount; ++m) {
Toshihiro Shimizu 890ddd
			PlasticDeformerData &data = group->m_datas[m];
Toshihiro Shimizu 890ddd
			data.m_deformer.deform(dstHandlePos, data.m_output);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		group->m_upToDate |= PlasticDeformerStorage::MESH;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticDeformerData  implementation
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticDeformerData::PlasticDeformerData()
Toshihiro Shimizu 890ddd
	: m_so(), m_output()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticDeformerData::~PlasticDeformerData()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete[] m_so;
Toshihiro Shimizu 890ddd
	delete[] m_output;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticDeformerDataGroup  implementation
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticDeformerDataGroup::PlasticDeformerDataGroup()
Toshihiro Shimizu 890ddd
	: m_datas(), m_compiled(PlasticDeformerStorage::NONE), m_upToDate(PlasticDeformerStorage::NONE), m_outputFrame((std::numeric_limits<double>::max)()), m_soMin(), m_soMax()</double>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticDeformerDataGroup::~PlasticDeformerDataGroup()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete[] m_datas;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticDeformerStorage::Imp  definition
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class PlasticDeformerStorage::Imp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	QMutex m_mutex;			  //!< Access mutex - needed for thread-safety
Toshihiro Shimizu 890ddd
	DeformersSet m_deformers; //!< Set of deformers, ordered by mesh image, deformation, and affine.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Imp() : m_mutex(QMutex::Recursive) {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticDeformerStorage  implementation
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticDeformerStorage::PlasticDeformerStorage()
Toshihiro Shimizu 890ddd
	: m_imp(new Imp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticDeformerStorage::~PlasticDeformerStorage()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticDeformerStorage *PlasticDeformerStorage::instance()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static PlasticDeformerStorage theInstance;
Toshihiro Shimizu 890ddd
	return &theInstance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticDeformerDataGroup *PlasticDeformerStorage::deformerData(
Toshihiro Shimizu 890ddd
	const TMeshImage *meshImage, const PlasticSkeletonDeformation *deformation, int skelId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Search for the corresponding deformation in the storage
Toshihiro Shimizu 890ddd
	Key key(meshImage, deformation, skelId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByKey::iterator dt = m_imp->m_deformers.find(key);
Toshihiro Shimizu 890ddd
	if (dt == m_imp->m_deformers.end()) {
Toshihiro Shimizu 890ddd
		// No deformer was found. Allocate it.
Toshihiro Shimizu 890ddd
		key.m_dataGroup = boost::make_shared<plasticdeformerdatagroup>();</plasticdeformerdatagroup>
Toshihiro Shimizu 890ddd
		initializeDeformersData(key.m_dataGroup.get(), meshImage);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		dt = m_imp->m_deformers.insert(key).first;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return dt->m_dataGroup.get();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const PlasticDeformerDataGroup *PlasticDeformerStorage::process(
Toshihiro Shimizu 890ddd
	double frame, const TMeshImage *meshImage,
Toshihiro Shimizu 890ddd
	const PlasticSkeletonDeformation *deformation, int skelId,
Toshihiro Shimizu 890ddd
	const TAffine &skeletonAffine, DataType dataType)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	PlasticDeformerDataGroup *group = deformerData(meshImage, deformation, skelId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// On-the-fly checks for data invalidation
Toshihiro Shimizu 890ddd
	if (group->m_skeletonAffine != skeletonAffine) {
Toshihiro Shimizu 890ddd
		group->m_upToDate = NONE;
Toshihiro Shimizu 890ddd
		group->m_compiled = NONE;
Toshihiro Shimizu 890ddd
		group->m_skeletonAffine = skeletonAffine;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (group->m_outputFrame != frame) {
Toshihiro Shimizu 890ddd
		group->m_upToDate = NONE;
Toshihiro Shimizu 890ddd
		group->m_outputFrame = frame;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool doMesh = (dataType & MESH);
Toshihiro Shimizu 890ddd
	bool doSO = (dataType & SO) || doMesh;
Toshihiro Shimizu 890ddd
	bool doHandles = (bool)dataType;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Process data
Toshihiro Shimizu 890ddd
	if (doHandles)
Toshihiro Shimizu 890ddd
		processHandles(group, frame, meshImage, deformation, skelId, skeletonAffine);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (doSO)
Toshihiro Shimizu 890ddd
		processSO(group, frame, meshImage, deformation, skelId, skeletonAffine);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (doMesh)
Toshihiro Shimizu 890ddd
		processMesh(group, frame, meshImage, deformation, skelId, skeletonAffine);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return group;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const PlasticDeformerDataGroup *PlasticDeformerStorage::processOnce(
Toshihiro Shimizu 890ddd
	double frame,
Toshihiro Shimizu 890ddd
	const TMeshImage *meshImage,
Toshihiro Shimizu 890ddd
	const PlasticSkeletonDeformation *deformation, int skelId,
Toshihiro Shimizu 890ddd
	const TAffine &skeletonAffine,
Toshihiro Shimizu 890ddd
	DataType dataType)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	PlasticDeformerDataGroup *group = new PlasticDeformerDataGroup;
Toshihiro Shimizu 890ddd
	initializeDeformersData(group, meshImage);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool doMesh = (dataType & MESH);
Toshihiro Shimizu 890ddd
	bool doSO = (dataType & SO) || doMesh;
Toshihiro Shimizu 890ddd
	bool doHandles = (bool)dataType;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Process data
Toshihiro Shimizu 890ddd
	if (doHandles)
Toshihiro Shimizu 890ddd
		processHandles(group, frame, meshImage, deformation, skelId, skeletonAffine);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (doSO)
Toshihiro Shimizu 890ddd
		processSO(group, frame, meshImage, deformation, skelId, skeletonAffine);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (doMesh)
Toshihiro Shimizu 890ddd
		processMesh(group, frame, meshImage, deformation, skelId, skeletonAffine);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return group;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticDeformerStorage::invalidateMeshImage(
Toshihiro Shimizu 890ddd
	const TMeshImage *meshImage, int recompiledData)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByMeshImage &deformers = m_imp->m_deformers.get<tmeshimage>();</tmeshimage>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByMeshImage::iterator dBegin(deformers.lower_bound(meshImage));
Toshihiro Shimizu 890ddd
	if (dBegin == deformers.end())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByMeshImage::iterator dt, dEnd(deformers.upper_bound(meshImage));
Toshihiro Shimizu 890ddd
	for (dt = dBegin; dt != dEnd; ++dt) {
Toshihiro Shimizu 890ddd
		dt->m_dataGroup->m_outputFrame = (std::numeric_limits<double>::max)(); // Schedule for redeformation</double>
Toshihiro Shimizu 890ddd
		if (recompiledData)
Toshihiro Shimizu 890ddd
			dt->m_dataGroup->m_compiled &= ~recompiledData; // Schedule for recompilation, too
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticDeformerStorage::invalidateSkeleton(
Toshihiro Shimizu 890ddd
	const PlasticSkeletonDeformation *deformation, int skelId, int recompiledData)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformedSkeleton ds(deformation, skelId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByDeformedSkeleton &deformers = m_imp->m_deformers.get<deformedskeleton>();</deformedskeleton>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByDeformedSkeleton::iterator dBegin(deformers.lower_bound(ds));
Toshihiro Shimizu 890ddd
	if (dBegin == deformers.end())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByDeformedSkeleton::iterator dt, dEnd(deformers.upper_bound(ds));
Toshihiro Shimizu 890ddd
	for (dt = dBegin; dt != dEnd; ++dt) {
Toshihiro Shimizu 890ddd
		dt->m_dataGroup->m_outputFrame = (std::numeric_limits<double>::max)(); // Schedule for redeformation</double>
Toshihiro Shimizu 890ddd
		if (recompiledData)
Toshihiro Shimizu 890ddd
			dt->m_dataGroup->m_compiled &= ~recompiledData; // Schedule for recompilation, too
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticDeformerStorage::invalidateDeformation(
Toshihiro Shimizu 890ddd
	const PlasticSkeletonDeformation *deformation, int recompiledData)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByDeformedSkeleton &deformers = m_imp->m_deformers.get<deformedskeleton>();</deformedskeleton>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformedSkeleton dsBegin(deformation, -(std::numeric_limits<int>::max)()),</int>
Toshihiro Shimizu 890ddd
		dsEnd(deformation, (std::numeric_limits<int>::max)());</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByDeformedSkeleton::iterator dBegin(deformers.lower_bound(dsBegin));
Toshihiro Shimizu 890ddd
	DeformersByDeformedSkeleton::iterator dEnd(deformers.upper_bound(dsEnd));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (dBegin == dEnd)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (DeformersByDeformedSkeleton::iterator dt = dBegin; dt != dEnd; ++dt) {
Toshihiro Shimizu 890ddd
		dt->m_dataGroup->m_outputFrame = (std::numeric_limits<double>::max)(); // Schedule for redeformation</double>
Toshihiro Shimizu 890ddd
		if (recompiledData)
Toshihiro Shimizu 890ddd
			dt->m_dataGroup->m_compiled &= ~recompiledData; // Schedule for recompilation, too
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticDeformerStorage::releaseMeshData(const TMeshImage *meshImage)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByMeshImage &deformers = m_imp->m_deformers.get<tmeshimage>();</tmeshimage>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByMeshImage::iterator dBegin(deformers.lower_bound(meshImage));
Toshihiro Shimizu 890ddd
	if (dBegin == deformers.end())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	deformers.erase(dBegin, deformers.upper_bound(meshImage));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticDeformerStorage::releaseSkeletonData(const SkD *deformation, int skelId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformedSkeleton ds(deformation, skelId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByDeformedSkeleton &deformers = m_imp->m_deformers.get<deformedskeleton>();</deformedskeleton>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByDeformedSkeleton::iterator dBegin(deformers.lower_bound(ds));
Toshihiro Shimizu 890ddd
	if (dBegin == deformers.end())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	deformers.erase(dBegin, deformers.upper_bound(ds));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticDeformerStorage::releaseDeformationData(const SkD *deformation)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByDeformedSkeleton &deformers = m_imp->m_deformers.get<deformedskeleton>();</deformedskeleton>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformedSkeleton dsBegin(deformation, -(std::numeric_limits<int>::max)()),</int>
Toshihiro Shimizu 890ddd
		dsEnd(deformation, (std::numeric_limits<int>::max)());</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DeformersByDeformedSkeleton::iterator dBegin(deformers.lower_bound(dsBegin));
Toshihiro Shimizu 890ddd
	DeformersByDeformedSkeleton::iterator dEnd(deformers.upper_bound(dsEnd));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (dBegin == dEnd)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	deformers.erase(dBegin, dEnd);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticDeformerStorage::clear()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_deformers.clear();
Toshihiro Shimizu 890ddd
}