Skip to content

Commit 683b661

Browse files
authored
Merge pull request #16852 from yomboprime/step_directive
LDrawLoader: Implement STEP directive
2 parents 0eedc63 + 9848016 commit 683b661

File tree

3 files changed

+170
-44
lines changed

3 files changed

+170
-44
lines changed

examples/js/loaders/LDrawLoader.js

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,9 @@ THREE.LDrawLoader = ( function () {
684684
triangles: null,
685685
lineSegments: null,
686686
conditionalSegments: null,
687+
688+
// If true, this object is the start of a construction step
689+
startingConstructionStep: false
687690
};
688691

689692
this.parseScopesStack.push( newParseScope );
@@ -1042,6 +1045,8 @@ THREE.LDrawLoader = ( function () {
10421045
// Retrieve data from the parent parse scope
10431046
var parentParseScope = this.getParentParseScope();
10441047

1048+
var isRoot = ! parentParseScope.isFromParse;
1049+
10451050
// Main colour codes passed to this subobject (or default codes 16 and 24 if it is the root object)
10461051
var mainColourCode = parentParseScope.mainColourCode;
10471052
var mainEdgeColourCode = parentParseScope.mainEdgeColourCode;
@@ -1079,6 +1084,8 @@ THREE.LDrawLoader = ( function () {
10791084
var bfcCull = true;
10801085
var type = '';
10811086

1087+
var startingConstructionStep = false;
1088+
10821089
var scope = this;
10831090
function parseColourCode( lineParser, forEdge ) {
10841091

@@ -1193,6 +1200,8 @@ THREE.LDrawLoader = ( function () {
11931200

11941201
currentParseScope.groupObject = new THREE.Group();
11951202

1203+
currentParseScope.groupObject.userData.startingConstructionStep = currentParseScope.startingConstructionStep;
1204+
11961205
}
11971206

11981207
// If the scale of the object is negated then the triangle winding order
@@ -1320,6 +1329,12 @@ THREE.LDrawLoader = ( function () {
13201329

13211330
break;
13221331

1332+
case 'STEP':
1333+
1334+
startingConstructionStep = true;
1335+
1336+
break;
1337+
13231338
default:
13241339
// Other meta directives are not implemented
13251340
break;
@@ -1385,7 +1400,8 @@ THREE.LDrawLoader = ( function () {
13851400
locationState: LDrawLoader.FILE_LOCATION_AS_IS,
13861401
url: null,
13871402
triedLowerCase: false,
1388-
inverted: bfcInverted !== currentParseScope.inverted
1403+
inverted: bfcInverted !== currentParseScope.inverted,
1404+
startingConstructionStep: startingConstructionStep
13891405
} );
13901406

13911407
bfcInverted = false;
@@ -1594,6 +1610,32 @@ THREE.LDrawLoader = ( function () {
15941610

15951611
},
15961612

1613+
computeConstructionSteps: function ( model ) {
1614+
1615+
// Sets userdata.constructionStep number in Group objects and userData.numConstructionSteps number in the root Group object.
1616+
1617+
var stepNumber = 0;
1618+
1619+
model.traverse( c => {
1620+
1621+
if ( c.isGroup ) {
1622+
1623+
if ( c.userData.startingConstructionStep ) {
1624+
1625+
stepNumber ++;
1626+
1627+
}
1628+
1629+
c.userData.constructionStep = stepNumber;
1630+
1631+
}
1632+
1633+
} );
1634+
1635+
model.userData.numConstructionSteps = stepNumber + 1;
1636+
1637+
},
1638+
15971639
processObject: function ( text, onProcessed, subobject, url ) {
15981640

15991641
var scope = this;
@@ -1609,6 +1651,7 @@ THREE.LDrawLoader = ( function () {
16091651
parseScope.currentMatrix.multiplyMatrices( parentParseScope.currentMatrix, subobject.matrix );
16101652
parseScope.matrix.copy( subobject.matrix );
16111653
parseScope.inverted = subobject.inverted;
1654+
parseScope.startingConstructionStep = subobject.startingConstructionStep;
16121655

16131656
}
16141657

@@ -1763,6 +1806,13 @@ THREE.LDrawLoader = ( function () {
17631806

17641807
scope.removeScopeLevel();
17651808

1809+
// If it is root object, compute construction steps
1810+
if ( ! parentParseScope.isFromParse ) {
1811+
1812+
scope.computeConstructionSteps( parseScope.groupObject );
1813+
1814+
}
1815+
17661816
if ( onProcessed ) {
17671817

17681818
onProcessed( parseScope.groupObject );

examples/jsm/loaders/LDrawLoader.js

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,9 @@ var LDrawLoader = ( function () {
702702
triangles: null,
703703
lineSegments: null,
704704
conditionalSegments: null,
705+
706+
// If true, this object is the start of a construction step
707+
startingConstructionStep: false
705708
};
706709

707710
this.parseScopesStack.push( newParseScope );
@@ -1060,6 +1063,8 @@ var LDrawLoader = ( function () {
10601063
// Retrieve data from the parent parse scope
10611064
var parentParseScope = this.getParentParseScope();
10621065

1066+
var isRoot = ! parentParseScope.isFromParse;
1067+
10631068
// Main colour codes passed to this subobject (or default codes 16 and 24 if it is the root object)
10641069
var mainColourCode = parentParseScope.mainColourCode;
10651070
var mainEdgeColourCode = parentParseScope.mainEdgeColourCode;
@@ -1097,6 +1102,8 @@ var LDrawLoader = ( function () {
10971102
var bfcCull = true;
10981103
var type = '';
10991104

1105+
var startingConstructionStep = false;
1106+
11001107
var scope = this;
11011108
function parseColourCode( lineParser, forEdge ) {
11021109

@@ -1211,6 +1218,8 @@ var LDrawLoader = ( function () {
12111218

12121219
currentParseScope.groupObject = new Group();
12131220

1221+
currentParseScope.groupObject.userData.startingConstructionStep = currentParseScope.startingConstructionStep;
1222+
12141223
}
12151224

12161225
// If the scale of the object is negated then the triangle winding order
@@ -1338,6 +1347,12 @@ var LDrawLoader = ( function () {
13381347

13391348
break;
13401349

1350+
case 'STEP':
1351+
1352+
startingConstructionStep = true;
1353+
1354+
break;
1355+
13411356
default:
13421357
// Other meta directives are not implemented
13431358
break;
@@ -1403,7 +1418,8 @@ var LDrawLoader = ( function () {
14031418
locationState: LDrawLoader.FILE_LOCATION_AS_IS,
14041419
url: null,
14051420
triedLowerCase: false,
1406-
inverted: bfcInverted !== currentParseScope.inverted
1421+
inverted: bfcInverted !== currentParseScope.inverted,
1422+
startingConstructionStep: startingConstructionStep
14071423
} );
14081424

14091425
bfcInverted = false;
@@ -1612,6 +1628,32 @@ var LDrawLoader = ( function () {
16121628

16131629
},
16141630

1631+
computeConstructionSteps: function ( model ) {
1632+
1633+
// Sets userdata.constructionStep number in Group objects and userData.numConstructionSteps number in the root Group object.
1634+
1635+
var stepNumber = 0;
1636+
1637+
model.traverse( c => {
1638+
1639+
if ( c.isGroup ) {
1640+
1641+
if ( c.userData.startingConstructionStep ) {
1642+
1643+
stepNumber ++;
1644+
1645+
}
1646+
1647+
c.userData.constructionStep = stepNumber;
1648+
1649+
}
1650+
1651+
} );
1652+
1653+
model.userData.numConstructionSteps = stepNumber + 1;
1654+
1655+
},
1656+
16151657
processObject: function ( text, onProcessed, subobject, url ) {
16161658

16171659
var scope = this;
@@ -1627,6 +1669,7 @@ var LDrawLoader = ( function () {
16271669
parseScope.currentMatrix.multiplyMatrices( parentParseScope.currentMatrix, subobject.matrix );
16281670
parseScope.matrix.copy( subobject.matrix );
16291671
parseScope.inverted = subobject.inverted;
1672+
parseScope.startingConstructionStep = subobject.startingConstructionStep;
16301673

16311674
}
16321675

@@ -1781,6 +1824,13 @@ var LDrawLoader = ( function () {
17811824

17821825
scope.removeScopeLevel();
17831826

1827+
// If it is root object, compute construction steps
1828+
if ( ! parentParseScope.isFromParse ) {
1829+
1830+
scope.computeConstructionSteps( parseScope.groupObject );
1831+
1832+
}
1833+
17841834
if ( onProcessed ) {
17851835

17861836
onProcessed( parseScope.groupObject );

examples/webgl_loader_ldraw.html

Lines changed: 68 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -110,48 +110,11 @@
110110
separateObjects: false,
111111
displayLines: true,
112112
conditionalLines: true,
113-
smoothNormals: true
113+
smoothNormals: true,
114+
constructionStep: 0,
115+
noConstructionSteps: "No steps."
114116
};
115117

116-
gui = new GUI();
117-
118-
gui.add( guiData, 'modelFileName', modelFileList ).name( 'Model' ).onFinishChange( function () {
119-
120-
reloadObject( true );
121-
122-
} );
123-
124-
gui.add( guiData, 'envMapActivated' ).name( 'Env. map' ).onChange( function ( value ) {
125-
126-
envMapActivated = value;
127-
128-
reloadObject( false );
129-
130-
} );
131-
132-
gui.add( guiData, 'separateObjects' ).name( 'Separate Objects' ).onChange( function () {
133-
134-
reloadObject( false );
135-
136-
} );
137-
138-
gui.add( guiData, 'smoothNormals' ).name( 'Smooth Normals' ).onChange( function () {
139-
140-
reloadObject( false );
141-
142-
} );
143-
144-
gui.add( guiData, 'displayLines' ).name( 'Display Lines' ).onChange( function () {
145-
146-
updateLineSegments();
147-
148-
} );
149-
150-
gui.add( guiData, 'conditionalLines' ).name( 'Conditional Lines' ).onChange( function () {
151-
152-
updateLineSegments();
153-
154-
} );
155118
window.addEventListener( 'resize', onWindowResize, false );
156119

157120
progressBarDiv = document.createElement( 'div' );
@@ -171,7 +134,7 @@
171134

172135
}
173136

174-
function updateLineSegments() {
137+
function updateObjectsVisibility() {
175138

176139
model.traverse( c => {
177140

@@ -188,6 +151,12 @@
188151
}
189152

190153
}
154+
else if ( c.isGroup ) {
155+
156+
// Hide objects with construction step > gui setting
157+
c.visible = c.userData.constructionStep <= guiData.constructionStep;
158+
159+
}
191160

192161
} );
193162

@@ -259,7 +228,9 @@
259228

260229
}
261230

262-
updateLineSegments();
231+
guiData.constructionStep = model.userData.numConstructionSteps - 1;
232+
233+
updateObjectsVisibility();
263234

264235
// Adjust camera and light
265236

@@ -275,6 +246,8 @@
275246

276247
}
277248

249+
createGUI();
250+
278251
hideProgressBar();
279252

280253
}, onProgress, onError );
@@ -290,6 +263,59 @@
290263

291264
}
292265

266+
function createGUI() {
267+
268+
if ( gui ) {
269+
270+
gui.destroy();
271+
}
272+
273+
gui = new GUI();
274+
275+
gui.add( guiData, 'modelFileName', modelFileList ).name( 'Model' ).onFinishChange( function () {
276+
277+
reloadObject( true );
278+
279+
} );
280+
281+
gui.add( guiData, 'separateObjects' ).name( 'Separate Objects' ).onChange( function ( value ) {
282+
283+
reloadObject( false );
284+
285+
} );
286+
287+
if ( guiData.separateObjects ) {
288+
289+
if ( model.userData.numConstructionSteps > 1 ) {
290+
291+
gui.add( guiData, 'constructionStep', 0, model.userData.numConstructionSteps - 1 ).step( 1 ).name( 'Construction step' ).onChange( updateObjectsVisibility );
292+
293+
}
294+
else {
295+
296+
gui.add( guiData, 'noConstructionSteps' ).name( 'Construction step' ).onChange( updateObjectsVisibility );
297+
298+
}
299+
}
300+
301+
gui.add( guiData, 'envMapActivated' ).name( 'Env. map' ).onChange( function changeEnvMap ( value ) {
302+
303+
envMapActivated = value;
304+
reloadObject( false );
305+
306+
} );
307+
308+
gui.add( guiData, 'smoothNormals' ).name( 'Smooth Normals' ).onChange( function changeNormals ( value ) {
309+
310+
reloadObject( false );
311+
312+
} );
313+
314+
gui.add( guiData, 'displayLines' ).name( 'Display Lines' ).onChange( updateObjectsVisibility );
315+
gui.add( guiData, 'conditionalLines' ).name( 'Conditional Lines' ).onChange( updateObjectsVisibility );
316+
317+
}
318+
293319
//
294320

295321
function animate() {

0 commit comments

Comments
 (0)