void convex::gl_render(view& scene) { if (degenerate()) return; long check = checksum(); if (check != last_checksum) { recalc(); last_checksum = check; } glShadeModel(GL_FLAT); gl_enable cull_face( GL_CULL_FACE); color.gl_set(1.0); glBegin(GL_TRIANGLES); for (std::vector<face>::const_iterator f = hull.begin(); f != hull.end(); ++f) { f->normal.gl_normal(); (f->corner[0] * scene.gcf).gl_render(); (f->corner[1] * scene.gcf).gl_render(); (f->corner[2] * scene.gcf).gl_render(); } glEnd(); glShadeModel( GL_SMOOTH); }
void cone::grow_extent( extent& e) { if (degenerate()) return; e.add_circle( pos, axis.norm(), radius ); e.add_point( pos + axis); e.add_body(); }
void cone::gl_render(view& scene) { if (degenerate()) return; init_model(scene); clear_gl_error(); // See sphere::gl_render() for a description of the level of detail calc. double coverage = scene.pixel_coverage( pos, radius); int lod = 0; if (coverage < 0) lod = 5; else if (coverage < 10) lod = 0; else if (coverage < 30) lod = 1; else if (coverage < 90) lod = 2; else if (coverage < 250) lod = 3; else if (coverage < 450) lod = 4; else lod = 5; lod += scene.lod_adjust; if (lod < 0) lod = 0; else if (lod > 5) lod = 5; gl_matrix_stackguard guard; const double length = axis.mag(); model_world_transform( scene.gcf, vector( length, radius, radius ) ).gl_mult(); color.gl_set(opacity); if (translucent()) { gl_enable cull_face( GL_CULL_FACE); // Render the back half. glCullFace( GL_FRONT); scene.cone_model[lod].gl_render(); // Render the front half. glCullFace( GL_BACK); scene.cone_model[lod].gl_render(); } else { scene.cone_model[lod].gl_render(); } check_gl_error(); }
void cylinder::grow_extent( extent& e) { if (degenerate()) return; vector a = axis.norm(); e.add_circle(pos, a, radius); e.add_circle(pos+axis, a, radius); e.add_body(); }
void sphere::gl_render( view& geometry) { if (degenerate()) return; //init_model(); init_model(geometry); // coverage is the radius of this sphere in pixels: double coverage = geometry.pixel_coverage( pos, radius); int lod = 0; if (coverage < 0) // Behind the camera, but still visible. lod = 4; else if (coverage < 30) lod = 0; else if (coverage < 100) lod = 1; else if (coverage < 500) lod = 2; else if (coverage < 5000) lod = 3; else lod = 4; lod += geometry.lod_adjust; // allow user to reduce level of detail if (lod > 5) lod = 5; else if (lod < 0) lod = 0; gl_matrix_stackguard guard; model_world_transform( geometry.gcf, get_scale() ).gl_mult(); color.gl_set(opacity); if (translucent()) { // Spheres are convex, so we don't need to sort gl_enable cull_face( GL_CULL_FACE); // Render the back half (inside) glCullFace( GL_FRONT ); geometry.sphere_model[lod].gl_render(); // Render the front half (outside) glCullFace( GL_BACK ); geometry.sphere_model[lod].gl_render(); } else { // Render a simple sphere. geometry.sphere_model[lod].gl_render(); } }
void ellipsoid::grow_extent( extent& world) { if (degenerate()) return; //world.add_sphere( pos, std::max( width, std::max( height, axis.mag()))); // TODO: not accurate (overestimates extent) vector s = vector(axis.mag(),height,width)*0.5; world.add_box( model_world_transform(1.0), -s, s ); world.add_body(); }
void sphere::gl_pick_render( view& geometry) { if (degenerate()) return; //init_model(); init_model(geometry); gl_matrix_stackguard guard; model_world_transform( geometry.gcf, get_scale() ).gl_mult(); geometry.sphere_model[0].gl_render(); //check_gl_error(); }
vector convex::get_center() const { if (degenerate()) return vector(); vector ret; for (std::vector<face>::const_iterator f = hull.begin(); f != hull.end(); ++f) { ret += f->center; } ret /= hull.empty() ? 1 : hull.size(); return ret; }
void arrow::gl_render( const view& scene) { if (degenerate()) return; init_model(); color.gl_set(opacity); double hl,hw,len,sw; effective_geometry( hw, sw, len, hl, 1.0 ); int model_material_loc = mat && mat->get_shader_program() ? mat->get_shader_program()->get_uniform_location( scene, "model_material" ) : -1; // Render the shaft and the head in back to front order (the shaft is in front // of the head if axis points away from the camera) int shaft = axis.dot( scene.camera - (pos + axis * (1-hl/len)) ) < 0; for(int part=0; part<2; part++) { gl_matrix_stackguard guard; model_world_transform( scene.gcf ).gl_mult(); if (part == shaft) { glScaled( len - hl, sw, sw ); glTranslated( 0.5, 0, 0 ); if (model_material_loc >= 0) { // TODO simplify tmatrix model_mat; double s = 1.0 / std::max( len, hw ); model_mat.translate( vector((len-hl)*s*0.5,0.5,0.5) ); model_mat.scale( vector((len-hl), sw, sw)*s ); mat->get_shader_program()->set_uniform_matrix( scene, model_material_loc, model_mat ); } shaft_model.gl_render(); } else { glTranslated( len - hl, 0, 0 ); glScaled( hl, hw, hw ); if (model_material_loc >= 0) { // TODO simplify tmatrix model_mat; double s = 1.0 / std::max( len, hw ); model_mat.translate( vector((len-hl)*s,0.5,0.5) ); model_mat.scale( vector(hl, hw, hw)*s ); mat->get_shader_program()->set_uniform_matrix( scene, model_material_loc, model_mat ); } pyramid::model.gl_render(); } } }
bool GjkCollisionState::intersect(const MatrixF& a2w, const MatrixF& b2w) { num_iterations = 0; MatrixF w2a,w2b; w2a = a2w; w2b = b2w; w2a.inverse(); w2b.inverse(); reset(a2w,b2w); bits = 0; all_bits = 0; do { nextBit(); VectorF va,sa; w2a.mulV(-v,&va); p[last] = a->support(va); a2w.mulP(p[last],&sa); VectorF vb,sb; w2b.mulV(v,&vb); q[last] = b->support(vb); b2w.mulP(q[last],&sb); VectorF w = sa - sb; if (mDot(v,w) > 0) return false; if (degenerate(w)) { ++num_irregularities; return false; } y[last] = w; all_bits = bits | last_bit; ++num_iterations; if (!closest(v) || num_iterations > sIteration) { ++num_irregularities; return false; } } while (bits < 15 && v.lenSquared() > sEpsilon2); return true; }
void cone::gl_pick_render(view& scene) { if (degenerate()) return; init_model(scene); size_t lod = 2; clear_gl_error(); gl_matrix_stackguard guard; const double length = axis.mag(); model_world_transform( scene.gcf, vector( length, radius, radius ) ).gl_mult(); scene.cone_model[lod].gl_render(); check_gl_error(); }
void arrow::grow_extent( extent& world) { if (degenerate()) return; double hl, hw, len, sw; effective_geometry( hw, sw, len, hl, 1.0); vector x = axis.cross(up).norm() * 0.5; vector y = axis.cross(x).norm() * 0.5; vector base = pos + axis.norm()*(len-hl); for(int i=-1; i<=+1; i+=2) for(int j=-1; j<=+1; j+=2) { world.add_point( pos + x*(i*sw) + y*(j*sw) ); world.add_point( base + x*(i*hw) + y*(j*hw) ); } world.add_point( pos + axis); world.add_body(); }
void convex::grow_extent( extent& world) { if (degenerate()) return; long check = checksum(); if (check != last_checksum) { recalc(); } assert( hull.size() != 0); for (std::vector<face>::const_iterator f = hull.begin(); f != hull.end(); ++f) { world.add_point( f->corner[0]); world.add_point( f->corner[1]); world.add_point( f->corner[2]); } world.add_body(); }
F32 GjkCollisionState::distance(const MatrixF& a2w, const MatrixF& b2w, const F32 dontCareDist, const MatrixF* _w2a, const MatrixF* _w2b) { num_iterations = 0; MatrixF w2a,w2b; if (_w2a == NULL || _w2b == NULL) { w2a = a2w; w2b = b2w; w2a.inverse(); w2b.inverse(); } else { w2a = *_w2a; w2b = *_w2b; } reset(a2w,b2w); bits = 0; all_bits = 0; F32 mu = 0; do { nextBit(); VectorF va,sa; w2a.mulV(-v,&va); p[last] = a->support(va); a2w.mulP(p[last],&sa); VectorF vb,sb; w2b.mulV(v,&vb); q[last] = b->support(vb); b2w.mulP(q[last],&sb); VectorF w = sa - sb; F32 nm = mDot(v, w) / dist; if (nm > mu) mu = nm; if (mu > dontCareDist) return mu; if (mFabs(dist - mu) <= dist * rel_error) return dist; ++num_iterations; if (degenerate(w) || num_iterations > sIteration) { ++num_irregularities; return dist; } y[last] = w; all_bits = bits | last_bit; if (!closest(v)) { ++num_irregularities; return dist; } dist = v.len(); } while (bits < 15 && dist > sTolerance) ; if (bits == 15 && mu <= 0) dist = 0; return dist; }
void generate_terrain_points(density_func_t function, float3 min, float3 max, float granularity, std::vector<float3>& vertices) { const float inv_gran = 1.0f/granularity; // Calculate the grid size int32_t x_size = (int32_t)((max.x - min.x) * inv_gran) + 1; int32_t y_size = (int32_t)((max.y - min.y) * inv_gran) + 1; int32_t z_size = (int32_t)((max.z - min.z) * inv_gran) + 1; uint32_t grid_size = x_size * y_size * z_size; #define ARRAY_INDEX(_x,_y,_z) ((_z)*x_size*y_size + (_y)*x_size + (_x)) float4* grid = (float4*)calloc(grid_size, sizeof(float4)); float xf, yf, zf; int xi, yi, zi; for(zf = min.z, zi = 0; zi < z_size; ++zi, zf += granularity) { for(yf = min.y, yi = 0; yi < y_size; ++yi, yf += granularity) { for(xf = min.x, xi = 0; xi < x_size; ++xi, xf += granularity) { float4 pt = { xf, yf, zf, 0.0f }; pt.w = function(*(float3*)&pt); grid[ARRAY_INDEX(xi,yi,zi)] = pt; } } } for(zi = 0; zi < z_size-1; ++zi) { for(yi = 0; yi < y_size-1; ++yi) { for(xi = 0; xi < x_size-1; ++xi) { gridcell_t cell; float4 val; int ii=0; // Get the cell corners val = grid[ARRAY_INDEX(xi, yi, zi)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi+1, yi, zi)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi+1, yi, zi+1)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi, yi, zi+1)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi, yi+1, zi)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi+1, yi+1, zi)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi+1, yi+1, zi+1)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi, yi+1, zi+1)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; // Polygonize the cell triangle_t triangles[5]; int num_triangles = Polygonise(cell, 0.0f, triangles); for(ii=0;ii<num_triangles;++ii) { triangle_t tri = triangles[ii]; if(degenerate(tri)) continue; for(int jj=2; jj>=0; --jj) { vertices.push_back(tri.p[jj]); } } } } } free(grid); }