Seite 2 von 5

Verfasst: 28.06.2007 21:40
von Kiffi
CSprengel hat geschrieben:*grinst*
*auchgrins* OK, jetzt habe ich Deinen Text auch richtig gelesen.
Nix für ungut ;-)

Grüße ... Kiffi

Re: 3D-Koordinaten in 2D-Koordinaten umrechnen

Verfasst: 29.06.2007 00:18
von Kaeru Gaman
NicTheQuick hat geschrieben:Das langsamste an der Include ist die Berechnung der Kamera-Achsen,
wenn ein oder mehrere Winkel geändert wurden. Die Umrechnungs-
Procedure selbst kommt ohne Winkelfunktionen aus und ist
daher auch recht schnell.
probier doch, precalculated tables zu benutzen...

Verfasst: 29.06.2007 15:27
von NicTheQuick
@Kaeru:
Ja, das wäre natürlich eine Möglichkeit, aber für diesen Zweck schon etwas
übertrieben, wie ich finde.

@all:
Ich habe die Include etwas geändert. Fehler ausgemerzt und weniger
Winkelfunktionen benutzt. Pro Winkeländerung werden jetzt 6 mal Cos() und
Sin() auf allen drei Achsen angewandt. Weniger geht nicht. :wink:

Für Sonderwünsche einfach melden. Vielleicht krieg ich das ja hin.

Ich bin mir nicht sicher, ob meine Berechnungen stimmen, wenn man den
Würfel z.B. oben links in der Ecke sieht und dann mit der Maus so
schwenkt, dass er nach unten oder rechts wandert. Dann scheint es, als ob
er sich leicht neigen würde. Ich hab das mal realistisch mit meiner
Handy-Kamera nachgespielt: Ein weißes Blatt Papier, das den Würfel
darstellen soll, neigt sich auch etwas. Also wird es wohl stimmen, oder?

Verfasst: 04.07.2007 21:37
von NicTheQuick
Falls jemand ein bisschen mit der SuperFormel herumspielen will. Weitere
Infos und Links finden sich bei Wikipedia.

Tasten:
- Numpad 1-6: Auswählen der Parameter
- Numpad 0: Wechseln der Superformel
- Bild Hoch/Runter: Ändern der Werte

Code: Alles auswählen

EnableExplicit

