Пример #1
0
bool Exporter::removeUnreferencedBones(NiNodeRef node)
{
   NiNodeRef parent = node->GetParent();
   bool remove = (NULL != parent) && !node->IsSkinInfluence();
   Matrix44 ntm = node->GetLocalTransform();
   vector<NiAVObjectRef> children = node->GetChildren();
   for (vector<NiAVObjectRef>::iterator itr = children.begin(); itr != children.end(); ++itr)
   {
      NiAVObjectRef& child = (*itr);
      bool childRemove = false;
      if (child->IsDerivedType(NiNode::TYPE))
      {
         childRemove = removeUnreferencedBones(StaticCast<NiNode>(child));
      }
      if (childRemove)
      {
         node->RemoveChild(child);
      }
      else if (remove) // Reparent abandoned nodes to root
      {
         Matrix44 tm = child->GetLocalTransform();
         child->SetLocalTransform( ntm * tm );
         node->RemoveChild(child);
         mNiRoot->AddChild(child);
      }
   }
   return remove;
}
Пример #2
0
/*---------------------------------------------------------------------------*/
unsigned int NifCollisionUtility::getGeometryFromNode(NiNodeRef pNode, vector<hkGeometry>& geometryMap, vector<hkGeometry>& geometryMapColl, vector<Matrix44>& transformAry)
{
	bhkCollisionObjectRef	pCollObject(DynamicCast<bhkCollisionObject>(pNode->GetCollisionObject()));
	vector<NiAVObjectRef>	childList  (pNode->GetChildren());

	//  add own translation to list
	transformAry.push_back(pNode->GetLocalTransform());

	//  get geometry from collision object
	if (pCollObject != NULL)
	{
		//  search for embedded shape
		bhkRigidBodyRef		pRBody(DynamicCast<bhkRigidBody>(pCollObject->GetBody()));

		if (pRBody != NULL)
		{
			getGeometryFromCollShape(pRBody->GetShape(), geometryMapColl, transformAry);
		}
	}  //  if (pCollObject != NULL)

	//  iterate over children
	for (vector<NiAVObjectRef>::iterator ppIter = childList.begin(); ppIter != childList.end(); ppIter++)
	{
		//  NiTriShape
		if (DynamicCast<NiTriShape>(*ppIter) != NULL)
		{
			getGeometryFromTriShape(DynamicCast<NiTriShape>(*ppIter), geometryMap, transformAry);
		}
		//  NiTriStrips
		else if (DynamicCast<NiTriStrips>(*ppIter) != NULL)
		{
			getGeometryFromTriStrips(DynamicCast<NiTriStrips>(*ppIter), geometryMap, transformAry);
		}
		//  RootCollisionNode
		else if (DynamicCast<RootCollisionNode>(*ppIter) != NULL)
		{
			getGeometryFromNode(&(*DynamicCast<RootCollisionNode>(*ppIter)), geometryMapColl, geometryMapColl, transformAry);
		}
		//  NiNode (and derived classes?)
		else if (DynamicCast<NiNode>(*ppIter) != NULL)
		{
			getGeometryFromNode(DynamicCast<NiNode>(*ppIter), geometryMap, geometryMapColl, transformAry);
		}
	}  //  for (vector<NiAVObjectRef>::iterator ppIter = childList.begin(); ppIter != childList.end(); ppIter++)

	//  remove own translation from list
	transformAry.pop_back();

	return geometryMap.size();
}
Пример #3
0
/*---------------------------------------------------------------------------*/
unsigned int NifConvertUtility::convertShape(string fileNameSrc, string fileNameDst, string fileNameTmpl)
{
	NiNodeRef				pRootInput     (NULL);
	NiNodeRef				pRootOutput    (NULL);
	NiNodeRef				pRootTemplate  (NULL);
	NiTriShapeRef			pNiTriShapeTmpl(NULL);
	vector<NiAVObjectRef>	srcChildList;
	bool					fakedRoot      (false);

	//  test on existing file names
	if (fileNameSrc.empty())		return NCU_ERROR_MISSING_FILE_NAME;
	if (fileNameDst.empty())		return NCU_ERROR_MISSING_FILE_NAME;
	if (fileNameTmpl.empty())		return NCU_ERROR_MISSING_FILE_NAME;

	//  initialize user messages
	_userMessages.clear();
	logMessage(NCU_MSG_TYPE_INFO, "Source:  "      + (fileNameSrc.empty() ? "- none -" : fileNameSrc));
	logMessage(NCU_MSG_TYPE_INFO, "Template:  "    + (fileNameTmpl.empty() ? "- none -" : fileNameTmpl));
	logMessage(NCU_MSG_TYPE_INFO, "Destination:  " + (fileNameDst.empty() ? "- none -" : fileNameDst));
	logMessage(NCU_MSG_TYPE_INFO, "Texture:  "     + (_pathTexture.empty() ? "- none -" : _pathTexture));

	//  initialize used texture list
	_usedTextures.clear();
	_newTextures.clear();

	//  read input NIF
	if ((pRootInput = getRootNodeFromNifFile(fileNameSrc, "source", fakedRoot)) == NULL)
	{
		logMessage(NCU_MSG_TYPE_ERROR, "Can't open '" + fileNameSrc + "' as input");
		return NCU_ERROR_CANT_OPEN_INPUT;
	}

	//  get template nif
	pRootTemplate = DynamicCast<BSFadeNode>(ReadNifTree((const char*) fileNameTmpl.c_str()));
	if (pRootTemplate == NULL)
	{
		logMessage(NCU_MSG_TYPE_ERROR, "Can't open '" + fileNameTmpl + "' as template");
		return NCU_ERROR_CANT_OPEN_TEMPLATE;
	}

	//  get shapes from template
	//  - shape root
	pNiTriShapeTmpl = DynamicCast<NiTriShape>(pRootTemplate->GetChildren().at(0));
	if (pNiTriShapeTmpl == NULL)
	{
		logMessage(NCU_MSG_TYPE_INFO, "Template has no NiTriShape.");
	}

	//  template root is used as root of output
	pRootOutput = pRootTemplate;

	//   get rid of unwanted subnodes
	pRootOutput->ClearChildren();           //  remove all children
	pRootOutput->SetCollisionObject(NULL);  //  unlink collision object
	//  hold extra data and property nodes

	//  copy translation from input node
	pRootOutput->SetLocalTransform(pRootInput->GetLocalTransform());

	//  copy name of root node
	pRootOutput->SetName(pRootInput->GetName());

	//  get list of children from input node
	srcChildList = pRootInput->GetChildren();

	//  unlink children 'cause moved to output
	pRootInput->ClearChildren();

	//  iterate over source nodes and convert using template
	for (vector<NiAVObjectRef>::iterator  ppIter = srcChildList.begin(); ppIter != srcChildList.end(); ppIter++)
	{
		//  NiTriShape
		if (DynamicCast<NiTriShape>(*ppIter) != NULL)
		{
			pRootOutput->AddChild(&(*convertNiTriShape(DynamicCast<NiTriShape>(*ppIter), pNiTriShapeTmpl)));
		}
		//  RootCollisionNode
		else if (DynamicCast<RootCollisionNode>(*ppIter) != NULL)
		{
			//  ignore node
		}
		//  NiNode (and derived classes?)
		else if (DynamicCast<NiNode>(*ppIter) != NULL)
		{
			pRootOutput->AddChild(&(*convertNiNode(DynamicCast<NiNode>(*ppIter), pNiTriShapeTmpl, pRootOutput)));
		}
	}

	//  write missing textures to log - as block
	for (set<string>::iterator pIter(_newTextures.begin()); pIter != _newTextures.end(); ++pIter)
	{
		logMessage(NCU_MSG_TYPE_TEXTURE_MISS, *pIter);
	}

	//  write modified nif file
	WriteNifTree((const char*) fileNameDst.c_str(), pRootOutput, NifInfo(VER_20_2_0_7, 12, 83));

	return NCU_OK;
}
Пример #4
0
/*---------------------------------------------------------------------------*/
unsigned int NifConvertUtility::convertShape(string fileNameSrc, string fileNameDst, string fileNameTmpl)
{
	cout << "Here3" << endl;
	NiNodeRef				pRootInput     (NULL);
	NiNodeRef				pRootOutput    (NULL);
	NiNodeRef				pRootTemplate  (NULL);
	NiTriShapeRef			pNiTriShapeTmpl(NULL);
	NiCollisionObjectRef	pRootCollObject(NULL);
	NifInfo					nifInfo;
	vector<NiAVObjectRef>	srcChildList;
	bool					fakedRoot      (false);
	cout << "Here4" << endl;
	//  test on existing file names
	if (fileNameSrc.empty())		return NCU_ERROR_MISSING_FILE_NAME;
	if (fileNameDst.empty())		return NCU_ERROR_MISSING_FILE_NAME;
	if (fileNameTmpl.empty())		return NCU_ERROR_MISSING_FILE_NAME;
	cout << "Here5" << endl;
	//  initialize user messages
	_userMessages.clear();
	logMessage(NCU_MSG_TYPE_INFO, "Source:  "      + (fileNameSrc.empty() ? "- none -" : fileNameSrc));
	logMessage(NCU_MSG_TYPE_INFO, "Template:  "    + (fileNameTmpl.empty() ? "- none -" : fileNameTmpl));
	logMessage(NCU_MSG_TYPE_INFO, "Destination:  " + (fileNameDst.empty() ? "- none -" : fileNameDst));
	logMessage(NCU_MSG_TYPE_INFO, "Texture:  "     + (_pathTexture.empty() ? "- none -" : _pathTexture));
	cout << "Here6" << endl;
	//  initialize used texture list
	_usedTextures.clear();
	_newTextures.clear();
	cout << "Here7" << endl;
	//  read input NIF
	if ((pRootInput = getRootNodeFromNifFile(fileNameSrc, "source", fakedRoot, &nifInfo)) == NULL)
	{
		logMessage(NCU_MSG_TYPE_ERROR, "Can't open '" + fileNameSrc + "' as input");
		return NCU_ERROR_CANT_OPEN_INPUT;
	}
	cout << "Here8" << endl;
	//  get template nif
	pRootTemplate = DynamicCast<BSFadeNode>(ReadNifTree((const char*) fileNameTmpl.c_str()));
	if (pRootTemplate == NULL)
	{
		logMessage(NCU_MSG_TYPE_ERROR, "Can't open '" + fileNameTmpl + "' as template");
		return NCU_ERROR_CANT_OPEN_TEMPLATE;
	}
	cout << "Here9" << endl;
	//  get shapes from template
	//  - shape root
	pNiTriShapeTmpl = DynamicCast<NiTriShape>(pRootTemplate->GetChildren().at(0));
	if (pNiTriShapeTmpl == NULL)
	{
		logMessage(NCU_MSG_TYPE_INFO, "Template has no NiTriShape.");
	}
	cout << "Here10" << endl;
	//  get data from input node
	srcChildList    = pRootInput->GetChildren();
	pRootCollObject = pRootInput->GetCollisionObject();
	cout << "Here11" << endl;
	//  template root is used as root of output
	pRootOutput = pRootTemplate;

	//  move date from input to output
	pRootInput ->SetCollisionObject(NULL);
	pRootOutput->SetCollisionObject(pRootCollObject);
	pRootOutput->SetLocalTransform(pRootInput->GetLocalTransform());
	pRootOutput->SetName(pRootInput->GetName());
	cout << "Here12" << endl;
	//  get rid of unwanted subnodes
	pRootOutput->ClearChildren();
	pRootInput->ClearChildren();
	cout << "Here13" << endl;
	//  move children to output
	for (auto pIter=srcChildList.begin(), pEnd=srcChildList.end(); pIter != pEnd; ++pIter)
	{
		pRootOutput->AddChild(*pIter);				
	}
	cout << "Here14" << endl;
	//  iterate over source nodes and convert using template
	root_bsafade = pRootOutput;
	pRootOutput = convertNiNode(pRootOutput, pNiTriShapeTmpl, pRootOutput);
	cout << "Here15" << endl;
	//  write missing textures to log - as block
	for (auto pIter=_newTextures.begin(), pEnd=_newTextures.end(); pIter != pEnd; ++pIter)
	{
		logMessage(NCU_MSG_TYPE_TEXTURE_MISS, *pIter);
	}
	cout << "Here16" << endl;
	//  set version information
	stringstream	sStream;
	cout << "Here17" << endl;
	sStream << nifInfo.version << ';' << nifInfo.userVersion;
	nifInfo.version      = VER_20_2_0_7;
	nifInfo.userVersion  = 12;
	nifInfo.userVersion2 = 83;
	nifInfo.creator      = "NifConvert";
	nifInfo.exportInfo1  = MASTER_PRODUCT_VERSION_STR;
	nifInfo.exportInfo2  = sStream.str();
	cout << "Here18" << endl;
	//  write modified nif file
	WriteNifTree((const char*) fileNameDst.c_str(), pRootOutput, nifInfo);
	cout << "Here19" << endl;
	return NCU_OK;
}
Пример #5
0
void NifImporter::ImportBones(NiNodeRef node, bool recurse)
{
   try 
   {
      if (uncontrolledDummies)
         BuildControllerRefList(node, ctrlCount);

      string name = node->GetName();

      vector<NiAVObjectRef> children = node->GetChildren();
      vector<NiNodeRef> childNodes = DynamicCast<NiNode>(children);

      NiAVObject::CollisionType cType = node->GetCollisionMode();
      if (children.empty() && name == "Bounding Box")
         return;

      // Do all node manipulations here
      NiNodeRef parent = node->GetParent();
      string parentname = (parent ? parent->GetName() : "");
      Matrix44 m4 = node->GetWorldTransform();

      // Check for Prn strings and change parent if necessary
      if (supportPrnStrings) {
         list<NiStringExtraDataRef> strings = DynamicCast<NiStringExtraData>(node->GetExtraData());
         for (list<NiStringExtraDataRef>::iterator itr = strings.begin(); itr != strings.end(); ++itr){
            if (strmatch((*itr)->GetName(), "Prn")) {
               parentname = (*itr)->GetData();
               if (INode *pn = gi->GetINodeByName(parentname.c_str())){
                  // Apparently Heads tend to need to be rotated 90 degrees on import for 
                  if (!rotate90Degrees.empty() && wildmatch(rotate90Degrees, parentname)) {
                     m4 *= TOMATRIX4(RotateYMatrix(TORAD(90)));
                  }
                  m4 *= TOMATRIX4(pn->GetObjTMAfterWSM(0, NULL));
               }
            }
         }
      }

      float len = node->GetLocalTranslation().Magnitude();

      // Remove NonAccum nodes and merge into primary bone
      if (mergeNonAccum && wildmatch("* NonAccum", name) && parent)
      {
         string realname = name.substr(0, name.length() - 9);
         if (strmatch(realname, parent->GetName()))
         {
            Matrix44 tm = parent->GetLocalTransform() * node->GetLocalTransform();
            name = realname;
            len += tm.GetTranslation().Magnitude();
			parent = parent->GetParent();
         }
      }

      PosRotScale prs = prsDefault;
      Vector3 pos; Matrix33 rot; float scale;
      m4.Decompose(pos, rot, scale);

      Matrix3 im = TOMATRIX3(m4);
      Point3 p = im.GetTrans();
      Quat q(im);
      //q.Normalize();
      Vector3 ppos;
      Point3 zAxis(0,0,0);
      bool hasChildren = !children.empty();
      if (hasChildren) {
         float len = 0.0f;
         for (vector<NiAVObjectRef>::iterator itr=children.begin(), end = children.end(); itr != end; ++itr) {
            len += GetObjectLength(*itr);
         }
         len /= float(children.size());
         ppos = pos + Vector3(len, 0.0f, 0.0f); // just really need magnitude as rotation will take care of positioning
      }
      else if (parent)
      {
         ppos = pos + Vector3(len/3.0f, 0.0f, 0.0f);
      }
      Point3 pp(ppos.x, ppos.y, ppos.z);

      Point3 qp = TORAD(TOEULER(im));


      INode *bone = NULL;
	  if (!doNotReuseExistingBones) // Games like BC3 reuse the same bone names
	  {
		  bone = FindNode(node);
		  if (bone == NULL) 
			  bone = gi->GetINodeByName(name.c_str());
	  }
      if (bone)
      {
         // Is there a better way of "Affect Pivot Only" behaviors?
         INode *pinode = bone->GetParentNode();
         if (pinode)
            bone->Detach(0,1);
         PosRotScaleNode(bone, p, q, scale, prs);
         if (pinode)
            pinode->AttachChild(bone, 1);
      }
      else
      {
         bool isDummy = ( (uncontrolledDummies && !HasControllerRef(ctrlCount, name))
                     || (!dummyNodeMatches.empty() && wildmatch(dummyNodeMatches, name))
                     || (convertBillboardsToDummyNodes && node->IsDerivedType(NiBillboardNode::TYPE))
                      );
         if (wildmatch("Camera*", name)) {
            if (enableCameras) {
               if (bone = CreateCamera(name)) {
                  PosRotScaleNode(bone, p, q, scale, prs);
                  bone->Hide(node->GetVisibility() ? FALSE : TRUE);
               }
            }
         }else if (isDummy && createNubsForBones)
            bone = CreateHelper(name, p);
         else if (bone = CreateBone(name, p, pp, zAxis))
         {
            PosRotScaleNode(bone, p, q, scale, prs);
            bone->Hide(node->GetVisibility() ? FALSE : TRUE);
         }
         if (bone)
         {
            if (!parentname.empty())
            {
               if (mergeNonAccum && wildmatch("* NonAccum", parentname)) {
                  parentname = parentname.substr(0, parentname.length() - 9);
               }
               if (INode *pn = gi->GetINodeByName(parentname.c_str()))
                  pn->AttachChild(bone, 1);
            }
			RegisterNode(node, bone);
         }
      }
      // Import UPB
      if (bone) ImportUPB(bone, node);

      // Import Havok Collision Data surrounding node,  
	  //   unfortunately this causes double import of collision so I'm disabling it for now.
	  if (enableCollision && node->GetParent()) {
		ImportCollision(node);
	  }

      if (bone && recurse)
      {
         ImportBones(childNodes);
      }
   }
   catch( exception & e ) 
   {
      e=e;
   }
   catch( ... ) 
   {
   }
}