hi,

it's me again, with another problem. perhaps some of you already have seen my "balls"-program. anyways, i've a new problem with it. originally the program is a physical simulation. at the moment, it is just important that the balls (actually gas molecules) have a nearly constant pressure. but i've only 28 balls, and the pressure is NOT constant. so i decided to create about 60 layers. all the 60 layers have 28 balls in them, that are independent of the other layers. just the pressure is calculated together. i hope to get a constant pressure with it, it seems to work pretty well. but here is the problem: i only show the first layer, the first 28 balls. when i use 10 layers, the whole stuff goes very slow, and i want to have about 60 layers. it doesn't help to increase the velocities of the balls, they just cause errors in the calculation (too difficult to explain now.)

so i let the GDI drawing operations out, and noticed that it goes about 75 times or more, faster!!!!! the drawing operation is pretty easy too. i have a procedure that gets x1, y1, x2, y2 coordinates (the balls are actually rectangle bitmaps), calculates the middle and does a BitBlt on a DC. that dc is then copied to the screen, on my window. then the whole dc is cleared, and the whole drawing starts again, with the new position of the balls. as you can see, pretty easy. now my question (finally :grin: ): would a directx window make the whole stuff much faster instead of using GDI? if yes, could somebody make the code for me? yeah, that sound very lame, but it would take too much time to get into the whole stuff, and i just need it for this program. that means: creating a directx window, "painting" bitmaps on the screen at x,y coordinates. that's all.

i would really appreciate any help. i attached the program, too. the main part is "testkug.asm" for the balls moving and drawing procedure, and "window.inc" for creating the window.

please help me!
Posted on 2001-12-07 14:54:04 by NOP-erator
If you place the balls surface in video memory, you will sure get big speed increase with DirectDraw. (100-200fps)

Just do not try to read from video memory ... this is extra slow

Asking for somebody else to write your code is lame indeed... after all this is a very simple task:

1.setup directx full screen, exclusive
2.load bitmaps into video surfaces

for very frame:
3.do your calculations and update bitmap positions
4.blit bitmaps into back buffer
5.flip primary/back buffers
go to 3

But its also naive to belive the GFX in your program will be the fast part :) ... esp if you have many GFX to do ... still i guess it depends on what you do in the non GFX part of the app :P

PS.
there is some source code just for this (simple blitting and flipping)called "asm flips" on Iczelion's site ...
Posted on 2001-12-07 17:11:58 by BogdanOntanu
hi,

i really hoped that you answer my question Bogdan. Thanks for your reply. I didn't find the example code on Iczelion's site, but somewhere else. I couldn't compile it, and downloaded some other DD sources. I now managed it to build a DD window and tried to implement the "Update" procedure of "ASM FLIPS". My program crashes, and I don't know why. There is my "update" procedure at the bottom.
OK, after i will have managed that problem, could you tell me, how i can get a bitmap into the back surface? and how do i specify the coordinates where the balls should be pastet in? btw: where can i get a documentation from, about the DirectDraw "APIs"?



Update proc uses edi esi ebx edx
;invoke GetFrameRate
mov ddbltfx.dwSize, sizeof ddbltfx
mov ddbltfx.dwFillColor,0FFFFFFh
DDSINVOKE Blt,lpDDSBack,0,0,0,DDBLT_COLORFILL + DDBLT_WAIT,addr ddbltfx
.IF eax!= DD_OK
FATAL "BLT (Make the screen white) failed!"
.ENDIF
mov ddbltfx.dwFillColor,0
DDSINVOKE Blt,lpDDSBack,addr rectsrc,0,0,DDBLT_COLORFILL + DDBLT_WAIT,addr ddbltfx
.IF eax!= DD_OK
FATAL "BLT (Paint rectangle) failed!"
.ENDIF
DDSINVOKE Flip,lpDDSPrimary,0,DDFLIP_WAIT
.IF eax!= DD_OK
FATAL "Flipping the buffers failed!"
.ENDIF

