Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
6892001b8d | |||
5bd62ffe31 | |||
a6a6e60894 |
@ -13,9 +13,11 @@ 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
|
||||||
* Grouping nodes including Transform, Separator, Group, Switch, and WWWAnchor
|
* PerspectiveCamera nodes (converted into Viewpoint nodes)
|
||||||
|
* Grouping nodes including Separator, Group, Switch, and WWWAnchor
|
||||||
|
* Interprets a Switch named "Cameras" (by a DEF) as a list of Viewpoints
|
||||||
* ShapeHints
|
* ShapeHints
|
||||||
* Rotations
|
* Transformation nodes including Translation, Rotation, Scale, and Transform
|
||||||
* 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
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
name: 'vrml1to97',
|
name: 'vrml1to97',
|
||||||
version: '0.3.0',
|
version: '0.4.0',
|
||||||
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$/
|
||||||
|
|
||||||
@ -155,22 +156,39 @@ 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'
|
||||||
'ShapeHints'
|
matches TransformNode
|
||||||
role = 'Dummy' // will fill in when we parse the ShapeHints
|
role = 'Transform'
|
||||||
'Coordinate3'
|
'Coordinate3'
|
||||||
role = 'Coordinate'
|
role = 'Coordinate'
|
||||||
'TextureCoordinate2'
|
|
||||||
role = 'TextureCoordinate'
|
|
||||||
'Texture2'
|
|
||||||
role = 'Texture'
|
|
||||||
/Cube|Cone|Cylinder|Sphere/
|
/Cube|Cone|Cylinder|Sphere/
|
||||||
role = 'Shape'
|
role = 'Shape'
|
||||||
|
'PerspectiveCamera'
|
||||||
|
role = 'Viewpoint'
|
||||||
|
'ShapeHints'
|
||||||
|
role = 'Dummy' // will fill in when we parse the ShapeHints
|
||||||
|
'Texture2'
|
||||||
|
role = 'Texture'
|
||||||
|
'TextureCoordinate2'
|
||||||
|
role = 'TextureCoordinate'
|
||||||
matches SetNode
|
matches SetNode
|
||||||
role = 'Shape'
|
role = 'Shape'
|
||||||
matches LightNode
|
matches LightNode
|
||||||
@ -193,6 +211,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,17 +234,30 @@ 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 :=
|
|
||||||
held.value.endsWith('Separator') ? 'Transform' : 'Group'
|
|
||||||
{children, ...context} := tree
|
{children, ...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
|
if held.value is 'Switch'
|
||||||
newChild += renderList subTree.Rotation
|
newChild = "Switch {\n "
|
||||||
newChild += "\n "
|
if 'whichChoice' in subTree
|
||||||
newChild += `children [\n ${renderList newKids} ] }\n`
|
newChild += `whichChoice ${subTree.whichChoice[0]}\n `
|
||||||
|
newChild += `choice [\n ${renderList newKids} ] }\n`
|
||||||
|
else newChild =
|
||||||
|
`Group { 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 := {}
|
||||||
@ -225,8 +269,14 @@ 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'
|
'PerspectiveCamera'
|
||||||
tree.Rotation = toksUntilClose stream
|
contents := toksUntilClose stream
|
||||||
|
hasDescription := contents.find (e) =>
|
||||||
|
e.type?[0] is 'word' and e.value?[0] is 'description'
|
||||||
|
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'
|
||||||
@ -293,6 +343,9 @@ 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
|
||||||
|
Loading…
Reference in New Issue
Block a user