void read_patches(const char* filename, vector<BezierPatch>& patches, bool flip_surface) { vector<int> indices; vector<vec3> points; FILE* file = fopen(filename, "r"); if (!file) { cerr << "Can't open " << filename << endl; exit(1); } int np, nv; int r = fscanf(file, "%i\n", &np); indices.resize(np * 16); for (int i = 0; i < np; ++i) { int *p = &(indices[i*16]); if (!flip_surface) { r = fscanf(file, "%i, %i, %i, %i,", p+ 0, p+ 1, p+ 2, p+ 3); r = fscanf(file, "%i, %i, %i, %i,", p+ 4, p+ 5, p+ 6, p+ 7); r = fscanf(file, "%i, %i, %i, %i,", p+ 8, p+ 9, p+10, p+11); r = fscanf(file, "%i, %i, %i, %i\n", p+12, p+13, p+14, p+15); } else { r = fscanf(file, "%i, %i, %i, %i,", p+ 0, p+ 4, p+ 8, p+12); r = fscanf(file, "%i, %i, %i, %i,", p+ 1, p+ 5, p+ 9, p+13); r = fscanf(file, "%i, %i, %i, %i,", p+ 2, p+ 6, p+10, p+14); r = fscanf(file, "%i, %i, %i, %i\n", p+ 3, p+ 7, p+11, p+15); } } BBox bbox; r= fscanf(file, "%i\n", &nv); points.resize(nv); for (int i = 0; i < nv; ++i) { float x,y,z; r= fscanf(file, "%f, %f, %f\n", &x, &y, &z); points[i] = vec3(x,y,z); bbox.add_point(vec3(x,y,z)); } vec3 center = bbox.center(); for (int i = 0; i < nv; ++i) { points[i] -= center; } patches.resize(np); int k = 0; for (int i = 0; i < np; ++i) { vec3* ps = patches[i].P[0]; for (int j = 0; j < 16; ++j) { ps[j] = points[indices[k]-1]; ++k; } } }
void GPUFont::renderCentered(const wchar_t * str, const Nimble::Matrix3 & transform) { BBox bb; cpuFont()->bbox(str, bb); Nimble::Vector2 center = bb.center(); render(str, transform * Nimble::Matrix3::translate2D(-center.x, center.y)); }
void GPUFont::renderCentered(const char * str, float x, float y) { BBox bb; cpuFont()->bbox(str, bb); // usually bb.low() != (0,0) Nimble::Vector2 offset = bb.center(); render(str, x - offset.x, y + offset.y); }
static void draw_statbar_with_text(GameState* gs, const BBox& bbox, int statmin, int statmax, Colour statcol, Colour backcol, Colour textcol = Colour(0, 0, 0)) { draw_statbar(bbox, float(statmin) / statmax, statcol, backcol); using namespace ldraw; const Font& font = gs->font(); font.drawf(DrawOptions(CENTER, textcol), bbox.center(), "%d/%d", statmin, statmax); }
Vec3f Grid::moveDeltaForBounds(const Model::Face& face, const BBox& bounds, const BBox& worldBounds, const Ray& ray, const Vec3f& position) const { const Plane dragPlane = Plane::alignedOrthogonalDragPlane(position, face.boundary().normal); const Vec3f halfSize = bounds.size() * 0.5f; float offsetLength = halfSize.dot(dragPlane.normal); if (offsetLength < 0.0f) offsetLength *= -1.0f; const Vec3f offset = dragPlane.normal * offsetLength; const float dist = dragPlane.intersectWithRay(ray); const Vec3f newPos = ray.pointAtDistance(dist); Vec3f delta = moveDeltaForPoint(bounds.center(), worldBounds, newPos - (bounds.center() - offset)); Axis::Type a = dragPlane.normal.firstComponent(); if (dragPlane.normal[a] > 0.0f) delta[a] = position[a] - bounds.min[a]; else delta[a] = position[a] - bounds.max[a]; return delta; }
float LightTree::node_prob(const LightQuery& lq, uint32_t index) const { const BBox bbox = lerp_seq(lq.time, nodes[index].bounds); const Vec3 d = bbox.center() - lq.pos; const float dist2 = d.length2(); const float r = bbox.diagonal() * 0.5f; const float r2 = r * r; const float inv_surface_area = 1.0f / r2; float cos_theta_max; if (dist2 <= r2) { cos_theta_max = -1.0f; } else { const float sin_theta_max2 = std::min(1.0f, r2 / dist2); cos_theta_max = std::sqrt(1.0f - sin_theta_max2); } // Get the approximate amount of light contribution from the // composite light source. const float approx_contrib = std::max(0.0f, lq.bsdf->estimate_eval_over_solid_angle(lq.d, d, cos_theta_max, lq.nor, lq.wavelength)); return nodes[index].energy * inv_surface_area * approx_contrib; }
Vec3f Grid::referencePoint(const BBox& bounds) { return snap(bounds.center()); }