mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-26 00:16:51 +00:00
Apply svdDecompose fixes from 1.19.4-pre4
This commit is contained in:
@@ -396,7 +396,7 @@ function approxGivensQuat(a: number, b: number, c: number): [number, number] {
|
||||
}
|
||||
}
|
||||
|
||||
function qrGivensQuat(a: number, b: number) {
|
||||
function qrGivensQuat(a: number, b: number): [number, number] {
|
||||
const c = Math.hypot(a, b)
|
||||
let d = c > 1e-6 ? b : 0
|
||||
let e = Math.abs(a) + Math.max(c, 1e-6)
|
||||
@@ -407,22 +407,20 @@ function qrGivensQuat(a: number, b: number) {
|
||||
return [d * f, e * f]
|
||||
}
|
||||
|
||||
// modifies the passed mat3
|
||||
// modifies the passed matrix
|
||||
function stepJacobi(m: Matrix3): quat {
|
||||
const n = new Matrix3()
|
||||
const q = quat.create()
|
||||
if (m.m01 * m.m01 + m.m10 * m.m10 > 1e-6) {
|
||||
const [a, b] = approxGivensQuat(m.m00, 0.5 * (m.m01 + m.m10), m.m11)
|
||||
const r = quat.fromValues(0, 0, a, b)
|
||||
const c = b * b - a * a
|
||||
const d = -2 * a * b
|
||||
const e = b * b + a * a
|
||||
quat.mul(q, q, r)
|
||||
const n = new Matrix3()
|
||||
n.m00 = c
|
||||
n.m11 = c
|
||||
n.m01 = -d
|
||||
n.m10 = d
|
||||
n.m22 = e
|
||||
m.mul(n)
|
||||
n.transpose().mul(m)
|
||||
m.copy(n)
|
||||
@@ -434,13 +432,12 @@ function stepJacobi(m: Matrix3): quat {
|
||||
const r = quat.fromValues(0, a, 0, b)
|
||||
const c = b * b - a * a
|
||||
const d = -2 * a * b
|
||||
const e = b * b + a * a
|
||||
quat.mul(q, q, r)
|
||||
const n = new Matrix3()
|
||||
n.m00 = c
|
||||
n.m22 = c
|
||||
n.m02 = d
|
||||
n.m20 = -d
|
||||
n.m11 = e
|
||||
m.mul(n)
|
||||
n.transpose().mul(m)
|
||||
m.copy(n)
|
||||
@@ -450,13 +447,12 @@ function stepJacobi(m: Matrix3): quat {
|
||||
const r = quat.fromValues(a, 0, 0, b)
|
||||
const c = b * b - a * a
|
||||
const d = -2 * a * b
|
||||
const e = b * b + a * a
|
||||
quat.mul(q, q, r)
|
||||
const n = new Matrix3()
|
||||
n.m11 = c
|
||||
n.m22 = c
|
||||
n.m12 = -d
|
||||
n.m21 = d
|
||||
n.m00 = e
|
||||
m.mul(n)
|
||||
n.transpose().mul(m)
|
||||
m.copy(n)
|
||||
@@ -477,12 +473,12 @@ export function svdDecompose(m: Matrix3): [quat, Vector, quat] {
|
||||
quat.normalize(r, r)
|
||||
const p0 = m.clone()
|
||||
.mul(Matrix3.fromQuat(r))
|
||||
let f = 1
|
||||
|
||||
const [a1, b1] = qrGivensQuat(p0.m00, p0.m01)
|
||||
const [a1, b1] = m.m00 < 1e-6
|
||||
? qrGivensQuat(p0.m11, -p0.m10)
|
||||
: qrGivensQuat(p0.m00, p0.m01)
|
||||
const c1 = b1 * b1 - a1 * a1
|
||||
const d1 = -2 * a1 * b1
|
||||
const e1 = b1 * b1 + a1 * a1
|
||||
const s1 = quat.fromValues(0, 0, a1, b1)
|
||||
quat.mul(q, q, s1)
|
||||
const p1 = new Matrix3()
|
||||
@@ -490,16 +486,15 @@ export function svdDecompose(m: Matrix3): [quat, Vector, quat] {
|
||||
p1.m11 = c1
|
||||
p1.m01 = d1
|
||||
p1.m10 = -d1
|
||||
p1.m22 = e1
|
||||
f *= e1
|
||||
p1.mul(p0)
|
||||
|
||||
const pair = qrGivensQuat(p1.m00, p1.m02)
|
||||
const pair = m.m00 < 1e-6
|
||||
? qrGivensQuat(p1.m22, -p1.m20)
|
||||
: qrGivensQuat(p1.m00, p1.m02)
|
||||
const a2 = -pair[0]
|
||||
const b2 = pair[1]
|
||||
const c2 = b2 * b2 - a2 * a2
|
||||
const d2 = -2 * a2 * b2
|
||||
const e2 = b2 * b2 + a2 * a2
|
||||
const s2 = quat.fromValues(0, a2, 0, b2)
|
||||
quat.mul(q, q, s2)
|
||||
const p2 = new Matrix3()
|
||||
@@ -507,14 +502,13 @@ export function svdDecompose(m: Matrix3): [quat, Vector, quat] {
|
||||
p2.m22 = c2
|
||||
p2.m02 = -d2
|
||||
p2.m20 = d2
|
||||
p2.m11 = e2
|
||||
f *= e2
|
||||
p2.mul(p1)
|
||||
|
||||
const [a3, b3] = qrGivensQuat(p2.m11, p2.m12)
|
||||
const [a3, b3] = m.m11 < 1e-6
|
||||
? qrGivensQuat(p2.m22, -p2.m21)
|
||||
: qrGivensQuat(p2.m11, p2.m12)
|
||||
const c3 = b3 * b3 - a3 * a3
|
||||
const d3 = -2 * a3 * b3
|
||||
const e3 = b3 * b3 + a3 * a3
|
||||
const s3 = quat.fromValues(a3, 0, 0, b3)
|
||||
quat.mul(q, q, s3)
|
||||
const p3 = new Matrix3()
|
||||
@@ -522,13 +516,11 @@ export function svdDecompose(m: Matrix3): [quat, Vector, quat] {
|
||||
p3.m22 = c3
|
||||
p3.m12 = d3
|
||||
p3.m21 = -d3
|
||||
p3.m00 = e3
|
||||
f *= e3
|
||||
p3.mul(p2)
|
||||
|
||||
f = 1 / f
|
||||
quat.scale(q, q, Math.sqrt(f))
|
||||
const scale = new Vector(p3.m00 * f, p3.m11 * f, p3.m22 * f)
|
||||
quat.scale(q, q, Math.sqrt(1))
|
||||
const scale = new Vector(p3.m00, p3.m11, p3.m22)
|
||||
quat.conjugate(r, r)
|
||||
return [q, scale, r]
|
||||
}
|
||||
|
||||
|
||||
@@ -44,14 +44,9 @@ export function Transformation({}: Props) {
|
||||
const [normalizeLeft, setNormalizeLeft] = useState(true)
|
||||
const [normalizeRight, setNormalizeRight] = useState(true)
|
||||
|
||||
const [useMatrixOverride, setUseMatrixOverride] = useState(false)
|
||||
|
||||
const usedMatrix = useMemo(() => {
|
||||
if (matrix !== undefined && useMatrixOverride) {
|
||||
return matrix
|
||||
}
|
||||
return composeMatrix(translation, leftRotation, scale, rightRotation)
|
||||
}, [matrix, useMatrixOverride])
|
||||
}, [translation, leftRotation, scale, rightRotation])
|
||||
|
||||
const updateMatrix = useCallback((m: Matrix4) => {
|
||||
const affine = m.clone().affine()
|
||||
@@ -233,10 +228,9 @@ export function Transformation({}: Props) {
|
||||
<span>{locale('transformation.matrix')}</span>
|
||||
<button class="tooltipped tip-se" aria-label={locale('reset')} onClick={() => updateMatrix(new Matrix4())}>{Octicon['history']}</button>
|
||||
<button class="tooltipped tip-se" aria-label={locale('transformation.copy_composed')} onClick={onCopyComposed}>{Octicon[copiedComposed ? 'check' : 'clippy']}</button>
|
||||
<button class="tooltipped tip-se" aria-label={`${useMatrixOverride ? 'Expected' : 'Current'} behavior (see MC-259853)`} onClick={() => setUseMatrixOverride(!useMatrixOverride)}>{Octicon['info']}</button>
|
||||
</div>
|
||||
{Array(16).fill(0).map((_, i) =>
|
||||
<Slider value={matrix.data[i]} onChange={v => changeMatrix(i, v)} />
|
||||
<Slider value={matrix.data[i]} onChange={v => changeMatrix(i, v)} disabled={i % 4 === 3} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -256,12 +250,13 @@ interface SliderProps {
|
||||
onChange?: (value: number) => void
|
||||
min?: number
|
||||
max?: number
|
||||
disabled?: boolean
|
||||
}
|
||||
function Slider({ label, value, onChange, min, max }: SliderProps) {
|
||||
function Slider({ label, value, onChange, min, max, disabled }: SliderProps) {
|
||||
return <div class="transformation-input">
|
||||
{label && <label>{label}</label>}
|
||||
<NumberInput value={value.toFixed(3)} onChange={onChange} />
|
||||
<RangeInput min={min ?? -1} max={max ?? 1} step={0.01} value={value} onChange={onChange} />
|
||||
<NumberInput value={value.toFixed(3)} onChange={onChange} disabled={disabled} readonly={disabled} />
|
||||
<RangeInput min={min ?? -1} max={max ?? 1} step={0.01} value={value} onChange={onChange} disabled={disabled} readonly={disabled} />
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user