From b6c5c6d0a56d70d8f797333def24217588dcef96 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Wed, 14 Feb 2024 00:00:09 -0800 Subject: [PATCH 1/2] fix: Transformation nodes must create new scope In VRML 1, transformations like translations and rotations accumulate within a scope as they are encountered, and one can even have multiple translations with shapes interleaved between them. This accumulation is not possible in VRML97. Therefore, it's necessary to insert new scopes in the translated file every time a new transformation is encountered. This commit makes sure that happens. --- package.json5 | 2 +- src/index.civet | 46 +++++++++++++++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/package.json5 b/package.json5 index e979332..4683d9c 100644 --- a/package.json5 +++ b/package.json5 @@ -1,6 +1,6 @@ { name: 'vrml1to97', - version: '0.3.1', + version: '0.3.2', description: 'JavaScript converter from VRML 1 to VRML97', scripts: { test: 'echo "Error: no test specified" && exit 1', diff --git a/src/index.civet b/src/index.civet index 60dc7d2..8b842f8 100644 --- a/src/index.civet +++ b/src/index.civet @@ -91,6 +91,7 @@ function addWorldParameter(name: string, value: string, tree: Tree): void matches := (str: string, pat: RegExp) => pat.test(str) operator matches GroupNode := /(?:Transform)?Separator|Group|Switch|WWWAnchor/ +TransformNode := /^(?:Rotation|Scale|Transform|Translation)$/ SetNode := /IndexedFaceSet|IndexedLineSet|PointSet/ LightNode := /Light$/ @@ -161,6 +162,8 @@ function parse(stream: Lexer, tree: DefTree = {}): DefTree switch role matches GroupNode role = 'Child' + matches TransformNode + role = 'Transform' 'ShapeHints' role = 'Dummy' // will fill in when we parse the ShapeHints 'Coordinate3' @@ -193,6 +196,19 @@ function parse(stream: Lexer, tree: DefTree = {}): DefTree addChild clause, tree 'Shape' addShape clause, [], tree + 'Transform' + // VRML97 doesn't allow just the transform part of + // a Transform to be USEd (the whole node must be), so + // we have to recreate the transform. FIXME: dedupe code + content := known[next.value][1..] + {children, ...context} := tree + restOfTree := parse stream, context + if remainingKids := restOfTree.children + newChild := `Transform {\n ${renderList content}\n ` + + `children [\n ${renderList remainingKids}` + + "] }\n" + addChild newChild, tree + return tree {} mergeTree role, tree else @@ -203,20 +219,24 @@ function parse(stream: Lexer, tree: DefTree = {}): DefTree {ht: 'word', nt: 'obrace'} switch held.value matches GroupNode - parent := - held.value.endsWith('Separator') ? 'Transform' : 'Group' - {children, Translation, Rotation, ...context} := tree + {children, ...context} := tree subTree := parse stream, context if newKids := subTree.children - newChild .= `${parent} {\n ` - if 'Rotation' in subTree - newChild += renderList subTree.Rotation - newChild += "\n " - if 'Translation' in subTree - newChild += renderList subTree.Translation - newChild += "\n " - newChild += `children [\n ${renderList newKids} ] }\n` + newChild := + `Group { children [\n ${renderList newKids} ] }\n` addChild newChild, tree + matches TransformNode + content := toksUntilClose stream + if (lastDefinition + and tree._definitions?[lastDefinition][0] is 'Transform') + tree._definitions[lastDefinition].push ...content + {children, ...context} := tree + restOfTree := parse stream, context + if remainingKids := restOfTree.children + newChild := `Transform {\n ${renderList content}\n ` + + `children [\n ${renderList remainingKids} ] }\n` + addChild newChild, tree + return tree // used the rest of the tree, so done 'ShapeHints' subTree := parse stream hints: Tree := {} @@ -228,10 +248,6 @@ function parse(stream: Lexer, tree: DefTree = {}): DefTree mergeTree hints, tree if lastDefinition and tree._definitions tree._definitions[lastDefinition] = [hints] - 'Rotation' - tree.Rotation = toksUntilClose stream - 'Translation' - tree.Translation = toksUntilClose stream 'Coordinate3' tree.Coordinate = toksUntilClose stream 'Normal' -- 2.34.1 From b5b4065d6b04865ea340a39e3f1e64f8d9c630e9 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Wed, 14 Feb 2024 00:07:27 -0800 Subject: [PATCH 2/2] doc: Prior changes mean all transformation nodes supported --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 35c4d01..95fc666 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ VRML 1.0. Overall, it recognizes and converts * Title, SceneInfo, BackgroundColor, and View "Info" nodes [this node type was removed in VRML97]. * All Light nodes - * Grouping nodes including Transform, Separator, Group, Switch, and WWWAnchor + * Grouping nodes including Separator, Group, Switch, and WWWAnchor * ShapeHints - * Rotations and Translations + * Transformation nodes including Translation, Rotation, Scale, and Transform * All shape nodes including Cube, Cone, Cylinder, Sphere, IndexedFaceSet, IndexedLineSet, PointSet, Coordinate3, and Normal * All material nodes including Material, TextureCoordinate2, and Texture2 -- 2.34.1