[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
|
||||
## \[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)
|
||||
- WFC
|
||||
- plot WFC hitbox (x-z plot and x/z-y plot) with matplotlib toolbar
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[metadata]
|
||||
name = supSMSTAS
|
||||
version = 0.0.1
|
||||
version = 0.0.1.1
|
||||
author = sup39
|
||||
author_email = sms@sup39.dev
|
||||
description = A tool to support Super Mario Sunshine Tool Assisted Speedrun/Superplay
|
||||
|
@ -23,9 +23,9 @@ packages = find_namespace:
|
|||
include_package_data = True
|
||||
python_requires = >=3.8
|
||||
install_requires =
|
||||
sup-dolphin-memory-lib ~= 0.1.0
|
||||
matplotlib ~= 3.5
|
||||
PyQt5 ~= 5.15
|
||||
sup-dolphin-memory-lib >= 0.1.1
|
||||
matplotlib >= 3.5
|
||||
PyQt5 >= 5.15
|
||||
|
||||
[options.packages.find]
|
||||
where = src
|
||||
|
|
|
@ -108,7 +108,7 @@ class WFCWidget(QWidget):
|
|||
self.showMario = Qt.Checked
|
||||
self.airborne = Qt.Checked
|
||||
self.yoshi = 0
|
||||
self.fps = 4
|
||||
self.fps = 8
|
||||
self.updating = False
|
||||
self.invertX = 0
|
||||
self.invertZ = 0
|
||||
|
@ -222,9 +222,9 @@ class WFCWidget(QWidget):
|
|||
pos = array(pos)
|
||||
x, y, z = pos
|
||||
# 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
|
||||
xLimit, zLimit, xBlockCount, ptrStCLR = colInfo
|
||||
xLimit, zLimit, xBlockCount, ptrStCLR, ptrDyCLR = colInfo
|
||||
## TBGCheckListRoot[zBlockCount][xBlockCount]
|
||||
colOff = int((z+zLimit)//1024*xBlockCount + (x+xLimit)//1024)*36
|
||||
## root->ground(12*2).next(4)
|
||||
|
@ -236,12 +236,14 @@ class WFCWidget(QWidget):
|
|||
|
||||
t0 = time.time()
|
||||
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)
|
||||
]
|
||||
hitboxs = [
|
||||
# ceiling
|
||||
([
|
||||
#(c, array((0, -1, 0)))
|
||||
(makeRoof(tri, 82 if airborne else 2), array([0, -1, 0]))
|
||||
|
@ -285,6 +287,7 @@ class WFCWidget(QWidget):
|
|||
(pnXZ, axesXZ),
|
||||
]):
|
||||
ax.patches.clear()
|
||||
ax.collections.clear()
|
||||
make_geo_plot(ax, hitboxs, pos, pn, axes)
|
||||
if self.showMario:
|
||||
ax.add_patch(patches.Circle(pos[axes], 25, fc='red'))
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
import numpy as np
|
||||
from numpy import array
|
||||
from .shape import Polyhedron
|
||||
import matplotlib.patches as patches
|
||||
from matplotlib.collections import PolyCollection
|
||||
|
||||
class Surface:
|
||||
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):
|
||||
# paras
|
||||
arrowWidthBase = 60
|
||||
arrowWidthMul = 0.2
|
||||
arrowLenMax = 80
|
||||
arrowWidthBase = 70
|
||||
arrowWidthMul = 0.5
|
||||
arrowLenMax = 200 #80
|
||||
arrowLenTher = 200
|
||||
arrowLenMul1 = 0.7
|
||||
arrowLenMul2 = 0.35
|
||||
arrowHeadLenMul = 0.3
|
||||
arrowLenMul2off = 0.025
|
||||
arrowCountMax = 20
|
||||
arrowLenMul2off = 0.1 #0.025
|
||||
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
|
||||
patches = []
|
||||
for polys, awmul, alen, facecolor, arcolor in hitboxs:
|
||||
# draw wall hitboxs (draw in reverse order)
|
||||
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]
|
||||
if len(verts) == 0: continue
|
||||
# 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
|
||||
n = n*(1, 0, 1) # no y arrow
|
||||
n = n[axes]
|
||||
|
@ -147,27 +158,34 @@ def make_geo_plot(ax, hitboxs, p0, pn, axes):
|
|||
ncts = nbss.mean(axis=0)
|
||||
nrgs = np.abs(np.diff(nbss, axis=0)[0])
|
||||
# add arrow
|
||||
maty = array([-n[1], n[0]])*arrowWidth
|
||||
for p, nrg in zip(
|
||||
C+np.matmul(np.column_stack([ncts, ls]), B),
|
||||
nrgs,
|
||||
):
|
||||
if nrg > arrowLenTher:
|
||||
nrg = min(arrowLenMax, nrg*arrowLenMul2)
|
||||
dn = n * nrg
|
||||
offs = [-arrowLenMul2off, 1+arrowLenMul2off]
|
||||
else:
|
||||
nrg = min(arrowLenMax, nrg*arrowLenMul1)
|
||||
dn = n * nrg
|
||||
offs = [0.5]
|
||||
arrowHeadLen = nrg*arrowHeadLenMul
|
||||
dn = n * nrg
|
||||
# add patches
|
||||
verts0 = np.matmul(arrowVerts, [n*nrg, maty])
|
||||
for off in offs:
|
||||
ax.arrow(
|
||||
*(p-dn*off), *dn,
|
||||
width=arrowWidth, #min(arrowWidth, nrg*0.15),
|
||||
head_length=arrowHeadLen,
|
||||
length_includes_head=True,
|
||||
color=arcolor,
|
||||
)
|
||||
patches.append((
|
||||
p-dn*off+verts0,
|
||||
arcolor, # fc
|
||||
arcolor, # ec
|
||||
))
|
||||
|
||||
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_ylabel('xyz'[axes[1]])
|
||||
|
|
Loading…
Reference in a new issue