simple image texture in game python

Hello everyone,

I’m trying to do something that should be very simple, but I must be
missing something somewhere.

The following python script successfully displays a plane with an attached
mono bitmap png image using a material in blender, when rendered with the
F12 key. My problem is that I need to do this in the game engine,
where materials can’t be used.
The material lines commented out with “##” are the only difference
I made to make the script run with no errors in the game engine.

With the material commented out, the plane appears but the image isn’t there.
The script runs on a non-pulsed “always” init sensor on an empty for testing.

I’ve tried many permutations, with different modes and UV info attached
to both face and vertexes, but with no success in seeing the image.

I’m using Blender 2.34 in FreeBSD, Python 2.3

What am I doing wrong ?

Python script follows:

=====

import Blender
from Blender import Texture, Image, NMesh, Material, Scene, Object
from math import *
import fcntl, sys, os

pi = 3.1415926
deg2rad = pi / 180.0
rad2deg = 180.0 / pi

def e2d(e):
return ( e * rad2deg )

def d2e(d):
return ( d * deg2rad )

def euler2deg( e3 ):
return( [ e2d( e3[0] ), e2d( e3[1] ), e2d( e3[2] )] )

def deg2euler( d3 ):
return( [ d2e( d3[0] ), d2e( d3[1] ), d2e( d3[2] )] )

def setPlane( nm, x0, y0, ww, hh ):
img = Image.Load("/home/S/PS/test00c.o.png")
bb = img.getSize()
print "image width: ", bb[0], " height: ", bb[1]
print "Images Now: ", Image.Get()

tx = Texture.New('Tex1')
tx.setType('Image')
tx.image = img

##mm = Material.Get()
##print "Materials: ", mm
##mat = Material.Get( "Material" )
##mat.setAlpha(0.0)
##mat.emit = 0.7 
##mat.setAdd(0.8)
##mat.setRGBCol( 1.0, 1.0, 1.0 )

##mat.setTexture( 0, tx, Texture.TexCo.ORCO, Texture.MapTo.ALPHA )

tt = Texture.Get()
print "Textures: ", tt

xx = x0 + ww
yy = y0 + hh
me = NMesh.GetRaw()
v = NMesh.Vert( xx, y0, 0.0 )
#v.uvco = ( 1.0, 0.0 )
me.verts.append(v)
v = NMesh.Vert( xx, yy, 0.0 )
#v.uvco = ( 1.0, 1.0 )
me.verts.append(v)
v = NMesh.Vert( x0, yy, 0.0 )
#v.uvco = ( 0.0, 1.0 )
me.verts.append(v)
v = NMesh.Vert( x0, y0, 0.0 )
#v.uvco = ( 0.0, 0.0 )
me.verts.append(v)
f = NMesh.Face()
f.v.append( me.verts[0 ] )
f.v.append( me.verts[1 ] )
f.v.append( me.verts[2 ] )
f.v.append( me.verts[3 ] )
me.faces.append( f )

NMesh.PutRaw( me, nm, 1 )

# use prior uvco or following faceUV
me.hasVertexUV(0)

f.uv = [(1.0,0.0),(1.0,1.0),(0.0,1.0),(0.0,0.0)]
me.hasFaceUV(1)
print "ME has face UV: ", me.hasFaceUV()

f.image = img
f.flag = NMesh.FaceModes.TEX + NMesh.FaceModes.LIGHT + NMesh.FaceModes.TWOSIDE
#f.transp = NMesh.FaceTranspModes.ALPHA
f.transp = NMesh.FaceTranspModes.SOLID

#me.mode = NMesh.Modes.TWOSIDED

##me.addMaterial( mat )

color = NMesh.Col( 255, 255, 255, 0 )
f.col.append( color )

oo = Object.Get( 'Mesh' )
oo.setName( nm )

    me.update()

print "ME has face UV: ", me.hasFaceUV()

Blender.Redraw()

setPlane( ‘plane1’, -5.5, -1.0, 11.0, 2.0 )
#setPlane( ‘plane2’, -1.0, -1.0, 2.0, 2.0 )

objects = Object.Get()
print "Objects: ", objects

camera = Object.Get(‘Camera’)
print "camera loc: ", camera.getLocation()
print "camera deltaloc: ", camera.getDeltaLocation()
print "camera euler: ", camera.getEuler()
print "camera euler: ", euler2deg( camera.getEuler() )
print "camera size: ", camera.getSize()

