Seite 1 von 2
Sprites rotieren - 2D o. 3D
Verfasst: 05.12.2007 14:25
von MvD-Service
Hallo zusammen,
herzliche Grüße an alle aus dem kalten Bergischen Land. Ich bin technischer Trainer im Kfz-Bereich und möchte Animationen mit PureBasic erstellen um komlizierte oder unsichtbare Sachverhalte anschaulich darzustellen. Im Kfz-Bereich drehen sich die meisten Dinge z.B. eine Pumpe....
Damit sind wir auch schon bei meiner eigentlichen Frage angekommen.
Ich möchte Sprites vor einem (meist) festen Hintergrund (teilw. Gradgenau) mit variabler Geschwindigkeit rotieren lassen können. Sagen wir mal ich möchte zwei verschiedengroße Zahnräder nebeneinander (Zähne im Eingriff) rotieren lassen. Wie gehe ich sowas am besten an?
Versuchsweise habe ich die Procedure RotateSprite() hier aus dem Forum benutzt. Funktioniert prima, bloß offenbar derart Rechenintensiv, daß sich bei zwei oder mehr rotiernden Sprites unschönes ruckeln zeigt.
Könnt Ihr mir bei dieser Herausforderung helfen? - Ich bin sicher Ihr könnt....
Bis denne,
Michael
Verfasst: 05.12.2007 14:32
von Fluid Byte
Ganz ehrlich, dafür ist PB eher ungeignet. Für Illustrationen und Präsentationen aller Art empfiehlt sich MS PowerPoint oder Adobe Flash.
Verfasst: 05.12.2007 15:19
von Zaphod
Wenn es Ruckelt, dann liegt das vermutlich eher an zu großen Sprüngen zwischen den Frames oder an etwas anderem. Mehrere hundert 3D Sprites zu rotieren sollte selbst auf Rechnern Problemlos funktionieren, die nur sehr rudimentäre 3D Beschleunigung haben.
Es könnte höchstens sein, dass du das mit einem Laptop komplett ohne 3D Beschleunigung hast laufen lassen, dann könnte es auch ruckeln.
Verfasst: 05.12.2007 15:32
von MvD-Service
@Fluid Byte / @all:
OK, Du hast damit sicher Recht. Meine Präsentationen erstelle ich mit PowerPoint und eine Testversion von AdobeFlash CS3 habe ich mir schon runtergeladen und auch damit gute Erfolge erzielt, gleichwohl habe ich mir gedacht mit den genialen Grafischen Leistungen von PureBasic müsste das doch mindestens ebenso gut, wenn nicht sogar besser zu machen sein. Meine Verwaltungs- und Abrechnungsprogramme usw. habe ich mit PB erstellt. Im Bereich Grafik habe ich noch keine Erfahrungen gesammelt.... Könnte mir evtl. jemand ein kleines Grundgerüst als Basis zur Verfügung stellen? Sprich: Ein Hintergrundbild und ein rotierendes Sprite im Vordergrund in 3D oder eine andere Möglichkeit der Rotation in 2D.... Evtl. nutze ich RotateSprite() auch einfach nur falsch...!?!
Alles andere versuche ich mir dann zu erarbeiten. Ich danke Euch schon jetzt...
@Zaphod: Ist RotateSprite() nicht eigentlich 2D ?? Oh, mann - ich und Grafik.... Du sagst "mehrere hundert" - zwei bis drei würden mir schon genügen... Ach ja, mein Laptop (woher weißt Du eigentlich das ich eins nutze??) ist recht neu und hat die Beschleunigung eingeschaltet.
Gruß
Michael
EDIT:
Sorry, habe für Verwirrung gesorgt - ich meinte dieses RotateSprite():
Code: Alles auswählen
; German forum:
; Author: Mischa (updated for PB4.00 by blbltheworm)
; Date: 15. October 2002
; OS: Windows
; Demo: No
Procedure RotateSprite(source,target,angle.f,scale)
s.f=Sin(6.28318531/3600*angle):c.f=Cos(6.28318531/3600*angle)
bitmap=CreateCompatibleBitmap_(GetDC_(0),SpriteWidth(source),SpriteHeight(source))
dc=CreateCompatibleDC_(GetDC_(0))
obj=SelectObject_(dc,bitmap)
sid=SpriteOutput(source)
workdc=StartDrawing(sid)
BitBlt_(dc,0,0,SpriteWidth(source),SpriteHeight(source),workdc,0,0,13369376)
transcolor=Point(SpriteWidth(source)-1,0);<-----transparente farbe oberes-rechtes pixel im sourcesprite
StopDrawing()
mx=SpriteWidth(source)/2:my=SpriteHeight(source)/2
radius.f=Sqr(mx*mx + my*my)+1
If scale=0
If SpriteWidth(target)=0
CreateSprite(target,SpriteWidth(source),SpriteHeight(source),0)
TransparentSpriteColor(2,RGB(Red(transcolor),Green(transcolor),Blue(transcolor)))
cl=1
EndIf
mx2=mx:my2=my
Else
If SpriteWidth(target)=0
CreateSprite(target,radius*2,radius*2,0)
TransparentSpriteColor(2,RGB(Red(transcolor),Green(transcolor),Blue(transcolor)))
cl=1
EndIf
mx2=radius:my2=radius:diffmx=mx2-mx:diffmy=my2-my
EndIf
max=SpriteWidth(target):may=SpriteHeight(target)
sid=SpriteOutput(target)
workdc=StartDrawing(sid)
Box(x, y, max, may,transcolor)
For y=0 To SpriteHeight(source)-1
For x=0 To SpriteWidth(source)-1
RotateX.l = ((x - mx) * c - (y - my) * s) + mx + diffmx
RotateY.l = ((x - mx) * s + (y - my) * c) + my + diffmy
If RotateX>0 And RotateX<max-1 And RotateY>0 And RotateY<may-1
color=GetPixel_(dc,x,y)
Plot(RotateX,RotateY,color)
If angle<>0 And angle<>900 And angle<>1800 And angle<>2700 And angle<>3600
Plot(RotateX+1,RotateY,color);<--Das ist mein wahnsinnig komplizierter
Plot(RotateX,RotateY+1,color);<--Antialiasing-Algorythmus *lol*
EndIf
EndIf
Next x
Next y
StopDrawing()
DeleteObject_(bitmap):DeleteObject_(obj):DeleteDC_(dc)
EndProcedure
If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or OpenScreen(800,600,32,"Rotate")=0
MessageRequester("Error", "Can't open DirectX 7 Or later", 0):End
EndIf
LoadSprite(1,"..\..\Gfx\Geebee2.bmp",0);<--Probiert erst mal den hier (zu finden in 'PureBasic\Examples\Sources\Data')
CreateSprite(2,SpriteWidth(1)*2,SpriteHeight(1)*2)
TransparentSpriteColor(2,RGB(255,0,255))
Repeat
ExamineMouse():ExamineKeyboard()
ClearScreen(RGB(100,50,50))
DisplayTransparentSprite(1,100,100)
If count<3650
If GetTickCount_()-zeit > 10
RotateSprite(1,2,count,1)
;RotateSprite(source,target,angle,scale)
;source - Nummer des Quellsprite
;target - Nummer des (neuen)Zielsprite
;angle - 0 - 3600 Zehntelgrad
;scale - 0 = Zielsprite ist so groß wie Quellsprite
; 1 = Zielspritegröße richtet sich nach dem max Rotationsradius
count+50
zeit=GetTickCount_()
EndIf
EndIf
DisplayTransparentSprite(2,300+count/20,100+count/20)
StartDrawing(ScreenOutput())
DrawText(10, 500,"Winkel= "+Str((count-50)/10)+" Grad")
StopDrawing()
FlipBuffers()
Sleep_(1)
Until KeyboardPushed(#PB_Key_Escape)
End
; IDE Options = PureBasic v4.00 (Windows - x86)
; Folding = -
; DisableDebugger
von dieser URL:
http://www.purearea.net/pb/CodeArchiv/G ... otate2D.pb
Ich hehme einfach zwei Grafiken, lade diese als Sprites und lege eins als Hintergrund und eins als bewegendes/rotierendes an.....
Verfasst: 05.12.2007 16:43
von STARGÅTE
ahh
das ist klar das das ding langsam ist, dann mache lieber n Sprite3D draus und innerhalb von Start3D() Stop3D() kannst du dnan die RotateSprite3D() und DisplaySprite3D() befehle verwenden die viel schneller sein.
Verfasst: 05.12.2007 17:33
von Zaphod
Naja, bei Präsentationen benutzt man ja meistens Notebooks
Das Problem ist tatsächlich das du nicht Sprite 3D nutzt... mit Sprite3D und einem neueren Notebook mit 3D Hardwarebeschleunigung sollten selbst 1000 rotierende Sprites nicht ruckeln.
Schau dir am besten mal Sprite3d.pb aus dem Examples Ordner deiner PB Installation an.
Verfasst: 05.12.2007 19:02
von Kaeru Gaman
die Sprite3D-Befehle heißen so, weil sie funktionen aus dem 3D-Bereich von DX benutzen.
ein normales 2D-Sprite ist einfach eine senkrechte matrix, die auch nur senkrecht dargestellt werden kann.
deswegen ist die Rotate Routine so rechenintensiv: alle pixel werden tatsächlich verschoben.
bei Sprite 3D fungiert das ursprüngliche Sprite nurnoch als Texture für ein 4-Vektoren-Mesh,
das dann direkt innerhalb der Grafikkarte mit wenigen kommandos manipuliert werden kann.
also auch um die oprische achse gedreht, aber genauso in jeder beliebigen form verzerrt.
das ist natürlich wesentlich schneller, weil tatsächlich 3D-hardware-funktionen benutzt werden.
denk dabei auch an die größenbeschränkungen für 3D-Sprites:
die ursprungstexture muss exakt 2^n² groß sein.
(also 16², 32², 64², 128² oder 512² ; 1024² und 2048² funktionieren nur auf 'größeren' Grafikkarten)
eine mögliche alternative für deine aufgabenstellung wäre noch,
für jedes zahnrad ein paar frames vor zu rendern,
also unterschiedliche stellungen vorab zu erzeugen,
und die dann je nach aktuellem drehwinkel anzuzeigen.
dann braucht du keine 3D-Sprites benutzen, aber du brauchst mehr speicher für die vielen frames.
Verfasst: 05.12.2007 19:42
von STARGÅTE
Kaeru Gaman hat geschrieben:denk dabei auch an die größenbeschränkungen für 3D-Sprites:
die ursprungstexture muss exakt 2^n² groß sein.
(also 16², 32², 64², 128² oder 512² ; 1024² und 2048² funktionieren nur auf 'größeren' Grafikkarten)
ich habe dabei festgestellt das auch kombinationen keine Probleme machen : 64*128 oder 512*32 ...
Natürlich kann dort das einfache RotateSprite3D() nicht benutzt werden, aber meine TransformProcedure funzt ohne grafikfehler, und meine Grafikkarte zeigt bei nicht 2^n großen Texturen fehler an.
Verfasst: 05.12.2007 20:03
von Fluid Byte
Die Erfahrung habe ich auch gemacht. Die Höhe und Breite einer Textur müssen nicht zwangsläufig identisch sein sondern nur ein Vielfaches von 2 sein. Wäre auch Platz- & GPU-Verschwendung wann bspw. ein rechteckiges Logo für ein Spiel hat was 512px breit aber nur 64px hoch ist.
Verfasst: 05.12.2007 20:42
von THEEX
Meines Wissens nach kommt es auf die Grafikkarte an, so kann es passiern das 32 * 64 funktioniert, aber nicht auf allen Rechnern. Zumindest hab ich sowas in Erinnerung.