Graphics Reference
In-Depth Information
sense to allow direct access to their representation. The classes that protect their
representation are ones whose representation we may (and truthfully, will) later
want to change. For example, the internal representation of Triangle in this list-
ing is an array of vertices. If we found that we computed the edge vectors or face
normal frequently, then it might be more efficient to extend the representation to
explicitly store those values.
For images, we choose the underlying representation to be an array of
Radiance3 , each array entry representing the radiance incident at the center of
one pixel in the image. We then wrap this array in a class to present it as a 2D
structure with appropriate utility methods in Listing 15.5.
Listing 15.5: An Image class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Image {
private :
int m_width;
int m_height;
std::vector< Radiance3 > m_data;
int PPMGammaEncode( float radiance, float displayConstant) const ;
public :
Image ( int width, int height) :
m_width(width), m_height(height), m_data(width * height) {}
int width() const { return m_width; }
int height() const { return m_height; }
void set( int x, int y, const Radiance3 & value) {
m_data[x + y * m_width] = value;
}
const Radiance3 & get( int x, int y) const {
return m_data[x + y * m_width];
}
void save( const std::string& filename, float displayConstant=15.0f) const ;
};
Under C++ conventions and syntax, the & following a type in a declaration
indicates that the corresponding variable or return value will be passed by ref-
erence. The m_ prefix avoids confusion between member variables and methods
or parameters with similar names. The std::vector class is the dynamic array
from the standard library.
One could imagine a more feature-rich image class with bounds checking,
documentation, and utility functions. Extending the implementation with these is
a good exercise.
The set and get methods follow the historical row-major mapping from a
2D to a 1D array. Although we do not need it here, note that the reverse mapping
from a 1D index i to the 2D indices (x, y) is
x = i % width; y = i / width
where % is the C++ integer modulo operation.
 
Search WWH ::




Custom Search