Skip to content

Commit

Permalink
Merge branch 'develop' for v2.11
Browse files Browse the repository at this point in the history
  • Loading branch information
paddywwoof committed Apr 25, 2016
2 parents cd33893 + 696477f commit 7bbc073
Show file tree
Hide file tree
Showing 14 changed files with 73 additions and 43 deletions.
10 changes: 8 additions & 2 deletions ChangeLog.txt
Expand Up @@ -4,6 +4,13 @@ Tim Skillman, Patrick Gaunt, Tom Ritchford

Date Amends

v2.11
2016-04-25 Improvements: screenshot() can be used to capture rendered
image to a numpy array (and not written to file) for use with
gtk or pyqt display for instance. More control over window features
when using pygame, thanks to @crashmatt (who did the creative
work for PointText and TextBlock in v2.8)

v2.10
2016-02-11 Bug fixes: GL_STENCIL_SIZE explicitly set in DisplayOpenGL
Mouse wheel movement doesn't crash when using pygame input -
Expand All @@ -15,7 +22,7 @@ v2.10
by an argument to the Texture.__init__() Also the mipmap code
has been moved to the correct location to drastically reduce
memory requirements with the mipmap=False. Thanks to @swehner for
all is work on this
all his work on this

v2.9
2016-01-16 Bug fixes: glReadPixels fixed on linux and windows so Screenshot
Expand Down Expand Up @@ -48,7 +55,6 @@ v2.7
than y position. Texture reflection in shaders fixed. Normals
in String fixed. Option to use pygame rather than X11 display,
mouse and keyboard to avoid having to run as root on linux.


v2.6
2015-07-02 Moved Shader specific code from Shape.draw() to Buffer.draw()
Expand Down
6 changes: 3 additions & 3 deletions LICENSE
@@ -1,9 +1,9 @@
# pi3D common module
# ==================
#
# Copyright (c) 2015, Tim Skillman.
# Copyright (c) 2015, Paddy Gaunt.
# Copyright (c) 2015, Tom Ritchford.
# Copyright (c) 2012-2016, Tim Skillman.
# Copyright (c) 2012-2016, Paddy Gaunt.
# Copyright (c) 2012-2016, Tom Ritchford.
# (Some code initially based on Peter de Rivaz pyopengles example.)
#
# www.github.com/tipam/pi3d
Expand Down
2 changes: 1 addition & 1 deletion README
Expand Up @@ -2,7 +2,7 @@
Introduction to Pi3D
====================

**Pi3D written by Tim Skillman, Paddy Gaunt, Tom Ritchford Copyright (c) 2015**
**Pi3D written by Tim Skillman, Paddy Gaunt, Tom Ritchford Copyright (c) 2016**

There's plenty of 3D code flying around at the moment for the Raspberry Pi,
but much of it is rather complicated to understand and most of it can sit
Expand Down
2 changes: 1 addition & 1 deletion ReadMe.rst
Expand Up @@ -4,7 +4,7 @@ Introduction to pi3d
.. image:: images/rpilogoshad128.png
:align: left

**pi3d written by Tim Skillman, Paddy Gaunt, Tom Ritchford Copyright (c) 2015**
**pi3d written by Tim Skillman, Paddy Gaunt, Tom Ritchford Copyright (c) 2012-2016**

Here is a link to an excellent, self explanatory `YouTube`_ video made by
Peter Farrell that covers much of the content of this ReadMe.
Expand Down
4 changes: 1 addition & 3 deletions pi3d/Buffer.py
Expand Up @@ -12,8 +12,6 @@
from pi3d.util.Loadable import Loadable
from pi3d.util.Ctypes import c_floats, c_shorts

LOGGER = Log.logger(__name__)

class Buffer(Loadable):
"""Holds the vertex, normals, incices and tex_coords for each part of
a Shape that needs to be rendered with a different material or texture
Expand Down Expand Up @@ -64,6 +62,7 @@ def __init__(self, shape, pts, texcoords, faces, normals=None, smooth=True):
2 umult, vmult, point_size 6 8
3 u_off, v_off, line_width/bump 9 10 #NB line width and bump factor
===== ============================ ==== == clash but shouldn't be an issue
"""
#self.shape = shape
self.textures = []
Expand Down Expand Up @@ -91,7 +90,6 @@ def __init__(self, shape, pts, texcoords, faces, normals=None, smooth=True):
self.array_buffer[:,6:8] = np.array(texcoords, dtype="float32")
if bufw > 3:
if normals is None: #i.e. normals will only be generated if explictly None
LOGGER.debug('Calculating normals ...')
self.array_buffer[:,3:6] = self.calc_normals()
else:
self.array_buffer[:,3:6] = np.array(normals, dtype="float32")
Expand Down
11 changes: 6 additions & 5 deletions pi3d/Display.py
Expand Up @@ -11,6 +11,7 @@
import pi3d
from pi3d.util import Log
from pi3d.util.DisplayOpenGL import DisplayOpenGL
from pi3d.constants import *

if pi3d.PLATFORM == pi3d.PLATFORM_WINDOWS:
import pygame
Expand Down Expand Up @@ -332,7 +333,6 @@ def _tidy(self):
to_del = []
for i in self.textures_dict:
tex = self.textures_dict[i]
LOGGER.debug('tex0=%s tex1=%s',tex[0], tex[1])
if tex[1] == 1:
pi3d.opengles.glDeleteTextures(1, byref(tex[0]))
to_del.append(i)
Expand Down Expand Up @@ -401,7 +401,8 @@ def swap_buffers(self):
def create(x=None, y=None, w=None, h=None, near=None, far=None,
fov=DEFAULT_FOV, depth=DEFAULT_DEPTH, background=None,
tk=False, window_title='', window_parent=None, mouse=False,
frames_per_second=None, samples=DEFAULT_SAMPLES, use_pygame=False, layer=0):
frames_per_second=None, samples=DEFAULT_SAMPLES, use_pygame=False, layer=0,
display_config=DISPLAY_CONFIG_DEFAULT):
"""
Creates a pi3d Display.
Expand Down Expand Up @@ -441,8 +442,8 @@ def create(x=None, y=None, w=None, h=None, near=None, far=None,
To use pygame for display surface, mouse and keyboard - as per windows
This almost certainly would conflict if attempting to use in combination
with tk=True. Default False
*layer*
Dispmanx layer for Raspberry PI. Default 0
*display_config*
Configuration of display - See pi3d.constants for DISPLAY_CONFIG options
"""
if tk: #NB this happens before Display created so use_pygame will not work on linux
if pi3d.PLATFORM != pi3d.PLATFORM_PI and pi3d.PLATFORM != pi3d.PLATFORM_ANDROID:
Expand Down Expand Up @@ -538,7 +539,7 @@ def update(self):
display.right = x + w
display.bottom = y + h

display.opengl.create_display(x, y, w, h, depth=depth, samples=samples, layer=layer)
display.opengl.create_display(x, y, w, h, depth=depth, samples=samples, layer=layer, display_config=display_config)
if pi3d.PLATFORM == pi3d.PLATFORM_ANDROID:
display.width = display.right = display.max_width = display.opengl.width #not available until after create_display
display.height = display.bottom = display.max_height = display.opengl.height
Expand Down
2 changes: 0 additions & 2 deletions pi3d/Mouse.py
Expand Up @@ -14,8 +14,6 @@

from pi3d.util import Log

LOGGER = Log.logger(__name__)

