Newer
Older
#include "../NifProps/bhkRigidBodyInterface.h"
#include "obj/bhkTransformShape.h"
#include "obj/bhkSphereShape.h"
#include "obj/bhkBoxShape.h"
#include "obj/bhkCapsuleShape.h"
#include "obj/hkPackedNiTriStripsData.h"
#include "obj/bhkPackedNiTriStripsShape.h"
#include "..\NifProps\bhkHelperFuncs.h"
#include "..\NifProps\bhkHelperInterface.h"
#ifdef _DEBUG
#include <assert.h>
#include <crtdbg.h>
#define ASSERT _ASSERTE
#else
#define ASSERT(x)
#endif
Gundalf
committed
static Class_ID SCUBA_CLASS_ID(0x6d3d77ac, 0x79c939a9);
extern Class_ID bhkBoxObject_CLASS_ID;
extern Class_ID BHKCAPSULEOBJECT_CLASS_ID;
extern Class_ID bhkSphereObject_CLASS_ID;
extern Class_ID BHKPROXYOBJECT_CLASS_ID;
Gundalf
committed
enum
{
CAPSULE_RADIUS = 0,
CAPSULE_HEIGHT = 1,
};
class HavokMoppCode
{
private:
typedef int (__stdcall * fnGenerateMoppCode)(int nVerts, Vector3 const* verts, int nTris, Triangle const *tris);
typedef int (__stdcall * fnRetrieveMoppCode)(int nBuffer, unsigned char *buffer);
typedef int (__stdcall * fnRetrieveMoppScale)(float *value);
typedef int (__stdcall * fnRetrieveMoppOrigin)(Vector3 *value);
HMODULE hMoppLib;
fnGenerateMoppCode GenerateMoppCode;
fnRetrieveMoppCode RetrieveMoppCode;
fnRetrieveMoppScale RetrieveMoppScale;
fnRetrieveMoppOrigin RetrieveMoppOrigin;
public:
HavokMoppCode() : hMoppLib(0), GenerateMoppCode(0), RetrieveMoppCode(0), RetrieveMoppScale(0), RetrieveMoppOrigin(0) {
}
Gundalf
committed
~HavokMoppCode() {
if (hMoppLib) FreeLibrary(hMoppLib);
}
bool Initialize()
{
if (hMoppLib == NULL)
{
hMoppLib = LoadLibraryA( "NifMopp.dll" );
GenerateMoppCode = (fnGenerateMoppCode)GetProcAddress( hMoppLib, "GenerateMoppCode" );
RetrieveMoppCode = (fnRetrieveMoppCode)GetProcAddress( hMoppLib, "RetrieveMoppCode" );
RetrieveMoppScale = (fnRetrieveMoppScale)GetProcAddress( hMoppLib, "RetrieveMoppScale" );
RetrieveMoppOrigin = (fnRetrieveMoppOrigin)GetProcAddress( hMoppLib, "RetrieveMoppOrigin" );
}
return ( NULL != GenerateMoppCode && NULL != RetrieveMoppCode
&& NULL != RetrieveMoppScale && NULL != RetrieveMoppOrigin
);
vector<Niflib::byte> CalculateMoppCode( vector<Niflib::Vector3> const & verts, vector<Niflib::Triangle> const & tris, Niflib::Vector3* origin, float* scale)
{
vector<Niflib::byte> code;
if ( Initialize() )
{
int len = GenerateMoppCode( verts.size(), &verts[0], tris.size(), &tris[0] );
if ( len > 0 )
{
code.resize( len );
if ( 0 != RetrieveMoppCode( len , &code[0] ) )
{
if ( NULL != scale )
RetrieveMoppScale(scale);
if ( NULL != origin )
RetrieveMoppOrigin(origin);
}
else
{
code.clear();
}
}
}
return code;
} TheHavokCode;
static vector<Niflib::byte> ConstructHKMesh( NiTriBasedGeomRef shape, Niflib::Vector3& origin, float& scale)
return TheHavokCode.CalculateMoppCode(data->GetVertices(), data->GetTriangles(), &origin, &scale);
static vector<Niflib::byte> ConstructHKMesh( bhkPackedNiTriStripsShapeRef shape, Niflib::Vector3& origin, float& scale)
return TheHavokCode.CalculateMoppCode(data->GetVertices(), data->GetTriangles(), &origin, &scale);
Gundalf
committed
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
To mimic the "Reset Transform" and "Reset Scale" behavior, the following code snippet should help:
Interface *ip = theResetScale.ip;
TimeValue t = ip->GetTime();
Control *tmControl = node->GetTMController();
BOOL lookAt = tmControl->GetRollController() ? TRUE : FALSE;
Matrix3 ntm = node->GetNodeTM(t);
Matrix3 ptm = node->GetParentTM(t);
Matrix3 rtm = ntm * Inverse(ptm);
Matrix3 otm(1);
Quat rot;
// Grab the trans, and then set it to 0
Point3 trans = rtm.GetTrans();
rtm.NoTrans();
// We're only doing scale - save out the
// rotation so we can put it back
AffineParts parts;
decomp_affine(rtm, &parts);
rot = parts.q;
// Build the offset tm
otm.PreTranslate(node->GetObjOffsetPos());
if (node->GetObjOffsetRot()!=IdentQuat()) {
PreRotateMatrix(otm,node->GetObjOffsetRot());
}
Point3 tS(1,1,1);
if ( node->GetObjOffsetScale().s != tS ) {
ApplyScaling(otm,node->GetObjOffsetScale());
}
// Apply the relative tm to the offset
otm = otm * rtm;
decomp_affine(otm, &parts);
node->SetObjOffsetPos(parts.t);
node->SetObjOffsetScale(ScaleValue(parts.k*parts.f,parts.u));
// Now set the transform controller with a matrix
// that has no rotation or scale
rtm.IdentityMatrix();
rtm.SetTrans(trans);
if (!lookAt) {
PreRotateMatrix(rtm,rot);
}
// But first, want to keep children stationary.
Matrix3 ttm = rtm*ptm;
for (int i=0; iNumberOfChildren(); i++) {
Control *tmc = node->GetChildNode(i)->GetTMController();
Matrix3 oldtm = node->GetChildNode(i)->GetNodeTM(t);
SetXFormPacket pk(oldtm,ttm);
tmc->SetValue(t,&pk);
}
SetXFormPacket pckt(rtm);
tmControl->SetValue(t,&pckt);
To mimic the "Align to world" behavior, the following code snippet should help:
AffineParts parts;
TimeValue currtime = m_pInterface->GetTime();
Matrix3 m = pNode->GetNodeTM(currtime);
decomp_affine(m, &parts);
if (rotobj) {
// if "affect obj only" we move it simply thus:
pNode->SetObjOffsetRot(Inverse(parts.q));
} else {
// otherwise, "affect pivot only" we would do:
IdentityTM ident;
Matrix3 wax = ident;
wax.SetTrans(m.GetTrans()); // world aligned axis, centered at pivot point
pNode->Rotate(currtime, wax, Inverse(parts.q),TRUE,FALSE, PIV_PIVOT_ONLY);
}
m_pInterface->RedrawViews(m_pInterface->GetTime(),REDRAW_NORMAL,NULL);
*/
int Exporter::addVertex(vector<Vector3> &verts, vector<Vector3> &vnorms, const Point3 &pt, const Point3 &norm)
{
{
if (equal(verts[i], pt, mWeldThresh) &&
equal(vnorms[i], norm, 0))
return i;
}
verts.push_back(Vector3(pt.x, pt.y, pt.z));
vnorms.push_back(Vector3(norm.x, norm.y, norm.z));
return verts.size()-1;
}
void Exporter::addFace(Triangles &tris, vector<Vector3> &verts, vector<Vector3> &vnorms,
Point3 pt = mesh->verts[ mesh->faces[ face ].v[ vi[i] ] ] * tm;
Point3 norm = getVertexNormal(mesh, face, mesh->getRVertPtr(mesh->faces[ face ].v[ vi[i] ])) * tm;
Gundalf
committed
Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node)
{
if (isHandled(node) || (node->IsHidden() && !mExportHidden))
ProgressUpdate(Collision, FormatText("'%s' Collision", node->GetName()));
Gundalf
committed
// marked as collision?
bool coll = isCollision(node);
bool local = !mFlattenHierarchy;
NiNodeRef nodeParent = mFlattenHierarchy ? mNiRoot : parent;
Gundalf
committed
NiNodeRef newParent;
Gundalf
committed
{
newParent = Exporter::findNode(node->GetParentNode());
//newParent = nodeParent; // always have collision one level up?
Gundalf
committed
TimeValue t = 0;
Gundalf
committed
bhkRigidBodyRef body = makeCollisionBody(node);
bool hasTrans = (body->IsDerivedType(bhkRigidBodyT::TYPE));
Matrix3 tm = getTransform(node, t, false); // has transform
Matrix3 pm = TOMATRIX3(newParent->GetWorldTransform());
tm = tm * Inverse(pm);
Matrix44 rm4 = TOMATRIX4(tm, false);
Vector3 trans; Matrix33 rm; float scale;
rm4.Decompose(trans, rm, scale);
QuaternionXYZW q = TOQUATXYZW(rm.AsQuaternion());
body->SetRotation(q);
body->SetTranslation(trans / Exporter::bhkScaleFactor);
if (hasTrans) {
tm = getTransform(node, t, false);
tm.NoScale();
tm.Invert();
} else {
tm = TOMATRIX3(newParent->GetWorldTransform());
tm.NoScale();
tm.Invert();
//tm.IdentityMatrix();
}
bhkShapeRef shape = makeCollisionShape(node, tm, body);
if (shape)
{
body->SetShape(DynamicCast<bhkShape>(shape));
bhkCollisionObjectRef co = new bhkCollisionObject();
co->SetBody(DynamicCast<NiObject>(body));
newParent->SetCollisionObject(DynamicCast<NiCollisionObject>(co));
}
} else if (isCollisionGroup(node) && !mFlattenHierarchy) {
newParent = makeNode(nodeParent, node);
} else {
newParent = Exporter::findNode(node->GetParentNode());
if (!newParent)
newParent = nodeParent;
if (!newParent)
newParent = nodeParent;
Gundalf
committed
for (int i=0; i<node->NumberOfChildren(); i++)
{
Result result = exportCollision(newParent, node->GetChildNode(i));
if (result!=Ok && result!=Skip)
return result;
}
return Ok;
}
bhkRigidBodyRef Exporter::makeCollisionBody(INode *node)
{
// get data from node
int lyr = NP_DEFAULT_HVK_LAYER;
int mtl = NP_DEFAULT_HVK_MATERIAL;
int msys = NP_DEFAULT_HVK_MOTION_SYSTEM;
int qtype = NP_DEFAULT_HVK_QUALITY_TYPE;
float mass = NP_DEFAULT_HVK_MASS;
float lindamp = NP_DEFAULT_HVK_LINEAR_DAMPING;
float angdamp = NP_DEFAULT_HVK_ANGULAR_DAMPING;
float frict = NP_DEFAULT_HVK_FRICTION;
float maxlinvel = NP_DEFAULT_HVK_MAX_LINEAR_VELOCITY;
float maxangvel = NP_DEFAULT_HVK_MAX_ANGULAR_VELOCITY;
float resti = NP_DEFAULT_HVK_RESTITUTION;
float pendepth = NP_DEFAULT_HVK_PENETRATION_DEPTH;
Vector3 center(0,0,0);
if (bhkRigidBodyInterface *irb = (bhkRigidBodyInterface *)node->GetObjectRef()->GetInterface(BHKRIGIDBODYINTERFACE_DESC))
{
mass = irb->GetMass(0);
frict = irb->GetFriction(0);
resti = irb->GetRestitution(0);
lyr = irb->GetLayer(0);
msys = irb->GetMotionSystem(0);
qtype = irb->GetQualityType(0);
lindamp = irb->GetLinearDamping(0);
angdamp = irb->GetAngularDamping(0);
maxlinvel = irb->GetMaxLinearVelocity(0);
pendepth = irb->GetPenetrationDepth(0);
maxangvel = irb->GetMaxAngularVelocity(0);
transenable = irb->GetEnableTransform(0);
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
{
// Handle compatibility
npGetProp(node, NP_HVK_MASS_OLD, mass, NP_DEFAULT_HVK_EMPTY);
if (mass == NP_DEFAULT_HVK_EMPTY)
npGetProp(node, NP_HVK_MASS, mass, NP_DEFAULT_HVK_MASS);
npGetProp(node, NP_HVK_FRICTION_OLD, frict, NP_DEFAULT_HVK_EMPTY);
if (frict == NP_DEFAULT_HVK_EMPTY)
npGetProp(node, NP_HVK_FRICTION, frict, NP_DEFAULT_HVK_FRICTION);
npGetProp(node, NP_HVK_RESTITUTION_OLD, resti, NP_DEFAULT_HVK_EMPTY);
if (resti == NP_DEFAULT_HVK_EMPTY)
npGetProp(node, NP_HVK_RESTITUTION, resti, NP_DEFAULT_HVK_RESTITUTION);
npGetProp(node, NP_HVK_LAYER, lyr, NP_DEFAULT_HVK_LAYER);
npGetProp(node, NP_HVK_MATERIAL, mtl, NP_DEFAULT_HVK_MATERIAL);
npGetProp(node, NP_HVK_MOTION_SYSTEM, msys, NP_DEFAULT_HVK_MOTION_SYSTEM);
npGetProp(node, NP_HVK_QUALITY_TYPE, qtype, NP_DEFAULT_HVK_QUALITY_TYPE);
npGetProp(node, NP_HVK_LINEAR_DAMPING, lindamp, NP_DEFAULT_HVK_LINEAR_DAMPING);
npGetProp(node, NP_HVK_ANGULAR_DAMPING, angdamp, NP_DEFAULT_HVK_ANGULAR_DAMPING);
npGetProp(node, NP_HVK_MAX_LINEAR_VELOCITY, maxlinvel, NP_DEFAULT_HVK_MAX_LINEAR_VELOCITY);
npGetProp(node, NP_HVK_MAX_ANGULAR_VELOCITY, maxangvel, NP_DEFAULT_HVK_MAX_ANGULAR_VELOCITY);
npGetProp(node, NP_HVK_PENETRATION_DEPTH, pendepth, NP_DEFAULT_HVK_PENETRATION_DEPTH);
npGetProp(node, NP_HVK_CENTER, center);
}
else
{
// Check self to see if is one of our bhkXXXObject classes
if (Object* obj = node->GetObjectRef())
{
if (obj->SuperClassID() == HELPER_CLASS_ID &&
obj->ClassID().PartB() == BHKRIGIDBODYCLASS_DESC.PartB())
{
// TODO: do standard body export
}
}
// else check redirection
}
Gundalf
committed
// setup body
bhkRigidBodyRef body = transenable ? new bhkRigidBodyT() : new bhkRigidBody();
body->SetLayer(OblivionLayer(lyr));
body->SetLayerCopy(OblivionLayer(lyr));
body->SetMotionSystem(MotionSystem(msys));
body->SetQualityType(MotionQuality(qtype));
Gundalf
committed
body->SetMass(mass);
body->SetLinearDamping(lindamp);
body->SetAngularDamping(angdamp);
body->SetFriction(frict);
body->SetRestitution(resti);
body->SetMaxLinearVelocity(maxlinvel);
body->SetMaxAngularVelocity(maxangvel);
body->SetPenetrationDepth(pendepth);
body->SetCenter(center);
QuaternionXYZW q; q.x = q.y = q.z = 0; q.w = 1.0f;
body->SetRotation(q);
Gundalf
committed
return body;
}
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
bhkNiTriStripsShapeRef Exporter::makeTriStripsShape(Mesh& mesh, Matrix3& sm)
{
typedef vector<Triangle> Triangles;
// setup shape data
vector<Vector3> verts;
vector<Vector3> vnorms;
Triangles tris;
int vi[3];
if (TMNegParity(sm)) {
vi[0] = 2; vi[1] = 1; vi[2] = 0;
} else {
vi[0] = 0; vi[1] = 1; vi[2] = 2;
}
for (int i=0; i<mesh.getNumFaces(); i++)
addFace(tris, verts, vnorms, i, vi, &mesh, sm);
NiTriStripsDataRef data = new NiTriStripsData(tris, Exporter::mUseAlternateStripper);
data->SetVertices(verts);
data->SetNormals(vnorms);
// setup shape
bhkNiTriStripsShapeRef shape = StaticCast<bhkNiTriStripsShape>(bhkNiTriStripsShape::Create());
shape->SetNumStripsData(1);
shape->SetStripsData(0, data);
shape->SetNumDataLayers(1);
shape->SetOblivionLayer(0, OL_STATIC);
static bhkMoppBvTreeShapeRef makeTreeShape(bhkPackedNiTriStripsShapeRef mesh)
{
bhkMoppBvTreeShapeRef mopp = new bhkMoppBvTreeShape();
mopp->SetMaterial( HAV_MAT_WOOD );
mopp->SetShape( mesh );
try
{
Niflib::Vector3 offset;
float scale;
vector<Niflib::byte> moppcode = ConstructHKMesh(mesh, offset, scale);
mopp->SetMoppOrigin( offset );
mopp->SetMoppScale( scale );
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
bhkPackedNiTriStripsShapeRef Exporter::makePackedTriStripsShape(Mesh& mesh, Matrix3& sm)
{
// Need to separate the vertices based on material.
typedef vector<Triangle> Triangles;
// setup shape data
vector<Vector3> verts;
vector<Vector3> norms;
Triangles tris;
int vi[3];
if (TMNegParity(sm)) {
vi[0] = 2; vi[1] = 1; vi[2] = 0;
} else {
vi[0] = 0; vi[1] = 1; vi[2] = 2;
}
int nvert = mesh.getNumVerts();
int nface = mesh.getNumFaces();
mesh.buildNormals();
tris.resize(nface);
verts.resize(nvert);
norms.resize(nface);
for (int i=0; i<nvert; ++i)
{
Point3 vert = (mesh.getVert(i) * sm) / Exporter::bhkScaleFactor;
verts[i] = TOVECTOR3(vert);
}
for (int i=0; i<nface; ++i)
{
Triangle& tri = tris[i];
norms[i] = TOVECTOR3(mesh.getFaceNormal(i));
Face& face = mesh.faces[i];
tri[0] = (USHORT)face.getVert(0);
tri[1] = (USHORT)face.getVert(1);
tri[2] = (USHORT)face.getVert(2);
hkPackedNiTriStripsDataRef data = new hkPackedNiTriStripsData();
data->SetNumFaces( tris.size() );
data->SetVertices(verts);
data->SetTriangles(tris);
data->SetNormals(norms);
// setup shape
bhkPackedNiTriStripsShapeRef shape = new bhkPackedNiTriStripsShape();
shape->SetData(data);
OblivionSubShape subshape;
subshape.layer = OL_STATIC;
subshape.material = HAV_MAT_WOOD;
subshape.numVertices = verts.size();
vector<OblivionSubShape> subshapes;
subshapes.push_back(subshape);
shape->SetSubShapes( subshapes );
//shape->SetStripsData(0, data);
//shape->SetNumDataLayers(1);
//shape->SetOblivionLayer(0, OL_STATIC);
return shape;
}
bhkConvexVerticesShapeRef Exporter::makeConvexShape(Mesh& mesh, Matrix3& tm)
{
bhkConvexVerticesShapeRef shape = StaticCast<bhkConvexVerticesShape>(bhkConvexVerticesShape::Create());
Point3 center(0.0f, 0.0f, 0.0f);
Tazpn
committed
CalcCenteredSphere(mesh, center, radius);
radius /= Exporter::bhkScaleFactor;
verts[i] = TOVECTOR3(vert);
}
for (int i=0; i<nface; ++i)
{
Float4 &value = norms[i];
Point3 &pt = mesh.getFaceNormal(i);
value[0] = pt.x;
value[1] = pt.y;
value[2] = pt.z;
Tazpn
committed
value[3] = -(mesh.FaceCenter(i) * tm).Length() / Exporter::bhkScaleFactor;
bhkShapeRef Exporter::makeCollisionShape(INode *node, Matrix3& tm, bhkRigidBodyRef body)
Gundalf
committed
{
bhkShapeRef shape;
Gundalf
committed
TimeValue t = 0;
ObjectState os = node->EvalWorldState(t);
if (os.obj->ClassID() == SCUBA_CLASS_ID)
shape = makeCapsuleShape(node, os.obj, tm);
else if (os.obj->ClassID() == Class_ID(BOXOBJ_CLASS_ID, 0))
shape = makeBoxShape(node, os.obj, tm);
else if (os.obj->ClassID() == Class_ID(SPHERE_CLASS_ID, 0))
shape = makeSphereShape(node, os.obj, tm);
else if (os.obj->ClassID() == bhkBoxObject_CLASS_ID)
shape = makebhkBoxShape(node, os.obj, tm);
else if (os.obj->ClassID() == bhkSphereObject_CLASS_ID)
shape = makebhkSphereShape(node, os.obj, tm);
else if (os.obj->ClassID() == BHKCAPSULEOBJECT_CLASS_ID)
shape = makebhkCapsuleShape(node, os.obj, tm);
else if (os.obj->ClassID() == BHKLISTOBJECT_CLASS_ID)
shape = makeListShape(node, tm, body);
else if (os.obj->ClassID() == BHKPROXYOBJECT_CLASS_ID)
shape = makeProxyShape(node, os.obj, tm);
else if (os.obj->SuperClassID() == GEOMOBJECT_CLASS_ID)
{
if (Modifier* mod = GetbhkCollisionModifier(node))
{
shape = makeModifierShape(node, os.obj, mod, tm);
}
else
{
shape = makeTriStripsShape(node, tm);
}
}
Gundalf
committed
return shape;
}
bhkShapeRef Exporter::makeBoxShape(INode *node, Object *obj, Matrix3& tm)
Gundalf
committed
{
Gundalf
committed
float length = 0;
float height = 0;
float width = 0;
if (IParamBlock2* pblock2 = obj->GetParamBlockByID(0))
{
pblock2->GetValue(BOXOBJ_LENGTH, 0, length, FOREVER);
pblock2->GetValue(BOXOBJ_HEIGHT, 0, height, FOREVER);
pblock2->GetValue(BOXOBJ_WIDTH, 0, width, FOREVER);
}
Gundalf
committed
Vector3 dim(width * scale[0], length * scale[1], height * scale[2]);
Gundalf
committed
// Adjust translation for center of z axis in box
tm.Translate(Point3(0.0, 0.0, dim.z / 2.0));
dim /= (Exporter::bhkScaleFactor * 2);
box->SetDimensions(dim);
int mtl = 0;
npGetProp(node, NP_HVK_MATERIAL, mtl, NP_DEFAULT_HVK_MATERIAL);
box->SetMaterial(HavokMaterial(mtl));
return bhkShapeRef(DynamicCast<bhkSphereRepShape>(box));
Gundalf
committed
}
bhkShapeRef Exporter::makeSphereShape(INode *node, Object *obj, Matrix3& tm)
Gundalf
committed
{
Gundalf
committed
float radius = 0;
if (IParamBlock2* pblock2 = obj->GetParamBlockByID(0))
{
pblock2->GetValue(SPHERE_RADIUS, 0, radius, FOREVER);
}
Gundalf
committed
bhkSphereShapeRef sphere = new bhkSphereShape();
sphere->SetRadius(radius * s);
Gundalf
committed
int mtl = 0;
npGetProp(node, NP_HVK_MATERIAL, mtl, NP_DEFAULT_HVK_MATERIAL);
sphere->SetMaterial(HavokMaterial(mtl));
return bhkShapeRef(DynamicCast<bhkSphereRepShape>(sphere));
Gundalf
committed
}
bhkShapeRef Exporter::makeCapsuleShape(INode *node, Object *obj, Matrix3& tm)
Gundalf
committed
{
float radius = 0.1f;
float height = 0.1f;
if (IParamBlock2* params = obj->GetParamBlockByID(0))
{
params->GetValue(CAPSULE_RADIUS, 0, radius, FOREVER);
params->GetValue(CAPSULE_HEIGHT, 0, height, FOREVER);
}
Gundalf
committed
bhkCapsuleShapeRef capsule = CreateNiObject<bhkCapsuleShape>();
Gundalf
committed
capsule->SetRadius(radius);
capsule->SetRadius1(radius);
capsule->SetRadius2(radius);
int mtl = 0;
npGetProp(node, NP_HVK_MATERIAL, mtl, NP_DEFAULT_HVK_MATERIAL);
capsule->SetMaterial(HavokMaterial(mtl));
return bhkShapeRef(DynamicCast<bhkSphereRepShape>(capsule));
Gundalf
committed
}
bhkShapeRef Exporter::makebhkBoxShape(INode *node, Object *obj, Matrix3& tm)
{
enum { box_params, };
enum { PB_MATERIAL, PB_LENGTH, PB_WIDTH, PB_HEIGHT, };
bhkShapeRef retval;
if (IParamBlock2* pblock2 = obj->GetParamBlockByID(box_params))
{
Point3 scale = GetScale(tm);
pblock2->GetValue(PB_MATERIAL, 0, mtl, FOREVER, 0);
pblock2->GetValue(PB_LENGTH, 0, length, FOREVER, 0);
pblock2->GetValue(PB_WIDTH, 0, width, FOREVER, 0);
pblock2->GetValue(PB_HEIGHT, 0, height, FOREVER, 0);
bhkBoxShapeRef box = new bhkBoxShape();
Vector3 dim(width * scale[0], length * scale[1], height * scale[2]);
float radius = max( max(dim.x, dim.y), dim.z );
box->SetRadius(radius);
// Adjust translation for center of z axis in box
tm.Translate(Point3(0.0, 0.0, dim.z / 2.0));
box->SetDimensions(dim);
box->SetMaterial(HavokMaterial(mtl));
transform->SetShape(box);
transform->SetMaterial(HavokMaterial(mtl));
retval = StaticCast<bhkShape>(transform);
}
}
return retval;
}
bhkShapeRef Exporter::makebhkSphereShape(INode *node, Object *obj, Matrix3& tm)
{
bhkShapeRef retval;
enum { sphere_params, };
enum { PB_MATERIAL, PB_RADIUS, PB_SEGS, PB_SMOOTH, };
if (IParamBlock2* pblock2 = obj->GetParamBlockByID(sphere_params))
{
float radius = 0.0f;
int mtl = NP_DEFAULT_HVK_MATERIAL;
pblock2->GetValue(PB_RADIUS, 0, radius, FOREVER, 0);
pblock2->GetValue(PB_MATERIAL, 0, mtl, FOREVER, 0);
bhkSphereShapeRef shape = new bhkSphereShape();
shape->SetRadius(radius);
shape->SetMaterial(HavokMaterial(mtl));
transform->SetShape(shape);
transform->SetMaterial(HavokMaterial(mtl));
retval = StaticCast<bhkShape>(transform);
}
}
return retval;
}
bhkShapeRef Exporter::makebhkCapsuleShape(INode *node, Object *obj, Matrix3& tm)
{
bhkShapeRef retval;
enum { cap_params, };
enum { PB_MATERIAL, PB_RADIUS1, PB_RADIUS2, PB_LENGTH, };
if (IParamBlock2* pblock2 = obj->GetParamBlockByID(cap_params))
{
float radius1 = 0.0f, radius2 = 0.0f, len = 0.0f;
int mtl = NP_DEFAULT_HVK_MATERIAL;
pblock2->GetValue(PB_RADIUS1, 0, radius1, FOREVER, 0);
pblock2->GetValue(PB_RADIUS2, 0, radius2, FOREVER, 0);
pblock2->GetValue(PB_LENGTH, 0, len, FOREVER, 0);
pblock2->GetValue(PB_MATERIAL, 0, mtl, FOREVER, 0);
bhkCapsuleShapeRef shape = new bhkCapsuleShape();
shape->SetRadius((radius1 + radius2)/2.0f);
shape->SetRadius1(radius1);
shape->SetRadius2(radius2);
shape->SetMaterial(HavokMaterial(mtl));
Matrix3 ltm = node->GetNodeTM(0) * tm;
Point3 center = ltm.GetTrans();
rot.NoTrans();
rot.NoScale();
float distFromCenter = len*Exporter::bhkScaleFactor/2.0f;
Point3 pt1 = ((TransMatrix(Point3(0.0f, 0.0f, +distFromCenter)) * rot).GetTrans() + center) / Exporter::bhkScaleFactor;
Point3 pt2 = ((TransMatrix(Point3(0.0f, 0.0f, -distFromCenter)) * rot).GetTrans() + center) / Exporter::bhkScaleFactor;
shape->SetFirstPoint(TOVECTOR3(pt1));
shape->SetSecondPoint(TOVECTOR3(pt2));
retval = StaticCast<bhkShape>(shape);
}
bhkShapeRef Exporter::makeTriStripsShape(INode *node, Matrix3& tm)
Gundalf
committed
{
TimeValue t = 0;
Gundalf
committed
// Order of the vertices. Get 'em counter clockwise if the objects is
// negatively scaled.
ObjectState os = node->EvalWorldState(t);
TriObject *tri = (TriObject *)os.obj->ConvertToType(t, Class_ID(TRIOBJ_CLASS_ID, 0));
if (!tri)
return false;
Gundalf
committed
bhkNiTriStripsShapeRef shape = makeTriStripsShape(mesh, sm);
Gundalf
committed
int lyr = OL_STATIC;
npGetProp(node, NP_HVK_LAYER, lyr, NP_DEFAULT_HVK_LAYER);
shape->SetNumDataLayers(1);
shape->SetOblivionLayer(0, OblivionLayer(lyr));
npGetProp(node, NP_HVK_MATERIAL, mtl, NP_DEFAULT_HVK_MATERIAL);
shape->SetMaterial(HavokMaterial(mtl));
return StaticCast<bhkShape>(shape);
Gundalf
committed
}
bhkShapeRef Exporter::makeConvexShape(INode *node, Object* obj, Matrix3& tm)
{
bhkShapeRef shape;
return shape;
}
Exporter::Result Exporter::scanForCollision(INode *node)
{
if (node == NULL || (node->IsHidden() && !mExportHidden))
return Exporter::Skip;
// Get the bhk RigidBody modifier if available and then get the picked node.
if (Modifier * mod = GetbhkCollisionModifier(node)){
if (IParamBlock2* pblock = (IParamBlock2*)mod->GetReference(0)) {
if (INode *collMesh = pblock->GetINode(0, 0)) {
mCollisionNodes.insert(collMesh);
} else {
if (mSceneCollisionNode != NULL) {
if (mExportCollision) {
throw runtime_error("There are more than one Collision mesh found at the Scene Level.");
}
} else {
mSceneCollisionNode = node;
}
}
}
}
// Check self to see if is one of our bhkXXXObject classes
if (Object* obj = node->GetObjectRef())
{
if (obj->ClassID() == BHKLISTOBJECT_CLASS_ID)
{
mCollisionNodes.insert(node);
const int PB_MESHLIST = 1;
IParamBlock2* pblock2 = obj->GetParamBlockByID(0);
int nBlocks = pblock2->Count(PB_MESHLIST);
for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++) {
INode *tnode = NULL;
pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i);
if (tnode != NULL && (!tnode->IsHidden() || mExportHidden)) {
mCollisionNodes.insert(tnode);
markAsHandled(tnode); // dont process collision since the list will
}
}
}
else if (obj->SuperClassID() == HELPER_CLASS_ID &&
obj->ClassID().PartB() == BHKRIGIDBODYCLASS_DESC.PartB())
{
mCollisionNodes.insert(node);
}
else
{
Modifier* mod = GetbhkCollisionModifier(node);
if (mod != NULL)
{
mCollisionNodes.insert(node);
}
}
if (npIsCollision(node))
{
mCollisionNodes.insert(node);
}
for (int i=0; i<node->NumberOfChildren(); i++) {
scanForCollision(node->GetChildNode(i));
}
return Exporter::Ok;
}
bool Exporter::isHandled(INode *node)
{
return (mHandledNodes.find(node) != mHandledNodes.end());
}
bool Exporter::markAsHandled(INode* node)
{
mHandledNodes.insert(node);
return true;
}
bool Exporter::isCollision(INode *node)
{
return (mCollisionNodes.find(node) != mCollisionNodes.end());
}
bhkShapeRef Exporter::makeListShape(INode *node, Matrix3& tm, bhkRigidBodyRef body)
{
const int PB_MATERIAL = 0;
const int PB_MESHLIST = 1;
IParamBlock2* pblock2 = node->GetObjectRef()->GetParamBlockByID(0);
int nBlocks = pblock2->Count(PB_MESHLIST);
if (nBlocks > 0)
{
if (bhkRigidBodyInterface *irb = (bhkRigidBodyInterface *)node->GetObjectRef()->GetInterface(BHKRIGIDBODYINTERFACE_DESC))
{
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
float frict = irb->GetFriction(0);
float resti = irb->GetRestitution(0);
int lyr = irb->GetLayer(0);
int msys = irb->GetMotionSystem(0);
int qtype = irb->GetQualityType(0);
float lindamp = irb->GetLinearDamping(0);
float angdamp = irb->GetAngularDamping(0);
float maxlinvel = irb->GetMaxLinearVelocity(0);
float maxangvel = irb->GetMaxAngularVelocity(0);
float pendepth = irb->GetPenetrationDepth(0);
body->SetLayer(OblivionLayer(lyr));
body->SetLayerCopy(OblivionLayer(lyr));
body->SetMotionSystem(MotionSystem(msys));
body->SetQualityType(MotionQuality(qtype));
body->SetMass(mass);
body->SetLinearDamping(lindamp);
body->SetAngularDamping(angdamp);
body->SetFriction(frict);
body->SetRestitution(resti);
body->SetMaxLinearVelocity(maxlinvel);
body->SetMaxAngularVelocity(maxangvel);
body->SetPenetrationDepth(pendepth);
}
bhkListShapeRef shape = new bhkListShape();
int mtl = pblock2->GetInt(PB_MATERIAL, 0, 0);
shape->SetMaterial(HavokMaterial(mtl));
vector<bhkShapeRef> shapes;
for (int i = 0; i < nBlocks; i++) {
INode *tnode = NULL;
pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i);
if (tnode != NULL && (!tnode->IsHidden() || mExportHidden))
{
bhkShapeRef subshape = makeCollisionShape(tnode, tm, body);
if (subshape)
shapes.push_back(subshape);
}
}
shape->SetSubShapes(shapes);
if (shapes.size() == 1) // ignore the list when only one object is present
{
return shapes[0];
}
else if (!shapes.empty())
{
return bhkShapeRef(shape);
}
}
return bhkShapeRef();
}
bhkShapeRef Exporter::makeProxyShape(INode *node, Object *obj, Matrix3& tm)
{
enum { list_params, bv_mesh, }; // pblock2 ID
enum { PB_MATERIAL, PB_MESHLIST, PB_BOUND_TYPE, PB_CENTER, };
enum { bv_type_none, bv_type_box, bv_type_shapes, bv_type_packed, bv_type_convex, }; // pblock ID
bhkShapeRef shape;
if (IParamBlock2* pblock2 = obj->GetParamBlockByID(list_params))
{
int bvType = bv_type_none;
pblock2->GetValue(PB_BOUND_TYPE, 0, bvType, FOREVER, 0);
if (bvType != bv_type_none)
{
if (TriObject *triObj = (TriObject *)obj->ConvertToType(0, triObjectClassID))
{
Mesh& mesh = triObj->GetMesh();
switch (bvType)
{
case bv_type_box:
//case bv_type_sphere:
// shape = makeProxySphereShape(node, obj, mesh, tm);
// break;
break;
}
}
}
}
return shape;
}
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
bhkShapeRef Exporter::makeProxyBoxShape(INode *node, Object *obj, Mesh& mesh, Matrix3& tm)
{
enum { list_params, bv_mesh, }; // pblock2 ID
enum { PB_MATERIAL, PB_MESHLIST, PB_BOUND_TYPE, PB_CENTER, };
enum { bv_type_none, bv_type_box, bv_type_shapes, bv_type_packed, bv_type_convex, }; // pblock ID
bhkShapeRef retval;
if (IParamBlock2* pblock2 = obj->GetParamBlockByID(list_params))
{
Box3 box; box.Init();
CalcAxisAlignedBox(mesh, box, NULL);
int mtl = 0;
float length = 0, width = 0, height = 0;
pblock2->GetValue(PB_MATERIAL, 0, mtl, FOREVER, 0);
bhkBoxShapeRef shape = new bhkBoxShape();
Vector3 dim(box.Max().x-box.Min().x, box.Max().y-box.Min().y, box.Max().z-box.Min().z);
dim /= (Exporter::bhkScaleFactor * 2);
shape->SetMaterial(HavokMaterial(mtl));
shape->SetDimensions(dim);
Matrix3 ltm = /*GetLocalTM(node) * */TransMatrix(box.Center()) * tm;
if (ltm.IsIdentity())
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
transform->SetShape(shape);
transform->SetMaterial(HavokMaterial(mtl));
retval = StaticCast<bhkShape>(transform);
}
}
return retval;
}
bhkShapeRef Exporter::makeProxySphereShape(INode *node, Object *obj, Mesh& mesh, Matrix3& tm)
{
enum { list_params, bv_mesh, }; // pblock2 ID
enum { PB_MATERIAL, PB_MESHLIST, PB_BOUND_TYPE, PB_CENTER, };
enum { bv_type_none, bv_type_box, bv_type_shapes, bv_type_packed, bv_type_convex, }; // pblock ID
bhkShapeRef shape;
if (IParamBlock2* pblock2 = obj->GetParamBlockByID(list_params))
{
//Matrix3 tm = GetLocalTM(node) * TransMatrix(box.Center());
}
return shape;
}
bhkShapeRef Exporter::makeProxyConvexShape(INode *node, Object *obj, Mesh& mesh, Matrix3& tm)
{
enum { list_params, bv_mesh, }; // pblock2 ID
enum { PB_MATERIAL, PB_MESHLIST, PB_BOUND_TYPE, PB_CENTER, };
enum { bv_type_none, bv_type_box, bv_type_shapes, bv_type_packed, bv_type_convex, }; // pblock ID
bhkShapeRef shape;
if (IParamBlock2* pblock2 = obj->GetParamBlockByID(list_params))
{
if (bhkConvexVerticesShapeRef convShape = makeConvexShape(mesh, tm))
{
int mtl = pblock2->GetInt(PB_MATERIAL, 0, 0);
convShape->SetMaterial(HavokMaterial(mtl));
shape = StaticCast<bhkShape>(convShape);
}
}
return shape;
}
bhkShapeRef Exporter::makeProxyTriStripShape(INode *node, Object *obj, Mesh& mesh, Matrix3& tm)
{
enum { list_params, bv_mesh, }; // pblock2 ID
enum { PB_MATERIAL, PB_MESHLIST, PB_BOUND_TYPE, PB_CENTER, };
enum { bv_type_none, bv_type_box, bv_type_shapes, bv_type_packed, bv_type_convex, }; // pblock ID
bhkShapeRef shape;
if (IParamBlock2* pblock2 = obj->GetParamBlockByID(list_params))
{
int mtl = pblock2->GetInt(PB_MATERIAL, 0, 0);
// Transform location
Mesh localmesh(mesh);
MNMesh tmpMesh(localmesh);
tmpMesh.Transform(tm);
tmpMesh.buildNormals();
tmpMesh.OutToTri(localmesh);
localmesh.buildNormals();
trishape->SetMaterial(HavokMaterial(mtl));
shape = StaticCast<bhkShape>(trishape);
}
return shape;
}
bhkShapeRef Exporter::makeProxyPackedTriStripShape(INode *node, Object *obj, Mesh& mesh, Matrix3& tm)
{
enum { list_params, bv_mesh, }; // pblock2 ID
enum { PB_MATERIAL, PB_MESHLIST, PB_BOUND_TYPE, PB_CENTER, };
enum { bv_type_none, bv_type_box, bv_type_shapes, bv_type_packed, bv_type_convex, }; // pblock ID
bhkShapeRef shape;
if (IParamBlock2* pblock2 = obj->GetParamBlockByID(list_params))
{
int mtl = pblock2->GetInt(PB_MATERIAL, 0, 0);
// Transform location
Mesh localmesh(mesh);
MNMesh tmpMesh(localmesh);
tmpMesh.Transform(tm);
tmpMesh.buildNormals();
tmpMesh.OutToTri(localmesh);
localmesh.buildNormals();
bhkPackedNiTriStripsShapeRef trishape = makePackedTriStripsShape(localmesh, ident);
if ( TheHavokCode.Initialize() )
shape = StaticCast<bhkShape>( makeTreeShape(trishape) );
else
shape = StaticCast<bhkShape>(trishape);
bhkShapeRef Exporter::makeModifierShape(INode *node, Object* obj, Modifier* mod, Matrix3& tm)
{
enum { havok_params };
enum { PB_BOUND_TYPE, PB_MATERIAL, };
enum { bv_type_none, bv_type_box, bv_type_sphere, bv_type_capsule, bv_type_shapes, bv_type_convex, bv_type_packed, }; // pblock ID
bhkShapeRef shape;
const Mesh* mesh = NULL;
int material = NP_DEFAULT_HVK_MATERIAL;
int type = bv_type_none;
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
if (bhkHelperInterface* bhkHelp = (bhkHelperInterface*)mod->GetInterface(BHKHELPERINTERFACE_DESC))
{
mesh = bhkHelp->GetMesh();
}
else
{
if (TriObject *tri = (TriObject *)obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0)))
{
mesh = &tri->GetMesh();
}
}
if (IParamBlock2* pblock2 = mod->GetParamBlockByID(havok_params))
{
pblock2->GetValue(PB_BOUND_TYPE, 0, type, FOREVER, 0);
pblock2->GetValue(PB_MATERIAL, 0, material, FOREVER, 0);
}
switch (type)
{
default:
case bv_type_none:
break;
case bv_type_box:
shape = makeModConvexShape(node, mod, const_cast<Mesh&>(*mesh), tm);
break;
case bv_type_packed:
shape = makeModPackedTriStripShape(node, mod, const_cast<Mesh&>(*mesh), tm);
break;
}
return shape;
}
bhkShapeRef Exporter::makeModBoxShape(INode *node, Modifier* mod, Mesh& mesh, Matrix3& tm)
{
enum { havok_params };
enum { PB_BOUND_TYPE, PB_MATERIAL, };
enum { bv_type_none, bv_type_box, bv_type_sphere, bv_type_capsule, bv_type_shapes, bv_type_convex, bv_type_packed, }; // pblock ID
int material = NP_DEFAULT_HVK_MATERIAL;
if (IParamBlock2* pblock2 = mod->GetParamBlockByID(havok_params))
{
pblock2->GetValue(PB_MATERIAL, 0, material, FOREVER, 0);
}
bhkShapeRef retval;
if (bhkBoxShapeRef shape = new bhkBoxShape())
{
Box3 box; box.Init();
CalcAxisAlignedBox(mesh, box, NULL);
Vector3 dim(box.Max().x-box.Min().x, box.Max().y-box.Min().y, box.Max().z-box.Min().z);
dim /= (Exporter::bhkScaleFactor * 2);
shape->SetDimensions(dim);
shape->SetMaterial(HavokMaterial(material));
Matrix3 ltm = TransMatrix(box.Center()) * node->GetNodeTM(0) * tm;
if (ltm.IsIdentity())
transform->SetShape(shape);
transform->SetMaterial(HavokMaterial(material));
retval = StaticCast<bhkShape>(transform);
}
}
return retval;
}
bhkShapeRef Exporter::makeModSphereShape(INode *node, Modifier* mod, Mesh& mesh, Matrix3& tm)
{
enum { havok_params };
enum { PB_BOUND_TYPE, PB_MATERIAL, };
enum { bv_type_none, bv_type_box, bv_type_sphere, bv_type_capsule, bv_type_shapes, bv_type_convex, bv_type_packed, }; // pblock ID
int material = NP_DEFAULT_HVK_MATERIAL;
if (IParamBlock2* pblock2 = mod->GetParamBlockByID(havok_params))
{
pblock2->GetValue(PB_MATERIAL, 0, material, FOREVER, 0);
}
bhkShapeRef retval;
Point3 center = Point3::Origin;
float radius = 0.0f;
CalcCenteredSphere(mesh, center, radius);
if (bhkSphereShapeRef shape = new bhkSphereShape())
{
shape->SetRadius(radius / Exporter::bhkScaleFactor);
shape->SetMaterial(HavokMaterial(material));
Matrix3 ltm = TransMatrix(center) * node->GetObjTMAfterWSM(0) * tm;
if (ltm.IsIdentity())
transform->SetShape(shape);
transform->SetMaterial(HavokMaterial(material));
retval = StaticCast<bhkShape>(transform);
}
return retval;
}
bhkShapeRef Exporter::makeModCapsuleShape(INode *node, Modifier* mod, Mesh& mesh, Matrix3& tm)
{
enum { havok_params };
enum { PB_BOUND_TYPE, PB_MATERIAL, };
enum { bv_type_none, bv_type_box, bv_type_sphere, bv_type_capsule, bv_type_shapes, bv_type_convex, bv_type_packed, }; // pblock ID
if (IParamBlock2* pblock2 = mod->GetParamBlockByID(havok_params))
{
pblock2->GetValue(PB_MATERIAL, 0, material, FOREVER, 0);
}
bhkShapeRef retval;
Point3 center = Point3::Origin;
float radius = 0.0f;
CalcCenteredSphere(mesh, center, radius);
if (bhkCapsuleShapeRef shape = new bhkCapsuleShape())
{
shape->SetRadius(radius / Exporter::bhkScaleFactor);
shape->SetRadius1(radius / Exporter::bhkScaleFactor);
shape->SetRadius2(radius / Exporter::bhkScaleFactor);
shape->SetFirstPoint(TOVECTOR3(center/Exporter::bhkScaleFactor));
shape->SetSecondPoint(TOVECTOR3(center/Exporter::bhkScaleFactor));
shape->SetMaterial(HavokMaterial(material));
Matrix3 ltm = TransMatrix(center) * node->GetObjTMAfterWSM(0) * tm;
if (ltm.IsIdentity())
transform->SetShape(shape);
transform->SetMaterial(HavokMaterial(material));
retval = StaticCast<bhkShape>(transform);
}
}
return retval;
}
bhkShapeRef Exporter::makeModConvexShape(INode *node, Modifier* mod, Mesh& mesh, Matrix3& tm)
{
enum { havok_params };
enum { PB_BOUND_TYPE, PB_MATERIAL, };
enum { bv_type_none, bv_type_box, bv_type_sphere, bv_type_capsule, bv_type_shapes, bv_type_convex, bv_type_packed, }; // pblock ID
{
if (IParamBlock2* pblock2 = mod->GetParamBlockByID(havok_params))
{
pblock2->GetValue(PB_MATERIAL, 0, material, FOREVER, 0);
}
convShape->SetMaterial(HavokMaterial(material));
shape = StaticCast<bhkShape>(convShape);
}
return shape;
}
bhkShapeRef Exporter::makeModTriStripShape(INode *node, Modifier* mod, Mesh& mesh, Matrix3& tm)
{
enum { havok_params };
enum { PB_BOUND_TYPE, PB_MATERIAL, };
enum { bv_type_none, bv_type_box, bv_type_sphere, bv_type_capsule, bv_type_shapes, bv_type_convex, bv_type_packed, }; // pblock ID
{
trishape->SetMaterial(HavokMaterial(material));
if (IParamBlock2* pblock2 = mod->GetParamBlockByID(havok_params))
{
pblock2->GetValue(PB_MATERIAL, 0, material, FOREVER, 0);
}
shape = StaticCast<bhkShape>(trishape);
}
bhkShapeRef Exporter::makeModPackedTriStripShape(INode *node, Modifier* mod, Mesh& mesh, Matrix3& tm)
{
enum { havok_params };
enum { PB_BOUND_TYPE, PB_MATERIAL, };
enum { bv_type_none, bv_type_box, bv_type_sphere, bv_type_capsule, bv_type_shapes, bv_type_convex, bv_type_packed, }; // pblock ID
int material = NP_DEFAULT_HVK_MATERIAL;
Matrix3 ltm = node->GetObjTMAfterWSM(0) * tm;
bhkShapeRef shape;
if (bhkPackedNiTriStripsShapeRef trishape = makePackedTriStripsShape(mesh, ltm))
{
//trishape->SetMaterial(HavokMaterial(material));
if (IParamBlock2* pblock2 = mod->GetParamBlockByID(havok_params))
{
pblock2->GetValue(PB_MATERIAL, 0, material, FOREVER, 0);
}
if ( TheHavokCode.Initialize() )
shape = StaticCast<bhkShape>( makeTreeShape(trishape) );
else
shape = StaticCast<bhkShape>(trishape);