-
Notifications
You must be signed in to change notification settings - Fork 3
/
MassDriverTube.js
127 lines (107 loc) · 6.85 KB
/
MassDriverTube.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import * as THREE from 'three'
import { CatmullRomSuperCurve3 } from './SuperCurves'
export class massDriverTubeModel {
// Each model along the mass driver curve is unique, since the pitch of the mass driver's drive thread changes along it's length
// so instead of dynamically allocating models from a pool of identical unallocated models, we need to create a unique model for each portion of the mass driver curve.
// We can't dynamically reallocate these models, since each model always has to be placed in the location that it was designed for.
// However, we can still hide and models, and also not update them, when they are too far from the camera to be visible.
constructor() {}
createModel(dParamWithUnits, curve, segmentIndex) {
const massDriverTubeSegments = dParamWithUnits['numVirtualMassDriverTubes'].value
const radius = dParamWithUnits['launcherMassDriverTubeInnerRadius'].value
const modelLengthSegments = 32 // This model, which is a segment of the whole mass driver, is itself divided into this many lengthwise segments
const modelRadialSegments = 32
const tubePoints = []
// Now we need a reference point in the middle of this segment of the whole mass driver
const modelsCurvePosition = (segmentIndex + 0.5) / massDriverTubeSegments
const refPoint = curve.getPointAt(modelsCurvePosition)
const modelForward = new THREE.Vector3(0, 1, 0) // The direction that the model considers "forward"
const modelUpward = new THREE.Vector3(0, 0, 1) // The direction that the model considers "upward"
const orientation = curve.getQuaternionAt(modelsCurvePosition, modelForward, modelUpward).invert()
const tubeTexture = new THREE.TextureLoader().load('textures/TubeTexture.png')
// We need to define a curve for this segment of the mass driver, and then use that curve to create a tube geometry for this model
for (let i = 0; i<=modelLengthSegments; i++) {
const modelsCurvePosition = (segmentIndex + i/modelLengthSegments) / massDriverTubeSegments
try {
tubePoints.push(curve.getPointAt(modelsCurvePosition).sub(refPoint).applyQuaternion(orientation))
}
catch (e) {
console.log('error!!!')
curve.getPointAt(modelsCurvePosition)
}
}
const massDriverSegmentCurve = new CatmullRomSuperCurve3(tubePoints)
const massDriverTubeGeometry = new THREE.TubeGeometry(massDriverSegmentCurve, modelLengthSegments, radius, modelRadialSegments, false)
// massDriverTubeGeometry.computeBoundingSphere() // No benefit seen
const massDriverTubeMaterial = new THREE.MeshPhongMaterial( {side: THREE.FrontSide, transparent: true, depthWrite: false, opacity: 0.25})
//const massDriverTubeMaterial = new THREE.MeshPhongMaterial( {map: tubeTexture, side: THREE.FrontSide, transparent: true, opacity: 0.2, shininess: 0.5})
const massDriverTubeMesh = new THREE.Mesh(massDriverTubeGeometry, massDriverTubeMaterial)
massDriverTubeMesh.renderOrder = 999
// Debug code
// const blueMaterial = new THREE.MeshLambertMaterial({color: 0x4040df})
// const massDriverTubeMesh = new THREE.Mesh(new THREE.SphereGeometry(100, 32, 16), blueMaterial)
// massDriverTubeMesh.position.copy(refPoint)
return massDriverTubeMesh
}
genSpecs(dParamWithUnits, specs) {
const launcherMassDriverTubeInnerRadius = dParamWithUnits['launcherMassDriverTubeInnerRadius'].value
const launcherMassDriverTubeWallThickness = dParamWithUnits['launcherMassDriverTubeLinerThickness'].value
const launcherMassDriverTubeLinerThickness = dParamWithUnits['launcherMassDriverTubeLinerThickness'].value
// Let's assume that we want the tube to be buoyant. We'll use tension lines to moore it to the sea floor.
// We need enough concrete to provide stuctural rigidity.
const launcherMassDriverTubeMaterial0Density = dParamWithUnits['launcherMassDriverTubeMaterial0Density'].value
const launcherMassDriverTubeMaterial0Cost = dParamWithUnits['launcherMassDriverTubeMaterial0Cost'].value
const launcherMassDriverTubeMaterial1Density = dParamWithUnits['launcherMassDriverTubeMaterial1Density'].value
const launcherMassDriverTubeMaterial1Cost = dParamWithUnits['launcherMassDriverTubeMaterial1Cost'].value
const massDriverTubeWallCrosssectionalArea = Math.PI * ((launcherMassDriverTubeInnerRadius+launcherMassDriverTubeWallThickness)**2 - launcherMassDriverTubeInnerRadius**2)
const massDriverTubeLinerCrosssectionalArea = Math.PI * ((launcherMassDriverTubeInnerRadius+launcherMassDriverTubeWallThickness+launcherMassDriverTubeLinerThickness)**2 - (launcherMassDriverTubeInnerRadius+launcherMassDriverTubeWallThickness)**2)
specs['massDriverTubeWallCrosssectionalArea'] = {value: massDriverTubeWallCrosssectionalArea, units: "m2"}
specs['massDriverTubeLinerCrosssectionalArea'] = {value: massDriverTubeLinerCrosssectionalArea, units: "m2"}
}
}
export class virtualMassDriverTube {
constructor(d, unallocatedModelsArray) {
this.d = d
this.unallocatedModels = unallocatedModelsArray
this.model = null
}
static update(dParamWithUnits, versionNumber) {
virtualMassDriverTube.isVisible = dParamWithUnits['showMassDriverTube'].value
virtualMassDriverTube.isDynamic = false
virtualMassDriverTube.hasChanged = true
virtualMassDriverTube.versionNumber = versionNumber
}
// allocateModel(om) {
// if () {
// om.material.side = THREE.TwoPassDoubleSide
// }
// }
placeAndOrientModel(om, refFrame) {
const d = this.d
if (d===undefined || (d<0) || (d>1)) {
console.log("error!!!")
}
else {
if (virtualMassDriverTube.isVisible) {
if (this.versionNumber!=virtualMassDriverTube.versionNumber) {
// Something about the design has been updated so this instance also needs to be updated
const modelForward = new THREE.Vector3(0, 1, 0) // The direction that the model considers "forward"
const modelUpward = new THREE.Vector3(0, 0, 1) // The direction that the model considers "upward"
// const forward = refFrame.curve.getTangentAt(d)
// const upward = refFrame.curve.getNormalAt(d)
// const rightward = refFrame.curve.getBinormalAt(d)
this.position = refFrame.curve.getPointAt(d)
// .add(rightward.clone().multiplyScalar(this.lr*virtualMassDriverTube.sidewaysOffset))
// .add(upward.clone().multiplyScalar(virtualMassDriverTube.upwardsOffset))
this.orientation = refFrame.curve.getQuaternionAt(d, modelForward, modelUpward)
this.versionNumber = virtualMassDriverTube.versionNumber
}
om.position.copy(this.position)
om.setRotationFromQuaternion(this.orientation)
}
om.visible = virtualMassDriverTube.isVisible
om.matrixValid = false
if (this.perfOptimizedThreeJS) om.freeze()
}
}
}