wireframe

This commit is contained in:
CJSatnarine
2025-02-26 19:23:22 -05:00
parent 3de1a87381
commit 16c5aa51b8
6 changed files with 6545 additions and 8 deletions

View File

@@ -5,4 +5,7 @@ add_executable(tiny_renderer
src/main.cpp src/main.cpp
src/tgaimage.cpp src/tgaimage.cpp
src/tgaimage.h src/tgaimage.h
src/geometry.h
src/model.h
src/model.cpp
) )

6357
obj/head.obj Normal file

File diff suppressed because it is too large Load Diff

56
src/geometry.h Normal file
View 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__

View File

@@ -1,21 +1,68 @@
#include "geometry.h"
#include "model.h"
#include "tgaimage.h" #include "tgaimage.h"
#include <cmath>
#include <vector>
using namespace std;
// Constants
const TGAColor white = TGAColor(255, 255, 255, 255); const TGAColor white = TGAColor(255, 255, 255, 255);
const TGAColor red = TGAColor(255, 0, 0, 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) { 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) { bool steep = false;
int x = x0 + (x1 - x0) * t;
int y = y0 + (y1 - y0) * t; // 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); image.set(x, y, color);
} }
}
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
TGAImage image(100, 100, TGAImage::RGB); model = new Model("../obj/head.obj");
line(0, 0, 99, 99, image, white);
image.flip_vertically(); // i want to have the origin at the left bottom TGAImage image(windowWidth, windowHeight, TGAImage::RGB);
// corner of the image // 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"); image.write_tga_file("output.tga");
delete model;
return 0; return 0;
} }

54
src/model.cpp Normal file
View 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
View 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__