ret
Update endp


bye
Posted on 2001-12-08 10:55:38 by NOP-erator
here is an windowed example with your kugel1.bmp :

it use offscreen buffer (not backbuffer+flip method) , it doesnt process any error conditions.

and i'm not sure if buffers created in video memory or not, try including DDSCAPS_VIDEOMEMORY flag in ddsd structure
Posted on 2001-12-08 14:48:19 by kamilh
Hi,

thanks kamilh for your effort, but your program confused me. the way you call the DirectX APIs is another than I am using. This for example is my DirectDraw init part:



INVOKE DirectDrawCreate, NULL, ADDR lpDD, NULL
.IF eax != DD_OK
FATAL "Couldn't init DirectDraw"
.ENDIF
DDINVOKE SetCooperativeLevel, lpDD, hWnd, DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN
.IF eax != DD_OK
FATAL "Couldn't set DirectDraw cooperative level"
.ENDIF
DDINVOKE SetDisplayMode, lpDD, 640, 480, 16
.IF eax != DD_OK
FATAL "Couldn't set display mode"
.ENDIF
mov [ddsd.dwSize], sizeof ddsd
mov [ddsd.dwFlags], DDSD_CAPS + DDSD_BACKBUFFERCOUNT
mov [ddsd.ddsCaps.dwCaps], DDSCAPS_PRIMARYSURFACE OR\
DDSCAPS_FLIP OR\
DDSCAPS_COMPLEX OR\
DDSCAPS_VIDEOMEMORY
mov ddsd.dwBackBufferCount, 1
DDINVOKE CreateSurface, lpDD, ADDR ddsd, ADDR lpDDSPrimary, NULL
.IF eax != DD_OK
FATAL "Couldn't create primary surface"
.ENDIF
mov [ddscaps.dwCaps],DDSCAPS_BACKBUFFER
DDSINVOKE GetAttachedSurface,lpDDSPrimary,addr ddscaps,addr lpDDSBack
.IF eax!= DD_OK
FATAL "GetAttachedSurface failed!"
.ENDIF


