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(); }