Text and OpenGL

I want to display text in front of an OpenGL canvas. What is currently the best way to do this? The existing platform-dependent C++ code in VPython (vpython.org) creates a texture from the text and displays this texture in front of the 3D scene, appropriately positioned to label a 3D object. Might it be possible to place some kind of drawing context in front of the 3D canvas and display the 2D text there? In this application the text always faces forward. I have found some information by searching, but some of the things I found are pretty old, and some requiring an additional dependency, the Python OpenGL module.

I’ll mention that I’ve managed to run all the standard VPython demos with a wxPython version, eliminating almost all the platform-dependent C++ code and opening the possibilities of writing VPython programs that have pull-down menus, buttons, etc. However, there remains the platform-dependent text-to-texture code, which is a pain. I’d like very much to get rid of that platform-dependent code before releasing a wxPython version of VPython.

I want to display text in front of an OpenGL canvas. What is currently the
best way to do this? The existing platform-dependent C++ code in VPython
(vpython.org) creates a texture from the text and displays this texture in
front of the 3D scene, appropriately positioned to label a 3D object. Might
it be possible to place some kind of drawing context in front of the 3D
canvas and display the 2D text there?

not totally sure, but I think it may be fragile to tryt o draw on top
of an OpenGL rendered window. You could experiment with wx.Overlay and
see if it works. Even if it does, you'd have to keep the transforms in
sync, so you'd know where to render.

I have found some information by searching, but some of the
things I found are pretty old, and some requiring an additional dependency,
the Python OpenGL module.

VPython doesn't already use that? interesting.

However, there remains the platform-dependent
text-to-texture code, which is a pain.

could you port that to wx? It's not hard to render it an offscreen
bitmap with wx, and then get the raw data from that, which you should
be able to create a texture from.

That last step is pretty easy with PyOpenGL -- not sure what you're
working with, but I suspect there is a pointer-to-RGBA-buffer used in
there somewhere, which you should be able to get from a python buffer
object.

HTH,
  -Chris

···

On Mon, Nov 19, 2012 at 9:53 AM, Bruce Sherwood <bruce.sherwood@gmail.com> wrote:

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

OpenGL and text rendering is a big pain, generally-speaking. The best
solution I've found is to use FTGL, which supports texture fonts (so
basically you set up your OpenGL transformation, tell FTGL to render
some text, and it'll show up where and how you want it). The PyFTGL
libraries can be aggravating to build, though, if there aren't
binaries already available for your choice of platform+Python.

-Chris

···

On Mon, Nov 19, 2012 at 9:53 AM, Bruce Sherwood <bruce.sherwood@gmail.com> wrote:

I want to display text in front of an OpenGL canvas. What is currently the
best way to do this?

Chris, almost all of VPython is written in C++, which is why the Python OpenGL module has until now played no role. My recent work has replaced all of the platform-dependent C++ code with wxPython, except for the text-to-texture piece, which includes both getting the font information and making the texture. It is already the case that VPython performs the necessary transformations to keep the 2D text placed properly with respect to the 3D objects, when you rotate or zoom the camera.

You might be right that the most straight-forward approach is to translate the existing C++ code to wxPython. But I’ll take a look at wx.Overlay. In the case of GlowScript (glowscript.org), I do use a 2D overlay in front of the WebGL 3D canvas for the labels.

Chris, almost all of VPython is written in C++, which is why the Python
OpenGL module has until now played no role. My recent work has replaced all
of the platform-dependent C++ code with wxPython, except for the
text-to-texture piece, which includes both getting the font information and
making the texture.

That should be pretty easy with wx at least.

It is already the case that VPython performs the
necessary transformations to keep the 2D text placed properly with respect
to the 3D objects, when you rotate or zoom the camera.

are they exposed so that you can make straight wx calls and get the
required pixel positions? If so, then doing an overlay should't be too
hard, either, if it works.

I suppose you could simply try drawing with a wx.DC after each GL
render, and see if it works, you may not even need the wx.Overlay --
it is designed for short-term overlays, which may not fit your
use-case well.

