[v0.0.1.1] improve performance by using PolyCollection

This commit is contained in:
sup39 2022-07-19 06:50:56 +09:00
parent ddde241d2b
commit 15aaecde12
4 changed files with 53 additions and 27 deletions

View file

@ -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

View file

@ -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

View file

@ -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'))

View file

@ -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]])