Skip to content
Snippets Groups Projects
Commit 7d177c7c authored by Gundalf's avatar Gundalf
Browse files

Proper hierarchies. Port to changed local niflib. Initial work for more collision shapes.

parent c3a0bfdf
No related branches found
No related tags found
No related merge requests found
#include "pch.h" #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) int Exporter::addVertex(vector<Vector3> &verts, vector<Vector3> &vnorms, const Point3 &pt, const Point3 &norm)
{ {
for (int i=0; i<verts.size(); i++) for (int i=0; i<verts.size(); i++)
...@@ -27,7 +124,7 @@ void Exporter::addFace(Triangles &tris, vector<Vector3> &verts, vector<Vector3> ...@@ -27,7 +124,7 @@ void Exporter::addFace(Triangles &tris, vector<Vector3> &verts, vector<Vector3>
} }
tris.push_back(tri); tris.push_back(tri);
} }
/*
bool Exporter::makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue t) bool Exporter::makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue t)
{ {
Matrix3 tm = node->GetObjTMAfterWSM(t); Matrix3 tm = node->GetObjTMAfterWSM(t);
...@@ -62,26 +159,6 @@ bool Exporter::makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue ...@@ -62,26 +159,6 @@ bool Exporter::makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue
Mesh *mesh = &tri->GetMesh(); Mesh *mesh = &tri->GetMesh();
mesh->buildNormals(); 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 // setup shape data
vector<Vector3> verts; vector<Vector3> verts;
vector<Vector3> vnorms; vector<Vector3> vnorms;
...@@ -160,3 +237,246 @@ bool Exporter::makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue ...@@ -160,3 +237,246 @@ bool Exporter::makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue
return true; 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));
}
...@@ -32,10 +32,25 @@ Exporter::Result Exporter::export(NiNodeRef &root, INode *node) ...@@ -32,10 +32,25 @@ Exporter::Result Exporter::export(NiNodeRef &root, INode *node)
root->AddExtraData(DynamicCast<NiExtraData>(strings)); root->AddExtraData(DynamicCast<NiExtraData>(strings));
mNiRoot = root; 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); bool coll = npIsCollision(node);
if ((coll && !mExportCollision) || if ((coll && !mExportCollision) ||
...@@ -60,26 +75,65 @@ Exporter::Result Exporter::exportTree(NiNodeRef &parent, INode *node) ...@@ -60,26 +75,65 @@ Exporter::Result Exporter::exportTree(NiNodeRef &parent, INode *node)
parent = n; parent = n;
} }
Result result;
ObjectState os = node->EvalWorldState(t); ObjectState os = node->EvalWorldState(t);
Result result;
if (os.obj) if (os.obj)
{ {
// We look at the super class ID to determine the type of the object. // We look at the super class ID to determine the type of the object.
switch(os.obj->SuperClassID()) switch(os.obj->SuperClassID())
{ {
case GEOMOBJECT_CLASS_ID: case GEOMOBJECT_CLASS_ID:
if (!coll) /* if (os.obj->ClassID() == SCUBA_CLASS_ID)
{ {
result = exportMesh(parent, node, t); float radius = 0;
if (result != Ok) float height = 0;
return result; 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 } else
if (os.obj->ClassID() == Class_ID(BOXOBJ_CLASS_ID, 0))
{ {
if (!makeCollisionHierarchy(mNiRoot, node, t)) float length = 0;
return Error; 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; break;
/* /*
case CAMERA_CLASS_ID: case CAMERA_CLASS_ID:
...@@ -101,7 +155,7 @@ Exporter::Result Exporter::exportTree(NiNodeRef &parent, INode *node) ...@@ -101,7 +155,7 @@ Exporter::Result Exporter::exportTree(NiNodeRef &parent, INode *node)
for (int i=0; i<node->NumberOfChildren(); i++) 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) if (result!=Ok && result!=Skip)
return result; return result;
} }
...@@ -111,3 +165,5 @@ Exporter::Result Exporter::exportTree(NiNodeRef &parent, INode *node) ...@@ -111,3 +165,5 @@ Exporter::Result Exporter::exportTree(NiNodeRef &parent, INode *node)
return Ok; return Ok;
} }
#endif
...@@ -19,24 +19,24 @@ public: ...@@ -19,24 +19,24 @@ public:
}; };
/* exporter version */ /* exporter version */
static int mVersion; static int mVersion;
/* export options, static for dialog usage. */ /* export options, static for dialog usage. */
static bool mSelectedOnly; static bool mSelectedOnly;
static bool mTriStrips; static bool mTriStrips;
static bool mExportHidden; static bool mExportHidden;
static bool mExportFurn; static bool mExportFurn;
static bool mExportLights; static bool mExportLights;
static string mTexPrefix; static string mTexPrefix;
static bool mVertexColors; static bool mVertexColors;
static float mWeldThresh; static float mWeldThresh;
static bool mExportCollision; static bool mExportCollision;
static bool mRemapIndices; static bool mRemapIndices;
Exporter(Interface *i); 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 /* config is written to the registry and the root node
of the scene, so that it is restored when opening it of the scene, so that it is restored when opening it
...@@ -44,14 +44,14 @@ public: ...@@ -44,14 +44,14 @@ public:
use the settings stored in the registry. */ use the settings stored in the registry. */
// writes config to root node // writes config to root node
static void writeConfig(INode *node); static void writeConfig(INode *node);
// writes config to registry // writes config to registry
static void writeConfig(); static void writeConfig();
// reads config from root node // reads config from root node
static void readConfig(INode *node); static void readConfig(INode *node);
// reads config from registry // reads config from registry
static void readConfig(); static void readConfig();
private: private:
...@@ -71,51 +71,63 @@ private: ...@@ -71,51 +71,63 @@ private:
// maps face groups to material ID // maps face groups to material ID
typedef std::map<int, FaceGroup> FaceGroups; typedef std::map<int, FaceGroup> FaceGroups;
Interface *mI; Interface *mI;
NiNodeRef mNiRoot; NiNodeRef mNiRoot;
Result exportTree(NiNodeRef &root, INode *node); Result exportCollision(NiNodeRef &root, INode *node);
Result exportMeshes(NiNodeRef &root, INode *node);
/* utility functions */ /* utility functions */
Mtl *getMaterial(INode *node, int subMtl); Mtl *getMaterial(INode *node, int subMtl);
bool TMNegParity(const Matrix3 &m); bool TMNegParity(const Matrix3 &m);
void convertMatrix(Matrix33 &dst, const Matrix3 &src); void convertMatrix(Matrix33 &dst, const Matrix3 &src);
void nodeTransform(Matrix33 &rot, Vector3 &trans, INode *node, TimeValue t, bool local=true); 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); void nodeTransform(QuaternionXYZW &rot, Vector3 &trans, INode *node, TimeValue t, bool local=true);
Point3 getVertexNormal(Mesh* mesh, int faceNo, RVertex* rv); Point3 getVertexNormal(Mesh* mesh, int faceNo, RVertex* rv);
bool equal(const Vector3 &a, const Point3 &b, float thresh); bool equal(const Vector3 &a, const Point3 &b, float thresh);
BitmapTex *getTexture(Mtl *mtl); BitmapTex *getTexture(Mtl *mtl);
void getTextureMatrix(Matrix3 &mat, Mtl *mtl); void getTextureMatrix(Matrix3 &mat, Mtl *mtl);
NiNodeRef makeNode(NiNodeRef &parent, INode *maxNode, bool local=true);
/* tristrips */ /* tristrips */
void strippify(TriStrips &strips, vector<Vector3> &verts, vector<Vector3> &norms, const Triangles &tris); void strippify(TriStrips &strips, vector<Vector3> &verts, vector<Vector3> &norms, const Triangles &tris);
void strippify(TriStrips &strips, FaceGroup &grp); void strippify(TriStrips &strips, FaceGroup &grp);
NiTriStripsDataRef makeTriStripsData(const TriStrips &strips); NiTriStripsDataRef makeTriStripsData(const TriStrips &strips);
/* mesh export */ /* mesh export */
// adds a vertex to a face group if it doesn't exist yet. returns new or previous index into the // adds a vertex to a face group if it doesn't exist yet. returns new or previous index into the
// vertex array. // 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 // 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 // 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 // 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 // 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 */ /* texture & material */
// creates NiTexturingProperty + NiSourceTexture // creates NiTexturingProperty + NiSourceTexture
void makeTexture(NiAVObjectRef &parent, Mtl *mtl); void makeTexture(NiAVObjectRef &parent, Mtl *mtl);
// creates a NiMaterialProperty // creates a NiMaterialProperty
void makeMaterial(NiAVObjectRef &parent, Mtl *mtl); void makeMaterial(NiAVObjectRef &parent, Mtl *mtl);
/* havok & collision */ /* havok & collision */
int addVertex(vector<Vector3> &verts, vector<Vector3> &vnorms, const Point3 &pt, const Point3 &norm); int addVertex(vector<Vector3> &verts, vector<Vector3> &vnorms, const Point3 &pt, const Point3 &norm);
void addFace(Triangles &tris, vector<Vector3> &verts, vector<Vector3> &vnorms, void addFace(Triangles &tris, vector<Vector3> &verts, vector<Vector3> &vnorms,
int face, const int vi[3], Mesh *mesh); int face, const int vi[3], Mesh *mesh);
bool makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue t); 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 #endif
#include "pch.h" #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); 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) if (!tri)
return Error; return Error;
if (obj != tri)
alloc = TRUE;
else
alloc = FALSE;
Mesh *mesh = &tri->GetMesh(); Mesh *mesh = &tri->GetMesh();
mesh->buildNormals(); 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; Result result = Ok;
while (1) while (1)
{ {
...@@ -57,7 +135,7 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &parent, INode *node, TimeValue ...@@ -57,7 +135,7 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &parent, INode *node, TimeValue
break; break;
} }
if (alloc) if (tri != os.obj)
tri->DeleteMe(); tri->DeleteMe();
return result; return result;
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
RuntimeLibrary="2" RuntimeLibrary="2"
BufferSecurityCheck="FALSE" BufferSecurityCheck="FALSE"
EnableFunctionLevelLinking="TRUE" EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="1" UsePrecompiledHeader="0"
PrecompiledHeaderThrough="pch.h" PrecompiledHeaderThrough="pch.h"
PrecompiledHeaderFile=".\Release\NifExport.pch" PrecompiledHeaderFile=".\Release\NifExport.pch"
AssemblerListingLocation=".\Release\" AssemblerListingLocation=".\Release\"
......
...@@ -87,3 +87,21 @@ bool Exporter::equal(const Vector3 &a, const Point3 &b, float thresh) ...@@ -87,3 +87,21 @@ bool Exporter::equal(const Vector3 &a, const Point3 &b, float thresh)
(fabsf(a.y-b.y) <= thresh) && (fabsf(a.y-b.y) <= thresh) &&
(fabsf(a.z-b.z) <= 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;
}
...@@ -12,13 +12,17 @@ ...@@ -12,13 +12,17 @@
// niflib/Ref.h' header guard caused havok! // niflib/Ref.h' header guard caused havok!
// near & far // near & far
#include "niflib/pch.h" #include "niflib/pch.h"
#include "niflib/obj/NiNode.h"
#include "niflib/obj/NiTriStrips.h" #include "niflib/obj/NiTriStrips.h"
#include "niflib/obj/NiTriStripsData.h" #include "niflib/obj/NiTriStripsData.h"
#include "niflib/obj/NiTriShape.h" #include "niflib/obj/NiTriShape.h"
#include "niflib/obj/NiTriShapeData.h" #include "niflib/obj/NiTriShapeData.h"
#include "niflib/obj/bhkCollisionObject.h" #include "niflib/obj/bhkCollisionObject.h"
#include "niflib/obj/bhkRigidBodyT.h" #include "niflib/obj/bhkRigidBody.h"
#include "niflib/obj/bhkNiTriStripsShape.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/NiMaterialProperty.h"
#include "niflib/obj/NiTexturingProperty.h" #include "niflib/obj/NiTexturingProperty.h"
#include "niflib/obj/NiSourceTexture.h" #include "niflib/obj/NiSourceTexture.h"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment