add some new ContextInstruction usefull for 3D rendering:

- PushState, ChangeState, PopState (like PushMatrix etc. but for any state/uniform)
  - ScaleXYZ (non uniform scale on all 3 axis)
  - UpdateNormalMatrix (set uniform 'normal_mat' based on current modelview_mat)
  - ApplyContextMatrix (multiply a current matrix by one from another matrix stack in context)
  - LoadIdentity (loads identity matrix)
  - all Matrixinstructions now als have 'stack' property to allow using multiple different kind of matrices.
This commit is contained in:
Thomas Hansen 2012-12-18 17:08:57 -06:00
parent e4c15b0443
commit 83ea2e07de
3 changed files with 226 additions and 16 deletions

View File

@ -77,8 +77,9 @@ from kivy.graphics.instructions import Callback, Canvas, CanvasBase, \
ContextInstruction, Instruction, InstructionGroup, RenderContext, \
VertexInstruction
from kivy.graphics.context_instructions import BindTexture, Color, \
MatrixInstruction, PopMatrix, PushMatrix, Rotate, Scale, \
Translate, gl_init_resources
PushState, ChangeState, PopState, MatrixInstruction, ApplyContextMatrix, \
PopMatrix, PushMatrix, Rotate, Scale, ScaleXYZ, Translate, LoadIdentity, \
UpdateNormalMatrix, gl_init_resources
from kivy.graphics.vertex_instructions import Bezier, BorderImage, Ellipse, \
GraphicException, Line, Mesh, Point, Quad, Rectangle, Triangle
from kivy.graphics.stencil_instructions import StencilPop, StencilPush, \
@ -98,5 +99,7 @@ __all__ = (Bezier.__name__, BindTexture.__name__, BorderImage.__name__,
StencilPush.__name__, StencilUse.__name__, StencilUnUse.__name__,
Translate.__name__, Triangle.__name__, VertexInstruction.__name__,
ClearColor.__name__, ClearBuffers.__name__,
gl_init_resources.__name__)
gl_init_resources.__name__, PushState.__name__, ChangeState.__name__,
PopState.__name__, ApplyContextMatrix.__name__, ScaleXYZ.__name__,
UpdateNormalMatrix.__name__,LoadIdentity.__name__)

View File

@ -6,6 +6,15 @@ from transformation cimport Matrix
from instructions cimport ContextInstruction
from texture cimport Texture
cdef class PushState(ContextInstruction):
pass
cdef class ChangeState(ContextInstruction):
pass
cdef class PopState(ContextInstruction):
pass
cdef class LineWidth(ContextInstruction):
cdef void apply(self)
@ -18,13 +27,26 @@ cdef class BindTexture(ContextInstruction):
cdef Texture _texture
cdef void apply(self)
cdef class LoadIdentity(ContextInstruction):
pass
cdef class PushMatrix(ContextInstruction):
cdef void apply(self)
cdef class PopMatrix(ContextInstruction):
cdef void apply(self)
cdef class ApplyContextMatrix(ContextInstruction):
cdef object _target_stack
cdef object _source_stack
cdef void apply(self)
cdef class UpdateNormalMatrix(ContextInstruction):
cdef void apply(self)
cdef class MatrixInstruction(ContextInstruction):
cdef object _stack
cdef Matrix _matrix
cdef void apply(self)
@ -34,7 +56,6 @@ cdef class Transform(MatrixInstruction):
cpdef rotate(self, float angle, float ax, float ay, float az)
cpdef scale(self, float s)
cpdef identity(self)
cdef void apply(self)
cdef class Rotate(Transform):
cdef float _angle
@ -45,6 +66,11 @@ cdef class Scale(Transform):
cdef float s
cdef void apply(self)
cdef class ScaleXYZ(Transform):
cdef float _x, _y, _z
cdef void apply(self)
cdef set_scale(self, double x, double y, double z)
cdef class Translate(Transform):
cdef double _x, _y, _z
cdef void apply(self)

View File

