kann man ein Sprite in einen Brush verwandeln ?

Probleme beim Erstellen von 3D-Modellen und Texturen, keine Ahnung womit man Musik macht? Dies ist dein Forum.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

hjbremer hat geschrieben:der Code kann aber nur mit normalen Sprites umgehen.
Das bringt nicht viel bis garnix. Hätte schon gerne 3D.
...
Obwohl, so ganz kann ich da noch nicht daran glauben, das es nicht geht.
Auch ein 3D Sprite hockt irgendwo im Speicher.
schon richtig... und zwar als simple senkrechtmatrix-textur,
die bekommst du aus dem normalen sprite, dem ursprungssprite,
und ein paar vektoren, die der grafikkarte sagen, wie sie die textur drehen und verzerren soll.

im speicher selber steht kein rotiertes sprite, das ist eine funktion, die die graka bei der darstellung durchführt.
dir bleibt also nix anderes übrig, als das rotierte sprite irgendwo rein zu displayn,
und diesen buffer dann in eine bitmap zu überführen.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Mein ich doch.
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Beitrag von hjbremer »

ich glaube ihr habt alle zu kompliziert gedacht. Dennoch habt ihr mich auf die richtige Spur gebracht.

Es geht doch so wie ich es will.

Hier ein Beispiel an Hand eines Codes, den ich schon mal gepostet habe, nur wird das Sprite nach dem erstellen als Brush benutzt.

Dank an denjenigen, der die Prozedur CreateBitmapFromSprite(Sprite) aus dem Codearchiv, erdacht hat. Auch an PMV für seinen Tip mit dem Codearchiv.

Code: Alles auswählen

Declare myTexturTextImage(pbnr,br,hh,txt$,font) 

#window_height = 600 
#window_width  = 400 ;900 wenn man auch den Screen sehen will
#screen_height = 570 
#screen_width  = 670 

Enumeration 
  #win_nr 
  
  #textur1 
  #textur2 
  
  #hgimage1 
  #hgimage2 
  #screenhg 

  #textur_img 
  #masken_img  
  
  #imagenr1 
  
  #sprite1 
  #sprite3D
  #Sprite3dneu 
  
  #button1
  #button2
  
  #dummy1 
  #dummy2 
  #dummy3 
EndEnumeration 