You might be right that the most straight-forward approach is to translate
the existing C++ code to wxPython.

Probably more like re-write than translate, but still work. Yo may not
have a use-case for it, but if you do do this, then you essentially
have a system in place to draw anything outside of GL, and put it on
your scene -- that may be useful for other things.

Also, if you want to go beyond simple labels, you can do stuff like
use wxHTML to render html to a bitmap, and turn that into a texture --
the possibilities are endless....

Let us know how it works out,

-Chris

the case of GlowScript (glowscript.org), I do use a 2D overlay in front of
the WebGL 3D canvas for the labels.

can you use exactly the same approach?

···

On Mon, Nov 19, 2012 at 1:39 PM, Bruce Sherwood <bruce.sherwood@gmail.com> wrote:

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

My preference would indeed be to do what I’ve done in GlowScript – display text in a 2D overlay in front of a 3D canvas, as this seems by far the simplest scheme, since it doesn’t involve creating a texture. But I’m bewildered by what looks like so many different ways to try to do this in the wxPython context that I don’t know how to start.

···

the case of GlowScript (glowscript.org), I do use a 2D overlay in front of

the WebGL 3D canvas for the labels.

can you use exactly the same approach?

My preference would indeed be to do what I've done in GlowScript -- display
text in a 2D overlay in front of a 3D canvas, as this seems by far the
simplest scheme, since it doesn't involve creating a texture. But I'm
bewildered by what looks like so many different ways to try to do this in
the wxPython context that I don't know how to start.

I think the wx.Overlay is a red herring in this case -- sorry about that.

I haven't really refreshed my memory of OpenGL and wx, but...

Somewhere, you should be asking OpenGL to draw -- maybe a
SwapBuffers() call? This should happen in a PaintEvent, but also, a
presume, at other time,s like maybe a a result of a timer going off,
etc.

After GL draws, you want to try to draw on top of it:

maybe the most robust but deprecated way:

Use a wx.ClientDC:

def AfterGL_Render(self):
    dc = wx.ClientDC(self)
    Font = wx.FontFromPixelSize(14, wx.SWISS, wx.NORMAL, wx.NORMAL)
    dc.SetFont(Font)
    dc.DrawText('This is some sample text', x, y)

In modern practice, it's considered a "bad idea" to use a ClientDC --
it can interupt the systems draw order, and slow things down. What is
better is to do all drawing in a Paint Event, using a wx.PaintDC.

In that case, you put your call to tell GL to draw in the PaintDC,
then call a funcition like the above, but passing the PaintDC for it
to draw to.

If you want a refresh outside or a system PaintEvent, you call:

self.Refresh()
self.UPdate()

which triggers a Paint event.

But I'd try the ClientDC method first, as it should be easy to plug
into your code.

Good luck,

-Chris

···

On Mon, Nov 19, 2012 at 3:33 PM, Bruce Sherwood <bruce.sherwood@gmail.com> wrote:

On Mon, Nov 19, 2012 at 3:37 PM, Chris Barker - NOAA Federal > <chris.barker@noaa.gov> wrote:

> the case of GlowScript (glowscript.org), I do use a 2D overlay in front
> of
> the WebGL 3D canvas for the labels.

can you use exactly the same approach?

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Bruce,

I just did a little test of my sugestion, using the GL demo from the
wxPython Wiki, and it doesn't work for me -- if I turn of the GL
SwapBuffers() call, the text renders, but if I turn i back on, you
can't see it -- I suspect that GL is taking over the rendering,a nd
you can't render on top of it. But someone else may know how to force
that.

Sorry not to be more helpful, but you may need to go the texture route

(code enclosed)

-Chris

DrawOverGL.py (3.58 KB)

···

On Mon, Nov 19, 2012 at 4:13 PM, Chris Barker - NOAA Federal <chris.barker@noaa.gov> wrote:

On Mon, Nov 19, 2012 at 3:33 PM, Bruce Sherwood > <bruce.sherwood@gmail.com> wrote:

My preference would indeed be to do what I've done in GlowScript -- display
text in a 2D overlay in front of a 3D canvas, as this seems by far the
simplest scheme, since it doesn't involve creating a texture. But I'm
bewildered by what looks like so many different ways to try to do this in
the wxPython context that I don't know how to start.

I think the wx.Overlay is a red herring in this case -- sorry about that.

I haven't really refreshed my memory of OpenGL and wx, but...

Somewhere, you should be asking OpenGL to draw -- maybe a
SwapBuffers() call? This should happen in a PaintEvent, but also, a
presume, at other time,s like maybe a a result of a timer going off,
etc.

After GL draws, you want to try to draw on top of it:

maybe the most robust but deprecated way:

Use a wx.ClientDC:

def AfterGL_Render(self):
    dc = wx.ClientDC(self)
    Font = wx.FontFromPixelSize(14, wx.SWISS, wx.NORMAL, wx.NORMAL)
    dc.SetFont(Font)
    dc.DrawText('This is some sample text', x, y)

In modern practice, it's considered a "bad idea" to use a ClientDC --
it can interupt the systems draw order, and slow things down. What is
better is to do all drawing in a Paint Event, using a wx.PaintDC.

In that case, you put your call to tell GL to draw in the PaintDC,
then call a funcition like the above, but passing the PaintDC for it
to draw to.

If you want a refresh outside or a system PaintEvent, you call:

self.Refresh()
self.UPdate()

which triggers a Paint event.

But I'd try the ClientDC method first, as it should be easy to plug
into your code.

Good luck,

-Chris

On Mon, Nov 19, 2012 at 3:37 PM, Chris Barker - NOAA Federal >> <chris.barker@noaa.gov> wrote:

> the case of GlowScript (glowscript.org), I do use a 2D overlay in front
> of
> the WebGL 3D canvas for the labels.

can you use exactly the same approach?

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

One other note:

I recall someone describing OpenGL on X-windows to me once, as the
X-server "blows a hole" in the screen buffer, and hands it over to
OpenGL to render.

That seems to indicate, at least on old X-windows systems, that you
can either have OpenGL rendering a given Window, or the usual system
rendering, but not both.

-CHB

···

On Mon, Nov 19, 2012 at 4:24 PM, Chris Barker - NOAA Federal <chris.barker@noaa.gov> wrote:

Bruce,

I just did a little test of my sugestion, using the GL demo from the
wxPython Wiki, and it doesn't work for me -- if I turn of the GL
SwapBuffers() call, the text renders, but if I turn i back on, you
can't see it -- I suspect that GL is taking over the rendering,a nd
you can't render on top of it. But someone else may know how to force
that.

Sorry not to be more helpful, but you may need to go the texture route

(code enclosed)

-Chris

On Mon, Nov 19, 2012 at 4:13 PM, Chris Barker - NOAA Federal > <chris.barker@noaa.gov> wrote:

On Mon, Nov 19, 2012 at 3:33 PM, Bruce Sherwood >> <bruce.sherwood@gmail.com> wrote:

My preference would indeed be to do what I've done in GlowScript -- display
text in a 2D overlay in front of a 3D canvas, as this seems by far the
simplest scheme, since it doesn't involve creating a texture. But I'm
bewildered by what looks like so many different ways to try to do this in
the wxPython context that I don't know how to start.

I think the wx.Overlay is a red herring in this case -- sorry about that.

I haven't really refreshed my memory of OpenGL and wx, but...

Somewhere, you should be asking OpenGL to draw -- maybe a
SwapBuffers() call? This should happen in a PaintEvent, but also, a
presume, at other time,s like maybe a a result of a timer going off,
etc.

After GL draws, you want to try to draw on top of it:

maybe the most robust but deprecated way:

Use a wx.ClientDC:

def AfterGL_Render(self):
    dc = wx.ClientDC(self)
    Font = wx.FontFromPixelSize(14, wx.SWISS, wx.NORMAL, wx.NORMAL)
    dc.SetFont(Font)
    dc.DrawText('This is some sample text', x, y)

In modern practice, it's considered a "bad idea" to use a ClientDC --
it can interupt the systems draw order, and slow things down. What is
better is to do all drawing in a Paint Event, using a wx.PaintDC.

