瀏覽代碼

Implement STEP directive

yomboprime 6 年之前
父節點
當前提交
9848016d19
共有 3 個文件被更改,包括 170 次插入44 次删除
  1. 51 1
      examples/js/loaders/LDrawLoader.js
  2. 51 1
      examples/jsm/loaders/LDrawLoader.js
  3. 68 42
      examples/webgl_loader_ldraw.html

+ 51 - 1
examples/js/loaders/LDrawLoader.js

@@ -684,6 +684,9 @@ THREE.LDrawLoader = ( function () {
 				triangles: null,
 				lineSegments: null,
 				conditionalSegments: null,
+
+				// If true, this object is the start of a construction step
+				startingConstructionStep: false
 			};
 
 			this.parseScopesStack.push( newParseScope );
@@ -1042,6 +1045,8 @@ THREE.LDrawLoader = ( function () {
 			// Retrieve data from the parent parse scope
 			var parentParseScope = this.getParentParseScope();
 
+			var isRoot = ! parentParseScope.isFromParse;
+
 			// Main colour codes passed to this subobject (or default codes 16 and 24 if it is the root object)
 			var mainColourCode = parentParseScope.mainColourCode;
 			var mainEdgeColourCode = parentParseScope.mainEdgeColourCode;
@@ -1079,6 +1084,8 @@ THREE.LDrawLoader = ( function () {
 			var bfcCull = true;
 			var type = '';
 
+			var startingConstructionStep = false;
+
 			var scope = this;
 			function parseColourCode( lineParser, forEdge ) {
 
@@ -1193,6 +1200,8 @@ THREE.LDrawLoader = ( function () {
 
 											currentParseScope.groupObject = new THREE.Group();
 
+											currentParseScope.groupObject.userData.startingConstructionStep = currentParseScope.startingConstructionStep;
+
 										}
 
 										// If the scale of the object is negated then the triangle winding order
@@ -1320,6 +1329,12 @@ THREE.LDrawLoader = ( function () {
 
 									break;
 
+								case 'STEP':
+
+									startingConstructionStep = true;
+
+									break;
+
 								default:
 									// Other meta directives are not implemented
 									break;
@@ -1385,7 +1400,8 @@ THREE.LDrawLoader = ( function () {
 							locationState: LDrawLoader.FILE_LOCATION_AS_IS,
 							url: null,
 							triedLowerCase: false,
-							inverted: bfcInverted !== currentParseScope.inverted
+							inverted: bfcInverted !== currentParseScope.inverted,
+							startingConstructionStep: startingConstructionStep
 						} );
 
 						bfcInverted = false;
@@ -1594,6 +1610,32 @@ THREE.LDrawLoader = ( function () {
 
 		},
 
+		computeConstructionSteps: function ( model ) {
+
+			// Sets userdata.constructionStep number in Group objects and userData.numConstructionSteps number in the root Group object.
+
+			var stepNumber = 0;
+
+			model.traverse( c => {
+
+				if ( c.isGroup ) {
+
+					if ( c.userData.startingConstructionStep ) {
+
+						stepNumber ++;
+
+					}
+
+					c.userData.constructionStep = stepNumber;
+
+				}
+
+			} );
+
+			model.userData.numConstructionSteps = stepNumber + 1;
+
+		},
+
 		processObject: function ( text, onProcessed, subobject, url ) {
 
 			var scope = this;
@@ -1609,6 +1651,7 @@ THREE.LDrawLoader = ( function () {
 				parseScope.currentMatrix.multiplyMatrices( parentParseScope.currentMatrix, subobject.matrix );
 				parseScope.matrix.copy( subobject.matrix );
 				parseScope.inverted = subobject.inverted;
+				parseScope.startingConstructionStep = subobject.startingConstructionStep;
 
 			}
 
@@ -1763,6 +1806,13 @@ THREE.LDrawLoader = ( function () {
 
 				scope.removeScopeLevel();
 
+				// If it is root object, compute construction steps
+				if ( ! parentParseScope.isFromParse ) {
+
+					scope.computeConstructionSteps( parseScope.groupObject );
+
+				}
+
 				if ( onProcessed ) {
 
 					onProcessed( parseScope.groupObject );

+ 51 - 1
examples/jsm/loaders/LDrawLoader.js

@@ -702,6 +702,9 @@ var LDrawLoader = ( function () {
 				triangles: null,
 				lineSegments: null,
 				conditionalSegments: null,
+
+				// If true, this object is the start of a construction step
+				startingConstructionStep: false
 			};
 
 			this.parseScopesStack.push( newParseScope );
@@ -1060,6 +1063,8 @@ var LDrawLoader = ( function () {
 			// Retrieve data from the parent parse scope
 			var parentParseScope = this.getParentParseScope();
 
+			var isRoot = ! parentParseScope.isFromParse;
+
 			// Main colour codes passed to this subobject (or default codes 16 and 24 if it is the root object)
 			var mainColourCode = parentParseScope.mainColourCode;
 			var mainEdgeColourCode = parentParseScope.mainEdgeColourCode;
@@ -1097,6 +1102,8 @@ var LDrawLoader = ( function () {
 			var bfcCull = true;
 			var type = '';
 
+			var startingConstructionStep = false;
+
 			var scope = this;
 			function parseColourCode( lineParser, forEdge ) {
 
@@ -1211,6 +1218,8 @@ var LDrawLoader = ( function () {
 
 											currentParseScope.groupObject = new Group();
 
+											currentParseScope.groupObject.userData.startingConstructionStep = currentParseScope.startingConstructionStep;
+
 										}
 
 										// If the scale of the object is negated then the triangle winding order
@@ -1338,6 +1347,12 @@ var LDrawLoader = ( function () {
 
 									break;
 
+								case 'STEP':
+
+									startingConstructionStep = true;
+
+									break;
+
 								default:
 									// Other meta directives are not implemented
 									break;
@@ -1403,7 +1418,8 @@ var LDrawLoader = ( function () {
 							locationState: LDrawLoader.FILE_LOCATION_AS_IS,
 							url: null,
 							triedLowerCase: false,
-							inverted: bfcInverted !== currentParseScope.inverted
+							inverted: bfcInverted !== currentParseScope.inverted,
+							startingConstructionStep: startingConstructionStep
 						} );
 
 						bfcInverted = false;
@@ -1612,6 +1628,32 @@ var LDrawLoader = ( function () {
 
 		},
 
+		computeConstructionSteps: function ( model ) {
+
+			// Sets userdata.constructionStep number in Group objects and userData.numConstructionSteps number in the root Group object.
+
+			var stepNumber = 0;
+
+			model.traverse( c => {
+
+				if ( c.isGroup ) {
+
+					if ( c.userData.startingConstructionStep ) {
+
+						stepNumber ++;
+
+					}
+
+					c.userData.constructionStep = stepNumber;
+
+				}
+
+			} );
+
+			model.userData.numConstructionSteps = stepNumber + 1;
+
+		},
+
 		processObject: function ( text, onProcessed, subobject, url ) {
 
 			var scope = this;
@@ -1627,6 +1669,7 @@ var LDrawLoader = ( function () {
 				parseScope.currentMatrix.multiplyMatrices( parentParseScope.currentMatrix, subobject.matrix );
 				parseScope.matrix.copy( subobject.matrix );
 				parseScope.inverted = subobject.inverted;
+				parseScope.startingConstructionStep = subobject.startingConstructionStep;
 
 			}
 
@@ -1781,6 +1824,13 @@ var LDrawLoader = ( function () {
 
 				scope.removeScopeLevel();
 
+				// If it is root object, compute construction steps
+				if ( ! parentParseScope.isFromParse ) {
+
+					scope.computeConstructionSteps( parseScope.groupObject );
+
+				}
+
 				if ( onProcessed ) {
 
 					onProcessed( parseScope.groupObject );

+ 68 - 42
examples/webgl_loader_ldraw.html

@@ -110,48 +110,11 @@
 					separateObjects: false,
 					displayLines: true,
 					conditionalLines: true,
-					smoothNormals: true
+					smoothNormals: true,
+					constructionStep: 0,
+					noConstructionSteps: "No steps."
 				};
 
-				gui = new GUI();
-
-				gui.add( guiData, 'modelFileName', modelFileList ).name( 'Model' ).onFinishChange( function () {
-
-					reloadObject( true );
-
-				} );
-
-				gui.add( guiData, 'envMapActivated' ).name( 'Env. map' ).onChange( function ( value ) {
-
-					envMapActivated = value;
-
-					reloadObject( false );
-
-				} );
-
-				gui.add( guiData, 'separateObjects' ).name( 'Separate Objects' ).onChange( function () {
-
-					reloadObject( false );
-
-				} );
-
-				gui.add( guiData, 'smoothNormals' ).name( 'Smooth Normals' ).onChange( function () {
-
-					reloadObject( false );
-
-				} );
-
-				gui.add( guiData, 'displayLines' ).name( 'Display Lines' ).onChange( function () {
-
-					updateLineSegments();
-
-				} );
-
-				gui.add( guiData, 'conditionalLines' ).name( 'Conditional Lines' ).onChange( function () {
-
-					updateLineSegments();
-
-				} );
 				window.addEventListener( 'resize', onWindowResize, false );
 
 				progressBarDiv = document.createElement( 'div' );
@@ -171,7 +134,7 @@
 
 			}
 
-			function updateLineSegments() {
+			function updateObjectsVisibility() {
 
 				model.traverse( c => {
 
@@ -188,6 +151,12 @@
 						}
 
 					}
+					else if ( c.isGroup ) {
+
+						// Hide objects with construction step > gui setting
+						c.visible = c.userData.constructionStep <= guiData.constructionStep;
+
+					}
 
 				} );
 
@@ -259,7 +228,9 @@
 
 						}
 
-						updateLineSegments();
+						guiData.constructionStep = model.userData.numConstructionSteps - 1;
+
+						updateObjectsVisibility();
 
 						// Adjust camera and light
 
@@ -275,6 +246,8 @@
 
 						}
 
+						createGUI();
+
 						hideProgressBar();
 
 					}, onProgress, onError );
@@ -290,6 +263,59 @@
 
 			}
 
+			function createGUI() {
+
+				if ( gui ) {
+
+					gui.destroy();
+				}
+
+				gui = new GUI();
+
+				gui.add( guiData, 'modelFileName', modelFileList ).name( 'Model' ).onFinishChange( function () {
+
+					reloadObject( true );
+
+				} );
+
+				gui.add( guiData, 'separateObjects' ).name( 'Separate Objects' ).onChange( function ( value ) {
+
+					reloadObject( false );
+
+				} );
+
+				if ( guiData.separateObjects ) {
+
+					if ( model.userData.numConstructionSteps > 1  ) {
+
+						gui.add( guiData, 'constructionStep', 0, model.userData.numConstructionSteps - 1 ).step( 1 ).name( 'Construction step' ).onChange( updateObjectsVisibility );
+
+					}
+					else {
+
+						gui.add( guiData, 'noConstructionSteps' ).name( 'Construction step' ).onChange( updateObjectsVisibility );
+
+					}
+				}
+
+				gui.add( guiData, 'envMapActivated' ).name( 'Env. map' ).onChange( function changeEnvMap ( value ) {
+
+					envMapActivated = value;
+					reloadObject( false );
+
+				} );
+
+				gui.add( guiData, 'smoothNormals' ).name( 'Smooth Normals' ).onChange( function changeNormals ( value ) {
+
+					reloadObject( false );
+
+				} );
+
+				gui.add( guiData, 'displayLines' ).name( 'Display Lines' ).onChange( updateObjectsVisibility );
+				gui.add( guiData, 'conditionalLines' ).name( 'Conditional Lines' ).onChange( updateObjectsVisibility );
+
+			}
+
 			//
 
 			function animate() {