class _nixMouse(threading.Thread):
"""holds Mouse object, see also (the preferred) events methods"""
BUTTON_1 = 1 << 1
Expand Down
2 changes: 1 addition & 1 deletion pi3d/Shape.py
Expand Up @@ -69,7 +69,7 @@ def __init__(self, camera, light, name, x, y, z,
11 light1 position, direction vector 33 35
12 light1 strength per shade 36 38
13 light1 ambient values 39 41
14 defocus dist, amount (only 2 used) 42 43 # also 2D x, y
14 defocus dist_from, dist_to, amount 42 43 # also 2D x, y
15 defocus frame width, height (only 2 used) 45 46 # also 2D w, h, tot_ht
16 custom data space 48 50
17 custom data space 51 53
Expand Down
9 changes: 5 additions & 4 deletions pi3d/Texture.py
Expand Up @@ -261,6 +261,11 @@ def update_ndarray(self, new_array=None):
for t in [GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER]:
opengles.glTexParameteri(GL_TEXTURE_2D, t, self._get_filter(t))

opengles.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
self.m_repeat)
opengles.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
self.m_repeat)

iformat = self._get_format_from_array(self.image, self.i_format)
opengles.glTexImage2D(GL_TEXTURE_2D, 0, iformat, self.ix, self.iy, 0, iformat,
GL_UNSIGNED_BYTE,
Expand All @@ -269,10 +274,6 @@ def update_ndarray(self, new_array=None):
if self.mipmap:
opengles.glGenerateMipmap(GL_TEXTURE_2D)

opengles.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
self.m_repeat)
opengles.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
self.m_repeat)
if self.free_after_load:
self.image = None
self._loaded = False
Expand Down
1 change: 1 addition & 0 deletions pi3d/__init__.py
Expand Up @@ -8,6 +8,7 @@
"""

from pi3d.constants import *
from pi3d.constants import __version__

from pi3d import Display

Expand Down
16 changes: 12 additions & 4 deletions pi3d/constants/__init__.py
Expand Up @@ -4,15 +4,15 @@
pi3d.constants contains constant values, mainly integers, from OpenGL ES 2.0.
"""

__version__ = '2.10'
__version__ = '2.11'

STARTUP_MESSAGE = """
Pi3D module - version {}s
Copyright (c) Tim Skillman, 2012-2015
Copyright (c) Patrick Gaunt, 2012-2015
Copyright (c) Tom Ritchford, 2012-2015
Copyright (c) Tim Skillman, 2012-2016
Copyright (c) Patrick Gaunt, 2012-2016
Copyright (c) Tom Ritchford, 2012-2016
Updates available from www.github.com/tipam/pi3d
""".format(__version__)
Expand Down Expand Up @@ -45,6 +45,14 @@
# Force pygame if possible
USE_PYGAME = False

#Display
DISPLAY_CONFIG_DEFAULT = 0
DISPLAY_CONFIG_NO_RESIZE = 1
DISPLAY_CONFIG_NO_FRAME = 2
DISPLAY_CONFIG_FULLSCREEN = 4
DISPLAY_CONFIG_MAXIMIZED = 8


# Lastly, load the libraries.
def _load_library(name, dll_type="C"):
"""Try to load a shared library, report an error on failure."""
Expand Down
2 changes: 1 addition & 1 deletion pi3d/shaders/defocus.fs
Expand Up @@ -15,7 +15,7 @@ void main(void) {
}
}
gl_FragColor = texc * 0.04;
gl_FragColor.a = 1.0;
gl_FragColor.a = unif[5][2];
}


22 changes: 18 additions & 4 deletions pi3d/util/DisplayOpenGL.py
Expand Up @@ -12,6 +12,7 @@

if pi3d.USE_PYGAME:
import pygame
from pygame.constants import FULLSCREEN
elif PLATFORM != PLATFORM_PI and PLATFORM != PLATFORM_ANDROID:
from pyxlib import xlib
from pyxlib.x import *
Expand Down Expand Up @@ -43,9 +44,11 @@ def __init__(self):
self.screen = xlib.XDefaultScreenOfDisplay(self.d)
self.width, self.height = xlib.XWidthOfScreen(self.screen), xlib.XHeightOfScreen(self.screen)

