Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: rotation/scale widget #194

Merged
merged 1 commit into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions app/src/components/LayerControlBody.vue
Original file line number Diff line number Diff line change
Expand Up @@ -606,15 +606,7 @@ export default {
},
setIsotropicScale: function(value) {
this.setScaleInc({
axis: 'x',
value
})
this.setScaleInc({
axis: 'y',
value
})
this.setScaleInc({
axis: 'z',
axis: 'xyz',
value
})
},
Expand Down
45 changes: 20 additions & 25 deletions app/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -907,34 +907,29 @@ export const viewerConfigs = [
]

export const getRotationVec3 = (index) => {
if ('export_nehuba' in window) {
return index === 0
? {
vec31: window.export_nehuba.vec3.fromValues(0, 0, 1),
vec32: window.export_nehuba.vec3.fromValues(1, 0, 0)
}
: index === 1
? {
vec31: window.export_nehuba.vec3.fromValues(0, 0, 1),
vec32: window.export_nehuba.vec3.fromValues(0, 1, 0)
}
: index === 2
? {
vec31: window.export_nehuba.vec3.fromValues(0, -1, 0),
vec32: window.export_nehuba.vec3.fromValues(1, 0, 0)
}
: (console.warn('getRotationVec3 index > 2, returning null'), {
vec31: null,
vec32: null
})

} else {
console.warn('export_nehuba is not present in window, has it not been exported?')
if (!('export_nehuba' in window)) {
throw new Error(`export_nehuba is not present in window, has it not been exported?`)
}
if (index === 0) {
return {
vec31: null,
vec32: null
vec31: window.export_nehuba.vec3.fromValues(0, 0, 1),
vec32: window.export_nehuba.vec3.fromValues(1, 0, 0)
}
}
if (index === 1) {
return {
vec31: window.export_nehuba.vec3.fromValues(0, 0, 1),
vec32: window.export_nehuba.vec3.fromValues(0, 1, 0)
}
}
if (index === 2) {
return {
vec31: window.export_nehuba.vec3.fromValues(0, -1, 0),
vec32: window.export_nehuba.vec3.fromValues(1, 0, 0)
}
}
throw new Error(`getRotationVec3 only supports index 0, 1, 2`)

}

export const incomingTemplateActiveOpacity = 0.8
Expand Down
4 changes: 2 additions & 2 deletions app/src/store/dataSelectionStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ const dataSelectionStore = {
return type
},
selectedIncomeVolumeDim: (state) => {
const { selectedIncomingVolumeSize } = state
return selectedIncomingVolumeSize
const { selectedIncomingVolumeSize: size, selectedIncomingVolumeResolution: res } = state
return [0, 1, 2].map(idx => size[idx] * res[idx])
}
}
}
Expand Down
202 changes: 99 additions & 103 deletions app/src/store/nehubaStore.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { identityMatFlattened } from '../constants'
import { identityMatFlattened, convertNmToVoxel } from '../constants'
import { incompatibleBrowserText } from "@/text"

const browserCompatible = () => 'WebGL2RenderingContext' in window

