/// <summary>
        /// Adds RMB models to block node.
        /// </summary>
        /// <param name="block">DFBlock.</param>
        /// <param name="blockNode">BlockNode.</param>
        private void AddRMBModels(ref DFBlock block, BlockNode blockNode)
        {
            // Iterate through all subrecords
            float degrees;

            foreach (DFBlock.RmbSubRecord subRecord in block.RmbBlock.SubRecords)
            {
                // Create subrecord node
                SceneNode subrecordNode = new SceneNode();
                degrees = subRecord.YRotation / rotationDivisor;
                subrecordNode.Position = new Vector3(subRecord.XPos, 0f, -rmbSide + subRecord.ZPos);
                subrecordNode.Rotation = new Vector3(0f, MathHelper.ToRadians(degrees), 0f);
                blockNode.Add(subrecordNode);

                // Iterate through models in this subrecord
                foreach (DFBlock.RmbBlock3dObjectRecord obj in subRecord.Exterior.Block3dObjectRecords)
                {
                    // Create model node
                    ModelNode modelNode = CreateModelNode(obj.ModelIdNum);
                    degrees            = obj.YRotation / rotationDivisor;
                    modelNode.Position = new Vector3(obj.XPos, -obj.YPos, -obj.ZPos);
                    modelNode.Rotation = new Vector3(0f, MathHelper.ToRadians(degrees), 0f);
                    subrecordNode.Add(modelNode);
                }
            }
        }
        /// <summary>
        /// Adds a point light to the scene.
        /// </summary>
        /// <param name="position">Position.</param>
        /// <param name="blockNode">Parent node.</param>
        private void AddPointLight(Vector3 position, float radius, BlockNode blockNode)
        {
            // Create light node
            PointLightNode pointLightNode = new PointLightNode(radius);

            pointLightNode.Position = position;
            blockNode.Add(pointLightNode);
        }
        /// <summary>
        /// Adds RMB ground plane to block node.
        /// </summary>
        /// <param name="block">DFBlock</param>
        /// <param name="climate">ClimateSettings.</param>
        private void AddRMBGroundPlane(ref DFBlock block, BlockNode blockNode, DFLocation.ClimateSettings climate)
        {
            // Add ground plane node
            GroundPlaneNode groundNode = new GroundPlaneNode(
                textureManager.GraphicsDevice,
                textureManager.LoadGroundPlaneTexture(ref block, climate));

            groundNode.Position = new Vector3(0f, groundHeight, 0f);
            blockNode.Add(groundNode);
        }
        /// <summary>
        /// Adds RMB scenery flats to block node.
        /// </summary>
        /// <param name="block">DFBlock</param>
        /// <param name="blockNode">BlockNode.</param>
        /// <param name="sceneryArchive">Scenery texture archive index.</param>
        private void AddRMBSceneryFlats(ref DFBlock block, BlockNode blockNode, int sceneryArchive)
        {
            // Flags
            TextureManager.TextureCreateFlags flags =
                TextureManager.TextureCreateFlags.Dilate |
                TextureManager.TextureCreateFlags.PreMultiplyAlpha;
            if (Core.GraphicsProfile == GraphicsProfile.HiDef)
            {
                flags |= TextureManager.TextureCreateFlags.MipMaps;
            }

            // Add block scenery
            for (int y = 0; y < 16; y++)
            {
                for (int x = 0; x < 16; x++)
                {
                    // Get scenery item
                    DFBlock.RmbGroundScenery scenery =
                        block.RmbBlock.FldHeader.GroundData.GroundScenery[x, y];

                    // Ignore 0 as this appears to be a marker/waypoint of some kind
                    if (scenery.TextureRecord > 0)
                    {
                        // Load flat
                        int     textureKey;
                        Vector2 startSize;
                        Vector2 finalSize;
                        if (true == LoadDaggerfallFlat(
                                sceneryArchive,
                                scenery.TextureRecord,
                                flags,
                                out textureKey,
                                out startSize,
                                out finalSize))
                        {
                            // Calcuate position
                            Vector3 position = new Vector3(
                                x * tileSide,
                                (finalSize.Y / 2) - 4,
                                -rmbSide + y * tileSide);

                            // Create billboard node
                            BillboardNode billboardNode = new BillboardNode(
                                BillboardNode.BillboardType.ClimateScenery,
                                textureKey,
                                finalSize);
                            billboardNode.Position = position;
                            blockNode.Add(billboardNode);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Adds miscellaneous RMB flats to block node.
        /// </summary>
        /// <param name="block">DFBlock</param>
        /// <param name="blockNode">BlockNode.</param>
        private void AddRMBMiscFlats(ref DFBlock block, BlockNode blockNode)
        {
            // Iterate through all misc flat records
            foreach (DFBlock.RmbBlockFlatObjectRecord obj in block.RmbBlock.MiscFlatObjectRecords)
            {
                // Get flat type
                BillboardNode.BillboardType billboardType =
                    GetFlatType(obj.TextureArchive);

                // Flags
                TextureManager.TextureCreateFlags flags =
                    TextureManager.TextureCreateFlags.Dilate |
                    TextureManager.TextureCreateFlags.PreMultiplyAlpha;
                if (Core.GraphicsProfile == GraphicsProfile.HiDef)
                {
                    flags |= TextureManager.TextureCreateFlags.MipMaps;
                }

                // Load flat
                int     textureKey;
                Vector2 startSize;
                Vector2 finalSize;
                if (true == LoadDaggerfallFlat(
                        obj.TextureArchive,
                        obj.TextureRecord,
                        flags,
                        out textureKey,
                        out startSize,
                        out finalSize))
                {
                    // Calcuate position
                    Vector3 position = new Vector3(
                        obj.XPos,
                        -obj.YPos + (finalSize.Y / 2) - 4,
                        -rmbSide + -obj.ZPos);

                    // Create billboard node
                    BillboardNode billboardNode = new BillboardNode(
                        billboardType,
                        textureKey,
                        finalSize);
                    billboardNode.Position = position;
                    blockNode.Add(billboardNode);

                    // Add point light node
                    if (billboardType == BillboardNode.BillboardType.Light)
                    {
                        AddPointLight(position, PointLightNode.ExteriorRadius, blockNode);
                    }
                }
            }
        }
        /// <summary>
        /// Adds RDB flat to scene node.
        /// </summary>
        /// <param name="obj">RdbObject.</param>
        /// <param name="blockNode">BlockNode.</param>
        private void AddRDBFlat(DFBlock.RdbObject obj, BlockNode blockNode)
        {
            // Get flat type
            BillboardNode.BillboardType billboardType =
                GetFlatType(obj.Resources.FlatResource.TextureArchive);

            // Add light if needed

            // Load flat
            int     textureKey;
            Vector2 startSize;
            Vector2 finalSize;

            if (true == LoadDaggerfallFlat(
                    obj.Resources.FlatResource.TextureArchive,
                    obj.Resources.FlatResource.TextureRecord,
                    TextureManager.TextureCreateFlags.Dilate |
                    TextureManager.TextureCreateFlags.PreMultiplyAlpha,
                    out textureKey,
                    out startSize,
                    out finalSize))
            {
                // Foliage (TEXTURE.500 and up) do not seem to use scaling
                // in dungeons. Revert scaling.
                if (obj.Resources.FlatResource.TextureArchive > 499)
                {
                    finalSize = startSize;
                }

                // Calcuate position
                Vector3 position = new Vector3(
                    obj.XPos,
                    -obj.YPos,
                    -obj.ZPos);

                // Create billboard node
                BillboardNode billboardNode = new BillboardNode(
                    billboardType,
                    textureKey,
                    finalSize);
                billboardNode.Position = position;
                blockNode.Add(billboardNode);

                // Add point light node
                if (billboardType == BillboardNode.BillboardType.Light)
                {
                    AddPointLight(position, PointLightNode.DungeonRadius, blockNode);
                }
            }
        }
        /// <summary>
        /// Adds miscellaneous RMB models to block node.
        /// </summary>
        /// <param name="block">DFBlock</param>
        /// <param name="blockNode">BlockNode.</param>
        private void AddRMBMiscModels(ref DFBlock block, BlockNode blockNode)
        {
            // Iterate through all misc records
            float degrees;

            foreach (DFBlock.RmbBlock3dObjectRecord obj in block.RmbBlock.Misc3dObjectRecords)
            {
                // Create misc record node
                SceneNode miscNode = CreateModelNode(obj.ModelIdNum);
                degrees           = obj.YRotation / rotationDivisor;
                miscNode.Position = new Vector3(obj.XPos, -obj.YPos, -rmbSide + -obj.ZPos);
                miscNode.Rotation = new Vector3(0f, MathHelper.ToRadians(degrees), 0f);
                blockNode.Add(miscNode);
            }
        }
        /// <summary>
        /// Adds RDB model to block node.
        /// </summary>
        /// <param name="block">DFBlock.</param>
        /// <param name="obj">RdbObject.</param>
        /// <param name="blockNode">BlockNode.</param>
        /// <param name="groupIndex">Group index.</param>
        private void AddRDBModel(ref DFBlock block, DFBlock.RdbObject obj, BlockNode blockNode, int groupIndex)
        {
            // Get model reference index, desc, and id
            int    modelReference   = obj.Resources.ModelResource.ModelIndex;
            string modelDescription = block.RdbBlock.ModelReferenceList[modelReference].Description;
            uint   modelId          = block.RdbBlock.ModelReferenceList[modelReference].ModelIdNum;

            // Get rotation angle for each axis
            float degreesX = obj.Resources.ModelResource.XRotation / rotationDivisor;
            float degreesY = obj.Resources.ModelResource.YRotation / rotationDivisor;
            float degreesZ = -obj.Resources.ModelResource.ZRotation / rotationDivisor;

            // Calcuate position
            Vector3 position = new Vector3(
                obj.XPos,
                -obj.YPos,
                -obj.ZPos);

            // Calculate rotation
            Vector3 rotation = new Vector3(
                MathHelper.ToRadians(degreesX),
                MathHelper.ToRadians(degreesY),
                MathHelper.ToRadians(degreesZ));

            // Create model node
            ModelNode modelNode = CreateModelNode(modelId);

            modelNode.Position = position;
            modelNode.Rotation = rotation;
            blockNode.Add(modelNode);

            // Setup actions for this node
            CreateModelAction(
                obj.Resources.ModelResource.ActionResource,
                modelNode,
                modelDescription,
                groupIndex,
                obj.Index);
        }