I don't think that the two methods are compatible. which one is better, or doesn't it matter? I attached my new code, with the DirectDraw Window. There is "update" proc in "window.inc". The program crashes, and it seems to be because of the "Blt". It would be very nice, if someone of you could show me how to Blt a bitmap on the screen with my method (just if it doesn't matter which i use). It would be too much work to change the whole stuff.
BTW: @kamilh: you told me that you don't flip the buffers. hmm, you know, i never did anything with direct draw, i don't understand the difference between what you have done, and between this "flipping". is the template you created good for animation without flickering? that means, painting the balls, "deleting" the whole screen, and painting them at the new positions.

i would appreciate an answer. thanks in advance....

Noppy
Posted on 2001-12-08 15:14:09 by NOP-erator
the probleme with your testdcc.exe is :

update proc is called before ddinit proc so lpDDSBack variable is null at the first call, i did not checked when you first update&init ddraw but changing update proc like :

.if lpDDSBack ; check backbuffer pointer is valid or not?
invoke Update
endif

may solve the probleme..

DDINVOKE & mcall are to different macros (maybe samething with different name, i'm not sure), it doesnt matter which one your are using.

in my example backbuffer is an offscreen surface, (constant width & height), it is scaled to window (part of primary surface) size when you blt.. with backbuffer/flip you have variable size surface (not in your case, exclusive fullscr mode).
i dont know which one is better for your special purpose.
flip method is faster but both methods prevents flickering. (you delete offscreen surface not visible surface before update)
Posted on 2001-12-08 21:41:37 by kamilh
@kamilh:

i decided to build in your method in my program, but: when i try to compile it, i get an "Unresolved external symbol _DirectDrawCreateEx@16" error, even when i try to compile your program.....

and something else: i begin to understand the system behind directdraw. but first: where can i get a documentation about the directdraw apis, and second: could you explain me, what this "Clipper" is, please?

thanks,
noppy
Posted on 2001-12-09 05:00:59 by NOP-erator
nop-erator ;

directdrawcreateex is used to create ddraw7 object, you need directx7 lib files to compile my project.

copy this lib file to masm32\lib library, it's from directx7 sdk, or better download directx sdk from microsoft (it has directx help files too.)
but new directx8 sdk doesnt have ddraw related hep files, you have to find directx7 sdk help files.

clipper prevents writing outside of your window (when using windowed DDSCL_NORMAL mode, primary surface holds entire desktop, not only your window region)
Posted on 2001-12-09 11:02:38 by kamilh
thanks, but one question left: wouldn't it be better to start with directx8? i read somewhere, that they removed that directdraw/direct3d stuff, and combined the two. will i get problems when i use directx7 stuff in the future?

noppy
Posted on 2001-12-09 11:07:40 by NOP-erator
You will not get problems. When you use DirectX, you query for an
interface version, say DX7, and you'll get it. So newer versions of
DX basically contain all the old versions, and the new one..
Posted on 2001-12-09 11:28:00 by f0dder
hi,

thanks to you all! i finally managed it to port the program graphics from GDI to DirectDraw. but there are still some questions and problems left.

1) it seems, that the program runs with the same speed. the balls don't move faster, although they should, because of the faster painting. but there is one thing that goes faster: when you press "p" or "m", you can force the program to show the next/previous layer. with the old version i took sometimes 4-5 seconds (obviously depending where the loop was), with the new version, it goes directly, without any delay. so, something goes faster, but why not the balls?

2) when you look at the balls, you probably notice, that they have a black corner (because it's a rectangular bitmap). how would i create sprites? how to do that? especially with this direct draw stuff.

3) i use InvalidateRect in the main message loop that causes a WM_PAINT message. there i call my "kugproc" (the procedure that calculates the balls coordinates). but when i call "kugproc" directly from the main message loop, the programs doesn't work (works, but very slowly, or doesn't work completely, graphic errors and stuff), i really don't know why. perhaps you can try out, and find out what's wrong? i attached one zip file with the working program, and there is also "windowb.inc", that you have to rename to window.inc and compile then. this would be the bad version in this case then.

thanks again for your help, it would be very cool, if i could solve the problems above, too, with your help.

thank you, thank you, thank you.
Posted on 2001-12-10 11:36:27 by NOP-erator
When in fullscreen. A DirectX application (or an openGL one for that matter), defaults to wait for the vertical retrace. (In windowed mode its default is not wait for retrace). So if you are getting 60Hz, 85hz or something like that thats possible the problem.

Then again, its probably a good idea to wait for the vertical retrace, no streaks and 60Hz is better than having 300Hz and streaks on the display.

If thats not the problem, it could be many things, including but not limited to:

- Bitmaps not on video card memory
- Sincronization with card. (Try tripple buffering instead of double if you have enough ram).
- Use PeekMessage and then wait when there is no message to flip your pages.
- If in windowed mode, the video card you are using maybe does not support page flipping on windowed mode.

etc, etc
Posted on 2001-12-10 12:28:39 by dxantos
sorry dxantos,

