Click here to Skip to main content
Click here to Skip to main content

Implementing a Basic Camera Model (Pinhole)

, 9 Apr 2013
Rate this:
Please Sign up or sign in to vote.
Implementing a basic camera model to extend the raytracing algorithms

Introduction

Extending our ray tracing algorithms now we will implement a camera class.

The objective is to render the images setting the viewer at any position without restrictions since in our previous models, the viewer must be located at positive z axis, (0,0,z) z>0.

Background

Although not implementing raytracing in this article, it is required to have an advanced level in mathematics and also read the previous articles on Raytracing on CodeProject.

Link to previous articles

The objective is to render the images setting the viewer at any position without restrictions as our previous model where the viewer must be located at positive z axis, (0,0,z) z > 0.

What is a pinhole camera?

"...A pinhole camera is a very simple camera with no lens and a single very small aperture. Simply explained, it is a light-proof box with a small hole on one side. Light from a scene passes through this single point and projects an inverted image on the opposite side of the box. Cameras using small apertures and the human eye in bright light both act like a pinhole camera.

The smaller the hole, the sharper the image, but the dimmer the projected image. Optimally, the size of the aperture should be 1/100 or less of the distance between it and the screen..."

See http://en.wikipedia.org/wiki/Pinhole_camera

Pinhole camera
A pinhole camera

Step 1 - Defining Parameters

In order to perform all calculations, we do need some predefined parameters:

  • Camera position Cp(x,y,z)
  • Viewing direction vector V (x,y,z) normalized... means its module = 1 |V| = 1
  • Focal length F (the distance between Camera position Cp and the camera projection plane S)

From the above parameters, we can retrieve other parameters which will be useful further:

  • P, a point located at the plane

P = Cp-V*F(x,y,z)

  • The S plane equation

From math books plane equation is in the form Ax+By+Cz+D=0

and also if we have a normal vector it is quite simple, and luckily we do have it and it is V.

From the same book...

A = Vx
B = Vy
C = VZ

we need to get D, but it simple now because we do have a point at the plane

so D = -(A*Px+B*PY+C*PZ)

A = normalVector.x;
B = normalVector.y;
C = normalVector.z;
D = -(normalVector.x * point.x + normalVector.y * point.y + normalVector.z * point.z);

The Camera Coordinates System

Now let's call pinhole model as camera coordinates system.

So to represent a model, now we do have a Cartesian reference system x,y,z and also a camera coordinates system.

The plan is to translate and rotate our camera coordinates system to fit the reference Cartesian coordinates system, for this we need some equations on spherical coordinates to retrieve the theta and phi angles.

"...In mathematics, a spherical coordinate system is a coordinate system for three-dimensional space where the position of a point is specified by three numbers: the radial distance of that point from a fixed origin, its elevation angle measured from a fixed plane, and the azimuth angle of its orthogonal projection on that plane, measured from a fixed reference direction on the same. The elevation angle is often replaced by the inclination angle measured from a zenith direction perpendicular to the reference plane. ..."

See http://en.wikipedia.org/wiki/Spherical_coordinate_system

Spherical coordinates

From my math book, we get how to represent a given R3 point into spherical coordinates and also conversions... (it will be used further).

Converting Cartesian coordinates to spherical

x = R sin (phi) cos (theta)
y = R sin (phi) sin (theta)
z = R cos (phi)

Converting spherical coordinates to Cartesian

R = sqrt(x2+y2+z2)
S = sqrt(x2+y2)
phi = acos(z/R)
theta = x>=0 asin(y/S)
x<0 PI - asin(y/S)

Follows how to calculate phi and theta angles, this will help us to rotate our coordinate system to fit the reference system

Point oNormalizedDirection = Algebra.Normalize(m_oDirection.x, 
				m_oDirection.y, m_oDirection.z);
// calculate frontpoint
m_oFrontPoint = new Point(m_oOrigin.x + oNormalizedDirection.x,
m_oOrigin.y + oNormalizedDirection.y,
m_oOrigin.z + oNormalizedDirection.z);
// 1 translate to origin
Point oTranslatedFrontPoint = new Point(m_oFrontPoint.x - m_oOrigin.x,
    m_oFrontPoint.y - m_oOrigin.y,
    m_oFrontPoint.z - m_oOrigin.z);