@ -100,6 +100,63 @@ cdef tuple hsv_to_rgb(float h, float s, float v):
# Cannot get here
cdef class PushState(ContextInstruction):
'''Instruction that pushes arbitrary states/uniforms on the context
state stack.
'''
def __init__(self, *args, **kwargs):
ContextInstruction.__init__(self, **kwargs)
self.context_push = list(args)
property state:
def __get__(self):
return ','.join(self.context_push)
def __set__(self, value):
self.context_push = value.split(',')
property states:
def __get__(self):
return self.context_push
def __set__(self, value):
self.context_push = list(value)
cdef class ChangeState(ContextInstruction):
'''Instruction that changes the values of arbitrary states/uniforms on the
current render context.
'''
def __init__(self, **kwargs):
ContextInstruction.__init__(self, **kwargs)
self.context_state.update(**kwargs)
property changes:
def __get__(self):
return self.context_state
def __set__(self, value):
self.context_state = dict(value)
cdef class PopState(ContextInstruction):
'''Instruction that pops arbitrary states/uniforms on the context
state stack.
'''
def __init__(self, *args, **kwargs):
ContextInstruction.__init__(self, **kwargs)
self.context_pop = list(args)
property state:
def __get__(self):
return ','.join(self.context_pop)
def __set__(self, value):
self.context_pop = value.split(',')
property states:
def __get__(self):
return self.context_pop
def __set__(self, value):
self.context_pop = list(value)
cdef class Color(ContextInstruction):
'''Instruction to set the color state for any vertices being drawn after it.
All the values passed are between 0 and 1, not 0 and 255.
@ -108,7 +165,7 @@ cdef class Color(ContextInstruction):
from kivy.graphics import Color
# create red color
# create red v
c = Color(1, 0, 0)
# create blue color
c = Color(0, 1, 0)
@ -301,19 +358,75 @@ cdef class BindTexture(ContextInstruction):
cdef double radians(double degrees):
return degrees * (3.14159265 / 180.)
cdef class LoadIdentity(ContextInstruction):
'''Load identity Matrix into the matrix stack sepcified by
the instructions stack property (default='modelview_mat')
'''
def __init__(self, **kwargs):
self.context_state = kwargs.get("stack", "modelview_mat")
property stack:
def __get__(self):
return self.context_state.keys()[0]
def __set__(self, value):
self.context_state = {value: Matrix()}
cdef class PushMatrix(ContextInstruction):
'''PushMatrix on context's matrix stack
'''
def __init__(self, *args, **kwargs):
ContextInstruction.__init__(self, **kwargs)
self.context_push = ['modelview_mat']
self.stack = kwargs.get("stack", "modelview_mat")
property stack:
def __get__(self):
return self.context_push[0]
def __set__(self, value):
value = value or "modelview_mat"
self.context_push = [value]
cdef class PopMatrix(ContextInstruction):
'''Pop Matrix from context's matrix stack onto model view
'''
def __init__(self, *args, **kwargs):
ContextInstruction.__init__(self, **kwargs)
self.context_pop = ['modelview_mat']
self.stack = kwargs.get("stack", "modelview_mat")
property stack:
def __get__(self):
return self.context_push[0]
def __set__(self, value):
value = value or "modelview_mat"
self.context_pop = [value]
cdef class ApplyContextMatrix(ContextInstruction):
'''pre-multiply the matrix at the top of the stack specified by
`target_stack` by the matrix at the top of the 'source_stack'
'''
def __init__(self, **kwargs):
self._target_stack = kwargs.get('target_stack', 'modelview_mat')
self._source_stack = kwargs.get('target_stack', 'modelview_mat')
cdef void apply(self):
cdef RenderContext context = self.get_context()
m = context.get_state(self._target_stack)
m = m.multiply(context.get_state(self._source_stack))
context.set_state(self._target_stack, m)
cdef class UpdateNormalMatrix(ContextInstruction):
'''Update the normal matrix 'normal_mat' based on the current
modelview matrix. will compute 'normal_mat' uniform as:
`inverse( transpose( mat3(mvm) ) )`
'''
cdef void apply(self):
cdef RenderContext context = self.get_context()
mvm = context.get_state('modelview_mat')
context.set_state('normal_mat', mvm.normal_matrix())
cdef class MatrixInstruction(ContextInstruction):
@ -322,6 +435,7 @@ cdef class MatrixInstruction(ContextInstruction):
def __init__(self, *args, **kwargs):
ContextInstruction.__init__(self, **kwargs)
self._stack = kwargs.get("stack", "modelview_mat")
self._matrix = None
cdef void apply(self):
@ -330,8 +444,8 @@ cdef class MatrixInstruction(ContextInstruction):
'''
cdef RenderContext context = self.get_context()
cdef Matrix mvm
mvm = context.get_state('modelview_mat')
context.set_state('modelview_mat', mvm.multiply(self.matrix))
mvm = context.get_state(self._stack)
context.set_state(self._stack, mvm.multiply(self.matrix))
property matrix:
''' Matrix property. Numpy matrix from transformation module
@ -346,10 +460,21 @@ cdef class MatrixInstruction(ContextInstruction):
self._matrix = x
self.flag_update()
property stack:
def __get__(self):
return self._stack
def __set__(self, value):
value = value or "modelview_mat"
self._stack = value
cdef class Transform(MatrixInstruction):
'''Transform class. A matrix instruction class which
has function to modify the transformation matrix
'''
def __init__(self, *args, **kwargs):
MatrixInstruction.__init__(self, **kwargs)
cpdef transform(self, Matrix trans):
'''Multiply the instructions matrix by trans
'''
@ -377,7 +502,6 @@ cdef class Transform(MatrixInstruction):
self.matrix = Matrix()
cdef class Rotate(Transform):
'''Rotate the coordinate space by applying a rotation transformation
on the modelview matrix. You can set the properties of the instructions
@ -387,8 +511,8 @@ cdef class Rotate(Transform):
rot.axis = (0,0,1)
'''
def __init__(self, *args):
Transform.__init__(self)
def __init__(self, *args, **kwargs):
Transform.__init__(self, **kwargs)
if len(args) == 4:
self.set(args[0], args[1], args[2], args[3])
else:
@ -425,9 +549,9 @@ cdef class Rotate(Transform):
cdef class Scale(Transform):
'''Instruction to perform a uniform scale transformation
'''
def __init__(self, *args):
def __init__(self, *args, **kwargs):
cdef double s
Transform.__init__(self)
Transform.__init__(self, **kwargs)
if len(args) == 1:
self.s = s = args[0]
self.matrix = Matrix().scale(s, s, s)
@ -443,13 +567,69 @@ cdef class Scale(Transform):
self.s = s
self.matrix = Matrix().scale(s, s, s)
cdef class ScaleXYZ(Transform):
'''Instruction to create a non uniform scale transformation
'''
def __init__(self, *args, **kwargs):
cdef double x, y, z
Transform.__init__(self, **kwargs)
if len(args) == 3:
x, y, z = args
self.set_scale(x, y, z)
cdef set_scale(self, double x, double y, double z):
self._x = x
self._y = y
self._z = z
self.matrix = Matrix().scale(x, y, z)
property x:
'''Property for getting/setting the scale on X axis
'''
def __get__(self):
return self._x
def __set__(self, double x):
self.set_scale(x, self._y, self._z)
property y:
'''Property for getting/setting the scale on Y axis
'''
def __get__(self):
return self._y
def __set__(self, double y):
self.set_scale(self._x, y, self._z)
property z:
'''Property for getting/setting the scale on Z axis
'''
def __get__(self):
return self._z
def __set__(self, double z):
self.set_scale(self._x, self._y, z)
property xy:
'''2 tuple with scale vector in 2D for x and y axis
'''
def __get__(self):
return self._x, self._y
def __set__(self, c):
self.set_scale(c[0], c[1], self._z)
property xyz:
'''3 tuple scale vector in 3D in x, y, and z axis
'''
def __get__(self):
return self._x, self._y, self._z
def __set__(self, c):
self.set_scale(c[0], c[1], c[2])
cdef class Translate(Transform):
'''Instruction to create a translation of the model view coordinate space
'''
def __init__(self, *args):
def __init__(self, *args, **kwargs):
cdef double x, y, z
Transform.__init__(self)
Transform.__init__(self, **kwargs)
if len(args) == 3:
x, y, z = args
self.set_translate(x, y, z)
@ -500,3 +680,4 @@ cdef class Translate(Transform):
def __set__(self, c):
self.set_translate(c[0], c[1], c[2])