|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "mesh_core.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool isPointInTri(point p, point p0, point p1, point p2) |
|
|
{ |
|
|
|
|
|
point v0, v1, v2; |
|
|
v0 = p2 - p0; |
|
|
v1 = p1 - p0; |
|
|
v2 = p - p0; |
|
|
|
|
|
|
|
|
float dot00 = v0.dot(v0); |
|
|
float dot01 = v0.dot(v1); |
|
|
float dot02 = v0.dot(v2); |
|
|
float dot11 = v1.dot(v1); |
|
|
float dot12 = v1.dot(v2); |
|
|
|
|
|
|
|
|
float inverDeno; |
|
|
if(dot00*dot11 - dot01*dot01 == 0) |
|
|
inverDeno = 0; |
|
|
else |
|
|
inverDeno = 1/(dot00*dot11 - dot01*dot01); |
|
|
|
|
|
float u = (dot11*dot02 - dot01*dot12)*inverDeno; |
|
|
float v = (dot00*dot12 - dot01*dot02)*inverDeno; |
|
|
|
|
|
|
|
|
return (u >= 0) && (v >= 0) && (u + v < 1); |
|
|
} |
|
|
|
|
|
|
|
|
void get_point_weight(float* weight, point p, point p0, point p1, point p2) |
|
|
{ |
|
|
|
|
|
point v0, v1, v2; |
|
|
v0 = p2 - p0; |
|
|
v1 = p1 - p0; |
|
|
v2 = p - p0; |
|
|
|
|
|
|
|
|
float dot00 = v0.dot(v0); |
|
|
float dot01 = v0.dot(v1); |
|
|
float dot02 = v0.dot(v2); |
|
|
float dot11 = v1.dot(v1); |
|
|
float dot12 = v1.dot(v2); |
|
|
|
|
|
|
|
|
float inverDeno; |
|
|
if(dot00*dot11 - dot01*dot01 == 0) |
|
|
inverDeno = 0; |
|
|
else |
|
|
inverDeno = 1/(dot00*dot11 - dot01*dot01); |
|
|
|
|
|
float u = (dot11*dot02 - dot01*dot12)*inverDeno; |
|
|
float v = (dot00*dot12 - dot01*dot02)*inverDeno; |
|
|
|
|
|
|
|
|
weight[0] = 1 - u - v; |
|
|
weight[1] = v; |
|
|
weight[2] = u; |
|
|
} |
|
|
|
|
|
|
|
|
void _get_normal_core( |
|
|
float* normal, float* tri_normal, int* triangles, |
|
|
int ntri) |
|
|
{ |
|
|
int i, j; |
|
|
int tri_p0_ind, tri_p1_ind, tri_p2_ind; |
|
|
|
|
|
for(i = 0; i < ntri; i++) |
|
|
{ |
|
|
tri_p0_ind = triangles[3*i]; |
|
|
tri_p1_ind = triangles[3*i + 1]; |
|
|
tri_p2_ind = triangles[3*i + 2]; |
|
|
|
|
|
for(j = 0; j < 3; j++) |
|
|
{ |
|
|
normal[3*tri_p0_ind + j] = normal[3*tri_p0_ind + j] + tri_normal[3*i + j]; |
|
|
normal[3*tri_p1_ind + j] = normal[3*tri_p1_ind + j] + tri_normal[3*i + j]; |
|
|
normal[3*tri_p2_ind + j] = normal[3*tri_p2_ind + j] + tri_normal[3*i + j]; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void _rasterize_triangles_core( |
|
|
float* vertices, int* triangles, |
|
|
float* depth_buffer, int* triangle_buffer, float* barycentric_weight, |
|
|
int nver, int ntri, |
|
|
int h, int w) |
|
|
{ |
|
|
int i; |
|
|
int x, y, k; |
|
|
int tri_p0_ind, tri_p1_ind, tri_p2_ind; |
|
|
point p0, p1, p2, p; |
|
|
int x_min, x_max, y_min, y_max; |
|
|
float p_depth, p0_depth, p1_depth, p2_depth; |
|
|
float weight[3]; |
|
|
|
|
|
for(i = 0; i < ntri; i++) |
|
|
{ |
|
|
tri_p0_ind = triangles[3*i]; |
|
|
tri_p1_ind = triangles[3*i + 1]; |
|
|
tri_p2_ind = triangles[3*i + 2]; |
|
|
|
|
|
p0.x = vertices[3*tri_p0_ind]; p0.y = vertices[3*tri_p0_ind + 1]; p0_depth = vertices[3*tri_p0_ind + 2]; |
|
|
p1.x = vertices[3*tri_p1_ind]; p1.y = vertices[3*tri_p1_ind + 1]; p1_depth = vertices[3*tri_p1_ind + 2]; |
|
|
p2.x = vertices[3*tri_p2_ind]; p2.y = vertices[3*tri_p2_ind + 1]; p2_depth = vertices[3*tri_p2_ind + 2]; |
|
|
|
|
|
x_min = max((int)ceil(min(p0.x, min(p1.x, p2.x))), 0); |
|
|
x_max = min((int)floor(max(p0.x, max(p1.x, p2.x))), w - 1); |
|
|
|
|
|
y_min = max((int)ceil(min(p0.y, min(p1.y, p2.y))), 0); |
|
|
y_max = min((int)floor(max(p0.y, max(p1.y, p2.y))), h - 1); |
|
|
|
|
|
if(x_max < x_min || y_max < y_min) |
|
|
{ |
|
|
continue; |
|
|
} |
|
|
|
|
|
for(y = y_min; y <= y_max; y++) |
|
|
{ |
|
|
for(x = x_min; x <= x_max; x++) |
|
|
{ |
|
|
p.x = x; p.y = y; |
|
|
if(p.x < 2 || p.x > w - 3 || p.y < 2 || p.y > h - 3 || isPointInTri(p, p0, p1, p2)) |
|
|
{ |
|
|
get_point_weight(weight, p, p0, p1, p2); |
|
|
p_depth = weight[0]*p0_depth + weight[1]*p1_depth + weight[2]*p2_depth; |
|
|
|
|
|
if((p_depth > depth_buffer[y*w + x])) |
|
|
{ |
|
|
depth_buffer[y*w + x] = p_depth; |
|
|
triangle_buffer[y*w + x] = i; |
|
|
for(k = 0; k < 3; k++) |
|
|
{ |
|
|
barycentric_weight[y*w*3 + x*3 + k] = weight[k]; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void _render_colors_core( |
|
|
float* image, float* vertices, int* triangles, |
|
|
float* colors, |
|
|
float* depth_buffer, |
|
|
int nver, int ntri, |
|
|
int h, int w, int c) |
|
|
{ |
|
|
int i; |
|
|
int x, y, k; |
|
|
int tri_p0_ind, tri_p1_ind, tri_p2_ind; |
|
|
point p0, p1, p2, p; |
|
|
int x_min, x_max, y_min, y_max; |
|
|
float p_depth, p0_depth, p1_depth, p2_depth; |
|
|
float p_color, p0_color, p1_color, p2_color; |
|
|
float weight[3]; |
|
|
|
|
|
for(i = 0; i < ntri; i++) |
|
|
{ |
|
|
tri_p0_ind = triangles[3*i]; |
|
|
tri_p1_ind = triangles[3*i + 1]; |
|
|
tri_p2_ind = triangles[3*i + 2]; |
|
|
|
|
|
p0.x = vertices[3*tri_p0_ind]; p0.y = vertices[3*tri_p0_ind + 1]; p0_depth = vertices[3*tri_p0_ind + 2]; |
|
|
p1.x = vertices[3*tri_p1_ind]; p1.y = vertices[3*tri_p1_ind + 1]; p1_depth = vertices[3*tri_p1_ind + 2]; |
|
|
p2.x = vertices[3*tri_p2_ind]; p2.y = vertices[3*tri_p2_ind + 1]; p2_depth = vertices[3*tri_p2_ind + 2]; |
|
|
|
|
|
x_min = max((int)ceil(min(p0.x, min(p1.x, p2.x))), 0); |
|
|
x_max = min((int)floor(max(p0.x, max(p1.x, p2.x))), w - 1); |
|
|
|
|
|
y_min = max((int)ceil(min(p0.y, min(p1.y, p2.y))), 0); |
|
|
y_max = min((int)floor(max(p0.y, max(p1.y, p2.y))), h - 1); |
|
|
|
|
|
if(x_max < x_min || y_max < y_min) |
|
|
{ |
|
|
continue; |
|
|
} |
|
|
|
|
|
for(y = y_min; y <= y_max; y++) |
|
|
{ |
|
|
for(x = x_min; x <= x_max; x++) |
|
|
{ |
|
|
p.x = x; p.y = y; |
|
|
if(p.x < 2 || p.x > w - 3 || p.y < 2 || p.y > h - 3 || isPointInTri(p, p0, p1, p2)) |
|
|
{ |
|
|
get_point_weight(weight, p, p0, p1, p2); |
|
|
p_depth = weight[0]*p0_depth + weight[1]*p1_depth + weight[2]*p2_depth; |
|
|
|
|
|
if((p_depth > depth_buffer[y*w + x])) |
|
|
{ |
|
|
for(k = 0; k < c; k++) |
|
|
{ |
|
|
p0_color = colors[c*tri_p0_ind + k]; |
|
|
p1_color = colors[c*tri_p1_ind + k]; |
|
|
p2_color = colors[c*tri_p2_ind + k]; |
|
|
|
|
|
p_color = weight[0]*p0_color + weight[1]*p1_color + weight[2]*p2_color; |
|
|
image[y*w*c + x*c + k] = p_color; |
|
|
} |
|
|
|
|
|
depth_buffer[y*w + x] = p_depth; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void _render_texture_core( |
|
|
float* image, float* vertices, int* triangles, |
|
|
float* texture, float* tex_coords, int* tex_triangles, |
|
|
float* depth_buffer, |
|
|
int nver, int tex_nver, int ntri, |
|
|
int h, int w, int c, |
|
|
int tex_h, int tex_w, int tex_c, |
|
|
int mapping_type) |
|
|
{ |
|
|
int i; |
|
|
int x, y, k; |
|
|
int tri_p0_ind, tri_p1_ind, tri_p2_ind; |
|
|
int tex_tri_p0_ind, tex_tri_p1_ind, tex_tri_p2_ind; |
|
|
point p0, p1, p2, p; |
|
|
point tex_p0, tex_p1, tex_p2, tex_p; |
|
|
int x_min, x_max, y_min, y_max; |
|
|
float weight[3]; |
|
|
float p_depth, p0_depth, p1_depth, p2_depth; |
|
|
float xd, yd; |
|
|
float ul, ur, dl, dr; |
|
|
for(i = 0; i < ntri; i++) |
|
|
{ |
|
|
|
|
|
tri_p0_ind = triangles[3*i]; |
|
|
tri_p1_ind = triangles[3*i + 1]; |
|
|
tri_p2_ind = triangles[3*i + 2]; |
|
|
|
|
|
p0.x = vertices[3*tri_p0_ind]; p0.y = vertices[3*tri_p0_ind + 1]; p0_depth = vertices[3*tri_p0_ind + 2]; |
|
|
p1.x = vertices[3*tri_p1_ind]; p1.y = vertices[3*tri_p1_ind + 1]; p1_depth = vertices[3*tri_p1_ind + 2]; |
|
|
p2.x = vertices[3*tri_p2_ind]; p2.y = vertices[3*tri_p2_ind + 1]; p2_depth = vertices[3*tri_p2_ind + 2]; |
|
|
|
|
|
|
|
|
tex_tri_p0_ind = tex_triangles[3*i]; |
|
|
tex_tri_p1_ind = tex_triangles[3*i + 1]; |
|
|
tex_tri_p2_ind = tex_triangles[3*i + 2]; |
|
|
|
|
|
tex_p0.x = tex_coords[3*tex_tri_p0_ind]; tex_p0.y = tex_coords[3*tri_p0_ind + 1]; |
|
|
tex_p1.x = tex_coords[3*tex_tri_p1_ind]; tex_p1.y = tex_coords[3*tri_p1_ind + 1]; |
|
|
tex_p2.x = tex_coords[3*tex_tri_p2_ind]; tex_p2.y = tex_coords[3*tri_p2_ind + 1]; |
|
|
|
|
|
|
|
|
x_min = max((int)ceil(min(p0.x, min(p1.x, p2.x))), 0); |
|
|
x_max = min((int)floor(max(p0.x, max(p1.x, p2.x))), w - 1); |
|
|
|
|
|
y_min = max((int)ceil(min(p0.y, min(p1.y, p2.y))), 0); |
|
|
y_max = min((int)floor(max(p0.y, max(p1.y, p2.y))), h - 1); |
|
|
|
|
|
|
|
|
if(x_max < x_min || y_max < y_min) |
|
|
{ |
|
|
continue; |
|
|
} |
|
|
|
|
|
for(y = y_min; y <= y_max; y++) |
|
|
{ |
|
|
for(x = x_min; x <= x_max; x++) |
|
|
{ |
|
|
p.x = x; p.y = y; |
|
|
if(p.x < 2 || p.x > w - 3 || p.y < 2 || p.y > h - 3 || isPointInTri(p, p0, p1, p2)) |
|
|
{ |
|
|
get_point_weight(weight, p, p0, p1, p2); |
|
|
p_depth = weight[0]*p0_depth + weight[1]*p1_depth + weight[2]*p2_depth; |
|
|
|
|
|
if((p_depth > depth_buffer[y*w + x])) |
|
|
{ |
|
|
|
|
|
|
|
|
get_point_weight(weight, p, p0, p1, p2); |
|
|
|
|
|
tex_p = tex_p0*weight[0] + tex_p1*weight[1] + tex_p2*weight[2]; |
|
|
tex_p.x = max(min(tex_p.x, float(tex_w - 1)), float(0)); |
|
|
tex_p.y = max(min(tex_p.y, float(tex_h - 1)), float(0)); |
|
|
|
|
|
yd = tex_p.y - floor(tex_p.y); |
|
|
xd = tex_p.x - floor(tex_p.x); |
|
|
for(k = 0; k < c; k++) |
|
|
{ |
|
|
if(mapping_type==0) |
|
|
{ |
|
|
image[y*w*c + x*c + k] = texture[int(round(tex_p.y))*tex_w*tex_c + int(round(tex_p.x))*tex_c + k]; |
|
|
} |
|
|
else |
|
|
{ |
|
|
ul = texture[(int)floor(tex_p.y)*tex_w*tex_c + (int)floor(tex_p.x)*tex_c + k]; |
|
|
ur = texture[(int)floor(tex_p.y)*tex_w*tex_c + (int)ceil(tex_p.x)*tex_c + k]; |
|
|
dl = texture[(int)ceil(tex_p.y)*tex_w*tex_c + (int)floor(tex_p.x)*tex_c + k]; |
|
|
dr = texture[(int)ceil(tex_p.y)*tex_w*tex_c + (int)ceil(tex_p.x)*tex_c + k]; |
|
|
|
|
|
image[y*w*c + x*c + k] = ul*(1-xd)*(1-yd) + ur*xd*(1-yd) + dl*(1-xd)*yd + dr*xd*yd; |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
depth_buffer[y*w + x] = p_depth; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void _write_obj_with_colors_texture(string filename, string mtl_name, |
|
|
float* vertices, int* triangles, float* colors, float* uv_coords, |
|
|
int nver, int ntri, int ntexver) |
|
|
{ |
|
|
int i; |
|
|
|
|
|
ofstream obj_file(filename.c_str()); |
|
|
|
|
|
|
|
|
obj_file << "mtllib " << mtl_name << endl; |
|
|
|
|
|
|
|
|
for (i = 0; i < nver; ++i) |
|
|
{ |
|
|
obj_file << "v " << vertices[3*i] << " " << vertices[3*i + 1] << " " << vertices[3*i + 2] << colors[3*i] << " " << colors[3*i + 1] << " " << colors[3*i + 2] << endl; |
|
|
} |
|
|
|
|
|
|
|
|
for (i = 0; i < ntexver; ++i) |
|
|
{ |
|
|
|
|
|
obj_file << "vt " << uv_coords[2*i] << " " << uv_coords[2*i + 1] << endl; |
|
|
} |
|
|
|
|
|
obj_file << "usemtl FaceTexture" << endl; |
|
|
|
|
|
for (i = 0; i < ntri; ++i) |
|
|
{ |
|
|
|
|
|
obj_file << "f " << triangles[3*i + 2] << "/" << triangles[3*i + 2] << " " << triangles[3*i + 1] << "/" << triangles[3*i + 1] << " " << triangles[3*i] << "/" << triangles[3*i] << endl; |
|
|
} |
|
|
|
|
|
} |
|
|
|