web analytics
Zurück zum Content

Panoramic Photography Revealed. Part III: Creating Perfect Virtual Tours, The Open Source Way

Diesen Artikel auf Deutsch


Introduction

Panoramic photography is a very specialized field of photography and in contrast to, let’s say portraits and nature photography, it’s not the first thing you get started with when getting your first camera. A lot of photographers and software companies are involved in panoramic photography and make a living out of it. That’s fair and my intention is not to set those people out on the street. But sometimes people want you to think panoramic photography is to be left to “the professionals” and that you shouldn’t even get started before you

  1. buy a panoramic tripod head for a couple of hundred bucks,
  2. buy various editing and stitching software for even more couples of hundred bucks and
  3. buy a Flash-based software to present your work on your website.

For me, there is definitely to much buying involved here! This series of articles tries to highlight every aspect of panoramic photography, always focused on keeping it low-cost and down to earth.

Part I: Hardware for Panoramic Photography, DIY

Part II: Creating Perfect Panoramas, The Open Source Way

Part III: Creating Perfect Virtual Tours, The Open Source Way (this one)

Part IV: Appendix / Frequently Asked Questions


Creating Perfect Virtual Tours, The Open Source Way


If you followed my first two articles about panoramic photography, you now have seen how to build your own panohead and how to create panoramas with the pictures you have shot with it. This article will show you how to create a high quality virtual tour by connecting multiple panoramas together, adding background music and/or sound, setting hotspots, defining actions and so on. Because I am still going open source here, the central piece of software will be the SaladoPlayer, for which I will show the necessary configuration.
Now this is very important: Even though there will be a lot of xml configuration to write, there are no programming skills needed whatsoever! Please try to follow this tutorial even if you have no experience in either programming or markup languages and please don’t be scared! I will try to start with very simple basics to make this tutorial comprehensible to everyone and walk you through any necessary step. You will be amazed what’s already possible with the SaladoPlayer and once you have your first tour running, the second will be a piece of cake!

If you have programming skills please read this:
I wrote this article to be as comprehensible as possible, even for those without any skills in programming language or without a good knowledge in computers in general. If you have experiences here, you will have to skip some parts and some will be too detailed for you. I am sorry for that, but I guess there is no other way. If you have good knowledge in xml, the SaladoPlayer wiki will be all what you need.

Basics

