e41a4f85e9
This directory contained a mix of both c/cython source code, scripts, and build information. Now, source is in src, scripts are in scripts, and setup.py is in the root.
347 lines
7.7 KiB
Python
347 lines
7.7 KiB
Python
from __future__ import print_function, unicode_literals
|
|
from sympy import symbols, Matrix, pi, cos, sin, simplify
|
|
import io
|
|
|
|
matrix_names = [
|
|
"xdx",
|
|
"xdy",
|
|
"xdz",
|
|
"xdw",
|
|
|
|
"ydx",
|
|
"ydy",
|
|
"ydz",
|
|
"ydw",
|
|
|
|
"zdx",
|
|
"zdy",
|
|
"zdz",
|
|
"zdw",
|
|
|
|
"wdx",
|
|
"wdy",
|
|
"wdz",
|
|
"wdw",
|
|
]
|
|
|
|
|
|
def prefixed_matrix(prefix):
|
|
"""
|
|
Returns a matrix where each entry is of the for prefix___name.
|
|
"""
|
|
|
|
return Matrix(4, 4, [ symbols(prefix + "___" + i) for i in matrix_names ])
|
|
|
|
###############################################################################
|
|
|
|
|
|
generators = [ ]
|
|
|
|
|
|
class Generator(object):
|
|
|
|
def __init__(self, name, docs):
|
|
|
|
self.pyd_f = io.StringIO()
|
|
self.pyx_f = io.StringIO()
|
|
|
|
self.f = io.StringIO()
|
|
|
|
self.name = name
|
|
self.docs = docs
|
|
|
|
generators.append(self)
|
|
|
|
self.first_let = True
|
|
|
|
def parameters(self, params):
|
|
|
|
# PYD.
|
|
print(" @staticmethod", file=self.pyd_f)
|
|
print(" cdef Matrix c{}({})".format(
|
|
self.name,
|
|
", ".join("float " + i for i in params.split())), file=self.pyd_f)
|
|
|
|
# PYX.
|
|
|
|
print(" @staticmethod", file=self.pyx_f)
|
|
print(" cdef Matrix c{}({}):".format(
|
|
self.name,
|
|
", ".join("float " + i for i in params.split())), file=self.pyx_f)
|
|
print(" return {}_matrix({})".format(
|
|
self.name, ", ".join(params.split())), file=self.pyx_f)
|
|
|
|
print(file=self.pyx_f)
|
|
|
|
print(" @staticmethod", file=self.pyx_f)
|
|
print(" def {}({}):".format(
|
|
self.name,
|
|
", ".join(params.split())), file=self.pyx_f)
|
|
|
|
if self.docs:
|
|
print(' """' + self.docs.replace("\n", "\n ") + '"""', file=self.pyx_f)
|
|
|
|
print(" return {}_matrix({})".format(
|
|
self.name, ", ".join(params.split())), file=self.pyx_f)
|
|
|
|
# PXI.
|
|
|
|
print(file=self.f)
|
|
print(file=self.f)
|
|
|
|
print("cpdef Matrix {}_matrix({}):".format(
|
|
self.name,
|
|
", ".join("float " + i for i in params.split())), file=self.f)
|
|
|
|
if params.split():
|
|
return symbols(params)
|
|
|
|
def let(self, name, value):
|
|
|
|
if self.first_let:
|
|
print(file=self.f)
|
|
self.first_let = False
|
|
|
|
value = simplify(value, rational=True)
|
|
|
|
print(" cdef float {} = {}".format(name, str(value)), file=self.f)
|
|
|
|
return symbols(name)
|
|
|
|
def matrix(self, m):
|
|
|
|
print(file=self.f)
|
|
|
|
print(" cdef Matrix rv = Matrix(None)", file=self.f)
|
|
print(file=self.f)
|
|
|
|
for name, value in zip(matrix_names, m):
|
|
if value == 0.0:
|
|
continue
|
|
|
|
print(" rv.{} =".format(name), simplify(value, rational=True), file=self.f)
|
|
|
|
print(file=self.f)
|
|
print(" return rv", file=self.f)
|
|
|
|
|
|
def generate(func):
|
|
g = Generator(func.__name__, func.__doc__)
|
|
func(g)
|
|
return func
|
|
|
|
|
|
def write(fn):
|
|
|
|
with open(fn, "w") as f:
|
|
for i in generators:
|
|
f.write(i.f.getvalue())
|
|
|
|
print("pxd ---------------------------------")
|
|
|
|
for i in generators:
|
|
print(i.pyd_f.getvalue())
|
|
|
|
print("pyx ---------------------------------")
|
|
|
|
for i in generators:
|
|
print(i.pyx_f.getvalue())
|
|
|
|
|
|
@generate
|
|
def identity(g):
|
|
"""
|
|
Returns an identity matrix.
|
|
"""
|
|
|
|
g.parameters("")
|
|
|
|
g.matrix(Matrix(4, 4, [
|
|
1.0, 0.0, 0.0, 0.0,
|
|
0.0, 1.0, 0.0, 0.0,
|
|
0.0, 0.0, 1.0, 0.0,
|
|
0.0, 0.0, 0.0, 1.0,
|
|
]))
|
|
|
|
|
|
@generate
|
|
def offset(g):
|
|
"""
|
|
Returns a matrix that offsets the vertex by a fixed amount.
|
|
"""
|
|
|
|
x, y, z = g.parameters("x y z")
|
|
|
|
g.matrix(Matrix(4, 4, [
|
|
1.0, 0.0, 0.0, x,
|
|
0.0, 1.0, 0.0, y,
|
|
0.0, 0.0, 1.0, z,
|
|
0.0, 0.0, 0.0, 1.0,
|
|
]))
|
|
|
|
|
|
@generate
|
|
def rotate(g):
|
|
"""
|
|
Returns a matrix that rotates the displayable around the
|
|
origin.
|
|
|
|
`x`, `y`, `x`
|
|
The amount to rotate around the origin, in degrees.
|
|
|
|
The rotations are applied in order:
|
|
|
|
* A clockwise rotation by `x` degrees in the Y/Z plane.
|
|
* A clockwise rotation by `y` degrees in the Z/X plane.
|
|
* A clockwise rotation by `z` degrees in the X/Y plane.
|
|
"""
|
|
|
|
x, y, z = g.parameters("x y z")
|
|
|
|
sinx = g.let("sinx", sin(x * pi / 180.0))
|
|
cosx = g.let("cosx", cos(x * pi / 180.0))
|
|
|
|
siny = g.let("siny", sin(y * pi / 180.0))
|
|
cosy = g.let("cosy", cos(y * pi / 180.0))
|
|
|
|
sinz = g.let("sinz", sin(z * pi / 180.0))
|
|
cosz = g.let("cosz", cos(z * pi / 180.0))
|
|
|
|
rx = Matrix(4, 4, [
|
|
1, 0, 0, 0,
|
|
0, cosx, -sinx, 0,
|
|
0, sinx, cosx, 0,
|
|
0, 0, 0, 1 ])
|
|
|
|
ry = Matrix(4, 4, [
|
|
cosy, 0, siny, 0,
|
|
0, 1, 0, 0,
|
|
-siny, 0, cosy, 0,
|
|
0, 0, 0, 1])
|
|
|
|
rz = Matrix(4, 4, [
|
|
cosz, -sinz, 0, 0,
|
|
sinz, cosz, 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1, ])
|
|
|
|
g.matrix(rz * ry * rx)
|
|
|
|
|
|
@generate
|
|
def scale(g):
|
|
"""
|
|
Returns a matrix that scales the displayable.
|
|
|
|
`x`, `y`, `z`
|
|
The factor to scale each axis by.
|
|
"""
|
|
|
|
x, y, z = g.parameters("x y z")
|
|
|
|
m = Matrix(4, 4, [
|
|
x, 0, 0, 0,
|
|
0, y, 0, 0,
|
|
0, 0, z, 0,
|
|
0, 0, 0, 1 ])
|
|
|
|
g.matrix(m)
|
|
|
|
|
|
@generate
|
|
def perspective(g):
|
|
"""
|
|
Returns the Ren'Py projection matrix. This is a view into a 3d space
|
|
where (0, 0) is the top left corner (`w`/2, `h`/2) is the center, and
|
|
(`w`,`h`) is the bottom right, when the z coordinate is 0.
|
|
|
|
`w`, `h`
|
|
The width and height of the input plane, in pixels.
|
|
|
|
`n`
|
|
The distance of the near plane from the camera.
|
|
|
|
`p`
|
|
The distance of the 1:1 plane from the camera. This is where 1 pixel
|
|
is one coordinate unit.
|
|
|
|
`f`
|
|
The distance of the far plane from the camera.
|
|
"""
|
|
|
|
w, h, n, p, f = g.parameters('w h n p f')
|
|
|
|
offset = Matrix(4, 4, [
|
|
1.0, 0.0, 0.0, -w / 2.0,
|
|
0.0, 1.0, 0.0, -h / 2.0,
|
|
0.0, 0.0, 1.0, -p,
|
|
0.0, 0.0, 0.0, 1.0,
|
|
])
|
|
|
|
projection = Matrix(4, 4, [
|
|
2.0 * p / w, 0.0, 0.0, 0.0,
|
|
0.0, 2.0 * p / h, 0.0, 0.0,
|
|
0.0, 0.0, -(f + n) / (f - n), -2 * f * n / (f - n),
|
|
0.0, 0.0, -1.0, 0.0,
|
|
])
|
|
|
|
reverse_offset = Matrix(4, 4, [
|
|
w / 2.0, 0.0, 0.0, w / 2.0,
|
|
0.0, h / 2.0, 0.0, h / 2.0,
|
|
0.0, 0.0, 1.0, 0.0,
|
|
0.0, 0.0, 0.0, 1.0,
|
|
])
|
|
|
|
g.matrix(reverse_offset * projection * offset)
|
|
|
|
|
|
@generate
|
|
def screen_projection(g):
|
|
"""
|
|
This generates a matrix that projects the Ren'Py space, where (0, 0) is the
|
|
top left and (`w`, `h`) is the bottom right, into the OpenGL viewport, where
|
|
(-1.0, 1.0) is the top left and (1.0, -1.0) is the bottom.
|
|
|
|
Generates the matrix that projects the Ren'Py screen to the OpenGL screen.
|
|
"""
|
|
|
|
w, h = g.parameters("w h")
|
|
|
|
m = Matrix(4, 4, [
|
|
2.0 / w, 0.0, 0.0, -1.0,
|
|
0.0, -2.0 / h, 0.0, 1.0,
|
|
0.0, 0.0, 1.0, 0.0,
|
|
0.0, 0.0, 0.0, 1.0
|
|
])
|
|
|
|
g.matrix(m)
|
|
|
|
|
|
@generate
|
|
def texture_projection(g):
|
|
"""
|
|
This generates a matrix that project the Ren'Py space, where (0, 0) is the
|
|
top left and (`w`, `h`) is the bottom right, into the OpenGL render-to-texture
|
|
space, where (-1.0, -1.0) is the top left and (1.0, 1.0) is the bottom.
|
|
|
|
Generates the matrix that projects the Ren'Py screen to the OpenGL screen.
|
|
"""
|
|
|
|
w, h = g.parameters("w h")
|
|
|
|
m = Matrix(4, 4, [
|
|
2.0 / w, 0.0, 0.0, -1.0,
|
|
0.0, 2.0 / h, 0.0, -1.0,
|
|
0.0, 0.0, 1.0, 0.0,
|
|
0.0, 0.0, 0.0, 1.0
|
|
])
|
|
|
|
g.matrix(m)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import os
|
|
|
|
RENPY = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
write(os.path.join(RENPY, "renpy", "display", "matrix_functions.pxi"))
|