elation-engine 0.9.113 → 0.9.115
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/systems/render.css +5 -1
- package/package.json +1 -1
- package/scripts/assets.js +103 -20
- package/scripts/assetworker.js +18 -1
- package/scripts/external/holoplay.js +1494 -0
- package/scripts/external/octree.js +0 -0
- package/scripts/external/three/CSS3DRenderer.js +46 -43
- package/scripts/external/three/CubemapToEquirectangular.js +1 -1
- package/scripts/external/three/three-extras.js +1553 -392
- package/scripts/external/three/three-icosa.js +2575 -0
- package/scripts/external/three/three-loaders.js +925 -133
- package/scripts/external/three/three-postprocessing.js +3 -3
- package/scripts/external/three/three-r116dev.js +50930 -0
- package/scripts/external/three/three-spotlighttextures.js +50953 -0
- package/scripts/external/three/three-vrm.js +2 -2
- package/scripts/external/three/three-working.js +35968 -0
- package/scripts/external/three/three.js +38532 -24087
- package/scripts/external/three-mesh-bvh.js +5370 -0
- package/scripts/external/three-old/BVHLoader.js +406 -0
- package/scripts/external/three-old/ColladaLoader.js +5519 -0
- package/scripts/external/three-old/ColladaLoader2.js +1694 -0
- package/scripts/external/three-old/CubemapToEquirectangular.js +188 -0
- package/scripts/external/three-old/DDSLoader.js +269 -0
- package/scripts/external/three-old/FBXLoader-mine.js +5063 -0
- package/scripts/external/three-old/FBXLoader.js +5112 -0
- package/scripts/external/three-old/FlyControls.js +295 -0
- package/scripts/external/three-old/GLTF2Loader.js +2950 -0
- package/scripts/external/three-old/GLTFLoader.js +2213 -0
- package/scripts/external/three-old/JSONLoader.js +435 -0
- package/scripts/external/three-old/MTLLoader.js +533 -0
- package/scripts/external/three-old/OBJLoader-experimental.js +874 -0
- package/scripts/external/three-old/OBJLoader-working.js +727 -0
- package/scripts/external/three-old/OBJLoader.js +723 -0
- package/scripts/external/three-old/OBJMTLLoader.js +440 -0
- package/scripts/external/three-old/OrbitControls.js +592 -0
- package/scripts/external/three-old/PLYLoader.js +517 -0
- package/scripts/external/three-old/TransformControls.js +1100 -0
- package/scripts/external/three-old/VRMLLoader.js +1021 -0
- package/scripts/external/three-old/glTFLoader-combined.js +2513 -0
- package/scripts/external/three-old/nodethree.js +44018 -0
- package/scripts/external/three-old/render/BleachBypassShader.js +64 -0
- package/scripts/external/three-old/render/BloomPass.js +116 -0
- package/scripts/external/three-old/render/CSS3DRenderer.js +310 -0
- package/scripts/external/three-old/render/ClearPass.js +44 -0
- package/scripts/external/three-old/render/ConvolutionShader.js +101 -0
- package/scripts/external/three-old/render/CopyShader.js +46 -0
- package/scripts/external/three-old/render/EffectComposer.js +211 -0
- package/scripts/external/three-old/render/FXAAShader.js +88 -0
- package/scripts/external/three-old/render/FilmPass.js +60 -0
- package/scripts/external/three-old/render/FilmShader.js +104 -0
- package/scripts/external/three-old/render/ManualMSAARenderPass.js +168 -0
- package/scripts/external/three-old/render/MaskPass.js +97 -0
- package/scripts/external/three-old/render/OculusRenderPass.js +84 -0
- package/scripts/external/three-old/render/OculusRiftEffect.js +240 -0
- package/scripts/external/three-old/render/PortalRenderPass.js +166 -0
- package/scripts/external/three-old/render/RecordingPass.js +208 -0
- package/scripts/external/three-old/render/RenderPass.js +57 -0
- package/scripts/external/three-old/render/SSAOShader.js +259 -0
- package/scripts/external/three-old/render/SepiaShader.js +54 -0
- package/scripts/external/three-old/render/ShaderPass.js +66 -0
- package/scripts/external/three-old/render/VREffect.js +482 -0
- package/scripts/external/three-old/shimthree.js +23 -0
- package/scripts/external/three-old/stats.js +6 -0
- package/scripts/external/three-old/three-88dev.js +45004 -0
- package/scripts/external/three-old/three-backgroundoptimization.js +44432 -0
- package/scripts/external/three-old/three-updates.js +44735 -0
- package/scripts/external/three-old/three-working.js +44719 -0
- package/scripts/external/three-old/three.js +44431 -0
- package/scripts/external/three-old/threex.rendererstats.js +66 -0
- package/scripts/external/three-old/tween.js +13 -0
- package/scripts/external/webvr-polyfill-new.js +3497 -0
- package/scripts/external/webvr-polyfill-newest.js +3491 -0
- package/scripts/external/webvr-polyfill-old.js +6337 -0
- package/scripts/geometries.js +2 -2
- package/scripts/math.js +6 -6
- package/scripts/systems/admin.js +1 -1
- package/scripts/systems/controls.js +6 -4
- package/scripts/systems/physics.js +10 -10
- package/scripts/systems/render.js +58 -20
- package/scripts/systems/render2.js +38 -0
- package/scripts/things/camera.js +6 -1
- package/scripts/things/generic-trackedvectors.js +1875 -0
- package/scripts/things/generic.js +3 -4
- package/scripts/things/label2d.js +1 -1
- package/scripts/things/leapmotion.js +6 -6
- package/scripts/things/menu.js +1 -1
- package/scripts/things/player-bak.js +638 -0
- package/scripts/things/player.js +28 -10
- package/scripts/things/skysphere.js +1 -1
- package/scripts/things/terrain.js +1 -1
- package/scripts/things/text.js +1 -1
|
@@ -0,0 +1,1021 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author mrdoob / http://mrdoob.com/
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
THREE.VRMLLoader = function ( manager ) {
|
|
6
|
+
|
|
7
|
+
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
|
|
8
|
+
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
THREE.VRMLLoader.prototype = {
|
|
12
|
+
|
|
13
|
+
constructor: THREE.VRMLLoader,
|
|
14
|
+
|
|
15
|
+
// for IndexedFaceSet support
|
|
16
|
+
isRecordingPoints: false,
|
|
17
|
+
isRecordingFaces: false,
|
|
18
|
+
points: [],
|
|
19
|
+
indexes : [],
|
|
20
|
+
|
|
21
|
+
// for Background support
|
|
22
|
+
isRecordingAngles: false,
|
|
23
|
+
isRecordingColors: false,
|
|
24
|
+
angles: [],
|
|
25
|
+
colors: [],
|
|
26
|
+
|
|
27
|
+
recordingFieldname: null,
|
|
28
|
+
|
|
29
|
+
load: function ( url, onLoad, onProgress, onError ) {
|
|
30
|
+
|
|
31
|
+
var scope = this;
|
|
32
|
+
|
|
33
|
+
var loader = new THREE.XHRLoader( this.manager );
|
|
34
|
+
loader.load( url, function ( text ) {
|
|
35
|
+
|
|
36
|
+
onLoad( scope.parse( text ) );
|
|
37
|
+
|
|
38
|
+
}, onProgress, onError );
|
|
39
|
+
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
setCrossOrigin: function ( value ) {
|
|
43
|
+
|
|
44
|
+
this.crossOrigin = value;
|
|
45
|
+
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
parse: function ( data ) {
|
|
49
|
+
|
|
50
|
+
var texturePath = this.texturePath || '';
|
|
51
|
+
|
|
52
|
+
var textureLoader = new THREE.TextureLoader( this.manager );
|
|
53
|
+
textureLoader.setCrossOrigin( this.crossOrigin );
|
|
54
|
+
|
|
55
|
+
var parseV1 = function ( lines, scene ) {
|
|
56
|
+
|
|
57
|
+
console.warn( 'VRML V1.0 not supported yet' );
|
|
58
|
+
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
var parseV2 = function ( lines, scene ) {
|
|
62
|
+
|
|
63
|
+
var defines = {};
|
|
64
|
+
var float_pattern = /(\b|\-|\+)([\d\.e]+)/;
|
|
65
|
+
var float2_pattern = /([\d\.\+\-e]+)\s+([\d\.\+\-e]+)/g;
|
|
66
|
+
var float3_pattern = /([\d\.\+\-e]+)\s+([\d\.\+\-e]+)\s+([\d\.\+\-e]+)/g;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Interpolates colors a and b following their relative distance
|
|
70
|
+
* expressed by t.
|
|
71
|
+
*
|
|
72
|
+
* @param float a
|
|
73
|
+
* @param float b
|
|
74
|
+
* @param float t
|
|
75
|
+
* @returns {Color}
|
|
76
|
+
*/
|
|
77
|
+
var interpolateColors = function( a, b, t ) {
|
|
78
|
+
|
|
79
|
+
var deltaR = a.r - b.r;
|
|
80
|
+
var deltaG = a.g - b.g;
|
|
81
|
+
var deltaB = a.b - b.b;
|
|
82
|
+
|
|
83
|
+
var c = new THREE.Color();
|
|
84
|
+
|
|
85
|
+
c.r = a.r - t * deltaR;
|
|
86
|
+
c.g = a.g - t * deltaG;
|
|
87
|
+
c.b = a.b - t * deltaB;
|
|
88
|
+
|
|
89
|
+
return c;
|
|
90
|
+
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Vertically paints the faces interpolating between the
|
|
95
|
+
* specified colors at the specified angels. This is used for the Background
|
|
96
|
+
* node, but could be applied to other nodes with multiple faces as well.
|
|
97
|
+
*
|
|
98
|
+
* When used with the Background node, default is directionIsDown is true if
|
|
99
|
+
* interpolating the skyColor down from the Zenith. When interpolationg up from
|
|
100
|
+
* the Nadir i.e. interpolating the groundColor, the directionIsDown is false.
|
|
101
|
+
*
|
|
102
|
+
* The first angle is never specified, it is the Zenith (0 rad). Angles are specified
|
|
103
|
+
* in radians. The geometry is thought a sphere, but could be anything. The color interpolation
|
|
104
|
+
* is linear along the Y axis in any case.
|
|
105
|
+
*
|
|
106
|
+
* You must specify one more color than you have angles at the beginning of the colors array.
|
|
107
|
+
* This is the color of the Zenith (the top of the shape).
|
|
108
|
+
*
|
|
109
|
+
* @param geometry
|
|
110
|
+
* @param radius
|
|
111
|
+
* @param angles
|
|
112
|
+
* @param colors
|
|
113
|
+
* @param boolean directionIsDown Whether to work bottom up or top down.
|
|
114
|
+
*/
|
|
115
|
+
var paintFaces = function ( geometry, radius, angles, colors, directionIsDown ) {
|
|
116
|
+
|
|
117
|
+
var f, n, p, vertexIndex, color;
|
|
118
|
+
|
|
119
|
+
var direction = directionIsDown ? 1 : - 1;
|
|
120
|
+
|
|
121
|
+
var faceIndices = [ 'a', 'b', 'c', 'd' ];
|
|
122
|
+
|
|
123
|
+
var coord = [ ], aColor, bColor, t = 1, A = {}, B = {}, applyColor = false, colorIndex;
|
|
124
|
+
|
|
125
|
+
for ( var k = 0; k < angles.length; k ++ ) {
|
|
126
|
+
|
|
127
|
+
var vec = { };
|
|
128
|
+
|
|
129
|
+
// push the vector at which the color changes
|
|
130
|
+
vec.y = direction * ( Math.cos( angles[ k ] ) * radius );
|
|
131
|
+
|
|
132
|
+
vec.x = direction * ( Math.sin( angles[ k ] ) * radius );
|
|
133
|
+
|
|
134
|
+
coord.push( vec );
|
|
135
|
+
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// painting the colors on the faces
|
|
139
|
+
for ( var i = 0; i < geometry.faces.length ; i ++ ) {
|
|
140
|
+
|
|
141
|
+
f = geometry.faces[ i ];
|
|
142
|
+
|
|
143
|
+
n = ( f instanceof THREE.Face3 ) ? 3 : 4;
|
|
144
|
+
|
|
145
|
+
for ( var j = 0; j < n; j ++ ) {
|
|
146
|
+
|
|
147
|
+
vertexIndex = f[ faceIndices[ j ] ];
|
|
148
|
+
|
|
149
|
+
p = geometry.vertices[ vertexIndex ];
|
|
150
|
+
|
|
151
|
+
for ( var index = 0; index < colors.length; index ++ ) {
|
|
152
|
+
|
|
153
|
+
// linear interpolation between aColor and bColor, calculate proportion
|
|
154
|
+
// A is previous point (angle)
|
|
155
|
+
if ( index === 0 ) {
|
|
156
|
+
|
|
157
|
+
A.x = 0;
|
|
158
|
+
A.y = directionIsDown ? radius : - 1 * radius;
|
|
159
|
+
|
|
160
|
+
} else {
|
|
161
|
+
|
|
162
|
+
A.x = coord[ index - 1 ].x;
|
|
163
|
+
A.y = coord[ index - 1 ].y;
|
|
164
|
+
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// B is current point (angle)
|
|
168
|
+
B = coord[ index ];
|
|
169
|
+
|
|
170
|
+
if ( undefined !== B ) {
|
|
171
|
+
|
|
172
|
+
// p has to be between the points A and B which we interpolate
|
|
173
|
+
applyColor = directionIsDown ? p.y <= A.y && p.y > B.y : p.y >= A.y && p.y < B.y;
|
|
174
|
+
|
|
175
|
+
if ( applyColor ) {
|
|
176
|
+
|
|
177
|
+
bColor = colors[ index + 1 ];
|
|
178
|
+
|
|
179
|
+
aColor = colors[ index ];
|
|
180
|
+
|
|
181
|
+
// below is simple linear interpolation
|
|
182
|
+
t = Math.abs( p.y - A.y ) / ( A.y - B.y );
|
|
183
|
+
|
|
184
|
+
// to make it faster, you can only calculate this if the y coord changes, the color is the same for points with the same y
|
|
185
|
+
color = interpolateColors( aColor, bColor, t );
|
|
186
|
+
|
|
187
|
+
f.vertexColors[ j ] = color;
|
|
188
|
+
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
} else if ( undefined === f.vertexColors[ j ] ) {
|
|
192
|
+
|
|
193
|
+
colorIndex = directionIsDown ? colors.length - 1 : 0;
|
|
194
|
+
f.vertexColors[ j ] = colors[ colorIndex ];
|
|
195
|
+
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
var index = [];
|
|
207
|
+
|
|
208
|
+
var parseProperty = function ( node, line ) {
|
|
209
|
+
|
|
210
|
+
var parts = [], part, property = {}, fieldName;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Expression for matching relevant information, such as a name or value, but not the separators
|
|
214
|
+
* @type {RegExp}
|
|
215
|
+
*/
|
|
216
|
+
var regex = /[^\s,\[\]]+/g;
|
|
217
|
+
|
|
218
|
+
var point, angles, colors;
|
|
219
|
+
|
|
220
|
+
while ( null != ( part = regex.exec( line ) ) ) {
|
|
221
|
+
|
|
222
|
+
parts.push( part[ 0 ] );
|
|
223
|
+
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
fieldName = parts[ 0 ];
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
// trigger several recorders
|
|
230
|
+
switch ( fieldName ) {
|
|
231
|
+
case 'skyAngle':
|
|
232
|
+
case 'groundAngle':
|
|
233
|
+
this.recordingFieldname = fieldName;
|
|
234
|
+
this.isRecordingAngles = true;
|
|
235
|
+
this.angles = [];
|
|
236
|
+
break;
|
|
237
|
+
case 'skyColor':
|
|
238
|
+
case 'groundColor':
|
|
239
|
+
this.recordingFieldname = fieldName;
|
|
240
|
+
this.isRecordingColors = true;
|
|
241
|
+
this.colors = [];
|
|
242
|
+
break;
|
|
243
|
+
case 'point':
|
|
244
|
+
this.recordingFieldname = fieldName;
|
|
245
|
+
this.isRecordingPoints = true;
|
|
246
|
+
this.points = [];
|
|
247
|
+
break;
|
|
248
|
+
case 'coordIndex':
|
|
249
|
+
case 'texCoordIndex':
|
|
250
|
+
this.recordingFieldname = fieldName;
|
|
251
|
+
this.isRecordingFaces = true;
|
|
252
|
+
this.indexes = [];
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if ( this.isRecordingFaces ) {
|
|
256
|
+
|
|
257
|
+
// the parts hold the indexes as strings
|
|
258
|
+
if ( parts.length > 0 ) {
|
|
259
|
+
|
|
260
|
+
for ( var ind = 0; ind < parts.length; ind ++ ) {
|
|
261
|
+
|
|
262
|
+
// the part should either be positive integer or -1
|
|
263
|
+
if ( ! /(-?\d+)/.test( parts[ ind ] ) ) {
|
|
264
|
+
|
|
265
|
+
continue;
|
|
266
|
+
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// end of current face
|
|
270
|
+
if ( parts[ ind ] === "-1" ) {
|
|
271
|
+
|
|
272
|
+
if ( index.length > 0 ) {
|
|
273
|
+
|
|
274
|
+
this.indexes.push( index );
|
|
275
|
+
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// start new one
|
|
279
|
+
index = [];
|
|
280
|
+
|
|
281
|
+
} else {
|
|
282
|
+
|
|
283
|
+
index.push( parseInt( parts[ ind ] ) );
|
|
284
|
+
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// end
|
|
292
|
+
if ( /]/.exec( line ) ) {
|
|
293
|
+
|
|
294
|
+
if ( index.length > 0 ) {
|
|
295
|
+
|
|
296
|
+
this.indexes.push( index );
|
|
297
|
+
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// start new one
|
|
301
|
+
index = [];
|
|
302
|
+
|
|
303
|
+
this.isRecordingFaces = false;
|
|
304
|
+
node[this.recordingFieldname] = this.indexes;
|
|
305
|
+
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
} else if ( this.isRecordingPoints ) {
|
|
309
|
+
|
|
310
|
+
if ( node.nodeType == 'Coordinate' )
|
|
311
|
+
|
|
312
|
+
while ( null !== ( parts = float3_pattern.exec( line ) ) ) {
|
|
313
|
+
|
|
314
|
+
point = {
|
|
315
|
+
x: parseFloat( parts[ 1 ] ),
|
|
316
|
+
y: parseFloat( parts[ 2 ] ),
|
|
317
|
+
z: parseFloat( parts[ 3 ] )
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
this.points.push( point );
|
|
321
|
+
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if ( node.nodeType == 'TextureCoordinate' )
|
|
325
|
+
|
|
326
|
+
while ( null !== ( parts = float2_pattern.exec( line ) ) ) {
|
|
327
|
+
|
|
328
|
+
point = {
|
|
329
|
+
x: parseFloat( parts[ 1 ] ),
|
|
330
|
+
y: parseFloat( parts[ 2 ] )
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
this.points.push( point );
|
|
334
|
+
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// end
|
|
338
|
+
if ( /]/.exec( line ) ) {
|
|
339
|
+
|
|
340
|
+
this.isRecordingPoints = false;
|
|
341
|
+
node.points = this.points;
|
|
342
|
+
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
} else if ( this.isRecordingAngles ) {
|
|
346
|
+
|
|
347
|
+
// the parts hold the angles as strings
|
|
348
|
+
if ( parts.length > 0 ) {
|
|
349
|
+
|
|
350
|
+
for ( var ind = 0; ind < parts.length; ind ++ ) {
|
|
351
|
+
|
|
352
|
+
// the part should be a float
|
|
353
|
+
if ( ! float_pattern.test( parts[ ind ] ) ) {
|
|
354
|
+
|
|
355
|
+
continue;
|
|
356
|
+
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
this.angles.push( parseFloat( parts[ ind ] ) );
|
|
360
|
+
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// end
|
|
366
|
+
if ( /]/.exec( line ) ) {
|
|
367
|
+
|
|
368
|
+
this.isRecordingAngles = false;
|
|
369
|
+
node[ this.recordingFieldname ] = this.angles;
|
|
370
|
+
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
} else if ( this.isRecordingColors ) {
|
|
374
|
+
|
|
375
|
+
while ( null !== ( parts = float3_pattern.exec( line ) ) ) {
|
|
376
|
+
|
|
377
|
+
color = {
|
|
378
|
+
r: parseFloat( parts[ 1 ] ),
|
|
379
|
+
g: parseFloat( parts[ 2 ] ),
|
|
380
|
+
b: parseFloat( parts[ 3 ] )
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
this.colors.push( color );
|
|
384
|
+
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// end
|
|
388
|
+
if ( /]/.exec( line ) ) {
|
|
389
|
+
|
|
390
|
+
this.isRecordingColors = false;
|
|
391
|
+
node[ this.recordingFieldname ] = this.colors;
|
|
392
|
+
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
} else if ( parts[ parts.length - 1 ] !== 'NULL' && fieldName !== 'children' ) {
|
|
396
|
+
|
|
397
|
+
switch ( fieldName ) {
|
|
398
|
+
|
|
399
|
+
case 'diffuseColor':
|
|
400
|
+
case 'emissiveColor':
|
|
401
|
+
case 'specularColor':
|
|
402
|
+
case 'color':
|
|
403
|
+
|
|
404
|
+
if ( parts.length != 4 ) {
|
|
405
|
+
|
|
406
|
+
console.warn( 'Invalid color format detected for ' + fieldName );
|
|
407
|
+
break;
|
|
408
|
+
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
property = {
|
|
412
|
+
r: parseFloat( parts[ 1 ] ),
|
|
413
|
+
g: parseFloat( parts[ 2 ] ),
|
|
414
|
+
b: parseFloat( parts[ 3 ] )
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
break;
|
|
418
|
+
|
|
419
|
+
case 'translation':
|
|
420
|
+
case 'scale':
|
|
421
|
+
case 'size':
|
|
422
|
+
if ( parts.length != 4 ) {
|
|
423
|
+
|
|
424
|
+
console.warn( 'Invalid vector format detected for ' + fieldName );
|
|
425
|
+
break;
|
|
426
|
+
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
property = {
|
|
430
|
+
x: parseFloat( parts[ 1 ] ),
|
|
431
|
+
y: parseFloat( parts[ 2 ] ),
|
|
432
|
+
z: parseFloat( parts[ 3 ] )
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
break;
|
|
436
|
+
|
|
437
|
+
case 'radius':
|
|
438
|
+
case 'topRadius':
|
|
439
|
+
case 'bottomRadius':
|
|
440
|
+
case 'height':
|
|
441
|
+
case 'transparency':
|
|
442
|
+
case 'shininess':
|
|
443
|
+
case 'ambientIntensity':
|
|
444
|
+
if ( parts.length != 2 ) {
|
|
445
|
+
|
|
446
|
+
console.warn( 'Invalid single float value specification detected for ' + fieldName );
|
|
447
|
+
break;
|
|
448
|
+
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
property = parseFloat( parts[ 1 ] );
|
|
452
|
+
|
|
453
|
+
break;
|
|
454
|
+
|
|
455
|
+
case 'rotation':
|
|
456
|
+
if ( parts.length != 5 ) {
|
|
457
|
+
|
|
458
|
+
console.warn( 'Invalid quaternion format detected for ' + fieldName );
|
|
459
|
+
break;
|
|
460
|
+
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
property = {
|
|
464
|
+
x: parseFloat( parts[ 1 ] ),
|
|
465
|
+
y: parseFloat( parts[ 2 ] ),
|
|
466
|
+
z: parseFloat( parts[ 3 ] ),
|
|
467
|
+
w: parseFloat( parts[ 4 ] )
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
break;
|
|
471
|
+
|
|
472
|
+
case 'ccw':
|
|
473
|
+
case 'solid':
|
|
474
|
+
case 'colorPerVertex':
|
|
475
|
+
case 'convex':
|
|
476
|
+
if ( parts.length != 2 ) {
|
|
477
|
+
|
|
478
|
+
console.warn( 'Invalid format detected for ' + fieldName );
|
|
479
|
+
break;
|
|
480
|
+
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
property = parts[ 1 ] === 'TRUE' ? true : false;
|
|
484
|
+
|
|
485
|
+
break;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
node[ fieldName ] = property;
|
|
489
|
+
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return property;
|
|
493
|
+
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
var getTree = function ( lines ) {
|
|
497
|
+
|
|
498
|
+
var tree = { 'string': 'Scene', children: [] };
|
|
499
|
+
var current = tree;
|
|
500
|
+
var matches;
|
|
501
|
+
var specification;
|
|
502
|
+
|
|
503
|
+
for ( var i = 0; i < lines.length; i ++ ) {
|
|
504
|
+
|
|
505
|
+
var comment = '';
|
|
506
|
+
|
|
507
|
+
var line = lines[ i ];
|
|
508
|
+
|
|
509
|
+
// omit whitespace only lines
|
|
510
|
+
if ( null !== ( result = /^\s+?$/g.exec( line ) ) ) {
|
|
511
|
+
|
|
512
|
+
continue;
|
|
513
|
+
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
line = line.trim();
|
|
517
|
+
|
|
518
|
+
// skip empty lines
|
|
519
|
+
if ( line === '' ) {
|
|
520
|
+
|
|
521
|
+
continue;
|
|
522
|
+
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
if ( /#/.exec( line ) ) {
|
|
526
|
+
|
|
527
|
+
var parts = line.split( '#' );
|
|
528
|
+
|
|
529
|
+
// discard everything after the #, it is a comment
|
|
530
|
+
line = parts[ 0 ];
|
|
531
|
+
|
|
532
|
+
// well, let's also keep the comment
|
|
533
|
+
comment = parts[ 1 ];
|
|
534
|
+
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
if ( matches = /([^\s]*){1}(?:\s+)?{/.exec( line ) ) {
|
|
538
|
+
|
|
539
|
+
// first subpattern should match the Node name
|
|
540
|
+
|
|
541
|
+
var block = { 'nodeType' : matches[ 1 ], 'string': line, 'parent': current, 'children': [], 'comment' : comment };
|
|
542
|
+
current.children.push( block );
|
|
543
|
+
current = block;
|
|
544
|
+
|
|
545
|
+
if ( /}/.exec( line ) ) {
|
|
546
|
+
|
|
547
|
+
// example: geometry Box { size 1 1 1 } # all on the same line
|
|
548
|
+
specification = /{(.*)}/.exec( line )[ 1 ];
|
|
549
|
+
|
|
550
|
+
// todo: remove once new parsing is complete?
|
|
551
|
+
block.children.push( specification );
|
|
552
|
+
|
|
553
|
+
parseProperty( current, specification );
|
|
554
|
+
|
|
555
|
+
current = current.parent;
|
|
556
|
+
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
} else if ( /}/.exec( line ) ) {
|
|
560
|
+
|
|
561
|
+
current = current.parent;
|
|
562
|
+
|
|
563
|
+
} else if ( line !== '' ) {
|
|
564
|
+
|
|
565
|
+
parseProperty( current, line );
|
|
566
|
+
// todo: remove once new parsing is complete? we still do not parse geometry and appearance the new way
|
|
567
|
+
current.children.push( line );
|
|
568
|
+
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
return tree;
|
|
574
|
+
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
var parseNode = function ( data, parent ) {
|
|
578
|
+
|
|
579
|
+
// console.log( data );
|
|
580
|
+
|
|
581
|
+
if ( typeof data === 'string' ) {
|
|
582
|
+
|
|
583
|
+
if ( /USE/.exec( data ) ) {
|
|
584
|
+
|
|
585
|
+
var defineKey = /USE\s+?([^\s]+)/.exec( data )[ 1 ];
|
|
586
|
+
|
|
587
|
+
if ( undefined == defines[ defineKey ] ) {
|
|
588
|
+
|
|
589
|
+
console.warn( defineKey + ' is not defined.' );
|
|
590
|
+
|
|
591
|
+
} else {
|
|
592
|
+
|
|
593
|
+
if ( /appearance/.exec( data ) && defineKey ) {
|
|
594
|
+
|
|
595
|
+
parent.material = defines[ defineKey ].clone();
|
|
596
|
+
|
|
597
|
+
} else if ( /geometry/.exec( data ) && defineKey ) {
|
|
598
|
+
|
|
599
|
+
parent.geometry = defines[ defineKey ].clone();
|
|
600
|
+
|
|
601
|
+
// the solid property is not cloned with clone(), is only needed for VRML loading, so we need to transfer it
|
|
602
|
+
if ( undefined !== defines[ defineKey ].solid && defines[ defineKey ].solid === false ) {
|
|
603
|
+
|
|
604
|
+
parent.geometry.solid = false;
|
|
605
|
+
parent.material.side = THREE.DoubleSide;
|
|
606
|
+
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
} else if ( defineKey ) {
|
|
610
|
+
|
|
611
|
+
var object = defines[ defineKey ].clone();
|
|
612
|
+
parent.add( object );
|
|
613
|
+
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
return;
|
|
621
|
+
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
var object = parent;
|
|
625
|
+
|
|
626
|
+
if ( 'Transform' === data.nodeType || 'Group' === data.nodeType ) {
|
|
627
|
+
|
|
628
|
+
object = new THREE.Object3D();
|
|
629
|
+
|
|
630
|
+
if ( /DEF/.exec( data.string ) ) {
|
|
631
|
+
|
|
632
|
+
object.name = /DEF\s+([^\s]+)/.exec( data.string )[ 1 ];
|
|
633
|
+
defines[ object.name ] = object;
|
|
634
|
+
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if ( undefined !== data[ 'translation' ] ) {
|
|
638
|
+
|
|
639
|
+
var t = data.translation;
|
|
640
|
+
|
|
641
|
+
object.position.set( t.x, t.y, t.z );
|
|
642
|
+
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if ( undefined !== data.rotation ) {
|
|
646
|
+
|
|
647
|
+
var r = data.rotation;
|
|
648
|
+
|
|
649
|
+
object.quaternion.setFromAxisAngle( new THREE.Vector3( r.x, r.y, r.z ), r.w );
|
|
650
|
+
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
if ( undefined !== data.scale ) {
|
|
654
|
+
|
|
655
|
+
var s = data.scale;
|
|
656
|
+
|
|
657
|
+
object.scale.set( s.x, s.y, s.z );
|
|
658
|
+
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
parent.add( object );
|
|
662
|
+
|
|
663
|
+
} else if ( 'Shape' === data.nodeType ) {
|
|
664
|
+
|
|
665
|
+
object = new THREE.Mesh();
|
|
666
|
+
|
|
667
|
+
if ( /DEF/.exec( data.string ) ) {
|
|
668
|
+
|
|
669
|
+
object.name = /DEF\s+([^\s]+)/.exec( data.string )[ 1 ];
|
|
670
|
+
|
|
671
|
+
defines[ object.name ] = object;
|
|
672
|
+
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
parent.add( object );
|
|
676
|
+
|
|
677
|
+
} else if ( 'Background' === data.nodeType ) {
|
|
678
|
+
|
|
679
|
+
var segments = 20;
|
|
680
|
+
|
|
681
|
+
// sky (full sphere):
|
|
682
|
+
|
|
683
|
+
var radius = 2e4;
|
|
684
|
+
|
|
685
|
+
var skyGeometry = new THREE.SphereGeometry( radius, segments, segments );
|
|
686
|
+
var skyMaterial = new THREE.MeshBasicMaterial( { fog: false, side: THREE.BackSide } );
|
|
687
|
+
|
|
688
|
+
if ( data.skyColor.length > 1 ) {
|
|
689
|
+
|
|
690
|
+
paintFaces( skyGeometry, radius, data.skyAngle, data.skyColor, true );
|
|
691
|
+
|
|
692
|
+
skyMaterial.vertexColors = THREE.VertexColors
|
|
693
|
+
|
|
694
|
+
} else {
|
|
695
|
+
|
|
696
|
+
var color = data.skyColor[ 0 ];
|
|
697
|
+
skyMaterial.color.setRGB( color.r, color.b, color.g );
|
|
698
|
+
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
scene.add( new THREE.Mesh( skyGeometry, skyMaterial ) );
|
|
702
|
+
|
|
703
|
+
// ground (half sphere):
|
|
704
|
+
|
|
705
|
+
if ( data.groundColor !== undefined ) {
|
|
706
|
+
|
|
707
|
+
radius = 1.2e4;
|
|
708
|
+
|
|
709
|
+
var groundGeometry = new THREE.SphereGeometry( radius, segments, segments, 0, 2 * Math.PI, 0.5 * Math.PI, 1.5 * Math.PI );
|
|
710
|
+
var groundMaterial = new THREE.MeshBasicMaterial( { fog: false, side: THREE.BackSide, vertexColors: THREE.VertexColors } );
|
|
711
|
+
|
|
712
|
+
paintFaces( groundGeometry, radius, data.groundAngle, data.groundColor, false );
|
|
713
|
+
|
|
714
|
+
scene.add( new THREE.Mesh( groundGeometry, groundMaterial ) );
|
|
715
|
+
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
} else if ( /geometry/.exec( data.string ) ) {
|
|
719
|
+
|
|
720
|
+
if ( 'Box' === data.nodeType ) {
|
|
721
|
+
|
|
722
|
+
var s = data.size;
|
|
723
|
+
|
|
724
|
+
parent.geometry = new THREE.BoxGeometry( s.x, s.y, s.z );
|
|
725
|
+
|
|
726
|
+
} else if ( 'Cylinder' === data.nodeType ) {
|
|
727
|
+
|
|
728
|
+
parent.geometry = new THREE.CylinderGeometry( data.radius, data.radius, data.height );
|
|
729
|
+
|
|
730
|
+
} else if ( 'Cone' === data.nodeType ) {
|
|
731
|
+
|
|
732
|
+
parent.geometry = new THREE.CylinderGeometry( data.topRadius, data.bottomRadius, data.height );
|
|
733
|
+
|
|
734
|
+
} else if ( 'Sphere' === data.nodeType ) {
|
|
735
|
+
|
|
736
|
+
parent.geometry = new THREE.SphereGeometry( data.radius );
|
|
737
|
+
|
|
738
|
+
} else if ( 'IndexedFaceSet' === data.nodeType ) {
|
|
739
|
+
|
|
740
|
+
var geometry = new THREE.Geometry();
|
|
741
|
+
|
|
742
|
+
var indexes, uvIndexes, uvs;
|
|
743
|
+
|
|
744
|
+
for ( var i = 0, j = data.children.length; i < j; i ++ ) {
|
|
745
|
+
|
|
746
|
+
var child = data.children[ i ];
|
|
747
|
+
|
|
748
|
+
var vec;
|
|
749
|
+
|
|
750
|
+
if ( 'TextureCoordinate' === child.nodeType ) {
|
|
751
|
+
|
|
752
|
+
uvs = child.points;
|
|
753
|
+
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
if ( 'Coordinate' === child.nodeType ) {
|
|
758
|
+
|
|
759
|
+
if ( child.points ) {
|
|
760
|
+
|
|
761
|
+
for ( var k = 0, l = child.points.length; k < l; k ++ ) {
|
|
762
|
+
|
|
763
|
+
var point = child.points[ k ];
|
|
764
|
+
|
|
765
|
+
vec = new THREE.Vector3( point.x, point.y, point.z );
|
|
766
|
+
|
|
767
|
+
geometry.vertices.push( vec );
|
|
768
|
+
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
if ( child.string.indexOf ( 'DEF' ) > -1 ) {
|
|
774
|
+
|
|
775
|
+
var name = /DEF\s+([^\s]+)/.exec( child.string )[ 1 ];
|
|
776
|
+
|
|
777
|
+
defines[ name ] = geometry.vertices;
|
|
778
|
+
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
if ( child.string.indexOf ( 'USE' ) > -1 ) {
|
|
782
|
+
|
|
783
|
+
var defineKey = /USE\s+([^\s]+)/.exec( child.string )[ 1 ];
|
|
784
|
+
|
|
785
|
+
geometry.vertices = defines[ defineKey ];
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
var skip = 0;
|
|
793
|
+
|
|
794
|
+
// some shapes only have vertices for use in other shapes
|
|
795
|
+
if ( data.coordIndex ) {
|
|
796
|
+
|
|
797
|
+
// read this: http://math.hws.edu/eck/cs424/notes2013/16_Threejs_Advanced.html
|
|
798
|
+
for ( var i = 0, j = data.coordIndex.length; i < j; i ++ ) {
|
|
799
|
+
|
|
800
|
+
indexes = data.coordIndex[ i ]; if ( data.texCoordIndex ) uvIndexes = data.texCoordIndex[ i ];
|
|
801
|
+
|
|
802
|
+
// vrml support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here
|
|
803
|
+
skip = 0;
|
|
804
|
+
|
|
805
|
+
// Face3 only works with triangles, but IndexedFaceSet allows shapes with more then three vertices, build them of triangles
|
|
806
|
+
while ( indexes.length >= 3 && skip < ( indexes.length - 2 ) ) {
|
|
807
|
+
|
|
808
|
+
var face = new THREE.Face3(
|
|
809
|
+
indexes[ 0 ],
|
|
810
|
+
indexes[ skip + (data.ccw ? 1 : 2) ],
|
|
811
|
+
indexes[ skip + (data.ccw ? 2 : 1) ],
|
|
812
|
+
null // normal, will be added later
|
|
813
|
+
// todo: pass in the color, if a color index is present
|
|
814
|
+
);
|
|
815
|
+
|
|
816
|
+
if ( uvs && uvIndexes ) {
|
|
817
|
+
geometry.faceVertexUvs [0].push( [
|
|
818
|
+
new THREE.Vector2 (
|
|
819
|
+
uvs[ uvIndexes[ 0 ] ].x ,
|
|
820
|
+
uvs[ uvIndexes[ 0 ] ].y
|
|
821
|
+
) ,
|
|
822
|
+
new THREE.Vector2 (
|
|
823
|
+
uvs[ uvIndexes[ skip + (data.ccw ? 1 : 2) ] ].x ,
|
|
824
|
+
uvs[ uvIndexes[ skip + (data.ccw ? 1 : 2) ] ].y
|
|
825
|
+
) ,
|
|
826
|
+
new THREE.Vector2 (
|
|
827
|
+
uvs[ uvIndexes[ skip + (data.ccw ? 2 : 1) ] ].x ,
|
|
828
|
+
uvs[ uvIndexes[ skip + (data.ccw ? 2 : 1) ] ].y
|
|
829
|
+
)
|
|
830
|
+
] );
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
skip ++;
|
|
834
|
+
|
|
835
|
+
geometry.faces.push( face );
|
|
836
|
+
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
} else {
|
|
843
|
+
|
|
844
|
+
// do not add dummy mesh to the scene
|
|
845
|
+
parent.parent.remove( parent );
|
|
846
|
+
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
if ( false === data.solid ) {
|
|
850
|
+
|
|
851
|
+
parent.material.side = THREE.DoubleSide;
|
|
852
|
+
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// we need to store it on the geometry for use with defines
|
|
856
|
+
geometry.solid = data.solid;
|
|
857
|
+
|
|
858
|
+
geometry.computeFaceNormals();
|
|
859
|
+
//geometry.computeVertexNormals(); // does not show
|
|
860
|
+
geometry.computeBoundingSphere();
|
|
861
|
+
|
|
862
|
+
// see if it's a define
|
|
863
|
+
if ( /DEF/.exec( data.string ) ) {
|
|
864
|
+
|
|
865
|
+
geometry.name = /DEF ([^\s]+)/.exec( data.string )[ 1 ];
|
|
866
|
+
defines[ geometry.name ] = geometry;
|
|
867
|
+
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
parent.geometry = geometry;
|
|
871
|
+
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
return;
|
|
875
|
+
|
|
876
|
+
} else if ( /appearance/.exec( data.string ) ) {
|
|
877
|
+
|
|
878
|
+
for ( var i = 0; i < data.children.length; i ++ ) {
|
|
879
|
+
|
|
880
|
+
var child = data.children[ i ];
|
|
881
|
+
|
|
882
|
+
if ( 'Material' === child.nodeType ) {
|
|
883
|
+
|
|
884
|
+
var material = new THREE.MeshPhongMaterial();
|
|
885
|
+
|
|
886
|
+
if ( undefined !== child.diffuseColor ) {
|
|
887
|
+
|
|
888
|
+
var d = child.diffuseColor;
|
|
889
|
+
|
|
890
|
+
material.color.setRGB( d.r, d.g, d.b );
|
|
891
|
+
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
if ( undefined !== child.emissiveColor ) {
|
|
895
|
+
|
|
896
|
+
var e = child.emissiveColor;
|
|
897
|
+
|
|
898
|
+
material.emissive.setRGB( e.r, e.g, e.b );
|
|
899
|
+
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
if ( undefined !== child.specularColor ) {
|
|
903
|
+
|
|
904
|
+
var s = child.specularColor;
|
|
905
|
+
|
|
906
|
+
material.specular.setRGB( s.r, s.g, s.b );
|
|
907
|
+
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
if ( undefined !== child.transparency ) {
|
|
911
|
+
|
|
912
|
+
var t = child.transparency;
|
|
913
|
+
|
|
914
|
+
// transparency is opposite of opacity
|
|
915
|
+
material.opacity = Math.abs( 1 - t );
|
|
916
|
+
|
|
917
|
+
material.transparent = true;
|
|
918
|
+
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
if ( /DEF/.exec( data.string ) ) {
|
|
922
|
+
|
|
923
|
+
material.name = /DEF ([^\s]+)/.exec( data.string )[ 1 ];
|
|
924
|
+
|
|
925
|
+
defines[ material.name ] = material;
|
|
926
|
+
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
parent.material = material;
|
|
930
|
+
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
if ( 'ImageTexture' === child.nodeType ) {
|
|
934
|
+
|
|
935
|
+
var textureName = /"([^"]+)"/.exec(child.children[ 0 ]);
|
|
936
|
+
|
|
937
|
+
if (textureName) {
|
|
938
|
+
|
|
939
|
+
parent.material.name = textureName[ 1 ];
|
|
940
|
+
|
|
941
|
+
parent.material.map = textureLoader.load( texturePath + textureName[ 1 ] );
|
|
942
|
+
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
return;
|
|
950
|
+
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
for ( var i = 0, l = data.children.length; i < l; i ++ ) {
|
|
954
|
+
|
|
955
|
+
var child = data.children[ i ];
|
|
956
|
+
|
|
957
|
+
parseNode( data.children[ i ], object );
|
|
958
|
+
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
};
|
|
962
|
+
|
|
963
|
+
parseNode( getTree( lines ), scene );
|
|
964
|
+
|
|
965
|
+
};
|
|
966
|
+
|
|
967
|
+
var scene = new THREE.Scene();
|
|
968
|
+
|
|
969
|
+
var lines = data.split( '\n' );
|
|
970
|
+
|
|
971
|
+
// some lines do not have breaks
|
|
972
|
+
for (var i = lines.length -1; i > -1; i--) {
|
|
973
|
+
|
|
974
|
+
// split lines with {..{ or {..[ - some have both
|
|
975
|
+
if (/{.*[{\[]/.test (lines[i])) {
|
|
976
|
+
var parts = lines[i].split ('{').join ('{\n').split ('\n');
|
|
977
|
+
parts.unshift(1);
|
|
978
|
+
parts.unshift(i);
|
|
979
|
+
lines.splice.apply(lines, parts);
|
|
980
|
+
} else
|
|
981
|
+
|
|
982
|
+
// split lines with ]..}
|
|
983
|
+
if (/\].*}/.test (lines[i])) {
|
|
984
|
+
var parts = lines[i].split (']').join (']\n').split ('\n');
|
|
985
|
+
parts.unshift(1);
|
|
986
|
+
parts.unshift(i);
|
|
987
|
+
lines.splice.apply(lines, parts);
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
// split lines with }..}
|
|
991
|
+
if (/}.*}/.test (lines[i])) {
|
|
992
|
+
var parts = lines[i].split ('}').join ('}\n').split ('\n');
|
|
993
|
+
parts.unshift(1);
|
|
994
|
+
parts.unshift(i);
|
|
995
|
+
lines.splice.apply(lines, parts);
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
// force the parser to create Coordinate node for empty coords
|
|
999
|
+
// coord USE something -> coord USE something Coordinate {}
|
|
1000
|
+
if((lines[i].indexOf ('coord') > -1) && (lines[i].indexOf ('[') < 0) && (lines[i].indexOf ('{') < 0)) {
|
|
1001
|
+
lines[i] += ' Coordinate {}';
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
var header = lines.shift();
|
|
1006
|
+
|
|
1007
|
+
if ( /V1.0/.exec( header ) ) {
|
|
1008
|
+
|
|
1009
|
+
parseV1( lines, scene );
|
|
1010
|
+
|
|
1011
|
+
} else if ( /V2.0/.exec( header ) ) {
|
|
1012
|
+
|
|
1013
|
+
parseV2( lines, scene );
|
|
1014
|
+
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
return scene;
|
|
1018
|
+
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
};
|