In that case, you put your call to tell GL to draw in the PaintDC,
then call a funcition like the above, but passing the PaintDC for it
to draw to.

If you want a refresh outside or a system PaintEvent, you call:

self.Refresh()
self.UPdate()

which triggers a Paint event.

But I'd try the ClientDC method first, as it should be easy to plug
into your code.

Good luck,

-Chris

On Mon, Nov 19, 2012 at 3:37 PM, Chris Barker - NOAA Federal >>> <chris.barker@noaa.gov> wrote:

> the case of GlowScript (glowscript.org), I do use a 2D overlay in front
> of
> the WebGL 3D canvas for the labels.

can you use exactly the same approach?

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

this is definitely true. back in the day (6 years ago) when there
wasn't really much memory bandwidth to get the hardware rendered
pixels back to the computer, the idea behind an opengl buffer was
basically, your computer sees it as a black hole, and the graphics
card fills it in at the last minute before sending it to the monitor.
This was the only way to offload all that rendering without having to
do a bunch of copies back. These days those limitations are less real
but it still works the same way for historical reasons.

That said, OpenGL itself is quite cross platform - are you sure maybe
the glut toolkit doesn't have some cross platform code for rendering
basic kinds of text?

-Mike

···

On Mon, Nov 19, 2012 at 7:29 PM, Chris Barker - NOAA Federal <chris.barker@noaa.gov> wrote:

One other note:

I recall someone describing OpenGL on X-windows to me once, as the
X-server "blows a hole" in the screen buffer, and hands it over to
OpenGL to render.

That seems to indicate, at least on old X-windows systems, that you
can either have OpenGL rendering a given Window, or the usual system
rendering, but not both.

-CHB

On Mon, Nov 19, 2012 at 4:24 PM, Chris Barker - NOAA Federal > <chris.barker@noaa.gov> wrote:

Bruce,

I just did a little test of my sugestion, using the GL demo from the
wxPython Wiki, and it doesn't work for me -- if I turn of the GL
SwapBuffers() call, the text renders, but if I turn i back on, you
can't see it -- I suspect that GL is taking over the rendering,a nd
you can't render on top of it. But someone else may know how to force
that.

Sorry not to be more helpful, but you may need to go the texture route

(code enclosed)

-Chris

On Mon, Nov 19, 2012 at 4:13 PM, Chris Barker - NOAA Federal >> <chris.barker@noaa.gov> wrote:

On Mon, Nov 19, 2012 at 3:33 PM, Bruce Sherwood >>> <bruce.sherwood@gmail.com> wrote:

My preference would indeed be to do what I've done in GlowScript -- display
text in a 2D overlay in front of a 3D canvas, as this seems by far the
simplest scheme, since it doesn't involve creating a texture. But I'm
bewildered by what looks like so many different ways to try to do this in
the wxPython context that I don't know how to start.

I think the wx.Overlay is a red herring in this case -- sorry about that.

I haven't really refreshed my memory of OpenGL and wx, but...

Somewhere, you should be asking OpenGL to draw -- maybe a
SwapBuffers() call? This should happen in a PaintEvent, but also, a
presume, at other time,s like maybe a a result of a timer going off,
etc.

After GL draws, you want to try to draw on top of it:

maybe the most robust but deprecated way:

Use a wx.ClientDC:

def AfterGL_Render(self):
    dc = wx.ClientDC(self)
    Font = wx.FontFromPixelSize(14, wx.SWISS, wx.NORMAL, wx.NORMAL)
    dc.SetFont(Font)
    dc.DrawText('This is some sample text', x, y)

In modern practice, it's considered a "bad idea" to use a ClientDC --
it can interupt the systems draw order, and slow things down. What is
better is to do all drawing in a Paint Event, using a wx.PaintDC.

In that case, you put your call to tell GL to draw in the PaintDC,
then call a funcition like the above, but passing the PaintDC for it
to draw to.

If you want a refresh outside or a system PaintEvent, you call:

self.Refresh()
self.UPdate()

which triggers a Paint event.

