Avatar billede kamikaze Nybegynder
04. marts 2002 - 12:05 Der er 25 kommentarer og
1 løsning

Rotation af bitmap i DirectDraw

Jeg skal bruge en effektiv måde at rotere bitmaps på i DirectDraw. Er der ikke noget a la PlgBlt()???
Avatar billede jpk Nybegynder
04. marts 2002 - 12:08 #1
Skulle du ikke bruge DirectX 8.x?
Avatar billede kamikaze Nybegynder
04. marts 2002 - 12:43 #2
Jo, men jeg har ikke styr på det endnu. I DirectX8 er directdraw og direct3d smeltet sammen, ikk? Men jeg skal kun bruge 2D-animation, og kender lidt til DirectDraw og overvejer DirectDraw7 interfacet. Har du andre forslag? Hvordan med rotation i 8.x???
Avatar billede jpk Nybegynder
04. marts 2002 - 12:49 #3
Jo, DirectDraw eksisterer ikke længere (8.0+)

Jeg bruger selv denne klasse, prøv at se om den ikke har hvad du skal bruge...



#include <D3dx8tex.h>


// Some D3DCOLOR shortcut macros:
#define DRGBA(r,g,b,a)      ((D3DCOLOR)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
#define DRGB(r,g,b)      ((D3DCOLOR)(((0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
#define GetB(rgb) ((BYTE)(rgb))
#define GetG(rgb) ((BYTE)(((WORD)(rgb)) >> 8))
#define GetR(rgb) ((BYTE)((rgb)>>16))
#define GetA(rgb) ((BYTE)((rgb)>>24))
// Flags Used by DrawRect()
#define DR3DLOOK 0x01
#define DR3DLOOK2 0x02



class CSprite
{
public:
    CSprite::CSprite();
    HRESULT Create(LPDIRECT3DDEVICE8 pd3dDevice, char* pFilename);
    HRESULT InvalidateDeviceObjects();
    HRESULT RestoreDeviceObjects(LPDIRECT3DDEVICE8 pd3dDevice);
    HRESULT DeleteDeviceObjects();
    HRESULT LoadTexture(char *filename);
    HRESULT BltSprite(RECT *pDestRect, RECT *pSrcRect, DWORD dwFlags);
    HRESULT BltSpriteEx(RECT *pDestRect, RECT *pSrcRect, DWORD dwFlags,
            D3DCOLOR modulate = 0xFFFFFFFF, float rotation = 0, POINT *prcenter = NULL);
    HRESULT DrawRect(RECT rc, DWORD fillstyle, D3DCOLOR fillcolor, int bordersize,
            D3DCOLOR bordercolor, DWORD drflags);


    LPDIRECT3DDEVICE8    m_pd3dDevice; // A D3DDevice used for rendering
    LPDIRECT3DTEXTURE8    m_pd3dTexture;
    LPD3DXSPRITE        m_pd3dxSprite;
};







#include "Sprite.h"
#include <ddraw.h>
#include "DXUtil.h"


CSprite::CSprite()
{
    m_pd3dDevice    = NULL;
    m_pd3dTexture    = NULL;
    m_pd3dxSprite    = NULL;
}

HRESULT CSprite::Create(LPDIRECT3DDEVICE8 pd3dDevice, char* pFilename)
{
    m_pd3dDevice = pd3dDevice;
    LoadTexture(pFilename);

    if(FAILED(D3DXCreateSprite(m_pd3dDevice, &m_pd3dxSprite)))
        return E_FAIL;

    return S_OK;
}

HRESULT CSprite::InvalidateDeviceObjects()
{
    SAFE_RELEASE(m_pd3dxSprite);

    return S_OK;
}

HRESULT CSprite::RestoreDeviceObjects(LPDIRECT3DDEVICE8 pd3dDevice)
{
    m_pd3dDevice = pd3dDevice;

    if(FAILED(D3DXCreateSprite(m_pd3dDevice, &m_pd3dxSprite)))
        return E_FAIL;

    return S_OK;
}

//-----------------------------------------------------------------------------
// Name: DeleteDeviceObjects()
// Desc: Destroys all device-dependent objects
//-----------------------------------------------------------------------------
HRESULT CSprite::DeleteDeviceObjects()
{
    SAFE_RELEASE(m_pd3dTexture);
    SAFE_RELEASE(m_pd3dxSprite);
    m_pd3dDevice = NULL;

    return S_OK;
}

