// swaps every time (keeps all values visible) void BinaryInsertionSort(SortArray& A) { for (size_t i = 1; i < A.size(); ++i) { value_type key = A[i]; A.mark(i); int lo = 0, hi = i; while (lo < hi) { int mid = (lo + hi) / 2; if (key <= A[mid]) hi = mid; else lo = mid + 1; } // item has to go into position lo ssize_t j = i - 1; while (j >= lo) { A.swap(j, j+1); j--; } A.unmark(i); } }
void ScriptDebuggerLocal::profiling_end() { int ofs = 0; for (int i = 0; i < ScriptServer::get_language_count(); i++) { ofs += ScriptServer::get_language(i)->profiling_get_accumulated_data(&pinfo[ofs], pinfo.size() - ofs); } SortArray<ScriptLanguage::ProfilingInfo, _ScriptDebuggerLocalProfileInfoSort> sort; sort.sort(pinfo.ptr(), ofs); uint64_t total_us = 0; for (int i = 0; i < ofs; i++) { total_us += pinfo[i].self_time; } float total_time = total_us / 1000000.0; for (int i = 0; i < ofs; i++) { print_line(itos(i) + ":" + pinfo[i].signature); float tt = USEC_TO_SEC(pinfo[i].total_time); float st = USEC_TO_SEC(pinfo[i].self_time); print_line("\ttotal_ms: " + rtos(tt) + "\tself_ms: " + rtos(st) + "total%: " + itos(tt * 100 / total_time) + "\tself%: " + itos(st * 100 / total_time) + "\tcalls: " + itos(pinfo[i].call_count)); } for (int i = 0; i < ScriptServer::get_language_count(); i++) { ScriptServer::get_language(i)->profiling_stop(); } profiling = false; }
void CombSort(SortArray& A) { const double shrink = 1.3; bool swapped = false; size_t gap = A.size(); while ((gap > 1) || swapped) { if (gap > 1) { gap = (size_t)((float)gap / shrink); } swapped = false; for (size_t i = 0; gap + i < A.size(); ++i) { if (A[i] > A[i + gap]) { A.swap(i, i+gap); swapped = true; } } } }
void OddEvenSort(SortArray& A) { bool sorted = false; while (!sorted) { sorted = true; for (size_t i = 1; i < A.size()-1; i += 2) { if(A[i] > A[i+1]) { A.swap(i, i+1); sorted = false; } } for (size_t i = 0; i < A.size()-1; i += 2) { if(A[i] > A[i+1]) { A.swap(i, i+1); sorted = false; } } } }
void CocktailShakerSort(SortArray& A) { size_t lo = 0, hi = A.size()-1, mov = lo; while (lo < hi) { for (size_t i = hi; i > lo; --i) { if (A[i-1] > A[i]) { A.swap(i-1, i); mov = i; } } lo = mov; for (size_t i = lo; i < hi; ++i) { if (A[i] > A[i+1]) { A.swap(i, i+1); mov = i; } } hi = mov; } }
void Array::sort_custom(Object *p_obj,const StringName& p_function){ ERR_FAIL_NULL(p_obj); SortArray<Variant,_ArrayVariantSortCustom> avs; avs.compare.obj=p_obj; avs.compare.func=p_function; avs.sort(_p->array.ptr(),_p->array.size()); }
Array &Array::sort_custom(Object *p_obj, const StringName &p_function) { ERR_FAIL_NULL_V(p_obj, *this); SortArray<Variant, _ArrayVariantSortCustom, true> avs; avs.compare.obj = p_obj; avs.compare.func = p_function; avs.sort(_p->array.ptrw(), _p->array.size()); return *this; }
void VoxelMeshUpdater::thread_sync(int queue_index, Stats stats) { if (!_input.blocks.empty()) { // Cleanup input vector if (queue_index >= _input.blocks.size()) { _input.blocks.clear(); } else if (queue_index > 0) { // Shift up remaining items since we use a Vector shift_up(_input.blocks, queue_index); } } stats.remaining_blocks = _input.blocks.size(); bool needs_sort; { // Get input MutexLock lock(_input_mutex); _input.blocks.append_array(_shared_input.blocks); _input.priority_position = _shared_input.priority_position; _shared_input.blocks.clear(); _block_indexes.clear(); needs_sort = _needs_sort; _needs_sort = false; } if(!_output.blocks.empty()) { // print_line(String("VoxelMeshUpdater: posting {0} blocks, {1} remaining ; cost [{2}..{3}] usec") // .format(varray(_output.blocks.size(), _input.blocks.size(), stats.min_time, stats.max_time))); // Post output MutexLock lock(_output_mutex); _shared_output.blocks.append_array(_output.blocks); _shared_output.stats = stats; _output.blocks.clear(); } if (!_input.blocks.empty() && needs_sort) { // Re-sort priority SortArray<VoxelMeshUpdater::InputBlock, BlockUpdateComparator> sorter; sorter.compare.center = _input.priority_position; sorter.sort(_input.blocks.ptrw(), _input.blocks.size()); } }
void BubbleSort(SortArray& A) { for (size_t i = 0; i < A.size()-1; ++i) { for (size_t j = 0; j < A.size()-1 - i; ++j) { if (A[j] > A[j + 1]) { A.swap(j, j+1); } } } }
void SelectionSort(SortArray& A) { volatile ssize_t jMin = 0; A.watch(&jMin, 3); for (size_t i = 0; i < A.size()-1; ++i) { jMin = i; for (size_t j = i+1; j < A.size(); ++j) { if (A[j] < A[jMin]) { A.mark_swap(j, jMin); jMin = j; } } A.swap(i, jMin); // mark the last good element if (i > 0) A.unmark(i-1); A.mark(i); } A.unwatch_all(); }
void GnomeSort(SortArray& A) { for (size_t i = 1; i < A.size(); ) { if (A[i] >= A[i-1]) { ++i; } else { A.swap(i, i-1); if (i > 1) --i; } } }
void VoxelProviderThread::thread_sync(int emerge_index, Stats stats) { if (!_input.blocks_to_emerge.empty()) { // Cleanup emerge vector if (emerge_index >= _input.blocks_to_emerge.size()) { _input.blocks_to_emerge.clear(); } else if (emerge_index > 0) { // Shift up remaining items since we use a Vector shift_up(_input.blocks_to_emerge, emerge_index); } } { // Get input MutexLock lock(_input_mutex); _input.blocks_to_emerge.append_array(_shared_input.blocks_to_emerge); _input.blocks_to_immerge.append_array(_shared_input.blocks_to_immerge); _input.priority_block_position = _shared_input.priority_block_position; _shared_input.blocks_to_emerge.clear(); _shared_input.blocks_to_immerge.clear(); } stats.remaining_blocks = _input.blocks_to_emerge.size(); // print_line(String("VoxelProviderThread: posting {0} blocks, {1} remaining ; cost [{2}..{3}] usec") // .format(varray(_output.size(), _input.blocks_to_emerge.size(), stats.min_time, stats.max_time))); { // Post output MutexLock lock(_output_mutex); _shared_output.append_array(_output); _shared_stats = stats; _output.clear(); } if (!_input.blocks_to_emerge.empty()) { // Re-sort priority SortArray<Vector3i, BlockPositionComparator> sorter; sorter.compare.center = _input.priority_block_position; sorter.sort(_input.blocks_to_emerge.ptrw(), _input.blocks_to_emerge.size()); } }
static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { #ifdef DEBUG_ENABLED ERR_FAIL_COND(p_point_count_A != 2); ERR_FAIL_COND(p_point_count_B != 2); // circle is actually a 4x3 matrix #endif Vector3 rel_A = p_points_A[1] - p_points_A[0]; Vector3 rel_B = p_points_B[1] - p_points_B[0]; Vector3 c = rel_A.cross(rel_B).cross(rel_B); //if ( Math::abs(rel_A.dot(c) )<_EDGE_IS_VALID_SUPPORT_TRESHOLD ) { if (Math::abs(rel_A.dot(c)) < CMP_EPSILON) { // should handle somehow.. //ERR_PRINT("TODO FIX"); //return; Vector3 axis = rel_A.normalized(); //make an axis Vector3 base_A = p_points_A[0] - axis * axis.dot(p_points_A[0]); Vector3 base_B = p_points_B[0] - axis * axis.dot(p_points_B[0]); //sort all 4 points in axis real_t dvec[4] = { axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) }; SortArray<real_t> sa; sa.sort(dvec, 4); //use the middle ones as contacts p_callback->call(base_A + axis * dvec[1], base_B + axis * dvec[1]); p_callback->call(base_A + axis * dvec[2], base_B + axis * dvec[2]); return; } real_t d = (c.dot(p_points_B[0]) - p_points_A[0].dot(c)) / rel_A.dot(c); if (d < 0.0) d = 0.0; else if (d > 1.0) d = 1.0; Vector3 closest_A = p_points_A[0] + rel_A * d; Vector3 closest_B = Geometry::get_closest_point_to_segment_uncapped(closest_A, p_points_B); p_callback->call(closest_A, closest_B); }
// swaps every time (keeps all values visible) void InsertionSort(SortArray& A) { for (size_t i = 1; i < A.size(); ++i) { value_type key = A[i]; A.mark(i); ssize_t j = i - 1; while (j >= 0 && A[j] > key) { A.swap(j, j+1); j--; } A.unmark(i); } }
size_t PartitionLL(SortArray& A, size_t lo, size_t hi) { // pick pivot and move to back size_t p = QuickSortSelectPivot(A, lo, hi); value_type pivot = A[p]; A.swap(p, hi-1); A.mark(hi-1); volatile ssize_t i = lo; A.watch(&i, 3); for (size_t j = lo; j < hi-1; ++j) { if (A[j] <= pivot) { A.swap(i, j); ++i; } } A.swap(i, hi-1); A.unmark(hi-1); A.unwatch_all(); return i; }
void Merge(SortArray& A, size_t lo, size_t mid, size_t hi) { // mark merge boundaries A.mark(lo); A.mark(mid,3); A.mark(hi-1); // allocate output std::vector<value_type> out(hi-lo); // merge size_t i = lo, j = mid, o = 0; // first and second halves while (i < mid && j < hi) { // copy out for fewer time steps value_type ai = A[i], aj = A[j]; out[o++] = (ai < aj ? (++i, ai) : (++j, aj)); } // copy rest while (i < mid) out[o++] = A[i++]; while (j < hi) out[o++] = A[j++]; ASSERT(o == hi-lo); A.unmark(mid); // copy back for (i = 0; i < hi-lo; ++i) A.set(lo + i, out[i]); A.unmark(lo); A.unmark(hi-1); }
void ScriptDebuggerLocal::idle_poll() { if (!profiling) return; uint64_t diff = OS::get_singleton()->get_ticks_usec() - idle_accum; if (diff < 1000000) //show every one second return; idle_accum = OS::get_singleton()->get_ticks_usec(); int ofs = 0; for (int i = 0; i < ScriptServer::get_language_count(); i++) { ofs += ScriptServer::get_language(i)->profiling_get_frame_data(&pinfo[ofs], pinfo.size() - ofs); } SortArray<ScriptLanguage::ProfilingInfo, _ScriptDebuggerLocalProfileInfoSort> sort; sort.sort(pinfo.ptr(), ofs); //falta el frame time uint64_t script_time_us = 0; for (int i = 0; i < ofs; i++) { script_time_us += pinfo[i].self_time; } float script_time = USEC_TO_SEC(script_time_us); float total_time = frame_time; //print script total print_line("FRAME: total: " + rtos(frame_time) + " script: " + rtos(script_time) + "/" + itos(script_time * 100 / total_time) + " %"); for (int i = 0; i < ofs; i++) { print_line(itos(i) + ":" + pinfo[i].signature); float tt = USEC_TO_SEC(pinfo[i].total_time); float st = USEC_TO_SEC(pinfo[i].self_time); print_line("\ttotal: " + rtos(tt) + "/" + itos(tt * 100 / total_time) + " % \tself: " + rtos(st) + "/" + itos(st * 100 / total_time) + " % tcalls: " + itos(pinfo[i].call_count)); } }
// with extra item on stack void InsertionSort2(SortArray& A) { for (size_t i = 1; i < A.size(); ++i) { value_type tmp, key = A[i]; A.mark(i); ssize_t j = i - 1; while (j >= 0 && (tmp = A[j]) > key) { A.set(j + 1, tmp); j--; } A.set(j + 1, key); A.unmark(i); } }
int ConcavePolygonShape2DSW::_generate_bvh(BVH *p_bvh,int p_len,int p_depth) { if (p_len==1) { bvh_depth=MAX(p_depth,bvh_depth); bvh.push_back(*p_bvh); return bvh.size()-1; } //else sort best Rect2 global_aabb=p_bvh[0].aabb; for(int i=1;i<p_len;i++) { global_aabb=global_aabb.merge(p_bvh[i].aabb); } if (global_aabb.size.x > global_aabb.size.y) { SortArray<BVH,BVH_CompareX> sort; sort.sort(p_bvh,p_len); } else { SortArray<BVH,BVH_CompareY> sort; sort.sort(p_bvh,p_len); } int median = p_len/2; BVH node; node.aabb=global_aabb; int node_idx = bvh.size(); bvh.push_back(node); int l = _generate_bvh(p_bvh,median,p_depth+1); int r = _generate_bvh(&p_bvh[median],p_len-median,p_depth+1); bvh[node_idx].left=l; bvh[node_idx].right=r; return node_idx; }
void QuickSortLR(SortArray& A, ssize_t lo, ssize_t hi) { // pick pivot and watch volatile ssize_t p = QuickSortSelectPivot(A, lo, hi+1); value_type pivot = A[p]; A.watch(&p, 2); volatile ssize_t i = lo, j = hi; A.watch(&i, 3); A.watch(&j, 3); while (i <= j) { while (A[i] < pivot) i++; while (A[j] > pivot) j--; if (i <= j) { A.swap(i,j); // follow pivot if it is swapped if (p == i) p = j; else if (p == j) p = i; i++, j--; } } A.unwatch_all(); if (lo < j) QuickSortLR(A, lo, j); if (i < hi) QuickSortLR(A, i, hi); }
std::pair<ssize_t,ssize_t> PartitionTernaryLL(SortArray& A, ssize_t lo, ssize_t hi) { // pick pivot and swap to back ssize_t p = QuickSortSelectPivot(A, lo, hi); value_type pivot = A[p]; A.swap(p, hi-1); A.mark(hi-1); volatile ssize_t i = lo, k = hi-1; A.watch(&i, 3); for (ssize_t j = lo; j < k; ++j) { int cmp = A[j].cmp(pivot); // ternary comparison if (cmp == 0) { A.swap(--k, j); --j; // reclassify A[j] A.mark(k,4); } else if (cmp < 0) { A.swap(i++, j); } } // unwatch i, because the pivot is swapped there // in the first step of the following swap loop. A.unwatch_all(); ssize_t j = i + (hi-k); for (ssize_t s = 0; s < hi-k; ++s) { A.swap(i+s, hi-1-s); A.mark_swap(i+s, hi-1-s); } A.unmark_all(); return std::make_pair(i,j); }
void ShellSort(SortArray& A) { size_t incs[16] = { 1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1 }; for (size_t k = 0; k < 16; k++) { for (size_t h = incs[k], i = h; i < A.size(); i++) { value_type v = A[i]; size_t j = i; while (j >= h && A[j-h] > v) { A.set(j, A[j-h]); j -= h; } A.set(j, v); } } }
void ScriptDebuggerRemote::_send_profiling_data(bool p_for_frame) { int ofs = 0; for (int i = 0; i < ScriptServer::get_language_count(); i++) { if (p_for_frame) ofs += ScriptServer::get_language(i)->profiling_get_frame_data(&profile_info[ofs], profile_info.size() - ofs); else ofs += ScriptServer::get_language(i)->profiling_get_accumulated_data(&profile_info[ofs], profile_info.size() - ofs); } for (int i = 0; i < ofs; i++) { profile_info_ptrs[i] = &profile_info[i]; } SortArray<ScriptLanguage::ProfilingInfo *, ProfileInfoSort> sa; sa.sort(profile_info_ptrs.ptr(), ofs); int to_send = MIN(ofs, max_frame_functions); //check signatures first uint64_t total_script_time = 0; for (int i = 0; i < to_send; i++) { if (!profiler_function_signature_map.has(profile_info_ptrs[i]->signature)) { int idx = profiler_function_signature_map.size(); packet_peer_stream->put_var("profile_sig"); packet_peer_stream->put_var(2); packet_peer_stream->put_var(profile_info_ptrs[i]->signature); packet_peer_stream->put_var(idx); profiler_function_signature_map[profile_info_ptrs[i]->signature] = idx; } total_script_time += profile_info_ptrs[i]->self_time; } //send frames then if (p_for_frame) { packet_peer_stream->put_var("profile_frame"); packet_peer_stream->put_var(8 + profile_frame_data.size() * 2 + to_send * 4); } else { packet_peer_stream->put_var("profile_total"); packet_peer_stream->put_var(8 + to_send * 4); } packet_peer_stream->put_var(Engine::get_singleton()->get_frames_drawn()); //total frame time packet_peer_stream->put_var(frame_time); //total frame time packet_peer_stream->put_var(idle_time); //idle frame time packet_peer_stream->put_var(fixed_time); //fixed frame time packet_peer_stream->put_var(fixed_frame_time); //fixed frame time packet_peer_stream->put_var(USEC_TO_SEC(total_script_time)); //total script execution time if (p_for_frame) { packet_peer_stream->put_var(profile_frame_data.size()); //how many profile framedatas to send packet_peer_stream->put_var(to_send); //how many script functions to send for (int i = 0; i < profile_frame_data.size(); i++) { packet_peer_stream->put_var(profile_frame_data[i].name); packet_peer_stream->put_var(profile_frame_data[i].data); } } else { packet_peer_stream->put_var(0); //how many script functions to send packet_peer_stream->put_var(to_send); //how many script functions to send } for (int i = 0; i < to_send; i++) { int sig_id = -1; if (profiler_function_signature_map.has(profile_info_ptrs[i]->signature)) { sig_id = profiler_function_signature_map[profile_info_ptrs[i]->signature]; } packet_peer_stream->put_var(sig_id); packet_peer_stream->put_var(profile_info_ptrs[i]->call_count); packet_peer_stream->put_var(profile_info_ptrs[i]->total_time / 1000000.0); packet_peer_stream->put_var(profile_info_ptrs[i]->self_time / 1000000.0); } if (p_for_frame) { profile_frame_data.clear(); } }
Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const { Set<StringName> exported; if (FileAccess::exists("res://engine.cfg")) exported.insert("res://engine.cfg"); if (EditorImportExport::get_singleton()->get_export_filter()!=EditorImportExport::EXPORT_SELECTED) { String filter; if (EditorImportExport::get_singleton()->get_export_filter()==EditorImportExport::EXPORT_ALL) { _add_filter_to_list(exported,"*"); } else { _add_to_list(EditorFileSystem::get_singleton()->get_filesystem(),exported); _add_filter_to_list(exported,EditorImportExport::get_singleton()->get_export_custom_filter()); } } else { Map<String,Map<String,String> > remapped_paths; Set<String> scene_extensions; Set<String> resource_extensions; { List<String> l; // SceneLoader::get_recognized_extensions(&l); // for(List<String>::Element *E=l.front();E;E=E->next()) { // // scene_extensions.insert(E->get()); // } ResourceLoader::get_recognized_extensions_for_type("",&l); for(List<String>::Element *E=l.front();E;E=E->next()) { resource_extensions.insert(E->get()); } } List<StringName> toexport; EditorImportExport::get_singleton()->get_export_file_list(&toexport); print_line("TO EXPORT: "+itos(toexport.size())); for (List<StringName>::Element *E=toexport.front();E;E=E->next()) { print_line("DEP: "+String(E->get())); exported.insert(E->get()); if (p_bundles && EditorImportExport::get_singleton()->get_export_file_action(E->get())==EditorImportExport::ACTION_BUNDLE) { print_line("NO BECAUSE OF BUNDLE!"); continue; //no dependencies needed to be copied } List<String> testsubs; testsubs.push_back(E->get()); while(testsubs.size()) { //recursive subdep search! List<String> deplist; ResourceLoader::get_dependencies(testsubs.front()->get(),&deplist); testsubs.pop_front(); List<String> subdeps; for (List<String>::Element *F=deplist.front();F;F=F->next()) { StringName dep = F->get(); if (exported.has(dep) || EditorImportExport::get_singleton()->get_export_file_action(dep)!=EditorImportExport::ACTION_NONE) continue; //dependency added or to be added print_line(" SUBDEP: "+String(dep)); exported.insert(dep); testsubs.push_back(dep); } } } _add_filter_to_list(exported,EditorImportExport::get_singleton()->get_export_custom_filter()); } Vector<StringName> ret; ret.resize(exported.size()); int idx=0; for(Set<StringName>::Element *E=exported.front();E;E=E->next()) { ret[idx++]=E->get(); } SortArray<StringName,__EESortDepCmp> sort; //some platforms work better if this is sorted sort.sort(ret.ptr(),ret.size()); return ret; }
void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) { Item *ci = p_canvas_item; if (!ci->visible) return; Rect2 rect = ci->get_rect(); Transform2D xform = p_transform * ci->xform; Rect2 global_rect = xform.xform(rect); global_rect.pos += p_clip_rect.pos; if (ci->use_parent_material && p_material_owner) ci->material_owner = p_material_owner; else { p_material_owner = ci; ci->material_owner = NULL; } Color modulate(ci->modulate.r * p_modulate.r, ci->modulate.g * p_modulate.g, ci->modulate.b * p_modulate.b, ci->modulate.a * p_modulate.a); if (modulate.a < 0.007) return; int child_item_count = ci->child_items.size(); Item **child_items = (Item **)alloca(child_item_count * sizeof(Item *)); copymem(child_items, ci->child_items.ptr(), child_item_count * sizeof(Item *)); if (ci->clip) { if (p_canvas_clip != NULL) { ci->final_clip_rect = p_canvas_clip->final_clip_rect.clip(global_rect); } else { ci->final_clip_rect = global_rect; } ci->final_clip_owner = ci; } else { ci->final_clip_owner = p_canvas_clip; } if (ci->sort_y) { SortArray<Item *, ItemPtrSort> sorter; sorter.sort(child_items, child_item_count); } if (ci->z_relative) p_z = CLAMP(p_z + ci->z, VS::CANVAS_ITEM_Z_MIN, VS::CANVAS_ITEM_Z_MAX); else p_z = ci->z; for (int i = 0; i < child_item_count; i++) { if (!child_items[i]->behind) continue; _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); } if (ci->copy_back_buffer) { ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect); } if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render || ci->copy_back_buffer) { //something to draw? ci->final_transform = xform; ci->final_modulate = Color(modulate.r * ci->self_modulate.r, modulate.g * ci->self_modulate.g, modulate.b * ci->self_modulate.b, modulate.a * ci->self_modulate.a); ci->global_rect_cache = global_rect; ci->global_rect_cache.pos -= p_clip_rect.pos; ci->light_masked = false; int zidx = p_z - VS::CANVAS_ITEM_Z_MIN; if (z_last_list[zidx]) { z_last_list[zidx]->next = ci; z_last_list[zidx] = ci; } else { z_list[zidx] = ci; z_last_list[zidx] = ci; } ci->next = NULL; } for (int i = 0; i < child_item_count; i++) { if (child_items[i]->behind) continue; _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); } }
_FORCE_INLINE_ static void _generate_contacts_edge_edge(const Vector2 * p_points_A,int p_point_count_A, const Vector2 * p_points_B,int p_point_count_B,_CollectorCallback2D *p_collector) { #ifdef DEBUG_ENABLED ERR_FAIL_COND( p_point_count_A != 2 ); ERR_FAIL_COND( p_point_count_B != 2 ); // circle is actually a 4x3 matrix #endif Vector2 rel_A=p_points_A[1]-p_points_A[0]; Vector2 rel_B=p_points_B[1]-p_points_B[0]; Vector2 t = p_collector->normal.tangent(); real_t dA[2]={t.dot(p_points_A[0]),t.dot(p_points_A[1])}; Vector2 pA[2]={p_points_A[0],p_points_A[1]}; if (dA[0]>dA[1]) { SWAP(dA[0],dA[1]); SWAP(pA[0],pA[1]); } float dB[2]={t.dot(p_points_B[0]),t.dot(p_points_B[1])}; Vector2 pB[2]={p_points_B[0],p_points_B[1]}; if (dB[0]>dB[1]) { SWAP(dB[0],dB[1]); SWAP(pB[0],pB[1]); } if (dA[0]<dB[0]) { Vector2 n = (p_points_A[1]-p_points_A[0]).normalized().tangent(); real_t d = n.dot(p_points_A[1]); if (dA[1]>dB[1]) { //A contains B for(int i=0;i<2;i++) { Vector2 b = p_points_B[i]; Vector2 a = n.plane_project(d,b); if (p_collector->normal.dot(a) > p_collector->normal.dot(b)-CMP_EPSILON) continue; p_collector->call(a,b); } } else { // B0,A1 containment Vector2 n_B = (p_points_B[1]-p_points_B[0]).normalized().tangent(); real_t d_B = n_B.dot(p_points_B[1]); // first, B on A { Vector2 b = p_points_B[0]; Vector2 a = n.plane_project(d,b); if (p_collector->normal.dot(a) < p_collector->normal.dot(b)-CMP_EPSILON) p_collector->call(a,b); } // second, A on B { Vector2 a = p_points_A[1]; Vector2 b = n_B.plane_project(d_B,a); if (p_collector->normal.dot(a) < p_collector->normal.dot(b)-CMP_EPSILON) p_collector->call(a,b); } } } else { Vector2 n = (p_points_B[1]-p_points_B[0]).normalized().tangent(); real_t d = n.dot(p_points_B[1]); if (dB[1]>dA[1]) { //B contains A for(int i=0;i<2;i++) { Vector2 a = p_points_A[i]; Vector2 b = n.plane_project(d,a); if (p_collector->normal.dot(a) > p_collector->normal.dot(b)-CMP_EPSILON) continue; p_collector->call(a,b); } } else { // A0,B1 containment Vector2 n_A = (p_points_A[1]-p_points_A[0]).normalized().tangent(); real_t d_A = n_A.dot(p_points_A[1]); // first A on B { Vector2 a = p_points_A[0]; Vector2 b = n.plane_project(d,a); if (p_collector->normal.dot(a) < p_collector->normal.dot(b)-CMP_EPSILON) p_collector->call(a,b); } //second, B on A { Vector2 b = p_points_B[1]; Vector2 a = n_A.plane_project(d_A,b); if (p_collector->normal.dot(a) < p_collector->normal.dot(b)-CMP_EPSILON) p_collector->call(a,b); } } } #if 0 Vector2 axis = rel_A.normalized(); Vector2 axis_B = rel_B.normalized(); if (axis.dot(axis_B)<0) axis_B=-axis_B; axis=(axis+axis_B)*0.5; Vector2 normal_A = axis.tangent(); real_t dA = normal_A.dot(p_points_A[0]); Vector2 normal_B = rel_B.tangent().normalized(); real_t dB = normal_A.dot(p_points_B[0]); Vector2 A[4]={ normal_A.plane_project(dA,p_points_B[0]), normal_A.plane_project(dA,p_points_B[1]), p_points_A[0], p_points_A[1] }; Vector2 B[4]={ p_points_B[0], p_points_B[1], normal_B.plane_project(dB,p_points_A[0]), normal_B.plane_project(dB,p_points_A[1]) }; _generate_contacts_Pair dvec[4]; for(int i=0;i<4;i++) { dvec[i].d=axis.dot(p_points_A[0]-A[i]); dvec[i].idx=i; } SortArray<_generate_contacts_Pair> sa; sa.sort(dvec,4); for(int i=1;i<=2;i++) { Vector2 a = A[i]; Vector2 b = B[i]; if (p_collector->normal.dot(a) > p_collector->normal.dot(b)-CMP_EPSILON) continue; p_collector->call(a,b); } #elif 0 Vector2 axis = rel_A.normalized(); //make an axis Vector2 axis_B = rel_B.normalized(); if (axis.dot(axis_B)<0) axis_B=-axis_B; axis=(axis+axis_B)*0.5; Vector2 base_A = p_points_A[0] - axis * axis.dot(p_points_A[0]); Vector2 base_B = p_points_B[0] - axis * axis.dot(p_points_B[0]); //sort all 4 points in axis float dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) }; //todo , find max/min and then use 2 central points SortArray<float> sa; sa.sort(dvec,4); //use the middle ones as contacts for (int i=1;i<=2;i++) { Vector2 a = base_A+axis*dvec[i]; Vector2 b = base_B+axis*dvec[i]; if (p_collector->normal.dot(a) > p_collector->normal.dot(b)-0.01) { print_line("fail a: "+a); print_line("fail b: "+b); continue; } print_line("res a: "+a); print_line("res b: "+b); p_collector->call(a,b); } #endif }
void MergeSort(SortArray& A) { return MergeSort(A, 0, A.size()); }
void QuickSortTernaryLR(SortArray& A, ssize_t lo, ssize_t hi) { if (hi <= lo) return; int cmp; // pick pivot and swap to back ssize_t piv = QuickSortSelectPivot(A, lo, hi+1); A.swap(piv, hi); A.mark(hi); const value_type& pivot = A[hi]; // schema: |p === |i <<< | ??? |j >>> |q === |piv volatile ssize_t i = lo, j = hi-1; volatile ssize_t p = lo, q = hi-1; A.watch(&i, 3); A.watch(&j, 3); for (;;) { // partition on left while (i <= j && (cmp = A[i].cmp(pivot)) <= 0) { if (cmp == 0) { A.mark(p,4); A.swap(i, p++); } ++i; } // partition on right while (i <= j && (cmp = A[j].cmp(pivot)) >= 0) { if (cmp == 0) { A.mark(q,4); A.swap(j, q--); } --j; } if (i > j) break; // swap item between < > regions A.swap(i++, j--); } // swap pivot to right place A.swap(i,hi); A.mark_swap(i,hi); ssize_t num_less = i - p; ssize_t num_greater = q - j; // swap equal ranges into center, but avoid swapping equal elements j = i-1; i = i+1; ssize_t pe = lo + std::min(p-lo, num_less); for (ssize_t k = lo; k < pe; k++, j--) { A.swap(k,j); A.mark_swap(k,j); } ssize_t qe = hi-1 - std::min(hi-1-q, num_greater-1); // one already greater at end for (ssize_t k = hi-1; k > qe; k--, i++) { A.swap(i,k); A.mark_swap(i,k); } A.unwatch_all(); A.unmark_all(); QuickSortTernaryLR(A, lo, lo + num_less - 1); QuickSortTernaryLR(A, hi - num_greater + 1, hi); }
void QuickSortTernaryLR(SortArray& A) { return QuickSortTernaryLR(A, 0, A.size()-1); }
void QuickSortTernaryLL(SortArray& A) { return QuickSortTernaryLL(A, 0, A.size()); }