With the help of the Simple Wrapper and Interface Generator (SWIG) we have created bindings so that you can access most of the VOS C++ API from the comfort of Perl. The API is similar enough that one should be able to get by using just the C++ API documentation and a little hacking!
This section presents a virtual world built using the Abstract 3D Layer (A3DL) in Perl. (This world, the Conic Temple, was inspired by one of our very first test worlds for an ancient VOS/3D prototype). This code can also be found in the source distribution as swig/perl/apps/conic.pl
#!/usr/bin/perl # # Conic.pl Conic Temple A Sample VOS World # # Copyright 2003 Peter Amstutz # # Permission is granted to use any part of the following Perl program, # with or without modification, in your own programs without # restriction. # Import the VOS library. use VOS; # We need to tell the C++ system which # extensions we're planning to use VOS::Property::registerExtenders(); VOS::Sector::registerExtenders(); VOS::Object3D::registerExtenders(); VOS::Cube::registerExtenders(); VOS::Cylinder::registerExtenders(); VOS::Cone::registerExtenders(); VOS::Light::registerExtenders(); VOS::PolygonMesh::registerExtenders(); VOS::Viewpoint::registerExtenders(); VOS::Search::registerExtenders(); VOS::Material::registerExtenders(); # Now create a local site. This will do all # our object management and handle network # communication my $site = VOSc::new_LocalSocketSite_a(VOS::NoAccessControl_static()); VOS::LocalSite::extendMetaObject($site, "misc:search"); # Tell the site we want it to sleep when it doesn't # have anything else to do $site->setTimeoutOnSelect(-1); # Create the world object! # Note that we need to explicitly cast # it to get the Sector API $w = VOS::castToSector($site->createMetaObject("world", ["a3dl:sector"])); # Create the light and position it in the world. This should # be pretty straightforward. Note that you need to set an # access control policy (in this case "no" access control, that is # to say, no restrictions) or else the system will by default # deny all remote access to an object for security reasons. my $light = VOS::castToLight($site->createMetaObject("light", ["a3dl:light"])); $light->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $light->setPosition(0, 5, -4); $light->setRadius(60); $light->setColor(.4, .4, .4); # Now add the light to the world. $w->insertChild(-1, "testlight", $light); # another light my $light = VOS::castToLight($site->createMetaObject("light", ["a3dl:light"])); $light->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $light->setPosition(0, 3, -20); $light->setRadius(30); $light->setColor(.4, .4, .4); $w->insertChild(-1, "anotherlight", $light); # A mesh is a set of polygons whose corners are specified by verticies. # This allows you to specify raw geometry in VOS. my $ps = VOS::castToPolygonMesh($site->createMetaObject("outerwalls", ["a3dl:object3D.polygonmesh", "a3dl:static"])); $ps->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $ps->setVertices([[-20, -1.2, -20], [-20, -1.2, 20], [-20, 2.9, -20], [-20, 2.9, 20], [20, -1.2, -20], [20, -1.2, 20], [20, 4.9, -20], [20, 4.9, 20]]); @verts = $ps->getVertices(); for($i = 0; $i < (scalar @verts); $i++) { print "$i: $verts[$i][0] $verts[$i][1] $verts[$i][2]\n"; } # The second parameter is the polygon color, as a hex triple, # the third parameter is texture scaling (unused for solid colors) # the final parameters are the vertices specifying the polygon $ps->setPolygons([[3, 2, 6, 7], [2, 3, 1, 0], [6, 4, 5, 7], [3, 7, 5, 1], [2, 0, 4, 6], [0, 1, 5, 4]]); @polys = $ps->getPolygons(); for($i = 0; $i < (scalar @polys); $i++) { $p = $polys[$i]; print "$polys[$i][$i2] "; for($i2 = 0; $i2 < (scalar @$p); $i2++) { print "$polys[$i][$i2] "; } print "\n"; } $ps->setOrientation(0, 1, 0, 0); $ps->setPosition(0, 0, 0); # now add these walls (well, actually just a big black box) to the world $w->insertChild(-1, "outerwalls", $ps); # The foundation is just a container object, it doesn't look like # anything on its own $foundation = VOS::castToObject3D($site->createMetaObject("foundation", ["a3dl:object3D"])); $foundation->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $foundation->setPosition(0, 0, 0); $foundation->setOrientation(0, 1, 0, 0); # Now the base (the big flat thing) $base = VOS::castToCube($site->createMetaObject("base", ["a3dl:object3D.cube"])); $base->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $base->setScalingHT(10, .2, 18.1); $base->setPosition(0, 1, -10); $base->setOrientation(0, 1, 0, 0); $basematerial = VOS::castToMaterial($site->createMetaObject("brown", ["a3dl:material"])); $basematerial->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $basematerial->setColor(VOS::Material::hexStringToFloats("#B3802A")); $base->setMaterial($basematerial); $foundation->insertChild(-1, "base", $base); $w->insertChild(-1, "foundation", $foundation); $columncolor = VOS::castToMaterial($site->createMetaObject("columncolor", ["a3dl:material"])); $columncolor->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $columncolor->setColor(VOS::Material::hexStringToFloats("#CCCCCC")); # We're going to create two a rows of columns, so first # define subroutine to create a single column sub createColumn { my ($x, $y, $z) = @_; # A column consists of a cylinder and a flat thingy on top $column = VOS::castToCylinder($site->createMetaObject("column$x$y$z", ["a3dl:object3D.cylinder"])); $column->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $column->setScalingHT(.2, 2, .2); $column->setPosition($x, $y, $z); $column->setMaterial($columncolor); $column->setOrientation(0, 1, 0, 0); $columntop = VOS::castToCube($site->createMetaObject("columntop$x$y$z", ["a3dl:object3D.cube"])); $columntop->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $columntop->setScalingHT(.22, .03, .22); $columntop->setPosition(0, 1, 0); $columntop->setOrientation(0, 1, 0, 0); $columntop->setMaterial($columncolor); $column->insertChild(-1, "columntop", $columntop); $foundation->insertChild(-1, "column", $column); } # create two parallel lines of columns for($i = -4; $i >= -16; $i -= 2) { createColumn(-2, 2, $i); createColumn(2, 2, $i); } # the dais at the far end $platform = VOS::castToCube($site->createMetaObject("platform", ["a3dl:object3D.cube"])); $platform->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $platform->setScalingHT(8, .3, 2.5); $platform->setPosition(0, 1.2, -2.3); $platform->setOrientation(0, 1, 0, 0); $platform->setMaterial($columncolor); $foundation->insertChild(-1, "platform", $platform); # the altar $altar = VOS::castToCube($site->createMetaObject("altar", ["a3dl:object3D.cube"])); $altar->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $altar->setScalingHT(2.2, 1, 1.7); $altar->setPosition(0, .5, 0); $altar->setOrientation(0, 1, 0, 0); $altar->setMaterial($columncolor); $platform->insertChild(-1, "altar", $altar); # the most holy cones... :-) $cone = VOS::castToCone($site->createMetaObject("cone1", ["a3dl:object3D.cone"])); $cone->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $cone->setScalingHT(2.4, 3, 2.4); $cone->setPosition(-2.8, 1.5, 0); $cone->setOrientation(0, 1, 0, 0); $cone->setMaterial($columncolor); $platform->insertChild(-1, "cone", $cone); $cone = VOS::castToCone($site->createMetaObject("cone2", ["a3dl:object3D.cone"])); $cone->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $cone->setScalingHT(2.4, 3, 2.4); $cone->setPosition(2.8, 1.5, 0); $cone->setOrientation(0, 1, 0, 0); $cone->setMaterial($columncolor); $platform->insertChild(-1, "cone", $cone); $red = VOS::castToMaterial($site->createMetaObject("red", ["a3dl:material"])); $red->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $red->setColor(VOS::Material::hexStringToFloats("#FF0000")); # the bright red carpet! $carpet = VOS::castToCube($site->createMetaObject("carpet", ["a3dl:object3D.cube"])); $carpet->setPropertyAccessControl(VOS::NoPropertyAccessControl_static()); $carpet->setScalingHT(3.5, .2, 16); $carpet->setPosition(0, 1.05, -11); $carpet->setOrientation(0, 1, 0, 0); $carpet->setMaterial($red); $foundation->insertChild(-1, "carpet", $carpet); # Set up a starting point for users $vp = VOS::castToViewpoint($site->createMetaObject("default-viewpoint", ["a3dl:viewpoint"])); $vp->initialize(); $vp->setPosition(0, 2, -20); $vp->setOrientation(0, 1, 0, 0); $w->insertChild(-1, "default-viewpoint", $vp); # Set up a starting point for users $vp = VOS::castToViewpoint($site->createMetaObject("webcam-viewpoint", ["a3dl:viewpoint"])); $vp->initialize(); $vp->setPosition(-2.195347, 5.173016, 1.916739); $vp->setOrientation(0.022262, 0.990621, -0.134815, 161.403654); $w->insertChild(-1, "webcam-viewpoint", $vp); # Inform the user as to what the site name is! print "Running world ".$w->getURL()->getString()."\n"; # Okay, the world is created, now go into a infinite loop # serving the world to whoever connects. while(1) { $site->flushIncomingBuffers(); }