First of all, I will give a quick overview how the SaladoPlayer works. Before we start, you need the latest release of SP, at the moment, this is version 1.3. Go to www.panozona.com or directly to the git (https://github.com/mstandio/SaladoPlayer/downloads) and download a .zip file with the latest release. After unpacking, you will see a directory as follows:

Attention! After years of development, the SaladoPlayer has moved away pretty far from it’s predecessor PanoSalado. That’s why the project will now transform to OpenPano. On June 9th, 2013, the newest version of SaladoPlayer 1.3.5 has been published on the new website www.openpano.org. With that release, folder structures and filenames has been changed, too. As I expect a lot of changes in the next month, I am not going to change this tutorial right away but instead I will wait until the transformation to OpenPano is complete. I expect this to be very confusing for the beginner, so I decided to provide the latest version of SaladoPlayer before the release on openpano.org, version 1.3, for download. From my experience, 1.3 is a very stable version with a lot of features, sufficient for a beginner to start with SaladoPlayer/OpenPano. Anyone who knows how to use SP after this tutorial should be able to work with version 1.3.5 and later versions, too.

Update (22.03.2017): As the SaladoPlayer or OpenPano projects are both gone, here are uploads from the latest stable versions.


Now, what do we see here? At first, there is more stuff than you will need at the beginning, so let’s brake down the things you will need. There are five things every working SaladoPlayer necessarily needs:

  1. The actual „Player“, in this case SaladoPlayer-1.3.swf
  2. An html file where the SP will be embedded. Here: index.html
  3. An xml configuration file, there are plenty in the folder examples
  4. A folder with your panorama images, typically panoramas
  5. The folder embed wich contains some javascript and a file called expressInstall.swf which performs an automatic update if a visitor tries to visit your panorama with an outdated version of Flash Player.

The html file is the one your visitor will access with his or her browser, it’s not necessary to call it index, but I will just leave it that way. Within the html file, the SaladoPlayer-1.3.swf will be loaded and shown to the visitor. The SaladoPlayer itselfs loads the given xml file and thus loads all your config, which panoramas to load, how they are connected via hotspots, where the panoramas are located on a map and many more settings. Calling the .swf file in a browser will just give you an emply player, because the information where SP will find the xml config is stored in the html file. Calling the xml file won’t work either. So if you like to link to your panorama, you should always link to the html.

Hello World! The first virtual panorama in 5 minutes.

To have a fresh start, please create a new folder somewhere on your computer and name it whatever you like. I will go with testpano„. Copy the folder embed and the files index.html and SaladoPlayer-1.3.swf as well as any xml file you want from the examples into testpano. It really doesn’t matter wich one you choose, just take the first you find. Paste everything into your new created folder, in my case testpano and rename the xml file to something useful, in my case it’s testpano1.xml. Then, create a new folder in testpano and name it panoramas. When you are done, it should look like this:
Before I go into detail about the configuration, we need a panorama. There are indeed panoramas included in the zip file you downloaded from github, but those are only colored checkers for showcasing some included modules and they are not really fun to „play“ with. If you followed my previous tutorial, you should already have a panorama in a structure prepared for SP. If so, copy the main folder with the prefix dz_ into the folder panoramas. If you have an equirectangular image at hand, please visit part 2 of this series to see how to create such a structure with SaladoConverter. If you have no suitable image right now, you can download the example I am using here as zip file (2 MB): dz_testpano.zip

Either way, I now have a folder panoramas/dz_testpano which contains one xml file testpano_f.xml and 6 folders testpano with suffixes _b,_d,_f,_l,_r and _u, everything created by SaladoConverter. This is now every file I need for my first panorama to be uploaded. Before we do that, there is a little bit of configuration necessary.

Open the index.html in any editor you like. I work with Scintilla/SciTE but you can use pretty much every editor on the market (notepad++ is a very popular one). You should at least choose one that is able of syntax highlighting. To be clear: Neither the built-in editor of Microsoft Windows is a good idea, nor is the one of MAC OS.
After opening the index.html, you should see this:

<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
	<head>
		<title>SaladoPlayer v1.3</title>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
		<script type="text/javascript" src="embed/swfobject.js"></script>
		<script type="text/javascript">
			var flashvars = {};
			flashvars.xml = "examples/00_demo/01_demo.xml"
			var params = {};
			params.menu = "false";
			params.quality = "high";
			params.allowfullscreen = "true";
			swfobject.embedSWF("SaladoPlayer-1.3.swf", "SaladoPlayer", "100%", "100%", "10.1.0", "embed/expressInstall.swf", flashvars, params);
		</script>
	</head>
	<body bgcolor="#000000">
		<div id="SaladoPlayer">
			<a href="http://www.adobe.com/go/getflashplayer">
				<img src="embed/get_flash_player.gif" alt="Get Adobe Flash player" />
			</a>
		</div>
	</body>
</html>

For the moment, there are two important lines, 8 and 13. Line 8 is the position where the xml configuration file is loaded and line 13 is for SaladoPlayer. As line 8 points to an example config file that isn’t there, we should change the line and let it point to our xml file. I have my config file in the main folder, so I just need to set the name:

flashvars.xml = "testpano1.xml"

My aim is to show you the fastest way to your first virtual panorama, so this is all for now, you can save and close the file.

Next in line is the xml configuration. I open testpano1.xml and delete everything that is in there. Now, I write the shortest configuration possible, which is shown below. It basically does nothing else then telling the SaladoPlayer that there is one single panorama in the virtual tour and then delivers the location of the panorama in deepzoom structure:

<?xml version="1.0" encoding="utf-8" ?>
<SaladoPlayer>
	<global>
		<panoramas firstPanorama="testpano"/> 
	</global>
	<panoramas>
		<panorama id="testpano" path="~panoramas/dz_testpano/testpano_f.xml"/> 
	</panoramas>
</SaladoPlayer>

You can copy this config, you just need to set panorama id="testpano" to an ID you like (or leave it that way) and then define the destination where your panorama can be found. If you created a folder panoramas like described before, the path to the xml file of the deepzoom structure will look like in the example: path="~panoramas/dz_yourpanoname/yourpanoname_f.xml". You have to call the ID of the panorama a few lines above that, in global. firstPanorama="yourpanoname". If you have done all this, your first virtual panorama config is ready.

This are 9 lines of configuration, big projects sometimes need more than 1000 lines of code. This may sound scary, but it’s not really a big deal, because most of it is very similar and usually created through copy&paste ;-). Once you have a good template, you just replace names and paths and there you go.

Upload the whole folder to your website and visit the index.html. I did the same myself, here is what it looks like, a virtual 360°x180° panorama, created with open source software, presented with open source software:

Hooray, the first pano is working! Now let’s get serious. Let’s learn SaladoPlayer

So far we have our first virtual panorama up and running. In fact, I left out a lot of fundamental knowledge about SP just to make the first panorama be ready within minutes. There are some more basics necessary to understand the structure of SP and to make you able to create bigger and more sophisticated virtual tours soon. So let’s start over.

XML

If you do know what XML, HTML or a markup language is, please skip this step!

Before we even start with more xml, here are some basics about it. XML is a markup language, like html is one. So, what is a markup language?

With a programming language I create programs to run on various machines. A programming language gives instructions to a machine to do something, for example, to solve a mathematical problem or to print out text on a screen. In contrast, a markup language doesn’t give instruction to do anything. A markup language produces annotations, so that computer programs can understand and distiguish between text and annotation. For example: In html I write <b>Word</b>. This makes „Word“ to be printed bold, like this: Word. Your browser understands the markup language html and thus won’t show the brackets (they are called tags in markup languages). They aren’t supposed to be shown, they are only annotations, especially set for your browser. Another html conform tag is <h2>Word</h2> which would make „Word“ become a heading of level 2. Something like <AVeryBigHeading>Word</AVeryBigHeading> in contrast is not html conform and your browser wouldn’t understand it.

Both in HTML and XML, there are start-tags and end-tags. Together, they form an element. End-tags contain the same word as the respective start-tag, but with a leading slash. For example: <Greeting>Hello World!</Greeting>.