But I'd try the ClientDC method first, as it should be easy to plug
into your code.

Good luck,

-Chris

On Mon, Nov 19, 2012 at 3:37 PM, Chris Barker - NOAA Federal >>>> <chris.barker@noaa.gov> wrote:

> the case of GlowScript (glowscript.org), I do use a 2D overlay in front
> of
> the WebGL 3D canvas for the labels.

can you use exactly the same approach?

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

glut comes with both bitmap fonts & vector fonts:

for vector fonts:

Fonts:
GLUT_STROKE_ROMAN
GLUT_STROKE_MONO_ROMAN
These are both void*
Functions:
void glutStrokeCharacter(void* font, char* c)
int glutStrokeWidth(void* font, char* c)

and you can look up the appropriate functions, etc. for the bitmap
fonts as well. These functions should work anywhere glut is
implemented (mac/win/linux/ios/android/etc...)

-Mike

···

On Mon, Nov 19, 2012 at 7:33 PM, Michael Haimes <michael.haimes@gmail.com> wrote:

this is definitely true. back in the day (6 years ago) when there
wasn't really much memory bandwidth to get the hardware rendered
pixels back to the computer, the idea behind an opengl buffer was
basically, your computer sees it as a black hole, and the graphics
card fills it in at the last minute before sending it to the monitor.
This was the only way to offload all that rendering without having to
do a bunch of copies back. These days those limitations are less real
but it still works the same way for historical reasons.

That said, OpenGL itself is quite cross platform - are you sure maybe
the glut toolkit doesn't have some cross platform code for rendering
basic kinds of text?

-Mike

On Mon, Nov 19, 2012 at 7:29 PM, Chris Barker - NOAA Federal > <chris.barker@noaa.gov> wrote:

One other note:

I recall someone describing OpenGL on X-windows to me once, as the
X-server "blows a hole" in the screen buffer, and hands it over to
OpenGL to render.

That seems to indicate, at least on old X-windows systems, that you
can either have OpenGL rendering a given Window, or the usual system
rendering, but not both.

-CHB

On Mon, Nov 19, 2012 at 4:24 PM, Chris Barker - NOAA Federal >> <chris.barker@noaa.gov> wrote:

Bruce,

I just did a little test of my sugestion, using the GL demo from the
wxPython Wiki, and it doesn't work for me -- if I turn of the GL
SwapBuffers() call, the text renders, but if I turn i back on, you
can't see it -- I suspect that GL is taking over the rendering,a nd
you can't render on top of it. But someone else may know how to force
that.

Sorry not to be more helpful, but you may need to go the texture route

(code enclosed)

-Chris

On Mon, Nov 19, 2012 at 4:13 PM, Chris Barker - NOAA Federal >>> <chris.barker@noaa.gov> wrote:

On Mon, Nov 19, 2012 at 3:33 PM, Bruce Sherwood >>>> <bruce.sherwood@gmail.com> wrote:

My preference would indeed be to do what I've done in GlowScript -- display
text in a 2D overlay in front of a 3D canvas, as this seems by far the
simplest scheme, since it doesn't involve creating a texture. But I'm
bewildered by what looks like so many different ways to try to do this in
the wxPython context that I don't know how to start.

I think the wx.Overlay is a red herring in this case -- sorry about that.

I haven't really refreshed my memory of OpenGL and wx, but...

Somewhere, you should be asking OpenGL to draw -- maybe a
SwapBuffers() call? This should happen in a PaintEvent, but also, a
presume, at other time,s like maybe a a result of a timer going off,
etc.

After GL draws, you want to try to draw on top of it:

maybe the most robust but deprecated way:

Use a wx.ClientDC:

def AfterGL_Render(self):
    dc = wx.ClientDC(self)
    Font = wx.FontFromPixelSize(14, wx.SWISS, wx.NORMAL, wx.NORMAL)
    dc.SetFont(Font)
    dc.DrawText('This is some sample text', x, y)

In modern practice, it's considered a "bad idea" to use a ClientDC --
it can interupt the systems draw order, and slow things down. What is
better is to do all drawing in a Paint Event, using a wx.PaintDC.

