[ LiB ] |
Let's take a look at the function prototypes that are used to read in each type of class listed in the scene definition file.
// scene primitives bool Read_Camera(ifstream& is); bool Read_Light(ifstream& is); cMaterial Read_Material(ifstream& is); bool Read_Sphere(ifstream& is); bool Read_Triangle(ifstream& is);
NOTE
TIP
You can extend the scene primitives anyway you want by including other primitives such as cones,cubes,planes,and polygons.
This method reads in a camera class from the scene definition file. The scene can only have one camera. If multiple entries are listed for the camera, the system will set up only the last camera class for the camera. The camera class contains five parameters, as follows :
The first parameter is the camera position (vector)
The second parameter is the LOOK vector (vector)
The third parameter is the UP vector (vector)
The fourth parameter is the viewing direction (vector)
The fifth parameter is the viewing distance (scalar)
Here's the code:
bool cScene::Read_Camera(ifstream& is) { // local buffer char buffer[BUFFER_LENGTH]; //=============================================================== // Statement : Camera { <0,0,0>, <0,0,0>, <0,0,1>, <0,0,1>, 256 } //=============================================================== // read { is >> buffer; // if the letter { wasn't found find it while(!COMPARE(buffer, "{")) is >> buffer; // set camera position CameraPosition = Read_Vector( is ); CameraPosition = cVector3( -CameraPosition.x, -CameraPosition.y, CameraPosition.z ) ; // read separating comma with white space Read_Comma ( is ); // set LOOK Vector Look = Read_Vector( is ); // read separating comma with white space Read_Comma ( is ); // set UP Vector Up = Read_Vector( is ); // read separating comma with white space Read_Comma ( is ); // read in Viewing Direction Viewing_Direction = Read_Vector( is ); Viewing_Direction = cVector3( -Viewing_Direction.x, -Viewing_Direction.y, Viewing_Direction.z ) ; // read separating comma with white space Read_Comma ( is ); // Read in Viewing Distance Viewing_Distance = Read_Scalar( is ); // We're done; ignore the rest of the statement return true; }
The read light method reads a diffuse point light into the scene. The scene definition file can have n number of lights listed in random order. As the parser finds each light class, the light is stored in the light list of the class. The light state is toggled so it can be used during rendering. The light class contains three parameters, as follows:
The first parameter is the light position (vector)
The second parameter is the color of the light ( color )
The third parameter is the wattage or brightness (scalar)
NOTE
TIP
You can extend the lights in the scene by including other lights such as spotlights ,directional lights,and area lights.
Here's the code:
bool cScene::Read_Light(ifstream& is) { // local buffer char buffer[BUFFER_LENGTH]; cLight Light; cVector3 pos; float power; color3 color; //======================================================= // Statement : Light { <0,50,0>, (255,0,0), 1 } //======================================================= // read { is >> buffer; // if the letter { wasn't found find it while(!COMPARE(buffer, "{")) is >> buffer; // set light position pos = Read_Vector( is ); // read separating comma with white space Read_Comma ( is ); // set light color color = Read_Color( is ); // read separating comma with white space Read_Comma ( is ); // set light wattage / power power = Read_Scalar( is ); // set up light Light.Setup( pos.x, pos.y, pos.z, power, color ); // set light active Light.bActive = true; // add to light list in scene AddToLightList(&pLightList, &nLightCount, Light); // We're done; ignore the rest of the statement return true; }
This method reads in a material subclass. Materials are normally attached to primitives such as spheres, polygons, planes, and so on. The material class is not an independent class; it depends on a parent class. The material class is included as a subclass in each sphere and triangle class. The material class reads in the different lighting coefficients for specific objects and, depending on the coefficient, simulates a specific kind of lighting effect. For example, if the material is specular, it will reflect light in the opposite direction. The material class contains nine parameters, as follows:
The first parameter is the ambient factor (scalar)
The second parameter is the specular factor (scalar)
The third parameter is the specular exponent that contributes to the highlight (scalar)
The fourth parameter is the opacity of the object (scalar)
The fifth parameter is the index of refraction (scalar)
The sixth parameter is the diffuse factor (scalar)
The seventh parameter is the shininess of the object (scalar)
The eighth parameter is the color of the object (color)
The ninth parameter is the texture of the object (string)
NOTE
TIP
Although the materials and lighting models have many more math ematical coefficients,I use only a subset in this book.This does not necessarily mean you should only use these few.You can add other factors for other lighting effects you choose to implement with this code.
Here's the code:
cMaterial cScene::Read_Material(ifstream& is) { cMaterial r; // local buffer char buffer[BUFFER_LENGTH]; cObject cObject( OBJECT_SPHERE) ; //======================================================= /* Material { fAmbientFactor 0.1 fSpecularFactor 0.9 fSpecularExponent 30.7 fOpacity 1.0 fIndex_Of_Refraction 0.1 fDiffuseFactor 0.8 fShininess 0.5 Color (1,1,1) Texture texture.ppm } */ //======================================================= // read { is >> buffer; // if the letter { wasn't found find it while(!COMPARE(buffer, "{")) is >> buffer; // Ambient Factor is >> buffer; if(COMPARE(buffer, "fAmbientFactor")) { // set value r.fAmbientFactor = Read_Scalar( is ); } // Specular Factor is >> buffer; if(COMPARE(buffer, "fSpecularFactor")) { // set value r.fSpecularFactor = Read_Scalar( is ); } // Specular Highlight is >> buffer; if(COMPARE(buffer, "fSpecularExponent")) { // set value r.fSpecularExponent = Read_Scalar( is ); } // Opacity is >> buffer; if(COMPARE(buffer, "fOpacity")) { // set value r.fOpacity = Read_Scalar( is ); } // Index of efraction is >> buffer; if(COMPARE(buffer, "fIndex_Of_Refraction")) { // set value r.fIndex_Of_Refraction = ead_Scalar( is ; } // DiffuseFactor is >> buffer; if(COMPARE(buffer, "fDiffuseFactor")) { // set value r.fDiffuseFactor = Read_Scalar( is ); } // Smoothness f urface is >> buffer; if(COMPARE(buffer, "fShininess")) { // set value r.fShininess = Read_Scalar( is ); } // Read Color is >> buffer; if(COMPARE(buffer, "Color")) { // set value r.Color = Read_Color( is ); } // Read Texture is >> buffer; if(COMPARE(buffer, "Texture")) { // set value is >> r.Texture; } // read } for material is >> buffer; // We're done return r; }
Read sphere reads a sphere class into the object array. The sphere class is a complex class because it includes a subclass. This subclass is the material class covered previously. You can have n amount of spheres listed in random order. The sphere class is read into the object list of the scene. A very important aspect to this read method is that the sphere class can be defined in both left-handed and right-handed systems. The sphere class contains one subclass and two parameters, as follows:
The material class is listed first (class)
The first parameter is the position of the sphere in space (vector)
The second parameter is the radius of the sphere (scalar)
The third parameter is a Boolean that determines which system (left or right) the sphere is defined in (scalar)
Here's the code:
bool cScene::Read_Sphere(ifstream& is) { // local buffer char buffer[BUFFER_LENGTH]; cMaterial m; cObject tObject( OBJECT_SPHERE) ; cVector3 pos; float radius; int handed_system; //======================================================= /* Sphere { Material { fAmbientFactor 0.1 fSpecularFactor 0.9 fSpecularExponent 30.7 fOpacity 1.0 fIndex_Of_Refraction 0.1 fDiffuseFactor 0.8 fShininess 0.5 Color (1,1,1) Texture texture.ppm } <0,0,0>, 1, 1 } */ //======================================================= // read { is >> buffer; // if the letter { wasn't found find it while(!COMPARE(buffer, "{")) is >> buffer; // read data into material structure m = Read_Material( is ) ; // copy data over to object structure tObject.fAmbientFactor = m.fAmbientFactor;; tObject.fDiffuseFactor = m.fDiffuseFactor; tObject.fSpecularFactor = m.fSpecularFactor; tObject.fSpecularExponent = m.fSpecularExponent; tObject.fOpacity = m.fOpacity; tObject.fIndex_Of_Refraction = m.fIndex_Of_Refraction; tObject.fShininess = m.fShininess; tObject.Color = m.Color; strcpy(tObject.Texture, m.Texture); // set sphere position pos = Read_Vector( is ); // read separating comma with white space Read_Comma ( is ); // set radius radius = Read_Scalar( is ); // read the handed system object was defined Read_Comma ( is ); // left (1) or ight 0) anded? handed_system = (int) Read_Scalar( is ); // set up object for handed system tObject.Setup_Sphere( pos.x, pos.y, pos.z, radius, (handed_system == 1 ? true: false)); // increment sphere count sphere_count++; // add to light list in scene AddToObjectList(&pObjectList, &nObjectCount, tObject); // We're done, Ignore the rest of the statement return true; }
Read triangle reads a triangle class into the object array. The triangle class is a complex class because it includes a subclass. The subclass is the material. You can have n amount of triangles listed in random order. The triangle class is read into the object list of the scene. A very important aspect to this read method is that the triangle class can be defined in both left-handed and right-handed systems. The triangle class contains one subclass and three parameters, as follows:
The material class is listed first (class)
The first parameter is vertex one or side A of the triangle (vector)
The second parameter is vertex two or side B (vector)
The third parameter is vertex three or side C (vector)
The fourth parameter is a Boolean that determines which system (left or right) the triangle is defined in (scalar)
Here's the code:
bool cScene::Read_Triangle(ifstream& is) { // local buffer char buffer[BUFFER_LENGTH]; cMaterial m; cObject tObject( OBJECT_TRIANGLE) ; cVector3 A,B,C; int handed_system; //======================================================= /* Triangle { Material { fAmbientFactor 0.1 fSpecularFactor 0.9 fSpecularExponent 30.7 fOpacity 1.0 fIndex_Of_Refraction 0.1 fDiffuseFactor 0.8 fShininess 0.5 Color (1,1,1) Texture texture.ppm } <-100,300,0>, <100,150,0>, <-30,-200,0>, 1 } */ //======================================================= // read { is >> buffer; // if the letter { wasn't found find it while(!COMPARE(buffer, "{")) is >> buffer; // read data into material structure m = Read_Material( is ) ; // copy data over to object structure tObject.fAmbientFactor = m.fAmbientFactor;; tObject.fDiffuseFactor = m.fDiffuseFactor; tObject.fSpecularFactor = m.fSpecularFactor; tObject.fSpecularExponent = m.fSpecularExponent; tObject.fOpacity = m.fOpacity; tObject.fIndex_Of_Refraction = m.fIndex_Of_Refraction; tObject.fShininess = m.fShininess; tObject.Color = m.Color; strcpy(tObject.Texture, m.Texture); // read Vertex A A = Read_Vector( is ); // read separating comma with white space Read_Comma ( is ); // read Vertex B B = Read_Vector( is ); // read separating comma with white space Read_Comma ( is ); // read Vertex C C = Read_Vector( is ); // read the anded system bject was efined Read_Comma ( is ); // left (1) or right (0) handed? handed_system = (int) Read_Scalar( is ); // set up object for handed system tObject.Setup_Triangle( A, B, C, (handed_system == 1 ? true: false)); // increment triangle count triangle_count++; // add to light list in scene AddToObjectList(&pObjectList, &nObjectCount, tObject); // We're done, Ignore the rest of the statement return true; }
A clever method for developing a 3D rendering program is to be selective about which types of lighting effects you choose to render. For example, there are numerous effects that can contribute to a rendered image. We are going to add a special variable that will be used to set up the scene to render certain lighting effects. The implementation of the lighting effects is really done with the rendering algorithm, but you should still allow the application to choose whether to use it or not. The selection of parameters is read in from file. Here is the list of lighting effects to add:
Diffuse interaction or diffuse shading
Specular highlights
Diffuse reflection
Specular (mirror) reflection
Refraction
NOTE
NOTE
Other natural lighting effects can be easily added to this list.
Here is the class definition, the read method, and the object that will be defined in the scene class:
// render settings class Render_Settings { public: Render_Settings() { use_diffuse_shading = false; use_diffuse_reflection = false; use_specular_reflection = false; use_refraction = false; use_specular_hightlights= false; } public: bool use_diffuse_shading, use_diffuse_reflection, use_specular_reflection, use_refraction, use_specular_hightlights; }; // Read lighting parameters from file bool Read_Render_Settings(ifstream& is); // The render settings object Render_Settings RenderSetting;
The body of the read method will take the elements from the Render_Settings class. If the value of the selected effect is the number 1, the Boolean is set to success for the effect in the RenderSetting object. This variable will be used during rendering to branch code, based on the enabled effects as you develop ray tracing and photon mapping.
bool cScene::Read_Render_Settings(ifstream& is) { // local buffer char buffer[BUFFER_LENGTH]; cScene::Render_Settings r; int Dummy; //======================================================= /* Render_Settings { Diffuse_Shading 1 Specular_Highlights 0 Diffuse_Reflection 0 Specular_Reflection 0 Refraction 0 } */ //======================================================= // read { is >> buffer; // if the letter { wasn't found find it while(!COMPARE(buffer, "{")) is >> buffer; // Diffuse Lighting on Surface is >> buffer; if(COMPARE(buffer, "Diffuse_Shading")) { // set value is >> Dummy; (Dummy == 1) ? r.use_diffuse_shading = true : r.use_diffuse_shading = false; } // Specular Hightlights is >> buffer; if(COMPARE(buffer, "Specular_Highlights")) { // set value is >> Dummy; (Dummy == 1) ? r.use_specular_hightlights = true : r.use_specular_hightlights = false; } // Diffuse Reflection to Other Surfaces is >> buffer; if(COMPARE(buffer, "Diffuse_Reflection")) { // set value is >> Dummy; (Dummy == 1) ? r.use_diffuse_reflection = true : r.use_diffuse_reflection = false; } // Specular Reflection to Mirror Surfaces is >> buffer; if(COMPARE(buffer, "Specular_Reflection")) { // set value is >> Dummy; (Dummy == 1) ? r.use_specular_reflection = true : r.use_specular_reflection = false; } // Refraction is >> buffer; if(COMPARE(buffer, "Refraction")) { // set value is >> Dummy; (Dummy == 1) ? r.use_refraction = true : r.use_refraction = false; } // read } for render lighting class is >> buffer; // save data to member variable RenderSetting = r; // We're done, Ignore the rest of the statement return true; }
[ LiB ] |