Why does a texture in OpenTK not show properly? (Wrong colors/Rotated) - vb.net

I've made a list of my own texture objects so that I can access them accordingly. These are the two bitmap images I'm using:
Every time I load my program, it reads from the two bitmap files and stores their texture data into my global texture list. The grass tile one loads first and then the checkerboard with the 1.0 loads after it. The grass tile texture renders. Here is how it looks like in my program:
It appears as if It's rotated 180 degrees and flipped horizontally. I've checked my 2d projection, coordinates and they're alright. Up goes towards positive Y, right towards positive X which, is fine. Also, the colors are alright, the texture works!
However, if I choose to render the second texture, which is the black/magenta checkerboard, it looks like this in my program:
It's rotated and flipped as well, but the colors aren't being rendered properly either. Why does this happen? Here is my code:
Loading the texture from Bitmap:
Private Function LoadFromBitmap(ByVal Bitmap As Bitmap) As Integer
Dim Tex As Integer
GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest)
GL.GenTextures(1, Tex)
GL.BindTexture(TextureTarget.Texture2D, Tex)
Dim Data As BitmapData = Bitmap.LockBits(New Rectangle(0, 0, Bitmap.Width, Bitmap.Height), ImageLockMode.ReadOnly, Imaging.PixelFormat.Format32bppArgb)
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Data.Width, Data.Height, 0, OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, Data.Scan0)
Bitmap.UnlockBits(Data)
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, TextureMagFilter.Nearest)
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, TextureMinFilter.Nearest)
Return Tex
End Function
Rendering:
GL.MatrixMode(MatrixMode.Modelview)
GL.LoadIdentity()
GL.Viewport(0, 0, ControlWidth, ControlHeight)
For X As Byte = 0 To EZSize(0) - 1
For Y As Byte = 0 To EZSize(1) - 1
GL.Enable(EnableCap.Texture2D)
GL.BindTexture(TextureTarget.Texture2D, TextureList.Item(1).IntData)
GL.Begin(PrimitiveType.Quads)
GL.TexCoord2(X, Y) : GL.Vertex2(X, Y)
GL.TexCoord2(X + 1, Y) : GL.Vertex2(X + 1, Y)
GL.TexCoord2(X + 1, Y + 1) : GL.Vertex2(X + 1, Y + 1)
GL.TexCoord2(X, Y + 1) : GL.Vertex2(X, Y + 1)
GL.End()
GL.Disable(EnableCap.Texture2D)
Next
Next
GL.LoadIdentity()
GL.Flush()
GraphicsContext.CurrentContext.SwapInterval = True
GlControl1.SwapBuffers()

If texturing is enabled, then by default the color of the texel is multiplied by the current color, because by default the texture environment mode (GL_TEXTURE_ENV_MODE) is GL_MODULATE. See glTexEnv.
This causes that the color of the texels of the texture is "mixed" by the last color which you have set by glColor.
Set a "white" color before you render the texture, to solve your issue:
GL.Color3(Color.White)
The texture is flipped, because the lower left window coordinate is (0,0), but in the texture the upper right coordinate is (0, 0). You've to compensate that by flipping the v-component of the texture coordinate:
e.g.:
GL.Enable(EnableCap.Texture2D)
GL.BindTexture(TextureTarget.Texture2D, TextureList.Item(1).IntData)
GL.Color3(Color.White)
GL.Begin(PrimitiveType.Quads)
GL.TexCoord2(X, Y + 1) : GL.Vertex2(X, Y)
GL.TexCoord2(X + 1, Y + 1) : GL.Vertex2(X + 1, Y)
GL.TexCoord2(X + 1, Y) : GL.Vertex2(X + 1, Y + 1)
GL.TexCoord2(X, Y) : GL.Vertex2(X, Y + 1)
GL.End()
GL.Disable(EnableCap.Texture2D)
Likewise you can change the environment mode to GL_REPLACE, instead by glTexEnv:
GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, GL_REPLACE)

