public override void parse(NIFFile file, NIFObject baseo, BinaryReader ds) { base.parse(file, baseo, ds); loadRenderable(file, ds); meshPrimType = ds.readInt(); numSubMeshes = ds.readUnsignedShort(); isInstanced = ds.readUnsignedByte() > 0; boundsCenter = new Point3f(ds.readFloat(), ds.readFloat(), ds.readFloat()); boundsRad = ds.readFloat(); numStreamRefs = ds.readInt(); streamRefs = new List <NifMeshStream>(); for (int i = 0; i < numStreamRefs; i++) { NifMeshStream meshStream = new NifMeshStream(); meshStream.parse(file, baseo, ds); streamRefs.Add(meshStream); } modLinks = loadLinkIDs(ds); file.addMesh(this); }
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); }
public StreamAndElement(NifMeshStream streamRef, NifStreamElement elem2, NiDataStream dataStream) { this.streamRef = streamRef; elem = elem2; this.dataStream = dataStream; }