public override void readData() { BinaryReader file = binaryFile.openReader(); //holds references int reference; //Holds length of lists uint listLength; //Positions Vector3[] verts; //1st channel uvs Vector2[] uvs; //second channel (lightmap) uvs Vector2[] luvs; //Make sure this is not a FX mesh (instance stream is 0) file.BaseStream.Seek(binaryFile.dataOffset + binaryFile.structs[0].fields[5].index, SeekOrigin.Begin); if (file.ReadByte() != 0) { chunks = new MeshChunk[0]; return; } //seek to the beginning of the data part of the file file.BaseStream.Seek(binaryFile.dataOffset, SeekOrigin.Begin); //get the reference to the name of the mesh //get the name of the mesh name = IOUtilities.readECString(file, binaryFile.dataOffset + file.ReadInt32()); //Get the reference to the list of chunks file.BaseStream.Seek(binaryFile.dataOffset + binaryFile.structs[0].fields[1].index, SeekOrigin.Begin); reference = file.ReadInt32(); file.BaseStream.Seek(binaryFile.dataOffset + reference, SeekOrigin.Begin); listLength = file.ReadUInt32(); //Save the current position for the loop long startPosition = file.BaseStream.Position; //Make an array of chunks of the correct size chunks = new MeshChunk[listLength]; int triangleNum = 0; //Create all the chunks for (int i = 0; i < listLength; i++) { file.BaseStream.Seek(startPosition + (i * 4), SeekOrigin.Begin); file.BaseStream.Seek(binaryFile.dataOffset + file.ReadInt32(), SeekOrigin.Begin); chunks[i] = new MeshChunk(file, binaryFile.dataOffset, binaryFile.structs[4], binaryFile.structs[1]); triangleNum += (int)chunks[i].indexCount / 3; } triangleNum = 0; //Seek to the vertex data position file.BaseStream.Seek(binaryFile.dataOffset + binaryFile.structs[0].fields[2].index, SeekOrigin.Begin); //Get the reference to the list long vertexOffset = file.ReadUInt32() + binaryFile.dataOffset + 4; //Seek to the index data position file.BaseStream.Seek(binaryFile.dataOffset + binaryFile.structs[0].fields[3].index, SeekOrigin.Begin); //Get the reference to the list long indexOffset = file.ReadUInt32() + binaryFile.dataOffset + 4; //Index variables for triangles ushort index1, index2, index3; //For each chunk read in vertex data for (int i = 0; i < chunks.Length; i++) { verts = new Vector3[chunks[i].vertexCount]; uvs = new Vector2[chunks[i].vertexCount]; luvs = new Vector2[chunks[i].vertexCount]; //Read in the vertex data for (int j = 0; j < chunks[i].vertexCount; j++) { int vertArrayIndex = j * (chunks[i].vertexElementCount); int positionIndex = vertArrayIndex; int normalIndex = vertArrayIndex + 3; int uvIndex = vertArrayIndex + 6; long currentIndex = vertexOffset + chunks[i].vertexOffset + (chunks[i].vertexSize * j); //Read in the positions file.BaseStream.Seek(currentIndex + chunks[i].positionOffset, SeekOrigin.Begin); //Put them in the vert array verts[j] = new Vector3(IOUtilities.readFloat16(file), IOUtilities.readFloat16(file), IOUtilities.readFloat16(file)); //Put them in the chunk for easy rendering chunks[i].verts[positionIndex] = verts[j].X; chunks[i].verts[positionIndex + 1] = verts[j].Y; chunks[i].verts[positionIndex + 2] = verts[j].Z; //Read in the normals for rendering only, we make our own normals later file.BaseStream.Seek(currentIndex + chunks[i].normalOffset, SeekOrigin.Begin); chunks[i].verts[normalIndex] = IOUtilities.readFloat16(file); chunks[i].verts[normalIndex + 1] = IOUtilities.readFloat16(file); chunks[i].verts[normalIndex + 2] = IOUtilities.readFloat16(file); //Read in the uvs file.BaseStream.Seek(currentIndex + chunks[i].textureOffset, SeekOrigin.Begin); uvs[j] = new Vector2(IOUtilities.readFloat16(file), IOUtilities.readFloat16(file)); //Put them in the chunk for easy rendering chunks[i].verts[uvIndex] = uvs[j].X; chunks[i].verts[uvIndex + 1] = uvs[j].Y; //If there are a second set, read them in too if (chunks[i].usesTwoTexCoords) { file.BaseStream.Seek(currentIndex + chunks[i].texture2Offset, SeekOrigin.Begin); luvs[j] = new Vector2(IOUtilities.readFloat16(file), IOUtilities.readFloat16(file)); } } //Seek to index data (skipping the length int at beginning) file.BaseStream.Seek(indexOffset, SeekOrigin.Begin); for (int j = 0; j < chunks[i].indexCount / 3; j++) { int indexIndex = j * 3; //Read in the indices index1 = file.ReadUInt16(); index2 = file.ReadUInt16(); index3 = file.ReadUInt16(); chunks[i].indices[indexIndex] = index1; chunks[i].indices[indexIndex + 1] = index2; chunks[i].indices[indexIndex + 2] = index3; //If lightmap coords are specified make a triangle with them if (chunks[i].usesTwoTexCoords) chunks[i].tris[j] = new Triangle(verts[index1], verts[index2], verts[index3], uvs[index1], uvs[index2], uvs[index3], luvs[index1], luvs[index2], luvs[index3]); else //Otherwise make one without them chunks[i].tris[j] = new Triangle(verts[index1], verts[index2], verts[index3], uvs[index1], uvs[index2], uvs[index3]); //Calculate the area of the triangle and add it to the total area of the mesh chunks[i].area += 0.5 * Vector3.Cross(chunks[i].tris[j].y - chunks[i].tris[j].x, chunks[i].tris[j].z - chunks[i].tris[j].x).Length; //Increase offset by 3 indices (2 bytes each) indexOffset += 6; } } //Close the file file.Close(); }
public override void readData() { int reference, length; long startOfList; //Get the binary reader BinaryReader file = binaryFile.openReader(); //Set up the struct definitions setStructDefinitions(); //Get the sector ID file.BaseStream.Seek(binaryFile.dataOffset + infoStruct.fields[SECTOR_ID_INDEX].index, SeekOrigin.Begin); _sectorID = file.ReadInt32(); name = "Sector " + sectorID; /*----------MAP VERTS----------*/ //Get the reference to the map vertex list and go there file.BaseStream.Seek(binaryFile.dataOffset + infoStruct.fields[MAP_VERTEX_LIST_INDEX].index, SeekOrigin.Begin); reference = file.ReadInt32(); file.BaseStream.Seek(binaryFile.dataOffset + reference, SeekOrigin.Begin); //Fill the map vertex list with all the map verts length = file.ReadInt32(); _mapVerts = new List<TerrainMapVertex>(length); startOfList = file.BaseStream.Position; for (int i = 0; i < length; i++) { //Seek to the next struct in the list file.BaseStream.Seek(startOfList + (i * mapVertexStruct.structSize), SeekOrigin.Begin); //Add it to the list _mapVerts.Add(new TerrainMapVertex(mapVertexStruct, file)); } /*----------MAP EDGES----------*/ //Get the reference to the map edge list and go there file.BaseStream.Seek(binaryFile.dataOffset + infoStruct.fields[MAP_EDGE_LIST_INDEX].index, SeekOrigin.Begin); reference = file.ReadInt32(); file.BaseStream.Seek(binaryFile.dataOffset + reference, SeekOrigin.Begin); //Fill the map edge list with all the map edges length = file.ReadInt32(); _mapEdges = new List<TerrainMapEdge>(length); startOfList = file.BaseStream.Position; TerrainMapEdge tempEdge; for (int i = 0; i < length; i++) { //Seek to the next struct in the list file.BaseStream.Seek(startOfList + (i * mapEdgeStruct.structSize), SeekOrigin.Begin); //Create the edge tempEdge = new TerrainMapEdge(mapEdgeStruct, file); //Get the actual index in the array of the map vert for (int j = 0; j < _mapVerts.Count; j++) { if (_mapVerts[j].id == tempEdge.startVertexIndex) { tempEdge.startVertexIndex = j; break; } } //Add it to the list _mapEdges.Add(tempEdge); } /*----------MAP FACES----------*/ //Get the reference to the map face list and go there file.BaseStream.Seek(binaryFile.dataOffset + infoStruct.fields[MAP_FACE_LIST_INDEX].index, SeekOrigin.Begin); reference = file.ReadInt32(); file.BaseStream.Seek(binaryFile.dataOffset + reference, SeekOrigin.Begin); //Fill the map face list with all the map faces length = file.ReadInt32(); _mapFaces = new List<TerrainMapFace>(length); startOfList = file.BaseStream.Position; TerrainMapFace tempFace; for (int i = 0; i < length; i++) { //Seek to the next struct in the list file.BaseStream.Seek(startOfList + (i * mapFaceStruct.structSize), SeekOrigin.Begin); //Create the face tempFace = new TerrainMapFace(mapFaceStruct, file); //Find the actual edge indices for (int edgeIndex = 0; edgeIndex < 3; edgeIndex++) { for (int j = 0; j < _mapEdges.Count; j++) { if (tempFace[edgeIndex] == _mapEdges[j].id) { tempFace[edgeIndex] = j; break; } } } //Add it to the list _mapFaces.Add(tempFace); } /*----------MESH VERTS----------*/ //Get the reference to the mesh vertex list and go there file.BaseStream.Seek(binaryFile.dataOffset + infoStruct.fields[MESH_VERTEX_LIST_INDEX].index, SeekOrigin.Begin); reference = file.ReadInt32(); file.BaseStream.Seek(binaryFile.dataOffset + reference, SeekOrigin.Begin); //Fill the vertex list with all the vertex length = file.ReadInt32(); _verts = new List<TerrainMeshVertex>(length); startOfList = file.BaseStream.Position; for (int i = 0; i < length; i++) { //Seek to the next struct in the list file.BaseStream.Seek(startOfList + (i * meshVertexStruct.structSize), SeekOrigin.Begin); //Add it to the list _verts.Add(new TerrainMeshVertex(meshVertexStruct, file)); } /*----------MESH EDGES----------*/ //Get the reference to the mesh edge list and go there file.BaseStream.Seek(binaryFile.dataOffset + infoStruct.fields[MESH_EDGE_LIST_INDEX].index, SeekOrigin.Begin); reference = file.ReadInt32(); file.BaseStream.Seek(binaryFile.dataOffset + reference, SeekOrigin.Begin); //Fill the edge list with all the edge length = file.ReadInt32(); _edges = new List<TerrainMeshEdge>(length); startOfList = file.BaseStream.Position; TerrainMeshEdge tempMeshEdge; for (int i = 0; i < length; i++) { //Seek to the next struct in the list file.BaseStream.Seek(startOfList + (i * meshEdgeStruct.structSize), SeekOrigin.Begin); //Create the edge tempMeshEdge = new TerrainMeshEdge(meshEdgeStruct, file); //Get the actual index in the array of the mesh vert for (int j = 0; j < _mapVerts.Count; j++) { if (_verts[j].id == tempMeshEdge.startVertexIndex) { tempMeshEdge.startVertexIndex = j; break; } } //Add it to the list _edges.Add(tempMeshEdge); } /*----------MESH FACES----------*/ //Get the reference to the mesh face list and go there file.BaseStream.Seek(binaryFile.dataOffset + infoStruct.fields[MESH_FACE_LIST_INDEX].index, SeekOrigin.Begin); reference = file.ReadInt32(); file.BaseStream.Seek(binaryFile.dataOffset + reference, SeekOrigin.Begin); //Fill the face list with all the faces length = file.ReadInt32(); _faces = new List<TerrainMeshFace>(length); startOfList = file.BaseStream.Position; TerrainMeshFace tempMeshFace; for (int i = 0; i < length; i++) { //Seek to the next struct in the list file.BaseStream.Seek(startOfList + (i * meshFaceStruct.structSize), SeekOrigin.Begin); //Make the face tempMeshFace = new TerrainMeshFace(meshFaceStruct, file); //Find the actual edge indices for (int edgeIndex = 0; edgeIndex < 3; edgeIndex++) { for (int j = 0; j < _edges.Count; j++) { if (tempMeshFace[edgeIndex] == _edges[j].id) { tempMeshFace[edgeIndex] = j; break; } } } //Find the actual map face index for (int j = 0; j < _mapFaces.Count; j++) { if (tempMeshFace.mapId == _mapFaces[j].id) { tempMeshFace.mapId = j; break; } } //Add it to the list _faces.Add(tempMeshFace); } file.Close(); chunks = new MeshChunk[1]; Triangle[] tris = new Triangle[faces.Count]; //Hold temporary vertex values Vector3 x, y, z; Vector2 u, v, w; //For each faces make a triangle for (int i = 0; i < faces.Count; i++) { //Get the mesh coordinates x = verts[edges[faces[i].edges[0]].startVertexIndex].position; y = verts[edges[faces[i].edges[1]].startVertexIndex].position; z = verts[edges[faces[i].edges[2]].startVertexIndex].position; //Get the map coordinates (lightmap coordinates are the same) u = mapVerts[mapEdges[mapFaces[faces[i].mapId].edges[0]].startVertexIndex].position.Xy; v = mapVerts[mapEdges[mapFaces[faces[i].mapId].edges[1]].startVertexIndex].position.Xy; w = mapVerts[mapEdges[mapFaces[faces[i].mapId].edges[2]].startVertexIndex].position.Xy; //Make the triangle tris[i] = new Triangle(x, y, z, u, v, w, u, v, w); } chunks[0] = new MeshChunk(tris); chunks[0].casts = true; chunks[0].receives = true; }
public ModelMesh(MeshChunk[] meshChunks) : base() { chunks = meshChunks; }