public void readData() { BinaryReader file = binaryFile.openReader(); int reference; //Get the name of the mmh file file.BaseStream.Seek(binaryFile.dataOffset + binaryFile.structs[0].fields[MMH_NAME_INDEX].index, SeekOrigin.Begin); mmhName = IOUtilities.readECString(file, binaryFile.dataOffset + file.ReadInt32()).ToLower(); //Get the name of the msh file file.BaseStream.Seek(binaryFile.dataOffset + binaryFile.structs[0].fields[MSH_NAME_INDEX].index, SeekOrigin.Begin); mshName = IOUtilities.readECString(file, binaryFile.dataOffset + file.ReadInt32()).ToLower(); //Get the total number of bones in the mmh file.BaseStream.Seek(binaryFile.dataOffset + binaryFile.structs[0].fields[TOTAL_BONES_INDEX].index, SeekOrigin.Begin); numBones = file.ReadInt32(); //Apparently fx models have an extra field... isFXModel = binaryFile.structs[0].fields.Length == 8; if (isFXModel) { file.Close(); return; } //Get the children list (should only contain GOB) file.BaseStream.Seek(binaryFile.dataOffset + binaryFile.structs[0].fields[TOP_LEVEL_CHILDREN_INDEX].index, SeekOrigin.Begin); reference = file.ReadInt32(); file.BaseStream.Seek(binaryFile.dataOffset + reference, SeekOrigin.Begin); GenericList childrenList = new GenericList(file); //Get the children of the GOB object //Sometimes its a node struct, sometimes its a mshh struct . . . if ((int)(childrenList.type[0].id) == nodeStructIndex) { file.BaseStream.Seek(binaryFile.dataOffset + childrenList[0] + nodeStruct.fields[GOB_CHILDREN_INDEX].index, SeekOrigin.Begin); } else if ((int)(childrenList.type[0].id) == meshChunkInfoIndex) { file.BaseStream.Seek(binaryFile.dataOffset + childrenList[0] + meshChunkInfoStruct.fields[MSH_CHUNK_CHILDREN_INDEX].index, SeekOrigin.Begin); } reference = file.ReadInt32(); file.BaseStream.Seek(binaryFile.dataOffset + reference, SeekOrigin.Begin); childrenList = new GenericList(file); //Find the mesh GFF temp = ResourceManager.findFile<GFF>(mshName); //If its not there throw an exception cause we need it if (temp == null) { Console.WriteLine("Could not find mesh file \"{0}\".", mshName); file.Close(); return; //throw new Exception("COULD NOT FIND MESH FILE, LOOK AT CONSOLE!!!!!!"); } loadedMesh = true; //Make the mesh mesh = new ModelMesh(temp); //For each thing in the child list for (int i = 0; i < childrenList.length; i++) { //If the child is a mesh chunk info struct if ((int)childrenList.type[i].id == meshChunkInfoIndex) { //Fill in the missing mesh chunk info updateChunk(file, binaryFile.dataOffset + childrenList[i], new Vector3(), new Quaternion()); } } file.Close(); }
private void updateChunk(BinaryReader file, long startPosition, Vector3 offset, Quaternion rotation) { file.BaseStream.Seek(startPosition + meshChunkInfoStruct.fields[MSH_CHUNK_GROUP_NAME_INDEX].index,SeekOrigin.Begin); //Get the name of the meshchunk this info is for String currentMeshChunkName = IOUtilities.readECString(file, binaryFile.dataOffset + file.ReadInt32()); //Console.WriteLine("Doing Chunk " + currentMeshChunkName); //Find the meshChunk we need MeshChunk currentMeshChunk = null; foreach (MeshChunk m in mesh.chunks) { if (m.name == currentMeshChunkName) { currentMeshChunk = m; break; } } //If no mesh chunk could be found there was a problem if (currentMeshChunk == null) { Console.WriteLine("Could not find mesh chunk \"{0}\" in msh file \"{1}\".", currentMeshChunkName, mshName); throw new Exception("COULD NOT FIND MESHCHUNK, LOOK AT CONSOLE!!!!!!"); } //Get the material name file.BaseStream.Seek(startPosition + meshChunkInfoStruct.fields[MSH_CHUNK_MATERIAL_INDEX].index, SeekOrigin.Begin); currentMeshChunk.materialObjectName = IOUtilities.readECString(file, binaryFile.dataOffset + file.ReadInt32()) + ".mao"; //Get the chunk ID file.BaseStream.Seek(startPosition + meshChunkInfoStruct.fields[MSH_CHUNK_ID_INDEX].index, SeekOrigin.Begin); currentMeshChunk.id = IOUtilities.readECString(file, binaryFile.dataOffset + file.ReadInt32()); //Get whether it casts shadows file.BaseStream.Seek(startPosition + meshChunkInfoStruct.fields[MSH_CHUNK_CASTS_BAKED_INDEX].index, SeekOrigin.Begin); currentMeshChunk.casts = file.ReadByte() == 1; //Get whether it receives shadows file.BaseStream.Seek(startPosition + meshChunkInfoStruct.fields[MSH_CHUNK_RECEIVES_BAKED_INDEX].index, SeekOrigin.Begin); currentMeshChunk.receives = currentMeshChunk.usesTwoTexCoords ? file.ReadByte() == 1 : false; //Get translation offset and rotation file.BaseStream.Seek(startPosition + meshChunkInfoStruct.fields[MSH_CHUNK_CHILDREN_INDEX].index, SeekOrigin.Begin); int reference = file.ReadInt32(); file.BaseStream.Seek(binaryFile.dataOffset + reference, SeekOrigin.Begin); GenericList attributes = new GenericList(file); for (int j = 0; j < attributes.length; j++) { if ((int)(attributes.type[j].id) == rotationStructIndex) { file.BaseStream.Seek(binaryFile.dataOffset + attributes[j], SeekOrigin.Begin); currentMeshChunk.chunkRotation = new Quaternion(file.ReadSingle(), file.ReadSingle(), file.ReadSingle(), file.ReadSingle()) * rotation; } else if ((int)(attributes.type[j].id) == translationStructIndex) { file.BaseStream.Seek(binaryFile.dataOffset + attributes[j], SeekOrigin.Begin); currentMeshChunk.chunkOffset = offset + new Vector3(file.ReadSingle(), file.ReadSingle(), file.ReadSingle()); } else if ((int)(attributes.type[j].id) == meshChunkInfoIndex) { updateChunk(file, binaryFile.dataOffset + attributes[j], currentMeshChunk.chunkOffset, currentMeshChunk.chunkRotation); } } }
private List<Light> readLights(GenericList objectList, Vector3 roomOffset, Quaternion roomOrientation, int roomID) { List<Light> lights = new List<Light>(); BinaryReader file = headerFile.openReader(); long currentPosition; //position of begining of light struct (for offsets within struct) int type; //point = 0, ambient = 1, spot = 2 -The type of the light int effect; //baked = 0, static = 2, animated = 3, negative = 4; -How light effects environment //LightType lightEffect; //enum for above (TODO: used to decide whether it affects shadow map or lightmap) float radius; //radius of point lights float intensity = 1; //intensity of light (colour multiplier) Vector3 position; //position of the light Quaternion rotation; //rotation of the light (only used in spot lights) Vector3 colour; //colour of the light float inAngle, outAngle, distance; //spot light values //for all the objects in the list for (int i = 0; i < objectList.length; i++) { //if its a light object process it if (headerFile.structs[(int)objectList.type[i].id].type == GFFSTRUCTTYPE.LIGHT) { //seek to the light struct data file.BaseStream.Seek(headerFile.dataOffset + objectList[i], SeekOrigin.Begin); currentPosition = file.BaseStream.Position; //get the position file.BaseStream.Seek(currentPosition + lightStruct.fields[LIGHT_POSITION_INDEX].index,SeekOrigin.Begin); position = new Vector3(file.ReadSingle(), file.ReadSingle(), file.ReadSingle()); position += roomOffset; //get the rotation file.BaseStream.Seek(currentPosition + lightStruct.fields[LIGHT_ROTATION_INDEX].index, SeekOrigin.Begin); rotation = new Quaternion(file.ReadSingle(), file.ReadSingle(), file.ReadSingle(), file.ReadSingle()); rotation *= roomOrientation; //get the colour file.BaseStream.Seek(currentPosition + lightStruct.fields[LIGHT_COLOUR_INDEX].index, SeekOrigin.Begin); colour = new Vector3(file.ReadSingle(), file.ReadSingle(), file.ReadSingle()); //get the type file.BaseStream.Seek(currentPosition + lightStruct.fields[LIGHT_TYPE_INDEX].index, SeekOrigin.Begin); type = file.ReadInt32(); file.BaseStream.Seek(currentPosition + lightStruct.fields[LIGHT_RADIUS_INDEX].index, SeekOrigin.Begin); radius = file.ReadSingle(); //get the multiplier file.BaseStream.Seek(currentPosition + lightStruct.fields[LIGHT_COLOUR_MULTIPLIER_INDEX].index, SeekOrigin.Begin); intensity = file.ReadSingle(); Console.WriteLine("Intensity is {0}.", intensity); //get the effect file.BaseStream.Seek(currentPosition + lightStruct.fields[LIGHT_EFFECT_INDEX].index, SeekOrigin.Begin); effect = file.ReadByte(); /* //set the lightEffect variable for easy constructing if (effect == LIGHT_BAKED) lightEffect = LightType.Baked; else if (effect == LIGHT_STATIC) lightEffect = LightType.Static; else continue; */ //get the in angle file.BaseStream.Seek(currentPosition + lightStruct.fields[LIGHT_INANGLE_INDEX].index, SeekOrigin.Begin); inAngle = file.ReadSingle(); //get the out angle file.BaseStream.Seek(currentPosition + lightStruct.fields[LIGHT_OUTANGLE_INDEX].index, SeekOrigin.Begin); outAngle = file.ReadSingle(); //get the distance file.BaseStream.Seek(currentPosition + lightStruct.fields[LIGHT_DISTANCE_INDEX].index, SeekOrigin.Begin); distance = file.ReadSingle(); //add the light to the lights list /* switch (type) { case LIGHT_AMBIENT: lights.Add(new AmbientLight(position, colour, intensity, lightEffect, false)); break; case LIGHT_SPOT: lights.Add(new SpotLight(position, rotation, colour, intensity, inAngle, outAngle, distance, lightEffect, true)); break; case LIGHT_POINT: lights.Add(new PointLight(position, colour, intensity, radius, lightEffect, true)); break; } */ } else if (headerFile.structs[(int)objectList.type[i].id].type == GFFSTRUCTTYPE.LVL_GROUP) { //seek to the group struct data file.BaseStream.Seek(headerFile.dataOffset + objectList[i], SeekOrigin.Begin); currentPosition = file.BaseStream.Position; file.BaseStream.Seek(currentPosition + levelGroupStruct.fields[GROUP_POSITION_INDEX].index, SeekOrigin.Begin); Vector3 groupPosition = new Vector3(file.ReadSingle(), file.ReadSingle(), file.ReadSingle()); file.BaseStream.Seek(currentPosition + levelGroupStruct.fields[GROUP_ROTATION_INDEX].index, SeekOrigin.Begin); Quaternion groupRotation = new Quaternion(file.ReadSingle(), file.ReadSingle(), file.ReadSingle(), file.ReadSingle()); //seek to the list file.BaseStream.Seek(currentPosition + levelGroupStruct.fields[GROUP_LIST_INDEX].index, SeekOrigin.Begin); int reference = file.ReadInt32(); file.BaseStream.Seek(headerFile.dataOffset + reference, SeekOrigin.Begin); lights.AddRange(readLights(new GenericList(file), roomOffset + Vector3.Transform(groupPosition, groupRotation * roomOrientation), groupRotation * roomOrientation, roomID)); } } return lights; }
private List<ModelInstance> readPropModels(GenericList objectList, Vector3 roomOffset, Quaternion roomOrientation, int roomID) { List<ModelInstance> propModels = new List<ModelInstance>(); BinaryReader file = headerFile.openReader(); long currentPosition; //position of beginning of model struct (for offsets within struct GenericList propertyList; //to hold the list of properties of the model int reference; //for referencing structs Vector3 position; Quaternion rotation; String modelFileName; int lightmapValue; uint modelID; //for all the objects in the list for (int i = 0; i < objectList.length; i++) { //if its a model object process it if (headerFile.structs[(int)objectList.type[i].id].type == GFFSTRUCTTYPE.MODEL) { //seek to the model struct data file.BaseStream.Seek(headerFile.dataOffset + objectList[i], SeekOrigin.Begin); currentPosition = file.BaseStream.Position; //get position file.BaseStream.Seek(currentPosition + modelStruct.fields[MODEL_POSITION_INDEX].index, SeekOrigin.Begin); position = new Vector3(file.ReadSingle(), file.ReadSingle(), file.ReadSingle()); position += roomOffset; //get the rotation file.BaseStream.Seek(currentPosition + modelStruct.fields[MODEL_ROTATION_INDEX].index, SeekOrigin.Begin); rotation = new Quaternion(file.ReadSingle(), file.ReadSingle(), file.ReadSingle(), file.ReadSingle()); rotation = rotation * roomOrientation; //get the property List reference file.BaseStream.Seek(currentPosition + modelStruct.fields[MODEL_PROPERTY_INDEX].index + propertyStruct.fields[PROPERTY_CHILDREN_INDEX].index, SeekOrigin.Begin); reference = file.ReadInt32(); //seek to the children field and make the children list file.BaseStream.Seek(headerFile.dataOffset + reference, SeekOrigin.Begin); propertyList = new GenericList(file); // get the reference to the model file name string file.BaseStream.Seek(headerFile.dataOffset + propertyList[MODEL_FILENAME_INDEX] + propertyStruct.fields[PROPERTY_VALUE_INDEX].index, SeekOrigin.Begin); modelFileName = IOUtilities.readECString(file, headerFile.dataOffset + file.ReadInt32()) + ".mmh"; //get the lightmap value file.BaseStream.Seek(headerFile.dataOffset + propertyList[MODEL_LIGHTMAPVALUE_INDEX] + propertyStruct.fields[PROPERTY_VALUE_INDEX].index, SeekOrigin.Begin); lightmapValue = Int32.Parse(IOUtilities.readECString(file, headerFile.dataOffset + file.ReadInt32())); //get the ID value file.BaseStream.Seek(currentPosition + modelStruct.fields[MODEL_ID_INDEX].index,SeekOrigin.Begin); modelID = file.ReadUInt32(); //If the model isnt in the dictionary already if (!baseModels.ContainsKey(modelFileName)) { //Find the mmh file GFF tempGFF = ResourceManager.findFile<GFF>(modelFileName); //If the file was not found if (tempGFF != null) { ModelHierarchy h = new ModelHierarchy(tempGFF); //Only add it if its not a effects model if (!h.isFXModel) { baseModels.Add(modelFileName, h.mesh.toModel()); } } else { //Print an error //Settings.stream.AppendFormatLine("Could not find model file \"{0}\".",modelFileName); } } //If its not in the dictionary this time then we just ignore it if(baseModels.ContainsKey(modelFileName)) { if (baseModels[modelFileName].isLightmapped || baseModels[modelFileName].castsShadows) { propModels.Add(new ModelInstance(modelFileName, baseModels[modelFileName], position, rotation, modelID, roomID, layoutName)); } } } else if (headerFile.structs[(int)objectList.type[i].id].type == GFFSTRUCTTYPE.LVL_GROUP) { //seek to the group struct data file.BaseStream.Seek(headerFile.dataOffset + objectList[i], SeekOrigin.Begin); currentPosition = file.BaseStream.Position; file.BaseStream.Seek(currentPosition + levelGroupStruct.fields[GROUP_POSITION_INDEX].index, SeekOrigin.Begin); Vector3 groupPosition = new Vector3(file.ReadSingle(), file.ReadSingle(), file.ReadSingle()); file.BaseStream.Seek(currentPosition + levelGroupStruct.fields[GROUP_ROTATION_INDEX].index, SeekOrigin.Begin); Quaternion groupRotation = new Quaternion(file.ReadSingle(), file.ReadSingle(), file.ReadSingle(), file.ReadSingle()); //seek to the list file.BaseStream.Seek(currentPosition + levelGroupStruct.fields[GROUP_LIST_INDEX].index, SeekOrigin.Begin); reference = file.ReadInt32(); file.BaseStream.Seek(headerFile.dataOffset + reference, SeekOrigin.Begin); propModels.AddRange(readPropModels(new GenericList(file), roomOffset + groupPosition, groupRotation * roomOrientation, roomID)); } } file.Close(); return propModels; }
public void readObjects() { int reference; //used for storing the reference to structs in files BinaryReader file = headerFile.openReader(); //If the level is outdoors, read the models and the terrain mesh, otherwise just read in the models // the file is layed out differently for outdoors and indoor environments models = new List<BiowareModel>(); lights = new List<Light>(); ; GenericList objectList; //If this is an outdoor level read in the terrain if (environmentStruct.type == GFFSTRUCTTYPE.ENV_WORLD_TERRAIN) { models.AddRange(readTerrainModels()); } //then make the generic list for lights and models //get to the beginning of the data block file.BaseStream.Seek(headerFile.dataOffset, SeekOrigin.Begin); //seek to the reference to the terrain world reference (first field in the struct) then go there file.BaseStream.Seek(headerFile.structs[TOP_LEVEL_STRUCT_INDEX].fields[0].index, SeekOrigin.Current); //seek to the list of objects in the environment struct and go there file.BaseStream.Seek(environmentStruct.fields[ENVIRONMENT_LIST_INDEX].index, SeekOrigin.Current); reference = file.ReadInt32(); file.BaseStream.Seek(headerFile.dataOffset + reference, SeekOrigin.Begin); //make the list of objects objectList = new GenericList(file); //If this is an outdoor level this is the list of models and lights if (environmentStruct.type == GFFSTRUCTTYPE.ENV_WORLD_TERRAIN) { lightmapModels.AddRange(readPropModels(objectList, new Vector3(), new Quaternion(), 0)); lights.AddRange(readLights(objectList, new Vector3(), new Quaternion(), 0)); } //if its an indoor room we have to go farther into the data else if (environmentStruct.type == GFFSTRUCTTYPE.ENV_WORLD_ROOM) { //get to the area struct data file.BaseStream.Seek(headerFile.dataOffset + objectList[0], SeekOrigin.Begin); //Get the layout name file.BaseStream.Seek(areaStruct.fields[AREA_PROPERTY_INDEX].index + propertyStruct.fields[PROPERTY_CHILDREN_INDEX].index, SeekOrigin.Current); reference = file.ReadInt32(); file.BaseStream.Seek(headerFile.dataOffset + reference, SeekOrigin.Begin); GenericList propertyList = new GenericList(file); file.BaseStream.Seek(headerFile.dataOffset + propertyList[AREA_LAYOUT_NAME_INDEX] + propertyStruct.fields[PROPERTY_VALUE_INDEX].index, SeekOrigin.Begin); layoutName = IOUtilities.readECString(file, headerFile.dataOffset + file.ReadInt32()); //now get the reference to the room list and make it file.BaseStream.Seek(headerFile.dataOffset + objectList[0], SeekOrigin.Begin); file.BaseStream.Seek(areaStruct.fields[AREA_LIST_INDEX].index, SeekOrigin.Current); reference = file.ReadInt32(); file.BaseStream.Seek(headerFile.dataOffset + reference, SeekOrigin.Begin); GenericList roomList = new GenericList(file); //for each room in the list for (int i = 0; i < roomList.length; i++) { if (headerFile.structs[(int)roomList.type[i].id].type == GFFSTRUCTTYPE.EVN_ROOM) { //get the room position file.BaseStream.Seek(headerFile.dataOffset + roomList[i] + roomStruct.fields[ROOM_POSITION_INDEX].index, SeekOrigin.Begin); Vector3 position = new Vector3(file.ReadSingle(), file.ReadSingle(), file.ReadSingle()); //get the room orientation file.BaseStream.Seek(headerFile.dataOffset + roomList[i] + roomStruct.fields[ROOM_ROTATION_INDEX].index, SeekOrigin.Begin); Quaternion orientation = new Quaternion(file.ReadSingle(), file.ReadSingle(), file.ReadSingle(), file.ReadSingle()); //get the room id file.BaseStream.Seek(headerFile.dataOffset + roomList[i] + roomStruct.fields[ROOM_ID_INDEX].index, SeekOrigin.Begin); int id = file.ReadInt32(); //seek to the object list file.BaseStream.Seek(headerFile.dataOffset + roomList[i] + roomStruct.fields[ROOM_OBJECT_LIST_INDEX].index, SeekOrigin.Begin); reference = file.ReadInt32(); file.BaseStream.Seek(headerFile.dataOffset + reference, SeekOrigin.Begin); //Make the list of objects in the room objectList = new GenericList(file); //Add the models and lights to the lists lightmapModels.AddRange(readPropModels(objectList, position, orientation, id)); lights.AddRange(readLights(objectList, position, orientation, id)); } } } generatePatches(baseModels); file.Close(); }