Compare commits

..

No commits in common. "main" and "0.3.1" have entirely different histories.
main ... 0.3.1

3 changed files with 24 additions and 74 deletions

View File

@ -13,11 +13,9 @@ VRML 1.0. Overall, it recognizes and converts
* Title, SceneInfo, BackgroundColor, and View "Info" nodes [this node type * Title, SceneInfo, BackgroundColor, and View "Info" nodes [this node type
was removed in VRML97]. was removed in VRML97].
* All Light nodes * All Light nodes
* PerspectiveCamera nodes (converted into Viewpoint nodes) * Grouping nodes including Transform, Separator, Group, Switch, and WWWAnchor
* Grouping nodes including Separator, Group, Switch, and WWWAnchor
* Interprets a Switch named "Cameras" (by a DEF) as a list of Viewpoints
* ShapeHints * ShapeHints
* Transformation nodes including Translation, Rotation, Scale, and Transform * Rotations and Translations
* All shape nodes including Cube, Cone, Cylinder, Sphere, IndexedFaceSet, * All shape nodes including Cube, Cone, Cylinder, Sphere, IndexedFaceSet,
IndexedLineSet, PointSet, Coordinate3, and Normal IndexedLineSet, PointSet, Coordinate3, and Normal
* All material nodes including Material, TextureCoordinate2, and Texture2 * All material nodes including Material, TextureCoordinate2, and Texture2

View File

@ -1,6 +1,6 @@
{ {
name: 'vrml1to97', name: 'vrml1to97',
version: '0.4.0', version: '0.3.1',
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',

View File

@ -91,7 +91,6 @@ 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$/
@ -156,39 +155,22 @@ function parse(stream: Lexer, tree: DefTree = {}): DefTree
continue continue
currentDefinition = next.value currentDefinition = next.value
held = filtered stream held = filtered stream
// Special case from VRML 1: DEF Cameras Switch { ... }
// needs to be hoisted to a list of viewpoints at this level
if currentDefinition is 'Cameras' and held?.value is 'Switch'
held = filtered stream
unless held?.type is 'obrace'
console.error
`DEF Cameras Switch followed by ${held?.value}, ignoring`
continue
{children, ...context} := tree
subTree := parse stream, context
addChild renderList(subTree.children), tree
held = filtered stream
continue
if held?.type is 'word' if held?.type is 'word'
clause := `DEF ${currentDefinition}` clause := `DEF ${currentDefinition}`
role .= held.value role .= held.value
switch role switch role
matches GroupNode matches GroupNode
role = 'Child' role = 'Child'
matches TransformNode
role = 'Transform'
'Coordinate3'
role = 'Coordinate'
/Cube|Cone|Cylinder|Sphere/
role = 'Shape'
'PerspectiveCamera'
role = 'Viewpoint'
'ShapeHints' 'ShapeHints'
role = 'Dummy' // will fill in when we parse the ShapeHints role = 'Dummy' // will fill in when we parse the ShapeHints
'Texture2' 'Coordinate3'
role = 'Texture' role = 'Coordinate'
'TextureCoordinate2' 'TextureCoordinate2'
role = 'TextureCoordinate' role = 'TextureCoordinate'
'Texture2'
role = 'Texture'
/Cube|Cone|Cylinder|Sphere/
role = 'Shape'
matches SetNode matches SetNode
role = 'Shape' role = 'Shape'
matches LightNode matches LightNode
@ -211,19 +193,6 @@ 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
@ -234,30 +203,20 @@ 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
{children, ...context} := tree parent :=
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 .= '' newChild .= `${parent} {\n `
if held.value is 'Switch' if 'Rotation' in subTree
newChild = "Switch {\n " newChild += renderList subTree.Rotation
if 'whichChoice' in subTree newChild += "\n "
newChild += `whichChoice ${subTree.whichChoice[0]}\n ` if 'Translation' in subTree
newChild += `choice [\n ${renderList newKids} ] }\n` newChild += renderList subTree.Translation
else newChild = newChild += "\n "
`Group { children [\n ${renderList newKids} ] }\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 := {}
@ -269,14 +228,10 @@ 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]
'PerspectiveCamera' 'Rotation'
contents := toksUntilClose stream tree.Rotation = toksUntilClose stream
hasDescription := contents.find (e) => 'Translation'
e.type?[0] is 'word' and e.value?[0] is 'description' tree.Translation = toksUntilClose stream
if lastDefinition and hasDescription is undefined
contents.push type: ['word'], value: ['description']
contents.push type: ['word'], value: [`"${lastDefinition}"`]
addChild {Viewpoint: contents}, tree
'Coordinate3' 'Coordinate3'
tree.Coordinate = toksUntilClose stream tree.Coordinate = toksUntilClose stream
'Normal' 'Normal'
@ -343,9 +298,6 @@ function parse(stream: Lexer, tree: DefTree = {}): DefTree
{ht: 'word', hv: 'creaseAngle', nt: 'number'} {ht: 'word', hv: 'creaseAngle', nt: 'number'}
tree.creaseAngle = [ next.value ] tree.creaseAngle = [ next.value ]
held = filtered stream held = filtered stream
{ht: 'word', hv: 'whichChild'}
tree.whichChoice = [ next.value ]
held = filtered stream
else else
console.error 'Ignoring unparseable token', held console.error 'Ignoring unparseable token', held
held = next // ignore unknown words held = next // ignore unknown words