private static void SubmitValuesVector(MatFile p)
        {
            RestRequest request;
            bool dataAvailable;
//float[] row;
            var rows = new float[ROWCOLLUMNS][];
            //int rowi = 0;
            dataAvailable = true;
            while (dataAvailable)
            {
                for (int i = 0; i < ROWCOLLUMNS; i++) dataAvailable = (rows[i] = p.getRowDataSection()) != null;
                request = new RestRequest(Method.POST);
                request.Resource = SimMultiVectorResource + ModelId;
                request.RequestFormat = DataFormat.Json;

                request.AddBody(rows);
                InitRestClient();
                // debug measure without sending  
                var response = client.Execute(request); //register variable values
                if (response.StatusCode != HttpStatusCode.OK)
                    throw new Exception("Error when sending variables to server:" + response.Content);
            }
        }
 private static void SubmitValuesVectorBinary(MatFile p)
 {
     RestRequest request;
     bool dataAvailable;
     //float[] row;
     //var rows = new float[ROWCOLLUMNS][];
     var rows = new byte[ROWCOLLUMNSBINARY*p.getRowSizeinBytes()];
     var row = new byte[p.getRowSizeinBytes()];
     //new List<byte>();//[ROWCOLLUMNS*1023];
     //int rowi = 0;
     dataAvailable = true;
     int writtenbytes = 0;
     int lastrowindex = 0;
     while (dataAvailable)
     {
         for (int i = 0; i < ROWCOLLUMNSBINARY; i++) { 
             dataAvailable = (row = p.getRowDataSectionBytes()) != null;
             if (dataAvailable) { 
                 Buffer.BlockCopy(row,0,rows,i*p.getRowSizeinBytes(),row.Length);
                 writtenbytes += p.getRowSizeinBytes();
             } else
             {
                 lastrowindex= i;
                 break;
             }
         }
         if (!dataAvailable)
         {
             Array.Resize(ref rows, lastrowindex*p.getRowSizeinBytes());
         }
         request = new RestRequest(Method.POST);
         request.Resource = SimMultiBinResource + ModelId+"/"+p.getRowSizeinBytes();
         //request.RequestFormat = DataFormat.Json;
         request.AddFile("vectors", rows,"vectors.bin");
         //request.AddBody(rows);
         InitRestClient();
         // debug measure without sending  
         var response = client.Execute(request); //register variable values
         if (response.StatusCode != HttpStatusCode.OK)
             throw new Exception("Error when sending variable names to server:" + response.Content);
     }
 }
Пример #3
0
        public CmpFile(IntermediateNode rootnode, ILibFile additionalLibrary)
        {
            this.additionalLibrary = additionalLibrary;

            Models     = new Dictionary <string, ModelFile>();
            Cameras    = new Dictionary <string, CmpCameraInfo>();
            Constructs = new ConstructCollection();
            Parts      = new List <Part>();
            List <string> modelNames = new List <string>();

            foreach (Node node in rootnode)
            {
                switch (node.Name.ToLowerInvariant())
                {
                case "exporter version":
                    break;

                case "vmeshlibrary":
                    IntermediateNode vMeshLibraryNode = node as IntermediateNode;
                    if (VMeshLibrary == null)
                    {
                        VMeshLibrary = new VmsFile(vMeshLibraryNode, this);
                    }
                    else
                    {
                        throw new Exception("Multiple vmeshlibrary nodes in cmp root");
                    }
                    break;

                case "animation":
                    IntermediateNode animationNode = node as IntermediateNode;
                    if (Animation == null)
                    {
                        Animation = new AnmFile(animationNode, Constructs);
                    }
                    else
                    {
                        throw new Exception("Multiple animation nodes in cmp root");
                    }
                    break;

                case "material library":
                    IntermediateNode materialLibraryNode = node as IntermediateNode;
                    if (MaterialLibrary == null)
                    {
                        MaterialLibrary = new MatFile(materialLibraryNode, this);
                    }
                    else
                    {
                        throw new Exception("Multiple material library nodes in cmp root");
                    }
                    break;

                case "texture library":
                    IntermediateNode textureLibraryNode = node as IntermediateNode;
                    if (TextureLibrary == null)
                    {
                        TextureLibrary = new TxmFile(textureLibraryNode);
                    }
                    else
                    {
                        throw new Exception("Multiple texture library nodes in cmp root");
                    }
                    break;

                case "cmpnd":
                    IntermediateNode cmpndNode = node as IntermediateNode;
                    foreach (Node SubNode in cmpndNode)
                    {
                        if (SubNode is LeafNode)
                        {
                            continue;
                        }
                        var cmpndSubNode = (IntermediateNode)SubNode;
                        if (cmpndSubNode.Name.Equals("cons", StringComparison.OrdinalIgnoreCase))
                        {
                            Constructs.AddNode(cmpndSubNode);
                        }
                        else if (
                            cmpndSubNode.Name.StartsWith("part_", StringComparison.OrdinalIgnoreCase) ||
                            cmpndSubNode.Name.Equals("root", StringComparison.OrdinalIgnoreCase)
                            )
                        {
                            string objectName = string.Empty, fileName = string.Empty;

                            foreach (LeafNode partNode in cmpndSubNode)
                            {
                                switch (partNode.Name.ToLowerInvariant())
                                {
                                case "object name":
                                    objectName = partNode.StringData;
                                    break;

                                case "file name":
                                    fileName = partNode.StringData;
                                    break;

                                case "index":
                                    break;

                                default:
                                    FLLog.Error("Cmp", "Invalid node in " + cmpndSubNode.Name + ": " + partNode.Name);
                                    break;
                                }
                            }
                            Parts.Add(new Part(objectName, fileName, Models, Cameras, Constructs));
                        }
                        else
                        {
                            throw new Exception("Invalid node in " + cmpndNode.Name + ": " + cmpndSubNode.Name);
                        }
                    }
                    break;

                case "materialanim":
                    MaterialAnim = new MaterialAnimCollection((IntermediateNode)node);
                    break;

                default:
                    if (node is IntermediateNode)
                    {
                        var im = (IntermediateNode)node;
                        if (im.Any(x => x.Name.Equals("vmeshpart", StringComparison.OrdinalIgnoreCase) ||
                                   x.Name.Equals("multilevel", StringComparison.OrdinalIgnoreCase)))
                        {
                            ModelFile m = new ModelFile(im, this);
                            m.Path = node.Name;
                            Models.Add(node.Name, m);
                            modelNames.Add(node.Name);
                            break;
                        }
                        else if (im.Any(x => x.Name.Equals("camera", StringComparison.OrdinalIgnoreCase)))
                        {
                            var cam = new CmpCameraInfo(im);
                            Cameras.Add(im.Name, cam);
                            break;
                        }
                    }
                    FLLog.Error("Cmp", Path ?? "Utf" + ": Invalid Node in cmp root: " + node.Name);
                    break;
                }
            }
            //FL handles cmpnd nodes that point to non-existant models: fix up here
            List <Part> broken = new List <Part>();

            for (int i = 0; i < Parts.Count; i++)
            {
                if (Parts[i].IsBroken())
                {
                    broken.Add(Parts[i]);
                }
            }
            foreach (var b in broken)
            {
                Parts.Remove(b);
            }
        }
