-
Notifications
You must be signed in to change notification settings - Fork 1
Day 7 (190916)
- Filled the triangles.
Suppose I have a point abp that moves on line t0-t2. Suppose there is a point bbp that moves on boundary B, that is, on line segments t0t1 and t1t2. If bbp has the same y value as abp, I can move the y coordinate of abp from t0 to t2 and draw a line with the corresponding bbp to fill the triangle.
Vec2i bbp;
for (abp.y = t0.y; abp.y <= t1.y; abp.y++) {
abp.x = boundary_x(t0, t2, abp.y);
bbp = Vec2i(boundary_x(t0, t1, abp.y), abp.y);
line(abp, bbp, image, white);
}
for (abp.y = t1.y; abp.y <= t2.y; abp.y++) {
abp.x = boundary_x(t0, t2, abp.y);
bbp = Vec2i(boundary_x(t1, t2, abp.y), abp.y);
line(abp, bbp, image, white);
}
-
For the first, when I runned this code, it made non-fully-filled triangles.
void line(Vec2i p0, Vec2i p1, TGAImage &image, TGAColor color) {
bool steep = false;
if (std::abs(p0.x-p1.x)<std::abs(p0.y-p1.y)) {
std::swap(p0.x, p0.y);
std::swap(p1.x, p1.y);
steep = true;
}
if (p0.x>p1.x) {
std::swap(p0, p1);
}
for (int x=p0.x; x<=p1.x; x++) {
float t = (x-p0.x)/(float)(p1.x-p0.x);
int y = p0.y*(1.-t) + p1.y*t;
if (steep) {
image.set(y, x, color);
} else {
image.set(x, y, color);
}
}
}
void triangle(Vec2i t0, Vec2i t1, Vec2i t2, TGAImage &image) {
if (t0.y > t1.y) {
std::swap(t0.x, t1.x);
std::swap(t0.y, t1.y);
}
if (t0.y > t2.y) {
std::swap(t0.x, t2.x);
std::swap(t0.y, t2.y);
}
if (t1.y > t2.y) {
std::swap(t1.x, t2.x);
std::swap(t1.y, t2.y);
}
Vec2i abp = Vec2i(boundary_x(t0, t2, t1.y), t1.y); // (the boundary) A boundary point
Vec2i bbp;
if (t1.x < abp.x) {
side = eSideType::Left;
for (abp.y = t0.y; abp.y <= t1.y; abp.y++) {
abp.x = boundary_x(t0, t2, abp.y);
bbp = Vec2i(boundary_x(t0, t1, abp.y), abp.y);
line(abp, bbp, image, white);
}
for (abp.y = t1.y; abp.y <= t2.y; abp.y++) {
abp.x = boundary_x(t0, t2, abp.y);
bbp = Vec2i(boundary_x(t1, t2, abp.y), abp.y);
line(abp, bbp, image, white);
}
} else {
side = eSideType::Right;
for (abp.y = t0.y; abp.y <= t1.y; abp.y++) {
abp.x = boundary_x(t0, t2, abp.y);
bbp = Vec2i(boundary_x(t0, t1, abp.y), abp.y);
line(abp, bbp, image, white);
}
for (abp.y = t1.y; abp.y <= t2.y; abp.y++) {
abp.x = boundary_x(t0, t2, abp.y);
bbp = Vec2i(boundary_x(t1, t2, abp.y), abp.y);
line(abp, bbp, image, white);
}
}
}
Like these:
So to find this reason, I put some couts.
void line(Vec2i p0, Vec2i p1, TGAImage &image, TGAColor color) {
bool steep = false;
if (std::abs(p0.x-p1.x)<std::abs(p0.y-p1.y)) {
std::swap(p0.x, p0.y);
std::swap(p1.x, p1.y);
steep = true;
}
if (p0.x>p1.x) {
std::swap(p0, p1);
}
for (int x=p0.x; x<=p1.x; x++) {
float t = (x-p0.x)/(float)(p1.x-p0.x);
int y = p0.y*(1.-t) + p1.y*t;
std::cout << p0.y*(1.-t) << "+" << p1.y*t << "=" << p0.y*(1.-t) + p1.y*t << std::endl; // *
if (steep) {
image.set(y, x, color);
std::cout << x << " " << y << std::endl; // *
} else {
image.set(x, y, color);
std::cout << x << " " << y << std::endl; // *
}
}
}
void triangle(Vec2i t0, Vec2i t1, Vec2i t2, TGAImage &image) {
if (t0.y > t1.y) {
std::swap(t0.x, t1.x);
std::swap(t0.y, t1.y);
}
if (t0.y > t2.y) {
std::swap(t0.x, t2.x);
std::swap(t0.y, t2.y);
}
if (t1.y > t2.y) {
std::swap(t1.x, t2.x);
std::swap(t1.y, t2.y);
}
Vec2i abp = Vec2i(boundary_x(t0, t2, t1.y), t1.y); // (the boundary) A boundary point
std::cout << t1.x << " " << abp.x << std::endl; // *
Vec2i bbp;
if (t1.x < abp.x) {
side = eSideType::Left;
for (abp.y = t0.y; abp.y <= t1.y; abp.y++) {
abp.x = boundary_x(t0, t2, abp.y);
bbp = Vec2i(boundary_x(t0, t1, abp.y), abp.y);
line(abp, bbp, image, white);
std::cout << abp << bbp << std::endl; // *
}
for (abp.y = t1.y; abp.y <= t2.y; abp.y++) {
abp.x = boundary_x(t0, t2, abp.y);
bbp = Vec2i(boundary_x(t1, t2, abp.y), abp.y);
line(abp, bbp, image, white);
std::cout << abp << bbp << std::endl; // *
}
} else {
side = eSideType::Right;
for (abp.y = t0.y; abp.y <= t1.y; abp.y++) {
abp.x = boundary_x(t0, t2, abp.y);
bbp = Vec2i(boundary_x(t0, t1, abp.y), abp.y);
line(abp, bbp, image, white);
std::cout << abp << bbp << std::endl; // *
}
for (abp.y = t1.y; abp.y <= t2.y; abp.y++) {
abp.x = boundary_x(t0, t2, abp.y);
bbp = Vec2i(boundary_x(t1, t2, abp.y), abp.y);
line(abp, bbp, image, white);
std::cout << abp << bbp << std::endl; // *
}
}
}
cout that I really need was like below.
std::cout << p0.y*(1.-t) << " + " << p1.y*t << " == " << p0.y*(1.-t) + p1.y*t << std::endl;
std::cout << y <<std::endl;
In the function line, while casting y to int, it was not rounding the float value. So to fix it, I had to plus 0.5 to y before cast it.
int y = p0.y*(1.-t) + p1.y*t + 0.5;
Then it works.
But the vertices are blunt. I checked the logs, and found that the y value of vertices became nan.
It was because the division by zero.
for (int x=p0.x; x<=p1.x; x++) {
float t = (x-p0.x)/(float)(p1.x-p0.x); // here
int y = p0.y*(1.-t) + p1.y*t + 0.5;
if (steep) {
image.set(y, x, color);
} else {
image.set(x, y, color);
}
}
For the case that p1.x and p0.x are the same, I had to make an exception handling.
if (p0.x != p1.x) {
for (int x=p0.x; x<=p1.x; x++) {
float t = (x-p0.x)/(float)(p1.x-p0.x);
int y = p0.y*(1.-t) + p1.y*t + 0.5;
if (steep) {
image.set(y, x, color);
} else {
image.set(x, y, color);
}
}
} else {
for (int y=p0.y; y<=p1.y; y++) {
image.set(p0.x, y, color);
}
}
After fixing it, the vertecies appeared.