// calc phi & theta
double x2 = oTranslatedFrontPoint.x * oTranslatedFrontPoint.x;
double y2 = oTranslatedFrontPoint.y * oTranslatedFrontPoint.y;
double radius = Math.Sqrt(x2 + y2 + oTranslatedFrontPoint.z * oTranslatedFrontPoint.z);
double s = Math.Sqrt(x2 + y2);
m_dPhi = Math.Acos(oTranslatedFrontPoint.z / radius);
m_dTheta = 0;
if (Math.Abs(s) > 1.0E-5)
    {
    if (oTranslatedFrontPoint.x >= 0)

        {
        m_dTheta = Math.Asin(oTranslatedFrontPoint.y / s);
        }
    else
        {
        m_dTheta = Math.PI - Math.Asin(oTranslatedFrontPoint.y / s);
        }
    }

Calculating Projections

Projection

Our first objective is to calculate the projected point a at the plane S.

How To Get This?

From my old math book again...

We can easily calculate the intersection between a line and a plane if we have both equations, and luckily again we do!

Our line equation in parametric form is r = p + t*v.

  • p is any point at the line t is an scalar
  • v is the line vector
  • our p is the point a
  • our v can be calculated from the Camera position to a as Cp-a

Using this parametric equation against the plane equation, we find the parameter t and so we do find the intersection point using

  • t value at p + tv

Code

public Point GetIntersection(Point p, Point Origin)
    {
    Vector v = new Vector(p, Origin);
    double E = (v.x * A + v.y * B + v.z * C);
    if (Math.Abs(E)<1.0E-5)
        {
        return null;
        }
    v = Algebra.Normalize(v.x, v.y, v.z);
    double t = -(A * p.x + B * p.y + C * p.z + D) / (E);
    return new Point(p.x + t * v.x, p.y + t * v.y, p.z + t * v.z);
    }

Our last objective is to map this intersection point into our screen.

For this, we need to fit the point into our reference coordinate system using the calculated phi and theta...

Code

public Point LocalToCartesian(Point point)
    {
    point.x -= m_oOrigin.x;
    point.y -= m_oOrigin.y;
    point.z -= m_oOrigin.z;

    rtPoint.RotZ(-m_dTheta, ref point.x, ref point.y);
    rtPoint.RotY(m_dPhi, ref point.x, ref point.z);

    return new Point(point.x, point.y, point.z);
    }

Using the Code

All required code is in a project in the zip file at the top of the article, just download and compile.

Points of Interest

It is very challenging to keep improving the algorithms on my own and using only math instead of using libraries. Many people ask me why to create something which is already in many libraries. The response is that I like the challenge, the discovery, and it is very satisfactory to see the results by my own hands and effort.

History

Creating a camera class is a next step in the raytracing articles series, it will bring us to the next level and allow to start creating animations.

License

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

About the Author

andalmeida
Engineer TIHunter
United States United States
"Full Remote" Senior Analyst at +19547627489 (mobile) - Open for contracts
 
C C++ C# .NET Java Android ASP.NET HTML PHP
 
Founder of TIHunter Vagas de TI
 
Linkedin Profile
Follow on   LinkedIn

Comments and Discussions

 
GeneralMy vote of 5 Pinmembermanoj kumar choubey26-Feb-12 21:46 
GeneralBroken link PinmemberJohn Whitmire3-Feb-10 5:41 
GeneralRe: Broken link Pinmemberandalmeida3-Feb-10 6:30 
GeneralRe: Broken link Pinmemberandalmeida1-Mar-10 14:15 
QuestionAre spherical coordinates necessary? Pinmembersupercat91-Feb-10 13:36 
AnswerRe: Are spherical coordinates necessary? Pinmemberandalmeida2-Feb-10 0:14 
GeneralNice... PinmemberAlexander Müller30-Jan-10 23:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 9 Apr 2013
Article Copyright 2010 by andalmeida
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid