Menu

[r136]: / trunk / src / MaxNode.cpp  Maximize  Restore  History

Download this file

143 lines (131 with data), 4.9 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "MaxNode.h"
#include <SimpObj.h>
#include "MxUtils.h"
#include "MaxWorld.h"
#include "PxPlugin.h"
ccMaxNode::ccMaxNode(INode* node) : MaxINode(node), MaxNodeTM(true), ScaledIsUnified(true), ShapeType(NX_SHAPE_MESH)
{
SetNode(node);
}
ccMaxNode::~ccMaxNode()
{
}
void ccMaxNode::SetNode(INode* node)
{
MaxINode = node;
SimpleMesh.release();
ScaledIsUnified = true;
MaxNodeTM.IdentityMatrix();
if(MaxINode) {
SyncFromMaxMesh();
}
}
/*
Transfer the max Node's mesh to PhysX unit and store it.
*/
void ccMaxNode::SyncFromMaxMesh()
{
ShapeType = NX_SHAPE_MESH;
const TimeValue t = ccMaxWorld::MaxTime();
MaxNodeTM = MaxINode->GetNodeTM(t);
MaxNodeTM = ccMaxWorld::ChangeToPhysXUnit(MaxNodeTM);
// get pivot TM
MaxPivotTM.IdentityMatrix();
MaxPivotTM.SetTrans(MaxINode->GetObjOffsetPos() * ccMaxWorld::GetUnitChange());
PreRotateMatrix(MaxPivotTM, MaxINode->GetObjOffsetRot());
ScaleValue scaleValue = MaxINode->GetObjOffsetScale();
ApplyScaling(MaxPivotTM, scaleValue);
// get scale TM
Point3 maxNodeScale = ccMaxWorld::ParseScale(MaxNodeTM, MaxNodeScaleTM, MaxNodePoseTM);
////modify pivotTM with scale
//Point3 pivot = MaxPivotTM.GetRow(3);
//NxMat34 scMat = MxMathUtils::MaxMatrixToNx(MaxNodeScaleTM);
//scMat.multiply(NxVec3(pivot.x, pivot.y, pivot.z), (NxVec3&) pivot);
//MaxPivotTM.SetRow(3, pivot);
////MaxPivotTM = MaxPivotTM * MaxNodeScaleTM;
MaxNodePoseTMInv = Inverse(MaxNodePoseTM);
NxReal tolerence = 0.01f;
// check whether the Node's mesh is scaled equally at x/y/z
ScaledIsUnified = (fabs((maxNodeScale.x - maxNodeScale.z)/maxNodeScale.z) < tolerence) && (fabs((maxNodeScale.y - maxNodeScale.z)/maxNodeScale.z) < tolerence);
Object* obj = MaxINode->EvalWorldState(t).obj;
if (obj != NULL)
{
SimpleObject* so = (SimpleObject*)obj;
Class_ID id = obj->ClassID();
if (id == Class_ID(SPHERE_CLASS_ID, 0)) {
ShapeType = NX_SHAPE_SPHERE;
so->pblock->GetValue(SPHERE_RADIUS, 0, PrimaryShapePara.Radius, FOREVER);
PrimaryShapePara.Radius *= maxNodeScale.x; // x/y/z is scaled with a same value
}
else if (id == Class_ID(BOXOBJ_CLASS_ID, 0)) {
ShapeType = NX_SHAPE_BOX;
so->pblock->GetValue(BOXOBJ_WIDTH , 0, PrimaryShapePara.BoxDimension.x, FOREVER);
so->pblock->GetValue(BOXOBJ_LENGTH, 0, PrimaryShapePara.BoxDimension.y, FOREVER);
so->pblock->GetValue(BOXOBJ_HEIGHT, 0, PrimaryShapePara.BoxDimension.z, FOREVER);
PrimaryShapePara.BoxDimension *= (0.5f * maxNodeScale.x); // x/y/z is scaled with a same value // Physics box is half the size
}
else if (id == CAPS_CLASS_ID) {
ShapeType = NX_SHAPE_CAPSULE;
int centersflag = 0;
so->pblock->GetValue(CAPS_RADIUS , 0, PrimaryShapePara.Radius, FOREVER);
so->pblock->GetValue(CAPS_HEIGHT , 0, PrimaryShapePara.Height, FOREVER);
so->pblock->GetValue(CAPS_CENTERS, 0, centersflag, FOREVER);
if(!centersflag) //there are some different ways in which you can specify a capsule in 3ds max, adjust length if "center" mode is not used
PrimaryShapePara.Height -= PrimaryShapePara.Radius * 2.0f;
PrimaryShapePara.Radius *= maxNodeScale.x; // x/y/z is scaled with a same value
PrimaryShapePara.Height *= maxNodeScale.x; // x/y/z is scaled with a same value
}
}
if(! ScaledIsUnified)
ShapeType = NX_SHAPE_MESH;
// Disable backface culling for cloth
//MaxINode->BackCull(FALSE);
// get mesh
BOOL needDel = FALSE;
TriObject* tri = MxUtils::GetTriObjectFromNode(MaxINode, t, needDel);
if (tri == NULL) return;
Mesh& mesh = tri->GetMesh();
SimpleMesh.alloc(mesh.getNumVerts(), mesh.getNumFaces());
for(NxU32 i = 0; i < SimpleMesh.numPoints; i++)
{
Point3 tmp = mesh.verts[i] * MaxNodeScaleTM;
((Point3*)SimpleMesh.points)[i] = tmp; // systemTM is unit change TM.
}
for(NxU32 i = 0; i < SimpleMesh.numFaces; i++)
{
for(NxU32 j = 0; j < 3; j++)
{
SimpleMesh.faces[i*3+j] = mesh.faces[i].v[j];
}
}
if (needDel)
tri->DeleteMe();
}
// transfer the Max node pose to PhysX pose. Need consider unit scaling
Matrix3& ccMaxNode::PoseToMax(NxMat34& pose)
{
Matrix3 p = MxMathUtils::NxMatrixToMax(pose);
p = ccMaxWorld::ChangeToMaxUnit(p);
return (MaxNodeScaleTM * p);
}
/*
use simulated PhysX Pose to update Max Node's pose. Need consider unit scaling
*/
void ccMaxNode::SetSimulatedPose(NxMat34& pose)
{
Matrix3 p = PoseToMax(pose);
MaxINode->SetNodeTM(ccMaxWorld::MaxTime(), p);
}
/*
Use stored original pose to reset the Max node
*/
void ccMaxNode::RestorePose()
{
Matrix3 org = MaxNodeTM;
org = ccMaxWorld::ChangeToMaxUnit(org);
MaxINode->SetNodeTM(ccMaxWorld::MaxTime(), org);
}
Matrix3& ccMaxNode::GetCurrentTM()
{
return ccMaxWorld::GetCurrentTM(MaxINode);
}
MongoDB Logo MongoDB