[880] | 1 | const numsegmentstube = 1; |
---|
| 2 | |
---|
| 3 | /** |
---|
| 4 | * Helper class for creating meshes for joints in Framsticks-SDK. It combines |
---|
| 5 | * Framsticks-SDK logic with THREE.js logic. |
---|
| 6 | * |
---|
| 7 | * For now shape versions of joints are hard-coded. It may need redefinition in |
---|
| 8 | * the future. |
---|
| 9 | */ |
---|
| 10 | class JointMeshFactory { |
---|
| 11 | /** |
---|
| 12 | * Basic constructor that takes information of how joints should be drawn. |
---|
| 13 | * @param {object} config basic config for joints drawing |
---|
| 14 | * @param {object} cylinderShape object holding following fields |
---|
| 15 | * @param {number} cylinderShape.radius radius of mesh |
---|
| 16 | * @param {number} cylinderShape.radiusSegments number of segments for mesh |
---|
| 17 | * @param {boolean} cylinderShape.isTransparent true if transparent, false otherwise |
---|
| 18 | * @param {number} cylinderShape.opacity opacity of mesh |
---|
| 19 | * @param {object} linkShape object holding following fields |
---|
| 20 | * @param {number} linkShape.radius radius of mesh |
---|
| 21 | * @param {number} linkShape.radiusSegments number of segments for mesh |
---|
| 22 | * @param {boolean} linkShape.isTransparent true if transparent, false otherwise |
---|
| 23 | * @param {number} linkShape.opacity opacity of mesh |
---|
| 24 | */ |
---|
| 25 | constructor(config) { |
---|
| 26 | this.config = config; |
---|
| 27 | this.transformations = new ShapeTransformations(); |
---|
| 28 | this.jointShapes = this.transformations.getJointShapes(); |
---|
| 29 | } |
---|
| 30 | |
---|
| 31 | /** |
---|
| 32 | * Creates Mesh for a given Joint. |
---|
| 33 | * @param {Module.Joint} joint Framsticks-SDK Joint class object |
---|
| 34 | * @param {object} shapeConfig object holding following fields |
---|
| 35 | * @param {number} shapeConfig.radius radius of mesh |
---|
| 36 | * @param {number} shapeConfig.radiusSegments number of segments for mesh |
---|
| 37 | * @param {boolean} shapeConfig.isTransparent true if transparent, false otherwise |
---|
| 38 | * @param {number} shapeConfig.opacity opacity of mesh |
---|
| 39 | * @returns {Mesh} Mesh for a given joint |
---|
| 40 | */ |
---|
| 41 | getNewJointMesh(joint, shapeConfig) { |
---|
| 42 | let firstPartPosVec = new THREE.Vector3( |
---|
| 43 | joint.get_part1().get_p().get_x(), |
---|
| 44 | joint.get_part1().get_p().get_y(), |
---|
| 45 | joint.get_part1().get_p().get_z()); |
---|
| 46 | let secondPartPosVec = new THREE.Vector3( |
---|
| 47 | joint.get_part2().get_p().get_x(), |
---|
| 48 | joint.get_part2().get_p().get_y(), |
---|
| 49 | joint.get_part2().get_p().get_z()); |
---|
| 50 | let line = new THREE.LineCurve3(firstPartPosVec, secondPartPosVec); |
---|
| 51 | let geometry = new THREE.TubeGeometry(line, numsegmentstube, shapeConfig.radius, |
---|
| 52 | shapeConfig.radiusSegments, false); |
---|
| 53 | |
---|
| 54 | let material = this.transformations.getNewMaterial( |
---|
| 55 | joint.get_vcolor().get_x(), |
---|
| 56 | joint.get_vcolor().get_y(), |
---|
| 57 | joint.get_vcolor().get_z()); |
---|
| 58 | material.transparent = shapeConfig.isTransparent; |
---|
| 59 | material.opacity = shapeConfig.opacity; |
---|
| 60 | let mesh = new THREE.Mesh(geometry, material); |
---|
| 61 | mesh.userData = { |
---|
| 62 | isBodyElement: true, |
---|
| 63 | type: 'j', |
---|
| 64 | data: joint, |
---|
| 65 | mesh: mesh, |
---|
| 66 | connectedParts: [], |
---|
| 67 | showTransparent: shapeConfig.isTransparent |
---|
| 68 | }; |
---|
| 69 | return mesh; |
---|
| 70 | } |
---|
| 71 | |
---|
| 72 | /** |
---|
| 73 | * Method finds for a given jointMesh all attached partMeshes and updates |
---|
| 74 | * respectively for those objects their connectedParts and connectedJoints |
---|
| 75 | * fields. |
---|
| 76 | * @param {JointMesh} jointMesh joint for which attached parts will be searched |
---|
| 77 | * @param {PartMesh} partMeshes list of available parts |
---|
| 78 | */ |
---|
| 79 | addConnectionInfo(jointMesh, partMeshes) { |
---|
| 80 | let p1 = jointMesh.data.get_part1(); |
---|
| 81 | let p2 = jointMesh.data.get_part2(); |
---|
| 82 | let count = 0; |
---|
| 83 | for (let i = 0; i < partMeshes.length && count < 2; ++i) { |
---|
| 84 | if (partMeshes[i].data === p1 || partMeshes[i].data === p2) { |
---|
| 85 | jointMesh.connectedParts.push(partMeshes[i]); |
---|
| 86 | partMeshes[i].connectedJoints.push(jointMesh); |
---|
| 87 | ++count; |
---|
| 88 | } |
---|
| 89 | } |
---|
| 90 | } |
---|
| 91 | |
---|
| 92 | /** |
---|
| 93 | * Creates mesh for a given Joint. Additional parameter partMeshes is |
---|
| 94 | * provided to update both Joint and connected Parts with info about |
---|
| 95 | * their connectivity. |
---|
| 96 | * @param {Module.Joint} joint joint for which mesh is created |
---|
| 97 | * @param {PartMesh} partMeshes list of available parts |
---|
| 98 | * @returns {JointMesh} new joint mesh, for properties of Object look at addConnectionInfo jointMesh param documentation |
---|
| 99 | */ |
---|
| 100 | create(joint, partMeshes) { |
---|
| 101 | let result; |
---|
| 102 | let shape = joint.get_shape(); |
---|
| 103 | |
---|
| 104 | if (this.jointShapes['SHAPE_FIXED'].value == shape) { |
---|
| 105 | result = this.getNewJointMesh(joint, this.config.linkShape); |
---|
| 106 | } else { |
---|
| 107 | result = this.getNewJointMesh(joint, this.config.cylinderShape); |
---|
| 108 | } |
---|
| 109 | |
---|
| 110 | if (partMeshes) { |
---|
| 111 | this.addConnectionInfo(result.userData, partMeshes); |
---|
| 112 | } |
---|
| 113 | |
---|
| 114 | return result; |
---|
| 115 | } |
---|
| 116 | } |
---|