In that case, you put your call to tell GL to draw in the PaintDC,
then call a funcition like the above, but passing the PaintDC for it
to draw to.

If you want a refresh outside or a system PaintEvent, you call:

self.Refresh()
self.UPdate()

which triggers a Paint event.

But I'd try the ClientDC method first, as it should be easy to plug
into your code.

Good luck,

-Chris

On Mon, Nov 19, 2012 at 3:37 PM, Chris Barker - NOAA Federal >>>>> <chris.barker@noaa.gov> wrote:

> the case of GlowScript (glowscript.org), I do use a 2D overlay in front
> of
> the WebGL 3D canvas for the labels.

can you use exactly the same approach?

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

I belatedly realize that you may be suggesting an approach that would be quite fruitful. There is already in VPython a mechanism for taking a numeric array of data and making it into a texture. So my problem can be restated as “how do I get an array of pixels corresponding to a character string in some font?” You seem to be saying that there’s some way in wxPython to render 2D text and graphics to a bitmap, which I could then use to generate an OpenGL texture. Can you point me to that part of wxPython that would let me do that? Thanks.

···

On Monday, November 19, 2012 3:38:07 PM UTC-7, Chris Barker - NOAA Federal wrote:

Probably more like re-write than translate, but still work. Yo may not

have a use-case for it, but if you do do this, then you essentially

have a system in place to draw anything outside of GL, and put it on

your scene – that may be useful for other things.

Also, if you want to go beyond simple labels, you can do stuff like

use wxHTML to render html to a bitmap, and turn that into a texture –

the possibilities are endless…

Thanks! I’ll try that.

···

On Fri, Nov 23, 2012 at 1:05 AM, Steve Barnes gadgetsteve@live.co.uk wrote:

Bruce,

I think what you need to explore is the wx.DC classes specifically wx.MemoryDC if I haven’t gotten hold of the wrong end of the stick what you are looking for is something along the lines of:

Create wx.BitMap → Assign it to a wx.MemroryDC → Set Font, DrawText, etc., onto DC → Deselect Bitmap from the DC to allow it to be accessed elsewhere → Use the bitmap…

Gadget/Steve

Okay, I tried this without success. The following code prints all zeros both before and after the DrawRectangle. What am I doing wrong? Note that I fill the numpy array “arr” with 1’s, then create an empty bitmap which when read shows all zeros, showing that the CopyToBuffer operation is working, but why does DrawRectangle not affect the bitmap?

import numpy

arr = numpy.ones((4,4,4), numpy.uint8)
bitmap = wx.EmptyBitmap(4, 4, 32)

bitmap.CopyToBuffer(arr, format=wx.BitmapBufferFormatRGBA)

print(arr)

print(‘------------------------------------’)

dc = wx.MemoryDC()

dc.SelectObject(bitmap)

