ソースを参照

fix to LWOLoader.js : add suport LWO2 format

adrs2002 6 年 前
コミット
325c9f45f0
1 ファイル変更165 行追加9 行削除
  1. 165 9
      examples/js/loaders/LWOLoader.js

+ 165 - 9
examples/js/loaders/LWOLoader.js

@@ -1,12 +1,12 @@
 /**
  * @author Lewy Blue https://github.com/looeee
  *
- * Load files in LWO3 format
+ * Load files in LWO3 and LWO2 format
  *
  * LWO3 format specification:
  * 	http://static.lightwave3d.com/sdk/2018/html/filefmts/lwo3.html
  *
- * LWO2 format specification (not tested, however the loader should be largely backwards compatible)
+ * LWO2 format specification:
  * 	http://static.lightwave3d.com/sdk/2018/html/filefmts/lwo2.html
  *
  */
@@ -291,7 +291,15 @@ THREE.LWOLoader = ( function () {
 
 			for ( var name in lwoTree.materials ) {
 
-				materials.push( this.parseMaterial( lwoTree.materials[ name ], name, lwoTree.textures ) );
+				if ( lwoTree.format === 'LWO3' ) {
+
+					materials.push( this.parseMaterial( lwoTree.materials[ name ], name, lwoTree.textures ) );
+
+				} else if ( lwoTree.format === 'LWO2' ) {
+
+					materials.push( this.parseMaterialLwo2( lwoTree.materials[ name ], name, lwoTree.textures ) );
+
+				}
 
 			}
 
@@ -326,6 +334,20 @@ THREE.LWOLoader = ( function () {
 
 		},
 
+		parseMaterialLwo2( materialData, name, textures ) {
+
+			var params = {
+				name: name,
+				side: this.getSide( materialData.attributes ),
+				flatShading: this.getSmooth( materialData.attributes ),
+			};
+
+			var attributes = this.parseAttributes( materialData.attributes, {} );
+			params = Object.assign( params, attributes );
+			return new THREE[ 'MeshPhongMaterial' ]( params );
+
+		},
+
 		// Note: converting from left to right handed coords by switching x -> -x in vertices, and
 		// then switching mat FrontSide -> BackSide
 		// NB: this means that THREE.FrontSide and THREE.BackSide have been switched!
@@ -744,7 +766,17 @@ THREE.LWOLoader = ( function () {
 
 					);
 
-				} else if ( dim > 4 ) console.warn( 'LWOLoader: polygons with greater than 4 sides are not supported' );
+				} else if ( dim > 4 ) {
+
+					for ( var k = 1; k < dim - 1; k ++ ) {
+
+						remappedIndices.push( indices[ i ], indices[ i + k ], indices[ i + k + 1 ] );
+
+					}
+
+					console.warn( 'LWOLoader: polygons with greater than 4 sides are not supported' );
+
+				}
 
 				i += dim;
 
@@ -850,7 +882,16 @@ THREE.LWOLoader = ( function () {
 
 					remappedIndices.push( indices[ i * 2 ], indices[ i * 2 + 1 ], indices[ i * 2 ], indices[ i * 2 + 1 ] );
 
-				} // ignore > 4 for now
+				} else {
+
+					 // ignore > 4 for now
+					for ( var k = 0; k < dim - 2; k ++ ) {
+
+						remappedIndices.push( indices[ i * 2 ], indices[ i * 2 + 1 ] );
+
+					}
+
+				}
 
 			} );
 
@@ -1001,6 +1042,13 @@ THREE.LWOLoader = ( function () {
 
 			var blockID = this.reader.getIDTag();
 			var length = this.reader.getUint32(); // size of data in bytes
+			if ( this.tree.format === 'LWO2' && length > this.reader.dv.byteLength - this.reader.offset ) {
+
+				this.reader.offset -= 4;
+				length = this.reader.getUint16();
+
+			}
+
 
 			// Data types may be found in either LWO2 OR LWO3 spec
 			switch ( blockID ) {
@@ -1080,7 +1128,6 @@ THREE.LWOLoader = ( function () {
 				case 'NPLA':
 				case 'VERS':
 				case 'ENUM':
-				case 'FLAG':
 				case 'TAG ':
 
 				// Car Material CHUNKS
@@ -1096,8 +1143,26 @@ THREE.LWOLoader = ( function () {
 					this.reader.skip( length );
 					break;
 
+				case 'FLAG':
+					if ( this.tree.format === 'LWO2' ) {
+
+						this.reader.skip( 4 ); // not suported
+
+					} else {
+
+						this.reader.skip( length );
+
+					}
+					break;
 				// Skipped LWO2 chunks
 				case 'DIFF': // diffuse level, may be necessary to modulate COLR with this
+					if ( this.tree.format === 'LWO2' ) {
+
+						this.currentSurface.diffusePower = this.reader.getFloat32();
+						this.reader.skip( 2 );
+
+					}
+					break;
 				case 'TRNL':
 				case 'REFL':
 				case 'GLOS':
@@ -1118,7 +1183,20 @@ THREE.LWOLoader = ( function () {
 				case 'ENAB':
 					this.reader.skip( length );
 					break;
+				case 'SURF':
+					if ( this.tree.format === 'LWO2' ) {
+
+						this.parseSurfaceLwo2( length );
+
+					}
+					break;
+				case 'CLIP':
+					if ( this.tree.format === 'LWO2' ) {
 
+						this.parseClipLwo2( length );
+
+					}
+					break;
 				// Texture node chunks (not in spec)
 				case 'IPIX': // usePixelBlending
 				case 'IMIP': // useMipMaps
@@ -1276,7 +1354,8 @@ THREE.LWOLoader = ( function () {
 
 				// LWO2: Basic Surface Parameters
 				case 'COLR':
-					this.currentSurface.attributes.color = this.reader.getFloat32Array( 3 );
+					this.currentSurface.attributes.Color = {};
+					this.currentSurface.attributes.Color.value = this.reader.getFloat32Array( 3 );
 					this.reader.skip( 2 ); // VX: envelope
 					break;
 
@@ -1323,7 +1402,15 @@ THREE.LWOLoader = ( function () {
 					break;
 
 				case 'IMAP':
-					this.currentSurface.attributes.imageMapIndex = this.reader.getUint32();
+					if ( this.tree.format === 'LWO2' ) {
+
+						this.reader.skip( 2 );
+
+					} else {
+
+						this.currentSurface.attributes.imageMapIndex = this.reader.getUint32();
+
+					}
 					break;
 
 				case 'IUVI': // uv channel name
@@ -1337,6 +1424,11 @@ THREE.LWOLoader = ( function () {
 					this.currentNode.heightWrappingMode = this.reader.getUint32();
 					break;
 
+				// LWO2 USE
+				case 'BLOK':
+					// skip
+					break;
+
 				default:
 					this.parseUnknownCHUNK( blockID, length );
 
@@ -1420,6 +1512,10 @@ THREE.LWOLoader = ( function () {
 					this.parseTextureNodeAttribute( type );
 					break;
 
+				case 'LWO2':
+					this.tree.format = type;
+					break;
+
 				case 'LWO3':
 					this.tree.format = type;
 					break;
@@ -1431,7 +1527,11 @@ THREE.LWOLoader = ( function () {
 					// CLIP FORM AND SUB FORMS
 
 				case 'CLIP':
-					this.parseClip( length );
+					if ( this.tree.format === 'LWO2' ) {
+
+						this.parseForm( length );
+
+					}
 					break;
 
 				case 'STIL':
@@ -1574,6 +1674,29 @@ THREE.LWOLoader = ( function () {
 
 			var name = this.reader.getString();
 
+			var surface = {
+				attributes: {}, // LWO2 style non-node attributes will go here
+				connections: {},
+				name: name,
+				inputName: name,
+				nodes: {},
+				source: this.reader.getString(),
+			};
+
+			this.tree.materials[ name ] = surface;
+			this.currentSurface = surface;
+
+			this.parentForm = this.tree.materials;
+			this.currentForm = surface;
+			this.currentFormEnd = this.reader.offset + length;
+
+		},
+
+		parseSurfaceLwo2( length ) {
+
+			var firstOffset = this.reader.offset;
+			var name = this.reader.getString();
+
 			var surface = {
 				attributes: {}, // LWO2 style non-node attributes will go here
 				connections: {},
@@ -1771,6 +1894,39 @@ THREE.LWOLoader = ( function () {
 
 		},
 
+		parseClipLwo2( length ) {
+
+			var texture = {
+				index: this.reader.getUint32(),
+				fileName: ""
+			};
+
+			var readed = 4;
+			// seach STIL block
+			while ( true ) {
+
+				var tag = this.reader.getIDTag();
+				var n_length = this.reader.getUint16();
+				if ( tag === 'STIL' ) {
+
+					texture.fileName = this.reader.getString();
+					break;
+
+				}
+				readed += 4 + n_length;
+				if ( n_length >= length ) {
+
+					break;
+
+				}
+
+			}
+
+			this.tree.textures.push( texture );
+			this.currentForm = texture;
+
+		},
+
 		parseImage() {
 
 			this.reader.skip( 8 ); // unknown