Seite 1 von 1

Lust auf ein paar Farben?

Verfasst: 01.06.2005 04:20
von NicTheQuick
Steuerung:
- Maus bewegt Punkt 1. Punkte 2 und 3 bewegen sich von selbst.
- F1 und F2 für andere Formeln
- ALT-F4 zum Beenden oder auf das X klicken :wink:

Wer Lust und Laune hat, findet vielleicht noch mehr interessante Einstellungen oder baut das ganze für beliebig viele Punkte um.

Code: Alles auswählen

InitSprite()
OpenWindow(0, 0, 0, 640, 480, #PB_Window_ScreenCentered | #PB_Window_SystemMenu, "blabla")
OpenWindowedScreen(WindowID(0), 0, 0, 640, 480, 0, 0, 0)

Structure PointF
  x.f
  y.f
  rx.f
  ry.f
EndStructure

P1.PointF 

P2.PointF
P2\x = Random(639)
P2\y = Random(479)
P2\rx = Random(100) / 50
P2\ry = Random(100) / 50

P3.PointF
P3\x = Random(639)
P3\y = Random(479)
P3\rx = Random(100) / 50
P3\ry = Random(100) / 50

D1.PointF
D2.PointF
D3.PointF

M_SQR = 0
M_Invert = 1
KeyTime.l
#ReleaseTime = 250

Repeat
  P1\x = WindowMouseX()
  P1\y = WindowMouseY()
  
  P2\x + P2\rx
  P2\y + P2\ry
  P3\x + P3\rx
  P3\y + P3\ry
  
  If P2\x < 0 Or P2\x > 639 : P2\rx = -P2\rx : EndIf
  If P2\y < 0 Or P2\y > 479 : P2\ry = -P2\ry : EndIf
  If P3\x < 0 Or P3\x > 639 : P3\rx = -P3\rx : EndIf
  If P3\y < 0 Or P3\y > 479 : P3\ry = -P3\ry : EndIf
  
  If ElapsedMilliseconds() > KeyTime
    If GetAsyncKeyState_(#VK_F1)
      KeyTime = ElapsedMilliseconds() + #ReleaseTime
      M_SQR ! 1
    EndIf
    If GetAsyncKeyState_(#VK_F2)
      KeyTime = ElapsedMilliseconds() + #ReleaseTime
      M_Invert ! 1
    EndIf
  EndIf
  
  StartDrawing(ScreenOutput())
    For x.l = 0 To 639
      
      D1\x = x - P1\x
      D2\x = x - P2\x
      D3\x = x - P3\x
      D1\x * D1\x
      D2\x * D2\x
      D3\x * D3\x
      For y.l = 0 To 479
        D1\y = y - P1\y
        D2\y = y - P2\y
        D3\y = y - P3\y
        D1\y * D1\y
        D2\y * D2\y
        D3\y * D3\y
        
        r.f = D1\x + D1\y
        g.f = D2\x + D2\y
        b.f = D3\x + D3\y
        If M_SQR
          r = Sqr(r)
          g = Sqr(g)
          b = Sqr(b)
        EndIf
        If M_Invert
          r = 1 / r
          g = 1 / g
          b = 1 / b
        EndIf
        
        f.f = 1/(r+g+b)
        r * f 
        g * f
        b * f
        
        Plot(x, y, RGB(r * 255, g * 255, b * 255))
      Next
    Next
    DrawingMode(1)
    Locate(P2\x - 4, P2\y - 8)
    DrawText("2")
    Locate(P3\x - 4, P3\y - 8)
    DrawText("3")
    Locate(0, 0)
    DrawText("M_SQR: " + Str(M_SQR))
    Locate(0, 16)
    DrawText("M_Invert: " + Str(M_Invert))
  StopDrawing()
  FlipBuffers()
Until WindowEvent() = #PB_EventCloseWindow
CloseScreen()
CloseWindow(0)

Verfasst: 01.06.2005 07:35
von Norbie
Sieht voll cool aus! :allright:

Erstaunlich wie kurz der Quellcode ist :shock:
Man muss es wohl einfach nur drauf haben :mrgreen:

Verfasst: 01.06.2005 10:55
von Kukulkan
Sehr schön! :allright:

Sieht Super aus!

Volker

Verfasst: 01.06.2005 12:26
von Green Snake
stimme zu, wirklich cool

sicher nützlich, für was weis ich jetzt nicht, aber jedenfalls nütslich, weils so gut aussieht :allright:

Verfasst: 01.06.2005 12:42
von DrShrek
Green Snake hat geschrieben:stimme zu, wirklich cool

sicher nützlich, für was weis ich jetzt nicht, aber jedenfalls nütslich, weils so gut aussieht :allright:
Eindeutig als Screensaver geignet.
Nur die Maus muss halt simuliert werden (Random())

Verfasst: 15.12.2006 16:06
von NicTheQuick
Hab das ganze mal wieder etwas umgebaut. Es hat für Tests meiner
Raytracing-Engine herhalten müssen und ob meine Farbmisch-
Berechnungen exakt sind.

In Zeile 111 bei CompilerSelect lassen sich 4 verschiedene Sachen
einstellen.

///Edit 1:
Einen Farbfilter gibt es in Zeile 66.

///Edit 2:
Ich hatte noch einen Fehler drin bei dem Farbmischmakro Mix3FColor3.

Viel Spaß damit!

Code: Alles auswählen

#Width = 400
#Height = 300

InitSprite()
OpenWindow(0, 0, 0, #Width, #Height, "blabla", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0), 0, 0, #Width, #Height, 0, 0, 0)

Structure PointF
  x.f
  y.f
  Rx.f
  Ry.f
EndStructure

Define.PointF p1, p2, p3, p4, P, D1, D2, D3, offset

p2\x = Random(#Width - 1)
p2\y = Random(#Height - 1)
p2\Rx = Random(200) / 50
p2\Ry = Random(200) / 50

p3\x = Random(#Width - 1)
p3\y = Random(#Height - 1)
p3\Rx = Random(200) / 50
p3\Ry = Random(200) / 50

;a, b, c    - Punkte des Dreiecks (a: Ausgangspunkt für offset)
;p          - anderer Punkt
;offset     - beinhaltet die relative Position von p im Dreieck
Procedure GetOffset(*a.PointF, *b.PointF, *c.PointF, *p.PointF, *Offset.PointF)
  Protected u.PointF, v.PointF
  
  u\x = *b\x - *a\x   ;Bestimmung des Richtungsvektors von a zu b
  u\y = *b\y - *a\y
  
  v\x = *c\x - *a\x   ;Bestimmung des Richtungsvektors von a zu c
  v\y = *c\y - *a\y
  
  ;Errechnung des Offsets
  *Offset\y = (*p\y - u\y * ((*p\x - *a\x) / u\x) - *a\y) / (- v\x * u\y / u\x + v\y)
  *Offset\x = (*p\x - *Offset\y * v\x - *a\x) / u\x
EndProcedure

Structure RTC3F
  r.f
  g.f
  b.f
EndStructure

Define.RTC3F Color1, Color2, Color3, Color4, Color, Filter

;Mischt Farben für ein Dreieck (0 <= (ratio1 + ratio2) <= 1)
Macro Mix3FColor3(out, in1, in2, in3, ratio1, ratio2)
  out\r = (ratio1 * ratio2) * (in1\r - 0.5 * (in2\r + in3\r)) + ratio1 * (in2\r - in1\r) + ratio2 * (in3\r - in1\r) + in1\r
  out\g = (ratio1 * ratio2) * (in1\g - 0.5 * (in2\g + in3\g)) + ratio1 * (in2\g - in1\g) + ratio2 * (in3\g - in1\g) + in1\g
  out\b = (ratio1 * ratio2) * (in1\b - 0.5 * (in2\b + in3\b)) + ratio1 * (in2\b - in1\b) + ratio2 * (in3\b - in1\b) + in1\b
EndMacro

;Mischt Farben für ein Viereck (0 <= ratio1 <= 1, 0 <= ratio2 <= 1)
Macro Mix3FColor4(out, in1, in2, in3, in4, ratio1, ratio2)
  out\r = (ratio1 * ratio2) * (in1\r - in2\r - in3\r + in4\r) + ratio1 * (in2\r - in1\r) + ratio2 * (in3\r - in1\r) + in1\r
  out\g = (ratio1 * ratio2) * (in1\g - in2\g - in3\g + in4\g) + ratio1 * (in2\g - in1\g) + ratio2 * (in3\g - in1\g) + in1\g
  out\b = (ratio1 * ratio2) * (in1\b - in2\b - in3\b + in4\b) + ratio1 * (in2\b - in1\b) + ratio2 * (in3\b - in1\b) + in1\b
EndMacro

Macro VectorLength(in)
  Sqr(in\x * in\x + in\y + in\y)
EndMacro

Macro Distance(in1, in2)
  Sqr((in1\x - in2\x) * (in1\x - in2\x) + (in1\y - in2\y) * (in1\y - in2\y))
EndMacro

Macro DistanceSq(in1, in2)
  ((in1\x - in2\x) * (in1\x - in2\x) + (in1\y - in2\y) * (in1\y - in2\y))
EndMacro

;Filter für die Farbkanäle
Filter\r = 1
Filter\g = 1
Filter\b = 1

;Farben für die Ecken
Color1\r = 1
Color1\g = 0
Color1\b = 0

Color2\r = 1
Color2\g = 0
Color2\b = 0

Color3\r = 1
Color3\g = 0
Color3\b = 0

Color4\r = 0
Color4\g = 0
Color4\b = 0

Define.d dist1, dist2, dist3, dist4, dist

Define mode.l = 0, maxmode = 7

Define KeyTime.l, KeyReleaseTime.l = 250

Repeat
  p1\x = WindowMouseX(0)
  p1\y = WindowMouseY(0)
  
  If ElapsedMilliseconds() > KeyTime
    If GetAsyncKeyState_(#VK_UP)
      KeyTime = ElapsedMilliseconds() + KeyReleaseTime
      mode = (mode + 1) % (maxmode + 1)
    EndIf
    If GetAsyncKeyState_(#VK_DOWN)
      KeyTime = ElapsedMilliseconds() + KeyReleaseTime
      mode = (mode + maxmode) % (maxmode + 1)
    EndIf
  EndIf
  
  p2\x + p2\Rx
  p2\y + p2\Ry
  p3\x + p3\Rx
  p3\y + p3\Ry
  
  If p2\x < 0 Or p2\x > #Width - 1 : p2\Rx = -p2\Rx : EndIf
  If p2\y < 0 Or p2\y > #Height - 1 : p2\Ry = -p2\Ry : EndIf
  If p3\x < 0 Or p3\x > #Width - 1 : p3\Rx = -p3\Rx : EndIf
  If p3\y < 0 Or p3\y > #Height - 1 : p3\Ry = -p3\Ry : EndIf
  
  StartDrawing(ScreenOutput())
    For x.l = 0 To #Width - 1
      For y.l = 0 To #Height - 1
        P\x = x
        P\y = y
        
        Select mode   ;Hier Werte zwischen 0 und 3 einsetzen
          Case 0 ;Zeigt nur Inhalt des Dreiecks an
            GetOffset(p1, p2, p3, P, offset)
            If offset\x >= 0 And offset\y >= 0 And offset\x + offset\y <= 1
              Mix3FColor3(Color, Color1, Color2, Color3, offset\x, offset\y)
            Else
              Color\r = 0;Color1\r
              Color\g = 0;Color1\g
              Color\b = 0;Color1\b
            EndIf
          
          Case 1 ;Zeigt Farbwerte in- und außerhalb des Dreiecks
            GetOffset(p1, p2, p3, P, offset)
            Mix3FColor3(Color, Color1, Color2, Color3, offset\x, offset\y)
            If Color\r < 0 : Color\r = 0 : EndIf
            If Color\g < 0 : Color\g = 0 : EndIf
            If Color\b < 0 : Color\b = 0 : EndIf
            If Color\r > 1 : Color\r = 1 : EndIf
            If Color\g > 1 : Color\g = 1 : EndIf
            If Color\b > 1 : Color\b = 1 : EndIf
          
          Case 2 ;Zeigt Farbwerte innerhalb des Parallelogramms
            GetOffset(p1, p2, p3, P, offset)
            If offset\x >= 0 And offset\y >= 0 And offset\x <= 1 And offset\y <= 1
              Mix3FColor4(Color, Color1, Color2, Color3, Color4, offset\x, offset\y)
            Else
              Color\r = 0
              Color\g = 0
              Color\b = 0
            EndIf
          
         Case 3 ;Zeigt Farbwerte in- und außerhalb des Parallelogramms
            GetOffset(p1, p2, p3, P, offset)
            Mix3FColor4(Color, Color1, Color2, Color3, Color4, offset\x, offset\y)
            If Color\r < 0 : Color\r = 0 : EndIf
            If Color\g < 0 : Color\g = 0 : EndIf
            If Color\b < 0 : Color\b = 0 : EndIf
            If Color\r > 1 : Color\r = 1 : EndIf
            If Color\g > 1 : Color\g = 1 : EndIf
            If Color\b > 1 : Color\b = 1 : EndIf
          
          Case 4
            dist1 = 1 / Distance(P, p1)
            dist2 = 1 / Distance(P, p2)
            dist3 = 1 / Distance(P, p3)
            dist = 1 / (dist1 + dist2 + dist3)
            dist1 * dist
            dist2 * dist
            dist3 * dist
            Color\r = Color1\r * dist1 + Color2\r * dist2 + Color3\r * dist3
            Color\g = Color1\g * dist1 + Color2\g * dist2 + Color3\g * dist3
            Color\b = Color1\b * dist1 + Color2\b * dist2 + Color3\b * dist3
          
          Case 5
            dist1 = 1 / DistanceSq(P, p1)
            dist2 = 1 / DistanceSq(P, p2)
            dist3 = 1 / DistanceSq(P, p3)
            dist = 1 / (dist1 + dist2 + dist3)
            dist1 * dist
            dist2 * dist
            dist3 * dist
            Color\r = Color1\r * dist1 + Color2\r * dist2 + Color3\r * dist3
            Color\g = Color1\g * dist1 + Color2\g * dist2 + Color3\g * dist3
            Color\b = Color1\b * dist1 + Color2\b * dist2 + Color3\b * dist3
          
          Case 6
            dist1 = 1 / Distance(P, p1)
            dist2 = 1 / Distance(P, p2)
            dist3 = 1 / Distance(P, p3)
            dist4 = 1 / Distance(P, p4)
            dist = 1 / (dist1 + dist2 + dist3 + dist4)
            dist1 * dist
            dist2 * dist
            dist3 * dist
            dist4 * dist
            Color\r = Color1\r * dist1 + Color2\r * dist2 + Color3\r * dist3 + Color4\r * dist4
            Color\g = Color1\g * dist1 + Color2\g * dist2 + Color3\g * dist3 + Color4\g * dist4
            Color\b = Color1\b * dist1 + Color2\b * dist2 + Color3\b * dist3 + Color4\b * dist4
          
          Case 7
            dist1 = 1 / DistanceSq(P, p1)
            dist2 = 1 / DistanceSq(P, p2)
            dist3 = 1 / DistanceSq(P, p3)
            dist4 = 1 / DistanceSq(P, p4)
            dist = 1 / (dist1 + dist2 + dist3 + dist4)
            dist1 * dist
            dist2 * dist
            dist3 * dist
            dist4 * dist
            Color\r = Color1\r * dist1 + Color2\r * dist2 + Color3\r * dist3 + Color4\r * dist4
            Color\g = Color1\g * dist1 + Color2\g * dist2 + Color3\g * dist3 + Color4\g * dist4
            Color\b = Color1\b * dist1 + Color2\b * dist2 + Color3\b * dist3 + Color4\b * dist4
        EndSelect
        
        ;*plott* *plott*
        Plot(x, y, RGB(Color\r * Filter\r * 255, Filter\g * Color\g * 255, Filter\b * Color\b * 255))
      Next
    Next
    
    p4\x = p2\x + p3\x - p1\x
    p4\y = p2\y + p3\y - p1\y
    LineXY(p1\x, p1\y, p2\x, p2\y, $FFFFFF)
    LineXY(p2\x, p2\y, p3\x, p3\y, $FFFFFF)
    LineXY(p3\x, p3\y, p1\x, p1\y, $FFFFFF)
    LineXY(p2\x, p2\y, p4\x, p4\y, $FFFFFF)
    LineXY(p3\x, p3\y, p4\x, p4\y, $FFFFFF)
    
    DrawingMode(1)
    DrawText(0, 0, "Mode: " + Str(mode), $FFFFFF)
    DrawText(p1\x - 4, p1\y - 8, "1", $FFFFFF)
    DrawText(p2\x - 4, p2\y - 8, "2", $FFFFFF)
    DrawText(p3\x - 4, p3\y - 8, "3", $FFFFFF)
    DrawText(p4\x - 4, p4\y - 8, "4", $FFFFFF)
  StopDrawing()
  FlipBuffers()
Until WindowEvent() = #PB_Event_CloseWindow
CloseScreen()
CloseWindow(0)

Verfasst: 19.12.2006 17:50
von Spirit
Was genau macht denn die GetOffset Prozedur? Werden da die
baryzentrischen Koordinaten des Punktes im Dreieck berechnet?

Verfasst: 19.12.2006 18:53
von NicTheQuick
Ich kennzeichne jetzt mal alle Vektoren mit dem Präfix v_ um dir das zu
erklären. Ob das die baryzentrischen Koordinaten sind, kann ich dir
nämlich so nicht sagen und laut Wikipedia glaube ich das sowieso nicht.

Du übergibst der Funktion deine drei Eckpunkte des Dreiecks v_p1, v_p2
und v_p3. Und dazu noch den Punkt, zu dem du das Offset wissen willst.

Innerhalb der Funktion werden v_u und v_v ausgerechnet:
v_u = v_p2 - v_p1
v_v = v_p3 - v_p1

Dann wird das Offset ausgerechnet, mit dem du folgendes erreichen
kannst:
v_p = (offset\x * v_u) + (offset\y * v_v)

Du kannst jetzt also durch v_u, v_v und das Offset wieder deinen
Punkt bekommen, weil das Offset das Verhältnis zu v_u und v_v angibt.

Wenn dein Punkt innerhalb des Dreiecks liegt, dann gilt:
0 <= offset\x + offset\y <= 1

Wenn v_p1, v_p2 und v_p3 ein Parallelogramm bilden, dann gilt:
0 <= offset\x <= 1
0 <= offset\y <= 1

Alles, was nicht zutrifft, ist außerhalb des Dreiecks oder des
Parallelogramms.


Auch wenn ich nicht weiß wie die Koordinaten heißen, die ich damit
errechne, weiß ich zumindest, was sie bedeuten. Ich hab die Formel ja
nicht umsonst von Hand ausgerechnet. :)

Verfasst: 20.12.2006 17:09
von Spirit
Jetzt weiß ich bescheid, danke für die Erklärung! :allright:

Verfasst: 21.12.2006 02:15
von NicTheQuick
Ich hab noch einen Fehler bemerkt in meiner RayTracing-Engine als es um
das Farben mischen ging. Der Fehler ist jetzt oben behoben. Siehe Edit 2.