dc.SetBrush(wx.Brush(‘#ff0000’))

dc.DrawRectangle(0, 0, 3, 3)

dc.SelectObject(wx.NullBitmap)

bitmap.CopyToBuffer(arr, format=wx.BitmapBufferFormatRGBA)

print(arr)

···

On Friday, November 23, 2012 1:05:23 AM UTC-7, Gadget Steve wrote:


Date: Thu, 22 Nov 2012 07:30:53 -0800
From: bruce.s...@gmail.com
To: wxpytho...@googlegroups.com
Subject: Re: [wxPython-users] Text and OpenGL

I belatedly realize that you may be suggesting an approach that would
be quite fruitful. There is already in VPython a mechanism for taking a
numeric array of data and making it into a texture. So my problem can
be restated as “how do I get an array of pixels corresponding to a
character string in some font?” You seem to be saying that there’s some
way in wxPython to render 2D text and graphics to a bitmap, which I
could then use to generate an OpenGL texture. Can you point me to that
part of wxPython that would let me do that? Thanks.

I tried a simpler test:

import numpy

arr = numpy.ones((4,4,4), numpy.uint8)

arr[1,2,2] = 37

arr[1,2,3] = 55

print(arr)

print(’------------------------------------’)

bitmap = wx.BitmapFromBufferRGBA(4, 4, arr)

bitmap.CopyToBuffer(arr, format=wx.BitmapBufferFormatRGBA)

print(arr)

What the second print statement shows is not what was in the “arr” array but rather that all slots are zero except that all entries arr[i,j,3] are 1. So even before attempting to write into the memory map, I apparently don’t know what I’m doing.

This is on Windows, using wxPython 2.9 with 64-bit Python 2.7.

Neither do I, that is odd -- you'd think you could round trip this,
but I get something similar to you, and tried a completely different
test, and got the same thing -- the round trip does not seem to work.

You might try wx.Image instead -- wx.Bitmap is a wrapper around the
native bitmap representation, so something may be odd with trying to
share the buffer.

(I'm testing on OS-X, so not just a Windows thing)
-Chris

···

On Mon, Nov 26, 2012 at 8:11 PM, Bruce Sherwood <bruce.sherwood@gmail.com> wrote:

I tried a simpler test:

import numpy
arr = numpy.ones((4,4,4), numpy.uint8)
arr[1,2,2] = 37
arr[1,2,3] = 55
print(arr)
print('------------------------------------')
bitmap = wx.BitmapFromBufferRGBA(4, 4, arr)
bitmap.CopyToBuffer(arr, format=wx.BitmapBufferFormatRGBA)
print(arr)

What the second print statement shows is not what was in the "arr" array but
rather that all slots are zero except that all entries arr[i,j,3] are 1. So
even before attempting to write into the memory map, I apparently don't know
what I'm doing.

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Thanks. I'll try wx.Image.

It's good news to know that it's not just me. It's bad news to know that
it's not just me.

You may be able to do it with less data copying (and add an alha
channel, but this is a start:

#!/usr/bin/env python

"""
A test of using wx, MemoryDC, wxImage, to draw text to a numpy array
as a buffer.
"""

import numpy as np
import wx

# create and app, so wx is initialized

a = wx.App(False)

#set up the wx objects:
w,h = 50, 14

bmp = wx.EmptyBitmap(w,h)
dc = wx.MemoryDC()
dc.SelectObject(bmp)

dc.SetBackground(wx.WHITE_BRUSH)
dc.Clear()
dc.DrawText("Text", 0, 0)

del dc

img = wx.ImageFromBitmap(bmp)

# to see what we're getting..
img.SaveFile("junk.png", wx.BITMAP_TYPE_PNG)

# create numpy array:
arr = np.fromstring(img.GetData(), dtype=np.uint8).reshape((h,w,3))
print (arr[:,:,0] < 255).astype(np.uint8)
print arr.shape

-Chris

···

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Many many thanks! That’s exactly what I need.

···

On Wed, Nov 28, 2012 at 8:45 AM, Chris Barker - NOAA Federal chris.barker@noaa.gov wrote:

You may be able to do it with less data copying (and add an alha

channel, but this is a start:

#!/usr/bin/env python

“”"

A test of using wx, MemoryDC, wxImage, to draw text to a numpy array

as a buffer.

“”"

import numpy as np

import wx

create and app, so wx is initialized

a = wx.App(False)

#set up the wx objects:

w,h = 50, 14

bmp = wx.EmptyBitmap(w,h)

dc = wx.MemoryDC()

dc.SelectObject(bmp)

dc.SetBackground(wx.WHITE_BRUSH)

dc.Clear()

dc.DrawText(“Text”, 0, 0)

del dc

img = wx.ImageFromBitmap(bmp)

to see what we’re getting…

img.SaveFile(“junk.png”, wx.BITMAP_TYPE_PNG)

create numpy array:

arr = np.fromstring(img.GetData(), dtype=np.uint8).reshape((h,w,3))

print (arr[:,:,0] < 255).astype(np.uint8)

print arr.shape

-Chris

Christopher Barker, Ph.D.

Oceanographer

Emergency Response Division

NOAA/NOS/OR&R (206) 526-6959 voice

7600 Sand Point Way NE (206) 526-6329 fax

Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en