Click here to Skip to main content
15,888,286 members
Articles / Programming Languages / C#

Implementing a Basic Camera Model (Pinhole) II

Rate me:
Please Sign up or sign in to vote.
4.90/5 (16 votes)
15 Jul 2016GPL33 min read 39.6K   624   46  
Extending the camera class and creating basic animations.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using Geometry;
using System.Threading;

namespace CameraTest
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        public bool TestA(Geometry.Point point)
        {
            Geometry.Point oCameraPos = new Geometry.Point(point);
            Geometry.Point oTarget = new Geometry.Point(0, 0, 0);
            Camera oCamera1 = new Camera();
            bool bSetup = oCamera1.Setup(1.0, oCameraPos, new Vector(oCameraPos, oTarget));
            if (bSetup)
            {
                Geometry.Point p = oCamera1.LocalToCartesian(oCameraPos);
                if (rtPoint.Module(new Vector(p.x, p.y, p.z)) > 0)
                {
                    return false;
                }
                return true;
            }
            else
            {
                return true;
            }
        }

        public bool TestB(Geometry.Point point)
        {
            Geometry.Point oCameraPos = new Geometry.Point(point);
            Geometry.Point oTarget = new Geometry.Point(0, 0, 0);
            Camera oCamera1 = new Camera();
            bool bSetup = oCamera1.Setup(1.0, oCameraPos, new Vector(oCameraPos, oTarget));
            if (bSetup)
            {
                Geometry.Point p2 = oCamera1.LocalToCartesian(new Geometry.Point(
                    oCameraPos.x + oCamera1.Direction.x,
                    oCameraPos.y + oCamera1.Direction.y,
                    oCameraPos.z + oCamera1.Direction.z));
                if ((Math.Abs(p2.x) > 1.0E-5) || (Math.Abs(p2.y) > 1.0E-5) || (Math.Abs(p2.z) < 1.0E-5))
                {
                    return false;
                }
            }
            return true;
        }

        public bool TestC(Geometry.Point point)
        {
            Geometry.Point oCameraPos = new Geometry.Point(point);
            Geometry.Point oTarget = new Geometry.Point(0, 0, 0);
            Camera oCamera1 = new Camera();
            bool bSetup = oCamera1.Setup(1.0, oCameraPos, new Vector(oCameraPos, oTarget));
            if (bSetup)
            {
                Geometry.Point p2 = oCamera1.LocalToCartesian(new Geometry.Point(
                    oCameraPos.x - oCamera1.Direction.x,
                    oCameraPos.y - oCamera1.Direction.y,
                    oCameraPos.z - oCamera1.Direction.z));
                if ((Math.Abs(p2.x) > 1.0E-5) || (Math.Abs(p2.y) > 1.0E-5) || (Math.Abs(p2.z) < 1.0E-5))
                {
                    return false;
                }
            }
            return true;
        }

        public void TestPoint(Geometry.Point oPoint)
        {
            double t = 0, i = 0, r = 1, x, y, z;
            Camera oCamera = new Camera();

            r = oCamera.GetSpherical(new Geometry.Point(oPoint.x, oPoint.y, oPoint.z), ref t, ref i);
            x = r * Math.Sin(i) * Math.Cos(t);
            y = r * Math.Sin(i) * Math.Sin(t);
            z = r * Math.Cos(i);
            bool ok = Check(oPoint, x, y, z);
            if (!ok) MessageBox.Show(string.Format("Error x={0:0.00} y={1:0.00} z={2:0.00}", oPoint.x, oPoint.y, oPoint.z));
        }

        /// <summary>
        /// testing axis and octants... todo test the inverse function in relatin to positive/negative octants
        /// </summary>
        /// <returns></returns>
        public bool TestSph()
        {

            TestPoint(new Geometry.Point(1, 0, 0));
            TestPoint(new Geometry.Point(1, 1, 0));
            TestPoint(new Geometry.Point(0, 1, 0));
            TestPoint(new Geometry.Point(-1, 1, 0));
            TestPoint(new Geometry.Point(-1, 0, 0));
            TestPoint(new Geometry.Point(-1, -1, 0));
            TestPoint(new Geometry.Point(0, -1, 0));
            TestPoint(new Geometry.Point(1, -1, 0));

            TestPoint(new Geometry.Point(1, 0, 1));
            TestPoint(new Geometry.Point(1, 1, 1));
            TestPoint(new Geometry.Point(0, 1, 1));
            TestPoint(new Geometry.Point(-1, 1, 1));
            TestPoint(new Geometry.Point(-1, 0, 1));
            TestPoint(new Geometry.Point(-1, -1, 1));
            TestPoint(new Geometry.Point(0, -1, 1));
            TestPoint(new Geometry.Point(1, -1, 1));

            TestPoint(new Geometry.Point(1, 0, -1));
            TestPoint(new Geometry.Point(1, 1, -1));
            TestPoint(new Geometry.Point(0, 1, -1));
            TestPoint(new Geometry.Point(-1, 1, -1));
            TestPoint(new Geometry.Point(-1, 0, -1));
            TestPoint(new Geometry.Point(-1, -1, -1));
            TestPoint(new Geometry.Point(0, -1, -1));
            TestPoint(new Geometry.Point(1, -1, -1));

            TestPoint(new Geometry.Point(1.5, 1, 1));
            TestPoint(new Geometry.Point(1, -1.5, 1));
            TestPoint(new Geometry.Point(0.5, 1, 1));
            TestPoint(new Geometry.Point(-1.5, -1, 1));
            TestPoint(new Geometry.Point(0.5, -1, 1));

            TestPoint(new Geometry.Point(-1.5, 1, 0));

            TestPoint(new Geometry.Point(1.000, 0.500, 0.000));
            TestPoint(new Geometry.Point(-1.0, 0.5, 0));
            TestPoint(new Geometry.Point(1.000, 0.500, 1.000));
            TestPoint(new Geometry.Point(-1.0, 0.5, 1));

            TestPoint(new Geometry.Point(-1.5, 2.5, 1.6));
            TestPoint(new Geometry.Point(4.0, 30.5, 10));
            TestPoint(new Geometry.Point(-100.0, 0.05, 1.9));
            TestPoint(new Geometry.Point(-10.0, 60.5, 100));
            TestPoint(new Geometry.Point(-551.0, 0, 1));
            return true;
        }

        private bool Check(Geometry.Point oPoint, double x, double y, double z)
        {
            if (rtPoint.Module(new Vector(oPoint, new Geometry.Point(x, y, z))) > 1.0E-6)
                return false;
            else
                return true;
        }

        public void TestCases()
        {
            Camera oCamera1 = new Camera();

            // test A at camerapos 
            bool t1 = TestA(new Geometry.Point(0, 0, 0));
            bool t2 = TestA(new Geometry.Point(100, 0, 0));
            bool t3 = TestA(new Geometry.Point(0, 100, 0));
            bool t4 = TestA(new Geometry.Point(0, 0, 100));
            bool t5 = TestA(new Geometry.Point(-100, 0, 0));
            bool t6 = TestA(new Geometry.Point(0, -100, 0));
            bool t7 = TestA(new Geometry.Point(0, 0, -100));
            bool t8 = TestA(new Geometry.Point(100, 100, 100));

            // test B in front of camera at direction line
            bool tb1 = TestB(new Geometry.Point(0, 0, 0));
            bool tb2 = TestB(new Geometry.Point(100, 0, 0));
            bool tb3 = TestB(new Geometry.Point(0, 100, 0));
            bool tb4 = TestB(new Geometry.Point(0, 0, 100));
            bool tb5 = TestB(new Geometry.Point(-100, 0, 0));
            bool tb6 = TestB(new Geometry.Point(0, -100, 0));
            bool tb7 = TestB(new Geometry.Point(0, 0, -100));
            bool tb8 = TestB(new Geometry.Point(100, 100, 100));

            // test C in back of camera at direction line
            bool tc1 = TestB(new Geometry.Point(0, 0, 0));
            bool tc2 = TestB(new Geometry.Point(100, 0, 0));
            bool tc3 = TestB(new Geometry.Point(0, 100, 0));
            bool tc4 = TestB(new Geometry.Point(0, 0, 100));
            bool tc5 = TestB(new Geometry.Point(-100, 0, 0));
            bool tc6 = TestB(new Geometry.Point(0, -100, 0));
            bool tc7 = TestB(new Geometry.Point(0, 0, -100));
            bool tc8 = TestB(new Geometry.Point(100, 100, 100));

            // test 3
            bool tc9 = true;
            Plane oPlane = new Plane(new Geometry.Point(0, 0, 0), new Vector(0, 0, 1));
            Geometry.Point p1 = oPlane.GetLineIntersection(new Geometry.Point(0, 0, 100), new Geometry.Point(0, 0, 0));
            if (Math.Abs(rtPoint.Module(new Vector(p1.x, p1.y, p1.z))) > 1.0E-5)
            {
                tc9 = false;
            }

            bool tc10 = true;
            Geometry.Point p2 = oPlane.GetLineIntersection(new Geometry.Point(10, 10, 100), new Geometry.Point(10, 10, 90));
            if (Math.Abs(p2.x - 10) > 1.0E-5)
            {
                tc10 = false;
            }
            if (Math.Abs(p2.y - 10) > 1.0E-5)
            {
                tc10 = false;
            }
            if (Math.Abs(p2.z) > 1.0E-5)
            {
                tc10 = false;
            }

        }

        double angle = 0;
        double angle2 = 0;
        Geometry.Point m_oCameraPos = new Geometry.Point(10, 10, 100);

        private void Form1_Load(object sender, EventArgs e)
        {
            //TestCases();
            //TestSph();
        }


        private void pictureBox1_Click(object sender, EventArgs e)
        {

        }

        private void timer1_Tick(object sender, EventArgs e)
        {

            //////////////////////////////////////////////////
            int m_iScreenPixels = 400;
            double m_fFocalLenght = 1.0;
            Geometry.Point m_oTarget = new Geometry.Point(5, 5, 5);
            double m_fVirtualSize = 1;

            Bitmap newBitmap = new Bitmap(m_iScreenPixels, m_iScreenPixels,
                               PixelFormat.Format32bppArgb);
            Graphics g = Graphics.FromImage(newBitmap);

            Camera oCamera1 = new Camera();
            Color color = Color.FromArgb(255, 0, 0);
            Rectangle rect = new Rectangle(0, 0, m_iScreenPixels, m_iScreenPixels);
            double fMax = m_fVirtualSize;
            Pen pen = new Pen(color);


            Geometry.Point p1 = new Geometry.Point(0.000000, 0.000000, 0.000000);
            Geometry.Point p2 = new Geometry.Point(10.000000, 0.000000, 0.000000);
            Geometry.Point p3 = new Geometry.Point(0.000000, 10.000000, 0.000000);
            Geometry.Point p4 = new Geometry.Point(0.000000, 0.000000, 10.000000);

            g.Clear(Color.Black);

            Geometry.Point eye = new Geometry.Point(m_oCameraPos);
            //eye = rtPoint.RotZ(angle2, eye);
            m_oCameraPos = rtPoint.Translate(eye, new Vector(0.001, 0, -0.35));
            //eye = rtPoint.RotY(angle2, eye);

            oCamera1.Setup(m_fFocalLenght, new Geometry.Point(eye.x, eye.y, eye.z), new Vector(eye, m_oTarget));

            Geometry.Point pointAux1 = oCamera1.GetProjectedMappedPoint(p1);
            Geometry.Point pointAux2 = oCamera1.GetProjectedMappedPoint(p2);
            Geometry.Point pointAux3 = oCamera1.GetProjectedMappedPoint(p3);
            Geometry.Point pointAux4 = oCamera1.GetProjectedMappedPoint(p4);

            if (pointAux1 != null && pointAux2 != null && pointAux3 != null && pointAux4 != null)
            {
                double x1 = rtPoint.GetCoord(-fMax, fMax, rect.Left, rect.Right, pointAux1.x);
                double y1 = rtPoint.GetCoord(-fMax, fMax, rect.Top, rect.Bottom, pointAux1.y);
                double x2 = rtPoint.GetCoord(-fMax, fMax, rect.Left, rect.Right, pointAux2.x);
                double y2 = rtPoint.GetCoord(-fMax, fMax, rect.Top, rect.Bottom, pointAux2.y);
                double x3 = rtPoint.GetCoord(-fMax, fMax, rect.Left, rect.Right, pointAux3.x);
                double y3 = rtPoint.GetCoord(-fMax, fMax, rect.Top, rect.Bottom, pointAux3.y);
                double x4 = rtPoint.GetCoord(-fMax, fMax, rect.Left, rect.Right, pointAux4.x);
                double y4 = rtPoint.GetCoord(-fMax, fMax, rect.Top, rect.Bottom, pointAux4.y);


                g.DrawLine(pen, (int)x1, (int)y1, (int)x2, (int)y2);
                g.DrawLine(pen, (int)x1, (int)y1, (int)x3, (int)y3);
                g.DrawLine(pen, (int)x1, (int)y1, (int)x4, (int)y4);
                g.DrawLine(pen, (int)x4, (int)y4, (int)x1, (int)y1);
            }

            Sphere s1 = new Sphere(10, 10);
            s1.Scale(2);
            s1.Translate(new Vector(5, 5, 5));
            s1.Draw(oCamera1, g, rect, fMax, Color.Yellow);

            Grid g1 = new Grid(50, 50);
            g1.Scale(50);
            g1.Rotate(3.14, 0, 0);
            g1.Draw(oCamera1, g, rect, fMax, Color.White);
            g1.Translate(new Vector(0, 0, 10));
            
            Cube c1 = new Cube();
            c1.Translate(new Vector(10, 3, 0));
            c1.Rotate(angle, 0, 0);
            c1.Draw(oCamera1, g, rect, fMax, Color.Red);

            Cube c2 = new Cube();
            c2.Translate(new Vector(-3, 10, 0));
            c2.Rotate(0, angle, 0);
            c2.Draw(oCamera1, g, rect, fMax, Color.Green);

            Cube c3 = new Cube();
            c3.Translate(new Vector(0, -3, 10));
            c3.Rotate(0, 0, angle);
            c3.Draw(oCamera1, g, rect, fMax, Color.Blue);

            Brush o = new SolidBrush(color);
            //g.DrawString(angle2.ToString(), new Font("Courier", 12), o, 5, 360);
            //g.DrawString(string.Format("Angle {0:0.00} Up ({1},{2},{3})", angle2, oCamera1.oUpPoint.x.ToString(), oCamera1.oUpPoint.y.ToString(), oCamera1.oUpPoint.z.ToString()), new Font("Courier", 12), o, 5, 360);

            newBitmap.Save("c:\\temp\\bitmap1.png");
            pictureBox1.Load("c:\\temp\\bitmap1.png");

            angle += 0.2;
            angle2 += 0.1;

            pen.Dispose();
        }

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
CEO
Brazil Brazil
"A well written code is self explanatory" - Anonymous Programmer
"The number of meetings is directly proportional to the bad management" - Another Anonymous Programmer
Founder @TIHUNTER.COM.BR
Linkedin Profile

Comments and Discussions