Skip to content

Latest commit

 

History

History
164 lines (123 loc) · 4.46 KB

CONTRIBUTING.md

File metadata and controls

164 lines (123 loc) · 4.46 KB

Dev Guide

The following description is based on some suggestion from the book.

  • Pass by Reference

    Pass all compound objects into functions with references or constant references.

    Triangle::Triangle(const Point3D & v1, const Point3D & v2, const Point3D & v3);
  • Don't Return by Reference

    Instead return like this:

    Matrix
    Matrix::operator* (const Matrix& mat) const
  • Avoid Floating-Point Divides

    Floating-point division requires more machine cycles than a floating multiplication. Define constants such as

    const float invPI = 0.3183098861837906715f;

    Also good practice to divide values, for example, with 2.0 as below.

    float x = 128.0f * 0.5f

  • Inlining

    Only inline small functions, don't inline constructors, destructors, or virtual functions. Place inline functions in a header file.

Styleguide

Style guide is based on chapter 1.10 Coding Style and Google C++ Style Guide. The latter have higher priority. For readability and consistency follow the suggested coding style please.

  • Identifiers

    • Class names start with uppercase and subsequent words start with uppercase.
    class Sphere;
    class GeometricObject;
    • Member function name and data members are lower case and subsequent words are separated by underscore.
    RGBColor
    trace_ray(const Ray& ray) const;
    
    class Sphere: public GeometricObject {
        private:
            Point3D center;
    };
    • Pointer names end with _ptr
    Sphere* sphere_prt = new Sphere;
    • Setter functions and function that modify data members contain the data member name after an underscore
    inline void
    Matte::set_cd(const RGBColor c) {
        ambient_brdf->set_cd(c);
        diffuse_brdf->set_cd(c);
    }
    
    void
    Camera::compute_uvw(void) {
        // implementation
    }
  • Data Types

    In the original source code every classes implements their own copy constructor, assignment operator, and destructor even if they don't allocate memory dynamically. In the book it is a recommendation but not a necessity (chapter 1.10.2). Follow this for consistency please.

    Ray::Ray (const Ray& ray)
    : 	o(ray.o),
    	d(ray.d)
    {}
    
    Ray&
    Ray::operator= (const Ray& rhs) {
    
        if (this == &rhs)
            return (*this);
    
        o = rhs.o;
        d = rhs.d;
    
        return (*this);
    }
    
    Ray::~Ray (void) {}
  • Encapsulation

    As the book specifies "Class members are generally private or protected, but there are exceptions based on their frequency of access."

    The following classes' data members are public: BBox, Matrix, Normal, Point3D, Ray, RGBColor, ShadeRec, Vector3D, ViewPlane, World

  • Function Signatures

    The author suggest that we should avoid temporarily constructed parameters like the example below.

    void
    Matter::set_cd(const RGBColor& c);
    
    matter_ptr->set_cd(RGBColor(r, g, b));

    Instead we should use a less object-oriented signature:

    void
    Matte::set_cd(float r, float g, float b);
    
    matte_ptr->set_cd(r, g, b);
  • Pure Virtual and Virtual Functions

    Declare a function pure virtual in the base class if it has to be defined for every derived class. Otherwise declare a function as virtual in the base class and also define it here. It can do nothing or return a default value.

  • File Structure

    Put each class declaration in a header file (Sphere.h) and put the class definition in a separate file (Sphere.cpp). To prevent it being included more than once use include guard.

    #ifndef __SPHERE__
    #define __SPHERE__
    #include "GeometricObject.h"
    class Sphere: public GeometricObject {
        // data member and member function declarations...
    };
    #endif
  • Curly Braces

    Always use curly braces, even if the block contains only one line of code.
    Open curly brace on the end of the function declaration or end of the conditional statement.

    // WRONG
    if (sr.hit_an_object)
    {
    	sr.ray = ray;			// used for specular shading
    	return (sr.material_ptr->shade(sr));
    }   
    else
    	return (world_ptr->background_color);
    
    // RIGHT
    if (sr.hit_an_object) {
    	sr.ray = ray;			// used for specular shading
    	return (sr.material_ptr->shade(sr));
    }   
    else {
    	return (world_ptr->background_color);
    }