00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020 #include "ItemSorter.h"
00021
00022 #include "Item.h"
00023 #include "Shape.h"
00024 #include "ShapeFrame.h"
00025 #include "ShapeInfo.h"
00026 #include "MainShapeArchive.h"
00027 #include "RenderSurface.h"
00028 #include "Rect.h"
00029 #include "GameData.h"
00030
00031
00032 #include "WeaponOverlay.h"
00033 #include "MainActor.h"
00034 #include "getObject.h"
00035
00036
00037 using Pentagram::Rect;
00038
00039 #if 0
00040 template<class _T> class MyVector
00041 {
00042 public:
00043 typedef _T *iterator;
00044 typedef _T &reference;
00045
00046 private:
00047 iterator _begin;
00048 iterator _end;
00049 iterator _last;
00050
00051 public:
00052 MyVector()
00053 {
00054 _begin = 0;
00055 _end = 0;
00056 _last = 0;
00057 }
00058
00059 iterator push_back(reference _R)
00060 {
00061 if (!_begin)
00062 {
00063 _begin = new _T[1];
00064 _end = _last = _begin + 1;
00065 *_begin = _R;
00066 return _begin;
00067 }
00068
00069 if (_end == _last)
00070 {
00071 size_t _capacity = _last - _begin;
00072 iterator _new = new _T[_capacity*2];
00073 std::memcpy (_new, _begin, _capacity * sizeof(_T));
00074 _end = _new + (_end - _begin);
00075 delete [] _begin;
00076 _begin = _new;
00077 _last = _begin + (_capacity*2);
00078 }
00079 *_end = _R;
00080 _end++;
00081 return _end-1;
00082 }
00083
00084 void clear() { _end = _begin; }
00085
00086 iterator begin() { return _begin; }
00087 iterator end() { return _end; }
00088 private:
00089
00090
00091 };
00092
00093 #endif
00094
00095
00096
00097 struct SortItem
00098 {
00099 SortItem() : item_num(0), shape(0), order(-1), depends() { }
00100
00101 uint16 item_num;
00102
00103 Shape *shape;
00104 uint32 shape_num;
00105 uint32 frame;
00106 uint32 flags;
00107 uint32 ext_flags;
00108
00109 int sx, sx2;
00110 int sy, sy2;
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 sint32 x, xleft;
00131 sint32 y, yfar;
00132 sint32 z, ztop;
00133
00134 sint32 sxleft;
00135 sint32 sxright;
00136
00137 sint32 sxtop;
00138 sint32 sytop;
00139
00140 sint32 sxbot;
00141 sint32 sybot;
00142
00143 bool f32x32 : 1;
00144 bool flat : 1;
00145 bool occl : 1;
00146 bool solid : 1;
00147 bool draw : 1;
00148 bool roof : 1;
00149 bool noisy : 1;
00150 bool anim : 1;
00151 bool trans : 1;
00152 bool fixed : 1;
00153 bool land : 1;
00154
00155 bool occluded : 1;
00156
00157 sint16 clipped;
00158
00159 sint32 order;
00160
00161 std::vector<SortItem *> depends;
00162
00163
00164
00165
00166
00167 inline bool overlap(const SortItem &si2) const;
00168
00169
00170 inline bool occludes(const SortItem &si2) const;
00171
00172
00173 inline bool operator<(const SortItem& si2) const;
00174
00175
00176 inline bool operator<<(const SortItem& si2) const;
00177
00178 };
00179
00180 typedef std::vector<SortItem *> SortItemVector;
00181
00182
00183
00184 inline bool SortItem::overlap(const SortItem &si2) const
00185 {
00186 const int point_top_diff[2] = { sxtop - si2.sxbot, sytop - si2.sybot };
00187 const int point_bot_diff[2] = { sxbot - si2.sxtop, sybot - si2.sytop };
00188
00189
00190
00191
00192
00193
00194 const sint32 dot_top_left = point_top_diff[0] + point_top_diff[1] * 2;
00195
00196
00197 const sint32 dot_top_right = -point_top_diff[0] + point_top_diff[1] * 2;
00198
00199
00200 const sint32 dot_bot_left = point_bot_diff[0] - point_bot_diff[1] * 2;
00201
00202
00203 const sint32 dot_bot_right = -point_bot_diff[0] - point_bot_diff[1] * 2;
00204
00205 const bool right_clear = sxright <= si2.sxleft;
00206 const bool left_clear = sxleft >= si2.sxright;
00207 const bool top_left_clear = dot_top_left >= 0;
00208 const bool top_right_clear = dot_top_right >= 0;
00209 const bool bot_left_clear = dot_bot_left >= 0;
00210 const bool bot_right_clear = dot_bot_right >= 0;
00211
00212 const bool clear = right_clear | left_clear |
00213 bot_right_clear | bot_left_clear |
00214 top_right_clear | top_left_clear;
00215
00216 return !clear;
00217 }
00218
00219
00220 inline bool SortItem::occludes(const SortItem &si2) const
00221 {
00222 const int point_top_diff[2] = { sxtop - si2.sxtop, sytop - si2.sytop };
00223 const int point_bot_diff[2] = { sxbot - si2.sxbot, sybot - si2.sybot };
00224
00225
00226
00227
00228
00229
00230 const sint32 dot_top_left = point_top_diff[0] + point_top_diff[1] * 2;
00231
00232
00233 const sint32 dot_top_right = -point_top_diff[0] + point_top_diff[1] * 2;
00234
00235
00236 const sint32 dot_bot_left = point_bot_diff[0] - point_bot_diff[1] * 2;
00237
00238
00239 const sint32 dot_bot_right = -point_bot_diff[0] - point_bot_diff[1] * 2;
00240
00241
00242 const bool right_res = sxright >= si2.sxright;
00243 const bool left_res = sxleft <= si2.sxleft;
00244 const bool top_left_res = dot_top_left <= 0;
00245 const bool top_right_res = dot_top_right <= 0;
00246 const bool bot_left_res = dot_bot_left <= 0;
00247 const bool bot_right_res = dot_bot_right <= 0;
00248
00249 const bool occluded = right_res & left_res &
00250 bot_right_res & bot_left_res &
00251 top_right_res & top_left_res;
00252
00253 return occluded;
00254 }
00255
00256 inline bool SortItem::operator<(const SortItem& si2) const
00257 {
00258 const SortItem& si1 = *this;
00259
00260
00261 if (si1.flat && si2.flat)
00262 {
00263
00264 if (si1.ztop != si2.ztop) return si1.ztop < si2.ztop;
00265
00266
00267
00268
00269 if (si1.anim != si2.anim) return si1.anim < si2.anim;
00270
00271
00272 if (si1.trans != si2.trans) return si1.trans < si2.trans;
00273
00274
00275 if (si1.draw != si2.draw) return si1.draw > si2.draw;
00276
00277
00278 if (si1.solid != si2.solid) return si1.solid > si2.solid;
00279
00280
00281 if (si1.occl != si2.occl) return si1.occl > si2.occl;
00282
00283
00284 if (si1.f32x32 != si2.f32x32) return si1.f32x32 > si2.f32x32;
00285 }
00286
00287 else {
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 if (si1.ztop <= si2.z) return true;
00304 else if (si1.z >= si2.ztop) return false;
00305
00306
00307
00308 }
00309
00310
00311
00312
00313
00314
00315 if (si1.x <= si2.xleft) return true;
00316 else if (si1.xleft >= si2.x) return false;
00317
00318
00319 if (si1.y <= si2.yfar) return true;
00320 else if (si1.yfar >= si2.y) return false;
00321
00322
00323
00324
00325 if (si1.ztop < si2.ztop) return true;
00326 else if (si1.ztop > si2.ztop) return false;
00327
00328
00329 if ((si1.ztop+si1.z)/2 <= si2.z) return true;
00330 else if (si1.z >= (si2.ztop+si2.z)/2) return false;
00331
00332
00333 if ((si1.x+si1.xleft)/2 <= si2.xleft) return true;
00334 else if (si1.xleft >= (si2.x+si2.xleft)/2) return false;
00335
00336
00337 if ((si1.y+si1.yfar)/2 <= si2.yfar) return true;
00338 else if (si1.yfar >= (si2.y+si2.yfar)/2) return false;
00339
00340
00341 if (si1.x + si1.y != si1.x + si2.y) return (si1.x + si1.y < si2.x + si2.y);
00342
00343
00344 if (si1.xleft + si1.yfar != si1.xleft + si2.yfar) return (si1.xleft + si1.yfar < si2.xleft + si2.yfar);
00345
00346
00347 if (si1.x != si2.x) return si1.x < si2.x;
00348
00349
00350 if (si1.y != si2.y) return si1.y < si2.y;
00351
00352
00353 if (si1.shape_num != si2.shape_num) return si1.shape_num < si2.shape_num;
00354
00355
00356 return si1.frame < si2.frame;
00357 }
00358
00359 #define COMPARISON_RETURN(val,op,tab) \
00360 pout << tab"if (si1."#val" != si2."#val") -> (" \
00361 << si1.val << " != " << si2.val << ") -> " \
00362 << (si1.val != si2.val) << std::endl; \
00363 pout << tab"{" << std::endl; \
00364 if (si1.val != si2.val) \
00365 { \
00366 pout << tab"\treturn si1."#val" "#op" si2."#val"; -> (" \
00367 << si1.val << " "#op" " << si2.val << ") -> "\
00368 << (si1.val op si2.val) << std::endl; \
00369 return si1.val op si2.val; \
00370 } \
00371 pout << tab"}" << std::endl;
00372
00373 #define COMPARISON_RETURN_EX(val1,op,val2,tab) \
00374 pout << tab"if ("#val1" != "#val2") -> (" \
00375 << val1 << " != " << val2 << ") -> " \
00376 << (val1 != val2) << std::endl; \
00377 pout << tab"{" << std::endl; \
00378 if (val1 != val2) \
00379 { \
00380 pout << tab"\treturn "#val1" "#op" "#val2"; -> (" \
00381 << val1 << " "#op" " << val2 << ") -> " \
00382 << (val1 op val2) << std::endl; \
00383 return val1 op val2; \
00384 } \
00385 pout << tab"}" << std::endl;
00386
00387 #define COMPARISON_RETURN_TF(val1,op,val2,tf,tab) \
00388 pout << tab "if ("#val1" "#op" "#val2") -> (" \
00389 << val1 << " "#op" " << val2 << ") -> " \
00390 << (val1 op val2) << std::endl; \
00391 pout << tab"{" << std::endl; \
00392 if (val1 op val2) \
00393 { \
00394 pout << tab"\treturn " << tf << std::endl; \
00395 return tf; \
00396 } \
00397 pout << tab"}" << std::endl;
00398
00399 inline bool SortItem::operator<<(const SortItem& si2) const
00400 {
00401 const SortItem& si1 = *this;
00402
00403 if (si2.overlap(si1)) pout << "Overlaping" << std::endl;
00404 else
00405 {
00406 pout << "Not Overlaping" << std::endl;
00407 return false;
00408 }
00409
00410
00411 pout << "if (si1.flat && si2.flat) -> if ("
00412 << si1.flat << " && " << si2.flat << ") -> "
00413 << (si1.flat && si2.flat) << std::endl;
00414 pout << "{" << std::endl;
00415
00416 if (si1.flat && si2.flat)
00417 {
00418
00419
00420 COMPARISON_RETURN(ztop,<,"\t");
00421
00422
00423
00424
00425
00426 COMPARISON_RETURN(anim,<,"\t");
00427
00428
00429
00430 COMPARISON_RETURN(trans,<,"\t");
00431
00432
00433
00434 COMPARISON_RETURN(draw,>,"\t");
00435
00436
00437
00438 COMPARISON_RETURN(solid,>,"\t");
00439
00440
00441
00442 COMPARISON_RETURN(occl,>,"\t");
00443
00444
00445
00446 COMPARISON_RETURN(f32x32,>,"\t");
00447 }
00448
00449 else {
00450 pout << "}" << std::endl;
00451 pout << "else" << std::endl;
00452 pout << "{" << std::endl;
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 COMPARISON_RETURN_TF(si1.ztop,<=,si2.z,true,"\t");
00473 COMPARISON_RETURN_TF(si1.z,>=,si2.ztop,false,"\t");
00474
00475
00476
00477 }
00478 pout << "}" << std::endl;
00479
00480
00481
00482
00483
00484
00485
00486
00487 COMPARISON_RETURN_TF(si1.x,<=,si2.xleft,true,"\t");
00488 COMPARISON_RETURN_TF(si1.xleft,>=,si2.x,false,"\t");
00489
00490
00491
00492
00493 COMPARISON_RETURN_TF(si1.y,<=,si2.yfar,true,"\t");
00494 COMPARISON_RETURN_TF(si1.yfar,>=,si2.y,false,"\t");
00495
00496
00497 COMPARISON_RETURN_TF(si1.ztop,<,si2.z,true,"");
00498 COMPARISON_RETURN_TF(si1.ztop,>,si2.ztop,false,"");
00499
00500
00501
00502
00503 COMPARISON_RETURN_TF((si1.ztop+si1.z)/2,<=,si2.z,true,"");
00504 COMPARISON_RETURN_TF(si1.z,>=,(si2.ztop+si2.z)/2,false,"");
00505
00506
00507
00508
00509 COMPARISON_RETURN_TF((si1.x+si1.xleft)/2,<=,si2.xleft,true,"");
00510 COMPARISON_RETURN_TF(si1.xleft,>=,(si2.x+si2.xleft)/2,false,"");
00511
00512
00513
00514
00515 COMPARISON_RETURN_TF((si1.y+si1.yfar)/2,<=,si2.yfar,true,"");
00516 COMPARISON_RETURN_TF(si1.yfar,>=,(si2.y+si2.yfar)/2,false,"");
00517
00518
00519
00520 COMPARISON_RETURN_EX(si1.x + si1.y,<,si1.x + si2.y,"");
00521
00522
00523
00524 COMPARISON_RETURN_EX(si1.xleft + si1.yfar,<,si1.xleft + si2.yfar,"");
00525
00526
00527
00528 COMPARISON_RETURN(x,<,"");
00529
00530
00531
00532 COMPARISON_RETURN(y,<,"");
00533
00534
00535
00536 COMPARISON_RETURN(shape_num,<,"");
00537
00538
00539
00540 COMPARISON_RETURN(frame,<,"");
00541 return 0;
00542 }
00543
00544
00545
00546
00547
00548 ItemSorter::ItemSorter(int Max_Items) :
00549 shapes(0), surf(0), max_items(Max_Items), num_items(0), num_extra(0), sort_limit(0)
00550 {
00551 if (max_items <= 0) max_items = Max_Items = 2048;
00552 items = new SortItem [max_items];
00553 }
00554
00555 ItemSorter::~ItemSorter()
00556 {
00557 delete [] items;
00558 }
00559
00560 void ItemSorter::BeginDisplayList(RenderSurface *rs,
00561 sint32 camx, sint32 camy, sint32 camz)
00562 {
00563
00564 if (!shapes) shapes = GameData::get_instance()->getMainShapes();
00565
00566
00567 if (num_extra)
00568 {
00569 delete [] items;
00570 max_items += num_extra*2;
00571 items = new SortItem [max_items];
00572 }
00573
00574 surf = rs;
00575 num_items = 0;
00576 order_counter = 0;
00577 num_extra = 0;
00578
00579
00580 cam_sx = (camx - camy)/4;
00581
00582 cam_sy = (camx + camy)/8 - camz;
00583 }
00584
00585 void ItemSorter::AddItem(sint32 x, sint32 y, sint32 z, uint32 shape_num, uint32 frame_num, uint32 flags, uint32 ext_flags, uint16 item_num)
00586 {
00587
00588
00589
00590
00591
00592 if (num_items >= max_items)
00593 {
00594 num_extra++;
00595 return;
00596 }
00597
00598 SortItem *si = items+num_items;
00599
00600 si->item_num = item_num;
00601 si->shape = shapes->getShape(shape_num);
00602 si->shape_num = shape_num;
00603 si->frame = frame_num;
00604 ShapeFrame *frame = si->shape->getFrame(si->frame);
00605 if (!frame) {
00606 perr << "Invalid shape: " << si->shape_num << "," << si->frame
00607 << std::endl;
00608 return;
00609 }
00610
00611 ShapeInfo *info = shapes->getShapeInfo(shape_num);
00612
00613
00614
00615
00616
00617 sint32 xd, yd, zd;
00618 si->flags = flags;
00619 si->ext_flags = ext_flags;
00620
00621
00622 if (si->flags & Item::FLG_FLIPPED)
00623 {
00624 xd = info->y * 32;
00625 yd = info->x * 32;
00626 }
00627 else
00628 {
00629 xd = info->x * 32;
00630 yd = info->y * 32;
00631 }
00632
00633 zd = info->z * 8;
00634
00635
00636 si->x = x; si->y = y; si->z = z;
00637 si->xleft = si->x - xd;
00638 si->yfar = si->y - yd;
00639 si->ztop = si->z + zd;
00640
00641
00642 si->sxleft = (si->xleft - si->y)/4 - cam_sx;
00643
00644 si->sxright= (si->x - si->yfar)/4 - cam_sx;
00645
00646
00647 si->sxtop = (si->xleft - si->yfar)/4 - cam_sx;
00648
00649 si->sytop = (si->xleft + si->yfar)/8 - si->ztop - cam_sy;
00650
00651
00652 si->sxbot = (si->x - si->y)/4 - cam_sx;
00653
00654 si->sybot = (si->x + si->y)/8 - si->z - cam_sy;
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665 si->sx = si->sxbot - frame->xoff;
00666 si->sy = si->sybot - frame->yoff;
00667 si->sx2 = si->sx + frame->width;
00668 si->sy2 = si->sy + frame->height;
00669
00670
00671 si->clipped = surf->CheckClipped(Rect (si->sx,si->sy, frame->width, frame->height));
00672 if (si->clipped < 0) return;
00673
00674
00675 si->f32x32 = xd==128 && yd==128;
00676 si->flat = zd == 0;
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 {
00691 si->draw = info->is_draw();
00692 si->solid = info->is_solid();
00693 si->occl = info->is_occl() && !(si->ext_flags & Item::FLG_INVISIBLE);
00694 si->roof = info->is_roof();
00695 si->noisy = info->is_noisy();
00696 si->anim = info->animtype != 0;
00697 si->trans = info->is_translucent();
00698 si->fixed = info->is_fixed();
00699 si->land = info->is_land();
00700 }
00701
00702 si->occluded = false;
00703 si->order = -1;
00704
00705
00706
00707
00708
00709 si->depends.erase(si->depends.begin(), si->depends.end());
00710
00711
00712
00713
00714 for (SortItem * si2 = items; si2 != si; ++si2)
00715 {
00716
00717 if (si2->occluded || !si->overlap(*si2)) continue;
00718
00719
00720 if (*si < *si2)
00721 {
00722
00723 if (si2->occl && si2->occludes(*si))
00724 {
00725
00726 si->occluded = true;
00727 break;
00728 }
00729
00730
00731 si2->depends.push_back(si);
00732 }
00733 else
00734 {
00735
00736 if (si->occl && si->occludes(*si2)) si2->occluded = true;
00737
00738 else si->depends.push_back(si2);
00739 }
00740 }
00741
00742
00743 num_items ++;
00744 }
00745
00746 void ItemSorter::AddItem(Item *add)
00747 {
00748 #if 0
00749
00750 sint32 x, y, z;
00751 add->getLerped(x, y, z);
00752 AddItem(x,y,z,add->getShape(), add->getFrame(), add->getFlags(), add->getObjId());
00753
00754 #else
00755
00756
00757
00758
00759
00760
00761 if (num_items >= max_items)
00762 {
00763 num_extra++;
00764 return;
00765 }
00766
00767 SortItem *si = items+num_items;
00768
00769 si->item_num = add->getObjId();
00770 si->shape = add->getShapeObject();
00771 si->shape_num = add->getShape();
00772 si->frame = add->getFrame();
00773 ShapeFrame *frame = si->shape->getFrame(si->frame);
00774 if (!frame) {
00775 perr << "Invalid shape: " << si->shape_num << "," << si->frame
00776 << std::endl;
00777 return;
00778 }
00779
00780 ShapeInfo *info = add->getShapeInfo();
00781
00782
00783
00784
00785
00786 sint32 xd, yd, zd;
00787 si->flags = add->getFlags();
00788 si->ext_flags = add->getExtFlags();
00789
00790
00791 if (si->flags & Item::FLG_FLIPPED)
00792 {
00793 xd = info->y * 32;
00794 yd = info->x * 32;
00795 }
00796 else
00797 {
00798 xd = info->x * 32;
00799 yd = info->y * 32;
00800 }
00801
00802 zd = info->z * 8;
00803
00804
00805 add->getLerped(si->x, si->y, si->z);
00806 si->xleft = si->x - xd;
00807 si->yfar = si->y - yd;
00808 si->ztop = si->z + zd;
00809
00810
00811 si->sxleft = (si->xleft - si->y)/4 - cam_sx;
00812
00813 si->sxright= (si->x - si->yfar)/4 - cam_sx;
00814
00815
00816 si->sxtop = (si->xleft - si->yfar)/4 - cam_sx;
00817
00818 si->sytop = (si->xleft + si->yfar)/8 - si->ztop - cam_sy;
00819
00820
00821 si->sxbot = (si->x - si->y)/4 - cam_sx;
00822
00823 si->sybot = (si->x + si->y)/8 - si->z - cam_sy;
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 si->sx = si->sxbot - frame->xoff;
00835 si->sy = si->sybot - frame->yoff;
00836 si->sx2 = si->sx + frame->width;
00837 si->sy2 = si->sy + frame->height;
00838
00839
00840 si->clipped = surf->CheckClipped(Rect (si->sx,si->sy, frame->width, frame->height));
00841 if (si->clipped < 0) return;
00842
00843