Related

How to draw an angle arc between line segments in ggplot2?

Is it possible to use ggplot2 (or plotnine or other grammar of graphics packages) to draw an angle arc between two straight line segments as shown below?
(ignore the circle etc.)
I know that this can be done with graphics programs such as Geogebra. But I am interested in drawing the angle mark (and label) programmatically in Jupyter.
(By the way, is there a word for this "angle arc"? I don't know how to call it, and just used "angle arc".)
For R, there is the ggforce package that extends ggplot2 and defines a geom_arc() that comes pretty close. Example below:
library(ggplot2)
library(ggforce)
start <- c(x = 0, y = 0)
dat <- data.frame(
x = start[c("x", "x")],
y = start[c("y", "y")],
xend = c(1, 4),
yend = c(5, 1)
)
angles <- with(dat, atan2(xend - x, yend - y))
ggplot(dat) +
geom_segment(aes(x, y, xend = xend, yend = yend)) +
geom_arc(aes(x0 = start["x"], y0 = start["y"], r = 1,
start = angles[1], end = angles[2])) +
coord_equal()

How to properly use the UnProject method in OpenTK and get world coordinates from mouse hover?

I am trying to get world coordinates by hovering my mouse over the GLControl control where the world is being rendered in. I've found dozens of examples and solutions but I can't work with them, I am still learning and haven't got to their point. But I kept digging and found some examples and picked one that is approved by its original author which works with a similar render construction but still doesn't seem to work for me.
I've set up a window to output the converted coordinates. I am getting x, y = 0 at the center of the control, which means that I'm possibly going the right way. When I move the mouse around the x and y axis it outputs proper values (eg. the higher the mouse from the center of the control, the higher y is, etc.), but only to like -1.65/1.65 max from the center. It does not seem like it gets my Modelview matrix, because It should differ depending on the eyeZ, which it doesn't. Changing the eyeZ has no effect at all. It still acts as if I didn't "zoom in/out".
I've set up my Projection, Modelview matrices and Viewport like this:
GL.MatrixMode(MatrixMode.Projection)
GL.LoadIdentity()
GL.LoadMatrix(Matrix4.CreatePerspectiveFieldOfView(Math.PI / 4, glControl.Width / glControl.Height, 1.0F, 128.0F))
GL.MatrixMode(MatrixMode.Modelview)
GL.LoadIdentity()
GL.LoadMatrix(Matrix4.LookAt(0F, 0F, zoom, 0F, 0F, 0F, 0F, 1.0F, 0F))
GL.Viewport(0, 0, glControl.Width, glControl.Height)
Then I have these two functions that get called when my mouse moves over the GLControl and pass in the mouse's coordinates.
Public Function screenToWorld(ByVal x As Integer, ByVal y As Integer) As Vector4
Dim modelViewMatrix As Matrix4
Dim projectionMatrix As Matrix4
Dim viewport(4) As Integer
GL.GetFloat(GetPName.ModelviewMatrix, modelViewMatrix)
GL.GetFloat(GetPName.ProjectionMatrix, projectionMatrix)
GL.GetInteger(GetPName.Viewport, viewport)
Return UnProject(projectionMatrix, modelViewMatrix, New Size(viewport(2), viewport(3)), New Vector2(x, y))
End Function
Public Function UnProject(ByRef projection As Matrix4, ByVal view As Matrix4, ByVal viewport As Size, ByVal mouse As Vector2) As Vector4
Dim vec As Vector4
vec.X = 2.0F * mouse.X / viewport.Width - 1
vec.Y = -(2.0F * mouse.Y / viewport.Height - 1)
vec.Z = 0F
vec.W = 1.0F
Dim viewInv As Matrix4 = Matrix4.Invert(view)
Dim projInv As Matrix4 = Matrix4.Invert(projection)
Vector4.Transform(vec, projInv, vec)
Vector4.Transform(vec, viewInv, vec)
If vec.W > Single.Epsilon OrElse vec.W < Single.Epsilon Then
vec.X /= vec.W
vec.Y /= vec.W
vec.Z /= vec.W
End If
Return vec
End Function
Also I refrain from using orthrographic projection.

The code/command to determine/change the length/height ratio of scale bar?

I would like to adjust the length/height ratio of the scale bar in an image by the DM scripting. As the following code shown, I can adjust the font size by changing "scalebar.componentsetfontinfo("Microsoft Sans Serif", 0, fontsize)", but I do not know how to change the shape (length/height ratio) of rectangle which constitute to the scale bar. Is there any code/command can achieve this? Thanks,
image front:=getfrontimage()
imagedisplay imgdisp=front.imagegetimagedisplay(0)
number nobar=imgdisp.componentcountchildrenoftype(31)
number fontsize=20
imgdisp.applydatabar(0)
component scalebar=imgdisp.componentgetnthchildoftype(31,0)
scalebar.componentsetfontinfo("Microsoft Sans Serif", 0, fontsize)
scalebar.componentsetdrawingmode(1)
When you select a scalebar, you will notice the green points showing that component's rectangle.
You control that rectangle like you control any component rectangle:
number kScaleBar = 31
image img := GetFrontImage()
imageDisplay disp = img.ImageGetImageDisplay(0)
component scaleBar = disp.ComponentGetNthChildOfType( kScaleBar, 0 )
number t,l,b,r
scaleBar.ComponentGetRect(t,l,b,r)
Result("\n Current rect: [" + t + "/" + l + "/" + b + "/" + r )
number sx, sy
img.GetSize( sx, sy )
// Set centered half at bottom
l = sx*1/4
r = sx*3/4
t = sy*17/20
b = sy*19/20
scaleBar.ComponentSetRect(t,l,b,r)
Note, that you can not explicitly specify the length of the scalebar, it will always "snap" to a meaningful fraction within the boundary box, depending on the image calibration.
Setting the bounding rect will also override the font-size, while setting the font-size will override the boundary rect's height.

implementing ease in update loop

I want to animate a sprite from point y1 to point y2 with some sort of deceleration. when it reaches point y2, the speed of the object will be 0 so it will completely stop.
I Know the two points, and I know the object's starting speed.
The animation time is not so important to me. I can decide on it if needed.
for example: y1 = 0, y2 = 400, v0 = 250 pixels per second (= starting speed)
I read about easing functions but I didn't understand how do I actually implement it in the
update loop.
here's my update loop code with the place that should somehow implement an easing function.
-(void)onTimerTick{
double currentTime = CFAbsoluteTimeGetCurrent() ;
float timeDelta = self.lastUpdateTime - currentTime;
self.lastUpdateTime = currentTime;
float *pixelsToMove = ???? // here needs to be some formula using v0, timeDelta, y2, y1
sprite.y += pixelsToMove;
}
Timing functions as Bézier curves
An easing timing function is basically a Bézier curve from (0,0) to (1,1) where the horizontal axis is "time" and the vertical axis is "amount of change". Since a Bézier curve mathematically is as
start*(1-t)^3 + c1*t(1-t)^2 + c2*t^2(1-t) + end*t^3
you can insert any time value and get the amount of change that should be applied. Note that both time and change is normalized (in the range of 0 to 1).
Note that the variable t is not the time value, t is how far along the curve you have come. The time value is the x value of the point along the curve.
The curve below is a sample "ease" curve that starts off slow, goes faster and slows down in the end.
If for example a third of the time had passed you would calculate what amount of change that corresponds to be update the value of the animated property as
currentValue = beginValue + amountOfChange*(endValue-beginValue)
Example
Say you are animating the position from (50, 50) to (200, 150) using a curve with control points at (0.6, 0.0) and (0.5, 0.9) and a duration of 4 seconds (the control points are trying to be close to that of the image above).
When 1 second of the animation has passed (25% of total duration) the value along the curve is:
(0.25,y) = (0,0)*(1-t)^3 + (0.6,0)*t(1-t)^2 + (0.5,0.9)*t^2(1-t) + (1,1)*t^3
This means that we can calculate t as:
0.25 = 0.6*t(1-t)^2 + 0.5*t^2(1-t) + t^3
Wolfram Alpha tells me that t = 0.482359
If we the input that t in
y = 0.9*t^2*(1-t) + t^3
we will get the "amount of change" for when 1 second of the duration has passed.
Once again Wolfram Alpha tells me that y = 0.220626 which means that 22% of the value has changed after 25% of the time. This is because the curve starts out slow (you can see in the image that it is mostly flat in the beginning).
So finally: 1 second into the animation the position is
(x, y) = (50, 50) + 0.220626 * (200-50, 150-50)
(x, y) = (50, 50) + 0.220626 * (150, 100)
(x, y) = (50, 50) + (33.0939, 22.0626)
(x, y) = (50+33.0939, 50+22.0626)
(x, y) = (83.0939, 72.0626)
I hope this example helps you understanding how to use timing functions.

OpenTK OpenGL Drawing text

I am trying to learn how to do OpenGL using OpenTK and I can successfully draw polygons, circles, and triangles so far but my next question is how to draw text? I have looked at the example on their homepage which was in C# and I translated it to VB .NET.
It currently just draws a white rectangle so I was hoping that someone could spot an error in my code or suggest another way to draw text. I will just list my paint event.
Paint event:
GL.Clear(ClearBufferMask.ColorBufferBit)
GL.Clear(ClearBufferMask.DepthBufferBit)
Dim text_bmp As Bitmap
Dim text_texture As Integer
text_bmp = New Bitmap(ClientSize.Width, ClientSize.Height)
text_texture = GL.GenTexture()
GL.BindTexture(TextureTarget.Texture2D, text_texture)
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, All.Linear)
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, All.Linear)
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, text_bmp.Width, text_bmp.Height, 0 _
, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero)
Dim gfx As Graphics
gfx = Graphics.FromImage(text_bmp)
gfx.DrawString("TEST", Me.Font, Brushes.Red, 0, 0)
Dim data As Imaging.BitmapData
data = text_bmp.LockBits(New Rectangle(0, 0, text_bmp.Width, text_bmp.Height), Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Width, Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0)
text_bmp.UnlockBits(data)
GL.MatrixMode(MatrixMode.Projection)
GL.LoadIdentity()
GL.Ortho(0, width, Height, 0, -1, 1)
GL.Enable(EnableCap.Texture2D)
GL.Enable(EnableCap.Blend)
GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha)
GL.Begin(BeginMode.Quads)
GL.TexCoord2(0.0F, 1.0F)
GL.Vertex2(0.0F, 0.0F)
GL.TexCoord2(1.0F, 1.0F)
GL.Vertex2(1.0F, 0.0F)
GL.TexCoord2(1.0F, 0.0F)
GL.Vertex2(1.0F, 1.0F)
GL.TexCoord2(0.0F, 0.0F)
GL.Vertex2(0.0F, 1.0F)
GL.End()
GlControl1.SwapBuffers()
You'll get a white rectangle if your card doesn't support NPOT (non-power-of-two) texture sizes. Try testing by setting the bitmap size to e.g. 256x256.
That is an ok method. If you plan to draw lots of text or even a medium amount, that will absolutely destroy performance. What you want to do is look into a program called BMFont:
www.angelcode.com/products/bmfont/‎
What this does is create a texture atlas of text, along with an xml file with the positions, width and height and offsets of every letter. You start off by reading that xml file, and loading each character into a class, with the various values. Then you simply make a function that you pass a string which binds the atlas, than depending on the letters in the string, draws a quad with texture coordinates that vary on the xml data. So you might make a:
for each _char in string
create quad according to xml size
assign texture coordinates relative to xml position
increase position so letters don't draw on top of each other
There are tutorials in other languages on the BMFont website which can be helpful.