Sign in to follow this  
Sync Views

can't get images to work with direct3d

Recommended Posts

For somereason my image won't draw. There is no indication that it failed to load. I think it might have something to do with passing and useing the pointers but I'm not sure... draw.h
int sprite_load(char *path)
{
	IDirect3DTexture9 *texture = NULL;
	D3DXIMAGE_INFO scr_info;

	if (FAILED(D3DXCreateTextureFromFileEx
		(d3d_device, path, 0, 0, 1, 0, 
        D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT, 
        NULL, &scr_info, NULL, &texture)))
	{
		texture = NULL;
		file << "texture load failed...\n";
	}

	sprite_data new_sprite;
	new_sprite.texture = texture;
	new_sprite.w = scr_info.Width;
	new_sprite.h = scr_info.Height;
	new_sprite.origin_x = 0;
	new_sprite.origin_y = 0;

	sprite.push_back(new_sprite);
	return sprite.size() -1;
}

int sprite_load_transparent(char *path, D3DCOLOR colourkey)
{
	IDirect3DTexture9 *texture = NULL;
	D3DXIMAGE_INFO scr_info;

	D3DXCreateTextureFromFileEx
		(d3d_device, path, 0, 0, 1, 0, 
        D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT, 
        colourkey, &scr_info, NULL, &texture);

	if (texture == NULL)MessageBox (hwnd, "Failed to load image.", "Error", MB_OK);

	sprite_data new_sprite;
	new_sprite.texture = texture;
	new_sprite.w = scr_info.Width;
	new_sprite.h = scr_info.Height;
	new_sprite.origin_x = 0;
	new_sprite.origin_y = 0;

	sprite.push_back(new_sprite);
	return sprite.size() -1;
}

//Draw a textured quad on the back-buffer
void d3d_blit (IDirect3DTexture9 *texture, RECT *rect_dest,
			   D3DCOLOR colour1, D3DCOLOR colour2, D3DCOLOR colour3, D3DCOLOR colour4,
			   double rotate, int centre_x, int centre_y)
{
	//centre dest
	rect_dest->left   -= centre_x;
	rect_dest->right  -= centre_x;
	rect_dest->top    -= centre_y;
	rect_dest->bottom -= centre_y;

	//convert to radians
	rotate = degtorad(rotate);

	d3d_vertex* vertices;

  //Lock the vertex buffer
	d3d_vertex_buffer->Lock(0, 0, (void**)&vertices, NULL);

  //Setup vertices
  //A -0.5f modifier is applied to vertex coordinates to match texture
  //and screen coords. Some drivers may compensate for this
  //automatically, but on others texture alignment errors are introduced
  //More information on this can be found in the Direct3D 9 documentation
  vertices[0].colour = colour1;
  vertices[0].x = rect_dest->left - 0.5f;
  vertices[0].y = rect_dest->top  - 0.5f;
  vertices[0].z = 0.0f;
  vertices[0].rhw = 1.0f;
  vertices[0].u = 0.0f;
  vertices[0].v = 0.0f;

  vertices[1].colour = colour2;
  vertices[1].x = rect_dest->right - 0.5f;
  vertices[1].y = rect_dest->top   - 0.5f;
  vertices[1].z = 0.0f;
  vertices[1].rhw = 1.0f;
  vertices[1].u = 1.0f;
  vertices[1].v = 0.0f;

  vertices[2].colour = colour3;
  vertices[2].x = rect_dest->right  - 0.5f;
  vertices[2].y = rect_dest->bottom - 0.5f;
  vertices[2].z = 0.0f;
  vertices[2].rhw = 1.0f;
  vertices[2].u = 1.0f;
  vertices[2].v = 1.0f;

  vertices[3].colour = colour4;
  vertices[3].x = rect_dest->left   - 0.5f;
  vertices[3].y = rect_dest->bottom - 0.5f;
  vertices[3].z = 0.0f;
  vertices[3].rhw = 1.0f;
  vertices[3].u = 0.0f;
  vertices[3].v = 1.0f;

  //Handle rotation
  if (rotate != 0)
  {
    RECT rect_origin;
    //Translate destination rect to be centered on the origin
    rect_origin.top    = rect_dest->top    - (int)(centre_y);
    rect_origin.bottom = rect_dest->bottom - (int)(centre_y);
    rect_origin.left   = rect_dest->left   - (int)(centre_x);
    rect_origin.right  = rect_dest->right  - (int)(centre_x);

    //Rotate vertices about the origin
    vertices[0].x = rect_origin.left * cos(rotate)  - rect_origin.top    * sin(rotate);
    vertices[0].y = rect_origin.left * sin(rotate)  + rect_origin.top    * cos(rotate);

	vertices[1].x = rect_origin.right * cos(rotate) - rect_origin.top    * sin(rotate);
    vertices[1].y = rect_origin.right * sin(rotate) + rect_origin.top    * cos(rotate);

    vertices[2].x = rect_origin.right * cos(rotate) - rect_origin.bottom * sin(rotate);
    vertices[2].y = rect_origin.right * sin(rotate) + rect_origin.bottom * cos(rotate);

    vertices[3].x = rect_origin.left * cos(rotate)  - rect_origin.bottom * sin(rotate);
    vertices[3].y = rect_origin.left * sin(rotate)  + rect_origin.bottom * cos(rotate);

    //Translate vertices to proper position
    vertices[0].x += centre_x;
    vertices[0].y += centre_y;
    vertices[1].x += centre_x;
    vertices[1].y += centre_y;
    vertices[2].x += centre_x;
    vertices[2].y += centre_y;
    vertices[3].x += centre_x;
    vertices[3].y += centre_y;
  }
	file << "\nDrawing Sprite:\n\n";
	file << "(" << vertices[0].x << "," << vertices[0].y << ")\n";
	file << "(" << vertices[1].x << "," << vertices[1].y << ")\n";
	file << "(" << vertices[2].x << "," << vertices[2].y << ")\n";
	file << "(" << vertices[3].x << "," << vertices[3].y << ")\n";
  //Unlock the vertex buffer
  d3d_vertex_buffer->Unlock();

  //Set texture
  d3d_device->SetTexture (0, texture);

  //Draw image
  d3d_device->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
}

