[v0.0.1.1] improve performance by using PolyCollection
This commit is contained in:
parent
ddde241d2b
commit
15aaecde12
4 changed files with 53 additions and 27 deletions
|
@ -1,4 +1,9 @@
|
||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
## \[v0.0.1.1] improve performance by using PolyCollection (2022/07/19)
|
||||||
|
- WFC
|
||||||
|
- improve process speed of `make_geo_plot()` by using PolyCollection
|
||||||
|
- README
|
||||||
|
- add Japanese version of README
|
||||||
## \[v0.0.1] init (2022/06/26)
|
## \[v0.0.1] init (2022/06/26)
|
||||||
- WFC
|
- WFC
|
||||||
- plot WFC hitbox (x-z plot and x/z-y plot) with matplotlib toolbar
|
- plot WFC hitbox (x-z plot and x/z-y plot) with matplotlib toolbar
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[metadata]
|
[metadata]
|
||||||
name = supSMSTAS
|
name = supSMSTAS
|
||||||
version = 0.0.1
|
version = 0.0.1.1
|
||||||
author = sup39
|
author = sup39
|
||||||
author_email = sms@sup39.dev
|
author_email = sms@sup39.dev
|
||||||
description = A tool to support Super Mario Sunshine Tool Assisted Speedrun/Superplay
|
description = A tool to support Super Mario Sunshine Tool Assisted Speedrun/Superplay
|
||||||
|
@ -23,9 +23,9 @@ packages = find_namespace:
|
||||||
include_package_data = True
|
include_package_data = True
|
||||||
python_requires = >=3.8
|
python_requires = >=3.8
|
||||||
install_requires =
|
install_requires =
|
||||||
sup-dolphin-memory-lib ~= 0.1.0
|
sup-dolphin-memory-lib >= 0.1.1
|
||||||
matplotlib ~= 3.5
|
matplotlib >= 3.5
|
||||||
PyQt5 ~= 5.15
|
PyQt5 >= 5.15
|
||||||
|
|
||||||
[options.packages.find]
|
[options.packages.find]
|
||||||
where = src
|
where = src
|
||||||
|
|
|
@ -108,7 +108,7 @@ class WFCWidget(QWidget):
|
||||||
self.showMario = Qt.Checked
|
self.showMario = Qt.Checked
|
||||||
self.airborne = Qt.Checked
|
self.airborne = Qt.Checked
|
||||||
self.yoshi = 0
|
self.yoshi = 0
|
||||||
self.fps = 4
|
self.fps = 8
|
||||||
self.updating = False
|
self.updating = False
|
||||||
self.invertX = 0
|
self.invertX = 0
|
||||||
self.invertZ = 0
|
self.invertZ = 0
|
||||||
|
@ -222,9 +222,9 @@ class WFCWidget(QWidget):
|
||||||
pos = array(pos)
|
pos = array(pos)
|
||||||
x, y, z = pos
|
x, y, z = pos
|
||||||
# get collision data (static collision)
|
# get collision data (static collision)
|
||||||
colInfo = d.read_struct(('gpMap', 0x10, 0), '>ffI4x4xI')
|
colInfo = d.read_struct(('gpMap', 0x10, 0), '>ffI4x4xII')
|
||||||
if colInfo is None: return
|
if colInfo is None: return
|
||||||
xLimit, zLimit, xBlockCount, ptrStCLR = colInfo
|
xLimit, zLimit, xBlockCount, ptrStCLR, ptrDyCLR = colInfo
|
||||||
## TBGCheckListRoot[zBlockCount][xBlockCount]
|
## TBGCheckListRoot[zBlockCount][xBlockCount]
|
||||||
colOff = int((z+zLimit)//1024*xBlockCount + (x+xLimit)//1024)*36
|
colOff = int((z+zLimit)//1024*xBlockCount + (x+xLimit)//1024)*36
|
||||||
## root->ground(12*2).next(4)
|
## root->ground(12*2).next(4)
|
||||||
|
@ -236,12 +236,14 @@ class WFCWidget(QWidget):
|
||||||
|
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
stGnds, stRoofs, stWalls = [
|
stGnds, stRoofs, stWalls = [
|
||||||
#data1 = [ # TODO dynamic data
|
[
|
||||||
d.checkList2list(d.read_uint32(ptrStCLR+colOff+4+12*j))
|
tri
|
||||||
|
for ptrCLR in [ptrStCLR, ptrDyCLR]
|
||||||
|
for tri in d.checkList2list(d.read_uint32(ptrCLR+colOff+4+12*j))
|
||||||
|
]
|
||||||
for j in range(3)
|
for j in range(3)
|
||||||
]
|
]
|
||||||
hitboxs = [
|
hitboxs = [
|
||||||
# ceiling
|
|
||||||
([
|
([
|
||||||
#(c, array((0, -1, 0)))
|
#(c, array((0, -1, 0)))
|
||||||
(makeRoof(tri, 82 if airborne else 2), array([0, -1, 0]))
|
(makeRoof(tri, 82 if airborne else 2), array([0, -1, 0]))
|
||||||
|
@ -285,6 +287,7 @@ class WFCWidget(QWidget):
|
||||||
(pnXZ, axesXZ),
|
(pnXZ, axesXZ),
|
||||||
]):
|
]):
|
||||||
ax.patches.clear()
|
ax.patches.clear()
|
||||||
|
ax.collections.clear()
|
||||||
make_geo_plot(ax, hitboxs, pos, pn, axes)
|
make_geo_plot(ax, hitboxs, pos, pn, axes)
|
||||||
if self.showMario:
|
if self.showMario:
|
||||||
ax.add_patch(patches.Circle(pos[axes], 25, fc='red'))
|
ax.add_patch(patches.Circle(pos[axes], 25, fc='red'))
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from numpy import array
|
from numpy import array
|
||||||
from .shape import Polyhedron
|
from .shape import Polyhedron
|
||||||
import matplotlib.patches as patches
|
from matplotlib.collections import PolyCollection
|
||||||
|
|
||||||
class Surface:
|
class Surface:
|
||||||
def __init__(self, surtype, surpara, trntype, unk7, verts, vidxs=None, n=None, c=None):
|
def __init__(self, surtype, surpara, trntype, unk7, verts, vidxs=None, n=None, c=None):
|
||||||
|
@ -81,17 +81,28 @@ def makeWall(tri, rW=50, dy=30):
|
||||||
|
|
||||||
def make_geo_plot(ax, hitboxs, p0, pn, axes):
|
def make_geo_plot(ax, hitboxs, p0, pn, axes):
|
||||||
# paras
|
# paras
|
||||||
arrowWidthBase = 60
|
arrowWidthBase = 70
|
||||||
arrowWidthMul = 0.2
|
arrowWidthMul = 0.5
|
||||||
arrowLenMax = 80
|
arrowLenMax = 200 #80
|
||||||
arrowLenTher = 200
|
arrowLenTher = 200
|
||||||
arrowLenMul1 = 0.7
|
arrowLenMul1 = 0.7
|
||||||
arrowLenMul2 = 0.35
|
arrowLenMul2 = 0.35
|
||||||
arrowHeadLenMul = 0.3
|
arrowHeadLenMul = 0.3
|
||||||
arrowLenMul2off = 0.025
|
arrowLenMul2off = 0.1 #0.025
|
||||||
arrowCountMax = 20
|
arrowCountMax = 100
|
||||||
|
aw, ah = 0.2, 0.6 # width, height of bottom rect
|
||||||
|
arrowVerts = array([
|
||||||
|
[0.0, aw],
|
||||||
|
[ ah, aw],
|
||||||
|
[ ah, 0.5],
|
||||||
|
[1.0, 0.0],
|
||||||
|
[ ah, -.5],
|
||||||
|
[ ah, -aw],
|
||||||
|
[0.0, -aw],
|
||||||
|
])
|
||||||
|
|
||||||
# plot
|
# plot
|
||||||
|
patches = []
|
||||||
for polys, awmul, alen, facecolor, arcolor in hitboxs:
|
for polys, awmul, alen, facecolor, arcolor in hitboxs:
|
||||||
# draw wall hitboxs (draw in reverse order)
|
# draw wall hitboxs (draw in reverse order)
|
||||||
for poly, n in polys[::-1]:
|
for poly, n in polys[::-1]:
|
||||||
|
@ -99,7 +110,7 @@ def make_geo_plot(ax, hitboxs, p0, pn, axes):
|
||||||
verts = poly.slicePlane(p0, pn)[:,axes]
|
verts = poly.slicePlane(p0, pn)[:,axes]
|
||||||
if len(verts) == 0: continue
|
if len(verts) == 0: continue
|
||||||
# plot hitbox area
|
# plot hitbox area
|
||||||
ax.add_patch(patches.Polygon(verts, fc=facecolor, ec='black', lw=1))
|
patches.append((verts, facecolor, 'black')) # (verts, fc, ec)
|
||||||
# plot arrow
|
# plot arrow
|
||||||
n = n*(1, 0, 1) # no y arrow
|
n = n*(1, 0, 1) # no y arrow
|
||||||
n = n[axes]
|
n = n[axes]
|
||||||
|
@ -147,27 +158,34 @@ def make_geo_plot(ax, hitboxs, p0, pn, axes):
|
||||||
ncts = nbss.mean(axis=0)
|
ncts = nbss.mean(axis=0)
|
||||||
nrgs = np.abs(np.diff(nbss, axis=0)[0])
|
nrgs = np.abs(np.diff(nbss, axis=0)[0])
|
||||||
# add arrow
|
# add arrow
|
||||||
|
maty = array([-n[1], n[0]])*arrowWidth
|
||||||
for p, nrg in zip(
|
for p, nrg in zip(
|
||||||
C+np.matmul(np.column_stack([ncts, ls]), B),
|
C+np.matmul(np.column_stack([ncts, ls]), B),
|
||||||
nrgs,
|
nrgs,
|
||||||
):
|
):
|
||||||
if nrg > arrowLenTher:
|
if nrg > arrowLenTher:
|
||||||
nrg = min(arrowLenMax, nrg*arrowLenMul2)
|
nrg = min(arrowLenMax, nrg*arrowLenMul2)
|
||||||
dn = n * nrg
|
|
||||||
offs = [-arrowLenMul2off, 1+arrowLenMul2off]
|
offs = [-arrowLenMul2off, 1+arrowLenMul2off]
|
||||||
else:
|
else:
|
||||||
nrg = min(arrowLenMax, nrg*arrowLenMul1)
|
nrg = min(arrowLenMax, nrg*arrowLenMul1)
|
||||||
dn = n * nrg
|
|
||||||
offs = [0.5]
|
offs = [0.5]
|
||||||
arrowHeadLen = nrg*arrowHeadLenMul
|
dn = n * nrg
|
||||||
|
# add patches
|
||||||
|
verts0 = np.matmul(arrowVerts, [n*nrg, maty])
|
||||||
for off in offs:
|
for off in offs:
|
||||||
ax.arrow(
|
patches.append((
|
||||||
*(p-dn*off), *dn,
|
p-dn*off+verts0,
|
||||||
width=arrowWidth, #min(arrowWidth, nrg*0.15),
|
arcolor, # fc
|
||||||
head_length=arrowHeadLen,
|
arcolor, # ec
|
||||||
length_includes_head=True,
|
))
|
||||||
color=arcolor,
|
|
||||||
)
|
if len(patches):
|
||||||
|
ax.add_collection(PolyCollection(
|
||||||
|
**{
|
||||||
|
k: v
|
||||||
|
for k, v in zip(('verts', 'facecolors', 'edgecolors'), zip(*patches))
|
||||||
|
},
|
||||||
|
))
|
||||||
|
|
||||||
ax.set_xlabel('xyz'[axes[0]])
|
ax.set_xlabel('xyz'[axes[0]])
|
||||||
ax.set_ylabel('xyz'[axes[1]])
|
ax.set_ylabel('xyz'[axes[1]])
|
||||||
|
|
Loading…
Reference in a new issue