heyho, hier ein kleiner code mit dem man bezierkurven rekursiv in geraden zerlegen kann. die können schneller gemalt werden und einfacher für kollisionsüberprüfungen benutzt werden.
hierfür werden die geraden so lange weiter zerteilt, bis der größte abstand zwischen bezierkurve und gerade kleiner als ein grenzwert ist.
ändert ihr den wert "abweichung" in der klasse Bezier könnt ihr die veränderung sehn, die kurve wird immer kantiger je höher der wert gewählt wird.
im beispielprogramm platziert ihr bezierpunkte durch mausklicks, die punkte haben eine waagerechte tangente.
viel spaß damit
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] SuperStrict
Type Bezier Field points:TList=New TList Field drawpoints:TList=New TList Const abweichung:Float=1.0 Method updatepart(a:BezierPoint,b:BezierPoint,from:Float=0,too:Float=1,first:Int=0) Local x1:Float=(1-from)*(1-from)*(1-from)*a.x+ 3*from*(1-from)*(1-from)*a.tan2x+ 3*from*from*(1-from)*b.tan1x+ from*from*from*b.x Local y1:Float=(1-from)*(1-from)*(1-from)*a.y+ 3*from*(1-from)*(1-from)*a.tan2y+ 3*from*from*(1-from)*b.tan1y+ from*from*from*b.y Local x2:Float=(1-too)*(1-too)*(1-too)*a.x+ 3*too*(1-too)*(1-too)*a.tan2x+ 3*too*too*(1-too)*b.tan1x+ too*too*too*b.x Local y2:Float=(1-too)*(1-too)*(1-too)*a.y+ 3*too*(1-too)*(1-too)*a.tan2y+ 3*too*too*(1-too)*b.tan1y+ too*too*too*b.y If(first) drawpoints.addLast([x1,y1]) Local nx:Float=y2-y1 Local ny:Float=-x2+x1 Local d:Float=Sqr(nx*nx+ny*ny) nx:/d ny:/d Local highscore:Float=0 Local hight:Float=from For Local t:Float=from To too Step 0.01 Local x:Float=(1-t)*(1-t)*(1-t)*a.x+ 3*t*(1-t)*(1-t)*a.tan2x+ 3*t*t*(1-t)*b.tan1x+ t*t*t*b.x Local y:Float=(1-t)*(1-t)*(1-t)*a.y+ 3*t*(1-t)*(1-t)*a.tan2y+ 3*t*t*(1-t)*b.tan1y+ t*t*t*b.y Local d:Float=(x-x1)*nx+(y-y1)*ny If(Abs(d)>highscore) hight=t highscore=Abs(d) EndIf Next If(highscore>abweichung) updatepart(a,b,from,hight) updatepart(a,b,hight,too) Else drawpoints.addLast([x2,y2]) EndIf EndMethod Method update() drawpoints=New TList Local lastpoint:BezierPoint=Null Local first:Int=1 For Local a:BezierPoint=EachIn points If(lastpoint<>Null) updatepart(lastpoint,a,0,1,first) first=0 EndIf lastpoint=a Next EndMethod Method draw() Local lastpoint:Float[]=Null Local lastx1:Float Local lasty1:Float Local lastx2:Float Local lasty2:Float Local color:Byte=0 For Local a:Float[]=EachIn drawpoints If(lastpoint<>Null) SetColor 255,0,0 If(color) SetColor 0,0,0 color=Not color Local normalx:Float=lastpoint[1]-a[1] Local normaly:Float=-(lastpoint[0]-a[0]) Local s:Float=Sqr(normalx*normalx+normaly*normaly) normalx:/s normaly:/s Local x1:Float=a[0]+normalx*5 Local y1:Float=a[1]+normaly*5 Local x2:Float=a[0]-normalx*5 Local y2:Float=a[1]-normaly*5
glBegin(GL_QUADS) glVertex2f(x1,y1) glVertex2f(x2,y2) glVertex2f(lastx2,lasty2) glVertex2f(lastx1,lasty1) glEnd()
lastx1:Float=lastpoint[0]+normalx*5 lasty1:Float=lastpoint[1]+normaly*5 lastx2:Float=lastpoint[0]-normalx*5 lasty2:Float=lastpoint[1]-normaly*5 glBegin(GL_QUADS) glVertex2f(x1,y1) glVertex2f(x2,y2) glVertex2f(lastx2,lasty2) glVertex2f(lastx1,lasty1) glEnd() lastx1=x1 lastx2=x2 lasty1=y1 lasty2=y2 Else lastx1=a[0] lastx2=a[0] lasty1=a[1] lasty2=a[1] EndIf lastpoint=a Next EndMethod EndType
Type BezierPoint Field x:Float,y:Float Field tan1x:Float,tan1y:Float Field tan2x:Float,tan2y:Float End Type
SetGraphicsDriver GLMax2DDriver() Graphics 800,600 SetClsColor(255,255,255)
Local b:Bezier=New Bezier
Repeat Cls b.draw() If(MouseHit(1)) Local a:BezierPoint=New Bezierpoint a.x=MouseX() a.y=MouseY() a.tan1x=a.x-50 a.tan1y=a.y a.tan2x=a.x+50 a.tan2y=a.y b.points.addLast(a) b.update() EndIf Flip Until AppTerminate()
getestet unter linux
|