Click here to Skip to main content
13,046,184 members (84,486 online)
Click here to Skip to main content
Add your own
alternative version


57 bookmarked
Posted 30 Jan 2010

Implementing a Basic Camera Model (Pinhole)

, 15 Jul 2016
Rate this:
Please Sign up or sign in to vote.
Implementing a basic camera model to extend the raytracing algorithms


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.


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..."


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. ..."


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);
        m_dTheta = Math.PI - Math.Asin(oTranslatedFrontPoint.y / s);

Calculating Projections


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


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...


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.


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.


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


About the Author

Brazil Brazil
Senior Analyst

Linkedin Profile

You may also be interested in...

Comments and Discussions

GeneralMy vote of 5 Pin
manoj kumar choubey26-Feb-12 21:46
membermanoj kumar choubey26-Feb-12 21:46 
GeneralBroken link Pin
John Whitmire3-Feb-10 5:41
memberJohn Whitmire3-Feb-10 5:41 
GeneralRe: Broken link Pin
andalmeida3-Feb-10 6:30
memberandalmeida3-Feb-10 6:30 
GeneralRe: Broken link Pin
andalmeida1-Mar-10 14:15
memberandalmeida1-Mar-10 14:15 
QuestionAre spherical coordinates necessary? Pin
supercat91-Feb-10 13:36
membersupercat91-Feb-10 13:36 
I would think that the simplest way to handle a pinhole camera would be to (1) assume that the lens is at (0,0,0) and the plane is at z coordinate h, in which case the coordinate on the 'film' will simply be (x*(h/z), y*(h/z)); (2) other placements of the 'camera' may be handled using a linear transformation matrix to map real coordinates to such a system.

Note that assuming the film is horizontal at a fixed z coordinate will make it practical to handle cameras with lenses. For example, the x and y slopes (with respect to z) of a line that hits a horizontal lens (constant z coordinate) will be adjusted by (-x/f, -y/f) where (x, y) is the z intercept and f is the focal length.

While it would be possible to handle lenses without mapping world coordinates to a fixed orientation, the formulas are so much simpler with such mapping that it's probably the way to go. Note that setting up the transformation matrix to handle the rotation and shifting will require using some trig functions, but those need only be used when the rotation is set or changed. Even if there are thousands of points that need to be mapped onto the camera plane, the trig functions won't have to be repeated.
AnswerRe: Are spherical coordinates necessary? Pin
andalmeida2-Feb-10 0:14
memberandalmeida2-Feb-10 0:14 
GeneralNice... Pin
Alexander Müller30-Jan-10 23:01
memberAlexander Müller30-Jan-10 23:01 

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

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

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170713.1 | Last Updated 15 Jul 2016
Article Copyright 2010 by andalmeida
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid