|
@@ -8,6 +8,14 @@ THREE.VRMLLoader.prototype = {
|
|
|
|
|
|
constructor: THREE.VRMLLoader,
|
|
constructor: THREE.VRMLLoader,
|
|
|
|
|
|
|
|
+ isRecordingPoints: false,
|
|
|
|
+
|
|
|
|
+ isRecordingFaces: false,
|
|
|
|
+
|
|
|
|
+ points: [],
|
|
|
|
+
|
|
|
|
+ indexes : [],
|
|
|
|
+
|
|
load: function ( url, callback ) {
|
|
load: function ( url, callback ) {
|
|
|
|
|
|
var scope = this;
|
|
var scope = this;
|
|
@@ -47,12 +55,192 @@ THREE.VRMLLoader.prototype = {
|
|
};
|
|
};
|
|
|
|
|
|
var parseV2 = function ( lines, scene ) {
|
|
var parseV2 = function ( lines, scene ) {
|
|
|
|
+ var defines = {};
|
|
|
|
+ var float3_pattern = /([\d\.\+\-e]+),?\s+([\d\.\+\-e]+),?\s+([\d\.\+\-e]+)/;
|
|
|
|
+
|
|
|
|
+ var parseProperty = function (node, line) {
|
|
|
|
+
|
|
|
|
+ var parts = [];
|
|
|
|
+ var part;
|
|
|
|
+ var property = {};
|
|
|
|
+ var fieldName;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Expression for matching relevant information, such as a name or value, but not the separators
|
|
|
|
+ * @type {RegExp}
|
|
|
|
+ */
|
|
|
|
+ var regex = /[^\s,\[\]]+/g;
|
|
|
|
+ var point;
|
|
|
|
+ var index;
|
|
|
|
+
|
|
|
|
+ while (null != ( part = regex.exec(line) ) ) {
|
|
|
|
+ parts.push(part[0]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fieldName = parts[0];
|
|
|
|
+
|
|
|
|
+ if (fieldName === 'point') {
|
|
|
|
+ // start recording points
|
|
|
|
+ this.isRecordingPoints = true;
|
|
|
|
+ this.points = [];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (fieldName === 'coordIndex') {
|
|
|
|
+ // start recording faces
|
|
|
|
+ this.isRecordingFaces = true;
|
|
|
|
+ this.indexes = [];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (this.isRecordingFaces) {
|
|
|
|
+
|
|
|
|
+ // the parts hold the indexes as strings
|
|
|
|
+ if (parts.length > 0) {
|
|
|
|
+ index = [];
|
|
|
|
+
|
|
|
|
+ for (var ind = 0;ind < parts.length; ind++) {
|
|
|
|
+
|
|
|
|
+ // the part should either be positive integer or -1
|
|
|
|
+ if (!/(-?\d+)/.test( parts[ind]) ) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // end of current face
|
|
|
|
+ if (parts[ind] === "-1") {
|
|
|
|
+ if (index.length > 0) {
|
|
|
|
+ this.indexes.push(index);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // start new one
|
|
|
|
+ index = [];
|
|
|
|
+ } else {
|
|
|
|
+ index.push(parseInt( parts[ind]) );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // end
|
|
|
|
+ if (/]/.exec(line)) {
|
|
|
|
+ this.isRecordingFaces = false;
|
|
|
|
+ node.coordIndex = this.indexes;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else if (this.isRecordingPoints) {
|
|
|
|
+
|
|
|
|
+ parts = float3_pattern.exec(line);
|
|
|
|
+
|
|
|
|
+ // parts may be empty on first and last line
|
|
|
|
+ if (null != parts) {
|
|
|
|
+ point = {
|
|
|
|
+ x: parseFloat(parts[1]),
|
|
|
|
+ y: parseFloat(parts[2]),
|
|
|
|
+ z: parseFloat(parts[3])
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ this.points.push(point);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // end
|
|
|
|
+ if (/]/.exec(line)) {
|
|
|
|
+ this.isRecordingPoints = false;
|
|
|
|
+ node.points = this.points;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else if ( parts[parts.length -1] !== 'NULL' && fieldName !== 'children') {
|
|
|
|
+
|
|
|
|
+ switch (fieldName) {
|
|
|
|
+
|
|
|
|
+ case 'diffuseColor':
|
|
|
|
+ case 'emissiveColor':
|
|
|
|
+ case 'specularColor':
|
|
|
|
+ case 'color':
|
|
|
|
+
|
|
|
|
+ if (parts.length != 4) {
|
|
|
|
+ console.warn('Invalid color format detected for ' + fieldName );
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ property = {
|
|
|
|
+ 'r' : parseFloat(parts[1]),
|
|
|
|
+ 'g' : parseFloat(parts[2]),
|
|
|
|
+ 'b' : parseFloat(parts[3])
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'translation':
|
|
|
|
+ case 'scale':
|
|
|
|
+ case 'size':
|
|
|
|
+ if (parts.length != 4) {
|
|
|
|
+ console.warn('Invalid vector format detected for ' + fieldName);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ property = {
|
|
|
|
+ 'x' : parseFloat(parts[1]),
|
|
|
|
+ 'y' : parseFloat(parts[2]),
|
|
|
|
+ 'z' : parseFloat(parts[3])
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'radius':
|
|
|
|
+ case 'topRadius':
|
|
|
|
+ case 'bottomRadius':
|
|
|
|
+ case 'height':
|
|
|
|
+ case 'transparency':
|
|
|
|
+ case 'shininess':
|
|
|
|
+ case 'ambientIntensity':
|
|
|
|
+ if (parts.length != 2) {
|
|
|
|
+ console.warn('Invalid single float value specification detected for ' + fieldName);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ property = parseFloat(parts[1]);
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'rotation':
|
|
|
|
+ if (parts.length != 5) {
|
|
|
|
+ console.warn('Invalid quaternion format detected for ' + fieldName);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ property = {
|
|
|
|
+ 'x' : parseFloat(parts[1]),
|
|
|
|
+ 'y' : parseFloat(parts[2]),
|
|
|
|
+ 'z' : parseFloat(parts[3]),
|
|
|
|
+ 'w' : parseFloat(parts[4])
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'ccw':
|
|
|
|
+ case 'solid':
|
|
|
|
+ case 'colorPerVertex':
|
|
|
|
+ case 'convex':
|
|
|
|
+ if (parts.length != 2) {
|
|
|
|
+ console.warn('Invalid format detected for ' + fieldName);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ property = parts[1] === 'TRUE' ? true : false;
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ node[fieldName] = property;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return property;
|
|
|
|
+ };
|
|
|
|
|
|
var getTree = function ( lines ) {
|
|
var getTree = function ( lines ) {
|
|
|
|
|
|
var tree = { 'string': 'Scene', children: [] };
|
|
var tree = { 'string': 'Scene', children: [] };
|
|
var current = tree;
|
|
var current = tree;
|
|
var matches;
|
|
var matches;
|
|
|
|
+ var specification;
|
|
|
|
|
|
for ( var i = 0; i < lines.length; i ++ ) {
|
|
for ( var i = 0; i < lines.length; i ++ ) {
|
|
|
|
|
|
@@ -65,6 +253,13 @@ THREE.VRMLLoader.prototype = {
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ line = line.trim();
|
|
|
|
+
|
|
|
|
+ // skip empty lines
|
|
|
|
+ if (line === '') {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
if ( /#/.exec( line ) ) {
|
|
if ( /#/.exec( line ) ) {
|
|
|
|
|
|
var parts = line.split('#');
|
|
var parts = line.split('#');
|
|
@@ -75,16 +270,22 @@ THREE.VRMLLoader.prototype = {
|
|
// well, let's also keep the comment
|
|
// well, let's also keep the comment
|
|
comment = parts[1];
|
|
comment = parts[1];
|
|
}
|
|
}
|
|
- // todo: add collection like coordIndex and colorIndex who are delimited by [ ]
|
|
|
|
|
|
+
|
|
if ( matches = /([^\s]*){1}\s?{/.exec( line ) ) { // first subpattern should match the Node name
|
|
if ( matches = /([^\s]*){1}\s?{/.exec( line ) ) { // first subpattern should match the Node name
|
|
|
|
|
|
- var block = { 'nodeType' : matches[1], 'string': line, 'parent': current, 'children': [],'comment' : comment };
|
|
|
|
|
|
+ var block = { 'nodeType' : matches[1], 'string': line, 'parent': current, 'children': [],'comment' : comment};
|
|
current.children.push( block );
|
|
current.children.push( block );
|
|
current = block;
|
|
current = block;
|
|
|
|
|
|
if ( /}/.exec( line ) ) {
|
|
if ( /}/.exec( line ) ) {
|
|
|
|
+ // example: geometry Box { size 1 1 1 } # all on the same line
|
|
|
|
+ specification = /{(.*)}/.exec( line )[ 1 ];
|
|
|
|
+
|
|
|
|
+ // todo: remove once new parsing is complete?
|
|
|
|
+ block.children.push( specification );
|
|
|
|
+
|
|
|
|
+ parseProperty(current, specification);
|
|
|
|
|
|
- block.children.push( /{(.*)}/.exec( line )[ 1 ] );
|
|
|
|
current = current.parent;
|
|
current = current.parent;
|
|
|
|
|
|
}
|
|
}
|
|
@@ -95,6 +296,8 @@ THREE.VRMLLoader.prototype = {
|
|
|
|
|
|
} else if ( line !== '' ) {
|
|
} else if ( line !== '' ) {
|
|
|
|
|
|
|
|
+ parseProperty(current, line);
|
|
|
|
+ // todo: remove once new parsing is complete?
|
|
current.children.push( line );
|
|
current.children.push( line );
|
|
|
|
|
|
}
|
|
}
|
|
@@ -102,14 +305,8 @@ THREE.VRMLLoader.prototype = {
|
|
}
|
|
}
|
|
|
|
|
|
return tree;
|
|
return tree;
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- var defines = {};
|
|
|
|
- var float_pattern = /\s+([\d|\.|\+|\-|e]+)/;
|
|
|
|
- var float3_pattern = /\s+([\d|\.|\+|\-|e]+),?\s+([\d|\.|\+|\-|e]+),?\s+([\d|\.|\+|\-|e]+)/;
|
|
|
|
- var float4_pattern = /\s+([\d|\.|\+|\-|e]+),?\s+([\d|\.|\+|\-|e]+),?\s+([\d|\.|\+|\-|e]+),?\s+([\d|\.|\+|\-|e]+)/;
|
|
|
|
-
|
|
|
|
var parseNode = function ( data, parent ) {
|
|
var parseNode = function ( data, parent ) {
|
|
|
|
|
|
// console.log( data );
|
|
// console.log( data );
|
|
@@ -121,20 +318,25 @@ THREE.VRMLLoader.prototype = {
|
|
var defineKey = /USE\s+?(\w+)/.exec( data )[ 1 ];
|
|
var defineKey = /USE\s+?(\w+)/.exec( data )[ 1 ];
|
|
|
|
|
|
if (undefined == defines[defineKey]) {
|
|
if (undefined == defines[defineKey]) {
|
|
- debugger;
|
|
|
|
console.warn(defineKey + ' is not defined.');
|
|
console.warn(defineKey + ' is not defined.');
|
|
-
|
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
if ( /appearance/.exec( data ) && defineKey ) {
|
|
if ( /appearance/.exec( data ) && defineKey ) {
|
|
|
|
|
|
- parent.material = defines[ defineKey].clone();
|
|
|
|
|
|
+ parent.material = defines[ defineKey ].clone();
|
|
|
|
|
|
} else if ( /geometry/.exec( data ) && defineKey ) {
|
|
} else if ( /geometry/.exec( data ) && defineKey ) {
|
|
|
|
|
|
- parent.geometry = defines[ defineKey].clone();
|
|
|
|
|
|
+ parent.geometry = defines[ defineKey ].clone();
|
|
|
|
+
|
|
|
|
+ // the solid property is not cloned with clone(), is only needed for VRML loading, so we need to transfer it
|
|
|
|
+ if (undefined !== defines[ defineKey ].solid && defines[ defineKey ].solid === false) {
|
|
|
|
+ parent.geometry.solid = false;
|
|
|
|
+ parent.material.side = THREE.DoubleSide;
|
|
|
|
+ }
|
|
|
|
|
|
} else if (defineKey){
|
|
} else if (defineKey){
|
|
|
|
+
|
|
var object = defines[ defineKey ].clone();
|
|
var object = defines[ defineKey ].clone();
|
|
parent.add( object );
|
|
parent.add( object );
|
|
|
|
|
|
@@ -150,59 +352,42 @@ THREE.VRMLLoader.prototype = {
|
|
|
|
|
|
var object = parent;
|
|
var object = parent;
|
|
|
|
|
|
- if ( /Transform/.exec( data.string ) || /Group/.exec( data.string ) ) {
|
|
|
|
|
|
+ if ( 'Transform' === data.nodeType || 'Group' === data.nodeType ) {
|
|
|
|
+
|
|
object = new THREE.Object3D();
|
|
object = new THREE.Object3D();
|
|
|
|
|
|
if ( /DEF/.exec( data.string ) ) {
|
|
if ( /DEF/.exec( data.string ) ) {
|
|
-
|
|
|
|
object.name = /DEF\s+(\w+)/.exec( data.string )[ 1 ];
|
|
object.name = /DEF\s+(\w+)/.exec( data.string )[ 1 ];
|
|
defines[ object.name ] = object;
|
|
defines[ object.name ] = object;
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- for ( var i = 0, j = data.children.length; i < j; i ++ ) {
|
|
|
|
|
|
+ if ( undefined !== data['translation'] ) {
|
|
|
|
|
|
- var child = data.children[ i ];
|
|
|
|
-
|
|
|
|
- if ( /translation/.exec( child ) ) {
|
|
|
|
|
|
+ var t = data.translation;
|
|
|
|
|
|
- var result = float3_pattern.exec( child );
|
|
|
|
|
|
+ object.position.set(t.x, t.y, t.z);
|
|
|
|
|
|
- object.position.set(
|
|
|
|
- parseFloat( result[ 1 ] ),
|
|
|
|
- parseFloat( result[ 2 ] ),
|
|
|
|
- parseFloat( result[ 3 ] )
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- } else if ( /rotation/.exec( child ) ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var result = float4_pattern.exec( child );
|
|
|
|
|
|
+ if ( undefined !== data.rotation ) {
|
|
|
|
|
|
- var quaternion = new THREE.Quaternion();
|
|
|
|
|
|
+ var r = data.rotation;
|
|
|
|
|
|
- var x = parseFloat( result[ 1 ] );
|
|
|
|
- var y = parseFloat(result[ 2 ]);
|
|
|
|
- var z = parseFloat(result[ 3 ]);
|
|
|
|
- var w = parseFloat(result[ 4 ]);
|
|
|
|
|
|
+ object.quaternion.setFromAxisAngle( new THREE.Vector3( r.x, r.y, r.z ), r.w );
|
|
|
|
|
|
- object.quaternion.setFromAxisAngle( new THREE.Vector3( x, y, z), w );
|
|
|
|
- } else if ( /scale/.exec( child ) ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var result = float3_pattern.exec( child );
|
|
|
|
|
|
+ if ( undefined !== data.scale ) {
|
|
|
|
|
|
- object.scale.set(
|
|
|
|
- parseFloat( result[ 1 ] ),
|
|
|
|
- parseFloat( result[ 2 ] ),
|
|
|
|
- parseFloat( result[ 3 ] )
|
|
|
|
- );
|
|
|
|
|
|
+ var s = data.scale;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ object.scale.set( s.x, s.y, s.z );
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
|
|
parent.add( object );
|
|
parent.add( object );
|
|
|
|
|
|
- } else if ( /Shape/.exec( data.string ) ) {
|
|
|
|
|
|
+ } else if ( 'Shape' === data.nodeType ) {
|
|
|
|
|
|
object = new THREE.Mesh();
|
|
object = new THREE.Mesh();
|
|
|
|
|
|
@@ -213,159 +398,95 @@ THREE.VRMLLoader.prototype = {
|
|
|
|
|
|
parent.add( object );
|
|
parent.add( object );
|
|
|
|
|
|
- } else if ( /geometry/.exec( data.string ) ) {
|
|
|
|
-
|
|
|
|
- if ( /Box/.exec( data.string ) ) {
|
|
|
|
-
|
|
|
|
- var width = 1, height = 1, depth = 1;
|
|
|
|
-
|
|
|
|
- for ( var i = 0, j = data.children.length; i < j; i ++ ) {
|
|
|
|
-
|
|
|
|
- var child = data.children[ i ];
|
|
|
|
-
|
|
|
|
- if ( /size/.exec( child ) ) {
|
|
|
|
-
|
|
|
|
- var result = float3_pattern.exec( child );
|
|
|
|
-
|
|
|
|
- width = parseFloat( result[ 1 ] );
|
|
|
|
- height = parseFloat( result[ 2 ] );
|
|
|
|
- depth = parseFloat( result[ 3 ] );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- parent.geometry = new THREE.CubeGeometry( width, height, depth );
|
|
|
|
-
|
|
|
|
- } else if ( /Cylinder/.exec( data.string ) ) {
|
|
|
|
-
|
|
|
|
- var radius = 1, height = 1;
|
|
|
|
-
|
|
|
|
- for ( var i = 0, j = data.children.length; i < j; i ++ ) {
|
|
|
|
-
|
|
|
|
- var child = data.children[ i ];
|
|
|
|
|
|
+ } else if ( 'Background' === data.nodeType ) {
|
|
|
|
|
|
- if ( /radius/.exec( child ) ) {
|
|
|
|
|
|
+ console.warn('Implement hemisphere light here');
|
|
|
|
|
|
- radius = parseFloat( float_pattern.exec( child )[ 1 ] );
|
|
|
|
-
|
|
|
|
- } else if ( /height/.exec( child ) ) {
|
|
|
|
-
|
|
|
|
- height = parseFloat( float_pattern.exec( child )[ 1 ] );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- parent.geometry = new THREE.CylinderGeometry( radius, radius, height );
|
|
|
|
-
|
|
|
|
- } else if ( /Cone/.exec( data.string ) ) {
|
|
|
|
-
|
|
|
|
- var topRadius = 0, bottomRadius = 1, height = 1;
|
|
|
|
-
|
|
|
|
- for ( var i = 0, j = data.children.length; i < j; i ++ ) {
|
|
|
|
-
|
|
|
|
- var child = data.children[ i ];
|
|
|
|
-
|
|
|
|
- if ( /bottomRadius/.exec( child ) ) {
|
|
|
|
|
|
+ } else if ( /geometry/.exec( data.string ) ) {
|
|
|
|
|
|
- bottomRadius = parseFloat( float_pattern.exec( child )[ 1 ] );
|
|
|
|
|
|
+ if ( 'Box' === data.nodeType ) {
|
|
|
|
|
|
- } else if ( /height/.exec( child ) ) {
|
|
|
|
|
|
+ var s = data.size;
|
|
|
|
|
|
- height = parseFloat( float_pattern.exec( child )[ 1 ] );
|
|
|
|
|
|
+ parent.geometry = new THREE.CubeGeometry( s.x, s.y, s.z );
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ } else if ( 'Cylinder' === data.nodeType ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ parent.geometry = new THREE.CylinderGeometry( data.radius, data.radius, data.height );
|
|
|
|
|
|
- parent.geometry = new THREE.CylinderGeometry( topRadius, bottomRadius, height );
|
|
|
|
|
|
+ } else if ( 'Cone' === data.nodeType ) {
|
|
|
|
|
|
- } else if ( /Sphere/.exec( data.string ) ) {
|
|
|
|
|
|
+ parent.geometry = new THREE.CylinderGeometry( data.topRadius, data.bottomRadius, data.height );
|
|
|
|
|
|
- var result = /radius\s+([\d|\.|\+|\-|e]+)/.exec( data.children[ 0 ] );
|
|
|
|
|
|
+ } else if ( 'Sphere' === data.nodeType ) {
|
|
|
|
|
|
- parent.geometry = new THREE.SphereGeometry( parseFloat( result[ 1 ] ) );
|
|
|
|
|
|
+ parent.geometry = new THREE.SphereGeometry( data.radius );
|
|
|
|
|
|
- } else if ( /IndexedFaceSet/.exec( data.string ) ) {
|
|
|
|
|
|
+ } else if ( 'IndexedFaceSet' === data.nodeType ) {
|
|
|
|
|
|
var geometry = new THREE.Geometry();
|
|
var geometry = new THREE.Geometry();
|
|
|
|
|
|
- var isRecordingCoordinates = false;
|
|
|
|
|
|
+ var indexes;
|
|
|
|
|
|
for (var i = 0, j = data.children.length; i < j; i++) {
|
|
for (var i = 0, j = data.children.length; i < j; i++) {
|
|
|
|
|
|
var child = data.children[i];
|
|
var child = data.children[i];
|
|
|
|
|
|
- var result;
|
|
|
|
var vec;
|
|
var vec;
|
|
|
|
|
|
- if ( /Coordinate/.exec (child.string)) {
|
|
|
|
|
|
+ if ( 'Coordinate' === child.nodeType ) {
|
|
|
|
|
|
- for (var k = 0, l = child.children.length; k < l; k++) {
|
|
|
|
|
|
+ for (var k = 0, l = child.points.length; k < l; k++) {
|
|
|
|
|
|
- var point = child.children[k];
|
|
|
|
|
|
+ var point = child.points[k];
|
|
|
|
|
|
- if (null != (result = float3_pattern.exec(point))) {
|
|
|
|
|
|
+ vec = new THREE.Vector3(point.x, point.y, point.z);
|
|
|
|
|
|
- vec = new THREE.Vector3(
|
|
|
|
- parseFloat(result[1]),
|
|
|
|
- parseFloat(result[2]),
|
|
|
|
- parseFloat(result[3])
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- geometry.vertices.push( vec );
|
|
|
|
- }
|
|
|
|
|
|
+ geometry.vertices.push( vec );
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
|
|
- if (/coordIndex/.exec(child)) {
|
|
|
|
- isRecordingCoordinates = true;
|
|
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
- var coordIndex = false;
|
|
|
|
- var points = [];
|
|
|
|
- var skip = 0;
|
|
|
|
- var regex = /(-?\d+)/g;
|
|
|
|
- // read this: http://math.hws.edu/eck/cs424/notes2013/16_Threejs_Advanced.html
|
|
|
|
- while ( isRecordingCoordinates && null != (coordIndex = regex.exec(child) ) ) {
|
|
|
|
- // parse coordIndex lines
|
|
|
|
- coordIndex = parseInt(coordIndex, 10);
|
|
|
|
-
|
|
|
|
- points.push(coordIndex);
|
|
|
|
-
|
|
|
|
- // -1 indicates end of face points
|
|
|
|
- if (coordIndex === -1) {
|
|
|
|
- // reset the collection
|
|
|
|
- points = [];
|
|
|
|
- }
|
|
|
|
|
|
+ var skip = 0;
|
|
|
|
+ // read this: http://math.hws.edu/eck/cs424/notes2013/16_Threejs_Advanced.html
|
|
|
|
+ for (var i = 0, j = data.coordIndex.length; i < j; i++) {
|
|
|
|
+
|
|
|
|
+ indexes = data.coordIndex[i];
|
|
|
|
+
|
|
|
|
+ // vrml support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here
|
|
|
|
+ skip = 0;
|
|
|
|
|
|
- // vrml support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here
|
|
|
|
|
|
+ // todo: this is the time to check if the faces are ordered ccw or not (cw)
|
|
|
|
|
|
- skip = points.length -3;
|
|
|
|
- skip = skip < 0 ? 0 : skip;
|
|
|
|
|
|
+ // Face3 only works with triangles, but IndexedFaceSet allows shapes with more then three vertices, build them of triangles
|
|
|
|
+ while ( indexes.length >= 3 && skip < (indexes.length -2) ) {
|
|
|
|
|
|
- // Face3 only works with triangles, but IndexedFaceSet allows shapes with more then three vertices, build them of triangles
|
|
|
|
- if (points.length >= 3) {
|
|
|
|
- var face = new THREE.Face3(
|
|
|
|
- points[0],
|
|
|
|
- points[skip + 1],
|
|
|
|
- points[skip + 2],
|
|
|
|
- null // normal, will be added later
|
|
|
|
- // todo: pass in the color
|
|
|
|
- );
|
|
|
|
|
|
+ var face = new THREE.Face3(
|
|
|
|
+ indexes[0],
|
|
|
|
+ indexes[skip + 1],
|
|
|
|
+ indexes[skip + 2],
|
|
|
|
+ null // normal, will be added later
|
|
|
|
+ // todo: pass in the color, if a color index is present
|
|
|
|
+ );
|
|
|
|
|
|
- geometry.faces.push(face);
|
|
|
|
|
|
+ skip++;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ geometry.faces.push(face);
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- // stop recording if a ] is encountered after recording was turned on
|
|
|
|
- isRecordingCoordinates = (isRecordingCoordinates && null === (/]/.exec(child) ) );
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (false === data.solid) {
|
|
|
|
+ parent.material.side = THREE.DoubleSide;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // we need to store it on the geometry for use with defines
|
|
|
|
+ geometry.solid = data.solid;
|
|
|
|
+
|
|
geometry.computeFaceNormals();
|
|
geometry.computeFaceNormals();
|
|
//geometry.computeVertexNormals(); // does not show
|
|
//geometry.computeVertexNormals(); // does not show
|
|
geometry.computeBoundingSphere();
|
|
geometry.computeBoundingSphere();
|
|
@@ -387,55 +508,42 @@ THREE.VRMLLoader.prototype = {
|
|
|
|
|
|
var child = data.children[ i ];
|
|
var child = data.children[ i ];
|
|
|
|
|
|
- if ( /Material/.exec( child.string ) ) {
|
|
|
|
-
|
|
|
|
|
|
+ if ( 'Material' === child.nodeType ) {
|
|
var material = new THREE.MeshPhongMaterial();
|
|
var material = new THREE.MeshPhongMaterial();
|
|
- material.side = THREE.DoubleSide;
|
|
|
|
|
|
|
|
- for ( var j = 0; j < child.children.length; j ++ ) {
|
|
|
|
|
|
+ if ( undefined !== child.diffuseColor ) {
|
|
|
|
|
|
- var parameter = child.children[ j ];
|
|
|
|
|
|
+ var d = child.diffuseColor;
|
|
|
|
|
|
- if ( /diffuseColor/.exec( parameter ) ) {
|
|
|
|
|
|
+ material.color.setRGB( d.r, d.g, d.b );
|
|
|
|
|
|
- var result = float3_pattern.exec( parameter );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- material.color.setRGB(
|
|
|
|
- parseFloat( result[ 1 ] ),
|
|
|
|
- parseFloat( result[ 2 ] ),
|
|
|
|
- parseFloat( result[ 3 ] )
|
|
|
|
- );
|
|
|
|
|
|
+ if ( undefined !== child.emissiveColor ) {
|
|
|
|
|
|
- } else if ( /emissiveColor/.exec( parameter ) ) {
|
|
|
|
|
|
+ var e = child.emissiveColor;
|
|
|
|
|
|
- var result = float3_pattern.exec( parameter );
|
|
|
|
|
|
+ material.emissive.setRGB( e.r, e.g, e.b);
|
|
|
|
|
|
- material.emissive.setRGB(
|
|
|
|
- parseFloat( result[ 1 ] ),
|
|
|
|
- parseFloat( result[ 2 ] ),
|
|
|
|
- parseFloat( result[ 3 ] )
|
|
|
|
- );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- } else if ( /specularColor/.exec( parameter ) ) {
|
|
|
|
|
|
+ if ( undefined !== child.specularColor ) {
|
|
|
|
|
|
- var result = float3_pattern.exec( parameter );
|
|
|
|
|
|
+ var s = child.specularColor;
|
|
|
|
|
|
- material.specular.setRGB(
|
|
|
|
- parseFloat( result[ 1 ] ),
|
|
|
|
- parseFloat( result[ 2 ] ),
|
|
|
|
- parseFloat( result[ 3 ] )
|
|
|
|
- );
|
|
|
|
|
|
+ material.specular.setRGB( s.r, s.g, s.b );
|
|
|
|
|
|
- } else if ( /transparency/.exec( parameter ) ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var result = /\s+([\d|\.|\+|\-|e]+)/.exec( parameter );
|
|
|
|
- // transparency is opposite of opacity
|
|
|
|
- material.opacity = Math.abs( 1 - parseFloat( result[ 1 ] ) );
|
|
|
|
- material.transparent = true;
|
|
|
|
|
|
+ if ( undefined !== child.transparency ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var t = child.transparency;
|
|
|
|
+ // transparency is opposite of opacity
|
|
|
|
+ material.opacity = Math.abs( 1 - t );
|
|
|
|
+ material.transparent = true;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
if ( /DEF/.exec( data.string ) ) {
|
|
if ( /DEF/.exec( data.string ) ) {
|
|
|
|
|
|
@@ -445,8 +553,15 @@ THREE.VRMLLoader.prototype = {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // todo: below does not work, but we should find a way to make it work (for USE(d) geometries (IndexedFaceSets) that are marked as solid)
|
|
|
|
+ if (undefined !== parent.geometry.solid && false === parent.geometry.solid) {
|
|
|
|
+ material.side = THREE.DoubleSide;
|
|
|
|
+ }
|
|
|
|
+
|
|
parent.material = material;
|
|
parent.material = material;
|
|
|
|
|
|
|
|
+ // material found, stop looping
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|