summit/frontend/node_modules/three-stdlib/loaders/VRMLLoader.js

2103 lines
68 KiB
JavaScript

import { Loader, LoaderUtils, FileLoader, Vector3, Vector2, TextureLoader, Scene, Object3D, Group, SphereGeometry, MeshBasicMaterial, BackSide, Mesh, PointsMaterial, Points, LineBasicMaterial, LineSegments, FrontSide, DoubleSide, MeshPhongMaterial, Color, DataTexture, BufferGeometry, Float32BufferAttribute, BoxGeometry, ConeGeometry, CylinderGeometry, Quaternion, ShapeUtils, BufferAttribute, RepeatWrapping, ClampToEdgeWrapping } from "three";
import { createToken, Lexer, CstParser } from "../libs/chevrotain.js";
class VRMLLoader extends Loader {
constructor(manager) {
super(manager);
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const path = scope.path === "" ? LoaderUtils.extractUrlBase(url) : scope.path;
const loader = new FileLoader(scope.manager);
loader.setPath(scope.path);
loader.setRequestHeader(scope.requestHeader);
loader.setWithCredentials(scope.withCredentials);
loader.load(
url,
function(text) {
try {
onLoad(scope.parse(text, path));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
},
onProgress,
onError
);
}
parse(data, path) {
const nodeMap = {};
function generateVRMLTree(data2) {
const tokenData = createTokens();
const lexer = new VRMLLexer(tokenData.tokens);
const parser = new VRMLParser(tokenData.tokenVocabulary);
const visitor = createVisitor(parser.getBaseCstVisitorConstructor());
const lexingResult = lexer.lex(data2);
parser.input = lexingResult.tokens;
const cstOutput = parser.vrml();
if (parser.errors.length > 0) {
console.error(parser.errors);
throw Error("THREE.VRMLLoader: Parsing errors detected.");
}
const ast = visitor.visit(cstOutput);
return ast;
}
function createTokens() {
const RouteIdentifier = createToken({
name: "RouteIdentifier",
pattern: /[^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*[\.][^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*/
});
const Identifier = createToken({
name: "Identifier",
pattern: /[^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*/,
longer_alt: RouteIdentifier
});
const nodeTypes = [
"Anchor",
"Billboard",
"Collision",
"Group",
"Transform",
// grouping nodes
"Inline",
"LOD",
"Switch",
// special groups
"AudioClip",
"DirectionalLight",
"PointLight",
"Script",
"Shape",
"Sound",
"SpotLight",
"WorldInfo",
// common nodes
"CylinderSensor",
"PlaneSensor",
"ProximitySensor",
"SphereSensor",
"TimeSensor",
"TouchSensor",
"VisibilitySensor",
// sensors
"Box",
"Cone",
"Cylinder",
"ElevationGrid",
"Extrusion",
"IndexedFaceSet",
"IndexedLineSet",
"PointSet",
"Sphere",
// geometries
"Color",
"Coordinate",
"Normal",
"TextureCoordinate",
// geometric properties
"Appearance",
"FontStyle",
"ImageTexture",
"Material",
"MovieTexture",
"PixelTexture",
"TextureTransform",
// appearance
"ColorInterpolator",
"CoordinateInterpolator",
"NormalInterpolator",
"OrientationInterpolator",
"PositionInterpolator",
"ScalarInterpolator",
// interpolators
"Background",
"Fog",
"NavigationInfo",
"Viewpoint",
// bindable nodes
"Text"
// Text must be placed at the end of the regex so there are no matches for TextureTransform and TextureCoordinate
];
const Version = createToken({
name: "Version",
pattern: /#VRML.*/,
longer_alt: Identifier
});
const NodeName = createToken({
name: "NodeName",
pattern: new RegExp(nodeTypes.join("|")),
longer_alt: Identifier
});
const DEF = createToken({
name: "DEF",
pattern: /DEF/,
longer_alt: Identifier
});
const USE = createToken({
name: "USE",
pattern: /USE/,
longer_alt: Identifier
});
const ROUTE = createToken({
name: "ROUTE",
pattern: /ROUTE/,
longer_alt: Identifier
});
const TO = createToken({
name: "TO",
pattern: /TO/,
longer_alt: Identifier
});
const StringLiteral = createToken({
name: "StringLiteral",
pattern: /"(?:[^\\"\n\r]|\\[bfnrtv"\\/]|\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])*"/
});
const HexLiteral = createToken({ name: "HexLiteral", pattern: /0[xX][0-9a-fA-F]+/ });
const NumberLiteral = createToken({ name: "NumberLiteral", pattern: /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/ });
const TrueLiteral = createToken({ name: "TrueLiteral", pattern: /TRUE/ });
const FalseLiteral = createToken({ name: "FalseLiteral", pattern: /FALSE/ });
const NullLiteral = createToken({ name: "NullLiteral", pattern: /NULL/ });
const LSquare = createToken({ name: "LSquare", pattern: /\[/ });
const RSquare = createToken({ name: "RSquare", pattern: /]/ });
const LCurly = createToken({ name: "LCurly", pattern: /{/ });
const RCurly = createToken({ name: "RCurly", pattern: /}/ });
const Comment = createToken({
name: "Comment",
pattern: /#.*/,
group: Lexer.SKIPPED
});
const WhiteSpace = createToken({
name: "WhiteSpace",
pattern: /[ ,\s]/,
group: Lexer.SKIPPED
});
const tokens = [
WhiteSpace,
// keywords appear before the Identifier
NodeName,
DEF,
USE,
ROUTE,
TO,
TrueLiteral,
FalseLiteral,
NullLiteral,
// the Identifier must appear after the keywords because all keywords are valid identifiers
Version,
Identifier,
RouteIdentifier,
StringLiteral,
HexLiteral,
NumberLiteral,
LSquare,
RSquare,
LCurly,
RCurly,
Comment
];
const tokenVocabulary = {};
for (let i = 0, l = tokens.length; i < l; i++) {
const token = tokens[i];
tokenVocabulary[token.name] = token;
}
return { tokens, tokenVocabulary };
}
function createVisitor(BaseVRMLVisitor) {
function VRMLToASTVisitor() {
BaseVRMLVisitor.call(this);
this.validateVisitor();
}
VRMLToASTVisitor.prototype = Object.assign(Object.create(BaseVRMLVisitor.prototype), {
constructor: VRMLToASTVisitor,
vrml: function(ctx) {
const data2 = {
version: this.visit(ctx.version),
nodes: [],
routes: []
};
for (let i = 0, l = ctx.node.length; i < l; i++) {
const node = ctx.node[i];
data2.nodes.push(this.visit(node));
}
if (ctx.route) {
for (let i = 0, l = ctx.route.length; i < l; i++) {
const route = ctx.route[i];
data2.routes.push(this.visit(route));
}
}
return data2;
},
version: function(ctx) {
return ctx.Version[0].image;
},
node: function(ctx) {
const data2 = {
name: ctx.NodeName[0].image,
fields: []
};
if (ctx.field) {
for (let i = 0, l = ctx.field.length; i < l; i++) {
const field = ctx.field[i];
data2.fields.push(this.visit(field));
}
}
if (ctx.def) {
data2.DEF = this.visit(ctx.def[0]);
}
return data2;
},
field: function(ctx) {
const data2 = {
name: ctx.Identifier[0].image,
type: null,
values: null
};
let result;
if (ctx.singleFieldValue) {
result = this.visit(ctx.singleFieldValue[0]);
}
if (ctx.multiFieldValue) {
result = this.visit(ctx.multiFieldValue[0]);
}
data2.type = result.type;
data2.values = result.values;
return data2;
},
def: function(ctx) {
return (ctx.Identifier || ctx.NodeName)[0].image;
},
use: function(ctx) {
return { USE: (ctx.Identifier || ctx.NodeName)[0].image };
},
singleFieldValue: function(ctx) {
return processField(this, ctx);
},
multiFieldValue: function(ctx) {
return processField(this, ctx);
},
route: function(ctx) {
const data2 = {
FROM: ctx.RouteIdentifier[0].image,
TO: ctx.RouteIdentifier[1].image
};
return data2;
}
});
function processField(scope, ctx) {
const field = {
type: null,
values: []
};
if (ctx.node) {
field.type = "node";
for (let i = 0, l = ctx.node.length; i < l; i++) {
const node = ctx.node[i];
field.values.push(scope.visit(node));
}
}
if (ctx.use) {
field.type = "use";
for (let i = 0, l = ctx.use.length; i < l; i++) {
const use = ctx.use[i];
field.values.push(scope.visit(use));
}
}
if (ctx.StringLiteral) {
field.type = "string";
for (let i = 0, l = ctx.StringLiteral.length; i < l; i++) {
const stringLiteral = ctx.StringLiteral[i];
field.values.push(stringLiteral.image.replace(/'|"/g, ""));
}
}
if (ctx.NumberLiteral) {
field.type = "number";
for (let i = 0, l = ctx.NumberLiteral.length; i < l; i++) {
const numberLiteral = ctx.NumberLiteral[i];
field.values.push(parseFloat(numberLiteral.image));
}
}
if (ctx.HexLiteral) {
field.type = "hex";
for (let i = 0, l = ctx.HexLiteral.length; i < l; i++) {
const hexLiteral = ctx.HexLiteral[i];
field.values.push(hexLiteral.image);
}
}
if (ctx.TrueLiteral) {
field.type = "boolean";
for (let i = 0, l = ctx.TrueLiteral.length; i < l; i++) {
const trueLiteral = ctx.TrueLiteral[i];
if (trueLiteral.image === "TRUE")
field.values.push(true);
}
}
if (ctx.FalseLiteral) {
field.type = "boolean";
for (let i = 0, l = ctx.FalseLiteral.length; i < l; i++) {
const falseLiteral = ctx.FalseLiteral[i];
if (falseLiteral.image === "FALSE")
field.values.push(false);
}
}
if (ctx.NullLiteral) {
field.type = "null";
ctx.NullLiteral.forEach(function() {
field.values.push(null);
});
}
return field;
}
return new VRMLToASTVisitor();
}
function parseTree(tree2) {
const nodes = tree2.nodes;
const scene2 = new Scene();
for (let i = 0, l = nodes.length; i < l; i++) {
const node = nodes[i];
buildNodeMap(node);
}
for (let i = 0, l = nodes.length; i < l; i++) {
const node = nodes[i];
const object = getNode(node);
if (object instanceof Object3D)
scene2.add(object);
if (node.name === "WorldInfo")
scene2.userData.worldInfo = object;
}
return scene2;
}
function buildNodeMap(node) {
if (node.DEF) {
nodeMap[node.DEF] = node;
}
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
if (field.type === "node") {
const fieldValues = field.values;
for (let j = 0, jl = fieldValues.length; j < jl; j++) {
buildNodeMap(fieldValues[j]);
}
}
}
}
function getNode(node) {
if (node.USE) {
return resolveUSE(node.USE);
}
if (node.build !== void 0)
return node.build;
node.build = buildNode(node);
return node.build;
}
function buildNode(node) {
const nodeName = node.name;
let build;
switch (nodeName) {
case "Group":
case "Transform":
case "Collision":
build = buildGroupingNode(node);
break;
case "Background":
build = buildBackgroundNode(node);
break;
case "Shape":
build = buildShapeNode(node);
break;
case "Appearance":
build = buildAppearanceNode(node);
break;
case "Material":
build = buildMaterialNode(node);
break;
case "ImageTexture":
build = buildImageTextureNode(node);
break;
case "PixelTexture":
build = buildPixelTextureNode(node);
break;
case "TextureTransform":
build = buildTextureTransformNode(node);
break;
case "IndexedFaceSet":
build = buildIndexedFaceSetNode(node);
break;
case "IndexedLineSet":
build = buildIndexedLineSetNode(node);
break;
case "PointSet":
build = buildPointSetNode(node);
break;
case "Box":
build = buildBoxNode(node);
break;
case "Cone":
build = buildConeNode(node);
break;
case "Cylinder":
build = buildCylinderNode(node);
break;
case "Sphere":
build = buildSphereNode(node);
break;
case "ElevationGrid":
build = buildElevationGridNode(node);
break;
case "Extrusion":
build = buildExtrusionNode(node);
break;
case "Color":
case "Coordinate":
case "Normal":
case "TextureCoordinate":
build = buildGeometricNode(node);
break;
case "WorldInfo":
build = buildWorldInfoNode(node);
break;
case "Anchor":
case "Billboard":
case "Inline":
case "LOD":
case "Switch":
case "AudioClip":
case "DirectionalLight":
case "PointLight":
case "Script":
case "Sound":
case "SpotLight":
case "CylinderSensor":
case "PlaneSensor":
case "ProximitySensor":
case "SphereSensor":
case "TimeSensor":
case "TouchSensor":
case "VisibilitySensor":
case "Text":
case "FontStyle":
case "MovieTexture":
case "ColorInterpolator":
case "CoordinateInterpolator":
case "NormalInterpolator":
case "OrientationInterpolator":
case "PositionInterpolator":
case "ScalarInterpolator":
case "Fog":
case "NavigationInfo":
case "Viewpoint":
break;
default:
console.warn("THREE.VRMLLoader: Unknown node:", nodeName);
break;
}
if (build !== void 0 && node.DEF !== void 0 && build.hasOwnProperty("name") === true) {
build.name = node.DEF;
}
return build;
}
function buildGroupingNode(node) {
const object = new Group();
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "bboxCenter":
break;
case "bboxSize":
break;
case "center":
break;
case "children":
parseFieldChildren(fieldValues, object);
break;
case "collide":
break;
case "rotation":
const axis = new Vector3(fieldValues[0], fieldValues[1], fieldValues[2]).normalize();
const angle = fieldValues[3];
object.quaternion.setFromAxisAngle(axis, angle);
break;
case "scale":
object.scale.set(fieldValues[0], fieldValues[1], fieldValues[2]);
break;
case "scaleOrientation":
break;
case "translation":
object.position.set(fieldValues[0], fieldValues[1], fieldValues[2]);
break;
case "proxy":
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
return object;
}
function buildBackgroundNode(node) {
const group = new Group();
let groundAngle, groundColor;
let skyAngle, skyColor;
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "groundAngle":
groundAngle = fieldValues;
break;
case "groundColor":
groundColor = fieldValues;
break;
case "backUrl":
break;
case "bottomUrl":
break;
case "frontUrl":
break;
case "leftUrl":
break;
case "rightUrl":
break;
case "topUrl":
break;
case "skyAngle":
skyAngle = fieldValues;
break;
case "skyColor":
skyColor = fieldValues;
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
const radius = 1e4;
if (skyColor) {
const skyGeometry = new SphereGeometry(radius, 32, 16);
const skyMaterial = new MeshBasicMaterial({ fog: false, side: BackSide, depthWrite: false, depthTest: false });
if (skyColor.length > 3) {
paintFaces(skyGeometry, radius, skyAngle, toColorArray(skyColor), true);
skyMaterial.vertexColors = true;
} else {
skyMaterial.color.setRGB(skyColor[0], skyColor[1], skyColor[2]);
}
const sky = new Mesh(skyGeometry, skyMaterial);
group.add(sky);
}
if (groundColor) {
if (groundColor.length > 0) {
const groundGeometry = new SphereGeometry(radius, 32, 16, 0, 2 * Math.PI, 0.5 * Math.PI, 1.5 * Math.PI);
const groundMaterial = new MeshBasicMaterial({
fog: false,
side: BackSide,
vertexColors: true,
depthWrite: false,
depthTest: false
});
paintFaces(groundGeometry, radius, groundAngle, toColorArray(groundColor), false);
const ground = new Mesh(groundGeometry, groundMaterial);
group.add(ground);
}
}
group.renderOrder = -Infinity;
return group;
}
function buildShapeNode(node) {
const fields = node.fields;
let material = new MeshBasicMaterial({ color: 0 });
let geometry;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "appearance":
if (fieldValues[0] !== null) {
material = getNode(fieldValues[0]);
}
break;
case "geometry":
if (fieldValues[0] !== null) {
geometry = getNode(fieldValues[0]);
}
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
let object;
if (geometry && geometry.attributes.position) {
const type = geometry._type;
if (type === "points") {
const pointsMaterial = new PointsMaterial({ color: 16777215 });
if (geometry.attributes.color !== void 0) {
pointsMaterial.vertexColors = true;
} else {
if (material.isMeshPhongMaterial) {
pointsMaterial.color.copy(material.emissive);
}
}
object = new Points(geometry, pointsMaterial);
} else if (type === "line") {
const lineMaterial = new LineBasicMaterial({ color: 16777215 });
if (geometry.attributes.color !== void 0) {
lineMaterial.vertexColors = true;
} else {
if (material.isMeshPhongMaterial) {
lineMaterial.color.copy(material.emissive);
}
}
object = new LineSegments(geometry, lineMaterial);
} else {
if (geometry._solid !== void 0) {
material.side = geometry._solid ? FrontSide : DoubleSide;
}
if (geometry.attributes.color !== void 0) {
material.vertexColors = true;
}
object = new Mesh(geometry, material);
}
} else {
object = new Object3D();
object.visible = false;
}
return object;
}
function buildAppearanceNode(node) {
let material = new MeshPhongMaterial();
let transformData;
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "material":
if (fieldValues[0] !== null) {
const materialData = getNode(fieldValues[0]);
if (materialData.diffuseColor)
material.color.copy(materialData.diffuseColor);
if (materialData.emissiveColor)
material.emissive.copy(materialData.emissiveColor);
if (materialData.shininess)
material.shininess = materialData.shininess;
if (materialData.specularColor)
material.specular.copy(materialData.specularColor);
if (materialData.transparency)
material.opacity = 1 - materialData.transparency;
if (materialData.transparency > 0)
material.transparent = true;
} else {
material = new MeshBasicMaterial({ color: 0 });
}
break;
case "texture":
const textureNode = fieldValues[0];
if (textureNode !== null) {
if (textureNode.name === "ImageTexture" || textureNode.name === "PixelTexture") {
material.map = getNode(textureNode);
}
}
break;
case "textureTransform":
if (fieldValues[0] !== null) {
transformData = getNode(fieldValues[0]);
}
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
if (material.map) {
if (material.map.__type) {
switch (material.map.__type) {
case TEXTURE_TYPE.INTENSITY_ALPHA:
material.opacity = 1;
break;
case TEXTURE_TYPE.RGB:
material.color.set(16777215);
break;
case TEXTURE_TYPE.RGBA:
material.color.set(16777215);
material.opacity = 1;
break;
}
delete material.map.__type;
}
if (transformData) {
material.map.center.copy(transformData.center);
material.map.rotation = transformData.rotation;
material.map.repeat.copy(transformData.scale);
material.map.offset.copy(transformData.translation);
}
}
return material;
}
function buildMaterialNode(node) {
const materialData = {};
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "ambientIntensity":
break;
case "diffuseColor":
materialData.diffuseColor = new Color(fieldValues[0], fieldValues[1], fieldValues[2]);
break;
case "emissiveColor":
materialData.emissiveColor = new Color(fieldValues[0], fieldValues[1], fieldValues[2]);
break;
case "shininess":
materialData.shininess = fieldValues[0];
break;
case "specularColor":
materialData.emissiveColor = new Color(fieldValues[0], fieldValues[1], fieldValues[2]);
break;
case "transparency":
materialData.transparency = fieldValues[0];
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
return materialData;
}
function parseHexColor(hex, textureType, color) {
let value;
switch (textureType) {
case TEXTURE_TYPE.INTENSITY:
value = parseInt(hex);
color.r = value;
color.g = value;
color.b = value;
color.a = 1;
break;
case TEXTURE_TYPE.INTENSITY_ALPHA:
value = parseInt("0x" + hex.substring(2, 4));
color.r = value;
color.g = value;
color.b = value;
color.a = parseInt("0x" + hex.substring(4, 6));
break;
case TEXTURE_TYPE.RGB:
color.r = parseInt("0x" + hex.substring(2, 4));
color.g = parseInt("0x" + hex.substring(4, 6));
color.b = parseInt("0x" + hex.substring(6, 8));
color.a = 1;
break;
case TEXTURE_TYPE.RGBA:
color.r = parseInt("0x" + hex.substring(2, 4));
color.g = parseInt("0x" + hex.substring(4, 6));
color.b = parseInt("0x" + hex.substring(6, 8));
color.a = parseInt("0x" + hex.substring(8, 10));
break;
}
}
function getTextureType(num_components) {
let type;
switch (num_components) {
case 1:
type = TEXTURE_TYPE.INTENSITY;
break;
case 2:
type = TEXTURE_TYPE.INTENSITY_ALPHA;
break;
case 3:
type = TEXTURE_TYPE.RGB;
break;
case 4:
type = TEXTURE_TYPE.RGBA;
break;
}
return type;
}
function buildPixelTextureNode(node) {
let texture;
let wrapS = RepeatWrapping;
let wrapT = RepeatWrapping;
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "image":
const width = fieldValues[0];
const height = fieldValues[1];
const num_components = fieldValues[2];
const textureType = getTextureType(num_components);
const data2 = new Uint8Array(4 * width * height);
const color = { r: 0, g: 0, b: 0, a: 0 };
for (let j = 3, k = 0, jl = fieldValues.length; j < jl; j++, k++) {
parseHexColor(fieldValues[j], textureType, color);
const stride = k * 4;
data2[stride + 0] = color.r;
data2[stride + 1] = color.g;
data2[stride + 2] = color.b;
data2[stride + 3] = color.a;
}
texture = new DataTexture(data2, width, height);
texture.needsUpdate = true;
texture.__type = textureType;
break;
case "repeatS":
if (fieldValues[0] === false)
wrapS = ClampToEdgeWrapping;
break;
case "repeatT":
if (fieldValues[0] === false)
wrapT = ClampToEdgeWrapping;
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
if (texture) {
texture.wrapS = wrapS;
texture.wrapT = wrapT;
}
return texture;
}
function buildImageTextureNode(node) {
let texture;
let wrapS = RepeatWrapping;
let wrapT = RepeatWrapping;
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "url":
const url = fieldValues[0];
if (url)
texture = textureLoader.load(url);
break;
case "repeatS":
if (fieldValues[0] === false)
wrapS = ClampToEdgeWrapping;
break;
case "repeatT":
if (fieldValues[0] === false)
wrapT = ClampToEdgeWrapping;
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
if (texture) {
texture.wrapS = wrapS;
texture.wrapT = wrapT;
}
return texture;
}
function buildTextureTransformNode(node) {
const transformData = {
center: new Vector2(),
rotation: new Vector2(),
scale: new Vector2(),
translation: new Vector2()
};
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "center":
transformData.center.set(fieldValues[0], fieldValues[1]);
break;
case "rotation":
transformData.rotation = fieldValues[0];
break;
case "scale":
transformData.scale.set(fieldValues[0], fieldValues[1]);
break;
case "translation":
transformData.translation.set(fieldValues[0], fieldValues[1]);
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
return transformData;
}
function buildGeometricNode(node) {
return node.fields[0].values;
}
function buildWorldInfoNode(node) {
const worldInfo = {};
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "title":
worldInfo.title = fieldValues[0];
break;
case "info":
worldInfo.info = fieldValues;
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
return worldInfo;
}
function buildIndexedFaceSetNode(node) {
let color, coord, normal, texCoord;
let ccw = true, solid = true, creaseAngle = 0;
let colorIndex, coordIndex, normalIndex, texCoordIndex;
let colorPerVertex = true, normalPerVertex = true;
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "color":
const colorNode = fieldValues[0];
if (colorNode !== null) {
color = getNode(colorNode);
}
break;
case "coord":
const coordNode = fieldValues[0];
if (coordNode !== null) {
coord = getNode(coordNode);
}
break;
case "normal":
const normalNode = fieldValues[0];
if (normalNode !== null) {
normal = getNode(normalNode);
}
break;
case "texCoord":
const texCoordNode = fieldValues[0];
if (texCoordNode !== null) {
texCoord = getNode(texCoordNode);
}
break;
case "ccw":
ccw = fieldValues[0];
break;
case "colorIndex":
colorIndex = fieldValues;
break;
case "colorPerVertex":
colorPerVertex = fieldValues[0];
break;
case "convex":
break;
case "coordIndex":
coordIndex = fieldValues;
break;
case "creaseAngle":
creaseAngle = fieldValues[0];
break;
case "normalIndex":
normalIndex = fieldValues;
break;
case "normalPerVertex":
normalPerVertex = fieldValues[0];
break;
case "solid":
solid = fieldValues[0];
break;
case "texCoordIndex":
texCoordIndex = fieldValues;
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
if (coordIndex === void 0) {
console.warn("THREE.VRMLLoader: Missing coordIndex.");
return new BufferGeometry();
}
const triangulatedCoordIndex = triangulateFaceIndex(coordIndex, ccw);
let colorAttribute;
let normalAttribute;
let uvAttribute;
if (color) {
if (colorPerVertex === true) {
if (colorIndex && colorIndex.length > 0) {
const triangulatedColorIndex = triangulateFaceIndex(colorIndex, ccw);
colorAttribute = computeAttributeFromIndexedData(triangulatedCoordIndex, triangulatedColorIndex, color, 3);
} else {
colorAttribute = toNonIndexedAttribute(triangulatedCoordIndex, new Float32BufferAttribute(color, 3));
}
} else {
if (colorIndex && colorIndex.length > 0) {
const flattenFaceColors = flattenData(color, colorIndex);
const triangulatedFaceColors = triangulateFaceData(flattenFaceColors, coordIndex);
colorAttribute = computeAttributeFromFaceData(triangulatedCoordIndex, triangulatedFaceColors);
} else {
const triangulatedFaceColors = triangulateFaceData(color, coordIndex);
colorAttribute = computeAttributeFromFaceData(triangulatedCoordIndex, triangulatedFaceColors);
}
}
}
if (normal) {
if (normalPerVertex === true) {
if (normalIndex && normalIndex.length > 0) {
const triangulatedNormalIndex = triangulateFaceIndex(normalIndex, ccw);
normalAttribute = computeAttributeFromIndexedData(
triangulatedCoordIndex,
triangulatedNormalIndex,
normal,
3
);
} else {
normalAttribute = toNonIndexedAttribute(triangulatedCoordIndex, new Float32BufferAttribute(normal, 3));
}
} else {
if (normalIndex && normalIndex.length > 0) {
const flattenFaceNormals = flattenData(normal, normalIndex);
const triangulatedFaceNormals = triangulateFaceData(flattenFaceNormals, coordIndex);
normalAttribute = computeAttributeFromFaceData(triangulatedCoordIndex, triangulatedFaceNormals);
} else {
const triangulatedFaceNormals = triangulateFaceData(normal, coordIndex);
normalAttribute = computeAttributeFromFaceData(triangulatedCoordIndex, triangulatedFaceNormals);
}
}
} else {
normalAttribute = computeNormalAttribute(triangulatedCoordIndex, coord, creaseAngle);
}
if (texCoord) {
if (texCoordIndex && texCoordIndex.length > 0) {
const triangulatedTexCoordIndex = triangulateFaceIndex(texCoordIndex, ccw);
uvAttribute = computeAttributeFromIndexedData(triangulatedCoordIndex, triangulatedTexCoordIndex, texCoord, 2);
} else {
uvAttribute = toNonIndexedAttribute(triangulatedCoordIndex, new Float32BufferAttribute(texCoord, 2));
}
}
const geometry = new BufferGeometry();
const positionAttribute = toNonIndexedAttribute(triangulatedCoordIndex, new Float32BufferAttribute(coord, 3));
geometry.setAttribute("position", positionAttribute);
geometry.setAttribute("normal", normalAttribute);
if (colorAttribute)
geometry.setAttribute("color", colorAttribute);
if (uvAttribute)
geometry.setAttribute("uv", uvAttribute);
geometry._solid = solid;
geometry._type = "mesh";
return geometry;
}
function buildIndexedLineSetNode(node) {
let color, coord;
let colorIndex, coordIndex;
let colorPerVertex = true;
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "color":
const colorNode = fieldValues[0];
if (colorNode !== null) {
color = getNode(colorNode);
}
break;
case "coord":
const coordNode = fieldValues[0];
if (coordNode !== null) {
coord = getNode(coordNode);
}
break;
case "colorIndex":
colorIndex = fieldValues;
break;
case "colorPerVertex":
colorPerVertex = fieldValues[0];
break;
case "coordIndex":
coordIndex = fieldValues;
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
let colorAttribute;
const expandedLineIndex = expandLineIndex(coordIndex);
if (color) {
if (colorPerVertex === true) {
if (colorIndex.length > 0) {
const expandedColorIndex = expandLineIndex(colorIndex);
colorAttribute = computeAttributeFromIndexedData(expandedLineIndex, expandedColorIndex, color, 3);
} else {
colorAttribute = toNonIndexedAttribute(expandedLineIndex, new Float32BufferAttribute(color, 3));
}
} else {
if (colorIndex.length > 0) {
const flattenLineColors = flattenData(color, colorIndex);
const expandedLineColors = expandLineData(flattenLineColors, coordIndex);
colorAttribute = computeAttributeFromLineData(expandedLineIndex, expandedLineColors);
} else {
const expandedLineColors = expandLineData(color, coordIndex);
colorAttribute = computeAttributeFromLineData(expandedLineIndex, expandedLineColors);
}
}
}
const geometry = new BufferGeometry();
const positionAttribute = toNonIndexedAttribute(expandedLineIndex, new Float32BufferAttribute(coord, 3));
geometry.setAttribute("position", positionAttribute);
if (colorAttribute)
geometry.setAttribute("color", colorAttribute);
geometry._type = "line";
return geometry;
}
function buildPointSetNode(node) {
let color, coord;
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "color":
const colorNode = fieldValues[0];
if (colorNode !== null) {
color = getNode(colorNode);
}
break;
case "coord":
const coordNode = fieldValues[0];
if (coordNode !== null) {
coord = getNode(coordNode);
}
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
const geometry = new BufferGeometry();
geometry.setAttribute("position", new Float32BufferAttribute(coord, 3));
if (color)
geometry.setAttribute("color", new Float32BufferAttribute(color, 3));
geometry._type = "points";
return geometry;
}
function buildBoxNode(node) {
const size = new Vector3(2, 2, 2);
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "size":
size.x = fieldValues[0];
size.y = fieldValues[1];
size.z = fieldValues[2];
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
const geometry = new BoxGeometry(size.x, size.y, size.z);
return geometry;
}
function buildConeNode(node) {
let radius = 1, height = 2, openEnded = false;
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "bottom":
openEnded = !fieldValues[0];
break;
case "bottomRadius":
radius = fieldValues[0];
break;
case "height":
height = fieldValues[0];
break;
case "side":
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
const geometry = new ConeGeometry(radius, height, 16, 1, openEnded);
return geometry;
}
function buildCylinderNode(node) {
let radius = 1, height = 2;
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "bottom":
break;
case "radius":
radius = fieldValues[0];
break;
case "height":
height = fieldValues[0];
break;
case "side":
break;
case "top":
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
const geometry = new CylinderGeometry(radius, radius, height, 16, 1);
return geometry;
}
function buildSphereNode(node) {
let radius = 1;
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "radius":
radius = fieldValues[0];
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
const geometry = new SphereGeometry(radius, 16, 16);
return geometry;
}
function buildElevationGridNode(node) {
let color;
let normal;
let texCoord;
let height;
let colorPerVertex = true;
let normalPerVertex = true;
let solid = true;
let ccw = true;
let creaseAngle = 0;
let xDimension = 2;
let zDimension = 2;
let xSpacing = 1;
let zSpacing = 1;
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "color":
const colorNode = fieldValues[0];
if (colorNode !== null) {
color = getNode(colorNode);
}
break;
case "normal":
const normalNode = fieldValues[0];
if (normalNode !== null) {
normal = getNode(normalNode);
}
break;
case "texCoord":
const texCoordNode = fieldValues[0];
if (texCoordNode !== null) {
texCoord = getNode(texCoordNode);
}
break;
case "height":
height = fieldValues;
break;
case "ccw":
ccw = fieldValues[0];
break;
case "colorPerVertex":
colorPerVertex = fieldValues[0];
break;
case "creaseAngle":
creaseAngle = fieldValues[0];
break;
case "normalPerVertex":
normalPerVertex = fieldValues[0];
break;
case "solid":
solid = fieldValues[0];
break;
case "xDimension":
xDimension = fieldValues[0];
break;
case "xSpacing":
xSpacing = fieldValues[0];
break;
case "zDimension":
zDimension = fieldValues[0];
break;
case "zSpacing":
zSpacing = fieldValues[0];
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
const vertices = [];
const normals = [];
const colors = [];
const uvs = [];
for (let i = 0; i < zDimension; i++) {
for (let j = 0; j < xDimension; j++) {
const index = i * xDimension + j;
const x = xSpacing * i;
const y = height[index];
const z = zSpacing * j;
vertices.push(x, y, z);
if (color && colorPerVertex === true) {
const r = color[index * 3 + 0];
const g = color[index * 3 + 1];
const b = color[index * 3 + 2];
colors.push(r, g, b);
}
if (normal && normalPerVertex === true) {
const xn = normal[index * 3 + 0];
const yn = normal[index * 3 + 1];
const zn = normal[index * 3 + 2];
normals.push(xn, yn, zn);
}
if (texCoord) {
const s = texCoord[index * 2 + 0];
const t = texCoord[index * 2 + 1];
uvs.push(s, t);
} else {
uvs.push(i / (xDimension - 1), j / (zDimension - 1));
}
}
}
const indices = [];
for (let i = 0; i < xDimension - 1; i++) {
for (let j = 0; j < zDimension - 1; j++) {
const a = i + j * xDimension;
const b = i + (j + 1) * xDimension;
const c = i + 1 + (j + 1) * xDimension;
const d = i + 1 + j * xDimension;
if (ccw === true) {
indices.push(a, c, b);
indices.push(c, a, d);
} else {
indices.push(a, b, c);
indices.push(c, d, a);
}
}
}
const positionAttribute = toNonIndexedAttribute(indices, new Float32BufferAttribute(vertices, 3));
const uvAttribute = toNonIndexedAttribute(indices, new Float32BufferAttribute(uvs, 2));
let colorAttribute;
let normalAttribute;
if (color) {
if (colorPerVertex === false) {
for (let i = 0; i < xDimension - 1; i++) {
for (let j = 0; j < zDimension - 1; j++) {
const index = i + j * (xDimension - 1);
const r = color[index * 3 + 0];
const g = color[index * 3 + 1];
const b = color[index * 3 + 2];
colors.push(r, g, b);
colors.push(r, g, b);
colors.push(r, g, b);
colors.push(r, g, b);
colors.push(r, g, b);
colors.push(r, g, b);
}
}
colorAttribute = new Float32BufferAttribute(colors, 3);
} else {
colorAttribute = toNonIndexedAttribute(indices, new Float32BufferAttribute(colors, 3));
}
}
if (normal) {
if (normalPerVertex === false) {
for (let i = 0; i < xDimension - 1; i++) {
for (let j = 0; j < zDimension - 1; j++) {
const index = i + j * (xDimension - 1);
const xn = normal[index * 3 + 0];
const yn = normal[index * 3 + 1];
const zn = normal[index * 3 + 2];
normals.push(xn, yn, zn);
normals.push(xn, yn, zn);
normals.push(xn, yn, zn);
normals.push(xn, yn, zn);
normals.push(xn, yn, zn);
normals.push(xn, yn, zn);
}
}
normalAttribute = new Float32BufferAttribute(normals, 3);
} else {
normalAttribute = toNonIndexedAttribute(indices, new Float32BufferAttribute(normals, 3));
}
} else {
normalAttribute = computeNormalAttribute(indices, vertices, creaseAngle);
}
const geometry = new BufferGeometry();
geometry.setAttribute("position", positionAttribute);
geometry.setAttribute("normal", normalAttribute);
geometry.setAttribute("uv", uvAttribute);
if (colorAttribute)
geometry.setAttribute("color", colorAttribute);
geometry._solid = solid;
geometry._type = "mesh";
return geometry;
}
function buildExtrusionNode(node) {
let crossSection = [1, 1, 1, -1, -1, -1, -1, 1, 1, 1];
let spine = [0, 0, 0, 0, 1, 0];
let scale;
let orientation;
let beginCap = true;
let ccw = true;
let creaseAngle = 0;
let endCap = true;
let solid = true;
const fields = node.fields;
for (let i = 0, l = fields.length; i < l; i++) {
const field = fields[i];
const fieldName = field.name;
const fieldValues = field.values;
switch (fieldName) {
case "beginCap":
beginCap = fieldValues[0];
break;
case "ccw":
ccw = fieldValues[0];
break;
case "convex":
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;
break;
default:
console.warn("THREE.VRMLLoader: Unknown field:", fieldName);
break;
}
}
const crossSectionClosed = crossSection[0] === crossSection[crossSection.length - 2] && crossSection[1] === crossSection[crossSection.length - 1];
const vertices = [];
const spineVector = new Vector3();
const scaling = new Vector3();
const axis = new Vector3();
const vertex = new Vector3();
const quaternion = new Quaternion();
for (let 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;
const angle = orientation ? orientation[o + 3] : 0;
for (let k = 0, kl = crossSection.length; k < kl; k += 2) {
vertex.x = crossSection[k + 0];
vertex.y = 0;
vertex.z = crossSection[k + 1];
vertex.multiply(scaling);
quaternion.setFromAxisAngle(axis, angle);
vertex.applyQuaternion(quaternion);
vertex.add(spineVector);
vertices.push(vertex.x, vertex.y, vertex.z);
}
}
const indices = [];
const spineCount = spine.length / 3;
const crossSectionCount = crossSection.length / 2;
for (let i = 0; i < spineCount - 1; i++) {
for (let j = 0; j < crossSectionCount - 1; j++) {
const a = j + i * crossSectionCount;
let b = j + 1 + i * crossSectionCount;
const c = j + (i + 1) * crossSectionCount;
let 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);
}
}
}
if (beginCap === true || endCap === true) {
const contour = [];
for (let i = 0, l = crossSection.length; i < l; i += 2) {
contour.push(new Vector2(crossSection[i], crossSection[i + 1]));
}
const faces = ShapeUtils.triangulateShape(contour, []);
const capIndices = [];
for (let i = 0, l = faces.length; i < l; i++) {
const face = faces[i];
capIndices.push(face[0], face[1], face[2]);
}
if (beginCap === true) {
for (let 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]);
}
}
}
if (endCap === true) {
const indexOffset = crossSectionCount * (spineCount - 1);
for (let 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]
);
}
}
}
}
const positionAttribute = toNonIndexedAttribute(indices, new Float32BufferAttribute(vertices, 3));
const normalAttribute = computeNormalAttribute(indices, vertices, creaseAngle);
const geometry = new BufferGeometry();
geometry.setAttribute("position", positionAttribute);
geometry.setAttribute("normal", normalAttribute);
geometry._solid = solid;
geometry._type = "mesh";
return geometry;
}
function resolveUSE(identifier) {
const node = nodeMap[identifier];
const build = getNode(node);
return build.isObject3D || build.isMaterial ? build.clone() : build;
}
function parseFieldChildren(children, owner) {
for (let i = 0, l = children.length; i < l; i++) {
const object = getNode(children[i]);
if (object instanceof Object3D)
owner.add(object);
}
}
function triangulateFaceIndex(index, ccw) {
const indices = [];
let start = 0;
for (let i = 0, l = index.length; i < l; i++) {
const i1 = index[start];
const i2 = index[i + (ccw ? 1 : 2)];
const i3 = index[i + (ccw ? 2 : 1)];
indices.push(i1, i2, i3);
if (index[i + 3] === -1 || i + 3 >= l) {
i += 3;
start = i + 1;
}
}
return indices;
}
function triangulateFaceData(data2, index) {
const triangulatedData = [];
let start = 0;
for (let i = 0, l = index.length; i < l; i++) {
const stride = start * 3;
const x = data2[stride];
const y = data2[stride + 1];
const z = data2[stride + 2];
triangulatedData.push(x, y, z);
if (index[i + 3] === -1 || i + 3 >= l) {
i += 3;
start++;
}
}
return triangulatedData;
}
function flattenData(data2, index) {
const flattenData2 = [];
for (let i = 0, l = index.length; i < l; i++) {
const i1 = index[i];
const stride = i1 * 3;
const x = data2[stride];
const y = data2[stride + 1];
const z = data2[stride + 2];
flattenData2.push(x, y, z);
}
return flattenData2;
}
function expandLineIndex(index) {
const indices = [];
for (let i = 0, l = index.length; i < l; i++) {
const i1 = index[i];
const i2 = index[i + 1];
indices.push(i1, i2);
if (index[i + 2] === -1 || i + 2 >= l) {
i += 2;
}
}
return indices;
}
function expandLineData(data2, index) {
const triangulatedData = [];
let start = 0;
for (let i = 0, l = index.length; i < l; i++) {
const stride = start * 3;
const x = data2[stride];
const y = data2[stride + 1];
const z = data2[stride + 2];
triangulatedData.push(x, y, z);
if (index[i + 2] === -1 || i + 2 >= l) {
i += 2;
start++;
}
}
return triangulatedData;
}
const vA = new Vector3();
const vB = new Vector3();
const vC = new Vector3();
const uvA = new Vector2();
const uvB = new Vector2();
const uvC = new Vector2();
function computeAttributeFromIndexedData(coordIndex, index, data2, itemSize) {
const array = [];
for (let i = 0, l = coordIndex.length; i < l; i += 3) {
const a = index[i];
const b = index[i + 1];
const c = index[i + 2];
if (itemSize === 2) {
uvA.fromArray(data2, a * itemSize);
uvB.fromArray(data2, b * itemSize);
uvC.fromArray(data2, c * itemSize);
array.push(uvA.x, uvA.y);
array.push(uvB.x, uvB.y);
array.push(uvC.x, uvC.y);
} else {
vA.fromArray(data2, a * itemSize);
vB.fromArray(data2, b * itemSize);
vC.fromArray(data2, c * itemSize);
array.push(vA.x, vA.y, vA.z);
array.push(vB.x, vB.y, vB.z);
array.push(vC.x, vC.y, vC.z);
}
}
return new Float32BufferAttribute(array, itemSize);
}
function computeAttributeFromFaceData(index, faceData) {
const array = [];
for (let i = 0, j = 0, l = index.length; i < l; i += 3, j++) {
vA.fromArray(faceData, j * 3);
array.push(vA.x, vA.y, vA.z);
array.push(vA.x, vA.y, vA.z);
array.push(vA.x, vA.y, vA.z);
}
return new Float32BufferAttribute(array, 3);
}
function computeAttributeFromLineData(index, lineData) {
const array = [];
for (let i = 0, j = 0, l = index.length; i < l; i += 2, j++) {
vA.fromArray(lineData, j * 3);
array.push(vA.x, vA.y, vA.z);
array.push(vA.x, vA.y, vA.z);
}
return new Float32BufferAttribute(array, 3);
}
function toNonIndexedAttribute(indices, attribute) {
const array = attribute.array;
const itemSize = attribute.itemSize;
const array2 = new array.constructor(indices.length * itemSize);
let index = 0, index2 = 0;
for (let i = 0, l = indices.length; i < l; i++) {
index = indices[i] * itemSize;
for (let j = 0; j < itemSize; j++) {
array2[index2++] = array[index++];
}
}
return new Float32BufferAttribute(array2, itemSize);
}
const ab = new Vector3();
const cb = new Vector3();
function computeNormalAttribute(index, coord, creaseAngle) {
const faces = [];
const vertexNormals = {};
for (let i = 0, l = index.length; i < l; i += 3) {
const a = index[i];
const b = index[i + 1];
const c = index[i + 2];
const face = new Face(a, b, c);
vA.fromArray(coord, a * 3);
vB.fromArray(coord, b * 3);
vC.fromArray(coord, c * 3);
cb.subVectors(vC, vB);
ab.subVectors(vA, vB);
cb.cross(ab);
cb.normalize();
face.normal.copy(cb);
if (vertexNormals[a] === void 0)
vertexNormals[a] = [];
if (vertexNormals[b] === void 0)
vertexNormals[b] = [];
if (vertexNormals[c] === void 0)
vertexNormals[c] = [];
vertexNormals[a].push(face.normal);
vertexNormals[b].push(face.normal);
vertexNormals[c].push(face.normal);
faces.push(face);
}
const normals = [];
for (let i = 0, l = faces.length; i < l; i++) {
const face = faces[i];
const nA = weightedNormal(vertexNormals[face.a], face.normal, creaseAngle);
const nB = weightedNormal(vertexNormals[face.b], face.normal, creaseAngle);
const nC = weightedNormal(vertexNormals[face.c], face.normal, creaseAngle);
vA.fromArray(coord, face.a * 3);
vB.fromArray(coord, face.b * 3);
vC.fromArray(coord, face.c * 3);
normals.push(nA.x, nA.y, nA.z);
normals.push(nB.x, nB.y, nB.z);
normals.push(nC.x, nC.y, nC.z);
}
return new Float32BufferAttribute(normals, 3);
}
function weightedNormal(normals, vector, creaseAngle) {
const normal = new Vector3();
if (creaseAngle === 0) {
normal.copy(vector);
} else {
for (let i = 0, l = normals.length; i < l; i++) {
if (normals[i].angleTo(vector) < creaseAngle) {
normal.add(normals[i]);
}
}
}
return normal.normalize();
}
function toColorArray(colors) {
const array = [];
for (let i = 0, l = colors.length; i < l; i += 3) {
array.push(new Color(colors[i], colors[i + 1], colors[i + 2]));
}
return array;
}
function paintFaces(geometry, radius, angles, colors, topDown) {
const thresholds = [];
const startAngle = topDown === true ? 0 : Math.PI;
for (let i = 0, l = colors.length; i < l; i++) {
let angle = i === 0 ? 0 : angles[i - 1];
angle = topDown === true ? angle : startAngle - angle;
const point = new Vector3();
point.setFromSphericalCoords(radius, angle, 0);
thresholds.push(point);
}
const indices = geometry.index;
const positionAttribute = geometry.attributes.position;
const colorAttribute = new BufferAttribute(new Float32Array(geometry.attributes.position.count * 3), 3);
const position = new Vector3();
const color = new Color();
for (let i = 0; i < indices.count; i++) {
const index = indices.getX(i);
position.fromBufferAttribute(positionAttribute, index);
let thresholdIndexA, thresholdIndexB;
let t = 1;
for (let j = 1; j < thresholds.length; j++) {
thresholdIndexA = j - 1;
thresholdIndexB = j;
const thresholdA = thresholds[thresholdIndexA];
const thresholdB = thresholds[thresholdIndexB];
if (topDown === true) {
if (position.y <= thresholdA.y && position.y > thresholdB.y) {
t = Math.abs(thresholdA.y - position.y) / Math.abs(thresholdA.y - thresholdB.y);
break;
}
} else {
if (position.y >= thresholdA.y && position.y < thresholdB.y) {
t = Math.abs(thresholdA.y - position.y) / Math.abs(thresholdA.y - thresholdB.y);
break;
}
}
}
const colorA = colors[thresholdIndexA];
const colorB = colors[thresholdIndexB];
color.copy(colorA).lerp(colorB, t);
colorAttribute.setXYZ(index, color.r, color.g, color.b);
}
geometry.setAttribute("color", colorAttribute);
}
const textureLoader = new TextureLoader(this.manager);
textureLoader.setPath(this.resourcePath || path).setCrossOrigin(this.crossOrigin);
if (data.indexOf("#VRML V2.0") === -1) {
throw Error("THREE.VRMLLexer: Version of VRML asset not supported.");
}
const tree = generateVRMLTree(data);
const scene = parseTree(tree);
return scene;
}
}
class VRMLLexer {
constructor(tokens) {
this.lexer = new Lexer(tokens);
}
lex(inputText) {
const lexingResult = this.lexer.tokenize(inputText);
if (lexingResult.errors.length > 0) {
console.error(lexingResult.errors);
throw Error("THREE.VRMLLexer: Lexing errors detected.");
}
return lexingResult;
}
}
class VRMLParser extends CstParser {
constructor(tokenVocabulary) {
super(tokenVocabulary);
const $ = this;
const Version = tokenVocabulary["Version"];
const LCurly = tokenVocabulary["LCurly"];
const RCurly = tokenVocabulary["RCurly"];
const LSquare = tokenVocabulary["LSquare"];
const RSquare = tokenVocabulary["RSquare"];
const Identifier = tokenVocabulary["Identifier"];
const RouteIdentifier = tokenVocabulary["RouteIdentifier"];
const StringLiteral = tokenVocabulary["StringLiteral"];
const HexLiteral = tokenVocabulary["HexLiteral"];
const NumberLiteral = tokenVocabulary["NumberLiteral"];
const TrueLiteral = tokenVocabulary["TrueLiteral"];
const FalseLiteral = tokenVocabulary["FalseLiteral"];
const NullLiteral = tokenVocabulary["NullLiteral"];
const DEF = tokenVocabulary["DEF"];
const USE = tokenVocabulary["USE"];
const ROUTE = tokenVocabulary["ROUTE"];
const TO = tokenVocabulary["TO"];
const NodeName = tokenVocabulary["NodeName"];
$.RULE("vrml", function() {
$.SUBRULE($.version);
$.AT_LEAST_ONE(function() {
$.SUBRULE($.node);
});
$.MANY(function() {
$.SUBRULE($.route);
});
});
$.RULE("version", function() {
$.CONSUME(Version);
});
$.RULE("node", function() {
$.OPTION(function() {
$.SUBRULE($.def);
});
$.CONSUME(NodeName);
$.CONSUME(LCurly);
$.MANY(function() {
$.SUBRULE($.field);
});
$.CONSUME(RCurly);
});
$.RULE("field", function() {
$.CONSUME(Identifier);
$.OR2([
{
ALT: function() {
$.SUBRULE($.singleFieldValue);
}
},
{
ALT: function() {
$.SUBRULE($.multiFieldValue);
}
}
]);
});
$.RULE("def", function() {
$.CONSUME(DEF);
$.OR([
{
ALT: function() {
$.CONSUME(Identifier);
}
},
{
ALT: function() {
$.CONSUME(NodeName);
}
}
]);
});
$.RULE("use", function() {
$.CONSUME(USE);
$.OR([
{
ALT: function() {
$.CONSUME(Identifier);
}
},
{
ALT: function() {
$.CONSUME(NodeName);
}
}
]);
});
$.RULE("singleFieldValue", function() {
$.AT_LEAST_ONE(function() {
$.OR([
{
ALT: function() {
$.SUBRULE($.node);
}
},
{
ALT: function() {
$.SUBRULE($.use);
}
},
{
ALT: function() {
$.CONSUME(StringLiteral);
}
},
{
ALT: function() {
$.CONSUME(HexLiteral);
}
},
{
ALT: function() {
$.CONSUME(NumberLiteral);
}
},
{
ALT: function() {
$.CONSUME(TrueLiteral);
}
},
{
ALT: function() {
$.CONSUME(FalseLiteral);
}
},
{
ALT: function() {
$.CONSUME(NullLiteral);
}
}
]);
});
});
$.RULE("multiFieldValue", function() {
$.CONSUME(LSquare);
$.MANY(function() {
$.OR([
{
ALT: function() {
$.SUBRULE($.node);
}
},
{
ALT: function() {
$.SUBRULE($.use);
}
},
{
ALT: function() {
$.CONSUME(StringLiteral);
}
},
{
ALT: function() {
$.CONSUME(HexLiteral);
}
},
{
ALT: function() {
$.CONSUME(NumberLiteral);
}
},
{
ALT: function() {
$.CONSUME(NullLiteral);
}
}
]);
});
$.CONSUME(RSquare);
});
$.RULE("route", function() {
$.CONSUME(ROUTE);
$.CONSUME(RouteIdentifier);
$.CONSUME(TO);
$.CONSUME2(RouteIdentifier);
});
this.performSelfAnalysis();
}
}
class Face {
constructor(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
this.normal = new Vector3();
}
}
const TEXTURE_TYPE = {
INTENSITY: 1,
INTENSITY_ALPHA: 2,
RGB: 3,
RGBA: 4
};
export {
VRMLLoader
};
//# sourceMappingURL=VRMLLoader.js.map