~mcfletch/openglcontext/trunk : /OpenGLContext/scenegraph/cubebackground.py (revision 351)

Line Revision Contents
1 1
"""Panoramic image-cube Background node
2
"""
3
from OpenGLContext.scenegraph import imagetexture
4 37
from OpenGL.arrays import vbo
5
from OpenGLContext.arrays import array
6 1
from vrml import field, protofunctions, fieldtypes, node
7
from vrml.vrml97 import basenodes, nodetypes
8
9
from OpenGL.GL import *
10
from OpenGLContext.arrays import *
11
from math import pi
12
13
class URLField( fieldtypes.MFString ):
14
	"""Cube-background URL field which forwards to the corresponding ImageTexture node's url
15
	"""
16
	fieldType = "MFString"
17
	def fset( self, client, value, notify=1 ):
18
		value = super( URLField, self).fset( client, value, notify )
19
		imageObject = getattr(client, self.name[:-3])
20
		setattr( imageObject, 'url', value )
21
		return value
22
	def fdel( self, client, notify=1 ):
23
		value = super( URLField, self).fdel( client, notify )
24
		imageObject = getattr(client, self.name[:-3])
25
		delattr( imageObject, 'url')
26
		return value
27
28
class _CubeBackground( object ):
29
	right = field.newField('right', 'SFNode', default=imagetexture.ImageTexture)
30
	top = field.newField('top', 'SFNode', default=imagetexture.ImageTexture)
31
	back = field.newField('back', 'SFNode', default=imagetexture.ImageTexture)
32
	left = field.newField('left', 'SFNode', default=imagetexture.ImageTexture)
33
	front = field.newField('front', 'SFNode', default=imagetexture.ImageTexture)
34
	bottom = field.newField('bottom', 'SFNode', default=imagetexture.ImageTexture)
35
	
36
	rightUrl = URLField( 'rightUrl')
37
	topUrl = URLField( 'topUrl')
38
	backUrl = URLField( 'backUrl')
39
	leftUrl = URLField( 'leftUrl')
40
	frontUrl = URLField( 'frontUrl')
41
	bottomUrl = URLField( 'bottomUrl')
42
	
43
	bound = field.newField( 'bound', 'SFBool', 1, 0)
44
	
45
	def Render( self, mode, clear=1 ):
46
		"""Render the cube background
47
48
		This renders those of our cube-faces which are
49
		facing us, and which have a non-0 component-count.
50
51
		After it's finished, it clears the depth-buffer
52
		to make the geometry appear "behind" everything
53
		else.
54
		"""
55
		if mode.passCount == 0:
56 244
			glPushAttrib( GL_ALL_ATTRIB_BITS )
57 154
			glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
58 1
			try:
59
				glDisable( GL_LIGHTING )
60
				glDisable( GL_COLOR_MATERIAL )
61 37
				if not self.VBO:
62
					self.compile( mode )
63 1
				if clear:
64 116
					glClear(
65
						GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT
66
					)
67 244
				# we don't want to do anything with the depth buffer
68
				# once we've cleared it...
69
				glDepthMask( GL_FALSE ) 
70
				matrix = glGetDoublev( GL_MODELVIEW_MATRIX )
71
				if matrix is None:
72
					# glGetDoublev can return None if uninitialised...
73
					matrix = identity( 4, 'd')
74
				forward = dot(matrix, [0,0,-1,0])
75
				self.VBO.bind()
76
				glInterleavedArrays( GL_T2F_V3F, 0, self.VBO )
77 1
				try:
78 244
					for offset,attr_name, normal, data in self.RENDER_DATA:
79
						texture = getattr( self, attr_name )
80
						if dot(forward, normal) <=0 and texture.components:
81
							# we are facing it, and it's loaded/non-null
82
							texture.render(lit=0, mode=mode)
83
							try:
84
								glDrawArrays( GL_TRIANGLES, offset, 6 )
85
							finally:
86
								texture.renderPost(mode=mode)
87 1
				finally:
88 244
					self.VBO.unbind()
89 1
			finally:
90 154
				glPopClientAttrib()
91 244
				glPopAttrib()
92 37
	
93
	# TODO: should have one-per-context...
94
	VBO = None
95
	def compile( self, mode ):
96
		"""Compile a VBO with our various triangles to render"""
97
		if self.VBO:
98
			return self.VBO
99
		def vertices( ):
100
			for (offset,attr,norm,(a,b,c,d)) in self.RENDER_DATA:
101
				yield a[1]+a[0]
102
				yield b[1]+b[0]
103
				yield c[1]+c[0]
104
				yield a[1]+a[0]
105
				yield c[1]+c[0]
106
				yield d[1]+d[0]
107
		vb = self.VBO = vbo.VBO(array(list(vertices()),'f'))
108
		return vb
109
	RENDER_DATA = [
110
		(0,'front',(0,0,1,0),[
111
			((-1,-1,-1), (0,0)),
112
			((1,-1,-1), (1,0)),
113
			((1,1,-1), (1,1)),
114
			((-1,1,-1), (0,1)),
115
		]),
116
		(6,'right',(-1,0,0,0),[
117
			((1,-1,-1), (0,0)),
118
			((1,-1,1), (1,0)),
119
			((1,1,1), (1,1)),
120
			((1,1,-1), (0,1)),
121
		]),
122
		(12,'back', (0,0,-1,0), [
123
			((1,-1,1), (0,0)),
124
			((-1,-1,1), (1,0)),
125
			((-1,1,1), (1,1)),
126
			((1,1,1), (0,1)),
127
		]),
128
		(18,'left',(1,0,0,0),[
129
			((-1,-1,1), (0,0)),
130
			((-1,-1,-1), (1,0)),
131
			((-1,1,-1), (1,1)),
132
			((-1,1,1), (0,1)),
133
		]),
134
		(24,'bottom',(0,1,0,0),[
135
			((-1,-1,1), (0,0)),
136
			((1,-1,1), (1,0)),
137
			((1,-1,-1), (1,1)),
138
			((-1,-1,-1), (0,1)),
139
		]),
140
		(30,'top',(0,-1,0,0),[
141
			((-1,1,-1), (0,0)),
142
			((1,1,-1), (1,0)),
143
			((1,1,1), (1,1)),
144
			((-1,1,1), (0,1)),
145
		]),
146
	]
147
		
148 1
149
class CubeBackground( _CubeBackground, nodetypes.Background, nodetypes.Children, node.Node  ):
150
	"""Image-cube Background node
151
152
	The CubeBackground node implements 1/2 of the VRML97
153
	background node, particularly the image-cube
154
	functionality represented by the rightUrl, topUrl,
155
	backUrl, leftUrl, frontUrl, and bottomUrl fields.
156
157
	Fields of note within the CubeBackground object:
158
159
		back, front, left, right, top, bottom -- texture
160
			objects applied to the geometry of the cube.
161
			Any node which supports the texture API
162
			should work for these attributes
163
			
164
		backUrl, frontUrl, leftUrl, rightUrl, topUrl,
165
		bottomUrl -- texture urls (MFStrings) used to
166
			load the images above
167
168
	Note: the common practice in 3DSMax for creating
169
	a cubic environment map produces useful
170
	background images, but it is often necessary to
171
	swap left and right images to work with the
172
	VRML 97 system.
173
	"""
174
	

Loggerhead 1.10 is a web-based interface for Bazaar branches