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.
This commit is contained in:
parent
a6a6e60894
commit
b6c5c6d0a5
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
name: 'vrml1to97',
|
name: 'vrml1to97',
|
||||||
version: '0.3.1',
|
version: '0.3.2',
|
||||||
description: 'JavaScript converter from VRML 1 to VRML97',
|
description: 'JavaScript converter from VRML 1 to VRML97',
|
||||||
scripts: {
|
scripts: {
|
||||||
test: 'echo "Error: no test specified" && exit 1',
|
test: 'echo "Error: no test specified" && exit 1',
|
||||||
|
@ -91,6 +91,7 @@ function addWorldParameter(name: string, value: string, tree: Tree): void
|
|||||||
matches := (str: string, pat: RegExp) => pat.test(str)
|
matches := (str: string, pat: RegExp) => pat.test(str)
|
||||||
operator matches
|
operator matches
|
||||||
GroupNode := /(?:Transform)?Separator|Group|Switch|WWWAnchor/
|
GroupNode := /(?:Transform)?Separator|Group|Switch|WWWAnchor/
|
||||||
|
TransformNode := /^(?:Rotation|Scale|Transform|Translation)$/
|
||||||
SetNode := /IndexedFaceSet|IndexedLineSet|PointSet/
|
SetNode := /IndexedFaceSet|IndexedLineSet|PointSet/
|
||||||
LightNode := /Light$/
|
LightNode := /Light$/
|
||||||
|
|
||||||
@ -161,6 +162,8 @@ function parse(stream: Lexer, tree: DefTree = {}): DefTree
|
|||||||
switch role
|
switch role
|
||||||
matches GroupNode
|
matches GroupNode
|
||||||
role = 'Child'
|
role = 'Child'
|
||||||
|
matches TransformNode
|
||||||
|
role = 'Transform'
|
||||||
'ShapeHints'
|
'ShapeHints'
|
||||||
role = 'Dummy' // will fill in when we parse the ShapeHints
|
role = 'Dummy' // will fill in when we parse the ShapeHints
|
||||||
'Coordinate3'
|
'Coordinate3'
|
||||||
@ -193,6 +196,19 @@ function parse(stream: Lexer, tree: DefTree = {}): DefTree
|
|||||||
addChild clause, tree
|
addChild clause, tree
|
||||||
'Shape'
|
'Shape'
|
||||||
addShape clause, [], tree
|
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
|
mergeTree role, tree
|
||||||
else
|
else
|
||||||
@ -203,20 +219,24 @@ function parse(stream: Lexer, tree: DefTree = {}): DefTree
|
|||||||
{ht: 'word', nt: 'obrace'}
|
{ht: 'word', nt: 'obrace'}
|
||||||
switch held.value
|
switch held.value
|
||||||
matches GroupNode
|
matches GroupNode
|
||||||
parent :=
|
{children, ...context} := tree
|
||||||
held.value.endsWith('Separator') ? 'Transform' : 'Group'
|
|
||||||
{children, Translation, Rotation, ...context} := tree
|
|
||||||
subTree := parse stream, context
|
subTree := parse stream, context
|
||||||
if newKids := subTree.children
|
if newKids := subTree.children
|
||||||
newChild .= `${parent} {\n `
|
newChild :=
|
||||||
if 'Rotation' in subTree
|
`Group { children [\n ${renderList newKids} ] }\n`
|
||||||
newChild += renderList subTree.Rotation
|
|
||||||
newChild += "\n "
|
|
||||||
if 'Translation' in subTree
|
|
||||||
newChild += renderList subTree.Translation
|
|
||||||
newChild += "\n "
|
|
||||||
newChild += `children [\n ${renderList newKids} ] }\n`
|
|
||||||
addChild newChild, tree
|
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'
|
'ShapeHints'
|
||||||
subTree := parse stream
|
subTree := parse stream
|
||||||
hints: Tree := {}
|
hints: Tree := {}
|
||||||
@ -228,10 +248,6 @@ function parse(stream: Lexer, tree: DefTree = {}): DefTree
|
|||||||
mergeTree hints, tree
|
mergeTree hints, tree
|
||||||
if lastDefinition and tree._definitions
|
if lastDefinition and tree._definitions
|
||||||
tree._definitions[lastDefinition] = [hints]
|
tree._definitions[lastDefinition] = [hints]
|
||||||
'Rotation'
|
|
||||||
tree.Rotation = toksUntilClose stream
|
|
||||||
'Translation'
|
|
||||||
tree.Translation = toksUntilClose stream
|
|
||||||
'Coordinate3'
|
'Coordinate3'
|
||||||
tree.Coordinate = toksUntilClose stream
|
tree.Coordinate = toksUntilClose stream
|
||||||
'Normal'
|
'Normal'
|
||||||
|
Loading…
Reference in New Issue
Block a user