コード例 #1
0
        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;
            }
        }
コード例 #2
0
        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++;
        }
コード例 #3
0
        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));
        }
コード例 #4
0
        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));
        }
コード例 #5
0
        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));
        }
コード例 #6
0
        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++;
        }
コード例 #7
0
 /// <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);
コード例 #8
0
 /// <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));
 }
コード例 #9
0
 /// <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));
 }
コード例 #10
0
        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);
        }
コード例 #11
0
ファイル: ShapeParser.cs プロジェクト: resonancellc/OpenBVE
        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;
            }
        }
コード例 #12
0
ファイル: ShapeParser.cs プロジェクト: resonancellc/OpenBVE
        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);
        }
コード例 #13
0
        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);
        }