What you write for SaladoPlayer is very similar to a website in html, but we use xml here. You write your page of xml configuration but instead of a website, SaladoPlayer will read and transform the elements into a virtual tour. While html is a fairly strict set of valid tags, xml just defines some „rules“ and it’s the SaladoPlayer who expects specific tags and elements, such as <global>,<panoramas> or <actions>. If you are searching for a specific element or attribute in html, you can search pretty much everywhere on the internet. If you are trying to do something wit SP and you don’t know which element or attribute you need, there is the SaladoPlayer-Wiki and the SaladoPlayer-Forum.

Why is SaladoPlayer configured by an XML file? The SaladoPlayer and all its modules are able to understand a lot of input. That way, you just have to change one line of code and you have a very different virtual tour. Or you can write two differenz XML configs for the same set of panoramas and you have two very different tours without having to upload everything again. In fact, you only need the SaladoPlayer.swf once on your webserver and you can open as many panoramas with as many configs as you want with it. It’s simply very efficient.

And there is more: When working with XML, you know exactly what you are doing, your input has direct influence on the tour. Also, you can copy configs from your old projects or from other users easily, share them and discuss creative ways to „get the max“ out of SP with the elements and attributes available.

You could think it would be better to have a graphical userinterface, and you might be right. There was something called SaladoConfigurator but the project is on hold right now. Maybe it will be revived somwhen in the future, if the community support for the SaladoPlayer gets good enough and somebody takes over the SaladoConfigurator project. For now, xml is a good way to set up our virtual tours and the limit is only set by your creativity.

The structure

It’s very important to understand the structure of SP, because once you do, it’s very easy to write sophisticated xml files and thus create amazing virtual tours.
In the first example you saw a very minimal structure, with only the components that are essentially needed for the SaladoPlayer to work. I would like to get to that configuration again and extend it step by step.

As the XML standard requires us to do, we start every config with one line that states the document type. Like so:

<?xml version="1.0" encoding="utf-8" ?>

After that, we open and close <SaladoPlayer> tags. Later, all our code will be inside those tags:

<?xml version="1.0" encoding="utf-8" ?>
<SaladoPlayer>
</SaladoPlayer>

There are four child elements to the <SaladoPlayer> element: <global>, <panoramas>, <modules> and <actions>:

  • global: Defines global settings, such as autorotation, what the first panorama of the tour is, how long transition effect lasts etc.
  • panoramas: Defines the locations of all panoramas and how they are connected between each other.
  • modules: Calls additional modules. Modules are used to include background music, lens flare, a map, buttons and so on. Here is a list of currently available modules.
  • actions: Actions are used to make transitions between panoramas possible, open and close context menus, start and stop music etc.

You will definitely need all four child elements in a tour. For example, it’s very unusual to have no action definded, my minimal example from the beginning is a rare exception. So adding empty versions of all four elements is a good idea:

<?xml version="1.0" encoding="utf-8" ?>
<SaladoPlayer>
	<global>
	</global>
	<panoramas>
	</panoramas>
	<modules>
	</modules>
	<action>
	</actions>
</SaladoPlayer>

The purpose of the four child elements of <SaladoPlayer> is mostly to provide a good structure. That is why they are not really used for configuration, but again have own child elements (a lot of them!) where most of the configuration happens. For example:

As one child element of <global> we have <control>. <control> has a lot of attributes (see here) which we can, but needn’t to set. What we don’t set, stays with it’s default values, that’s a basic principle for everything in SaladoPlayer.

I would like to disable autorotation in a virtual tour, so I need to set the value of autorotation to false. Autorotation is an attribute of control, so here is what I do:

<global>
        <control autorotation="enabled:false" />
</global>

Notice, that there is only one <control> tag, but with the slash at the end. This is a short version of

<global>
        <control autorotation="enabled:false"></control>
</global>

and it’s defined in XML as valid. It’s valid, because the <control> element is empty. Remember, when I write <b>Word</b>, there is something in between the tags, there is something in the element. A tag with a slash at the end is thus called an empty-element tag and is intented to be used in such situations to simplify the code. As we have a lot of empty elements in SP, you will find those abbreviations widely spread.

As this is all you need to know to write your own XML file, I will now present some examples to help you understand the principle better.

Adding Panoramas

I will go with the example before, where I already disabled autoroation. I would like to add panoramas, this is obviously the most important thing to do.

<?xml version="1.0" encoding="utf-8" ?>
<SaladoPlayer>
	<global>
                <control autorotation="enabled:false" />
	</global>
	<panoramas>
	</panoramas>
	<modules>
	</modules>
	<action>
	</actions>
</SaladoPlayer>

