I need to draw string/text in opengl/opentk and then rotate it along z axis from the center of text itself.
This is what I have tried so far:
void drawstring(string text, Font font, float fontsize, SolidBrush brush, float x, float y)
{
if (text == null || text == "")
return;
/*
OpenTK.Graphics.Begin();
OpenTK.Graphics.OpenGL.GL.PushMatrix();
OpenTK.Graphics.OpenGL.GL.Translate(x, y, 0);
printer.Print(text, font, c);
OpenTK.Graphics.OpenGL.GL.PopMatrix(); printer.End();
*/
float maxy = 1;
foreach (char cha in text)
{
int charno = (int)cha;
int charid = charno ^ (int)(fontsize * 1000) ^ brush.Color.ToArgb();
if (!charDict.ContainsKey(charid))
{
charDict[charid] = new character()
{
bitmap = new Bitmap(128, 128, System.Drawing.Imaging.PixelFormat.Format32bppArgb),
size = (int)fontsize
};
charDict[charid].bitmap.MakeTransparent(Color.Transparent);
//charbitmaptexid
float maxx = this.Width / 150; // for space
// create bitmap
using (var gfx = Graphics.FromImage(charDict[charid].bitmap))
{
var pth = new GraphicsPath();
if (text != null)
pth.AddString(cha + "", font.FontFamily, 0, fontsize + 5, new Point((int)0, (int)0),
StringFormat.GenericTypographic);
charDict[charid].pth = pth;
gfx.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
gfx.DrawPath(this._p, pth);
//Draw the face
gfx.FillPath(brush, pth);
if (pth.PointCount > 0)
{
foreach (PointF pnt in pth.PathPoints)
{
if (pnt.X > maxx)
maxx = pnt.X;
if (pnt.Y > maxy)
maxy = pnt.Y;
}
}
}
charDict[charid].width = (int)(maxx + 2);
//charbitmaps[charid] = charbitmaps[charid].Clone(new RectangleF(0, 0, maxx + 2, maxy + 2), charbitmaps[charid].PixelFormat);
//charbitmaps[charno * (int)fontsize].Save(charno + " " + (int)fontsize + ".png");
// create texture
int textureId;
OpenTK.Graphics.OpenGL.GL.TexEnv(OpenTK.Graphics.OpenGL.TextureEnvTarget.TextureEnv, OpenTK.Graphics.OpenGL.TextureEnvParameter.TextureEnvMode,
(float)TextureEnvModeCombine.Replace); //Important, or wrong color on some computers
Bitmap bitmap = charDict[charid].bitmap;
OpenTK.Graphics.OpenGL.GL.GenTextures(1, out textureId);
OpenTK.Graphics.OpenGL.GL.BindTexture(OpenTK.Graphics.OpenGL.TextureTarget.Texture2D, textureId);
BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
OpenTK.Graphics.OpenGL.GL.TexImage2D(OpenTK.Graphics.OpenGL.TextureTarget.Texture2D, 0, OpenTK.Graphics.OpenGL.PixelInternalFormat.Rgba, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, OpenTK.Graphics.OpenGL.PixelType.UnsignedByte, data.Scan0);
OpenTK.Graphics.OpenGL.GL.TexParameter(OpenTK.Graphics.OpenGL.TextureTarget.Texture2D, OpenTK.Graphics.OpenGL.TextureParameterName.TextureMinFilter,
(int)TextureMinFilter.Linear);
OpenTK.Graphics.OpenGL.GL.TexParameter(OpenTK.Graphics.OpenGL.TextureTarget.Texture2D, OpenTK.Graphics.OpenGL.TextureParameterName.TextureMagFilter,
(int)TextureMagFilter.Linear);
// OpenTK.Graphics.OpenGL.GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest);
//OpenTK.Graphics.OpenGL.GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Nearest);
OpenTK.Graphics.OpenGL.GL.Flush();
bitmap.UnlockBits(data);
charDict[charid].gltextureid = textureId;
}
float scale = 1.0f;
// dont draw spaces
if (cha != ' ')
{
/*
TranslateTransform(x, y);
DrawPath(this._p, charDict[charid].pth);
//Draw the face
FillPath(brush, charDict[charid].pth);
TranslateTransform(-x, -y);
*/
//OpenTK.Graphics.OpenGL.GL.Enable(EnableCap.Blend);
//OpenTK.Graphics.OpenGL.GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
OpenTK.Graphics.OpenGL.GL.BlendFunc(OpenTK.Graphics.OpenGL.BlendingFactor.SrcAlpha, OpenTK.Graphics.OpenGL.BlendingFactor.OneMinusSrcAlpha);
OpenTK.Graphics.OpenGL.GL.Enable(OpenTK.Graphics.OpenGL.EnableCap.Texture2D);
OpenTK.Graphics.OpenGL.GL.BindTexture(OpenTK.Graphics.OpenGL.TextureTarget.Texture2D, charDict[charid].gltextureid);
OpenTK.Graphics.OpenGL.GL.Begin(OpenTK.Graphics.OpenGL.PrimitiveType.TriangleFan);
OpenTK.Graphics.OpenGL.GL.TexCoord2(0, 0);
OpenTK.Graphics.OpenGL.GL.Vertex2(x, y);
OpenTK.Graphics.OpenGL.GL.TexCoord2(1, 0);
OpenTK.Graphics.OpenGL.GL.Vertex2(x + charDict[charid].bitmap.Width * scale, y);
OpenTK.Graphics.OpenGL.GL.TexCoord2(1, 1);
OpenTK.Graphics.OpenGL.GL.Vertex2(x + charDict[charid].bitmap.Width * scale, y + charDict[charid].bitmap.Height * scale);
OpenTK.Graphics.OpenGL.GL.TexCoord2(0, 1);
OpenTK.Graphics.OpenGL.GL.Vertex2(x + 0, y + charDict[charid].bitmap.Height * scale);
OpenTK.Graphics.OpenGL.GL.End();
//OpenTK.Graphics.OpenGL.GL.Disable(EnableCap.Blend);
OpenTK.Graphics.OpenGL.GL.Disable(OpenTK.Graphics.OpenGL.EnableCap.Texture2D);
}
x += charDict[charid].width * scale;
}
}
I am able to write text with this but unable to rotate. And also for some characters it is taking too much space which causes a gap between texts.
I am able to write text with this but unable to rotate
You have to apply a rotation matrix to the model view matrix.
Choose the model view matrix stack glMatrixMode(GL_MODELVIEW)
.
Push the current matrix on the matrix stack glPushMatrix
.
Multiply the current matrix by a rotation matrix around the z-axis glRotate
OpenTK.Graphics.OpenGL.GL.MatrixMode(OpenTK.Graphics.OpenGL.MatrixMode.ModelView);
OpenTK.Graphics.OpenGL.GL.PushMatrix();
OpenTK.Graphics.OpenGL.GL.Rotated( angle_degree, 0.0, 0.0, 1.0);
OpenTK.Graphics.OpenGL.GL.Begin(OpenTK.Graphics.OpenGL.PrimitiveType.TriangleFan);
OpenTK.Graphics.OpenGL.GL.TexCoord2(0, 0);
OpenTK.Graphics.OpenGL.GL.Vertex2(x, y);
OpenTK.Graphics.OpenGL.GL.TexCoord2(1, 0);
OpenTK.Graphics.OpenGL.GL.Vertex2(x + charDict[charid].bitmap.Width * scale, y);
OpenTK.Graphics.OpenGL.GL.TexCoord2(1, 1);
OpenTK.Graphics.OpenGL.GL.Vertex2(x + charDict[charid].bitmap.Width * scale, y + charDict[charid].bitmap.Height * scale);
OpenTK.Graphics.OpenGL.GL.TexCoord2(0, 1);
OpenTK.Graphics.OpenGL.GL.Vertex2(x + 0, y + charDict[charid].bitmap.Height * scale);
OpenTK.Graphics.OpenGL.GL.End();
OpenTK.Graphics.OpenGL.GL.PopMatrix();
Note, if you want to "reset" the current matrix, then this can be done by
glLoadIdentity
.
If you want to change the rotation point, then you have to translate to the rotation point, then rotate and finally translated back from the rotation point.
The translation can be done by glTranslate
. Possibly TranslateTransform
can be used in your case, but since I can't "see" what it is doing, I can't be sure.
OpenTK.Graphics.OpenGL.GL.PushMatrix();
OpenTK.Graphics.OpenGL.GL.Translate( rotate_center_x, rotate_center_y, 0.0);
OpenTK.Graphics.OpenGL.GL.Rotated( angle_degree, 0.0, 0.0, 1.0);
OpenTK.Graphics.OpenGL.GL.Translate( -rotate_center_x, -rotate_center_y, 0.0);
.....
OpenTK.Graphics.OpenGL.GL.PopMatrix();