addict selbst ist schon etwas betagt. Neue Demotools arbeiten besser und kommen völlig ohne Wrapper aus, weil sie meist einen WYSIWYG Editor heben.
Ein Beispiel dafür wäre 3D Dead Deer.
addict selbst ist schon etwas betagt. Neue Demotools arbeiten besser und kommen völlig ohne Wrapper aus, weil sie meist einen WYSIWYG Editor heben.
Ein Beispiel dafür wäre 3D Dead Deer.
Ich dachte Farbrausch wäre eine Deutsche Gruppe, was nahe liegend ist, aber dem ist nicht so...
Natürlich ist es eine deutsche Gruppe :D. Aus Hamburg. Hier eine kleine uralte Doku von arte dazu: http://www.youtube.com/watch?v=hqh1iXIlyJk
Hi,
auf Anfrage eines einzelnen Herrn heute Nacht in der SB hole ich mal diesen Thread aus dem Keller.
UEZ fragte an, ob man nicht eine tropfenförmige Grafik "prozedural" erzeugen könne (so habe ich es jedenfalls verstanden^^ )
http://www.google.com/mapfiles/markerA.png
Daraufhin habe ich folgende Idee gehabt. Ich habe nur den "rechten" Teil des Tropfens betrachtet.
Der obere Teil ist klar, besteht aus einem Viertelkreis mit Mittelpunkt M1.
Beim unteren Teil geht der Viertelkreis um einen bestimmten Winkel weiter bis zum Punkt S.
Stellt man sich jetzt vor, an diesem Punkt S würden sich 2 Kreise schneiden, und der 2. Kreis hätte genau den Radius, dass er
- den 1. Kreis im Punkt S berührt
- die y-Achse in einem Punkt berührt
dann wäre die Fläche zwischen dem 2.Kreis und der y-Achse genau das Stück, was unten zum Tropfen fehlt.
Man sucht also den Radius von Kreis 2!
Mathematisch habe ich mir einen abgebrochen^^
Kreisformel: x²+y²=r²
Weiterhin gilt, dass der Mittelpunkt von Kreis2 auf der Geraden von Mittelpunkt1 und S liegt.
Mit den bekannten Radius Kreis1 (r1) und Winkel Kreis1(alpha) erstellt man 2 Gleichungen um den gesuchten Radius2 (r2) zu finden :
(r1+r2)²=r2²+(r1+t)²
t ist dabei eine Hilfsvariable und ist die senkrechte Länge zwischen dem Schnittpunkt der beiden Kreise S und der waagrechten durch dem Mittelpunkt von Kreis2.
t=sin(alpha)*r2
Weiterhin habe ich noch die "Stichhöhe" h berechnet, das ist das "fehlende" Stück unten von Kreis1
h=2*r1*sin²(alpha/2)
Gleichungen ineinander einsetzen und r2 ausklammern führt zu einer quadratischen Gleichung, Lösung nach siehe die allseits bekannte pq-Formel.
Da das Ergebnis immer positiv sein muss, bleibt von den beiden Ergebnissen der pq-Formel nur eins: r2, der Radius des 2. Kreises.
Mit bissl Dreiecksgedöns ergibt sich der Mittelpunkt M2 aus M1
Man muss nun nur noch die beiden Flächen einfärben, fertig ist der "halbe" Tropfen.
#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
Local $hGUI, $hGraphic
[/autoit] [autoit][/autoit] [autoit]_GDIPlus_Startup()
[/autoit] [autoit][/autoit] [autoit]; Create GUI
$hGUI = GUICreate("Tropfen", 500, 600)
GUISetState()
;Mittelpunkt
$M1_x = 200
$M1_y = 200
$r1 = 100 ;radius
$alpha = 35 ;winkel zur x-achse
$farbe = 0xFF00FF00 ;grün
$pi = ATan(1) * 4
$degToRad = $pi / 180
$alpha = $alpha * $degToRad
;stichhöhe bogen
$h = 2 * $r1 * (Sin(($pi / 2 - $alpha) / 2) ^ 2)
;Lösungen p+q aus quadratischer Gleichung Berührung v. 2 Kreisen ergibt r2
$p = -2 / Sin($alpha) * ($h - $r1 + $r1 / Sin($alpha))
$q = ($h * $h - 2 * $r1 * $h) / (Sin($alpha) ^ 2)
;Radius 2. Kreis aus p+q
$r2 = -$p / 2 + Sqrt(($p * $p / 4) - $q)
;länge schnittpunkt bis Mittelpunkt 2.Kreis
$t = $r2 * Sin($alpha)
;Mittelpunkt 2. Kreis
$M2_x = $M1_x + $r2
$M2_y = $M1_y + $t + $r1 - $h
;schnittpunkt als y-koordinate im einheitskreis
$sy = -$r1 + $h
$hpen1 = _GDIPlus_PenCreate(0xFF00FF00)
$hpen2 = _GDIPlus_PenCreate(0xFF0000FF)
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
;oberes segment
for $y = $r1 to $sy step -1
$x = Sqrt(($r1 * $r1) - ($y * $y))
_GDIPlus_GraphicsDrawLine($hGraphics, $M1_x, $M1_y - $y, $M1_x + $x, $M1_y - $y, $hpen1)
next
;unteres Segment
for $y = 0 to $t
$x = Sqrt(($r2 * $r2) - ($y * $y))
_GDIPlus_GraphicsDrawLine($hGraphics, $M1_x, $M2_y - $y, $M2_x - $x, $M2_y - $y, $hpen2)
next
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
; Clean up resources
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()
;==>_Main
[/autoit]Um einen "ganzen" Tropfen zu bekommen, muss man einfach nur die die Koordinaten der Kontur rechts nach links übertragen.
Funktion Tropfen(Mx,My,r1,alpha,farbe) zeichnet nun den kompletten Tropfen in einer Farbe.
#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
Local $hGUI, $hGraphic
[/autoit] [autoit][/autoit] [autoit]_GDIPlus_Startup()
[/autoit] [autoit][/autoit] [autoit]; Create GUI
$hGUI = GUICreate("Tropfen", 500, 600)
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
GUISetState()
$M1_x = 200 ;Mittelpunkt
$M1_y = 200
$r1 = 100 ;Radius
$alpha = 30 ;Winkel zur x-achse
$farbe = 0xFFFF0000 ;rot
_Tropfen($hGraphics, $M1_x, $M1_y, $r1, $alpha, $farbe)
[/autoit] [autoit][/autoit] [autoit]Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
; Clean up resources
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()
func _Tropfen($hGraphics, $M1_x, $M1_y, $r1, $alpha, $farbe);mittelpunkt 1. Kreis, Radius 1. kreis, Winkel zur x-Achse
[/autoit] [autoit][/autoit] [autoit]if $alpha < 15 or $alpha > 85 then return
if $r1 < 10 or $r1 > 1000 then Return
$pi = ATan(1) * 4
$degToRad = $pi / 180
$alpha = $alpha * $degToRad
;stichhöhe bogen
$h = 2 * $r1 * (Sin(($pi / 2 - $alpha) / 2) ^ 2)
;Lösungen p+q aus quadratischer Gleichung Berührung v. 2 Kreisen ergibt r2
$p = -2 / Sin($alpha) * ($h - $r1 + $r1 / Sin($alpha))
$q = ($h * $h - 2 * $r1 * $h) / (Sin($alpha) ^ 2)
;Radius 2. Kreis aus p+q
$r2 = -$p / 2 + Sqrt(($p * $p / 4) - $q)
;länge schnittpunkt bis Mittelpunkt 2.Kreis
$t = $r2 * Sin($alpha)
;Mittelpunkt 2. Kreis
$M2_x = $M1_x + $r2
$M2_y = $M1_y + $t + $r1 - $h
;schnittpunkt als y-koordinate im einheitskreis
$sy = -$r1 + $h
$hpen = _GDIPlus_PenCreate($farbe)
[/autoit] [autoit][/autoit] [autoit];oberes segment
for $y = $r1 to $sy step -1
$x = Sqrt(($r1 * $r1) - ($y * $y))
_GDIPlus_GraphicsDrawLine($hGraphics, $M1_x - $x, $M1_y - $y, $M1_x + $x, $M1_y - $y, $hpen)
next
;unteres Segment
for $y = 0 to $t
$x = Sqrt(($r2 * $r2) - ($y * $y))
_GDIPlus_GraphicsDrawLine($hGraphics, 2 * $M1_x - ($M2_x - $x), $M2_y - $y, $M2_x - $x, $M2_y - $y, $hpen)
next
endfunc ;==>_Tropfen
[/autoit] [autoit][/autoit] [autoit][/autoit]Ich dachte gerade "Na den Thread kenn ich ja, Leichenschändung?"
Sehr coole Umsetzung, gefällt mir richtig gut, zeigt auch wie man Grafiken per Mathematischen Algorithmus umsetzen kann...
Mir erscheint das ganze aber dennoch ein bisschen lang, kann man das nicht weiter optimieren (kein Vorwurf, nur eine reine Interessenfrage)?
Aus dem engl. Forum hat jemand gefragt, ob man in AutoIt einen Marker mit Text erstellen kann, der so ähnlich aussieht, wie in diesem Bild: http://www.google.com/mapfiles/markerA.png
Deshalb die Frage, wie man solch einen "Tropfen" erstellen kann.
Ich habe mir das Leben etwas einfacher gemacht und es "nur" ähnlich gehalten, da mir nichts besseres eingefallen ist.
Danke Andy für die mathematische Lösung.
Hier die Lösung, ohne viel Mathe (benötigt die aktuelle Beta
;coded by UEZ build 2013-11-24
#AutoIt3Wrapper_Version=b
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
_GDIPlus_Startup()
Global $hGUI = GUICreate("GDI+ Example", 340, 400)
GUISetState()
Global Const $hGfx = _GDIPlus_GraphicsCreateFromHWND($hGUI)
Global $hBitmap = _GDIPlus_CreateMarkerWithText("AutoIt" & @LF &"rulez")
;~ Global $hBitmap = _GDIPlus_CreateMarkerWithText("A")
_GDIPlus_GraphicsDrawImage($hGfx, $hBitmap, 0, 5)
Do
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
_GDIPlus_GraphicsDispose($hGfx)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_Shutdown()
GUIDelete()
Exit
EndSwitch
Until False
Func _GDIPlus_CreateMarkerWithText($sText, $sFont = "Comic Sans MS", $iFSize = 15.5, $iFColor = 0xFF1F0F0F,$iColorBorder = 0xFF1F0F0F, $iColorFill = 0xFFFF766A) ;beta
Local Const $hFormat = _GDIPlus_StringFormatCreate()
Local Const $hFamily = _GDIPlus_FontFamilyCreate($sFont)
Local Const $hFont = _GDIPlus_FontCreate($hFamily, $iFSize)
_GDIPlus_StringFormatSetAlign($hFormat, 1)
Local $tLayout = _GDIPlus_RectFCreate(0, 0, 0, 0)
Local Const $hGfx_tmp = _GDIPlus_GraphicsCreateFromHDC(_WinAPI_GetWindowDC(0))
Local $aInfo = _GDIPlus_GraphicsMeasureString($hGfx_tmp, $sText, $hFont, $tLayout, $hFormat)
_GDIPlus_GraphicsDispose($hGfx_tmp)
Local $iW = $aInfo[0].Width, $iH = $aInfo[0].Height, $iHF = 3
If $iW < 9 Then $iW = 9
Local Const $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW * 2, $iH * $iHF)
Local Const $hGfxCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hGfxCtxt, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
_GDIPlus_GraphicsSetTextRenderingHint($hGfxCtxt, $GDIP_TEXTRENDERINGHINT_ANTIALIASGRIDFIT)
Local Const $hBrushBgColor = _GDIPlus_BrushCreateSolid($iColorFill)
Local Const $hBrushFontColor = _GDIPlus_BrushCreateSolid($iFColor)
Local Const $hPen = _GDIPlus_PenCreate($iColorBorder, 2)
Local Const $hPath = _GDIPlus_PathCreate()
_GDIPlus_PathAddPie($hPath, $iW / 4, 0, $iW * 1.5 - 2, $iH * 2, 150, 240)
Local $aCoords = _GDIPlus_PathGetPoints($hPath)
Local $aPoints[4][2] = [[3]]
$aPoints[1][0] = $aCoords[2][0]
$aPoints[1][1] = $aCoords[2][1]
$aPoints[2][0] = $iW
$aPoints[2][1] = $iH * $iHF - 7
$aPoints[3][0] = $aCoords[UBound($aCoords) - 1][0]
$aPoints[3][1] = $aCoords[UBound($aCoords) - 1][1]
_GDIPlus_PathAddCurve2($hPath, $aPoints, 0.25)
_GDIPlus_GraphicsDrawPath($hGfxCtxt, $hPath, $hPen)
_GDIPlus_GraphicsFillPath($hGfxCtxt, $hPath, $hBrushBgColor)
_GDIPlus_GraphicsFillEllipse($hGfxCtxt, $iW / 4 + 1, 1, 2 * $iW * 0.75 - $iHF - 1, $iH * ($iHF - 1), $hBrushBgColor)
_GDIPlus_PathReset($hPath)
$tLayout.X = $iW - 1
$tLayout.Y = $iH * 0.25
_GDIPlus_PathAddString($hPath, $sText, $tLayout, $hFamily, 0, $iFSize + 4, $hFormat)
_GDIPlus_GraphicsFillPath($hGfxCtxt, $hPath, $hBrushFontColor)
_GDIPlus_PenDispose($hPen)
_GDIPlus_BrushDispose($hBrushBgColor)
_GDIPlus_BrushDispose($hBrushFontColor)
_GDIPlus_PathDispose($hPath)
_GDIPlus_FontDispose($hFont)
_GDIPlus_FontFamilyDispose($hFamily)
_GDIPlus_StringFormatDispose($hFormat)
_GDIPlus_GraphicsDispose($hGfxCtxt)
Return $hBitmap
EndFunc
Gruß,
UEZ
Die GDI+ Methode zählt doch auch zur prozeduralen Grafikgeneration, oder impliziert dieser Begriff das Erzeugen via Formeln, sodass man bei x,y Eingabe dir resultierende Farbe erhält ?
lg
M
Naja, ich habe das jetzt einfach mal "prozedural" benannt...
Natürlich ist jede Funktion in irgendeiner Art und Weise eine Prozedur, aber darauf kommt es mir nicht an.
Siehe div. meiner Posts hier im Thread, da geht es nicht darum, per "GDI(+)" und dem gesamten dahinterstehenden Apparat ein Bild aus div. Funktionen zusammenzustellen, sondern eine Funktion zu erstellen, die auf jedem (!) Rechner das Bild als Ergebnis dieser Funktion erhält.
So wird beim "Tropfen" zwar auch GDI+ benutzt, aber nur, weil sich das Beispiel aus der Hilfe für die _GDIPlus_GraphicsDrawLine()-Funktion so schön angeboten hatte das Ergebnis darzustellen.
Auf einem 30 Jahre alten DOS-Rechner würde die Funktion genauso einen Tropfen darstellen können, unter DOS gab es schon Grafik^^
In der allergrössten Not könnte man die "Pixel" auch als farbige "#" in eine HTML-Datei schreiben und so im Browser den Tropfen darstellen.
Letztendlich geht es darum, mit mathematischen Funktionen ein "Bild" zu berechnen, und nicht, eins zu "malen". Ich verweise da nochmal auf die Seite von Iñigo Quílez
http://www.iquilezles.org/ Bereich Strawberry ,
z.B. http://www.iquilezles.org/www/articles/m…e/morenoise.htm
Genaugenommen bräuchte man für das "Malen" des Bildes nur die SetPixel()-Funktion, um mittels einer einfachen Formel ein komplexes Bild zu erstellen.
Zitat von xorinatorMir erscheint das ganze aber dennoch ein bisschen lang, kann man das nicht weiter optimieren
Sicherlich^^
Ich habe einfach mal angefangen um zu sehen, wie man so etwas aufbauen kann.
Die Funktion ohne Kommentare hat als Sourcecode ca. 1000 Byte (lange Variablennamen^^ ), wer Lust hat, kann diese ja mal in C oder einer anderen Kompilersprache eintippern und als dll kompilieren
Ich wette, mit 200-300 Bytes (!) kommt man da locker hin....
Im Vergleich zum "gemalten" Bild von 300x400Pixeln a 4 Byte/Pixel = 480Kb, welches selbst wenn es komprimiert wird vielleicht 80Kb groß wird, ist das ziemlich "optimiert"
Zitat]Mir erscheint das ganze aber dennoch ein bisschen lang
Genausogut hätte man eine Funktion 4. Ordnung durch 4 Punkte erstellen können.
Das mache ich auch noch, zum Vergleich^^
Jede Kurve kann man als Funktion darstellen, die Frage ist, wieviel Aufwand man betreiben will.
Bei diesen einfachen Sachen ist es relativ simpel, aber sobald es aufwendiger wird und höhere Mathematik ins Spiel kommt, streiche ich die Segel. Dafür brauche ich viel zu viel Zeit und stecke auch nicht mehr so tief in der Materie.
Wieso zitierst du mich 2 mal in einem Beitrag :D? Unterlief dir ein Fehler?
Ne gefällt mir echt gut, aber angenommen man macht (um mal auf das Topic zurück zu kommen) so einen Film, wären dann nicht 300 Bytes für so eine Grafik schon viel zu viel wenn man dann 5 Minuten ausfüttern muss (gut, in dem Film wiederholen sich viele Models die auch algorithmisch bestimmt sind (Vierecke, Vierecke die sich in Kreisbahnen bewegen)), oder irre ich da?
aber angenommen man macht (um mal auf das Topic zurück zu kommen) so einen Film, wären dann nicht 300 Bytes für so eine Grafik schon viel zu viel wenn man dann 5 Minuten ausfüttern muss?
Es gibt ja auch noch fraktale Landschaften und andere nette Tricks. So eine Hügellandschaft wie in elevated lässt sich wahrscheinlich in (weniger als) 1000 Bytes erstellen, reicht dann aber auch für 5 oder 10 Minuten Kameraflug.
Die Light-Version einer prozeduralen Landschaft ist Minecraft (oder das City Beispiel bei OpenGL). Elevated wurde imho durch einen Mandelbulb Shader erzeugt, ähnliches ließe sich auch mit OpenCL + GL erreichen
Hier ein Mandelbulb Shader in 1024 Byte: http://www.geeks3d.com/20101126/demos…tes-openglglsl/
Durch SB-Link nach hier inpiriert^^
$user32 = DllOpen("user32.dll")
$gdi32 = DllOpen("gdi32.dll")
$w = 400
$h = 400
Global $pi = 4 * ATan(1)
[/autoit] [autoit][/autoit] [autoit]$hgui = GUICreate("Landschaft", $w, $h)
$hdc_gui = GetDC($hgui)
GUISetState()
$xmin = -20
$xmax = 30
$dx = ($xmax - $xmin) / $w
$ymin = -15
$ymax = 35
$dy = ($ymax - $ymin) / $h
For $fy = 0 To $w Step 1
For $fx = 0 To $h Step 1
$x = $xmin + $fx * $dx
$y = $ymin + $fy * $dy
;**************************************************************************************************************
If $y > Sin($x) And $y > Cos($x) And $y < Tan($x) And $y < Sin($pi * $x) + 7 And $x < 9 Then
$col = 0x0
ElseIf ((Mod(Abs($x) - $pi / 2, 2 * $pi) - $pi) ^ 2 + ($y - 8.5 + $x ^ 2 / 250) ^ 2) < 5 And $x < 8 Then
$col = 0x00AD00
ElseIf ((Mod(Abs($x) + $pi / 2, 2 * $pi) - $pi) ^ 2 + ($y - 7.5 + $x ^ 2 / 280) ^ 2) < 5 And $x < 11 Then
$col = 0x005200
ElseIf $y <= ATan(10 - $x) Then
$col = 0x0052ad
ElseIf $y < 0.8*Sin($x*2 - 9) ^ 2 + 0.5 And $y < $x - 8 Then
$col = 0xad0000
Else
$col = 0xADFFFF
EndIf
;**************************************************************************************************************
pix($hdc_gui, $fx, $h - $fy, $col)
Next
Next
While GUIGetMsg() <> -3
WEnd
Func pix($dc, $x, $y, $color) ;pixel mit farbe an koordinaten setzen
DllCall($gdi32, "long", "SetPixel", "long", $dc, "long", $x, "long", $y, "long", $color)
EndFunc ;==>pix
Func GetDC($handle)
$dc = DllCall($user32, "int", "GetDC", "hwnd", $handle)
Return $dc[0]
EndFunc ;==>GetDC
Bitte noch eine Sonne dazu, und Schmetterlinge....
Mich interessiert eher das Halftoning bei dem Sphere-Beispiel. Damit kann man ja 3D darstellen ohne jemals 3D-relevante Berechnungen durchzuführen. Vielleicht eine neue Art von Engine
Andy nicht schlecht, nicht schlecht. Erinnert mich wieder an UEZs Google Maps Marker.