Closed aditya-c2512 closed 2 years ago
NOTE : I am getting different UV values from the uvs[j] = model->uv(i,j);
statement so that does not seem to be the problem. I am guessing the problem is in the diffuse.get(...)
function after I get the uv values.
Update : I found some of my mistakes, which I have fixed now. I was giving the get(...)
function incorrect values, it should rather be
int uv_x = uvs[j].x*1024;
int uv_y = 1uvs[j].y*1024;
colors[j] = diffuse.get(uv_x, uv_y);
However, I am still getting incorrect diffuse colors, as shown below :
You have to use the barycentric to get uvs for any points in the triangle
This is the triangle(...)
I am using right now :
void triangle(Vec3f *pts, float *zbuffer, TGAImage &image, TGAColor color)
{
Vec2f bboxmin( std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
Vec2f bboxmax(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max());
Vec2f clamp(image.get_width()-1, image.get_height()-1);
for (int i=0; i<3; i++)
{
for (int j=0; j<2; j++)
{
bboxmin[j] = std::max(0.f, std::min(bboxmin[j], pts[i][j]));
bboxmax[j] = std::min(clamp[j], std::max(bboxmax[j], pts[i][j]));
}
}
Vec3f P;
for (P.x=bboxmin.x; P.x<=bboxmax.x; P.x++)
{
for (P.y=bboxmin.y; P.y<=bboxmax.y; P.y++)
{
Vec3f bc_screen = barycentric(pts[0], pts[1], pts[2], P);
if (bc_screen.x<0 || bc_screen.y<0 || bc_screen.z<0) continue;
P.z = 0;
for (int i=0; i<3; i++) P.z += pts[i][2]*bc_screen[i];
if (zbuffer[int(P.x+P.y*width)]<P.z)
{
zbuffer[int(P.x+P.y*width)] = P.z;
image.set(P.x, P.y, color);
}
}
}
}
If I pass the UV coordinates of the 3 points contained in pts
to triangle(...)
and use the barycentric(...)
, passing the 3 UV coordinates and P
(screen coordinates), will I get back the UV coordinates for P
?
Here is my current code that I have for function(...)
and main(...)
:
void triangle(Vec3f *pts, float *zbuffer, TGAImage &image, TGAImage& diffuse, Vec2f* uvs, float intensity)
{
Vec2f bboxmin( std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
Vec2f bboxmax(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max());
Vec2f clamp(image.get_width()-1, image.get_height()-1);
for (int i=0; i<3; i++)
{
for (int j=0; j<2; j++)
{
bboxmin[j] = std::max(0.f, std::min(bboxmin[j], pts[i][j]));
bboxmax[j] = std::min(clamp[j], std::max(bboxmax[j], pts[i][j]));
}
}
Vec3f P;
TGAColor colors[3];
for (P.x=bboxmin.x; P.x<=bboxmax.x; P.x++)
{
for (P.y=bboxmin.y; P.y<=bboxmax.y; P.y++)
{
Vec3f bc_screen = barycentric(pts[0], pts[1], pts[2], P);
if (bc_screen.x<0 || bc_screen.y<0 || bc_screen.z<0) continue;
P.z = 0;
for(int i=0; i<3; i++) P.z += pts[i][2]*bc_screen[i];
for(int i=0; i<3; i++)
{
colors[i] = diffuse.get(uvs[i].x, uvs[i].y);
colors[i].r *= bc_screen[i];
colors[i].g *= bc_screen[i];
colors[i].b *= bc_screen[i];
}
TGAColor final_color = TGAColor((colors[0].r+colors[1].r+colors[2].r)*intensity,
(colors[0].g+colors[1].g+colors[2].g)*intensity,
(colors[0].b+colors[1].b+colors[2].b)*intensity,
255);
if (zbuffer[int(P.x+P.y*width)]<P.z)
{
zbuffer[int(P.x+P.y*width)] = P.z;
image.set(P.x, P.y, final_color);
}
}
}
}
main()
:
for (int i=0; i<model->nfaces(); i++)
{
std::vector<int> face = model->face(i);
Vec3f world_coords[3];
Vec3f pts[3];
Vec2f uvs[3];
for (int j=0; j<3; j++)
{
pts[j] = world2screen(model->vert(face[j]));
world_coords[j] = model->vert(face[j]);
uvs[j] = model->uv(i,j);
int uv_x = uvs[j].x*diffuse.get_width();
int uv_y = diffuse.get_height() - uvs[j].y*diffuse.get_height();
uvs[j].x = uv_x;
uvs[j].y = uv_y;
}
Vec3f n = cross((world_coords[2]-world_coords[0]),(world_coords[1]-world_coords[0]));
n.normalize();
float intensity = n*light_dir;
if(intensity > 0)
{
triangle(pts, zbuffer, image, diffuse, uvs, intensity);
}
}
You have to get uvs for any point P in the triangle first. It's the same way as you get P.z using the barycentric. and then you can use the uv to get the color in the texture. Using "colors[i] = diffuse.get(uvs[i].x, uvs[i].y);", you will get the same color for all the points in the triangle
try something like this:
P.z = 0;
Vec2f uv;
for (int i = 0; i < 3; i++)
{
P.z += pts[i][2] * bc_screen[i];
uv.x += uvs[i].x * bc_screen[i];//get uv for point P in the triangle
uv.y += uvs[i].y * bc_screen[i];
}
Thanks! I will try it out.
I have implemented a few of my own functions in
model.cpp
and used them to get back the texture coordinates. However, I am not getting the required output from the whole operation.model.cpp
:main.cpp
:final_color
is the average of thecolor[]
array, which are the diffuse colors for each vertex of facei
.When printing the
color
array to the standard output for each pixel, I get that the array is constantly[{c,0,F},{c,0,F},{c,0,F}]
so I am pretty confused as to where I am going wrong. Can anyone help me debug this particular error?FINAL OUTPUT :