NiNodeRef Exporter::createNode() { NiNodeRef node = CreateNiObject<NiNode>(); if (IsFallout3() || IsSkyrim()) { node->SetFlags(14); } return node; }
NiNodeRef Exporter::getNode(const string& name) { NodeMap::iterator itr = mNameMap.find(name); if (itr != mNameMap.end()) return (*itr).second; NiNodeRef node = CreateNiObject<NiNode>(); if ( IsFallout3() || IsSkyrim() ) { node->SetFlags( 14 ); } node->SetName(name); mNameMap[name] = node; return node; }
bool Exporter::makeSkin(NiTriBasedGeomRef shape, INode *node, FaceGroup &grp, TimeValue t) { if (!mExportSkin) return false; if (grp.verts.empty()) return false; //get the skin modifier Modifier *mod = GetSkin(node); if (!mod) return false; ISkin *skin = (ISkin *) mod->GetInterface(I_SKIN); if (!skin) return false; ISkinContextData *skinData = skin->GetContextInterface(node); if (!skinData) return false; if (grp.strips.empty()) strippify(grp); // Create new call back to finish export SkinInstance* si = new SkinInstance(this); mPostExportCallbacks.push_back(si); skin->GetSkinInitTM(node, si->bone_init_tm, false); skin->GetSkinInitTM(node, si->node_init_tm, true); si->shape = shape; // Get bone references (may not actually exist in proper structure at this time) int totalBones = skin->GetNumBones(); si->boneWeights.resize(totalBones); si->boneList.resize(totalBones); for (int i=0; i<totalBones; ++i) { si->boneList[i] = getNode(skin->GetBone(i)); } vector<int>& vidx = grp.vidx; int nv = vidx.size(); for (int i=0; i<nv; ++i) { int vi = vidx[i]; int nbones = skinData->GetNumAssignedBones(vi); for (int j=0; j<nbones; ++j) { SkinWeight sw; sw.index = i; sw.weight = skinData->GetBoneWeight(vi,j); int boneIndex = skinData->GetAssignedBone(vi,j); SkinInstance::SkinWeightList& weights = si->boneWeights[boneIndex]; weights.push_back(sw); } } // remove unused bones vector<NiNodeRef>::iterator bitr = si->boneList.begin(); SkinInstance::BoneWeightList::iterator switr = si->boneWeights.begin(); for (int i=0; i<totalBones; ++i) { vector<SkinWeight> &weights = (*switr); if (weights.empty()) { bitr = si->boneList.erase(bitr); switr = si->boneWeights.erase(switr); } else { ++bitr, ++switr; } } // Check for dismemberment if (IsFallout3() || IsSkyrim()) { Modifier *dismemberSkinMod = GetBSDismemberSkin(node); if (dismemberSkinMod) { if (IBSDismemberSkinModifier *disSkin = (IBSDismemberSkinModifier *) dismemberSkinMod->GetInterface(I_BSDISMEMBERSKINMODIFIER)){ Tab<IBSDismemberSkinModifierData*> modData = disSkin->GetModifierData(); if (modData.Count() >= 1) { IBSDismemberSkinModifierData* bsdsmd = modData[0]; si->SkinInstConstructor = BSDismemberSkinInstance::Create; Tab<BSDSPartitionData> &flags = bsdsmd->GetPartitionFlags(); GenericNamedSelSetList &fselSet = bsdsmd->GetFaceSelList(); FaceMap fmap; NiTriBasedGeomDataRef data = DynamicCast<NiTriBasedGeomData>(shape->GetData()); vector<Triangle> tris = data->GetTriangles(); for (int i=0; i<tris.size(); ++i) { Triangle tri = tris[i]; fmap[ rotate(tri) ] = i; } // Build up list of partitions and face to partition map si->partitions.resize(flags.Count()); si->facePartList.resize( grp.faces.size(), -1 ); for (int i=0; i<flags.Count(); ++i) { BodyPartList& bp = si->partitions[i]; bp.bodyPart = (BSDismemberBodyPartType)flags[i].bodyPart; bp.partFlag = (BSPartFlag)(flags[i].partFlag | PF_START_NET_BONESET); BitArray& fSelect = fselSet[i]; for (int j=0; j<fSelect.GetSize(); ++j){ if ( fSelect[j] ) { Triangle tri = grp.faces[grp.fidx[j]]; FaceMap::iterator fitr = fmap.find( rotate(tri) ); if (fitr != fmap.end()) si->facePartList[ (*fitr).second ] = i; } } } } } } } return true; }
NiTriBasedGeomRef Exporter::makeMesh(NiNodeRef &parent, Mtl *mtl, FaceGroup &grp, bool exportStrips) { NiTriBasedGeomRef shape; NiTriBasedGeomDataRef data; //if (Exporter::mFixNormals) { // FixNormals(grp.faces, grp.verts, grp.vnorms); //} if (exportStrips) { shape = new NiTriStrips(); data = new NiTriStripsData(grp.faces, !mUseAlternateStripper); } else { shape = new NiTriShape(); data = new NiTriShapeData(grp.faces); } if ( IsFallout3() || IsSkyrim() ) shape->SetFlags( 14 ); data->SetVertices(grp.verts); data->SetNormals(grp.vnorms); data->SetVertexIndices(grp.vidx); data->SetUVSetMap(grp.uvMapping); int nUVs = grp.uvs.size(); if ( IsFallout3() || IsSkyrim() ) nUVs = min(1, nUVs); data->SetUVSetCount(nUVs); for (int i =0;i<nUVs; ++i) { data->SetUVSet(i, grp.uvs[i]); } //if (IsSkyrim() && grp.vcolors.size() == 0) // grp.vcolors.resize(grp.verts.size(), Color4(1.0f,1.0f,1.0f,1.0f)); if (mVertexColors && grp.vcolors.size() > 0) { bool allWhite = true; Color4 white(1.0f, 1.0f, 1.0f, 1.0f); for (int i=0,n=grp.vcolors.size();i<n; ++i) { if (white != grp.vcolors[i]) { allWhite = false; break; } } if (!allWhite) data->SetVertexColors(grp.vcolors); } data->SetConsistencyFlags(CT_STATIC); shape->SetData(data); if (Exporter::mTangentAndBinormalExtraData && (Exporter::mNifVersionInt > VER_4_2_2_0)) { // enable traditional tangents and binormals for non-oblivion meshes if ( !IsOblivion() && (Exporter::mNifVersionInt >= VER_10_0_1_0) ) data->SetTspaceFlag( 0x01 ); shape->UpdateTangentSpace(Exporter::mTangentAndBinormalMethod); } parent->AddChild(DynamicCast<NiAVObject>(shape)); NiAVObjectRef av(DynamicCast<NiAVObject>(shape)); makeMaterial(av, mtl); shape->SetActiveMaterial(0); return shape; }