public StreamAndElement getStreamAndElement(NIFFile file, String elementName, int preferredIndex) { foreach (NifMeshStream streamRef in streamRefs) { for (int i = 0; i < streamRef.elementDescs.Count(); i++) { Pair <String, int> pair = streamRef.elementDescs[i]; String elemCheckName = pair.getKey(); int elemCheckIndex = pair.getValue(); if (preferredIndex == -1 || elemCheckIndex == preferredIndex) { if (elemCheckName.StartsWith(elementName)) { NiDataStream dataStream = (NiDataStream)file.getObject(streamRef.streamLinkID); if (dataStream == null) { Debug.Log("null dataStream"); } if (dataStream.streamElems == null) { Debug.Log("null dataStream.streamElems: " + dataStream); } if (i >= dataStream.streamElems.Count()) { Debug.Log("WARNING: Data stream does not have enough elements."); } else { NifStreamElement elem = dataStream.streamElems[i]; return(new StreamAndElement(streamRef, elem, dataStream)); } } } } } return(null); }
public static MeshData prepareMesh(NIFFile nf, NiMesh mesh) { bool IS_TERRAIN = (nf.getStringTable().Contains("terrainL1")); StreamAndElement indexStreamObj = mesh.getStreamAndElement(nf, "INDEX", -1); NifMeshStream indexStreamRef = indexStreamObj.streamRef; NiDataStream indexStream = indexStreamObj.dataStream; NifStreamElement indexElem = indexStreamObj.elem; StreamAndElement nStreamObj = mesh.getStreamAndElement(nf, "NORMAL", -1); NifMeshStream nStreamRef = nStreamObj.streamRef; NiDataStream nStream = nStreamObj.dataStream; NifStreamElement nElem = nStreamObj.elem; StreamAndElement uvStreamObj = mesh.getStreamAndElement(nf, "TEXCOORD", -1); StreamAndElement uv2StreamObj = mesh.getStreamAndElement(nf, "TEXCOORD", 1); StreamAndElement positionStreamObj = mesh.getStreamAndElement(nf, "POSITION", -1); NifMeshStream posStreamRef = positionStreamObj.streamRef; NiDataStream posStream = positionStreamObj.dataStream; NifStreamElement posElem = positionStreamObj.elem; DataType indexDataType = typeForNifDataType(indexStreamObj.elem.dataType); DataType posDataType = typeForNifDataType(positionStreamObj.elem.dataType); if (posDataType != DataType.FLOAT) { throw new Exception("Unknown position types"); } MeshData meshData = new MeshData(); List <Vector3> verts = meshData.verts; List <Vector2> uvs = meshData.uvs; List <List <int> > triangles = meshData.triangles; List <Vector3> inNormals = meshData.inNormals; List <BoneWeight> boneWeights = meshData.boneWeights; for (int i = 0; i < mesh.numSubMeshes; i++) { List <int> bonePalette = new List <int>(); int vOffset = verts.Count; /** vertices */ StreamRegion posRegion = posStream.streamRegions[posStreamRef.submeshRegionMap[i]]; int posOfs = posRegion.a * posStream.elemStride; int posEnd = posOfs + posRegion.b * posStream.elemStride; byte[] posStreamData = posStream.streamData; using (BinaryReader dis = new BinaryReader(new MemoryStream(posStreamData, posOfs, posEnd - posOfs))) { // Debug.Log("\tverts:" + posRegion.b); for (int v = 0; v < (posEnd - posOfs) / posStream.elemStride; v++) { float x = dis.readFloat(); float y = dis.readFloat(); float z = dis.readFloat(); verts.Add(new Vector3(x, y, z)); } //Debug.Log("pos: left over: " + (dis.BaseStream.Length - dis.BaseStream.Position)); } /** faces */ StreamRegion idxRegion = indexStream.streamRegions[indexStreamRef.submeshRegionMap[i]]; int idxOfs = idxRegion.a * indexStream.elemStride; DataType idxType = typeForNifDataType(indexStreamObj.elem.dataType); int idxEnd = idxOfs + idxRegion.b * indexStream.elemStride; byte[] idxStreamData = indexStream.streamData; List <int> tris = new List <int>(); using (BinaryReader dis = new BinaryReader(new MemoryStream(idxStreamData, idxOfs, idxEnd - idxOfs))) { for (int idx = 0; idx < (idxEnd - idxOfs) / indexStream.elemStride; idx++) { int v1x = (dis.readUnsignedShort()) + vOffset; tris.Add(v1x); } //Debug.Log("idx left over:" + (dis.BaseStream.Length - dis.BaseStream.Position)); } triangles.Add(tris); { /** uvs */ if (uvStreamObj != null) { NiDataStream uvStream = uvStreamObj.dataStream; StreamRegion uvRegion = uvStreamObj.dataStream.streamRegions[uvStreamObj.streamRef.submeshRegionMap[i]]; DataType uvType = typeForNifDataType(uvStreamObj.elem.dataType); int uvOfs = uvRegion.a * uvStream.elemStride; int uvEnd = uvOfs + uvRegion.b * uvStream.elemStride; byte[] uvStreamData = uvStream.streamData; //Debug.Log("uv datatype:" + uvType + ":" + uvStream.elemStride); using (BinaryReader dis = new BinaryReader(new MemoryStream(uvStreamData, uvOfs, uvEnd - uvOfs))) { for (int uv = 0; uv < (uvEnd - uvOfs) / uvStream.elemStride; uv++) { float u = dis.readFloat(); float v = dis.readFloat(); uvs.Add(new Vector2(u, v)); } } } /** normals */ if (nStreamObj != null) { StreamRegion nRegion = nStreamObj.dataStream.streamRegions[nStreamObj.streamRef.submeshRegionMap[i]]; DataType nType = typeForNifDataType(nStreamObj.elem.dataType); int nOfs = nRegion.a * nStream.elemStride; int nEnd = nOfs + nRegion.b * nStream.elemStride; byte[] nStreamData = nStream.streamData; using (BinaryReader dis = new BinaryReader(new MemoryStream(nStreamData, nOfs, nEnd - nOfs))) { for (int n = 0; n < (nEnd - nOfs) / nStream.elemStride; n++) { float x = dis.readFloat(); float y = dis.readFloat(); float z = dis.readFloat(); inNormals.Add(new Vector3(x, y, z)); } } } /** bone palette */ { StreamAndElement bonePalStreamObj = mesh.getStreamAndElement(nf, "BONE_PALETTE", -1); if (bonePalStreamObj != null) { NifMeshStream bonePalStreamRef = bonePalStreamObj.streamRef; NiDataStream bonePalStream = bonePalStreamObj.dataStream; NifStreamElement bonePalElem = bonePalStreamObj.elem; StreamRegion bonePalRegion = bonePalStreamObj.dataStream.streamRegions[bonePalStreamObj.streamRef.submeshRegionMap[i]]; DataType bonePalType = typeForNifDataType(bonePalStreamObj.elem.dataType); int bonePalOfs = bonePalRegion.a * bonePalStream.elemStride; int bonePalEnd = bonePalOfs + bonePalRegion.b * bonePalStream.elemStride; byte[] bonePalStreamData = bonePalStream.streamData; using (BinaryReader dis = new BinaryReader(new MemoryStream(bonePalStreamData, bonePalOfs, bonePalEnd - bonePalOfs))) { for (int n = 0; n < (bonePalEnd - bonePalOfs) / bonePalStream.elemStride; n++) { bonePalette.Add(dis.readUnsignedShort()); } } } } { /** blend indicies */ StreamAndElement StreamObj = mesh.getStreamAndElement(nf, "BLENDINDICES", -1); if (StreamObj != null) { NifMeshStream StreamRef = StreamObj.streamRef; NiDataStream Stream = StreamObj.dataStream; StreamRegion Region = StreamObj.dataStream.streamRegions[StreamObj.streamRef.submeshRegionMap[i]]; DataType type = typeForNifDataType(StreamObj.elem.dataType); int Ofs = Region.a * Stream.elemStride; int End = Ofs + Region.b * Stream.elemStride; byte[] StreamData = Stream.streamData; //Debug.Log("blendi stride:" + Stream.elemStride + ": type:" + type); // each vertex has a blend index using (BinaryReader dis = new BinaryReader(new MemoryStream(StreamData, Ofs, End - Ofs))) { for (int n = 0; n < (End - Ofs) / Stream.elemStride; n++) { byte idx1 = dis.ReadByte(); byte idx2 = dis.ReadByte(); byte idx3 = dis.ReadByte(); byte idx4 = dis.ReadByte(); BoneWeight weight = new BoneWeight(); weight.boneIndex0 = bonePalette[idx1]; weight.boneIndex1 = bonePalette[idx2]; weight.boneIndex2 = bonePalette[idx3]; weight.boneIndex3 = bonePalette[idx4]; boneWeights.Add(weight); } //Debug.Log("blend: left over: " + (dis.BaseStream.Length - dis.BaseStream.Position)); } } } { /** blend weights */ StreamAndElement StreamObj = mesh.getStreamAndElement(nf, "BLENDWEIGHT", -1); if (StreamObj != null) { NifMeshStream StreamRef = StreamObj.streamRef; NiDataStream Stream = StreamObj.dataStream; StreamRegion Region = StreamObj.dataStream.streamRegions[StreamObj.streamRef.submeshRegionMap[i]]; DataType type = typeForNifDataType(StreamObj.elem.dataType); int Ofs = Region.a * Stream.elemStride; int End = Ofs + Region.b * Stream.elemStride; byte[] StreamData = Stream.streamData; using (BinaryReader dis = new BinaryReader(new MemoryStream(StreamData, Ofs, End - Ofs))) { int total = (End - Ofs) / Stream.elemStride; // each vertex has weights for (int n = 0; n < total; n++) { BoneWeight w = boneWeights[n + vOffset]; w.weight0 = dis.readFloat(); w.weight1 = dis.readFloat(); w.weight2 = dis.readFloat(); w.weight3 = 0; boneWeights[n + vOffset] = w; } } } } } } if (IS_TERRAIN && uvs.Count == 0) { for (int i = 0; i < verts.Count; i++) { Vector3 vert = verts[i]; float x = vert.x; float z = vert.z; float u = (x / 256.0f); float v = (z / 256.0f); uvs.Add(new Vector2(u, v)); } } List <int> trisList = new List <int>(); for (int i = 0; i < triangles.Count; i++) { List <int> tris = triangles[i]; trisList.AddRange(tris); } meshData.tristest = trisList.ToArray(); return(meshData); }
private void loadObjects(BinaryReader dis) { for (int i = 0; i < numObjects; i++) { NIFObject obj = objects[i]; obj.index = i; String typeName = obj.typeName; int size = obj.nifSize; byte[] data; String cName = "Assets.NIF." + typeName; try { long pos = dis.BaseStream.Position; data = dis.ReadBytes(size); if (notImplementedMap.ContainsKey(typeName)) { continue; } using (BinaryReader ds = new BinaryReader(new MemoryStream(data, false))) { if (typeName.StartsWith("NiDataStream")) { NiDataStream newObj = new NiDataStream(); newObj.parse(this, obj, ds); objects[i] = newObj; } else { NIFObject newObj; //if (typeName.Contains("Eval")) //Debug.Log("[" + i + "]: type[" + typeName + "] @ " + pos); if (typeCacheC.ContainsKey(typeName)) { newObj = (NIFObject)typeCacheC[typeName].Invoke(); } else { // Debug.LogWarning("[PERFORMANCE WARNING] using activator for " + typeName); Type t = Type.GetType(cName); if (t == null) { notImplementedMap[typeName] = true; continue; } else { newObj = (NIFObject)Activator.CreateInstance(t); } } objects[i] = newObj; try { newObj.parse(this, obj, ds); } catch (Exception ex) { Debug.Log(ex); } } } //Debug.Log("[" + i + "]: " + objects[i].GetType()); } catch (Exception ex) { Debug.Log(typeName + ":" + ex); //Debug.Log("Unhandled nif type:" + typeName + " due to exception:" + ex.Message + " :data size:" + obj.nifSize); notImplementedMap[typeName] = true; continue; } } setParents(); }
public StreamAndElement(NifMeshStream streamRef, NifStreamElement elem2, NiDataStream dataStream) { this.streamRef = streamRef; elem = elem2; this.dataStream = dataStream; }