1 | "use strict"; |
---|
2 | import * as THREE from 'three'; |
---|
3 | import Transformations from './transformations'; |
---|
4 | |
---|
5 | /** |
---|
6 | * Helper class for creating meshes for parts in Framsticks-SDK. |
---|
7 | * It combines Framsticks-SDK logic with THREE.js logic. |
---|
8 | * |
---|
9 | * For now shape versions of parts are hard-coded. It may need redefinition |
---|
10 | * in the future. |
---|
11 | */ |
---|
12 | class PartMeshFactory { |
---|
13 | /** |
---|
14 | * Basic constructor that takes information of how parts should be drawn. |
---|
15 | * @param {object} config object holding following fields |
---|
16 | * @param {object} config.defaultShape object holding following fields |
---|
17 | * @param {number} config.defaultShape.radius radius of part cylinder |
---|
18 | * @param {number} config.defaultShape.segments number of segments on cylinder |
---|
19 | * @param {object} config.ellipsoidShape object holding following fields |
---|
20 | * @param {number} config.ellipsoidShape.radius radius of part ellipsoid |
---|
21 | * @param {number} config.ellipsoidShape.segments number of segments on ellipsoid |
---|
22 | * |
---|
23 | */ |
---|
24 | constructor(config) { |
---|
25 | this.config = config; |
---|
26 | this.transformations = new Transformations(); |
---|
27 | this.partShapes = this.transformations.getPartShapes(); |
---|
28 | } |
---|
29 | |
---|
30 | /** |
---|
31 | * Creates sphere mesh for a given part. |
---|
32 | * @param {Module.Part} part part, for which Mesh is generated |
---|
33 | * @param {number} sphereRadius radius of part sphere |
---|
34 | * @param {number} segments number of created segments |
---|
35 | * @param {boolean} applyScale true if scale for this mesh should be applied from Module.Part |
---|
36 | * @returns {PartMesh} info about part mesh |
---|
37 | */ |
---|
38 | getNewSphereMesh(part, color, sphereRadius, segments, applyScale) { |
---|
39 | let geometry = new THREE.SphereGeometry(sphereRadius, segments, segments); |
---|
40 | let material = this.transformations.getNewMaterial(color); |
---|
41 | let mesh = null; |
---|
42 | if (applyScale) { |
---|
43 | geometry.scale( |
---|
44 | part.get_scale().get_x(), |
---|
45 | part.get_scale().get_y(), |
---|
46 | part.get_scale().get_z()); |
---|
47 | if (part.get_scale().get_x() == part.get_scale().get_y() && |
---|
48 | part.get_scale().get_x() == part.get_scale().get_z()) { |
---|
49 | mesh = new THREE.Mesh(geometry, material); |
---|
50 | } else { |
---|
51 | mesh = new THREE.Mesh(geometry, material); |
---|
52 | } |
---|
53 | } |
---|
54 | else { |
---|
55 | mesh = new THREE.Mesh(geometry, material); |
---|
56 | } |
---|
57 | mesh.position.set( |
---|
58 | part.get_p().get_x(), |
---|
59 | part.get_p().get_y(), |
---|
60 | part.get_p().get_z()); |
---|
61 | |
---|
62 | // if (applyScale) { |
---|
63 | // mesh.scale.set( |
---|
64 | // part.get_scale().get_x(), |
---|
65 | // part.get_scale().get_y(), |
---|
66 | // part.get_scale().get_z()); |
---|
67 | // } |
---|
68 | |
---|
69 | let angles = part.get_o().getAngles(); |
---|
70 | mesh.rotation.copy( |
---|
71 | this.transformations.getPartRotation( |
---|
72 | angles.get_x(), |
---|
73 | angles.get_y(), |
---|
74 | angles.get_z()) |
---|
75 | ); |
---|
76 | |
---|
77 | mesh.userData = { |
---|
78 | isBodyElement: true, |
---|
79 | type: 'p', |
---|
80 | data: part, |
---|
81 | mesh: mesh, |
---|
82 | isPhysical: this.physics, |
---|
83 | connectedJoints: [] |
---|
84 | }; |
---|
85 | return mesh; |
---|
86 | } |
---|
87 | |
---|
88 | /** |
---|
89 | * Creates box mesh for a given part |
---|
90 | * @param {Module.Part} part part, for which Mesh is generated |
---|
91 | * @returns {PartMesh} info about part mesh |
---|
92 | */ |
---|
93 | getNewBoxMesh(part, color) { |
---|
94 | let geometry = new THREE.BoxGeometry(2, 2, 2); |
---|
95 | geometry.scale( |
---|
96 | part.get_scale().get_x(), |
---|
97 | part.get_scale().get_y(), |
---|
98 | part.get_scale().get_z()); |
---|
99 | |
---|
100 | let material = this.transformations.getNewMaterial(color); |
---|
101 | let mesh = new THREE.Mesh(geometry, material); |
---|
102 | mesh.position.set( |
---|
103 | part.get_p().get_x(), |
---|
104 | part.get_p().get_y(), |
---|
105 | part.get_p().get_z()); |
---|
106 | |
---|
107 | let angles = part.get_o().getAngles(); |
---|
108 | mesh.rotation.copy(this.transformations.getPartRotation( |
---|
109 | angles.get_x(), |
---|
110 | angles.get_y(), |
---|
111 | angles.get_z())); |
---|
112 | |
---|
113 | mesh.userData = { |
---|
114 | isBodyElement: true, |
---|
115 | type: 'p', |
---|
116 | data: part, |
---|
117 | mesh: mesh, |
---|
118 | isPhysical: this.physics, |
---|
119 | connectedJoints: [] |
---|
120 | }; |
---|
121 | return mesh; |
---|
122 | } |
---|
123 | |
---|
124 | /** |
---|
125 | * Creates cylinder mesh for a given part |
---|
126 | * @param {Module.Part} part part, for which Mesh is generated |
---|
127 | * @returns {PartMesh} info about part mesh |
---|
128 | */ |
---|
129 | getNewCylinderMesh(part, color) { |
---|
130 | let geometry = new THREE.CylinderGeometry(1, 1, 2, 32); |
---|
131 | let material = this.transformations.getNewMaterial(color); |
---|
132 | |
---|
133 | geometry.scale( |
---|
134 | part.get_scale().get_y(), |
---|
135 | part.get_scale().get_x(), |
---|
136 | part.get_scale().get_z()); |
---|
137 | |
---|
138 | let mesh = null; |
---|
139 | if (part.get_scale().get_y() == part.get_scale().get_z()) { |
---|
140 | mesh = new THREE.Mesh(geometry, material); |
---|
141 | } else { |
---|
142 | mesh = new THREE.Mesh(geometry, material); |
---|
143 | } |
---|
144 | mesh.position.set( |
---|
145 | part.get_p().get_x(), |
---|
146 | part.get_p().get_y(), |
---|
147 | part.get_p().get_z()); |
---|
148 | |
---|
149 | let angles = part.get_o().getAngles(); |
---|
150 | let m = this.transformations.getCylinderPartRotationMatrix( |
---|
151 | angles.get_x(), |
---|
152 | angles.get_y(), |
---|
153 | angles.get_z()); |
---|
154 | |
---|
155 | mesh.rotation.setFromRotationMatrix(m); |
---|
156 | |
---|
157 | mesh.userData = { |
---|
158 | isBodyElement: true, |
---|
159 | type: 'p', |
---|
160 | data: part, |
---|
161 | mesh: mesh, |
---|
162 | isPhysical: this.physics, |
---|
163 | connectedJoints: [] |
---|
164 | }; |
---|
165 | return mesh; |
---|
166 | } |
---|
167 | |
---|
168 | /** |
---|
169 | * Creates part mesh according to which shape should be applied for a given |
---|
170 | * part. |
---|
171 | * @param {Module.Part} part part, for which Mesh is generated |
---|
172 | * @returns {PartMesh} info about part mesh |
---|
173 | */ |
---|
174 | create(part, color) { |
---|
175 | |
---|
176 | let shape = part.get_shape(); |
---|
177 | if (this.partShapes['SHAPE_ELLIPSOID'].value == shape) { |
---|
178 | return this.getNewSphereMesh( |
---|
179 | part, |
---|
180 | color, |
---|
181 | this.config.ellipsoidShape.radius, |
---|
182 | this.config.ellipsoidShape.segments, true); |
---|
183 | } |
---|
184 | else if (this.partShapes['SHAPE_CUBOID'].value == shape) { |
---|
185 | return this.getNewBoxMesh(part, color); |
---|
186 | } |
---|
187 | else if (this.partShapes['SHAPE_CYLINDER'].value == shape) { |
---|
188 | return this.getNewCylinderMesh(part, color); |
---|
189 | } |
---|
190 | return this.getNewSphereMesh( |
---|
191 | part, |
---|
192 | color, |
---|
193 | this.config.defaultShape.radius, |
---|
194 | this.config.defaultShape.segments, |
---|
195 | false); |
---|
196 | } |
---|
197 | } |
---|
198 | |
---|
199 | export default PartMeshFactory; |
---|