Browse Source

Merge pull request #17888 from Mugen87/dev33

VRMLLoader: Add support for PixelTexture.
Mr.doob 5 years ago
parent
commit
2d37cd41f0

+ 237 - 10
examples/js/loaders/VRMLLoader.js

@@ -146,6 +146,7 @@ THREE.VRMLLoader = ( function () {
 				//
 
 				var StringLiteral = createToken( { name: "StringLiteral", pattern: /"(:?[^\\"\n\r]+|\\(:?[bfnrtv"\\/]|u[0-9a-fA-F]{4}))*"/ } );
+				var HexLiteral = createToken( { name: 'HexLiteral', pattern: /0[xX][0-9a-fA-F]+/ } );
 				var NumberLiteral = createToken( { name: 'NumberLiteral', pattern: /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/ } );
 				var TrueLiteral = createToken( { name: 'TrueLiteral', pattern: /TRUE/ } );
 				var FalseLiteral = createToken( { name: 'FalseLiteral', pattern: /FALSE/ } );
@@ -184,6 +185,7 @@ THREE.VRMLLoader = ( function () {
 					Identifier,
 					RouteIdentifier,
 					StringLiteral,
+					HexLiteral,
 					NumberLiteral,
 					LSquare,
 					RSquare,
@@ -425,6 +427,20 @@ THREE.VRMLLoader = ( function () {
 
 					}
 
+					if ( ctx.HexLiteral ) {
+
+						field.type = 'hex';
+
+						for ( var i = 0, l = ctx.HexLiteral.length; i < l; i ++ ) {
+
+							var hexLiteral = ctx.HexLiteral[ i ];
+
+							field.values.push( hexLiteral.image );
+
+						}
+
+					}
+
 					if ( ctx.TrueLiteral ) {
 
 						field.type = 'boolean';
@@ -578,7 +594,7 @@ THREE.VRMLLoader = ( function () {
 						break;
 
 					case 'Appearance':
-						build = buildApperanceNode( node );
+						build = buildAppearanceNode( node );
 						break;
 
 					case 'Material':
@@ -589,6 +605,10 @@ THREE.VRMLLoader = ( function () {
 						build = buildImageTextureNode( node );
 						break;
 
+					case 'PixelTexture':
+						build = buildPixelTextureNode( node );
+						break;
+
 					case 'TextureTransform':
 						build = buildTextureTransformNode( node );
 						break;
@@ -658,7 +678,6 @@ THREE.VRMLLoader = ( function () {
 
 					case 'FontStyle':
 					case 'MovieTexture':
-					case 'PixelTexture':
 
 					case 'ColorInterpolator':
 					case 'CoordinateInterpolator':
@@ -990,7 +1009,7 @@ THREE.VRMLLoader = ( function () {
 
 			}
 
-			function buildApperanceNode( node ) {
+			function buildAppearanceNode( node ) {
 
 				var material = new THREE.MeshPhongMaterial();
 				var transformData;
@@ -1030,13 +1049,13 @@ THREE.VRMLLoader = ( function () {
 							var textureNode = fieldValues[ 0 ];
 							if ( textureNode !== null ) {
 
-								if ( textureNode.name === 'ImageTexture' ) {
+								if ( textureNode.name === 'ImageTexture' || textureNode.name === 'PixelTexture' ) {
 
 									material.map = getNode( textureNode );
 
 								} else {
 
-									// MovieTexture and PixelTexture not supported yet
+									// MovieTexture not supported yet
 
 								}
 
@@ -1061,12 +1080,45 @@ THREE.VRMLLoader = ( function () {
 
 				// only apply texture transform data if a texture was defined
 
-				if ( material.map && transformData ) {
+				if ( material.map ) {
+
+					// respect VRML lighting model
+
+					if ( material.map.__type ) {
+
+						switch ( material.map.__type ) {
+
+							case TEXTURE_TYPE.INTENSITY_ALPHA:
+								material.opacity = 1; // ignore transparency
+								break;
 
-					material.map.center.copy( transformData.center );
-					material.map.rotation = transformData.rotation;
-					material.map.repeat.copy( transformData.scale );
-					material.map.offset.copy( transformData.translation );
+							case TEXTURE_TYPE.RGB:
+								material.color.set( 0xffffff ); // ignore material color
+								break;
+
+							case TEXTURE_TYPE.RGBA:
+								material.color.set( 0xffffff ); // ignore material color
+								material.opacity = 1; // ignore transparency
+								break;
+
+							default:
+
+						}
+
+						delete material.map.__type;
+
+					}
+
+					// apply texture transform
+
+					if ( transformData ) {
+
+						material.map.center.copy( transformData.center );
+						material.map.rotation = transformData.rotation;
+						material.map.repeat.copy( transformData.scale );
+						material.map.offset.copy( transformData.translation );
+
+					}
 
 				}
 
@@ -1124,6 +1176,163 @@ THREE.VRMLLoader = ( function () {
 
 			}
 
+			function parseHexColor( hex, textureType, color ) {
+
+				switch ( textureType ) {
+
+					case TEXTURE_TYPE.INTENSITY:
+						// Intensity texture: A one-component image specifies one-byte hexadecimal or integer values representing the intensity of the image
+						var value = parseInt( hex );
+						color.r = value;
+						color.g = value;
+						color.b = value;
+						break;
+
+					case TEXTURE_TYPE.INTENSITY_ALPHA:
+						// Intensity+Alpha texture: A two-component image specifies the intensity in the first (high) byte and the alpha opacity in the second (low) byte.
+						var value = parseInt( "0x" + hex.substring( 2, 4 ) );
+						color.r = value;
+						color.g = value;
+						color.b = value;
+						color.a = parseInt( "0x" + hex.substring( 4, 6 ) );
+						break;
+
+					case TEXTURE_TYPE.RGB:
+						// RGB texture: Pixels in a three-component image specify the red component in the first (high) byte, followed by the green and blue components
+						color.r = parseInt( "0x" + hex.substring( 2, 4 ) );
+						color.g = parseInt( "0x" + hex.substring( 4, 6 ) );
+						color.b = parseInt( "0x" + hex.substring( 6, 8 ) );
+						break;
+
+					case TEXTURE_TYPE.RGBA:
+						// RGBA texture: Four-component images specify the alpha opacity byte after red/green/blue
+						color.r = parseInt( "0x" + hex.substring( 2, 4 ) );
+						color.g = parseInt( "0x" + hex.substring( 4, 6 ) );
+						color.b = parseInt( "0x" + hex.substring( 6, 8 ) );
+						color.a = parseInt( "0x" + hex.substring( 8, 10 ) );
+						break;
+
+					default:
+
+				}
+
+			}
+
+			function getTextureType( num_components ) {
+
+				var type;
+
+				switch ( num_components ) {
+
+					case 1:
+						type = TEXTURE_TYPE.INTENSITY;
+						break;
+
+					case 2:
+						type = TEXTURE_TYPE.INTENSITY_ALPHA;
+						break;
+
+					case 3:
+						type = TEXTURE_TYPE.RGB;
+						break;
+
+					case 4:
+						type = TEXTURE_TYPE.RGBA;
+						break;
+
+					default:
+
+				}
+
+				return type;
+
+			}
+
+			function buildPixelTextureNode( node ) {
+
+				var texture;
+				var wrapS = THREE.RepeatWrapping;
+				var wrapT = THREE.RepeatWrapping;
+
+				var fields = node.fields;
+
+				for ( var i = 0, l = fields.length; i < l; i ++ ) {
+
+					var field = fields[ i ];
+					var fieldName = field.name;
+					var fieldValues = field.values;
+
+					switch ( fieldName ) {
+
+						case 'image':
+							var width = fieldValues[ 0 ];
+							var height = fieldValues[ 1 ];
+							var num_components = fieldValues[ 2 ];
+
+							var useAlpha = ( num_components === 2 || num_components === 4 );
+							var textureType = getTextureType( num_components );
+
+							var size = ( ( useAlpha === true ) ? 4 : 3 ) * ( width * height );
+							var data = new Uint8Array( size );
+
+							var color = { r: 0, g: 0, b: 0, a: 0 };
+
+							for ( var j = 3, k = 0, jl = fieldValues.length; j < jl; j ++, k ++ ) {
+
+								parseHexColor( fieldValues[ j ], textureType, color );
+
+								if ( useAlpha === true ) {
+
+									var stride = k * 4;
+
+									data[ stride + 0 ] = color.r;
+									data[ stride + 1 ] = color.g;
+									data[ stride + 2 ] = color.b;
+									data[ stride + 3 ] = color.a;
+
+								} else {
+
+									var stride = k * 3;
+
+									data[ stride + 0 ] = color.r;
+									data[ stride + 1 ] = color.g;
+									data[ stride + 2 ] = color.b;
+
+								}
+
+							}
+
+							texture = new THREE.DataTexture( data, width, height, ( useAlpha === true ) ? THREE.RGBAFormat : THREE.RGBFormat );
+							texture.__type = textureType; // needed for material modifications
+							break;
+
+						case 'repeatS':
+							if ( fieldValues[ 0 ] === false ) wrapS = THREE.ClampToEdgeWrapping;
+							break;
+
+						case 'repeatT':
+							if ( fieldValues[ 0 ] === false ) wrapT = THREE.ClampToEdgeWrapping;
+							break;
+
+						default:
+							console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
+							break;
+
+					}
+
+				}
+
+				if ( texture ) {
+
+					texture.wrapS = wrapS;
+					texture.wrapT = wrapT;
+
+				}
+
+				return texture;
+
+			}
+
 			function buildImageTextureNode( node ) {
 
 				var texture;
@@ -2382,6 +2591,7 @@ THREE.VRMLLoader = ( function () {
 		var Identifier = tokenVocabulary[ 'Identifier' ];
 		var RouteIdentifier = tokenVocabulary[ 'RouteIdentifier' ];
 		var StringLiteral = tokenVocabulary[ 'StringLiteral' ];
+		var HexLiteral = tokenVocabulary[ 'HexLiteral' ];
 		var NumberLiteral = tokenVocabulary[ 'NumberLiteral' ];
 		var TrueLiteral = tokenVocabulary[ 'TrueLiteral' ];
 		var FalseLiteral = tokenVocabulary[ 'FalseLiteral' ];
@@ -2485,6 +2695,11 @@ THREE.VRMLLoader = ( function () {
 
 						$.CONSUME( StringLiteral );
 
+					} },
+					{ ALT: function () {
+
+						$.CONSUME( HexLiteral );
+
 					} },
 					{ ALT: function () {
 
@@ -2533,6 +2748,11 @@ THREE.VRMLLoader = ( function () {
 
 						$.CONSUME( StringLiteral );
 
+					} },
+					{ ALT: function () {
+
+						$.CONSUME( HexLiteral );
+
 					} },
 					{ ALT: function () {
 
@@ -2576,6 +2796,13 @@ THREE.VRMLLoader = ( function () {
 
 	}
 
+	var TEXTURE_TYPE = {
+		INTENSITY: 1,
+		INTENSITY_ALPHA: 2,
+		RGB: 3,
+		RGBA: 4
+	};
+
 	return VRMLLoader;
 
 } )();

+ 243 - 9
examples/jsm/loaders/VRMLLoader.js

@@ -11,6 +11,7 @@ import {
 	Color,
 	ConeBufferGeometry,
 	CylinderBufferGeometry,
+	DataTexture,
 	DoubleSide,
 	FileLoader,
 	Float32BufferAttribute,
@@ -26,6 +27,8 @@ import {
 	Object3D,
 	Points,
 	PointsMaterial,
+	RGBAFormat,
+	RGBFormat,
 	RepeatWrapping,
 	Scene,
 	SphereBufferGeometry,
@@ -180,6 +183,7 @@ var VRMLLoader = ( function () {
 				//
 
 				var StringLiteral = createToken( { name: "StringLiteral", pattern: /"(:?[^\\"\n\r]+|\\(:?[bfnrtv"\\/]|u[0-9a-fA-F]{4}))*"/ } );
+				var HexLiteral = createToken( { name: 'HexLiteral', pattern: /0[xX][0-9a-fA-F]+/ } );
 				var NumberLiteral = createToken( { name: 'NumberLiteral', pattern: /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/ } );
 				var TrueLiteral = createToken( { name: 'TrueLiteral', pattern: /TRUE/ } );
 				var FalseLiteral = createToken( { name: 'FalseLiteral', pattern: /FALSE/ } );
@@ -218,6 +222,7 @@ var VRMLLoader = ( function () {
 					Identifier,
 					RouteIdentifier,
 					StringLiteral,
+					HexLiteral,
 					NumberLiteral,
 					LSquare,
 					RSquare,
@@ -459,6 +464,20 @@ var VRMLLoader = ( function () {
 
 					}
 
+					if ( ctx.HexLiteral ) {
+
+						field.type = 'hex';
+
+						for ( var i = 0, l = ctx.HexLiteral.length; i < l; i ++ ) {
+
+							var hexLiteral = ctx.HexLiteral[ i ];
+
+							field.values.push( hexLiteral.image );
+
+						}
+
+					}
+
 					if ( ctx.TrueLiteral ) {
 
 						field.type = 'boolean';
@@ -612,7 +631,7 @@ var VRMLLoader = ( function () {
 						break;
 
 					case 'Appearance':
-						build = buildApperanceNode( node );
+						build = buildAppearanceNode( node );
 						break;
 
 					case 'Material':
@@ -623,6 +642,10 @@ var VRMLLoader = ( function () {
 						build = buildImageTextureNode( node );
 						break;
 
+					case 'PixelTexture':
+						build = buildPixelTextureNode( node );
+						break;
+
 					case 'TextureTransform':
 						build = buildTextureTransformNode( node );
 						break;
@@ -692,7 +715,6 @@ var VRMLLoader = ( function () {
 
 					case 'FontStyle':
 					case 'MovieTexture':
-					case 'PixelTexture':
 
 					case 'ColorInterpolator':
 					case 'CoordinateInterpolator':
@@ -1024,7 +1046,7 @@ var VRMLLoader = ( function () {
 
 			}
 
-			function buildApperanceNode( node ) {
+			function buildAppearanceNode( node ) {
 
 				var material = new MeshPhongMaterial();
 				var transformData;
@@ -1068,9 +1090,13 @@ var VRMLLoader = ( function () {
 
 									material.map = getNode( textureNode );
 
+								} else if ( textureNode.name === 'PixelTexture' ) {
+
+									material.map = getNode( textureNode );
+
 								} else {
 
-									// MovieTexture and PixelTexture not supported yet
+									// MovieTexture not supported yet
 
 								}
 
@@ -1095,12 +1121,45 @@ var VRMLLoader = ( function () {
 
 				// only apply texture transform data if a texture was defined
 
-				if ( material.map && transformData ) {
+				if ( material.map ) {
+
+					// respect VRML lighting model
+
+					if ( material.map.__type ) {
 
-					material.map.center.copy( transformData.center );
-					material.map.rotation = transformData.rotation;
-					material.map.repeat.copy( transformData.scale );
-					material.map.offset.copy( transformData.translation );
+						switch ( material.map.__type ) {
+
+							case TEXTURE_TYPE.INTENSITY_ALPHA:
+								material.opacity = 1; // ignore transparency
+								break;
+
+							case TEXTURE_TYPE.RGB:
+								material.color.set( 0xffffff ); // ignore material color
+								break;
+
+							case TEXTURE_TYPE.RGBA:
+								material.color.set( 0xffffff ); // ignore material color
+								material.opacity = 1; // ignore transparency
+								break;
+
+							default:
+
+						}
+
+						delete material.map.__type;
+
+					}
+
+					// apply texture transform
+
+					if ( transformData ) {
+
+						material.map.center.copy( transformData.center );
+						material.map.rotation = transformData.rotation;
+						material.map.repeat.copy( transformData.scale );
+						material.map.offset.copy( transformData.translation );
+
+					}
 
 				}
 
@@ -1158,6 +1217,163 @@ var VRMLLoader = ( function () {
 
 			}
 
+			function parseHexColor( hex, textureType, color ) {
+
+				switch ( textureType ) {
+
+					case TEXTURE_TYPE.INTENSITY:
+						// Intensity texture: A one-component image specifies one-byte hexadecimal or integer values representing the intensity of the image
+						var value = parseInt( hex );
+						color.r = value;
+						color.g = value;
+						color.b = value;
+						break;
+
+					case TEXTURE_TYPE.INTENSITY_ALPHA:
+						// Intensity+Alpha texture: A two-component image specifies the intensity in the first (high) byte and the alpha opacity in the second (low) byte.
+						var value = parseInt( "0x" + hex.substring( 2, 4 ) );
+						color.r = value;
+						color.g = value;
+						color.b = value;
+						color.a = parseInt( "0x" + hex.substring( 4, 6 ) );
+						break;
+
+					case TEXTURE_TYPE.RGB:
+						// RGB texture: Pixels in a three-component image specify the red component in the first (high) byte, followed by the green and blue components
+						color.r = parseInt( "0x" + hex.substring( 2, 4 ) );
+						color.g = parseInt( "0x" + hex.substring( 4, 6 ) );
+						color.b = parseInt( "0x" + hex.substring( 6, 8 ) );
+						break;
+
+					case TEXTURE_TYPE.RGBA:
+						// RGBA texture: Four-component images specify the alpha opacity byte after red/green/blue
+						color.r = parseInt( "0x" + hex.substring( 2, 4 ) );
+						color.g = parseInt( "0x" + hex.substring( 4, 6 ) );
+						color.b = parseInt( "0x" + hex.substring( 6, 8 ) );
+						color.a = parseInt( "0x" + hex.substring( 8, 10 ) );
+						break;
+
+					default:
+
+				}
+
+			}
+
+			function getTextureType( num_components ) {
+
+				var type;
+
+				switch ( num_components ) {
+
+					case 1:
+						type = TEXTURE_TYPE.INTENSITY;
+						break;
+
+					case 2:
+						type = TEXTURE_TYPE.INTENSITY_ALPHA;
+						break;
+
+					case 3:
+						type = TEXTURE_TYPE.RGB;
+						break;
+
+					case 4:
+						type = TEXTURE_TYPE.RGBA;
+						break;
+
+					default:
+
+				}
+
+				return type;
+
+			}
+
+			function buildPixelTextureNode( node ) {
+
+				var texture;
+				var wrapS = RepeatWrapping;
+				var wrapT = RepeatWrapping;
+
+				var fields = node.fields;
+
+				for ( var i = 0, l = fields.length; i < l; i ++ ) {
+
+					var field = fields[ i ];
+					var fieldName = field.name;
+					var fieldValues = field.values;
+
+					switch ( fieldName ) {
+
+						case 'image':
+							var width = fieldValues[ 0 ];
+							var height = fieldValues[ 1 ];
+							var num_components = fieldValues[ 2 ];
+
+							var useAlpha = ( num_components === 2 || num_components === 4 );
+							var textureType = getTextureType( num_components );
+
+							var size = ( ( useAlpha === true ) ? 4 : 3 ) * ( width * height );
+							var data = new Uint8Array( size );
+
+							var color = { r: 0, g: 0, b: 0, a: 0 };
+
+							for ( var j = 3, k = 0, jl = fieldValues.length; j < jl; j ++, k ++ ) {
+
+								parseHexColor( fieldValues[ j ], textureType, color );
+
+								if ( useAlpha === true ) {
+
+									var stride = k * 4;
+
+									data[ stride + 0 ] = color.r;
+									data[ stride + 1 ] = color.g;
+									data[ stride + 2 ] = color.b;
+									data[ stride + 3 ] = color.a;
+
+								} else {
+
+									var stride = k * 3;
+
+									data[ stride + 0 ] = color.r;
+									data[ stride + 1 ] = color.g;
+									data[ stride + 2 ] = color.b;
+
+								}
+
+							}
+
+							texture = new DataTexture( data, width, height, ( useAlpha === true ) ? RGBAFormat : RGBFormat );
+							texture.__type = textureType; // needed for material modifications
+							break;
+
+						case 'repeatS':
+							if ( fieldValues[ 0 ] === false ) wrapS = ClampToEdgeWrapping;
+							break;
+
+						case 'repeatT':
+							if ( fieldValues[ 0 ] === false ) wrapT = ClampToEdgeWrapping;
+							break;
+
+						default:
+							console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
+							break;
+
+					}
+
+				}
+
+				if ( texture ) {
+
+					texture.wrapS = wrapS;
+					texture.wrapT = wrapT;
+
+				}
+
+				return texture;
+
+			}
+
 			function buildImageTextureNode( node ) {
 
 				var texture;
@@ -2416,6 +2632,7 @@ var VRMLLoader = ( function () {
 		var Identifier = tokenVocabulary[ 'Identifier' ];
 		var RouteIdentifier = tokenVocabulary[ 'RouteIdentifier' ];
 		var StringLiteral = tokenVocabulary[ 'StringLiteral' ];
+		var HexLiteral = tokenVocabulary[ 'HexLiteral' ];
 		var NumberLiteral = tokenVocabulary[ 'NumberLiteral' ];
 		var TrueLiteral = tokenVocabulary[ 'TrueLiteral' ];
 		var FalseLiteral = tokenVocabulary[ 'FalseLiteral' ];
@@ -2519,6 +2736,11 @@ var VRMLLoader = ( function () {
 
 						$.CONSUME( StringLiteral );
 
+					} },
+					{ ALT: function () {
+
+						$.CONSUME( HexLiteral );
+
 					} },
 					{ ALT: function () {
 
@@ -2567,6 +2789,11 @@ var VRMLLoader = ( function () {
 
 						$.CONSUME( StringLiteral );
 
+					} },
+					{ ALT: function () {
+
+						$.CONSUME( HexLiteral );
+
 					} },
 					{ ALT: function () {
 
@@ -2610,6 +2837,13 @@ var VRMLLoader = ( function () {
 
 	}
 
+	var TEXTURE_TYPE = {
+		INTENSITY: 1,
+		INTENSITY_ALPHA: 2,
+		RGB: 3,
+		RGBA: 4
+	};
+
 	return VRMLLoader;
 
 } )();

+ 87 - 0
examples/models/vrml/test/pixelTexture.wrl

@@ -0,0 +1,87 @@
+#VRML V2.0 utf8
+Group { children [
+  Transform {
+    translation -2.5 0 0.5
+    rotation 0 1 0 0.5
+    children Shape {
+      appearance Appearance {
+        texture PixelTexture {   # One component (gray scale)
+          image 4 4 1 0x00 0xDD 0xAA 0xFF
+                                     0xDD 0x00 0xDD 0x00
+                                     0xAA 0xDD 0x00 0x00
+                                     0xFF 0x00 0x00 0x00
+        }
+               # Notice how the diffuseColor darkens the texture
+        material DEF M Material { diffuseColor .7 .7 .7 }
+      }
+      geometry DEF IFS IndexedFaceSet {
+               coord Coordinate {
+               point [ -1.1 -1 0, 1 -1 0, 1 1 0, -1.1 1 0 ] }
+                       coordIndex [ 0 1 2 3 ]
+                       texCoord TextureCoordinate { point [ 0 0, 3 0, 3 3, 0 3 ] }
+      }
+    }
+  }
+  Transform {
+    translation 0 0 0
+    children Shape {
+      appearance Appearance {
+                       # For faster rendering, do not specify a Material
+                       # and avoid lighting calculations on the texture.
+               texture PixelTexture {
+          image 2 2 3 0xFFFFFF 0xAAAAAA 0xDDDDDD  0x000000
+               }
+      }
+      geometry USE IFS
+    }
+  }
+
+  Transform {
+    translation 2.5 0 0
+    children Shape {
+      appearance Appearance {
+        texture PixelTexture {
+          image 2 2 4 0xFFFFFF00 0xAAAAAAA0 0xDDDDDDA0  0x000000AA
+               }
+               material DEF M Material {
+          diffuseColor 0 0 0  # diffuseColor and transp have no
+          transparency 1.0    # effect - replaced by image values.
+          shininess  0.5      # All other fields work fine.
+          ambientIntensity 0.0
+        }
+      }
+      geometry USE IFS
+    }
+  }
+  Transform {
+    translation 5 0 0
+    children Shape {
+      appearance Appearance {
+        texture PixelTexture {    # repeat fields
+          image 4 4 1 0x00 0xDD 0xAA 0xFF
+                      0xDD 0x00 0xDD 0x00
+                      0xAA 0xDD 0x00 0x00
+                      0xFF 0x00 0x00 0x00
+          repeatS FALSE
+          repeatT FALSE
+               }
+               material DEF M Material { diffuseColor 1 1 1 }
+      }
+      geometry IndexedFaceSet {
+        coord Coordinate { point [ -1 -1 0, 1 -1 0, 1 1 0, -1 1 0 ] }
+               coordIndex [ 0 1 2 3 ]
+               texCoord TextureCoordinate {
+                 point [ -0.25 -0.5, 1.25 -0.5, 1.25 1.5, -0.25 1.5 ]
+               }
+      }
+    }
+  }
+  Background {
+    skyColor [ 1 1 1, 1 1 1, .5 .5 .5, 1 1 1, .2 .2 .2, 1 1 1 ]
+    skyAngle [ 1.35, 1.4, 1.45, 1.5, 1.55 ]
+    groundColor [ 1 1 1, 1 1 1, 0.4 0.4 0.4 ]
+    groundAngle [ 1.3, 1.57 ]
+  }
+  NavigationInfo { type "EXAMINE" }
+  Viewpoint { position  0 1 6 orientation -.707 0 -.707 0 }
+]}