camera.setLocation(0.0, 0.0, 10.0)
camera.setEuler(deg2euler( [0.0, 0.0, 0.0] ))

lamp = Object.Get(‘Lamp’)
lamp.setLocation(0.0, 0.0, -5.0)

Blender.Redraw()

=====

The execution output is:

=====

Xlib: extension “XFree86-DRI” missing on display “:0.0”.
fcntl: Device not configured
image width: 704 height: 128
Images Now: [[Image “test00c.o.png”]]
Textures: [[Texture “Tex1”]]
ME has face UV: False
ME has face UV: True
Objects: [[Object “Camera”], [Object “Lamp”], [Object “Empty”], [Object “plane1”]]
camera loc: (0.0, 0.0, 10.0)
camera deltaloc: (0.0, 0.0, 0.0)
camera euler: [0.0000, 0.0000, 0.0000]

camera euler: [0.0, 0.0, 0.0]
camera size: (1.0, 1.0, 1.0)
GL_VERSION: 1.3 (1.3 Mesa 4.0.4)

I don’t think this is possible du to the game engine uses UV mapping. If so you would have to access the uv faces and attach a saved image to it. I’ll have to double check to see if I’m right.

I’ve tried the two forms of UV mapping, the vertex “uvco” and the face “uv” as you can see in the code.
Not sure what’s really happening internally, but this simple applying of an image to a plane should be supported somehow in Plyhon under the game engine.

LET ME SEE

If you are trying to load an external file and map it in realtime, this is not supported. If you just want to texture something beforehand, you don’t need python. Use the UV edit functions. I’m not totally sure what you are trying to do.

Some methods of the normal blender python modules areavailable from the game engine, but they aren’t fully supported, some of them only work if you restart the game, and none of them will work in an executable file. Game python is a different beast entirely,

Ok Saluk and I are right, this is not possible.

If you are trying to load an external file and map it in realtime, this is not supported

def setPlane( nm, x0, y0, ww, hh ): 
img = Image.Load("/home/S/PS/test00c.o.png") 
bb = img.getSize() 
print "image width: ", bb[0], " height: ", bb[1] 
print "Images Now: ", Image.Get() 

I’m not totally sure what you are trying to do

He is trying to redraw a plane with an image mapped to the face.

Blender.Redraw() 


setPlane( 'plane1', -5.5, -1.0, 11.0, 2.0 ) 
[quote][/quote]

Too bad. This is a show-stopper for me.
spent several months immersing in Blender to get to the point of knowing what to ask.
still seems a simple operation to support.
Well anyway, could anyone suggest the best place to look next ?
Crystal Space ? Irrlicht ?
I guess you may want me to post in “other software” to ask this question …

Ask alien-xmp/kester if he can implement this feature?

How do I best approach “alien-xmp/kester” with this request ?
Where can I contact him/her/them ?

I’d love to stick with Blender.

Present him with a small offering of nuts and berries. Just leave it outside your back step at night. Try to lure him out of the woods, where you can capture him…

Check out the webcam script posted here recently - you should be able to modify that.

Also, see about getting DRI working. You don’t want to be doing 3D (especially realtime 3d) without 3D acceleration.

giggles Does that really work?! :wink:

