 |
 |
Member Community Game Development, 3D Modeling, Art, Sound Effects and more
|
 |
 |
 |
 |
|
 |
 |
 |
 |
 |
codeslasher
Joined: 23 Jun 2007 Posts: 144
 |
Posted: Sat Dec 13, 2008 1:49 pm Post subject: Assumptions about coord (0,0) in games engines |
 |
|
Hi people,
I recently started working with the MS3D format for my game engine.
After getting all the code in place, including texture mapping, I noticed that the texture for the models were upside down.
I spent hours going over the code and rewriting it thinking that it was my fault.
After a lot of trials, I finally discovered the problem.
All my texture so far have been in the TGA format but the MS3D models I was working with used BMP formats for the textures.
It seems that the game engine works with texture maps where the (0,0) coord is at the lower left hand corner, while the models use BMP textures with (0,0) at the top left hand corner.
To solve the problem, I had to flip the BMP image.
Is there a way to avoid this kind of problems?
Does a game engine need to set conventions for these kind of things? |
|
| |
|
|
|
 |
 |
 |
 |
 |
BugHunter

Joined: 06 Aug 2008 Posts: 180 Location: Russia  |
Posted: Sun Dec 14, 2008 5:08 am Post subject: Texture origin/orientation standard |
 |
|
Thank you, codeslasher, for this warning, you probably safe someone’s time. The idea to standardize the texture-orientation in GE is quite topical.
I would propose some simple and straightforward solution. IMHO, there is no way to avoid memory swapping in general case, especially because GE employs Texture Transformation already. To avoid confusion and overdesign we would better to flip (if necessary) the texture on the loading stage. Later on, if we want to reduce load-time we can prepare (e.g. flip properly) textures at design-time. The idea is that when we are only on the developing & testing stage the performance is not critical yet. If we are going to ship the product, it may be worth to spend some time on optimization (in this case – just flipping the textures in some picture-editor to make them right oriented, so there would be no need to flip at run-time).
The idea is that we should separate image-flipping subsystem from image-loader. After that what we do is:
• load image into memory: Texture::LoadImage( ) => LoadTGA( ) | LoadBMP( ) | LoadTIFF( ) etc.
• determine texture orientation (read appropriate fields of native image-file format, or accompany meta-file, or apply defaults);
• flip memory if current orientation differs from targeting one;
• create texture;
Additionally, taking into account that some (if not most of) image-file formats do not have an information about orientation, we can add an extra file with meta-information (similar to accompany file for font texture), which reports the orientation. Btw, I use ini-file to accompany font textures, so for me it is not difficult to add “texture orientation” field. The lack of the field (or even the lack of the accompany file) means default behavior or that the orientation should be obtained by reading native image format (i.e., as you remember, TGA has such info). Image-loader, i.e. LoadTGA( ), LoadBMP( ) etc must know how to obtain orientation. For instance, LoadTGA( ) should always read appropriate TGA fields, LoadBMP( ) should check external file first, and if there is no external file, then assume default for BMP orientation = origin is at TopLeft. Etc.
(One small drawback of this approach is that for those “unfortunate” formats which happened to have different orientation then OpenGL wants by default, i.e. BMP, we have to either, flip the image at load-time, or apply the “optimization” – make metafile & flip the image in pic-editor).
THE TEXTURE'S ORIENTATION/ORIGIN STANDARD for MK-GE:
• for OpenGL: origin is at the left bottom corner, thus x-axe points right, y-axe points up;
• for DirectX (I’m not sure): origin is at the left up corner, thus x-axe points right, y-axe points down;
• 3rd party renderer: RTM
• your renderer: you should know
Below is some sample stuff which might be useful to reach our goals (that is only the mere idea, everyone can adjust the code to her liking).
| Code: |
//
// Origin and axes direction
//
// | |
// T--10---11--
// | |
// B--00---01--
// | |
// L R
//
enum AxeAndDirBit
{
AXE_X = 0, //
AXE_Y = 1, //
DirLeftToRight = 0, // DirL2R -->
DirRightToLeft = 1, // DirR2L <--
DirBottomToTop = 0, // DirB2T ^
DirTopToBottom = 1, // DirT2B v
};
enum TexOrigin //
{ // YX
TexOriginLeftBottom = ( DirBottomToTop << AXE_Y ) | ( DirLeftToRight << AXE_X ), // 00 = 0 = BL
TexOriginRightBottom = ( DirBottomToTop << AXE_Y ) | ( DirRightToLeft << AXE_X ), // 01 = 1 = BR
TexOriginLeftTop = ( DirTopToBottom << AXE_Y ) | ( DirLeftToRight << AXE_X ), // 10 = 2 = UL
TexOriginRightTop = ( DirTopToBottom << AXE_Y ) | ( DirRightToLeft << AXE_X ), // 11 = 3 = UR
TexOriginDefaultGL = TexOriginLeftBottom, //
TexOriginDefaultDX = TexOriginLeftTop, // ? check it
};
Texture::TexOrigin Texture::GetTargetOrigin() const
{
switch ( Options::GetRendererType() )
{
default:
case GR_OpenGL : return TexOriginDefaultGL;
case GR_DirectX: return TexOriginDefaultDX;
}
}
:
TexOrigin Texture::m_curOrigin;
// At the end of LoadXXX ( XXX = TGA | BMP | TIFF etc ) define orientation
// for instance, for in LoadTGA():
//
// encode image orientation
//
{
m_texOrigin = TexOrigin(
(( (header.ImageDescriptor & 0x10) ? DirRightToLeft : DirLeftToRight ) << AXE_X) |
(( (header.ImageDescriptor & 0x20) ? DirTopToBottom : DirBottomToTop ) << AXE_Y) );
}
:
// At the end of LoadImage() call FlipImage( )
// NOTE: m_colorType = 3 for RGB, or 4 for RGBA
void Texture::FlipImage()
{
const bool flipAxeY = ( GetTargetOrientation() & (1 << AXE_Y) ) != ( GetCurOrientation() & (1 << AXE_Y) );
const bool flipAxeX = ( GetTargetOrientation() & (1 << AXE_X) ) != ( GetCurOrientation() & (1 << AXE_X) );
if ( flipAxeX )
{
for (size_t h = 0; h < m_height; ++h)
for (size_t wi = 0, wj = m_width - 1; wi < wj; ++wi, --wj)
swap_block( GetPixel(wi, h), GetPixel(wj, h), m_colorType );
}
if ( flipAxeY )
{
const size_t lineSize = m_colorType * m_width;
for (size_t hi = 0, hj = m_height - 1; hi < hj; ++hi, --hj)
swap_mem( GetPixel(0, hi), GetPixel(0, hj), lineSize );
}
}
inline
BYTE* Texture::GetPixel( size_t x, size_t y ) { return &m_imageData[ m_colorType * ( x + y * m_width ) ]; }
//------------------------------------------------------------------------------
// the helpers from my library
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Swap two small blocks of memory (slow, good for short blocks)
//------------------------------------------------------------------------------
inline void swap_block(BYTE *a, BYTE *b, size_t block_size)
{
while ( block_size-- )
std::swap( *a++, *b++ );
}
//------------------------------------------------------------------------------
// swap_mem() uses intermediate buffer.
//------------------------------------------------------------------------------
void swap_mem(BYTE *a, BYTE *b, size_t block_size)
{
const size_t CUTOFF = 8;
const size_t CHUNK = 256;
const size_t bloks = block_size / CHUNK;
const size_t remain = block_size % CHUNK;
BYTE t[ CHUNK ];
for (size_t c = 0; c < bloks; ++c, a += CHUNK, b += CHUNK) // swap main part
{
memcpy( t, a, CHUNK ); memcpy( a, b, CHUNK ); memcpy( b, t, CHUNK );
}
if (remain > CUTOFF) // swap the remainder via buffer memory
{
memcpy( t, a, remain ); memcpy( a, b, remain ); memcpy( b, t, remain );
}
else // use byte-wise copy
{
swap_block( a, b, remain );
}
}
|
Anyway, any ideas which can improve this approach are cordial welcome. _________________ «Computer scientists deal with algorithms that you may call practical in theory but unpractical in practice.» © Timothy Gowers |
|
| |
|
|
|
 |
 |
 |
 |
 |
codeslasher
Joined: 23 Jun 2007 Posts: 144
 |
Posted: Tue May 04, 2010 11:08 am Post subject: |
 |
|
My assumption about BMP format above is not correct
While working on skinning, I finally found out what the problem was.
Its MilkShape3D. In milkshape3D, the texture (0,0) is at the TOP Left hand corner. So to sucessfully load any image used to texture an ms3d model, we have to flip it VERTICALLY. |
|
| |
|
|
|
 |
 |
 |
 |
 |
|
 |
 |
 |
 |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|
|
 |