def create_display(self, x=0, y=0, w=0, h=0, depth=24, samples=4, layer=0):
def create_display(self, x=0, y=0, w=0, h=0, depth=24, samples=4, layer=0, display_config=DISPLAY_CONFIG_DEFAULT):
self.display = openegl.eglGetDisplay(EGL_DEFAULT_DISPLAY)
assert self.display != EGL_NO_DISPLAY

self.display_config = display_config

r = openegl.eglInitialize(self.display, 0, 0)
#assert r == EGL_FALSE
Expand Down Expand Up @@ -85,7 +88,8 @@ def create_display(self, x=0, y=0, w=0, h=0, depth=24, samples=4, layer=0):
opengles.glDepthMask(1);
opengles.glCullFace(GL_FRONT)
opengles.glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST)
opengles.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
opengles.glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1, GL_ONE_MINUS_SRC_ALPHA)

# Switches off alpha blending problem with desktop - is there a bug in the
# driver?
Expand Down Expand Up @@ -131,11 +135,21 @@ def create_surface(self, x=0, y=0, w=0, h=0, layer=0):

elif pi3d.USE_PYGAME:
import pygame
flags = pygame.RESIZABLE | pygame.OPENGL
flags = pygame.OPENGL
wsize = (w, h)
if w == self.width and h == self.height: # i.e. full screen
flags = pygame.FULLSCREEN | pygame.OPENGL | pygame.NOFRAME
flags = pygame.FULLSCREEN | pygame.OPENGL
wsize = (0, 0)
if self.display_config & DISPLAY_CONFIG_NO_RESIZE:
flags |= pygame.RESIZABLE
if self.display_config & DISPLAY_CONFIG_NO_FRAME:
flags |= pygame.NOFRAME
if self.display_config & DISPLAY_CONFIG_FULLSCREEN:
flags |= pygame.FULLSCREEN
elif self.display_config & DISPLAY_CONFIG_MAXIMIZED:
flags |= pygame.FULLSCREEN
wsize = (0, 0)

self.width, self.height = w, h
self.d = pygame.display.set_mode(wsize, flags)
self.window = pygame.display.get_wm_info()["window"]
Expand Down
27 changes: 15 additions & 12 deletions pi3d/util/Screenshot.py
@@ -1,32 +1,35 @@
from __future__ import absolute_import, division, print_function, unicode_literals

import ctypes
import numpy as np
from PIL import Image

from pi3d.constants import *
from pi3d.util import Log

LOGGER = Log.logger(__name__)

def screenshot(filestring):
def screenshot(filestring=None):
"""
Save whatever's in the display to a file.
Will save whatever has been rendered since the last call to Display.clear().
The file will be saved in the top-level directory if you don't add a path
The file will be saved in the same directory as the app if you don't add a path
to it!
If this function is called without any argument then it will not save to
file and will return a numpy array of the screen. The array and file, if
saved, will have the alpha values removed.
"""

from pi3d.Display import Display
LOGGER.info('Taking screenshot of "%s"', filestring)

w, h = Display.INSTANCE.width, Display.INSTANCE.height
size = h * w * 4
img = (ctypes.c_char * size)()
opengles.glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ctypes.byref(img))

im = Image.frombuffer('RGBA', (w, h), img, 'raw', 'RGBA', 0, 1)
im = im.transpose(Image.FLIP_TOP_BOTTOM)
im.save(filestring)
img = np.zeros((h, w, 4), dtype=np.uint8)
opengles.glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte)))
img = img[::-1,:,:3].copy()
if filestring is None:
return img

im = Image.frombuffer('RGB', (w, h), img, 'raw', 'RGB', 0, 1)
im.save(filestring, quality=90)

0 comments on commit 7bbc073

Please sign in to comment.