Added the webcam code (see ### at end) - plane still appears,
but getOwner() call on gamelogic controller returns nothing

not sure what’s wrong – verified the call from the docs

Didn’t mean to be so dense … sorry

Python script follows: (also sorry for the repetition)

=====

import Blender
from Blender import Texture, Image, NMesh, Material, Scene, Object
from math import *
import fcntl, sys, os
import GameLogic

pi = 3.1415926
deg2rad = pi / 180.0
rad2deg = 180.0 / pi

def e2d(e):
return ( e * rad2deg )

def d2e(d):
return ( d * deg2rad )

def euler2deg( e3 ):
return( [ e2d( e3[0] ), e2d( e3[1] ), e2d( e3[2] )] )

def deg2euler( d3 ):
return( [ d2e( d3[0] ), d2e( d3[1] ), d2e( d3[2] )] )

def setPlane( nm, x0, y0, ww, hh ):
img = Image.Load("/home/S/PS/test00c.o.png")
bb = img.getSize()
print "image width: ", bb[0], " height: ", bb[1]
print "Images Now: ", Image.Get()

tx = Texture.New('Tex1')
tx.setType('Image')
tx.image = img

##mm = Material.Get()
##print "Materials: ", mm
##mat = Material.Get( "Material" )
##mat.setAlpha(0.0)
##mat.emit = 0.7 
##mat.setAdd(0.8)
##mat.setRGBCol( 1.0, 1.0, 1.0 )

##mat.setTexture( 0, tx, Texture.TexCo.ORCO, Texture.MapTo.ALPHA )

tt = Texture.Get()
print "Textures: ", tt

xx = x0 + ww
yy = y0 + hh
me = NMesh.GetRaw()
v = NMesh.Vert( xx, y0, 0.0 )
#v.uvco = ( 1.0, 0.0 )
me.verts.append(v)
v = NMesh.Vert( xx, yy, 0.0 )
#v.uvco = ( 1.0, 1.0 )
me.verts.append(v)
v = NMesh.Vert( x0, yy, 0.0 )
#v.uvco = ( 0.0, 1.0 )
me.verts.append(v)
v = NMesh.Vert( x0, y0, 0.0 )
#v.uvco = ( 0.0, 0.0 )
me.verts.append(v)
f = NMesh.Face()
f.v.append( me.verts[0 ] )
f.v.append( me.verts[1 ] )
f.v.append( me.verts[2 ] )
f.v.append( me.verts[3 ] )
me.faces.append( f )

NMesh.PutRaw( me, nm, 1 )

me.update()

# use prior uvco or following faceUV
me.hasVertexUV(0)

f.uv = [(1.0,0.0),(1.0,1.0),(0.0,1.0),(0.0,0.0)]
me.hasFaceUV(1)
print "ME has face UV: ", me.hasFaceUV()

f.image = img
f.flag = NMesh.FaceModes.TEX + NMesh.FaceModes.LIGHT + NMesh.FaceModes.TWOSIDE
#f.transp = NMesh.FaceTranspModes.ALPHA
f.transp = NMesh.FaceTranspModes.SOLID

#me.mode = NMesh.Modes.TWOSIDED

##me.addMaterial( mat )

color = NMesh.Col( 255, 255, 255, 0 )
f.col.append( color )

oo = Object.Get( 'Mesh' )
oo.setName( nm )

    me.update()

print "ME has face UV: ", me.hasFaceUV()

Blender.Redraw()

setPlane( ‘plane1’, -5.5, -1.0, 11.0, 2.0 )
#setPlane( ‘plane2’, -1.0, -1.0, 2.0, 2.0 )

objects = Object.Get()
print "Objects: ", objects

camera = Object.Get(‘Camera’)
print "camera loc: ", camera.getLocation()
print "camera deltaloc: ", camera.getDeltaLocation()
print "camera euler: ", camera.getEuler()
print "camera euler: ", euler2deg( camera.getEuler() )
print "camera size: ", camera.getSize()

camera.setLocation(0.0, 0.0, 10.0)
camera.setEuler(deg2euler( [0.0, 0.0, 0.0] ))

lamp = Object.Get(‘Lamp’)
lamp.setLocation(0.0, 0.0, -5.0)

code from webcam script

gobjc = GameLogic.getCurrentController()
print "gobjc: ", gobjc

#gobj = GameLogic.getCurrentController().getOwner()
gobj = gobjc.getOwner()
print "gobj: ", gobj
print "gobj.name: ", gobj.name
print "gobj.name[2]: ", gobj.name[2]
print "gobj.name[2:]: ", gobj.name[2:]

Assumes mesh name == object name… very bad

bme = Blender.NMesh.GetRaw(gobj.name[2:])

Get Image handle for first face

ima = bme.faces[0].image

ima.Load("/home/S/PS/test00c.o.png")
#ima.reload()

Blender.Redraw()

=====

The execution output is:

=====

Xlib: extension “XFree86-DRI” missing on display “:0.0”.
bad call to addqueue: 0 (16384, 1)
fcntl: Device not configured
image width: 704 height: 128
Images Now: [[Image “test00c.o.png”]]
Textures: [[Texture “Tex1”]]
ME has face UV: False
ME has face UV: True
Objects: [[Object “Camera”], [Object “Lamp”], [Object “Empty”], [Object “plane1”]]
camera loc: (0.0, 0.0, 10.0)
camera deltaloc: (0.0, 0.0, 0.0)
camera euler: [0.0000, 0.0000, 0.0000]

camera euler: [0.0, 0.0, 0.0]
camera size: (1.0, 1.0, 1.0)
gobjc: C:init#CONTR#1
gobj:
gobj.name: OBEmpty
gobj.name[2]: E
gobj.name[2:]: Empty
PYTHON SCRIPT ERROR:
Traceback (most recent call last):
File “image_g.py”, line 140, in ?
ima = bme.faces[0].image
AttributeError: ‘NoneType’ object has no attribute ‘faces’
GL_VERSION: 1.3 (1.3 Mesa 4.0.4)

@a1000: please learn how to use the

 block

to save space here I will not do it for you

put your python code inside of the 

block and tabs [very important to python] and stuff are preserved

Sorry again for losing the tabs,
I should follow your tagline and slow down a bit when I post

=====


import Blender
from Blender import Texture, Image, NMesh, Material, Scene, Object
from math import * 
import fcntl, sys, os
import GameLogic

pi = 3.1415926
deg2rad = pi / 180.0
rad2deg = 180.0 / pi


def e2d(e):
	return ( e * rad2deg )
	
def d2e(d):
	return ( d * deg2rad )
    
def euler2deg( e3 ):
	return( [ e2d( e3[0] ),  e2d( e3[1] ), e2d( e3[2] )] )

def deg2euler( d3 ):
	return( [ d2e( d3[0] ),  d2e( d3[1] ), d2e( d3[2] )] )


def setPlane( nm, x0, y0, ww, hh ):
	img = Image.Load("/home/S/PS/test00c.o.png")
	bb = img.getSize()
	print "image width: ", bb[0], " height: ", bb[1]
	print "Images Now: ", Image.Get()
	
	tx = Texture.New('Tex1')
	tx.setType('Image')
	tx.image = img
	
	##mm = Material.Get()
	##print "Materials: ", mm
	##mat = Material.Get( "Material" )
	##mat.setAlpha(0.0)
	##mat.emit = 0.7 
	##mat.setAdd(0.8)
	##mat.setRGBCol( 1.0, 1.0, 1.0 )
	
	##mat.setTexture( 0, tx, Texture.TexCo.ORCO, Texture.MapTo.ALPHA )
	
	tt = Texture.Get()
	print "Textures: ", tt

	xx = x0 + ww
	yy = y0 + hh
	me = NMesh.GetRaw()
	v = NMesh.Vert( xx, y0, 0.0 )
	#v.uvco = ( 1.0, 0.0 )
	me.verts.append(v)
	v = NMesh.Vert( xx, yy, 0.0 )
	#v.uvco = ( 1.0, 1.0 )
	me.verts.append(v)
	v = NMesh.Vert( x0, yy, 0.0 )
	#v.uvco = ( 0.0, 1.0 )
	me.verts.append(v)
	v = NMesh.Vert( x0, y0, 0.0 )
	#v.uvco = ( 0.0, 0.0 )
	me.verts.append(v)
	f = NMesh.Face()
	f.v.append( me.verts[0 ] )
	f.v.append( me.verts[1 ] )
	f.v.append( me.verts[2 ] )
	f.v.append( me.verts[3 ] )
	me.faces.append( f )
	
	NMesh.PutRaw( me, nm, 1 )
	
	me.update()
	
	# use prior uvco or following faceUV
	me.hasVertexUV(0)
	
	f.uv = [(1.0,0.0),(1.0,1.0),(0.0,1.0),(0.0,0.0)]
	me.hasFaceUV(1)
	print "ME has face UV: ", me.hasFaceUV()
	
	f.image = img
	f.flag = NMesh.FaceModes.TEX + NMesh.FaceModes.LIGHT + NMesh.FaceModes.TWOSIDE
	#f.transp = NMesh.FaceTranspModes.ALPHA
	f.transp = NMesh.FaceTranspModes.SOLID
	
	#me.mode = NMesh.Modes.TWOSIDED
	
	##me.addMaterial( mat )
	
	color = NMesh.Col( 255, 255, 255, 0 )
	f.col.append( color )
	
	oo = Object.Get( 'Mesh' )
	oo.setName( nm )
	
        me.update()
	
	print "ME has face UV: ", me.hasFaceUV()
	
	Blender.Redraw()


setPlane( 'plane1', -5.5, -1.0, 11.0, 2.0 )
#setPlane( 'plane2', -1.0, -1.0, 2.0, 2.0 )


objects = Object.Get()
print "Objects: ", objects


camera = Object.Get('Camera')
print  "camera loc: ", camera.getLocation()
print  "camera deltaloc: ", camera.getDeltaLocation()
print  "camera euler: ", camera.getEuler()
print  "camera euler: ", euler2deg( camera.getEuler() )
print  "camera size: ", camera.getSize() 

camera.setLocation(0.0, 0.0, 10.0)
camera.setEuler(deg2euler( [0.0, 0.0, 0.0] ))

lamp = Object.Get('Lamp')
lamp.setLocation(0.0, 0.0, -5.0)

### code from webcam script ###
gobjc = GameLogic.getCurrentController()
print "gobjc: ", gobjc

#gobj = GameLogic.getCurrentController().getOwner()
gobj = gobjc.getOwner()
print "gobj: ", gobj
print "gobj.name: ", gobj.name
print "gobj.name[2]: ", gobj.name[2]
print "gobj.name[2:]: ", gobj.name[2:]

# Assumes mesh name == object name... very bad
bme = Blender.NMesh.GetRaw(gobj.name[2:])

# Get Image handle for first face
ima = bme.faces[0].image

ima.Load("/home/S/PS/test00c.o.png")
#ima.reload() 

Blender.Redraw()


The webcam script updates a texture attached to a mesh - it looks like you’ve attached the script to an empty.

You also look like you are creating a mesh in the Blender scene - the gameengine copies & converts the Blender scene,

  1. So running the game doesn’t destroy the blend file
  2. So it can be optimised for realtime rendering.

You can use the KX_MeshProxy class for modifying a mesh in realtime, but you can only modify vertex attributes (position, normals, UV etc), not the mesh topology. I have some code for adding polygons to a mesh for Tuhopuu2, but I can’t remember if I’ve committed it.

And try to get DRI working - realtime 3d graphics is just painful without 3d acceleration.

Alien-xmp,

Thank You for responding to this thread and for your work on the Blender code.

I’m trying to make a 3D environment in which simple 2D “billboard” planes
can be dynamically created and displayed with their “texture” contents coming from
existing image files.

After much study of the Blender books, online docs & tutorials, I’m still
unsure of the control model which the game engine would most easily use to
achieve this. The interactions of the realtime engine with the Blender scene
are still unclear to me, as most tutorials deal with one or the other,
with their respective Python API’s being another separate area of documentation.
(The new game API shows a rapidly expanding feature set, but I haven’t
yet found or intuited an overview of game engine control flow.)

Could you suggest some doc or code example I’ve missed ?

Although I successfully built Blender 2.33a from source here on FreeBSD 4.10,
2.34 had enough problems building that I just ran with the canned FreeBSD binary.
I’m unclear if you are talking about features in Tuhopuu2 code or in 2.34.
Building Tuhopuu2 while its still in work up there may be a task in itself for me.

On DRI: This workstation is an older 200mhz laptop where I’m not expecting to
produce acceptable game action. Another faster target PC with fully operable
acceleration is going to be required once the parts of the game are better
fleshed out. Making X config files is still a bit of a “black art”, and
I’m not even sure if this Thinkpad 770Z has acceleration worth worrying about.
Blender itself responds quite adequately on this little box.

Once again, thanks for your help !

Can you create your billboards and add them with the add object actuator?

Trying to get away from a canned procedural sequence to a fully dynamic process.

I assume the add object actuator cannot be used to display a copy of
the pre-created object that exists in the hidden level.
(Going by the gamekit book p 172 mention of that actuator.
Is there any better reference around ?)

The 2D image attachment needs to be dynamic,
along with the size and placement of the plane object being displayed in 3D.
All objects would have same topology - 1 quad face

Means a number of objects would need to be waiting in that hidden layer
to be mapped with their “texture” image, sized, positioned, displayed,
and “recycled” to the invisible layer again to later be attached to
a different image, resized, repositioned, and redisplayed.

Possible ?

It would be nice if a number of these hidden layer objects could be generated
before runtime and imported in some sort of .blend or other flat object file.
Makes reconfiguration much easier.

Am I off into something unrealistic ?

Once again, Thanks very much !

Just found the “KX_SCA_AddObjectActuator” doc

Does a setTime(0) call give a permanent display, or no display ?
the doc implies no display-- 0 frames

the doc says the setObject(obj) call adds a copy of the hidden object to the scene.

assume the copy can be individually modified / positioned from Python calls ?

setTime(0) gives permanent display.

Yes, the add object actuator makes a copy of it’s target object.

The setObject(obj) method sets the object that will be copied; it doesn’t actually add the object. Use GameLogic.addActiveActuator method to do that.

Once you are done with them, you don’t recycle the objects, you can just delete them and create new copies.

If you want to create a number of hidden objects before runtime, you can use the Blender modules to do that.