Пример #4
0
        public DfmFile(IntermediateNode root, ILibFile additionalLibrary)
        {
            this.additionalLibrary = additionalLibrary;
            Levels = new Dictionary <int, DfmMesh>();

            Bones      = new Dictionary <string, Bone>();
            Parts      = new Dictionary <int, DfmPart>();
            Constructs = new DfmConstructs();

            foreach (Node node in root)
            {
                switch (node.Name.ToLowerInvariant())
                {
                case "exporter version":
                    break;

                case "material library":
                    IntermediateNode materialLibraryNode = node as IntermediateNode;
                    if (MaterialLibrary == null)
                    {
                        MaterialLibrary = new MatFile(materialLibraryNode, this);
                    }
                    else
                    {
                        throw new Exception("Multiple material library nodes in dfm root");
                    }
                    break;

                case "texture library":
                    IntermediateNode textureLibraryNode = node as IntermediateNode;
                    if (TextureLibrary == null)
                    {
                        TextureLibrary = new TxmFile(textureLibraryNode);
                    }
                    else
                    {
                        throw new Exception("Multiple texture library nodes in dfm root");
                    }
                    break;

                case "multilevel":
                    IntermediateNode multiLevelNode = node as IntermediateNode;
                    foreach (Node multiLevelSubNode in multiLevelNode)
                    {
                        if (multiLevelSubNode.Name.StartsWith("mesh", StringComparison.OrdinalIgnoreCase))
                        {
                            IntermediateNode meshNode = multiLevelSubNode as IntermediateNode;

                            int level = 0;
                            if (!int.TryParse(meshNode.Name.Substring(4), out level))
                            {
                                throw new Exception("");
                            }
                            Levels.Add(level, new DfmMesh(meshNode, this, Parts));
                        }
                        else if (multiLevelSubNode.Name.Equals("fractions", StringComparison.OrdinalIgnoreCase))
                        {
                            LeafNode fractionsNode = multiLevelSubNode as LeafNode;
                            if (Fractions == null)
                            {
                                Fractions = fractionsNode.SingleArrayData;
                            }
                            else
                            {
                                throw new Exception("Multiple fractions nodes in multilevel node");
                            }
                        }
                        else
                        {
                            throw new Exception("Invalid node in " + multiLevelNode.Name + ": " + multiLevelSubNode.Name);
                        }
                    }
                    break;

                case "skeleton":
                    IntermediateNode skeletonNode = node as IntermediateNode;
                    foreach (LeafNode skeletonSubNode in skeletonNode)
                    {
                        switch (skeletonSubNode.Name.ToLowerInvariant())
                        {
                        case "name":
                            if (Skeleton == null)
                            {
                                Skeleton = skeletonSubNode.StringData;
                            }
                            else
                            {
                                throw new Exception("Multiple name nodes in skeleton node");
                            }
                            break;

                        default: throw new Exception("Invalid node in " + skeletonSubNode.Name + ": " + skeletonSubNode.Name);
                        }
                    }
                    break;

                case "cmpnd":
                    IntermediateNode cmpndNode = node as IntermediateNode;
                    foreach (Node cmpndSubNode in cmpndNode)
                    {
                        if (cmpndSubNode.Name.Equals("scale", StringComparison.OrdinalIgnoreCase))
                        {
                            if (Scale == null)
                            {
                                Scale = (cmpndSubNode as LeafNode).SingleData;
                            }
                            else
                            {
                                throw new Exception("Multiple scale nodes in cmpnd node");
                            }
                        }
                        else if (cmpndSubNode.Name.Equals("cons", StringComparison.OrdinalIgnoreCase))
                        {
                            IntermediateNode consNode = cmpndSubNode as IntermediateNode;
                            Constructs.AddNode(consNode);
                        }
                        else if (
                            cmpndSubNode.Name.StartsWith("part_", StringComparison.OrdinalIgnoreCase) ||
                            cmpndSubNode.Name.Equals("root", StringComparison.OrdinalIgnoreCase)
                            )
                        {
                            IntermediateNode partsNode = cmpndSubNode as IntermediateNode;
                            string           objectName = string.Empty, fileName = string.Empty;
                            int index = -1;

                            foreach (LeafNode partNode in partsNode)
                            {
                                switch (partNode.Name.ToLowerInvariant())
                                {
                                case "object name":
                                    objectName = partNode.StringData;
                                    break;

                                case "file name":
                                    fileName = partNode.StringData;
                                    break;

                                case "index":
                                    index = partNode.Int32Data.Value;
                                    break;

                                default: throw new Exception("Invalid node in " + cmpndSubNode.Name + ": " + partNode.Name);
                                }
                            }

                            Parts.Add(index, new DfmPart(objectName, fileName, Bones, null));
                        }
                        else
                        {
                            throw new Exception("Invalid node in " + node.Name + ": " + cmpndSubNode.Name);
                        }
                    }
                    break;

                default:
                    if (node.Name.EndsWith(".3db", StringComparison.OrdinalIgnoreCase))
                    {
                        Bone b = new Bone(node as IntermediateNode);
                        Bones.Add(node.Name, b);
                    }
                    else
                    {
                        throw new Exception("Invalid Node in dfm root: " + node.Name);
                    }
                    break;
                }
            }
        }
