Skip to content
Snippets Groups Projects
Commit ba6acd3c authored by Tazpn's avatar Tazpn
Browse files

Additional fixes for Collision import/export.

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