Is there some strange problem with directX that makes it strech the X axis of textures on widescreen computers? I'm using rectangles to load animation frames and the rectangles match perfectly with the image in photoshop. However, I recently upgraded my engine core to be able to randomly place the rectangle on the image as opposed to using a static row/columns setup. It seems to work, but for some reason the coordinate system isn't matching up to the directX texture. I've debugged and everything I wrote has consistent values (the rectangles still mach up with photoshop's images). The texture is not square, but it is a power of 2. My card is fairly new, so I don't think that's the problem. My code covers several pages, but I'll post as much of it as I can, my animation classes and such.
struct cFrame2d
{
RECT coords; //texture position
//int ox; //offset
//int oy; //offset
float duration;
cFrame2d()
{
coords.left = 0;
coords.bottom = 1;
coords.right = 1;
coords.top = 0;
//ox = 0;
//oy = 0;
duration = 10.0f;
}
void operator=(const cFrame2d &rhs)
{
coords = rhs.coords;
//ox = rhs.ox;
//oy = rhs.oy;
duration = rhs.duration;
}
void Save(std::ofstream &file)
{
file.write((char*)&coords, sizeof(RECT));
file.write((char*)&duration, sizeof(float));
}
void Load(std::ifstream &file)
{
file.read((char*)&coords, sizeof(RECT));
file.read((char*)&duration, sizeof(float));
}
};
class cAnimData2d
{
protected:
cFrame2d *m_anim; //This is the actual animation
unsigned long size; //This is the size of the animation
//Engine vars
float last;
int index;
//bool loop; //Looping trigger
public:
cAnimData2d()
{
m_anim = new cFrame2d[1];
size = 1;
last = 0.0f;
index = 0;
}
cAnimData2d(const cAnimData2d &rhs)
{
delete [] m_anim;
size = rhs.size;
m_anim = new cFrame2d[size];
for(int i = 0; i < size; i++)
{
m_anim = rhs.m_anim;
}
last = rhs.last;
index = rhs.index;
}
~cAnimData2d()
{
delete [] m_anim;
}
void operator=(const cAnimData2d &rhs)
{
delete [] m_anim;
size = rhs.size;
m_anim = new cFrame2d[size];
for(int i = 0; i < size; i++)
{
m_anim = rhs.m_anim;
}
last = rhs.last;
index = rhs.index;
}
void Start()
{
last = 0.0f;
index = 0;
}
void Reset()
{
index = 0;
}
void Stop()
{
index = size;
}
void SetFrame(int i)
{
if(i >= size || i < 0)
return;
else
index = i;
}
bool Ended()
{
if(index >= size)
return true;
else
return false;
}
bool CheckDuration(float now)
{
if(((now-last) >= m_anim[index].duration))
return true;
else
return false;
}
void Update(float now)
{
if(CheckDuration(now) && !Ended())
{
++index;
last = now;
}
}
RECT *GetFrame(float now)
{
if(CheckDuration(now) && !Ended())
{
++index;
last = now;
}
if(Ended())
return &m_anim[0].coords;
else
return &m_anim[index].coords;
}
RECT* GetFrame()
{
if(Ended())
return &m_anim[0].coords;
else
return &m_anim[index].coords;
}
void Save(std::ofstream &file)
{
file.write((char*)&size, sizeof(unsigned long));
for(int i = 0; i < size; i++)
{
m_anim.Save(file);
}
}
void Load(std::ifstream &file)
{
file.read((char*)&size, sizeof(unsigned long));
delete [] m_anim;
m_anim = new cFrame2d[size];
for(int i = 0; i < size; i++)
{
m_anim.Load(file);
}
}
};
class cAnimation2d //Holds animation information. Use an array to hold multiple animation
{
protected:
cAnimData2d *m_data; //Pointer to array of animation datas
unsigned long m_size;
public:
cAnimation2d()
{
m_data = new cAnimData2d[1];
m_size = 1;
}
cAnimation2d(const cAnimation2d &rhs)
{
m_size = rhs.m_size;
delete [] m_data;
m_data = new cAnimData2d[m_size];
for(int a = 0; a < m_size; a++)
{
m_data[a] = rhs.m_data[a];
}
}
void operator=(const cAnimation2d &rhs)
{
m_size = rhs.m_size;
delete [] m_data;
m_data = new cAnimData2d[m_size];
for(int a = 0; a < m_size; a++)
{
m_data[a] = rhs.m_data[a];
}
}
~cAnimation2d()
{
delete [] m_data; //free data memory
m_size = 0;
}
RECT* GetFrame(int index, float now) {
if(index >= m_size || index < 0)
return NULL;
return m_data[index].GetFrame(now);
}
RECT* GetFrame(int index)
{
if(index >= m_size || index < 0)
return NULL;
return m_data[index].GetFrame();
}
bool Start(int index)
{
if(index >= m_size || index < 0)
return false;
else
m_data[index].Start();
return true;
}
bool Reset(int index)
{
if(index >= m_size || index < 0)
return false;
else
m_data[index].Reset();
return true;
}
void Stop(int index){
if(index >= m_size || index < 0)
return;
else
m_data[index].Stop();
}
bool Check(int index)
{
if(index >= m_size || index < 0)
return false;
return m_data[index].Ended();
}
void Update(int index, float now)
{
if(index >= m_size || index < 0)
return;
m_data[index].Update(now);
}
void SetFrame(int index, int frame)
{
if(index >= m_size || index < 0)
return;
else
m_data[index].SetFrame(frame);
}
RECT* LoopAnimation(int index, float now) //If an end tag is throw we just continue to run
{
if(index >= m_size || index < 0)
return NULL;
if(m_data[index].Ended())
m_data[index].Reset();
return m_data[index].GetFrame(now);
}
bool Save(LPCSTR filename)
{
std::ofstream file;
file.open(filename, std::ios::binary);
if(file.is_open())
{
file.write((char*)&m_size, sizeof(unsigned long));
for(int i = 0; i < m_size; i++)
{
m_data.Save(file);
}
file.close();
return true;
}
else
return false;
}
bool Load(LPCSTR filename)
{
std::ifstream file;
file.open(filename, std::ios::binary);
if(file.is_open())
{
file.read((char*)&m_size, sizeof(unsigned long));
delete [] m_data;
m_data = new cAnimData2d[m_size];
for(int i = 0; i < m_size; i++)
{
m_data.Load(file);
}
file.close();
return true;
}
else
return false;
}
};
those are the animation classes. Here is the rendering routine
bool CORE::cGraphics::_LoadTexture(std::string &dir)
{
Graphics::DirectX::iTexture* texture = new Graphics::DirectX::iTexture;
if(texture->Create(&m_D3D, dir.c_str()))
{
//map mode
m_textures[dir] = texture;
return true;
}
delete texture;
texture = NULL;
return false;
}
bool CORE::cGraphics::_RenderSprite(cBase2d *source)
{
if(source == NULL)
return false;
//use typecasting here. This keeps the RSM in line
m_sprite.Place(source->m_x, source->m_y);
m_sprite.Rotate(source->m_r);
m_sprite.Scale(source->m_sx, source->m_sy);
m_sprite.SetCenter(source->m_cx, source->m_cy);
m_sprite.SetScaleCenter(source->m_sc);
//do animtation calculations
//set the sprite RECT to the animation index rect
RECT *area;
RECT rect;
area = NULL;
if(source->m_index != -1)
{
area = source->m_animation.GetFrame(source->m_index);
if(area == NULL)
{
m_sprite.SetRect(NULL);
}
else
{
if(area->bottom == 0||area->right == 0)
{
m_sprite.SetRect(NULL);
}
else{
m_sprite.SetRect(area);
}
}
}
else
{
m_sprite.SetRect(NULL);
}
//This sets the rect and is all we really have to do
if(!m_sprite.Render(m_textures[source->m_dir])) //draws a single sprite
return false;
m_sprite.SetRect(NULL);
return true;
}
both are class based, and cBase2d holds an animation class that it uses to render a texture loaded by the texture class. I'll throw that up here too:
class iTexture
{
protected:
LPDIRECT3DTEXTURE9 pTexture;
friend class iSprite;;
public:
iTexture() { pTexture = NULL; }
~iTexture()
{
if(pTexture)
pTexture->Release();
pTexture = NULL;
}
bool Create(Graphics::DirectX::DirectXLayer *parent, LPCSTR file)
{
return SUCCEEDED(D3DXCreateTextureFromFile(parent->Device(),file,&pTexture));
}
bool Use(Graphics::DirectX::DirectXLayer *parent, DWORD stage = 0)
{
return SUCCEEDED(parent->Device()->SetTexture(stage,pTexture));
}
};
for the life of me I cannot see how I broke the system I created. Sorry for the long post, but I should mention that I did have the row/column thing working using a vector to hold animation data. I figured this would be an improvement, but the X axis just hates me alot I guess.
***********
Update: I did some experimenting. It seems that when the texture is square it streches it on both axises. Is it my graphics card not supporting textures larger that 512? Just for closure: It's not my card, actually, it is DirectX ensuring that I don't actually have a crappy card, and so it is forcing the texture to a square power of 2 texture by streching, rather than simply adding null pixels.
[Edited by - Plasmarobo on March 9, 2008 10:30:03 AM]
___________________________________________________Optimists see the glass as Half FullPessimists See the glass as Half EmptyEngineers See the glass as Twice as big as it needs to be