Пример #5
0
        public Race(string filename, string playerVehicleFile)
        {
            Race.Current = this;

            Logger.Log("Starting race " + Path.GetFileName(filename));

            ConfigFile = new RaceFile(filename);

            foreach (string matFileName in ConfigFile.MaterialFiles)
            {
                MatFile matFile = new MatFile(matFileName);
                ResourceCache.Add(matFile);
            }

            foreach (string pixFileName in ConfigFile.PixFiles)
            {
                PixFile pixFile = new PixFile(pixFileName);
                ResourceCache.Add(pixFile);
            }

            if (GameVars.Emulation == EmulationMode.Demo)
            {
                ResourceCache.Add(new CMaterial("drkcurb.mat", 226)); //demo doesn't have this file, I guess the color is hard-coded
            }
            else
            {
                ResourceCache.Add(new MatFile("drkcurb.mat"));
            }

            ResourceCache.ResolveMaterials();

            if (filename.Contains("TESTMAP")) //nasty hack...
            {
                GameVars.Scale.Y *= 0.5f;
            }

            DatFile modelFile = new DatFile(ConfigFile.ModelFile);

            ActFile actFile = new ActFile(ConfigFile.ActorFile);

            _actors = actFile.Hierarchy;
            _actors.AttachModels(modelFile.Models);
            _actors.ResolveTransforms(false, ConfigFile.Grooves);

            if (filename.Contains("TESTMAP")) //nasty hack...
            {
                GameVars.Scale.Y *= 2f;
            }

            // link the actors and grooves
            foreach (BaseGroove g in ConfigFile.Grooves)
            {
                g.SetActor(_actors.GetByName(g.ActorName));
            }

            // link the funks and materials
            foreach (BaseFunk f in ConfigFile.Funks)
            {
                f.Resolve();
            }

            if (ConfigFile.SkyboxTexture != "none")
            {
                PixFile horizonPix = new PixFile(ConfigFile.SkyboxTexture);
                _skybox = SkyboxGenerator.Generate(horizonPix.PixMaps[0].Texture, ConfigFile.SkyboxRepetitionsX - 3f, ConfigFile.DepthCueMode);
                _skybox.HeightOffset = -220 + ConfigFile.SkyboxPositionY * 1.5f;
            }

            Physics.TrackProcessor.GenerateTrackActor(ConfigFile, _actors, out _nonCars);

            Logger.Log("NonCars: " + _nonCars.Count);

            GridPlacer.Reset();

            List <int> opponentIds = new List <int>();
            List <int> pickedNbrs  = new List <int>();

            for (int i = 0; i < 5; i++)
            {
                int index = 0;
                while (true)
                {
                    index = Engine.Random.Next(1, OpponentsFile.Instance.Opponents.Count);
                    if (!pickedNbrs.Contains(index))
                    {
                        pickedNbrs.Add(index);
                        break;
                    }
                }
                try
                {
                    Opponents.Add(new Opponent(OpponentsFile.Instance.Opponents[index].FileName, ConfigFile.GridPosition, ConfigFile.GridDirection));
                    NbrOpponents++;
                }
                catch (Exception ex)
                {
                    Logger.Log("Error while loading opponent " + OpponentsFile.Instance.Opponents[index].FileName + ", " + ex.Message);
                }
            }

            foreach (CopStartPoint point in ConfigFile.CopStartPoints)
            {
                Opponents.Add(new Opponent(point.IsSpecialForces ? "bigapc.txt" : "apc.txt", point.Position, 0, new CopDriver()));
            }

            foreach (Opponent o in Opponents)
            {
                Drivers.Add(o.Driver);
            }

            OpponentController.Nodes = ConfigFile.OpponentPathNodes;

            PlayerVehicle = new Vehicle(GameVars.BasePath + @"cars\" + playerVehicleFile, new PlayerDriver());
            PlayerVehicle.PlaceOnGrid(ConfigFile.GridPosition, ConfigFile.GridDirection);
            Drivers.Add(PlayerVehicle.Driver);

            Peds = new PedestrianController(ConfigFile.Peds);
            _map = new RaceMap(this);

            RaceTime = new RaceTimeController();

            PhysX.Instance.Scene.SetActorGroupPairFlags(PhysXConsts.TrackId, PhysXConsts.VehicleId, ContactPairFlag.Forces | ContactPairFlag.OnStartTouch | ContactPairFlag.OnTouch);
            PhysX.Instance.Scene.SetActorGroupPairFlags(PhysXConsts.VehicleId, PhysXConsts.NonCarId, ContactPairFlag.Forces | ContactPairFlag.OnStartTouch | ContactPairFlag.OnTouch);
            PhysX.Instance.Scene.SetActorGroupPairFlags(PhysXConsts.TrackId, PhysXConsts.NonCarId, ContactPairFlag.OnTouch);
            PhysX.Instance.Scene.SetActorGroupPairFlags(PhysXConsts.VehicleId, PhysXConsts.VehicleId, ContactPairFlag.Forces | ContactPairFlag.OnTouch | ContactPairFlag.OnStartTouch | ContactPairFlag.OnEndTouch);
        }
Пример #6
0
        private void load(IntermediateNode root, ILibFile additionalLibrary)
        {
            this.additionalLibrary = additionalLibrary;
            ready = false;

            Hardpoints = new List <HardpointDefinition>();
            var lvls = new Dictionary <int, VMeshRef>();

            foreach (Node node in root)
            {
                switch (node.Name.ToLowerInvariant())
                {
                case "exporter version":
                    break;

                case "vmeshlibrary":
                    IntermediateNode vMeshLibraryNode = node as IntermediateNode;
                    if (VMeshLibrary == null)
                    {
                        VMeshLibrary = new VmsFile(vMeshLibraryNode, this);
                    }
                    else
                    {
                        throw new Exception("Multiple vmeshlibrary nodes in 3db root");
                    }
                    break;

                case "material library":
                    IntermediateNode materialLibraryNode = node as IntermediateNode;
                    if (MaterialLibrary == null)
                    {
                        MaterialLibrary = new MatFile(materialLibraryNode, this);
                    }
                    else
                    {
                        throw new Exception("Multiple material library nodes in 3db root");
                    }
                    break;

                case "texture library":
                    IntermediateNode textureLibraryNode = node as IntermediateNode;
                    if (TextureLibrary == null)
                    {
                        TextureLibrary = new TxmFile(textureLibraryNode);
                    }
                    else
                    {
                        throw new Exception("Multiple texture library nodes in 3db root");
                    }
                    break;

                case "hardpoints":
                    IntermediateNode hardpointsNode = node as IntermediateNode;
                    foreach (Node hpn in hardpointsNode)
                    {
                        if (hpn is LeafNode)
                        {
                            continue;                                     //No nodes here
                        }
                        var hardpointTypeNode = (IntermediateNode)hpn;
                        switch (hardpointTypeNode.Name.ToLowerInvariant())
                        {
                        case "fixed":
                            foreach (IntermediateNode fixedNode in hardpointTypeNode)
                            {
                                Hardpoints.Add(new FixedHardpointDefinition(fixedNode));
                            }
                            break;

                        case "revolute":
                            foreach (IntermediateNode revoluteNode in hardpointTypeNode)
                            {
                                Hardpoints.Add(new RevoluteHardpointDefinition(revoluteNode));
                            }
                            break;

                        default:
                            Hardpoints.Add(new FixedHardpointDefinition(hardpointTypeNode));
                            break;
                        }
                    }
                    break;

                case "vmeshpart":
                {
                    IntermediateNode vMeshPartNode = node as IntermediateNode;
                    if (vMeshPartNode.Count == 1)
                    {
                        LeafNode vMeshRefNode = vMeshPartNode[0] as LeafNode;
                        lvls.Add(0, new VMeshRef(vMeshRefNode.DataSegment, this));
                    }
                    else
                    {
                        throw new Exception("Invalid VMeshPart: More than one child or zero elements");
                    }
                }
                break;

                case "multilevel":
                    IntermediateNode multiLevelNode = node as IntermediateNode;
                    foreach (Node multiLevelSubNode in multiLevelNode)
                    {
                        if (multiLevelSubNode.Name.StartsWith("level", StringComparison.OrdinalIgnoreCase))
                        {
                            if (multiLevelSubNode is LeafNode)
                            {
                                continue;
                            }
                            IntermediateNode levelNode = multiLevelSubNode as IntermediateNode;
                            if (levelNode.Count == 1)
                            {
                                int level = 0;
                                if (!int.TryParse(levelNode.Name.Substring(5), out level))
                                {
                                    throw new Exception("Invalid Level: Missing index");
                                }

                                IntermediateNode vMeshPartNode = levelNode[0] as IntermediateNode;

                                if (vMeshPartNode.Count == 1)
                                {
                                    LeafNode vMeshRefNode = vMeshPartNode[0] as LeafNode;
                                    if (vMeshRefNode != null && vMeshRefNode.Name.Equals("vmeshref",
                                                                                         StringComparison.OrdinalIgnoreCase))
                                    {
                                        lvls.Add(level, new VMeshRef(vMeshRefNode.DataSegment, this));
                                    }
                                }
                                else
                                {
                                    throw new Exception("Invalid VMeshPart: More than one child or zero elements");
                                }
                            }
                            //else throw new Exception("Invalid Level: More than one child or zero elements");
                        }
                        else if (multiLevelSubNode.Name.Equals("switch2", StringComparison.OrdinalIgnoreCase))
                        {
                            LeafNode switch2Node = multiLevelSubNode as LeafNode;
                            Switch2 = switch2Node.SingleArrayData;
                        }
                        else
                        {
                            throw new Exception("Invalid node in " + multiLevelNode.Name + ": " + multiLevelSubNode.Name);
                        }
                    }
                    break;

                case "vmeshwire":
                    VMeshWire = new VMeshWire(node as IntermediateNode, this);
                    break;

                case "mass properties":
                    // TODO 3db Mass Properties
                    break;

                case "extent tree":
                    // TODO 3db Extent Tree
                    break;

                case "materialanim":
                    MaterialAnim = new MaterialAnimCollection((IntermediateNode)node);
                    break;

                default:
                    FLLog.Error("3db", (Path ?? "") + ": Invalid node: " + node.Name);
                    break;
                }
            }

            //Sort levels in order
            var lvl2 = new List <VMeshRef>();

            for (int i = 0; i < 100; i++)
            {
                if (lvls.ContainsKey(i))
                {
                    lvl2.Add(lvls[i]);
                }
                else
                {
                    break;
                }
            }
            Levels = lvl2.ToArray();
        }
Пример #7
0
        public CmpFile(IntermediateNode rootnode, ILibFile additionalLibrary)
        {
            this.additionalLibrary = additionalLibrary;

            Models     = new Dictionary <string, ModelFile>();
            Constructs = new ConstructCollection();
            Parts      = new Dictionary <int, Part>();

            foreach (Node node in rootnode)
            {
                switch (node.Name.ToLowerInvariant())
                {
                case "exporter version":
                    break;

                case "vmeshlibrary":
                    IntermediateNode vMeshLibraryNode = node as IntermediateNode;
                    if (VMeshLibrary == null)
                    {
                        VMeshLibrary = new VmsFile(vMeshLibraryNode, this);
                    }
                    else
                    {
                        throw new Exception("Multiple vmeshlibrary nodes in cmp root");
                    }
                    break;

                case "animation":
                    IntermediateNode animationNode = node as IntermediateNode;
                    if (Animation == null)
                    {
                        Animation = new AnmFile(animationNode, Constructs);
                    }
                    else
                    {
                        throw new Exception("Multiple animation nodes in cmp root");
                    }
                    break;

                case "material library":
                    IntermediateNode materialLibraryNode = node as IntermediateNode;
                    if (MaterialLibrary == null)
                    {
                        MaterialLibrary = new MatFile(materialLibraryNode, this);
                    }
                    else
                    {
                        throw new Exception("Multiple material library nodes in cmp root");
                    }
                    break;

                case "texture library":
                    IntermediateNode textureLibraryNode = node as IntermediateNode;
                    if (TextureLibrary == null)
                    {
                        TextureLibrary = new TxmFile(textureLibraryNode);
                    }
                    else
                    {
                        throw new Exception("Multiple texture library nodes in cmp root");
                    }
                    break;

                case "cmpnd":
                    IntermediateNode cmpndNode = node as IntermediateNode;
                    int maxIndices             = int.MaxValue;
                    foreach (Node SubNode in cmpndNode)
                    {
                        if (SubNode is LeafNode)
                        {
                            continue;
                        }
                        var cmpndSubNode = (IntermediateNode)SubNode;
                        if (cmpndSubNode.Name.Equals("cons", StringComparison.OrdinalIgnoreCase))
                        {
                            Constructs.AddNode(cmpndSubNode);
                        }
                        else if (
                            cmpndSubNode.Name.StartsWith("part_", StringComparison.OrdinalIgnoreCase) ||
                            cmpndSubNode.Name.Equals("root", StringComparison.OrdinalIgnoreCase)
                            )
                        {
                            string objectName = string.Empty, fileName = string.Empty;
                            int    index = -1;

                            foreach (LeafNode partNode in cmpndSubNode)
                            {
                                switch (partNode.Name.ToLowerInvariant())
                                {
                                case "object name":
                                    objectName = partNode.StringData;
                                    break;

                                case "file name":
                                    fileName = partNode.StringData;
                                    break;

                                case "index":
                                    if (partNode.Int32Data != null)
                                    {
                                        index = partNode.Int32Data.Value;
                                    }
                                    else
                                    {
                                        index = partNode.Int32ArrayData [0];
                                    }
                                    break;

                                default: throw new Exception("Invalid node in " + cmpndSubNode.Name + ": " + partNode.Name);
                                }
                            }
                            if (Parts.ContainsKey(index))
                            {
                                FLLog.Error("Cmp", "Duplicate index");
                                Parts.Add(maxIndices--, new Part(objectName, fileName, Models, Constructs));
                            }
                            else
                            {
                                Parts.Add(index, new Part(objectName, fileName, Models, Constructs));
                            }
                        }
                        else
                        {
                            throw new Exception("Invalid node in " + cmpndNode.Name + ": " + cmpndSubNode.Name);
                        }
                    }
                    break;

                case "materialanim":
                    MaterialAnim = new MaterialAnimCollection((IntermediateNode)node);
                    break;

                default:
                    if (node.Name.EndsWith(".3db", StringComparison.OrdinalIgnoreCase))
                    {
                        ModelFile m = new ModelFile(node as IntermediateNode, this);
                        m.Path = node.Name;
                        Models.Add(node.Name, m);
                    }
                    else
                    {
                        FLLog.Error("Cmp", Path ?? "Utf" + ": Invalid Node in cmp root: " + node.Name);
                    }
                    break;
                }
            }
        }