Eli hiirellä voi lisätä kulmia, välilyönti tyhjentää polygonin ja enter vaihtaa kolmioiden täytön pois ja päälle. Vasen ja oikea nuoli pyörittävät polygonia ja oikea hiiren painike vaihtaa polygonin paikkaa, Kohdistuspisteet tai polygonin rakennus kuitenkaan ei (vielä) esimerkissä toimi siirretyillä tai käännetyillä polygoneilla.
Code: Select all
SCREEN 800,600
poly = AddPolygon(0,0,0)
DrawToWorld ON
Repeat
If KeyHit(cbkeyspace) Then
DeletePolygon(poly)
poly = AddPolygon(0,0,0)
EndIf
If MouseHit(1) Then AddPolygonVertex(poly,MouseWX(),MouseWY())
If MouseHit(2) Then PositionPolygon(poly,MouseWX(),MouseWY())
If KeyHit(cbkeyreturn) Then fill = Not fill
If LeftKey() Then RotatePolygon(poly,1.0)
If RightKey() Then RotatePolygon(poly,-1.0)
Color cbblue
DrawPolygon(poly,fill)
Color cbwhite
vertex = PeekInt (poly,20)
For i=4 To MEMBlockSize(vertex)-1 Step 8
Circle PeekFloat(vertex,i)-3,PeekFloat(vertex,i+4)-3,7,1
Next i
SetWindow str("FPS: "+FPS())
DrawScreen
Forever
Function PrintMemBlock(mem,datasequence$,offset=0,lenght=0)
Locate 0,0
Print "Sequence.Id Type: Value @ Offset"
If lenght=0 Then memsize = MEMBlockSize(mem) Else memsize = Min(lenght,MEMBlockSize(mem)-offset)
datasize = Len(datasequence$)
pointer=offset
datapointer=1
sequence = 1
While pointer < memsize-1
Select Mid(datasequence$,datapointer,1)
Case "b","B"
b = PeekByte(mem,pointer)
Print sequence+"."+datapointer+" Byte: "+b+" @ "+pointer
pointer=pointer+1
Case "i","I"
i = PeekInt(mem,pointer)
Print sequence+"."+datapointer+" Int: "+i+" @ "+pointer
pointer=pointer+4
Case "f","F"
f# = PeekFloat(mem,pointer)
Print sequence+"."+datapointer+" Float: "+f#+" @ "+pointer
pointer=pointer+4
End Select
datapointer+1
If datapointer>datasize Then datapointer=1 : sequence+1
Wend
WaitKey
End Function
Function PositionPolygon(polygon,x#,y#)
PokeFloat polygon,0,x#
PokeFloat polygon,4,y#
End Function
Function RotatePolygon(polygon,angplus#,ang#=0.0)
curang#=PeekFloat(polygon,8)
If angplus# Then
ang#=curang#+angplus#
EndIf
PokeFloat polygon,8,ang#
Return ang#
End Function
Function AddPolygon(x#,y#,ang#)
mem = MakeMEMBlock(28)
//kirjoitetaan polygonin tiedot
PokeFloat mem,0,x#
PokeFloat mem,4,y#
PokeFloat mem,8,ang#
//hotspot
PokeFloat mem,12,hang#
PokeFloat mem,16,hdis#
vertex = MakeMEMBlock(4)
PokeInt vertex,0,0
PokeInt mem,20,vertex
tri = MakeMEMBlock(4)
PokeInt tri,0,0
PokeInt mem,24,tri
Return mem
End Function
Function DeletePolygon(polygon)
DeleteMEMBlock PeekInt (polygon,20)
DeleteMEMBlock PeekInt (polygon,24)
DeleteMEMBlock polygon
End Function
Function DrawPolygon(polygon,fill)
x# = PeekFloat(polygon,0)
y# = PeekFloat(polygon,4)
ang# = PeekFloat(polygon,8)
tri = PeekInt (polygon,24)
c = PeekInt(tri,0)
If c Then
For i=0 To c-1
pointer = 4+i*24
angle# = PeekFloat(tri,pointer)+ang#
dis# = PeekFloat(tri,pointer+4)
x1# = x# + Cos(angle#)*dis#
y1# = y# - Sin(angle#)*dis#
angle# = PeekFloat(tri,pointer+8)+ang#
dis# = PeekFloat(tri,pointer+12)
x2# = x# + Cos(angle#)*dis#
y2# = y# - Sin(angle#)*dis#
angle# = PeekFloat(tri,pointer+16)+ang#
dis# = PeekFloat(tri,pointer+20)
x3# = x# + Cos(angle#)*dis#
y3# = y# - Sin(angle#)*dis#
Triangle(x1#,y1#,x2#,y2#,x3#,y3#,fill)
Next i
EndIf
End Function
Function TriangulatePolygon(polygon,start=0)
vertex = PeekInt(polygon,20)
c = PeekInt(vertex,0)
If c>3 Then
temp = MakeMEMBlock(MEMBlockSize(polygon))
MemCopy polygon,0,temp,0,MEMBlockSize(polygon)
tempv = MakeMEMBlock(MEMBlockSize(vertex))
MemCopy vertex,0,tempv,0,MEMBlockSize(vertex)
pokeint temp,20,tempv
'PrintMemBlock(temp,"fffffii")
ori = orientation(temp)
i=start
While i < c-1
ear=1
n=i+1
p=i-1
If n>c-1 Then n=0
If p<0 Then p=c-1
point = GetPolygonVertexPointer(temp,i)
ix# = PeekFloat(vertex,point)
iy# = PeekFloat(vertex,point+4)
point = GetPolygonVertexPointer(temp,p)
px# = PeekFloat(vertex,point)
py# = PeekFloat(vertex,point+4)
point = GetPolygonVertexPointer(temp,n)
nx# = PeekFloat(vertex,point)
ny# = PeekFloat(vertex,point+4)
adis# = AngleDistance(GetAngle(px#,py#,ix#,iy#),GetAngle(ix#,iy#,nx#,ny#))
If adis#*ori > 0.0 Then //reflex
ear = 0
Else
For o=0 To c-1
If o<>i And o<>n And o<>p Then
point = GetPolygonVertexPointer(temp,o)
x# = PeekFloat(vertex,point)
y# = PeekFloat(vertex,point+4)
If PointInTriangle(x#, y#, ix#,iy#,nx#,ny#,px#,py#) Then ear = 0
EndIf
Next o
EndIf
If ear Then
AddPolygonTriangle(temp,ix#,iy#,nx#,ny#,px#,py#)
RemovePolygonVertex(temp,i)
vertex =PeekInt(temp,20)
If p=c-1 Then p = c - 2
Return TriangulatePolygon(temp,p)
EndIf
i=i+1
Wend
If ear=0 And start=0 Then MakeError "ERROR: Not a simple polygon, self intersect detected."
TriangulatePolygon(temp)
ElseIf c=3
point = GetPolygonVertexPointer(polygon,0)
ix# = PeekFloat(vertex,point)
iy# = PeekFloat(vertex,point+4)
point = GetPolygonVertexPointer(polygon,1)
px# = PeekFloat(vertex,point)
py# = PeekFloat(vertex,point+4)
point = GetPolygonVertexPointer(polygon,2)
nx# = PeekFloat(vertex,point)
ny# = PeekFloat(vertex,point+4)
AddPolygonTriangle(polygon,ix#,iy#,nx#,ny#,px#,py#)
EndIf
End Function
Function AddPolygonTriangle(polygon,x1#,y1#,x2#,y2#,x3#,y3#)
x# = PeekFloat(polygon,0)
y# = PeekFloat(polygon,4)
tri = PeekInt (polygon,24)
pointer = MEMBlockSize(tri)
ResizeMEMBlock tri,pointer+24
angle# = GetAngle(x#,y#,x1#,y1#)
dis# = Distance(x#,y#,x1#,y1#)
PokeFloat tri,pointer+0,angle#
PokeFloat tri,pointer+4,dis#
angle# = GetAngle(x#,y#,x2#,y2#)
dis# = Distance(x#,y#,x2#,y2#)
PokeFloat tri,pointer+8,angle#
PokeFloat tri,pointer+12,dis#
angle# = GetAngle(x#,y#,x3#,y3#)
dis# = Distance(x#,y#,x3#,y3#)
PokeFloat tri,pointer+16,angle#
PokeFloat tri,pointer+20,dis#
PokeInt tri,0,PeekInt(tri,0)+1
PokeInt polygon,24,tri
'PrintMemBlock(tri,"ffffff",4)
End Function
Function AddPolygonVertex(polygon,x#,y#)
vertex = PeekInt (polygon,20)
pointer = MEMBlockSize(vertex)
ResizeMEMBlock vertex,pointer+8
PokeFloat vertex,pointer+0,x#
PokeFloat vertex,pointer+4,y#
PokeInt vertex,0,PeekInt(vertex,0)+1
PokeInt polygon,20,vertex
DeleteMEMBlock PeekInt (polygon,24)
tri = MakeMEMBlock(4)
PokeInt tri,0,0
PokeInt polygon,24,tri
TriangulatePolygon(polygon)
End Function
Function GetPolygonVertexPointer(polygon,id)
vertex = PeekInt (polygon,20)
size = MEMBlockSize(vertex)
If id*8+4 <= size-8 Then
Return id*8+4
Else
MakeError "No such vertex: "+id
EndIf
End Function
Function RemovePolygonVertex(polygon,id)
vertex = PeekInt (polygon,20)
vertices = PeekInt(vertex,0)
If vertices Then
size = MEMBlockSize(vertex)
pointer = GetPolygonVertexPointer(polygon,id)
lenght = size-pointer-8
If lenght Then
MemCopy vertex,pointer+8,vertex,pointer,lenght
ResizeMEMBlock vertex,size-8
PokeInt polygon,20,vertex
EndIf
PokeInt vertex,0,vertices-1
EndIf
End Function
Function orientation(polygon)
//paluttaa onko polygoni myötäpäivään vai vastapäivään
//n = verteksien lukumäärä¨
vertex = PeekInt (polygon,20)
n = PeekInt(vertex,0)
If n
//haetaan viimeisen ja ensimmäisen verteksin koordinaatit
p = GetPolygonVertexPointer(polygon,n-1)
x1# = PeekFloat(vertex,p)
y1# = PeekFloat(vertex,p+4)
p = GetPolygonVertexPointer(polygon,0)
x2# = PeekFloat(vertex,p)
y2# = PeekFloat(vertex,p+4)
area# = x1# * y2# - x2# * y1#
i=0
//käydään kaikki listan verteksit läpi ja lisätään ne aluesummaan
While i < n-1
p = GetPolygonVertexPointer(polygon,i)
x1# = PeekFloat(vertex,p)
y1# = PeekFloat(vertex,p+4)
p = GetPolygonVertexPointer(polygon,i+1)
x2# = PeekFloat(vertex,p)
y2# = PeekFloat(vertex,p+4)
area# = area# + x1# * y2# - x2# * y1#
i=i+1
Wend
If area# >= 0.0 Then
Return 1
Else
Return -1
EndIf
EndIf
End Function
Function AngleDistance(targetangle#,oldangle#) 'Curves "oldangle" to "targetangle" by "incre" (e.g.homing missile)
targetangle = WrapAngle(targetangle) : oldangle = WrapAngle(oldangle)
If (oldangle + 360) - targetangle < targetangle - oldangle Then oldangle = 360 + oldangle
If (targetangle + 360) - oldangle < oldangle - targetangle Then targetangle = 360 + targetangle
Return (oldangle-targetangle)
End Function
Function PointInTriangle(x#, y#, x1#, y1#, x2#, y2#, x3#, y3#)
ab# = ((y - y1) * (x2 - x1) - (x - x1) * (y2 - y1)) / 1000.0
bc# = ((y - y2) * (x3 - x2) - (x - x2) * (y3 - y2)) / 1000.0
ca# = ((y - y3) * (x1 - x3) - (x - x3) * (y1 - y3)) / 1000.0
If (ab * bc) > 0 And (bc * ca) > 0 Then Return True
Return False
EndFunction
Function Triangle(x1,y1,x2,y2,x3,y3,fill=0) 'by atomimalli
Line x1,y1,x2,y2
Line x2,y2,x3,y3
Line x3,y3,x1,y1
If fill = True Then
If y2<y1 Then 'jos p2 on ylempänä kuin p1 vaihdetaan niiden paikkaa
tmp=y1
y1=y2
y2=tmp
tmp=x1
x1=x2
x2=tmp
EndIf
If y3<y1 Then 'jos p3 on ylempänä kuin p1 vaihdetaan niiden paikkaa
tmp=y1
y1=y3
y3=tmp
tmp=x1
x1=x3
x3=tmp
EndIf
If y3<y2 Then 'jos p3 on ylempänä kuin p2 vaihdetaan niiden paikkaa
tmp=y2
y2=y3
y3=tmp
tmp=x2
x2=x3
x3=tmp
EndIf
'pisteet ovat nyt järjestyksessä
'ylhäältä alas p1(x1,y1), p2(x2,y2), p3(x3,y3)
dy1=y2-y1'pystysuora matka p1:sta p2:seen
dx1=x2-x1'vaakasuora matka p1:sta p2:seen
dy2=y3-y1'pystysuora matka p1:sta p3:meen
dx2=x3-x1'vaakasuora matka p1:sta p3:meen
If dy1 Then 'jos kolmion yläosa on pidempi kuin 0
'käydään läpi kaikki vaakaviivat kolmion yläosassa(p1-p2)
For i = y1 To y2
'lasketaan seuraava x-koordinaatti p1:stä p2:seen
ax=x1+((i-y1)*dx1)/dy1
'lasketaan seuraava x-koordinaatti p1:stä p3:meen
bx=x1+((i-y1)*dx2)/dy2
Line ax,i,bx,i 'piirretään viiva kolmion reunojen välille
Next i
EndIf
dy1=y3-y2'pystysuora matka p2:sta p3:meen
dx1=x3-x2'vaakasuora matka p2:sta p3:meen
If dy1 Then 'jos kolmion alaosa on pidempi kuin 0
'käydään läpi kaikki vaakaviivat kolmion alaosassa(p2-p3)
For i = y2 To y3
'lasketaan seuraava x-koordinaatti p2:stä p3:meen
ax=x2+((i-y2)*dx1)/dy1
'lasketaan seuraava x-koordinaatti p1:stä p3:meen
bx=x1+((i-y1)*dx2)/dy2
Line ax,i,bx,i 'piirretään viiva kolmion reunojen välille
Next i
EndIf
EndIf
EndFunction