在 opengl/opentk 中沿 z 轴绘制和旋转文本
Draw and rotate the text along z axis in opengl/opentk
我需要在 opengl/opentk 中绘制 string/text,然后从文本本身的中心沿着 z 轴旋转它。
这是我目前尝试过的方法:
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;
}
}
我可以用这个写文字但不能旋转。而且对于某些字符来说,它占用了太多 space 导致文本之间存在差距。
I am able to write text with this but unable to rotate
您必须将旋转矩阵应用于模型视图矩阵。
选择模型视图矩阵堆栈glMatrixMode(GL_MODELVIEW)
。
将当前矩阵压入矩阵栈glPushMatrix
.
将当前矩阵乘以绕z轴的旋转矩阵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();
注意,如果你想"reset"当前矩阵,那么这可以通过
glLoadIdentity
.
如果你想改变旋转点,那么你必须平移到旋转点,然后旋转,最后从旋转点平移回来。
翻译可以通过glTranslate
来完成。可能 TranslateTransform
可以用于你的情况,但由于我不能 "see" 它在做什么,我不能确定。
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();
我需要在 opengl/opentk 中绘制 string/text,然后从文本本身的中心沿着 z 轴旋转它。
这是我目前尝试过的方法:
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;
}
}
我可以用这个写文字但不能旋转。而且对于某些字符来说,它占用了太多 space 导致文本之间存在差距。
I am able to write text with this but unable to rotate
您必须将旋转矩阵应用于模型视图矩阵。
选择模型视图矩阵堆栈glMatrixMode(GL_MODELVIEW)
。
将当前矩阵压入矩阵栈glPushMatrix
.
将当前矩阵乘以绕z轴的旋转矩阵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();
注意,如果你想"reset"当前矩阵,那么这可以通过
glLoadIdentity
.
如果你想改变旋转点,那么你必须平移到旋转点,然后旋转,最后从旋转点平移回来。
翻译可以通过glTranslate
来完成。可能 TranslateTransform
可以用于你的情况,但由于我不能 "see" 它在做什么,我不能确定。
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();