//////////////////////////////////////// //// Metadata //////////////////////////////////////// VideoMetadata::SortKey VideoMetadata::GenerateDefaultSortKey(const VideoMetadata &m, bool ignore_case) { QString title(ignore_case ? m.GetTitle().toLower() : m.GetTitle()); title = TrimTitle(title, ignore_case); return SortKey(SortData(title, m.GetFilename(), QString().sprintf("%.7d", m.GetID()))); }
SortKey Renderer::CreateSortKey(float depth, Material* material, uint8_t pass) { uint32_t materialId; auto iter = _materialMap.find(material); if (iter == _materialMap.end()) { materialId = _lastMaterialId++; //Add to the hashmap for later _materialMap.insert( std::pair<Material*, uint32_t>(material, materialId)); } else { //It already exists, use the existing ID materialId = iter->second; } return SortKey(material->blendType, depth, materialId, pass); }
// Build a ragged TabVector by copying another's direction, shifting it // to match the given blob, and making its initial extent the height // of the blob, but its extended bounds from the bounds of the original. TabVector::TabVector(const TabVector& src, TabAlignment alignment, const ICOORD& vertical_skew, BLOBNBOX* blob) : extended_ymin_(src.extended_ymin_), extended_ymax_(src.extended_ymax_), sort_key_(0), percent_score_(0), mean_width_(0), needs_refit_(true), needs_evaluation_(true), intersects_other_lines_(false), alignment_(alignment), top_constraints_(NULL), bottom_constraints_(NULL) { BLOBNBOX_C_IT it(&boxes_); it.add_to_end(blob); TBOX box = blob->bounding_box(); if (IsLeftTab()) { startpt_ = box.botleft(); endpt_ = box.topleft(); } else { startpt_ = box.botright(); endpt_ = box.topright(); } sort_key_ = SortKey(vertical_skew, (startpt_.x() + endpt_.x()) / 2, (startpt_.y() + endpt_.y()) / 2); if (textord_debug_tabfind > 3) Print("Constructed a new tab vector:"); }
// (Re)Fit a line to the stored points. Returns false if the line // is degenerate. Althougth the TabVector code mostly doesn't care about the // direction of lines, XAtY would give silly results for a horizontal line. // The class is mostly aimed at use for vertical lines representing // horizontal tab stops. bool TabVector::Fit(ICOORD vertical, bool force_parallel) { needs_refit_ = false; if (boxes_.empty()) { // Don't refit something with no boxes, as that only happens // in Evaluate, and we don't want to end up with a zero vector. if (!force_parallel) return false; // If we are forcing parallel, then we just need to set the sort_key_. ICOORD midpt = startpt_; midpt += endpt_; midpt /= 2; sort_key_ = SortKey(vertical, midpt.x(), midpt.y()); return startpt_.y() != endpt_.y(); } if (!force_parallel && !IsRagged()) { // Use a fitted line as the vertical. DetLineFit linepoints; BLOBNBOX_C_IT it(&boxes_); // Fit a line to all the boxes in the list. for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) { BLOBNBOX* bbox = it.data(); TBOX box = bbox->bounding_box(); int x1 = IsRightTab() ? box.right() : box.left(); ICOORD boxpt(x1, box.bottom()); linepoints.Add(boxpt); if (it.at_last()) { ICOORD top_pt(x1, box.top()); linepoints.Add(top_pt); } } linepoints.Fit(&startpt_, &endpt_); if (startpt_.y() != endpt_.y()) { vertical = endpt_; vertical -= startpt_; } } int start_y = startpt_.y(); int end_y = endpt_.y(); sort_key_ = IsLeftTab() ? MAX_INT32 : -MAX_INT32; BLOBNBOX_C_IT it(&boxes_); // Choose a line parallel to the vertical such that all boxes are on the // correct side of it. mean_width_ = 0; int width_count = 0; for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) { BLOBNBOX* bbox = it.data(); TBOX box = bbox->bounding_box(); mean_width_ += box.width(); ++width_count; int x1 = IsRightTab() ? box.right() : box.left(); // Test both the bottom and the top, as one will be more extreme, depending // on the direction of skew. int bottom_y = box.bottom(); int top_y = box.top(); int key = SortKey(vertical, x1, bottom_y); if (IsLeftTab() == (key < sort_key_)) { sort_key_ = key; startpt_ = ICOORD(x1, bottom_y); } key = SortKey(vertical, x1, top_y); if (IsLeftTab() == (key < sort_key_)) { sort_key_ = key; startpt_ = ICOORD(x1, top_y); } if (it.at_first()) start_y = bottom_y; if (it.at_last()) end_y = top_y; } if (width_count > 0) { mean_width_ = (mean_width_ + width_count - 1) / width_count; } endpt_ = startpt_ + vertical; needs_evaluation_ = true; if (start_y != end_y) { // Set the ends of the vector to fully include the first and last blobs. startpt_.set_x(XAtY(vertical, sort_key_, start_y)); startpt_.set_y(start_y); endpt_.set_x(XAtY(vertical, sort_key_, end_y)); endpt_.set_y(end_y); return true; } return false; }
void Application::RenderDeferred() { _renderer.SetProjectionMatrix(Matrix4x4::Perspective(65, 16.0f / 9.0f, 0.01f, 1000)); _renderer.SetViewMatrix(_camera.GetViewMatrix()); _renderer.SetEyePosition(_camera.GetPosition()); for (auto& entity : _entities) { //Update sort key entity.sortKey.UpdateDepth( Vector3::DistanceSqr(_camera.GetPosition(), entity.position)); entity.sortKey.UpdatePass(0); //Construct draw call DrawCall drawCall; entity.mesh->FillDrawCall(drawCall); drawCall.pass = 0; drawCall.material = entity.deferredMaterial; drawCall.modelMatrix = Matrix4x4::FromTransform( entity.position, entity.rotation, Vector3(entity.scale)); _renderer.Submit(entity.sortKey, drawCall); } //Render to GBuffer _gbuffer.framebuffer.Start(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_CULL_FACE); _renderer.Draw(); _gbuffer.framebuffer.Stop(); //Render contents of GBuffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_CULL_FACE); Light ambientLight; ambientLight.Ambient(ambient); DrawCall drawCall; _quad.FillDrawCall(drawCall); drawCall.material = &_deferredLightMaterial; drawCall.modelMatrix = Matrix4x4(); drawCall.light = &ambientLight; drawCall.pass = 1; //Additive _renderer.Submit(SortKey(), drawCall); for (Light& light : _lights) { DrawCall drawCall; _quad.FillDrawCall(drawCall); drawCall.material = &_deferredLightMaterial; drawCall.modelMatrix = Matrix4x4(); drawCall.light = &light; drawCall.pass = 1; //Additive _renderer.Submit(SortKey(), drawCall); } _renderer.Draw(); }