mirror of
https://github.com/bulletphysics/bullet3
synced 2025-01-11 01:40:10 +00:00
2162f6663d
improve CollisionDemo.cpp, show multi-contact generation using perturbation improve ColladaConverter: add hinge/point 2 point constraint conversion support, add btScaledTriangleMeshShape support Fix Dynamica MayaPlygin: remove 'active' flag, it has to be replaced by mass=0 for active, mass<>0 for passive Added missing projectfiles Fixed single-shot contact generation. it is disabled by default to improve performance Bugfixes for character controller, thanks to John McCutchan for reporting Constraint solver: better default settings btDefaultAllocator: aligned allocator uses non-aligned allocator (instead of directly malloc/free) disable memalign by default, use Bullet's aligned allocator
541 lines
20 KiB
C++
541 lines
20 KiB
C++
/*
|
|
Bullet Continuous Collision Detection and Physics Library Maya Plugin
|
|
Copyright (c) 2008 Walt Disney Studios
|
|
|
|
This software is provided 'as-is', without any express or implied warranty.
|
|
In no event will the authors be held liable for any damages arising
|
|
from the use of this software.
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it freely,
|
|
subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must
|
|
not claim that you wrote the original software. If you use this
|
|
software in a product, an acknowledgment in the product documentation
|
|
would be appreciated but is not required.
|
|
2. Altered source versions must be plainly marked as such, and must
|
|
not be misrepresented as being the original software.
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
Written by: Nicola Candussi <nicola@fluidinteractive.com>
|
|
*/
|
|
|
|
//rigidBodyArrayNode.cpp
|
|
|
|
#include <maya/MFnDependencyNode.h>
|
|
#include <maya/MPlugArray.h>
|
|
#include <maya/MFnMessageAttribute.h>
|
|
#include <maya/MFnNumericAttribute.h>
|
|
#include <maya/MFnMatrixAttribute.h>
|
|
#include <maya/MFnTypedAttribute.h>
|
|
#include <maya/MMatrix.h>
|
|
#include <maya/MFnMatrixData.h>
|
|
#include <maya/MFnStringData.h>
|
|
#include <maya/MFnTransform.h>
|
|
#include <maya/MQuaternion.h>
|
|
#include <maya/MEulerRotation.h>
|
|
#include <maya/MNodeMessage.h>
|
|
#include <maya/MVector.h>
|
|
|
|
#include "rigidBodyArrayNode.h"
|
|
#include "collisionShapeNode.h"
|
|
#include "mayaUtils.h"
|
|
|
|
#include "solver.h"
|
|
|
|
MTypeId rigidBodyArrayNode::typeId(0x100330);
|
|
MString rigidBodyArrayNode::typeName("dRigidBodyArray");
|
|
|
|
MObject rigidBodyArrayNode::ia_collisionShape;
|
|
MObject rigidBodyArrayNode::ia_solver;
|
|
MObject rigidBodyArrayNode::ia_numBodies;
|
|
|
|
MObject rigidBodyArrayNode::ia_mass;
|
|
MObject rigidBodyArrayNode::ia_restitution;
|
|
MObject rigidBodyArrayNode::ia_friction;
|
|
MObject rigidBodyArrayNode::ia_linearDamping;
|
|
MObject rigidBodyArrayNode::ia_angularDamping;
|
|
MObject rigidBodyArrayNode::ia_initialPosition;
|
|
MObject rigidBodyArrayNode::ia_initialRotation;
|
|
MObject rigidBodyArrayNode::ia_initialVelocity;
|
|
MObject rigidBodyArrayNode::ia_initialSpin;
|
|
MObject rigidBodyArrayNode::ia_fileIO;
|
|
MObject rigidBodyArrayNode::ia_fioFiles;
|
|
MObject rigidBodyArrayNode::io_position;
|
|
MObject rigidBodyArrayNode::io_rotation;
|
|
MObject rigidBodyArrayNode::ca_rigidBodies;
|
|
MObject rigidBodyArrayNode::ca_rigidBodyParam;
|
|
MObject rigidBodyArrayNode::ca_solver;
|
|
|
|
MStatus rigidBodyArrayNode::initialize()
|
|
{
|
|
MStatus status;
|
|
MFnMessageAttribute fnMsgAttr;
|
|
MFnNumericAttribute fnNumericAttr;
|
|
MFnMatrixAttribute fnMatrixAttr;
|
|
MFnTypedAttribute fnTypedAttr;
|
|
MFnStringData fnStringData;
|
|
|
|
ia_collisionShape = fnMsgAttr.create("inCollisionShape", "incs", &status);
|
|
MCHECKSTATUS(status, "creating inCollisionShape attribute")
|
|
status = addAttribute(ia_collisionShape);
|
|
MCHECKSTATUS(status, "adding inCollisionShape attribute")
|
|
|
|
ia_solver = fnMsgAttr.create("solver", "solv", &status);
|
|
MCHECKSTATUS(status, "creating solver attribute")
|
|
status = addAttribute(ia_solver);
|
|
MCHECKSTATUS(status, "adding solver attribute")
|
|
|
|
ia_numBodies = fnNumericAttr.create("numBodies", "nbds", MFnNumericData::kInt, 1, &status);
|
|
MCHECKSTATUS(status, "creating numBodies attribute")
|
|
fnNumericAttr.setKeyable(false);
|
|
status = addAttribute(ia_numBodies);
|
|
MCHECKSTATUS(status, "adding numBodies attribute")
|
|
|
|
|
|
ia_mass = fnNumericAttr.create("mass", "ma", MFnNumericData::kDouble, 1.0, &status);
|
|
MCHECKSTATUS(status, "creating mass attribute")
|
|
fnNumericAttr.setKeyable(true);
|
|
status = addAttribute(ia_mass);
|
|
MCHECKSTATUS(status, "adding mass attribute")
|
|
|
|
ia_restitution = fnNumericAttr.create("restitution", "rst", MFnNumericData::kDouble, 0.1, &status);
|
|
MCHECKSTATUS(status, "creating restitution attribute")
|
|
fnNumericAttr.setKeyable(true);
|
|
status = addAttribute(ia_restitution);
|
|
MCHECKSTATUS(status, "adding restitution attribute")
|
|
|
|
ia_friction = fnNumericAttr.create("friction", "fc", MFnNumericData::kDouble, 0.5, &status);
|
|
MCHECKSTATUS(status, "creating friction attribute")
|
|
fnNumericAttr.setKeyable(true);
|
|
status = addAttribute(ia_friction);
|
|
MCHECKSTATUS(status, "adding friction attribute")
|
|
|
|
ia_linearDamping = fnNumericAttr.create("linearDamping", "ld", MFnNumericData::kDouble, 0.3, &status);
|
|
MCHECKSTATUS(status, "creating linearDamping attribute")
|
|
fnNumericAttr.setKeyable(true);
|
|
status = addAttribute(ia_linearDamping);
|
|
MCHECKSTATUS(status, "adding linearDamping attribute")
|
|
|
|
ia_angularDamping = fnNumericAttr.create("angularDamping", "ad", MFnNumericData::kDouble, 0.3, &status);
|
|
MCHECKSTATUS(status, "creating angularDamping attribute")
|
|
fnNumericAttr.setKeyable(true);
|
|
status = addAttribute(ia_angularDamping);
|
|
MCHECKSTATUS(status, "adding angularDamping attribute")
|
|
|
|
ia_initialPosition = fnNumericAttr.createPoint("initialPosition", "inpo", &status);
|
|
MCHECKSTATUS(status, "creating initialPosition attribute")
|
|
fnNumericAttr.setArray(true);
|
|
status = addAttribute(ia_initialPosition);
|
|
MCHECKSTATUS(status, "adding initialPosition attribute")
|
|
|
|
ia_initialRotation = fnNumericAttr.createPoint("initialRotation", "inro", &status);
|
|
MCHECKSTATUS(status, "creating initialRotation attribute")
|
|
fnNumericAttr.setArray(true);
|
|
status = addAttribute(ia_initialRotation);
|
|
MCHECKSTATUS(status, "adding initialRotation attribute")
|
|
|
|
ia_initialVelocity = fnNumericAttr.createPoint("initialVelocity", "inve", &status);
|
|
MCHECKSTATUS(status, "creating initialVelocity attribute")
|
|
fnNumericAttr.setArray(true);
|
|
status = addAttribute(ia_initialVelocity);
|
|
MCHECKSTATUS(status, "adding initialVelocity attribute")
|
|
|
|
ia_initialSpin = fnNumericAttr.createPoint("initialSpin", "insp", &status);
|
|
MCHECKSTATUS(status, "creating initialSpin attribute")
|
|
fnNumericAttr.setArray(true);
|
|
status = addAttribute(ia_initialSpin);
|
|
MCHECKSTATUS(status, "adding initialSpin attribute")
|
|
|
|
ia_fileIO = fnNumericAttr.create("fileIO", "fio", MFnNumericData::kBoolean, 0, &status);
|
|
MCHECKSTATUS(status, "creating fileIO attribute")
|
|
fnNumericAttr.setKeyable(false);
|
|
status = addAttribute(ia_fileIO);
|
|
MCHECKSTATUS(status, "adding fileIO attribute")
|
|
|
|
ia_fioFiles = fnTypedAttr.create( "files", "fls", MFnData::kString,
|
|
fnStringData.create("/tmp/rigidBodyArray.${frame}.pdb"), &status );
|
|
MCHECKSTATUS(status, "creating ia_fioFiles attribute")
|
|
fnTypedAttr.setKeyable(false);
|
|
status = addAttribute(ia_fioFiles);
|
|
MCHECKSTATUS(status, "adding ia_fioFiles attribute")
|
|
|
|
io_position = fnNumericAttr.createPoint("position", "pos", &status);
|
|
MCHECKSTATUS(status, "creating position attribute")
|
|
fnNumericAttr.setArray(true);
|
|
status = addAttribute(io_position);
|
|
MCHECKSTATUS(status, "adding io_position attribute")
|
|
|
|
io_rotation = fnNumericAttr.createPoint("rotation", "rot", &status);
|
|
MCHECKSTATUS(status, "creating rotation attribute")
|
|
fnNumericAttr.setArray(true);
|
|
status = addAttribute(io_rotation);
|
|
MCHECKSTATUS(status, "adding io_rotation attribute")
|
|
|
|
ca_rigidBodies = fnNumericAttr.create("ca_rigidBodies", "carb", MFnNumericData::kBoolean, 0, &status);
|
|
MCHECKSTATUS(status, "creating ca_rigidBodies attribute")
|
|
fnNumericAttr.setConnectable(false);
|
|
fnNumericAttr.setHidden(true);
|
|
fnNumericAttr.setStorable(false);
|
|
fnNumericAttr.setKeyable(false);
|
|
status = addAttribute(ca_rigidBodies);
|
|
MCHECKSTATUS(status, "adding ca_rigidBodies attribute")
|
|
|
|
ca_rigidBodyParam = fnNumericAttr.create("ca_rigidBodyParam", "carbp", MFnNumericData::kBoolean, 0, &status);
|
|
MCHECKSTATUS(status, "creating ca_rigidBodyParam attribute")
|
|
fnNumericAttr.setConnectable(false);
|
|
fnNumericAttr.setHidden(true);
|
|
fnNumericAttr.setStorable(false);
|
|
fnNumericAttr.setKeyable(false);
|
|
status = addAttribute(ca_rigidBodyParam);
|
|
MCHECKSTATUS(status, "adding ca_rigidBodyParam attribute")
|
|
|
|
ca_solver = fnNumericAttr.create("ca_solver", "caso", MFnNumericData::kBoolean, 0, &status);
|
|
MCHECKSTATUS(status, "creating ca_solver attribute")
|
|
fnNumericAttr.setConnectable(false);
|
|
fnNumericAttr.setHidden(true);
|
|
fnNumericAttr.setStorable(false);
|
|
fnNumericAttr.setKeyable(false);
|
|
status = addAttribute(ca_solver);
|
|
MCHECKSTATUS(status, "adding ca_solver attribute")
|
|
|
|
status = attributeAffects(ia_numBodies, ca_rigidBodies);
|
|
MCHECKSTATUS(status, "adding attributeAffects(ia_numBodies, ca_rigidBodies)")
|
|
|
|
status = attributeAffects(ia_numBodies, ca_rigidBodyParam);
|
|
MCHECKSTATUS(status, "adding attributeAffects(ia_numBodies, ca_rigidBodyParam)")
|
|
|
|
status = attributeAffects(ia_collisionShape, ca_rigidBodies);
|
|
MCHECKSTATUS(status, "adding attributeAffects(ia_collisionShape, ca_rigidBodies)")
|
|
|
|
status = attributeAffects(ia_collisionShape, ca_rigidBodyParam);
|
|
MCHECKSTATUS(status, "adding attributeAffects(ia_collisionShape, ca_rigidBodyParam)")
|
|
|
|
status = attributeAffects(ia_mass, ca_rigidBodyParam);
|
|
MCHECKSTATUS(status, "adding attributeAffects(ia_mass, ca_rigidBodyParam)")
|
|
|
|
status = attributeAffects(ia_restitution, ca_rigidBodyParam);
|
|
MCHECKSTATUS(status, "adding attributeAffects(ia_restitution, ca_rigidBodyParam)")
|
|
|
|
status = attributeAffects(ia_friction, ca_rigidBodyParam);
|
|
MCHECKSTATUS(status, "adding attributeAffects(ia_friction, ca_rigidBodyParam)")
|
|
|
|
status = attributeAffects(ia_linearDamping, ca_rigidBodyParam);
|
|
MCHECKSTATUS(status, "adding attributeAffects(ia_linearDamping, ca_rigidBodyParam)")
|
|
|
|
status = attributeAffects(ia_angularDamping, ca_rigidBodyParam);
|
|
MCHECKSTATUS(status, "adding attributeAffects(ia_angularDamping, ca_rigidBodyParam)")
|
|
|
|
status = attributeAffects(ia_solver, ca_solver);
|
|
MCHECKSTATUS(status, "adding attributeAffects(ia_solver, ca_solver)")
|
|
|
|
return MS::kSuccess;
|
|
}
|
|
|
|
rigidBodyArrayNode::rigidBodyArrayNode()
|
|
{
|
|
// std::cout << "rigidBodyArrayNode::rigidBodyArrayNode" << std::endl;
|
|
}
|
|
|
|
rigidBodyArrayNode::~rigidBodyArrayNode()
|
|
{
|
|
// std::cout << "rigidBodyArrayNode::~rigidBodyArrayNode" << std::endl;
|
|
for(size_t i = 0; i < m_rigid_bodies.size(); ++i) {
|
|
solver_t::remove_rigid_body(m_rigid_bodies[i]);
|
|
}
|
|
}
|
|
|
|
void rigidBodyArrayNode::nodeRemoved(MObject& node, void *clientData)
|
|
{
|
|
// std::cout << "rigidBodyArrayNode::nodeRemoved" << std::endl;
|
|
MFnDependencyNode fnNode(node);
|
|
rigidBodyArrayNode *thisNode = static_cast<rigidBodyArrayNode*>(fnNode.userNode());
|
|
for(size_t i = 0; i < thisNode->m_rigid_bodies.size(); ++i) {
|
|
solver_t::remove_rigid_body(thisNode->m_rigid_bodies[i]);
|
|
}
|
|
}
|
|
|
|
void rigidBodyArrayNode::postConstructor()
|
|
{
|
|
// MStatus status;
|
|
// MObject thisObject = thisMObject();
|
|
// MCallbackId cid = MNodeMessage::addAttributeAddedOrRemovedCallback(thisObject, attributeAddedOrRemoved, NULL, &status);
|
|
}
|
|
|
|
void* rigidBodyArrayNode::creator()
|
|
{
|
|
return new rigidBodyArrayNode();
|
|
}
|
|
|
|
|
|
bool rigidBodyArrayNode::setInternalValueInContext ( const MPlug & plug,
|
|
const MDataHandle & dataHandle,
|
|
MDGContext & ctx)
|
|
{
|
|
/* if ((plug == pdbFiles) || (plug == ia_scale) || (plug == ia_percent)) {
|
|
m_framesDirty = true;
|
|
} else if(plug == textureFiles) {
|
|
gpufx::m_renderer.setColorTextureDirty();
|
|
}*/
|
|
return false; //setInternalValueInContext(plug,dataHandle,ctx);
|
|
}
|
|
|
|
MStatus rigidBodyArrayNode::compute(const MPlug& plug, MDataBlock& data)
|
|
{
|
|
//std::cout << "rigidBodyArrayNode::compute: " << plug.name() << std::endl;
|
|
//MTime time = data.inputValue( rigidBodyArrayNode::inTime ).asTime();
|
|
if(plug == ca_rigidBodies) {
|
|
computeRigidBodies(plug, data);
|
|
} else if(plug == ca_rigidBodyParam) {
|
|
computeRigidBodyParam(plug, data);
|
|
} else if(plug == ca_solver) {
|
|
data.inputValue(ia_solver).asBool();
|
|
} else if(plug.isElement()) {
|
|
if(plug.array() == worldMatrix) {
|
|
computeWorldMatrix(plug, data);
|
|
} else {
|
|
return MStatus::kUnknownParameter;
|
|
}
|
|
} else {
|
|
return MStatus::kUnknownParameter;
|
|
}
|
|
return MStatus::kSuccess;
|
|
}
|
|
|
|
void rigidBodyArrayNode::draw( M3dView & view, const MDagPath &path,
|
|
M3dView::DisplayStyle style,
|
|
M3dView::DisplayStatus status )
|
|
{
|
|
// std::cout << "rigidBodyArrayNode::draw" << std::endl;
|
|
|
|
update();
|
|
|
|
view.beginGL();
|
|
glPushAttrib( GL_ALL_ATTRIB_BITS );
|
|
|
|
glPushMatrix();
|
|
//remove the parent transform here
|
|
double m[4][4];
|
|
m_worldMatrix.inverse().get(m);
|
|
glMultMatrixd(&(m[0][0]));
|
|
|
|
if(!m_rigid_bodies.empty()) {
|
|
mat4x4f xform;
|
|
if(style == M3dView::kFlatShaded ||
|
|
style == M3dView::kGouraudShaded) {
|
|
glEnable(GL_LIGHTING);
|
|
float material[] = { 0.4, 0.3, 1.0, 1.0 };
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, material);
|
|
for(size_t i = 0; i < m_rigid_bodies.size(); ++i) {
|
|
glPushMatrix();
|
|
m_rigid_bodies[i]->get_transform(xform);
|
|
glMultMatrixf(xform.begin());
|
|
m_rigid_bodies[i]->collision_shape()->gl_draw(collision_shape_t::kDSSolid);
|
|
glPopMatrix();
|
|
}
|
|
}
|
|
|
|
|
|
if( status == M3dView::kActive ||
|
|
status == M3dView::kLead ||
|
|
status == M3dView::kHilite ||
|
|
( style != M3dView::kGouraudShaded && style != M3dView::kFlatShaded ) ) {
|
|
|
|
glDisable(GL_LIGHTING);
|
|
for(size_t i = 0; i < m_rigid_bodies.size(); ++i) {
|
|
glPushMatrix();
|
|
m_rigid_bodies[i]->get_transform(xform);
|
|
glMultMatrixf(xform.begin());
|
|
m_rigid_bodies[i]->collision_shape()->gl_draw(collision_shape_t::kDSWireframe);
|
|
glPopMatrix();
|
|
}
|
|
}
|
|
}
|
|
glPopMatrix();
|
|
glPopAttrib();
|
|
view.endGL();
|
|
}
|
|
|
|
bool rigidBodyArrayNode::isBounded() const
|
|
{
|
|
//return true;
|
|
return false;
|
|
}
|
|
|
|
MBoundingBox rigidBodyArrayNode::boundingBox() const
|
|
{
|
|
// std::cout << "rigidBodyArrayNode::boundingBox()" << std::endl;
|
|
//load the pdbs
|
|
MObject node = thisMObject();
|
|
|
|
MPoint corner1(-1, -1, -1);
|
|
MPoint corner2(1, 1, 1);
|
|
return MBoundingBox(corner1, corner2);
|
|
}
|
|
|
|
//standard attributes
|
|
|
|
void rigidBodyArrayNode::computeRigidBodies(const MPlug& plug, MDataBlock& data)
|
|
{
|
|
// std::cout << "rigidBodyArrayNode::computeRigidBodies" << std::endl;
|
|
|
|
MObject thisObject(thisMObject());
|
|
MPlug plgCollisionShape(thisObject, ia_collisionShape);
|
|
MObject update;
|
|
//force evaluation of the shape
|
|
plgCollisionShape.getValue(update);
|
|
size_t numBodies = data.inputValue(ia_numBodies).asInt();
|
|
// MDataHandle coll = data.inputValue(ia_collisionShape);
|
|
|
|
// collisionShapeNode * pCollisionShapeNode = NULL;
|
|
collision_shape_t::pointer collision_shape;
|
|
if(plgCollisionShape.isConnected()) {
|
|
MPlugArray connections;
|
|
plgCollisionShape.connectedTo(connections, true, true);
|
|
if(connections.length() != 0) {
|
|
MFnDependencyNode fnNode(connections[0].node());
|
|
if(fnNode.typeId() == collisionShapeNode::typeId) {
|
|
collisionShapeNode *pCollisionShapeNode = static_cast<collisionShapeNode*>(fnNode.userNode());
|
|
collision_shape = pCollisionShapeNode->collisionShape();
|
|
} else {
|
|
std::cout << "rigidBodyArrayNode connected to a non-collision shape node!" << std::endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!collision_shape) {
|
|
//not connected to a collision shape, put a default one
|
|
collision_shape = solver_t::create_sphere_shape();
|
|
}
|
|
|
|
//save the positions and orientations to restore them
|
|
std::vector<vec3f> positions(m_rigid_bodies.size());
|
|
std::vector<quatf> rotations(m_rigid_bodies.size());
|
|
for(size_t i = 0; i < m_rigid_bodies.size(); ++i) {
|
|
m_rigid_bodies[i]->get_transform(positions[i], rotations[i]);
|
|
solver_t::remove_rigid_body(m_rigid_bodies[i]);
|
|
}
|
|
|
|
m_rigid_bodies.resize(numBodies);
|
|
for(size_t i = 0; i < m_rigid_bodies.size(); ++i) {
|
|
m_rigid_bodies[i] = solver_t::create_rigid_body(collision_shape);
|
|
if (i < positions.size()) {
|
|
m_rigid_bodies[i]->set_transform(positions[i], rotations[i]);
|
|
} else {
|
|
m_rigid_bodies[i]->set_transform(vec3f(0.f,0.f,0.f),quatf(1.f,0.f,0.f,0.f));
|
|
}
|
|
solver_t::add_rigid_body(m_rigid_bodies[i]);
|
|
}
|
|
|
|
data.outputValue(ca_rigidBodies).set(true);
|
|
data.setClean(plug);
|
|
}
|
|
|
|
|
|
void rigidBodyArrayNode::computeRigidBodyParam(const MPlug& plug, MDataBlock& data)
|
|
{
|
|
// std::cout << "rigidBodyArrayNode::computeRigidBodyParam" << std::endl;
|
|
|
|
MObject thisObject(thisMObject());
|
|
MObject update;
|
|
|
|
MPlug(thisObject, ca_rigidBodies).getValue(update);
|
|
|
|
double mass = data.inputValue(ia_mass).asDouble();
|
|
vec3f inertia;
|
|
if(!m_rigid_bodies.empty()) {
|
|
inertia = mass * m_rigid_bodies[0]->collision_shape()->local_inertia();
|
|
}
|
|
double restitution = data.inputValue(ia_restitution).asDouble();
|
|
double friction = data.inputValue(ia_friction).asDouble();
|
|
double linearDamping = data.inputValue(ia_linearDamping).asDouble();
|
|
double angularDamping = data.inputValue(ia_angularDamping).asDouble();
|
|
|
|
for(size_t i = 0; i < m_rigid_bodies.size(); ++i) {
|
|
m_rigid_bodies[i]->set_mass(mass);
|
|
m_rigid_bodies[i]->set_inertia(inertia);
|
|
m_rigid_bodies[i]->set_restitution(restitution);
|
|
m_rigid_bodies[i]->set_friction(friction);
|
|
m_rigid_bodies[i]->set_linear_damping(linearDamping);
|
|
m_rigid_bodies[i]->set_angular_damping(angularDamping);
|
|
}
|
|
|
|
data.outputValue(ca_rigidBodyParam).set(true);
|
|
data.setClean(plug);
|
|
}
|
|
|
|
void rigidBodyArrayNode::computeWorldMatrix(const MPlug& plug, MDataBlock& data)
|
|
{
|
|
//std::cout << "rigidBodyArrayNode::computeWorldMatrix" << std::endl;
|
|
MObject thisObject(thisMObject());
|
|
MFnDagNode fnDagNode(thisObject);
|
|
|
|
MObject update;
|
|
MPlug(thisObject, ca_rigidBodies).getValue(update);
|
|
MPlug(thisObject, ca_rigidBodyParam).getValue(update);
|
|
|
|
MFnTransform fnParentTransform(fnDagNode.parent(0));
|
|
MTransformationMatrix dm(fnParentTransform.transformation().asMatrix() * m_worldMatrix.inverse());
|
|
MVector mtranslation = dm.getTranslation(MSpace::kTransform);
|
|
MQuaternion mrotation = dm.rotation();
|
|
|
|
// std::cout << mtranslation << std::endl;
|
|
|
|
MArrayDataHandle hInitPosArray = data.outputArrayValue(ia_initialPosition);
|
|
if(hInitPosArray.elementCount() < m_rigid_bodies.size()) {
|
|
std::cout << "rigidBodyArrayNode::computeWorldMatrix: array size mismatch" << std::endl;
|
|
}
|
|
for(size_t i = 0; i < m_rigid_bodies.size(); ++i) {
|
|
MDataHandle hInitPos = hInitPosArray.outputValue();
|
|
float3 &ipos = hInitPos.asFloat3();
|
|
|
|
vec3f pos, newpos;
|
|
quatf rot, newrot;
|
|
|
|
m_rigid_bodies[i]->get_transform(pos, rot);
|
|
|
|
newpos = pos + vec3f(mtranslation.x, mtranslation.y, mtranslation.z);
|
|
// newrot = qprod(rot, quatf(mrotation.w, mrotation.x, mrotation.y, mrotation.z));
|
|
newrot = rot;
|
|
|
|
m_rigid_bodies[i]->set_transform(newpos, newrot);
|
|
|
|
float3 &ihpos=hInitPos.asFloat3();
|
|
//hInitPos.set3Float(ipos[0] + mtranslation.x, ipos[1] + mtranslation.y, ipos[2] + mtranslation.z);
|
|
ihpos[0] = ipos[0] + mtranslation.x;
|
|
ihpos[1] = ipos[1] + mtranslation.y;
|
|
ihpos[2] = ipos[2] + mtranslation.z;
|
|
|
|
|
|
hInitPosArray.next();
|
|
}
|
|
|
|
m_worldMatrix = fnParentTransform.transformation().asMatrix();
|
|
|
|
data.setClean(plug);
|
|
}
|
|
|
|
std::vector<rigid_body_t::pointer>& rigidBodyArrayNode::rigid_bodies()
|
|
{
|
|
// std::cout << "rigidBodyArrayNode::rigid_bodies" << std::endl;
|
|
|
|
MObject thisObject(thisMObject());
|
|
MObject update;
|
|
MPlug(thisObject, ca_rigidBodies).getValue(update);
|
|
MPlug(thisObject, ca_rigidBodyParam).getValue(update);
|
|
|
|
return m_rigid_bodies;
|
|
}
|
|
|
|
|
|
void rigidBodyArrayNode::update()
|
|
{
|
|
MObject thisObject(thisMObject());
|
|
|
|
MObject update;
|
|
MPlug(thisObject, ca_rigidBodies).getValue(update);
|
|
MPlug(thisObject, ca_rigidBodyParam).getValue(update);
|
|
MPlug(thisObject, ca_solver).getValue(update);
|
|
MPlug(thisObject, worldMatrix).elementByLogicalIndex(0).getValue(update);
|
|
}
|