From 0000eb508f0f0a9ee3b0e4c273af1e3b4463632b Mon Sep 17 00:00:00 2001 From: paddywwoof Date: Tue, 21 Mar 2017 23:04:26 +0000 Subject: [PATCH 1/7] ElevationMap now copes with multiple textures using uv_env_map shader --- ReadMe.rst | 9 +++++-- pi3d/Display.py | 2 +- pi3d/Shader.py | 3 ++- pi3d/shape/ElevationMap.py | 55 ++++++++++++++++++++++++-------------- 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/ReadMe.rst b/ReadMe.rst index 0119fb71..00bbc19d 100644 --- a/ReadMe.rst +++ b/ReadMe.rst @@ -293,11 +293,16 @@ Setup on desktop and laptop machines The machine will need to have a gpu that runs OpenGL2+ and obviously it will need to have python installed. Setting up in a Linux environment - is most similar to the procedure for the Raspberry Pi. Linux can be set + is most similar to the procedure for the Raspberry Pi. In fact by far the + most staightforward route is to make a Raspbian Pixel USB stick following + the instructions here https://www.raspberrypi.org/blog/pixel-pc-mac/ + After that your PC will behave pretty much like the Raspberry Pi and pi3d + will work after a simple ``sudo pip3 install pi3d`` The USB isn't as fast + as a hard drive but everything else will run at PC speed. Linux can be set up in its own boot partition or in vmware (eg Player which is free, you will also need to ``enable 3d acceleration``.) - You need to install libraries + For non Pixel linux you will need to install libraries that emulate OpenGLES behaviour for the gpu:: $ sudo apt-get install mesa-utils-extra diff --git a/pi3d/Display.py b/pi3d/Display.py index c521eab1..0d51b71d 100644 --- a/pi3d/Display.py +++ b/pi3d/Display.py @@ -131,7 +131,7 @@ def __init__(self, tkwin=None, use_pygame=False): self.vbufs_dict = {} self.ebufs_dict = {} self.last_shader = None - self.last_textures = [None, None, None] # if more than 3 used this will break in Buffer.draw() + self.last_textures = [None for i in range(8)] # 8 is max no. texture2D on broadcom GPU self.external_mouse = None self.offscreen_tex = False # used in Buffer.draw() to force reload of textures diff --git a/pi3d/Shader.py b/pi3d/Shader.py index b99d8080..fa76f627 100644 --- a/pi3d/Shader.py +++ b/pi3d/Shader.py @@ -122,7 +122,8 @@ def make_shader(src, suffix, shader_type): opengles.glEnableVertexAttribArray(self.attr_texcoord) self.unif_tex = [] self.textures = [] - for s in [b'tex0', b'tex1', b'tex2']: + for i in range(8): + s = 'tex{}'.format(i).encode() self.unif_tex.append(opengles.glGetUniformLocation(self.program, s)) self.textures.append(None) """ diff --git a/pi3d/shape/ElevationMap.py b/pi3d/shape/ElevationMap.py index 97fe78b5..dab54d98 100644 --- a/pi3d/shape/ElevationMap.py +++ b/pi3d/shape/ElevationMap.py @@ -18,6 +18,14 @@ if PIL_OK: from PIL import Image +def file_pathify(file_path): + if file_path[0] != '/': + for p in sys.path: + if os.path.isfile(p + '/' + file_path): # this could theoretically get different files with same name + file_path = p + '/' + file_path + break + return file_path + # a rectangular surface where elevation is defined by a greyscal image class ElevationMap(Shape): """ 3d model inherits from Shape @@ -26,7 +34,8 @@ def __init__(self, mapfile, camera=None, light=None, width=100.0, depth=100.0, height=10.0, divx=0, divy=0, ntiles=1.0, name="", x=0.0, y=0.0, z=0.0, rx=0.0, ry=0.0, rz=0.0, - sx=1.0, sy=1.0, sz=1.0, cx=0.0, cy=0.0, cz=0.0, smooth=True, cubic=False): + sx=1.0, sy=1.0, sz=1.0, cx=0.0, cy=0.0, cz=0.0, smooth=True, + cubic=False, texmap=None): """uses standard constructor for Shape Arguments: @@ -65,11 +74,7 @@ def __init__(self, mapfile, camera=None, light=None, if PIL_OK: try: if '' + mapfile == mapfile: #HORRIBLE. Only way to cope with python2v3 - if mapfile[0] != '/': - for p in sys.path: - if os.path.isfile(p + '/' + mapfile): # this could theoretically get different files with same name - mapfile = p + '/' + mapfile - break + mapfile = file_pathify(mapfile) LOGGER.info("Loading height map ...%s", mapfile) im = Image.open(mapfile) @@ -84,20 +89,28 @@ def __init__(self, mapfile, camera=None, light=None, divy = 200 im = im.resize((divx, divy), Image.ANTIALIAS) ix, iy = im.size - + im = im.convert('L') im = im.transpose(Image.FLIP_TOP_BOTTOM) im = im.transpose(Image.FLIP_LEFT_RIGHT) self.pixels = im.load() + if texmap is not None: + try: + texmap = file_pathify(texmap) + tm = Image.open(texmap) + except: + tm = texmap + tm = tm.convert('L') + tm = tm.resize((ix, iy)) + tm = np.array(tm) + tm = np.floor(tm * 3.99 / (tm.max() - tm.min())) + else: ''' images saved as compressed numpy npz file. No resizing so needs - to be right size. TODO make this repeated code less WET''' - if mapfile[0] != '/': - for p in sys.path: - if os.path.isfile(p + '/' + mapfile): # this could theoretically get different files with same name - mapfile = p + '/' + mapfile - break + to be right size.''' + mapfile = file_pathify(mapfile) self.pixels = np.load(mapfile)['arr_0'][::-1,::-1] # has to be saved with default key ix, iy = self.pixels.shape[:2] + self.width = width self.depth = depth self.height = height @@ -124,13 +137,15 @@ def __init__(self, mapfile, camera=None, light=None, for y in xrange(0, iy): for x in xrange(0, ix): - pxl = self.pixels[x, y] - hgt = pxl[0] if hasattr(pxl, '__iter__') else pxl - hgt *= self.ht - this_x = -self.wh + x * self.ws - this_z = -self.hh + y * self.hs - verts.append((this_x, hgt, this_z)) - tex_coords.append(((ix - x) * tx, (iy - y) * ty)) + hgt = self.pixels[x, y] * self.ht + verts.append((-self.wh + x * self.ws, + hgt, + -self.hh + y * self.hs)) + if texmap is not None: + tex_n = tm[x, y] + else: + tex_n = 0.0 + tex_coords.append((tex_n + (ix - x) * tx, (iy - y) * ty)) s = 0 #create one long triangle_strip by alternating X directions From 4c345578b32dd83c8062fa5d6750d03a5e107a8f Mon Sep 17 00:00:00 2001 From: paddywwoof Date: Tue, 21 Mar 2017 23:07:55 +0000 Subject: [PATCH 2/7] fixed name of multi texture ElevationMap specific shaders --- pi3d/shaders/uv_elev_map.fs | 33 +++++++++++++++++++++++++++++++++ pi3d/shaders/uv_elev_map.vs | 22 ++++++++++++++++++++++ pi3d/shaders/uv_env_map.fs | 33 +++++++++++++++++++++++++++++++++ pi3d/shaders/uv_env_map.vs | 22 ++++++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 pi3d/shaders/uv_elev_map.fs create mode 100644 pi3d/shaders/uv_elev_map.vs create mode 100644 pi3d/shaders/uv_env_map.fs create mode 100644 pi3d/shaders/uv_env_map.vs diff --git a/pi3d/shaders/uv_elev_map.fs b/pi3d/shaders/uv_elev_map.fs new file mode 100644 index 00000000..eee57f02 --- /dev/null +++ b/pi3d/shaders/uv_elev_map.fs @@ -0,0 +1,33 @@ +#include std_head_fs.inc + +uniform sampler2D tex3; +uniform sampler2D tex4; +uniform sampler2D tex5; +uniform sampler2D tex6; +uniform sampler2D tex7; + +varying vec2 texcoordout; +varying vec2 bumpcoordout; +varying vec3 lightVector; +varying float dist; +varying float lightFactor; +varying float texFactor; + +void main(void) { + vec4 texc = mix( + mix(texture2D(tex0, texcoordout), texture2D(tex2, texcoordout), clamp(texFactor, 0.0, 1.0)), + mix(texture2D(tex4, texcoordout), texture2D(tex6, texcoordout), clamp((texFactor - 2.0), 0.0, 1.0)), + clamp((texFactor - 1.0), 0.0, 1.0)); + texc.rgb += unib[1] - vec3(0.5); + float ffact = smoothstep(unif[5][0]/3.0, unif[5][0], dist); // ------ smoothly increase fog between 1/3 and full fogdist + vec3 bump = normalize(mix( + mix(texture2D(tex1, bumpcoordout), texture2D(tex3, bumpcoordout), clamp(texFactor, 0.0, 1.0)), + mix(texture2D(tex5, bumpcoordout), texture2D(tex7, bumpcoordout), clamp((texFactor - 2.0), 0.0, 1.0)), + clamp((texFactor - 1.0), 0.0, 1.0)).rgb * 2.0 - 1.0); +#include std_bump.inc + + gl_FragColor = (1.0 - ffact) * texc + ffact * vec4(unif[4], unif[5][1]); // ------ combine using factors + gl_FragColor.a *= unif[5][2]; +} + + diff --git a/pi3d/shaders/uv_elev_map.vs b/pi3d/shaders/uv_elev_map.vs new file mode 100644 index 00000000..ab148eeb --- /dev/null +++ b/pi3d/shaders/uv_elev_map.vs @@ -0,0 +1,22 @@ +#include std_head_vs.inc + +varying vec2 texcoordout; +varying vec2 bumpcoordout; +varying float dist; +varying vec3 lightVector; +varying float lightFactor; +varying float texFactor; + +void main(void) { + vec3 normout; +#include std_main_vs.inc + texcoordout = fract(texcoord * unib[2].xy + unib[3].xy); + bumpcoordout = texcoordout * vec2(1.0, 1.0) * unib[0][0]; + texFactor = floor(texcoord[0]); // ----- u and v expected to go up together! + + vec3 inray = vec3(relPosn - vec4(unif[6], 0.0)); // ----- vector from the camera to this vertex + dist = length(inray); + + gl_Position = modelviewmatrix[1] * vec4(vertex,1.0); + gl_PointSize = unib[2][2] / dist; +} diff --git a/pi3d/shaders/uv_env_map.fs b/pi3d/shaders/uv_env_map.fs new file mode 100644 index 00000000..eee57f02 --- /dev/null +++ b/pi3d/shaders/uv_env_map.fs @@ -0,0 +1,33 @@ +#include std_head_fs.inc + +uniform sampler2D tex3; +uniform sampler2D tex4; +uniform sampler2D tex5; +uniform sampler2D tex6; +uniform sampler2D tex7; + +varying vec2 texcoordout; +varying vec2 bumpcoordout; +varying vec3 lightVector; +varying float dist; +varying float lightFactor; +varying float texFactor; + +void main(void) { + vec4 texc = mix( + mix(texture2D(tex0, texcoordout), texture2D(tex2, texcoordout), clamp(texFactor, 0.0, 1.0)), + mix(texture2D(tex4, texcoordout), texture2D(tex6, texcoordout), clamp((texFactor - 2.0), 0.0, 1.0)), + clamp((texFactor - 1.0), 0.0, 1.0)); + texc.rgb += unib[1] - vec3(0.5); + float ffact = smoothstep(unif[5][0]/3.0, unif[5][0], dist); // ------ smoothly increase fog between 1/3 and full fogdist + vec3 bump = normalize(mix( + mix(texture2D(tex1, bumpcoordout), texture2D(tex3, bumpcoordout), clamp(texFactor, 0.0, 1.0)), + mix(texture2D(tex5, bumpcoordout), texture2D(tex7, bumpcoordout), clamp((texFactor - 2.0), 0.0, 1.0)), + clamp((texFactor - 1.0), 0.0, 1.0)).rgb * 2.0 - 1.0); +#include std_bump.inc + + gl_FragColor = (1.0 - ffact) * texc + ffact * vec4(unif[4], unif[5][1]); // ------ combine using factors + gl_FragColor.a *= unif[5][2]; +} + + diff --git a/pi3d/shaders/uv_env_map.vs b/pi3d/shaders/uv_env_map.vs new file mode 100644 index 00000000..ab148eeb --- /dev/null +++ b/pi3d/shaders/uv_env_map.vs @@ -0,0 +1,22 @@ +#include std_head_vs.inc + +varying vec2 texcoordout; +varying vec2 bumpcoordout; +varying float dist; +varying vec3 lightVector; +varying float lightFactor; +varying float texFactor; + +void main(void) { + vec3 normout; +#include std_main_vs.inc + texcoordout = fract(texcoord * unib[2].xy + unib[3].xy); + bumpcoordout = texcoordout * vec2(1.0, 1.0) * unib[0][0]; + texFactor = floor(texcoord[0]); // ----- u and v expected to go up together! + + vec3 inray = vec3(relPosn - vec4(unif[6], 0.0)); // ----- vector from the camera to this vertex + dist = length(inray); + + gl_Position = modelviewmatrix[1] * vec4(vertex,1.0); + gl_PointSize = unib[2][2] / dist; +} From 7b19bfddcecd45c56f4bee6f87de438ee03e1faa Mon Sep 17 00:00:00 2001 From: paddywwoof Date: Tue, 21 Mar 2017 23:09:00 +0000 Subject: [PATCH 3/7] removed wrong named shaders --- pi3d/shaders/uv_env_map.fs | 33 --------------------------------- pi3d/shaders/uv_env_map.vs | 22 ---------------------- 2 files changed, 55 deletions(-) delete mode 100644 pi3d/shaders/uv_env_map.fs delete mode 100644 pi3d/shaders/uv_env_map.vs diff --git a/pi3d/shaders/uv_env_map.fs b/pi3d/shaders/uv_env_map.fs deleted file mode 100644 index eee57f02..00000000 --- a/pi3d/shaders/uv_env_map.fs +++ /dev/null @@ -1,33 +0,0 @@ -#include std_head_fs.inc - -uniform sampler2D tex3; -uniform sampler2D tex4; -uniform sampler2D tex5; -uniform sampler2D tex6; -uniform sampler2D tex7; - -varying vec2 texcoordout; -varying vec2 bumpcoordout; -varying vec3 lightVector; -varying float dist; -varying float lightFactor; -varying float texFactor; - -void main(void) { - vec4 texc = mix( - mix(texture2D(tex0, texcoordout), texture2D(tex2, texcoordout), clamp(texFactor, 0.0, 1.0)), - mix(texture2D(tex4, texcoordout), texture2D(tex6, texcoordout), clamp((texFactor - 2.0), 0.0, 1.0)), - clamp((texFactor - 1.0), 0.0, 1.0)); - texc.rgb += unib[1] - vec3(0.5); - float ffact = smoothstep(unif[5][0]/3.0, unif[5][0], dist); // ------ smoothly increase fog between 1/3 and full fogdist - vec3 bump = normalize(mix( - mix(texture2D(tex1, bumpcoordout), texture2D(tex3, bumpcoordout), clamp(texFactor, 0.0, 1.0)), - mix(texture2D(tex5, bumpcoordout), texture2D(tex7, bumpcoordout), clamp((texFactor - 2.0), 0.0, 1.0)), - clamp((texFactor - 1.0), 0.0, 1.0)).rgb * 2.0 - 1.0); -#include std_bump.inc - - gl_FragColor = (1.0 - ffact) * texc + ffact * vec4(unif[4], unif[5][1]); // ------ combine using factors - gl_FragColor.a *= unif[5][2]; -} - - diff --git a/pi3d/shaders/uv_env_map.vs b/pi3d/shaders/uv_env_map.vs deleted file mode 100644 index ab148eeb..00000000 --- a/pi3d/shaders/uv_env_map.vs +++ /dev/null @@ -1,22 +0,0 @@ -#include std_head_vs.inc - -varying vec2 texcoordout; -varying vec2 bumpcoordout; -varying float dist; -varying vec3 lightVector; -varying float lightFactor; -varying float texFactor; - -void main(void) { - vec3 normout; -#include std_main_vs.inc - texcoordout = fract(texcoord * unib[2].xy + unib[3].xy); - bumpcoordout = texcoordout * vec2(1.0, 1.0) * unib[0][0]; - texFactor = floor(texcoord[0]); // ----- u and v expected to go up together! - - vec3 inray = vec3(relPosn - vec4(unif[6], 0.0)); // ----- vector from the camera to this vertex - dist = length(inray); - - gl_Position = modelviewmatrix[1] * vec4(vertex,1.0); - gl_PointSize = unib[2][2] / dist; -} From b5ae7fc0837f2757f21f2ba7b5345f4bbe1db195 Mon Sep 17 00:00:00 2001 From: int-0 Date: Tue, 11 Apr 2017 19:14:08 +0200 Subject: [PATCH 4/7] Support vertical and/or horizontal texture flipping --- pi3d/Texture.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pi3d/Texture.py b/pi3d/Texture.py index a46a215e..750b56a6 100644 --- a/pi3d/Texture.py +++ b/pi3d/Texture.py @@ -64,7 +64,10 @@ def __init__(self, file_string, blend=False, flip=False, size=0, by the shader. If set to true then this texture needs to be drawn AFTER other objects that are FURTHER AWAY *flip* - flips the image [not used for numpy arrays] + flips the image [not used for numpy arrays]. If flip is 1 works like + True, but if flip is 2 flips the image left to right and is 3, then + flips both horizontal and vertical + *size* to resize image to [not used for numpy arrays] *defer* @@ -240,8 +243,13 @@ def _load_disk(self): LOGGER.debug('Loading ...%s', s) - if self.flip: + if isinstance(self.flip, bool): im = im.transpose(Image.FLIP_TOP_BOTTOM) + else: + if self.flip & 1: + im = im.transpose(Image.FLIP_TOP_BOTTOM) + if self.flip & 2: + im = im.transpose(Image.FLIP_LEFT_RIGHT) #self.image = im.tostring('raw', RGBs) # TODO change to tobytes WHEN Pillow is default PIL in debian (jessie becomes current) self.image = self._img_to_array(im) From 58dd4ef5be110efd09103f9800d8246fa1b71392 Mon Sep 17 00:00:00 2001 From: int-0 Date: Tue, 11 Apr 2017 19:34:05 +0200 Subject: [PATCH 5/7] Fix typo --- pi3d/Texture.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pi3d/Texture.py b/pi3d/Texture.py index 750b56a6..a4ca8e2e 100644 --- a/pi3d/Texture.py +++ b/pi3d/Texture.py @@ -64,9 +64,9 @@ def __init__(self, file_string, blend=False, flip=False, size=0, by the shader. If set to true then this texture needs to be drawn AFTER other objects that are FURTHER AWAY *flip* - flips the image [not used for numpy arrays]. If flip is 1 works like - True, but if flip is 2 flips the image left to right and is 3, then - flips both horizontal and vertical + flips the image [not used for numpy arrays]. Now this parameter could + be an integer value. If bit #0 is 1, a up-down flip is perfomed, + also if bit #1 is set, a left-right flip occurs *size* to resize image to [not used for numpy arrays] @@ -244,7 +244,9 @@ def _load_disk(self): LOGGER.debug('Loading ...%s', s) if isinstance(self.flip, bool): - im = im.transpose(Image.FLIP_TOP_BOTTOM) + # Old behaviour + if self.flip: + im = im.transpose(Image.FLIP_TOP_BOTTOM) else: if self.flip & 1: im = im.transpose(Image.FLIP_TOP_BOTTOM) From 1fdc7f17a3fcdb9b20dd1346ad391d069a490f59 Mon Sep 17 00:00:00 2001 From: paddywwoof Date: Tue, 18 Apr 2017 18:48:13 +0100 Subject: [PATCH 6/7] bugfix - increased restriction on number of devices --- pi3d/event/EventHandler.py | 28 ++++++++++++++-------------- pi3d/event/FindDevices.py | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/pi3d/event/EventHandler.py b/pi3d/event/EventHandler.py index 311357a3..a082adb3 100644 --- a/pi3d/event/EventHandler.py +++ b/pi3d/event/EventHandler.py @@ -20,20 +20,20 @@ def __init__(self, keyHandler=None, relHandler=None, absHandler=None, synHandler self.mutex = threading.Lock() - self.absx = [0.0]*4 - self.absy = [0.0]*4 - self.absz = [0.0]*4 - self.absx2 = [0.0]*4 - self.absy2 = [0.0]*4 - self.absz2 = [0.0]*4 - self.abshatx = [0.0]*4 - self.abshaty = [0.0]*4 - - self.relx = [0]*4 - self.rely = [0]*4 - self.relv = [0]*4 - self.relh = [0]*4 - self.reld = [0]*4 + self.absx = [0.0]*16 + self.absy = [0.0]*16 + self.absz = [0.0]*16 + self.absx2 = [0.0]*16 + self.absy2 = [0.0]*16 + self.absz2 = [0.0]*16 + self.abshatx = [0.0]*16 + self.abshaty = [0.0]*16 + + self.relx = [0]*16 + self.rely = [0]*16 + self.relv = [0]*16 + self.relh = [0]*16 + self.reld = [0]*16 def event(self, event): """ diff --git a/pi3d/event/FindDevices.py b/pi3d/event/FindDevices.py index 089cde84..b2103c2d 100644 --- a/pi3d/event/FindDevices.py +++ b/pi3d/event/FindDevices.py @@ -191,7 +191,7 @@ def find_devices(identifier, butNot= [ ]): else: pass # print "No need to remove", old[1] - else: + else: # i.e. there was no break from above for loop (horrible for-else syntax!) ret.append((index, int(eventindex))) index += 1 From 67738fc8937b529fa3bfc44e45141d02d19da328 Mon Sep 17 00:00:00 2001 From: paddywwoof Date: Thu, 20 Apr 2017 23:11:27 +0100 Subject: [PATCH 7/7] update for v2.19 --- ReadMe.rst | 19 ++++++++++--------- pi3d/constants/__init__.py | 2 +- pi3d/shape/ElevationMap.py | 7 +++++++ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/ReadMe.rst b/ReadMe.rst index 00bbc19d..4e603d82 100644 --- a/ReadMe.rst +++ b/ReadMe.rst @@ -132,15 +132,16 @@ pi3d with different levels of complexity. Files and folders in this repository ==================================== -Total zipped download from github c. 574 kB extracts to 1.2 MB - -#. **pi3d** The main pi3d module files 446 kB -#. **pyxlib** Library to enable use on general linux machines 209 kB -#. **images** To show in ReadMe on github 325 kB -#. **ReadMe** This file in markup and plain text 31 kB -#. **ChangeLog.txt** Latest changes of pi3d 19 kB -#. **six_mod.py** utilities to help run under python2 and python3 13 kB -#. **misc. others** 10 kB +Installation tar.gz on python.pypi.org is c.190kB extracts to 770kB. Total +zipped download from github is c.600 kB extracts to c.1100kB + +#. **pi3d** The main pi3d module files 517kB +#. **pyxlib** Library to enable use on general linux machines 209kB +#. **images** To show in ReadMe on github 325kB +#. **ReadMe** This file in markup and plain text 27kB +#. **ChangeLog.txt** Latest changes of pi3d 16kB +#. **six_mod.py** utilities to help run under python2 and python3 13kB +#. **misc. others** 10kB Setup on the Raspberry Pi ========================= diff --git a/pi3d/constants/__init__.py b/pi3d/constants/__init__.py index da5f1c5e..1210fd03 100644 --- a/pi3d/constants/__init__.py +++ b/pi3d/constants/__init__.py @@ -5,7 +5,7 @@ """ import time -__version__ = '2.18' +__version__ = '2.19' year = time.localtime().tm_year STARTUP_MESSAGE = """ diff --git a/pi3d/shape/ElevationMap.py b/pi3d/shape/ElevationMap.py index dab54d98..ab1ec375 100644 --- a/pi3d/shape/ElevationMap.py +++ b/pi3d/shape/ElevationMap.py @@ -60,6 +60,13 @@ def __init__(self, mapfile, camera=None, light=None, *smooth* Calculate normals with averaging rather than pointing straight up, slightly faster if false. + *texmap* + Image file path or PIL.Image to be used to represent each of four + textures and normals using the uv_elev_map shader. The image is + converted to greyscale and apportioned between darkest (first and + second entries in Buffer.textures list) and lightest (seventh and + eighth entries). The resulting 0.0, 1.0, 2.0 or 3.0 is added to the + uv texture coordinate i.e. Buffer.array_buffer[:,6:8] """ super(ElevationMap, self).__init__(camera, light, name, x, y, z, rx, ry, rz, sx, sy, sz, cx, cy, cz)