Jump to content
  • Advertisement
Sign in to follow this  
David_SO

OpenGL Direct3D Texture Coordinates

This topic is 5439 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am a hobbyist programmer and I have been studying Direct3D and OpenGL at the same time for about 2 months. I am now able to successfully load a rotating textured cube from vertex arrays on both APIs (thanks to the excellent Codesampler, Drunken Hyena and Nehe tutorials). I have gathered the following relevant differences between the two APIs. OpenGL uses a right handed coordinate system while Direct3D defaults to the left. OpenGL places the (0,0) UV texture coordinates from the bottom left while Direct3D places them at the top left. So here is my problem. I want a single/common vertex array to provide information for my 3D object (i.e., a rotating textured cube) for both APIs. I have decided to use the OpenGL defaults because there are far more OpenGL tutorials out there in the internet than Direct3D. However, to be able to do this I need to convert the Direct3D coordinate systems to match OpenGL. I know that I can tell Direct3D to use a right handed coordinate system BUT I have not seen anything in the DirectX SDK docs on how to modify the texture coordinate systems so that the texture is read from the bottom left just like OpenGL. I suspect (someone please correct me if I am wrong) that this is the reason why it is a bit more difficult to write a Direct3D MD2 loader as MD2 files have been written natively for OpenGL. Alternatively, has anyone ever attempted to write an algorithm in C++ to flip the texture in software so that even if Direct3D reads it from the top, the textures would still be properly mapped to the mesh? Can anyone help please? And sorry for the long post...

Share this post


Link to post
Share on other sites
Advertisement
Well, this isn't really helpful, but the only way I can figure it out (I might be wrong, I've never used OpenGL) is to swap the values. This would be slower, but when you're loading the information:
Make a temporary copy of the vertices, then do as follows:
00 = temp01
10 = temp11
01 = temp00
11 = temp10

This may be way off and not even useful, so sorry if it isn't.

Oh, and I believe I saw something about the difference between (how to switch between) the two different systems on one of the sites out here (drunkenhyena's site, andypike.com, nexe/nehe, etc), but I can't remember which one it was.

Hopefully this helps somehow, if not sorry again

Share this post


Link to post
Share on other sites
Hey Programmer16, thanks.

Your proposed solution would involve a texture "flipper" (no pun intended) of some sort. However, I would not want to do this unless I have no other choice. The reason is because I would have to devise an algorithm that needs to perform texture transformation via matrices (I think). There is bound to be some significant performance hit for this.

I do know for a fact that several open source 3D Engines have managed to pull this off like Irrlicht and 3DE and I suppose I can try to dig into their source code for the solution... But before I start doing that, there may just be a clever programmer here in Gamedev who have done it before and is willing to share his/her knowledge...

Share this post


Link to post
Share on other sites
Okay, I think I found the section of code that irrlicht uses to flip their texture coords, but it uses all of the classes that they do. So, I can send you the file in an email, or (if you have it downloaded you can look in the CVideoDirectX9.cpp file in the void CVideoDirectX9::draw2DImage() function. I believe that its done in that function:


if (!texture)
return;

if (texture)
{
if (texture->getDriverType() != EDT_DIRECTX9)
{
os::Printer::log("Fatal Error: Tried to copy from a surface not owned by this driver.", ELL_ERROR);
return;
}
}

if (sourceRect.UpperLeftCorner.X >= sourceRect.LowerRightCorner.X ||
sourceRect.UpperLeftCorner.Y >= sourceRect.LowerRightCorner.Y)
return;

core::position2d<s32> targetPos = pos;
core::position2d<s32> sourcePos = sourceRect.UpperLeftCorner;
core::dimension2d<s32> sourceSize(sourceRect.getWidth(), sourceRect.getHeight());
const core::dimension2d<s32> targetSurfaceSize = ScreenSize;

if (clipRect)
{
if (targetPos.X < clipRect->UpperLeftCorner.X)
{
sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;
if (sourceSize.Width <= 0)
return;

sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
targetPos.X = clipRect->UpperLeftCorner.X;
}

if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X)
{
sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
if (sourceSize.Width <= 0)
return;
}

if (targetPos.Y < clipRect->UpperLeftCorner.Y)
{
sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
if (sourceSize.Height <= 0)
return;

sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
targetPos.Y = clipRect->UpperLeftCorner.Y;
}

if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y)
{
sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
if (sourceSize.Height <= 0)
return;
}
}

// clip these coordinates

if (targetPos.X<0)
{
sourceSize.Width += targetPos.X;
if (sourceSize.Width <= 0)
return;

sourcePos.X -= targetPos.X;
targetPos.X = 0;
}

if (targetPos.X + sourceSize.Width > targetSurfaceSize.Width)
{
sourceSize.Width -= (targetPos.X + sourceSize.Width) - targetSurfaceSize.Width;
if (sourceSize.Width <= 0)
return;
}

if (targetPos.Y<0)
{
sourceSize.Height += targetPos.Y;
if (sourceSize.Height <= 0)
return;

sourcePos.Y -= targetPos.Y;
targetPos.Y = 0;
}

if (targetPos.Y + sourceSize.Height > targetSurfaceSize.Height)
{
sourceSize.Height -= (targetPos.Y + sourceSize.Height) - targetSurfaceSize.Height;
if (sourceSize.Height <= 0)
return;
}

// ok, we've clipped everything.
// now draw it.

if (useAlphaChannelOfTexture)
setRenderStates2DMode(false, true, true);
else
setRenderStates2DMode(false, true, false);

setTexture(0, texture);

core::rect<s32> poss(targetPos, sourceSize);

s32 xPlus = -(ScreenSize.Width>>1);
f32 xFact = 1.0f / (ScreenSize.Width>>1);

s32 yPlus = ScreenSize.Height-(ScreenSize.Height>>1);
f32 yFact = 1.0f / (ScreenSize.Height>>1);

const core::dimension2d<s32> sourceSurfaceSize = texture->getOriginalSize();
core::rect<f32> tcoords;
tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)+0.5f) / texture->getOriginalSize().Width ;
tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)+0.5f) / texture->getOriginalSize().Height;
tcoords.LowerRightCorner.X = (((f32)sourcePos.X +0.5f + (f32)sourceSize.Width)) / texture->getOriginalSize().Width;
tcoords.LowerRightCorner.Y = (((f32)sourcePos.Y +0.5f + (f32)sourceSize.Height)) / texture->getOriginalSize().Height;

S3DVertex vtx[4];
vtx[0] = S3DVertex((f32)(poss.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-poss.UpperLeftCorner.Y ) * yFact , 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
vtx[1] = S3DVertex((f32)(poss.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus- poss.UpperLeftCorner.Y) * yFact, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
vtx[2] = S3DVertex((f32)(poss.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus-poss.LowerRightCorner.Y) * yFact, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
vtx[3] = S3DVertex((f32)(poss.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-poss.LowerRightCorner.Y) * yFact, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);

s16 indices[6] = {0,1,2,0,2,3};

setVertexShader(EVT_STANDARD);

pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0],
D3DFMT_INDEX16,&vtx[0], sizeof(S3DVertex));



Hopefully thats the right code, because I can't seem to find any other code that seems to do it.

Share this post


Link to post
Share on other sites
Thanks but I think the code above is the clipping methods used by the Irrlicht engine for materials in Direct3D.

At any rate, here is my proposed texture coordinate transformation algorithm for Direct3D

// Define a texture object
IDirect3DTexture9 *g_texture=NULL;

// Load in the image file to create the texture at stage 0
D3DXCreateTextureFromFile( g_d3d_device, "Foo.bmp",&g_texture );

// HELP!!! - Set up the matrix for the desired transformation.
D3DMATRIX matTrans = D3DXMatrixFooFunction( Params that I do not know );

// Apply the texture coordinate transformation for texture stage 0. The
// D3DTS_TEXTURE0 flag tells Direct3D to apply the transformation to the
// texture located at texture stage 0.
g_d3d_device->SetTransform( D3DTS_TEXTURE0, &matTrans );

// The D3DTTFF_COUNT2 value instructs the system to apply the transformation
// matrix set for texture stage 0, and then pass the first two elements of the
// modified texture coordinates to the rasterizer.
g_d3d_device->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );

// Set the texture
g_d3d_device->SetTexture( 0, g_texture );


What kind of matrix transformation do i need to do above? Is this inverse (D3DXMatrixInverse) or transpose (D3DMatrixTranspose) or some other obscure D3DX function???

Share this post


Link to post
Share on other sites
Umm, I have edited my post. My previous rant about the MD2 stuff was completely wrong... ahem.

I have found out that the best way to achieve what I wanted to do (single vertex array for OpenGL and Direct3D) was to simply use a right handed coordinate system for Direct3D for the mesh coordinates. For the UV coordinates, if the texture address is from 0 to 1, just subtract 1 from the V coordinates, feed the adjusted coordinates to a list and then whack them to the screen.

Hope this becomes useful to someone.

[Edited by - David_SO on October 21, 2004 8:04:12 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Heh. That is better (referring to previous post).

If you do not want to use the right hand coordinates for Direct3D, you just need to negate the Z axis of the model - multiply by negative one (in addition to adjusting the v coordinates of the texture).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!