Procedure CreateBitmapFromSprite(Sprite) 
  hDC=StartDrawing(SpriteOutput(Sprite)) 
  bmp.BITMAP\bmWidth=SpriteWidth(Sprite) 
  bmp\bmHeight=SpriteHeight(Sprite) 
  bmp\bmPlanes=1 
  bmp\bmBitsPixel=GetDeviceCaps_(hDC,#BITSPIXEL) 
  bmp\bmBits=DrawingBuffer() 
  bmp\bmWidthBytes=DrawingBufferPitch() 
  hBmp=CreateBitmapIndirect_(bmp) 
  StopDrawing() 
  ProcedureReturn hBmp 
EndProcedure

InitSprite() 
InitSprite3D() 

fontsize = 35 
fontidnr = FontID(LoadFont(#PB_Any,"Verdana",fontsize,#PB_Font_Bold)) 

UseJPEGImageDecoder() 
;Texturen zum füllen 
LoadImage(#textur1, #PB_Compiler_Home+"examples\sources\Data\clouds.jpg") 
LoadImage(#textur2, "C:\WINDOWS\Web\Wallpaper\windkanal.jpg") 

;Hintergrundbild 
LoadImage(#hgimage1, "C:\WINDOWS\Web\Wallpaper\mondkrater.jpg") 
LoadImage(#hgimage2, "C:\WINDOWS\Web\Wallpaper\mondaufgang.jpg") 

flag = #PB_Window_SystemMenu|#PB_Window_ScreenCentered | #PB_Window_Invisible
hwnd = OpenWindow(#win_nr, #PB_Ignore, #PB_Ignore, #window_width, #window_height, "DisplaySprite3D", flag) 
       CreateGadgetList(hwnd) 
        
       OpenWindowedScreen(hwnd,15,15,#screen_width,#screen_height,0,15,15) 
        
       Restore datatext1 
        Read lines: For j=1 To lines: Read a$: txt$+a$:Next: txt$+#CRLF$ ;#CRLF$=Leerzeile am Ende 
        
       myimageID = myTexturTextImage(#imagenr1,800,1000,txt$,fontidnr) 
      
       ;===================================================== 

       CreateSprite(#screenhg, #screen_width, #screen_height) 
       StartDrawing(SpriteOutput(#screenhg)) 
    
        DrawImage(ImageID(#hgimage1),0,0,#screen_width,#screen_height) 
        ;DrawImage(ImageID(#hgimage2),0,0,#screen_width,#screen_height) 
            
       StopDrawing() 
                    
       ;===================================================== 
        
       sprite_width  = ImageWidth(#Imagenr1):  ;Debug sprite_width 
       sprite_height = ImageHeight(#Imagenr1): ;Debug sprite_height 
      
       flag=#PB_Sprite_Texture 

       CreateSprite(#sprite1, sprite_width, sprite_height, flag) 
       StartDrawing(SpriteOutput(#sprite1)) 
    
        DrawImage(myimageID,0,0) 
            
       StopDrawing() 
                    
      ;======================================= 

       CreateSprite3D(#Sprite3D, #Sprite1) 
        
       trapez=200 
       tiefe=200 
        
       ;x1 bis x4 siehe PB Hilfe 
       x1sp=trapez:              x1ze=0 
       x2sp=sprite_width-trapez: x2ze=0 
       x3sp=sprite_width:        x3ze=sprite_height 
       x4sp=0:                   x4ze=sprite_height 
        
       z1=sprite_width+tiefe 
       z2=sprite_width+tiefe 
       z3=sprite_height-tiefe 
       z4=sprite_height-tiefe 
        
       TransformSprite3D(#Sprite3D, x1sp,x1ze,z1, x2sp,x2ze,z2, x3sp,x3ze,z3, x4sp,x4ze,z4) 

  ;======================================= 
      
  ;Hintergrund anzeigen
  DisplaySprite(#screenhg,0,0) 
  
  ;Sprite3D anzeigen
  Start3D() 
      
    DisplaySprite3D(#sprite3d, -60,20,250) 

  Stop3D() 

  FlipBuffers() 
  
  ;======================================= 
  
  ;neues Sprite für Grab
  CreateSprite(#sprite3dneu,#screen_width,#screen_height,#PB_Sprite_Memory ) 

  ;Sprite3D grabben
  GrabSprite(#sprite3dneu, 0,0, #screen_width, #screen_height)
  
  ;SaveSprite(#sprite3dneu, "3dsprite.bmp")

  ;umwandeln 
  id = CreateBitmapFromSprite(#sprite3dneu)
  
  ;in neues Image schreiben um es zu verkleinern und bei Bedarf Text drauflegen
  br=200:hh=200
   
  ;nur weil DrawImage besser resizen kann als CopyImage_()
  nr1 = CreateImage(98,br,hh)
   dc = StartDrawing(ImageOutput(98))
         DrawImage(id,0,0,br,hh) 
        StopDrawing()
        DeleteObject_(id)  ;wird nicht mehr gebraucht

  ;als Brush verwenden, nun kann man sich mit der API richtig austoben
  nr2 = CreateImage(99,br,hh)
   dc = StartDrawing(ImageOutput(99))
       
        pen = CreatePen_(#PS_SOLID,3,#Green)
        SelectObject_(dc,pen)
        brush = CreatePatternBrush_(nr1)
        SelectObject_(dc,brush)
        
        Rectangle_(dc,0,0,br,hh)
              
        DrawingMode(#PB_2DDrawing_Transparent)
        DrawingFont(fontidnr)
        DrawText(25,55, "Press", #White) 
       
        StopDrawing()       

  ;dem Gadget zuweisen
  ImageGadget(#button1, 90,10,br,hh,nr2)
  ImageGadget(#button2,690,10,br,hh,nr2) ;dieser nur sichtbar bei WindowBreite 900
  
  ;SpriteScreen schliessen
  CloseScreen()

  ;Window anzeigen
  HideWindow(#win_nr,0) 
  
;======================================= 
  
Repeat 

  Event = WaitWindowEvent() 
  
  If Event = #PB_Event_Gadget Or Event = #PB_Event_Menu 
          
            welcherButton=EventGadget()            
            
            Select welcherButton                      
            
                  Case #button1: Debug "Button gedrückt"
                  Case #button2: Debug "Button gedrückt"

            EndSelect
            
  EndIf
                         
                  
Until Event = #PB_Event_CloseWindow 

End 

;======================================= ======================================= 

Procedure myTexturTextImage(pbnr,br,hh,txt$,fontidnr) 

  ;die br+hh gilt hier nur für die Maske, damit Text komplett hineinpaßt 

  maskenID = CreateImage(#masken_img, br, hh,1) 
        dc = StartDrawing(ImageOutput(#masken_img)) 
                          
               ;Textfont 
               SelectObject_(dc,FontIDnr)           ;oder DrawingFont(FontIDnr) 
              
               ;Text 
               SetBkMode_(dc,#TRANSPARENT)          ;oder DrawingMode() 
               SetTextColor_(dc,#White)             ;#white = ganz wichtig                
                
               SetTextAlign_(dc,#TA_TOP)            ;ohne geht es nicht 
               SetRect_(r.RECT,0,0,br,hh)           ;Basiswerte für rect; left,top,right,bottom 
              
               ;berechne via Api die Größe von r.rect für den Text !!! 
               DrawText_(dc,txt$,-1,r,#DT_CALCRECT|#DT_WORDBREAK)  
              
               ;zeichne Text 
               DrawText_(dc,txt$,-1,r,#DT_CENTER|#DT_WORDBREAK) 
            
             StopDrawing() 
  
  ;nur zur Demo wie Maske aussieht 
  ;ImageGadget(#dummy1, 400, 10, 0, 0, maskenID) 
  
  ;======================================= 
  
  ;Source(Quelle)=Textur braucht nur so groß sein wie der Text 
  
  sourcebr = r\right    ;r wird bei Maske berechnet 
  sourcehh = r\bottom    

  sourceID = CreateImage(#textur_img, sourcebr, sourcehh) 
        dc = StartDrawing(ImageOutput(#textur_img)) 
                
               ;Textur malen 
               DrawImage(ImageID(#textur1),0,0,sourcebr,sourcehh) 
               ;DrawImage(ImageID(#textur2),0,0,sourcebr,sourcehh) 
                
             StopDrawing()    
  
  ;nur zur Demo wie Source aussieht 
  ;ImageGadget(#dummy2, 400, 310, 0, 0, sourceID) 
  
  ;======================================= 
  
  ;Target(Ziel) 
  
  maskbltflag=$AACC0020    ;Billys Geheimnis, http://support.microsoft.com/kb/89375/de 
  
  targetbr = r\right 
  targethh = r\bottom: ;Debug r\bottom 
  
  target_img=pbnr      ;pbnr ist die Nummer des erstellten Images, zum weiterarbeiten damit 
  
  targetID = CreateImage(target_img, targetbr, targethh) 
  targetDC = StartDrawing(ImageOutput(target_img)) 
              
               ;wir müssen eine Kopie anlegen, dieses dc dient als Source für MaskBlt 
               dc = CreateCompatibleDC_(targetDC)    
               ;füllen Kopie mit Bild von source, also dem Farbverlauf oder was auch immer 
               SelectObject_(dc, sourceID)          
                
               MaskBlt_(targetDC, 0, 0, br, hh, dc, 0, 0, maskenID, 0, 0, maskbltflag) 
                              
               ;Kopie löschen 
               DeleteDC_(dc)  
              
             StopDrawing() 
  
  ;nur zur Demo wie Source aussieht 
  ;ImageGadget(#dummy3, 400, 610, 0, 0, targetID) 
  
  ProcedureReturn targetID 

EndProcedure 

DataSection 
datatext1: 
Data.l 4 
Data.s "Ich will ja nur mal testen ob ich das hinbekomme und für Geschwindigkeit muß am " 
Data.s "'Y-Wert' gedreht werden und als nächstes probier ich dann endlosscrollen und dann " 
Data.s "zu zentrieren und danach eine Textur statt Textfarbe und dann versuch ich, daß es oben " 
Data.s "schmaler wird (STAR WARS) und dann.............."  
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

> GrabSprite(#sprite3dneu, 0,0, #screen_width, #screen_height)

das ist doch der punkt, wo du es von einem dargestellten Sprite3D wieder in
ein normales sprite überführst, von dem du dann die Bitmap machen kannst.
nichts anderes haben Nic und ich die ganze zeit erzählt....
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

Du und Nic seit nicht alleine hier im Thread :wink:

... und ich halte das hier für ne schnellere Lösung ...

Code: Alles auswählen

Procedure CreateBitmapFromScreen(ScreenWidth.l, ScreenHeight.l) 
  Protected hDC.l, bmp.BITMAP, hBmp.l
  hDC=StartDrawing(ScreenOutput()) 
  bmp\bmWidth=ScreenWidth 
  bmp\bmHeight=ScreenHeight 
  bmp\bmPlanes=1 
  bmp\bmBitsPixel=GetDeviceCaps_(hDC,#BITSPIXEL) 
  bmp\bmBits=DrawingBuffer() 
  bmp\bmWidthBytes=DrawingBufferPitch() 
  hBmp=CreateBitmapIndirect_(bmp) 
  StopDrawing() 
  ProcedureReturn hBmp 
EndProcedure
Da du eh den kompleten Screen grabst in deinem Code, sollte das hier
schneller funktionieren ... habs aber nicht auf funktionalität getestet. Den
Gedankenanstoss hatte ich ja schon geschrieben, aber mal getestet
scheinst es ja nicht zu haben.

Hm, warum erstellst du ein #screenhg-Sprite, in welches du ein Image
zeichnest? ... Warum zeichnest du das Image nicht direkt auf den Screen?

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Beitrag von hjbremer »

dein Code befindet sich bereits in meinem Code ganz am Anfang ! :D

Und das mit dem screenhg, ja gute Frage - nächste Frage, der Screen wird eh nicht mehr gebraucht siehe CloseScreen und dann ist das Imagegadget da.
Es ist halt ein Beispiel ohne tieferen Anwendungssinn, nur zum Ausprobieren von Funktionen und Ideen. Wie wärs mit neuen Ideen ?
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

Du solltest dir die zwei Prozeduren noch mal genauer anschauen.

Die aus dem CodeArchiv (ist außerdem nicht von mir :wink: ) greift auf
ein Sprite zu, die Prozedur in meinem Post aber direkt auf den Screen ...
fals das klappt, sparst du dir das GrabSprite()

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Beitrag von hjbremer »

Hi , entschuldige habe ich übersehen

und es klappt :allright:
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Antworten