void OnRenderObject()
    {
        if (topCircle != null)
        {
            m_renderEngine.DrawCircle(ref topCircle, Color.red);
        }
        if (topRect != null)
        {
            m_renderEngine.DrawRect3(ref topRect, Color.red);
        }

        //m_renderEngine.DrawCircle(ref c1, Color.red);
        //m_renderEngine.DrawCircle(ref topCircle, Color.red);
    }
    public void Optimize_allRects()
    {
        // Init FOV
        float fov_aver = 0;

        foreach (var fe in m_FEs)
        {
            fov_aver = fe.fov_face;
        }
        fov_aver /= m_FEs.Count;
        m_engine.m_fovOptimizer.SetFOV(fov_aver);
        float fov_init = m_projector.m_mainCamera.fieldOfView;

        // Count rect engines
        foreach (var fe in m_FEs)
        {
            if (!fe.isTopCircle_Current)
            {
                REs.Add(fe);
            }
        }

        // Params Prepare
        //foreach (var re in rectEngines) corners_list.Add(re.corner_points);
        int params_num = 4 * REs.Count + 1;

        double[] bndl = new double[params_num];
        double[] x    = new double[params_num];
        double[] bndu = new double[params_num];
        for (int i = 0; i < REs.Count; i++)
        {
            bndl[4 * i]     = 0;
            bndl[4 * i + 1] = 0;
            bndl[4 * i + 2] = 0;
            bndl[4 * i + 3] = 0;
            x[4 * i]        = REs[i].x0;
            x[4 * i + 1]    = REs[i].x1;
            x[4 * i + 2]    = REs[i].x2;
            x[4 * i + 3]    = REs[i].x3;
            bndu[4 * i]     = 20;
            bndu[4 * i + 1] = 20;
            bndu[4 * i + 2] = 20;
            bndu[4 * i + 3] = 20;
        }
        bndl[params_num - 1] = 1 / fov_optimal_scale;
        x[params_num - 1]    = fov_aver / fov_optimal_scale;
        bndu[params_num - 1] = 179 / fov_optimal_scale;

        int funNum = 11;

        double diffstep = 0.0001;
        double epsg     = 0.000000000001;
        double epsf     = 0;
        double epsx     = 0;
        int    maxits   = 0;

        alglib.minlmstate  state;
        alglib.minlmreport rep;

        //set timer
        System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
        stopwatch.Start();
        Inter_Num = 0;
        alglib.minlmcreatev(funNum, x, diffstep, out state);
        alglib.minlmsetbc(state, bndl, bndu);
        alglib.minlmsetcond(state, epsg, epsf, epsx, maxits);
        alglib.minlmoptimize(state, function_multi, null, null);
        alglib.minlmresults(state, out x, out rep);


        stopwatch.Stop();
        if (!m_engine.m_is_quiet)
        {
            Debug.Log("End fitting , Total time:" + stopwatch.ElapsedMilliseconds / 1000.0 + "s");
        }

        m_engine.m_fovOptimizer.SetFOV((float)x[x.Length - 1] * fov_optimal_scale);
        for (int i = 0; i < REs.Count; i++)
        {
            Ray ray1 = m_projector.GenerateRay(REs[i].corner_points[0]);
            Ray ray2 = m_projector.GenerateRay(REs[i].corner_points[1]);
            Ray ray3 = m_projector.GenerateRay(REs[i].corner_points[2]);
            Ray ray4 = m_projector.GenerateRay(REs[i].corner_points[3]);

            Vector3 v1_3 = ray1.GetPoint((float)x[4 * i]);
            Vector3 v2_3 = ray2.GetPoint((float)x[4 * i + 1]);
            Vector3 v3_3 = ray3.GetPoint((float)x[4 * i + 2]);
            Vector3 v4_3 = ray4.GetPoint((float)x[4 * i + 3]);
            // project to a new plane
            List <Vector3> points = new List <Vector3>();
            points.Add(v1_3);
            points.Add(v2_3);
            points.Add(v3_3);
            points.Add(v4_3);
            Vector3 mean = v1_3 + v2_3 + v3_3 + v4_3;
            mean /= 4;
            Vector3 normal   = Utility.GetNormal(points);
            Plane   newplane = new Plane(normal, mean);
            v1_3           = Utility.PlaneProjectPoint(newplane, v1_3);
            v2_3           = Utility.PlaneProjectPoint(newplane, v2_3);
            v3_3           = Utility.PlaneProjectPoint(newplane, v3_3);
            v4_3           = Utility.PlaneProjectPoint(newplane, v4_3);
            REs[i].topRect = new Quad(v1_3, v2_3, v3_3);
            REs[i].topRect.FitRect();
            m_renderEngine.DrawRect3(REs[i].topRect, Color.green);
            m_renderEngine.DrawLine(REs[i].topRect.Center, REs[i].topRect.Center + 2 * REs[i].topRect.Normal, Color.blue);
            if (!m_engine.m_is_quiet)
            {
                Debug.Log("angle: " + Vector3.Angle(REs[i].topRect.CornerPoints3d[0] - REs[i].topRect.CornerPoints3d[1], REs[i].topRect.CornerPoints3d[2] - REs[i].topRect.CornerPoints3d[1]));
            }
        }
    }