but i suppose that you even didn't look at my source, did you? for example, i don't flip anything! and i'm pretty sure, that my problems don't have anything to do with vertical retrace and stuff (If i'm wrong, then sorry). i'm sorry to say that, but that didn't help me actually.....

bye,
noppy
Posted on 2001-12-10 13:25:15 by NOP-erator
Sorry I didnt read the code before answering. I dindn't have time and just wanted to help anyway.

Your loop is:


StartLoop:
invoke GetMessage,ADDR msg,NULL,0,0
cmp eax, 0
je ExitLoop
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg

;|> we call InvalidateRect to send a WM_PAINT message to our window and there is
;|> called out animation loop. i tried to call the animation loop directly from here
;|> but the program gets really slow, i don't know why
invoke InvalidateRect,hWnd,addr updatescr,FALSE
;invoke kugproc,hWnd,hDC
jmp StartLoop
ExitLoop:


You are using GetMessage, that is telling Windows to wait until there is a message.

Instead try:

1. Add a flag to tell if your app is active or not.


app_flag dd 0
APP_ACTIVE = 1


2. Change the loop to this one:


StartLoop:
mov eax, app_flags
test eax, APP_ACTIVE
jz NonActive

;This is the loop called when the application is active
;PeekMessage will return inmediately.
invoke PeekMessage, addr msg, NULL, 0, 0, PM_REMOVE
and eax, eax
jz IdleTime
cmp [msg.message], WM_QUIT
je ExitLoop
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp StartLoop

IdleTime:
;This should be called ONLY when there is no windows msg available.
;Otherwise things will slow down.
invoke kugproc,hWnd,hDC
jmp StartLoop

NonActive:
; This area is executed when the application is not active, so it doent take all CPU cycles.
; GetMessage will WAIT UNTIL there is a message available
invoke GetMessage,ADDR msg,NULL,0,0
and eax, eax
jz ExitLoop
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp StartLoop
ExitLoop:


3. In the windows proc intersect the WM_ACTIVATE message. This is necesary because we dont wat to take too many CPU cycles when the app is not active.



.elseif uMsg == WM_ACTIVATE
.if wParam & 0FFFFh
or app_flag, APP_ACTIVE
.else
and app_flag, NOT APP_ACTIVE
.endif
invoke DefWindowProc,hWin,uMsg,wParam,lParam
ret


I havent tested the code. (Have no time to do that). But it should work.
Posted on 2001-12-10 14:22:13 by dxantos
if you want to learn how to do sprites there's a great vb tutorial at http://www.vbexplorer.com/show.asp?id=188

Basically you first draw a bitmask and then the graphic...
Posted on 2001-12-10 14:46:15 by grv575
thank you for your posting dxantos! i don't have time now too, to test the code, but i'll do it tomorrow evening (24h since this post). but it sound very sensible what you're telling......thanks!

@grv575: i basically wanted to know how to "draw" the sprites with direct draw. is it the same stuff as with one ball, but just that i Blt the sprite bitmap over the other, or is there a special function?

bye, and thanks again
Posted on 2001-12-10 14:53:22 by NOP-erator
Yeah just use two DCs and two bitmaps. Make a kugel2.bmp where the ball is black and the background white. Then bitblt that onto the window first. Then bitblt kugel1.bmp using SRCAND as the raster-operation code. What happends is the black background gets anded with the mask bitmap's white background and it shows up clear.
Posted on 2001-12-10 16:03:15 by grv575
nop erator

replace line (inside putball proc)

mcall ,IDirectDrawSurface7_Blt,addr rc,dds_bitmap,NULL,DDBLT_WAIT,addr ddbltfx

with

mcall ,IDirectDrawSurface7_Blt,addr rc,dds_bitmap,NULL,DDBLT_WAIT or DDBLT_KEYSRCOVERRIDE,addr ddbltfx

it will set black as source surface (your bitmap) color key & black pixels wont be drawn on screen.
Posted on 2001-12-10 16:42:17 by kamilh
hi,

ok, everything works fine now. but changing the loop just helped me out not to use InvalidateRect, this is pretty cool. but the whole stuff doesn't go really faster (moving of the balls) than with GDI. i just can press the left mouse button and other keys on the keyboard and there happens something directly. with gdi (as i said), i had to wait a few seconds. but why isn'T the loop executed faster, still?

bye
Posted on 2001-12-11 12:52:19 by NOP-erator
hi,

i just noticed another problem: the static box where the pressure of the gas is shown in, isn't displayed on the screen anymore. why? is it because of the direct x stuff? how can i put text on the window, and delete it again?

thanks,
nop
Posted on 2001-12-11 15:49:46 by NOP-erator