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?
Aucun commentaire:
Enregistrer un commentaire