Hi all,
This code calculates the size in pixels of an object in the screen, using the "small angle approximation" formula.
It works for any camera Field Of View angle (FOV).
Ideal for Level Of Detail (LOD) systems based on size in pixels in screen (rather than based directly on distance calculus).
It allows to precisely find out if an object is not visible anymore (pixel size < 1), or when it has a particular size on the screen.
Particularly useful for LOD binocular view, or any other changing FOV scenery.
Also suitable for many other uses, as line of sight occlusion, combined with the x,y screen coordinates:
Knowing the 2d screen coordinates, the size in pixels, and the distance, it can be known if an object is visually occluded by another one.
Note on accuracy: This code is based on the "small angle approximation" formula, a simplification of the laws of trigonometry which only returns an approximated value. The greater the angle measured, or the FOV angle, the greater the error in the returned value.
Despite of this, accuracy should suffice for a standard gaming environment.
DBPro code version:
remstart
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
//////// This code calculates the size in pixels of an object in the screen,
//////// using the "small angle approximation" formula.
////////
//////// It works for any camera Field Of View angle (FOV).
//////// Ideal for Level Of Detail (LOD) systems based on size in pixels in screen
//////// (rather than based directly on distance# calculus).
//////// It allows to precisely find out if an object is not visible anymore (pixel size < 1),
//////// or when it has a particular size on the screen.
////////
//////// Particularly useful for LOD binocular view, or any other changing FOV scenery.
////////
//////// Also suitable for many other uses, as line of sight occlusion,
//////// combined with the x,y screen coordinates:
//////// Knowing the 2d screen coordinates, the size in pixels, and the distance#,
//////// it can be known if an object is visually occluded by another one.
////////
//////// Note on accuracy: This code is based on the "small angle approximation" formula,
//////// a simplification of the laws of trigonometry which only returns an approximated value.
//////// The greater the angle measured, or the FOV angle,
//////// the greater the error in the returned value.
//////// Despite of this, accuracy should suffice for a standard gaming environment.
////////
//////// 2010, Manuel Perez de Lema Lopez - MPL3D Team.
//////// If you use any portion of this code in a program, please credit "MPL3D".
////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
remend
angular_size# = 0.0
Diameter# = 200.0
distance# = 0.0
camera_FOV# = 55.0
pixel_size# = 0.0
Sync On
Sync Rate 30
Set Display Mode 640,480,32
Set Window On
Make Object Sphere 1, Diameter#/2.0, 10, 10
Position Object 1, 0.0, Diameter#/8.0, 0.0
Set Camera Range 1.0, 100000.0
Set Camera FOV camera_FOV#
do
if ShiftKey()
camera_FOV# = camera_FOV# + 0.5
Set Camera FOV camera_FOV#
endif
if ControlKey()
camera_FOV# = camera_FOV# - 0.5
Set Camera FOV camera_FOV#
endif
Control Camera Using ArrowKeys 0, 100.0, 0.5
distance# = (Object Position X(1) - Camera Position X()) * (Object Position X(1) - Camera Position X()) + (Object Position Y(1) - Camera Position Y()) * (Object Position Y(1) - Camera Position Y()) + (Object Position Z(1) - Camera Position Z()) * (Object Position Z(1) - Camera Position Z())
distance# = sqrt(distance#)
remstart
//Calculate angular size:
//
//d = distance# to the object
//D = Diameter# of the object
//Angle A ~ (D/d) x 57.3 deg.
//Note: This is called the "small angle approximation"
remend
angular_size# = ( Diameter# / distance# ) * 57.3
remstart
//Tranform into pixels:
//
// camera_FOV# º (degrees) -> Screen height (pixels)
// Angular size º (degrees) -> 'X' Object size (pixels)
//
//then,
//
// 'X' (pixels) = ( angular_size# (degrees) * Screen height (pixels) ) / camera_FOV# (degrees)
remend
pixel_size# = ( angular_size# * Screen Height() ) / camera_FOV#
pixel_size# = pixel_size# / 2.0
Set Cursor 0,10
Print Screen FPS()
Print "camera_FOV# = " + Str$(camera_FOV#)
Print "distance# = " + Str$(distance#)
Print "angular_size = " + Str$(angular_size#)
Print "pixel_size# = " + Str$(pixel_size#)
Sync
loop
end
DGDK code version:
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
//////// This code calculates the size in pixels of an object in the screen,
//////// using the "small angle approximation" formula.
////////
//////// It works for any camera Field Of View angle (FOV).
//////// Ideal for Level Of Detail (LOD) systems based on size in pixels in screen
//////// (rather than based directly on distance calculus).
//////// It allows to precisely find out if an object is not visible anymore (pixel size < 1),
//////// or when it has a particular size on the screen.
////////
//////// Particularly useful for LOD binocular view, or any other changing FOV scenery.
////////
//////// Also suitable for many other uses, as line of sight occlusion,
//////// combined with the x,y screen coordinates:
//////// Knowing the 2d screen coordinates, the size in pixels, and the distance,
//////// it can be known if an object is visually occluded by another one.
////////
//////// Note on accuracy: This code is based on the "small angle approximation" formula,
//////// a simplification of the laws of trigonometry which only returns an approximated value.
//////// The greater the angle measured, or the FOV angle,
//////// the greater the error in the returned value.
//////// Despite of this, accuracy should suffice for a standard gaming environment.
////////
//////// 2010, Manuel Perez de Lema Lopez - MPL3D Team.
//////// If you use any portion of this code in a program, please credit "MPL3D".
////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "windows.h"
#include "DarkGDK.h"
#include "math.h"
#include "stdio.h"
void DarkGDK ( void )
{
char text_line[256];
float angular_size = 0.0f;
float Diameter = 200.0f;
float distance = 0.0f;
float camera_FOV = 55.0f;
float pixel_size = 0.0f;
dbSyncOn();
dbSyncRate(30);
dbSetDisplayMode (640,480,32);
dbSetWindowOn();
dbMakeObjectSphere ( 1, Diameter/2.0f, 10, 10 );
dbPositionObject ( 1, 0.0f, Diameter/8.0f, 0.0f);
dbSetCameraRange (1.0f, 100000.0f );
dbSetCameraFOV( camera_FOV );
while ( LoopGDK ( ) )
{
if (dbShiftKey())
{
camera_FOV = camera_FOV + 0.5f ;
dbSetCameraFOV( camera_FOV );
}
if (dbControlKey())
{
camera_FOV = camera_FOV - 0.5f ;
dbSetCameraFOV( camera_FOV );
}
dbControlCameraUsingArrowKeys(0, 100.0f, 0.5f);
distance = (dbObjectPositionX(1) - dbCameraPositionX()) * (dbObjectPositionX(1) - dbCameraPositionX())
+ (dbObjectPositionY(1) - dbCameraPositionY()) * (dbObjectPositionY(1) - dbCameraPositionY())
+ (dbObjectPositionZ(1) - dbCameraPositionZ()) * (dbObjectPositionZ(1) - dbCameraPositionZ()) ;
distance = sqrt(distance);
//Calculate angular size:
//
//d = distance to the object
//D = Diameter of the object
//Angle A ~ (D/d) x 57.3 deg.
//Note: This is called the "small angle approximation"
angular_size = ( Diameter / distance ) * 57.3f;
//Tranform into pixels:
//
// camera_FOV º (degrees) -> Screen height (pixels)
// Angular size º (degrees) -> 'X' Object size (pixels)
//
//then,
//
// 'X' (pixels) = ( angular_size (degrees) * Screen height (pixels) ) / camera_FOV (degrees)
pixel_size = ( angular_size * dbScreenHeight() ) / camera_FOV ;
pixel_size = pixel_size / 2.0f;
dbSetCursor (0,10);
dbPrint ((float) dbScreenFPS());
sprintf(text_line, "camera_FOV = %f" , camera_FOV);
dbPrint (text_line);
sprintf(text_line, "distance = %f" , distance);
dbPrint (text_line);
sprintf(text_line, "angular_size = %f" , angular_size);
dbPrint (text_line);
sprintf(text_line, "pixel_size = %f" , pixel_size);
dbPrint (text_line);
dbSync();
} //end while
}// end DarkGDK
The maths behind the size in pixels is very simple using the small angle formula, just a couple of multiplications, so don't be afraid to use it
A note on the DBPro version, I have noticed that DBPro's screen resolution includes the window menu, so the pixel ratio looks weird here. To correct this, fix the camera aspect by adding the menu size (8x34 pixels), for example 640x480 would be:
Set Camera Aspect (640.0-8.0) / (480.0 - 34.0)
Not a thing to worry if using the right full screen resolution.
DGDK image:
If you use any portion of this code in a program, please credit "MPL3D", I got a brand name to maintain