const getMirrorMat = (flippedState, dim) => {
if (! ('export_nehuba' in window))
if (! ('export_nehuba' in window)) {
return null
}
const { vec3, mat4 } = window.export_nehuba

const applyMirror = mat4.create()
Expand Down Expand Up @@ -137,32 +138,34 @@ const nehubaStore = {
incVolScaleLock: incVolScaleLock !== null ? incVolScaleLock : state.incVolScaleLock
})
},
flipAxis ({ commit, state, getters, dispatch }, { axis }) {
const { flippedState: currentFlippedState } = state
const { dim } = getters

const idx = axis === 0
? 0
: axis === 1
? 5
: axis === 2
? 10
: -1
flipAxis ({ commit, state, dispatch }, { axis }) {
const { flippedState: currentFlippedState, incTransformMatrix } = state

const { mat4, vec3 } = window.export_nehuba

if (idx < 0) return
/**
* @type {'x' | 'y' | 'z'}
*/
let parsedAxis = null
if (axis === 0) {
parsedAxis = 'x'
}
if (axis === 1) {
parsedAxis = 'y'
}
if (axis === 2) {
parsedAxis = 'z'
}

const flippedState = currentFlippedState.map((v, id) => id === axis ? v * -1 : v)

const mirrorVec = [1, 1, 1]
mirrorVec[axis] = -1
const mirror = getMirrorMat(mirrorVec, dim)

if (!mirror) return
const cXform = mat4.fromValues(...incTransformMatrix)
const cScaling = mat4.getScaling(vec3.create(), cXform)

const { applyMirror } = mirror
cScaling[axis] *= -1 * currentFlippedState[axis]

commit('setFlippedState', { flippedState })
dispatch('multiplyIncXformMatrix', Array.from(applyMirror))
dispatch('setScaleInc', { axis: parsedAxis, value: cScaling[axis] })
},
highlightIncomingVolume ({ commit }, bool) {
commit('setIncomingVolumeHighlighted', bool)
Expand All @@ -179,9 +182,9 @@ const nehubaStore = {
)
})
},
rotIncBy ({ state, getters, dispatch }, { quaternion }) {
rotIncBy ({ state, getters, dispatch, commit }, { quaternion }) {

const { flippedState, incTransformMatrix } = state
const { incTransformMatrix } = state
if (!quaternion) {
return
}
Expand All @@ -190,8 +193,12 @@ const nehubaStore = {
}
const {quat, vec3, mat4} = window.export_nehuba

const axis = vec3.create()
const cXformMat = mat4.fromValues(...incTransformMatrix)

const axis = vec3.fromValues(1, 0, 0)
const rotQuat = quat.fromValues(...quaternion)
// necessary to normalize?
quat.normalize(rotQuat, rotQuat)
const angle = quat.getAxisAngle(axis, rotQuat)
const rotMat = mat4.fromRotation(mat4.create(), angle, rotQuat)

Expand All @@ -202,106 +209,84 @@ const nehubaStore = {

const xformMat = mat4.create()

/**
* translation mat for operations at the center of the volume
*/
const { size: _size } = getters
const size = [..._size]

/**
* get mirror mats
*/
const mirror = getMirrorMat(flippedState, size)

if (!mirror) return

const { undoMirror } = mirror

/**
* undo mirror & undo scale
*/
const cXformMat = mat4.fromValues(...incTransformMatrix)
const cScaling = mat4.getScaling(vec3.create(), cXformMat)
const ivCScaling = vec3.inverse(vec3.create(), cScaling)
const cScalingMat = mat4.fromScaling(mat4.create(), ivCScaling)
mat4.mul(xformMat, undoMirror, cScalingMat)

/**
* apply translation correction
*/

const incTransl = vec3.mul(size, size, cScaling)
vec3.scale(incTransl, incTransl, 0.5)
const incTranslMat = mat4.fromTranslation(mat4.create(), incTransl)
mat4.mul(xformMat, xformMat, incTranslMat)

/**
* save invert
*/
const invert = mat4.invert(mat4.create(), xformMat)

/**
* apply rotation
*/
mat4.mul(xformMat, xformMat, rotMat)

/**
* apply invert
*/
mat4.mul(xformMat, xformMat, invert)

dispatch('multiplyIncXformMatrix', Array.from(xformMat))
if (getters.originAtCenter) {
const centralizeMatrix = mat4.fromTranslation(mat4.create(), getters.centerVoxel.map(v => v * -1))
const decentralizeMatrix = mat4.fromTranslation(mat4.create(), getters.centerVoxel)

mat4.mul(xformMat, centralizeMatrix, xformMat)

mat4.mul(
xformMat,
rotMat,
xformMat)

mat4.mul(xformMat, decentralizeMatrix, xformMat)

mat4.mul(xformMat, cXformMat, xformMat)

commit("setIncTransformMatrix", { matrix: Array.from(xformMat) })
return
}
throw new Error(`non origin rotinc not yet implemented`)
},

setScaleInc ({commit, state, getters}, {axis, value}) {
setScaleInc ({ commit, state, getters }, { axis, value }) {

const { incTransformMatrix } = state
const { mat4, vec3 } = window.export_nehuba
const { mat4, vec3, quat } = window.export_nehuba

if (axis !== 'x' && axis !== 'y' && axis !== 'z') {
if (axis !== 'x' && axis !== 'y' && axis !== 'z' && axis !== "xyz") {
return
}
if (Number.isNaN(value) || !(value > 0)) {
if (Number.isNaN(value)) {
return
}
const idx = axis === 'x'
? 0
: axis === 'y'
? 1
: 2

const { size } = getters
const dimVec = vec3.fromValues(...size)

const cXform = mat4.fromValues(...incTransformMatrix)

/**
* returning mat
*/
const xformMat = mat4.create()
const cRot = mat4.getRotation(quat.create(), cXform)

/**
* apply scale
*/
const oldScale = mat4.getScaling(vec3.create(), cXform)
const newScale = vec3.fromValues(1, 1, 1)
newScale[idx] = value / oldScale[idx]
const newScale = vec3.copy(vec3.create(), oldScale)

if (axis === "x") {
newScale[0] = value / oldScale[0]
}
if (axis === "y") {
newScale[1] = value / oldScale[1]
}
if (axis === "z") {
newScale[2] = value / oldScale[2]
}
if (axis === "xyz") {
newScale[0] = value / oldScale[0]
newScale[1] = value / oldScale[1]
newScale[2] = value / oldScale[2]
}
const scaleMat = mat4.fromScaling(mat4.create(), newScale)
mat4.mul(xformMat, scaleMat, xformMat)

/**
* apply excess transform
*/
const xtraScale = vec3.sub(vec3.create(), vec3.fromValues(1,1,1), newScale)
vec3.scale(xtraScale, xtraScale, 0.5)
vec3.mul(xtraScale, xtraScale, dimVec)
mat4.mul(xformMat, mat4.fromTranslation(mat4.create(), xtraScale), xformMat)

/**
* apply original xform
* returning mat
*/
mat4.mul(xformMat, cXform, xformMat)
const xformMat = mat4.create()
if (getters.originAtCenter) {
const centralizeMatrix = mat4.fromTranslation(mat4.create(), getters.centerVoxel.map(v => v * -1))
const decentralizeMatrix = mat4.fromTranslation(mat4.create(), getters.centerVoxel)
mat4.mul(xformMat, centralizeMatrix, xformMat)
mat4.mul(xformMat, scaleMat, xformMat)
mat4.mul(xformMat, decentralizeMatrix, xformMat)

mat4.mul(xformMat, cXform, xformMat)

}

if (!getters.originAtCenter) {

const cXlate = mat4.getTranslation(vec3.create(), cXform)
mat4.fromRotationTranslationScale(xformMat, cRot, cXlate, newScale)
}
commit("setIncTransformMatrix", { matrix: Array.from(xformMat) })
},
setTranslInc ({commit, state}, {axis, value}) {
Expand Down Expand Up @@ -435,6 +420,17 @@ const nehubaStore = {
mat4.mul(incM, translMat, incM)
return Array.from(incM)
},
originAtCenter: () => {
return true
},
centerVoxel: (state, getters, rootState, rootGetters) => {

const dim = rootGetters['dataSelectionStore/selectedIncomeVolumeDim']
const { dataSelectionStore } = rootState
const { coordinateSpace } = dataSelectionStore
const dimVox = convertNmToVoxel(coordinateSpace, dim, "vec3")
return dimVox.map(v => v / 2)
},
},
}

Expand Down