Iodiplin
Knave
USA
67 Posts |
Posted - Aug 27 2004 : 6:53:59 PM
|
This is an error I have known of for quite some time, but I've never worried about it. Now that I'm writing a game with my engine, I need the bug fixed.
Here's the problem:
When initializing the vertices for the images I'm rendering, I obviously must set the texture coordinates. This works fine, in some cases.
My image is not square, therefore I put it in a bitmap whose dementions are square in squares of 2. When I render the entire bitmap, with or without transparency, and all things at normal values (no flipping, no cropping), it looks just fune:
However, when I flip it, it doesn't work out so well:
As you can see, after being flipped horizontally, a column of pixels has been taken from the right side of the image and rendered on the left side.
The same thing happens when it is flipped vertically:
When both horizontal and vertical flipping are applied, the you get glitches on both ends:
I did some specialized debeugging and found that if I subtracted two pixel rows/columns from the texture coordinates the problem was fixed. (Two pixels in texture coordinates found by 1 / TextureSize * 2.)
However, when I then set up the geomitry with the actual size of the image (so that it cropped the render to the size 41x15), it produced an image with 2 rows/columns of pixels missing on one the opposite side of the flip.
Like this (flipped both horizontally and vertically):
So, I'm stuck, I can't think of any reason why this is happening besides some esoteric glitch in my texture coordinate calculations.
My Initialize Lit Geometry function is supplied below. I hope it is commented enough that you can understand what's going on.
Public Function InitLitGeom(Vertices() As VERTEX_LIT, X As Single, Y As Single, TextureDesc As D3DSURFACE_DESC, Optional Width As Single, Optional Height As Single, Optional SrcX As Single, Optional SrcY As Single, Optional SrcWidth As Single, Optional SrcHeight As Single, Optional Angle As Single, Optional FlipHorizontal As Boolean, Optional FlipVertical As Boolean, Optional Color0 As Long, Optional Color1 As Long, Optional Color2 As Long, Optional Color3 As Long, Optional DefaultColor As Long = COL_BLACK, Optional Spec0 As Long, Optional Spec1 As Long, Optional Spec2 As Long, Optional Spec3 As Long, Optional DefaultSpec As Long) As Long Dim XCenter As Single Dim YCenter As Single Dim UsedX As Single Dim UsedY As Single Dim SinAngle As Double Dim CosAngle As Double Dim Src As RECT Dim Dest As RECT Dim TwoPixX As Single Dim TwoPixY As Single On Local Error GoTo ErrorHandler If SrcWidth = 0 Then SrcWidth = TextureDesc.Width If SrcHeight = 0 Then SrcHeight = TextureDesc.Height If Width = 0 Then Width = SrcWidth If Height = 0 Then Height = SrcHeight With Src .Left = SrcX .Top = SrcY .Right = SrcX + SrcWidth .Bottom = SrcY + SrcHeight End With With Dest .Left = X .Top = Y .Right = X + Width .Bottom = Y + Height End With If Color0 = 0 Then Color0 = DefaultColor If Color1 = 0 Then Color1 = DefaultColor If Color2 = 0 Then Color2 = DefaultColor If Color3 = 0 Then Color3 = DefaultColor If Spec0 = 0 Then Spec0 = DefaultSpec If Spec1 = 0 Then Spec1 = DefaultSpec If Spec2 = 0 Then Spec2 = DefaultSpec If Spec3 = 0 Then Spec3 = DefaultSpec TwoPixX = 1 / TextureDesc.Width TwoPixX = TwoPixX + TwoPixX TwoPixY = 1 / TextureDesc.Height TwoPixY = TwoPixY + TwoPixY If Angle = 0 Then UsedX = Dest.Left UsedY = Dest.Top Else XCenter = Dest.Left + (Dest.Right - Dest.Left - 1) * 0.5 YCenter = Dest.Top + (Dest.Bottom - Dest.Top - 1) * 0.5 SinAngle = Sin(Angle + RightAngle) CosAngle = Cos(Angle + RightAngle) UsedX = XCenter + (Dest.Left - XCenter) * SinAngle + (Dest.Top - YCenter) * CosAngle UsedY = YCenter + (Dest.Top - YCenter) * SinAngle - (Dest.Left - XCenter) * CosAngle End If If FlipHorizontal = True And FlipVertical = False Then Vertices(0) = CreateTLVertex(UsedX, UsedY, 0, 1, Color0, Spec0, (Src.Right + 1) / TextureDesc.Width - TwoPixX, Src.Top / TextureDesc.Height) ElseIf FlipVertical = True And FlipHorizontal = False Then Vertices(0) = CreateTLVertex(UsedX, UsedY, 0, 1, Color0, Spec0, Src.Left / TextureDesc.Width, (Src.Bottom + 1) / TextureDesc.Height - TwoPixY) ElseIf FlipHorizontal = True And FlipVertical = True Then Vertices(0) = CreateTLVertex(UsedX, UsedY, 0, 1, Color0, Spec0, (Src.Right + 1) / TextureDesc.Width - TwoPixX, (Src.Bottom) / TextureDesc.Height - TwoPixY) Else Vertices(0) = CreateTLVertex(UsedX, UsedY, 0, 1, Color0, Spec0, Src.Left / TextureDesc.Width, Src.Top / TextureDesc.Height) End If If Angle = 0 Then UsedX = Dest.Right UsedY = Dest.Top Else UsedX = XCenter + (Dest.Right - XCenter) * SinAngle + (Dest.Top - YCenter) * CosAngle UsedY = YCenter + (Dest.Top - YCenter) * SinAngle - (Dest.Right - XCenter) * CosAngle End If If FlipHorizontal = True And FlipVertical = False Then Vertices(1) = CreateTLVertex(UsedX, UsedY, 0, 1, Color1, Spec1, Src.Left / TextureDesc.Width - TwoPixX, Src.Top / TextureDesc.Height) ElseIf FlipVertical = True And FlipHorizontal = False Then Vertices(1) = CreateTLVertex(UsedX, UsedY, 0, 1, Color1, Spec1, (Src.Right + 1) / TextureDesc.Width, (Src.Bottom + 1) / TextureDesc.Height - TwoPixY) ElseIf FlipHorizontal = True And FlipVertical = True Then Vertices(1) = CreateTLVertex(UsedX, UsedY, 0, 1, Color1, Spec1, Src.Left / TextureDesc.Width - TwoPixX, (Src.Bottom + 1) / TextureDesc.Height - TwoPixY) Else Vertices(1) = CreateTLVertex(UsedX, UsedY, 0, 1, Color1, Spec1, (Src.Right + 1) / TextureDesc.Width, Src.Top / TextureDesc.Height) End If If Angle = 0 Then UsedX = Dest.Left UsedY = Dest.Bottom Else UsedX = XCenter + (Dest.Left - XCenter) * SinAngle + (Dest.Bottom - YCenter) * CosAngle UsedY = YCenter + (Dest.Bottom - YCenter) * SinAngle - (Dest.Left - XCenter) * CosAngle End If If FlipHorizontal = True And FlipVertical = False Then Vertices(2) = CreateTLVertex(UsedX, UsedY, 0, 1, Color2, Spec2, (Src.Right + 1) / TextureDesc.Width - TwoPixX, (Src.Bottom + 1) / TextureDesc.Height) ElseIf FlipVertical = True And FlipHorizontal = False Then Vertices(2) = CreateTLVertex(UsedX, UsedY, 0, 1, Color2, Spec2, Src.Left / TextureDesc.Width, Src.Top / TextureDesc.Height - TwoPixY) ElseIf FlipHorizontal = True And FlipVertical = True Then Vertices(2) = CreateTLVertex(UsedX, UsedY, 0, 1, Color2, Spec2, (Src.Right + 1) / TextureDesc.Width - TwoPixX, Src.Top / TextureDesc.Height - TwoPixY) Else Vertices(2) = CreateTLVertex(UsedX, UsedY, 0, 1, Color2, Spec2, Src.Left / TextureDesc.Width, (Src.Bottom + 1) / TextureDesc.Height) End If If Angle = 0 Then UsedX = Dest.Right UsedY = Dest.Bottom Else UsedX = XCenter + (Dest.Right - XCenter) * SinAngle + (Dest.Bottom - YCenter) * CosAngle UsedY = YCenter + (Dest.Bottom - YCenter) * SinAngle - (Dest.Right - XCenter) * CosAngle End If If FlipHorizontal = True And FlipVertical = False Then Vertices(3) = CreateTLVertex(UsedX, UsedY, 0, 1, Color3, Spec3, Src.Left / TextureDesc.Width - TwoPixX, (Src.Bottom + 1) / TextureDesc.Height) ElseIf FlipVertical = True And FlipHorizontal = False Then Vertices(3) = CreateTLVertex(UsedX, UsedY, 0, 1, Color3, Spec3, (Src.Right + 1) / TextureDesc.Width, Src.Top / TextureDesc.Height - TwoPixY) ElseIf FlipHorizontal = True And FlipVertical = True Then Vertices(3) = CreateTLVertex(UsedX, UsedY, 0, 1, Color3, Spec3, Src.Left / TextureDesc.Width - TwoPixX, Src.Top / TextureDesc.Height - TwoPixY) Else Vertices(3) = CreateTLVertex(UsedX, UsedY, 0, 1, Color3, Spec3, (Src.Right + 1) / TextureDesc.Width, (Src.Bottom + 1) / TextureDesc.Height) End If ErrorHandler: InitLitGeom = Err.Number End Function
Thank you so much for your assistance. |
Environment Makes All the Difference. |
|
sdw
Warrior
USA
160 Posts |
Posted - Aug 27 2004 : 7:57:16 PM
|
For one, use some other variable for TextureDesc.Width and TextureDesc.Height, they're the same value and using something like TextureDimension would make it more readable. Same thing for the TwoPixY and TwoPixX deal, except I would get rid of those altogether. That center doesn't look right, it should be something like:
XCenter = Dest.Left + (Width / 2) YCenter = Dest.Top + (Height /2)
Also everywhere there's a (Src.Right + 1) and (Src.Bottom + 1) should be the opposite: (Src.Right - 1) and (Src.Bottom - 1)
I remember fixing this function up a while ago, and I think I got it to work nicely, except that I never had it flip the image. If you like you can look at the function:
Public Sub DrawObj(TexID As Long, DestX As Single, DestY As Single, SrcWidth As Integer, SrcHeight As Integer, Optional SrcX As Single, Optional SrcY As Single, Optional DestWidth As Integer, Optional DestHeight As Integer, Optional Color As Long, Optional Specular As Long, Optional Alphablend As Boolean, Optional Angle As Single) Dim TempVerts(3) As TLVERTEX Dim lDim As Long Dim DestXRight As Single Dim DestYBottom As Single Dim SrcXRight As Single Dim SrcYBottom As Single Dim XCor As Single Dim YCor As Single Dim XCenter As Single Dim YCenter As Single If DestWidth = 0 Then DestWidth = SrcWidth If DestHeight = 0 Then DestHeight = SrcHeight XCenter = DestX + (DestWidth / 2) YCenter = DestY + (DestHeight / 2) DestXRight = DestX + DestWidth DestYBottom = DestY + DestHeight SrcXRight = SrcX + SrcWidth SrcYBottom = SrcY + SrcHeight lDim = Textures(TexID).lDimension If Angle = 0 Then XCor = DestX YCor = DestY Else XCor = XCenter + RotateX(DestX - XCenter, DestY - YCenter, Angle) YCor = YCenter + RotateY(DestX - XCenter, DestY - YCenter, Angle) End If TempVerts(0) = CreateTLVertex(XCor, YCor, 0, 1, Color, Specular, SrcX / lDim, SrcY / lDim) If Angle = 0 Then XCor = DestXRight YCor = DestY Else XCor = XCenter + RotateX(DestXRight - XCenter, DestY - YCenter, Angle) YCor = YCenter + RotateY(DestXRight - XCenter, DestY - YCenter, Angle) End If TempVerts(1) = CreateTLVertex(XCor, YCor, 0, 1, Color, Specular, (SrcXRight - 1) / lDim, SrcY / lDim) If Angle = 0 Then XCor = DestX YCor = DestYBottom Else XCor = XCenter + RotateX(DestX - XCenter, DestYBottom - YCenter, Angle) YCor = YCenter + RotateY(DestX - XCenter, DestYBottom - YCenter, Angle) End If TempVerts(2) = CreateTLVertex(XCor, YCor, 0, 1, Color, Specular, SrcX / lDim, (SrcYBottom - 1) / lDim) If Angle = 0 Then XCor = DestXRight YCor = DestYBottom Else XCor = XCenter + RotateX(DestXRight - XCenter, DestYBottom - YCenter, Angle) YCor = YCenter + RotateY(DestXRight - XCenter, DestYBottom - YCenter, Angle) End If TempVerts(3) = CreateTLVertex(XCor, YCor, 0, 1, Color, Specular, (SrcXRight - 1) / lDim, (SrcYBottom - 1) / lDim) Dev.SetTexture 0, Textures(TexID).D3DTexture If (D3DCaps.TextureCaps And D3DPTEXTURECAPS_ALPHA) Then Dev.SetRenderState D3DRS_ALPHABLENDENABLE, True If Alphablend = True Then Dev.SetRenderState D3DRS_SRCBLEND, D3DBLEND_ONE Dev.SetRenderState D3DRS_DESTBLEND, D3DBLEND_ONE Else Dev.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA Dev.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA End If End If Dev.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, TempVerts(0), Len(TempVerts(0)) If Dev.GetRenderState(D3DRS_ALPHABLENDENABLE) Then Dev.SetRenderState D3DRS_ALPHABLENDENABLE, 0 End If End Sub Public Function RotateX(X As Single, Y As Single, Angle As Single) As Single Dim tx As Single, TAngle As Single TAngle = Angle * (Pi / 180) tx = X * Cos(TAngle) - Y * Sin(TAngle) RotateX = tx End Function Public Function RotateY(X As Single, Y As Single, Angle As Single) As Single Dim ty As Single, TAngle As Single TAngle = Angle * (Pi / 180) ty = Y * Cos(TAngle) + X * Sin(TAngle) RotateY = ty End Function
I think those rotation functions are from the dabooda engine. If you add your flipping code to that then it might get you what you want.
|
|
|
Iodiplin
Knave
USA
67 Posts |
Posted - Aug 27 2004 : 8:18:05 PM
|
Hey thanks! I'll see what I can do with your code. |
Environment Makes All the Difference. |
|
|
Iodiplin
Knave
USA
67 Posts |
Posted - Aug 27 2004 : 8:51:16 PM
|
I used your function to render my image with cropping (no flipping) and it added an extra column of pixels at the left and cut of the tips of the bottom and end.
Perhaps I'm just using it incorrectly. Any ideas?
EDIT: Does anyone have any working projects I can download to see the whole thing working? |
Environment Makes All the Difference. |
Edited by - Iodiplin on Aug 27 2004 8:52:15 PM |
|
|
sdw
Warrior
USA
160 Posts |
Posted - Aug 28 2004 : 12:32:04 AM
|
Hmm, it seems when I tested it I was not using it to crop an image. The subtraction of 1 from the SrcXRight and SrcYBottom is not needed. I again modified the function:
Public Sub DrawObj(TexID As Long, DestX As Single, DestY As Single, SrcWidth As Integer, SrcHeight As Integer, Optional SrcX As Single, Optional SrcY As Single, Optional DestWidth As Integer, Optional DestHeight As Integer, Optional Color As Long, Optional Specular As Long, Optional Alphablend As Boolean, Optional Angle As Single) Dim TempVerts(3) As TLVERTEX Dim lDim As Long Dim DestXRight As Single Dim DestYBottom As Single Dim SrcXRight As Single Dim SrcYBottom As Single Dim XCor As Single Dim YCor As Single Dim XCenter As Single Dim YCenter As Single If Not Color Then Color = RGB(255, 255, 255) If DestWidth = 0 Then DestWidth = SrcWidth If DestHeight = 0 Then DestHeight = SrcHeight XCenter = DestX + (DestWidth / 2) YCenter = DestY + (DestHeight / 2) DestXRight = DestX + DestWidth DestYBottom = DestY + DestHeight SrcXRight = SrcX + SrcWidth SrcYBottom = SrcY + SrcHeight lDim = Textures(TexID).lDimension If Angle = 0 Then XCor = DestX YCor = DestY Else XCor = XCenter + RotateX(DestX - XCenter, DestY - YCenter, Angle) YCor = YCenter + RotateY(DestX - XCenter, DestY - YCenter, Angle) End If TempVerts(0) = CreateTLVertex(XCor, YCor, 0, 1, Color, Specular, SrcX / lDim, SrcY / lDim) If Angle = 0 Then XCor = DestXRight YCor = DestY Else XCor = XCenter + RotateX(DestXRight - XCenter, DestY - YCenter, Angle) YCor = YCenter + RotateY(DestXRight - XCenter, DestY - YCenter, Angle) End If TempVerts(1) = CreateTLVertex(XCor, YCor, 0, 1, Color, Specular, SrcXRight / lDim, SrcY / lDim) If Angle = 0 Then XCor = DestX YCor = DestYBottom Else XCor = XCenter + RotateX(DestX - XCenter, DestYBottom - YCenter, Angle) YCor = YCenter + RotateY(DestX - XCenter, DestYBottom - YCenter, Angle) End If TempVerts(2) = CreateTLVertex(XCor, YCor, 0, 1, Color, Specular, SrcX / lDim, SrcYBottom / lDim) If Angle = 0 Then XCor = DestXRight YCor = DestYBottom Else XCor = XCenter + RotateX(DestXRight - XCenter, DestYBottom - YCenter, Angle) YCor = YCenter + RotateY(DestXRight - XCenter, DestYBottom - YCenter, Angle) End If TempVerts(3) = CreateTLVertex(XCor, YCor, 0, 1, Color, Specular, SrcXRight / lDim, SrcYBottom / lDim) Dev.SetTexture 0, Textures(TexID).D3DTexture If (D3DCaps.TextureCaps And D3DPTEXTURECAPS_ALPHA) Then Dev.SetRenderState D3DRS_ALPHABLENDENABLE, True If Alphablend = True Then Dev.SetRenderState D3DRS_SRCBLEND, D3DBLEND_ONE Dev.SetRenderState D3DRS_DESTBLEND, D3DBLEND_ONE Else Dev.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA Dev.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA End If End If Dev.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, TempVerts(0), Len(TempVerts(0)) If Dev.GetRenderState(D3DRS_ALPHABLENDENABLE) Then Dev.SetRenderState D3DRS_ALPHABLENDENABLE, 0 End If End Sub
I tested it and it seems to work, hopefully for you as well. I'm going to be needing to use this function too :)
-> On another subject -> Eric, if you're reading, the 'Preview Reply' window does not display the code tags properly, unless that's intended to be that way. I am just making sure you know. |
Edited by - sdw on Aug 28 2004 12:33:14 AM |
|
|
Iodiplin
Knave
USA
67 Posts |
Posted - Aug 28 2004 : 10:26:36 AM
|
I tested it, and got the same results as last time. There must be something wrong with the way I'm calling it. Would you mind e-mailing me your project (if it's small) or maybe just give me an example of how you call it and use it?
I'm a desperate man as of now, I'll take anything I can get to clear this up. Thank you very much.
P.S. I was able to get around my problem in some cercumstances by offsetting the image in the bitmap by 1 pixel. However, this made cropping worse, but eliminated the extra columns/rows of pixels when flipping (unclipped). |
Environment Makes All the Difference. |
|
|
Iodiplin
Knave
USA
67 Posts |
Posted - Aug 28 2004 : 10:50:49 AM
|
Actually, with a little more testing, I think I might be able to get this to work. Thanks!
|
Environment Makes All the Difference. |
|
|
Eric Coleman
Gladiator
USA
811 Posts |
Posted - Aug 28 2004 : 2:37:55 PM
|
Open the DirectX 8 help file and follow this directory structure...
DirectX 8.1 (Visual Basic) > DirectX Graphics >> Programmers Guide >>> Using Direct 3D >>>> Textures >>>>> Texture Coordinates >>>>>> Directly Mapping Texels to Pixels
It gives the formula for converting texture coordinates into texel coordinates. It seems you need to calculate the correct texture coordinate, so the formula that you would use would be:
u = (Tx + 0.5) / Mx v = (Ty + 0.5) / My
And this generates single precision (float) coordinates, which is what you need. |
|
|
Eric Coleman
Gladiator
USA
811 Posts |
Posted - Aug 28 2004 : 2:41:17 PM
|
quote: Originally posted by sdw
-> On another subject -> Eric, if you're reading, the 'Preview Reply' window does not display the code tags properly, unless that's intended to be that way. I am just making sure you know.
The code formatting is a bit of a hack that I added to the forum. I am aware that the preview function doesn't display the code formatting properly. I'm so busy working on other parts of VBgamer that it's not really a priority to fix. And hopefully I'll be able to get rid of this forum and use the custom forum that the news comments are now using. |
|
|
Almar
Moderator
Netherlands
192 Posts |
Posted - Aug 29 2004 : 07:48:56 AM
|
- Make your textures like 16x32 or 64x64, 128x128, etc. - Turn off filtering, or texture wrapping. It's something with that. I had it too with my Elements contest entry, until I finally figured out the problem.
|
|
|
Iodiplin
Knave
USA
67 Posts |
Posted - Aug 29 2004 : 2:55:49 PM
|
My textures are all square and all dimensions (of the bitmaps) are in squares of two.
Thanks a lot! |
Environment Makes All the Difference. |
|
|
|
|