bool NifImporter::ImportMeshes(NiNodeRef node)
{
   bool ok = true;
   try 
   {
#if 1
      vector<NiTriShapeRef> trinodes = DynamicCast<NiTriShape>(node->GetChildren());
      for (vector<NiTriShapeRef>::iterator itr = trinodes.begin(), end = trinodes.end(); itr != end; ++itr){
         ok |= ImportMesh(*itr);
      }
      vector<NiTriStripsRef> tristrips = DynamicCast<NiTriStrips>(node->GetChildren());
      for (vector<NiTriStripsRef>::iterator itr = tristrips.begin(), end = tristrips.end(); itr != end; ++itr){
         ok |= ImportMesh(*itr);
      }
#else
      // Only do multiples on object that have same name and use XXX:# notation
      vector<NiTriBasedGeomRef> trigeom = DynamicCast<NiTriBasedGeom>(node->GetChildren());
      ok |= ImportMultipleGeometry(node, trigeom);
#endif
      vector<NiNodeRef> nodes = DynamicCast<NiNode>(node->GetChildren());
      for (vector<NiNodeRef>::iterator itr = nodes.begin(), end = nodes.end(); itr != end; ++itr){
         ok |= ImportMeshes(*itr);
      }
   }
   catch( exception & e ) 
   {
      e=e;
      ok = false;
   }
   catch( ... ) 
   {
	   ok = false;
   }
   return ok;
}
Ejemplo n.º 2
0
/*---------------------------------------------------------------------------*/
void NifCollisionUtility::cleanTreeCollision(NiNodeRef pNode)
{
	vector<NiAVObjectRef>	srcChildList(pNode->GetChildren());		//  children of node

	//  remove collision object (new style [>= Oblivion])
	pNode->SetCollisionObject(NULL);

	//  iterate over source nodes and remove possible old-style [Morrowind] collision node
	for (auto  ppIter=srcChildList.begin(), pEnd=srcChildList.end(); ppIter != pEnd; ppIter++)
	{
		//  RootCollisionNode
		if (DynamicCast<RootCollisionNode>(*ppIter) != NULL)
		{
			pNode->RemoveChild(*ppIter);
		}
		//  NiNode
		else if (DynamicCast<NiNode>(*ppIter) != NULL)
		{
			cleanTreeCollision(DynamicCast<NiNode>(*ppIter));
		}
		//  other children
		else
		{
			(*ppIter)->SetCollisionObject(NULL);
		}
	}  //  for (vector<NiAVObjectRef>::iterator  ppIter = srcChildList.begin(); ....
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
void Exporter::sortNodes(NiNodeRef node)
{
   node->SortChildren(SortNodeEquivalence());

   vector<NiNodeRef> children = DynamicCast<NiNode>(node->GetChildren());
   for (vector<NiNodeRef>::iterator itr = children.begin(); itr != children.end(); ++itr)
      sortNodes(*itr);
}
Ejemplo n.º 5
0
static void BuildNodes(NiNodeRef object, vector<NiNodeRef>& nodes)
{
   if (!object)
      return;
   nodes.push_back(object);
   vector<NiNodeRef> links = DynamicCast<NiNode>(object->GetChildren());
   for (vector<NiNodeRef>::iterator itr = links.begin(), end = links.end(); itr != end; ++itr)
      BuildNodes(*itr, nodes);
}
Ejemplo n.º 6
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();
}
Ejemplo n.º 7
0
/*---------------------------------------------------------------------------*/
NiNodeRef NifPrepareUtility::parse4Blender(NiNodeRef pNode)
{
	vector<NiAVObjectRef>	childList(pNode->GetChildren());
	list<NiExtraDataRef>	extraList(pNode->GetExtraData());

	//  parse extra data for BSInvMarker
	for (auto pIter(extraList.begin()), pEnd(extraList.end()); pIter != pEnd; pIter++)
	{
		if (_remBSInvMarker && (DynamicCast<BSInvMarker>(*pIter) != NULL))
		{
			pNode->RemoveExtraData(*pIter);
		}
	}

	//  unlink children
	pNode->ClearChildren();

	//  iterate over children
	for (auto pIter(childList.begin()), pEnd(childList.end()); pIter != pEnd; pIter++)
	{
		//  NiTriShape => remove BSLightingShaderProperty
		if (DynamicCast<NiTriShape>(*pIter) != NULL)
		{
			if (_remBSProperties)
			{
				NiTriShapeRef	pShape (DynamicCast<NiTriShape>(*pIter));

				//  remove properties (Bethesda uses max. 2)
				pShape->SetBSProperty(0, NULL);
				pShape->SetBSProperty(1, NULL);
			}

			//  add shape to node
			pNode->AddChild(*pIter);
		}
		//  BSInvMarker => remove whole object
		else if (_remBSInvMarker && (DynamicCast<BSInvMarker>(*pIter) != NULL))
		{
			//  skip entry => do not add to final list
		}
		//  NiNode (and derived classes?) => iterate subnodes
		else if (DynamicCast<NiNode>(*pIter) != NULL)
		{
			pNode->AddChild(&(*parse4Blender(DynamicCast<NiNode>(*pIter))));
		}
	}  //  for (auto pIter(childList.begin()), pEnd(childList.end()); pIter != pEnd; pIter++)

	return pNode;
}
Ejemplo n.º 8
0
void Exporter::ApplyAllSkinOffsets( NiAVObjectRef & root ) {
   NiGeometryRef niGeom = DynamicCast<NiGeometry>(root);
   if ( niGeom != NULL && niGeom->IsSkin() == true ) {
      niGeom->ApplySkinOffset();
   }

   NiNodeRef niNode = DynamicCast<NiNode>(root);
   if ( niNode != NULL ) {
      //Call this function on all children
      vector<NiAVObjectRef> children = niNode->GetChildren();

      for ( unsigned i = 0; i < children.size(); ++i ) {
         ApplyAllSkinOffsets( children[i] );
      }
   }
} 
Ejemplo n.º 9
0
/*---------------------------------------------------------------------------*/
NiNodeRef NifConvertUtility::convertNiNode(NiNodeRef pSrcNode, NiTriShapeRef pTmplNode, NiNodeRef pRootNode, NiAlphaPropertyRef pTmplAlphaProp)
{
	NiNodeRef				pDstNode    (pSrcNode);
	vector<NiAVObjectRef>	srcShapeList(pDstNode->GetChildren());

	//  find NiAlphaProperty and use as template in sub-nodes
	if (DynamicCast<NiAlphaProperty>(pDstNode->GetPropertyByType(NiAlphaProperty::TYPE)) != NULL)
	{
		pTmplAlphaProp = DynamicCast<NiAlphaProperty>(pDstNode->GetPropertyByType(NiAlphaProperty::TYPE));
	}

	//  unlink protperties -> not used in new format
	pDstNode->ClearProperties();

	//  shift extra data to new version
	pDstNode->ShiftExtraData(VER_20_2_0_7);

	//  unlink children
	pDstNode->ClearChildren();

	//  iterate over source nodes and convert using template
	for (vector<NiAVObjectRef>::iterator  ppIter = srcShapeList.begin(); ppIter != srcShapeList.end(); ppIter++)
	{
		//  NiTriShape
		//Type t = (*ppIter)->GetType();
		if (DynamicCast<NiTriShape>(*ppIter) != NULL)
		{
			pDstNode->AddChild(&(*convertNiTriShape(DynamicCast<NiTriShape>(*ppIter), pTmplNode, pTmplAlphaProp)));
		}
		//  NiNode (and derived classes?)
		else if (DynamicCast<NiNode>(*ppIter) != NULL)
		{
			pDstNode->AddChild(&(*convertNiNode(DynamicCast<NiNode>(*ppIter), pTmplNode, pRootNode, pTmplAlphaProp)));
		}
	}

	return pDstNode;
}
Ejemplo n.º 10
0
/*---------------------------------------------------------------------------*/
unsigned int NifCollisionUtility::getGeometryFromNifFile(string fileName, vector<hkGeometry>& geometryMap)
{
	NiNodeRef				pRootInput (NULL);
	bhkCollisionObjectRef	pCollObject(NULL);
	vector<NiAVObjectRef>	srcChildList;
	vector<Matrix44>		transformAry;
	vector<hkGeometry>		geometryMapColl;
	vector<hkGeometry>		geometryMapShape;
	bool					fakedRoot  (false);

	//  read input NIF
	if ((pRootInput = getRootNodeFromNifFile(fileName, "collSource", fakedRoot, true)) == NULL)
	{
		return NCU_ERROR_CANT_OPEN_INPUT;
	}

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

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

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

	//  iterate over source nodes and get geometry
	for (vector<NiAVObjectRef>::iterator  ppIter = srcChildList.begin(); ppIter != srcChildList.end(); ppIter++)
	{
		//  NiTriShape
		if (DynamicCast<NiTriShape>(*ppIter) != NULL)
		{
			getGeometryFromTriShape(DynamicCast<NiTriShape>(*ppIter), geometryMapShape, transformAry);
		}
		//  NiTriStrips
		else if (DynamicCast<NiTriStrips>(*ppIter) != NULL)
		{
			getGeometryFromTriStrips(DynamicCast<NiTriStrips>(*ppIter), geometryMapShape, 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), geometryMapShape, geometryMapColl, transformAry);
		}
	}

	//  which geomertry should be used?
	if ((_cnHandling == NCU_CN_COLLISION) || (_cnHandling == NCU_CN_FALLBACK))
	{
		geometryMap.swap(geometryMapColl);
	}
	else if (_cnHandling == NCU_CN_SHAPES)
	{
		geometryMap.swap(geometryMapShape);
	}
	if ((_cnHandling == NCU_CN_FALLBACK) && (geometryMap.size() <= 0))
	{
		geometryMap.swap(geometryMapShape);
	}

	return geometryMap.size();
}
Ejemplo n.º 11
0
void NifMeshExporterSkyrim::ExportMesh( MObject dagNode ) {
	//out << "NifTranslator::ExportMesh {";
	ComplexShape cs;
	MStatus stat;
	MObject mesh;

	//Find Mesh child of given transform object
	MFnDagNode nodeFn(dagNode);

	cs.SetName(this->translatorUtils->MakeNifName(nodeFn.name()));


	for (int i = 0; i != nodeFn.childCount(); ++i) {
		// get a handle to the child
		if (nodeFn.child(i).hasFn(MFn::kMesh)) {
			MFnMesh tempFn(nodeFn.child(i));
			//No history items
			if (!tempFn.isIntermediateObject()) {
				//out << "Found a mesh child." << endl;
				mesh = nodeFn.child(i);
				break;
			}
		}
	}

	MFnMesh visibleMeshFn(mesh, &stat);
	if (stat != MS::kSuccess) {
		//out << stat.errorString().asChar() << endl;
		throw runtime_error("Failed to create visibleMeshFn.");
	}

	//out << visibleMeshFn.name().asChar() << ") {" << endl;
	MFnMesh meshFn;
	MObject dataObj;
	MPlugArray inMeshPlugArray;
	MPlug childPlug;
	MPlug geomPlug;
	MPlug inputPlug;

	// this will hold the returned vertex positions
	MPointArray vts;

	//For now always use the visible mesh
	meshFn.setObject(mesh);

	//out << "Use the function set to get the points" << endl;
	// use the function set to get the points
	stat = meshFn.getPoints(vts);
	if (stat != MS::kSuccess) {
		//out << stat.errorString().asChar() << endl;
		throw runtime_error("Failed to get points.");
	}

	//Maya won't store any information about objects with no vertices.  Just skip it.
	if (vts.length() == 0) {
		MGlobal::displayWarning("An object in this scene has no vertices.  Nothing will be exported.");
		return;
	}

	vector<WeightedVertex> nif_vts(vts.length());
	for (int i = 0; i != vts.length(); ++i) {
		nif_vts[i].position.x = float(vts[i].x);
		nif_vts[i].position.y = float(vts[i].y);
		nif_vts[i].position.z = float(vts[i].z);
	}

	//Set vertex info later since it includes skin weights
	//cs.SetVertices( nif_vts );

	//out << "Use the function set to get the colors" << endl;
	MColorArray myColors;
	meshFn.getFaceVertexColors(myColors);

	//out << "Prepare NIF color vector" << endl;
	vector<Color4> niColors(myColors.length());
	for (unsigned int i = 0; i < myColors.length(); ++i) {
		niColors[i] = Color4(myColors[i].r, myColors[i].g, myColors[i].b, myColors[i].a);
	}
	cs.SetColors(niColors);


	// this will hold the returned vertex positions
	MFloatVectorArray nmls;

	//out << "Use the function set to get the normals" << endl;
	// use the function set to get the normals
	stat = meshFn.getNormals(nmls, MSpace::kTransform);
	if (stat != MS::kSuccess) {
		//out << stat.errorString().asChar() << endl;
		throw runtime_error("Failed to get normals");
	}

	//out << "Prepare NIF normal vector" << endl;
	vector<Vector3> nif_nmls(nmls.length());
	for (int i = 0; i != nmls.length(); ++i) {
		nif_nmls[i].x = float(nmls[i].x);
		nif_nmls[i].y = float(nmls[i].y);
		nif_nmls[i].z = float(nmls[i].z);
	}
	cs.SetNormals(nif_nmls);

	//out << "Use the function set to get the UV set names" << endl;
	MStringArray uvSetNames;
	MString baseUVSet;
	MFloatArray myUCoords;
	MFloatArray myVCoords;
	bool has_uvs = false;

	// get the names of the uv sets on the mesh
	meshFn.getUVSetNames(uvSetNames);

	vector<TexCoordSet> nif_uvs;

	//Record assotiation between name and uv set index for later
	map<string, int> uvSetNums;

	int set_num = 0;
	for (unsigned int i = 0; i < uvSetNames.length(); ++i) {
		if (meshFn.numUVs(uvSetNames[i]) > 0) {
			TexType tt;
			string set_name = uvSetNames[i].asChar();
			if (set_name == "base" || set_name == "map1") {
				tt = BASE_MAP;
			}
			else if (set_name == "dark") {
				tt = DARK_MAP;
			}
			else if (set_name == "detail") {
				tt = DETAIL_MAP;
			}
			else if (set_name == "gloss") {
				tt = GLOSS_MAP;
			}
			else if (set_name == "glow") {
				tt = GLOW_MAP;
			}
			else if (set_name == "bump") {
				tt = BUMP_MAP;
			}
			else if (set_name == "decal0") {
				tt = DECAL_0_MAP;
			}
			else if (set_name == "decal1") {
				tt = DECAL_1_MAP;
			}
			else {
				tt = BASE_MAP;
			}

			//Record the assotiation
			uvSetNums[set_name] = set_num;

			//Get the UVs
			meshFn.getUVs(myUCoords, myVCoords, &uvSetNames[i]);

			//Make sure this set actually has some UVs in it.  Maya sometimes returns empty UV sets.
			if (myUCoords.length() == 0) {
				continue;
			}

			//Store the data
			TexCoordSet tcs;
			tcs.texType = tt;
			tcs.texCoords.resize(myUCoords.length());
			for (unsigned int j = 0; j < myUCoords.length(); ++j) {
				tcs.texCoords[j].u = myUCoords[j];
				//Flip the V coords
				tcs.texCoords[j].v = 1.0f - myVCoords[j];
			}
			nif_uvs.push_back(tcs);

			baseUVSet = uvSetNames[i];
			has_uvs = true;

			set_num++;
		}
	}

	cs.SetTexCoordSets(nif_uvs);

	// this will hold references to the shaders used on the meshes
	MObjectArray Shaders;

	// this is used to hold indices to the materials returned in the object array
	MIntArray    FaceIndices;

	//out << "Get the connected shaders" << endl;
	// get the shaders used by the i'th mesh instance
	// Assume this is not instanced for now
	// TODO support instancing properly
	stat = visibleMeshFn.getConnectedShaders(0, Shaders, FaceIndices);

	if (stat != MS::kSuccess) {
		//out << stat.errorString().asChar() << endl;
		throw runtime_error("Failed to get connected shader list.");

	}

	vector<ComplexFace> nif_faces;


	//Add shaders to propGroup array
	vector< vector<NiPropertyRef> > propGroups;
	for (unsigned int shader_num = 0; shader_num < Shaders.length(); ++shader_num) {

		//Maya sometimes lists shaders that are not actually attached to any face.  Disregard them.
		bool shader_is_used = false;
		for (size_t f = 0; f < FaceIndices.length(); ++f) {
			if (FaceIndices[f] == shader_num) {
				shader_is_used = true;
				break;
			}
		}

		if (shader_is_used == false) {
			//Shader isn't actually used, so continue to the next one.
			continue;
		}

		//out << "Found attached shader:  ";
		//Attach all properties previously associated with this shader to
		//this NiTriShape
		MFnDependencyNode fnDep(Shaders[shader_num]);

		//Find the shader that this shading group connects to
		MPlug p = fnDep.findPlug("surfaceShader");
		MPlugArray plugs;
		p.connectedTo(plugs, true, false);
		for (unsigned int i = 0; i < plugs.length(); ++i) {
			if (plugs[i].node().hasFn(MFn::kLambert)) {
				fnDep.setObject(plugs[i].node());
				break;
			}
		}

		//out << fnDep.name().asChar() << endl;
		vector<NiPropertyRef> niProps = this->translatorData->shaders[fnDep.name().asChar()];

		propGroups.push_back(niProps);
	}
	cs.SetPropGroups(propGroups);

	//out << "Export vertex and normal data" << endl;
	// attach an iterator to the mesh
	MItMeshPolygon itPoly(mesh, &stat);
	if (stat != MS::kSuccess) {
		throw runtime_error("Failed to create polygon iterator.");
	}

	// Create a list of faces with vertex IDs, and duplicate normals so they have the same ID
	for (; !itPoly.isDone(); itPoly.next()) {
		int poly_vert_count = itPoly.polygonVertexCount(&stat);

		if (stat != MS::kSuccess) {
			throw runtime_error("Failed to get vertex count.");
		}

		//Ignore polygons with less than 3 vertices
		if (poly_vert_count < 3) {
			continue;
		}

		ComplexFace cf;

		//Assume all faces use material 0 for now
		cf.propGroupIndex = 0;

		for (int i = 0; i < poly_vert_count; ++i) {
			ComplexPoint cp;

			cp.vertexIndex = itPoly.vertexIndex(i);
			cp.normalIndex = itPoly.normalIndex(i);
			if (niColors.size() > 0) {
				int color_index;
				stat = meshFn.getFaceVertexColorIndex(itPoly.index(), i, color_index);
				if (stat != MS::kSuccess) {
					//out << stat.errorString().asChar() << endl;
					throw runtime_error("Failed to get vertex color.");
				}
				cp.colorIndex = color_index;
			}

			//Get the UV set names used by this particular vertex
			MStringArray vertUvSetNames;
			itPoly.getUVSetNames(vertUvSetNames);
			for (unsigned int j = 0; j < vertUvSetNames.length(); ++j) {
				TexCoordIndex tci;
				tci.texCoordSetIndex = uvSetNums[vertUvSetNames[j].asChar()];
				int uv_index;
				itPoly.getUVIndex(i, uv_index, &vertUvSetNames[j]);
				tci.texCoordIndex = uv_index;
				cp.texCoordIndices.push_back(tci);
			}
			cf.points.push_back(cp);
		}
		nif_faces.push_back(cf);
	}

	//Set shader/face association
	if (nif_faces.size() != FaceIndices.length()) {
		throw runtime_error("Num faces found do not match num faces reported.");
	}
	for (unsigned int face_index = 0; face_index < nif_faces.size(); ++face_index) {
		nif_faces[face_index].propGroupIndex = FaceIndices[face_index];
	}

	cs.SetFaces(nif_faces);

	//--Skin Processing--//

	//Look up any skin clusters
	if (this->translatorData->meshClusters.find(visibleMeshFn.fullPathName().asChar()) != this->translatorData->meshClusters.end()) {
		const vector<MObject> & clusters = this->translatorData->meshClusters[visibleMeshFn.fullPathName().asChar()];
		if (clusters.size() > 1) {
			throw runtime_error("Objects with multiple skin clusters affecting them are not currently supported.  Try deleting the history and re-binding them.");
		}

		vector<MObject>::const_iterator cluster = clusters.begin();
		if (cluster->isNull() != true) {
			MFnSkinCluster clusterFn(*cluster);


			//out << "Processing skin..." << endl;
			//Get path to visible mesh
			MDagPath meshPath;
			visibleMeshFn.getPath(meshPath);

			//out << "Getting a list of all verticies in this mesh" << endl;
			//Get a list of all vertices in this mesh
			MFnSingleIndexedComponent compFn;
			MObject vertices = compFn.create(MFn::kMeshVertComponent);
			MItGeometry gIt(meshPath);
			MIntArray vertex_indices(gIt.count());
			for (int vert_index = 0; vert_index < gIt.count(); ++vert_index) {
				vertex_indices[vert_index] = vert_index;
			}
			compFn.addElements(vertex_indices);

			//out << "Getting Influences" << endl;
			//Get influences
			MDagPathArray myBones;
			clusterFn.influenceObjects(myBones, &stat);

			//out << "Creating a list of NiNodeRefs of influences." << endl;
			//Create list of NiNodeRefs of influences
			vector<NiNodeRef> niBones(myBones.length());
			for (unsigned int bone_index = 0; bone_index < niBones.size(); ++bone_index) {
				const char* boneName = myBones[bone_index].fullPathName().asChar();
				if (this->translatorData->nodes.find(myBones[bone_index].fullPathName().asChar()) == this->translatorData->nodes.end()) {
					//There is a problem; one of the joints was not exported.  Abort.
					throw runtime_error("One of the joints necessary to export a bound skin was not exported.");
				}
				niBones[bone_index] = this->translatorData->nodes[myBones[bone_index].fullPathName().asChar()];
			}

			//out << "Getting weights from Maya" << endl;
			//Get weights from Maya
			MDoubleArray myWeights;
			unsigned int bone_count = myBones.length();
			stat = clusterFn.getWeights(meshPath, vertices, myWeights, bone_count);
			if (stat != MS::kSuccess) {
				//out << stat.errorString().asChar() << endl;
				throw runtime_error("Failed to get vertex weights.");
			}

			//out << "Setting skin influence list in ComplexShape" << endl;
			//Set skin information in ComplexShape
			cs.SetSkinInfluences(niBones);

			//out << "Adding weights to ComplexShape vertices" << endl;
			//out << "Number of weights:  " << myWeights.length() << endl;
			//out << "Number of bones:  " << myBones.length() << endl;
			//out << "Number of Maya vertices:  " << gIt.count() << endl;
			//out << "Number of NIF vertices:  " << int(nif_vts.size()) << endl;
			unsigned int weight_index = 0;
			SkinInfluence sk;
			for (unsigned int vert_index = 0; vert_index < nif_vts.size(); ++vert_index) {
				for (unsigned int bone_index = 0; bone_index < myBones.length(); ++bone_index) {
					//out << "vert_index:  " << vert_index << "  bone_index:  " << bone_index << "  weight_index:  " << weight_index << endl;	
					// Only bother with weights that are significant
					if (myWeights[weight_index] > 0.0f) {
						sk.influenceIndex = bone_index;
						sk.weight = float(myWeights[weight_index]);

						nif_vts[vert_index].weights.push_back(sk);
					}
					++weight_index;
				}
			}
		}

		MPlugArray connected_dismember_plugs;
		MObjectArray dismember_nodes;
		meshFn.findPlug("message").connectedTo(connected_dismember_plugs, false, true);

		bool has_valid_dismemember_partitions = true;
		int faces_count = cs.GetFaces().size();
		int current_face_index;
		vector<BodyPartList> body_parts_list;
		vector<uint> dismember_faces(faces_count, 0);

		for (int x = 0; x < connected_dismember_plugs.length(); x++) {
			MFnDependencyNode dependency_node(connected_dismember_plugs[x].node());
			if (dependency_node.typeName() == "nifDismemberPartition") {
				dismember_nodes.append(dependency_node.object());
			}
		}

		if (dismember_nodes.length() == 0) {
			has_valid_dismemember_partitions = false;
		}
		else {
			int blind_data_id;
			int blind_data_value;
			MStatus status;
			MPlug target_faces_plug;
			MItMeshPolygon it_polygons(meshFn.object());
			MString mel_command;
			MStringArray current_body_parts_flags;
			MFnDependencyNode current_dismember_node;
			MFnDependencyNode current_blind_data_node;

			//Naive sort here, there is no reason and is extremely undesirable and not recommended to have more
			//than 10-20 dismember partitions out of many reasons, so it's okay here
			//as it makes the code easier to understand
			vector<int> dismember_nodes_id(dismember_nodes.length(), -1);
			for (int x = 0; x < dismember_nodes.length(); x++) {
				current_dismember_node.setObject(dismember_nodes[x]);
				connected_dismember_plugs.clear();
				current_dismember_node.findPlug("targetFaces").connectedTo(connected_dismember_plugs, true, false);
				if (connected_dismember_plugs.length() == 0) {
					has_valid_dismemember_partitions = false;
					break;
				}
				current_blind_data_node.setObject(connected_dismember_plugs[0].node());
				dismember_nodes_id[x] = current_blind_data_node.findPlug("typeId").asInt();
			}
			for (int x = 0; x < dismember_nodes.length() - 1; x++) {
				for (int y = x + 1; y < dismember_nodes.length(); y++) {
					if (dismember_nodes_id[x] > dismember_nodes_id[y]) {
						MObject aux = dismember_nodes[x];
						blind_data_id = dismember_nodes_id[x];
						dismember_nodes[x] = dismember_nodes[y];
						dismember_nodes_id[x] = dismember_nodes_id[y];
						dismember_nodes[y] = aux;
						dismember_nodes_id[y] = blind_data_id;
					}
				}
			}

			for (int x = 0; x < dismember_nodes.length(); x++) {
				current_dismember_node.setObject(dismember_nodes[x]);
				target_faces_plug = current_dismember_node.findPlug("targetFaces");
				connected_dismember_plugs.clear();
				target_faces_plug.connectedTo(connected_dismember_plugs, true, false);
				if (connected_dismember_plugs.length() > 0) {
					current_blind_data_node.setObject(connected_dismember_plugs[0].node());
					current_face_index = 0;
					blind_data_id = current_blind_data_node.findPlug("typeId").asInt();
					for (it_polygons.reset(); !it_polygons.isDone(); it_polygons.next()) {
						if (it_polygons.polygonVertexCount() >= 3) {
							status = meshFn.getIntBlindData(it_polygons.index(), MFn::Type::kMeshPolygonComponent, blind_data_id, "dismemberValue", blind_data_value);
							if (status == MStatus::kSuccess && blind_data_value == 1 &&
								meshFn.hasBlindDataComponentId(it_polygons.index(), MFn::Type::kMeshPolygonComponent, blind_data_id)) {
								dismember_faces[current_face_index] = x;
							}
							current_face_index++;
						}
					}
				}
				else {
					has_valid_dismemember_partitions = false;
					break;
				}

				mel_command = "getAttr ";
				mel_command += current_dismember_node.name();
				mel_command += ".bodyPartsFlags";
				status = MGlobal::executeCommand(mel_command, current_body_parts_flags);
				BSDismemberBodyPartType body_part_type = NifDismemberPartition::stringArrayToBodyPartType(current_body_parts_flags);
				current_body_parts_flags.clear();

				mel_command = "getAttr ";
				mel_command += current_dismember_node.name();
				mel_command += ".partsFlags";
				status = MGlobal::executeCommand(mel_command, current_body_parts_flags);
				BSPartFlag part_type = NifDismemberPartition::stringArrayToPart(current_body_parts_flags);
				current_body_parts_flags.clear();

				BodyPartList body_part;
				body_part.bodyPart = body_part_type;
				body_part.partFlag = part_type;
				body_parts_list.push_back(body_part);
			}
		}

		if (has_valid_dismemember_partitions == false) {
			MGlobal::displayWarning("No proper dismember partitions, generating default ones for " + meshFn.name());

			for (int x = 0; x < dismember_faces.size(); x++) {
				dismember_faces[x] = 0;
			}

			BodyPartList body_part;
			body_part.bodyPart = (BSDismemberBodyPartType)0;
			body_part.partFlag = (BSPartFlag)(PF_EDITOR_VISIBLE | PF_START_NET_BONESET);
			body_parts_list.clear();
			body_parts_list.push_back(body_part);
		}

		cs.SetDismemberPartitionsBodyParts(body_parts_list);
		cs.SetDismemberPartitionsFaces(dismember_faces);
	}

	//out << "Setting vertex info" << endl;
	//Set vertex info now that any skins have been processed
	cs.SetVertices(nif_vts);

	//ComplexShape is now complete, so split it

	//Get parent
	NiNodeRef parNode = this->translatorUtils->GetDAGParent(dagNode);
	Matrix44 transform = Matrix44::IDENTITY;
	vector<NiNodeRef> influences = cs.GetSkinInfluences();
	if (influences.size() > 0) {
		//This is a skin, so we use the common ancestor of all influences
		//as the parent
		vector<NiAVObjectRef> objects;
		for (size_t i = 0; i < influences.size(); ++i) {
			objects.push_back(StaticCast<NiAVObject>(influences[i]));
		}

		//Get world transform of existing parent
		Matrix44 oldParWorld = parNode->GetWorldTransform();

		//Set new parent node
		parNode = FindCommonAncestor(objects);

		transform = oldParWorld * parNode->GetWorldTransform().Inverse();
	}

	//Get transform using temporary NiAVObject
	NiAVObjectRef tempAV = new NiAVObject;
	this->nodeExporter->ExportAV(tempAV, dagNode);

	NiAVObjectRef avObj;
	if (this->translatorOptions->exportTangentSpace == "falloutskyrimtangentspace") {
		//out << "Split ComplexShape from " << meshFn.name().asChar() << endl;
		avObj = cs.Split(parNode, tempAV->GetLocalTransform() * transform, this->translatorOptions->exportBonesPerSkinPartition,
			this->translatorOptions->exportAsTriStrips, true, this->translatorOptions->exportMinimumVertexWeight, 16);
	}
	else {
		avObj = cs.Split(parNode, tempAV->GetLocalTransform() * transform, this->translatorOptions->exportBonesPerSkinPartition,
			this->translatorOptions->exportAsTriStrips, false, this->translatorOptions->exportMinimumVertexWeight);
	}


	//out << "Get the NiAVObject portion of the root of the split" <<endl;
	//Get the NiAVObject portion of the root of the split
	avObj->SetName(tempAV->GetName());
	avObj->SetVisibility(tempAV->GetVisibility());
	avObj->SetFlags(tempAV->GetFlags());

	//If polygon mesh is hidden, hide tri_shape
	MPlug vis = visibleMeshFn.findPlug(MString("visibility"));
	bool visibility;
	vis.getValue(visibility);


	NiNodeRef splitRoot = DynamicCast<NiNode>(avObj);
	if (splitRoot != NULL) {
		//Root is a NiNode with NiTriBasedGeom children.
		vector<NiAVObjectRef> children = splitRoot->GetChildren();
		for (unsigned c = 0; c < children.size(); ++c) {
			//Set the default collision propogation flag to "use triangles"
			children[c]->SetFlags(2);
			// Make the mesh invisible if necessary
			if (visibility == false) {
				children[c]->SetVisibility(false);
			}
		}

	}
	else {
		//Root must be a NiTriBasedGeom.  Make it invisible if necessary
		if (visibility == false) {
			avObj->SetVisibility(false);
		}
	}

}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
0
NiNodeRef NifConvertUtility::convertNiNode(NiNodeRef pSrcNode, NiTriShapeRef pTmplNode, NiNodeRef pRootNode, NiAlphaPropertyRef pTmplAlphaProp)
{
	
	
	NiNodeRef				pDstNode    (pSrcNode);
	

	//pDstNode->SetName(pDstNode->GetName().replace(
	string node_name_in = pDstNode->GetName();
	string node_name_out = "";
	for (int i = 0; i < node_name_in.length(); i++)
	{
		if (node_name_in[i] != '.' && node_name_in[i] != '_' && node_name_in[i] != ' ')
		{
			node_name_out = node_name_out + node_name_in[i];
		}
	}

	pDstNode->SetName(node_name_out);
	node_name_in = node_name_out;

	if (node_name_in.compare("AttachLight") == 0)
	{
		Vector3 tr = pDstNode->GetLocalTranslation();
		tr.z += 10.0f;
		pDstNode->SetLocalTranslation(tr);
		
	}
	
	if (node_name_in.compare("ShadowBox") == 0)
	{
		cout << "Removing ShadowBox" << endl;
		pDstNode->ClearChildren();
	}

	if (toLower(node_name_in).find("fireemit") != -1)
	{
		NiExtraDataRef ed = root_bsafade->GetExtraData().front();
		NiIntegerExtraDataRef iref = DynamicCast<NiIntegerExtraData>(ed);

		iref->SetData(147);
		
		cout << "Adding TorchFlame Addon" << endl;
		BSValueNodeRef candle_flame = new BSValueNode();
		candle_flame->SetName("AddOnNode");
		candle_flame->value = 46;
		pDstNode->AddChild(DynamicCast<NiAVObject>(candle_flame));
	}

	else if (node_name_in.find("CandleFlame") != -1)
	{
		NiExtraDataRef ed = root_bsafade->GetExtraData().front();
		NiIntegerExtraDataRef iref = DynamicCast<NiIntegerExtraData>(ed);

		iref->SetData(147);
		
		cout << "Adding CandleFlame Addon" << endl;
		BSValueNodeRef candle_flame = new BSValueNode();
		candle_flame->SetName("AddOnNode");
		candle_flame->value = 49;
		pDstNode->AddChild(DynamicCast<NiAVObject>(candle_flame));
	}


		

	
	vector<NiAVObjectRef>	srcShapeList(pDstNode->GetChildren());

	//if (!pDstNode->GetType().IsSameType(NiNode::TYPE) && !pDstNode->GetType().IsSameType(BSFadeNode::TYPE) && !pDstNode->GetType().IsSameType(NiTriShape::TYPE) && !pDstNode->GetType().IsSameType(NiTriStrips::TYPE))
	{

	}

	//  find NiAlphaProperty and use as template in sub-nodes
	if (DynamicCast<NiAlphaProperty>(pDstNode->GetPropertyByType(NiAlphaProperty::TYPE)) != NULL)
	{
		pTmplAlphaProp = DynamicCast<NiAlphaProperty>(pDstNode->GetPropertyByType(NiAlphaProperty::TYPE));
	}

	//  unlink protperties -> not used in new format
	pDstNode->ClearProperties();

	//  shift extra data to new version
	pDstNode->ShiftExtraData(VER_20_2_0_7);

	//  unlink children
	pDstNode->ClearChildren();
	pDstNode->ClearEffects();	
	pDstNode->ClearControllers();

	if (!pDstNode->GetType().IsSameType(BSFadeNode::TYPE))
	{
		pDstNode->ClearExtraData();
	}
	//  iterate over source nodes and convert using template
	for (auto  ppIter=srcShapeList.begin(), pEnd=srcShapeList.end(); ppIter != pEnd; ppIter++)
	{
		
		//DynamicCast<NiTriShape>(*ppIter) == NULL && DynamicCast<NiTriStrips>(*ppIter) == NULL ** DynamicCast<NiTriStrips>(*ppIter) != NULL

		

		//  NiTriShape
		if (DynamicCast<NiTriShape>(*ppIter) != NULL)
		{
			pDstNode->AddChild(&(*convertNiTriShape(DynamicCast<NiTriShape>(*ppIter), pTmplNode, pTmplAlphaProp)));
		}
		//  NiTriStrips
		else if (DynamicCast<NiTriStrips>(*ppIter) != NULL)
		{
			pDstNode->AddChild(&(*convertNiTriStrips(DynamicCast<NiTriStrips>(*ppIter), pTmplNode, pTmplAlphaProp)));
		}
		//  RootCollisionNode
		else if ((DynamicCast<RootCollisionNode>(*ppIter) != NULL) && _cleanTreeCollision)
		{
			//  ignore node
		}
		//  NiNode (and derived classes?)
		else if (DynamicCast<NiNode>(*ppIter) != NULL)
		{
			NiNode* node_hashmi = DynamicCast<NiNode>(*ppIter);

						
			if (node_hashmi->GetType().IsSameType(NiNode::TYPE) || node_hashmi->GetType().IsSameType(BSFadeNode::TYPE) || node_hashmi->GetType().IsSameType(BSValueNode::TYPE))
				{
					pDstNode->AddChild(&(*convertNiNode(DynamicCast<NiNode>(*ppIter), pTmplNode, pRootNode, pTmplAlphaProp)));
				}
			

			
		}
	}

	//  remove collision object (newer version)
	if (_cleanTreeCollision)
	{
		pDstNode->SetCollisionObject(NULL);
	}
	else if (DynamicCast<bhkCollisionObject>(pDstNode->GetCollisionObject()) != NULL)
	{
		bhkRigidBodyRef		pBody(DynamicCast<bhkRigidBody>((DynamicCast<bhkCollisionObject>(pDstNode->GetCollisionObject()))->GetBody()));

		if (pBody != NULL)
		{
			parseCollisionTree(pBody->GetShape());
		}
	}

	return pDstNode;
}
Ejemplo n.º 15
0
/*---------------------------------------------------------------------------*/
NiNodeRef NifPrepareUtility::parse4Armor(NiNodeRef pNode, BSLightingShaderPropertyRef pShaderTmpl)
{
	vector<NiAVObjectRef>	childList(pNode->GetChildren());

	//  unlink children
	pNode->ClearChildren();

	//  iterate over children
	for (auto pIter(childList.begin()), pEnd(childList.end()); pIter != pEnd; pIter++)
	{
		//  NiTriShape => remodel BSLightingShaderProperty
		if (DynamicCast<NiTriShape>(*pIter) != NULL)
		{
			NiTriShapeRef				pShape  (DynamicCast<NiTriShape>(*pIter));
			BSDismemberSkinInstanceRef	pSkin   (DynamicCast<BSDismemberSkinInstance>(pShape->GetSkinInstance()));
			vector<NiPropertyRef>		propList(pShape->GetProperties());

			//  part of skin data? => modify skin code
			if (pSkin != NULL)
			{
				vector<BodyPartList>	bPartList(pSkin->GetPartitions());

				for (auto pIter(bPartList.begin()), pEnd(bPartList.end()); pIter != pEnd; pIter++)
				{
					if (_bodyPartMap.count(pIter->bodyPart) > 0)
					{
						pIter->bodyPart = (BSDismemberBodyPartType) _bodyPartMap[pIter->bodyPart];
					}
				}  //  for (auto pIter(bPartList.begin()), pEnd(bPartList.end()); pIter != pEnd; pIter++)

				//  set modified parts
				pSkin->SetPartitions(bPartList);

			}  //  if (pSkin != NULL)

			//  remove all properties
			pShape->ClearProperties();

			//  create new BSLightingShaderProperty if template given
			if (pShaderTmpl != NULL)
			{
				//  check properties
				for (auto pIterProp(propList.begin()), pEnd(propList.end()); pIterProp != pEnd; pIterProp++)
				{
					//  convert BSShaderPPLightingProperty to BSLightingShaderProperty
					if (DynamicCast<BSShaderPPLightingProperty>(*pIterProp) != NULL)
					{
						BSShaderPPLightingProperty*	pPProp(DynamicCast<BSShaderPPLightingProperty>(*pIterProp));
						BSLightingShaderProperty*	pLProp(new BSLightingShaderProperty());

						//  move texture set
						pLProp->SetTextureSet(pPProp->GetTextureSet());
						pPProp->SetTextureSet(NULL);

						pLProp->SetShaderFlags1       (pShaderTmpl->GetShaderFlags1());
						pLProp->SetShaderFlags2       (pShaderTmpl->GetShaderFlags2());
						pLProp->SetEmissiveMultiple   (pShaderTmpl->GetEmissiveMultiple());
						pLProp->SetEmissiveColor      (pShaderTmpl->GetEmissiveColor());
						pLProp->SetLightingEffect1    (pShaderTmpl->GetLightingEffect1());
						pLProp->SetLightingEffect2    (pShaderTmpl->GetLightingEffect2());
						pLProp->SetEnvironmentMapScale(pShaderTmpl->GetEnvironmentMapScale());
						pLProp->SetSkyrimShaderType   (pShaderTmpl->GetSkyrimShaderType());
						pLProp->SetSpecularColor      (pShaderTmpl->GetSpecularColor());
						pLProp->SetSpecularStrength   (pShaderTmpl->GetSpecularStrength());
						pLProp->SetTextureClampMode   (pShaderTmpl->GetTextureClampMode());
						pLProp->SetUnknownFloat2      (pShaderTmpl->GetUnknownFloat2());
						pLProp->SetGlossiness         (pShaderTmpl->GetGlossiness());

						//  add property to shape
						pShape->SetBSProperty(0, pLProp);
					}
				}  //  for (auto pIterProp(propList.begin()), pEnd(propList.end()); pIterProp != pEnd; pIterProp++)
			}  //  if (pShaderTmpl != NULL)

			//  add shape to node
			pNode->AddChild(*pIter);
		}
		//  NiNode (and derived classes?) => iterate subnodes
		else if (DynamicCast<NiNode>(*pIter) != NULL)
		{
			pNode->AddChild(&(*parse4Armor(DynamicCast<NiNode>(*pIter), pShaderTmpl)));
		}
	}  //  for (auto pIter(childList.begin()), pEnd(childList.end()); pIter != pEnd; pIter++)

	return pNode;
}
Ejemplo n.º 16
0
/*---------------------------------------------------------------------------*/
bool NifCollisionUtility::parseTreeCollision(NiNodeRef pNode, string fileNameCollTmpl, vector<hkGeometry>& geometryMapColl)
{
	vector<NiAVObjectRef>	srcChildList (pNode->GetChildren());	//  get list of children from input node
	bool					haveCollision(false);

	//  check for own collision object
	if (DynamicCast<bhkCollisionObject>(pNode->GetCollisionObject()) != NULL)
	{
		bhkCollisionObjectRef	pCollObj(DynamicCast<bhkCollisionObject>(pNode->GetCollisionObject()));
		bhkRigidBodyRef			pRBody  (DynamicCast<bhkRigidBody>      (pCollObj->GetBody()));

		//  check on valid body
		if (pRBody != NULL)
		{
			array<7, unsigned short>	unknown7(pRBody->GetUnknown7Shorts());

			//  force SKYRIM values
			unknown7[3] = 0;
			unknown7[4] = 0;
			unknown7[5] = 1;
			unknown7[6] = 65535;
			pRBody->SetUnknown7Shorts(unknown7);
			pRBody->SetTranslation(pRBody->GetTranslation() * 0.1f);

			pRBody->SetShape(parseCollisionShape(fileNameCollTmpl, pRBody->GetShape(), pRBody));

		}  //  if (pRBody != NULL)

		haveCollision |= true;

	}  //  if (DynamicCast<bhkCollisionObject>(pNode->GetCollisionObject()) != NULL)

	//  iterate over source nodes and get geometry
	for (vector<NiAVObjectRef>::iterator  ppIter = srcChildList.begin(); ppIter != srcChildList.end(); ppIter++)
	{
		//  RootCollisionNode
		if (DynamicCast<RootCollisionNode>(*ppIter) != NULL)
		{
			NiNodeRef				pRootTemplate(DynamicCast<BSFadeNode>(ReadNifTree((const char*) fileNameCollTmpl.c_str())));
			vector<hkGeometry>		geometryMapCollLocal;
			vector<Matrix44>		transformAryLocal;

			//  get template
			if (pRootTemplate != NULL)
			{
				bhkCollisionObjectRef	pCollNodeTmpl(DynamicCast<bhkCollisionObject>(pRootTemplate->GetCollisionObject()));

				if (pCollNodeTmpl != NULL)
				{
					//  get collision data from sub-nodes
					getGeometryFromNode(&(*DynamicCast<RootCollisionNode>(*ppIter)), geometryMapCollLocal, geometryMapCollLocal, transformAryLocal);

					//  replace collision object
					pNode->SetCollisionObject(createCollNode(geometryMapCollLocal, pCollNodeTmpl, pNode));
					pNode->RemoveChild(*ppIter);

					haveCollision |= true;

				}  //  if (pCollNodeTmpl == NULL)
			}  //  if (pRootTemplate != NULL)
		}
		//  NiNode (and derived classes?)
		else if (DynamicCast<NiNode>(*ppIter) != NULL)
		{
			haveCollision |= parseTreeCollision(DynamicCast<NiNode>(*ppIter), fileNameCollTmpl, geometryMapColl);
		}
	}  //  for (vector<NiAVObjectRef>::iterator  ppIter = srcChildList.begin(); ppIter != srcChildList.end(); ppIter++)

	return haveCollision;
}
Ejemplo n.º 17
0
void NifImporter::AlignBiped(IBipMaster* master, NiNodeRef node)
{
#ifdef USE_BIPED
   NiNodeRef parent = node->GetParent();
   string name = node->GetName();
   vector<NiAVObjectRef> children = node->GetChildren();
   vector<NiNodeRef> childNodes = DynamicCast<NiNode>(children);

   TSTR s1 = FormatText("Processing %s:", name.c_str());
   TSTR s2 = FormatText("Processing %s:", name.c_str());
   INode *bone = GetNode(node);
   if (bone != NULL) 
   {
      if (uncontrolledDummies)
         BuildControllerRefList(node, ctrlCount);

      Matrix44 m4 = node->GetWorldTransform();
      Vector3 pos; Matrix33 rot; float scale;
      m4.Decompose(pos, rot, scale);
      Matrix3 m = TOMATRIX3(m4);
      Point3 p = m.GetTrans();
      Quat q(m);

      s1 += FormatText(" ( %s)", PrintMatrix3(m).data());
      if (strmatch(name, master->GetRootName()))
      {
         // Align COM
         //PosRotScaleNode(bone, p, q, 1.0f, prsPos);
         PosRotScaleBiped(master, bone, p, q, 1.0f, prsPos);
      }
      else if (INode *pnode = bone->GetParentNode())
      {
         // Reparent if necessary
         if (!strmatch(parent->GetName(), pnode->GetName())) {
            if (pnode = FindNode(parent)) {
               bone->Detach(0);
               pnode->AttachChild(bone);
            }
         }

         // Hack to scale the object until it fits
         for (int i=0; i<10; ++i) {
            float s = CalcScale(bone, node, childNodes);
            if (fabs(s-1.0f) < (FLT_EPSILON*100.0f))
               break;
            s1 += FormatText(" (%g)", s);
            master->SetBipedScale(TRUE, ScaleValue(Point3(s,s,s)), 0, bone);
         }
         PosRotScale prs = prsDefault;
         PosRotScaleBiped(master, bone, p, q, scale, prs);

         // Rotation with Clavicle is useless in Figure Mode using the standard interface
         //   I was tring unsuccessfully to correct for it
         //if (wildcmpi("Bip?? ? Clavicle", name.c_str())) {
         //   AngAxis a1 = CalcTransform(bone, node, childNodes);
         //   Matrix3 tm1 = GenerateRotMatrix(a1);
         //   Quat nq = TransformQuat(tm1, q);
         //   PosRotScaleNode(bone, p, nq, scale, prsRot);
         //}
      }
      s2 += FormatText(" ( %s)", PrintMatrix3(bone->GetNodeTM(0)).data());
   }
   else
   {
      ImportBones(node, false);
   }
   for (char *p = s1; *p != 0; ++p) if (isspace(*p)) *p = ' ';
   for (char *p = s2; *p != 0; ++p) if (isspace(*p)) *p = ' ';
   OutputDebugString(s1 + "\n");
   OutputDebugString(s2 + "\n");

   for (vector<NiNodeRef>::iterator itr = childNodes.begin(), end = childNodes.end(); itr != end; ++itr){
      AlignBiped(master, *itr);
   }
#endif
}
Ejemplo n.º 18
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( ... ) 
   {
   }
}
Ejemplo n.º 19
0
unsigned long CMesh::Load_Mesh(unsigned long want_formID)
{
	unsigned long index;
	CStat_Record *dastat;
	MeshData *dameshdata;
	char tmppath[MAX_PATH];

	dastat=pTreeManager->GetStat(want_formID);
	if(dastat==NULL) return 1;

	formID=want_formID;

	strcpy_s(tmppath,MAX_PATH,"data\\meshes\\");
	strcat_s(tmppath,MAX_PATH,dastat->Get_Filename());

	//output_text_char(L"Filename: ",tmppath);
	
	NiObjectRef root=ReadNifTree(tmppath);

	NiNodeRef node = DynamicCast<NiNode>(root);
	if(node==NULL) return 2;

	vector<NiAVObjectRef> refs=node->GetChildren();
	for(index=0;index<refs.size();index++)
	{
		if(refs[index]->IsSameType(NiTriStrips::TYPE))
		{
			NiTriStripsRef datristrip=DynamicCast<NiTriStrips>(refs[index]);
			//Add a tri strip buffer to the mesh
			dameshdata=AddTriStrips(datristrip);
			if(dameshdata==NULL)
			{
				output_text(L"Error AddTriStrips\r\n");
				return 3;
			}
			Vector3 translation=datristrip->GetLocalTranslation();
			dameshdata->local_translation[0]=translation.x;
			dameshdata->local_translation[1]=translation.y;
			dameshdata->local_translation[2]=translation.z;
			dameshdata->tristrip=1;
		}
		else
		{
			if(refs[index]->IsSameType(NiTriShape::TYPE))
			{
				NiTriShapeRef datrishape=DynamicCast<NiTriShape>(refs[index]);
				//Add a tri shape to the mesh
				dameshdata=AddTriShape(datrishape);
				if(dameshdata==NULL)
				{
					output_text(L"Error AddTriShape\r\n");
					return 3;
				}
				Vector3 translation=datrishape->GetLocalTranslation();
				dameshdata->local_translation[0]=translation.x;
				dameshdata->local_translation[1]=translation.y;
				dameshdata->local_translation[2]=translation.z;
				dameshdata->tristrip=0;
			}
		}
	}

	//Load the collision data
	/*NiCollisionObjectRef dacol=node->GetCollisionObject();
	if(dacol->IsSameType(bhkCollisionObject::TYPE))
	{
		bhkCollisionObjectRef bhkCol=DynamicCast<bhkCollisionObject>(dacol);
		NiObjectRef daobj=bhkCol->GetBody();
		if(daobj->IsSameType(bhkRigidBody::TYPE))
		{
			bhkRigidBody
		}
		
	}*/

	return 0;
}
Ejemplo n.º 20
0
bool NifImporter::DoImport()
{
   bool ok = true;
   if (!suppressPrompts)
   {
      if (!ShowDialog())
         return true;

      ApplyAppSettings();
      SaveIniSettings();
   }

   vector<string> importedBones;
   if (!isBiped && importSkeleton && importBones)
   {
      if (importSkeleton && !skeleton.empty()) {
         try
         {
            NifImporter skelImport(skeleton.c_str(), i, gi, suppressPrompts);
            if (skelImport.isValid())
            {
               // Enable Skeleton specific items
               skelImport.isBiped = true;
               skelImport.importBones = true;
               // Disable undesirable skeleton items
               skelImport.enableCollision = false;
               skelImport.enableAnimations = false;
               skelImport.suppressPrompts = true;
               skelImport.DoImport();
               if (!skelImport.useBiped && removeUnusedImportedBones)
                  importedBones = GetNamesOfNodes(skelImport.nodes);
            }
         }
         catch (RuntimeError &error)
         {
            // ignore import errors and continue
         }
      }
   } else if (hasSkeleton && useBiped && importBones) {
      ImportBipeds(nodes);
   }

   if (isValid()) {

      if (root->IsDerivedType(NiNode::TYPE))
      {
         NiNodeRef rootNode = root;

		 if (importBones) {
			 if (ignoreRootNode || strmatch(rootNode->GetName(), "Scene Root")) {
				 RegisterNode(root, gi->GetRootNode());
				 ImportBones(DynamicCast<NiNode>(rootNode->GetChildren()));
			 } else {
				 ImportBones(rootNode);
			 }
		 }


         if (enableLights){
            ok = ImportLights(rootNode);
         }

         ok = ImportMeshes(rootNode);

		 // Import Havok Collision Data surrounding node
		 if (enableCollision) {
			 ImportCollision(rootNode);
		 }

         if (importSkeleton && removeUnusedImportedBones){
            vector<string> importedNodes = GetNamesOfNodes(nodes);
            sort(importedBones.begin(), importedBones.end());
            sort(importedNodes.begin(), importedNodes.end());
            vector<string> results;
            results.resize(importedBones.size());
            vector<string>::iterator end = set_difference ( 
               importedBones.begin(), importedBones.end(),
               importedNodes.begin(), importedNodes.end(), results.begin());
            for (vector<string>::iterator itr = results.begin(); itr != end; ++itr){
               if (INode *node = gi->GetINodeByName((*itr).c_str())){
				   gi->DeleteNode(node, FALSE);
               }
            }
         }
      }
      else if (root->IsDerivedType(NiTriShape::TYPE))
      {
         ok |= ImportMesh(NiTriShapeRef(root));
      }
      else if (root->IsDerivedType(NiTriStrips::TYPE))
      {
         ok |= ImportMesh(NiTriStripsRef(root));
      }
   }

   ClearAnimation();
   ImportAnimation();
   return true;
}