Seite 1 von 1

3D Meshes etc. während Laufzeit erstellen

Verfasst: 22.03.2007 16:42
von Olaf
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.

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

Hab den Fehler gefunden

Verfasst: 26.03.2007 23:23
von 4DWelt
Du must 2 Dateien aus PureBasic\Compilers
in das selbe Verzeichnis wie deine exe kopieren
Engine3D.dll und stlport_vc646.dll.

Habs Probiert Es funktioniert.:allright:

Ich interessiere mich zur Zeit auch für 3D Programmierung.
Will eine Step datei ISO 10303-21 einlesen können.

dein Beispiel könnte mich vieleicht weiterbringen.
Kannst du mir Vieleicht erklären wie ein mesh
aufgebaut wird. Und welche zusammenhänge in SetMeschData
bestehen.

Blick in der Hilfe Beschreibung nicht durch. :cry:

Verfasst: 27.03.2007 18:34
von Olaf
@4DWelt: Danke...wie konnt ich nur so blöd sein und die DLLs vergessen??? :lol:
Bis das mit den Meshes genau erklärt ist dauert 'n bisschen. Am besten kontaktierste mich mal per icq oder telefon (06851-81927). Bis ich das nämlich postingreif zusammengeschrieben hätte...das könnt dauern. :lol:

P.S.: werd's aber später Posten.