diff --git a/NifExport/Coll.cpp b/NifExport/Coll.cpp index 76ce0971108d11a5cb223d658350e004c250ddb2..10ace05330b0f56884fc32fb844e102752a9db1c 100755 --- a/NifExport/Coll.cpp +++ b/NifExport/Coll.cpp @@ -1,5 +1,102 @@ #include "pch.h" +static Class_ID SCUBA_CLASS_ID(0x6d3d77ac, 0x79c939a9); + +enum +{ + CAPSULE_RADIUS = 0, + CAPSULE_HEIGHT = 1, +}; + + +/* +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) { for (int i=0; i<verts.size(); i++) @@ -27,7 +124,7 @@ void Exporter::addFace(Triangles &tris, vector<Vector3> &verts, vector<Vector3> } tris.push_back(tri); } - +/* bool Exporter::makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue t) { Matrix3 tm = node->GetObjTMAfterWSM(t); @@ -62,26 +159,6 @@ bool Exporter::makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue Mesh *mesh = &tri->GetMesh(); mesh->buildNormals(); - // get data from node - int lyr, mtl, msys, qtype; - float mass, lindamp, angdamp, frict, maxlinvel, maxangvel, resti, pendepth; - Vector3 center; - - 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_MASS, mass, NP_DEFAULT_HVK_MASS); - 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_FRICTION, frict, NP_DEFAULT_HVK_FRICTION); - npGetProp(node, NP_HVK_RESTITUTION, resti, NP_DEFAULT_HVK_RESTITUTION); - 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); - - // setup shape data vector<Vector3> verts; vector<Vector3> vnorms; @@ -160,3 +237,246 @@ bool Exporter::makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue return true; } +*/ + +Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node) +{ + // marked as collision? + NiNodeRef newParent; + if (npIsCollision(node)) + { +/* NiNodeRef n = DynamicCast<NiNode>(CreateBlock("NiNode")); + parent->AddChild(DynamicCast<NiAVObject>(n)); + + Matrix33 rot; + Vector3 trans; + TimeValue t = 0; + nodeTransform(rot, trans, node, t); + n->SetLocalRotation(rot); + n->SetLocalTranslation(trans); + string name = (char*)node->GetName(); + n->SetName(name); + + +/* Vector3 trans; + QuaternionXYZW q; + TimeValue t = 0; + nodeTransform(q, trans, node, t, false); + body->SetRotation(q); + body->SetTranslation(Vector3(trans.x/7, trans.y/7, trans.z/7)); +*/ + newParent = makeNode(parent, node); + + bhkSphereRepShapeRef shape = makeCollisionShape(node); + bhkRigidBodyRef body = makeCollisionBody(node); + body->SetShape(DynamicCast<bhkShape>(shape)); + + bhkCollisionObjectRef co = DynamicCast<bhkCollisionObject>(CreateBlock("bhkCollisionObject")); + co->SetBody(DynamicCast<NiObject>(body)); + co->SetParent(newParent); + + // link + newParent->SetCollisionObject(DynamicCast<NiCollisionObject>(co)); + + } else + if (node->IsGroupHead()) + { + newParent = makeNode(parent, node); + } else + newParent = parent; + + 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, mtl, msys, qtype; + float mass, lindamp, angdamp, frict, maxlinvel, maxangvel, resti, pendepth; + Vector3 center; + + 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_MASS, mass, NP_DEFAULT_HVK_MASS); + 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_FRICTION, frict, NP_DEFAULT_HVK_FRICTION); + npGetProp(node, NP_HVK_RESTITUTION, resti, NP_DEFAULT_HVK_RESTITUTION); + 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); + + // setup body + bhkRigidBodyRef body = DynamicCast<bhkRigidBody>(CreateBlock("bhkRigidBody")); + + 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); + + return body; +} + +bhkSphereRepShapeRef Exporter::makeCollisionShape(INode *node) +{ + bhkSphereRepShapeRef shape; + + TimeValue t = 0; + ObjectState os = node->EvalWorldState(t); + if (os.obj->ClassID() == SCUBA_CLASS_ID) + shape = makeCapsuleShape(os.obj); + else + if (os.obj->ClassID() == Class_ID(BOXOBJ_CLASS_ID, 0)) + shape = makeBoxShape(os.obj); + else + if (os.obj->ClassID() == Class_ID(SPHERE_CLASS_ID, 0)) + shape = makeSphereShape(os.obj); + else + if (os.obj->SuperClassID() == GEOMOBJECT_CLASS_ID) + shape = makeTriStripsShape(node); + + if (shape) + { + int mtl; + npGetProp(node, NP_HVK_MATERIAL, mtl, NP_DEFAULT_HVK_MATERIAL); + shape->SetMaterial(mtl); + } + + return shape; +} + +bhkSphereRepShapeRef Exporter::makeBoxShape(Object *obj) +{ + float length = 0; + float height = 0; + float width = 0; + IParamArray *params = obj->GetParamBlock(); + params->GetValue(obj->GetParamBlockIndex(BOXOBJ_LENGTH), 0, length, FOREVER); + params->GetValue(obj->GetParamBlockIndex(BOXOBJ_HEIGHT), 0, height, FOREVER); + params->GetValue(obj->GetParamBlockIndex(BOXOBJ_WIDTH), 0, width, FOREVER); + + bhkBoxShapeRef box = DynamicCast<bhkBoxShape>(CreateBlock("bhkBoxShape")); + box->SetDimensions(Vector3(width, height, length)); + + return bhkSphereRepShapeRef(DynamicCast<bhkSphereRepShape>(box)); +} + +bhkSphereRepShapeRef Exporter::makeSphereShape(Object *obj) +{ + float radius = 0; + IParamArray *params = obj->GetParamBlock(); + params->GetValue(obj->GetParamBlockIndex(SPHERE_RADIUS), 0, radius, FOREVER); + + bhkSphereShapeRef sphere = DynamicCast<bhkSphereShape>(CreateBlock("bhkSphereShape")); + sphere->SetRadius(radius); + + return bhkSphereRepShapeRef(DynamicCast<bhkSphereRepShape>(sphere)); +} + +bhkSphereRepShapeRef Exporter::makeCapsuleShape(Object *obj) +{ + 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); + + bhkCapsuleShapeRef capsule = DynamicCast<bhkCapsuleShape>(CreateBlock("bhkCapsuleShape")); + + return bhkSphereRepShapeRef(DynamicCast<bhkSphereRepShape>(capsule)); +} + +bhkSphereRepShapeRef Exporter::makeTriStripsShape(INode *node) +{ + TimeValue t = 0; + Matrix3 tm = node->GetObjTMAfterWSM(t); + + // Order of the vertices. Get 'em counter clockwise if the objects is + // negatively scaled. + int vi[3]; + if (TMNegParity(tm)) + { + vi[0] = 2; + vi[1] = 1; + vi[2] = 0; + } else + { + vi[0] = 0; + vi[1] = 1; + vi[2] = 2; + } + + ObjectState os = node->EvalWorldState(t); + + TriObject *tri = (TriObject *)os.obj->ConvertToType(t, Class_ID(TRIOBJ_CLASS_ID, 0)); + if (!tri) + return false; + + Mesh *mesh = &tri->GetMesh(); + mesh->buildNormals(); + + // setup shape data + vector<Vector3> verts; + vector<Vector3> vnorms; + Triangles tris; + + for (int i=0; i<mesh->getNumFaces(); i++) + addFace(tris, verts, vnorms, i, vi, mesh); + + TriStrips strips; + strippify(strips, verts, vnorms, tris); + NiTriStripsDataRef data = makeTriStripsData(strips); + data->SetVertices(verts); + data->SetNormals(vnorms); + + // setup shape + bhkNiTriStripsShapeRef shape = DynamicCast<bhkNiTriStripsShape>(CreateBlock("bhkNiTriStripsShape")); + shape->SetNumStripsData(1); + shape->SetStripsData(0, data); +/* + array<float, 2> unknownFloats1; + uint i1 = 0x3DCCCCCD; + uint i2 = 0x004ABE60; + unknownFloats1[0] = *((float*)&i1); + unknownFloats1[1] = *((float*)&i2); + shape->SetUnknownFloats1(unknownFloats1); + + array<float, 3> unknownFloats2; + unknownFloats2[0] = 1; + unknownFloats2[1] = 1; + unknownFloats2[2] = 1; + shape->SetUnknownFloats2(unknownFloats2); +*/ +/* array<uint, 5> unknownInts1; + unknownInts1[4] = 1; + shape->SetUnknownInts1(unknownInts1); +*/ + vector<uint> unknownInts2; + unknownInts2.resize(1); + shape->SetUnknownInts2(unknownInts2); + + if (tri != os.obj) + tri->DeleteMe(); + + return bhkSphereRepShapeRef(DynamicCast<bhkSphereRepShape>(shape)); +} diff --git a/NifExport/Exporter.cpp b/NifExport/Exporter.cpp index dfb713e267792f9a7b52a0e1764323e4d1faf4bd..e60f07f28f3ed8c426b912e7931a6f03a1d3de5c 100755 --- a/NifExport/Exporter.cpp +++ b/NifExport/Exporter.cpp @@ -32,10 +32,25 @@ Exporter::Result Exporter::export(NiNodeRef &root, INode *node) root->AddExtraData(DynamicCast<NiExtraData>(strings)); mNiRoot = root; - return exportTree(root, node); + + Result result; + result = exportMeshes(root, node); + if (result != Ok) + return result; + + if (mExportCollision) + { + + result = exportCollision(root, node); + if (result != Ok) + return result; + } + return Ok; } -Exporter::Result Exporter::exportTree(NiNodeRef &parent, INode *node) +#if 0 + +Exporter::Result Exporter::exportMeshes(NiNodeRef &parent, INode *node) { bool coll = npIsCollision(node); if ((coll && !mExportCollision) || @@ -60,26 +75,65 @@ Exporter::Result Exporter::exportTree(NiNodeRef &parent, INode *node) parent = n; } + Result result; ObjectState os = node->EvalWorldState(t); - - Result result; if (os.obj) { // We look at the super class ID to determine the type of the object. switch(os.obj->SuperClassID()) { case GEOMOBJECT_CLASS_ID: - if (!coll) +/* if (os.obj->ClassID() == SCUBA_CLASS_ID) { - result = exportMesh(parent, node, t); - if (result != Ok) - return result; + float radius = 0; + float height = 0; + IParamArray *params = os.obj->GetParamBlock(); + params->GetValue(os.obj->GetParamBlockIndex(CAPSULE_RADIUS), 0, radius, FOREVER); + params->GetValue(os.obj->GetParamBlockIndex(CAPSULE_HEIGHT), 0, height, FOREVER); + + int foo=1+2; } else + if (os.obj->ClassID() == Class_ID(BOXOBJ_CLASS_ID, 0)) { - if (!makeCollisionHierarchy(mNiRoot, node, t)) - return Error; + float length = 0; + float height = 0; + float width = 0; + + IParamArray *params = os.obj->GetParamBlock(); + params->GetValue(os.obj->GetParamBlockIndex(BOXOBJ_LENGTH), 0, length, FOREVER); + params->GetValue(os.obj->GetParamBlockIndex(BOXOBJ_HEIGHT), 0, height, FOREVER); + params->GetValue(os.obj->GetParamBlockIndex(BOXOBJ_WIDTH), 0, width, FOREVER); + + int foo=1+2; + + } else + if (os.obj->ClassID() == Class_ID(SPHERE_CLASS_ID, 0)) + { + float radius = 0; + + IParamArray *params = os.obj->GetParamBlock(); + params->GetValue(os.obj->GetParamBlockIndex(SPHERE_RADIUS), 0, radius, FOREVER); + + int foo=1+2; + + } else + { +*/ + if (!coll) + { + + result = exportMesh(parent, node, t); + if (result != Ok) + return result; + } /*else + { + + if (!makeCollisionHierarchy(mNiRoot, node, t)) + return Error; + } } +*/ break; /* case CAMERA_CLASS_ID: @@ -101,7 +155,7 @@ Exporter::Result Exporter::exportTree(NiNodeRef &parent, INode *node) for (int i=0; i<node->NumberOfChildren(); i++) { - Result result = exportTree(parent, node->GetChildNode(i)); + Result result = exportMeshes(parent, node->GetChildNode(i)); if (result!=Ok && result!=Skip) return result; } @@ -111,3 +165,5 @@ Exporter::Result Exporter::exportTree(NiNodeRef &parent, INode *node) return Ok; } + +#endif diff --git a/NifExport/Exporter.h b/NifExport/Exporter.h index 34d045746270bdc7a8ea58a858091e4490a46609..3154d3b0a57327c7e3692a329e01ec953038edc2 100755 --- a/NifExport/Exporter.h +++ b/NifExport/Exporter.h @@ -19,24 +19,24 @@ public: }; /* exporter version */ - static int mVersion; + static int mVersion; /* export options, static for dialog usage. */ - static bool mSelectedOnly; - static bool mTriStrips; - static bool mExportHidden; - static bool mExportFurn; - static bool mExportLights; - static string mTexPrefix; - static bool mVertexColors; - static float mWeldThresh; - static bool mExportCollision; - static bool mRemapIndices; + static bool mSelectedOnly; + static bool mTriStrips; + static bool mExportHidden; + static bool mExportFurn; + static bool mExportLights; + static string mTexPrefix; + static bool mVertexColors; + static float mWeldThresh; + static bool mExportCollision; + static bool mRemapIndices; Exporter(Interface *i); - Result export(NiNodeRef &root, INode *node); + Result export(NiNodeRef &root, INode *node); /* config is written to the registry and the root node of the scene, so that it is restored when opening it @@ -44,14 +44,14 @@ public: use the settings stored in the registry. */ // writes config to root node - static void writeConfig(INode *node); + static void writeConfig(INode *node); // writes config to registry - static void writeConfig(); + static void writeConfig(); // reads config from root node - static void readConfig(INode *node); + static void readConfig(INode *node); // reads config from registry - static void readConfig(); + static void readConfig(); private: @@ -71,51 +71,63 @@ private: // maps face groups to material ID typedef std::map<int, FaceGroup> FaceGroups; - Interface *mI; - NiNodeRef mNiRoot; + Interface *mI; + NiNodeRef mNiRoot; - Result exportTree(NiNodeRef &root, INode *node); + Result exportCollision(NiNodeRef &root, INode *node); + Result exportMeshes(NiNodeRef &root, INode *node); /* utility functions */ - Mtl *getMaterial(INode *node, int subMtl); - bool TMNegParity(const Matrix3 &m); - void convertMatrix(Matrix33 &dst, const Matrix3 &src); - void nodeTransform(Matrix33 &rot, Vector3 &trans, INode *node, TimeValue t, bool local=true); - void nodeTransform(QuaternionXYZW &rot, Vector3 &trans, INode *node, TimeValue t, bool local=true); - Point3 getVertexNormal(Mesh* mesh, int faceNo, RVertex* rv); - bool equal(const Vector3 &a, const Point3 &b, float thresh); - BitmapTex *getTexture(Mtl *mtl); - void getTextureMatrix(Matrix3 &mat, Mtl *mtl); + Mtl *getMaterial(INode *node, int subMtl); + bool TMNegParity(const Matrix3 &m); + void convertMatrix(Matrix33 &dst, const Matrix3 &src); + void nodeTransform(Matrix33 &rot, Vector3 &trans, INode *node, TimeValue t, bool local=true); + void nodeTransform(QuaternionXYZW &rot, Vector3 &trans, INode *node, TimeValue t, bool local=true); + Point3 getVertexNormal(Mesh* mesh, int faceNo, RVertex* rv); + bool equal(const Vector3 &a, const Point3 &b, float thresh); + BitmapTex *getTexture(Mtl *mtl); + void getTextureMatrix(Matrix3 &mat, Mtl *mtl); + NiNodeRef makeNode(NiNodeRef &parent, INode *maxNode, bool local=true); /* tristrips */ - void strippify(TriStrips &strips, vector<Vector3> &verts, vector<Vector3> &norms, const Triangles &tris); - void strippify(TriStrips &strips, FaceGroup &grp); - NiTriStripsDataRef makeTriStripsData(const TriStrips &strips); + void strippify(TriStrips &strips, vector<Vector3> &verts, vector<Vector3> &norms, const Triangles &tris); + void strippify(TriStrips &strips, FaceGroup &grp); + NiTriStripsDataRef makeTriStripsData(const TriStrips &strips); /* mesh export */ // adds a vertex to a face group if it doesn't exist yet. returns new or previous index into the // vertex array. - int addVertex(FaceGroup &grp, int face, int vi, Mesh *mesh, const Matrix3 &texm); + int addVertex(FaceGroup &grp, int face, int vi, Mesh *mesh, const Matrix3 &texm); // adds a face to a face group - void addFace(FaceGroup &grp, int face, const int vi[3], Mesh *mesh, const Matrix3 &texm); + void addFace(FaceGroup &grp, int face, const int vi[3], Mesh *mesh, const Matrix3 &texm); // creates face groups from faces with same sub material id - bool splitMesh(INode *node, Mesh *, FaceGroups &grps, TimeValue t); + bool splitMesh(INode *node, Mesh *, FaceGroups &grps, TimeValue t); // creates a NiTriStrips or NiTriShape hierarchy from a face group - bool makeMesh(NiNodeRef &parent, Mtl *mtl, FaceGroup &grp); + bool makeMesh(NiNodeRef &parent, Mtl *mtl, FaceGroup &grp); // splits mesh and converts it into nif blocks - Result exportMesh(NiNodeRef &parent, INode *node, TimeValue t); + Result exportMesh(NiNodeRef &parent, INode *node, TimeValue t); /* texture & material */ // creates NiTexturingProperty + NiSourceTexture - void makeTexture(NiAVObjectRef &parent, Mtl *mtl); + void makeTexture(NiAVObjectRef &parent, Mtl *mtl); // creates a NiMaterialProperty - void makeMaterial(NiAVObjectRef &parent, Mtl *mtl); + void makeMaterial(NiAVObjectRef &parent, Mtl *mtl); /* havok & collision */ - int addVertex(vector<Vector3> &verts, vector<Vector3> &vnorms, const Point3 &pt, const Point3 &norm); - void addFace(Triangles &tris, vector<Vector3> &verts, vector<Vector3> &vnorms, - int face, const int vi[3], Mesh *mesh); - bool makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue t); + int addVertex(vector<Vector3> &verts, vector<Vector3> &vnorms, const Point3 &pt, const Point3 &norm); + void addFace(Triangles &tris, vector<Vector3> &verts, vector<Vector3> &vnorms, + int face, const int vi[3], Mesh *mesh); + bool makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue t); + + /* creates a bhkRigidBody */ + bhkRigidBodyRef makeCollisionBody(INode *node); + /* creates a collision shape from a node */ + bhkSphereRepShapeRef makeCollisionShape(INode *node); + + bhkSphereRepShapeRef makeTriStripsShape(INode *node); + bhkSphereRepShapeRef makeBoxShape(Object *obj); + bhkSphereRepShapeRef makeSphereShape(Object *obj); + bhkSphereRepShapeRef makeCapsuleShape(Object *obj); }; #endif diff --git a/NifExport/Mesh.cpp b/NifExport/Mesh.cpp index 532450056bf95aca1d8ce3f8a3a35f68fbd8ad69..2f7af6f2f6809c88202571043cddfb285867e960 100755 --- a/NifExport/Mesh.cpp +++ b/NifExport/Mesh.cpp @@ -1,39 +1,117 @@ #include "pch.h" -Exporter::Result Exporter::exportMesh(NiNodeRef &parent, INode *node, TimeValue t) +/* + +void FPUtility::GetAlphaVal(void) +{ + if(ip->GetSelNodeCount()<1)return; + INode *node = ip->GetSelNode(0); + if(!node)return; + ObjectState os = node->EvalWorldState(0); + Object *obj = os.obj; + BOOL delMesh = false; + + if (obj && obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) { + TriObject * tri = NULL; + tri = (TriObject *) obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0)); + if (obj != tri) + delMesh = true; // we own the copy + if (tri) + { + Mesh * mesh = &(tri->GetMesh()); + MeshDelta md(*mesh); + BOOL support = mesh->mapSupport(MAP_ALPHA); + if(support) + { + UVVert *alpha = mesh->mapVerts(MAP_ALPHA); + for(int i=0;igetNumVerts();i++) + { + float a = alpha[i].x; + } + } + + } + + if (delMesh) + delete tri; + } +} + +*/ + + +Exporter::Result Exporter::exportMeshes(NiNodeRef &parent, INode *node) +{ + bool coll = npIsCollision(node); + if ((coll && !mExportCollision) || + (node->IsHidden() && !mExportHidden && !coll) || + (mSelectedOnly && !node->Selected())) + return Skip; + + NiNodeRef newParent; + TimeValue t = 0; + ObjectState os = node->EvalWorldState(t); + if (!coll && os.obj && os.obj->SuperClassID()==GEOMOBJECT_CLASS_ID) + { +/* newParent = DynamicCast<NiNode>(CreateBlock("NiNode")); + parent->AddChild(DynamicCast<NiAVObject>(newParent)); + + Matrix33 rot; + Vector3 trans; + nodeTransform(rot, trans, node, t); + + newParent->SetLocalRotation(rot); + newParent->SetLocalTranslation(trans); + string name = (char*)node->GetName(); + newParent->SetName(name); +*/ + newParent = makeNode(parent, node); + + Result result; + result = exportMesh(newParent, node, t); + if (result != Ok) + return result; + + } else + if (node->IsGroupHead()) + { + newParent = makeNode(parent, node); +/* newParent = DynamicCast<NiNode>(CreateBlock("NiNode")); + Matrix33 rot; + Vector3 trans; + nodeTransform(rot, trans, node, t); + newParent->SetLocalRotation(rot); + newParent->SetLocalTranslation(trans); + string name = (char*)node->GetName(); + newParent->SetName(name); + + parent->AddChild(DynamicCast<NiAVObject>(newParent)); +*/ + } else + newParent = parent; + + for (int i=0; i<node->NumberOfChildren(); i++) + { + Result result = exportMeshes(newParent, node->GetChildNode(i)); + if (result!=Ok && result!=Skip) + return result; + } + + return Ok; +} + + +Exporter::Result Exporter::exportMesh(NiNodeRef &ninode, INode *node, TimeValue t) { ObjectState os = node->EvalWorldState(t); - if (!os.obj || os.obj->SuperClassID()!=GEOMOBJECT_CLASS_ID) - return Error; - - BOOL alloc; - Object *obj = os.obj; - if (!obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) - return Error; - TriObject *tri = (TriObject *) obj->ConvertToType(t, Class_ID(TRIOBJ_CLASS_ID, 0)); + TriObject *tri = (TriObject *)os.obj->ConvertToType(t, Class_ID(TRIOBJ_CLASS_ID, 0)); if (!tri) return Error; - if (obj != tri) - alloc = TRUE; - else - alloc = FALSE; - Mesh *mesh = &tri->GetMesh(); mesh->buildNormals(); - Matrix33 rot; - Vector3 trans; - nodeTransform(rot, trans, node, t); - - NiNodeRef ninode = DynamicCast<NiNode>(CreateBlock("NiNode")); - ninode->SetLocalRotation(rot); - ninode->SetLocalTranslation(trans); - string name = (char*)node->GetName(); - ninode->SetName(name); - parent->AddChild(DynamicCast<NiAVObject>(ninode)); - Result result = Ok; while (1) { @@ -57,7 +135,7 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &parent, INode *node, TimeValue break; } - if (alloc) + if (tri != os.obj) tri->DeleteMe(); return result; diff --git a/NifExport/NifExport.vcproj b/NifExport/NifExport.vcproj index 16d2155da5081c726ececb39456c1e63de4a9c70..82855bc3db2995497b411a2dae204ea6653d9a60 100755 --- a/NifExport/NifExport.vcproj +++ b/NifExport/NifExport.vcproj @@ -36,7 +36,7 @@ RuntimeLibrary="2" BufferSecurityCheck="FALSE" EnableFunctionLevelLinking="TRUE" - UsePrecompiledHeader="1" + UsePrecompiledHeader="0" PrecompiledHeaderThrough="pch.h" PrecompiledHeaderFile=".\Release\NifExport.pch" AssemblerListingLocation=".\Release\" diff --git a/NifExport/Util.cpp b/NifExport/Util.cpp index 39822c4d3c7c214b55e41c238d87935ae18fa1cc..2c072ce2a322886249fbfaca6bf035202d4fe71c 100755 --- a/NifExport/Util.cpp +++ b/NifExport/Util.cpp @@ -87,3 +87,21 @@ bool Exporter::equal(const Vector3 &a, const Point3 &b, float thresh) (fabsf(a.y-b.y) <= thresh) && (fabsf(a.z-b.z) <= thresh); } + +NiNodeRef Exporter::makeNode(NiNodeRef &parent, INode *maxNode, bool local) +{ + NiNodeRef node = DynamicCast<NiNode>(CreateBlock("NiNode")); + + Matrix33 rot; + Vector3 trans; + TimeValue t = 0; + nodeTransform(rot, trans, maxNode, t, local); + + node->SetLocalRotation(rot); + node->SetLocalTranslation(trans); + string name = (char*)maxNode->GetName(); + node->SetName(name); + + parent->AddChild(DynamicCast<NiAVObject>(node)); + return node; +} diff --git a/NifExport/pch.h b/NifExport/pch.h index 31b1b2276e11f0c8526bbf2197793a52a95325d5..a2a4a78835d232329384e5a696f49774f39a345a 100755 --- a/NifExport/pch.h +++ b/NifExport/pch.h @@ -12,13 +12,17 @@ // niflib/Ref.h' header guard caused havok! // near & far #include "niflib/pch.h" +#include "niflib/obj/NiNode.h" #include "niflib/obj/NiTriStrips.h" #include "niflib/obj/NiTriStripsData.h" #include "niflib/obj/NiTriShape.h" #include "niflib/obj/NiTriShapeData.h" #include "niflib/obj/bhkCollisionObject.h" -#include "niflib/obj/bhkRigidBodyT.h" +#include "niflib/obj/bhkRigidBody.h" #include "niflib/obj/bhkNiTriStripsShape.h" +#include "niflib/obj/bhkBoxShape.h" +#include "niflib/obj/bhkSphereShape.h" +#include "niflib/obj/bhkCapsuleShape.h" #include "niflib/obj/NiMaterialProperty.h" #include "niflib/obj/NiTexturingProperty.h" #include "niflib/obj/NiSourceTexture.h"