public static ClipPlaneType SelectClippingPlane(Vertex[] clipVertices, int[] clipIndices,
            ViewportType viewportType, Point pos, Point size, Vector2 orthoSize, Vector3 orthoPos,
            Vector3 orthoLookAt, ViewportOrientation viewport)
        {
            if (viewportType == ViewportType.Perspective)
                return ClipPlaneType.NONE;

            Vector3 outCamPos = new Vector3(), outSurfPos = new Vector3();
            CalcOrthoCoords(pos, size, orthoSize, orthoPos, orthoLookAt, out outCamPos, out outSurfPos);

            // Indeksy trójkątów które trzeba odrzucić, aby można było wybrać
            // właściwą płaszczyznę obcinającą.
            int minRejectIdx, maxRejectIdx;

            switch (viewport)
            {
                case ViewportOrientation.Front:
                    minRejectIdx = 144/3;
                    maxRejectIdx = 216/3-1;
                    break;
                case ViewportOrientation.Side:
                    minRejectIdx = 72/3;
                    maxRejectIdx = 144/3-1;
                    break;
                case ViewportOrientation.Top:
                    minRejectIdx = 0/3;
                    maxRejectIdx = 72/3-1;
                    break;
                default:
                    minRejectIdx = 0;
                    maxRejectIdx = 0;
                    break;
            }

            Vector3[] shiftDist = new Vector3[6];
            for(int i = 0; i < 6; ++i)
            {
                shiftDist[i] = (clipVertices[8 * i].Position - clipVertices[8 * i + 4].Position) * 2;
            }

            for(int i = 0; i < 6; ++i)
            {
                for(int j = 0; j < 8; ++j)
                {
                    if(j < 4)
                    {
                        clipVertices[i * 8 + j].Position += shiftDist[i];
                    }
                    else
                    {
                        clipVertices[i * 8 + j].Position -= shiftDist[i];
                    }
                }
            }

            List<Triang> clipPlaneTriangs = new List<Triang>();
            for (int i = 0; i < clipIndices.Length; i += 3)
            {
                clipPlaneTriangs.Add(new Triang(clipVertices[clipIndices[i]].Position,
                                                clipVertices[clipIndices[i + 1]].Position,
                                                clipVertices[clipIndices[i + 2]].Position));

            }

            for(int i = 0; i < 6; ++i)
            {
                for(int j = 0; j < 8; ++j)
                {
                    if(j < 4)
                    {
                        clipVertices[i * 8 + j].Position -= shiftDist[i];
                    }
                    else
                    {
                        clipVertices[i * 8 + j].Position += shiftDist[i];
                    }
                }
            }

            Vector3 rayDir = Vector3.Normalize(outSurfPos - outCamPos);
            Ray ray = new Ray(outCamPos + 0.01f*rayDir, rayDir);
            float dist = float.PositiveInfinity;
            float tmpDist;
            int minIdx = -1;

            for (int i = 0; i < clipPlaneTriangs.Count; ++i)
            {
                if (i < minRejectIdx || i > maxRejectIdx)
                {
                    if (Ray.Intersects(ray, clipPlaneTriangs[i].p1, clipPlaneTriangs[i].p2, clipPlaneTriangs[i].p3,
                                       out tmpDist))
                    {
                        if (tmpDist < dist)
                        {
                            dist = tmpDist;
                            minIdx = i;
                        }
                    }
                }
            }

            return (ClipPlaneType) (minIdx == -1 ? -1 : minIdx/12);
        }
        public void RenderBezier(ViewportInfo viewportInfo, BezierSurface bezier)
        {
            if (bezierPp.BackBufferWidth != viewportInfo.resX || bezierPp.BackBufferHeight != viewportInfo.resY || bezierImageCreated)
            {
                bezierPp = new PresentParameters();
                bezierPp.SwapEffect = SwapEffect.Discard;
                bezierPp.Windowed = true;
                bezierPp.BackBufferWidth = viewportInfo.resX;
                bezierPp.BackBufferHeight = viewportInfo.resY;
                bezierPp.BackBufferFormat = Format.A8R8G8B8;

                if (d3dBezier != null)
                {
                    d3dBezier.Dispose();
                }
                if (deviceBezier != null)
                {
                    deviceBezier.Dispose();
                }

                bezierImageCreated = false;

                d3dBezier = new Direct3D();
                deviceBezier = new Device(d3dBezier, 0, DeviceType.Hardware, handleBezier, CreateFlags.HardwareVertexProcessing, bezierPp);

                if(font2 != null)
                {
                    font2.Dispose();
                }
                font2 = new SlimDX.Direct3D9.Font(deviceBezier, new System.Drawing.Font(FontFamily.GenericSansSerif, 7));
            }

            if (top.X != viewportInfo.posX[2] || top.Y != viewportInfo.posY[2] || top.Width != viewportInfo.sizeX[2] ||
                top.Height != viewportInfo.sizeY[2])
            {
                top = new Viewport();
                top.X = viewportInfo.posX[2];
                top.Y = viewportInfo.posY[2];
                top.Width = viewportInfo.sizeX[2];
                top.Height = viewportInfo.sizeY[2];
                top.MinZ = 0;
                top.MaxZ = 1;
            }

            if (front.X != viewportInfo.posX[0] || front.Y != viewportInfo.posY[0] || front.Width != viewportInfo.sizeX[0] ||
                front.Height != viewportInfo.sizeY[0])
            {
                front = new Viewport();
                front.X = viewportInfo.posX[0];
                front.Y = viewportInfo.posY[0];
                front.Width = viewportInfo.sizeX[0];
                front.Height = viewportInfo.sizeY[0];
                front.MinZ = 0;
                front.MaxZ = 1;
            }

            if (side.X != viewportInfo.posX[1] || side.Y != viewportInfo.posY[1] || side.Width != viewportInfo.sizeX[1] ||
                side.Height != viewportInfo.sizeY[1])
            {
                side = new Viewport();
                side.X = viewportInfo.posX[1];
                side.Y = viewportInfo.posY[1];
                side.Width = viewportInfo.sizeX[1];
                side.Height = viewportInfo.sizeY[1];
                side.MinZ = 0;
                side.MaxZ = 1;
            }

            if(perspective.X != viewportInfo.posX[3] || perspective.Y != viewportInfo.posY[3] || perspective.Width != viewportInfo.sizeX[3] ||
                perspective.Height != viewportInfo.sizeY[3])
            {
                perspective = new Viewport();
                perspective.X = viewportInfo.posX[3];
                perspective.Y = viewportInfo.posY[3];
                perspective.Width = viewportInfo.sizeX[3];
                perspective.Height = viewportInfo.sizeY[3];
                perspective.MinZ = 0;
                perspective.MaxZ = 1;
            }

            deviceBezier.SetRenderState(RenderState.Lighting, true);

            deviceBezier.SetLight(0, defLight);
            deviceBezier.EnableLight(0, true);

            deviceBezier.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);
            deviceBezier.SetRenderState(RenderState.CullMode, Cull.None);

            deviceBezier.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);

            Vertex[] gridVertices = new Vertex[bezier.OutputPoints.Length];
            Vertex[] controlVertices = new Vertex[bezier.ControlPoints.Length];

            List<int>[] vertexTriangle = new List<int>[bezier.OutputPoints.Length];
            Parallel.For(0, vertexTriangle.Length, index => vertexTriangle[index] = new List<int>());
            /*for(int i = 0; i < vertexTriangle.Length; ++i)
            {
                vertexTriangle[i] = new List<int>();
            }*/

            int[] indices = new int[3 * bezier.triangles.Count];
            //int[] selIndices = new int[3 * scene.triangles.Count];
            uint numIndices = 0;
            //uint numSelIndices = 0;

            //bool[] selPoints = new bool[scene.points.Count];
            //Parallel.For(0, selPoints.Length, index => selPoints[index] = false);

            for (int i = 0; i < bezier.triangles.Count; i++)
            {
                indices[numIndices++] = (int)bezier.triangles[i].p1;
                indices[numIndices++] = (int)bezier.triangles[i].p2;
                indices[numIndices++] = (int)bezier.triangles[i].p3;

                vertexTriangle[bezier.triangles[i].p1].Add(i);
                vertexTriangle[bezier.triangles[i].p2].Add(i);
                vertexTriangle[bezier.triangles[i].p3].Add(i);
            }

            // Liczenie normalnych siatki trojkątów
            for (int i = 0; i < bezier.OutputPoints.Length; i++)
            {
                Vector3 normal = new Vector3();
                foreach (int face in vertexTriangle[i])
                {
                    normal += Utilities.CalculateNormal(bezier.OutputPoints[(int)bezier.triangles[face].p3], bezier.OutputPoints[(int)bezier.triangles[face].p2],
                            bezier.OutputPoints[(int)bezier.triangles[face].p1]);
                }
                normal.Normalize();

                gridVertices[i].Position = new Vector3(bezier.OutputPoints[i].x, bezier.OutputPoints[i].y, bezier.OutputPoints[i].z);
                gridVertices[i].Normal = normal;
                gridVertices[i].Color = Color.Beige.ToArgb();

            }

            Mesh gridMesh = numIndices > 2 ? new Mesh(deviceBezier, (int)numIndices / 3, bezier.OutputPoints.Length, MeshFlags.Managed | MeshFlags.Use32Bit,
                                                        vertexElems): null;
            VertexBuffer vb = gridMesh != null ? gridMesh.VertexBuffer : null;
            IndexBuffer ib = gridMesh != null ? gridMesh.IndexBuffer : null;

            if (gridMesh != null)
            {
                vb.Lock(0, 0, LockFlags.None).WriteRange(gridVertices);
                vb.Unlock();

                ib.Lock(0, 0, LockFlags.None).WriteRange(indices, 0, (int)numIndices);
                ib.Unlock();
            }

            Mesh controlPointsMesh = Mesh.CreateSphere(deviceBezier, 0.05f, 12, 12);

            if (perspective.Width > 0 && perspective.Height > 0)
            {
                deviceBezier.Viewport = perspective;
                float aspect = (float)perspective.Width / perspective.Height;

                deviceBezier.SetTransform(TransformState.View, Matrix.LookAtRH(
                    bezierCam.position,
                    bezierCam.lookAt,
                    Utilities.RotatePointAroundVector(new Vector3(0, 1, 0),
                    Vector3.Normalize(bezierCam.lookAt - bezierCam.position), bezierCam.rotateAngle)));

                deviceBezier.SetTransform(TransformState.Projection, Matrix.PerspectiveFovRH(
                    bezierCam.fovAngle,
                    aspect,
                    0.01f,
                    110000));

                deviceBezier.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.FromArgb(230, 230, 230), 1.0f, 0);
                deviceBezier.BeginScene();

                if (gridMesh != null)
                {
                    gridMesh.DrawSubset(0);
                    deviceBezier.SetRenderState(RenderState.FillMode, FillMode.Solid);

                    for (int i = 0; i < bezier.ControlPoints.Length; i++)
                    {
                        deviceBezier.SetTransform(TransformState.World, Matrix.Translation(
                                                                        bezier.ControlPoints[i].x,
                                                                        bezier.ControlPoints[i].y,
                                                                        bezier.ControlPoints[i].z));
                        if (i == bezier.selectedPointIdx)
                        {
                            deviceBezier.Material = selectedControlPointMaterial;
                            deviceBezier.SetRenderState(RenderState.Lighting, false);
                            controlPointsMesh.DrawSubset(0);
                            deviceBezier.Material = controlPointMaterial;
                            deviceBezier.SetRenderState(RenderState.Lighting, true);
                        }
                        else
                        {
                            controlPointsMesh.DrawSubset(0);
                        }
                    }
                    deviceBezier.SetTransform(TransformState.World, Matrix.Identity);
                    deviceBezier.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);

                }

                deviceBezier.EndScene();
            }
            if (top.Width > 0 && top.Height > 0)
            {
                deviceBezier.Viewport = top;

                deviceBezier.SetTransform(TransformState.View, Matrix.LookAtRH(
                   bezierOrthoPos[2],
                   bezierOrthoLookAt[2],
                   new Vector3(0, 1, 0)));

                deviceBezier.SetTransform(TransformState.Projection, Matrix.OrthoRH(
                    bezierOrthoWidth[2],
                    (float)(top.Height) / top.Width * bezierOrthoWidth[2],
                    0.01f,
                    110000));

                deviceBezier.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.FromArgb(230, 230, 230), 1.0f, 0);
                deviceBezier.BeginScene();

                string text1 = " -z\n/|\\\n |\n";
                font2.DrawString(null, text1, viewportInfo.posX[2] + 15, viewportInfo.posY[2], Color.Blue);
                string text2 = "\n\n\n  -----> x";
                font2.DrawString(null, text2, viewportInfo.posX[2] + 15, viewportInfo.posY[2], Color.Red);

                if (gridMesh != null)
                {
                    gridMesh.DrawSubset(0);
                    deviceBezier.SetRenderState(RenderState.FillMode, FillMode.Solid);

                    for (int i = 0; i < bezier.ControlPoints.Length; i++)
                    {
                        deviceBezier.SetTransform(TransformState.World, Matrix.Translation(
                                                                        bezier.ControlPoints[i].x,
                                                                        bezier.ControlPoints[i].y,
                                                                        bezier.ControlPoints[i].z));
                        if (i == bezier.selectedPointIdx)
                        {
                            deviceBezier.Material = selectedControlPointMaterial;
                            deviceBezier.SetRenderState(RenderState.Lighting, false);
                            controlPointsMesh.DrawSubset(0);
                            deviceBezier.Material = controlPointMaterial;
                            deviceBezier.SetRenderState(RenderState.Lighting, true);
                        }
                        else
                        {
                            controlPointsMesh.DrawSubset(0);
                        }
                    }
                    deviceBezier.SetTransform(TransformState.World, Matrix.Identity);
                    deviceBezier.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);
                }

                deviceBezier.EndScene();
            }

            if (front.Width > 0 && front.Height > 0)
            {
                deviceBezier.Viewport = front;

                deviceBezier.SetTransform(TransformState.View, Matrix.LookAtRH(
                   bezierOrthoPos[0],
                   bezierOrthoLookAt[0],
                   new Vector3(0, 1, 0)));

                deviceBezier.SetTransform(TransformState.Projection, Matrix.OrthoRH(
                    bezierOrthoWidth[0],
                    (float)(front.Height) / front.Width * bezierOrthoWidth[0],
                    0.01f,
                    110000));

                deviceBezier.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.FromArgb(230, 230, 230), 1.0f, 0);
                deviceBezier.BeginScene();

                string text1 = " y\n/|\\\n |\n";
                font2.DrawString(null, text1, viewportInfo.posX[0] + 15, viewportInfo.posY[0], Color.Green);
                string text2 = "\n\n\n  -----> x";
                font2.DrawString(null, text2, viewportInfo.posX[0] + 15, viewportInfo.posY[0], Color.Red);

                if (gridMesh != null)
                {
                    gridMesh.DrawSubset(0);
                    deviceBezier.SetRenderState(RenderState.FillMode, FillMode.Solid);

                    for (int i = 0; i < bezier.ControlPoints.Length; i++)
                    {
                        deviceBezier.SetTransform(TransformState.World, Matrix.Translation(
                                                                        bezier.ControlPoints[i].x,
                                                                        bezier.ControlPoints[i].y,
                                                                        bezier.ControlPoints[i].z));
                        if (i == bezier.selectedPointIdx)
                        {
                            deviceBezier.Material = selectedControlPointMaterial;
                            deviceBezier.SetRenderState(RenderState.Lighting, false);
                            controlPointsMesh.DrawSubset(0);
                            deviceBezier.Material = controlPointMaterial;
                            deviceBezier.SetRenderState(RenderState.Lighting, true);
                        }
                        else
                        {
                            controlPointsMesh.DrawSubset(0);
                        }
                    }
                    deviceBezier.SetTransform(TransformState.World, Matrix.Identity);
                    deviceBezier.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);

                }

                deviceBezier.EndScene();
            }

            if (side.Width > 0 && side.Height > 0)
            {
                deviceBezier.Viewport = side;

                deviceBezier.SetTransform(TransformState.View, Matrix.LookAtRH(
                   bezierOrthoPos[1],
                   bezierOrthoLookAt[1],
                   new Vector3(0, 1, 0)));

                deviceBezier.SetTransform(TransformState.Projection, Matrix.OrthoRH(
                    bezierOrthoWidth[1],
                    (float)(side.Height) / side.Width * bezierOrthoWidth[1],
                    0.01f,
                    110000));

                deviceBezier.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.FromArgb(230, 230, 230), 1.0f, 0);
                deviceBezier.BeginScene();

                string text1 = " y\n/|\\\n |\n";
                font2.DrawString(null, text1, viewportInfo.posX[1] + 15, viewportInfo.posY[1], Color.Green);
                string text2 = "\n\n\n  -----> -z";
                font2.DrawString(null, text2, viewportInfo.posX[1] + 15, viewportInfo.posY[1], Color.Blue);

                if (gridMesh != null)
                {
                    gridMesh.DrawSubset(0);
                    deviceBezier.SetRenderState(RenderState.FillMode, FillMode.Solid);

                    for (int i = 0; i < bezier.ControlPoints.Length; i++)
                    {
                        deviceBezier.SetTransform(TransformState.World, Matrix.Translation(
                                                                        bezier.ControlPoints[i].x,
                                                                        bezier.ControlPoints[i].y,
                                                                        bezier.ControlPoints[i].z));
                        if (i == bezier.selectedPointIdx)
                        {
                            deviceBezier.Material = selectedControlPointMaterial;
                            deviceBezier.SetRenderState(RenderState.Lighting, false);
                            controlPointsMesh.DrawSubset(0);
                            deviceBezier.Material = controlPointMaterial;
                            deviceBezier.SetRenderState(RenderState.Lighting, true);
                        }
                        else
                        {
                            controlPointsMesh.DrawSubset(0);
                        }
                    }
                    deviceBezier.SetTransform(TransformState.World, Matrix.Identity);
                    deviceBezier.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);

                }

                deviceBezier.EndScene();
            }

            deviceBezier.Present();

            gridMesh.Dispose();
            controlPointsMesh.Dispose();

            //d3dBezier.Dispose();
            //deviceBezier.Dispose();
        }
        public Renderer(IntPtr handle, IntPtr handleBezier)
        {
            this.handle = handle;
            this.handleBezier = handleBezier;

            currScene = null;

            font = null;
            font2 = null;

            cameras = new List<RenderCamera>();
            lights = new List<RenderLight>();

            orthoWidth = new float[] { 10, 10, 10 };
            orthoPos = new Vector3[] { new Vector3(0, 0, 50001), new Vector3(50001, 0, 0), new Vector3(0, 50001, 0) };
            orthoLookAt = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 0, 0), new Vector3(0, 0, -0.01f) };

            ortoWidhtChange = false;

            bezierOrthoWidth = new float[] { 5, 5, 5 };
            bezierOrthoPos = new Vector3[] { new Vector3(0, 0, 50000), new Vector3(50000, 0, 0), new Vector3(0, 50000, 0) };
            bezierOrthoLookAt = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 0, 0), new Vector3(0, 0, -0.01f) };
            bezierCam = new Camera(null, 0, 0, new Vector3(-10, 10, -10), new Vector3(0, 0, 0), Utilities.DegToRad(15), 0);
            selectedControlPointMaterial = new Material() { Diffuse = new Color4(Color.Red) };
            controlPointMaterial = new Material() { Diffuse = new Color4(Color.Black) };

            camsLookAtPoints = new List<Vector3>();

            clipping = false;
            clipVertices = new Vertex[48];
            for(int i = 0; i < clipVertices.Length; ++i)
            {
                clipVertices[i] = new Vertex();
                clipVertices[i].Color = Color.DarkViolet.ToArgb();
            }
            for(int i = 0; i < 8; ++i)
            {
                clipVertices[i + 0].Position = new Vector3(i == 0 || i == 3 || i == 4 || i == 7 ? -50000 : 50000,
                                                           i == 0 || i == 1 || i == 2 || i == 3 ? 2 : 2 + clipPlaneWidth * orthoWidth[0],
                                                           i == 0 || i == 1 || i == 4 || i == 5 ? 50000 : -50000);
            }
            for(int i = 0; i < 8; ++i)
            {
                clipVertices[i + 8].Position = new Vector3(i == 0 || i == 3 || i == 4 || i == 7 ? 50000 : -50000,
                                                           i == 0 || i == 1 || i == 2 || i == 3 ? -2 : -2 - clipPlaneWidth * orthoWidth[0],
                                                           i == 0 || i == 1 || i == 4 || i == 5 ? 50000 : -50000);
            }
            for(int i = 0; i < 8; ++i)
            {
                clipVertices[i + 16].Position = new Vector3(i == 0 || i == 1 || i == 2 || i == 3 ? 2 : 2 + clipPlaneWidth * orthoWidth[0],
                                                            i == 0 || i == 3 || i == 4 || i == 7 ? 50000 : -50000,
                                                            i == 0 || i == 1 || i == 4 || i == 5 ? 50000 : -50000);
            }
            for(int i = 0; i < 8; ++i)
            {
                clipVertices[i + 24].Position = new Vector3(i == 0 || i == 1 || i == 2 || i == 3 ? -2 : -2 - clipPlaneWidth * orthoWidth[0],
                                                            i == 0 || i == 3 || i == 4 || i == 7 ? -50000 : 50000,
                                                            i == 0 || i == 1 || i == 4 || i == 5 ? 50000 : -50000);
            }
            for(int i = 0; i < 8; ++i)
            {
                clipVertices[i + 32].Position = new Vector3(i == 0 || i == 3 || i == 4 || i == 7 ? -50000 : 50000,
                                                            i == 0 || i == 1 || i == 4 || i == 5 ? -50000 : 50000,
                                                            i == 0 || i == 1 || i == 2 || i == 3 ? -2 : -2 - clipPlaneWidth * orthoWidth[0]);
            }
            for(int i = 0; i < 8; ++i)
            {
                clipVertices[i + 40].Position = new Vector3(i == 0 || i == 3 || i == 4 || i == 7 ? 50000 : -50000,
                                                            i == 0 || i == 1 || i == 4 || i == 5 ? -50000 : 50000,
                                                            i == 0 || i == 1 || i == 2 || i == 3 ? 2 : 2 + clipPlaneWidth * orthoWidth[0]);
            }

            clipIndices = new int[216];
            for(int i = 0; i < 6; ++i)
            {
                clipIndices[36 * i + 0] = 8 * i + 0; clipIndices[36 * i + 1] = 8 * i + 1; clipIndices[36 * i + 2] = 8 * i + 5;
                clipIndices[36 * i + 3] = 8 * i + 0; clipIndices[36 * i + 4] = 8 * i + 5; clipIndices[36 * i + 5] = 8 * i + 4;
                clipIndices[36 * i + 6] = 8 * i + 1; clipIndices[36 * i + 7] = 8 * i + 2; clipIndices[36 * i + 8] = 8 * i + 6;
                clipIndices[36 * i + 9] = 8 * i + 1; clipIndices[36 * i + 10] = 8 * i + 6; clipIndices[36 * i + 11] = 8 * i + 5;
                clipIndices[36 * i + 12] = 8 * i + 2; clipIndices[36 * i + 13] = 8 * i + 3; clipIndices[36 * i + 14] = 8 * i + 7;
                clipIndices[36 * i + 15] = 8 * i + 2; clipIndices[36 * i + 16] = 8 * i + 7; clipIndices[36 * i + 17] = 8 * i + 6;
                clipIndices[36 * i + 18] = 8 * i + 3; clipIndices[36 * i + 19] = 8 * i + 0; clipIndices[36 * i + 20] = 8 * i + 5;
                clipIndices[36 * i + 21] = 8 * i + 3; clipIndices[36 * i + 22] = 8 * i + 5; clipIndices[36 * i + 23] = 8 * i + 7;
                clipIndices[36 * i + 24] = 8 * i + 0; clipIndices[36 * i + 25] = 8 * i + 1; clipIndices[36 * i + 26] = 8 * i + 2;
                clipIndices[36 * i + 27] = 8 * i + 0; clipIndices[36 * i + 28] = 8 * i + 2; clipIndices[36 * i + 29] = 8 * i + 3;
                clipIndices[36 * i + 30] = 8 * i + 4; clipIndices[36 * i + 31] = 8 * i + 5; clipIndices[36 * i + 32] = 8 * i + 6;
                clipIndices[36 * i + 33] = 8 * i + 4; clipIndices[36 * i + 34] = 8 * i + 6; clipIndices[36 * i + 35] = 8 * i + 7;
            }

            perspective = new Viewport();
            perspective.X = 0;
            perspective.Y = 0;
            perspective.Width = 1;
            perspective.Height = 1;
            perspective.MinZ = -1000;
            perspective.MaxZ = 1000;

            top = new Viewport();
            top.X = 0;
            top.Y = 0;
            top.Width = 1;
            top.Height = 1;
            top.MinZ = -1000;
            top.MaxZ = 1000;

            front = new Viewport();
            front.X = 0;
            front.Y = 0;
            front.Width = 1;
            front.Height = 1;
            front.MinZ = -1000;
            front.MaxZ = 1000;

            side = new Viewport();
            side.X = 0;
            side.Y = 0;
            side.Width = 1;
            side.Height = 1;
            side.MinZ = -1000;
            side.MaxZ = 1000;

            defLight = new Light();
            defLight.Type = LightType.Directional;
            defLight.Diffuse = Color.White;
            defLight.Direction = new Vector3(1, -1, -2);

            maxLights = 0;

            vertexElems = new[] {
                new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0),
                new VertexElement(0, 12, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Normal, 0),
                new VertexElement(0, 24, DeclarationType.Color, DeclarationMethod.Default, DeclarationUsage.Color, 0),
                new VertexElement(0, 28, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 0),
                VertexElement.VertexDeclarationEnd
            };

            wireframe = true;
            pp = new PresentParameters();
            pp.SwapEffect = SwapEffect.Discard;
            pp.Windowed = true;
            pp.BackBufferFormat = Format.A8R8G8B8;

            bezierPp = new PresentParameters();
            bezierPp.SwapEffect = SwapEffect.Discard;
            bezierPp.Windowed = true;
            bezierPp.BackBufferFormat = Format.A8R8G8B8;
        }
        public Image GetBezierImage(BezierSurface bezier)
        {
            pp = new PresentParameters();
            pp.SwapEffect = SwapEffect.Discard;
            pp.Windowed = true;
            pp.BackBufferWidth = 512;
            pp.BackBufferHeight = 512;
            pp.BackBufferFormat = Format.A8R8G8B8;

            if (d3dBezier != null)
            {
                d3dBezier.Dispose();
            }
            if (deviceBezier != null)
            {
                deviceBezier.Dispose();
            }

            d3dBezier = new Direct3D();
            deviceBezier = new Device(d3d, 0, DeviceType.Hardware, handle, CreateFlags.HardwareVertexProcessing, pp);

            deviceBezier.SetRenderState(RenderState.Lighting, true);

            deviceBezier.SetLight(0, defLight);
            deviceBezier.EnableLight(0, true);

            deviceBezier.SetRenderState(RenderState.FillMode, FillMode.Solid);
            deviceBezier.SetRenderState(RenderState.CullMode, Cull.None);
            deviceBezier.SetRenderState(RenderState.ShadeMode, ShadeMode.Gouraud);

            Vertex[] gridVertices = new Vertex[bezier.OutputPoints.Length];
            Vertex[] controlVertices = new Vertex[bezier.ControlPoints.Length];

            List<int>[] vertexTriangle = new List<int>[bezier.OutputPoints.Length];
            Parallel.For(0, vertexTriangle.Length, index => vertexTriangle[index] = new List<int>());
            /*for(int i = 0; i < vertexTriangle.Length; ++i)
            {
                vertexTriangle[i] = new List<int>();
            }*/

            int[] indices = new int[3 * bezier.triangles.Count];
            //int[] selIndices = new int[3 * scene.triangles.Count];
            uint numIndices = 0;
            //uint numSelIndices = 0;

            //bool[] selPoints = new bool[scene.points.Count];
            //Parallel.For(0, selPoints.Length, index => selPoints[index] = false);

            for (int i = 0; i < bezier.triangles.Count; i++)
            {
                indices[numIndices++] = (int)bezier.triangles[i].p1;
                indices[numIndices++] = (int)bezier.triangles[i].p2;
                indices[numIndices++] = (int)bezier.triangles[i].p3;

                vertexTriangle[bezier.triangles[i].p1].Add(i);
                vertexTriangle[bezier.triangles[i].p2].Add(i);
                vertexTriangle[bezier.triangles[i].p3].Add(i);
            }

            // Liczenie normalnych siatki trojkątów
            for (int i = 0; i < bezier.OutputPoints.Length; i++)
            {
                Vector3 normal = new Vector3();
                foreach (int face in vertexTriangle[i])
                {
                    normal += Utilities.CalculateNormal(bezier.OutputPoints[(int)bezier.triangles[face].p3], bezier.OutputPoints[(int)bezier.triangles[face].p2],
                            bezier.OutputPoints[(int)bezier.triangles[face].p1]);
                }
                normal.Normalize();

                gridVertices[i].Position = new Vector3(bezier.OutputPoints[i].x, bezier.OutputPoints[i].y, bezier.OutputPoints[i].z);
                gridVertices[i].Normal = normal;
                gridVertices[i].Color = Color.Beige.ToArgb();

            }

            Mesh gridMesh = numIndices > 2 ? new Mesh(deviceBezier, (int)numIndices / 3, bezier.OutputPoints.Length, MeshFlags.Managed | MeshFlags.Use32Bit,
                                                        vertexElems) : null;
            VertexBuffer vb = gridMesh != null ? gridMesh.VertexBuffer : null;
            IndexBuffer ib = gridMesh != null ? gridMesh.IndexBuffer : null;

            if (gridMesh != null)
            {
                vb.Lock(0, 0, LockFlags.None).WriteRange(gridVertices);
                vb.Unlock();

                ib.Lock(0, 0, LockFlags.None).WriteRange(indices, 0, (int)numIndices);
                ib.Unlock();
            }

            Viewport viewport = new Viewport(0, 0, 512, 512, 0, 1);

            Texture texture = new Texture(deviceBezier, 64, 64, 0, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default);
            deviceBezier.SetRenderTarget(0, texture.GetSurfaceLevel(0));

            float aspect = (float)perspective.Width / perspective.Height;

            deviceBezier.SetTransform(TransformState.View, Matrix.LookAtRH(
                bezierCam.position,
                bezierCam.lookAt,
                Utilities.RotatePointAroundVector(new Vector3(0, 1, 0),
                Vector3.Normalize(bezierCam.lookAt - bezierCam.position), bezierCam.rotateAngle)));

            deviceBezier.SetTransform(TransformState.Projection, Matrix.PerspectiveFovRH(
                bezierCam.fovAngle,
                aspect,
                0.01f,
                110000));

            deviceBezier.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.White, 1.0f, 0);
            deviceBezier.BeginScene();

            if (gridMesh != null)
            {
                gridMesh.DrawSubset(0);
            }

            deviceBezier.EndScene();

            Image image = Bitmap.FromStream(Texture.ToStream(texture, ImageFileFormat.Png));

            texture.Dispose();

            bezierImageCreated = true;

            return image;
        }
        public void RenderViews(ViewportInfo viewportInfo, Scene scene)
        {
            currScene = scene;
            #if MEASURE_TIMES
            DateTime ts = DateTime.Now;

            DateTime t1 = DateTime.Now;
            #endif
            if (pp.BackBufferWidth != viewportInfo.resX || pp.BackBufferHeight != viewportInfo.resY)
            {
                pp = new PresentParameters();
                pp.SwapEffect = SwapEffect.Discard;
                pp.Windowed = true;
                pp.BackBufferWidth = viewportInfo.resX;
                pp.BackBufferHeight = viewportInfo.resY;
                pp.BackBufferFormat = Format.A8R8G8B8;

                if (d3d != null)
                {
                    d3d.Dispose();
                }
                if (device != null)
                {
                    device.Dispose();
                }

                d3d = new Direct3D();
                device = new Device(d3d, 0, DeviceType.Hardware, handle, CreateFlags.HardwareVertexProcessing, pp);

                if(font != null)
                {
                    font.Dispose();
                }
                font = new SlimDX.Direct3D9.Font(device, new System.Drawing.Font(FontFamily.GenericSansSerif, 7));
            }

            bool viewportChange = false;

            if(top.X != viewportInfo.posX[2] || top.Y != viewportInfo.posY[2] || top.Width != viewportInfo.sizeX[2] ||
                top.Height != viewportInfo.sizeY[2])
            {
                top = new Viewport();
                top.X = viewportInfo.posX[2];
                top.Y = viewportInfo.posY[2];
                top.Width = viewportInfo.sizeX[2];
                top.Height = viewportInfo.sizeY[2];
                top.MinZ = 0;
                top.MaxZ = 1;

                viewportChange = true;
            }

            if(front.X != viewportInfo.posX[0] || front.Y != viewportInfo.posY[0] || front.Width != viewportInfo.sizeX[0] ||
                front.Height != viewportInfo.sizeY[0])
            {
                front = new Viewport();
                front.X = viewportInfo.posX[0];
                front.Y = viewportInfo.posY[0];
                front.Width = viewportInfo.sizeX[0];
                front.Height = viewportInfo.sizeY[0];
                front.MinZ = 0;
                front.MaxZ = 1;

                viewportChange = true;
            }

            if(side.X != viewportInfo.posX[1] || side.Y != viewportInfo.posY[1] || side.Width != viewportInfo.sizeX[1] ||
                side.Height != viewportInfo.sizeY[1])
            {
                side = new Viewport();
                side.X = viewportInfo.posX[1];
                side.Y = viewportInfo.posY[1];
                side.Width = viewportInfo.sizeX[1];
                side.Height = viewportInfo.sizeY[1];
                side.MinZ = 0;
                side.MaxZ = 1;

                viewportChange = true;
            }

            if(perspective.X != viewportInfo.posX[3] || perspective.Y != viewportInfo.posY[3] || perspective.Width != viewportInfo.sizeX[3] ||
                perspective.Height != viewportInfo.sizeY[3])
            {
                perspective = new Viewport();
                perspective.X = viewportInfo.posX[3];
                perspective.Y = viewportInfo.posY[3];
                perspective.Width = viewportInfo.sizeX[3];
                perspective.Height = viewportInfo.sizeY[3];
                perspective.MinZ = 0;
                perspective.MaxZ = 1;

                viewportChange = true;
            }

            if(perspective.Width > 0 && perspective.Height > 0)
            {
                persPos = new System.Drawing.Point(perspective.Width, perspective.Height);
            }

            #if MEASURE_TIMES
            DateTime t2 = DateTime.Now;
            TimeSpan t = t2 - t1;
            w.WriteLine("Tworzenie device'a                          " + t.Milliseconds);
            #endif

            //selectionTex = Texture.FromFile(device, "..\\..\\selectionTex.png");

            #if MEASURE_TIMES
            t1 = DateTime.Now;
            #endif
            device.SetRenderState(RenderState.Lighting, true);

            for(int i = scene.lights.Count; i < maxLights; ++i)
            {
                device.EnableLight(i, false);
            }
            maxLights = scene.lights.Count;

            int l = 0;
            foreach (Light_ light_ in scene.lights)
            {
                Light light = new Light();
                light.Diffuse = new Color4(light_.colorR, light_.colorG, light_.colorB);
                light.Position = light_.position;
                light.Range = 100000;
                light.Attenuation1 = 2.0f / light_.power;
                if(light_.type == Light_Type.Point || light_.type == Light_Type.Goniometric)
                {
                    light.Type = LightType.Point;
                }
                else
                {
                    light.Type = LightType.Spot;
                }
                if(light_.type == Light_Type.Spot)
                {
                    light.Direction = light_.direction;
                    light.Theta = Utilities.DegToRad(light_.innerAngle);
                    light.Phi = Utilities.DegToRad(light_.outerAngle);
                    light.Falloff = 1;
                }
                device.SetLight(l, light);
                device.EnableLight(l, true);
                ++l;
            }
            #if MEASURE_TIMES
            t2 = DateTime.Now;
            t = t2 - t1;
            w.WriteLine("Tworzenie świateł                           " + t.Milliseconds);

            t1 = DateTime.Now;
            #endif
            device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);
            device.SetRenderState(RenderState.CullMode, Cull.None);
            device.SetRenderState(RenderState.ShadeMode, ShadeMode.Gouraud);
            #if MEASURE_TIMES
            t2 = DateTime.Now;
            t = t2 - t1;
            w.WriteLine("SetRenderState                              " + t.Milliseconds);

            t1 = DateTime.Now;
            #endif

            for(int i = 0; i < scene.points.Count; ++i)
            {
                if(selPoints[i] == true || scene.normals.Count <= i)
                {
                    Vector3D normal = new Vector3D();

                    foreach(int face in vertexTriangle[i])
                    {
                        normal += Utilities.CalculateNormal(scene.points[(int)scene.triangles[face].p3], scene.points[(int)scene.triangles[face].p2],
                            scene.points[(int)scene.triangles[face].p1]);
                    }

                    normal.Normalize();
                    if(scene.normals.Count <= i)
                    {
                        scene.normals.Add(normal);
                    }
                    else
                    {
                        scene.normals[i] = normal;
                    }

                    Vector3D point = scene.points[i];
                    vertices[i].Position = new Vector3(point.x, point.y, point.z);
                    vertices[i].Normal = new Vector3(scene.normals[i].x, scene.normals[i].y, scene.normals[i].z);
                }
            }
            #if MEASURE_TIMES
            t2 = DateTime.Now;
            t = t2 - t1;
            w.WriteLine("Liczenie normalnych                         " + t.Milliseconds);

            t1 = DateTime.Now;
            #endif
            Mesh mesh = numIndices >= 3 ? new Mesh(device, (int)numIndices / 3, scene.points.Count, MeshFlags.Managed | MeshFlags.Use32Bit, vertexElems) : null;
            VertexBuffer vb = mesh != null ? mesh.VertexBuffer : null;
            IndexBuffer ib = mesh != null ? mesh.IndexBuffer : null;
            #if MEASURE_TIMES
            t2 = DateTime.Now;
            t = t2 - t1;
            w.WriteLine("Tworzenie mesh1                             " + t.Milliseconds);

            t1 = DateTime.Now;
            #endif
            if (mesh != null)
            {
                vb.Lock(0, 0, LockFlags.None).WriteRange(vertices);
                vb.Unlock();

                ib.Lock(0, 0, LockFlags.None).WriteRange(indices, 0, (int)numIndices);
                ib.Unlock();
            #if MEASURE_TIMES
                t2 = DateTime.Now;
                t = t2 - t1;
                w.WriteLine("Kopiowanie buforów mesh1                    " + t.Milliseconds);
            #endif
            }

            #if MEASURE_TIMES
            t1 = DateTime.Now;
            #endif
            Mesh selMesh = numSelIndices >= 3 ? new Mesh(device, (int)numSelIndices / 3, scene.points.Count, MeshFlags.Managed | MeshFlags.Use32Bit, vertexElems) : null;
            VertexBuffer selvb = selMesh != null ? selMesh.VertexBuffer : null;
            IndexBuffer selib = selMesh != null ? selMesh.IndexBuffer : null;
            #if MEASURE_TIMES
            t2 = DateTime.Now;
            t = t2 - t1;
            w.WriteLine("Tworzenie mesh2                              " + t.Milliseconds);

            t1 = DateTime.Now;
            #endif
            if (selMesh != null)
            {
                selvb.Lock(0, 0, LockFlags.None).WriteRange(vertices);
                selvb.Unlock();

                selib.Lock(0, 0, LockFlags.None).WriteRange(selIndices, 0, (int)numSelIndices);
                selib.Unlock();
            #if MEASURE_TIMES
                t2 = DateTime.Now;
                t = t2 - t1;
                w.WriteLine("Kopiowanie buforów mesh2                    " + t.Milliseconds);
            #endif
            }

            while(cameras.Count < scene.cams.Count)
            {
                cameras.Add(new RenderCamera());
            }
            while(cameras.Count > scene.cams.Count)
            {
                cameras.RemoveAt(cameras.Count - 1);
            }

            while(camsLookAtPoints.Count < scene.cams.Count)
            {
                camsLookAtPoints.Add(new Vector3());
            }
            while(camsLookAtPoints.Count > scene.cams.Count)
            {
                camsLookAtPoints.RemoveAt(camsLookAtPoints.Count - 1);
            }

            for(int i = 0; i < cameras.Count; ++i)
            {
                if(cameras[i].set == false || viewportChange || cameras[i].position != scene.cams[i].position || cameras[i].lookAt != scene.cams[i].lookAt ||
                    cameras[i].fovAngle != scene.cams[i].fovAngle || cameras[i].rotateAngle != scene.cams[i].rotateAngle)
                {
                    if(cameras[i].set == false)
                    {
                        cameras[i].set = true;
                    }

                    cameras[i].position = scene.cams[i].position;
                    cameras[i].lookAt = scene.cams[i].lookAt;
                    cameras[i].fovAngle = scene.cams[i].fovAngle;
                    cameras[i].rotateAngle = scene.cams[i].rotateAngle;

                    Vector3 upLeft, upRight, loLeft, loRight;
                    SelectingElems.GetViewCorners(cameras[i].position, cameras[i].lookAt, cameras[i].fovAngle, cameras[i].rotateAngle,
                        persPos, out upLeft, out upRight, out loLeft, out loRight);

                    const float camViewLength = 2.0f;

                    Vector3 ld = loLeft - cameras[i].position;
                    ld.Normalize();
                    Vector3 lu = upLeft - cameras[i].position;
                    lu.Normalize();
                    Vector3 rd = loRight - cameras[i].position;
                    rd.Normalize();
                    Vector3 ru = upRight - cameras[i].position;
                    ru.Normalize();

                    cameras[i].points[0] = cameras[i].position;
                    /*cameras[i].points[1] = cameras[i].position + ((0.5f + (cameras[i].fovAngle / 180)) * camViewLength) * ld;
                    cameras[i].points[2] = cameras[i].position + ((0.5f + (cameras[i].fovAngle / 180)) * camViewLength) * lu;
                    cameras[i].points[3] = cameras[i].position + ((0.5f + (cameras[i].fovAngle / 180)) * camViewLength) * ru;
                    cameras[i].points[4] = cameras[i].position + ((0.5f + (cameras[i].fovAngle / 180)) * camViewLength) * rd;*/
                    cameras[i].points[1] = loLeft;
                    cameras[i].points[2] = upLeft;
                    cameras[i].points[3] = upRight;
                    cameras[i].points[4] = loRight;

                    Vector3 up = cameras[i].points[2] - cameras[i].points[1];
                    up.Normalize();
                    Vector3 left = cameras[i].points[2] - cameras[i].points[3];
                    left.Normalize();
                    Vector3 right = -left;

                    float dist = (float)Math.Sqrt((cameras[i].points[2].X - cameras[i].points[3].X) * (cameras[i].points[2].X - cameras[i].points[3].X) +
                                                  (cameras[i].points[2].Y - cameras[i].points[3].Y) * (cameras[i].points[2].Y - cameras[i].points[3].Y) +
                                                  (cameras[i].points[2].Z - cameras[i].points[3].Z) * (cameras[i].points[2].Z - cameras[i].points[3].Z));
                    dist *= 0.8f;

                    float upTriangleFactor = cameras[i].fovAngle / 60;

                    cameras[i].points[5] = (cameras[i].points[2] + cameras[i].points[3]) / 2 + left * upTriangleFactor * 0.3f * dist;
                    cameras[i].points[6] = (cameras[i].points[2] + cameras[i].points[3]) / 2 + up * upTriangleFactor * 0.25f * dist;
                    cameras[i].points[7] = (cameras[i].points[2] + cameras[i].points[3]) / 2 + right * upTriangleFactor * 0.3f * dist;

                    camsLookAtPoints[i] = (cameras[i].points[1] + cameras[i].points[2] + cameras[i].points[3] + cameras[i].points[4]) / 4;
                }
            }

            Vertex[] camVertices = new Vertex[cameras.Count * 8];
            int[] camIndices = new int[3 * cameras.Count * RenderCamera.triangles.Length];

            for(int i = 0; i < cameras.Count; ++i)
            {
                for(int j = 0; j < RenderCamera.triangles.Length; ++j)
                {
                    camIndices[i * 3 * RenderCamera.triangles.Length + 3 * j + 0] = i * cameras[i].points.Length + (int)RenderCamera.triangles[j].p1;
                    camIndices[i * 3 * RenderCamera.triangles.Length + 3 * j + 1] = i * cameras[i].points.Length + (int)RenderCamera.triangles[j].p2;
                    camIndices[i * 3 * RenderCamera.triangles.Length + 3 * j + 2] = i * cameras[i].points.Length + (int)RenderCamera.triangles[j].p3;
                }
            }

            bool[] selCameras = new bool[cameras.Count];
            for(int i = 0; i < selCameras.Length; ++i)
            {
                selCameras[i] = false;
            }
            for(int i = 0; i < scene.selCams.Count; ++i)
            {
                selCameras[scene.selCams[i]] = true;
            }

            for(int i = 0; i < cameras.Count; ++i)
            {
                for(int j = 0; j < cameras[i].points.Length; ++j)
                {
                    camVertices[i * 8 + j].Position = cameras[i].points[j];
                    camVertices[i * 8 + j].Normal = new Vector3();
                    if(selCameras[i] == false)
                    {
                        if(scene.activeCamera == i)
                        {
                            camVertices[i * 8 + j].Color = Color.FromArgb(249, 203, 44).ToArgb();
                        }
                        else
                        {
                            camVertices[i * 8 + j].Color = Color.FromArgb(193, 227, 195).ToArgb();
                        }
                    }
                    else
                    {
                        if(scene.activeCamera == i)
                        {
                            camVertices[i * 8 + j].Color = Color.FromArgb(243, 106, 24).ToArgb();
                        }
                        else
                        {
                            camVertices[i * 8 + j].Color = Color.FromArgb(255, 255, 150).ToArgb();
                        }
                    }
                    camVertices[i * 8 + j].tex0 = 0;
                    camVertices[i * 8 + j].tex1 = 0;
                }
            }

            Mesh camMesh = cameras.Count > 0 ? new Mesh(device, (int)camIndices.Length / 3, camVertices.Length, MeshFlags.Managed | MeshFlags.Use32Bit, vertexElems) : null;
            VertexBuffer camVB = camMesh != null ? camMesh.VertexBuffer : null;
            IndexBuffer camIB = camMesh != null ? camMesh.IndexBuffer : null;

            if(camMesh != null)
            {
                camVB.Lock(0, 0, LockFlags.None).WriteRange(camVertices);
                camVB.Unlock();

                camIB.Lock(0, 0, LockFlags.None).WriteRange(camIndices);
                camIB.Unlock();
            }

            while(lights.Count < scene.lights.Count)
            {
                lights.Add(new RenderLight());
            }
            while(lights.Count > scene.lights.Count)
            {
                lights.RemoveAt(lights.Count - 1);
            }

            for(int i = 0; i < lights.Count; ++i)
            {
                if(ortoWidhtChange == true || lights[i].set == false || lights[i].position != scene.lights[i].position || lights[i].direction != scene.lights[i].direction ||
                    lights[i].type != scene.lights[i].type || lights[i].innerAngle != scene.lights[i].innerAngle || lights[i].outerAngle != scene.lights[i].outerAngle)
                {
                    if(lights[i].set == false)
                    {
                        lights[i].set = true;
                    }

                    lights[i].position = scene.lights[i].position;
                    lights[i].direction = scene.lights[i].direction;
                    lights[i].type = scene.lights[i].type;
                    lights[i].innerAngle = scene.lights[i].innerAngle;
                    lights[i].outerAngle = scene.lights[i].outerAngle;

                    for(int j = 0; j < RenderLight.pointsDef.Length; ++j)
                    {
                        lights[i].points[j] = RenderLight.pointsDef[j];
                    }
                    for(int j = RenderLight.pointsDef.Length; j < RenderLight.pointsSpotNum; ++j)
                    {
                        lights[i].points[j] = new Vector3();
                    }

                    if(lights[i].type == Light_Type.Spot || lights[i].type == Light_Type.Goniometric)
                    {
                        Vector3 dir = lights[i].direction;
                        dir.Normalize();

                        if(dir.Z == 0)
                        {
                            dir.Z = 0.0001f;
                        }
                        Vector3 Vs = new Vector3(1, 1, -(dir.X + dir.Y) / dir.Z);

                        Vector3 V1 = Vector3.Normalize(Vs);
                        Vector3 V2 = Vector3.Cross(dir, V1);

                        Vector2[,] circle = new Vector2[2, 20];

                        float r1 = spotLightDist * (float)Math.Tan(Utilities.DegToRad(lights[i].innerAngle / 2));
                        float r2 = spotLightDist * (float)Math.Tan(Utilities.DegToRad(lights[i].outerAngle / 2));

                        for(int j = 0; j < 2; ++j)
                        {
                            for(int k = 0; k < 20; ++k)
                            {
                                circle[j, k] = new Vector2((j == 0 ? r1 : r2) * (float)Math.Sin(Utilities.DegToRad(18 * k)),
                                                           (j == 0 ? r1 : r2) * (float)Math.Cos(Utilities.DegToRad(18 * k)));
                            }
                        }

                        Vector3[,] circle3D = new Vector3[2, 20];

                        for(int j = 0; j < 2; ++j)
                        {
                            for(int k = 0; k < 20; ++k)
                            {
                                float X = V1.X * circle[j, k].X + V2.X * circle[j, k].Y;
                                float Y = V1.Y * circle[j, k].X + V2.Y * circle[j, k].Y;
                                float Z = V1.Z * circle[j, k].X + V2.Z * circle[j, k].Y;

                                Vector3 radius = spotLightDist * dir;
                                circle3D[j, k] = new Vector3(X, Y, Z) + radius;
                            }
                        }

                        for(int j = 0; j < 20; ++j)
                        {
                            lights[i].points[RenderLight.pointsPointNum + 2 * j] = new Vector3(circle3D[0, j].X, circle3D[0, j].Y, circle3D[0, j].Z);
                            lights[i].points[RenderLight.pointsPointNum + 2 * j + 1] = new Vector3(circle3D[0, j].X + 0.000001f, circle3D[0, j].Y, circle3D[0, j].Z);

                            lights[i].points[RenderLight.pointsPointNum + 40 + 2 * j] = new Vector3(circle3D[1, j].X, circle3D[1, j].Y, circle3D[1, j].Z);
                            lights[i].points[RenderLight.pointsPointNum + 40 + 2 * j + 1] = new Vector3(circle3D[1, j].X + 0.000001f, circle3D[1, j].Y, circle3D[1, j].Z);
                        }

                        lights[i].points[120] = new Vector3(0, 0, 0);
                        lights[i].points[121] = new Vector3(0.000001f, 0, 0);
                    }

                    for(int j = 0; j < lights[i].points.Length; ++j)
                    {
                        lights[i].points[j] *= OrthoWidth[0] / 10;
                        lights[i].points[j] += lights[i].position;
                    }
                }
            }

            ortoWidhtChange = false;

            Vertex[] lightsVertices = new Vertex[lights.Count * RenderLight.pointsSpotNum];
            int[] lightsIndices = new int[3 * lights.Count * RenderLight.triangles.Length];

            int trIndex = 0;
            for(int i = 0; i < lights.Count; ++i)
            {
                int trNum = lights[i].type == Light_Type.Point ? RenderLight.trianglesPointNum : RenderLight.trianglesSpotNum;
                for(int j = 0; j < trNum; ++j)
                {
                    lightsIndices[trIndex++] = i * lights[i].points.Length + (int)RenderLight.triangles[j].p1;
                    lightsIndices[trIndex++] = i * lights[i].points.Length + (int)RenderLight.triangles[j].p2;
                    lightsIndices[trIndex++] = i * lights[i].points.Length + (int)RenderLight.triangles[j].p3;
                }
            }

            bool[] selLights = new bool[lights.Count];
            for(int i = 0; i < selLights.Length; ++i)
            {
                selLights[i] = false;
            }
            for(int i = 0; i < scene.selLights.Count; ++i)
            {
                selLights[scene.selLights[i]] = true;
            }

            for(int i = 0; i < lights.Count; ++i)
            {
                for(int j = 0; j < lights[i].points.Length; ++j)
                {
                    lightsVertices[i * RenderLight.pointsSpotNum + j].Position = lights[i].points[j];
                    lightsVertices[i * RenderLight.pointsSpotNum + j].Normal = new Vector3();
                    if(selLights[i] == false)
                    {
                        if(scene.lights[i].enabled == true)
                        {
                            if(scene.lights[i].type != Light_Type.Goniometric)
                            {
                                lightsVertices[i * RenderLight.pointsSpotNum + j].Color = Color.FromArgb(234, 203, 28).ToArgb();
                            }
                            else
                            {
                                lightsVertices[i * RenderLight.pointsSpotNum + j].Color = Color.FromArgb(123, 120, 46).ToArgb();
                            }
                        }
                        else
                        {
                            if(scene.lights[i].type != Light_Type.Goniometric)
                            {
                                lightsVertices[i * RenderLight.pointsSpotNum + j].Color = Color.FromArgb(48, 46, 54).ToArgb();
                            }
                            else
                            {
                                lightsVertices[i * RenderLight.pointsSpotNum + j].Color = Color.FromArgb(67, 78, 63).ToArgb();
                            }
                        }
                    }
                    else
                    {
                        if(scene.lights[i].enabled == true)
                        {
                            if(scene.lights[i].type != Light_Type.Goniometric)
                            {
                                lightsVertices[i * RenderLight.pointsSpotNum + j].Color = Color.FromArgb(243, 106, 24).ToArgb();
                            }
                            else
                            {
                                lightsVertices[i * RenderLight.pointsSpotNum + j].Color = Color.FromArgb(159, 210, 4).ToArgb();
                            }
                        }
                        else
                        {
                            if(scene.lights[i].type != Light_Type.Goniometric)
                            {
                                lightsVertices[i * RenderLight.pointsSpotNum + j].Color = Color.FromArgb(19, 24, 224).ToArgb();
                            }
                            else
                            {
                                lightsVertices[i * RenderLight.pointsSpotNum + j].Color = Color.FromArgb(19, 224, 96).ToArgb();
                            }
                        }
                    }
                    lightsVertices[i * RenderLight.pointsSpotNum + j].tex0 = 0;
                    lightsVertices[i * RenderLight.pointsSpotNum + j].tex1 = 0;
                }
            }

            Mesh lightsMesh = lights.Count > 0 ? new Mesh(device, trIndex / 3, lightsVertices.Length, MeshFlags.Managed | MeshFlags.Use32Bit, vertexElems) : null;
            VertexBuffer lightsVB = lightsMesh != null ? lightsMesh.VertexBuffer : null;
            IndexBuffer lightsIB = lightsMesh != null ? lightsMesh.IndexBuffer : null;

            if(lightsMesh != null)
            {
                lightsVB.Lock(0, 0, LockFlags.None).WriteRange(lightsVertices);
                lightsVB.Unlock();

                lightsIB.Lock(0, 0, LockFlags.None).WriteRange(lightsIndices, 0, trIndex);
                lightsIB.Unlock();
            }

            int coneLights = 0;
            foreach(Light_ light in scene.lights)
            {
                if(light.type == Light_Type.Spot || light.type == Light_Type.Goniometric)
                {
                    ++coneLights;
                }
            }
            Mesh pointsMesh = Mesh.CreateBox(device, pointSize, pointSize, pointSize);

            Mesh clipMeshX = null;
            Mesh clipMeshY = null;
            Mesh clipMeshZ = null;
            VertexBuffer clipVBX = null;
            IndexBuffer clipIBX = null;
            VertexBuffer clipVBY = null;
            IndexBuffer clipIBY = null;
            VertexBuffer clipVBZ = null;
            IndexBuffer clipIBZ = null;

            if(clipping == true)
            {
                clipMeshX = new Mesh(device, clipIndices.Length / 9, clipVertices.Length, MeshFlags.Managed | MeshFlags.Use32Bit, vertexElems);
                clipMeshY = new Mesh(device, clipIndices.Length / 9, clipVertices.Length, MeshFlags.Managed | MeshFlags.Use32Bit, vertexElems);
                clipMeshZ = new Mesh(device, clipIndices.Length / 9, clipVertices.Length, MeshFlags.Managed | MeshFlags.Use32Bit, vertexElems);

                clipVBX = clipMeshX.VertexBuffer;
                clipIBX = clipMeshX.IndexBuffer;

                clipVBX.Lock(0, 0, LockFlags.None).WriteRange(clipVertices);
                clipVBX.Unlock();

                clipIBX.Lock(0, 0, LockFlags.None).WriteRange(clipIndices, (clipIndices.Length / 6) * 2, (clipIndices.Length / 6) * 2);
                clipIBX.Unlock();

                clipVBY = clipMeshY.VertexBuffer;
                clipIBY = clipMeshY.IndexBuffer;

                clipVBY.Lock(0, 0, LockFlags.None).WriteRange(clipVertices);
                clipVBY.Unlock();

                clipIBY.Lock(0, 0, LockFlags.None).WriteRange(clipIndices, 0, (clipIndices.Length / 6) * 2);
                clipIBY.Unlock();

                clipVBZ = clipMeshZ.VertexBuffer;
                clipIBZ = clipMeshZ.IndexBuffer;

                clipVBZ.Lock(0, 0, LockFlags.None).WriteRange(clipVertices);
                clipVBZ.Unlock();

                clipIBZ.Lock(0, 0, LockFlags.None).WriteRange(clipIndices, (clipIndices.Length / 6) * 4, (clipIndices.Length / 6) * 2);
                clipIBZ.Unlock();
            }

            #if MEASURE_TIMES
            t1 = DateTime.Now;
            #endif
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);

            #if MEASURE_TIMES
            t2 = DateTime.Now;
            t = t2 - t1;
            w.WriteLine("Modyfikacja viewport'ów                     " + t.Milliseconds);

            t1 = DateTime.Now;
            #endif
            if (perspective.Width > 0 && perspective.Height > 0)
            {
                device.Viewport = perspective;

                float camRotAngle = scene.cams.ElementAt(scene.activeCamera).rotateAngle;
                float aspect = (float)perspective.Width / perspective.Height;
                float angle = 2.0f * (float)Math.Atan(Math.Tan(Utilities.DegToRad(scene.cams.ElementAt(scene.activeCamera).fovAngle) / 2.0f) / aspect);

                device.SetTransform(TransformState.View, Matrix.LookAtRH(
                    scene.cams[scene.activeCamera].position,
                    scene.cams[scene.activeCamera].lookAt,
                    Utilities.RotatePointAroundVector(new Vector3(0, 1, 0),
                    Vector3.Normalize(scene.cams[scene.activeCamera].lookAt - scene.cams[scene.activeCamera].position), camRotAngle)));

                device.SetTransform(TransformState.Projection, Matrix.PerspectiveFovRH(
                    angle,
                    aspect,
                    0.01f,
                    110000));

                device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.FromArgb(230, 230, 230), 1.0f, 0);
                device.BeginScene();

                if (mesh != null)
                {
                    mesh.DrawSubset(0);
                }

                //device.SetTexture(0, selectionTex);
                device.SetRenderState(RenderState.Lighting, false);
                if (selMesh != null)
                {
                    selMesh.DrawSubset(0);
                }
                device.SetRenderState(RenderState.Lighting, true);
                //device.SetTexture(0, null);

                device.EndScene();
            }

            SlimDX.Plane clipPlaneX = new SlimDX.Plane();
            SlimDX.Plane clipPlaneX2 = new SlimDX.Plane();
            SlimDX.Plane clipPlaneY = new SlimDX.Plane();
            SlimDX.Plane clipPlaneY2 = new SlimDX.Plane();
            SlimDX.Plane clipPlaneZ = new SlimDX.Plane();
            SlimDX.Plane clipPlaneZ2 = new SlimDX.Plane();

            SlimDX.Plane clipPlaneXPlus = new SlimDX.Plane();
            SlimDX.Plane clipPlaneX2Minus = new SlimDX.Plane();
            SlimDX.Plane clipPlaneYPlus = new SlimDX.Plane();
            SlimDX.Plane clipPlaneY2Minus = new SlimDX.Plane();
            SlimDX.Plane clipPlaneZPlus = new SlimDX.Plane();
            SlimDX.Plane clipPlaneZ2Minus = new SlimDX.Plane();

            clipPlaneYPlus = new SlimDX.Plane(new Vector3(0, 50000, 0), new Vector3(0, -1, 0));
            clipPlaneY2Minus = new SlimDX.Plane(new Vector3(0, -50000, 0), new Vector3(0, 1, 0));
            clipPlaneXPlus = new SlimDX.Plane(new Vector3(50000, 0, 0), new Vector3(-1, 0, 0));
            clipPlaneX2Minus = new SlimDX.Plane(new Vector3(-50000, 0, 0), new Vector3(1, 0, 0));
            clipPlaneZPlus = new SlimDX.Plane(new Vector3(0, 0, -50000), new Vector3(0, 0, 1));
            clipPlaneZ2Minus = new SlimDX.Plane(new Vector3(0, 0, 50000), new Vector3(0, 0, -1));

            if(clipping == true)
            {
                clipPlaneY =  new SlimDX.Plane(new Vector3(0, clipVertices[0].Position.Y, 0), new Vector3(0, -1, 0));
                clipPlaneY2 = new SlimDX.Plane(new Vector3(0, clipVertices[8].Position.Y, 0), new Vector3(0, 1, 0));
                clipPlaneX =  new SlimDX.Plane(new Vector3(clipVertices[16].Position.X, 0, 0), new Vector3(-1, 0, 0));
                clipPlaneX2 = new SlimDX.Plane(new Vector3(clipVertices[24].Position.X, 0, 0), new Vector3(1, 0, 0));
                clipPlaneZ =  new SlimDX.Plane(new Vector3(0, 0, clipVertices[32].Position.Z), new Vector3(0, 0, 1));
                clipPlaneZ2 = new SlimDX.Plane(new Vector3(0, 0, clipVertices[40].Position.Z), new Vector3(0, 0, -1));

                device.SetRenderState(RenderState.ClipPlaneEnable, ClipFlags.Bottom | ClipFlags.Front | ClipFlags.Left | ClipFlags.Right |
                    ClipFlags.Back | ClipFlags.Top);
            }

            if (top.Width > 0 && top.Height > 0)
            {
                device.Viewport = top;

                device.SetTransform(TransformState.View, Matrix.LookAtRH(
                   orthoPos[2],
                   orthoLookAt[2],
                   new Vector3(0, 1, 0)));

                device.SetTransform(TransformState.Projection, Matrix.OrthoRH(
                    orthoWidth[2],
                    (float)(top.Height) / top.Width * orthoWidth[2],
                    0.01f,
                    110000));

                device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.FromArgb(230, 230, 230), 1.0f, 0);
                device.BeginScene();

                string text1 = " -z\n/|\\\n |\n";
                font.DrawString(null, text1, viewportInfo.posX[2] + 15, viewportInfo.posY[2], Color.Blue);
                string text2 = "\n\n\n  -----> x";
                font.DrawString(null, text2, viewportInfo.posX[2] + 15, viewportInfo.posY[2], Color.Red);

                if(clipping == true)
                {
                    device.SetRenderState(RenderState.Lighting, false);
                    device.SetRenderState(RenderState.FillMode, FillMode.Solid);
                    clipMeshX.DrawSubset(0);
                    clipMeshZ.DrawSubset(0);
                    device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);
                    device.SetRenderState(RenderState.Lighting, true);

                    device.SetClipPlane(0, clipPlaneX);
                    device.SetClipPlane(1, clipPlaneX2);
                    device.SetClipPlane(2, clipPlaneY);
                    device.SetClipPlane(3, clipPlaneY2);
                    device.SetClipPlane(4, clipPlaneZ);
                    device.SetClipPlane(5, clipPlaneZ2);
                }

                if (mesh != null)
                {
                    mesh.DrawSubset(0);
                }

                //device.SetTexture(0, selectionTex);
                device.SetRenderState(RenderState.Lighting, false);
                if (selMesh != null)
                {
                    selMesh.DrawSubset(0);
                }
                device.SetRenderState(RenderState.Lighting, true);
                //device.SetTexture(0, null);

                device.SetClipPlane(0, clipPlaneXPlus);
                device.SetClipPlane(1, clipPlaneX2Minus);
                device.SetClipPlane(2, clipPlaneYPlus);
                device.SetClipPlane(3, clipPlaneY2Minus);
                device.SetClipPlane(4, clipPlaneZPlus);
                device.SetClipPlane(5, clipPlaneZ2Minus);

                device.SetRenderState(RenderState.FillMode, FillMode.Solid);
                for(int i = 0; i < scene.lights.Count; ++i)
                {
                    if(scene.lights[i].type == Light_Type.Spot || scene.lights[i].type == Light_Type.Goniometric)
                    {
                        device.SetTransform(TransformState.World, Matrix.Scaling(orthoWidth[2] / 10, orthoWidth[0] / 10, orthoWidth[2] / 10) *
                                            Matrix.Translation(scene.lights[i].position + scene.lights[i].direction * spotLightDist * orthoWidth[1] / 10));
                        pointsMesh.DrawSubset(0);
                    }
                }
                for(int i = 0; i < scene.cams.Count; ++i)
                {
                    device.SetTransform(TransformState.World, Matrix.Scaling(orthoWidth[2] / 10, orthoWidth[2] / 10, orthoWidth[2] / 10) *
                        Matrix.Translation(scene.cams[i].position));
                    pointsMesh.DrawSubset(0);

                    device.SetTransform(TransformState.World, Matrix.Scaling(orthoWidth[2] / 10, orthoWidth[2] / 10, orthoWidth[2] / 10) *
                        Matrix.Translation(camsLookAtPoints[i]));
                    pointsMesh.DrawSubset(0);
                }
                device.SetTransform(TransformState.World, Matrix.Identity);
                device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);

                if(camMesh != null)
                {
                    device.SetRenderState(RenderState.FillMode, FillMode.Wireframe);
                    device.SetRenderState(RenderState.Lighting, false);
                    camMesh.DrawSubset(0);
                    device.SetRenderState(RenderState.Lighting, true);
                    device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);
                }
                if(lightsMesh != null)
                {
                    device.SetRenderState(RenderState.FillMode, FillMode.Wireframe);
                    device.SetRenderState(RenderState.Lighting, false);
                    lightsMesh.DrawSubset(0);
                    device.SetRenderState(RenderState.Lighting, true);
                    device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);
                }

                device.EndScene();
            }

            if (front.Width > 0 && front.Height > 0)
            {
                device.Viewport = front;

                device.SetTransform(TransformState.View, Matrix.LookAtRH(
                   orthoPos[0],
                   orthoLookAt[0],
                   new Vector3(0, 1, 0)));

                device.SetTransform(TransformState.Projection, Matrix.OrthoRH(
                    orthoWidth[0],
                    (float)(front.Height) / front.Width * orthoWidth[0],
                    0.01f,
                    110000));

                device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.FromArgb(230, 230, 230), 1.0f, 0);
                device.BeginScene();

                string text1 = " y\n/|\\\n |\n";
                font.DrawString(null, text1, viewportInfo.posX[0] + 15, viewportInfo.posY[0], Color.Green);
                string text2 = "\n\n\n  -----> x";
                font.DrawString(null, text2, viewportInfo.posX[0] + 15, viewportInfo.posY[0], Color.Red);

                if(clipping == true)
                {
                    device.SetRenderState(RenderState.Lighting, false);
                    device.SetRenderState(RenderState.FillMode, FillMode.Solid);
                    clipMeshX.DrawSubset(0);
                    clipMeshY.DrawSubset(0);
                    device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);
                    device.SetRenderState(RenderState.Lighting, true);

                    device.SetClipPlane(0, clipPlaneX);
                    device.SetClipPlane(1, clipPlaneX2);
                    device.SetClipPlane(2, clipPlaneY);
                    device.SetClipPlane(3, clipPlaneY2);
                    device.SetClipPlane(4, clipPlaneZ);
                    device.SetClipPlane(5, clipPlaneZ2);
                }

                if (mesh != null)
                {
                    mesh.DrawSubset(0);
                }

                //device.SetTexture(0, selectionTex);
                device.SetRenderState(RenderState.Lighting, false);
                if (selMesh != null)
                {
                    selMesh.DrawSubset(0);
                }
                device.SetRenderState(RenderState.Lighting, true);
                //device.SetTexture(0, null);

                device.SetClipPlane(0, clipPlaneXPlus);
                device.SetClipPlane(1, clipPlaneX2Minus);
                device.SetClipPlane(2, clipPlaneYPlus);
                device.SetClipPlane(3, clipPlaneY2Minus);
                device.SetClipPlane(4, clipPlaneZPlus);
                device.SetClipPlane(5, clipPlaneZ2Minus);

                device.SetRenderState(RenderState.FillMode, FillMode.Solid);
                for(int i = 0; i < scene.lights.Count; ++i)
                {
                    if(scene.lights[i].type == Light_Type.Spot || scene.lights[i].type == Light_Type.Goniometric)
                    {
                        device.SetTransform(TransformState.World, Matrix.Scaling(orthoWidth[0] / 10, orthoWidth[0] / 10, orthoWidth[0] / 10) *
                                            Matrix.Translation(scene.lights[i].position + scene.lights[i].direction * spotLightDist * orthoWidth[0] / 10));
                        pointsMesh.DrawSubset(0);
                    }
                }
                for(int i = 0; i < scene.cams.Count; ++i)
                {
                    device.SetTransform(TransformState.World, Matrix.Scaling(orthoWidth[0] / 10, orthoWidth[0] / 10, orthoWidth[0] / 10) *
                        Matrix.Translation(scene.cams[i].position));
                    pointsMesh.DrawSubset(0);

                    device.SetTransform(TransformState.World, Matrix.Scaling(orthoWidth[0] / 10, orthoWidth[0] / 10, orthoWidth[0] / 10) *
                        Matrix.Translation(camsLookAtPoints[i]));
                    pointsMesh.DrawSubset(0);
                }
                device.SetTransform(TransformState.World, Matrix.Identity);
                device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);

                if(camMesh != null)
                {
                    device.SetRenderState(RenderState.FillMode, FillMode.Wireframe);
                    device.SetRenderState(RenderState.Lighting, false);
                    camMesh.DrawSubset(0);
                    device.SetRenderState(RenderState.Lighting, true);
                    device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);
                }
                if(lightsMesh != null)
                {
                    device.SetRenderState(RenderState.FillMode, FillMode.Wireframe);
                    device.SetRenderState(RenderState.Lighting, false);
                    lightsMesh.DrawSubset(0);
                    device.SetRenderState(RenderState.Lighting, true);
                    device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);
                }

                device.EndScene();
            }

            if (side.Width > 0 && side.Height > 0)
            {
                device.Viewport = side;

                device.SetTransform(TransformState.View, Matrix.LookAtRH(
                   orthoPos[1],
                   orthoLookAt[1],
                   new Vector3(0, 1, 0)));

                device.SetTransform(TransformState.Projection, Matrix.OrthoRH(
                    orthoWidth[1],
                    (float)(side.Height) / side.Width * orthoWidth[1],
                    0.01f,
                    110000));

                device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.FromArgb(230, 230, 230), 1.0f, 0);
                device.BeginScene();

                string text1 = " y\n/|\\\n |\n";
                font.DrawString(null, text1, viewportInfo.posX[1] + 15, viewportInfo.posY[1], Color.Green);
                string text2 = "\n\n\n  -----> -z";
                font.DrawString(null, text2, viewportInfo.posX[1] + 15, viewportInfo.posY[1], Color.Blue);

                if(clipping == true)
                {
                    device.SetRenderState(RenderState.Lighting, false);
                    device.SetRenderState(RenderState.FillMode, FillMode.Solid);
                    clipMeshY.DrawSubset(0);
                    clipMeshZ.DrawSubset(0);
                    device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);
                    device.SetRenderState(RenderState.Lighting, true);

                    device.SetClipPlane(0, clipPlaneX);
                    device.SetClipPlane(1, clipPlaneX2);
                    device.SetClipPlane(2, clipPlaneY);
                    device.SetClipPlane(3, clipPlaneY2);
                    device.SetClipPlane(4, clipPlaneZ);
                    device.SetClipPlane(5, clipPlaneZ2);
                }

                if (mesh != null)
                {
                    mesh.DrawSubset(0);
                }

                //device.SetTexture(0, selectionTex);
                device.SetRenderState(RenderState.Lighting, false);
                if (selMesh != null)
                {
                    selMesh.DrawSubset(0);
                }
                device.SetRenderState(RenderState.Lighting, true);
                //device.SetTexture(0, null);

                device.SetClipPlane(0, clipPlaneXPlus);
                device.SetClipPlane(1, clipPlaneX2Minus);
                device.SetClipPlane(2, clipPlaneYPlus);
                device.SetClipPlane(3, clipPlaneY2Minus);
                device.SetClipPlane(4, clipPlaneZPlus);
                device.SetClipPlane(5, clipPlaneZ2Minus);

                device.SetRenderState(RenderState.FillMode, FillMode.Solid);
                for(int i = 0; i < scene.lights.Count; ++i)
                {
                    if(scene.lights[i].type == Light_Type.Spot || scene.lights[i].type == Light_Type.Goniometric)
                    {
                        device.SetTransform(TransformState.World, Matrix.Scaling(orthoWidth[1] / 10, orthoWidth[0] / 10, orthoWidth[1] / 10) *
                                            Matrix.Translation(scene.lights[i].position + scene.lights[i].direction * spotLightDist * orthoWidth[1] / 10));
                        pointsMesh.DrawSubset(0);
                    }
                }
                for(int i = 0; i < scene.cams.Count; ++i)
                {
                    device.SetTransform(TransformState.World, Matrix.Scaling(orthoWidth[1] / 10, orthoWidth[1] / 10, orthoWidth[1] / 10) *
                        Matrix.Translation(scene.cams[i].position));
                    pointsMesh.DrawSubset(0);

                    device.SetTransform(TransformState.World, Matrix.Scaling(orthoWidth[1] / 10, orthoWidth[1] / 10, orthoWidth[1] / 10) *
                        Matrix.Translation(camsLookAtPoints[i]));
                    pointsMesh.DrawSubset(0);
                }
                device.SetTransform(TransformState.World, Matrix.Identity);
                device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);

                if(camMesh != null)
                {
                    device.SetRenderState(RenderState.FillMode, FillMode.Wireframe);
                    device.SetRenderState(RenderState.Lighting, false);
                    camMesh.DrawSubset(0);
                    device.SetRenderState(RenderState.Lighting, true);
                    device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);
                }
                if(lightsMesh != null)
                {
                    device.SetRenderState(RenderState.FillMode, FillMode.Wireframe);
                    device.SetRenderState(RenderState.Lighting, false);
                    lightsMesh.DrawSubset(0);
                    device.SetRenderState(RenderState.Lighting, true);
                    device.SetRenderState(RenderState.FillMode, wireframe ? FillMode.Wireframe : FillMode.Solid);
                }

                device.EndScene();
            }
            #if MEASURE_TIMES
            t2 = DateTime.Now;
            t = t2 - t1;
            w.WriteLine("Renderowanie                               " + t.Milliseconds);

            t1 = DateTime.Now;
            #endif
            device.Present();

            #if MEASURE_TIMES
            t2 = DateTime.Now;
            t = t2 - t1;
            w.WriteLine("Present                                    " + t.Milliseconds);

            t1 = DateTime.Now;
            #endif
            //selectionTex.Dispose();
            if (selMesh != null)
            {
                selvb.Dispose();
                selib.Dispose();
                selMesh.Dispose();
            }
            if (mesh != null)
            {
                vb.Dispose();
                ib.Dispose();
                mesh.Dispose();
            }
            if(camMesh != null)
            {
                camVB.Dispose();
                camIB.Dispose();
                camMesh.Dispose();
            }
            if(lightsMesh != null)
            {
                lightsVB.Dispose();
                lightsIB.Dispose();
                lightsMesh.Dispose();
            }
            if(clipping == true)
            {
                clipVBX.Dispose();
                clipIBX.Dispose();
                clipVBY.Dispose();
                clipIBY.Dispose();
                clipVBZ.Dispose();
                clipIBZ.Dispose();
                clipMeshX.Dispose();
                clipMeshY.Dispose();
                clipMeshZ.Dispose();
            }
            pointsMesh.Dispose();

            #if MEASURE_TIMES
            t2 = DateTime.Now;
            t = t2 - t1;
            w.WriteLine("Czyszczenie                              " + t.Milliseconds);

            DateTime te = DateTime.Now;
            t = te - ts;
            w.WriteLine("Całość                             " + t.Milliseconds);
            w.WriteLine("-----------------------------------------------------------------");
            w.WriteLine();
            w.WriteLine();
            w.WriteLine();
            #endif
        }