//begin main function int main (void) { int xsize = 800, ysize = 800 ; gfx_open( xsize, ysize, "Test Graph of Function triangle_waveform" ) ; int stillgoing = 1; while (stillgoing) { gfx_clear() ; gfx_color(255, 255, 255) ; //axis is white draw_axes( xsize, ysize) ; gfx_color(150, 0, 255) ; plot_triangle(xsize, ysize, -10., 10, .1) ; gfx_flush() ; char c = gfx_wait() ; if (c == 'q') stillgoing = 0 ; } return 0 ; } //end main
/* Draw a set of 3D triangles on the canvas. Each point in geometry is * formatted (vx, vy, vz, nx, ny, nz, s, t). Don't forget to clip the * triangles against the clipping planes of the projection. You can't * just not render them because you'll get some weird popping at the * edge of the view. Also, this is where font/back face culling is implemented. */ void canvashdl::draw_triangles(const vector<vec8f> &geometry, const vector<int> &indices) { update_normal_matrix(); mat4f transform = matrices[projection_matrix]*matrices[modelview_matrix]; vec4f planes[6]; for (int i = 0; i < 6; i++) planes[i] = transform.row(3) + (float)pow(-1.0, i)*(vec4f)transform.row(i/2); vec3f eye = matrices[modelview_matrix].col(3)(0,3); vector<pair<vec3f, vector<float> > > processed_geometry; vector<int> processed_indices; processed_geometry.reserve(geometry.size()); processed_indices.reserve(indices.size()); vector<int> index_map; index_map.resize(geometry.size(), -1); for (int i = 0; i < indices.size(); i += 3) { vector<pair<vec8f, int> > polygon; for (int j = 0; j < 3; j++) polygon.push_back(pair<vec8f, int>(geometry[indices[i+j]], indices[i+j])); vector<pair<vec8f, int> > clipped; for (int j = 0; j < 6; j++) { pair<vec8f, int> x0 = polygon[polygon.size()-1]; float d0 = dot(homogenize(x0.first), planes[j]); for (int k = 0; k < polygon.size(); k++) { pair<vec8f, int> x1 = polygon[k]; float d1 = dot(homogenize(x1.first), planes[j]); float del = dot(homogenize(x1.first) - homogenize(x0.first), planes[j]); float p = -d0/del; if (d0 >= 0.0 && d1 >= 0.0) clipped.push_back(x1); else if (d0 >= 0.0 && d1 < 0.0) clipped.push_back(pair<vec8f, int>((1-(p+0.001f))*x0.first + (p+0.001f)*x1.first, -1)); else if (d0 < 0.0 && d1 >= 0.0) { clipped.push_back(pair<vec8f, int>((1-(p-0.001f))*x0.first + (p-0.001f)*x1.first, -1)); clipped.push_back(x1); } x0 = x1; d0 = d1; } polygon = clipped; clipped.clear(); } if (polygon.size() > 2) { for (int i = 0; i < polygon.size(); i++) { vector<float> varying; vec3f position; if (polygon[i].second == -1) { polygon[i].second = processed_geometry.size(); position = matrices[viewport_matrix]*homogenize(shade_vertex(polygon[i].first, varying)); polygon[i].first = position; processed_geometry.push_back(pair<vec3f, vector<float> >(position, varying)); } else if (index_map[polygon[i].second] == -1) { index_map[polygon[i].second] = processed_geometry.size(); polygon[i].second = processed_geometry.size(); position = matrices[viewport_matrix]*homogenize(shade_vertex(polygon[i].first, varying)); polygon[i].first = position; processed_geometry.push_back(pair<vec3f, vector<float> >(position, varying)); } else { polygon[i].second = index_map[polygon[i].second]; polygon[i].first = processed_geometry[polygon[i].second].first; } } for (int i = 2; i < polygon.size(); i++) { vec3f normal = cross(norm((vec3f)polygon[0].first - (vec3f)polygon[i-1].first), norm((vec3f)polygon[i].first - (vec3f)polygon[i-1].first)); if (culling == disable || (normal[2] >= 0.0 && culling == backface) || (normal[2] <= 0.0 && culling == frontface)) { processed_indices.push_back(polygon[0].second); processed_indices.push_back(polygon[i-1].second); processed_indices.push_back(polygon[i].second); } } } } for (int i = 2; i < processed_indices.size(); i+=3) plot_triangle(processed_geometry[processed_indices[i-2]].first, processed_geometry[processed_indices[i-2]].second, processed_geometry[processed_indices[i-1]].first, processed_geometry[processed_indices[i-1]].second, processed_geometry[processed_indices[i]].first, processed_geometry[processed_indices[i]].second); }