diff options
| author | Simon Robertshaw <simon@hardwired.org.uk> | 2012-06-12 17:41:36 (GMT) |
|---|---|---|
| committer | Simon Robertshaw <simon@hardwired.org.uk> | 2012-06-12 17:41:36 (GMT) |
| commit | 391165409ddcf14b4a888b5aac90871999caa9a2 (patch) | |
| tree | f6d642c5869c822639b0fadd25a48d12882f9ffe /src/simulation/Simulation.cpp | |
| parent | 10f51cb586d2a1846ab395e76b0b33a2693ddf50 (diff) | |
| download | powder-391165409ddcf14b4a888b5aac90871999caa9a2.zip powder-391165409ddcf14b4a888b5aac90871999caa9a2.tar.gz | |
TPT: New flood_parts function, should fix crashing due to too much recursion a11202313d
Diffstat (limited to 'src/simulation/Simulation.cpp')
| -rw-r--r-- | src/simulation/Simulation.cpp | 214 |
1 files changed, 140 insertions, 74 deletions
diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index 30b2fcc..5bc64b9 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -345,11 +345,18 @@ Particle Simulation::Get(int x, int y) return Particle(); } +#define PMAP_CMP_CONDUCTIVE(pmap, t) (((pmap)&0xFF)==(t) || (((pmap)&0xFF)==PT_SPRK && parts[(pmap)>>8].ctype==(t))) + int Simulation::FloodParts(int x, int y, int fullc, int cm, int bm, int flags) { int c = fullc&0xFF; - int x1, x2, dy = 1; + int x1, x2, dy = (c<PT_NUM)?1:CELL; int co = c; + int coord_stack_limit = XRES*YRES; + unsigned short (*coord_stack)[2] = (short unsigned int (*)[2])malloc(sizeof(unsigned short)*2*coord_stack_limit); + int coord_stack_size = 0; + int created_something = 0; + if (c==SPC_PROP) return 0; if (cm==PT_INST&&co==PT_SPRK) @@ -362,8 +369,6 @@ int Simulation::FloodParts(int x, int y, int fullc, int cm, int bm, int flags) cm = pmap[y][x]&0xFF; if (!cm) return 0; - //if ((flags&BRUSH_REPLACEMODE) && cm!=SLALT) - // return 0; } else cm = 0; @@ -381,89 +386,150 @@ int Simulation::FloodParts(int x, int y, int fullc, int cm, int bm, int flags) else bm = 0; } - - if (((pmap[y][x]&0xFF)!=cm || bmap[y/CELL][x/CELL]!=bm )/*||( (flags&BRUSH_SPECIFIC_DELETE) && cm!=SLALT)*/) + + if (((pmap[y][x]&0xFF)!=cm || bmap[y/CELL][x/CELL]!=bm )) return 1; - - // go left as far as possible - x1 = x2 = x; - while (x1>=CELL) + + coord_stack[coord_stack_size][0] = x; + coord_stack[coord_stack_size][1] = y; + coord_stack_size++; + + do { - if ((pmap[y][x1-1]&0xFF)!=cm || bmap[y/CELL][(x1-1)/CELL]!=bm) + coord_stack_size--; + x = coord_stack[coord_stack_size][0]; + y = coord_stack[coord_stack_size][1]; + x1 = x2 = x; + // go left as far as possible + while (x1>=CELL) { - break; + if ((pmap[y][x1-1]&0xFF)!=cm || bmap[y/CELL][(x1-1)/CELL]!=bm) + { + break; + } + x1--; } - x1--; - } - while (x2<XRES-CELL) - { - if ((pmap[y][x2+1]&0xFF)!=cm || bmap[y/CELL][(x2+1)/CELL]!=bm) + // go right as far as possible + while (x2<XRES-CELL) { - break; + if ((pmap[y][x2+1]&0xFF)!=cm || bmap[y/CELL][(x2+1)/CELL]!=bm) + { + break; + } + x2++; } - x2++; - } - - // fill span - for (x=x1; x<=x2; x++) - { - if (cm==PT_INST&&co==PT_SPRK) + // fill span + for (x=x1; x<=x2; x++) { - if (create_part(-1,x, y, fullc)==-1) - return 0; + if (cm==PT_INST&&co==PT_SPRK) + { + if (create_part(-1, x, y, fullc)>=0) + created_something = 1; + } + else + { + if (CreateParts(x, y, 0, 0, fullc, flags)) + created_something = 1; + } } - else if (!CreateParts(x, y, 0, 0, fullc, flags)) - return 0; - } - // fill children - if (cm==PT_INST&&co==PT_SPRK)//wire crossing for INST - { - if (y>=CELL+dy && x1==x2 && - ((pmap[y-1][x1-1]&0xFF)==PT_INST||(pmap[y-1][x1-1]&0xFF)==PT_SPRK) && ((pmap[y-1][x1]&0xFF)==PT_INST||(pmap[y-1][x1]&0xFF)==PT_SPRK) && ((pmap[y-1][x1+1]&0xFF)==PT_INST || (pmap[y-1][x1+1]&0xFF)==PT_SPRK) && - (pmap[y-2][x1-1]&0xFF)!=PT_INST && ((pmap[y-2][x1]&0xFF)==PT_INST ||(pmap[y-2][x1]&0xFF)==PT_SPRK) && (pmap[y-2][x1+1]&0xFF)!=PT_INST) - FloodParts(x1, y-2, fullc, cm, bm, flags); - else if (y>=CELL+dy) - for (x=x1; x<=x2; x++) - if ((pmap[y-1][x]&0xFF)!=PT_SPRK) + + // add vertically adjacent pixels to stack + if (cm==PT_INST&&co==PT_SPRK) + { + //wire crossing for INST + if (y>=CELL+1 && x1==x2 && + PMAP_CMP_CONDUCTIVE(pmap[y-1][x1-1], PT_INST) && PMAP_CMP_CONDUCTIVE(pmap[y-1][x1], PT_INST) && PMAP_CMP_CONDUCTIVE(pmap[y-1][x1+1], PT_INST) && + !PMAP_CMP_CONDUCTIVE(pmap[y-2][x1-1], PT_INST) && PMAP_CMP_CONDUCTIVE(pmap[y-2][x1], PT_INST) && !PMAP_CMP_CONDUCTIVE(pmap[y-2][x1+1], PT_INST)) + { + // travelling vertically up, skipping a horizontal line + if ((pmap[y-2][x1]&0xFF)==PT_INST) { - if (x==x1 || x==x2 || y>=YRES-CELL-1 || - (pmap[y-1][x-1]&0xFF)==PT_INST || (pmap[y-1][x+1]&0xFF)==PT_INST || - (pmap[y+1][x-1]&0xFF)==PT_INST || ((pmap[y+1][x]&0xFF)!=PT_INST&&(pmap[y+1][x]&0xFF)!=PT_SPRK) || (pmap[y+1][x+1]&0xFF)==PT_INST) - FloodParts(x, y-dy, fullc, cm, bm, flags); - + coord_stack[coord_stack_size][0] = x1; + coord_stack[coord_stack_size][1] = y-2; + coord_stack_size++; + if (coord_stack_size>=coord_stack_limit) + return -1; } - - if (y<YRES-CELL-dy && x1==x2 && - ((pmap[y+1][x1-1]&0xFF)==PT_INST||(pmap[y+1][x1-1]&0xFF)==PT_SPRK) && ((pmap[y+1][x1]&0xFF)==PT_INST||(pmap[y+1][x1]&0xFF)==PT_SPRK) && ((pmap[y+1][x1+1]&0xFF)==PT_INST || (pmap[y+1][x1+1]&0xFF)==PT_SPRK) && - (pmap[y+2][x1-1]&0xFF)!=PT_INST && ((pmap[y+2][x1]&0xFF)==PT_INST ||(pmap[y+2][x1]&0xFF)==PT_SPRK) && (pmap[y+2][x1+1]&0xFF)!=PT_INST) - FloodParts(x1, y+2, fullc, cm, bm, flags); - else if (y<YRES-CELL-dy) - for (x=x1; x<=x2; x++) - if ((pmap[y+1][x]&0xFF)!=PT_SPRK) + } + else if (y>=CELL+1) + { + for (x=x1; x<=x2; x++) { - if (x==x1 || x==x2 || y<0 || - (pmap[y+1][x-1]&0xFF)==PT_INST || (pmap[y+1][x+1]&0xFF)==PT_INST || - (pmap[y-1][x-1]&0xFF)==PT_INST || ((pmap[y-1][x]&0xFF)!=PT_INST&&(pmap[y-1][x]&0xFF)!=PT_SPRK) || (pmap[y-1][x+1]&0xFF)==PT_INST) - FloodParts(x, y+dy, fullc, cm, bm, flags); - + if ((pmap[y-1][x]&0xFF)==PT_INST) + { + if (x==x1 || x==x2 || y>=YRES-CELL-1 || !PMAP_CMP_CONDUCTIVE(pmap[y+1][x], PT_INST)) + { + // if at the end of a horizontal section, or if it's a T junction + coord_stack[coord_stack_size][0] = x; + coord_stack[coord_stack_size][1] = y-1; + coord_stack_size++; + if (coord_stack_size>=coord_stack_limit) + return -1; + } + } } - } - else - { - if (y>=CELL+dy) - for (x=x1; x<=x2; x++) - if ((pmap[y-dy][x]&0xFF)==cm && bmap[(y-dy)/CELL][x/CELL]==bm) - if (!FloodParts(x, y-dy, fullc, cm, bm, flags)) - return 0; - if (y<YRES-CELL-dy) - for (x=x1; x<=x2; x++) - if ((pmap[y+dy][x]&0xFF)==cm && bmap[(y+dy)/CELL][x/CELL]==bm) - if (!FloodParts(x, y+dy, fullc, cm, bm, flags)) - return 0; - } - if (!(cm==PT_INST&&co==PT_SPRK)) - return 1; - return 0; + } + + if (y<YRES-CELL-1 && x1==x2 && + PMAP_CMP_CONDUCTIVE(pmap[y+1][x1-1], PT_INST) && PMAP_CMP_CONDUCTIVE(pmap[y+1][x1], PT_INST) && PMAP_CMP_CONDUCTIVE(pmap[y+1][x1+1], PT_INST) && + !PMAP_CMP_CONDUCTIVE(pmap[y+2][x1-1], PT_INST) && PMAP_CMP_CONDUCTIVE(pmap[y+2][x1], PT_INST) && !PMAP_CMP_CONDUCTIVE(pmap[y+2][x1+1], PT_INST)) + { + // travelling vertically down, skipping a horizontal line + if ((pmap[y+2][x1]&0xFF)==PT_INST) + { + coord_stack[coord_stack_size][0] = x1; + coord_stack[coord_stack_size][1] = y+2; + coord_stack_size++; + if (coord_stack_size>=coord_stack_limit) + return -1; + } + } + else if (y<YRES-CELL-1) + { + for (x=x1; x<=x2; x++) + { + if ((pmap[y+1][x]&0xFF)==PT_INST) + { + if (x==x1 || x==x2 || y<0 || !PMAP_CMP_CONDUCTIVE(pmap[y-1][x], PT_INST)) + { + // if at the end of a horizontal section, or if it's a T junction + coord_stack[coord_stack_size][0] = x; + coord_stack[coord_stack_size][1] = y+1; + coord_stack_size++; + if (coord_stack_size>=coord_stack_limit) + return -1; + } + + } + } + } + } + else + { + if (y>=CELL+dy) + for (x=x1; x<=x2; x++) + if ((pmap[y-dy][x]&0xFF)==cm && bmap[(y-dy)/CELL][x/CELL]==bm) + { + coord_stack[coord_stack_size][0] = x; + coord_stack[coord_stack_size][1] = y-dy; + coord_stack_size++; + if (coord_stack_size>=coord_stack_limit) + return -1; + } + if (y<YRES-CELL-dy) + for (x=x1; x<=x2; x++) + if ((pmap[y+dy][x]&0xFF)==cm && bmap[(y+dy)/CELL][x/CELL]==bm) + { + coord_stack[coord_stack_size][0] = x; + coord_stack[coord_stack_size][1] = y+dy; + coord_stack_size++; + if (coord_stack_size>=coord_stack_limit) + return -1; + } + } + } while (coord_stack_size>0); + free(coord_stack); + return created_something; } int Simulation::FloodWalls(int x, int y, int c, int cm, int bm, int flags) |
