00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "builderPrim.h"
00020 #include "mesherTempl.h"
00021 #include "builderNormalVisualizer.h"
00022 #include "config_builder.h"
00023
00024 #include <geom.h>
00025 #include <geomprimitives.h>
00026
00027 #include <algorithm>
00028
00029 struct DecompVtx {
00030 int index;
00031 BuilderV coord;
00032 struct DecompVtx *next;
00033 };
00034
00035
00036
00037
00038
00039
00040
00041 template <class PrimType, class OutputIterator>
00042 static bool
00043 decomp_concave(const PrimType &prim, BuilderBucket &bucket,
00044 OutputIterator result,
00045 int asum, int x, int y) {
00046 #define VX(p, c) p->coord[c]
00047
00048 pvector<PrimType> output_prims;
00049
00050 DecompVtx *p0, *p1, *p2, *t0, *vert;
00051 DecompVtx *m[3];
00052 float xmin, xmax, ymin, ymax;
00053 int i, init, csum, chek;
00054 float a[3], b[3], c[3], s[3];
00055
00056 int num_verts = prim.get_num_verts();
00057 nassertr(num_verts >= 3, false);
00058
00059
00060 vert = (DecompVtx *) alloca(sizeof(DecompVtx));
00061 vert->index = 0;
00062 vert->coord = prim.get_vertex(0).get_coord_value(bucket);
00063 p1 = vert;
00064
00065 for (i = 1; i < num_verts; i++) {
00066 p0 = (DecompVtx *) alloca(sizeof(DecompVtx));
00067 p0->index = i;
00068 p0->coord = prim.get_vertex(i).get_coord_value(bucket);
00069
00070
00071 if (!(p0->coord == p1->coord)) {
00072 p1->next = p0;
00073 p1 = p0;
00074 }
00075 }
00076 p1->next = vert;
00077
00078 p0 = vert;
00079 p1 = p0->next;
00080 p2 = p1->next;
00081 m[0] = p0;
00082 m[1] = p1;
00083 m[2] = p2;
00084 chek = 0;
00085
00086 while (p0 != p2->next) {
00087
00088 if (chek &&
00089 m[0] == p0 &&
00090 m[1] == p1 &&
00091 m[2] == p2) {
00092
00093
00094 return false;
00095 }
00096
00097 chek = 1;
00098
00099 a[0] = VX(p1, y) - VX(p2, y);
00100 b[0] = VX(p2, x) - VX(p1, x);
00101 a[2] = VX(p0, y) - VX(p1, y);
00102 b[2] = VX(p1, x) - VX(p0, x);
00103
00104 csum = ((b[0] * a[2] - b[2] * a[0] >= 0.0) ? 1 : 0);
00105
00106 if (csum ^ asum) {
00107
00108 p0 = p1;
00109 p1 = p2;
00110 p2 = p2->next;
00111
00112 } else {
00113
00114 xmin = (VX(p0, x) < VX(p1, x)) ? VX(p0, x) : VX(p1, x);
00115 if (xmin > VX(p2, x))
00116 xmin = VX(p2, x);
00117
00118 xmax = (VX(p0, x) > VX(p1, x)) ? VX(p0, x) : VX(p1, x);
00119 if (xmax < VX(p2, x))
00120 xmax = VX(p2, x);
00121
00122 ymin = (VX(p0, y) < VX(p1, y)) ? VX(p0, y) : VX(p1, y);
00123 if (ymin > VX(p2, y))
00124 ymin = VX(p2, y);
00125
00126 ymax = (VX(p0, y) > VX(p1, y)) ? VX(p0, y) : VX(p1, y);
00127 if (ymax < VX(p2, y))
00128 ymax = VX(p2, y);
00129
00130 for (init = 1, t0 = p2->next; t0 != p0; t0 = t0->next) {
00131 if (VX(t0, x) >= xmin && VX(t0, x) <= xmax &&
00132 VX(t0, y) >= ymin && VX(t0, y) <= ymax) {
00133 if (init) {
00134 a[1] = VX(p2, y) - VX(p0, y);
00135 b[1] = VX(p0, x) - VX(p2, x);
00136 init = 0;
00137 c[0] = VX(p1, x) * VX(p2, y) - VX(p2, x) * VX(p1, y);
00138 c[1] = VX(p2, x) * VX(p0, y) - VX(p0, x) * VX(p2, y);
00139 c[2] = VX(p0, x) * VX(p1, y) - VX(p1, x) * VX(p0, y);
00140 }
00141
00142 s[0] = a[0] * VX(t0, x) + b[0] * VX(t0, y) + c[0];
00143 s[1] = a[1] * VX(t0, x) + b[1] * VX(t0, y) + c[1];
00144 s[2] = a[2] * VX(t0, x) + b[2] * VX(t0, y) + c[2];
00145
00146 if (asum) {
00147 if (s[0] >= 0.0 && s[1] >= 0.0 && s[2] >= 0.0)
00148 break;
00149 } else {
00150 if (s[0] <= 0.0 && s[1] <= 0.0 && s[2] <= 0.0)
00151 break;
00152 }
00153 }
00154 }
00155
00156 if (t0 != p0) {
00157 p0 = p1;
00158 p1 = p2;
00159 p2 = p2->next;
00160 } else {
00161 PrimType new_prim(prim);
00162 new_prim.set_type(BPT_tri);
00163 new_prim.clear_vertices();
00164 new_prim.add_vertex(prim.get_vertex(p0->index));
00165 new_prim.add_vertex(prim.get_vertex(p1->index));
00166 new_prim.add_vertex(prim.get_vertex(p2->index));
00167 output_prims.push_back(new_prim);
00168
00169 p0->next = p1->next;
00170 p1 = p2;
00171 p2 = p2->next;
00172
00173 m[0] = p0;
00174 m[1] = p1;
00175 m[2] = p2;
00176 chek = 0;
00177 }
00178 }
00179 }
00180
00181 PrimType new_prim(prim);
00182 new_prim.set_type(BPT_tri);
00183 new_prim.clear_vertices();
00184 new_prim.add_vertex(prim.get_vertex(p0->index));
00185 new_prim.add_vertex(prim.get_vertex(p1->index));
00186 new_prim.add_vertex(prim.get_vertex(p2->index));
00187 output_prims.push_back(new_prim);
00188
00189 copy(output_prims.begin(), output_prims.end(), result);
00190 return true;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 template <class PrimType, class OutputIterator>
00200 static bool
00201 triangulate_poly(const PrimType &prim, BuilderBucket &bucket,
00202 OutputIterator result) {
00203 BuilderV p0, p1, as;
00204 float dx1, dy1, dx2, dy2, max;
00205 int i, flag, asum, csum, index, x, y, v0, v1, v, even;
00206
00207
00208 int num_verts = prim.get_num_verts();
00209 if (num_verts == 3) {
00210 PrimType new_prim(prim);
00211 new_prim.set_type(BPT_tri);
00212 *result++ = new_prim;
00213
00214 return true;
00215
00216 } else if (num_verts < 3) {
00217
00218 return false;
00219 }
00220
00221
00222 as[0] = 0.0;
00223 as[1] = 0.0;
00224 as[2] = 0.0;
00225
00226 for (i = 0; i < num_verts; i++) {
00227 p0 = prim.get_vertex(i).get_coord_value(bucket);
00228 p1 = prim.get_vertex((i + 1) % num_verts).get_coord_value(bucket);
00229 as[0] += p0[0] * p1[1] - p0[1] * p1[0];
00230 as[1] += p0[0] * p1[2] - p0[2] * p1[0];
00231 as[2] += p0[1] * p1[2] - p0[2] * p1[1];
00232 }
00233
00234
00235 max = 0.0;
00236 index = 0;
00237 flag = 0;
00238 for (i = 0; i < 3; i++) {
00239 if (as[i] >= 0.0) {
00240 if (as[i] > max) {
00241 max = as[i];
00242 index = i;
00243 flag = 1;
00244 }
00245 } else {
00246 as[i] = -as[i];
00247 if (as[i] > max) {
00248 max = as[i];
00249 index = i;
00250 flag = 0;
00251 }
00252 }
00253 }
00254
00255
00256 switch (index) {
00257 case 0:
00258 x = 0;
00259 y = 1;
00260 break;
00261
00262 case 1:
00263 x = 0;
00264 y = 2;
00265 break;
00266
00267 default:
00268 x = 1;
00269 y = 2;
00270 break;
00271 }
00272
00273
00274 p0 = prim.get_vertex(0).get_coord_value(bucket);
00275 p1 = prim.get_vertex(1).get_coord_value(bucket);
00276 dx1 = p1[x] - p0[x];
00277 dy1 = p1[y] - p0[y];
00278 p0 = p1;
00279 p1 = prim.get_vertex(2).get_coord_value(bucket);
00280
00281 dx2 = p1[x] - p0[x];
00282 dy2 = p1[y] - p0[y];
00283 asum = ((dx1 * dy2 - dx2 * dy1 >= 0.0) ? 1 : 0);
00284
00285 for (i = 0; i < num_verts - 1; i++) {
00286 p0 = p1;
00287 p1 = prim.get_vertex((i+3) % num_verts).get_coord_value(bucket);
00288
00289 dx1 = dx2;
00290 dy1 = dy2;
00291 dx2 = p1[x] - p0[x];
00292 dy2 = p1[y] - p0[y];
00293 csum = ((dx1 * dy2 - dx2 * dy1 >= 0.0) ? 1 : 0);
00294
00295 if (csum ^ asum) {
00296 return decomp_concave(prim, bucket, result, flag, x, y);
00297 }
00298 }
00299
00300 v0 = 0;
00301 v1 = 1;
00302 v = num_verts - 1;
00303
00304 even = 1;
00305
00306
00307
00308
00309
00310 for (i = 0; i < num_verts - 2; i++) {
00311 if (even) {
00312 PrimType new_prim(prim);
00313 new_prim.set_type(BPT_tri);
00314 new_prim.clear_vertices();
00315 new_prim.add_vertex(prim.get_vertex(v0));
00316 new_prim.add_vertex(prim.get_vertex(v1));
00317 new_prim.add_vertex(prim.get_vertex(v));
00318 *result++ = new_prim;
00319 v0 = v1;
00320 v1 = v;
00321 v = v0 + 1;
00322 } else {
00323 PrimType new_prim(prim);
00324 new_prim.set_type(BPT_tri);
00325 new_prim.clear_vertices();
00326 new_prim.add_vertex(prim.get_vertex(v1));
00327 new_prim.add_vertex(prim.get_vertex(v0));
00328 new_prim.add_vertex(prim.get_vertex(v));
00329 *result++ = new_prim;
00330 v0 = v1;
00331 v1 = v;
00332 v = v0 - 1;
00333 }
00334
00335 even = !even;
00336 }
00337
00338 return true;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348 template <class PrimType, class OutputIterator>
00349 static bool
00350 expand_polys(PrimType &prim, BuilderBucket &,
00351 OutputIterator result) {
00352 switch (prim.get_num_verts()) {
00353 case 0:
00354 case 1:
00355 case 2:
00356 return false;
00357
00358 case 3:
00359 prim.set_type(BPT_tri);
00360 break;
00361
00362 case 4:
00363 prim.set_type(BPT_quad);
00364 break;
00365
00366 default:
00367 prim.set_type(BPT_poly);
00368 }
00369
00370 *result++ = prim;
00371 return true;
00372 }
00373
00374
00375
00376
00377
00378
00379
00380 template <class PrimType, class OutputIterator>
00381 static bool
00382 expand_points(const PrimType &prim, BuilderBucket &,
00383 OutputIterator result) {
00384
00385
00386 int num_verts = prim.get_num_verts();
00387 for (int i = 0; i < num_verts; i++) {
00388 PrimType new_prim(prim);
00389 new_prim.clear_vertices();
00390 new_prim.add_vertex(prim.get_vertex(i));
00391 *result++ = new_prim;
00392 }
00393 return true;
00394 }
00395
00396
00397
00398
00399
00400
00401
00402 template <class PrimType, class OutputIterator>
00403 static bool
00404 expand_lines(const PrimType &prim, BuilderBucket &,
00405 OutputIterator result) {
00406
00407
00408
00409
00410 int num_verts = prim.get_num_verts();
00411 for (int i = 1; i < num_verts; i++) {
00412 PrimType new_prim(prim);
00413 new_prim.clear_vertices();
00414 new_prim.add_vertex(prim.get_vertex(i-1));
00415 new_prim.add_vertex(prim.get_vertex(i));
00416 *result++ = new_prim;
00417 }
00418 return true;
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439 template <class PrimType, class OutputIterator>
00440 bool
00441 expand(const PrimType &prim, BuilderBucket &bucket, OutputIterator result) {
00442
00443 PrimType new_prim = prim;
00444
00445 switch (new_prim.get_type()) {
00446 case BPT_poly:
00447 case BPT_tri:
00448 case BPT_quad:
00449
00450
00451
00452 new_prim.remove_doubled_verts(true);
00453
00454 if (!bucket._subdivide_polys ||
00455 (bucket._mesh && new_prim.get_num_verts() <= 4)) {
00456
00457
00458
00459 return expand_polys(new_prim, bucket, result);
00460 } else {
00461
00462 return triangulate_poly(new_prim, bucket, result);
00463 }
00464
00465 case BPT_point:
00466 new_prim.remove_doubled_verts(false);
00467 return expand_points(new_prim, bucket, result);
00468
00469 case BPT_line:
00470 new_prim.remove_doubled_verts(false);
00471 return expand_lines(new_prim, bucket, result);
00472
00473 default:
00474 builder_cat.error() << "Unknown prim type\n";
00475 return false;
00476 }
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 template<class InputIterator, class PrimType>
00488 static int
00489 build_geoms(InputIterator first, InputIterator last,
00490 BuilderBucket &bucket, GeomNode *geom_node,
00491 PrimType *) {
00492 if (first==last) {
00493 return 0;
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 typedef TYPENAME PrimType::VType VType;
00511 typedef TYPENAME PrimType::NType NType;
00512 typedef TYPENAME PrimType::TType TType;
00513 typedef TYPENAME PrimType::CType CType;
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538 GeomBindType bind_normals = G_OVERALL;
00539 GeomBindType bind_colors = G_OVERALL;
00540 GeomBindType bind_texcoords = G_PER_VERTEX;
00541
00542 NType overall_normal(0);
00543 CType overall_color(0);
00544 bool first_normal = true;
00545 bool first_color = true;
00546
00547 InputIterator i;
00548 for (i = first; i != last; ++i) {
00549
00550
00551
00552
00553 if (!(*i).has_any_normal()) {
00554 bind_normals = G_OFF;
00555 } else if (bind_normals != G_OFF) {
00556
00557 if ((*i).has_vertex_normal()) {
00558 bind_normals = G_PER_VERTEX;
00559 } else if (bind_normals != G_PER_VERTEX) {
00560
00561 if ((*i).has_component_normal()) {
00562 bind_normals = G_PER_COMPONENT;
00563 } else if (bind_normals != G_PER_COMPONENT) {
00564
00565 nassertr((*i).has_overall_normal(), 0);
00566 if (first_normal) {
00567 overall_normal = (*i).get_normal();
00568 first_normal = false;
00569 } else if ( !((*i).get_normal() == overall_normal)) {
00570 bind_normals = G_PER_PRIM;
00571 }
00572 }
00573 }
00574 }
00575
00576
00577
00578
00579 if (!(*i).has_any_color()) {
00580 bind_colors = G_OFF;
00581 } else if (bind_colors != G_OFF) {
00582
00583 if ((*i).has_vertex_color()) {
00584 bind_colors = G_PER_VERTEX;
00585 } else if (bind_colors != G_PER_VERTEX) {
00586
00587 if ((*i).has_component_color()) {
00588 bind_colors = G_PER_COMPONENT;
00589 } else if (bind_colors != G_PER_COMPONENT) {
00590
00591 nassertr((*i).has_overall_color(), 0);
00592 if (first_color) {
00593 overall_color = (*i).get_color();
00594 first_color = false;
00595 } else if ( !((*i).get_color() == overall_color)) {
00596 bind_colors = G_PER_PRIM;
00597 }
00598 }
00599 }
00600 }
00601
00602
00603
00604
00605 if (!(*i).has_any_texcoord()) {
00606 bind_texcoords = G_OFF;
00607 }
00608 }
00609
00610
00611 PTA_int lengths;
00612 bool want_lengths = false;
00613 int j;
00614
00615 Geom *geom = NULL;
00616 BuilderPrimType type = (*first).get_type();
00617 switch (type) {
00618 case BPT_poly:
00619 geom = new GeomPolygon;
00620 want_lengths = true;
00621 break;
00622
00623 case BPT_tristrip:
00624 geom = new GeomTristrip;
00625 want_lengths = true;
00626 break;
00627
00628 case BPT_trifan:
00629 geom = new GeomTrifan;
00630 want_lengths = true;
00631 break;
00632
00633 case BPT_line:
00634 geom = new GeomLine;
00635 break;
00636
00637 case BPT_point:
00638 geom = new GeomPoint;
00639 break;
00640
00641 case BPT_tri:
00642 geom = new GeomTri;
00643 break;
00644
00645 case BPT_quad:
00646 geom = new GeomQuad;
00647 break;
00648
00649 default:
00650 builder_cat.fatal() << "Invalid primitive type.\n";
00651 abort();
00652 }
00653
00654 if (geom == NULL) {
00655 builder_cat.error() << "Unsupported primitive type " << type << "\n";
00656 return 0;
00657 }
00658
00659
00660 int num_prims = 0;
00661 for (i = first; i != last; ++i) {
00662 if ((*i).is_valid()) {
00663 num_prims++;
00664 }
00665 }
00666
00667 if (num_prims==0) {
00668 builder_cat.error() << "All primitives were invalid!\n";
00669 return 0;
00670 }
00671
00672 if (want_lengths) {
00673 lengths = PTA_int::empty_array(num_prims);
00674 j = 0;
00675 for (i = first; i != last; ++i) {
00676 if ((*i).is_valid()) {
00677 lengths[j++] = (*i).get_num_verts();
00678 }
00679 }
00680 nassertr(j == num_prims, 0);
00681 }
00682
00683
00684 PTA(VType) coords=PTA(VType)::empty_array(0);
00685 PTA(NType) normals=PTA(NType)::empty_array(0);
00686 PTA(TType) texcoords=PTA(TType)::empty_array(0);
00687 PTA(CType) colors=PTA(CType)::empty_array(0);
00688
00689 int total_verts = 0;
00690 int total_components = 0;
00691
00692 int v, num_verts;
00693 int c, num_components;
00694 for (i = first; i != last; ++i) {
00695 if ((*i).is_valid()) {
00696 num_verts = (*i).get_num_verts();
00697 total_verts += num_verts;
00698 for (v = 0; v < num_verts; v++) {
00699 coords.push_back((*i).get_vertex(v).get_coord());
00700
00701 if (bind_normals == G_PER_VERTEX) {
00702 normals.push_back((*i).get_vertex(v).get_normal());
00703 }
00704 if (bind_texcoords == G_PER_VERTEX) {
00705 texcoords.push_back((*i).get_vertex(v).get_texcoord());
00706 }
00707 if (bind_colors == G_PER_VERTEX) {
00708 colors.push_back((*i).get_vertex(v).get_color());
00709 }
00710 }
00711
00712 num_components = (*i).get_num_components();
00713 total_components += num_components;
00714 for (c = 0; c < num_components; c++) {
00715 if (bind_normals == G_PER_COMPONENT) {
00716 normals.push_back((*i).get_component(c).get_normal());
00717 }
00718 if (bind_colors == G_PER_COMPONENT) {
00719 colors.push_back((*i).get_component(c).get_color());
00720 }
00721 }
00722
00723 if (bind_normals == G_PER_PRIM) {
00724 normals.push_back((*i).get_normal());
00725 }
00726 if (bind_colors == G_PER_PRIM) {
00727 colors.push_back((*i).get_color());
00728 }
00729 }
00730 }
00731
00732 if (bind_normals == G_OVERALL) {
00733 normals.push_back(overall_normal);
00734 }
00735 if (bind_colors == G_OVERALL) {
00736 colors.push_back(overall_color);
00737 }
00738
00739
00740
00741 geom->set_num_prims(num_prims);
00742
00743 if (lengths != (int *)NULL) {
00744 geom->set_lengths(lengths);
00745 }
00746
00747 PrimType::fill_geom(geom, coords,
00748 bind_normals, normals,
00749 bind_texcoords, texcoords,
00750 bind_colors, colors,
00751 bucket, num_prims,
00752 total_components, total_verts);
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 Geom *new_geom = bucket.done_geom(geom);
00768 if (new_geom != (Geom *)NULL) {
00769 geom_node->add_geom(new_geom, bucket._state);
00770 }
00771
00772 return 1;
00773 }
00774
00775
00776
00777
00778
00779
00780
00781 template<class PrimType>
00782 class PrimByType {
00783 public:
00784 int operator () (const PrimType &p1, const PrimType &p2) const {
00785 return p1.get_type() < p2.get_type();
00786 }
00787 };
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 template<class InputIterator, class PrimType>
00798 static int
00799 __mesh_and_build(InputIterator first, InputIterator last,
00800 BuilderBucket &bucket, GeomNode *geom_node,
00801 PrimType *) {
00802 if (first==last) {
00803 return 0;
00804 }
00805
00806 typedef pvector<PrimType> Prims;
00807 Prims prims;
00808 BuilderBucket *local_bucket = NULL;
00809 BuilderBucket *bucket_ptr = &bucket;
00810
00811 if (bucket._mesh) {
00812
00813
00814 local_bucket = bucket.make_copy();
00815 bucket_ptr = local_bucket;
00816 MesherTempl<PrimType> mesher(local_bucket);
00817
00818 for (InputIterator ii = first; ii != last; ++ii) {
00819 mesher.add_prim(*ii);
00820 }
00821 mesher.mesh();
00822 PrimType prim;
00823 prim = mesher.getPrim();
00824 while (prim.get_num_verts() > 0) {
00825 prims.push_back(prim);
00826 prim = mesher.getPrim();
00827 }
00828
00829 } else {
00830
00831 copy(first, last, back_inserter(prims));
00832 }
00833
00834
00835
00836
00837 sort(prims.begin(), prims.end(), PrimByType<PrimType>());
00838
00839 int count = 0;
00840 if (!prims.empty()) {
00841 TYPENAME Prims::iterator pi, last_pi;
00842 pi = prims.begin();
00843 last_pi = pi;
00844 for (++pi; pi != prims.end(); ++pi) {
00845 if ((*pi).get_type() != (*last_pi).get_type()) {
00846 count += build_geoms(last_pi, pi, *bucket_ptr, geom_node, (PrimType*)0);
00847 last_pi = pi;
00848 }
00849 }
00850 count += build_geoms(last_pi, pi, *bucket_ptr, geom_node, (PrimType*)0);
00851 }
00852
00853 if (local_bucket!=NULL) {
00854 delete local_bucket;
00855 }
00856
00857
00858
00859 #ifdef SUPPORT_SHOW_NORMALS
00860 if (bucket._show_normals) {
00861 BuilderNormalVisualizer bnv(bucket);
00862 for (InputIterator ii = first; ii != last; ++ii) {
00863 bnv.add_prim(*ii);
00864 }
00865 bnv.show_normals(geom_node);
00866 }
00867 #endif
00868
00869 return count;
00870 }
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880 template<class InputIterator, class value_type>
00881 int
00882 mesh_and_build(InputIterator first, InputIterator last,
00883 BuilderBucket &bucket, GeomNode *geom_node,
00884 value_type *value_type_ptr) {
00885 return __mesh_and_build(first, last, bucket, geom_node, value_type_ptr);
00886 }
00887
00888
00889
00890
00891
00892
00893
00894 template <class InputIterator, class OutputIterator, class Predicate>
00895 OutputIterator split(InputIterator first, InputIterator last,
00896 OutputIterator true_result, OutputIterator false_result,
00897 Predicate pred) {
00898 while (first != last) {
00899 if (pred(*first)) {
00900 *true_result++ = *first++;
00901 } else {
00902 *false_result++ = *first++;
00903 }
00904 }
00905 return true_result;
00906 }
00907