From e4bf0cfc793995a23c699239dc6f265e8ab7f590 Mon Sep 17 00:00:00 2001 From: Tazpn <tazpn@users.sourceforge.net> Date: Sun, 1 Jul 2007 18:33:31 +0000 Subject: [PATCH] 0.2.15 ----- o Props - Resolve issue with bhkRigidBody object not saving and restoring data o Exporter/Importer - Resolve many issues with transforms and bhk shapes. o Exporter - Fix crash when exporting animations. - Fix issue with exporting Skin data causing missing vertexes in nifskope - Fix issue with exporting textkeys for morrowind and geomorph faces (Requires import to not ignore root node and selected export of that node) - Add animation export support for accumulate transforms (translation only) - Fix some issues with geometry Morpher exporter with bad UV data. o Importer - Fixed issue with not ignoring root node when option unchecked - Fixed issue of bhkRigidBody object not importing data properly - Set Accumulate Transforms to accumulate y-data by default --- MaxNifPlugins_Readme.txt | 25 +++- NifCommon/niutils.h | 2 +- NifExport/Animation.cpp | 137 +++++++++++++++--- NifExport/Coll.cpp | 215 +++++++++++++++++++---------- NifExport/Exporter.h | 12 ++ NifExport/Mesh.cpp | 16 ++- NifExport/Util.cpp | 19 +-- NifImport/ImportAnimation.cpp | 29 +++- NifImport/ImportCollision.cpp | 104 ++++++-------- NifImport/NIFImport.cpp | 2 +- NifPlugins_VC80.sln | 53 +++++++ NifPlugins_VC80.vcproj | 50 +++---- NifProps/bhkListObj.cpp | 24 ++++ NifProps/bhkRigidBodyInterface.cpp | 27 ++++ NifProps/bhkRigidBodyInterface.h | 3 + 15 files changed, 511 insertions(+), 207 deletions(-) diff --git a/MaxNifPlugins_Readme.txt b/MaxNifPlugins_Readme.txt index ccdd24b..dfa96a8 100644 --- a/MaxNifPlugins_Readme.txt +++ b/MaxNifPlugins_Readme.txt @@ -1,4 +1,4 @@ - MaxPlugins 0.2.14 + MaxPlugins 0.2.15 ================= @@ -33,15 +33,32 @@ Change log ---------- + 0.2.15 + ----- + o Props + - Resolve issue with bhkRigidBody object not saving and restoring data + o Exporter/Importer + - Resolve many issues with transforms and bhk shapes. + o Exporter + - Fix crash when exporting animations. + - Fix issue with exporting Skin data causing missing vertexes in nifskope + - Fix issue with exporting textkeys for morrowind and geomorph faces + (Requires import to not ignore root node and selected export of that node) + - Add animation export support for accumulate transforms (translation only) + - Fix some issues with geometry Morpher exporter with bad UV data. + o Importer + - Fixed issue with not ignoring root node when option unchecked + - Fixed issue of bhkRigidBody object not importing data properly + - Set Accumulate Transforms to accumulate y-data by default + 0.2.14 ----- o Exporter - Fix issues with bhkConvexShape and bhkRigidBody o Exporter/Importer - Introduce Morpher animation support - - - 0.2.13 + + 0.2.13.1 ----- o Properties - Add Optimize option to proxy and modifier diff --git a/NifCommon/niutils.h b/NifCommon/niutils.h index 362f64b..a8c37cb 100644 --- a/NifCommon/niutils.h +++ b/NifCommon/niutils.h @@ -348,7 +348,7 @@ static inline Niflib::Matrix33 TOMATRIX33(const Matrix3 &tm, bool invert = false } static inline Matrix3 TOMATRIX3(Niflib::Vector3& trans, Niflib::QuaternionXYZW quat, float scale){ - Matrix3 tm, qm; + Matrix3 tm(true), qm; Quat q(quat.x, quat.y, quat.z, quat.w); q.MakeMatrix(qm); tm.SetTranslate(TOPOINT3(trans)); diff --git a/NifExport/Animation.cpp b/NifExport/Animation.cpp index 8ea410c..d634aa9 100644 --- a/NifExport/Animation.cpp +++ b/NifExport/Animation.cpp @@ -59,12 +59,13 @@ struct AnimationExport bool doExport(NiControllerSequenceRef seq); bool doExport(NiControllerManagerRef ctrl, INode *node); - bool exportController(INode *node, bool hasAccum); + bool exportController(INode *node, Exporter::AccumType accumType); Control *GetTMController(INode* node); NiTimeControllerRef exportController(INode *node, Interval range, bool setTM ); bool GetTextKeys(INode *node, vector<StringKey>& textKeys); Interval GetTimeRange(INode *n); void GetTimeRange(Control *c, Interval& range); + bool splitAccum(NiTransformDataRef base, NiTransformDataRef accum, Exporter::AccumType accumType); Exporter ≠ Interval range; @@ -372,6 +373,8 @@ bool AnimationExport::doExport(NiControllerSequenceRef seq) NiTextKeyExtraDataRef textKeyData = new NiTextKeyExtraData(); seq->SetTextKey(textKeyData); + Exporter::AccumType accumType = Exporter::AT_NONE; + // Populate Text keys and Sequence information from note tracks if (Exporter::mUseTimeTags) { #if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7 @@ -411,7 +414,22 @@ bool AnimationExport::doExport(NiControllerSequenceRef seq) seq->SetName(*itr); } else if (strmatch("-loop", *itr)) { seq->SetCycleType(CYCLE_LOOP); - } + } else if (strmatch("-at", *itr)) { + if (++itr == args.end()) break; + string type = (*itr); + if (strmatch(type, "none")) { + accumType = Exporter::AT_NONE; + } else { + for (int j=0; j<type.size(); ++j) { + if (tolower(type[j]) == 'x') + accumType = Exporter::AccumType(accumType | Exporter::AT_X); + else if (tolower(type[j]) == 'y') + accumType = Exporter::AccumType(accumType | Exporter::AT_Y); + else if (tolower(type[j]) == 'z') + accumType = Exporter::AccumType(accumType | Exporter::AT_Z); + } + } + } } } else if ( wildmatch("end*", key->note) ) { range.SetEnd( key->time ); @@ -439,7 +457,7 @@ bool AnimationExport::doExport(NiControllerSequenceRef seq) // Now let the fun begin. - return exportController(node, true); + return exportController(node, accumType); } bool AnimationExport::doExport(NiControllerManagerRef mgr, INode *node) @@ -452,6 +470,7 @@ bool AnimationExport::doExport(NiControllerManagerRef mgr, INode *node) vector<NiControllerSequenceRef> seqs; vector<StringKey> textKeys; NiControllerSequenceRef curSeq; + Exporter::AccumType accumType = Exporter::AT_FORCE; // Populate Text keys and Sequence information from note tracks if (Exporter::mUseTimeTags) { @@ -528,7 +547,22 @@ bool AnimationExport::doExport(NiControllerManagerRef mgr, INode *node) curSeq->SetName(*itr); } else if (strmatch("-loop", *itr)) { curSeq->SetCycleType(CYCLE_LOOP); - } + } else if (strmatch("-at", *itr)) { + if (++itr == args.end()) break; + string type = (*itr); + if (strmatch(type, "none")) { + accumType = Exporter::AT_NONE; + } else { + for (int j=0; j<type.size(); ++j) { + if (tolower(type[j]) == 'x') + accumType = Exporter::AccumType( accumType | Exporter::AT_X ); + else if (tolower(type[j]) == 'y') + accumType = Exporter::AccumType( accumType | Exporter::AT_Y ); + else if (tolower(type[j]) == 'z') + accumType = Exporter::AccumType( accumType | Exporter::AT_Z ); + } + } + } } } @@ -571,7 +605,7 @@ bool AnimationExport::doExport(NiControllerManagerRef mgr, INode *node) this->range = this->ranges[this->seq]; // Now let the fun begin. - bool ok = exportController(node, true); + bool ok = exportController(node, accumType); } // Set objects with animation @@ -688,16 +722,16 @@ Interval AnimationExport::GetTimeRange(INode *node) NiTimeControllerRef Exporter::CreateController(INode *node, Interval range) { AnimationExport ae(*this); + if (Exporter::mExportType == Exporter::NIF_WO_KF && isNodeTracked(node)) { + NiNodeRef ninode = getNode(node); + vector<StringKey> textKeys; + if (GetTextKeys(node, textKeys, range)) { + NiTextKeyExtraDataRef textKeyData = new NiTextKeyExtraData(); + ninode->AddExtraData(StaticCast<NiExtraData>(textKeyData), Exporter::mNifVersionInt); + textKeyData->SetKeys(textKeys); + } + } if ( NiTimeControllerRef tc = ae.exportController(node, range, false) ) { - if (Exporter::mExportType == Exporter::NIF_WO_KF && isNodeTracked(node)) { - NiNodeRef ninode = getNode(node); - vector<StringKey> textKeys; - if (GetTextKeys(node, textKeys, range)) { - NiTextKeyExtraDataRef textKeyData = new NiTextKeyExtraData(); - ninode->AddExtraData(StaticCast<NiExtraData>(textKeyData), Exporter::mNifVersionInt); - textKeyData->SetKeys(textKeys); - } - } return tc; } return NiTimeControllerRef(); @@ -994,7 +1028,54 @@ NiTimeControllerRef AnimationExport::exportController(INode *node, Interval rang return timeControl; } -bool AnimationExport::exportController(INode *node, bool hasAccum) +bool AnimationExport::splitAccum(NiTransformDataRef base, NiTransformDataRef accum, Exporter::AccumType accumType) +{ + vector<Vector3Key> baseTrans = base->GetTranslateKeys(); + vector<Vector3Key> accmTrans; accmTrans.resize( baseTrans.size() ); + accum->SetTranslateType( base->GetTranslateType() ); + + for (int i=0, n=baseTrans.size(); i<n; ++i) { + accmTrans[i] = baseTrans[i]; + accmTrans[i].data = Vector3(0.0f, 0.0f, 0.0f); + if (accumType & Exporter::AT_X) { + swap(accmTrans[i].data.x, baseTrans[i].data.x); + } + if (accumType & Exporter::AT_Y) { + swap(accmTrans[i].data.y, baseTrans[i].data.y); + } + if (accumType & Exporter::AT_Z) { + swap(accmTrans[i].data.z, baseTrans[i].data.z); + } + } + base->SetTranslateKeys(accmTrans); + accum->SetTranslateKeys(baseTrans); + + // Rotate + accum->SetRotateType( base->GetRotateType() ); + accum->SetQuatRotateKeys( base->GetQuatRotateKeys() ); + base->SetQuatRotateKeys( vector<QuatKey>() ); + + accum->SetXRotateType( base->GetXRotateType() ); + accum->SetXRotateKeys( base->GetXRotateKeys() ); + base->SetXRotateKeys( vector<FloatKey>() ); + + accum->SetYRotateType( base->GetYRotateType() ); + accum->SetYRotateKeys( base->GetYRotateKeys() ); + base->SetYRotateKeys( vector<FloatKey>() ); + + accum->SetZRotateType( base->GetZRotateType() ); + accum->SetZRotateKeys( base->GetZRotateKeys() ); + base->SetZRotateKeys( vector<FloatKey>() ); + + // Scale + accum->SetScaleType( base->GetScaleType() ); + accum->SetScaleKeys( base->GetScaleKeys() ); + base->SetScaleKeys( vector<FloatKey>() ); + + return true; +} + +bool AnimationExport::exportController(INode *node, Exporter::AccumType accumType) { bool ok = true; @@ -1015,7 +1096,7 @@ bool AnimationExport::exportController(INode *node, bool hasAccum) seq->AddInterpolator(StaticCast<NiSingleInterpController>(control), priority); // Handle NonAccum - if (Exporter::mAllowAccum && hasAccum) + if (Exporter::mAllowAccum && accumType != Exporter::AT_NONE) { NiTransformInterpolatorRef interp = DynamicCast<NiTransformInterpolator>(interpControl->GetInterpolator()); NiNodeRef accnode = ne.getNode( FormatString("%s NonAccum", node->GetName()) ); @@ -1032,10 +1113,16 @@ bool AnimationExport::exportController(INode *node, bool hasAccum) accinterp->SetScale( 1.0f ); accinterp->SetRotation( Quaternion(1.0f, 0.0f, 0.0f, 0.0f) ); - // Transfer entire data to accum node if (interp != NULL) { - accinterp->SetData( interp->GetData() ); - interp->SetData( NiTransformDataRef() ); + NiTransformDataRef accumData = new NiTransformData(); + // Transfer entire data to accum node + if ((accumType & Exporter::AT_XYZ) == Exporter::AT_XYZ) { + accinterp->SetData( interp->GetData() ); + interp->SetData( accumData ); + } else { + accinterp->SetData( accumData ); + splitAccum(interp->GetData(), accumData, accumType); + } } seq->AddInterpolator(StaticCast<NiSingleInterpController>(acccontrol), Exporter::mDefaultPriority); @@ -1057,7 +1144,7 @@ bool AnimationExport::exportController(INode *node, bool hasAccum) for (int i=0, n=node->NumberOfChildren(); ok && i<n; ++i) { INode *child = node->GetChildNode(i); - ok |= exportController(child, false); + ok |= exportController(child, Exporter::AT_NONE); } return ok; } @@ -1069,6 +1156,7 @@ Exporter::Result Exporter::exportGeomMorpherControl(Modifier* mod, vector<Vector if (mod != NULL) { if (mod->IsEnabled()) { + NiGeomMorpherControllerRef ctrl = new NiGeomMorpherController(); NiMorphDataRef data = new NiMorphData(); vector<NiInterpolatorRef> interpolators; @@ -1110,6 +1198,15 @@ Exporter::Result Exporter::exportGeomMorpherControl(Modifier* mod, vector<Vector } } + //// Root text keys ??? + //NiNodeRef ninode = this->mNiRoot; + //vector<StringKey> textKeys; + //if (GetTextKeys(mI->GetRootNode(), textKeys, range)) { + // NiTextKeyExtraDataRef textKeyData = new NiTextKeyExtraData(); + // ninode->AddExtraData(StaticCast<NiExtraData>(textKeyData), Exporter::mNifVersionInt); + // textKeyData->SetKeys(textKeys); + //} + for (int i=0; i<indices.size(); ++i) { int idx = indices[i]; diff --git a/NifExport/Coll.cpp b/NifExport/Coll.cpp index 4195c15..2652220 100755 --- a/NifExport/Coll.cpp +++ b/NifExport/Coll.cpp @@ -6,6 +6,8 @@ #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" @@ -142,8 +144,8 @@ void Exporter::addFace(Triangles &tris, vector<Vector3> &verts, vector<Vector3> Triangle tri; for (int i=0; i<3; i++) { - Point3 pt = VectorTransform(mesh->verts[ mesh->faces[ face ].v[ vi[i] ] ], tm); - Point3 norm = VectorTransform(getVertexNormal(mesh, face, mesh->getRVertPtr(mesh->faces[ face ].v[ vi[i] ])), tm); + 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; tri[i] = addVertex(verts, vnorms, pt, norm); } tris.push_back(tri); @@ -169,26 +171,38 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node) markAsHandled(node); newParent = Exporter::findNode(node->GetParentNode()); - if (!newParent) + if (!newParent) { newParent = nodeParent; - + } //newParent = nodeParent; // always have collision one level up? TimeValue t = 0; - Matrix3 tm = getTransform(node, t, local); bhkRigidBodyRef body = makeCollisionBody(node); if (body) { + 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); - - body->SetTranslation(TOVECTOR3(Point3(0.0f, 0.0f, 0.0f))); - body->SetRotation(TOQUATXYZW(Quat())); - //QuaternionXYZW q = TOQUATXYZW(rm.AsQuaternion()); - //body->SetRotation(q); - //body->SetTranslation(trans / Exporter::bhkScaleFactor); + 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) @@ -197,10 +211,6 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node) bhkCollisionObjectRef co = new bhkCollisionObject(); co->SetBody(DynamicCast<NiObject>(body)); - - //co->SetTarget(newParent); - - // link newParent->SetCollisionObject(DynamicCast<NiCollisionObject>(co)); } } @@ -299,7 +309,7 @@ bhkRigidBodyRef Exporter::makeCollisionBody(INode *node) // setup body - bhkRigidBodyRef body = transenable ? CreateNiObject<bhkRigidBodyT>() : CreateNiObject<bhkRigidBody>(); + bhkRigidBodyRef body = transenable ? new bhkRigidBodyT() : new bhkRigidBody(); body->SetLayer(OblivionLayer(lyr)); body->SetLayerCopy(OblivionLayer(lyr)); @@ -343,22 +353,66 @@ bhkNiTriStripsShapeRef Exporter::makeTriStripsShape(Mesh& mesh, Matrix3& sm) data->SetVertices(verts); data->SetNormals(vnorms); - //int lyr = OL_STATIC; - //npGetProp(node, NP_HVK_LAYER, lyr, NP_DEFAULT_HVK_LAYER); - - //int mtl; - //npGetProp(node, NP_HVK_MATERIAL, mtl, NP_DEFAULT_HVK_MATERIAL); - //shape->SetMaterial(HavokMaterial(mtl)); - // setup shape bhkNiTriStripsShapeRef shape = StaticCast<bhkNiTriStripsShape>(bhkNiTriStripsShape::Create()); shape->SetNumStripsData(1); shape->SetStripsData(0, data); shape->SetNumDataLayers(1); shape->SetOblivionLayer(0, OL_STATIC); + return shape; +} + +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] = face.getVert(0); + tri[1] = face.getVert(1); + tri[2] = face.getVert(2); + } - //if (tri != os.obj) - // tri->DeleteMe(); + 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); + //shape->SetStripsData(0, data); + //shape->SetNumDataLayers(1); + //shape->SetOblivionLayer(0, OL_STATIC); return shape; } @@ -373,12 +427,14 @@ bhkConvexVerticesShapeRef Exporter::makeConvexShape(Mesh& mesh, Matrix3& tm) vector<Float4> norms; int nvert = mesh.getNumVerts(); int nface = mesh.getNumFaces(); + mesh.checkNormals(FALSE); + mesh.buildNormals(); verts.resize(nvert); norms.resize(nface); for (int i=0; i<nvert; ++i) { - Point3 vert = mesh.getVert(i) / Exporter::bhkScaleFactor * tm; + Point3 vert = (mesh.getVert(i) * tm) / Exporter::bhkScaleFactor; verts[i] = TOVECTOR3(vert); } for (int i=0; i<nface; ++i) @@ -534,22 +590,20 @@ bhkShapeRef Exporter::makebhkBoxShape(INode *node, Object *obj, Matrix3& tm) // 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); - box->SetMaterial(HavokMaterial(mtl)); - Matrix3 tm = node->GetObjectTM(0); - //tm.SetTrans(tm.GetTrans() / Exporter::bhkScaleFactor); - if (tm.IsIdentity()) + Matrix3 ltm = node->GetNodeTM(0) * tm; + if (ltm.IsIdentity()) { retval = StaticCast<bhkShape>(box); } else { + ltm.SetTrans(ltm.GetTrans() / Exporter::bhkScaleFactor); + bhkTransformShapeRef transform = new bhkTransformShape(); - transform->SetTransform(TOMATRIX4(tm).Transpose()); + transform->SetTransform(TOMATRIX4(ltm).Transpose()); transform->SetShape(box); transform->SetMaterial(HavokMaterial(mtl)); retval = StaticCast<bhkShape>(transform); @@ -577,16 +631,17 @@ bhkShapeRef Exporter::makebhkSphereShape(INode *node, Object *obj, Matrix3& tm) shape->SetRadius(radius); shape->SetMaterial(HavokMaterial(mtl)); - Matrix3 tm = node->GetObjectTM(0); - tm.SetTrans(tm.GetTrans() / Exporter::bhkScaleFactor); - if (tm.IsIdentity()) + Matrix3 ltm = node->GetNodeTM(0) * tm; + if (ltm.IsIdentity()) { retval = StaticCast<bhkShape>(shape); } else { + ltm.SetTrans(ltm.GetTrans() / Exporter::bhkScaleFactor); + bhkTransformShapeRef transform = new bhkTransformShape(); - transform->SetTransform(TOMATRIX4(tm).Transpose()); + transform->SetTransform(TOMATRIX4(ltm).Transpose()); transform->SetShape(shape); transform->SetMaterial(HavokMaterial(mtl)); retval = StaticCast<bhkShape>(transform); @@ -617,10 +672,10 @@ bhkShapeRef Exporter::makebhkCapsuleShape(INode *node, Object *obj, Matrix3& tm) shape->SetRadius2(radius2); shape->SetMaterial(HavokMaterial(mtl)); - Matrix3 tm = node->GetObjectTM(0); - Point3 center = tm.GetTrans(); + Matrix3 ltm = node->GetNodeTM(0) * tm; + Point3 center = ltm.GetTrans(); - Matrix3 rot = tm; + Matrix3 rot = ltm; rot.NoTrans(); rot.NoScale(); @@ -640,10 +695,8 @@ bhkShapeRef Exporter::makebhkCapsuleShape(INode *node, Object *obj, Matrix3& tm) bhkShapeRef Exporter::makeTriStripsShape(INode *node, Matrix3& tm) { TimeValue t = 0; - Matrix3 sm = ScaleMatrix( GetScale(tm) ); + Matrix3 sm = ScaleMatrix( GetScale(tm) ); - //Matrix3 tm = node->GetObjTMAfterWSM(t); - // Order of the vertices. Get 'em counter clockwise if the objects is // negatively scaled. ObjectState os = node->EvalWorldState(t); @@ -758,11 +811,6 @@ bool Exporter::isCollision(INode *node) bhkShapeRef Exporter::makeListShape(INode *node, Matrix3& tm, bhkRigidBodyRef body) { - // reset transform - body->SetCenter(Vector3(0,0,0)); - body->SetTranslation(Vector3(0.0f,0.0f,0.0f)); - body->SetRotation(TOQUATXYZW(Quat(0.0f,0.0f,0.0f,1.0f))); - const int PB_MATERIAL = 0; const int PB_MESHLIST = 1; IParamBlock2* pblock2 = node->GetObjectRef()->GetParamBlockByID(0); @@ -798,12 +846,10 @@ bhkShapeRef Exporter::makeListShape(INode *node, Matrix3& tm, bhkRigidBodyRef bo } 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); @@ -844,8 +890,6 @@ bhkShapeRef Exporter::makeProxyShape(INode *node, Object *obj, Matrix3& tm) if (TriObject *triObj = (TriObject *)obj->ConvertToType(0, triObjectClassID)) { Mesh& mesh = triObj->GetMesh(); - mesh.buildNormals(); - switch (bvType) { case bv_type_box: @@ -857,8 +901,11 @@ bhkShapeRef Exporter::makeProxyShape(INode *node, Object *obj, Matrix3& tm) // break; case bv_type_shapes: + shape = makeProxyTriStripShape(node, obj, mesh, tm); + break; case bv_type_packed: shape = makeProxyTriStripShape(node, obj, mesh, tm); + //shape = makeProxyPackedTriStripShape(node, obj, mesh, tm); break; case bv_type_convex: @@ -894,15 +941,17 @@ bhkShapeRef Exporter::makeProxyBoxShape(INode *node, Object *obj, Mesh& mesh, Ma shape->SetMaterial(HavokMaterial(mtl)); shape->SetDimensions(dim); - Matrix3 tm = /*GetLocalTM(node) * */TransMatrix(box.Center()/Exporter::bhkScaleFactor); - if (tm.IsIdentity()) + Matrix3 ltm = /*GetLocalTM(node) * */TransMatrix(box.Center()) * tm; + if (ltm.IsIdentity()) { retval = StaticCast<bhkShape>(shape); } else { + ltm.SetTrans(ltm.GetTrans() / Exporter::bhkScaleFactor); + bhkTransformShapeRef transform = new bhkTransformShape(); - transform->SetTransform(TOMATRIX4(tm).Transpose()); + transform->SetTransform(TOMATRIX4(ltm).Transpose()); transform->SetShape(shape); transform->SetMaterial(HavokMaterial(mtl)); retval = StaticCast<bhkShape>(transform); @@ -935,7 +984,6 @@ bhkShapeRef Exporter::makeProxyConvexShape(INode *node, Object *obj, Mesh& mesh, bhkShapeRef shape; if (IParamBlock2* pblock2 = obj->GetParamBlockByID(list_params)) { - Matrix3 tm(true); if (bhkConvexVerticesShapeRef convShape = makeConvexShape(mesh, tm)) { int mtl = pblock2->GetInt(PB_MATERIAL, 0, 0); @@ -957,8 +1005,16 @@ bhkShapeRef Exporter::makeProxyTriStripShape(INode *node, Object *obj, Mesh& mes { 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(); + Matrix3 ident(true); - bhkNiTriStripsShapeRef trishape = makeTriStripsShape(mesh, ident); + bhkNiTriStripsShapeRef trishape = makeTriStripsShape(localmesh, ident); trishape->SetMaterial(HavokMaterial(mtl)); shape = StaticCast<bhkShape>(trishape); @@ -977,9 +1033,16 @@ bhkShapeRef Exporter::makeProxyPackedTriStripShape(INode *node, Object *obj, Mes { 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(); + Matrix3 ident(true); - bhkNiTriStripsShapeRef trishape = makeTriStripsShape(mesh, ident); - trishape->SetMaterial(HavokMaterial(mtl)); + bhkPackedNiTriStripsShapeRef trishape = makePackedTriStripsShape(localmesh, ident); shape = StaticCast<bhkShape>(trishape); } @@ -998,6 +1061,7 @@ bhkShapeRef Exporter::makeModifierShape(INode *node, Object* obj, Modifier* mod, int material = NP_DEFAULT_HVK_MATERIAL; int type = bv_type_none; + node->EvalWorldState(0); if (bhkHelperInterface* bhkHelp = (bhkHelperInterface*)mod->GetInterface(BHKHELPERINTERFACE_DESC)) { mesh = bhkHelp->GetMesh(); @@ -1066,15 +1130,17 @@ bhkShapeRef Exporter::makeModBoxShape(INode *node, Modifier* mod, Mesh& mesh, Ma shape->SetDimensions(dim); shape->SetMaterial(HavokMaterial(material)); - Matrix3 tm = /*GetLocalTM(node) * */TransMatrix(box.Center()/Exporter::bhkScaleFactor); - if (tm.IsIdentity()) + Matrix3 ltm = TransMatrix(box.Center()) * node->GetNodeTM(0) * tm; + if (ltm.IsIdentity()) { retval = StaticCast<bhkShape>(shape); } else { + ltm.SetTrans(ltm.GetTrans() / Exporter::bhkScaleFactor); + bhkTransformShapeRef transform = new bhkTransformShape(); - transform->SetTransform(TOMATRIX4(tm).Transpose()); + transform->SetTransform(TOMATRIX4(ltm).Transpose()); transform->SetShape(shape); transform->SetMaterial(HavokMaterial(material)); retval = StaticCast<bhkShape>(transform); @@ -1106,15 +1172,17 @@ bhkShapeRef Exporter::makeModSphereShape(INode *node, Modifier* mod, Mesh& mesh, shape->SetRadius(radius / Exporter::bhkScaleFactor); shape->SetMaterial(HavokMaterial(material)); - Matrix3 tm = /*GetLocalTM(node) * */TransMatrix(center/Exporter::bhkScaleFactor); - if (tm.IsIdentity()) + Matrix3 ltm = TransMatrix(center) * node->GetObjTMAfterWSM(0) * tm; + if (ltm.IsIdentity()) { retval = StaticCast<bhkShape>(shape); } else { + ltm.SetTrans(ltm.GetTrans() / Exporter::bhkScaleFactor); + bhkTransformShapeRef transform = new bhkTransformShape(); - transform->SetTransform(TOMATRIX4(tm).Transpose()); + transform->SetTransform(TOMATRIX4(ltm).Transpose()); transform->SetShape(shape); transform->SetMaterial(HavokMaterial(material)); retval = StaticCast<bhkShape>(transform); @@ -1130,6 +1198,7 @@ bhkShapeRef Exporter::makeModCapsuleShape(INode *node, Modifier* mod, Mesh& mesh enum { bv_type_none, bv_type_box, bv_type_sphere, bv_type_capsule, bv_type_shapes, bv_type_convex, }; // pblock ID int material = NP_DEFAULT_HVK_MATERIAL; + node->EvalWorldState(0); if (IParamBlock2* pblock2 = mod->GetParamBlockByID(havok_params)) { pblock2->GetValue(PB_MATERIAL, 0, material, FOREVER, 0); @@ -1150,15 +1219,17 @@ bhkShapeRef Exporter::makeModCapsuleShape(INode *node, Modifier* mod, Mesh& mesh shape->SetSecondPoint(TOVECTOR3(center/Exporter::bhkScaleFactor)); shape->SetMaterial(HavokMaterial(material)); - Matrix3 tm = /*GetLocalTM(node) * */TransMatrix(center/Exporter::bhkScaleFactor); - if (tm.IsIdentity()) + Matrix3 ltm = TransMatrix(center) * node->GetObjTMAfterWSM(0) * tm; + if (ltm.IsIdentity()) { retval = StaticCast<bhkShape>(shape); } else { + ltm.SetTrans(ltm.GetTrans() / Exporter::bhkScaleFactor); + bhkTransformShapeRef transform = new bhkTransformShape(); - transform->SetTransform(TOMATRIX4(tm).Transpose()); + transform->SetTransform(TOMATRIX4(ltm).Transpose()); transform->SetShape(shape); transform->SetMaterial(HavokMaterial(material)); retval = StaticCast<bhkShape>(transform); @@ -1174,8 +1245,10 @@ bhkShapeRef Exporter::makeModConvexShape(INode *node, Modifier* mod, Mesh& mesh, enum { bv_type_none, bv_type_box, bv_type_sphere, bv_type_capsule, bv_type_shapes, bv_type_convex, }; // pblock ID int material = NP_DEFAULT_HVK_MATERIAL; + Matrix3 ltm = node->GetObjTMAfterWSM(0) * tm; + bhkShapeRef shape; - if (bhkConvexVerticesShapeRef convShape = makeConvexShape(mesh, tm)) + if (bhkConvexVerticesShapeRef convShape = makeConvexShape(mesh, ltm)) { if (IParamBlock2* pblock2 = mod->GetParamBlockByID(havok_params)) { @@ -1194,8 +1267,10 @@ bhkShapeRef Exporter::makeModTriStripShape(INode *node, Modifier* mod, Mesh& mes enum { bv_type_none, bv_type_box, bv_type_sphere, bv_type_capsule, bv_type_shapes, bv_type_convex, }; // pblock ID int material = NP_DEFAULT_HVK_MATERIAL; + Matrix3 ltm = node->GetObjTMAfterWSM(0) * tm; + bhkShapeRef shape; - if (bhkNiTriStripsShapeRef trishape = makeTriStripsShape(mesh, tm)) + if (bhkNiTriStripsShapeRef trishape = makeTriStripsShape(mesh, ltm)) { trishape->SetMaterial(HavokMaterial(material)); if (IParamBlock2* pblock2 = mod->GetParamBlockByID(havok_params)) diff --git a/NifExport/Exporter.h b/NifExport/Exporter.h index 16aafb0..580f3aa 100755 --- a/NifExport/Exporter.h +++ b/NifExport/Exporter.h @@ -9,6 +9,7 @@ namespace Niflib class bhkConvexVerticesShape; class bhkNiTriStripsShape; + class bhkPackedNiTriStripsShape; } using namespace Niflib; @@ -41,6 +42,16 @@ public: MULTI_KF_WO_NIF = 5, NIF_WITH_MGR = 6, }; + enum AccumType + { + AT_NONE = 0, + AT_X = 0x01, + AT_Y = 0x02, + AT_Z = 0x04, + + AT_XYZ = AT_X | AT_Y | AT_Z, + AT_FORCE = 0x80000000, + }; // Callback for post-processing instructions struct NiCallback @@ -244,6 +255,7 @@ public: Ref<bhkConvexVerticesShape> makeConvexShape(Mesh& mesh, Matrix3& tm); Ref<bhkNiTriStripsShape> makeTriStripsShape(Mesh& mesh, Matrix3& sm); + Ref<bhkPackedNiTriStripsShape> makePackedTriStripsShape(Mesh& mesh, Matrix3& sm); bhkShapeRef makeProxyShape(INode *node, Object *obj, Matrix3& tm); bhkShapeRef makeProxyBoxShape(INode *node, Object *obj, Mesh& mesh, Matrix3& tm); diff --git a/NifExport/Mesh.cpp b/NifExport/Mesh.cpp index 9ce3def..a101973 100755 --- a/NifExport/Mesh.cpp +++ b/NifExport/Mesh.cpp @@ -325,6 +325,10 @@ bool Exporter::splitMesh(INode *node, Mesh& mesh, FaceGroups &grps, TimeValue t, grp.uvs.resize(nv); grp.vnorms.resize(nv); + Matrix3 texm; + getTextureMatrix(texm, getMaterial(node, 0)); + texm *= flip; + for (int face=0; face<nf; ++face) { for (int vi=0; vi<3; ++vi) { int idx = mesh.faces[face].getVert(vi); @@ -341,21 +345,25 @@ bool Exporter::splitMesh(INode *node, Mesh& mesh, FaceGroups &grps, TimeValue t, else norm = getVertexNormal(&mesh, face, mesh.getRVertPtr(idx)); #endif + Point3 uv; + if (mesh.tVerts && mesh.tvFace) { + uv = mesh.tVerts[ mesh.tvFace[ face ].t[ vi ]] * texm; + uv.y += 1.0f; + } + if (grp.vidx[idx] == idx){ ASSERT(grp.verts[idx] == TOVECTOR3(mesh.getVert(idx))); //ASSERT(vg.norm == norm); - Point3 uv = mesh.getTVert(idx); + //Point3 uv = mesh.getTVert(idx); if (mesh.getNumTVerts() > 0) { - uv.y = -uv.y; ASSERT(grp.uvs[idx].u == uv.x && grp.uvs[idx].v == uv.y); } } else { grp.vidx[idx] = idx; grp.verts[idx] = TOVECTOR3(mesh.getVert(idx)); - Point3 uv = (mesh.getNumTVerts() > 0) ? mesh.getTVert(idx) : Point3(0.0f,0.0f,0.0f); grp.uvs[idx].u = uv.x; - grp.uvs[idx].v = -uv.y; + grp.uvs[idx].v = uv.y; grp.vnorms[idx] = TOVECTOR3(norm); } } diff --git a/NifExport/Util.cpp b/NifExport/Util.cpp index 4e25720..f5a0a24 100755 --- a/NifExport/Util.cpp +++ b/NifExport/Util.cpp @@ -118,10 +118,8 @@ NiNodeRef Exporter::getNode(INode* maxNode) NodeToNodeMap::iterator itr = mNodeMap.find(maxNode); if (itr != mNodeMap.end()) return (*itr).second; - NiNodeRef node = CreateNiObject<NiNode>(); - node->SetName(name); + NiNodeRef node = getNode(name); mNodeMap[maxNode] = node; - mNameMap[name] = node; return node; } NiNodeRef Exporter::getNode(const string& name) @@ -150,14 +148,11 @@ NiNodeRef Exporter::makeNode(NiNodeRef &parent, INode *maxNode, bool local) exportUPB(node, maxNode); - if (node->GetParent() == NULL) { + // Normal Embedded Animation + if (mExportType == NIF_WO_KF) + CreateController(maxNode, Interval()); - // Normal Embedded Animation - if (mExportType == NIF_WO_KF) - CreateController(maxNode, Interval()); - - parent->AddChild(DynamicCast<NiAVObject>(node)); - } + parent->AddChild(DynamicCast<NiAVObject>(node)); return node; } @@ -492,7 +487,7 @@ void Exporter::getChildNodes(INode *node, vector<NiNodeRef>& list) } if (addBone) { - list.push_back( getNode(child->GetName()) ); + list.push_back( getNode(child) ); } getChildNodes(child, list); } @@ -502,7 +497,7 @@ void Exporter::getChildNodes(INode *node, vector<NiNodeRef>& list) bool Exporter::exportPrn(NiNodeRef &obj, INode *node) { // Export Prn Text strings for any parent bones if parent is root - if (mSupportPrnStrings) { + if (mSupportPrnStrings && Exporter::mNifVersionInt >= VER_10_0_1_0) { if (INode *parentNode = node->GetParentNode()){ string parentName = parentNode->GetName(); NiStringExtraDataRef strings = new NiStringExtraData(); diff --git a/NifImport/ImportAnimation.cpp b/NifImport/ImportAnimation.cpp index edbead6..71d404f 100644 --- a/NifImport/ImportAnimation.cpp +++ b/NifImport/ImportAnimation.cpp @@ -115,9 +115,12 @@ bool NifImporter::ImportAnimation() if (nodes.empty()) return false; - NiNodeRef rootNode = root; AnimationImport ai(*this); - return ai.AddValues(DynamicCast<NiObjectNET>(rootNode->GetChildren())); + vector<NiObjectNETRef> roots; + roots.push_back(root); + return ai.AddValues(roots); + //NiNodeRef rootNode = root; + //return ai.AddValues(DynamicCast<NiObjectNET>(rootNode->GetChildren())); } static vector<ControllerLink>::iterator FindLink(string name, vector<ControllerLink>& links) @@ -360,13 +363,18 @@ bool NifImporter::AddNoteTracks(float time, string name, string target, NiTextKe if (args.empty()) continue; bool hasName = false; bool hasLoop = false; + bool hasAt = false; for (stringlist::iterator itr = args.begin(); itr != args.end(); ++itr) { if (strmatch("-name", *itr)) { if (++itr == args.end()) break; hasName = true; } else if (strmatch("-loop", *itr)) { hasLoop = true; - } + } else if (strmatch("-at", *itr)) { + if (++itr == args.end()) break; + hasAt = true; + } + } if (!hasName) { if (name.empty()) @@ -377,6 +385,10 @@ bool NifImporter::AddNoteTracks(float time, string name, string target, NiTextKe if (!hasLoop && loop) { args.push_back("-loop"); } + if (!hasAt) { + args.push_back("-at"); + args.push_back("y"); + } string line = JoinCommandLine(args); NoteKey *key = new NoteKey(t, line.c_str(), 0); @@ -417,13 +429,17 @@ bool NifImporter::AddNoteTracks(float time, string name, string target, NiTextKe if (args.empty()) continue; bool hasName = false; bool hasLoop = loop; + bool hasAt = false; for (stringlist::iterator itr = args.begin(); itr != args.end(); ++itr) { if (strmatch("-name", *itr)) { if (++itr == args.end()) break; hasName = true; } else if (strmatch("-loop", *itr)) { hasLoop = true; - } + } else if (strmatch("-at", *itr)) { + if (++itr == args.end()) break; + hasAt = true; + } } if (!hasName) { string name = FormatString("EMPTY_SEQUENCE_AT_%df", int(t * FramesPerSecond / TicksPerFrame) ); @@ -433,7 +449,10 @@ bool NifImporter::AddNoteTracks(float time, string name, string target, NiTextKe if (!hasLoop) { args.push_back("-loop"); } - + if (!hasAt) { + args.push_back("-at"); + args.push_back("y"); + } string line = JoinCommandLine(args); script += FormatText("addNoteKey nt (%d/ticksPerFrame) \"%s\"\n", t, line.c_str()); } else { diff --git a/NifImport/ImportCollision.cpp b/NifImport/ImportCollision.cpp index 6400a53..27d9994 100644 --- a/NifImport/ImportCollision.cpp +++ b/NifImport/ImportCollision.cpp @@ -52,7 +52,7 @@ struct CollisionImport void AddShape(INode *rbody, INode *shapeNode); bool ImportRigidBody(bhkRigidBodyRef rb, INode* node); - INode *CreateRigidBody(bhkRigidBodyRef body, INode* parent); + INode *CreateRigidBody(bhkRigidBodyRef body, INode* parent, Matrix3& tm); bool ImportBase(bhkRigidBodyRef body, bhkShapeRef shape, INode* parent, INode *shapeNode, Matrix3& tm); bool ImportShape(INode *rbody, bhkRigidBodyRef body, bhkShapeRef shape, INode* parent, Matrix3& tm); @@ -103,9 +103,9 @@ bool NifImporter::ImportCollision(NiNodeRef node) } CollisionImport ci(*this); - if (INode *body = ci.CreateRigidBody(rbody, node)) + Matrix3 tm(true); + if (INode *body = ci.CreateRigidBody(rbody, node, tm)) { - Matrix3 tm(true); if (!ci.ImportShape(body, rbody, shape, node, tm)) { gi->DeleteNode(body, FALSE); @@ -156,7 +156,7 @@ bool CollisionImport::ImportRigidBody(bhkRigidBodyRef body, INode* node) return true; } -INode* CollisionImport::CreateRigidBody(bhkRigidBodyRef body, INode *parent) +INode* CollisionImport::CreateRigidBody(bhkRigidBodyRef body, INode *parent, Matrix3& tm) { INode *rbody = NULL; if (body == NULL) @@ -179,31 +179,40 @@ INode* CollisionImport::CreateRigidBody(bhkRigidBodyRef body, INode *parent) SimpleObject2* listObj = (SimpleObject2*)ni.gi->CreateInstance(HELPER_CLASS_ID, BHKLISTOBJECT_CLASS_ID); if (listObj != NULL) { + bool isTransform = false; if (bhkRigidBodyInterface *irb = (bhkRigidBodyInterface *)listObj->GetInterface(BHKRIGIDBODYINTERFACE_DESC)) { - body->SetLayer(lyr); - //body->SetLayerCopy(lyr); - body->SetMotionSystem(msys); - body->SetQualityType(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); - body->SetCenter(center); + irb->SetLayer(lyr, 0); + //irb->SetLayerCopy(lyr, 0); + irb->SetMotionSystem(msys, 0); + irb->SetQualityType(qtype, 0); + irb->SetMass(mass, 0); + irb->SetLinearDamping(lindamp, 0); + irb->SetAngularDamping(angdamp, 0); + irb->SetFriction(frict, 0); + irb->SetRestitution(resti, 0); + irb->SetMaxLinearVelocity(maxlinvel, 0); + irb->SetMaxAngularVelocity(maxangvel, 0); + irb->SetPenetrationDepth(pendepth, 0); + //irb->SetCenter(center); + + isTransform = (body->IsDerivedType(bhkRigidBodyT::TYPE)); + irb->SetEnableTransform(isTransform ? TRUE : FALSE, 0); } - RefTargetHandle t = listObj->GetReference(0); - 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); + Point3 pos = TOPOINT3(body->GetTranslation()* ni.bhkScaleFactor); + Quat q = TOQUAT(body->GetRotation(), true); + PosRotScaleNode(n, pos, q, 1.0f, prsDefault); rbody = n; + if (isTransform) { + Matrix3 qm(true); + q.MakeMatrix(qm); + qm.Translate(pos); + tm *= qm; + //tm *= TransMatrix(pos); + } } } @@ -230,12 +239,6 @@ bool CollisionImport::ImportBase(bhkRigidBodyRef body, bhkShapeRef shape, INode* { shapeNode->SetName( TSTR(shape->GetType().GetTypeName().c_str()) ); - //ImportRigidBody(body, shapeNode); - - //Point3 pos = TOPOINT3(body->GetTranslation()) / ni.bhkScaleFactor; - //Quat rot = TOQUAT(body->GetRotation()); - //PosRotScaleNode(shapeNode, pos, rot, 1.0, prsDefault); - if (!tm.IsIdentity()) { Point3 pos = tm.GetTrans(); @@ -505,12 +508,12 @@ extern vector<Triangle> compute_convex_hull(const vector<Vector3>& verts); bool CollisionImport::ImportConvexVertices(INode *rbody, bhkRigidBodyRef body, bhkConvexVerticesShapeRef shape, INode *parent, Matrix3& tm) { + Matrix3 ltm(true); INode *returnNode = NULL; 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, tm, parent); + returnNode = ImportCollisionMesh(verts, tris, norms, ltm, parent); CreatebhkCollisionModifier(returnNode, bv_type_convex, shape->GetMaterial()); ImportBase(body, shape, parent, returnNode, tm); @@ -528,9 +531,6 @@ bool CollisionImport::ImportTriStripsShape(INode *rbody, bhkRigidBodyRef body, b TriObject *triObject = CreateNewTriObject(); node->Reference(triObject); - //string name = shape->GetName(); - //node->SetName(name.c_str()); - INode *inode = node->GetINode(); // Texture @@ -541,18 +541,8 @@ bool CollisionImport::ImportTriStripsShape(INode *rbody, bhkRigidBodyRef body, b // Temporary shape NiTriStripsRef triShape = new NiTriStrips(); - Point3 pos = TOPOINT3(body->GetTranslation()) / ni.bhkScaleFactor; - triShape->SetLocalTranslation( TOVECTOR3(pos) ); - - Quat rot = TOQUAT(body->GetRotation()); - Matrix3 mat; - rot.MakeMatrix(mat, false); - triShape->SetLocalRotation( TOMATRIX33(mat, false) ); - - vector<Triangle> tris = triShapeData->GetTriangles(); ni.ImportMesh(node, triObject, triShape, triShapeData, tris); - CreatebhkCollisionModifier(inode, bv_type_shapes, shape->GetMaterial()); ImportBase(body, shape, parent, inode, tm); AddShape(rbody, inode); @@ -564,12 +554,6 @@ bool CollisionImport::ImportTriStripsShape(INode *rbody, bhkRigidBodyRef body, b bool CollisionImport::ImportMoppBvTreeShape(INode *rbody, bhkRigidBodyRef body, bhkMoppBvTreeShapeRef shape, INode *parent, Matrix3& tm) { bool retval = ImportShape(rbody, body, shape->GetShape(), parent, tm); - //if (shapes.Count() > 0) { - // for (int i=0, n=shapes.Count(); i<n; ++i) - // { - // npSetProp(shapes[i], NP_HVK_MATERIAL, shape->GetMaterial()); - // } - //} return retval; } @@ -577,18 +561,14 @@ 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); - + Matrix3 ltm(true); vector<Vector3> verts = data->GetVertices(); vector<Triangle> tris = data->GetTriangles(); vector<Vector3> norms = data->GetNormals(); INode *inode = ImportCollisionMesh(verts, tris, norms, tm, parent); CreatebhkCollisionModifier(inode, bv_type_shapes, HavokMaterial(NP_DEFAULT_HVK_MATERIAL)); - ImportBase(body, shape, parent, inode, tm); + ImportBase(body, shape, parent, inode, ltm); AddShape(rbody, inode); return true; } @@ -610,11 +590,6 @@ bool CollisionImport::ImportListShape(INode *rbody, bhkRigidBodyRef body, bhkLis vector<Ref<bhkShape > > bhkshapes = shape->GetSubShapes(); for (int i = 0, n = bhkshapes.size(); i<n; ++i) { ok |= ImportShape(rbody, body, bhkshapes[i], parent, tm); - //if (shapes.Count() > 0) { - // for (int i=0, n=shapes.Count(); i<n; ++i) { - // npSetProp(shapes[i], NP_HVK_MATERIAL, shape->GetMaterial()); - // } - //} } return ok; } @@ -624,10 +599,9 @@ bool CollisionImport::ImportTransform(INode *rbody, bhkRigidBodyRef body, bhkTra Matrix44 m4 = shape->GetTransform().Transpose(); Vector3 trans; Matrix33 rot; float scale; m4.Decompose(trans, rot, scale); - Matrix3 wm = tm - * TransMatrix(TOPOINT3(trans * ni.bhkScaleFactor)) - * TOMATRIX3(rot) - * ScaleMatrix(Point3(scale, scale, scale)) - ; + Matrix3 wm = TOMATRIX3(rot); + wm.Translate(TOPOINT3(trans) * ni.bhkScaleFactor); + wm *= ScaleMatrix(Point3(scale, scale, scale)); + wm = wm * tm; return ImportShape(rbody, body, shape->GetShape(), parent, wm); } \ No newline at end of file diff --git a/NifImport/NIFImport.cpp b/NifImport/NIFImport.cpp index c668025..93b4718 100644 --- a/NifImport/NIFImport.cpp +++ b/NifImport/NIFImport.cpp @@ -331,10 +331,10 @@ bool NifImporter::DoImport() if (root->IsDerivedType(NiNode::TYPE)) { NiNodeRef rootNode = root; - RegisterNode(root, gi->GetRootNode()); if (importBones) { if (ignoreRootNode || strmatch(rootNode->GetName(), "Scene Root")) { + RegisterNode(root, gi->GetRootNode()); ImportBones(DynamicCast<NiNode>(rootNode->GetChildren())); } else { ImportBones(rootNode); diff --git a/NifPlugins_VC80.sln b/NifPlugins_VC80.sln index 6cc5564..8124748 100644 --- a/NifPlugins_VC80.sln +++ b/NifPlugins_VC80.sln @@ -16,6 +16,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NifPlugins", "NifPlugins_VC {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E} = {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NifCmd", "..\contrib\niflib\NifCmd\NifCmd_VC80.vcproj", "{3976526D-2906-443B-B716-95E3915A7CBE}" + ProjectSection(ProjectDependencies) = postProject + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E} = {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug - gmax|Win32 = Debug - gmax|Win32 @@ -152,6 +157,54 @@ Global {466F2D3E-2663-4583-A05C-128683677617}.Release - Max 9|Win32.Build.0 = Release - Max 9|Win32 {466F2D3E-2663-4583-A05C-128683677617}.Release - Max 9|x64.ActiveCfg = Release - Max 9|x64 {466F2D3E-2663-4583-A05C-128683677617}.Release - Max 9|x64.Build.0 = Release - Max 9|x64 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - gmax|Win32.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - gmax|Win32.Build.0 = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - gmax|x64.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 4.2|Win32.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 4.2|Win32.Build.0 = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 4.2|x64.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 4|Win32.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 4|Win32.Build.0 = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 4|x64.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 5|Win32.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 5|Win32.Build.0 = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 5|x64.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 6|Win32.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 6|Win32.Build.0 = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 6|x64.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 7|Win32.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 7|Win32.Build.0 = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 7|x64.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 8|Win32.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 8|Win32.Build.0 = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 8|x64.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 9|Win32.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 9|Win32.Build.0 = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Debug - Max 9|x64.ActiveCfg = Debug|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - gmax|Win32.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - gmax|Win32.Build.0 = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - gmax|x64.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 4.2|Win32.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 4.2|Win32.Build.0 = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 4.2|x64.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 4|Win32.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 4|Win32.Build.0 = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 4|x64.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 5|Win32.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 5|Win32.Build.0 = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 5|x64.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 6|Win32.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 6|Win32.Build.0 = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 6|x64.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 7|Win32.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 7|Win32.Build.0 = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 7|x64.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 8|Win32.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 8|Win32.Build.0 = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 8|x64.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 9|Win32.ActiveCfg = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 9|Win32.Build.0 = Release|Win32 + {3976526D-2906-443B-B716-95E3915A7CBE}.Release - Max 9|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/NifPlugins_VC80.vcproj b/NifPlugins_VC80.vcproj index 192deaf..4c901d8 100644 --- a/NifPlugins_VC80.vcproj +++ b/NifPlugins_VC80.vcproj @@ -1709,7 +1709,7 @@ Name="VCCLCompilerTool" AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" Optimization="0" - InlineFunctionExpansion="2" + InlineFunctionExpansion="0" AdditionalIncludeDirectories="C:\3dsmax9\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;USE_BIPED;NIFLIB_STATIC_LINK" GeneratePreprocessedFile="0" @@ -5030,6 +5030,26 @@ > </File> </Filter> + <Filter + Name="Header Files" + > + <File + RelativePath=".\NifExport\Exporter.h" + > + </File> + <File + RelativePath=".\NifExport\NifExport.h" + > + </File> + <File + RelativePath=".\NifExport\pch.h" + > + </File> + <File + RelativePath=".\NifExport\resource.h" + > + </File> + </Filter> </Filter> <Filter Name="NifCommon" @@ -8854,6 +8874,10 @@ RelativePath=".\NifPlugins\pch.h" > </File> + <File + RelativePath=".\NifPlugins\resource.h" + > + </File> </Filter> <Filter Name="NifImport" @@ -8951,30 +8975,6 @@ </File> </Filter> </Filter> - <Filter - Name="Header Files" - > - <File - RelativePath=".\NifExport\Exporter.h" - > - </File> - <File - RelativePath=".\NifExport\NifExport.h" - > - </File> - <File - RelativePath=".\NifExport\pch.h" - > - </File> - <File - RelativePath=".\NifExport\resource.h" - > - </File> - </Filter> - <File - RelativePath=".\NifPlugins\resource.h" - > - </File> </Files> <Globals> </Globals> diff --git a/NifProps/bhkListObj.cpp b/NifProps/bhkListObj.cpp index 56c7cdc..e0fa4cb 100644 --- a/NifProps/bhkListObj.cpp +++ b/NifProps/bhkListObj.cpp @@ -98,6 +98,9 @@ public: BOOL OKtoDisplay(TimeValue t); void InvalidateUI(); + virtual IOResult Save(ISave *isave); + virtual IOResult Load(ILoad *iload); + int Display(TimeValue t, INode* inode, ViewExp *vpt, int flags); //int HitTest(TimeValue t, INode *inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt); @@ -571,3 +574,24 @@ int bhkListObject::Display(TimeValue t, INode* inode, ViewExp *vpt, int flags) gw->setRndLimits(rlim); return 0; } + +const USHORT kModChunkSelLevel = 0x0100; + +IOResult bhkListObject::Save(ISave *isave) +{ + IOResult res; + res = SimpleObject2::Save(isave); + if (res == IO_OK) + res = RBSave(isave); + return res; +} + +IOResult bhkListObject::Load(ILoad *iload) +{ + IOResult res; + res = SimpleObject2::Load(iload); + if (res == IO_OK) + res = RBLoad(iload); + return res; +} + diff --git a/NifProps/bhkRigidBodyInterface.cpp b/NifProps/bhkRigidBodyInterface.cpp index cd77e05..f8f338d 100644 --- a/NifProps/bhkRigidBodyInterface.cpp +++ b/NifProps/bhkRigidBodyInterface.cpp @@ -576,3 +576,30 @@ BOOL bhkRigidBodyIfcHelper::GetEnableTransform(TimeValue time, Interval& valid) rbpblock->GetValue(PB_RB_ENABLE_TRANS,time,value,valid); return value; } + +const USHORT kRBChunkSelLevel = 0x8000; +IOResult bhkRigidBodyIfcHelper::RBSave(ISave *isave) +{ + IOResult res; + + isave->BeginChunk(kRBChunkSelLevel); + res = rbpblock->Save(isave); + isave->EndChunk(); + + return res; +} + +IOResult bhkRigidBodyIfcHelper::RBLoad(ILoad *iload) +{ + IOResult res; + while (IO_OK==(res=iload->OpenChunk())) { + switch(iload->CurChunkID()) { + case kRBChunkSelLevel: + res = rbpblock->Load(iload); + break; + } + iload->CloseChunk(); + if (res!=IO_OK) return res; + } + return IO_OK; +} diff --git a/NifProps/bhkRigidBodyInterface.h b/NifProps/bhkRigidBodyInterface.h index 58ce275..97b7e22 100644 --- a/NifProps/bhkRigidBodyInterface.h +++ b/NifProps/bhkRigidBodyInterface.h @@ -179,6 +179,9 @@ public: virtual BOOL GetEnableTransform(TimeValue time, Interval& valid = FOREVER) const; virtual FPInterfaceDesc* GetDesc() { return GetbhkRigidBodyInterfaceDesc(); } + + virtual IOResult RBSave(ISave *isave); + virtual IOResult RBLoad(ILoad *iload); protected: IParamBlock* rbpblock; -- GitLab