;Schnellerer Cos() und Sin() über Array und Macros gelöst
Global Dim RAD2CosSin.d($FFFFF)
Define _.l
#RT_RAD2CosSin = $FFFFF / (#PI * 2)
For _ = 0 To $FFFFF : RAD2CosSin(_) = Sin(_ * #PI * 2 / $FFFFF) : Next
Macro Sin(RAD)
  RAD2CosSin(Int(RAD * #RT_RAD2CosSin) & $FFFFF)
EndMacro
Macro Cos(RAD)
  RAD2CosSin(Int(RAD * #RT_RAD2CosSin + $3FFFF) & $FFFFF)
EndMacro

Macro SuperFormel(W, m, a, b, n1, n2, n3)
  Pow(Pow(Abs(Cos(m * W * 0.25) / a), n2) + Pow(Abs(Sin(m * W * 0.25) / b), n3), -1 / n1)
EndMacro
Macro SuperFormelS(W, SF)
  Pow(Pow(Abs(Cos(SF\m * W * 0.25) / SF\a), SF\n2) + Pow(Abs(Sin(SF\m * W * 0.25) / SF\b), SF\n3), -1 / SF\n1)
EndMacro

Structure Dots
  p.V3D
  c.l
EndStructure
Structure SuperFormel
  m.d
  a.d
  b.d
  n1.d
  n2.d
  n3.d
EndStructure

Procedure.l SelectedColor(Selected.l, nr.l)
  If Selected = nr
    ProcedureReturn $FF
  EndIf
  
  ProcedureReturn $FFFFFF
EndProcedure
Procedure DrawSF(x.l, y.l, *SF.SuperFormel, Selected.l = 0)
  Protected s.s
  s = "m=" + StrD(*SF\m, 3)
  DrawText(x, y, s, SelectedColor(Selected, 1))
  x + TextWidth(s) + 10
  s = "a=" + StrD(*SF\a, 3)
  DrawText(x, y, s, SelectedColor(Selected, 2))
  x + TextWidth(s) + 10
  s = "b=" + StrD(*SF\b, 3)
  DrawText(x, y, s, SelectedColor(Selected, 3))
  x + TextWidth(s) + 10
  s = "n1=" + StrD(*SF\n1, 3)
  DrawText(x, y, s, SelectedColor(Selected, 4))
  x + TextWidth(s) + 10
  s = "n2=" + StrD(*SF\n2, 3)
  DrawText(x, y, s, SelectedColor(Selected, 5))
  x + TextWidth(s) + 10
  s = "n3=" + StrD(*SF\n3, 3)
  DrawText(x, y, s, SelectedColor(Selected, 6))
EndProcedure
Procedure.d GetSFValue(*SF.SuperFormel, nr.l)
  Select nr
    Case 1 : ProcedureReturn *SF\m
    Case 2 : ProcedureReturn *SF\a
    Case 3 : ProcedureReturn *SF\b
    Case 4 : ProcedureReturn *SF\n1
    Case 5 : ProcedureReturn *SF\n2
    Case 6 : ProcedureReturn *SF\n3
  EndSelect
EndProcedure
Procedure SetSFValue(*SF.SuperFormel, nr.l, Value.d)
  Select nr
    Case 1 : *SF\m  = Value
    Case 2 : *SF\a  = Value
    Case 3 : *SF\b  = Value
    Case 4 : *SF\n1 = Value
    Case 5 : *SF\n2 = Value
    Case 6 : *SF\n3 = Value
  EndSelect
EndProcedure

Global Width.l = 800, Height.l = 600

Define SF1.SuperFormel, SF2.SuperFormel
Define d.d, e.d, R1.d, R2.d, d_add.d, e_add.d, dot.Dots
Define Selected.l
d_add = 0.025
e_add = 0.025

With SF1
  \m = 1
  \a = 1
  \b = 1
  \n1 = 1
  \n2 = 1
  \n3 = 1
EndWith

With SF2
  \m = 1
  \a = 1
  \b = 1
  \n1 = 1
  \n2 = 1
  \n3 = 1
EndWith

If Not (InitSprite() And InitKeyboard() And InitMouse()) : End : EndIf

If OpenWindow(0, 0, 0, Width, Height, "Superformel in 3D") = 0 : End : EndIf
If OpenWindowedScreen(WindowID(0), 0, 0, Width, Height, 0, 0, 0) = 0 : End : EndIf

Define p.V3D, a.V3D, p2d.V3D, SF.d

Define p_add.d, a_add.d, FOV.d, sf_add.d
p_add.d = 0.05
a_add.d = 1.5
sf_add.d = 0.1
FOV.d = 45


Selected = 1

Define *Camera.Camera
*Camera.Camera = Camera_New()
Camera_Size(*Camera, 0, Width - 1, 0, Height - 1)

Repeat
  ClearScreen(0)
  ExamineKeyboard()
  ExamineMouse()
  
  p\x = 0 : p\y = 0 : p\z = 0
  a\x = 0 : a\y = 0 : a\z = 0
  If KeyboardPushed(#PB_Key_LeftControl) Or KeyboardPushed(#PB_Key_RightControl)
    If KeyboardPushed(#PB_Key_Up)    : p\y - p_add : EndIf
    If KeyboardPushed(#PB_Key_Down)  : p\y + p_add : EndIf
    If KeyboardPushed(#PB_Key_Left)  : a\y - a_add : EndIf
    If KeyboardPushed(#PB_Key_Right) : a\y + a_add : EndIf
  Else
    If KeyboardPushed(#PB_Key_Up)    : p\z + p_add : EndIf
    If KeyboardPushed(#PB_Key_Down)  : p\z - p_add : EndIf
    If KeyboardPushed(#PB_Key_Left)  : p\x - p_add : EndIf
    If KeyboardPushed(#PB_Key_Right) : p\x + p_add : EndIf
  EndIf
  
  a\x + MouseDeltaY() * 0.5
  a\y + MouseDeltaX() * 0.5
  
  If KeyboardPushed(#PB_Key_A)     : a\x + a_add : EndIf
  If KeyboardPushed(#PB_Key_Z)     : a\x - a_add : EndIf
  If KeyboardPushed(#PB_Key_S)     : a\z + a_add : EndIf
  If KeyboardPushed(#PB_Key_X)     : a\z - a_add : EndIf
  If KeyboardPushed(#PB_Key_D) And FOV > 0.25    : FOV - 0.25 : EndIf
  If KeyboardPushed(#PB_Key_C) And FOV < 179.75  : FOV + 0.25 : EndIf
  
  If KeyboardReleased(#PB_Key_Pad1)  : Selected - (Selected - 1) % 6 + 0 : EndIf
  If KeyboardReleased(#PB_Key_Pad2)  : Selected - (Selected - 1) % 6 + 1 : EndIf
  If KeyboardReleased(#PB_Key_Pad3)  : Selected - (Selected - 1) % 6 + 2 : EndIf
  If KeyboardReleased(#PB_Key_Pad4)  : Selected - (Selected - 1) % 6 + 3 : EndIf
  If KeyboardReleased(#PB_Key_Pad5)  : Selected - (Selected - 1) % 6 + 4 : EndIf
  If KeyboardReleased(#PB_Key_Pad6)  : Selected - (Selected - 1) % 6 + 5 : EndIf
  If KeyboardReleased(#PB_Key_Pad0)  : Selected  = (Selected + 5) % 12 + 1: EndIf
  
  SF = 0
  If KeyboardPushed(#PB_Key_PageUp)   : SF + sf_add : EndIf
  If KeyboardPushed(#PB_Key_PageDown) : SF - sf_add : EndIf
  
  SetSFValue(SF1, Selected, GetSFValue(SF1, Selected) + SF)
  SetSFValue(SF2, Selected - 6, GetSFValue(SF2, Selected - 6) + SF)
  
  Camera_FOV(*Camera, FOV)
  Camera_Move(*Camera, p, a)
  
  StartDrawing(ScreenOutput())
    d = -#PI
    While d <= #PI 
      d + d_add
      R1 = SuperFormelS(d, SF1)
      
      e = -#PI * 0.5
      While e <= #PI * 0.5
        e + e_add
        R2 = SuperFormelS(e, SF2)
        
        dot\p\x = Cos(d) * R1 * Cos(e) * R2
        dot\p\y = Sin(d) * R1 * Cos(e) * R2
        dot\p\z = Sin(e) * R2
        dot\c = $FFFFFF;RGB((d + #PI) * 255 / (2 * #PI), (e + #PI * 0.5) * 255 / #PI, 255)
        
        If Camera_3Dto2D(*Camera, dot\p, p2d)
          Plot(p2d\x, p2d\y, dot\c)
        EndIf
      Wend
    Wend
    
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawSF(0, 0, SF1, Selected)
    DrawSF(0, 16, SF2, Selected - 6)
  StopDrawing()
  
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
///Edit:
Hab die Superformel berichtigt. Sie war falsch.

Verfasst: 04.07.2007 21:46
von THEEX
Falls jemand ein bisschen mit der SuperFormel herumspielen will. Weitere
Infos und Links finden sich bei Wikipedia.
Etwas mehr Info würde die Suche deutlich vereinfachen...

Verfasst: 05.07.2007 19:59
von hardfalcon
Ich wäre nie auf die Idee gekommen, nen Renderer als "Projektion von 3D-Koordinaten auf eine 2D-Fläche" zu betrachten. Da kann ich nur sagen: Faszinierend! :allright:

Verfasst: 06.07.2007 16:33
von NicTheQuick
@CSprengel:
Ja, ich hatte gerade wenig Zeit um viel zu schreiben, war in Eile.
Aber im Grund finden sich unter Weblinks bei Wikipedia die besten Links
dazu. Ein schöner mit Erklärung und Beispielen ist der hier: 3D Supershape / Superformula

@hardfalcon:
Es ist kein Renderer, nur ein bisschen Rechnerei. Klingt ähnlich, aber mehr
macht die Include wirklich nicht.

Verfasst: 20.09.2007 14:23
von Scarabol
@Nic
Falls du noch immer nen Anreiz suchst kannst du ja noch ein Beispiel mit Sprites erstellen...
Dann währste schon fast bei ner kompletten 3D Engine, naja fast eben...

Gruß
Scarabol

Verfasst: 22.09.2007 17:10
von Scarabol
Hi Leute,

1. ich hab mal versucht ein Beispiel zu schreiben das Quadrate zwischen den einzelnen Punkten anzeigt (wie Terrain). Aber irgendwie tauchen falsche Linien auf und ich weiß nicht wie ich die Filtern soll.
http://www.purebasic.fr/german/viewtopi ... 9&start=20

2. Wie kann ich die Entfernung von Punkt zu Kamera ermitteln und die angezeigten Punkte danach begrenzen?

Gruß
Scarabol

Verfasst: 22.09.2007 18:29
von NicTheQuick
zu 1.: Das passiert dann, wenn du den Rückgabewert von 'Camera_3Dto2D()'
nicht auswertest. Bei #True, liegt die 2D-Koordinate im sichtbaren Bereich,
bei #False nicht.

zu 2.: Du kannst den letzten Parameter von 'Camera_3Dto2D()' nutzen, um
herauszufinden in welcher relativen Entfernung zur Kamera der 3D-Punkt
liegt, der übergeben wurde. Wenn die Z-Koordinate von '*c3d' negativ ist,
liegt der Punkt z.B. hinter der Kamera. Wenn die X-Koordinate negativ ist,
links von der Kamera und wenn die Y-Koordinate negativ ist, unter der
Kamera.

Du solltest also die Punkte dann nicht anzeigen, wenn die Funktion #False
zurückgibt oder wenn die Z-Koordinate von '*c3d* negativ ist.