Adding panoramas is possible by adding <panorama> as child element to the <panoramas> element. After a quick look into the SP wiki (http://panozona.com/wiki/SaladoPlayer:Configuration#panorama) I see, that has two mandatory attributes: ‚id‘ and ‚path‘. So this is what I do:

<?xml version="1.0" encoding="utf-8" ?>
<SaladoPlayer>
	<global>
                <control autorotation="enabled:false" />
	</global>
	<panoramas>
		<panorama id="pano1" path="~panoramas/dz_pano1/pano1_f.xml" />
		<panorama id="pano2" path="~panoramas/dz_pano2/pano2_f.xml" />
		<panorama id="pano3" path="~panoramas/dz_pano3/pano3_f.xml" />
	</panoramas>
	<modules>
	</modules>
	<action>
	</actions>
</SaladoPlayer>

Adding panoramas doesn’t change much without calling them. This happens in the next step:

Connecting Panoramas via Hotspots

If there is more than one panorama added to SaladoPlayer, we can connect them together via hotspots. Basically, hotspots are objects that perform actions when being clicked. There are a lot of actions that can be caused by a click onto a hotspot, e.g. playing a sound, showing text messages, jumping to a camera view, or like I am going to show it, switching to a different panorama.
SaladoPlayer knows three different types of hotspots, SimpleHotspot, AdvancedHotspot and VideoHotspot. As you can guess, the last one is for embedding videos and the first two for more-or-less static graphic hotspots. To make it easy, I will choose the SimpleHotspot.
First, search for the folder hotspots which is included in the SaladoPlayer archive you downloaded from github and upload it to the main directory of your panorama. We need this folder, because the respective swf-files SimpleHotspot-1.0.swf, AdvancedHotspot-1.0.swf and VideoHotspot-1.0.swf are located in there, besides some sample images we can use as hotspots.
Now, I am going to place a hotspot in pano1 that points to pano2. Therefore, I need two things: One action that I will call jumpToPano2 and the hotspot in pano1 that triggers that action.
I modify the currently empty actions element, by adding the action:

<action id="jumpToPano2" content="SaladoPlayer.loadPano(pano2)"/>

Then, I insert the hotspot as childelement of pano1, which means, it will be visible in pano1:

<swf id="Pano1ToPano2" path="~hotspots/SimpleHotspot-1.0.swf" mouse="onClick:jumpToPano2">

In total, we have this:

<?xml version="1.0" encoding="utf-8" ?>
<SaladoPlayer>
    <global>
                <control autorotation="enabled:false" />
    </global>
    <panoramas>
	<panorama id="pano1" path="~panoramas/dz_pano1/pano1_f.xml">
             <swf id="Pano1ToPano2" path="~hotspots/SimpleHotspot-1.0.swf" mouse="onClick:jumpToPano2"/>
	</panorama>
	<panorama id="pano2" path="~panoramas/dz_pano2/pano2_f.xml" />
	<panorama id="pano3" path="~panoramas/dz_pano3/pano3_f.xml" />
    </panoramas>
    <modules>
    </modules>
    <actions>
                <action id="jumpToPano2" content="SaladoPlayer.loadPano(pano2)"/>
    </actions>
</SaladoPlayer>
As I said in the previous tutorial, it is important to choose short and representative names, for the image as well as for IDs. You will call and reuse the panorama id a lot of times, so it should be always something like diningroom or reception_day or even pano1 and not myfirsthalloweenpano_with_familyTest4(aerialpano).

Now you added one hotspot into the first panorama. It’s obvious that we need at least another hotspot to get back to pano1. Therefore, you need another hotspot and another action. I will do that for all 3 panoramas, thus I need 4 hotspots to connect all panoramas together. To do so, I have to place the hotspots correctly (at the moment, they are just placed at standard position). For that, I use the location attribute of swf:

location="distance:0,pan:0,tilt:0"

distance determines the distance of the hotspot image to the camera, so basically lets it appear bigger or smaller. pan determines the horizontal position of the hotspot in degress (-180 to 180) and tilt the vertical position, respectively, -90 to 90 degrees. Setting the values for all panoramas correctly brings me here:

<?xml version="1.0" encoding="utf-8" ?>
<SaladoPlayer>
    <global>
                <control autorotation="enabled:false" />
    </global>
    <panoramas>
	<panorama id="pano1" path="~panoramas/dz_pano1/pano1_f.xml">
                    <swf id="Pano1ToPano2" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:0,tilt:-15" mouse="onClick:jumpToPano2"/>
	</panorama>
	<panorama id="pano2" path="~panoramas/dz_pano2/pano2_f.xml">
                   <swf id="Pano2ToPano1" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:-127,tilt:-10" mouse="onClick:jumpToPano1"/>
                   <swf id="Pano2ToPano3" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:70,tilt:-15" mouse="onClick:jumpToPano3"/>
	</panorama>
	<panorama id="pano3" path="~panoramas/dz_pano3/pano3_f.xml">
                   <swf id="Pano3ToPano2" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:-40,tilt:-15" mouse="onClick:jumpToPano2"/>
	</panorama>
    </panoramas>
    <modules>
    </modules>
    <actions>
                <action id="jumpToPano1" content="SaladoPlayer.loadPano(pano1)"/>
                <action id="jumpToPano2" content="SaladoPlayer.loadPano(pano2)"/>
                <action id="jumpToPano3" content="SaladoPlayer.loadPano(pano3)"/>
    </actions>
</SaladoPlayer>

Now you may ask yourself how to get the necessary values for pan and tilt. You could find them by changing values by trial and error, but there is a better way, and that’s using the ViewFinder. ViewFinder is a module that is not made to be shown in a tour, but to help you while configuring yours. It’s the first module we will use, so check the next step to see how to use it.

Adding Modules

There are still empty modules tags in our config file, but we are about to change that. Modules play an important part in the SaladoPlayer’s configuration, because everything that exceeds SaladoPlayer’s basic functionality can be achieved by using modules. There is already a pretty long list of available modules and because SaladoPlayer is a community project, modules can be written by everyone. Latest example of a module from the community is LensFlare, a feature request that came from the community and that has been filled by the community.

Example: ViewFinder

I would like to start with the module ViewFinder. In the SaladoPlayer archive, there is a folder called modules. You can either upload the whole folder to your webserver or just create a folder with the same name in the main folder of your panorama and upload the file ViewFinder-1.3.swf you find in there. ViewFinder is one of the simplest modules you find, with only one mandatory attribute (path) and not much to configure in general. I call the module with a single line of code:

<ViewFinder path="~modules/ViewFinder-1.3.swf"/>

Which you will find in the xml file as child element of modules:

<?xml version="1.0" encoding="utf-8" ?>
<SaladoPlayer>
    <global>
                <control autorotation="enabled:false" />
    </global>
    <panoramas>
            <panorama id="pano1" path="~panoramas/dz_pano1/pano1_f.xml">
                    <swf id="Pano1ToPano2" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:0,tilt:-15" mouse="onClick:jumpToPano2"/>
	    </panorama>
	    <panorama id="pano2" path="~panoramas/dz_pano2/pano2_f.xml">
                   <swf id="Pano2ToPano1" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:-127,tilt:-10" mouse="onClick:jumpToPano1"/>
                   <swf id="Pano2ToPano3" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:70,tilt:-15" mouse="onClick:jumpToPano3"/>
	    </panorama>
	    <panorama id="pano3" path="~panoramas/dz_pano3/pano3_f.xml">
                   <swf id="Pano3ToPano2" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:-40,tilt:-15" mouse="onClick:jumpToPano2"/>
	    </panorama>
    </panoramas>
    <modules>
	    <ViewFinder path="~modules/ViewFinder-1.3.swf"/>
    </modules>
    <actions>
                <action id="jumpToPano1" content="SaladoPlayer.loadPano(pano1)"/>
                <action id="jumpToPano2" content="SaladoPlayer.loadPano(pano2)"/>
                <action id="jumpToPano3" content="SaladoPlayer.loadPano(pano3)"/>
    </actions>
</SaladoPlayer>

Now you see the pan, tilt, and fov values in the top left corner, which is very convenient when creating virtual tours with a lot of hotspots. After setting all the values, the module should be obviously deactivated again, by simply deleting the line of code, or by commenting it out as follows:

<!-- <ViewFinder path="~modules/ViewFinder-1.3.swf"/> -->

Adding modules works the same with all available modules, but most of them require more configuration than ViewFinder. In general, modules and actions come together. First, we define all necessary config for the module. Then, we define actions that are going to be performed on that module, which often results in the module to trigger another action itself. This might sound confusing, so here is another example:

Example: BackgroundMusic

I would like to add some background sounds to my panorama. This exceeds a basic functionality and thus is done by a module. BackgroundMusic-1.1.swf is included in the SaladoPlayer package, you find it in the folder modules. What I need besides the swf-file of the module, is a soundfile, which I copy in the newly created folder media/sounds/

BackgroundMusic is a good example to show a more complex use of a module. The task: Every panorama should have it’s own background sound, which should automatically be played when entering the panorama. Also, there should be a hotspot for the sound to be toggled on/off.
You can imagine the BackgroundMusic module as a CD-Player: It’s only capable of playing one CD at a time, but it has a built-in CD changer that is able to hold hundreds of CDs. In the beginning, you place all the CDs you need in the CD changer. Every time you enter a panorama, the CD has to be changed. You define all tracks within the module configuration and then use BackgroundMusic.setTrack() to „choose a CD“ with it’s ID.

First of all, I define the module BackgroundMusic in modules and define three different tracks with the IDs pano1, pano2, pano3:

<BackgroundMusic path="~modules/BackgroundMusic-1.1.swf">
	<tracks>
		<track id="pano1" path="~media/sounds/pano1_recorded_sounds.mp3"/>
		<track id="pano2" path="~media/sounds/pano2_recorded_sounds.mp3"/>
		<track id="pano3" path="~media/sounds/pano3_recorded_sounds.mp3"/>
	</tracks>
</BackgroundMusic>    

Then, I need actions. One is needed to toggle the music on/off, three are needed for changing the sound files:

<action id="toggleBackgroundMusic" content="BackgroundMusic.togglePlay()"/>
<action id="setTrackPano1" content="BackgroundMusic.setTrack(pano1)"/>
<action id="setTrackPano2" content="BackgroundMusic.setTrack(pano2)"/>			
<action id="setTrackPano3" content="BackgroundMusic.setTrack(pano3)"/>	  

So, the actions need to be performed when entering a panorama. This is done by adding the onEnter attribute to panorama, like in this example:

<panorama id="pano1" path="~panoramas/dz_pano1/pano1_f.xml" onEnter="setTrackPano1">

Now we’re almost there. I wanted to have a hotspot to toggle the sound on and off. I would like to have some more settings, so I am using the AdvancedHotspot here:

<swf id="playMusic" path="~hotspots/AdvancedHotspot-1.0.swf" location="distance:1000,pan:-20,tilt:10" mouse="onClick:toggleBackgroundMusic">
	<settings path="~hotspots/images/soundspeaker.png" beat="false"/>
</swf>

The complete configuration looks as follows, below the working example:

<?xml version="1.0" encoding="utf-8" ?>
<SaladoPlayer>
    <global>
                <control autorotation="enabled:false" />
    </global>
    <panoramas>
	<panorama id="pano1" path="~panoramas/dz_pano1/pano1_f.xml" onEnter="setTrackPano1">
		<swf id="Pano1ToPano2" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:0,tilt:-15" mouse="onClick:jumpToPano2"/>
		<swf id="playMusic" path="~hotspots/AdvancedHotspot-1.0.swf" location="distance:1000,pan:-20,tilt:10" mouse="onClick:toggleBackgroundMusic">
			<settings path="~hotspots/images/soundspeaker.png" beat="false"/>
		</swf>
	</panorama>
	<panorama id="pano2" path="~panoramas/dz_pano2/pano2_f.xml" onEnter="setTrackPano2">
		<swf id="Pano2ToPano1" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:-127,tilt:-10" mouse="onClick:jumpToPano1"/>
		<swf id="Pano2ToPano3" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:70,tilt:-15" mouse="onClick:jumpToPano3"/>
	</panorama>
	<panorama id="pano3" path="~panoramas/dz_pano3/pano3_f.xml" onEnter="setTrackPano3">
		<swf id="Pano3ToPano2" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:-40,tilt:-15" mouse="onClick:jumpToPano2"/>
	</panorama>
    </panoramas>
    <modules>
		<BackgroundMusic path="~modules/BackgroundMusic-1.1.swf">
			<tracks>
				<track id="pano1" path="~media/sounds/pano1_recorded_sounds.mp3"/>
				<track id="pano2" path="~media/sounds/pano2_recorded_sounds.mp3"/>
				<track id="pano3" path="~media/sounds/pano3_recorded_sounds.mp3"/>
			</tracks>
		</BackgroundMusic>    
    </modules>
    <actions>
		<action id="jumpToPano1" content="SaladoPlayer.loadPano(pano1)"/>
		<action id="jumpToPano2" content="SaladoPlayer.loadPano(pano2)"/>
		<action id="jumpToPano3" content="SaladoPlayer.loadPano(pano3)"/>
		
		<action id="toggleBackgroundMusic" content="BackgroundMusic.togglePlay()"/>
		<action id="setTrackPano1" content="BackgroundMusic.setTrack(pano1)"/>
		<action id="setTrackPano2" content="BackgroundMusic.setTrack(pano2)"/>			
		<action id="setTrackPano3" content="BackgroundMusic.setTrack(pano3)"/>		

    </actions>
</SaladoPlayer>

Example: BackgroundMusic (Again)

Earlier, I said that a module itself can trigger actions. This didn’t happen in the previous example, so I will extend it a little more to show you how this works, and what it can do for you.
Let’s say, you want the soundspeaker icon to change when the sound is being toggled. This is an action, the module BackgroundMusic will trigger by itself.
First of all, a hotspot can’t be disabled once it’s in the panorama, so this isn’t he right element to use. I will use another module instead: ImageButton. ImageButton lets us „stick“ graphics to the visitor’s screen that follow the camera’s movement instead of staying at a specific position in the panorama, like the hotspot does. This also makes more sense here, because your visitors want to toggle music or background sound from everywhere in the tour.
So, I define the ImageButton-module with two different buttons, an activeSoundButton and an inactiveSoundButton. Both buttons should appear in the upper left corner of the screen, 50px away from the left and top border. Both buttons trigger the same action, which is the same as in the previous example: toggleBackgroundMusic. As the sound should be play right from the start, the activeSoundButton should be visible right from the start, so the activeSoundButton gets the open="true" attribute:

<ImageButton path="~modules/ImageButton-1.3.swf">
	<button id="activeSoundButton" path="~hotspots/images/soundspeaker_enabled.png" action="toggleBackgroundMusic" >
		<window align="vertical:top,horizontal:left" move="horizontal:50,vertical:50" open="true"/>
	</button>
	<button id="inactiveSoundButton" path="~hotspots/images/soundspeaker_disabled.png" action="toggleBackgroundMusic" >
		<window align="vertical:top,horizontal:left" move="horizontal:50,vertical:50" open="false"/>
	</button>
</ImageButton>

So far, so clear. Clicking on the icon should now toggle the sound. But I also want the icon to change depending on if the music is playing or not. That is, what the BackgroundMusic-module will do. At first, there are two new actions needed, one that shows the active button and hides the inactive one, and the other action vice versa:

<action id="showActiveSoundButton" content="ImageButton.setOpen(activeSoundButton,true);ImageButton.setOpen(inactiveSoundButton,false)"/>
<action id="showInactiveSoundButton" content="ImageButton.setOpen(activeSoundButton,false);ImageButton.setOpen(inactiveSoundButton,true)"/>

As child-element of BackgroundMusic I add following line:

<settings play="true" onPlay="showActiveSoundButton" onStop="showInactiveSoundButton"/>

play="true" will make the sounds play right from the start. What’s new here, is onPlay. This attribute contains an action that will be performed by the BackgroundMusic-module when it starts the music. Same with onStop. What we have now, is a circle: A click on a button triggers an action, the action activates a module, the module triggers another action which changes the button we clicked in the first place.

The whole configuration looks like follows:

<?xml version="1.0" encoding="utf-8" ?>
<SaladoPlayer>
	<global>
                <control autorotation="enabled:false" />
	</global>
	<panoramas>
		<panorama id="pano1" path="~panoramas/dz_pano1/pano1_f.xml" onEnter="setTrackPano1">
			<swf id="Pano1ToPano2" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:0,tilt:-15" mouse="onClick:jumpToPano2"/>
		</panorama>
		<panorama id="pano2" path="~panoramas/dz_pano2/pano2_f.xml" onEnter="setTrackPano2">
			<swf id="Pano2ToPano1" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:-127,tilt:-10" mouse="onClick:jumpToPano1"/>
			<swf id="Pano2ToPano3" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:70,tilt:-15" mouse="onClick:jumpToPano3"/>
		</panorama>
		<panorama id="pano3" path="~panoramas/dz_pano3/pano3_f.xml" onEnter="setTrackPano3">
			<swf id="Pano3ToPano2" path="~hotspots/SimpleHotspot-1.0.swf" location="distance:500,pan:-40,tilt:-15" mouse="onClick:jumpToPano2"/>
		</panorama>
	</panoramas>
	<modules>
		<BackgroundMusic path="~modules/BackgroundMusic-1.1.swf">
			<settings play="true" onPlay="showActiveSoundButton" onStop="showInactiveSoundButton"/>
			<tracks>
				<track id="pano1" path="~media/sounds/pano1_recorded_sounds.mp3"/>
				<track id="pano2" path="~media/sounds/pano2_recorded_sounds.mp3"/>
				<track id="pano3" path="~media/sounds/pano3_recorded_sounds.mp3"/>
			</tracks>
		</BackgroundMusic> 
		<ImageButton path="~modules/ImageButton-1.3.swf">
			<button id="activeSoundButton" path="~hotspots/images/soundspeaker_enabled.png" action="toggleBackgroundMusic" >
				<window align="vertical:top,horizontal:left" move="horizontal:50,vertical:50" open="true"/>
			</button>
			<button id="inactiveSoundButton" path="~hotspots/images/soundspeaker_disabled.png" action="toggleBackgroundMusic" >
				<window align="vertical:top,horizontal:left" move="horizontal:50,vertical:50" open="false"/>
			</button>
		</ImageButton>
	</modules>
	<actions>
		<action id="jumpToPano1" content="SaladoPlayer.loadPano(pano1)"/>
		<action id="jumpToPano2" content="SaladoPlayer.loadPano(pano2)"/>
		<action id="jumpToPano3" content="SaladoPlayer.loadPano(pano3)"/>
		
		<action id="toggleBackgroundMusic" content="BackgroundMusic.togglePlay()"/>
		<action id="setTrackPano1" content="BackgroundMusic.setTrack(pano1)"/>
		<action id="setTrackPano2" content="BackgroundMusic.setTrack(pano2)"/>			
		<action id="setTrackPano3" content="BackgroundMusic.setTrack(pano3)"/>
		
		<action id="showActiveSoundButton" content="ImageButton.setOpen(activeSoundButton,true);ImageButton.setOpen(inactiveSoundButton,false)"/>
		<action id="showInactiveSoundButton" content="ImageButton.setOpen(inactiveSoundButton,true);ImageButton.setOpen(activeSoundButton,false)"/>
    </actions>
</SaladoPlayer>

What I did here is a good way of creating complex combinations of actions and modules that can result in very dynamic, interactive virtual tours. The use of modules and actions should now be quite clear, which pretty much concludes my tutorial about SaladoPlayer at this point. Now it’s on you to explore the possibilites of SaladoPlayer. Use the examples on this site as a starting point and expand them to your taste. When you download SaladoPlayer, look in the examples folder to see examples for everything that comes with it: modules, triggers, functions… and share your experience in the SaladoPlayer forum to make the software become even better!

Credits

Thanks to Marek Standio for maintaining the SaladoPlayer and for the great help in the SaladoPlayer forum!

The XML folder icon is copyright by Dellustrations (http://www.dellustrations.com/).

All other drawings, pictures and texts are licenced under the creative commons license by-nc.

If you liked this article, please show your appreciation by sharing it! I am also glad about a click on the flattr button, or a small paypal donation that is possible via the button in the sidebar on the left.


24 Comments

  1. Horst Jahn Horst Jahn

    Hallo Tilman,
    vielen Dank für dieses schöne Tutorial! In deutsch wärs noch schöner, aber das kommt ja sicher bald. Hab nur mittelmäßige Kenntnisse in html und trotzdem ist es mir gelungen, testweise ein Pano sogar mit den Bedienfeldern online zu stellen. Eine Frage hab ich allerdings noch.
    Kann ich mit dem SaladoPlayer auch flache 180° Panoramas (GigaPixel etc.) abbilden, oder gehen nur Kugelpanos?

    Gruß Horst

  2. Also der SaladoPlayer ist tatsächlich nur auf sphärische Panoramen ausgelegt, was ich tatsächlich selbst sehr schade finde. Das DeepZoom Format würde sich für eine flache Verwendung ja genauso anbieten.
    Mann kann den SP etwas vergewaltigen um ihn zur Darstellung von flachen Panoramen zu zwingen, darüber habe ich selbst im Forum auf panozona.com ausführlich berichtet: http://panozona.com/wiki/Special:AWCforum/st/id210/Orthogonal_Panorama_with_SaladoP….html
    Es gibt allerdings elegantere Lösungen (siehe auch in meinem Beitrag dort).

  3. Asalle Kim Asalle Kim

    Hello, Mr Bremen.

    Thank you so much for this wonderful article, especially for Open Source point of view.

    But, following your advices I got a question. Can I see my panorama working offline? In other words, can I lauch it by clicking on index.html on my own laptop?

    Thanks again.

  4. Igor Igor

    Great tutorial! I was looking for full featured freeware panorama/virtual tour player and found Salado Player. Its demo tour impressed me. I am not a coder or programmer so when I downloaded the SP i was really frustrated. Open source applications often are hard to understand, mainly because of lack of adequate help. Your tutorial helped me very much. Thank you!

  5. Katherine Katherine

    Hello Tilman, This is a really great open source virtual tour, is it possible to make it dynamic, like when i click this link then it will show one photo, another link then will show another panorama photo…

  6. Katherine Katherine

    I can’t test it in localhost, I already added the directory name which i wasn’t sure if correct. I would be glad if you could provide a guide with this one.. ty

  7. For testing, you could just add your complete drive as a „secure directory“, if that doesn’t work, there might be an error in your tour rather than a problem with flash player security settings. If you have doubts about flash player having too much access, just redo the settings after testing.

  8. Hallo Tilman, tolle Seite und tolle Tutorials. Aber ich habe ein Problem mit Salado Player, speziell in Teil III des Tutorials „schaffen perfekte Tour über Open Source“ auf „Ihre erste virtuelle Tour in fünf Minuten“, um das Bild auf der Web-Anzeige sagt mir SaladoPlayer 1.3
    > Fehler in der Konfigurationsdatei Struktur: Error # 1088.
    Ich habe die Dateien überprüft und scheinen in Ordnung.
    Der Link lautet: franpacopepe.com -> Link.
    Meine Kenntnisse der deutschen Sprache ist null, so wandte ich mich an google Übersetzer, ich hoffe, Sie verstehen, und kann mir helfen.
    Vielen Dank für alles, Fran.
    PS: Sorry ich zweimal gesendet: (

  9. Hello Francisco,

    thanks for you answer, I hope it is okay if I answer in English?

    Your testpano1.xml file contains a line:

    - See more at: http://www.tilmanbremer.de/2012/05/panoramic-photography-revealed-part-iii-creating-virtual-tours-the-open-source-way/#sthash.IDZ4TjLA.dpuf

    This is not valid xml and should be the reason why your SaladoPlayer crashes. I guess you wanted to insert this line as a comment in your code? If so, thanks for the credits ;-). Try adding <!-- and --> around the comment, that is the correct way to tell SaladoPlayer to not read that line. Like this:

    <!--
    See more at:
    http://www.tilmanbremer.de/2012/05/panoramic-photography-revealed-part-iii-creating-virtual-tours-the-open-source-way/
    -->

    I’d like to hear if that worked for you.

    Best regards,
    Tilman

  10. Hi Tilman, I’ve gotten! I hope you visit my site and check to see the result of our work. Can be improved, as it is made with 55 pictures with a regular camera, but I’m very happy, it was only language problems (other xml and html), etc..
    Thank you, Fran.

  11. I had a look and it looks good :-). Glad I could help and nice to see another beginner starting with SaladoPlayer!

  12. Good job, great tutorial.Thanksssss.

  13. Karan Karan

    Hello Tilman.
    I was going through your tutorial. Thanks alot for your help. But i came accros one prob. I have been stuck at Hello World Tutorial. I have Done everything as written according to ur tutorial.
    But i am getting a black screen error.
    ERROR:

    >SaladoPlayer 1.3
    >Loading panorama: testpano
    >File not found: Error #2032

    What to do?

  14. Hi Karan, this error occurs when the path to the panorama file is not correctly specified. If you post the part of the code where you include the panorama i can have a look and maybe find the error. Its unfortunate that the errors arent more detailed, so something its hard to find it, but this is definitely something with an incorrect path. Please use <code></code> tags if you are going to post from your xml file.

  15. ray ray

    hi Tilman,

    i’m following all step on your tutorial at Hello World part. but there is problem occurs.

    >SaladoPlayer 1.3
    >Could not access local files, error: #2148
    >Add directory of unzipped files to Global Security Settings panel if you want to use player on local mashine

    how to fix it?

    Thanks

  16. Hi Ray,
    this is due to the security settings of the Adobe Flash Player. Please have a look into part 4 of this series, I addressed that problem there.

  17. bryan bryan

    Hi Tilman,
    Nice tutorial and thanks for sharing.
    i have a question, how to put a logo or watermark? is it possible if i change the watermark (powered by….)? how to do that?

    thank you.

  18. You mean the „powered by SaladoPlayer“ or „powered by OpenPano“ watermark? It is possible to change that, but you shouldn’t, its free software after all and deserves some support…

  19. Error in configuration file structure: Error #1088
    How to resolve it

  20. Hi tilman, i have to say lots of thanks for you.
    finaly its working for me.

  21. hi tilman i got some problem…how to set panorama in website

  22. i need cylindrical panorama projection using salado player how would i need to configure it

  23. I had a look and it looks good :-). Glad I could help and nice to see another beginner starting with SaladoPlayer! --
    BhoomiBazaar

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.