|
@@ -271,7 +271,19 @@ THREE.LDrawLoader = ( function () {
|
|
|
|
|
|
}, onProgress, onError );
|
|
|
|
|
|
- function processObject( text, onProcessed ) {
|
|
|
+ function subobjectLoad( url, onLoad, onProgress, onError, subobject ) {
|
|
|
+
|
|
|
+ var fileLoader = new THREE.FileLoader( scope.manager );
|
|
|
+ fileLoader.setPath( scope.path );
|
|
|
+ fileLoader.load( url, function ( text ) {
|
|
|
+
|
|
|
+ processObject( text, onLoad, subobject );
|
|
|
+
|
|
|
+ }, onProgress, onError );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function processObject( text, onProcessed, subobject ) {
|
|
|
|
|
|
var parseScope = scope.newParseScopeLevel();
|
|
|
parseScope.url = url;
|
|
@@ -284,9 +296,10 @@ THREE.LDrawLoader = ( function () {
|
|
|
|
|
|
scope.subobjectCache[ currentFileName ] = text;
|
|
|
|
|
|
-
|
|
|
}
|
|
|
|
|
|
+ parseScope.inverted = subobject !== undefined ? subobject.inverted : false;
|
|
|
+
|
|
|
// Parse the object (returns a THREE.Group)
|
|
|
var objGroup = scope.parse( text );
|
|
|
|
|
@@ -372,7 +385,7 @@ THREE.LDrawLoader = ( function () {
|
|
|
var cached = scope.subobjectCache[ subobject.originalFileName ];
|
|
|
if ( cached ) {
|
|
|
|
|
|
- var subobjectGroup = processObject( cached, sync ? undefined : onSubobjectLoaded );
|
|
|
+ var subobjectGroup = processObject( cached, sync ? undefined : onSubobjectLoaded, subobject );
|
|
|
if ( sync ) {
|
|
|
|
|
|
addSubobject( subobject, subobjectGroup );
|
|
@@ -462,7 +475,7 @@ THREE.LDrawLoader = ( function () {
|
|
|
subobject.url = subobjectURL;
|
|
|
|
|
|
// Load the subobject
|
|
|
- scope.load( subobjectURL, onSubobjectLoaded, undefined, onSubobjectError );
|
|
|
+ subobjectLoad( subobjectURL, onSubobjectLoaded, undefined, onSubobjectError, subobject );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -587,6 +600,7 @@ THREE.LDrawLoader = ( function () {
|
|
|
subobjects: null,
|
|
|
numSubobjects: 0,
|
|
|
subobjectIndex: 0,
|
|
|
+ inverted: false,
|
|
|
|
|
|
// Current subobject
|
|
|
currentFileName: null,
|
|
@@ -897,9 +911,6 @@ THREE.LDrawLoader = ( function () {
|
|
|
|
|
|
}
|
|
|
|
|
|
- // BFC (Back Face Culling) LDraw language meta extension is not implemented, so set all materials double-sided:
|
|
|
- material.side = THREE.DoubleSide;
|
|
|
-
|
|
|
material.transparent = isTransparent;
|
|
|
material.opacity = alpha;
|
|
|
|
|
@@ -1035,6 +1046,10 @@ THREE.LDrawLoader = ( function () {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ var bfcEnabled = false;
|
|
|
+ var bfcCCW = true;
|
|
|
+ var bfcInverted = false;
|
|
|
+
|
|
|
// Parse all line commands
|
|
|
for ( lineIndex = 0; lineIndex < numLines; lineIndex ++ ) {
|
|
|
|
|
@@ -1137,6 +1152,56 @@ THREE.LDrawLoader = ( function () {
|
|
|
currentEmbeddedFileName = lp.getRemainingString();
|
|
|
currentEmbeddedText = '';
|
|
|
|
|
|
+ bfcEnabled = false;
|
|
|
+ bfcCCW = true;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'BFC':
|
|
|
+
|
|
|
+ while ( ! lp.isAtTheEnd() ) {
|
|
|
+
|
|
|
+ var token = lp.getToken();
|
|
|
+ bfcCCW = true;
|
|
|
+ switch ( token ) {
|
|
|
+
|
|
|
+ case 'CERTIFY':
|
|
|
+ case 'NOCERTIFY':
|
|
|
+
|
|
|
+ bfcEnabled = token === 'CERTIFY';
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'CW':
|
|
|
+ case 'CCW':
|
|
|
+
|
|
|
+ bfcCCW = token === 'CCW';
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'INVERTNEXT':
|
|
|
+
|
|
|
+ bfcInverted = true;
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'CLIP':
|
|
|
+ case 'NOCLIP':
|
|
|
+
|
|
|
+ console.warn( 'THREE.LDrawLoader: BFC CLIP and NOCLIP directives ignored.' );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+
|
|
|
+ console.warn( 'THREE.LDrawLoader: BFC directive "' + token + '" is unknown.' );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
break;
|
|
@@ -1205,9 +1270,12 @@ THREE.LDrawLoader = ( function () {
|
|
|
originalFileName: fileName,
|
|
|
locationState: LDrawLoader.FILE_LOCATION_AS_IS,
|
|
|
url: null,
|
|
|
- triedLowerCase: false
|
|
|
+ triedLowerCase: false,
|
|
|
+ inverted: bfcInverted !== currentParseScope.inverted
|
|
|
} );
|
|
|
|
|
|
+ bfcInverted = false;
|
|
|
+
|
|
|
break;
|
|
|
|
|
|
// Line type 2: Line segment
|
|
@@ -1229,12 +1297,30 @@ THREE.LDrawLoader = ( function () {
|
|
|
|
|
|
var material = parseColourCode( lp );
|
|
|
|
|
|
+ var inverted = currentParseScope.inverted;
|
|
|
+ var ccw = ! bfcEnabled || bfcEnabled && bfcCCW && ! inverted;
|
|
|
+ var v0, v1, v2;
|
|
|
+
|
|
|
+ if ( ccw === true ) {
|
|
|
+
|
|
|
+ v0 = parseVector( lp );
|
|
|
+ v1 = parseVector( lp );
|
|
|
+ v2 = parseVector( lp );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ v2 = parseVector( lp );
|
|
|
+ v1 = parseVector( lp );
|
|
|
+ v0 = parseVector( lp );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
triangles.push( {
|
|
|
material: material,
|
|
|
colourCode: material.userData.code,
|
|
|
- v0: parseVector( lp ),
|
|
|
- v1: parseVector( lp ),
|
|
|
- v2: parseVector( lp )
|
|
|
+ v0: v0,
|
|
|
+ v1: v1,
|
|
|
+ v2: v2
|
|
|
} );
|
|
|
|
|
|
break;
|
|
@@ -1244,10 +1330,25 @@ THREE.LDrawLoader = ( function () {
|
|
|
|
|
|
var material = parseColourCode( lp );
|
|
|
|
|
|
- var v0 = parseVector( lp );
|
|
|
- var v1 = parseVector( lp );
|
|
|
- var v2 = parseVector( lp );
|
|
|
- var v3 = parseVector( lp );
|
|
|
+ var inverted = currentParseScope.inverted;
|
|
|
+ var ccw = ! bfcEnabled || bfcEnabled && bfcCCW && ! inverted;
|
|
|
+ var v0, v1, v2, v3;
|
|
|
+
|
|
|
+ if ( ccw === true ) {
|
|
|
+
|
|
|
+ v0 = parseVector( lp );
|
|
|
+ v1 = parseVector( lp );
|
|
|
+ v2 = parseVector( lp );
|
|
|
+ v3 = parseVector( lp );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ v3 = parseVector( lp );
|
|
|
+ v2 = parseVector( lp );
|
|
|
+ v1 = parseVector( lp );
|
|
|
+ v0 = parseVector( lp );
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
triangles.push( {
|
|
|
material: material,
|