未验证 提交 284fe38a 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #19312 from Mugen87/dev49

VRMLLoader: Basic support for Extrusion.
......@@ -647,6 +647,10 @@ THREE.VRMLLoader = ( function () {
build = buildElevationGridNode( node );
break;
case 'Extrusion':
build = buildExtrusionNode( node );
break;
case 'Color':
case 'Coordinate':
case 'Normal':
......@@ -681,7 +685,6 @@ THREE.VRMLLoader = ( function () {
case 'TouchSensor':
case 'VisibilitySensor':
case 'Extrusion':
case 'Text':
case 'FontStyle':
......@@ -2386,6 +2389,250 @@ THREE.VRMLLoader = ( function () {
}
function buildExtrusionNode( node ) {
var crossSection = [ 1, 1, 1, - 1, - 1, - 1, - 1, 1, 1, 1 ];
var spine = [ 0, 0, 0, 0, 1, 0 ];
var scale;
var orientation;
var beginCap = true;
var ccw = true;
var creaseAngle = 0;
var endCap = true;
var solid = true;
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 'beginCap':
beginCap = fieldValues[ 0 ];
break;
case 'ccw':
ccw = fieldValues[ 0 ];
break;
case 'convex':
// field not supported
break;
case 'creaseAngle':
creaseAngle = fieldValues[ 0 ];
break;
case 'crossSection':
crossSection = fieldValues;
break;
case 'endCap':
endCap = fieldValues[ 0 ];
break;
case 'orientation':
orientation = fieldValues;
break;
case 'scale':
scale = fieldValues;
break;
case 'solid':
solid = fieldValues[ 0 ];
break;
case 'spine':
spine = fieldValues; // only extrusion along the Y-axis are supported so far
break;
default:
console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
break;
}
}
var crossSectionClosed = ( crossSection[ 0 ] === crossSection[ crossSection.length - 2 ] && crossSection[ 1 ] === crossSection[ crossSection.length - 1 ] );
// vertices
var vertices = [];
var spineVector = new THREE.Vector3();
var scaling = new THREE.Vector3();
var axis = new THREE.Vector3();
var vertex = new THREE.Vector3();
var quaternion = new THREE.Quaternion();
for ( var i = 0, j = 0, o = 0, il = spine.length; i < il; i += 3, j += 2, o += 4 ) {
spineVector.fromArray( spine, i );
scaling.x = scale ? scale[ j + 0 ] : 1;
scaling.y = 1;
scaling.z = scale ? scale[ j + 1 ] : 1;
axis.x = orientation ? orientation[ o + 0 ] : 0;
axis.y = orientation ? orientation[ o + 1 ] : 0;
axis.z = orientation ? orientation[ o + 2 ] : 1;
var angle = orientation ? orientation[ o + 3 ] : 0;
for ( var k = 0, kl = crossSection.length; k < kl; k += 2 ) {
vertex.x = crossSection[ k + 0 ];
vertex.y = 0;
vertex.z = crossSection[ k + 1 ];
// scale
vertex.multiply( scaling );
// rotate
quaternion.setFromAxisAngle( axis, angle );
vertex.applyQuaternion( quaternion );
// translate
vertex.add( spineVector );
vertices.push( vertex.x, vertex.y, vertex.z );
}
}
// indices
var indices = [];
var spineCount = spine.length / 3;
var crossSectionCount = crossSection.length / 2;
for ( var i = 0; i < spineCount - 1; i ++ ) {
for ( var j = 0; j < crossSectionCount - 1; j ++ ) {
var a = j + i * crossSectionCount;
var b = ( j + 1 ) + i * crossSectionCount;
var c = j + ( i + 1 ) * crossSectionCount;
var d = ( j + 1 ) + ( i + 1 ) * crossSectionCount;
if ( ( j === crossSectionCount - 2 ) && ( crossSectionClosed === true ) ) {
b = i * crossSectionCount;
d = ( i + 1 ) * crossSectionCount;
}
if ( ccw === true ) {
indices.push( a, b, c );
indices.push( c, b, d );
} else {
indices.push( a, c, b );
indices.push( c, d, b );
}
}
}
// triangulate cap
if ( beginCap === true || endCap === true ) {
var contour = [];
for ( var i = 0, l = crossSection.length; i < l; i += 2 ) {
contour.push( new THREE.Vector2( crossSection[ i ], crossSection[ i + 1 ] ) );
}
var faces = THREE.ShapeUtils.triangulateShape( contour, [] );
var capIndices = [];
for ( var i = 0, l = faces.length; i < l; i ++ ) {
var face = faces[ i ];
capIndices.push( face[ 0 ], face[ 1 ], face[ 2 ] );
}
// begin cap
if ( beginCap === true ) {
for ( var i = 0, l = capIndices.length; i < l; i += 3 ) {
if ( ccw === true ) {
indices.push( capIndices[ i + 0 ], capIndices[ i + 1 ], capIndices[ i + 2 ] );
} else {
indices.push( capIndices[ i + 0 ], capIndices[ i + 2 ], capIndices[ i + 1 ] );
}
}
}
// end cap
if ( endCap === true ) {
var indexOffset = crossSectionCount * ( spineCount - 1 ); // references to the first vertex of the last cross section
for ( var i = 0, l = capIndices.length; i < l; i += 3 ) {
if ( ccw === true ) {
indices.push( indexOffset + capIndices[ i + 0 ], indexOffset + capIndices[ i + 2 ], indexOffset + capIndices[ i + 1 ] );
} else {
indices.push( indexOffset + capIndices[ i + 0 ], indexOffset + capIndices[ i + 1 ], indexOffset + capIndices[ i + 2 ] );
}
}
}
}
var positionAttribute = toNonIndexedAttribute( indices, new THREE.Float32BufferAttribute( vertices, 3 ) );
var normalAttribute = computeNormalAttribute( indices, vertices, creaseAngle );
var geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', positionAttribute );
geometry.setAttribute( 'normal', normalAttribute );
// no uvs yet
// "solid" influences the material so let's store it for later use
geometry._solid = solid;
geometry._type = 'mesh';
return geometry;
}
// helper functions
function resolveUSE( identifier ) {
......
......@@ -27,10 +27,12 @@ import {
Object3D,
Points,
PointsMaterial,
Quaternion,
RGBAFormat,
RGBFormat,
RepeatWrapping,
Scene,
ShapeUtils,
SphereBufferGeometry,
TextureLoader,
Vector2,
......@@ -683,6 +685,10 @@ var VRMLLoader = ( function () {
build = buildElevationGridNode( node );
break;
case 'Extrusion':
build = buildExtrusionNode( node );
break;
case 'Color':
case 'Coordinate':
case 'Normal':
......@@ -717,7 +723,6 @@ var VRMLLoader = ( function () {
case 'TouchSensor':
case 'VisibilitySensor':
case 'Extrusion':
case 'Text':
case 'FontStyle':
......@@ -2422,6 +2427,249 @@ var VRMLLoader = ( function () {
}
function buildExtrusionNode( node ) {
var crossSection = [ 1, 1, 1, - 1, - 1, - 1, - 1, 1, 1, 1 ];
var spine = [ 0, 0, 0, 0, 1, 0 ];
var scale;
var orientation;
var beginCap = true;
var ccw = true;
var creaseAngle = 0;
var endCap = true;
var solid = true;
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 'beginCap':
beginCap = fieldValues[ 0 ];
break;
case 'ccw':
ccw = fieldValues[ 0 ];
break;
case 'convex':
// field not supported
break;
case 'creaseAngle':
creaseAngle = fieldValues[ 0 ];
break;
case 'crossSection':
crossSection = fieldValues;
break;
case 'endCap':
endCap = fieldValues[ 0 ];
break;
case 'orientation':
orientation = fieldValues;
break;
case 'scale':
scale = fieldValues;
break;
case 'solid':
solid = fieldValues[ 0 ];
break;
case 'spine':
spine = fieldValues; // only extrusion along the Y-axis are supported so far
break;
default:
console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
break;
}
}
var crossSectionClosed = ( crossSection[ 0 ] === crossSection[ crossSection.length - 2 ] && crossSection[ 1 ] === crossSection[ crossSection.length - 1 ] );
// vertices
var vertices = [];
var spineVector = new Vector3();
var scaling = new Vector3();
var axis = new Vector3();
var vertex = new Vector3();
var quaternion = new Quaternion();
for ( var i = 0, j = 0, o = 0, il = spine.length; i < il; i += 3, j += 2, o += 4 ) {
spineVector.fromArray( spine, i );
scaling.x = scale ? scale[ j + 0 ] : 1;
scaling.y = 1;
scaling.z = scale ? scale[ j + 1 ] : 1;
axis.x = orientation ? orientation[ o + 0 ] : 0;
axis.y = orientation ? orientation[ o + 1 ] : 0;
axis.z = orientation ? orientation[ o + 2 ] : 1;
var angle = orientation ? orientation[ o + 3 ] : 0;
for ( var k = 0, kl = crossSection.length; k < kl; k += 2 ) {
vertex.x = crossSection[ k + 0 ];
vertex.y = 0;
vertex.z = crossSection[ k + 1 ];
// scale
vertex.multiply( scaling );
// rotation
quaternion.setFromAxisAngle( axis, angle );
vertex.applyQuaternion( quaternion );
// translate
vertex.add( spineVector );
vertices.push( vertex.x, vertex.y, vertex.z );
}
}
// indices
var indices = [];
var spineCount = spine.length / 3;
var crossSectionCount = crossSection.length / 2;
for ( var i = 0; i < spineCount - 1; i ++ ) {
for ( var j = 0; j < crossSectionCount - 1; j ++ ) {
var a = j + i * crossSectionCount;
var b = ( j + 1 ) + i * crossSectionCount;
var c = j + ( i + 1 ) * crossSectionCount;
var d = ( j + 1 ) + ( i + 1 ) * crossSectionCount;
if ( ( j === crossSectionCount - 2 ) && ( crossSectionClosed === true ) ) {
b = i * crossSectionCount;
d = ( i + 1 ) * crossSectionCount;
}
if ( ccw === true ) {
indices.push( a, b, c );
indices.push( c, b, d );
} else {
indices.push( a, c, b );
indices.push( c, d, b );
}
}
}
// triangulate cap
if ( beginCap === true || endCap === true ) {
var contour = [];
for ( var i = 0, l = crossSection.length; i < l; i += 2 ) {
contour.push( new Vector2( crossSection[ i ], crossSection[ i + 1 ] ) );
}
var faces = ShapeUtils.triangulateShape( contour, [] );
var capIndices = [];
for ( var i = 0, l = faces.length; i < l; i ++ ) {
var face = faces[ i ];
capIndices.push( face[ 0 ], face[ 1 ], face[ 2 ] );
}
// begin cap
if ( beginCap === true ) {
for ( var i = 0, l = capIndices.length; i < l; i += 3 ) {
if ( ccw === true ) {
indices.push( capIndices[ i + 0 ], capIndices[ i + 1 ], capIndices[ i + 2 ] );
} else {
indices.push( capIndices[ i + 0 ], capIndices[ i + 2 ], capIndices[ i + 1 ] );
}
}
}
// end cap
if ( endCap === true ) {
var indexOffset = crossSectionCount * ( spineCount - 1 ); // references to the first vertex of the last cross section
for ( var i = 0, l = capIndices.length; i < l; i += 3 ) {
if ( ccw === true ) {
indices.push( indexOffset + capIndices[ i + 0 ], indexOffset + capIndices[ i + 2 ], indexOffset + capIndices[ i + 1 ] );
} else {
indices.push( indexOffset + capIndices[ i + 0 ], indexOffset + capIndices[ i + 1 ], indexOffset + capIndices[ i + 2 ] );
}
}
}
}
var positionAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( vertices, 3 ) );
var normalAttribute = computeNormalAttribute( indices, vertices, creaseAngle );
var geometry = new BufferGeometry();
geometry.setAttribute( 'position', positionAttribute );
geometry.setAttribute( 'normal', normalAttribute );
// "solid" influences the material so let's store it for later use
geometry._solid = solid;
geometry._type = 'mesh';
return geometry;
}
// helper functions
function resolveUSE( identifier ) {
......
#VRML V2.0 utf8
# X3D-to-VRML-97 XSL translation autogenerated by X3dToVrml97.xslt
# http://www.web3d.org/x3d/content/X3dToVrml97.xslt
# Generated using XSLT processor: SAXON 9.1.0.2 from Saxonica
# [X3D] VRML V3.0 utf8
# PROFILE Immersive
# [X3D] version=3.0
# [X3D] noNamespaceSchemaLocation=http://www.web3d.org/specifications/x3d-3.0.xsd
# [head]
# META "title" "Figure15.10ExtrudedRoom.x3d"
# META "creator" "Figure 15.10, The VRML 2.0 Sourcebook, Copyright [1997] By Andrea L. Ames, David R. Nadeau, and John L. Moreland"
# META "reference" "http://www.wiley.com/legacy/compbooks/vrml2sbk/ch15/15fig10.htm"
# META "translator" "Don Brutzman"
# META "created" "20 August 2000"
# META "modified" "14 January 2010"
# META "description" "An extruded room using a floor plan as the cross section."
# META "identifier" "http://www.web3d.org/x3d/content/examples/Vrml2Sourcebook/Chapter15-Extrusion/Figure15.10ExtrudedRoom.x3d"
# META "generator" "X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit"
# META "license" "../../license.html"
# [Scene] ========== ========== ==========
NavigationInfo { type [ "EXAMINE" "ANY" ] } ### Default X3D NavigationInfo
# Computational cost of Extrusion compared to IndexedFaceSet: quicker to download, takes time to calculate polygonal faces and normals during initial loading, equally fast at run time.
# Authoring capabilities of Extrusion compared to IndexedFaceSet: can be more complicated to express, but also can provide great detail with much less effort.
# First position and rotate viewpoint into positive-X-Y-Z octant using a Transform
Transform {
rotation 0 1 0 0.758
translation 6 3 6
children [
Viewpoint {
description "Extruded room with a doorway"
orientation 1 0 0 -0.2
position 0 0 0
}
]
}
Shape {
appearance Appearance {
material Material {
diffuseColor 1 0.9 0.7
}
}
geometry Extrusion {
convex FALSE
creaseAngle 0.785
crossSection [ -0.5 1.0 -0.5 0.8 -1.8 0.8 -1.8 -0.8 1.8 -0.8 1.8 0.8 0.5 0.8 0.5 1.0 2.0 1.0 2.0 -1.0 -2.0 -1.0 -2.0 1.0 -0.5 1.0 ]
solid FALSE
spine [ 0 0 0 0 2 0 ]
}
}
#VRML V2.0 utf8
# X3D-to-VRML-97 XSL translation autogenerated by X3dToVrml97.xslt
# http://www.web3d.org/x3d/content/X3dToVrml97.xslt
# Generated using XSLT processor: SAXON 9.1.0.2 from Saxonica
# [X3D] VRML V3.0 utf8
# PROFILE Immersive
# [X3D] version=3.0
# [X3D] noNamespaceSchemaLocation=http://www.web3d.org/specifications/x3d-3.0.xsd
# [head]
# META "title" "Figure15.13ExtrudedPyramid.x3d"
# META "creator" "Figure 15.13, The VRML 2.0 Sourcebook, Copyright [1997] By Andrea L. Ames, David R. Nadeau, and John L. Moreland"
# META "reference" "http://www.wiley.com/legacy/compbooks/vrml2sbk/ch15/15fig13.htm"
# META "translator" "Don Brutzman"
# META "created" "20 August 2000"
# META "modified" "11 January 2014"
# META "description" "A pyramid built by scaling a square cross section to 0.01 at the pyramid apex."
# META "identifier" "http://www.web3d.org/x3d/content/examples/Vrml2Sourcebook/Chapter15-Extrusion/Figure15.13ExtrudedPyramid.x3d"
# META "generator" "X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit"
# META "license" "../../license.html"
# [Scene] ========== ========== ==========
NavigationInfo { type [ "EXAMINE" "ANY" ] } ### Default X3D NavigationInfo
# Computational cost of Extrusion compared to IndexedFaceSet: quicker to download, takes time to calculate polygonal faces and normals during initial loading, equally fast at run time.
# Authoring capabilities of Extrusion compared to IndexedFaceSet: can be more complicated to express, but also can provide great detail with much less effort.
# First position and rotate viewpoint into positive-X-Y-Z octant using a Transform
Transform {
rotation 0 1 0 0.758
translation 4 2 4
children [
Viewpoint {
description "Extruded pyramid"
orientation 1 0 0 -0.3
position 0 0 0
}
]
}
Shape {
appearance Appearance {
material Material {
diffuseColor 1 0.5 0
}
}
geometry Extrusion {
crossSection [ -1 1 1 1 1 -1 -1 -1 -1 1 ]
scale [ 1 1 0.01 0.01 ]
}
}
#VRML V2.0 utf8
# X3D-to-VRML-97 XSL translation autogenerated by X3dToVrml97.xslt
# http://www.web3d.org/x3d/content/X3dToVrml97.xslt
# Generated using XSLT processor: SAXON 9.1.0.2 from Saxonica
# [X3D] VRML V3.0 utf8
# PROFILE Immersive
# [X3D] version=3.0
# [X3D] noNamespaceSchemaLocation=http://www.web3d.org/specifications/x3d-3.0.xsd
# [head]
# META "title" "Figure15.15TwistedBar.x3d"
# META "creator" "Figure 15.15, The VRML 2.0 Sourcebook, Copyright [1997] By Andrea L. Ames, David R. Nadeau, and John L. Moreland"
# META "reference" "http://www.wiley.com/legacy/compbooks/vrml2sbk/ch15/15fig15.htm"
# META "translator" "Don Brutzman"
# META "created" "20 August 2000"
# META "modified" "14 January 2010"
# META "description" "A bar twisted using Y-axis, cross-section rotation at each spine coordinate."
# META "identifier" "http://www.web3d.org/x3d/content/examples/Vrml2Sourcebook/Chapter15-Extrusion/Figure15.15TwistedBar.x3d"
# META "generator" "X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit"
# META "license" "../../license.html"
# [Scene] ========== ========== ==========
NavigationInfo { type [ "EXAMINE" "ANY" ] } ### Default X3D NavigationInfo
# Computational cost of Extrusion compared to IndexedFaceSet: quicker to download, takes time to calculate polygonal faces and normals during initial loading, equally fast at run time.
# Authoring capabilities of Extrusion compared to IndexedFaceSet: can be more complicated to express, but also can provide great detail with much less effort.
# First position and rotate viewpoint into positive-X-Y-Z octant using a Transform
Transform {
rotation 0 1 0 0.758
translation 10 5 10
children [
Viewpoint {
description "Twisted bar using extrusion orientations"
orientation 1 0 0 -0.3
position 0 0 0
}
]
}
Shape {
appearance Appearance {
material Material {
diffuseColor 1 0.5 0
}
}
geometry Extrusion {
creaseAngle 0.785
crossSection [ -1 1 1 1 1 -1 -1 -1 -1 1 ]
orientation [ 0 1 0 0 0 1 0 0.175 0 1 0 0.349 0 1 0 0.524 0 1 0 0.698 0 1 0 0.873 0 1 0 1.047 0 1 0 1.222 0 1 0 1.396 ]
spine [ 0 0.0 0 0 0.5 0 0 1.0 0 0 1.5 0 0 2.0 0 0 2.5 0 0 3.0 0 0 3.5 0 0 4.0 0 ]
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册