pyOgre html to texture - solved - example class provided.

bharling

10-10-2006 11:06:44

Hi all,

Ok, this is going to sound a bit weird but here goes. I'm looking to produce a 3D GUI, using Ogre as the rendering system, and wxWidgets to create the gui elements. Thing is, I want to actually put wxPython within ogre (as opposed to putting an ogre window within a wxPython application). Basically, I want to do cool things like having a HTML browser mapped onto a plane, and have it interactive (simple eh? :))

I've already done a bit of work on this, and have written something which will take a screengrab of my html browser widget, and make it available as a texture image to ogre, but I can't get my head around how to structure it from there onwards. I'm using wx.MemoryDC to take a grab of the html window, but of course the widget would need to be on-screen already for the DC to know what to grab. I'd rather have wx rendering completely in the background, and only displaying anything when the image data actually reaches the ogre app.

anyone got any ideas or pointers on how I might do this?
(Possibly I might be posting this in the wrong place :))

viblo2

10-10-2006 11:49:57

You might get some inspiration from this thread: http://www.ogre3d.org/phpBB2/viewtopic. ... sc&start=0

bharling

10-10-2006 11:56:20

Thanks, actually OgreSWF was partly what inspired me to do this in the first place, also Java's rather nifty LG3D project at https://lg3d.dev.java.net/.

I think I may have the beginning of a solution, looks like you can force wxPython to draw to an off-screen buffer, before drawing to the screen. I guess the technique is to intercept the function before it draws to the screen, and tell it to draw to the texture instead (that much seems easy).

My next problem would be passing events back to the widget from Ogre, which I imagine will be hours of fun ...

Bekas

10-10-2006 12:21:40

An interesting link about having a html browser as texture: http://ubrowser.com/

bharling

10-10-2006 12:39:06

Thanks for that, I'd never seen UBrowser before. Thats very like what I'm trying to do :)

bharling

10-10-2006 16:42:55

Unfortunately, I have hit a brick wall with this. It seems you cannot draw to a buffer in wxWidgets without drawing something to the screen first. So I'm pretty much back to square one. Can anyone think of a creative solution to my troubles? :)

OvermindDL1

10-10-2006 21:22:23

wxWidgets is built so that it extends off a base interface (usually native widgets for the system). I would think you would need to make a new base to allow it to properly paint natively within Ogre...

bharling

11-10-2006 08:56:37

Aha, yes that was what I was afraid may be the case, and it looks like that is what I'll have to do. According to Robin Dunn of wxPython fame, it can only be done with a few widgets, and even then very intermittently. Ah well.

Therefore I have been looking for a package to convert HTML to images using python. So far I've only found commercial software, anyone know of an OS solution providing this feature?

thanks,

willism

11-10-2006 13:25:34

The Gecko engine, used by browsers such as mozilla, epiphany, and flock, is open-source. In fact, at a job where I used to work, we were considering using it to render scaled-down web page previews in a stylesheet editor. However, I'm not sure what you can find in the way of Python bindings for Gecko, short of doing it yourself. :?

bharling

11-10-2006 16:26:54

Thanks for all the suggestions. I'm now thinking about writing a paired down html -> cegui loader of some sort. Does anyone have an example of mapping cegui to ogre textures? I'm sure I've seen a mention of it being done somewhere

bharling

16-10-2006 00:18:35

HAHA!

Scratch the cegui html renderer, cos its only gone and started working from wxWidgets - check out this :)



of course, links do not work, and its having to write a bitmap to the hard-disc each time, because I cant seem to get Image.loadRawData() to work at all. However, it is loading, rendering and creating ogre textures from html pages.

a code snippet to follow ..

bharling

16-10-2006 13:15:09

heres a self contained class, which loads a url and returns an ogre material pointer containing the web-page as a texture.

# pyOgre / wxPython HTML renderer class.
# constructor: htmMaker = htmRenderer(resolution)
# usage: htmMaker.RenderHTM(URI, workingPath, outputPath) -> Ogre.MaterialPointer()

# Example:
# htmRender = htmRenderer(1024)
# htmRender.RenderHTM("http://www.microsoft.com", "", "cache/")
#
# Would return an ogre material containing a bitmap of www.microsoft.com (using wxwidgets default html display).
# The output folder must be in your ogre resources.cfg. Also, textures must follow the power-of-two rule.

import pyogre12.ogre as ogre
import wx
import wx.html
import urllib as url


class htmRenderer:
def __init__(self, resolution):
self.memDC = wx.MemoryDC()
self.memDC.Clear()
self.memDC.CanGetTextExtent = True
self.bmp = wx.EmptyBitmap(resolution, resolution, -1)
self.memDC.SelectObject(self.bmp)
self.renderhtm = wx.html.HtmlDCRenderer()
self.renderhtm.SetDC(self.memDC, 1.0)
self.renderhtm.SetSize(resolution,resolution)
self.htmTextureCount = 0
self.resolution = resolution

def RenderHTM(self, URI, workingPath, outputPath):
pen = wx.Pen( wx.Colour(160, 0, 50), 1, wx.SOLID)
self.memDC.SetPen(pen)
brush = wx.Brush( wx.Colour(255, 255, 255), wx.SOLID)
self.memDC.SetBrush(brush)
self.memDC.DrawRectangle( 0,0, self.resolution, self.resolution )
u = url.urlopen(URI)
u = u.read()
self.renderhtm.SetHtmlText(u, "", True)
self.renderhtm.Render(0,0)
self.img = self.bmp.ConvertToImage()
self.img.SaveFile(outputPath + "Test.bmp", 1)
group = 'General'
im = ogre.Image()
im.load("Test.bmp", group )
self.htmTextureCount += 1
name = "htmlWidg" + str(self.htmTextureCount)
tex = ogre.TextureManager.getSingleton().loadImage(name, group, im)
mat = ogre.MaterialPointer( ogre.MaterialManager.getSingleton().create(name + "_mat", 'General'))
t = mat.getTechnique(0).getPass(0).createTextureUnitState(name)
return mat

willism

16-10-2006 14:24:39

Nice. :D

Now that you've figured it out, how are you going to use it? Is this a case of "I want to have a virtual computer with a web browser in my game", or are you thinking of using it for menus, in-game documentation, etc.?

bharling

16-10-2006 16:28:24

Well, its mainly for a GUI project, thats not really related to a game. It looks like getting links to work would be an utter nightmare, so this is mainly designed so that our designers can easily add formatted text and images to the 3D interface, using existing technology that they are familiar with already. I think navigation will be handled by the interface wrapper (written in ogre).

The code above could be improved a lot if I could get image.loadRawData to work, but having looked on this forum, it looks like this feature is broken in Istari's pyogre build. Has anyone got this to work in Istari's builds, or can give me a build that would work with 'loadRawData' :) ?

A wxImage can spit out a raw byte stream, which should theoretically load straight into an ogre dataStreamPtr, thus eliminating the need to save a texture to disc each time, which is eating up some time during the function.

The HTML rendering is only using wxWidgets built in html window class, which cant deal with anything complicated, so most web-sites don't render too well (but at least they render!), however, please feel free to use the class in your own project if you think it would be useful.

Srekel

18-10-2006 15:13:47

Cool! :) This could very well come in handy some day. Let us know if you find a better solution or just update it somehow.