I am studying Shading and how light interacts with objects. I found a great website and wanted to implement knowledge from https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/shading-normals in my own way.
I wrote a code. It is supposed to calculate a facing ratio (cosine of the angle between a normal vector and a light Ray ) and generate a ".BMP" image with that. I took a surface as an object (well, on the image it will be a circle). The idea was to calculate the effect of this ratio on the color of the surface, i.e how light and object interact.
The code is as follows
template <typename T>
class Vec3
{
private:
T x, y, z;
public:
Vec3(): x{0},y{0},z{0} {}
Vec3(T xx): x{xx}, y{xx},z{xx} {}
Vec3(T xx, T yy, T zz): x{xx}, y{yy}, z{zz} {}
friend Vec3<T> operator+(const Vec3<T>& vec1, const Vec3<T>& vec2) { return Vec3<T>(vec1.x + vec2.x, vec1.y + vec2.y, vec1.z + vec2.z); }
friend Vec3<T> operator-(const Vec3<T>& vec1, const Vec3<T>& vec2) { return Vec3<T>(vec1.x - vec2.x, vec1.y - vec2.y, vec1.z - vec2.z); }
friend Vec3<T> operator*(const Vec3<T>& vec1, const Vec3<T>& vec2) { return Vec3<T>(vec1.x * vec2.x, vec1.y * vec2.y, vec1.z * vec2.z); }
friend Vec3<T> operator*(const Vec3<T>& vec1, const T& k) { return Vec3<T>(vec1.x * k, vec1.y * k, vec1.z * k); }
friend Vec3<T> operator/(const Vec3<T>& vec1, const T& k) { return Vec3<T>(vec1.x / k, vec1.y / k, vec1.z / k); }
Vec3<T> operator - () const { return Vec3<T>(-x, -y, -z); }
T dot (const Vec3<T>& v) const { return x * v.x + y * v.y + z * v.z; }
T lengthWithoutRoot() const { return x * x + y * y + z * z; }
T length() const { return sqrt(lengthWithoutRoot()); }
Vec3& normalize()
{
T nor2 = lengthWithoutRoot();
if (nor2 > 0) {
T divider = 1 / sqrt(nor2);
x *= divider, y *= divider, z *= divider;
}
return *this;
}
Vec3<T> reflection(const Vec3<T>& prim,const Vec3<T>& normal) // TO BE CHECKED
{
Vec3<T> reflection = prim - 2 * (prim.dot(normal)) * normal;
return reflection;
}
friend std::ostream& operator<<(std::ostream &out, const Vec3<T>& vec)
{
out << '(' << vec.x << ',' << vec.y << ',' << vec.z << ')';
return out;
}
const T& getX() { return x; }
const T& getY() { return y; }
const T& getZ() { return z; }
};
typedef Vec3<float> Vec3f;
class Sphere
{
private:
Vec3f center;
float radius;
public:
Sphere(const Vec3f& c, const float& r): center{c}, radius{r} {}
bool intersect(const Vec3f& primRay)
{
Vec3f vecRadius = center - primRay;
float distLength = vecRadius.length();
if (distLength > radius)
return false;
return true;
}
bool intersectSurface(const Vec3f& primRay)
{
Vec3f vecRadius = center - primRay;
float distLength = vecRadius.length();
if (distLength == radius)
return true;
return false;
}
float alphaPositive(const Vec3f& p, const Vec3f& source)
{
Vec3f primRay = (source-p).normalize();
Vec3f normal = (p-center).normalize();
float diff = primRay.dot(normal);
return std::max(diff,0.f) ;
}
};
int main()
{
Sphere sphere (Vec3f{ 250.0f, 250.0f, 0.0 }, 150.0f );
Vec3f source{ 100,200,0.0 };
Vec3f color{ 255,255,255 };
std::ofstream file;
file.open("DIF_SPHERE36.ppm");
file << "P6\n" << height << " " << width << "\n255\n";
for (float h = 0; h < 500; ++h)
{
for (float w = 0; w < 500; ++w)
{
Vec3f primRay = { h,w,0.0 };
if (sphere.intersect(primRay))
{
float facingRatio= sphere.alphaPositive(primRay, source);
color = Vec3f{255,0,0}*facingRatio;
file << unsigned char(color.getX()) << unsigned char(color.getY()) << unsigned char(color.getZ());
}
else
file << unsigned char(255) << unsigned char(255) << unsigned char(255);
}
}
file.close();
return 0;
}
However. I get smth strange, even when I try to change 'source' coordinates.
Facing ratio is calculated in alphaPositive function This is what a code must generate according to the idea
Thank you all for your comments.
I made following conclusions:
In function alphaPositive I had to use return std::max(diff,0.1f) instead of return std::max(diff,0.f).
Had to change positioning of the Object and Light by adding z-coordinates.
With that I managed to get a sphere with some effects.
Related
I've tried several times to get rid of the error, one of which was to use #ifndef but it hasn't worked yet. Please help!
vec3.h file
#ifndef VEC3_H
#define VEC3_H
#include <cmath>
#include <iostream>
using std::sqrt;
class vec3 {
public:
vec3() : e{0,0,0} {}
vec3(double e0, double e1, double e2) : e{e0, e1, e2} {}
double x() const { return e[0]; }
double y() const { return e[1]; }
double z() const { return e[2]; }
vec3 operator-() const { return vec3(-e[0], -e[1], -e[2]); }
double operator[](int i) const { return e[i]; }
double& operator[](int i) { return e[i]; }
vec3& operator+=(const vec3 &v) {
e[0] += v.e[0];
e[1] += v.e[1];
e[2] += v.e[2];
return *this;
}
vec3& operator*=(const double t) {
e[0] *= t;
e[1] *= t;
e[2] *= t;
return *this;
}
vec3& operator/=(const double t) {
return *this *= 1/t;
}
double length() const {
return sqrt(length_squared());
}
double length_squared() const {
return e[0]*e[0] + e[1]*e[1] + e[2]*e[2];
}
public:
double e[3];
};
// Type aliases for vec3
using point3 = vec3; // 3D point
using color = vec3; // RGB color
#endif
// vec3 Utility Functions
inline std::ostream& operator<<(std::ostream &out, const vec3 &v) {
return out << v.e[0] << ' ' << v.e[1] << ' ' << v.e[2];
}
inline vec3 operator+(const vec3 &u, const vec3 &v) {
return vec3(u.e[0] + v.e[0], u.e[1] + v.e[1], u.e[2] + v.e[2]);
}
inline vec3 operator-(const vec3 &u, const vec3 &v) {
return vec3(u.e[0] - v.e[0], u.e[1] - v.e[1], u.e[2] - v.e[2]);
}
inline vec3 operator*(const vec3 &u, const vec3 &v) {
return vec3(u.e[0] * v.e[0], u.e[1] * v.e[1], u.e[2] * v.e[2]);
}
inline vec3 operator*(double t, const vec3 &v) {
return vec3(t*v.e[0], t*v.e[1], t*v.e[2]);
}
inline vec3 operator*(const vec3 &v, double t) {
return t * v;
}
inline vec3 operator/(vec3 v, double t) {
return (1/t) * v;
}
inline double dot(const vec3 &u, const vec3 &v) {
return u.e[0] * v.e[0]
+ u.e[1] * v.e[1]
+ u.e[2] * v.e[2];
}
inline vec3 cross(const vec3 &u, const vec3 &v) {
return vec3(u.e[1] * v.e[2] - u.e[2] * v.e[1],
u.e[2] * v.e[0] - u.e[0] * v.e[2],
u.e[0] * v.e[1] - u.e[1] * v.e[0]);
}
inline vec3 unit_vector(vec3 v) {
return v / v.length();
}
main file, chap_3.cpp
#include "color.h"
#include "ray.h"
#include "vec3.h"
#include <iostream>
color ray_color(const ray& r) {
vec3 unit_direction = unit_vector(r.direction());
auto t = 0.5*(unit_direction.y() + 1.0);
return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0);
}
int main() {
// Image
const auto aspect_ratio = 16.0 / 9.0;
const int image_width = 400;
const int image_height = static_cast<int>(image_width / aspect_ratio);
// Camera
auto viewport_height = 2.0;
auto viewport_width = aspect_ratio * viewport_height;
auto focal_length = 1.0;
auto origin = point3(0, 0, 0);
auto horizontal = vec3(viewport_width, 0, 0);
auto vertical = vec3(0, viewport_height, 0);
auto lower_left_corner = origin - horizontal/2 - vertical/2 - vec3(0, 0, focal_length);
// Render
std::cout << "P3\n" << image_width << " " << image_height << "\n255\n";
for (int j = image_height-1; j >= 0; --j) {
std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush;
for (int i = 0; i < image_width; ++i) {
auto u = double(i) / (image_width-1);
auto v = double(j) / (image_height-1);
ray r(origin, lower_left_corner + u*horizontal + v*vertical - origin);
color pixel_color = ray_color(r);
write_color(std::cout, pixel_color);
}
}
std::cerr << "\nDone.\n";
}
How can I solve errors like the following:
enter codevec3.h: In function 'vec3 operator+(const vec3&, const vec3&)':
vec3.h:65:17: error: redefinition of 'vec3 operator+(const vec3&, const vec3&)'
inline vec3 operator+(const vec3 &u, const vec3 &v) {
^~~~~~~~
In file included from color.h:4:0,
from chap_3.cpp:1:
vec3.h:65:17: note: 'vec3 operator+(const vec3&, const vec3&)' previously defined here
inline vec3 operator+(const vec3 &u, const vec3 &v) {
^~~~~~~~ here
I've tried several sources but to no avail, also I picked the code from a trusted source and have made only minor changes so I am not able to understand why the error is occuring.
Your inline definitions are after the #ifndef/#endif surrounding the rest of the header file, meaning they will be picked up by every #include. You can either
Move the #endif to the very end of the header file, or
Use #pragma once instead of the include guards (not standard but most compilers support it).
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I'm analyzing a piece of code and I came across this
class X
{
//content
};
typedef X<float> X;
Can someone points me to something closer to the source of what this (using
<type> to basically make a second class working with second type) is called, how does it work or in what cases we use this so I can continue the search. (In my case it was used as a class defining a 3-dimensional vector.)
this is the entire code:
template<typename T>
class Vec3
{
public:
T x, y, z;
Vec3() : x(T(0)), y(T(0)), z(T(0)) {}
Vec3(T xx) : x(xx), y(xx), z(xx) {}
Vec3(T xx, T yy, T zz) : x(xx), y(yy), z(zz) {}
Vec3& normalize()
{
T nor2 = length2();
if (nor2 > 0) {
T invNor = 1 / sqrt(nor2);
x *= invNor, y *= invNor, z *= invNor;
}
return *this;
}
Vec3<T> operator * (const T &f) const { return Vec3<T>(x * f, y * f, z * f); }
Vec3<T> operator * (const Vec3<T> &v) const { return Vec3<T>(x * v.x, y * v.y, z * v.z); }
T dot(const Vec3<T> &v) const { return x * v.x + y * v.y + z * v.z; }
Vec3<T> operator - (const Vec3<T> &v) const { return Vec3<T>(x - v.x, y - v.y, z - v.z); }
Vec3<T> operator + (const Vec3<T> &v) const { return Vec3<T>(x + v.x, y + v.y, z + v.z); }
Vec3<T>& operator += (const Vec3<T> &v) { x += v.x, y += v.y, z += v.z; return *this; }
Vec3<T>& operator *= (const Vec3<T> &v) { x *= v.x, y *= v.y, z *= v.z; return *this; }
Vec3<T> operator - () const { return Vec3<T>(-x, -y, -z); }
T length2() const { return x * x + y * y + z * z; }
T length() const { return sqrt(length2()); }
friend std::ostream & operator << (std::ostream &os, const Vec3<T> &v)
{
os << "[" << v.x << " " << v.y << " " << v.z << "]";
return os;
}
};
typedef Vec3<float> Vec3f;
You have probably missed some related piece of code appearing before class X:
template <typename T> // <<<<<<<<<<<<<<<<<<<<<<
class X
{
//content
};
Can someone points me to something closer to the source of what this is called,
That's called a class template.
how does it work
The code provided in the class template definition will be instantiated for various types as provided by
typedef X<float> X;
or
typedef X<int> Y;
I am defining a Vec2 class with a friend functions. I am getting the error: argument list for class template Vec2 is missing for the friend function: friend Vec2 operator * (const T &r, const Vec2 &v).
template<typename T>
class Vec2
{
public:
Vec2() : x(0), y(0) {}
Vec2(T xx) : x(xx), y(xx) {}
Vec2(T xx, T yy) : x(xx), y(yy) {}
Vec2 operator + (const Vec2 &v) const
{ return Vec2(x + v.x, y + v.y); }
Vec2 operator / (const T &r) const
{ return Vec2(x / r, y / r); }
Vec2 operator * (const T &r) const
{ return Vec2(x * r, y * r); }
Vec2& operator /= (const T &r)
{ x /= r, y /= r; return *this; }
Vec2& operator *= (const T &r)
{ x *= r, y *= r; return *this; }
friend std::ostream& operator << (std::ostream &s, const Vec2<T> &v)
{
return s << '[' << v.x << ' ' << v.y << ']';
}
friend Vec2 operator * (const T &r, const Vec2<T> &v)
{ return Vec2(v.x * r, v.y * r); }
T x, y;
};
I'm using CLion with GCC 7.8 for coding in C++. We have this code, which using for "rendering" image from *.OBJ files.
#ifndef __GEOMETRY_H__
#define __GEOMETRY_H__
#include <cmath>
template <class t> struct Vec2 {
t x, y;
Vec2<t>() : x(t()), y(t()) {}
Vec2<t>(t _x, t _y) : x(_x), y(_y) {}
Vec2<t>(const Vec2<t> &v) : x(t()), y(t()) { *this = v; }
Vec2<t> & operator =(const Vec2<t> &v) {
if (this != &v) {
x = v.x;
y = v.y;
}
return *this;
}
Vec2<t> operator +(const Vec2<t> &V) const { return Vec2<t>(x+V.x, y+V.y); }
Vec2<t> operator -(const Vec2<t> &V) const { return Vec2<t>(x-V.x, y-V.y); }
Vec2<t> operator *(float f) const { return Vec2<t>(x*f, y*f); }
t& operator[](const int i) { if (x<=0) return x; else return y; }
template <class > friend std::ostream& operator<<(std::ostream& s, Vec2<t>& v);
};
template <class t> struct Vec3 {
t x, y, z;
Vec3<t>() : x(t()), y(t()), z(t()) { }
Vec3<t>(t _x, t _y, t _z) : x(_x), y(_y), z(_z) {}
template <class u> Vec3<t>(const Vec3<u> &v);
Vec3<t>(const Vec3<t> &v) : x(t()), y(t()), z(t()) { *this = v; }
Vec3<t> & operator =(const Vec3<t> &v) {
if (this != &v) {
x = v.x;
y = v.y;
z = v.z;
}
return *this;
}
Vec3<t> operator ^(const Vec3<t> &v) const { return Vec3<t>(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); }
Vec3<t> operator +(const Vec3<t> &v) const { return Vec3<t>(x+v.x, y+v.y, z+v.z); }
Vec3<t> operator -(const Vec3<t> &v) const { return Vec3<t>(x-v.x, y-v.y, z-v.z); }
Vec3<t> operator *(float f) const { return Vec3<t>(x*f, y*f, z*f); }
t operator *(const Vec3<t> &v) const { return x*v.x + y*v.y + z*v.z; }
float norm () const { return std::sqrt(x*x+y*y+z*z); }
Vec3<t> & normalize(t l=1) { *this = (*this)*(l/norm()); return *this; }
t& operator[](const int i) { if (i<=0) return x; else if (i==1) return y; else return z; }
template <class > friend std::ostream& operator<<(std::ostream& s, Vec3<t>& v);
};
typedef Vec2<float> Vec2f;
typedef Vec2<int> Vec2i;
typedef Vec3<float> Vec3f;
typedef Vec3<int> Vec3i;
template <> template <> Vec3<int>::Vec3(const Vec3<float> &v);
template <> template <> Vec3<float>::Vec3(const Vec3<int> &v);
template <class t> std::ostream& operator<<(std::ostream& s, Vec2<t>& v) {
s << "(" << v.x << ", " << v.y << ")\n";
return s;
}
template <class t> std::ostream& operator<<(std::ostream& s, Vec3<t>& v) {
s << "(" << v.x << ", " << v.y << ", " << v.z << ")\n";
return s;
}
#endif //__GEOMETRY_H__
This template used in my main.cpp file, something like that:
void triangle(Vec3i t0, Vec3i t1, Vec3i t2, TGAImage &image, TGAColor color, int *zbuffer) {
if (t0.y == t1.y && t0.y == t2.y) return;
// sort point by Y coordinate
if (t0.y > t1.y) std::swap(t0, t1);
if (t0.y > t2.y) std::swap(t0, t2);
if (t1.y > t2.y) std::swap(t1, t2);
int total_height = t2.y - t0.y;
for (int i=0; i<total_height; i++) {
bool second_half = i > t1.y - t0.y || t1.y == t0.y;
int segment_height = second_half ? t2.y - t1.y : t1.y - t0.y;
float alpha = (float)i / total_height;
float beta = (float)(i - (second_half ? t1.y - t0.y : 0)) / segment_height;
Vec3i A = t0 + Vec3f(t2 - t0) * alpha;
Vec3i B = second_half ? t1 + Vec3f(t2 - t1) * beta : t0 + Vec3f(t1 - t0) * beta;
if (A.x > B.x) std::swap(A, B);
for (int j=A.x; j<=B.x; j++) {
float phi = B.x == A.x ? 1. : (float)(j - A.x) / (float)(B.x - A.x);
Vec3i P = Vec3f(A) + Vec3f(B - A) * phi;
int idx = P.x + P.y * width;
// Z-buffer
if (zbuffer[idx] < P.z) {
zbuffer[idx] = P.z;
image.set(P.x, P.y, color);
}
}
}
}
void add_light_zbuffer(Vec3f light_dir, Model &model, TGAImage &image, int* zbuffer) {
for (int i=0; i<model.nfaces(); i++) {
std::vector<int> face = model.face(i);
Vec3i screen_coords[3];
Vec3f world_coords[3];
for (int j = 0; j < 3; j++) {
Vec3f v = model.vert(face[j]);
screen_coords[j] = Vec3i((v.x + 1.) * width / 2.,
(v.y + 1.) * height / 2.,
(v.z + 1.) * depth / 2.);
world_coords[j] = v;
}
// calculate light intensity
Vec3f n = (world_coords[2] - world_coords[0]) ^ (world_coords[1] - world_coords[0]);
n.normalize();
float intensity = n * light_dir;
// and apply it on image
if (intensity > 0) {
triangle(screen_coords[0], screen_coords[1], screen_coords[2], image,
TGAColor((unsigned char)(intensity * 255),
(unsigned char)(intensity * 255),
(unsigned char)(intensity * 255),
(unsigned char) 255),
zbuffer);
}
}
}
void scene_3d_zbuffer() {
TGAImage render(width, height, TGAImage::RGB);
Model* model = new Model("../assets/african_head.obj");
int* zbuffer = new int[width * height];
for (int i=0; i<width * height; i++) {
zbuffer[i] = std::numeric_limits<int>::min();
}
Vec3f light_dir = Vec3f(0, 0, -1);
add_light_zbuffer(light_dir, *model, render, zbuffer);
render.flip_vertically();
render.write_tga_file("output3_2.tga");
delete zbuffer;
delete model;
}
But after start building by CMake 3.2.2, I taken this messages in my console:
[ 25%] Linking CXX executable /Users/savicvalera/code/LearnComputerGraphics/bin/Lesson_3_Deleting_hidden_surfaces
[ 66%] Built target Lesson_1_Bresenham_algorithm
Built target Lesson_2_Trinagles_rasterization
Undefined symbols for architecture x86_64:
"Vec3<float>::Vec3<int>(Vec3<int> const&)", referenced from:
triangle(Vec3<int>, Vec3<int>, Vec3<int>, TGAImage&, TGAColor, int*) in main.cpp.o
"Vec3<int>::Vec3<float>(Vec3<float> const&)", referenced from:
triangle(Vec3<int>, Vec3<int>, Vec3<int>, TGAImage&, TGAColor, int*) in main.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [/Users/savicvalera/code/LearnComputerGraphics/bin/Lesson_3_Deleting_hidden_surfaces] Error 1
make[1]: *** [CMakeFiles/Lesson_3_Deleting_hidden_surfaces.dir/all] Error 2
make: *** [all] Error 2
And my question is: what happens with code, and why build failed every time?
For solving this issue necessary add links on cpp/h files into CMake file. For example, in this situation was:
project(Lesson_3_Deleting_hidden_surfaces)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES src/IntroCG/Lesson_3_Deleting_hidden_surfaces/main.cpp)
add_executable(Lesson_3_Deleting_hidden_surfaces ${SOURCE_FILES}
src/IntroCG/tgaimage.cpp src/IntroCG/tgaimage.h
src/IntroCG/model.cpp src/IntroCG/model.h
src/IntroCG/painter.cpp src/IntroCG/painter.h)
and became
project(Lesson_3_Deleting_hidden_surfaces)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES src/IntroCG/Lesson_3_Deleting_hidden_surfaces/main.cpp)
add_executable(Lesson_3_Deleting_hidden_surfaces ${SOURCE_FILES}
src/IntroCG/geometry.cpp src/IntroCG/geometry.h
src/IntroCG/tgaimage.cpp src/IntroCG/tgaimage.h
src/IntroCG/model.cpp src/IntroCG/model.h
src/IntroCG/painter.cpp src/IntroCG/painter.h)
Hi I am trying to create a ray tracer that renders a polygonized, triangle-based model.
I have a point 3D struct in point3d.h that holds x,y, and z coordinates.
#ifndef __POINT3D_H__
#define __POINT3D_H__
#include <iostream>
using namespace std;
struct Point3D
{
double x;
double y;
double z;
Point3D() : x(0.0), y(0.0), z(0.0) {}
Point3D(const double & nx, const double & ny, const double & nz) : x(nx), y(ny), z(nz) {}
Point3D operator+(const Point3D & rhs) const {
return Point3D(x + rhs.x, y + rhs.y, z + rhs.z); }
Point3D operator-(const Point3D & rhs) const {
return Point3D(x - rhs.x, y - rhs.y, z - rhs.z); }
Point3D operator*(double val) const {
return Point3D(x * val, y * val, z * val); }
Point3D operator/(double val) const {
return Point3D(x / val, y / val, z / val); }
Point3D operator+=(const Point3D & rhs) {
x += rhs.x; y += rhs.y; z += rhs.z; return *this; }
Point3D operator-=(const Point3D & rhs) {
x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this; }
Point3D operator*=(double val) {
x *= val; y *= val; z *= val; return *this; }
Point3D operator/=(double val) {
x /= val; y /= val; z /= val; return *this; }
void print() {
cout << '(' << x << ',' << y << ',' << z << ')';
}
};
#endif
Here is where I try to use the * operator to multiple two Point3Ds together
Point3D phong(Point3D mColor, Point3D lColor, Point3D L, Point3D N, Point3D R, Point3D V)
{
Point3D k(1.0, 1.0, 1.0);
Point3D ambient = mColor * k.x;
Point3D diffuse_angle = ((N * L) / (length(N) * length(L)));
Point3D diffuse = lColor * k.y * diffuse_angle;
Point3D specular_angle = ((R * V) / (length(R) * length(V)));
double specular_x = pow(specular_angle.x, 100.0);
double specular_y = pow(specular_angle.y, 100.0);
double specular_z = pow(specular_angle.z, 100.0);
Point3D specular_power(specular_x, specular_y, specular_z);
Point3D specular = lColor * k.z * specular_power;
return ambient + (lColor * (diffuse + specular));
}
When I try to multiple two Point3D's together, I am getting a no match error.
Here is where the code fails. I feel like it is a simple mistake but I cannot figure it out. I am including the Point3d header file as follows: #include "point3d.h".
Point3D operator*(double val) const
You have just this version, Point3D * double and nothing else, but you are trying to use this operator for Point3D * Point3D. Point3D is not implicitly constructible from double, so this is why you have compilation error.
Point3D operator*(double val) const {
This is for multiplication Point3D * double. And by
N * L
you are trying to do Point3D * Point3D.
You can rectify this either by providing proper operator* for your class OR provide a conversion from double to your class through single argument constructor. Although I prefer former.
You should need a function like this
Point3D operator *(Point3D &temp) const {
}
Since you don't have function to multiply two 3d points you are getting errors.Try adding this function.
You need a function for the operation Point3D * Point3D, which can't be adapted for the call of Point3D::operator*(double val). Such as:
Point3D operator*(const Point3D & rhs) const {
return Point3D(x * rhs.x, y * rhs.y, z * rhs.z); }