#include /* NOTE: this code is OVERLY COMMENTED * Normally, you need way fewer comments./ /* * Vec3: * A class to represent a 3D VECTOR * (maybe also a 3D point and 3D versor? we'll see) */ struct Vec3{ /* everything is public here becuse that's the default for "struct". * If it was a "class", we'd need to add something like: public: */ // fields (the 3 coordinates) double x; double y; double z; // a basic constructor (commented out) /* Vec3(double _x, double _y, double _z){ this->x = _x; this->y = _y; this->z = _z; } */ /* A better way to do the above: * Here, the three fields are INITIALIZED (not, assigned) to the values */ Vec3(double _x, double _y, double _z): x(_x), y(_y), z(_z){} // A default constructor (no input parameter) /* We decide that a default vector is the "degenerate" (all 0s) vector. * Note: if we didn't assign them, the field would contain just dirty memory! * (this method is commented out) Vec3(){ x = 0; y = 0; z = 0; } */ // A better way to write the above (initializing x,y,z instead of assigning them) Vec3():x(0), y(0), z(0) {} // vector scaling as "in-place" function // in-place = this method works directly on the field of the struct invoking it. void scale(double k){ x *= k; y *= k; z *= k; } // Just like the above, but expressed as an operator "*=" instad of "scale" // (operator overloading) // To use this: see main void operator *=(double k){ // same implementatin as "scale" x *= k; y *= k; z *= k; } // vector scaling, but this time "out-of-place" // out-of-place: it doesn't change the instance invoking it. // instead, it returns the result (the scaled vector -- hance the name) // Note: with "const" we promise to the compiler that we will not change "this". // the compliler will check that we don't. // Both humans and complilers, just by looking at that "const" (part of the singature of the funciton) // will know that invoking "v.scaled" doesn't change "v", and maybe optimize accordingly. Vec3 scaled(double k) const{ // way one: using one temorary local variable // Vec3 result(x, y, z); // result.scale(k); // we invoke the in-place version... on a copy of ourself // return result; /* note: no memory is allocated in the heap! * (no "new", no "calloc", no explicit memory allocation of any sort) * no memory will need to be freed from the heap. * Instaed, the local variable "result" is stored in the stack, as any local variable, * and will be deallocated automatically when we get out of the function. * The result is passed as a copy, so that's safe. */ // way two: a one-liner (both ways invoke the constructor) return Vec3(x*k, y*k, z*k); } /* note on the method names: * in-place: v.scale ("please, v, scale yourself!" -- "scale" as a verb, imperative form). * out-of-place: v.scaled ("v, give me a scaled version of yourself, but don't change -- "scaled" as an adjective). */ // Same as above, but as an operator "*" instead of a method called "scaled" // (operator overloading). // To use this: see main. Vec3 operator *(double k) const{ // same implementation as "scaled" ! return Vec3(x*k, y*k, z*k); } // let's add the vector sum... // out-of-place version Vec3 added(const Vec3 &b) const{ // Note on the passage of parameters // ... added(Vec3 b) --> copy b (three doubles) and give the copy to the method "added". Can be inefficient (useless copy of 24 bytes) // ... added(Vec3 &b) --> give a *reference* to b to the method "added". No useless copy, but now we are worried that "added" might change b // ... added(const Vec3 &b) --> no useless copy (a reference is passed to "added"), but added "promises" not to change b return Vec3(x + b.x, y+ b.y, z + b.z ); } // alternative syntax: the above but as the operator "+" Vec3 operator +(const Vec3 &b) const{ // same implementation return Vec3(x + b.x, y+ b.y, z + b.z ); } // in-place version of vector sum void add(const Vec3 &b) { x += b.x; y += b.y; z += b.z; } // alternative syntax: the above but as the operator "+=" void operator += (const Vec3 &b) { // same implementation x += b.x; y += b.y; z += b.z; } // useful to write this vetor on screen void debug_print() const{ std::cout<<"X:" << x << " Y:" << y << " Z:" <