private LineRenderable CreateNormalLines()
        {
            List<Vector3> points = new List<Vector3>();
            List<ColorEx> colors = new List<ColorEx>();

            foreach (SubEntity subEntity in loadedModel.SubEntities) {
                if (subEntity.IsVisible) {
                    VertexData vData = subEntity.SubMesh.VertexData;
                    VertexElement[] elems = new VertexElement[4];
                    elems[0] = vData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Position);
                    elems[1] = vData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Normal);
                    elems[2] = vData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Tangent);
                    elems[3] = vData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Binormal);
                    HardwareVertexBuffer[] vBuffers = new HardwareVertexBuffer[4];
                    for (int i = 0; i < 4; ++i) {
                        if (elems[i] == null)
                            vBuffers[i] = null;
                        else
                            vBuffers[i] = vData.vertexBufferBinding.Bindings[elems[i].Source];
                    }
                    Vector3[] positionVectors = ReadBuffer(vBuffers[0], elems[0], vData.vertexCount);
                    Vector3[] normalVectors   = ReadBuffer(vBuffers[1], elems[1], vData.vertexCount);
                    Vector3[] tangentVectors  = ReadBuffer(vBuffers[2], elems[2], vData.vertexCount);
                    Vector3[] binormalVectors = ReadBuffer(vBuffers[3], elems[3], vData.vertexCount);
                    for (int i = 0; i < vData.vertexCount; ++i)
                        BuildAxisLines(points, colors, positionVectors[i],
                                       normalsAxisLength * normalVectors[i],
                                       normalsAxisLength * tangentVectors[i],
                                       normalsAxisLength * binormalVectors[i]);
                }
            }

            if (points.Count == 0)
                return null;
            LineRenderable lines = new LineRenderable();
            lines.SetPoints(points, colors);
            lines.MaterialName = "MVLines";

            return lines;
        }
        private LineRenderable CreateBoneLines(Skeleton skeleton)
        {
            List<Vector3> points = new List<Vector3>();
            List<ColorEx> colors = new List<ColorEx>();
            List<VertexBoneAssignment> vbas = new List<VertexBoneAssignment>();
            int vertexIndex = 0;
            VertexBoneAssignment vba;
            foreach (Bone bone in skeleton.Bones) {
                Matrix4 bindTransform = bone.BindDerivedInverseTransform.Inverse();
                Vector3 bonePosition = bindTransform.Translation;
                Bone parentBone = null;
                if (bone.Parent != null)
                    parentBone = bone.Parent as Bone;
                // If we have a parent bone, draw a line to the parent bone
                if (parentBone != null) {
                    points.Add(parentBone.BindDerivedInverseTransform.Inverse().Translation);
                    points.Add(bonePosition);
                    colors.Add(ColorEx.Cyan);
                    colors.Add(ColorEx.Cyan);
                    // Set up the vba for the bone base
                    vba = new VertexBoneAssignment();
                    vba.vertexIndex = vertexIndex++;
                    vba.weight = 1.0f;
                    vba.boneIndex = parentBone.Handle;
                    vbas.Add(vba);
                    // Set up the vba for the bone end
                    vba = new VertexBoneAssignment();
                    vba.vertexIndex = vertexIndex++;
                    vba.weight = 1.0f;
                    vba.boneIndex = bone.Handle;
                    vbas.Add(vba);
                }
                // Set up axis lines for this entry
                // X axis line
                points.Add(bonePosition);
                points.Add(bindTransform * (Vector3.UnitX * boneAxisLength));
                colors.Add(ColorEx.Red);
                colors.Add(ColorEx.Red);
                vba = new VertexBoneAssignment();
                vba.vertexIndex = vertexIndex++;
                vba.weight = 1.0f;
                vba.boneIndex = bone.Handle;
                vbas.Add(vba);
                vba = new VertexBoneAssignment();
                vba.vertexIndex = vertexIndex++;
                vba.weight = 1.0f;
                vba.boneIndex = bone.Handle;
                vbas.Add(vba);
                // Y axis line
                points.Add(bonePosition);
                points.Add(bindTransform * (Vector3.UnitY * boneAxisLength));
                colors.Add(ColorEx.Blue);
                colors.Add(ColorEx.Blue);
                vba = new VertexBoneAssignment();
                vba.vertexIndex = vertexIndex++;
                vba.weight = 1.0f;
                vba.boneIndex = bone.Handle;
                vbas.Add(vba);
                vba = new VertexBoneAssignment();
                vba.vertexIndex = vertexIndex++;
                vba.weight = 1.0f;
                vba.boneIndex = bone.Handle;
                vbas.Add(vba);
                // Z axis line
                points.Add(bonePosition);
                points.Add(bindTransform * (Vector3.UnitZ * boneAxisLength));
                colors.Add(ColorEx.Lime);
                colors.Add(ColorEx.Lime);
                vba = new VertexBoneAssignment();
                vba.vertexIndex = vertexIndex++;
                vba.weight = 1.0f;
                vba.boneIndex = bone.Handle;
                vbas.Add(vba);
                vba = new VertexBoneAssignment();
                vba.vertexIndex = vertexIndex++;
                vba.weight = 1.0f;
                vba.boneIndex = bone.Handle;
                vbas.Add(vba);
            }

            LineRenderable lines = new LineRenderable();
            lines.SetPoints(points, colors, vbas);
            lines.MaterialName = "MVSkinnedLines";
            lines.Skeleton = skeleton;
            return lines;
        }
        private LineRenderable CreateGridLines(float size, int majorDivisions, int minorDivisions)
        {
            List<Vector3> points = new List<Vector3>();
            List<ColorEx> colors = new List<ColorEx>();

            ColorEx axisColor = ColorEx.Black;
            ColorEx majorColor = ColorEx.DarkGray;
            ColorEx minorColor = ColorEx.Gray;
            float majorIncrement = size / majorDivisions;
            float minorIncrement = size / majorDivisions / minorDivisions;
            float x_max = size / 2;
            float x_min = -1 * size / 2;
            float z_max = size / 2;
            float z_min = -1 * size / 2;
            for (int i = 0; i < majorDivisions + 1; ++i)
            {
                for (int j = 0; j < minorDivisions; j++)
                {
                    float x = x_min + i * majorIncrement + j * minorIncrement;
                    points.Add(new Vector3(x, 0, z_min));
                    points.Add(new Vector3(x, 0, z_max));
                    if (j == 0 && x == 0)
                    {
                        colors.Add(axisColor);
                        colors.Add(axisColor);
                    }
                    else if (j == 0)
                    {
                        colors.Add(majorColor);
                        colors.Add(majorColor);
                    }
                    else
                    {
                        colors.Add(minorColor);
                        colors.Add(minorColor);
                    }
                    float z = z_min + i * majorIncrement + j * minorIncrement;
                    points.Add(new Vector3(x_min, 0, z));
                    points.Add(new Vector3(x_max, 0, z));
                    if (j == 0 && z == 0)
                    {
                        colors.Add(axisColor);
                        colors.Add(axisColor);
                    }
                    else if (j == 0)
                    {
                        colors.Add(majorColor);
                        colors.Add(majorColor);
                    }
                    else
                    {
                        colors.Add(minorColor);
                        colors.Add(minorColor);
                    }
                    // On the last set, don't generate more minor lines
                    if (i == majorDivisions)
                        break;
                }
            }

            LineRenderable lines = new LineRenderable();
            lines.SetPoints(points, colors);
            lines.MaterialName = "MVGridLines";
            return lines;
        }
        private LineRenderable CreateAxisLines(bool selected)
        {
            List<Vector3> points = new List<Vector3>();
            List<ColorEx> colors = new List<ColorEx>();

            BuildAxisLines(points, colors, Vector3.Zero,
                           Vector3.UnitX * socketAxisLength,
                           Vector3.UnitY * socketAxisLength,
                           Vector3.UnitZ * socketAxisLength);

            if (selected)
                BuildCubeLines(points, colors, selectBoxSize);

            LineRenderable lines = new LineRenderable();
            lines.SetPoints(points, colors);
            lines.MaterialName = "MVLines";
            return lines;
        }