3D Meshes etc. während Laufzeit erstellen
Verfasst: 22.03.2007 16:42
Ich hab mich mal in letzter Zeit (ist im Moment aber auch schon eig. wieder länger her) mit der 3D-Darstellung befasst, um Funktionen im 3-dimensionalen Raum zeichnen zu lassen. Also mussten 3D-Objekte während der Laufzeit erstellt werden.
So habe ich schließlich einen Weg gefunden mittels Speichermanipulation 3D-Objekte zu erzeugen. Leider hat die Sache im Moment noch ein paar Haken.
Beispielsweise ist die Darstellung nur im Modus #PB_Camera_Wireframe korrekt. Ausserdem stürzt das fertige Programm immer sofort ab, obwohl es in PureBasic noch fehlerfrei läuft.
Die zugehörige Fehlerquelle habe ich bisher leider noch nicht finden können.
So habe ich schließlich einen Weg gefunden mittels Speichermanipulation 3D-Objekte zu erzeugen. Leider hat die Sache im Moment noch ein paar Haken.
Beispielsweise ist die Darstellung nur im Modus #PB_Camera_Wireframe korrekt. Ausserdem stürzt das fertige Programm immer sofort ab, obwohl es in PureBasic noch fehlerfrei läuft.
Die zugehörige Fehlerquelle habe ich bisher leider noch nicht finden können.
Code: Alles auswählen
Global Term.s
Global Function
MaxF=11 ;Maximale Anzahl der Funktionen
Function=Random(MaxF) ;Startfunktion per Zufall auswählen
Procedure.d Function(x.d,y.d)
Select Function
Case 0
Erg.d=Cos(Sqr(x*x+y*y))*8*Pow(0.9,x*x+y*y)
Term="f(x,y) = Cos(Sqr( x² + y² )) * 8 * 0,9^( x² + y² )"
Case 1
Erg.d=x*y/2
Term="f(x,y) = x * y / 2"
Case 2
Erg.d=Sqr(16-x*x-y*y)
Term="f(x,y) = Sqr( 16 - x² - y²)"
Case 3
Erg.d=x*x+y*y-4
Term="f(x,y) = x² + y² - 4"
Case 4
Erg.d=Cos(1/(x*y))
Term="f(x,y) = Cos( 1 / ( x * y ))"
Case 5
Erg.d=Sin(1/Sqr(x*x+y*y))
Term="f(x,y) = Sin( 1 / Sqr( x² + y² ))"
Case 6
Erg.d=Cos(x)*Sin(y)
Term="f(x,y) = Cos( x ) * Sin( y )"
Case 7
Erg.d=Cos(Sqr(x*x*y*y))
Term="f(x,y) = Cos(Sqr( x²y² ))"
Case 8
Erg.d=Log(Sqr(x*x*y*y)+0.125)
Term="f(x,y) = Log(Sqr( x²y² ) + 0,125 )"
Case 9
Erg.d=ATan(x*y)
Term="f(x,y) = ATan( x * y )"
Case 10
Erg.d=1/(Pow((Abs(x)-0.5),2)+Pow((Abs(y)-0.5),2)+0.125)
Term="f(x,y) = 1/( |x-0,5|² + |y-0,5|² + 0,125 )"
Case 11
Erg.d=Log(y+4)/Log(2)+Cos(x*#PI)
Term="f(x,y) = Log2( y + 4 ) + Cos( x * "+StrD(#PI,5)+" )"
EndSelect
ProcedureReturn Erg
EndProcedure
Procedure GetColor(Vertex.d) ;Prozedur zur Farbgebung der Scheitel
;Achtung: nicht RGB-, sondern BGR-codiert!!!! -> alle R- bzw. B-Werte vertauscht
Vertex=-Vertex
If Vertex>4
Color.l=RGB(Round(255-255/(Vertex-3),0),Round(255-255/(Vertex-3),0),255)
ElseIf Vertex<=4 And Vertex>=-4
Int.l =Round(255*(Vertex+4)/8,0)
Group.l=Round(Int/51,0)
Select Group
Case 0 ;magenta->blau
Color.l=RGB(255,0,255-5*Int)
Case 1 ;blau->cyan
Color.l=RGB(255,5*(Int-51),0)
Case 2 ;cyan->grün
Color.l=RGB(255-5*(Int-102),255,0)
Case 3 ;grün->gelb
Color.l=RGB(0,255,5*(Int-153))
Case 4 ;gelb->rot
Color.l=RGB(0,255-5*(Int-204),255)
EndSelect
ElseIf Vertex<-4
Color.l=RGB(Round(255/(-3-Vertex),0),0,Round(255/(-3-Vertex),0))
EndIf
ProcedureReturn Color
EndProcedure
Procedure Create3DData(Columns.l,Rows.l,MinX.d,MinY.d,MaxX.d,MaxY.d)
*Vertexes=AllocateMemory(16*(Columns+1)*(Rows+1)) ;Speicher für alle Scheiteldaten reservieren
PVertex=*Vertexes ;Pointer auf Anfang setzen
StepX.d=(MaxX-MinX)/Columns ;Schrittweite in X-Richtung
StepY.d=(MaxY-MinY)/Rows ;Schrittweite in Y-Richtung
For py=0 To Rows
For px=0 To Columns
x.d=MinX+StepX*px ;mathematisches x berechnen
y.d=MinY+StepY*py ;mathematisches y berechnen
Vertex.d=-Function(x,y) ;z=f(x,y) berechnen
Color=GetColor(Vertex) ;Scheitelfärbung vornehmen
PokeF(PVertex,(px*400/Columns)-200):PVertex+4 ;X-Koordinaten in Speicher schreiben
PokeF(PVertex, -50*Vertex ):PVertex+4 ;Z-Koordinaten in Speicher schreiben
PokeF(PVertex,(py*400/Rows) -200):PVertex+4 ;Y-Koordinaten in Speicher schreiben
PokeL(PVertex,Color):PVertex+4 ;Farbwert in Speicher schreiben
Next px
Next py
ProcedureReturn *Vertexes
EndProcedure
Columns=160 ;Spalten
Rows=160 ;Zeilen
p=0
Dim NBVertex(Columns,Rows)
For y=0 To Rows
For x=0 To Columns
NBVertex(x,y)=p
p+1
Next x
Next y
#Mesh=0
#Material=0
#Entity=0
#Camera=0
*CornerData=AllocateMemory(12*Columns*Rows) ;pro "Kästchen" 2 Dreiecke à 3 Word Daten -> 12 Bytes pro "Kästchen"
InitEngine3D()
InitSprite()
InitSprite3D()
InitKeyboard()
OpenWindow(0,0,0,600,450,"3D-Funktionen",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0),0,0,600,450,0,0,0)
CreateMesh(#Mesh,(Columns+1)*(Rows+1))
CreateTexture(0,256,256)
SetMeshData(#Mesh,#PB_Mesh_Vertex|#PB_Mesh_Color,Create3DData(Columns,Rows,-4,-4,4,4),(Columns+1)*(Rows+1))
CData=0
Pointer=*CornerData
For y=0 To Rows-1
For x=0 To Columns-1
PokeW(Pointer,NBVertex(x ,y )):Pointer+2 ; *--*
PokeW(Pointer,NBVertex(x+1,y )):Pointer+2 ; | /
PokeW(Pointer,NBVertex(x ,y+1)):Pointer+2 ; *
CData+1
PokeW(Pointer,NBVertex(x+1,y )):Pointer+2 ; *
PokeW(Pointer,NBVertex(x ,y+1)):Pointer+2 ; / |
PokeW(Pointer,NBVertex(x+1,y+1)):Pointer+2 ; *--*
CData+1
Next x
Next y
SetMeshData(#Mesh,#PB_Mesh_Face,*CornerData,CData)
StartDrawing(TextureOutput(0))
Box(0,0,256,256,16777215)
StopDrawing()
CreateMaterial(#Material,TextureID(0))
CreateEntity(#Entity,MeshID(#Mesh),MaterialID(#Material))
MaterialAmbientColor(#Material,#PB_Material_AmbientColors)
MaterialSpecularColor(#Material,16777215)
CreateLight(0,16777215,0,0,0)
LightSpecularColor(0,16777215)
CreateCamera(#Camera,0,0,100,100)
CameraLocate(#Camera,0,0,707)
RotateCamera(#Camera,0,0,180)
CameraBackColor(#Camera,$000000)
CameraRenderMode(#Camera,#PB_Camera_Wireframe)
Fog($000000,1,500,1000)
chv=700
crl=0
cou=0
vrl=0
vou=0
Repeat
ExamineKeyboard()
event=WindowEvent()
ClearScreen(0)
If KeyboardPushed(#PB_Key_Left) ;Kamera links drehen
vrl+1:If vrl>359:vrl=0:EndIf
ElseIf KeyboardPushed(#PB_Key_Right) ;Kamera rechts drehen
vrl-1:If vrl<0:vrl=359:EndIf
EndIf
If KeyboardPushed(#PB_Key_Up) ;Kamera nach oben drehen
vou+1:If vou>359:vou=0:EndIf
ElseIf KeyboardPushed(#PB_Key_Down) ;Kamera nach unten drehen
vou-1:If vou<0:vou=359:EndIf
EndIf
If KeyboardPushed(#PB_Key_PageUp) ;Kamera höher verschieben
cou+10:If cou>1000:cou=1000:EndIf
ElseIf KeyboardPushed(#PB_Key_PageDown) ;Kamera niedriger verschieben
cou-10:If cou<-1000:cou=-1000:EndIf
EndIf
If KeyboardPushed(#PB_Key_A) ;Kamera nach links verschieben
crl-10:If crl<-1000:crl=-1000:EndIf
ElseIf KeyboardPushed(#PB_Key_D) ;Kamera nach rechts verschieben
crl+10:If crl>1000:crl=1000:EndIf
EndIf
If KeyboardPushed(#PB_Key_W) ;Kamera räumlich weiter in den Hintergrund
chv-10:If chv<-1000:chv=-1000:EndIf
ElseIf KeyboardPushed(#PB_Key_S) ;Kamera räumlich weiter in den Vordergrund
chv+10:If chv>1000:chv=1000:EndIf
EndIf
If KeyboardPushed(#PB_Key_L) ;Kamera zurücksetzen
chv=700
crl=0
cou=0
vrl=0
vou=0
EndIf
If KeyboardPushed(#PB_Key_O) ;Kamera auf Koordinatenursprung (0|0|0) setzen
chv=0
crl=0
cou=0
vrl=0
vou=0
EndIf
If KeyboardPushed(#PB_Key_C) ;Funktion wechseln
Function=Random(MaxF)
SetMeshData(#Mesh,#PB_Mesh_Vertex|#PB_Mesh_Color,Create3DData(Columns,Rows,-4,-4,4,4),(Columns+1)*(Rows+1))
EndIf
If KeyboardPushed(#PB_Key_K)
Function+1:If Function>MaxF:Function=0:EndIf
SetMeshData(#Mesh,#PB_Mesh_Vertex|#PB_Mesh_Color,Create3DData(Columns,Rows,-4,-4,4,4),(Columns+1)*(Rows+1))
EndIf
If KeyboardPushed(#PB_Key_J)
Function-1:If Function<0:Function=MaxF:EndIf
SetMeshData(#Mesh,#PB_Mesh_Vertex|#PB_Mesh_Color,Create3DData(Columns,Rows,-4,-4,4,4),(Columns+1)*(Rows+1))
EndIf
CameraLocate(#Camera,crl,cou,chv)
CameraLookAt(#Camera,crl,cou,chv-100)
RotateCamera(#Camera,vrl,vou,0)
LightLocate(0,crl,cou,chv)
RenderWorld()
StartDrawing(ScreenOutput())
DrawingMode(#PB_2DDrawing_Transparent|#PB_2DDrawing_Outlined)
FrontColor(16777215)
BackColor(0)
Box(06,09,290,41)
DrawText(10, 10,"Funktion "+Str(Function+1)+":")
DrawText(10, 30,Term)
Box(06,52,90,80)
DrawText(10, 53,"Kamera:")
DrawText(10, 73,"X: "+StrD(crl/50,1))
DrawText(10, 93,"Y: "+StrD(chv/50,1))
DrawText(10,113,"Z: "+StrD(cou/50,1))
Box(06,135,90,60)
DrawText(10,136,"Blickwinkel:")
DrawText(10,156,"X: "+Str(vou%360)+"°")
DrawText(10,176,"Z: "+Str(vrl%360)+"°")
Box(06,198,90,20)
DrawText(10,199,Str(Engine3DFrameRate(#PB_Engine3D_Current))+" FPS")
Box(299,200,2,50)
Box(275,224,50,2)
StopDrawing()
FlipBuffers()
Delay(15)
Until event=#PB_Event_CloseWindow