//void d3d_blit (IDirect3DTexture9 *texture, RECT *rect_dest,
//			   D3DCOLOR colour1, D3DCOLOR colour2, D3DCOLOR colour3, D3DCOLOR colour4,
//			   double rotate, int centre_x, int centre_y)

void draw_sprite(const int id, const int x, const int y)
{
	RECT rect_dest;
	rect_dest.left   = x;
	rect_dest.right  = x + sprite[id].w;
	rect_dest.top    = y;
	rect_dest.bottom = y + sprite[id].h;

	d3d_blit(sprite[id].texture, &rect_dest, c_white, c_white, c_white, c_white, 0, 0, 0);
}

main.cpp -I cut the window creation code out as the window it self works fine just I can't get an image to draw...
struct sprite_data
{
	IDirect3DTexture9 *texture;
	int w, h, origin_x, origin_y;
};
std::vector<sprite_data> sprite;
...
#include "draw.h"
...
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    ...
    int myspr = sprite_load ("texture.jpg");
    while (game_run)
    {
        //message loop...
        ...
        d3d_device->Clear(0, NULL, D3DCLEAR_TARGET,
            D3DCOLOR_XRGB(background_r, background_g, background_b),
            1.0f, 0);
        d3d_device->BeginScene();
        draw_sprite(myspr, 50, 50);
        d3d_device->EndScene();
        d3d_device->Present(NULL, NULL, NULL, NULL);
    }
...
}

output.txt
Drawing Sprite:

(49.5,49.5)
(561.5,49.5)
(561.5,561.5)
(49.5,561.5)

Drawing Sprite:

(49.5,49.5)
(561.5,49.5)
(561.5,561.5)
(49.5,561.5)

...

Share this post


Link to post
Share on other sites
I noticed that you were handling rotation and writing to the file in between Lock() and Unlock(). You should try to keep the code in between as concise as possible because in between those two functions, your program is stalling so that nothing accesses the vertex data. Also, in this section:


rect_dest->left -= centre_x;
rect_dest->right -= centre_x;
rect_dest->top -= centre_y;
rect_dest->bottom -= centre_y;





Are you trying to pinpoint the centre? If so, the left and top values probably shouldn't subtract the centre_x/centre_y variables from themselves because that won't give you the centre (unless there is a reason for it somewhere else in code that you haven't posted)

EDIT: As a side note, you should probably look up D3DXSPRITE because it is useful if you don't want to use too many transformations for a 2D game or program. It could greatly simplify your code while keeping the functionality (after all, it is a 2D program).

Share this post


Link to post
Share on other sites
if the centre was subtracted from some edges and added to others surely that would have the effect of scaling rather than translateing.

Doesn't really ansew why it doesn't draw the image at all though...I'm sure it's something to do with pointers as I had to play around with the "*"'s and "&"'s to get it to even compile so I'm breaking them somewhere between being loaded and draw...

Share this post


Link to post
Share on other sites
Well I redid it all and it seems to work. I think it was the pointers as the diffrence is this time I passed the element number for a vector containing the textures (rather than a pointer to the texture it's self). Might also be because this time I wrote it all my self rather than trying to bolt it together from the example code blocks.

Ive currently got this. Just need to write a version with rotation but I'm not entirly sure how I should do rotation without ending up with a mess like before... (note the c_* are D3DCOLOR constants)

struct sprite_struct
{
IDirect3DTexture9 *image;
int w, h;
int offset_x, offset_y;
};
std::vector<sprite_struct> sprite;


sprite.h

int sprite_load(char *path);
void draw_sprite (const int id, float x, float y, D3DCOLOR c1 = c_white, D3DCOLOR c2 = NULL, D3DCOLOR c3 = NULL, D3DCOLOR c4 = NULL);
void draw_sprite_scaled (const int id, float x, float y, const float scale_x, const float scale_y, D3DCOLOR c1 = c_white, D3DCOLOR c2 = NULL, D3DCOLOR c3 = NULL, D3DCOLOR c4 = NULL);
void draw_sprite_stretched(const int id, float x, float y, const float w, const float h, D3DCOLOR c1 = c_white, D3DCOLOR c2 = NULL, D3DCOLOR c3 = NULL, D3DCOLOR c4 = NULL);

int sprite_load(char *path)
{
IDirect3DTexture9 *texture = NULL;
D3DXIMAGE_INFO scr_info;

if (FAILED(D3DXCreateTextureFromFileEx
(d3d_device, path, 0, 0, 1, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT,
NULL, &scr_info, NULL, &texture)))return -1;

cgm::sprite_struct new_sprite;
new_sprite.image = texture;
new_sprite.w = scr_info.Width;
new_sprite.h = scr_info.Height;
new_sprite.offset_x = 0;
new_sprite.offset_y = 0;

sprite.push_back(new_sprite);
return sprite.size() -1;
}

void draw_sprite(const int id, float x, float y, D3DCOLOR c1, D3DCOLOR c2, D3DCOLOR c3, D3DCOLOR c4)
{
if (c4 == NULL)
{
c2 = c1;
c3 = c1;
c4 = c1;
}

x -= 0.5f + sprite[id].offset_x;
y -= 0.5f + sprite[id].offset_y;

d3d_vertex* vertices;
d3d_vertex_buffer->Lock(0, 0, (void**)&vertices, NULL);

vertices[0].colour = c1;
vertices[0].x = x;
vertices[0].y = y;
vertices[0].z = 0.0;
vertices[0].rhw = 1.0;
vertices[0].u = 0.0;
vertices[0].v = 0.0;

vertices[1].colour = c2;
vertices[1].x = x + sprite[id].w;
vertices[1].y = y;
vertices[1].z = 0.0;
vertices[1].rhw = 1.0;
vertices[1].u = 1.0;
vertices[1].v = 0.0;

vertices[2].colour = c3;
vertices[2].x = x + sprite[id].w;
vertices[2].y = y + sprite[id].h;
vertices[2].z = 0.0;
vertices[2].rhw = 1.0;
vertices[2].u = 1.0;
vertices[2].v = 1.0;

vertices[3].colour = c4;
vertices[3].x = x;
vertices[3].y = y + sprite[id].h;
vertices[3].z = 0.0;
vertices[3].rhw = 1.0;
vertices[3].u = 0.0;
vertices[3].v = 1.0;

d3d_vertex_buffer->Unlock();
d3d_device->SetTexture (0, sprite[id].image);
d3d_device->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
}


void draw_sprite_scaled(const int id, float x, float y, const float scale_x, const float scale_y, D3DCOLOR c1, D3DCOLOR c2, D3DCOLOR c3, D3DCOLOR c4)
{
if (c4 == NULL)
{
c2 = c1;
c3 = c1;
c4 = c1;
}
//scale offset so it's position is still the same relative to the image
x -= 0.5f + (sprite[id].offset_x*scale_x);
y -= 0.5f + (sprite[id].offset_y*scale_y);

d3d_vertex* vertices;
d3d_vertex_buffer->Lock(0, 0, (void**)&vertices, NULL);

vertices[0].colour = c1;
vertices[0].x = x;
vertices[0].y = y;
vertices[0].z = 0.0;
vertices[0].rhw = 1.0;
vertices[0].u = 0.0;
vertices[0].v = 0.0;

vertices[1].colour = c2;
vertices[1].x = x + sprite[id].w*scale_x;
vertices[1].y = y;
vertices[1].z = 0.0;
vertices[1].rhw = 1.0;
vertices[1].u = 1.0;
vertices[1].v = 0.0;

vertices[2].colour = c3;
vertices[2].x = x + sprite[id].w*scale_x;
vertices[2].y = y + sprite[id].h*scale_y;
vertices[2].z = 0.0;
vertices[2].rhw = 1.0;
vertices[2].u = 1.0;
vertices[2].v = 1.0;

vertices[3].colour = c4;
vertices[3].x = x;
vertices[3].y = y + sprite[id].h*scale_y;
vertices[3].z = 0.0;
vertices[3].rhw = 1.0;
vertices[3].u = 0.0;
vertices[3].v = 1.0;

d3d_vertex_buffer->Unlock();
d3d_device->SetTexture (0, sprite[id].image);
d3d_device->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
}

void draw_sprite_stretched(const int id, float x, float y, const float w, const float h, D3DCOLOR c1, D3DCOLOR c2, D3DCOLOR c3, D3DCOLOR c4)
{
if (c4 == NULL)
{
c2 = c1;
c3 = c1;
c4 = c1;
}
//scale offset so it's position is still the same relative to the image
x -= 0.5f + (((float)sprite[id].offset_x/sprite[id].w)*w);
y -= 0.5f + (((float)sprite[id].offset_y/sprite[id].h)*h);

d3d_vertex* vertices;
d3d_vertex_buffer->Lock(0, 0, (void**)&vertices, NULL);

vertices[0].colour = c1;
vertices[0].x = x;
vertices[0].y = y;
vertices[0].z = 0.0;
vertices[0].rhw = 1.0;
vertices[0].u = 0.0;
vertices[0].v = 0.0;

vertices[1].colour = c2;
vertices[1].x = x + w;
vertices[1].y = y;
vertices[1].z = 0.0;
vertices[1].rhw = 1.0;
vertices[1].u = 1.0;
vertices[1].v = 0.0;

vertices[2].colour = c3;
vertices[2].x = x + w;
vertices[2].y = y + h;
vertices[2].z = 0.0;
vertices[2].rhw = 1.0;
vertices[2].u = 1.0;
vertices[2].v = 1.0;

vertices[3].colour = c4;
vertices[3].x = x;
vertices[3].y = y + h;
vertices[3].z = 0.0;
vertices[3].rhw = 1.0;
vertices[3].u = 0.0;
vertices[3].v = 1.0;

d3d_vertex_buffer->Unlock();
d3d_device->SetTexture (0, sprite[id].image);
d3d_device->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this