jsuarez/extra/embyr_deprecated/embyr/oldnewapi.py (233 lines of code) (raw):
from pdb import set_trace as T
import numpy as np
import os
import kivy3
from kivy.app import App
from kivy3 import Scene, Renderer, PerspectiveCamera
from kivy3.loaders import OBJLoader, OBJMTLLoader
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.config import Config
from kivy.graphics import opengl as gl
from kivy.graphics import Mesh as KivyMesh
from kivy3.core.object3d import Object3D
from kivy3.materials import Material
from kivy.core.image import Image
from copy import deepcopy
from embyr import Application
import pywavefront as pywave
import pytmx
import enums
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
def loadTiled(fPath):
import pytmx
tm = pytmx.TiledMap(fPath)
assert len(tm.layers) == 1
layer = tm.layers[0]
W, H = layer.width, layer.height
tilemap = np.zeros((H, W), dtype=object)
for w, h, dat in layer.tiles():
f = dat[0]
tex = f.split('/')[-1].split('.')[0]
tilemap[h, w] = tex
return tilemap
class Pan(Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.x, self.y, self.xVol, self.yVol = 0, 0, 0, 0
self.zoom, self.zoomVol = 1, 0
def on_touch_down(self, touch):
self.xStart, self.yStart = touch.pos
def on_touch_up(self, touch):
if touch.button == 'left':
self.xVol, self.yVol= 0, 0
xEnd, yEnd = touch.pos
self.x += xEnd - self.xStart
self.y += yEnd - self.yStart
def on_touch_move(self, touch):
if touch.button == 'left':
xEnd, yEnd = touch.pos
self.xVol = xEnd - self.xStart
self.yVol = yEnd - self.yStart
class Rotate(Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.x, self.y, self.xVol, self.yVol = 0, 0, 0, 0
self.zoom, self.zoomVol = 1, 0
def on_touch_down(self, touch):
self.xStart, self.yStart = touch.pos
def on_touch_up(self, touch):
if touch.button == 'right':
self.xVol, self.yVol= 0, 0
xEnd, yEnd = touch.pos
self.x += xEnd - self.xStart
self.y += yEnd - self.yStart
bound = 3.14159*250
self.y = int(np.clip(self.y, -bound, 0))
def on_touch_move(self, touch):
if touch.button == 'right':
xEnd, yEnd = touch.pos
self.xVol = xEnd - self.xStart
self.yVol = yEnd - self.yStart
class Zoom(Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.zoom, self.delta = 1, 0.2
def clipZoom(zoom, exprange=2):
return np.clip(zoom, 0.5**exprange, 2**exprange)
def on_touch_down(self, touch):
print(touch.button)
if touch.button == 'scrollup':
self.zoom = Zoom.clipZoom(self.zoom + self.delta)
if touch.button == 'scrolldown':
self.zoom = Zoom.clipZoom(self.zoom - self.delta)
class MyApp(Application):
def __init__(self, size):
super().__init__(size)
self.title = 'Projekt: Godsword'
self.pan = Pan()
self.rotate = Rotate()
self.zoom = Zoom()
self.loader = OBJMTLLoader()
self.blocks = dict((mat.value.tex, mat.value)
for mat in enums.Material)
self.vec = np.array([0, 0, 1])
self.t = 0
'''
super(Mesh, self).__init__(**kw)
self.geometry = geometry
self.material = material
self.mtl = self.material # shortcut for material property
self.vertex_format = kw.pop("vertex_format", DEFAULT_VERTEX_FORMAT)
self.create_mesh()
'''
def cube(self, tile):
DEFAULT_VERTEX_FORMAT = [
(b'v_tc0', 2, 'float'),
(b'v_normal', 3, 'float'),
(b'v_pos', 3, 'float')]
obj = self.blocks[tile].obj
T()
obj = pywave.Wavefront('tex/block.obj', collect_faces=True)
material = obj.materials['grass']
cube = obj.meshes['Cube']
vertices = obj.vertices
faces = cube.faces
grass = obj.materials['grass']
dirt = obj.materials['dirt']
vertices = grass.vertices + dirt.vertices
#indices = np.array(faces).ravel().tolist()
indices = np.arange(36).astype(int).tolist()
#vertices = np.array(vertices).ravel().tolist()
tex = Image('tex/grass.png').texture
mat = Material(tex)
kw = {"vertices": vertices, "indices": indices,
"fmt": DEFAULT_VERTEX_FORMAT,
"mode": "triangles",
'texture':tex
}
#if self.material.map:
# kw["texture"] = self.material.map
mesh = KivyMesh(**kw)
class Meshy(Object3D):
def __init__(self, mesh, material):
super().__init__()
self._mesh = mesh
self.material = material
self.mtl = material
self.vertex_format = DEFAULT_VERTEX_FORMAT
cube = Meshy(mesh, tex)
#cube.material = orig.material
#cube.geometry = orig.geometry
orig._mesh = cube._mesh
orig.material = mat
cube = orig
#cube = kivy3.Mesh([], material)
if tile == 'lava':
cube.pos.y = -0.5
elif tile == 'stone':
cube.pos.y = 1
elif tile == 'grass':
pass
elif tile == 'forest':
pass
elif tile == 'water':
cube.pos.y = -0.33
#cube.material.color = 0., .7, 0. # green
#cube.material.diffuse = 0., .7, 0. # green
return cube
def makeMap(self):
tiles = loadTiled('../Projekt-Godsword/resource/maps/map1/map.tmx')
n, sz = tiles.shape[0], 1
for i in range(n):
for j in range(n):
tile = tiles[i, j]
cube = self.cube(tile)
self.scene.add(cube)
#NEVER set cube.pos directly.
#It won't do anything
cube.pos.x = i - n//2 + sz//2
cube.pos.z = j - n//2 + sz//2
def glSetup(self):
#gl.glEnable(gl.GL_CULL_FACE)
#gl.glCullFace(gl.GL_BACK)
pass
def build(self):
camera = PerspectiveCamera(30, 1, 1, 1000)
self.renderer = Renderer()
self.scene = Scene()
root = FloatLayout()
obj = self.loader.load('tex/nn.obj', 'tex/nn.mtl')
self.scene.add(obj)
obj.pos.y = 1
self.makeMap()
self.renderer.render(self.scene, camera)
self.renderer.camera.look_at(0, 0, 0)
root.add_widget(self.renderer)
root.add_widget(self.pan)
root.add_widget(self.rotate)
root.add_widget(self.zoom)
self.renderer.bind(size=self._adjust_aspect)
self.loop(self.update)
return root
def update(self, t):
print(1/t)
self.t += t
rad = 80
sz = 500
pi = 3.14159265
r = self.rotate
x = r.x + r.xVol
y = r.y + r.yVol
x = x / sz
y = y / sz
yclip = np.clip(y, -pi/2, 0)
xz_x = np.cos(x)
xz_z = np.sin(x)
yz_y = np.cos(yclip)
yz_z = np.sin(yclip)
xz = np.array([
[xz_x, 0, -xz_z],
[0 , 1, 0 ],
[xz_z, 0, xz_x]])
yz = np.array([
[1, 0, 0 ],
[0, yz_y, -yz_z],
[0, yz_z, yz_y]])
#Find cylindrical xz plane rotation
rot_xz = rad*np.dot(xz, self.vec)
xx, _, zz = rot_xz
xz_vec = np.array([xx, 0, zz])
#Find spherical yz plane rotation
_, yy, zn = np.dot(yz, self.vec)
xz_norm = zn
#For x, z: shrink to position of spherical rotation
#For y: use height from spherical rotation
vec = np.array([xx*xz_norm, -rad*yy, zz*xz_norm])
#Zoom factor
zoom = Zoom.clipZoom(self.zoom.zoom)
vec = vec * zoom
p = self.pan
x = p.x + p.xVol
z = p.y + p.yVol
x = 10*x / sz
z = -10*z / sz
#Horizontal component
unit_y = np.array([0, 1, 0])
xx, _, zz = np.cross(rot_xz, unit_y)
norm = np.sqrt(xx**2 + zz**2)
xh, zh = x*xx/norm, x*zz/norm
#Depth component
xx, _, zz = -xz_vec
norm = np.sqrt(xx**2 + zz**2)
xd, zd = z*xx/norm, z*zz/norm
xx, yy, zz = vec
vec = np.array([xx+xh+xd, yy, zz+zh+zd])
self.renderer.camera.look_at([-xh-xd, 0, -zh-zd])
self.renderer.camera.pos = vec.tolist()
def _adjust_aspect(self, inst, val):
rsize = self.renderer.size
aspect = rsize[0] / float(rsize[1])
self.renderer.camera.aspect = aspect
if __name__ == '__main__':
MyApp((2048, 1024)).run()