From ba6acd3c4b31d8e6acf48c740846864e63b704dd Mon Sep 17 00:00:00 2001 From: Tazpn <tazpn@users.sourceforge.net> Date: Sun, 17 Jun 2007 17:39:41 +0000 Subject: [PATCH] Additional fixes for Collision import/export. --- MaxNifPlugins_Readme.txt | 2 +- NifCommon/niutils.cpp | 5 +++ NifCommon/niutils.h | 20 ++++++++++++ NifExport/Coll.cpp | 46 +++++++++++++++++--------- NifExport/Exporter.h | 1 + NifExport/Util.cpp | 8 +++++ NifImport/ImportCollision.cpp | 56 ++++++++++++++++++++++---------- NifImport/ImportLights.cpp | 2 +- NifImport/ImportSkeleton.cpp | 6 ++-- NifImport/NIFImport.cpp | 18 ++++++++++ NifImport/NIFImporter.h | 2 ++ NifProps/bhkRigidBodyModifer.cpp | 1 + 12 files changed, 128 insertions(+), 39 deletions(-) diff --git a/MaxNifPlugins_Readme.txt b/MaxNifPlugins_Readme.txt index 07980bc..8565759 100644 --- a/MaxNifPlugins_Readme.txt +++ b/MaxNifPlugins_Readme.txt @@ -37,7 +37,7 @@ ----- o Importer/Exporter - Improved Bridge Commander support. - + - Added more Collision support (bhkRigidBodyModifier, bhkCollisionShape) 0.2.12 ----- diff --git a/NifCommon/niutils.cpp b/NifCommon/niutils.cpp index 5a9d682..7326a69 100644 --- a/NifCommon/niutils.cpp +++ b/NifCommon/niutils.cpp @@ -1163,4 +1163,9 @@ Modifier *CreatebhkCollisionModifier(INode* node, int type, HavokMaterial materi pblock2->SetValue(PB_MATERIAL, 0, material, 0); } return rbMod; +} + +TSTR GetNodeName(INode* node) +{ + return node->GetName(); } \ No newline at end of file diff --git a/NifCommon/niutils.h b/NifCommon/niutils.h index 3c46117..f9b4e27 100644 --- a/NifCommon/niutils.h +++ b/NifCommon/niutils.h @@ -347,6 +347,26 @@ static inline Niflib::Matrix33 TOMATRIX33(const Matrix3 &tm, bool invert = false return m3; } +static inline Matrix3 TOMATRIX3(Niflib::Vector3& trans, Niflib::QuaternionXYZW quat, float scale){ + Matrix3 tm, qm; + Quat q(quat.x, quat.y, quat.z, quat.w); + q.MakeMatrix(qm); + tm.SetTranslate(TOPOINT3(trans)); + tm *= qm; + tm *= ScaleMatrix(Point3(scale, scale, scale)); + return tm; +} + +static inline Matrix3 TOMATRIX3(Niflib::Vector3& trans, Niflib::Quaternion quat, float scale){ + Matrix3 tm, qm; + Quat q(quat.x, quat.y, quat.z, quat.w); + q.MakeMatrix(qm); + tm.SetTranslate(TOPOINT3(trans)); + tm *= qm; + tm *= ScaleMatrix(Point3(scale, scale, scale)); + return tm; +} + static inline Niflib::Matrix44 TOMATRIX4(const Matrix3 &tm, bool invert = false){ Niflib::Matrix33 m3(tm.GetRow(0)[0], tm.GetRow(0)[1], tm.GetRow(0)[2], tm.GetRow(1)[0], tm.GetRow(1)[1], tm.GetRow(1)[2], diff --git a/NifExport/Coll.cpp b/NifExport/Coll.cpp index 7c65585..e007f43 100755 --- a/NifExport/Coll.cpp +++ b/NifExport/Coll.cpp @@ -163,7 +163,11 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node) { markAsHandled(node); - newParent = nodeParent; // always have collision one level up? + newParent = Exporter::findNode(node->GetParentNode()); + if (!newParent) + newParent = nodeParent; + + //newParent = nodeParent; // always have collision one level up? TimeValue t = 0; Matrix3 tm = getTransform(node, t, local); @@ -196,8 +200,13 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node) } else if (isCollisionGroup(node) && !mFlattenHierarchy) { newParent = makeNode(nodeParent, node); } else { - newParent = nodeParent; + newParent = Exporter::findNode(node->GetParentNode()); + if (!newParent) + newParent = nodeParent; } + if (!newParent) + newParent = nodeParent; + for (int i=0; i<node->NumberOfChildren(); i++) { Result result = exportCollision(newParent, node->GetChildNode(i)); @@ -348,21 +357,26 @@ bhkConvexVerticesShapeRef Exporter::makeConvexShape(Mesh& mesh, Matrix3& tm) { bhkConvexVerticesShapeRef shape = StaticCast<bhkConvexVerticesShape>(bhkConvexVerticesShape::Create()); Point3 center(0.0f, 0.0f, 0.0f); - float radius = 0.0f; - CalcAxisAlignedSphere(mesh, center, radius); + float radius = 0.10f; + //CalcAxisAlignedSphere(mesh, center, radius); shape->SetRadius(radius); vector<Vector3> verts, norms; vector<float> dist; int nvert = mesh.getNumVerts(); + int nface = mesh.getNumFaces(); + verts.resize(nvert); - norms.resize(nvert); - dist.resize(nvert); + norms.resize(nface); + dist.resize(nface); for (int i=0; i<nvert; ++i) { - Point3& vert = mesh.getVert(i); - verts[i] = TOVECTOR3(vert) / Exporter::bhkScaleFactor; - norms[i] = TOVECTOR3(mesh.getNormal(i)); - dist[i] = vert.Length(); + Point3 vert = mesh.getVert(i) / Exporter::bhkScaleFactor; + verts[i] = TOVECTOR3(vert); + } + for (int i=0; i<nface; ++i) + { + norms[i] = TOVECTOR3(mesh.getFaceNormal(i)); + dist[i] = -mesh.FaceCenter(i).Length(); } shape->SetVertices(verts); shape->SetNormals(norms); @@ -458,11 +472,13 @@ bhkShapeRef Exporter::makeCapsuleShape(INode *node, Object *obj, Matrix3& tm) Point3 scale = GetScale(tm); float s = (scale[0] + scale[1] + scale[2]) / 3.0; - float radius = 0; - float height = 0; - IParamArray *params = obj->GetParamBlock(); - params->GetValue(obj->GetParamBlockIndex(CAPSULE_RADIUS), 0, radius, FOREVER); - params->GetValue(obj->GetParamBlockIndex(CAPSULE_HEIGHT), 0, height, FOREVER); + 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); + } bhkCapsuleShapeRef capsule = CreateNiObject<bhkCapsuleShape>(); diff --git a/NifExport/Exporter.h b/NifExport/Exporter.h index ccc0f99..1f2c12d 100755 --- a/NifExport/Exporter.h +++ b/NifExport/Exporter.h @@ -185,6 +185,7 @@ public: NiNodeRef makeNode(NiNodeRef &parent, INode *maxNode, bool local=true); NiNodeRef getNode(const string& name); NiNodeRef getNode(INode* maxNode); + NiNodeRef findNode(INode* maxNode); // returns true if the node contains collision objects bool isCollisionGroup(INode *maxNode, bool root=true); // returns true if the node contains meshes diff --git a/NifExport/Util.cpp b/NifExport/Util.cpp index 196da24..7b831e5 100755 --- a/NifExport/Util.cpp +++ b/NifExport/Util.cpp @@ -103,6 +103,14 @@ bool Exporter::equal(const Vector3 &a, const Point3 &b, float thresh) (fabsf(a.z-b.z) <= thresh); } +NiNodeRef Exporter::findNode(INode* maxNode) +{ + NodeToNodeMap::iterator itr = mNodeMap.find(maxNode); + if (itr != mNodeMap.end()) + return (*itr).second; + return NiNodeRef(); +} + NiNodeRef Exporter::getNode(INode* maxNode) { string name = maxNode->GetName(); diff --git a/NifImport/ImportCollision.cpp b/NifImport/ImportCollision.cpp index 719467a..f607859 100644 --- a/NifImport/ImportCollision.cpp +++ b/NifImport/ImportCollision.cpp @@ -48,7 +48,7 @@ struct CollisionImport void AddShape(INode *rbody, INode *shapeNode); bool ImportRigidBody(bhkRigidBodyRef rb, INode* node); - INode *CreateRigidBody(bhkRigidBodyRef body); + INode *CreateRigidBody(bhkRigidBodyRef body, INode* parent); bool ImportBase(bhkRigidBodyRef body, bhkShapeRef shape, INode* parent, INode *shapeNode); bool ImportShape(INode *rbody, bhkRigidBodyRef body, bhkShapeRef shape, INode* parent); @@ -65,6 +65,7 @@ struct CollisionImport const vector<Vector3>& verts, const vector<Triangle>& tris, const vector<Vector3>& norms, + Matrix3& tm, INode *parent ); @@ -88,16 +89,18 @@ bool NifImporter::ImportCollision(NiNodeRef node) if (bhkShapeRef shape = rbody->GetShape()) { INode *node = NULL; NiNodeRef target = collObj->GetTarget(); - if (ignoreRootNode || strmatch(target->GetName(), "Scene Root")) + if (strmatch(target->GetName(), "Scene Root")) node = gi->GetRootNode(); else node = FindNode(target); CollisionImport ci(*this); - INode *body = ci.CreateRigidBody(rbody); - if (!ci.ImportShape(body, rbody, shape, node)) + if (INode *body = ci.CreateRigidBody(rbody, node)) { - body->Delete(0, 1); + if (!ci.ImportShape(body, rbody, shape, node)) + { + body->Delete(0, 1); + } } } } @@ -144,7 +147,7 @@ bool CollisionImport::ImportRigidBody(bhkRigidBodyRef body, INode* node) return true; } -INode* CollisionImport::CreateRigidBody(bhkRigidBodyRef body) +INode* CollisionImport::CreateRigidBody(bhkRigidBodyRef body, INode *parent) { INode *rbody = NULL; if (body == NULL) @@ -184,11 +187,13 @@ INode* CollisionImport::CreateRigidBody(bhkRigidBodyRef body) body->SetCenter(center); } RefTargetHandle t = listObj->GetReference(0); - if (INode *n = ni.gi->CreateObjectNode(listObj)) { - Point3 startPos(0.0,0.0,0.0); - Quat q; q.Identity(); - PosRotScaleNode(n, startPos, q, 1.0f, prsPos); + TSTR clsName; + listObj->GetClassName(clsName); + if (INode *n = ni.CreateImportNode(clsName, listObj, parent)) { + Point3 startPos = TOPOINT3(body->GetTranslation()); + Quat q = TOQUAT(body->GetRotation()); + PosRotScaleNode(n, startPos, q, 1.0f, prsPos); rbody = n; } } @@ -218,9 +223,9 @@ bool CollisionImport::ImportBase(bhkRigidBodyRef body, bhkShapeRef shape, INode* //ImportRigidBody(body, shapeNode); - Point3 pos = TOPOINT3(body->GetTranslation()) / ni.bhkScaleFactor; - Quat rot = TOQUAT(body->GetRotation()); - PosRotScaleNode(shapeNode, pos, rot, 1.0, prsDefault); + //Point3 pos = TOPOINT3(body->GetTranslation()) / ni.bhkScaleFactor; + //Quat rot = TOQUAT(body->GetRotation()); + //PosRotScaleNode(shapeNode, pos, rot, 1.0, prsDefault); // Wireframe Red color @@ -285,6 +290,7 @@ INode *CollisionImport::ImportCollisionMesh( const vector<Vector3>& verts, const vector<Triangle>& tris, const vector<Vector3>& norms, + Matrix3& tm, INode *parent ) { @@ -309,7 +315,12 @@ INode *CollisionImport::ImportCollisionMesh( // Triangles and texture vertices ni.SetTriangles(mesh, tris); - ni.SetNormals(mesh, tris, norms); + //ni.SetNormals(mesh, tris, norms); + + MNMesh mn(mesh); + mn.Transform(tm); + mn.OutToTri(mesh); + mesh.checkNormals(TRUE); ni.i->AddNodeToScene(node); @@ -330,7 +341,7 @@ bool CollisionImport::ImportSphere(INode *rbody, bhkRigidBodyRef body, bhkSphere RefTargetHandle t = ob->GetReference(0); setMAXScriptValue(t, "radius", 0, radius); - if (INode *n = ni.gi->CreateObjectNode(ob)) { + if (INode *n = ni.CreateImportNode(shape->GetType().GetTypeName().c_str(), ob, parent)) { #if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5 // Need to "Affect Pivot Only" and "Center to Object" first n->CenterPivot(0, FALSE); @@ -368,7 +379,7 @@ bool CollisionImport::ImportCapsule(INode *rbody, bhkRigidBodyRef body, bhkCapsu params->SetValue(ob->GetParamBlockIndex(CAPSULE_HEIGHT), 0, height); params->SetValue(ob->GetParamBlockIndex(CAPSULE_CENTERS), 0, heighttype); - if (INode *n = ni.gi->CreateObjectNode(ob)) { + if (INode *n = ni.CreateImportNode(shape->GetType().GetTypeName().c_str(), ob, parent)) { // Need to "Affect Pivot Only" and "Center to Object" first //n->CenterPivot(0, FALSE); @@ -388,11 +399,15 @@ extern vector<Triangle> compute_convex_hull(const vector<Vector3>& verts); bool CollisionImport::ImportConvexVertices(INode *rbody, bhkRigidBodyRef body, bhkConvexVerticesShapeRef shape, INode *parent) { INode *returnNode = NULL; + //Vector3 trans = body->GetTranslation(); + //QuaternionXYZW quat = body->GetRotation(); + //Matrix3 tm = TOMATRIX3(trans, quat, 1.0f); + Matrix3 tm(true); vector<Vector3> verts = shape->GetVertices(); //vector<Triangle> tris = shape->GetTriangles(); vector<Vector3> norms = shape->GetNormals(); vector<Triangle> tris = compute_convex_hull(verts); - returnNode = ImportCollisionMesh(verts, tris, norms, parent); + returnNode = ImportCollisionMesh(verts, tris, norms, tm, parent); CreatebhkCollisionModifier(returnNode, bv_type_convex, shape->GetMaterial()); ImportBase(body, shape, parent, returnNode); @@ -459,11 +474,16 @@ bool CollisionImport::ImportPackedNiTriStripsShape(INode *rbody, bhkRigidBodyRef { if (hkPackedNiTriStripsDataRef data = shape->GetData()) { + //Vector3 trans = body->GetTranslation(); + //QuaternionXYZW quat = body->GetRotation(); + //Matrix3 tm = TOMATRIX3(trans, quat, 1.0f); + Matrix3 tm(true); + vector<Vector3> verts = data->GetVertices(); vector<Triangle> tris = data->GetTriangles(); vector<Vector3> norms = data->GetNormals(); - INode *inode = ImportCollisionMesh(verts, tris, norms, parent); + INode *inode = ImportCollisionMesh(verts, tris, norms, tm, parent); CreatebhkCollisionModifier(inode, bv_type_shapes, HavokMaterial(NP_DEFAULT_HVK_MATERIAL)); ImportBase(body, shape, parent, inode); AddShape(rbody, inode); diff --git a/NifImport/ImportLights.cpp b/NifImport/ImportLights.cpp index c9c546d..36f1d02 100644 --- a/NifImport/ImportLights.cpp +++ b/NifImport/ImportLights.cpp @@ -96,7 +96,7 @@ bool NifImporter::ImportLights(vector<NiLightRef> lights) } else if (light->IsSameType(NiSpotLight::TYPE)){ ob = CreateLight(gi, light, FSPOT_LIGHT); } - if (INode *n = gi->CreateObjectNode(ob)) { + if (INode *n = CreateImportNode(light->GetName().c_str(), ob, NULL)) { string name = light->GetName(); if (!name.empty()) { n->SetName(const_cast<TCHAR*>(name.c_str())); diff --git a/NifImport/ImportSkeleton.cpp b/NifImport/ImportSkeleton.cpp index 8d6448e..99c42fc 100644 --- a/NifImport/ImportSkeleton.cpp +++ b/NifImport/ImportSkeleton.cpp @@ -504,8 +504,7 @@ INode *NifImporter::CreateHelper(const string& name, Point3 startPos) if (DummyObject *ob = (DummyObject *)gi->CreateInstance(HELPER_CLASS_ID,Class_ID(DUMMY_CLASS_ID,0))) { const float DUMSZ = 1.0f; ob->SetBox(Box3(Point3(-DUMSZ,-DUMSZ,-DUMSZ),Point3(DUMSZ,DUMSZ,DUMSZ))); - if (INode *n = gi->CreateObjectNode(ob)) { - n->SetName(const_cast<TCHAR*>(name.c_str())); + if (INode *n = CreateImportNode(name.c_str(), ob, NULL)) { Quat q; q.Identity(); PosRotScaleNode(n, startPos, q, 1.0f, prsPos); return n; @@ -528,9 +527,8 @@ INode *NifImporter::CreateCamera(const string& name) ob->Enable(1); ob->NewCamera(0); ob->SetFOV(0, TORAD(75.0f)); - if (INode *n = gi->CreateObjectNode(ob)) { + if (INode *n = CreateImportNode(name.c_str(), ob, NULL)) { n->Hide(TRUE); - n->SetName(const_cast<TCHAR*>(name.c_str())); n->BoneAsLine(1); return n; } diff --git a/NifImport/NIFImport.cpp b/NifImport/NIFImport.cpp index b6de409..53cb702 100644 --- a/NifImport/NIFImport.cpp +++ b/NifImport/NIFImport.cpp @@ -36,6 +36,24 @@ NifImporter::NifImporter() { } +INode* NifImporter::CreateImportNode(const char *name, Object *obj, INode* parent) +{ + ImpNode* impNode = i->CreateNode(); + if (INode *n = impNode->GetINode()) { + n->SetName(const_cast<TCHAR*>(name)); + n->SetObjectRef(obj); + i->AddNodeToScene(impNode); + if (parent) + { + parent->AttachChild(impNode->GetINode()); + + ASSERT(parent == n->GetParentNode()); + + } + } + return impNode->GetINode(); +} + void NifImporter::ReadBlocks() { //blocks = ReadNifList( name ); diff --git a/NifImport/NIFImporter.h b/NifImport/NIFImporter.h index 6a601f8..d16023b 100644 --- a/NifImport/NIFImporter.h +++ b/NifImport/NIFImporter.h @@ -132,6 +132,8 @@ public: INode *CreateHelper(const string& name, Point3 startPos); INode *CreateCamera(const string& name); + INode *CreateImportNode(const char *name, Object *obj, INode* parent); + bool ImportLights(Niflib::NiNodeRef node); bool ImportLights(vector<Niflib::NiLightRef> lights); diff --git a/NifProps/bhkRigidBodyModifer.cpp b/NifProps/bhkRigidBodyModifer.cpp index 2753e93..d142115 100644 --- a/NifProps/bhkRigidBodyModifer.cpp +++ b/NifProps/bhkRigidBodyModifer.cpp @@ -375,6 +375,7 @@ void bhkRigidBodyModifier::ModifyObject (TimeValue t, ModContext &mc, ObjectStat //BuildScubaMesh(); break; } + proxyMesh.buildNormals(); if (needsDelete) { os->obj = tobj; -- GitLab