wireframe
This commit is contained in:
@@ -5,4 +5,7 @@ add_executable(tiny_renderer
|
||||
src/main.cpp
|
||||
src/tgaimage.cpp
|
||||
src/tgaimage.h
|
||||
src/geometry.h
|
||||
src/model.h
|
||||
src/model.cpp
|
||||
)
|
||||
|
6357
obj/head.obj
Normal file
6357
obj/head.obj
Normal file
File diff suppressed because it is too large
Load Diff
56
src/geometry.h
Normal file
56
src/geometry.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef __GEOMETRY_H__
|
||||
#define __GEOMETRY_H__
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class t> struct Vec2 {
|
||||
union {
|
||||
struct {t u, v;};
|
||||
struct {t x, y;};
|
||||
t raw[2];
|
||||
};
|
||||
Vec2() : u(0), v(0) {}
|
||||
Vec2(t _u, t _v) : u(_u),v(_v) {}
|
||||
inline Vec2<t> operator +(const Vec2<t> &V) const { return Vec2<t>(u+V.u, v+V.v); }
|
||||
inline Vec2<t> operator -(const Vec2<t> &V) const { return Vec2<t>(u-V.u, v-V.v); }
|
||||
inline Vec2<t> operator *(float f) const { return Vec2<t>(u*f, v*f); }
|
||||
template <class > friend std::ostream& operator<<(std::ostream& s, Vec2<t>& v);
|
||||
};
|
||||
|
||||
template <class t> struct Vec3 {
|
||||
union {
|
||||
struct {t x, y, z;};
|
||||
struct { t ivert, iuv, inorm; };
|
||||
t raw[3];
|
||||
};
|
||||
Vec3() : x(0), y(0), z(0) {}
|
||||
Vec3(t _x, t _y, t _z) : x(_x),y(_y),z(_z) {}
|
||||
inline 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); }
|
||||
inline Vec3<t> operator +(const Vec3<t> &v) const { return Vec3<t>(x+v.x, y+v.y, z+v.z); }
|
||||
inline Vec3<t> operator -(const Vec3<t> &v) const { return Vec3<t>(x-v.x, y-v.y, z-v.z); }
|
||||
inline Vec3<t> operator *(float f) const { return Vec3<t>(x*f, y*f, z*f); }
|
||||
inline 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; }
|
||||
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 <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__
|
63
src/main.cpp
63
src/main.cpp
@@ -1,21 +1,68 @@
|
||||
#include "geometry.h"
|
||||
#include "model.h"
|
||||
#include "tgaimage.h"
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Constants
|
||||
const TGAColor white = TGAColor(255, 255, 255, 255);
|
||||
const TGAColor red = TGAColor(255, 0, 0, 255);
|
||||
const TGAColor purple = TGAColor(255, 0, 255, 255);
|
||||
const int windowHeight = 800;
|
||||
const int windowWidth = 800;
|
||||
|
||||
Model *model = NULL;
|
||||
|
||||
void line(int x0, int y0, int x1, int y1, TGAImage &image, TGAColor color) {
|
||||
for (float t = 0.0; t < 1.0; t += 0.01) {
|
||||
int x = x0 + (x1 - x0) * t;
|
||||
int y = y0 + (y1 - y0) * t;
|
||||
image.set(x, y, color);
|
||||
bool steep = false;
|
||||
|
||||
// if the line is steep, we transpose the image.
|
||||
if (abs(x0 - x1) < abs(y0 - y1)) {
|
||||
swap(x0, y0);
|
||||
swap(x1, y1);
|
||||
steep = true;
|
||||
}
|
||||
// Make it left to right.
|
||||
if (x0 > x1) {
|
||||
swap(x0, x1);
|
||||
swap(y0, y1);
|
||||
}
|
||||
|
||||
for (int x = x0; x <= x1; x++) {
|
||||
float t = (x - x0) / (float)(x1 - x0);
|
||||
int y = y0 * (1.0 - t) + y1 * t;
|
||||
if (steep) {
|
||||
image.set(y, x, color); // if transposed, de-transpose.
|
||||
} else {
|
||||
image.set(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
TGAImage image(100, 100, TGAImage::RGB);
|
||||
line(0, 0, 99, 99, image, white);
|
||||
image.flip_vertically(); // i want to have the origin at the left bottom
|
||||
// corner of the image
|
||||
model = new Model("../obj/head.obj");
|
||||
|
||||
TGAImage image(windowWidth, windowHeight, TGAImage::RGB);
|
||||
// Iterate for the number of faces.
|
||||
for (int i = 0; i < model->nfaces(); i++) {
|
||||
// Set each face to be part of the vector.
|
||||
vector<int> face = model->face(i);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
Vec3f v0 = model->vert(face[j]);
|
||||
Vec3f v1 = model->vert(face[(j + 1) % 3]);
|
||||
int x0 = (v0.x + 1.0) * windowWidth / 2.0;
|
||||
int y0 = (v0.y + 1.0) * windowHeight / 2.0;
|
||||
int x1 = (v1.x + 1.0) * windowWidth / 2.0;
|
||||
int y1 = (v1.y + 1.0) * windowHeight / 2.0;
|
||||
line(x0, y0, x1, y1, image, white);
|
||||
}
|
||||
}
|
||||
|
||||
image. flip_vertically(); // Origin at bottom left of image.
|
||||
image.write_tga_file("output.tga");
|
||||
delete model;
|
||||
return 0;
|
||||
}
|
||||
|
54
src/model.cpp
Normal file
54
src/model.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include "model.h"
|
||||
|
||||
Model::Model(const char *filename) : verts_(), faces_() {
|
||||
std::ifstream in;
|
||||
in.open (filename, std::ifstream::in);
|
||||
if (in.fail()) return;
|
||||
std::string line;
|
||||
while (!in.eof()) {
|
||||
std::getline(in, line);
|
||||
std::istringstream iss(line.c_str());
|
||||
char trash;
|
||||
if (!line.compare(0, 2, "v ")) {
|
||||
iss >> trash;
|
||||
Vec3f v;
|
||||
for (int i=0;i<3;i++) iss >> v.raw[i];
|
||||
verts_.push_back(v);
|
||||
} else if (!line.compare(0, 2, "f ")) {
|
||||
std::vector<int> f;
|
||||
int itrash, idx;
|
||||
iss >> trash;
|
||||
while (iss >> idx >> trash >> itrash >> trash >> itrash) {
|
||||
idx--; // in wavefront obj all indices start at 1, not zero
|
||||
f.push_back(idx);
|
||||
}
|
||||
faces_.push_back(f);
|
||||
}
|
||||
}
|
||||
std::cerr << "# v# " << verts_.size() << " f# " << faces_.size() << std::endl;
|
||||
}
|
||||
|
||||
Model::~Model() {
|
||||
}
|
||||
|
||||
int Model::nverts() {
|
||||
return (int)verts_.size();
|
||||
}
|
||||
|
||||
int Model::nfaces() {
|
||||
return (int)faces_.size();
|
||||
}
|
||||
|
||||
std::vector<int> Model::face(int idx) {
|
||||
return faces_[idx];
|
||||
}
|
||||
|
||||
Vec3f Model::vert(int i) {
|
||||
return verts_[i];
|
||||
}
|
||||
|
20
src/model.h
Normal file
20
src/model.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __MODEL_H__
|
||||
#define __MODEL_H__
|
||||
|
||||
#include <vector>
|
||||
#include "geometry.h"
|
||||
|
||||
class Model {
|
||||
private:
|
||||
std::vector<Vec3f> verts_;
|
||||
std::vector<std::vector<int> > faces_;
|
||||
public:
|
||||
Model(const char *filename);
|
||||
~Model();
|
||||
int nverts();
|
||||
int nfaces();
|
||||
Vec3f vert(int i);
|
||||
std::vector<int> face(int idx);
|
||||
};
|
||||
|
||||
#endif //__MODEL_H__
|
Reference in New Issue
Block a user