//----------------------------------------------------------------------------
// LoadTexture() : Load a texture from a file, returns ptr to texture.
//                  D3DX8 supports BMP, PPM, DDS, JPG, PNG, TGA & DIB.
//----------------------------------------------------------------------------
HRESULT CSprite::LoadTexture(char* pFilename)
{
    // Set black as our source color key. Use 0xFFFF00FF for magenta instead.
    // Use 0x00000000 for no 'color key' substitution
    D3DCOLOR colorkey = 0xFF000000;
    // The D3DX function will fill in the following image info for us
    D3DXIMAGE_INFO SrcInfo; // Optional

    // Load image from file - maintain size of original file.
    // It is also possible to specify a new height/width and ask D3DX to      filter
    // the image to the new size (stretch/shrink). See SDK docs for details.
    return D3DXCreateTextureFromFileEx(m_pd3dDevice, pFilename, 0, 0, 1, 0,
          D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT,
          colorkey, &SrcInfo , NULL, &m_pd3dTexture);
}


//----------------------------------------------------------------------------
// BltSprite() : A replacement of the DirectDraw Blt() function for Direct3D8
// Supports DDBLTFX_MIRRORLEFTRIGHT and DDBLTFX_MIRRORUPDOWN
// If pDestRect is NULL, copies it to the same co-ord as src
// If pSrcRect is NULL, copies the entire texture
//----------------------------------------------------------------------------
HRESULT CSprite::BltSprite(RECT *pDestRect, RECT *pSrcRect, DWORD dwFlags)
{
    D3DXVECTOR2 scaling(1,1), rcenter(0,0), trans(0,0);

    // Set the parameters - translation (screen location)
    if (pDestRect)
    {
          trans.x = (float) pDestRect->left;
          trans.y = (float) pDestRect->top;
    }
    // Scaling - If Source & Destination are different size rects, then scale
    if (pDestRect && pSrcRect)
    {
          scaling.x = ((float) (pDestRect->right - pDestRect->left)) /
              ((float) (pSrcRect->right - pSrcRect->left));
          scaling.y = ((float) (pDestRect->bottom - pDestRect->top)) /
              ((float) (pSrcRect->bottom - pSrcRect->top));
    }
    // Handle the flags - need to change scaling & adjust translation
    if (pSrcRect && dwFlags)
    {
          if (dwFlags&DDBLTFX_MIRRORLEFTRIGHT)
          {
              scaling.x = -scaling.x;
              trans.x += (float) (pDestRect->right - pDestRect->left);
          }
          if (dwFlags&DDBLTFX_MIRRORUPDOWN)
          {
              scaling.y = -scaling.y;
              trans.y += (float) (pDestRect->bottom - pDestRect->top);
          }
    }

    // And here we go:
    return m_pd3dxSprite->Draw(m_pd3dTexture, pSrcRect, &scaling,
              &rcenter, 0, &trans, 0xFFFFFFFF);

}




//----------------------------------------------------------------------------
// BltSpriteEx() : A replacement of the DirectDraw Blt() function for Direct3D8
// Supports DDBLTFX_MIRRORLEFTRIGHT and DDBLTFX_MIRRORUPDOWN,
// modulate is color/alpha modifier
// rotation is value of rotation in RADIANS, counter-clockwise
// prcenter is the rotation centre point of the obj, or NULL
// If pDestRect is NULL, copies it to the same co-ord as src
// If pSrcRect is NULL, copies the entire texture
//----------------------------------------------------------------------------
HRESULT CSprite::BltSpriteEx(RECT *pDestRect, RECT *pSrcRect, DWORD dwFlags,
                    D3DCOLOR modulate, float rotation, POINT *prcenter)
{
    D3DXVECTOR2 scaling(1,1), rcenter(0,0), trans(0,0);

    // Set the parameters - translation (screen location)
    if (pDestRect) {
          trans.x = (float) pDestRect->left;
          trans.y = (float) pDestRect->top;
    }
    // Rotation Center
    if (prcenter) {
          rcenter.x = (float) prcenter->x;
          rcenter.y = (float) prcenter->y;
    } else if (pSrcRect) {
          // Set Rotation Center to be object center if none provided
          rcenter.x = (float) (pSrcRect->right - pSrcRect->left) / 2;
          rcenter.y = (float) (pSrcRect->bottom - pSrcRect->top) / 2;
    }
    // Scaling - If Source & Destination are different size rects, then scale
    if (pDestRect && pSrcRect) {
          scaling.x = ((float) (pDestRect->right - pDestRect->left)) /
              ((float) (pSrcRect->right - pSrcRect->left));
          scaling.y = ((float) (pDestRect->bottom - pDestRect->top)) /
              ((float) (pSrcRect->bottom - pSrcRect->top));
    }
    // Handle the flags - need to change scaling & adjust translation
    if (pSrcRect && dwFlags) {
          if (dwFlags&DDBLTFX_MIRRORLEFTRIGHT) {
              scaling.x = -scaling.x;
              trans.x += (float) (pDestRect->right - pDestRect->left);
    }
          if (dwFlags&DDBLTFX_MIRRORUPDOWN) {
              scaling.y = -scaling.y;
              trans.y += (float) (pDestRect->bottom - pDestRect->top);
          }
    }

    // And here we go:
    return m_pd3dxSprite->Draw(m_pd3dTexture, pSrcRect, &scaling,
              &rcenter, rotation, &trans, modulate);

}



//-----------------------------------------------------------------------------
// DrawRect() : Draws a rect on 'the viewport' using Clear, with some options
//      This is not a Microsoft-endorsed use of the Clear command!
//      Note that the Alpha values of colors are significant - 0xFF for opaque
//      fillstyle: GDI values of BS_SOLID or BS_NULL (hollow)
//      bordersize is -ve for internal to rectangle
//      drflags are DR3DLOOK or DR3DLOOK2 for embossed shadow button effects
//-----------------------------------------------------------------------------
HRESULT CSprite::DrawRect(RECT rc, DWORD fillstyle, D3DCOLOR fillcolor, int bordersize,
          D3DCOLOR bordercolor, DWORD drflags)
{
    // Error if not a normal rectangle
    if (rc.bottom-rc.top < 1) return DDERR_INVALIDPARAMS;
    if (rc.right-rc.left < 1) return DDERR_INVALIDPARAMS;

    // First, we do the inside (fill) part
    switch (fillstyle) {
    case BS_SOLID:
          // Fill area is full size of rectangle
          m_pd3dDevice->Clear( 1, (D3DRECT *)&rc, D3DCLEAR_TARGET,
              fillcolor, 1.0f, 0);
          break;
    case BS_NULL:
    default:
          // No fill or unknown, no action
          break;
    }

    // This handles drawing the borders (four sides)
    if (bordersize != 0) {
          D3DCOLOR topbord=bordercolor, botbord=bordercolor;
          RECT brc;
          // Adjust for border outside of rect if +ve border size:
          if (bordersize > 0) {
              rc.left -= bordersize;
              rc.right += bordersize;
              rc.top -= bordersize;
              rc.bottom += bordersize;
              bordersize = -bordersize;
          }

          // Embossed effect flags:
          if (drflags & DR3DLOOK) {
              topbord = DRGB( (GetR(bordercolor)+255)/2,
                    (GetG(bordercolor)+255)/2, (GetB(bordercolor)+255)/2 );
              botbord = DRGB( (GetR(bordercolor))/2,
                        (GetG(bordercolor))/2, (GetB(bordercolor))/2 );
          } else if (drflags & DR3DLOOK2) {
              // Reversed shadow, for 'selected' look
              topbord = DRGB( (GetR(bordercolor))/2,
                    (GetG(bordercolor))/2, (GetB(bordercolor))/2 );
              botbord = DRGB( (GetR(bordercolor)+255)/2,
                    (GetG(bordercolor)+255)/2, (GetB(bordercolor)+255)/2 );
          }

          // Draw top and left
          SetRect(&brc, rc.left, rc.top, rc.right, rc.top - bordersize);
          m_pd3dDevice->Clear( 1, (D3DRECT *)&brc, D3DCLEAR_TARGET,
                    topbord, 1.0f, 0);
          SetRect(&brc, rc.left, rc.top, rc.left-bordersize, rc.bottom);
          m_pd3dDevice->Clear( 1, (D3DRECT *)&brc, D3DCLEAR_TARGET,
                    topbord, 1.0f, 0);

          // Draw bottom and right
          SetRect(&brc, rc.left, rc.bottom+bordersize, rc.right, rc.bottom);
          m_pd3dDevice->Clear( 1, (D3DRECT *)&brc, D3DCLEAR_TARGET,
                    botbord, 1.0f, 0);
          SetRect(&brc, rc.right+bordersize, rc.top, rc.right, rc.bottom);
          m_pd3dDevice->Clear( 1, (D3DRECT *)&brc, D3DCLEAR_TARGET,
                    botbord, 1.0f, 0);

    }

    return S_OK;
}
Avatar billede kamikaze Nybegynder
04. marts 2002 - 13:15 #4
Tak - Det ser rigtig godt ud. Tjekker den lige ud...
Avatar billede kamikaze Nybegynder
04. marts 2002 - 13:18 #5
Hvad skal der linkes til???
Avatar billede jpk Nybegynder
04. marts 2002 - 13:25 #6
For at bruge IDirect3DDevice8 & IDirect3DTexture8, skal du linke med D3d8.lib
Avatar billede kamikaze Nybegynder
04. marts 2002 - 13:29 #7
TNX
Avatar billede kamikaze Nybegynder
04. marts 2002 - 13:32 #8
Mangler der ikke nogen private attributter i classen (CSprite)???
Avatar billede kamikaze Nybegynder
04. marts 2002 - 13:34 #9
Sorry, nej det gør der ikke....
Avatar billede jpk Nybegynder
04. marts 2002 - 13:35 #10
Man kunne godt "privatisere" de 3 attributter, jeg kan ikke lige huske hvad grund jeg har haft til ikke at gøre det...
Avatar billede jpk Nybegynder
04. marts 2002 - 13:39 #11
Klassen gør det rimelig simpelt at lavbe 2D-grafik i DX8.
Den gør det faktisk ved at bruge 3D-funktionalitet, så den kan bruge hardwareacceleration, hvis det er tilgængelig.
Avatar billede kamikaze Nybegynder
04. marts 2002 - 13:42 #12
Hvad med dxutil.h - Hvor er c eller lib filen? (eller er det dynamisk?)
Avatar billede jpk Nybegynder
04. marts 2002 - 13:50 #13
Du includer den bare ligesom enhver anden fil.
Du kan bare bruge:
#include <DXUtil.h>,
Avatar billede kamikaze Nybegynder
04. marts 2002 - 13:52 #14
c:\msvc_proj\ddtest\ddtest\csprite.cpp(3) : fatal error C1083: Cannot open include file: 'DXUtil.h': No such file or directory
Avatar billede kamikaze Nybegynder
04. marts 2002 - 13:54 #15
Det skal lige siges, at jeg sidder på en NT40 maskine med DirectX8 sdk installeret, så det kommer ikke til at køre. Men det skulle da gerne kompilere!?! (Jeg skal lige tage mig sammen, og køre win2k på den senere idag)
Avatar billede jpk Nybegynder
04. marts 2002 - 13:56 #16
Har du sat path'en til DX libs'ne?
Bruger du VC++?
Avatar billede kamikaze Nybegynder
04. marts 2002 - 14:05 #17
Jeg bruger VC++ og lod installationen sætte path'en. Har også søgt efter DXUtil.h og fandt to i nogle samples. Men ikke i include-mappen.
Avatar billede jpk Nybegynder
04. marts 2002 - 14:12 #18
Ahh, du har ret...

Jeg bruger faktisk kun en enkelt makro derfra, i CSprite klassen, nemlig:

#define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }

Denn kan du bare lige sætte i .cpp-filen
Avatar billede kamikaze Nybegynder
04. marts 2002 - 14:19 #19
Så har jeg lige nogle nye linker-fejl:

CSprite.obj : error LNK2001: unresolved external symbol _D3DXCreateSprite@8
CSprite.obj : error LNK2001: unresolved external symbol _D3DXCreateTextureFromFileExA@56
Avatar billede kamikaze Nybegynder
04. marts 2002 - 14:21 #20
Det kunne måske skyldes at det er en NT4 maskine ???
Avatar billede jpk Nybegynder
04. marts 2002 - 14:23 #21
ID3DXSprite kræver D3dx8.lib, sorry...
Avatar billede kamikaze Nybegynder
04. marts 2002 - 14:28 #22
Nu kompilerer det. Glæder mig til at prøve din klasse - det ser lækkert ud - men det må lige vente på nyt OS... 1000 tak indtil videre, lader lige spm være åbent et par dage, OK? :-)
Avatar billede kamikaze Nybegynder
09. marts 2002 - 11:58 #23
jpk >> Undskyld ventetiden, men har først lige fået tid til at prøve det af. Har lidt problemer:

DDMain.obj : error LNK2001: unresolved external symbol _Direct3DCreate8@4

Kan ikke finde oplysninger i SDK'en om hvad jeg skal linke til. Gider du ikke at poste navne på alle libs+header filer du bruger, eller at poste noget kode der skaber et LPDIRECT3D8 object???
Avatar billede kamikaze Nybegynder
09. marts 2002 - 12:01 #24
Jeg gør flg.:

LPDIRECT3D8 g_pD3D;
D3DDISPLAYMODE d3ddm;
LPDIRECT3DDEVICE8 g_pd3dDevice; //pd3dDevice;
D3DPRESENT_PARAMETERS d3dpp;

// i min main WndProc, under WM_CREATE:

if( NULL == ( g_pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) )
    return E_FAIL;
   
if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
    return E_FAIL;

               
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed  = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;


if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice )))
    return E_FAIL;

// Det er copy-and-paste fra SDK'en, men giver ovenstående linkerfejl.
Avatar billede kamikaze Nybegynder
09. marts 2002 - 12:09 #25
OK, jeg har fundet ud af linker fejlen (manglede d3d8.lib). Nu skal jeg bare have din sprite-klasse til at vise noget.........
Avatar billede kamikaze Nybegynder
09. marts 2002 - 12:17 #26
Jamen, det virker jo. Glæder mig til at teste rotations-hastigheden..... 1000 tak for hjælpen :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester