|
Post by rogercabo on May 27, 2023 17:05:54 GMT 1
Hi, does anyone know how to get a bitmap/brush out of another bitmap? I made a bitmap font and like to create and array of single objects from this bitmap.  I want to use this image to create a Global FontSet(90) as Object array. Set BmpFish = D2Bitmap(":BitmapFont") Dim FontChars(90) As Object Then Set FontChars(i) = D2BitmapFromBitmap(BmpFish,x,y,w,h) or similar. It's a really ugly to cut and save every single piece as a png, also for other game objects.. Accept for Texture Atlases. Edit: I started to look into the direct2D lib for D2Put and D2Bitmap but that's quite complex and I have no idea what going on there. Does anyone know how wrote the D2D Lib?
|
|
|
Post by rogercabo on May 28, 2023 18:01:53 GMT 1
On my new attempt I tried to create a brush and from what I know it's possible to use the D2TransformAdd D2TF_MOVE, X, Y method to reposition the texture map before using the D2PBox 0, 0, 1000, 1000, brush function. Now we use the Brush in the same way like Bitmap to place it anywhere on the screen with the correct texture coordinates!
Example:$Library "direct2d"
Global Object Win1RT OpenW 1, 0, 0, 500, 500, ~15 Global Object brHatch, brCol, bmpFish, brFish Set Win1RT = D2GetRT()
Set bmpFish = D2Bitmap(":goldfish")
// 0,0 is the texture offset x,y Set brFish = D2Brush(bmpFish, 0, 0)
Do WinRTPaint() Sleep(16) DoEvents Until Me Is Nothing
Sub WinRTPaint Static x%, y% x++ y = 142 D2BeginDraw Win1RT, D2C_White // Draw the standard texture with at it's exact position D2Put x, 10, bmpFish // ============================================================================================== // The brush works a bit different. At first we disable line drawing and size around the PBox // Unfortunately we have to do every time for every brush we use. D2DefLine 0, 0 // Transform with MOVE to place the Brush to the right position instead the D2PBox D2TransformAdd D2TF_MOVE, x, y // Set the parameter of the D2PBox to the original size of the texture you want to display D2PBox 0, 0, 192, 131, brFish // ============================================================================================== D2EndDraw EndSub
I'm not sure if there is any better solution in this case. The reason is to grab different textures from texture atlas (see first post) and do not save every single texture as separated file to create animations.
Further we must grab also the transparency but that's another test and I will try todo later... Gratefully it's possible to do animations with an object array like this. $Library "gfawinx" $Library "UpdateRT" UpdateRuntime ' Patches GfaWin23.Ocx
$Library "direct2d"
Global Object Win1RT OpenW 1, 0, 0, 320, 500, ~15
// Create an Object array and load into index 0 Global bmpFish(1) As Object Set Win1RT = D2GetRT()
Set bmpFish(0) = D2Bitmap(":goldfish01") Set bmpFish(1) = D2Bitmap(":goldfish02")
Do WinPaint() Sleep(33) DoEvents Until Me Is Nothing
Sub WinPaint() Static ani% Dim t# = Timer D2BeginDraw Win1RT, D2C_White D2Put 10, 10, bmpFish(ani) D2EndDraw ani = Abs(!ani) Print AT(1, 1); Timer - t EndSub
But it seems not possible to use a HASH like this: Global bmpFish As Object // Object is legal to use Set bmpFish = D2Bitmap(":goldfish01")
Global anima As Hash Object Hash Add anima["1"], bmpFish
Or
Set anima["1"] = bmpFish
Not big a deal because the first works well!
|
|
|
Post by scalion on Jun 18, 2023 12:24:13 GMT 1
Hi, does anyone know how to get a bitmap/brush out of another bitmap? I made a bitmap font and like to create and array of single objects from this bitmap. View AttachmentI want to use this image to create a Global FontSet(90) as Object array. Set BmpFish = D2Bitmap(":BitmapFont") Dim FontChars(90) As Object Then Set FontChars(i) = D2BitmapFromBitmap(BmpFish,x,y,w,h) or similar. It's a really ugly to cut and save every single piece as a png, also for other game objects.. Accept for Texture Atlases. Edit: I started to look into the direct2D lib for D2Put and D2Bitmap but that's quite complex and I have no idea what going on there. Does anyone know how wrote the D2D Lib? Yes i know how to do that, ill be back later, dont have my computer for 1/2 day.
|
|
|
Post by rogercabo on Jun 18, 2023 13:16:29 GMT 1
Hi Scalion, great.. In the other demo you made Circle/wall collision by raytrace, all the walls or polygons are in CW mode and i like to know if the player from from the in or outside of the wall. Ar = Gow.Address xStart = DblPeek(Ar) Add Ar, 8 yStart = DblPeek(Ar) Add Ar, 8 x2 = xStart y2 = yStart 'DrawGOW(Gow) 'Return False ' Check Inside or Outside If isOutsideCollision(Shifting, xStart, yStart, x1, y1, Radius) Return False EndIf ' Start with the maximum value for U, alway's work. u = _maxDbl Function isOutsideCollision(ByRef Shifting As DblLine_Struct, xStart, yStart, x2, y2, Radius) As Boolean Local Double dx, dy, nx, ny, dotProduct, lengths ' Berechne die Bewegungsrichtung des Kreises dx = Shifting.x2 - Shifting.x1 dy = Shifting.y2 - Shifting.y1 ' Berechne die Normale der Wand nx = (x2 - xStart) / Radius ny = (y2 - yStart) / Radius ' Berechne das Skalarprodukt der beiden Vektoren dotProduct = dx * nx + dy * ny Print "dotProduct : " & dotProduct Print "xStart", "yStart", "x2", "y2", "Radius" Print xStart, yStart, x2, y2, Radius ' Berechne die Längen der beiden Vektoren lengths = Sqr(dx * dx + dy * dy) * Sqr(nx * nx + ny * ny) ' Prüfe, ob der Winkel zwischen den Vektoren größer als 90 Grad ist If dotProduct / lengths < 0 Return True ' Die Kollision erfolgt von außen Else Return False ' Die Kollision erfolgt von innen EndIf But anything I does wrong. Of the half way of the line, it go through then not. Any idea what I'm doing wrong here? ------------------------------------------- Dans l'autre démo que vous avez réalisée, vous avez effectué une collision cercle/mur par raytracing. Tous les murs ou polygones sont en mode horaire (sens des aiguilles d'une montre) et j'aimerais savoir si le joueur vient de l'intérieur ou de l'extérieur du mur. Mais quoi que je fasse, ça ne fonctionne pas. À mi-chemin de la ligne, ça traverse puis non. Avez-vous une idée de ce que je fais de travers ici ?
|
|
|
Post by (X) on Jun 18, 2023 13:38:13 GMT 1
But it seems not possible to use a HASH like this: Global bmpFish As Object // Object is legal to use Set bmpFish = D2Bitmap(":goldfish01")
Global anima As Hash Object Hash Add anima["1"], bmpFish
Or
Set anima["1"] = bmpFish
Not big a deal because the first works well!
Hi Roger,
You got me thinking... I played around with your idea and found that if you define the Hash as a Variant this seems to work.
$Library "direct2d" $Library "gfawinx" $Library "UpdateRT" UpdateRuntime ' Patches GfaWin23.Ocx
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Given, 5 png files in this application's directory:{0.png .. 4.png} and if ' the Hash declared as Variant instead of Object, this seems to work. ' P_Main
Proc P_Main P_Init Do WinPaint() Sleep(66) DoEvents Until Me Is Nothing EndProc
Proc P_Init P_Init_Main_Form P_Init_Render_Target P_Load_Hash_Table EndProc
Proc P_Init_Main_Form OpenW 1, 0, 0, 300, 300, ~15 EndProc
Proc P_Init_Render_Target Global Win1RT As Object Set Win1RT = D2GetRT() EndProc
Proc P_Load_Hash_Table '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Load Hash Table with D2 bitmap objects from file names... ' Global H_D2Bmp As Hash Variant, i_max% = 4 Dim i% For i = 0 To i_max Hash Add H_D2Bmp[i], D2Bitmap(Format(i) & ".png") Next i EndProc
Sub WinPaint() P_Animate P_Show_dt EndSub
Proc P_Animate D2BeginDraw Win1RT, D2C_White D2Put 0, 0, H_D2Bmp[F_Next_i] D2EndDraw EndProc
Function F_Next_i() As Long Static i% = 0 i++ : If (i% > i_max) i = 0 Return i EndFunc
Proc P_Show_dt Dim t_new# = Timer Static t_old# = t_new Print AT(1, 1); t_new - t_old# t_old = t_new EndProc
|
|
|
Post by rogercabo on Jun 18, 2023 21:36:19 GMT 1
You got me thinking... I played around with your idea and found that if you define the Hash as a Variant this seems to work.
Hi X, that works. the disadvantage is, you have to extract all your 1000ths of animations with your paint program into separate files.. this is mega time consumptive! But sure this works.. and I hope  .. when using D2Put 0, 0, OBJECT then the texture already in the GPU VRAM memory.. and the RT rendering can start immediately. Instead of loading the each texture for an animation step by step. In c# or using you can cache a texture by string imagePath = "example.png"; Bitmap bitmap = LoadTexture(factory, imagePath);
// Cachen der Textur im GPU-VRAM using (var texture = new Texture2D(renderTarget, new Texture2DDescription { Width = bitmap.PixelSize.Width, Height = bitmap.PixelSize.Height, ArraySize = 1, BindFlags = BindFlags.ShaderResource, Usage = ResourceUsage.Default, CpuAccessFlags = CpuAccessFlags.None, Format = Format.B8G8R8A8_UNorm, MipLevels = 1, OptionFlags = ResourceOptionFlags.None, SampleDescription = new SampleDescription(1, 0) }, new DataRectangle(bitmap.DataPointer, bitmap.PixelSize.Width * 4))) {
From this point it's cached.. What we do here is D2PUT I hope again.  renderTarget.BeginDraw(); renderTarget.Clear(Color.White); renderTarget.DrawBitmap(bitmap, 1.0f, BitmapInterpolationMode.Linear); renderTarget.EndDraw();
|
|
|
Post by scalion on Jun 19, 2023 18:20:15 GMT 1
Well, Your first solution is the correct one: use the D2Put parameters by simply specifying the source x,y,w,h. That's what I would have told you. But I really want to answer all the same toon first post: How to take parts of a Direct2D image? Well it's very simple, just use the GDI+ functions which allow you to load PNG files (among others) and access the RGBA components. This demo use this image (Right Clic / Save link target as ...) : Have a nice day.
|
|
|
Post by (X) on Jun 19, 2023 21:28:17 GMT 1
Here is my demo that maps a bitmap to an ASCII letter... I try to always check the demo as if I was downloading it for the first time from someone else. You wouldn't believe how many times this process reveals a hiccup/glick/catch. I think it is ok now. I ended up storing the bmpChrs.png file as a resource. Just start typing and the corresponding chr should appear. (No editing)
This is the source bitmap...

'################################################################################# ' ' DISCLAIMER: THIS CODE IS OFFERED AS IS FOR EDUCATIONAL PURPOSES. ' YOU ARE FREE TO USE, COPY AND DISTRIBUTE. ' THE USE OF THIS CODE IS AT YOUR OWN RISK. ' I ACCEPT NO LIABILITY NOR MAKE ANY CLAIM OF ' CORRECTNESS OR SUITABILITY IN PART OR IN WHOLE. ' '################################################################################# ' ' FILENAME Demo Copy D2D SubBmp to RT.G32 ' ' DESCRIPTION Demonstration of how to copy a portion of a bitmap to a Direct2D ' render target. ' ' AUTHOR (X) ' EMAIL xman.gb32@gmail.com ' WEBSITE https://gfabasic32.blogspot.com/ ' FORUM https://gb32.proboards.com/ ' STARTED 2023-06-19 Proof of concept ' UPDATED 2023-06-20 Simplified and tidied up, more comments ' ' ' $Library "Direct2D" $Library "GfaWinX" $Library "UpdateRT" UpdateRuntime Mode Date "-"
P_Main
Proc P_Main P_Init LoadForm frm1 Do : Sleep : Until frm1 Is Nothing EndProc
Proc P_Init Type T_xy -Long x -Long y EndType '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Store the characters in the bitmap in a zero based variant array to make it ' easy to recall the characters in an ordered sequence: 1 to i_max... ' Global Dim VA_chrs = Array( " ", _ " ", "!", #34, "#", "$", "%", "&", "'", "(", _ ")", "°", "+", ",", "-", ".", "/", "0", "1", _ "2", "3", "4", "5", "6", "7", "8", "9", ":", _ ";", "<", "=", ">", "?", "@", "A", "B", "C", _ "D", "E", "F", "G", "H", "I", "J", "K", "L", _ "M", "N", "O", "P", "Q", "R", "S", "T", "U", _ "V", "W", "X", "Y", "Z", "[", "\", "]") As String '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Calculate and store the x,y coordinates in a single indexed array for each ' character in the bitmap based on the chracter width and height... ' Dim i% Global i_max% = 62 Global chrMap(i_max) As T_xy Global chrW% = 56, chrH% = 57 Dim x% = 0, y% = 0 For i = 1 To i_max chrMap(i).x = x * chrW chrMap(i).y = y * chrH '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Increment the x and y coordinates based on the number of character in a row ' and the number of rows... ' x++ If (x > 8) x = 0 y++ If (y > 7) y = 0 EndIf EndIf Next i '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Store an integer mapped to a 'key string': the character, in a Hash table to ' make it easy to obtain the index of the character as mapped in the chrMap() ' array. From the index it willbe easy to obtain the left, top x,y coordinates ' from the .x and .y properties of the chrMap()... ' Global H_chrs As Hash Long For i = 1 To i_max H_chrs[VA_chrs(i)] = i Next i EndProc
Sub frm1_Load() frm1.AutoRedraw = 1 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Create the variable to hold the window's D2 render target object initialize ' Direct2D and obtain a DC render target... ' Global Object Win1RT Set Win1RT = D2GetRT() '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Load the character bitmap. This could also contain sprites or animation ' frames that could be indexed and played in sequence. ' Global Object bmpSrc Set bmpSrc = D2Bitmap( ":bmpChrs") End Sub
Sub chr_Out(s$) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Render the individual character bitmaps onto the render target... ' D2BeginDraw Win1RT //, D2C_White PutBmpChrOnRT(s$) D2EndDraw End Sub
Sub frm1_Close(Cancel? ) ' Cleanup resources Set Win1RT = Nothing Set bmpSrc = Nothing End Sub
Sub PutBmpChrOnRT(s$) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copy the specified region from the larger bitmap onto the render target ' Try '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Get the index previously associated with each character... ' The Hash table is an easy fit for taking a 'key string' and returning the ' value associated with the key, in this case an integer index. ' Dim i% = H_chrs[s$] If (i > i_max) Exit Proc Dim srcx = chrMap(i).x Dim srcy = chrMap(i).y Static dstX% = 0 Static dstY% = 0 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' The magical D2Put function ... You can see more details about this in the ' 'Direct2D.g32' file in the ' GFABASIC32/include' directory. GFA 'hides' what ' is perhaps more 'visible' in C++ language related to Direct2D functions. ' Dim scl! = 1.5 D2Put _ dstX, _ dstY, _ bmpSrc, _ chrW * scl, _ chrH, _ 1.0 /* Opacity:{0.0 .. 1.0} */, _ srcx, _ srcy, _ chrW, _ chrH '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' A simple (column, row) cursor increment... ' dstX += chrW If (dstX > (frm1.ScaleWidth - chrW * scl)) dstX = 0 dstY += chrH EndIf Catch Trace Err$ Exit Proc EndCatch End Sub
Sub frm1_KeyPress(Ascii&) chr_Out(Chr$(Ascii)) EndSub
|
|
|
Post by rogercabo on Jun 20, 2023 0:26:40 GMT 1
I'm really impressed! Great acknowledge.. what can I say else.
Thanks a lot!
|
|
|
Post by (X) on Jun 20, 2023 15:16:35 GMT 1
Scaling the chr width has the effect of bringing the letters close to one another...
|
|
|
Post by (X) on Jun 21, 2023 17:02:02 GMT 1
I've been trying out different tactics to stop the form from clearing or loosing information while resizing. I was able to create a backup area to which the form is contiually updated and when the form is resized, it is used to recall previously painted areas. Of course, if the application requires a complete redraw then this technique would not be of any use.
In the case of an edit box, it may be better to reformat the text according to the new form size.
|
|
|
Post by scalion on Jun 27, 2023 7:08:59 GMT 1
I've been trying out different tactics to stop the form from clearing or loosing information while resizing. I was able to create a backup area to which the form is contiually updated and when the form is resized, it is used to recall previously painted areas. Of course, if the application requires a complete redraw then this technique would not be of any use.
In the case of an edit box, it may be better to reformat the text according to the new form size.
Génial ce petit éditeur de texte 
|
|