/* draw_points * * Draw a set of 3D points on the canvas. Each point in geometry is * formatted (vx, vy, vz, nx, ny, nz, s, t). Don't forget to test the * points against the clipping plains of the projection. If you don't * you'll get weird behavior (especially when objects behind the camera * are being rendered). */ void canvashdl::draw_points(const vector<vec8f> &geometry) { 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); vector<pair<vec3f, vector<float> > > processed_geometry; processed_geometry.reserve(geometry.size()); for (int i = 0; i < geometry.size(); i += 3) { bool keep = true; for (int j = 0; j < 6 && keep; j++) if (dot(homogenize((vec3f)geometry[i]), planes[j]) <= 0) keep = false; if (keep) { vector<float> varying; vec3f position = matrices[viewport_matrix]*homogenize(shade_vertex(geometry[i], varying)); processed_geometry.push_back(pair<vec3f, vector<float> >(position, varying)); } } for (int i = 0; i < processed_geometry.size(); i++) plot_point(processed_geometry[i].first, processed_geometry[i].second); }
MatrixX<ElementType> projective_transform( const MatrixX<ElementType>& image, const Matrix33d& transform, const ElementType fill_value = ElementType(0)) { // 1. Figure out sizes of new matrix auto c0 = homogenize(transform * Vector3d{-0.5, -0.5, 1}); auto c1 = homogenize(transform * Vector3d{-0.5, image.dims[0] - 0.5, 1}); auto c2 = homogenize(transform * Vector3d{image.dims[1] - 0.5, -0.5, 1}); auto c3 = homogenize(transform * Vector3d{image.dims[1] - 0.5, image.dims[0] - 0.5, 1}); // Raise or lower values as needed auto xs = Vector4d{c0[0], c1[0], c2[0], c3[0]}; auto ys = Vector4d{c0[1], c1[1], c2[1], c3[1]}; // Create new matrix Matrix33d inverse = inv(transform); MatrixX<ElementType> new_image(int32_t(ys.max() - ys.min()), int32_t(xs.max() - xs.min())); // Do interpolation for each output pixel Interpolator interp; for (int32_t i = 0; i < new_image.dims[0]; ++i) { for (int32_t j = 0; j < new_image.dims[1]; ++j) { Vector3d uv{j + xs.min(), i + ys.min(), 1}; Vector3d xy = homogenize(inverse * uv); new_image(i, j) = interp(image, xy[0], xy[1], fill_value); } } return new_image; }
static Matrix *Polyhedron2standard_form(Polyhedron *P, Matrix **T) { int i, j; int rows; unsigned dim = P->Dimension; Matrix *M2; Matrix *H, *U; Matrix M; assert(P->NbEq == 0); Polyhedron_Remove_Positivity_Constraint(P); for (i = 0; i < P->NbConstraints; ++i) assert(value_zero_p(P->Constraint[i][1+dim])); Polyhedron_Matrix_View(P, &M, P->NbConstraints); H = standard_constraints(&M, 0, &rows, &U); *T = homogenize(U); Matrix_Free(U); M2 = Matrix_Alloc(rows, 2+dim+rows); for (i = dim; i < H->NbRows; ++i) { Vector_Copy(H->p[i], M2->p[i-dim]+1, dim); value_set_si(M2->p[i-dim][1+i], -1); } for (i = 0, j = H->NbRows-dim; i < dim; ++i) { if (First_Non_Zero(H->p[i], i) == -1) continue; Vector_Oppose(H->p[i], M2->p[j]+1, dim); value_set_si(M2->p[j][1+j+dim], 1); ++j; } Matrix_Free(H); return M2; }
int main(const int argc, const char** argv) { double tstart1, tstop1, tstart2, tstop2, tstartall, tstopall; // start clocking tstartall = (double)clock()/(double)CLOCKS_PER_SEC; // mi will be the cards of the support sets and m is the total card std::vector<int> mi; int m; // construct an empty pointset and an index std::vector<std::vector<Field> > pointset; map<std::vector<Field>,int> points_index; //read input (points, mi, m), apply cayley trick // (now you have the pointset), make the index cayley_trick(pointset, points_index, mi, m); // compute the big matrix // BUT first homogenize the pointset, dirty way.. vector<vector<Field> > homo_pointset; homogenize(pointset,homo_pointset); std::cout << homo_pointset << std::endl; HD dets(homo_pointset.begin(),homo_pointset.end()); //define the projection vector<int> proj = proj_first_coord(PD,m,mi); // the data structure to hold the res polytope int numof_triangs=0, numof_init_Res_vertices; Convex_hull_d CH(PD); //compute the res polytope compute_res(pointset,points_index,m,mi,proj,dets,numof_triangs, numof_init_Res_vertices,CH); //compute_res_fast(pointset,points_index,m,mi,proj,dets,numof_triangs, numof_init_Res_vertices,CH); // stop clocking tstopall = (double)clock()/(double)CLOCKS_PER_SEC; // print the vertices of the res polytope for (Vertex_iterator_d vit = CH.vertices_begin(); vit != CH.vertices_end(); vit++) std::cout << vit->point() << " "; std::cout << std::endl; // print some statistics print_statistics(numof_triangs, numof_init_Res_vertices, CH.number_of_vertices(), tstopall-tstartall); return 0; }
/* 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); }
/* Draw a set of 3D lines on the canvas. Each point in geometry * is formatted (vx, vy, vz, nx, ny, nz, s, t). Don't forget to clip * the lines 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. */ void canvashdl::draw_lines(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); 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 += 2) { pair<vec8f, int> x0 = pair<vec8f, int>(geometry[indices[i]], indices[i]); pair<vec8f, int> x1 = pair<vec8f, int>(geometry[indices[i+1]], indices[i+1]); bool keep = true; for (int j = 0; j < 6 && keep; j++) { float d0 = dot(homogenize(x0.first), planes[j]); 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) { x1.first = (1-p)*x0.first + p*x1.first; x1.second = -1; } else if (d0 <= 0.0 && d1 > 0.0) { x0.first = (1-p)*x0.first + p*x1.first; x0.second = -1; } else if (d0 <= 0.0 && d1 <= 0.0) keep = false; } if (keep) { vector<float> varying; vec3f position; if (x0.second == -1) { x0.second = processed_geometry.size(); position = matrices[viewport_matrix]*homogenize(shade_vertex(x0.first, varying)); processed_geometry.push_back(pair<vec3f, vector<float> >(position, varying)); } else if (index_map[x0.second] == -1) { index_map[x0.second] = processed_geometry.size(); x0.second = processed_geometry.size(); position = matrices[viewport_matrix]*homogenize(shade_vertex(x0.first, varying)); processed_geometry.push_back(pair<vec3f, vector<float> >(position, varying)); } else x0.second = index_map[x0.second]; if (x1.second == -1) { x1.second = processed_geometry.size(); position = matrices[viewport_matrix]*homogenize(shade_vertex(x1.first, varying)); processed_geometry.push_back(pair<vec3f, vector<float> >(position, varying)); } else if (index_map[x1.second] == -1) { index_map[x1.second] = processed_geometry.size(); x1.second = processed_geometry.size(); position = matrices[viewport_matrix]*homogenize(shade_vertex(x1.first, varying)); processed_geometry.push_back(pair<vec3f, vector<float> >(position, varying)); } else x1.second = index_map[x1.second]; processed_indices.push_back(x0.second); processed_indices.push_back(x1.second); } } for (int i = 1; i < processed_indices.size(); i+=2) plot_line(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); }
/* unproject * * Unproject a window coordinate into world coordinates. */ vec3f canvashdl::unproject(vec3f window) { return inverse(matrices[modelview_matrix])*inverse(matrices[projection_matrix])*homogenize(window); }
vector<Point2f> CoordHomogenization::homogenize(const vector<Point2f>& pts) const { vector<Point2f> retval(pts.size()); std::transform(begin(pts), end(pts), begin(retval), [this](const Point2f& _){return homogenize(_);} ); return retval; }