Created
September 6, 2018 07:32
-
-
Save KeanW/f1f5edf3661f347f4f3970da802e88f3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <reference path='../../types/three.d.ts' /> | |
import { Logger } from '../../core/Logger'; | |
let logger = Logger.getInstance(); | |
import { ShowableExtension } from '../../core/ShowableExtension'; | |
import { DasherModel } from '../../core/DasherModel'; | |
import { SkeletonHelper2 } from './SkeletonHelper2'; | |
export class SkeletonExtension extends ShowableExtension { | |
private _skeletons: { [key: number]: [THREE.SkinnedMesh, THREE.Bone, SkeletonHelper2] }; | |
private _skeletonMaterial: any = null; | |
private _overlayScene = "DasherSkeletonOverlay"; | |
constructor(viewer: Autodesk.Viewing.Private.GuiViewer3D, options: any) { | |
super(viewer, options); | |
this._skeletons = {}; | |
} | |
public load(): boolean { | |
this.createUI( | |
'toolbar-sensor-skeleton', | |
'Skeletons', | |
'DasherControlSensors', | |
'grain' | |
); | |
this._dataModel.on( | |
DasherModel.eventTypes.CurrentHistoricTimeChanged, | |
this.onCurrentHistoricTimeChanged | |
); | |
logger.log('SkeletonExtension loaded'); | |
return true; | |
} | |
public unload(): boolean { | |
this.destroyUI('DasherControlSensors'); | |
this._dataModel.off( | |
DasherModel.eventTypes.CurrentHistoricTimeChanged, | |
this.onCurrentHistoricTimeChanged | |
); | |
logger.log('SkeletonExtension unloaded'); | |
return true; | |
} | |
public show(): boolean { | |
this.viewer.addEventListener( | |
Autodesk.Viewing.SELECTION_CHANGED_EVENT, | |
this.onSelectionChanged); | |
this._skeletonMaterial = this.createSkeletonMaterial(); | |
this.viewer.impl.createOverlayScene(this._overlayScene); | |
this.viewer.getSelection().forEach(fragId => { | |
this.drawSkeletonForFragment(fragId); | |
}); | |
return true; | |
} | |
public hide(): boolean { | |
this.viewer.removeEventListener( | |
Autodesk.Viewing.SELECTION_CHANGED_EVENT, | |
this.onSelectionChanged); | |
this._skeletonMaterial = null; | |
for (let id in this._skeletons) { | |
let skel = this._skeletons[id]; | |
if (skel) { | |
this.removeFromScene(skel[0]); | |
this.removeFromScene(skel[1]); | |
this.removeFromScene(skel[2]); | |
this._skeletons[id] = undefined; | |
this.viewer.impl.invalidate(false, true, true); | |
} | |
} | |
this.viewer.impl.removeOverlayScene(this._overlayScene); | |
return true; | |
} | |
private addToScene(obj: THREE.Object3D) { | |
// this.viewer.impl.scene.add(obj); | |
// this.viewer.impl.invalidate(true, true, false); | |
this.viewer.impl.addOverlay(this._overlayScene, obj); | |
this.viewer.impl.invalidate(false, false, true); | |
} | |
private removeFromScene(obj: THREE.Object3D) { | |
// this.viewer.impl.scene.remove(obj); | |
// this.viewer.impl.invalidate(true, true, false); | |
this.viewer.impl.removeOverlay(this._overlayScene, obj); | |
this.viewer.impl.invalidate(false, false, true); | |
} | |
private createSkeletonMaterial() { | |
let material = new THREE.MeshBasicMaterial( { color: 0x007700, skinning: true }); | |
this.viewer.impl.matman().addMaterial( | |
'dasher-material-skeleton', | |
material, | |
true); | |
return material; | |
} | |
private onSelectionChanged = (event) => { | |
event.fragIdsArray.forEach(fragId => { | |
let skel = this._skeletons[fragId]; | |
if (skel) { | |
this.removeFromScene(skel[0]); | |
this.removeFromScene(skel[1]); | |
this.removeFromScene(skel[2]); | |
this._skeletons[fragId] = undefined; | |
this.viewer.impl.invalidate(false, true, false); | |
} else { | |
this.drawSkeletonForFragment(fragId); | |
} | |
}); | |
} | |
private onCurrentHistoricTimeChanged = (time: Date): void => { | |
this.update(); | |
} | |
private drawSkeletonForFragment(fragId) { | |
let renderProxy = this.viewer.impl.getRenderProxy( | |
this.viewer.model, | |
fragId); | |
let matrix = renderProxy.matrixWorld; | |
this.addSkeleton(fragId, matrix); | |
} | |
private addSkeleton(id: number, mat: THREE.Matrix4): void { | |
// Define bone/joint parameters | |
const torsoLength = 6; | |
const headLength = 3; | |
const shoulderLength = 2; | |
const shoulderSlope = 1; | |
const upperArmLength = 3; | |
const upperArmSlope = 1; | |
const lowerArmLength = 3; | |
const lowerArmSlope = 0; | |
const hipLength = 2; | |
const hipSlope = 1; | |
const upperLegLength = 4; | |
const upperLegSlope = 0; | |
const lowerLegLength = 5; | |
const lowerLegSlope = 0; | |
// Define relative joint positions | |
const bodyRel = new THREE.Vector3(0, 0, 0); | |
const neckRel = new THREE.Vector3(0, torsoLength, 0); | |
const headRel = new THREE.Vector3(0, headLength, 0); | |
const leftShoulderRel = new THREE.Vector3(shoulderLength, -shoulderSlope, 0); | |
const rightShoulderRel = new THREE.Vector3(-shoulderLength, -shoulderSlope, 0); | |
const leftElbowRel = new THREE.Vector3(upperArmSlope, -upperArmLength, 0); | |
const rightElbowRel = new THREE.Vector3(-upperArmSlope, -upperArmLength, 0); | |
const leftHandRel = new THREE.Vector3(lowerArmSlope, -lowerArmLength, 0); | |
const rightHandRel = new THREE.Vector3(-lowerArmSlope, -lowerArmLength, 0); | |
const leftHipRel = new THREE.Vector3(hipLength, -hipSlope, 0); | |
const rightHipRel = new THREE.Vector3(-hipLength, -hipSlope, 0); | |
const leftKneeRel = new THREE.Vector3(upperLegSlope, -upperLegLength, 0); | |
const rightKneeRel = new THREE.Vector3(-upperLegSlope, -upperLegLength, 0); | |
const leftFootRel = new THREE.Vector3(lowerLegSlope, -lowerLegLength, 0); | |
const rightFootRel = new THREE.Vector3(-lowerLegSlope, -lowerLegLength, 0); | |
// Calculate absolute joint positions | |
const bodyAbs = bodyRel.clone(); | |
const neckAbs = new THREE.Vector3().addVectors(bodyAbs, neckRel); | |
const headAbs = new THREE.Vector3().addVectors(neckAbs, headRel); | |
const leftShoulderAbs = new THREE.Vector3().addVectors(neckAbs, leftShoulderRel); | |
const leftElbowAbs = new THREE.Vector3().addVectors(leftShoulderAbs, leftElbowRel); | |
const leftHandAbs = new THREE.Vector3().addVectors(leftElbowAbs, leftHandRel); | |
const rightShoulderAbs = new THREE.Vector3().addVectors(neckAbs, rightShoulderRel); | |
const rightElbowAbs = new THREE.Vector3().addVectors(rightShoulderAbs, rightElbowRel); | |
const rightHandAbs = new THREE.Vector3().addVectors(rightElbowAbs, rightHandRel); | |
const leftHipAbs = new THREE.Vector3().addVectors(bodyAbs, leftHipRel); | |
const leftKneeAbs = new THREE.Vector3().addVectors(leftHipAbs, leftKneeRel); | |
const leftFootAbs = new THREE.Vector3().addVectors(leftKneeAbs, leftFootRel); | |
const rightHipAbs = new THREE.Vector3().addVectors(bodyAbs, rightHipRel); | |
const rightKneeAbs = new THREE.Vector3().addVectors(rightHipAbs, rightKneeRel); | |
const rightFootAbs = new THREE.Vector3().addVectors(rightKneeAbs, rightFootRel); | |
// Declare the mesh, create it later | |
let mesh = null; | |
// Create the bones connected to the mesh | |
let bodyBone = new THREE.Bone(mesh); | |
let headBone = new THREE.Bone(mesh); | |
let neckBone = new THREE.Bone(mesh); | |
let leftShoulderBone = new THREE.Bone(mesh); | |
let leftElbowBone = new THREE.Bone(mesh); | |
let leftHandBone = new THREE.Bone(mesh); | |
let rightShoulderBone = new THREE.Bone(mesh); | |
let rightElbowBone = new THREE.Bone(mesh); | |
let rightHandBone = new THREE.Bone(mesh); | |
let leftHipBone = new THREE.Bone(mesh); | |
let leftKneeBone = new THREE.Bone(mesh); | |
let leftFootBone = new THREE.Bone(mesh); | |
let rightHipBone = new THREE.Bone(mesh); | |
let rightKneeBone = new THREE.Bone(mesh); | |
let rightFootBone = new THREE.Bone(mesh); | |
// Set the relative positions of the joints | |
bodyBone.position.set(bodyRel.x, bodyRel.y, bodyRel.z); | |
headBone.position.set(headRel.x, headRel.y, headRel.z); | |
neckBone.position.set(neckRel.x, neckRel.y, neckRel.z); | |
leftShoulderBone.position.set(leftShoulderRel.x, leftShoulderRel.y, leftShoulderRel.z); | |
leftElbowBone.position.set(leftElbowRel.x, leftElbowRel.y, leftElbowRel.z); | |
leftHandBone.position.set(leftHandRel.x, leftHandRel.y, leftHandRel.z); | |
rightShoulderBone.position.set(rightShoulderRel.x, rightShoulderRel.y, rightShoulderRel.z); | |
rightElbowBone.position.set(rightElbowRel.x, rightElbowRel.y, rightElbowRel.z); | |
rightHandBone.position.set(rightHandRel.x, rightHandRel.y, rightHandRel.z); | |
leftHipBone.position.set(leftHipRel.x, leftHipRel.y, leftHipRel.z); | |
leftKneeBone.position.set(leftKneeRel.x, leftKneeRel.y, leftKneeRel.z); | |
leftFootBone.position.set(leftFootRel.x, leftFootRel.y, leftFootRel.z); | |
rightHipBone.position.set(rightHipRel.x, rightHipRel.y, rightHipRel.z); | |
rightKneeBone.position.set(rightKneeRel.x, rightKneeRel.y, rightKneeRel.z); | |
rightFootBone.position.set(rightFootRel.x, rightFootRel.y, rightFootRel.z); | |
// Define the bone topology by adding them to their parents | |
bodyBone.add(neckBone); | |
neckBone.add(headBone); | |
neckBone.add(leftShoulderBone); | |
leftShoulderBone.add(leftElbowBone); | |
leftElbowBone.add(leftHandBone); | |
neckBone.add(rightShoulderBone); | |
rightShoulderBone.add(rightElbowBone); | |
rightElbowBone.add(rightHandBone); | |
bodyBone.add(leftHipBone); | |
leftHipBone.add(leftKneeBone); | |
leftKneeBone.add(leftFootBone); | |
bodyBone.add(rightHipBone); | |
rightHipBone.add(rightKneeBone); | |
rightKneeBone.add(rightFootBone); | |
// Create a list of bones for this skeleton | |
let bones = []; | |
bones.push(bodyBone); | |
bones.push(neckBone); | |
bones.push(headBone); | |
bones.push(leftShoulderBone); | |
bones.push(leftElbowBone); | |
bones.push(leftHandBone); | |
bones.push(rightShoulderBone); | |
bones.push(rightElbowBone); | |
bones.push(rightHandBone); | |
bones.push(leftHipBone); | |
bones.push(leftKneeBone); | |
bones.push(leftFootBone); | |
bones.push(rightHipBone); | |
bones.push(rightKneeBone); | |
bones.push(rightFootBone); | |
let skeleton = new THREE.Skeleton(bones); | |
let humanGeometry = new THREE.Geometry(); | |
mesh = new THREE.SkinnedMesh(humanGeometry, this._skeletonMaterial); | |
mesh.add(bodyBone); | |
mesh.bind(skeleton); | |
let dims = this.viewer.getDimensions(); | |
let helper = new SkeletonHelper2(mesh, new THREE.Vector2(dims.width, dims.height)); | |
this.addToScene(mesh); | |
this.addToScene(bodyBone); | |
this.addToScene(helper); | |
// Transform the skeleton and the mesh | |
let rotate = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), Math.PI / 2); // Make upright | |
let translate = new THREE.Matrix4().makeTranslation(0, 0, hipSlope + upperLegLength + lowerLegLength); // Move to surface | |
let scale = new THREE.Matrix4().makeScale(0.5, 0.5, 0.5); // Make it half the size | |
mat.multiply(scale).multiply(translate).multiply(rotate); // Combine with the transform passed in | |
mesh.applyMatrix(mat); | |
bodyBone.applyMatrix(mat); | |
this._skeletons[id] = [mesh, bodyBone, helper]; | |
} | |
private update() { | |
let angle = Math.sin(Date.now() * 0.003); | |
let ang = (Math.PI * angle) / 8; | |
for (let id in this._skeletons) { | |
let skelInfo = this._skeletons[id]; | |
if (skelInfo) { | |
let bones = skelInfo[0].skeleton.bones; | |
bones[3].rotation.x = ang; // Left shoulder | |
bones[4].rotation.x = ang; // Left elbow | |
bones[6].rotation.x = -ang; // Right shoulder | |
bones[7].rotation.x = -ang; // Right elbow | |
bones[9].rotation.x = -ang; // Left hip | |
bones[10].rotation.x = -ang; // Left knee | |
bones[12].rotation.x = ang; // Right hip | |
bones[13].rotation.x = ang; // Right knee | |
skelInfo[2].update(); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment