Will CreateCompatibleBitmap bei großen Größen nimmer?



  • Hallo!
    Ich programmiere einen Leveleditor. Ihr kennt sicherlich die Fenster, außer dem 3D Fenster. Wenn man zB von Links oder Oben auf das Objekt schaut. Solche Fenster habe ich auch 🙂 Bisher hatte ich es so, dass ich bei jedem WM_PAINT alle Polygone neu in das Fenster zeichne. Bei einem großen Model dauert das aber knapp eine Sekunde...bei einem Level mehrere. Um das zu vermeiden, erstelle ich einen sekundären DC und male in den das komplette Objekt. Dieses male ich dann per BitBlt einfach auf den richtigen DC. Klappt wunderbar. Nun habe ich noch eine Zoomfunktion. Also das Objekt wird immer größer / kleiner. Wenn das Objekt eine bestimmte Größe erreicht hat, scheint der sekundäre DC nicht mehr zu funktionieren. Dies ist ab etwa 6000 Pixeln Breite der Fall. Wisst ihr warum? Ich habe dazu mal eine kleine Demonstrationsanwendung geschrieben (während der Laufzeit einfach in das Fenster Klicken (Rechtsklicken)):

    #include "windows.h"
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    
    int iSize = 100;
    
    int WINAPI WinMain(          HINSTANCE hInstance,
        HINSTANCE hPrevInstance,
        LPSTR lpCmdLine,
        int nCmdShow
    )
    {
    	MSG msg;
    	WNDCLASS wc;
    	wc.style = CS_HREDRAW | CS_VREDRAW;
    	wc.lpfnWndProc = WndProc;
    	wc.cbClsExtra = 0;
    	wc.cbWndExtra = 0;
    	wc.hInstance = hInstance;
    	wc.hIcon = 0;
    	wc.hCursor = LoadCursor(0, IDC_ARROW);
    	wc.hbrBackground = CreateSolidBrush(RGB(200, 100, 200));
    	wc.lpszMenuName = 0;
    	wc.lpszClassName = "Class";
    
    	RegisterClass(&wc);
    
    	HWND hWindow = CreateWindow("Class", "CreateBitmapTest", WS_OVERLAPPEDWINDOW, 0, 0,
    		400, 400, 0, 0, 0, 0);
    
    	ShowWindow(hWindow, SW_SHOW);
    	UpdateWindow(hWindow);
    
    	while(GetMessage(&msg, 0, 0, 0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    
    	return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	HDC hDC, hMemDC;
    	HBITMAP hMemBitmap;
    	PAINTSTRUCT ps;
    	RECT rect;
    	switch(message)
    	{
    	case WM_LBUTTONUP:
    		iSize *= 2;
    		InvalidateRect(hWnd, 0, TRUE);
    		break;
    	case WM_RBUTTONUP:
    		iSize /= 2;
    		InvalidateRect(hWnd, 0, TRUE);	
    		break;
    	case WM_PAINT:
    		hDC = BeginPaint(hWnd, &ps);
    		hMemDC = CreateCompatibleDC(hDC);
    		hMemBitmap = CreateCompatibleBitmap(hDC, iSize, iSize);
    		SelectObject(hMemDC, hMemBitmap);
    		rect.left = 0;
    		rect.top = 0;
    		rect.right = iSize;
    		rect.bottom = iSize;
    		{
    			char debug[256];
    			wsprintf(debug, "iSize: %i iSize: %i", iSize, iSize);
    			MessageBox(0, debug, 0, 0);
    		}
    		FillRect(hMemDC, &rect, CreateSolidBrush(RGB(100,200,100)));
    		BitBlt(hDC, 0, 0, iSize, iSize, hMemDC, 0, 0, SRCCOPY);
    		EndPaint(hWnd, &ps);
    		DeleteDC(hMemDC);
    		DeleteObject(hMemBitmap);
    		break;
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		break;
    	}
    
    	return DefWindowProc(hWnd, message, wParam, lParam);
    }
    

    DANKE!
    Gruß,
    Kevin



  • Würde es nicht ausreichen, nur den sichtbaren Bereich in den Back-Buffer zu zeichen 🙄



  • Nein, weil ich dann beim Verschieben des Objektes alle Linien neu zeichnen muss => Große Wartezeiten 😞



  • Aber du kannst doch nicht immer alles komplett rendern, wenn du sehr nahe rangezoomt hast - ich denke, du musst da halt einen Kompromiss eingehen und nur etwas über das Fenster hinausrenden.
    BTW: Wäre für solche Sachen nicht OpenGL oder DirectX eigentlich die bessere Wahl 🙄



  • Ich frag mal im Spieleforum nach, wie die das machen.



  • weiß hier niemand mehr weiter?



  • Kleiner Tipp: Wenn du Windows-Nachrichten bearbeitest, solltest du sie (außer wenn es so in der Doku steht) nicht an DefWindowProc weiterreichen. Sonst werden sie doppelt bearbeitet.



  • _Surkevin schrieb:

    weiß hier niemand mehr weiter?

    flenders hat Recht. Du solltest evtl. auf eine andere API umsteigen (OpenGL/Direct3D o.ä.) oder deinen Algorithmus soweit optimieren, dass nur ein kleiner Teil dessen gerendert wird, was über das Fenster hinausragt.

    Benutzt du Windows 9x oder XP?



  • Win2k 🙂



  • directX müsste gut klappen, kann man ja direkt in das fenster rendern lassen 🙂



  • im allgemeinen rendert man alle ansichten mit d3d bzw. ogl.
    für die 2d ansichten verwendet man afaik anstatt der perspektive eine orthogonale projektionsmatrix. dann brauchst du nur die kamera an die entspr. positionen bewegen und das bild in dein denster rendern...fertig


Log in to reply