So... I have this program... It's kind of odd, and an approximation of a fractal - from "The Fractal Geometry of Nature". So... It's hard to tell what's going on.
My problem is that I have global, user defined types, being used as vectors. The only thing I do to these vectors is average them, or set them to one of three vectors. However, I get points OUTSIDE the triangle defined by these three vectors - points that are impossible to get by just averaging three points! HOW?! I'm pretty sure I'm somehow mistreating global user defined type variables... but... I don't see how. Are user defined types passed by reference?
Here's the code:
type vector2
x as float
y as float
endtype
global retvec as vector2
global linevec as vector2
global retvec1 as vector2
global retvec2 as vector2
global retvec3 as vector2
global masterNode as dword
masterNode=alloc zeroed(32)
poke dword masterNode,1
poke dword masterNode+4,2
trivert1 as vector2
trivert2 as vector2
trivert3 as vector2
trivert1.x=10
trivert1.y=10
trivert2.x=10
trivert2.y=screen height()-10
trivert3.x=screen height()-100
trivert3.y=screen height()/2
recurse(masterNode,0)
recurse(masterNode,0)
recurse(masterNode,0)
recurse(masterNode,0)
linevec=trivert1
line trivert1.x,trivert1.y,trivert2.x,trivert2.y
line trivert2.x,trivert2.y,trivert3.x,trivert3.y
line trivert3.x,trivert3.y,trivert1.x,trivert1.y
draw_node(masternode,trivert1,trivert2,trivert3)
sync
wait key
cleanup_node(masterNode)
//0: edge start
//4: edge end
//8: triangle 1
//12: triangle 2
//16: triangle 3
//20: triangle 4
//24: starting cell
//28: ending cell
end
function draw_node(mem as dword,p1 as vector2, p2 as vector2, p3 as vector2)
zerovec as vector2
zerovec.x=0
zerovec.y=0
if mem=0
retvec=zerovec
exitfunction 0
endif
if peek dword(mem+8)=0 and peek dword(mem+12)=0 and peek dword(mem+20)=0
retvec.x=(p1.x+p2.x+p3.x)/3
retvec.y=(p1.y+p2.y+p3.y)/3
exitfunction 1
else
if peek dword(mem+16)=0
getSubNodePos(peek dword(mem+24),p1,p2,p3)
if draw_node(peek dword(mem+4+4*peek dword(mem+24)),retvec1,retvec2,retvec3)=1
line linevec.x,linevec.y,retvec.x,retvec.y
linevec=retvec
exitfunction 0
endif
else
getSubNodePos(peek dword(mem+24),p1,p2,p3)
if draw_node(peek dword(mem+4+4*peek dword(mem+24)),retvec1,retvec2,retvec3)=1
line linevec.x,linevec.y,retvec.x,retvec.y
linevec=retvec
endif
getSubNodePos(3,p1,p2,p3)
if draw_node(peek dword(mem+16),retvec1,retvec2,retvec3)=1
line linevec.x,linevec.y,retvec.x,retvec.y
linevec=retvec
endif
getSubNodePos(peek dword(mem+28),p1,p2,p3)
if draw_node(peek dword(mem+4+4*peek dword(mem+28)),retvec1,retvec2,retvec3)=1
line linevec.x,linevec.y,retvec.x,retvec.y
linevec=retvec
endif
endif
endif
endfunction 0
function getSubNodePos(cell as integer, p1 as vector2, p2 as vector2, p3 as vector2)
if cell=1
retvec1=p1
retvec2.x=(retvec2.x+retvec1.x)/2
retvec2.y=(retvec2.y+retvec1.y)/2
retvec3.x=(retvec3.x+retvec1.x)/2
retvec3.y=(retvec3.y+retvec1.y)/2
exitfunction
endif
if cell=2
retvec2=p2
retvec1.x=(retvec1.x+retvec2.x)/2
retvec1.y=(retvec1.y+retvec2.y)/2
retvec3.x=(retvec3.x+retvec2.x)/2
retvec3.y=(retvec3.y+retvec2.y)/2
exitfunction
endif
if cell=4
retvec3=p3
retvec1.x=(retvec1.x+retvec3.x)/2
retvec1.y=(retvec1.y+retvec3.y)/2
retvec2.x=(retvec2.x+retvec3.x)/2
retvec2.y=(retvec2.y+retvec3.y)/2
exitfunction
endif
if cell=3
retvec3.x=(retvec1.x+retvec2.x)/2
retvec3.y=(retvec1.y+retvec2.y)/2
retvec2.x=(retvec1.x+retvec3.x)/2
retvec2.y=(retvec1.y+retvec3.y)/2
retvec1.x=(retvec3.x+retvec2.x)/2
retvec1.y=(retvec3.y+retvec2.y)/2
exitfunction
endif
endfunction
function recurse(mem as dword, startcell as integer)
if mem=0 then exitfunction 0
if peek dword(mem+8)=0 and peek dword(mem+12)=0 and peek dword(mem+20)=0
ret=div_Node(mem,peek dword(mem),peek dword(mem+4),startcell)
exitfunction ret
else
ret=0
startside=peek dword(mem)
endside=peek dword(mem+4)
if peek dword(mem+16)=0
ret=recurse(peek dword(mem+4+4*peek dword(mem+24)),startcell)
exitfunction ret
else
ret=recurse(peek dword(mem+4+4*peek dword(mem+24)),startcell)
ret=recurse(peek dword(mem+16),ret)
ret=recurse(peek dword(mem+4+4*peek dword(mem+28)),ret)
exitfunction ret
endif
endif
endfunction 0
function cleanup_node(mem as dword)
if peek dword(mem+ 8)>0 then cleanup_node(peek dword(mem+ 8))
if peek dword(mem+12)>0 then cleanup_node(peek dword(mem+12))
if peek dword(mem+16)>0 then cleanup_node(peek dword(mem+16))
if peek dword(mem+20)>0 then cleanup_node(peek dword(mem+20))
free mem
endfunction
function div_Node(mem as dword,startside as integer,endside as integer,startcell as integer)
endcell as integer
endcell=getRandCellTouchingSide(endside)
if startcell=0
startcell=getRandCellTouchingSide(startside)
endif
poke dword mem+24,startcell
poke dword mem+28,endcell
if startcell=endcell
newmem as dword
newmem=alloc zeroed(32)
poke dword mem+4+startcell*4,newmem
poke dword newmem,startside
poke dword newmem+4,endside
else
newmem as dword
newmem=alloc zeroed(32)
poke dword mem+4+startcell*4,newmem
poke dword newmem,getStartSideStartCell(startcell,endcell,startside,endside)
poke dword newmem+4,getEndSideStartCell(startcell,endcell,startside,endside)
newmem=alloc zeroed(32)
poke dword mem+4+endcell*4,newmem
poke dword newmem,getStartSideEndCell(startcell,endcell,startside,endside)
poke dword newmem+4,getEndSideEndCell(startcell,endcell,startside,endside)
newmem=alloc zeroed(32)
poke dword mem+16,newmem
poke dword newmem,getStartSideMidCell(startcell,endcell,startside,endside)
poke dword newmem+4,getEndSideMidCell(startcell,endcell,startside,endside)
endif
ret=0
select endside
case 1
if endcell=1
ret=2
endif
if endcell=2
ret=1
endif
endcase
case 2
if endcell=1
ret=4
endif
if endcell=4
ret=1
endif
endcase
case 3
if endcell=2
ret=4
endif
if endcell=4
ret=2
endif
endcase
endselect
endfunction ret
function getEndSideMidCell(startcell as integer, endcell as integer, startside as integer, endside as integer)
ret=0
select endcell
case 1
ret=3
endcase
case 2
ret=1
endcase
case 4
ret=2
endcase
endselect
endfunction ret
function getStartSideMidCell(startcell as integer, endcell as integer,startside as integer, endside as integer)
ret=0
select startcell
case 1
ret=3
endcase
case 2
ret=1
endcase
case 4
ret=2
endcase
endselect
endfunction ret
function getEndSideEndCell(startcell as integer, endcell as integer,startside as integer, endside as integer)
ret=endside
endfunction ret
function getStartSideEndCell(startcell as integer, endcell as integer,startside as integer, endside as integer)
ret=0
select endcell
case 1
ret=3
endcase
case 2
ret=2
endcase
case 4
ret=1
endcase
endselect
endfunction ret
function getStartSideStartCell(startcell as integer, endcell as integer,startside as integer, endside as integer)
ret=startside
endfunction ret
function getEndSideStartCell(startcell as integer, endcell as integer,startside as integer, endside as integer)
ret=0
select startcell
case 1
ret=3
endcase
case 2
ret=2
endcase
case 4
ret=1
endcase
endselect
endfunction ret
function getRandCellTouchingSide(side as integer)
switchval=rnd(1)
startcell as integer
select side
case 1
if switchval=1
startcell=1
else
startcell=2
endif
endcase
case 2
if switchval=1
startcell=1
else
startcell=4
endif
endcase
case 3
if switchval=1
startcell=2
else
startcell=4
endif
endcase
endselect
endfunction startcell
Also, there is one line setting a global vector to zero, however, it shouldn't ever be called (It's in case I pass a 0 address into the function on accident), and removing it doesn't change the program at all.
[edit]
also, I think this is similar to the cause of many problems I've had with dbp... ones that I finish (or so I think), can't get to run, port to C++ or something, and have it run perfectly :\