############################################################################ # # File: vrml.icn # # Subject: Procedures to support creation of VRML files # # Author: Ralph E. Griswold # # Date: May 2, 2001 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This file contains procedures for producing VRML files. # # point_field(L) create VRML point field from point list L # # u_crd_idx(i) create VRML coordinate index for 0 through i - 1 # # render(x) render node x # # vrml1(x) produces VRML 1.0 file for node x # # vrml2(x) produces VRML 2.0 file for node x # # vrml_color(s) convert Icon color specification to vrml form # # Notes: # # Not all node types have been tested. # # Where field values are complex, as in vectors, these must be built # separately as strings to go in the appropriate fields. # # There is no error checking. Fields must be given in the # order they appear in the node record declarations and field values # must be of the correct type and form. # # The introduction of record types other than for nodes will cause # bogus output. A structural loop will produce output until the # evaluation stack overflows. # ############################################################################ # # Links: ptutils, records # ############################################################################ # # Requires: Version 9 graphics for color conversion # ############################################################################ # # See also: vrml1lib.icn and vrml2.icn # ############################################################################ link ptutils, records procedure point_field(pts) #: create VRML point field local field field := "[\n" every field ||:= pt2coord(!pts) || ",\n" return field || "\n]" end procedure u_crd_idx(i) #: create VRML coordinate index local index index := "[\n" every index ||:= (0 to i - 1) || ",\n" return index ||:= "\n]" end procedure vrml1(x, f) #: write VRML 1.0 file /f := &output write(f, "#VRML V1.0 ascii") render(x, f) end procedure vrml2(x, f) #: produce VRML 2.0 file write(f, "#VRML V2.0 utf8") render(x, f) end procedure render(x, f) # render VRML object local i, bar, fieldname, input static indent initial indent := 0 if /x then return # skip any stray null values indent +:= 3 bar := repl(" ", indent) if x := string(x) then write(f, " ", x) else case type(x) of { "USE": write(f, bar, "USE ", x.name) "DEF": { writes(f, bar, "DEF ", x.name) render(x.node, f) } "Comment": write(f, "# ", x.text) "Include": { input := open(x.name) | stop("*** cannot find inline file") while write(f, read(input)) close(input) } default: { # all other nodes write(f, bar, type(x), " {") # must be record for VRML node every i := 1 to *x do { if type(x[i]) == "list" then # list of children every render(!x[i], f) else if /x[i] then next # skip empty fields else { writes(f, bar, " ") fieldname := field(x, i) if fieldname ~== "null" then writes(f, fieldname) render(x[i], f) } } write(f, bar, " }") } } indent -:= 3 return end procedure vrml_color(s) local result static factor initial factor := real(2 ^ 16 - 1) s := ColorValue(s) | fail result := "" s ? { every 1 to 3 do { result ||:= (tab(upto(',') | 0) / factor) || " " move(1) } } return result end