public BinaryBlock(byte[] bytes, KujuTokenID token) { Token = token; myStream = new MemoryStream(bytes); myReader = new BinaryReader(myStream); int length = myReader.ReadByte(); if (length > 0) { //Note: For most blocks, the label length will be zero byte[] buff = new byte[length * 2]; int i = 0; while (i < length * 2) { buff[i] = myReader.ReadByte(); i++; } Label = System.Text.Encoding.Unicode.GetString(buff, 0, length * 2); } else { Label = string.Empty; } }
public TextualBlock(string text, KujuTokenID token) { myText = text; //Replace special characters and escaped brackets to stop the parser barfing myText = myText.Replace("\r\n", " ").Replace("\n", " ").Replace("\r", " ").Replace("\t", " ").Trim(new char[] { }); myText = myText.Replace(@"\(", "[").Replace(@"\)", "]"); // FIXME: Current parser needs whitespace around brackets, else it throws a wobbly for (int i = 0; i < myText.Length; i++) { if (i > 0 && myText[i] == ')' && !char.IsWhiteSpace(myText[i - 1])) { myText = myText.Insert(i, " "); i++; } if (i > 0 && myText[i] == '(' && !char.IsWhiteSpace(myText[i + 1])) { myText = myText.Insert(i + 1, " "); i++; } } Token = token; currentPosition = 0; Label = string.Empty; while (myText[currentPosition] != '(') { currentPosition++; } if (currentPosition == 0) { throw new InvalidDataException("Token " + token + " was not found."); } string s = myText.Substring(0, currentPosition); int ws = s.IndexOf(' '); if (ws != -1) { //The block has the optional label Label = s.Substring(ws, s.Length - ws).Trim(new char[] { }); s = s.Substring(0, ws); } KujuTokenID currentToken; if (!Enum.TryParse(s, true, out currentToken)) { throw new InvalidDataException("Invalid token " + s); } if (currentToken != Token) { throw new InvalidDataException("Expected the " + Token + " token, got " + currentToken); } currentPosition++; }
public override Block ReadSubBlock() { KujuTokenID currentToken = (KujuTokenID)myReader.ReadUInt16(); myReader.ReadUInt16(); uint remainingBytes = myReader.ReadUInt32(); byte[] newBytes = myReader.ReadBytes((int)remainingBytes); return(new BinaryBlock(newBytes, currentToken)); }
public override Block ReadSubBlock(KujuTokenID[] validTokens) { KujuTokenID currentToken = (KujuTokenID)myReader.ReadUInt16(); if (!validTokens.Contains(currentToken)) { throw new Exception("Expected one of the following tokens: " + validTokens + ", got " + currentToken); } myReader.ReadUInt16(); uint remainingBytes = myReader.ReadUInt32(); byte[] newBytes = myReader.ReadBytes((int)remainingBytes); return(new BinaryBlock(newBytes, currentToken)); }
public override Block ReadSubBlock(KujuTokenID newToken) { KujuTokenID currentToken = (KujuTokenID)myReader.ReadUInt16(); if (currentToken != newToken) { throw new Exception("Expected the " + newToken + " token, got " + currentToken); } myReader.ReadUInt16(); uint remainingBytes = myReader.ReadUInt32(); byte[] newBytes = myReader.ReadBytes((int)remainingBytes); return(new BinaryBlock(newBytes, newToken)); }
public TextualBlock(string text, KujuTokenID token) { myText = text; Token = token; currentPosition = 0; Label = string.Empty; while (myText[currentPosition] != '(') { currentPosition++; } if (currentPosition == 0) { throw new Exception("Token " + token + " was not found."); } string s = myText.Substring(0, currentPosition); int ws = s.IndexOf(' '); if (ws != -1) { //The block has the optional label Label = s.Substring(ws, s.Length - ws).Trim(); s = s.Substring(0, ws); } KujuTokenID currentToken; if (!Enum.TryParse(s, true, out currentToken)) { throw new Exception("Invalid token " + s); } if (currentToken != Token) { throw new Exception("Expected the " + Token + " token, got " + currentToken); } currentPosition++; }
/// <summary>Reads a sub-block from the enclosing block</summary> /// <param name="newToken">The expected token for the new block</param> /// <returns>The new block</returns> /// <remarks>The type of the new block will always match that of the base block</remarks> public abstract Block ReadSubBlock(KujuTokenID newToken);
/// <summary>Creates a new block from the supplied string</summary> /// <param name="text">The string</param> /// <param name="token">The token for the new block</param> /// <returns>The new block</returns> /// <remarks>Always creates a TextualBlock</remarks> public static Block ReadBlock(string text, KujuTokenID token) { return(new TextualBlock(text, token)); }
/// <summary>Creates a new block from the supplied byte array</summary> /// <param name="bytes">The block of data</param> /// <param name="token">The token for the new block</param> /// <returns>The new block</returns> /// <remarks>Always creates a BinaryBlock</remarks> public static Block ReadBlock(byte[] bytes, KujuTokenID token) { return(new BinaryBlock(bytes, token)); }
public override Block ReadSubBlock(KujuTokenID newToken) { startPosition = currentPosition; string s = String.Empty; while (currentPosition < myText.Length) { if (myText[currentPosition] == '(') { int l = currentPosition - startPosition; s = myText.Substring(startPosition, l).Trim(); currentPosition++; break; } currentPosition++; } KujuTokenID currentToken; int ws = s.IndexOf(' '); if (ws != -1) { //The block has the optional label Label = s.Substring(ws, s.Length - ws).Trim(); s = s.Substring(0, ws); } if (!Enum.TryParse(s, true, out currentToken)) { throw new Exception("Unrecognised token " + s); } if (newToken != currentToken) { throw new Exception("Expected the " + newToken + " token, got " + currentToken); } int level = 0; while (currentPosition < myText.Length) { if (myText[currentPosition] == '(') { level++; } if (myText[currentPosition] == ')') { currentPosition++; if (level == 0) { return(new TextualBlock(myText.Substring(startPosition, currentPosition - startPosition).Trim(), newToken)); } level--; } currentPosition++; } throw new Exception("Unexpected end of block in " + Token); }
private static void ParseBlock(Block block, ref MsTsShape shape, ref Vertex vertex, ref int[] intArray) { float x, y, z; Vector3 point; KujuTokenID currentToken = KujuTokenID.error; Block newBlock; uint flags; switch (block.Token) { case KujuTokenID.shape: newBlock = block.ReadSubBlock(KujuTokenID.shape_header); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.volumes); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.shader_names); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.texture_filter_names); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.points); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.uv_points); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.normals); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.sort_vectors); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.colours); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.matrices); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.images); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.textures); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.light_materials); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.light_model_cfgs); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.vtx_states); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.prim_states); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.lod_controls); ParseBlock(newBlock, ref shape); break; case KujuTokenID.shape_header: case KujuTokenID.volumes: case KujuTokenID.texture_filter_names: case KujuTokenID.sort_vectors: case KujuTokenID.colours: case KujuTokenID.light_materials: case KujuTokenID.light_model_cfgs: //Unsupported stuff, so just read to the end at the minute block.Skip((int)block.Length()); break; case KujuTokenID.vtx_state: flags = block.ReadUInt32(); int matrix1 = block.ReadInt32(); int lightMaterialIdx = block.ReadInt32(); int lightStateCfgIdx = block.ReadInt32(); uint lightFlags = block.ReadUInt32(); int matrix2 = -1; if ((block is BinaryBlock && block.Length() - block.Position() > 1) || (!(block is BinaryBlock) && block.Length() - block.Position() > 2)) { matrix2 = block.ReadInt32(); } VertexStates vs = new VertexStates(); vs.flags = flags; vs.hierarchyID = matrix1; vs.lightingMatrixID = lightMaterialIdx; vs.lightingConfigIdx = lightStateCfgIdx; vs.lightingFlags = lightFlags; vs.matrix2ID = matrix2; shape.vtx_states.Add(vs); break; case KujuTokenID.vtx_states: int vtxStateCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (vtxStateCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.vtx_state); ParseBlock(newBlock, ref shape); vtxStateCount--; } break; case KujuTokenID.prim_state: flags = block.ReadUInt32(); int shader = block.ReadInt32(); int[] texIdxs = {}; newBlock = block.ReadSubBlock(KujuTokenID.tex_idxs); ParseBlock(newBlock, ref shape, ref texIdxs); float zBias = block.ReadSingle(); int vertexStates = block.ReadInt32(); int alphaTestMode = block.ReadInt32(); int lightCfgIdx = block.ReadInt32(); int zBufferMode = block.ReadInt32(); PrimitiveState p = new PrimitiveState(); p.Name = block.Label; p.Flags = flags; p.Shader = shader; p.Textures = texIdxs; p.ZBias = zBias; p.vertexStates = vertexStates; p.alphaTestMode = alphaTestMode; p.lightCfgIdx = lightCfgIdx; p.zBufferMode = zBufferMode; shape.prim_states.Add(p); break; case KujuTokenID.tex_idxs: int texIdxCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } Array.Resize(ref intArray, texIdxCount); int idx = 0; while (texIdxCount > 0) { intArray[idx] = block.ReadUInt16(); idx++; texIdxCount--; } break; case KujuTokenID.prim_states: int primStateCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (primStateCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.prim_state); ParseBlock(newBlock, ref shape); primStateCount--; } break; case KujuTokenID.texture: int imageIDX = block.ReadInt32(); int filterMode = (int)block.ReadUInt32(); float mipmapLODBias = block.ReadSingle(); uint borderColor = 0xff000000U; if (block.Length() - block.Position() > 1) { borderColor = block.ReadUInt32(); } //Unpack border color float r, g, b, a; r = borderColor % 256; g = (borderColor / 256) % 256; b = (borderColor / 256 / 256) % 256; a = (borderColor / 256 / 256 / 256) % 256; Texture t = new Texture(); t.fileName = shape.images[imageIDX]; t.filterMode = filterMode; t.mipmapLODBias = (int)mipmapLODBias; t.borderColor = new Color32((byte)r, (byte)g, (byte)b, (byte)a); shape.textures.Add(t); break; case KujuTokenID.textures: int textureCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (textureCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.texture); ParseBlock(newBlock, ref shape); textureCount--; } break; case KujuTokenID.image: shape.images.Add(block.ReadString()); break; case KujuTokenID.images: int imageCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (imageCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.image); ParseBlock(newBlock, ref shape); imageCount--; } break; case KujuTokenID.cullable_prims: int numPrims = block.ReadInt32(); int numFlatSections = block.ReadInt32(); int numPrimIdxs = block.ReadInt32(); break; case KujuTokenID.geometry_info: int faceNormals = block.ReadInt32(); int txLightCommands = block.ReadInt32(); int nodeXTrilistIdxs = block.ReadInt32(); int trilistIdxs = block.ReadInt32(); int lineListIdxs = block.ReadInt32(); nodeXTrilistIdxs = block.ReadInt32(); //Duped, or is the first one actually something else? int trilists = block.ReadInt32(); int lineLists = block.ReadInt32(); int pointLists = block.ReadInt32(); int nodeXTrilists = block.ReadInt32(); newBlock = block.ReadSubBlock(KujuTokenID.geometry_nodes); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.geometry_node_map); ParseBlock(newBlock, ref shape); break; case KujuTokenID.geometry_node_map: int[] geometryNodes = new int[block.ReadInt32()]; for (int i = 0; i < geometryNodes.Length; i++) { geometryNodes[i] = block.ReadInt32(); } break; case KujuTokenID.geometry_node: int n_txLightCommands = block.ReadInt32(); int n_nodeXTxLightCmds = block.ReadInt32(); int n_trilists = block.ReadInt32(); int n_lineLists = block.ReadInt32(); int n_pointLists = block.ReadInt32(); newBlock = block.ReadSubBlock(KujuTokenID.cullable_prims); ParseBlock(newBlock, ref shape); break; case KujuTokenID.geometry_nodes: int geometryNodeCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (geometryNodeCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.geometry_node); ParseBlock(newBlock, ref shape); geometryNodeCount--; } break; case KujuTokenID.point: x = block.ReadSingle(); y = block.ReadSingle(); z = block.ReadSingle(); point = new Vector3(x, y, z); shape.points.Add(point); break; case KujuTokenID.vector: x = block.ReadSingle(); y = block.ReadSingle(); z = block.ReadSingle(); point = new Vector3(x, y, z); shape.normals.Add(point); break; case KujuTokenID.points: int pointCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (pointCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.point); ParseBlock(newBlock, ref shape); pointCount--; } break; case KujuTokenID.uv_point: x = block.ReadSingle(); y = block.ReadSingle(); var uv_point = new Vector2(x, y); shape.uv_points.Add(uv_point); break; case KujuTokenID.uv_points: int uvPointCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (uvPointCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.uv_point); ParseBlock(newBlock, ref shape); uvPointCount--; } break; case KujuTokenID.matrices: int matrixCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (matrixCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.matrix); ParseBlock(newBlock, ref shape); matrixCount--; } break; case KujuTokenID.matrix: Matrix currentMatrix = new Matrix(); currentMatrix.Name = block.Label; currentMatrix.A = new Vector3(block.ReadSingle(), block.ReadSingle(), block.ReadSingle()); currentMatrix.B = new Vector3(block.ReadSingle(), block.ReadSingle(), block.ReadSingle()); currentMatrix.C = new Vector3(block.ReadSingle(), block.ReadSingle(), block.ReadSingle()); currentMatrix.D = new Vector3(block.ReadSingle(), block.ReadSingle(), block.ReadSingle()); shape.matrices.Add(currentMatrix); break; case KujuTokenID.normals: int normalCount = block.ReadUInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (normalCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.vector); ParseBlock(newBlock, ref shape); normalCount--; } break; case KujuTokenID.distance_levels_header: int DLevBias = block.ReadInt16(); break; case KujuTokenID.distance_levels: int distanceLevelCount = block.ReadInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (distanceLevelCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.distance_level); ParseBlock(newBlock, ref shape); distanceLevelCount--; } break; case KujuTokenID.distance_level_header: newBlock = block.ReadSubBlock(KujuTokenID.dlevel_selection); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.hierarchy); ParseBlock(newBlock, ref shape); break; case KujuTokenID.distance_level: newBlock = block.ReadSubBlock(KujuTokenID.distance_level_header); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.sub_objects); ParseBlock(newBlock, ref shape); shape.LODs.Add(currentLOD); break; case KujuTokenID.dlevel_selection: currentLOD = new LOD(block.ReadSingle()); break; case KujuTokenID.hierarchy: currentLOD.hierarchy = new int[block.ReadInt32()]; for (int i = 0; i < currentLOD.hierarchy.Length; i++) { currentLOD.hierarchy[i] = block.ReadInt32(); } break; case KujuTokenID.lod_control: newBlock = block.ReadSubBlock(KujuTokenID.distance_levels_header); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.distance_levels); ParseBlock(newBlock, ref shape); break; case KujuTokenID.lod_controls: int lodCount = block.ReadInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (lodCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.lod_control); ParseBlock(newBlock, ref shape); lodCount--; } break; case KujuTokenID.primitives: int capacity = block.ReadInt32(); //Count of the number of entries in the block, not the number of primitives while (capacity > 0) { newBlock = block.ReadSubBlock(new KujuTokenID[] { KujuTokenID.prim_state_idx, KujuTokenID.indexed_trilist }); switch (newBlock.Token) { case KujuTokenID.prim_state_idx: ParseBlock(newBlock, ref shape); string txF = null; try { txF = OpenBveApi.Path.CombineFile(currentFolder, shape.textures[shape.prim_states[shape.currentPrimitiveState].Textures[0]].fileName); if (!File.Exists(txF)) { Interface.AddMessage(MessageType.Warning, true, "Texture file " + shape.textures[shape.prim_states[shape.currentPrimitiveState].Textures[0]].fileName + " was not found."); txF = null; } } catch { Interface.AddMessage(MessageType.Warning, true, "Texture file path " + shape.textures[shape.prim_states[shape.currentPrimitiveState].Textures[0]].fileName + " was invalid."); } currentLOD.subObjects[currentLOD.subObjects.Count - 1].materials.Add(new Material(txF)); break; case KujuTokenID.indexed_trilist: ParseBlock(newBlock, ref shape); break; default: throw new Exception("Unexpected primitive type, got " + currentToken); } capacity--; } break; case KujuTokenID.prim_state_idx: shape.currentPrimitiveState = block.ReadInt32(); break; case KujuTokenID.indexed_trilist: newBlock = block.ReadSubBlock(KujuTokenID.vertex_idxs); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.normal_idxs); ParseBlock(newBlock, ref shape); break; case KujuTokenID.sub_object: newBlock = block.ReadSubBlock(KujuTokenID.sub_object_header); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.vertices); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.vertex_sets); ParseBlock(newBlock, ref shape); newBlock = block.ReadSubBlock(KujuTokenID.primitives); ParseBlock(newBlock, ref shape); break; case KujuTokenID.sub_objects: int subObjectCount = block.ReadInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (subObjectCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.sub_object); ParseBlock(newBlock, ref shape); subObjectCount--; } break; case KujuTokenID.sub_object_header: currentLOD.subObjects.Add(new SubObject()); shape.totalObjects++; flags = block.ReadUInt32(); int sortVectorIdx = block.ReadInt32(); int volIdx = block.ReadInt32(); uint sourceVertexFormatFlags = block.ReadUInt32(); uint destinationVertexFormatFlags = block.ReadUInt32(); newBlock = block.ReadSubBlock(KujuTokenID.geometry_info); ParseBlock(newBlock, ref shape); /* * Optional stuff, need to check if we're running off the end of the stream before reading each block */ if (block.Length() - block.Position() > 1) { newBlock = block.ReadSubBlock(KujuTokenID.subobject_shaders); ParseBlock(newBlock, ref shape); } if (block.Length() - block.Position() > 1) { newBlock = block.ReadSubBlock(KujuTokenID.subobject_light_cfgs); ParseBlock(newBlock, ref shape); } if (block.Length() - block.Position() > 1) { int subObjectID = block.ReadInt32(); } break; case KujuTokenID.subobject_light_cfgs: int[] subobject_light_cfgs = new int[block.ReadInt32()]; for (int i = 0; i < subobject_light_cfgs.Length; i++) { subobject_light_cfgs[i] = block.ReadInt32(); } break; case KujuTokenID.subobject_shaders: int[] subobject_shaders = new int[block.ReadInt32()]; for (int i = 0; i < subobject_shaders.Length; i++) { subobject_shaders[i] = block.ReadInt32(); } break; case KujuTokenID.vertices: int vertexCount = block.ReadInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (vertexCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.vertex); ParseBlock(newBlock, ref shape); vertexCount--; } break; case KujuTokenID.vertex: flags = block.ReadUInt32(); //Various control variables, not supported int myPoint = block.ReadInt32(); //Index to points array int myNormal = block.ReadInt32(); //Index to normals array Vertex v = new Vertex(shape.points[myPoint], shape.normals[myNormal]); uint Color1 = block.ReadUInt32(); uint Color2 = block.ReadUInt32(); newBlock = block.ReadSubBlock(KujuTokenID.vertex_uvs); ParseBlock(newBlock, ref shape, ref v); currentLOD.subObjects[currentLOD.subObjects.Count - 1].verticies.Add(v); break; case KujuTokenID.vertex_idxs: int remainingVertex = block.ReadInt32() / 3; while (remainingVertex > 0) { int v1 = block.ReadInt32(); int v2 = block.ReadInt32(); int v3 = block.ReadInt32(); currentLOD.subObjects[currentLOD.subObjects.Count - 1].faces.Add(new Face(new int[] { v1, v2, v3 }, currentLOD.subObjects[currentLOD.subObjects.Count - 1].materials.Count - 1)); remainingVertex--; } break; case KujuTokenID.vertex_set: int vertexStateIndex = block.ReadInt32(); //Index to the vtx_states member int hierarchy = shape.vtx_states[vertexStateIndex].hierarchyID; //Now pull the hierachy ID out int setStartVertexIndex = block.ReadInt32(); //First vertex int setVertexCount = block.ReadInt32(); //Total number of vert VertexSet vts = new VertexSet(); vts.hierarchyIndex = hierarchy; vts.startVertex = setStartVertexIndex; vts.numVerticies = setVertexCount; currentLOD.subObjects[currentLOD.subObjects.Count - 1].vertexSets.Add(vts); break; case KujuTokenID.vertex_sets: int vertexSetCount = block.ReadInt16(); if (block is BinaryBlock) { block.ReadUInt16(); } while (vertexSetCount > 0) { newBlock = block.ReadSubBlock(KujuTokenID.vertex_set); ParseBlock(newBlock, ref shape); vertexSetCount--; } //We now need to transform our verticies currentLOD.subObjects[currentLOD.subObjects.Count - 1].TransformVerticies(shape.matrices); break; case KujuTokenID.vertex_uvs: int[] vertex_uvs = new int[block.ReadInt32()]; for (int i = 0; i < vertex_uvs.Length; i++) { vertex_uvs[i] = block.ReadInt32(); } //Looks as if vertex_uvs should always be of length 1, thus: vertex.TextureCoordinates = shape.uv_points[vertex_uvs[0]]; break; } }
internal static ObjectManager.AnimatedObjectCollection ReadObject(string fileName) { MsTsShape shape = new MsTsShape(); ObjectManager.AnimatedObjectCollection Result = new ObjectManager.AnimatedObjectCollection { Objects = new ObjectManager.AnimatedObject[4] }; currentFolder = Path.GetDirectoryName(fileName); Stream fb = new FileStream(fileName, FileMode.Open, FileAccess.Read); byte[] buffer = new byte[34]; fb.Read(buffer, 0, 2); bool unicode = (buffer[0] == 0xFF && buffer[1] == 0xFE); string headerString; if (unicode) { fb.Read(buffer, 0, 32); headerString = Encoding.Unicode.GetString(buffer, 0, 16); } else { fb.Read(buffer, 2, 14); headerString = Encoding.ASCII.GetString(buffer, 0, 8); } // SIMISA@F means compressed // SIMISA@@ means uncompressed if (headerString.StartsWith("SIMISA@F")) { fb = new ZlibStream(fb, CompressionMode.Decompress); } else if (headerString.StartsWith("\r\nSIMISA")) { // ie us1rd2l1000r10d.s, we are going to allow this but warn Console.Error.WriteLine("Improper header in " + fileName); fb.Read(buffer, 0, 4); } else if (!headerString.StartsWith("SIMISA@@")) { throw new Exception("Unrecognized shape file header " + headerString + " in " + fileName); } string subHeader; if (unicode) { fb.Read(buffer, 0, 32); subHeader = Encoding.Unicode.GetString(buffer, 0, 16); } else { fb.Read(buffer, 0, 16); subHeader = Encoding.ASCII.GetString(buffer, 0, 8); } if (subHeader[7] == 't') { using (BinaryReader reader = new BinaryReader(fb)) { byte[] newBytes = reader.ReadBytes((int)(fb.Length - fb.Position)); string s; if (unicode) { s = Encoding.Unicode.GetString(newBytes); } else { s = Encoding.ASCII.GetString(newBytes); } s = s.Replace("\r\n", " ").Replace("\n", " ").Replace("\r", " ").Replace("\t", " ").Trim(); if (!s.StartsWith("shape", StringComparison.InvariantCultureIgnoreCase)) { throw new Exception(); //Shape definition } TextualBlock block = new TextualBlock(s, KujuTokenID.shape); ParseBlock(block, ref shape); } } else if (subHeader[7] != 'b') { throw new Exception("Unrecognized subHeader \"" + subHeader + "\" in " + fileName); } else { using (BinaryReader reader = new BinaryReader(fb)) { KujuTokenID currentToken = (KujuTokenID)reader.ReadUInt16(); if (currentToken != KujuTokenID.shape) { throw new Exception(); //Shape definition } reader.ReadUInt16(); uint remainingBytes = reader.ReadUInt32(); byte[] newBytes = reader.ReadBytes((int)remainingBytes); BinaryBlock block = new BinaryBlock(newBytes, KujuTokenID.shape); ParseBlock(block, ref shape); } } Array.Resize(ref Result.Objects, shape.totalObjects); int idx = 0; double[] previousLODs = new double[shape.totalObjects]; for (int i = 0; i < shape.LODs.Count; i++) { for (int j = 0; j < shape.LODs[i].subObjects.Count; j++) { Result.Objects[idx] = new ObjectManager.AnimatedObject(); Result.Objects[idx].States = new AnimatedObjectState[1]; AnimatedObjectState aos = new AnimatedObjectState(null, Vector3.Zero); shape.LODs[i].subObjects[j].Apply(out aos.Object); aos.Position = new Vector3(0, 0, 0); Result.Objects[idx].States[0] = aos; previousLODs[idx] = shape.LODs[i].viewingDistance; int k = idx; while (k > 0) { if (previousLODs[k] < shape.LODs[i].viewingDistance) { break; } k--; } if (k != 0) { Result.Objects[idx].StateFunction = new FunctionScript(Program.CurrentHost, "if[cameraDistance <" + shape.LODs[i].viewingDistance + ",if[cameraDistance >" + previousLODs[k] + ",0,-1],-1]", true); } else { Result.Objects[idx].StateFunction = new FunctionScript(Program.CurrentHost, "if[cameraDistance <" + shape.LODs[i].viewingDistance + ",0,-1]", true); } idx++; } } return(Result); }
public override bool CanLoadObject(string path) { Stream fb = new FileStream(path, FileMode.Open, FileAccess.Read); byte[] buffer = new byte[34]; fb.Read(buffer, 0, 2); bool unicode = (buffer[0] == 0xFF && buffer[1] == 0xFE); string headerString; if (unicode) { fb.Read(buffer, 0, 32); headerString = Encoding.Unicode.GetString(buffer, 0, 16); } else { fb.Read(buffer, 2, 14); headerString = Encoding.ASCII.GetString(buffer, 0, 8); } // SIMISA@F means compressed // SIMISA@@ means uncompressed if (headerString.StartsWith("SIMISA@F")) { fb = new ZlibStream(fb, CompressionMode.Decompress); } else if (headerString.StartsWith("\r\nSIMISA")) { // ie us1rd2l1000r10d.s, we are going to allow this but warn fb.Read(buffer, 0, 4); } else if (!headerString.StartsWith("SIMISA@@")) { return(false); } string subHeader; if (unicode) { fb.Read(buffer, 0, 32); subHeader = Encoding.Unicode.GetString(buffer, 0, 16); } else { fb.Read(buffer, 0, 16); subHeader = Encoding.ASCII.GetString(buffer, 0, 8); } if (subHeader[7] == 't') { using (BinaryReader reader = new BinaryReader(fb)) { byte[] newBytes = reader.ReadBytes((int)(fb.Length - fb.Position)); string s; if (unicode) { s = Encoding.Unicode.GetString(newBytes); } else { s = Encoding.ASCII.GetString(newBytes); } s = s.Replace("\r\n", " ").Replace("\n", " ").Replace("\r", " ").Replace("\t", " ").Trim(new char[] { }); if (s.StartsWith("shape", StringComparison.InvariantCultureIgnoreCase)) { return(true); } } } else if (subHeader[7] != 'b') { return(false); } else { using (BinaryReader reader = new BinaryReader(fb)) { KujuTokenID currentToken = (KujuTokenID)reader.ReadUInt16(); if (currentToken == KujuTokenID.shape) { return(true); //Shape definition } } } return(false); }