qboolean RecursiveFillOutside (node_t *l, qboolean fill) { portal_t *p; int s; if (l->contents == CONTENTS_SOLID || l->contents == CONTENTS_SKY) return false; if (l->valid == valid) return false; if (l->occupied) { hit_occupied = l->occupied; backdraw = 1000; return true; } l->valid = valid; // fill it and it's neighbors if (fill) { l->contents = CONTENTS_SOLID; l->planenum = -1; } outleafs++; for (p=l->portals ; p ; ) { s = (p->nodes[0] == l); if (RecursiveFillOutside (p->nodes[s], fill) ) { // leaked, so stop filling if (backdraw-- > 0) { MarkLeakTrail (p); DrawLeaf (l, 2); } return true; } p = p->next[!s]; } return false; }
qboolean RecursiveFillOutside (node_t *l, qboolean fill) { portal_t *p; int s; if (l->contents == CONTENTS_SOLID || l->contents == CONTENTS_SKY) return false; if (l->valid == valid) return false; if (l->occupied) { hit_occupied = l->occupied; // LordHavoc: this was missing from the released source... odd return true; } l->valid = valid; // fill it and it's neighbors if (fill) l->contents = CONTENTS_SOLID; outleafs++; for (p = l->portals; p;) { s = (p->nodes[0] == l); if (RecursiveFillOutside (p->nodes[s], fill) ) { // leaked, so stop filling if (!hullnum) { MarkLeakTrail (p); DrawLeaf (l, 2); } return true; } p = p->next[!s]; } return false; }
//------------------------------------------------------------------------------ void TreeDrawer::Draw () { NodeIterator <Node> n (t->GetRoot()); Node *q = n.begin(); while (q) { if (q->IsLeaf ()) { DrawLeaf (q); } else { DrawInternal (q); } q = n.next(); } if (rooted) { DrawRoot (); } }
/* ================ NumberLeafs_r ================ */ void NumberLeafs_r (node_t *node) { portal_t *p; if (!node->contents) { // decision node node->visleafnum = -99; NumberLeafs_r (node->children[0]); NumberLeafs_r (node->children[1]); return; } Draw_ClearWindow (); DrawLeaf (node, 1); if (node->contents == CONTENTS_SOLID) { // solid block, viewpoint never inside node->visleafnum = -1; return; } node->visleafnum = num_visleafs++; for (p = node->portals ; p ; ) { if (p->nodes[0] == node) // only write out from first leaf { if ( (watervis && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID) || (p->nodes[0]->contents == p->nodes[1]->contents) ) num_visportals++; p = p->next[0]; } else p = p->next[1]; } }
//----------------------------------------------------------------------------- // Draw a particular subcircuit with its top left corner at *cx and *cy (in // characters). If it is a leaf element then just print it and return; else // loop over the elements of the subcircuit and call ourselves recursively. // At the end updates *cx and *cy. // // In simulation mode, returns TRUE the circuit is energized after the given // element, else FALSE. This is needed to colour all the wires correctly, // since the colouring indicates whether a wire is energized. //----------------------------------------------------------------------------- BOOL DrawElement(int which, void *elem, int *cx, int *cy, BOOL poweredBefore) { BOOL poweredAfter; int cx0 = *cx, cy0 = *cy; ElemLeaf *leaf = (ElemLeaf *)elem; SetBkColor(Hdc, InSimulationMode ? HighlightColours.simBg : HighlightColours.bg); NormText(); if(elem == Selected && !InSimulationMode) { EmphText(); ThisHighlighted = TRUE; } else { ThisHighlighted = FALSE; } switch(which) { case ELEM_SERIES_SUBCKT: { int i; ElemSubcktSeries *s = (ElemSubcktSeries *)elem; poweredAfter = poweredBefore; for(i = 0; i < s->count; i++) { poweredAfter = DrawElement(s->contents[i].which, s->contents[i].d.any, cx, cy, poweredAfter); } break; } case ELEM_PARALLEL_SUBCKT: { int i; ElemSubcktParallel *p = (ElemSubcktParallel *)elem; int widthMax = CountWidthOfElement(which, elem, (*cx)/POS_WIDTH); int heightMax = CountHeightOfElement(which, elem); poweredAfter = FALSE; int lowestPowered = -1; int downBy = 0; for(i = 0; i < p->count; i++) { BOOL poweredThis; poweredThis = DrawElement(p->contents[i].which, p->contents[i].d.any, cx, cy, poweredBefore); if(InSimulationMode) { if(poweredThis) poweredAfter = TRUE; PoweredText(poweredThis); } while((*cx - cx0) < widthMax*POS_WIDTH) { int gx = *cx/POS_WIDTH; int gy = *cy/POS_HEIGHT; if(CheckBoundsUndoIfFails(gx, gy)) return FALSE; DM_BOUNDS(gx, gy); DisplayMatrix[gx][gy] = PADDING_IN_DISPLAY_MATRIX; DisplayMatrixWhich[gx][gy] = ELEM_PADDING; char buf[256]; int j; for(j = 0; j < POS_WIDTH; j++) { buf[j] = '-'; } buf[j] = '\0'; DrawChars(*cx, *cy + (POS_HEIGHT/2), buf); *cx += POS_WIDTH; } *cx = cx0; int justDrewHeight = CountHeightOfElement(p->contents[i].which, p->contents[i].d.any); *cy += POS_HEIGHT*justDrewHeight; downBy += justDrewHeight; if(poweredThis) { lowestPowered = downBy - 1; } } *cx = cx0 + POS_WIDTH*widthMax; *cy = cy0; int j; BOOL needWire; if(*cx/POS_WIDTH != ColsAvailable) { needWire = FALSE; for(j = heightMax - 1; j >= 1; j--) { if(j <= lowestPowered) PoweredText(poweredAfter); if(DisplayMatrix[*cx/POS_WIDTH - 1][*cy/POS_HEIGHT + j]) { needWire = TRUE; } if(needWire) VerticalWire(*cx - 1, *cy + j*POS_HEIGHT); } // stupid special case if(lowestPowered == 0 && InSimulationMode) { EmphText(); DrawChars(*cx - 1, *cy + (POS_HEIGHT/2), "+"); } } PoweredText(poweredBefore); needWire = FALSE; for(j = heightMax - 1; j >= 1; j--) { if(DisplayMatrix[cx0/POS_WIDTH][*cy/POS_HEIGHT + j]) { needWire = TRUE; } if(needWire) VerticalWire(cx0 - 1, *cy + j*POS_HEIGHT); } break; } default: poweredAfter = DrawLeaf(which, leaf, cx, cy, poweredBefore); break; } NormText(); return poweredAfter; }
/* ================ CutNodePortals_r ================ */ void CutNodePortals_r (node_t *node) { plane_t *plane, clipplane; node_t *f, *b, *other_node; portal_t *p, *new_portal, *next_portal; winding_t *w, *frontwinding, *backwinding; int side; // CheckLeafPortalConsistancy (node); // // seperate the portals on node into it's children // if (node->contents) { return; // at a leaf, no more dividing } plane = &planes[node->planenum]; f = node->children[0]; b = node->children[1]; // // create the new portal by taking the full plane winding for the cutting plane // and clipping it by all of the planes from the other portals // new_portal = AllocPortal (); new_portal->planenum = node->planenum; w = BaseWindingForPlane (&planes[node->planenum]); side = 0; // shut up compiler warning for (p = node->portals ; p ; p = p->next[side]) { clipplane = planes[p->planenum]; if (p->nodes[0] == node) side = 0; else if (p->nodes[1] == node) { clipplane.dist = -clipplane.dist; VectorSubtract (vec3_origin, clipplane.normal, clipplane.normal); side = 1; } else Error ("CutNodePortals_r: mislinked portal"); w = ClipWinding (w, &clipplane, true); if (!w) { printf ("WARNING: CutNodePortals_r:new portal was clipped away\n"); break; } } if (w) { // if the plane was not clipped on all sides, there was an error new_portal->winding = w; AddPortalToNodes (new_portal, f, b); } // // partition the portals // for (p = node->portals ; p ; p = next_portal) { if (p->nodes[0] == node) side = 0; else if (p->nodes[1] == node) side = 1; else Error ("CutNodePortals_r: mislinked portal"); next_portal = p->next[side]; other_node = p->nodes[!side]; RemovePortalFromNode (p, p->nodes[0]); RemovePortalFromNode (p, p->nodes[1]); // // cut the portal into two portals, one on each side of the cut plane // DivideWinding (p->winding, plane, &frontwinding, &backwinding); if (!frontwinding) { if (side == 0) AddPortalToNodes (p, b, other_node); else AddPortalToNodes (p, other_node, b); continue; } if (!backwinding) { if (side == 0) AddPortalToNodes (p, f, other_node); else AddPortalToNodes (p, other_node, f); continue; } // the winding is split new_portal = AllocPortal (); *new_portal = *p; new_portal->winding = backwinding; FreeWinding (p->winding); p->winding = frontwinding; if (side == 0) { AddPortalToNodes (p, f, other_node); AddPortalToNodes (new_portal, b, other_node); } else { AddPortalToNodes (p, other_node, f); AddPortalToNodes (new_portal, other_node, b); } } DrawLeaf (f,1); DrawLeaf (b,2); CutNodePortals_r (f); CutNodePortals_r (b); }